dsh-cliworker-now 0.7.7 → 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 +29 -7
- package/README.md +30 -7
- package/lib/account-models.mjs +33 -5
- package/lib/client.js +575 -102
- package/lib/client.js.map +1 -1
- package/lib/index.js +7573 -6269
- package/lib/index.js.map +1 -1
- package/lib/pi-native-catalog.mjs +15 -5
- package/lib/pi-omp-refresh.mjs +3 -3
- package/lib/typert.host.js +194 -26
- package/lib/typert.remote-client.d.ts +6 -0
- package/lib/typert.remote-client.d.ts.map +1 -1
- package/lib/typert.remote-client.js +176 -26
- 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 +134 -45
- 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/host/account-models.d.mts +7 -1
- package/lib/types/host/account-models.mjs +33 -5
- package/lib/types/host/accounts.js +51 -19
- package/lib/types/host/accounts.js.map +1 -1
- package/lib/types/host/adapters.d.ts +2 -0
- package/lib/types/host/adapters.js +93 -15
- 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/claude-native-oauth.js +2 -0
- package/lib/types/host/claude-native-oauth.js.map +1 -1
- package/lib/types/host/claude-own-route.d.ts +15 -3
- package/lib/types/host/claude-own-route.js +158 -33
- package/lib/types/host/claude-own-route.js.map +1 -1
- package/lib/types/host/cli-account-binding.js +9 -4
- 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 +37 -4
- package/lib/types/host/codex-models.js.map +1 -1
- package/lib/types/host/first-party-models.d.ts +4 -0
- package/lib/types/host/first-party-models.js +43 -9
- package/lib/types/host/first-party-models.js.map +1 -1
- package/lib/types/host/hermes-accounts.js +54 -9
- package/lib/types/host/hermes-accounts.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/index.d.ts +10 -0
- package/lib/types/host/index.js +121 -6
- package/lib/types/host/index.js.map +1 -1
- package/lib/types/host/native-process.js +14 -4
- package/lib/types/host/native-process.js.map +1 -1
- package/lib/types/host/opencode-native.js +13 -0
- package/lib/types/host/opencode-native.js.map +1 -1
- package/lib/types/host/pi-omp-adapter.js +2 -2
- 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/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/runtime.js +5 -1
- 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-cli-installation.d.ts +4 -0
- package/lib/types/host/windows-cli-installation.js +7 -0
- package/lib/types/host/windows-cli-installation.js.map +1 -1
- 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 +3 -1
- package/lib/types/shared/cli-settings.d.ts +8 -0
- package/lib/windows-hidden-launch.mjs +3 -1
- 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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"}
|
|
@@ -8,7 +8,9 @@ import { forwardNativeStdio, spawnNativeProcess } from './native-spawn.mjs'
|
|
|
8
8
|
const marker = process.env.DSH_SUBPROCESS_CONTROL
|
|
9
9
|
delete process.env.DSH_SUBPROCESS_CONTROL
|
|
10
10
|
if (marker !== 'pipe') throw new Error('Windows background control channel is unavailable')
|
|
11
|
-
|
|
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 })
|
|
12
14
|
let child, sent = false
|
|
13
15
|
function receipt(value) {
|
|
14
16
|
if (sent) return
|
|
@@ -3,3 +3,11 @@ import type { CliId } from './types.ts';
|
|
|
3
3
|
export interface CliSettings {
|
|
4
4
|
enabled: Record<CliId, boolean>;
|
|
5
5
|
}
|
|
6
|
+
/** Machine-local executable selection; separate from project model preferences. */
|
|
7
|
+
export interface CliExecutablePathStatus {
|
|
8
|
+
cli: CliId;
|
|
9
|
+
path: string;
|
|
10
|
+
source: 'auto' | 'manual' | 'configured' | 'none';
|
|
11
|
+
available: boolean;
|
|
12
|
+
error?: string;
|
|
13
|
+
}
|
|
@@ -8,7 +8,9 @@ import { forwardNativeStdio, spawnNativeProcess } from './native-spawn.mjs'
|
|
|
8
8
|
const marker = process.env.DSH_SUBPROCESS_CONTROL
|
|
9
9
|
delete process.env.DSH_SUBPROCESS_CONTROL
|
|
10
10
|
if (marker !== 'pipe') throw new Error('Windows background control channel is unavailable')
|
|
11
|
-
|
|
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 })
|
|
12
14
|
let child, sent = false
|
|
13
15
|
function receipt(value) {
|
|
14
16
|
if (sent) return
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "dsh-cliworker-now",
|
|
3
|
-
"version": "0.7.
|
|
3
|
+
"version": "0.7.8",
|
|
4
4
|
"description": "Multiple agent CLI conversations in the DeepSeek Harness sidebar",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"license": "MIT",
|
|
@@ -108,4 +108,4 @@
|
|
|
108
108
|
"access": "public",
|
|
109
109
|
"registry": "https://registry.npmjs.org/"
|
|
110
110
|
}
|
|
111
|
-
}
|
|
111
|
+
}
|