Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
49 commits
Select commit Hold shift + click to select a range
a48e741
initial
khmyznikov Mar 10, 2026
eed0e20
fix shortcut
khmyznikov Mar 10, 2026
ecc93ea
more customization
khmyznikov Mar 11, 2026
1c78950
more improvements
khmyznikov Mar 12, 2026
6072ec7
fix settings buttons
khmyznikov Mar 12, 2026
74eafb5
Custom models picker, default models picker
khmyznikov Mar 12, 2026
f6149bb
default provider
khmyznikov Mar 12, 2026
a025d4d
add settings collapse
khmyznikov Mar 13, 2026
f8b1586
Phi Silica not tested
khmyznikov Mar 17, 2026
a3620f1
add settings ui manifest
khmyznikov Mar 19, 2026
a25ce4e
WinAppSdk 2.0 try
khmyznikov Mar 19, 2026
b5fc9fe
Revert "WinAppSdk 2.0 try"
khmyznikov Mar 19, 2026
51c5d32
upgrade to 260317003
khmyznikov Mar 19, 2026
dc14845
Add LAF helper
khmyznikov Mar 19, 2026
8224062
add workaround
khmyznikov Mar 20, 2026
c2789d6
launch hacks
khmyznikov Mar 21, 2026
a60eab4
add more params from sample
khmyznikov Mar 21, 2026
32ffd3a
change workaround
khmyznikov Mar 22, 2026
9421efe
update readme
khmyznikov Mar 22, 2026
fd96b46
Add laf as ADO secret
khmyznikov Mar 22, 2026
0a2bc81
fix laf attestation string
khmyznikov Mar 23, 2026
f53e64a
fix xaml
khmyznikov Mar 23, 2026
9f6d6b9
Fix build
khmyznikov Mar 23, 2026
0343840
fix installer
khmyznikov Mar 24, 2026
0bc4504
Merge branch 'gleb/advanced-paste' of https://github.com/microsoft/Po…
khmyznikov Mar 24, 2026
401ddcd
move AP to packaged identity
khmyznikov Mar 24, 2026
d28ae33
fix ap package
khmyznikov Mar 25, 2026
4fac403
debug build
khmyznikov Mar 25, 2026
36366e1
fix msix
khmyznikov Mar 25, 2026
c46e614
fix build
khmyznikov Mar 26, 2026
26bbfde
another try
khmyznikov Mar 26, 2026
3dfeece
Merge branch 'main' into gleb/advanced-paste
khmyznikov Mar 26, 2026
7436b46
another try 2
khmyznikov Mar 26, 2026
9befd28
another try 3
khmyznikov Mar 26, 2026
ab9a8c9
fix ap msix search
khmyznikov Mar 26, 2026
ce8508e
fix ap vnext
khmyznikov Mar 26, 2026
c43261f
keep fixing msix
khmyznikov Mar 27, 2026
faae1ae
to prev
khmyznikov Mar 27, 2026
00bc7ec
to prev 2
khmyznikov Mar 27, 2026
749378d
to prev 3
khmyznikov Mar 28, 2026
3281c0e
fix missing VCLibs
khmyznikov Mar 28, 2026
d628d73
AP DisableTransitiveFrameworkReferences
khmyznikov Mar 30, 2026
011fc5a
exclude AP from audit
khmyznikov Mar 30, 2026
dbae67d
Fixing AP crash
khmyznikov Mar 30, 2026
d776b64
another thing
khmyznikov Mar 30, 2026
68eb695
maybe final fix?
khmyznikov Mar 31, 2026
822303a
fix LAF tokens
khmyznikov Mar 31, 2026
9e02f48
fix debug tokens
khmyznikov Mar 31, 2026
96c5d16
Fix AP uninstall
khmyznikov Apr 1, 2026
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
51 changes: 51 additions & 0 deletions .pipelines/ESRPSigning_advancedpaste_msix_content.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
{
"Version": "1.0.0",
"UseMinimatch": false,
"SignBatches": [
{
"MatchedPath": [
"*.dll",
"*.exe"
],
"SigningInfo": {
"Operations": [
{
"KeyCode": "CP-230012",
"OperationSetCode": "SigntoolSign",
"Parameters": [
{
"parameterName": "OpusName",
"parameterValue": "Microsoft"
},
{
"parameterName": "OpusInfo",
"parameterValue": "http://www.microsoft.com"
},
{
"parameterName": "FileDigest",
"parameterValue": "/fd \"SHA256\""
},
{
"parameterName": "PageHash",
"parameterValue": "/NPH"
},
{
"parameterName": "TimeStamp",
"parameterValue": "/tr \"http://rfc3161.gtm.corp.microsoft.com/TSS/HttpTspServer\" /td sha256"
}
],
"ToolName": "sign",
"ToolVersion": "1.0"
},
{
"KeyCode": "CP-230012",
"OperationSetCode": "SigntoolVerify",
"Parameters": [],
"ToolName": "sign",
"ToolVersion": "1.0"
}
]
}
}
]
}
3 changes: 1 addition & 2 deletions .pipelines/ESRPSigning_core.json
Original file line number Diff line number Diff line change
Expand Up @@ -49,8 +49,7 @@
"PowerToys.PowerOCR.exe",

