@ran-sh/dsh-crew 2.2.17 → 2.2.19
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/package.json
CHANGED
package/src/dsh-cli-runtime.mjs
CHANGED
|
@@ -198,6 +198,23 @@ export function runResolvedDsh(cli, args = [], {
|
|
|
198
198
|
};
|
|
199
199
|
}
|
|
200
200
|
|
|
201
|
+
/**
|
|
202
|
+
* Environment for a package-manager child that installs Crew's own runtime.
|
|
203
|
+
*
|
|
204
|
+
* `--prefix`/`--dir` already pin the destination and scripts are disabled, so the
|
|
205
|
+
* child cannot be redirected by a variable — but it must not be *told* about the
|
|
206
|
+
* official Harness home either. Crew's installer is routinely run from inside a
|
|
207
|
+
* DSH session, whose ambient `DSH_HOME` is `~/.dsh`, and the contract these two
|
|
208
|
+
* installers carry is "installs only under the Crew home". Dropping the variable
|
|
209
|
+
* keeps that true by construction instead of by caller discipline, which is what
|
|
210
|
+
* the unit contract asserts and what an operator shell can silently break.
|
|
211
|
+
*/
|
|
212
|
+
function packageManagerEnv(env) {
|
|
213
|
+
const child = { ...env };
|
|
214
|
+
delete child.DSH_HOME;
|
|
215
|
+
return child;
|
|
216
|
+
}
|
|
217
|
+
|
|
201
218
|
/**
|
|
202
219
|
* Install a reusable DSH CLI into Crew-owned state. This is the only helper
|
|
203
220
|
* that may invoke a package manager, and callers must explicitly opt into it.
|
|
@@ -266,11 +283,12 @@ export function ensureCrewDshRuntime({
|
|
|
266
283
|
? ['add', '--dir', runtimeRoot, '--ignore-scripts', packageSpec]
|
|
267
284
|
: ['install', '--prefix', runtimeRoot, '--no-package-lock', '--ignore-scripts', '--omit=dev', packageSpec];
|
|
268
285
|
const invocation = buildDshInvocation(packageManager, packageArgs, { platform, comspec });
|
|
286
|
+
const installEnv = packageManagerEnv(env);
|
|
269
287
|
const runInstall = () => runner(invocation.command, invocation.args, {
|
|
270
288
|
encoding: 'utf8',
|
|
271
289
|
stdio: ['ignore', 'pipe', 'pipe'],
|
|
272
290
|
shell: invocation.shell,
|
|
273
|
-
env:
|
|
291
|
+
env: installEnv,
|
|
274
292
|
});
|
|
275
293
|
const result = runInstall();
|
|
276
294
|
const cli = resolveDshCli({ home, env, platform, exists, findCommand, includeCompatibility: false, read });
|
|
@@ -457,11 +475,12 @@ export function installDshInto({
|
|
|
457
475
|
? ['add', '--dir', root, '--ignore-scripts', packageSpec]
|
|
458
476
|
: ['install', '--prefix', root, '--no-package-lock', '--ignore-scripts', '--omit=dev', packageSpec];
|
|
459
477
|
const invocation = buildDshInvocation(packageManager, packageArgs, { platform, comspec });
|
|
478
|
+
const installEnv = packageManagerEnv(env);
|
|
460
479
|
const runInstall = () => runner(invocation.command, invocation.args, {
|
|
461
480
|
encoding: 'utf8',
|
|
462
481
|
stdio: ['ignore', 'pipe', 'pipe'],
|
|
463
482
|
shell: invocation.shell,
|
|
464
|
-
env:
|
|
483
|
+
env: installEnv,
|
|
465
484
|
});
|
|
466
485
|
const result = runInstall();
|
|
467
486
|
if (result.status !== 0) {
|
package/src/runtime-identity.mjs
CHANGED
|
@@ -36,7 +36,7 @@ export {
|
|
|
36
36
|
// included in the identity contract.
|
|
37
37
|
const RUNTIME_ID = randomUUID();
|
|
38
38
|
|
|
39
|
-
export const RUNTIME_VERSION = '2.2.
|
|
39
|
+
export const RUNTIME_VERSION = '2.2.19';
|
|
40
40
|
export const HUB_PROTOCOL_VERSION = 1;
|
|
41
41
|
|
|
42
42
|
export const HUB_CAPABILITIES = Object.freeze([
|
|
@@ -145,6 +145,60 @@ function Rotate-LaunchLog {
|
|
|
145
145
|
} catch { }
|
|
146
146
|
}
|
|
147
147
|
|
|
148
|
+
# A Crew-launched Harness process resolves its `env:` credential references from
|
|
149
|
+
# its own environment, and the launcher does not only run from a logon session.
|
|
150
|
+
# A terminal, a scheduled task, or an automation/agent shell can start it with a
|
|
151
|
+
# narrow environment, and then the Hub boots and answers every health check while
|
|
152
|
+
# its first job fails with CREDENTIAL_MISSING — the failure arrives long after the
|
|
153
|
+
# launch that caused it. The operator's persisted user scope is merged back in
|
|
154
|
+
# before any Harness process starts, which is what a logon start already had.
|
|
155
|
+
#
|
|
156
|
+
# Only names this process does not define are added, so a logon launch is
|
|
157
|
+
# unchanged and an explicitly exported value always wins over the registry. The
|
|
158
|
+
# skip list is what must not be taken from the user scope alone: its Path is one
|
|
159
|
+
# fragment of a real logon PATH (machine scope contributes the rest), and the rest
|
|
160
|
+
# describe the running process rather than the operator's profile.
|
|
161
|
+
$persistedEnvironmentSkip = @('Path', 'PATHEXT', 'ComSpec', 'SystemRoot', 'windir', 'TEMP', 'TMP', 'PSModulePath')
|
|
162
|
+
|
|
163
|
+
function Get-PersistedUserEnvironment {
|
|
164
|
+
$values = @{}
|
|
165
|
+
try {
|
|
166
|
+
$key = [Microsoft.Win32.Registry]::CurrentUser.OpenSubKey('Environment')
|
|
167
|
+
if ($key) {
|
|
168
|
+
try {
|
|
169
|
+
foreach ($name in $key.GetValueNames()) {
|
|
170
|
+
if ([string]::IsNullOrWhiteSpace($name)) { continue }
|
|
171
|
+
# GetValue expands REG_EXPAND_SZ, which is what a logon session sees.
|
|
172
|
+
$values[$name] = [string] $key.GetValue($name)
|
|
173
|
+
}
|
|
174
|
+
} finally { $key.Dispose() }
|
|
175
|
+
}
|
|
176
|
+
} catch { }
|
|
177
|
+
return $values
|
|
178
|
+
}
|
|
179
|
+
|
|
180
|
+
function Import-PersistedUserEnvironment {
|
|
181
|
+
$added = @()
|
|
182
|
+
$persisted = Get-PersistedUserEnvironment
|
|
183
|
+
if (-not $persisted) { return $added }
|
|
184
|
+
foreach ($entry in $persisted.GetEnumerator()) {
|
|
185
|
+
$name = [string] $entry.Key
|
|
186
|
+
if (-not $name) { continue }
|
|
187
|
+
if ($persistedEnvironmentSkip -contains $name) { continue }
|
|
188
|
+
if ($null -ne [Environment]::GetEnvironmentVariable($name, 'Process')) { continue }
|
|
189
|
+
[Environment]::SetEnvironmentVariable($name, [string] $entry.Value, 'Process')
|
|
190
|
+
$added += $name
|
|
191
|
+
}
|
|
192
|
+
return $added
|
|
193
|
+
}
|
|
194
|
+
|
|
195
|
+
function Remove-ImportedUserEnvironment {
|
|
196
|
+
param([string[]] $Names)
|
|
197
|
+
foreach ($name in @($Names)) {
|
|
198
|
+
if ($name) { [Environment]::SetEnvironmentVariable($name, $null, 'Process') }
|
|
199
|
+
}
|
|
200
|
+
}
|
|
201
|
+
|
|
148
202
|
function Resolve-OfficialHarnessCommand {
|
|
149
203
|
$shim = Get-Command dsh.cmd -CommandType Application -ErrorAction Stop | Select-Object -First 1
|
|
150
204
|
$root = Join-Path (Split-Path -Parent $shim.Source) 'node_modules\@deepseek-ai\dsh'
|
|
@@ -487,14 +541,19 @@ function Open-OfficialFrontend {
|
|
|
487
541
|
$stdout = Join-Path $logRoot ('dsh-official-web-{0}.out.log' -f $stamp)
|
|
488
542
|
$stderr = Join-Path $logRoot ('dsh-official-web-{0}.err.log' -f $stamp)
|
|
489
543
|
$previousHome = $env:DSH_HOME
|
|
544
|
+
$importedEnvironment = @()
|
|
490
545
|
try {
|
|
491
546
|
# The official application owns its normal state; no Crew plugin/profile
|
|
492
547
|
# registration or repair is performed in this home by the launcher.
|
|
493
548
|
$env:DSH_HOME = Join-Path $env:USERPROFILE '.dsh'
|
|
549
|
+
$importedEnvironment = Import-PersistedUserEnvironment
|
|
494
550
|
$arguments = @(('"{0}"' -f $official.Entry), 'web', '--patch', ('"{0}"' -f $frontend.Path), '--host', '127.0.0.1', '--port', '3080')
|
|
495
551
|
$process = Start-Process -FilePath $official.NodePath -ArgumentList $arguments -WindowStyle Hidden -PassThru `
|
|
496
552
|
-RedirectStandardOutput $stdout -RedirectStandardError $stderr
|
|
497
|
-
} finally {
|
|
553
|
+
} finally {
|
|
554
|
+
$env:DSH_HOME = $previousHome
|
|
555
|
+
Remove-ImportedUserEnvironment -Names $importedEnvironment
|
|
556
|
+
}
|
|
498
557
|
Write-LaunchLog ('Started official Harness on 3080; PID={0}. The official CLI opens the browser. Logs: {1}, {2}' -f $process.Id, $stdout, $stderr)
|
|
499
558
|
$deadline = (Get-Date).AddSeconds($TimeoutSeconds)
|
|
500
559
|
$nextProgress = (Get-Date).AddSeconds(5)
|
|
@@ -1306,8 +1365,10 @@ function Start-CrewService {
|
|
|
1306
1365
|
$stdout = Join-Path $logRoot ('dsh-crew-{0}-{1}-{2}.out.log' -f $Service.Profile, $Service.Port, $serviceRunStamp)
|
|
1307
1366
|
$stderr = Join-Path $logRoot ('dsh-crew-{0}-{1}-{2}.err.log' -f $Service.Profile, $Service.Port, $serviceRunStamp)
|
|
1308
1367
|
$previousHome = $env:DSH_HOME
|
|
1368
|
+
$importedEnvironment = @()
|
|
1309
1369
|
try {
|
|
1310
1370
|
$env:DSH_HOME = $Service.Home
|
|
1371
|
+
$importedEnvironment = Import-PersistedUserEnvironment
|
|
1311
1372
|
$arguments = @('--profile', $Service.Profile, '--host', '127.0.0.1', '--port', [string] $Service.Port, '--no-open')
|
|
1312
1373
|
$launchArguments = if ($dshCliIsNodeEntry) { @($dshCli) + $arguments } else { $arguments }
|
|
1313
1374
|
$process = Start-Process -FilePath $dshCommand -ArgumentList $launchArguments -WindowStyle Hidden -PassThru `
|
|
@@ -1326,6 +1387,7 @@ function Start-CrewService {
|
|
|
1326
1387
|
Write-LaunchLog ('Started {0} on port {1}; PID={2}; stdout={3}; stderr={4}' -f $Service.Profile, $Service.Port, $process.Id, $stdout, $stderr)
|
|
1327
1388
|
} finally {
|
|
1328
1389
|
$env:DSH_HOME = $previousHome
|
|
1390
|
+
Remove-ImportedUserEnvironment -Names $importedEnvironment
|
|
1329
1391
|
}
|
|
1330
1392
|
}
|
|
1331
1393
|
|