dsh-cliworker-now 0.7.6 → 0.7.8
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.en.md +53 -11
- package/README.md +56 -11
- package/lib/account-models.mjs +49 -18
- package/lib/client.js +1221 -151
- package/lib/client.js.map +1 -1
- package/lib/grok-catalog.mjs +2 -2
- package/lib/hermes-native-entry.py +48 -13
- package/lib/hermes-nous-refresh.py +331 -0
- package/lib/index.js +9469 -6030
- package/lib/index.js.map +1 -1
- package/lib/native-launch.mjs +62 -7
- package/lib/native-spawn.mjs +32 -0
- package/lib/pi-installation.mjs +27 -3
- package/lib/pi-native-catalog.mjs +17 -7
- package/lib/pi-omp-bridge.mjs +2 -2
- package/lib/pi-omp-refresh.mjs +3 -3
- package/lib/private-launch.mjs +6 -2
- package/lib/terminal-bridge.mjs +2 -2
- package/lib/typert.host.js +265 -25
- package/lib/typert.remote-client.d.ts +8 -0
- package/lib/typert.remote-client.d.ts.map +1 -1
- package/lib/typert.remote-client.js +241 -25
- package/lib/types/client/account-query-queue.d.ts +16 -0
- package/lib/types/client/account-query-queue.js +61 -0
- package/lib/types/client/account-query-queue.js.map +1 -0
- package/lib/types/client/account-terminal.d.ts +6 -2
- package/lib/types/client/account-terminal.js +260 -31
- package/lib/types/client/account-terminal.js.map +1 -1
- package/lib/types/client/cli-executable-settings.d.ts +13 -0
- package/lib/types/client/cli-executable-settings.js +128 -0
- package/lib/types/client/cli-executable-settings.js.map +1 -0
- package/lib/types/client/management-styles.d.ts +1 -1
- package/lib/types/client/management-styles.js +4 -0
- package/lib/types/client/management-styles.js.map +1 -1
- package/lib/types/client/settings-dialog.js +196 -80
- package/lib/types/client/settings-dialog.js.map +1 -1
- package/lib/types/client/styles.d.ts +1 -1
- package/lib/types/client/styles.js +18 -16
- package/lib/types/client/styles.js.map +1 -1
- package/lib/types/client/zcode-login-link-provider.d.ts +9 -0
- package/lib/types/client/zcode-login-link-provider.js +105 -0
- package/lib/types/client/zcode-login-link-provider.js.map +1 -0
- package/lib/types/client/zcode-login-link.d.ts +16 -0
- package/lib/types/client/zcode-login-link.js +194 -0
- package/lib/types/client/zcode-login-link.js.map +1 -0
- package/lib/types/host/account-models.d.mts +10 -2
- package/lib/types/host/account-models.mjs +49 -18
- package/lib/types/host/accounts.d.ts +3 -2
- package/lib/types/host/accounts.js +168 -29
- package/lib/types/host/accounts.js.map +1 -1
- package/lib/types/host/adapters.d.ts +3 -1
- package/lib/types/host/adapters.js +138 -11
- package/lib/types/host/adapters.js.map +1 -1
- package/lib/types/host/agy-background-environment.d.ts +2 -0
- package/lib/types/host/agy-background-environment.js +7 -0
- package/lib/types/host/agy-background-environment.js.map +1 -0
- package/lib/types/host/agy-models.d.ts +2 -1
- package/lib/types/host/agy-models.js +6 -6
- package/lib/types/host/agy-models.js.map +1 -1
- package/lib/types/host/agy-windows-account.d.ts +14 -0
- package/lib/types/host/agy-windows-account.js +104 -0
- package/lib/types/host/agy-windows-account.js.map +1 -0
- package/lib/types/host/authorized-catalog.js +13 -4
- package/lib/types/host/authorized-catalog.js.map +1 -1
- package/lib/types/host/claude-native-oauth.d.ts +17 -0
- package/lib/types/host/claude-native-oauth.js +274 -0
- package/lib/types/host/claude-native-oauth.js.map +1 -0
- package/lib/types/host/claude-own-route.d.ts +45 -0
- package/lib/types/host/claude-own-route.js +375 -0
- package/lib/types/host/claude-own-route.js.map +1 -0
- package/lib/types/host/cli-account-binding.d.ts +2 -1
- package/lib/types/host/cli-account-binding.js +64 -21
- package/lib/types/host/cli-account-binding.js.map +1 -1
- package/lib/types/host/cli-executable-paths.d.ts +30 -0
- package/lib/types/host/cli-executable-paths.js +272 -0
- package/lib/types/host/cli-executable-paths.js.map +1 -0
- package/lib/types/host/codex-models.d.ts +3 -1
- package/lib/types/host/codex-models.js +41 -4
- package/lib/types/host/codex-models.js.map +1 -1
- package/lib/types/host/extended-adapters.d.ts +3 -2
- package/lib/types/host/extended-adapters.js +9 -7
- package/lib/types/host/extended-adapters.js.map +1 -1
- package/lib/types/host/first-party-models.d.ts +5 -0
- package/lib/types/host/first-party-models.js +173 -50
- package/lib/types/host/first-party-models.js.map +1 -1
- package/lib/types/host/hermes-accounts.js +68 -9
- package/lib/types/host/hermes-accounts.js.map +1 -1
- package/lib/types/host/hermes-adapter.d.ts +3 -0
- package/lib/types/host/hermes-adapter.js +13 -4
- package/lib/types/host/hermes-adapter.js.map +1 -1
- package/lib/types/host/hermes-installation.js +54 -35
- package/lib/types/host/hermes-installation.js.map +1 -1
- package/lib/types/host/hermes-models.js +21 -2
- package/lib/types/host/hermes-models.js.map +1 -1
- package/lib/types/host/hermes-native-entry.py +48 -13
- package/lib/types/host/hermes-nous-refresh.py +331 -0
- package/lib/types/host/hermes-nous.d.ts +5 -1
- package/lib/types/host/hermes-nous.js +5 -5
- package/lib/types/host/hermes-nous.js.map +1 -1
- package/lib/types/host/hermes-renewal.d.ts +27 -0
- package/lib/types/host/hermes-renewal.js +292 -0
- package/lib/types/host/hermes-renewal.js.map +1 -0
- package/lib/types/host/hermes-windows-installation.d.ts +5 -0
- package/lib/types/host/hermes-windows-installation.js +91 -0
- package/lib/types/host/hermes-windows-installation.js.map +1 -0
- package/lib/types/host/index.d.ts +12 -0
- package/lib/types/host/index.js +138 -8
- package/lib/types/host/index.js.map +1 -1
- package/lib/types/host/kimi-accounts.d.ts +2 -0
- package/lib/types/host/kimi-accounts.js +4 -2
- package/lib/types/host/kimi-accounts.js.map +1 -1
- package/lib/types/host/kimi-oauth-models.d.ts +14 -0
- package/lib/types/host/kimi-oauth-models.js +246 -0
- package/lib/types/host/kimi-oauth-models.js.map +1 -0
- package/lib/types/host/mimo-metadata-cache.d.ts +22 -0
- package/lib/types/host/mimo-metadata-cache.js +121 -0
- package/lib/types/host/mimo-metadata-cache.js.map +1 -0
- package/lib/types/host/native-capability-cache.d.ts +11 -0
- package/lib/types/host/native-capability-cache.js +94 -0
- package/lib/types/host/native-capability-cache.js.map +1 -0
- package/lib/types/host/native-launch.mjs +62 -7
- package/lib/types/host/native-process.d.ts +3 -1
- package/lib/types/host/native-process.js +30 -5
- package/lib/types/host/native-process.js.map +1 -1
- package/lib/types/host/native-spawn.mjs +32 -0
- package/lib/types/host/opencode-native.js +13 -0
- package/lib/types/host/opencode-native.js.map +1 -1
- package/lib/types/host/pi-installation.d.mts +1 -1
- package/lib/types/host/pi-installation.mjs +27 -3
- package/lib/types/host/pi-omp-adapter.js +17 -3
- package/lib/types/host/pi-omp-adapter.js.map +1 -1
- package/lib/types/host/pi-omp-native.js +5 -3
- package/lib/types/host/pi-omp-native.js.map +1 -1
- package/lib/types/host/pi-omp-refresh.mjs +3 -3
- package/lib/types/host/private-launch.mjs +23 -0
- package/lib/types/host/process.d.ts +3 -0
- package/lib/types/host/process.js +3 -1
- package/lib/types/host/process.js.map +1 -1
- package/lib/types/host/routing.js +25 -2
- package/lib/types/host/routing.js.map +1 -1
- package/lib/types/host/runtime.js +21 -5
- package/lib/types/host/runtime.js.map +1 -1
- package/lib/types/host/settings-catalog-cache.d.ts +28 -0
- package/lib/types/host/settings-catalog-cache.js +189 -0
- package/lib/types/host/settings-catalog-cache.js.map +1 -0
- package/lib/types/host/windows-account-bootstrap.ps1 +44 -0
- package/lib/types/host/windows-account-launch.mjs +47 -0
- package/lib/types/host/windows-account-owner.ps1 +137 -0
- package/lib/types/host/windows-account-stdio.mjs +19 -0
- package/lib/types/host/windows-account-terminal.d.ts +17 -0
- package/lib/types/host/windows-account-terminal.js +208 -0
- package/lib/types/host/windows-account-terminal.js.map +1 -0
- package/lib/types/host/windows-agy-account.ps1 +81 -0
- package/lib/types/host/windows-cli-installation.d.ts +35 -0
- package/lib/types/host/windows-cli-installation.js +164 -0
- package/lib/types/host/windows-cli-installation.js.map +1 -0
- package/lib/types/host/windows-codex-launch.d.ts +9 -0
- package/lib/types/host/windows-codex-launch.js +216 -0
- package/lib/types/host/windows-codex-launch.js.map +1 -0
- package/lib/types/host/windows-desktop-cli-installation.d.ts +20 -0
- package/lib/types/host/windows-desktop-cli-installation.js +420 -0
- package/lib/types/host/windows-desktop-cli-installation.js.map +1 -0
- package/lib/types/host/windows-hidden-launch.mjs +51 -0
- package/lib/types/host/windows-hidden-process.d.ts +12 -0
- package/lib/types/host/windows-hidden-process.js +116 -0
- package/lib/types/host/windows-hidden-process.js.map +1 -0
- package/lib/types/host/zcode-adapter.js +5 -1
- package/lib/types/host/zcode-adapter.js.map +1 -1
- package/lib/types/host/zcode-grok-accounts.d.ts +3 -1
- package/lib/types/host/zcode-grok-accounts.js +60 -11
- package/lib/types/host/zcode-grok-accounts.js.map +1 -1
- package/lib/types/shared/accounts.d.ts +4 -0
- package/lib/types/shared/cli-settings.d.ts +8 -0
- package/lib/windows-account-bootstrap.ps1 +44 -0
- package/lib/windows-account-launch.mjs +47 -0
- package/lib/windows-account-owner.ps1 +137 -0
- package/lib/windows-account-stdio.mjs +19 -0
- package/lib/windows-agy-account.ps1 +81 -0
- package/lib/windows-hidden-launch.mjs +51 -0
- package/lib/zcode-resume.mjs +2 -2
- package/package.json +2 -2
|
@@ -0,0 +1,420 @@
|
|
|
1
|
+
import * as nodeFs from 'node:fs';
|
|
2
|
+
import { createRequire } from 'node:module';
|
|
3
|
+
import { homedir } from 'node:os';
|
|
4
|
+
import { win32 } from 'node:path';
|
|
5
|
+
import { WindowsCliInstallationError } from "./windows-cli-installation.js";
|
|
6
|
+
import { ProcessCleanupUnconfirmedError } from "./process.js";
|
|
7
|
+
const label = (cli) => (cli === 'zcode' ? 'ZCode' : 'OpenCode');
|
|
8
|
+
const failure = (cli, message = '桌面安装信息探测失败') => new WindowsCliInstallationError(`${label(cli)} ${message},请配置 ${cli}Executable`);
|
|
9
|
+
/** Fixed OS metadata query only. No installer, shortcut target, or user command is executed. */
|
|
10
|
+
export const WINDOWS_DESKTOP_INSTALL_QUERY = String.raw `
|
|
11
|
+
$ErrorActionPreference='Stop'
|
|
12
|
+
[Console]::OutputEncoding=[Text.UTF8Encoding]::new($false)
|
|
13
|
+
$watch=[Diagnostics.Stopwatch]::StartNew()
|
|
14
|
+
$rows=[Collections.Generic.List[object]]::new()
|
|
15
|
+
$complete=$true
|
|
16
|
+
$seen=0
|
|
17
|
+
function Bound {
|
|
18
|
+
$script:seen++
|
|
19
|
+
if($watch.ElapsedMilliseconds -gt 8000 -or $script:seen -gt 4096 -or $rows.Count -ge 128){throw 'Metadata limit'}
|
|
20
|
+
}
|
|
21
|
+
function Product([string]$name) {
|
|
22
|
+
if($name -match '^ZCode(?:\s.*)?$'){return 'zcode'}
|
|
23
|
+
if($name -match '^OpenCode(?:\s.*)?$'){return 'opencode'}
|
|
24
|
+
return $null
|
|
25
|
+
}
|
|
26
|
+
function CleanFile([string]$value,[bool]$icon) {
|
|
27
|
+
if([string]::IsNullOrWhiteSpace($value)){return $null}
|
|
28
|
+
$p=$value.Trim()
|
|
29
|
+
if($icon){$p=$p -replace ',\s*-?\d+\s*$',''}
|
|
30
|
+
if($p.StartsWith('"') -and $p.EndsWith('"')){$p=$p.Substring(1,$p.Length-2)}
|
|
31
|
+
if($p -match '[\x00-\x1f\x7f"]' -or $p -notmatch '^[A-Za-z]:[\\/]' -or $p -notmatch '\.(?:exe|ico)$'){return $null}
|
|
32
|
+
return $p
|
|
33
|
+
}
|
|
34
|
+
function AddRoot([string]$cli,[string]$source,[string]$value) {
|
|
35
|
+
if([string]::IsNullOrWhiteSpace($value)){return}
|
|
36
|
+
Bound
|
|
37
|
+
$p=$value.Trim().Trim('"')
|
|
38
|
+
if($p -match '[\x00-\x1f\x7f"]' -or $p -notmatch '^[A-Za-z]:[\\/]'){return}
|
|
39
|
+
$rows.Add([ordered]@{cli=$cli;source=$source;root=$p})
|
|
40
|
+
}
|
|
41
|
+
function AddTarget([string]$cli,[string]$source,[string]$value,[bool]$icon) {
|
|
42
|
+
$p=CleanFile $value $icon
|
|
43
|
+
if(!$p){return}
|
|
44
|
+
Bound
|
|
45
|
+
$rows.Add([ordered]@{cli=$cli;source=$source;target=$p})
|
|
46
|
+
}
|
|
47
|
+
$shell=$null
|
|
48
|
+
try {
|
|
49
|
+
# Defaults are independent hints: deleting shortcuts/registration does not
|
|
50
|
+
# hide a complete installation left at a known vendor location.
|
|
51
|
+
if($env:LOCALAPPDATA) {
|
|
52
|
+
foreach($leaf in @('Programs\ZCode')){AddRoot 'zcode' 'default-location' (Join-Path $env:LOCALAPPDATA $leaf)}
|
|
53
|
+
foreach($leaf in @('Programs\@opencodedesktop','Programs\OpenCode','OpenCode')){AddRoot 'opencode' 'default-location' (Join-Path $env:LOCALAPPDATA $leaf)}
|
|
54
|
+
}
|
|
55
|
+
foreach($baseDir in @($env:ProgramFiles,[Environment]::GetEnvironmentVariable('ProgramFiles(x86)'))) {
|
|
56
|
+
if($baseDir){AddRoot 'zcode' 'default-location' (Join-Path $baseDir 'ZCode');AddRoot 'opencode' 'default-location' (Join-Path $baseDir 'OpenCode')}
|
|
57
|
+
}
|
|
58
|
+
foreach($hive in @([Microsoft.Win32.RegistryHive]::CurrentUser,[Microsoft.Win32.RegistryHive]::LocalMachine)) {
|
|
59
|
+
foreach($view in @([Microsoft.Win32.RegistryView]::Registry64,[Microsoft.Win32.RegistryView]::Registry32)) {
|
|
60
|
+
Bound
|
|
61
|
+
$base=[Microsoft.Win32.RegistryKey]::OpenBaseKey($hive,$view)
|
|
62
|
+
try {
|
|
63
|
+
$uninstall=$base.OpenSubKey('Software\Microsoft\Windows\CurrentVersion\Uninstall')
|
|
64
|
+
if($uninstall) {
|
|
65
|
+
try {
|
|
66
|
+
foreach($name in $uninstall.GetSubKeyNames()) {
|
|
67
|
+
Bound
|
|
68
|
+
$key=$uninstall.OpenSubKey($name)
|
|
69
|
+
if(!$key){continue}
|
|
70
|
+
try {
|
|
71
|
+
$cli=Product ([string]$key.GetValue('DisplayName'))
|
|
72
|
+
if(!$cli){continue}
|
|
73
|
+
AddRoot $cli 'uninstall-location' ([string]$key.GetValue('InstallLocation'))
|
|
74
|
+
AddTarget $cli 'uninstall-icon' ([string]$key.GetValue('DisplayIcon')) $true
|
|
75
|
+
} finally {$key.Dispose()}
|
|
76
|
+
}
|
|
77
|
+
} finally {$uninstall.Dispose()}
|
|
78
|
+
}
|
|
79
|
+
foreach($entry in @(@('zcode','ZCode.exe'),@('opencode','OpenCode.exe'),@('opencode','opencode-cli.exe'))) {
|
|
80
|
+
Bound
|
|
81
|
+
$key=$base.OpenSubKey('Software\Microsoft\Windows\CurrentVersion\App Paths\'+$entry[1])
|
|
82
|
+
if(!$key){continue}
|
|
83
|
+
try {AddTarget $entry[0] 'app-path' ([string]$key.GetValue('')) $false} finally {$key.Dispose()}
|
|
84
|
+
}
|
|
85
|
+
} finally {$base.Dispose()}
|
|
86
|
+
}
|
|
87
|
+
}
|
|
88
|
+
# Read only image paths of exact product names, never arguments or accounts.
|
|
89
|
+
foreach($process in @(Get-Process -Name 'ZCode','OpenCode','OpenCode Beta','OpenCode Dev','OpenCode Desktop','OpenCode-Beta','OpenCode-Dev','OpenCode-Desktop' -ErrorAction SilentlyContinue)) {
|
|
90
|
+
Bound
|
|
91
|
+
$target=[string]$process.Path
|
|
92
|
+
if($target){AddTarget $(if($process.ProcessName -ieq 'ZCode'){'zcode'}else{'opencode'}) 'running-process' $target $false}
|
|
93
|
+
}
|
|
94
|
+
$shell=New-Object -ComObject Shell.Application
|
|
95
|
+
$queue=[Collections.Generic.Queue[object]]::new()
|
|
96
|
+
$visited=[Collections.Generic.HashSet[string]]::new([StringComparer]::OrdinalIgnoreCase)
|
|
97
|
+
foreach($folder in @('StartMenu','CommonStartMenu','DesktopDirectory','CommonDesktopDirectory')) {
|
|
98
|
+
$path=[Environment]::GetFolderPath([Environment+SpecialFolder]::$folder)
|
|
99
|
+
$maxDepth=if($folder -match 'StartMenu'){4}else{0}
|
|
100
|
+
if($path -and $visited.Add($path)){$queue.Enqueue(@($path,0,$maxDepth))}
|
|
101
|
+
}
|
|
102
|
+
while($queue.Count -gt 0) {
|
|
103
|
+
Bound
|
|
104
|
+
if($visited.Count -gt 256){throw 'Directory limit'}
|
|
105
|
+
$entry=$queue.Dequeue();$directory=[IO.DirectoryInfo]::new([string]$entry[0]);$depth=[int]$entry[1];$maxDepth=[int]$entry[2]
|
|
106
|
+
if(!$directory.Exists -or ($directory.Attributes -band [IO.FileAttributes]::ReparsePoint)){continue}
|
|
107
|
+
foreach($item in $directory.GetFileSystemInfos()) {
|
|
108
|
+
Bound
|
|
109
|
+
if($item.Attributes -band [IO.FileAttributes]::ReparsePoint){continue}
|
|
110
|
+
if($item -is [IO.DirectoryInfo]) {
|
|
111
|
+
if($depth -lt $maxDepth -and $visited.Add($item.FullName)){$queue.Enqueue(@($item.FullName,$depth+1,$maxDepth))}
|
|
112
|
+
# Only known shell folders and their bounded descendants are searched.
|
|
113
|
+
continue
|
|
114
|
+
}
|
|
115
|
+
if($item.Extension -ine '.lnk'){continue}
|
|
116
|
+
$cli=Product $item.BaseName
|
|
117
|
+
if(!$cli){continue}
|
|
118
|
+
$folder=$null;$linkItem=$null;$link=$null
|
|
119
|
+
try {
|
|
120
|
+
$folder=$shell.Namespace($directory.FullName)
|
|
121
|
+
if(!$folder){throw 'Shortcut metadata unavailable'}
|
|
122
|
+
$linkItem=$folder.ParseName($item.Name)
|
|
123
|
+
if(!$linkItem -or !$linkItem.IsLink){throw 'Shortcut metadata unavailable'}
|
|
124
|
+
$link=$linkItem.GetLink
|
|
125
|
+
$target=CleanFile ([string]$link.Path) $false
|
|
126
|
+
$name=if($target){[IO.Path]::GetFileName($target)}else{''}
|
|
127
|
+
if(($cli -eq 'zcode' -and $name -ieq 'ZCode.exe') -or ($cli -eq 'opencode' -and $name -match '^(?:OpenCode(?:[ -](?:Beta|Dev|Desktop))?|opencode-cli)\.exe$')) {
|
|
128
|
+
AddTarget $cli 'shortcut' $target $false
|
|
129
|
+
}
|
|
130
|
+
} finally {
|
|
131
|
+
foreach($com in @($link,$linkItem,$folder)){if($com -and [Runtime.InteropServices.Marshal]::IsComObject($com)){[void][Runtime.InteropServices.Marshal]::FinalReleaseComObject($com)}}
|
|
132
|
+
}
|
|
133
|
+
}
|
|
134
|
+
}
|
|
135
|
+
} catch {$complete=$false}
|
|
136
|
+
finally {if($shell -and [Runtime.InteropServices.Marshal]::IsComObject($shell)){[void][Runtime.InteropServices.Marshal]::FinalReleaseComObject($shell)}}
|
|
137
|
+
$json=[ordered]@{schema=1;complete=$complete;records=@($rows.ToArray())}|ConvertTo-Json -Depth 5 -Compress
|
|
138
|
+
if([Text.Encoding]::UTF8.GetByteCount($json) -gt 65536){$json='{"schema":1,"complete":false,"records":[]}'}
|
|
139
|
+
[Console]::WriteLine($json)
|
|
140
|
+
`;
|
|
141
|
+
let physicalFiles;
|
|
142
|
+
/** Installation identity is about disk files, not Electron's virtual ASAR tree. */
|
|
143
|
+
function physicalFs() {
|
|
144
|
+
return (physicalFiles ??= process.versions.electron
|
|
145
|
+
? createRequire(import.meta.url)('original-fs')
|
|
146
|
+
: nodeFs);
|
|
147
|
+
}
|
|
148
|
+
function ordinary(path) {
|
|
149
|
+
const { statSync, accessSync, constants, realpathSync } = physicalFs();
|
|
150
|
+
try {
|
|
151
|
+
const info = statSync(path);
|
|
152
|
+
if (!info.isFile() || !info.size)
|
|
153
|
+
throw new Error('Invalid file');
|
|
154
|
+
accessSync(path, constants.R_OK);
|
|
155
|
+
return realpathSync(path);
|
|
156
|
+
}
|
|
157
|
+
catch (error) {
|
|
158
|
+
if (['ENOENT', 'ENOTDIR'].includes(error.code))
|
|
159
|
+
return undefined;
|
|
160
|
+
throw error;
|
|
161
|
+
}
|
|
162
|
+
}
|
|
163
|
+
function directory(path) {
|
|
164
|
+
const { statSync, realpathSync } = physicalFs();
|
|
165
|
+
try {
|
|
166
|
+
return statSync(path).isDirectory() ? realpathSync(path) : undefined;
|
|
167
|
+
}
|
|
168
|
+
catch (error) {
|
|
169
|
+
if (['ENOENT', 'ENOTDIR'].includes(error.code))
|
|
170
|
+
return undefined;
|
|
171
|
+
throw error;
|
|
172
|
+
}
|
|
173
|
+
}
|
|
174
|
+
function pe(path) {
|
|
175
|
+
const canonical = ordinary(path);
|
|
176
|
+
if (!canonical)
|
|
177
|
+
return undefined;
|
|
178
|
+
const { openSync, fstatSync, readSync, closeSync } = physicalFs();
|
|
179
|
+
const fd = openSync(canonical, 'r');
|
|
180
|
+
try {
|
|
181
|
+
const info = fstatSync(fd), head = Buffer.alloc(64), signature = Buffer.alloc(4);
|
|
182
|
+
if (readSync(fd, head, 0, 64, 0) !== 64 || head.toString('ascii', 0, 2) !== 'MZ')
|
|
183
|
+
throw new Error('Invalid PE');
|
|
184
|
+
const offset = head.readUInt32LE(0x3c);
|
|
185
|
+
if (offset < 64 ||
|
|
186
|
+
offset + 4 > info.size ||
|
|
187
|
+
readSync(fd, signature, 0, 4, offset) !== 4 ||
|
|
188
|
+
signature.toString('hex') !== '50450000')
|
|
189
|
+
throw new Error('Invalid PE');
|
|
190
|
+
return canonical;
|
|
191
|
+
}
|
|
192
|
+
finally {
|
|
193
|
+
closeSync(fd);
|
|
194
|
+
}
|
|
195
|
+
}
|
|
196
|
+
const files = { ordinaryFile: ordinary, directory, peFile: pe };
|
|
197
|
+
const contained = (root, entry, path) => {
|
|
198
|
+
const relative = path.relative(root.toLowerCase(), entry.toLowerCase());
|
|
199
|
+
return (!!relative && !path.isAbsolute(relative) && relative !== '..' && !relative.startsWith('..' + path.sep));
|
|
200
|
+
};
|
|
201
|
+
function safePath(value, path) {
|
|
202
|
+
if (typeof value !== 'string' ||
|
|
203
|
+
!value ||
|
|
204
|
+
value.length > 2048 ||
|
|
205
|
+
/[\x00-\x1f\x7f"]/.test(value) ||
|
|
206
|
+
!path.isAbsolute(value) ||
|
|
207
|
+
(path === win32 && (!/^[A-Za-z]:[\\/]/.test(value) || /^[\\/]{2}/.test(value))) ||
|
|
208
|
+
value.split(/[\\/]/).includes('..'))
|
|
209
|
+
throw new Error('Invalid path');
|
|
210
|
+
return path.normalize(value);
|
|
211
|
+
}
|
|
212
|
+
function iconPath(value, path) {
|
|
213
|
+
if (typeof value !== 'string')
|
|
214
|
+
throw new Error('Invalid path');
|
|
215
|
+
let target = value.trim().replace(/,\s*-?\d+\s*$/, '');
|
|
216
|
+
if (target.startsWith('"') && target.endsWith('"'))
|
|
217
|
+
target = target.slice(1, -1);
|
|
218
|
+
return safePath(target, path);
|
|
219
|
+
}
|
|
220
|
+
function installationEntries(cli, root, fs, path) {
|
|
221
|
+
const foundRoot = fs.directory(root);
|
|
222
|
+
if (!foundRoot)
|
|
223
|
+
return [];
|
|
224
|
+
const canonicalRoot = safePath(foundRoot, path);
|
|
225
|
+
const entries = [];
|
|
226
|
+
if (cli === 'zcode') {
|
|
227
|
+
const entry = fs.ordinaryFile(path.join(root, 'resources', 'glm', 'zcode.cjs'));
|
|
228
|
+
const provider = fs.ordinaryFile(path.join(root, 'resources', 'config', 'provider', 'zcode-builtin.json'));
|
|
229
|
+
if (entry &&
|
|
230
|
+
provider &&
|
|
231
|
+
contained(canonicalRoot, entry, path) &&
|
|
232
|
+
contained(canonicalRoot, provider, path))
|
|
233
|
+
entries.push(entry);
|
|
234
|
+
else if (entry || provider)
|
|
235
|
+
throw failure(cli, '桌面 CLI 配套文件不可用');
|
|
236
|
+
}
|
|
237
|
+
else {
|
|
238
|
+
for (const candidate of [
|
|
239
|
+
path.join(root, 'resources', 'opencode-cli.exe'),
|
|
240
|
+
path.join(root, 'opencode-cli.exe'),
|
|
241
|
+
]) {
|
|
242
|
+
const entry = fs.peFile(candidate);
|
|
243
|
+
if (entry) {
|
|
244
|
+
if (!contained(canonicalRoot, entry, path))
|
|
245
|
+
throw failure(cli, '桌面 CLI 入口被重定向');
|
|
246
|
+
entries.push(entry);
|
|
247
|
+
}
|
|
248
|
+
}
|
|
249
|
+
}
|
|
250
|
+
const desktopNames = cli === 'zcode'
|
|
251
|
+
? ['ZCode.exe']
|
|
252
|
+
: [
|
|
253
|
+
'OpenCode.exe',
|
|
254
|
+
'OpenCode Beta.exe',
|
|
255
|
+
'OpenCode Dev.exe',
|
|
256
|
+
'OpenCode Desktop.exe',
|
|
257
|
+
'OpenCode-Beta.exe',
|
|
258
|
+
'OpenCode-Dev.exe',
|
|
259
|
+
'OpenCode-Desktop.exe',
|
|
260
|
+
];
|
|
261
|
+
if (!entries.length && desktopNames.some((name) => fs.ordinaryFile(path.join(root, name))))
|
|
262
|
+
throw failure(cli, '桌面已存在,但没有可用独立 CLI');
|
|
263
|
+
return entries;
|
|
264
|
+
}
|
|
265
|
+
/** Metadata is a bounded hint, never a command or an account source. */
|
|
266
|
+
export function windowsDesktopCliFromMetadata(cli, raw, options = {}) {
|
|
267
|
+
const path = options.path ?? win32, fs = options.files ?? files;
|
|
268
|
+
try {
|
|
269
|
+
if (Buffer.byteLength(raw, 'utf8') > 65536)
|
|
270
|
+
throw new Error('Metadata limit');
|
|
271
|
+
const value = JSON.parse(raw.replace(/^\uFEFF/, '').trim());
|
|
272
|
+
if (!value ||
|
|
273
|
+
value.schema !== 1 ||
|
|
274
|
+
value.complete !== true ||
|
|
275
|
+
!Array.isArray(value.records) ||
|
|
276
|
+
value.records.length > 128)
|
|
277
|
+
throw new Error('Invalid metadata');
|
|
278
|
+
const roots = new Map();
|
|
279
|
+
for (const record of value.records) {
|
|
280
|
+
if (!record ||
|
|
281
|
+
typeof record !== 'object' ||
|
|
282
|
+
Array.isArray(record) ||
|
|
283
|
+
!['zcode', 'opencode'].includes(record.cli) ||
|
|
284
|
+
![
|
|
285
|
+
'uninstall-location',
|
|
286
|
+
'uninstall-icon',
|
|
287
|
+
'app-path',
|
|
288
|
+
'shortcut',
|
|
289
|
+
'default-location',
|
|
290
|
+
'running-process',
|
|
291
|
+
].includes(record.source) ||
|
|
292
|
+
Object.keys(record).some((key) => !['cli', 'source', 'root', 'target'].includes(key)))
|
|
293
|
+
throw new Error('Invalid metadata');
|
|
294
|
+
if (record.cli !== cli)
|
|
295
|
+
continue;
|
|
296
|
+
let root;
|
|
297
|
+
if (record.root !== undefined &&
|
|
298
|
+
record.target === undefined &&
|
|
299
|
+
['uninstall-location', 'default-location'].includes(record.source))
|
|
300
|
+
root = safePath(record.root, path);
|
|
301
|
+
else if (record.target !== undefined &&
|
|
302
|
+
record.root === undefined &&
|
|
303
|
+
!['uninstall-location', 'default-location'].includes(record.source)) {
|
|
304
|
+
const target = iconPath(record.target, path), name = path.basename(target).toLowerCase();
|
|
305
|
+
if (record.source === 'uninstall-icon') {
|
|
306
|
+
if (!/\.(?:exe|ico)$/i.test(name))
|
|
307
|
+
throw new Error('Invalid icon');
|
|
308
|
+
}
|
|
309
|
+
else if (cli === 'zcode'
|
|
310
|
+
? name !== 'zcode.exe'
|
|
311
|
+
: !/^(?:opencode(?:[ -](?:beta|dev|desktop))?|opencode-cli)\.exe$/.test(name))
|
|
312
|
+
throw new Error('Invalid target');
|
|
313
|
+
root = path.dirname(target);
|
|
314
|
+
if (cli === 'opencode' && name === 'opencode-cli.exe') {
|
|
315
|
+
if (path.basename(root).toLowerCase() === 'resources')
|
|
316
|
+
root = path.dirname(root);
|
|
317
|
+
}
|
|
318
|
+
}
|
|
319
|
+
else
|
|
320
|
+
throw new Error('Invalid metadata');
|
|
321
|
+
roots.set(root.toLowerCase(), root);
|
|
322
|
+
}
|
|
323
|
+
const candidates = [];
|
|
324
|
+
let incomplete;
|
|
325
|
+
for (const root of roots.values()) {
|
|
326
|
+
try {
|
|
327
|
+
candidates.push(...installationEntries(cli, root, fs, path));
|
|
328
|
+
}
|
|
329
|
+
catch (error) {
|
|
330
|
+
// An old desktop missing its companion CLI must not hide a complete
|
|
331
|
+
// installation. Read/access errors still fail the overall discovery.
|
|
332
|
+
if (!(error instanceof WindowsCliInstallationError))
|
|
333
|
+
throw error;
|
|
334
|
+
incomplete ??= error;
|
|
335
|
+
}
|
|
336
|
+
}
|
|
337
|
+
const unique = new Map(candidates.map((entry) => [entry.toLowerCase(), entry]));
|
|
338
|
+
if (unique.size > 1)
|
|
339
|
+
throw failure(cli, '发现多个可用安装');
|
|
340
|
+
if (!unique.size && incomplete)
|
|
341
|
+
throw incomplete;
|
|
342
|
+
return [...unique.values()][0];
|
|
343
|
+
}
|
|
344
|
+
catch (error) {
|
|
345
|
+
if (error instanceof WindowsCliInstallationError)
|
|
346
|
+
throw error;
|
|
347
|
+
throw failure(cli);
|
|
348
|
+
}
|
|
349
|
+
}
|
|
350
|
+
export async function findWindowsDesktopCli(cli, capture, signal, env = process.env) {
|
|
351
|
+
signal.throwIfAborted();
|
|
352
|
+
const root = env.SystemRoot || env.WINDIR || 'C:\\Windows';
|
|
353
|
+
let raw;
|
|
354
|
+
try {
|
|
355
|
+
const command = win32.join(safePath(root, win32), 'System32', 'WindowsPowerShell', 'v1.0', 'powershell.exe');
|
|
356
|
+
raw = await capture([
|
|
357
|
+
command,
|
|
358
|
+
'-NoLogo',
|
|
359
|
+
'-NoProfile',
|
|
360
|
+
'-NonInteractive',
|
|
361
|
+
'-EncodedCommand',
|
|
362
|
+
Buffer.from(WINDOWS_DESKTOP_INSTALL_QUERY, 'utf16le').toString('base64'),
|
|
363
|
+
], homedir());
|
|
364
|
+
}
|
|
365
|
+
catch (error) {
|
|
366
|
+
if (error instanceof ProcessCleanupUnconfirmedError)
|
|
367
|
+
throw error;
|
|
368
|
+
signal.throwIfAborted();
|
|
369
|
+
throw failure(cli);
|
|
370
|
+
}
|
|
371
|
+
signal.throwIfAborted();
|
|
372
|
+
return windowsDesktopCliFromMetadata(cli, raw);
|
|
373
|
+
}
|
|
374
|
+
/** Do not treat a PATH/explicit Desktop GUI as the command-line binary. */
|
|
375
|
+
export function windowsOpenCodeDesktopCli(executable, explicit = false, options = {}) {
|
|
376
|
+
const path = options.path ?? win32, fs = options.files ?? files;
|
|
377
|
+
if (!/^opencode(?:[ -](?:beta|dev|desktop))?\.exe$/i.test(path.basename(executable)))
|
|
378
|
+
return undefined;
|
|
379
|
+
const root = path.dirname(executable);
|
|
380
|
+
try {
|
|
381
|
+
const marker = fs.ordinaryFile(path.join(root, 'resources', 'app.asar'));
|
|
382
|
+
// Old Tauri bundles place a CLI alongside their GUI. The GUI PE subsystem
|
|
383
|
+
// must confirm that case; a standalone console opencode.exe is unchanged.
|
|
384
|
+
let legacyGui = false;
|
|
385
|
+
if (!marker && fs.ordinaryFile(executable)) {
|
|
386
|
+
const { openSync, readSync, closeSync } = physicalFs();
|
|
387
|
+
const fd = openSync(executable, 'r');
|
|
388
|
+
try {
|
|
389
|
+
const head = Buffer.alloc(64), kind = Buffer.alloc(2), signature = Buffer.alloc(4);
|
|
390
|
+
if (readSync(fd, head, 0, 64, 0) === 64 && head.toString('ascii', 0, 2) === 'MZ') {
|
|
391
|
+
const peOffset = head.readUInt32LE(0x3c), offset = peOffset + 24 + 68;
|
|
392
|
+
legacyGui =
|
|
393
|
+
peOffset >= 64 &&
|
|
394
|
+
readSync(fd, signature, 0, 4, peOffset) === 4 &&
|
|
395
|
+
signature.toString('hex') === '50450000' &&
|
|
396
|
+
readSync(fd, kind, 0, 2, offset) === 2 &&
|
|
397
|
+
kind.readUInt16LE(0) === 2;
|
|
398
|
+
}
|
|
399
|
+
}
|
|
400
|
+
finally {
|
|
401
|
+
closeSync(fd);
|
|
402
|
+
}
|
|
403
|
+
}
|
|
404
|
+
if (!marker && !legacyGui)
|
|
405
|
+
return undefined;
|
|
406
|
+
if (explicit)
|
|
407
|
+
throw failure('opencode', '执行路径指向桌面主程序');
|
|
408
|
+
const entries = installationEntries('opencode', root, fs, path);
|
|
409
|
+
const unique = new Map(entries.map((entry) => [entry.toLowerCase(), entry]));
|
|
410
|
+
if (unique.size !== 1)
|
|
411
|
+
throw failure('opencode', unique.size ? '发现多个可用安装' : '桌面已存在,但没有可用独立 CLI');
|
|
412
|
+
return [...unique.values()][0];
|
|
413
|
+
}
|
|
414
|
+
catch (error) {
|
|
415
|
+
if (error instanceof WindowsCliInstallationError)
|
|
416
|
+
throw error;
|
|
417
|
+
throw failure('opencode', '桌面 CLI 入口不可用');
|
|
418
|
+
}
|
|
419
|
+
}
|
|
420
|
+
//# sourceMappingURL=windows-desktop-cli-installation.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"windows-desktop-cli-installation.js","sourceRoot":"","sources":["../../../src/host/windows-desktop-cli-installation.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
// A GUI-subsystem Electron root avoids Windows Terminal's console delegation.
|
|
2
|
+
// The enclosing Harness Job still owns this root and every native descendant.
|
|
3
|
+
import { Socket } from 'node:net'
|
|
4
|
+
import { forwardNativeStdio, spawnNativeProcess } from './native-spawn.mjs'
|
|
5
|
+
|
|
6
|
+
// Pinned Harness 0.2.0-rc.2 public control contract. This helper must remain
|
|
7
|
+
// self-contained: an ordinary child does not use the Host's SDK module loader.
|
|
8
|
+
const marker = process.env.DSH_SUBPROCESS_CONTROL
|
|
9
|
+
delete process.env.DSH_SUBPROCESS_CONTROL
|
|
10
|
+
if (marker !== 'pipe') throw new Error('Windows background control channel is unavailable')
|
|
11
|
+
// Receipts are write-only. Reading this inherited Windows pipe keeps a read
|
|
12
|
+
// operation alive after the receipt flush and prevents the relay from exiting.
|
|
13
|
+
const control = new Socket({ fd: 7, readable: false, writable: true, allowHalfOpen: true })
|
|
14
|
+
let child, sent = false
|
|
15
|
+
function receipt(value) {
|
|
16
|
+
if (sent) return
|
|
17
|
+
sent = true
|
|
18
|
+
control.end(JSON.stringify(value) + '\n', () => control.destroy())
|
|
19
|
+
}
|
|
20
|
+
control.on('error', () => {
|
|
21
|
+
child?.kill('SIGTERM')
|
|
22
|
+
process.exitCode = 1
|
|
23
|
+
})
|
|
24
|
+
try {
|
|
25
|
+
const [encoded, executable, ...argv] = process.argv.slice(2)
|
|
26
|
+
const restore = JSON.parse(encoded)
|
|
27
|
+
if (!restore || !Object.hasOwn(restore, 'nodeEnv') ||
|
|
28
|
+
(restore.nodeEnv !== null && typeof restore.nodeEnv !== 'string') || !executable)
|
|
29
|
+
throw new Error('Invalid fixed bootstrap arguments')
|
|
30
|
+
if (restore.privateUmask === true) process.umask(0o077)
|
|
31
|
+
// ELECTRON_RUN_AS_NODE belongs only to this GUI bootstrap. Preserve the
|
|
32
|
+
// original target environment, including an explicit deletion of that value.
|
|
33
|
+
const env = { ...process.env }
|
|
34
|
+
for (const key of Object.keys(env))
|
|
35
|
+
if (key.toUpperCase() === 'ELECTRON_RUN_AS_NODE') delete env[key]
|
|
36
|
+
if (restore.nodeEnv !== null) env.ELECTRON_RUN_AS_NODE = restore.nodeEnv
|
|
37
|
+
child = spawnNativeProcess(executable, argv, { env, stdio: ['pipe', 'pipe', 'pipe'], detached: false })
|
|
38
|
+
forwardNativeStdio(child)
|
|
39
|
+
child.once('error', error => receipt({
|
|
40
|
+
kind: 'spawn-error',
|
|
41
|
+
code: ['ENOENT', 'EACCES', 'ENOEXEC', 'EINVAL'].includes(error.code) ? error.code : 'UNKNOWN',
|
|
42
|
+
}))
|
|
43
|
+
// A descendant may keep these pipes open after the native parent exits.
|
|
44
|
+
// Report its actual exit now; keep forwarding bytes until the pipes close.
|
|
45
|
+
// The Host's original Job remains responsible for the entire process range.
|
|
46
|
+
child.once('exit', (exitCode, signal) => receipt({ kind: 'exit', exitCode, signal }))
|
|
47
|
+
for (const signal of ['SIGTERM', 'SIGINT'])
|
|
48
|
+
process.on(signal, () => child.kill(signal))
|
|
49
|
+
} catch {
|
|
50
|
+
receipt({ kind: 'spawn-error', code: 'UNKNOWN' })
|
|
51
|
+
}
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
import type { SubprocessHandle, SubprocessSpawnSpec } from '@deepseek-ai/dsh-subprocess';
|
|
2
|
+
import type { ProcessBackend } from './process.ts';
|
|
3
|
+
export declare const isCurrentWindowsRuntime: (value: string) => boolean;
|
|
4
|
+
/** Only console-subsystem targets need a GUI bootstrap. Existing Node helpers
|
|
5
|
+
* already use Electron's GUI executable; terminal allocation stays untouched. */
|
|
6
|
+
export declare function needsWindowsHiddenLaunch(argv: readonly string[], platform: NodeJS.Platform, electron: boolean): boolean;
|
|
7
|
+
/** Window presentation only: all byte streams, collection and process-range
|
|
8
|
+
* ownership remain the SDK's. Native exit facts travel over a private channel,
|
|
9
|
+
* never stdout/stderr and never the native CLI's credential/session protocol. */
|
|
10
|
+
export declare function spawnWindowsHidden(backend: ProcessBackend, spec: SubprocessSpawnSpec, options?: {
|
|
11
|
+
privateUmask?: true;
|
|
12
|
+
}): SubprocessHandle;
|
|
@@ -0,0 +1,116 @@
|
|
|
1
|
+
import { win32 } from 'node:path';
|
|
2
|
+
import { fileURLToPath } from 'node:url';
|
|
3
|
+
const failure = () => new Error('Windows 后台 CLI 启动回执异常');
|
|
4
|
+
const bootstrap = fileURLToPath(new URL('./windows-hidden-launch.mjs', import.meta.url));
|
|
5
|
+
export const isCurrentWindowsRuntime = (value) => win32.normalize(value).toLowerCase() === win32.normalize(process.execPath).toLowerCase();
|
|
6
|
+
/** Only console-subsystem targets need a GUI bootstrap. Existing Node helpers
|
|
7
|
+
* already use Electron's GUI executable; terminal allocation stays untouched. */
|
|
8
|
+
export function needsWindowsHiddenLaunch(argv, platform, electron) {
|
|
9
|
+
return platform === 'win32' && electron && !isCurrentWindowsRuntime(argv[0]);
|
|
10
|
+
}
|
|
11
|
+
function nodeEnvironment(env) {
|
|
12
|
+
let value;
|
|
13
|
+
for (const [key, entry] of Object.entries(process.env))
|
|
14
|
+
if (key.toUpperCase() === 'ELECTRON_RUN_AS_NODE')
|
|
15
|
+
value = entry;
|
|
16
|
+
for (const [key, entry] of Object.entries(env ?? {}))
|
|
17
|
+
if (key.toUpperCase() === 'ELECTRON_RUN_AS_NODE')
|
|
18
|
+
value = entry;
|
|
19
|
+
return value ?? null;
|
|
20
|
+
}
|
|
21
|
+
/** Window presentation only: all byte streams, collection and process-range
|
|
22
|
+
* ownership remain the SDK's. Native exit facts travel over a private channel,
|
|
23
|
+
* never stdout/stderr and never the native CLI's credential/session protocol. */
|
|
24
|
+
export function spawnWindowsHidden(backend, spec, options = {}) {
|
|
25
|
+
// Current plugin calls do not use this channel. Never silently take a future
|
|
26
|
+
// consumer's control protocol or downgrade to an unhidden spawn.
|
|
27
|
+
if (spec.stdio.control)
|
|
28
|
+
throw new Error('Windows 后台 CLI 启动不能复用已占用的控制通道');
|
|
29
|
+
const inner = backend.spawn({
|
|
30
|
+
...spec,
|
|
31
|
+
argv: [process.execPath, bootstrap, JSON.stringify({ nodeEnv: nodeEnvironment(spec.env), ...options }), ...spec.argv],
|
|
32
|
+
env: { ...spec.env, ELECTRON_RUN_AS_NODE: '1' },
|
|
33
|
+
stdio: { ...spec.stdio, control: 'pipe' },
|
|
34
|
+
});
|
|
35
|
+
let cancelled = false, bytes = 0, raw = '', invalid = false;
|
|
36
|
+
const channel = inner.control;
|
|
37
|
+
if (!channel)
|
|
38
|
+
inner.terminate();
|
|
39
|
+
// Attach readers immediately so a fast metadata process cannot fill a pipe.
|
|
40
|
+
const reading = channel ? new Promise((resolve) => {
|
|
41
|
+
channel.on('data', (chunk) => {
|
|
42
|
+
bytes += Buffer.byteLength(chunk);
|
|
43
|
+
if (bytes > 1024) {
|
|
44
|
+
invalid = true;
|
|
45
|
+
channel.destroy();
|
|
46
|
+
inner.terminate();
|
|
47
|
+
}
|
|
48
|
+
else
|
|
49
|
+
raw += String(chunk);
|
|
50
|
+
});
|
|
51
|
+
channel.once('error', () => { invalid = true; inner.terminate(); resolve(); });
|
|
52
|
+
channel.once('end', resolve);
|
|
53
|
+
channel.once('close', resolve);
|
|
54
|
+
}) : Promise.resolve();
|
|
55
|
+
// A native parent can exit while its descendants retain stdout/stderr. The
|
|
56
|
+
// GUI relay must remain alive to forward those bytes, so its exit cannot be
|
|
57
|
+
// used as the native process's completion signal. Keep range exit on the SDK.
|
|
58
|
+
const outerDone = inner.done.then(async (outer) => {
|
|
59
|
+
let timer;
|
|
60
|
+
try {
|
|
61
|
+
await Promise.race([reading, new Promise((_, reject) => {
|
|
62
|
+
timer = setTimeout(() => reject(failure()), 1000);
|
|
63
|
+
})]);
|
|
64
|
+
}
|
|
65
|
+
finally {
|
|
66
|
+
clearTimeout(timer);
|
|
67
|
+
}
|
|
68
|
+
return outer;
|
|
69
|
+
});
|
|
70
|
+
void outerDone.catch(() => inner.terminate());
|
|
71
|
+
const done = (async () => {
|
|
72
|
+
try {
|
|
73
|
+
if (!channel) {
|
|
74
|
+
await inner.done;
|
|
75
|
+
throw failure();
|
|
76
|
+
}
|
|
77
|
+
const outer = await Promise.race([reading.then(() => undefined), outerDone]);
|
|
78
|
+
if (cancelled || spec.signal?.aborted)
|
|
79
|
+
return await inner.done;
|
|
80
|
+
if (invalid || (outer && (outer.exitCode !== 0 || outer.signal)))
|
|
81
|
+
throw failure();
|
|
82
|
+
const value = JSON.parse(raw);
|
|
83
|
+
if (!value || typeof value !== 'object' || Array.isArray(value))
|
|
84
|
+
throw failure();
|
|
85
|
+
if (value.kind === 'spawn-error' && ['ENOENT', 'EACCES', 'ENOEXEC', 'EINVAL', 'UNKNOWN'].includes(value.code))
|
|
86
|
+
throw Object.assign(new Error('Windows 后台 CLI 无法启动'), { code: value.code });
|
|
87
|
+
if (value.kind !== 'exit' ||
|
|
88
|
+
!(value.exitCode === null || (Number.isInteger(value.exitCode) && value.exitCode >= -2147483648 && value.exitCode <= 4294967295)) ||
|
|
89
|
+
!(value.signal === null || (typeof value.signal === 'string' && /^SIG[A-Z0-9]+$/.test(value.signal))) ||
|
|
90
|
+
(value.exitCode === null) === (value.signal === null))
|
|
91
|
+
throw failure();
|
|
92
|
+
return { exitCode: value.exitCode, signal: value.signal };
|
|
93
|
+
}
|
|
94
|
+
catch (error) {
|
|
95
|
+
inner.terminate();
|
|
96
|
+
if (error instanceof SyntaxError)
|
|
97
|
+
throw failure();
|
|
98
|
+
throw error;
|
|
99
|
+
}
|
|
100
|
+
finally {
|
|
101
|
+
channel?.destroy();
|
|
102
|
+
}
|
|
103
|
+
})();
|
|
104
|
+
void done.catch(() => undefined);
|
|
105
|
+
return {
|
|
106
|
+
stdin: inner.stdin,
|
|
107
|
+
stdout: inner.stdout,
|
|
108
|
+
stderr: inner.stderr,
|
|
109
|
+
collected: inner.collected,
|
|
110
|
+
control: undefined,
|
|
111
|
+
done,
|
|
112
|
+
terminate: () => { cancelled = true; channel?.destroy(); inner.terminate(); },
|
|
113
|
+
waitForExit: (signal) => inner.waitForExit(signal),
|
|
114
|
+
};
|
|
115
|
+
}
|
|
116
|
+
//# sourceMappingURL=windows-hidden-process.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"windows-hidden-process.js","sourceRoot":"","sources":["../../../src/host/windows-hidden-process.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,KAAK,EAAE,MAAM,WAAW,CAAA;AACjC,OAAO,EAAE,aAAa,EAAE,MAAM,UAAU,CAAA;AAIxC,MAAM,OAAO,GAAG,GAAG,EAAE,CAAC,IAAI,KAAK,CAAC,uBAAuB,CAAC,CAAA;AACxD,MAAM,SAAS,GAAG,aAAa,CAAC,IAAI,GAAG,CAAC,6BAA6B,EAAE,MAAM,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,CAAA;AACxF,MAAM,CAAC,MAAM,uBAAuB,GAAG,CAAC,KAAa,EAAE,EAAE,CAAC,KAAK,CAAC,SAAS,CAAC,KAAK,CAAC,CAAC,WAAW,EAAE,KAAK,KAAK,CAAC,SAAS,CAAC,OAAO,CAAC,QAAQ,CAAC,CAAC,WAAW,EAAE,CAAA;AAElJ;iFACiF;AACjF,MAAM,UAAU,wBAAwB,CAAC,IAAuB,EAAE,QAAyB,EAAE,QAAiB;IAC5G,OAAO,QAAQ,KAAK,OAAO,IAAI,QAAQ,IAAI,CAAC,uBAAuB,CAAC,IAAI,CAAC,CAAC,CAAE,CAAC,CAAA;AAC/E,CAAC;AAED,SAAS,eAAe,CAAC,GAAuB;IAC9C,IAAI,KAAyB,CAAA;IAC7B,KAAK,MAAM,CAAC,GAAG,EAAE,KAAK,CAAC,IAAI,MAAM,CAAC,OAAO,CAAC,OAAO,CAAC,GAAG,CAAC;QACpD,IAAI,GAAG,CAAC,WAAW,EAAE,KAAK,sBAAsB;YAAE,KAAK,GAAG,KAAK,CAAA;IACjE,KAAK,MAAM,CAAC,GAAG,EAAE,KAAK,CAAC,IAAI,MAAM,CAAC,OAAO,CAAC,GAAG,IAAI,EAAE,CAAC;QAClD,IAAI,GAAG,CAAC,WAAW,EAAE,KAAK,sBAAsB;YAAE,KAAK,GAAG,KAAK,CAAA;IACjE,OAAO,KAAK,IAAI,IAAI,CAAA;AACtB,CAAC;AAED;;iFAEiF;AACjF,MAAM,UAAU,kBAAkB,CAAC,OAAuB,EAAE,IAAyB,EAAE,UAAmC,EAAE;IAC1H,6EAA6E;IAC7E,iEAAiE;IACjE,IAAI,IAAI,CAAC,KAAK,CAAC,OAAO;QAAE,MAAM,IAAI,KAAK,CAAC,+BAA+B,CAAC,CAAA;IACxE,MAAM,KAAK,GAAG,OAAO,CAAC,KAAK,CAAC;QAC1B,GAAG,IAAI;QACP,IAAI,EAAE,CAAC,OAAO,CAAC,QAAQ,EAAE,SAAS,EAAE,IAAI,CAAC,SAAS,CAAC,EAAE,OAAO,EAAE,eAAe,CAAC,IAAI,CAAC,GAAG,CAAC,EAAE,GAAG,OAAO,EAAE,CAAC,EAAE,GAAG,IAAI,CAAC,IAAI,CAAC;QACrH,GAAG,EAAE,EAAE,GAAG,IAAI,CAAC,GAAG,EAAE,oBAAoB,EAAE,GAAG,EAAE;QAC/C,KAAK,EAAE,EAAE,GAAG,IAAI,CAAC,KAAK,EAAE,OAAO,EAAE,MAAM,EAAE;KAC1C,CAAC,CAAA;IACF,IAAI,SAAS,GAAG,KAAK,EAAE,KAAK,GAAG,CAAC,EAAE,GAAG,GAAG,EAAE,EAAE,OAAO,GAAG,KAAK,CAAA;IAC3D,MAAM,OAAO,GAAG,KAAK,CAAC,OAAO,CAAA;IAC7B,IAAI,CAAC,OAAO;QAAE,KAAK,CAAC,SAAS,EAAE,CAAA;IAC/B,4EAA4E;IAC5E,MAAM,OAAO,GAAG,OAAO,CAAC,CAAC,CAAC,IAAI,OAAO,CAAO,CAAC,OAAO,EAAE,EAAE;QACtD,OAAO,CAAC,EAAE,CAAC,MAAM,EAAE,CAAC,KAAsB,EAAE,EAAE;YAC5C,KAAK,IAAI,MAAM,CAAC,UAAU,CAAC,KAAK,CAAC,CAAA;YACjC,IAAI,KAAK,GAAG,IAAI,EAAE,CAAC;gBACjB,OAAO,GAAG,IAAI,CAAA;gBACd,OAAO,CAAC,OAAO,EAAE,CAAA;gBACjB,KAAK,CAAC,SAAS,EAAE,CAAA;YACnB,CAAC;;gBAAM,GAAG,IAAI,MAAM,CAAC,KAAK,CAAC,CAAA;QAC7B,CAAC,CAAC,CAAA;QACF,OAAO,CAAC,IAAI,CAAC,OAAO,EAAE,GAAG,EAAE,GAAG,OAAO,GAAG,IAAI,CAAC,CAAC,KAAK,CAAC,SAAS,EAAE,CAAC,CAAC,OAAO,EAAE,CAAA,CAAC,CAAC,CAAC,CAAA;QAC7E,OAAO,CAAC,IAAI,CAAC,KAAK,EAAE,OAAO,CAAC,CAAA;QAC5B,OAAO,CAAC,IAAI,CAAC,OAAO,EAAE,OAAO,CAAC,CAAA;IAChC,CAAC,CAAC,CAAC,CAAC,CAAC,OAAO,CAAC,OAAO,EAAE,CAAA;IACtB,2EAA2E;IAC3E,4EAA4E;IAC5E,8EAA8E;IAC9E,MAAM,SAAS,GAAG,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,KAAK,EAAE,KAAK,EAAE,EAAE;QAChD,IAAI,KAAgD,CAAA;QACpD,IAAI,CAAC;YACH,MAAM,OAAO,CAAC,IAAI,CAAC,CAAC,OAAO,EAAE,IAAI,OAAO,CAAQ,CAAC,CAAC,EAAE,MAAM,EAAE,EAAE;oBAC5D,KAAK,GAAG,UAAU,CAAC,GAAG,EAAE,CAAC,MAAM,CAAC,OAAO,EAAE,CAAC,EAAE,IAAI,CAAC,CAAA;gBACnD,CAAC,CAAC,CAAC,CAAC,CAAA;QACN,CAAC;gBAAS,CAAC;YAAC,YAAY,CAAC,KAAK,CAAC,CAAA;QAAC,CAAC;QACjC,OAAO,KAAK,CAAA;IACd,CAAC,CAAC,CAAA;IACF,KAAK,SAAS,CAAC,KAAK,CAAC,GAAG,EAAE,CAAC,KAAK,CAAC,SAAS,EAAE,CAAC,CAAA;IAC7C,MAAM,IAAI,GAAG,CAAC,KAAK,IAAgC,EAAE;QACnD,IAAI,CAAC;YACH,IAAI,CAAC,OAAO,EAAE,CAAC;gBAAC,MAAM,KAAK,CAAC,IAAI,CAAC;gBAAC,MAAM,OAAO,EAAE,CAAA;YAAC,CAAC;YACnD,MAAM,KAAK,GAAG,MAAM,OAAO,CAAC,IAAI,CAAC,CAAC,OAAO,CAAC,IAAI,CAAC,GAAG,EAAE,CAAC,SAAS,CAAC,EAAE,SAAS,CAAC,CAAC,CAAA;YAC5E,IAAI,SAAS,IAAI,IAAI,CAAC,MAAM,EAAE,OAAO;gBAAE,OAAO,MAAM,KAAK,CAAC,IAAI,CAAA;YAC9D,IAAI,OAAO,IAAI,CAAC,KAAK,IAAI,CAAC,KAAK,CAAC,QAAQ,KAAK,CAAC,IAAI,KAAK,CAAC,MAAM,CAAC,CAAC;gBAAE,MAAM,OAAO,EAAE,CAAA;YACjF,MAAM,KAAK,GAAG,IAAI,CAAC,KAAK,CAAC,GAAG,CAAC,CAAA;YAC7B,IAAI,CAAC,KAAK,IAAI,OAAO,KAAK,KAAK,QAAQ,IAAI,KAAK,CAAC,OAAO,CAAC,KAAK,CAAC;gBAAE,MAAM,OAAO,EAAE,CAAA;YAChF,IAAI,KAAK,CAAC,IAAI,KAAK,aAAa,IAAI,CAAC,QAAQ,EAAE,QAAQ,EAAE,SAAS,EAAE,QAAQ,EAAE,SAAS,CAAC,CAAC,QAAQ,CAAC,KAAK,CAAC,IAAI,CAAC;gBAC3G,MAAM,MAAM,CAAC,MAAM,CAAC,IAAI,KAAK,CAAC,qBAAqB,CAAC,EAAE,EAAE,IAAI,EAAE,KAAK,CAAC,IAAI,EAAE,CAAC,CAAA;YAC7E,IAAI,KAAK,CAAC,IAAI,KAAK,MAAM;gBACrB,CAAC,CAAC,KAAK,CAAC,QAAQ,KAAK,IAAI,IAAI,CAAC,MAAM,CAAC,SAAS,CAAC,KAAK,CAAC,QAAQ,CAAC,IAAI,KAAK,CAAC,QAAQ,IAAI,CAAC,UAAU,IAAI,KAAK,CAAC,QAAQ,IAAI,UAAU,CAAC,CAAC;gBACjI,CAAC,CAAC,KAAK,CAAC,MAAM,KAAK,IAAI,IAAI,CAAC,OAAO,KAAK,CAAC,MAAM,KAAK,QAAQ,IAAI,gBAAgB,CAAC,IAAI,CAAC,KAAK,CAAC,MAAM,CAAC,CAAC,CAAC;gBACrG,CAAC,KAAK,CAAC,QAAQ,KAAK,IAAI,CAAC,KAAK,CAAC,KAAK,CAAC,MAAM,KAAK,IAAI,CAAC;gBAAE,MAAM,OAAO,EAAE,CAAA;YAC1E,OAAO,EAAE,QAAQ,EAAE,KAAK,CAAC,QAAQ,EAAE,MAAM,EAAE,KAAK,CAAC,MAAM,EAAE,CAAA;QAC3D,CAAC;QAAC,OAAO,KAAK,EAAE,CAAC;YACf,KAAK,CAAC,SAAS,EAAE,CAAA;YACjB,IAAI,KAAK,YAAY,WAAW;gBAAE,MAAM,OAAO,EAAE,CAAA;YACjD,MAAM,KAAK,CAAA;QACb,CAAC;gBAAS,CAAC;YACT,OAAO,EAAE,OAAO,EAAE,CAAA;QACpB,CAAC;IACH,CAAC,CAAC,EAAE,CAAA;IACJ,KAAK,IAAI,CAAC,KAAK,CAAC,GAAG,EAAE,CAAC,SAAS,CAAC,CAAA;IAChC,OAAO;QACL,KAAK,EAAE,KAAK,CAAC,KAAK;QAClB,MAAM,EAAE,KAAK,CAAC,MAAM;QACpB,MAAM,EAAE,KAAK,CAAC,MAAM;QACpB,SAAS,EAAE,KAAK,CAAC,SAAS;QAC1B,OAAO,EAAE,SAAS;QAClB,IAAI;QACJ,SAAS,EAAE,GAAG,EAAE,GAAG,SAAS,GAAG,IAAI,CAAC,CAAC,OAAO,EAAE,OAAO,EAAE,CAAC,CAAC,KAAK,CAAC,SAAS,EAAE,CAAA,CAAC,CAAC;QAC5E,WAAW,EAAE,CAAC,MAAM,EAAE,EAAE,CAAC,KAAK,CAAC,WAAW,CAAC,MAAM,CAAC;KACnD,CAAA;AACH,CAAC"}
|
|
@@ -43,10 +43,14 @@ export function managedZCodeEntry(home = homedir()) {
|
|
|
43
43
|
}
|
|
44
44
|
function builtinPath(executable, builtin) {
|
|
45
45
|
const adjacent = join(dirname(executable), 'provider/zcode-builtin.json');
|
|
46
|
+
// Both Desktop bundles keep glm/zcode.cjs next to config/provider resources.
|
|
47
|
+
const bundled = join(dirname(executable), '../config/provider/zcode-builtin.json');
|
|
46
48
|
const config = builtin ??
|
|
47
49
|
(existsSync(adjacent)
|
|
48
50
|
? adjacent
|
|
49
|
-
:
|
|
51
|
+
: existsSync(bundled)
|
|
52
|
+
? bundled
|
|
53
|
+
: '/Applications/ZCode.app/Contents/Resources/config/provider/zcode-builtin.json');
|
|
50
54
|
if (!existsSync(config))
|
|
51
55
|
throw new Error('请配置与 ZCode CLI 配套的 zcodeBuiltinConfig');
|
|
52
56
|
return config;
|