"PowerToys.AdvancedPasteModuleInterface.dll",
"WinUI3Apps\\PowerToys.AdvancedPaste.exe",
"WinUI3Apps\\PowerToys.AdvancedPaste.dll",
"WinUI3Apps\\AdvancedPaste\\*PowerToys.AdvancedPaste*.msix",

"PowerToys.AwakeModuleInterface.dll",
"PowerToys.Awake.exe",
Expand Down
2 changes: 1 addition & 1 deletion .pipelines/v2/release.yml
Original file line number Diff line number Diff line change
Expand Up @@ -102,7 +102,7 @@
useManagedIdentity: $(SigningUseManagedIdentity)
clientId: $(SigningOriginalClientId)
# Have msbuild use the release nuget config profile
additionalBuildOptions: /p:RestoreConfigFile="$(Build.SourcesDirectory)\.pipelines\release-nuget.config" /p:EnableCmdPalAOT=true
additionalBuildOptions: /p:RestoreConfigFile="$(Build.SourcesDirectory)\.pipelines\release-nuget.config" /p:EnableCmdPalAOT=true /p:PhiSilicaLafToken=$(PhiSilicaLafToken) /p:PhiSilicaLafAttestation="$(PhiSilicaLafAttestation)"

Check failure

Code scanning / check-spelling

Unrecognized Spelling Error

Laf is not a recognized word. (unrecognized-spelling)

Check failure

Code scanning / check-spelling

Unrecognized Spelling Error

Laf is not a recognized word. (unrecognized-spelling)

Check failure

Code scanning / check-spelling

Unrecognized Spelling Error

Laf is not a recognized word. (unrecognized-spelling)

Check failure

Code scanning / check-spelling

Unrecognized Spelling Error

Laf is not a recognized word. (unrecognized-spelling)
beforeBuildSteps:
# Sets versions for all PowerToy created DLLs
- pwsh: |-
Expand Down
70 changes: 70 additions & 0 deletions .pipelines/v2/templates/job-build-project.yml
Original file line number Diff line number Diff line change
Expand Up @@ -269,6 +269,9 @@ jobs:
- template: .\steps-setup-versioning.yml
parameters:
directory: $(build.sourcesdirectory)\src\modules\cmdpal
- template: .\steps-setup-versioning.yml
parameters:
directory: $(build.sourcesdirectory)\src\modules\AdvancedPaste



Expand Down Expand Up @@ -484,6 +487,46 @@ jobs:
**\*UnitTest*.dll
!**\obj\**

- pwsh: |-
$SearchRoot = "$(Build.SourcesDirectory)/$(BuildPlatform)/$(BuildConfiguration)"
Write-Host "Searching for AdvancedPaste MSIX in: $SearchRoot"
if (-not (Test-Path $SearchRoot)) {
Write-Warning "Search root does not exist: $SearchRoot"
$SearchRoot = "$(Build.SourcesDirectory)"
Write-Host "Falling back to: $SearchRoot"
}
# Log the AdvancedPaste output folder structure for diagnostics
$apDir = Join-Path $SearchRoot "WinUI3Apps/AdvancedPaste"
if (Test-Path $apDir) {
Write-Host "AdvancedPaste output folder contents:"
Get-ChildItem $apDir -Recurse -Include "*.msix","*.appx" | ForEach-Object { Write-Host " - $($_.FullName)" }
} else {
Write-Host "AdvancedPaste output folder not found at: $apDir"
}
$Packages = Get-ChildItem -Path $SearchRoot -Recurse -Filter "PowerToys.AdvancedPaste*.msix" -ErrorAction SilentlyContinue
Write-Host "Found $($Packages.Count) AdvancedPaste MSIX package(s):"
foreach ($pkg in $Packages) {
Write-Host " - $($pkg.FullName)"
}

