launch skill: match Windows cleanup by path and run outside the agent sandbox

Windows PowerShell expands the 8.3 TEMP path when normalizing the run directory, so cleanup never matched processes launched with the short --user-data-dir. Compare the argument by the directory it refers to. Also tell agents to request unsandboxed execution for the launcher, Playwright, and cleanup instead of asking the user to change sandbox settings.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
This commit is contained in:
Henning DieterichsandCopilot committed 2026-10-22 22:55:25 +02:00
1 parent 290a5c585e
commit 3f0560b9e1
3 files changed
+32 -6

No files matched your search

+1 -1
View File
@@ -32,7 +32,7 @@ The clone is **slim**: workspace storage, browser caches, file history, cached V
- `@playwright/cli` available (it's a devDependency in the vscode repo - `npm install` then use `npx @playwright/cli`).
- For debugger work: `dap-cli` on `PATH`. If debugger support would be useful but the `dap-cli` skill is not present, prompt the user to install it from https://github.com/roblourens/dap-cli.
- CSS selectors are internal implementation details. If a selector-based `eval` stops working, take a fresh `snapshot`, inspect the current DOM, and update the selector rather than assuming an old one still applies.
- When running from an agent session with a sandboxed terminal, run the launcher and `@playwright/cli` outside the sandbox. The sandbox blocks starting Code OSS (`[launch.ps1] Access is denied` on Windows) and connecting to its local debug ports.
- When running from an agent session with a sandboxed terminal, the sandbox blocks starting Code OSS (`[launch.ps1] Access is denied` on Windows) and connecting to its local debug ports. Run the launcher, `@playwright/cli`, and the cleanup script outside the sandbox: request unsandboxed execution for those commands rather than asking the user to change sandbox settings.
> The launcher **copies** the source profile to a temp dir and never mutates the original. Each launch gets its own isolated `--user-data-dir` and `--extensions-dir`.
@@ -33,7 +33,6 @@ if (-not [string]::IsNullOrWhiteSpace($PlaywrightSession)) {
}
$userDataDir = Join-Path $RunDir 'user-data'
$userDataArgument = "--user-data-dir=$userDataDir"
$remainingProcesses = @()
for ($attempt = 0; $attempt -lt 5; $attempt++) {
$remainingProcesses = @(
@@ -42,7 +41,7 @@ for ($attempt = 0; $attempt -lt 5; $attempt++) {
$commandLine = $_.CommandLine
$_.Name -eq 'Code - OSS.exe' -and
$null -ne $commandLine -and
(Test-CommandLineHasArgument $commandLine $userDataArgument)
(Test-CommandLineHasPathArgument $commandLine '--user-data-dir' $userDataDir)
}
)
if ($remainingProcesses.Count -eq 0) {
@@ -60,7 +59,7 @@ $remainingProcesses = @(
$commandLine = $_.CommandLine
$_.Name -eq 'Code - OSS.exe' -and
$null -ne $commandLine -and
(Test-CommandLineHasArgument $commandLine $userDataArgument)
(Test-CommandLineHasPathArgument $commandLine '--user-data-dir' $userDataDir)
}
)
if ($remainingProcesses.Count -gt 0) {
@@ -35,8 +35,35 @@ namespace LaunchSkill {
'@
}
function Test-CommandLineHasArgument([string]$commandLine, [string]$expectedArgument) {
if (-not ('LaunchSkill.NativePath' -as [type])) {
Add-Type -TypeDefinition @'
using System.Runtime.InteropServices;
using System.Text;
namespace LaunchSkill {
public static class NativePath {
[DllImport("kernel32.dll", CharSet = CharSet.Unicode, SetLastError = true)]
private static extern uint GetLongPathName(string shortPath, StringBuilder longPath, uint bufferLength);
public static string ToLongPath(string path) {
StringBuilder buffer = new StringBuilder(32768);
uint length = GetLongPathName(path, buffer, (uint)buffer.Capacity);
return length == 0 || length >= buffer.Capacity ? path : buffer.ToString();
}
}
}
'@
}
# Matches `--<name>=<path>` arguments by the path they refer to, so short (8.3)
# and long spellings of the same existing directory compare equal.
function Test-CommandLineHasPathArgument([string]$commandLine, [string]$argumentName, [string]$expectedPath) {
$prefix = "$argumentName="
$expected = [LaunchSkill.NativePath]::ToLongPath($expectedPath).TrimEnd('\')
return [LaunchSkill.NativeCommandLine]::Parse($commandLine) |
Where-Object { [string]::Equals($_, $expectedArgument, [StringComparison]::OrdinalIgnoreCase) } |
Where-Object {
$_.StartsWith($prefix, [StringComparison]::OrdinalIgnoreCase) -and
[string]::Equals([LaunchSkill.NativePath]::ToLongPath($_.Substring($prefix.Length)).TrimEnd('\'), $expected, [StringComparison]::OrdinalIgnoreCase)
} |
Select-Object -First 1
}