if ($Packages.Count -gt 0) {
$PlatformPackage = $Packages | Where-Object { $_.Name -match "PowerToys\.AdvancedPaste.*_(x64|arm64)\.msix$" } | Select-Object -First 1
if ($PlatformPackage) {
$Package = $PlatformPackage
Write-Host "Using platform-specific package: $($Package.FullName)"
} else {
$Package = $Packages | Select-Object -First 1
Write-Host "Using first available package: $($Package.FullName)"
}

$PackageFilename = $Package.FullName
Write-Host "##vso[task.setvariable variable=AdvancedPastePackagePath]${PackageFilename}"
} else {
Write-Error "No AdvancedPaste MSIX packages found! The build may have failed to generate the MSIX."
exit 1
}
displayName: Locate the AdvancedPaste MSIX

- pwsh: |-
$Packages = Get-ChildItem -Recurse -Filter "Microsoft.CmdPal.UI_*.msix"
Write-Host "Found $($Packages.Count) CmdPal MSIX package(s):"
Expand Down Expand Up @@ -533,6 +576,29 @@ jobs:
Remove-Item -Force -Recurse "$(JobOutputDirectory)/_appx" -ErrorAction:Ignore
displayName: Re-pack the new CmdPal package after signing

- pwsh: |-
& "$(MakeAppxPath)" unpack /p "$(AdvancedPastePackagePath)" /d "$(JobOutputDirectory)/AdvancedPastePackageContents"
displayName: Unpack the AdvancedPaste MSIX for signing

- template: steps-esrp-signing.yml
parameters:
displayName: Sign AdvancedPaste MSIX content
signingIdentity: ${{ parameters.signingIdentity }}
inputs:
FolderPath: '$(JobOutputDirectory)/AdvancedPastePackageContents'
signType: batchSigning
batchSignPolicyFile: '$(build.sourcesdirectory)\.pipelines\ESRPSigning_advancedpaste_msix_content.json'
ciPolicyFile: '$(build.sourcesdirectory)\.pipelines\CIPolicy.xml'

- pwsh: |-
$outDir = New-Item -Type Directory "$(JobOutputDirectory)/_appx" -ErrorAction:Ignore
$PackageFilename = Join-Path $outDir.FullName (Split-Path -Leaf "$(AdvancedPastePackagePath)")
& "$(MakeAppxPath)" pack /h SHA256 /o /p $PackageFilename /d "$(JobOutputDirectory)/AdvancedPastePackageContents"
Copy-Item -Force $PackageFilename "$(AdvancedPastePackagePath)"
Remove-Item -Force -Recurse "$(JobOutputDirectory)/AdvancedPastePackageContents" -ErrorAction:Ignore
Remove-Item -Force -Recurse "$(JobOutputDirectory)/_appx" -ErrorAction:Ignore
displayName: Re-pack the new AdvancedPaste package after signing

- pwsh: |
$testsPath = "$(Build.SourcesDirectory)/$(BuildPlatform)/$(BuildConfiguration)/tests"
if (Test-Path $testsPath) {
Expand Down Expand Up @@ -565,6 +631,10 @@ jobs:
Copy-Item -Verbose -Force "$(CmdPalPackagePath)" "$(JobOutputDirectory)"
displayName: Stage the final CmdPal package

- pwsh: |-
Copy-Item -Verbose -Force "$(AdvancedPastePackagePath)" "$(JobOutputDirectory)"
displayName: Stage the final AdvancedPaste package



- template: steps-build-installer-vnext.yml
Expand Down
2 changes: 1 addition & 1 deletion .vscode/launch.json
Original file line number Diff line number Diff line change
Expand Up @@ -43,7 +43,7 @@
"name": "Run AdvancedPaste (managed, no build, ARCH configurable)",
"type": "coreclr",
"request": "launch",
"program": "${workspaceFolder}\\${input:arch}\\Debug\\WinUI3Apps\\PowerToys.AdvancedPaste.exe",
"program": "${workspaceFolder}\\${input:arch}\\Debug\\WinUI3Apps\\AdvancedPaste\\PowerToys.AdvancedPaste.exe",
"args": [],
"cwd": "${workspaceFolder}",
"env": {},
Expand Down
1 change: 1 addition & 0 deletions Directory.Build.props
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
<RepoRoot>$(MSBuildThisFileDirectory)</RepoRoot>
</PropertyGroup>
<Import Project="$(RepoRoot)src\Version.props" />
<Import Project="$(RepoRoot)src\PhiSilicaLaf.props" />

Check failure

Code scanning / check-spelling

Unrecognized Spelling Error

Laf is not a recognized word. (unrecognized-spelling)
<PropertyGroup>
<Copyright>Copyright (C) Microsoft Corporation. All rights reserved.</Copyright>
<AssemblyCopyright>Copyright (C) Microsoft Corporation. All rights reserved.</AssemblyCopyright>
Expand Down
8 changes: 4 additions & 4 deletions Directory.Packages.props
Original file line number Diff line number Diff line change
Expand Up @@ -78,10 +78,10 @@
<PackageVersion Include="Microsoft.Windows.CsWinRT" Version="2.2.0" />
<PackageVersion Include="Microsoft.Windows.ImplementationLibrary" Version="1.0.231216.1"/>
<PackageVersion Include="Microsoft.Windows.SDK.BuildTools" Version="10.0.26100.6901" />
<PackageVersion Include="Microsoft.WindowsAppSDK" Version="1.8.260209005" />
<PackageVersion Include="Microsoft.WindowsAppSDK.Foundation" Version="1.8.260203002" />
<PackageVersion Include="Microsoft.WindowsAppSDK.AI" Version="1.8.47" />
<PackageVersion Include="Microsoft.WindowsAppSDK.Runtime" Version="1.8.260209005" />
<PackageVersion Include="Microsoft.WindowsAppSDK" Version="1.8.260317003" />
<PackageVersion Include="Microsoft.WindowsAppSDK.Foundation" Version="1.8.260222000" />
<PackageVersion Include="Microsoft.WindowsAppSDK.AI" Version="1.8.53" />
<PackageVersion Include="Microsoft.WindowsAppSDK.Runtime" Version="1.8.260317003" />
<PackageVersion Include="Microsoft.Xaml.Behaviors.WinUI.Managed" Version="2.0.9" />
<PackageVersion Include="Microsoft.Xaml.Behaviors.Wpf" Version="1.1.39" />
<PackageVersion Include="ModernWpfUI" Version="0.9.4" />
Expand Down
48 changes: 47 additions & 1 deletion doc/devdocs/modules/advancedpaste.md
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,53 @@

## Debugging

TODO: Add debugging information
Advanced Paste is packaged as a self-contained MSIX with its own identity (`Microsoft.PowerToys.AdvancedPaste`). This gives it native package identity for Windows AI APIs (Phi Silica) and clean `ms-appx:///` resource resolution without workarounds.

The MSIX is output to `WinUI3Apps/AdvancedPaste/` and registered by the module interface at runtime (or by the installer on release builds).

### Running and attaching the debugger

1. Set the **Runner** project (`src/runner`) as the startup project in Visual Studio.
2. Launch the Runner (F5). This starts the PowerToys tray icon and loads all module interfaces.
3. Open Settings (right-click tray icon → Settings) and enable the **Advanced Paste** module if it isn't already. The module launches `PowerToys.AdvancedPaste.exe` in the background immediately.
4. In Visual Studio, go to **Debug → Attach to Process** (`Ctrl+Alt+P`) and attach to `PowerToys.AdvancedPaste.exe` (select **Managed (.NET Core)** debugger).

Alternatively, use the VS Code launch configuration **"Run AdvancedPaste"** from [.vscode/launch.json](/.vscode/launch.json) to launch the exe directly — but note that without the Runner, IPC and hotkeys won't work.

### MSIX package identity

Advanced Paste uses the Windows AI APIs (Phi Silica / `Microsoft.Windows.AI.Text.LanguageModel`) which require **package identity** at runtime. The app is packaged as a self-contained MSIX (following the same pattern as Command Palette).

#### How it works

- **Build**: The csproj has `EnableMsixTooling=true` and `GenerateAppxPackageOnBuild=true` (CI builds). This produces an MSIX in `AppPackages/`.
- **Local dev**: VS registers the package automatically via `Add-AppxPackage -Register AppxManifest.xml` when you build.
- **Installer**: The WiX installer deploys the MSIX file and a custom action (`InstallAdvancedPastePackageCA`) registers it via `PackageManager`.

#### Local development setup

For local debug builds, Visual Studio handles MSIX registration automatically. Select the **"PowerToys.AdvancedPaste (Package)"** launch profile in the debug dropdown.

To manually register:
```powershell
Add-AppxPackage -Register "ARM64\Debug\WinUI3Apps\AdvancedPaste\AppxManifest.xml"
```

Verify:
```powershell
$pkg = Get-AppxPackage -Name "*AdvancedPaste*"
$pkg.Name # Microsoft.PowerToys.AdvancedPaste.Dev
$pkg.IsDevelopmentMode # True
```

### How Settings UI checks Phi Silica availability

Settings UI does not have MSIX package identity. To check whether Phi Silica is available, it queries the running Advanced Paste process via a named pipe (`powertoys_advancedpaste_phi_status`).

Advanced Paste checks LAF + `GetReadyState()` once on startup (with MSIX identity), caches the result, and serves it to any client that connects. Settings connects with a 5-second timeout and reads one of:

Check failure

Code scanning / check-spelling

Unrecognized Spelling Error documentation

LAF is not a recognized word. (unrecognized-spelling)
- `Available` — model is ready
- `NotReady` — model needs download via Windows Update
- `NotSupported` — not a Copilot+ PC, API unavailable, or Advanced Paste not running

## Settings

Expand Down
74 changes: 74 additions & 0 deletions installer/PowerToysSetupCustomActionsVNext/CustomAction.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1415,6 +1415,80 @@ UINT __stdcall UnRegisterCmdPalPackageCA(MSIHANDLE hInstall)
return WcaFinalize(er);
}

UINT __stdcall InstallAdvancedPastePackageCA(MSIHANDLE hInstall)
{
using namespace winrt::Windows::Foundation;
using namespace winrt::Windows::Management::Deployment;

HRESULT hr = S_OK;
UINT er = ERROR_SUCCESS;
std::wstring installationFolder;

hr = WcaInitialize(hInstall, "InstallAdvancedPastePackage");
hr = getInstallFolder(hInstall, installationFolder);

try
{
auto msix = package::FindMsixFile(installationFolder + L"\\WinUI3Apps\\AdvancedPaste\\", false);
auto dependencies = package::FindMsixFile(installationFolder + L"\\WinUI3Apps\\AdvancedPaste\\Dependencies\\", true);

if (!msix.empty())
{
auto msixPath = msix[0];

if (!package::RegisterPackage(msixPath, dependencies))
{
Logger::error(L"Failed to install AdvancedPaste package");
er = ERROR_INSTALL_FAILURE;
}
}
}
catch (std::exception &e)
{
std::string errorMessage{"Exception thrown while trying to install AdvancedPaste package: "};
errorMessage += e.what();
Logger::error(errorMessage);

er = ERROR_INSTALL_FAILURE;
}

er = er == ERROR_SUCCESS ? (SUCCEEDED(hr) ? ERROR_SUCCESS : ERROR_INSTALL_FAILURE) : er;
return WcaFinalize(er);
}

UINT __stdcall UnRegisterAdvancedPastePackageCA(MSIHANDLE hInstall)
{
using namespace winrt::Windows::Foundation;
using namespace winrt::Windows::Management::Deployment;

HRESULT hr = S_OK;
UINT er = ERROR_SUCCESS;

hr = WcaInitialize(hInstall, "UnRegisterAdvancedPastePackageCA");

try
{
std::wstring packageToRemoveDisplayName{L"PowerToys.AdvancedPaste"};

if (!package::UnRegisterPackage(packageToRemoveDisplayName))
{
Logger::error(L"Failed to unregister package: " + packageToRemoveDisplayName);
er = ERROR_INSTALL_FAILURE;
}
}
catch (std::exception &e)
{
std::string errorMessage{"Exception thrown while trying to unregister the AdvancedPaste package: "};
errorMessage += e.what();
Logger::error(errorMessage);

er = ERROR_INSTALL_FAILURE;
}

er = er == ERROR_SUCCESS ? (SUCCEEDED(hr) ? ERROR_SUCCESS : ERROR_INSTALL_FAILURE) : er;
return WcaFinalize(er);
}


UINT __stdcall UnRegisterContextMenuPackagesCA(MSIHANDLE hInstall)
{
Expand Down
2 changes: 2 additions & 0 deletions installer/PowerToysSetupCustomActionsVNext/CustomAction.def
Original file line number Diff line number Diff line change
Expand Up @@ -20,8 +20,10 @@ EXPORTS
InstallEmbeddedMSIXCA
InstallDSCModuleCA
InstallCmdPalPackageCA
InstallAdvancedPastePackageCA
UnApplyModulesRegistryChangeSetsCA
UnRegisterCmdPalPackageCA
UnRegisterAdvancedPastePackageCA
UnRegisterContextMenuPackagesCA
UninstallEmbeddedMSIXCA
UninstallDSCModuleCA
Expand Down
Loading
Loading