dsh-cliworker-now 0.7.6 → 0.7.7
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 -9
- package/README.md +31 -9
- package/lib/account-models.mjs +16 -13
- package/lib/client.js +658 -61
- 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 +3724 -1589
- 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 +2 -2
- package/lib/pi-omp-bridge.mjs +2 -2
- package/lib/private-launch.mjs +6 -2
- package/lib/terminal-bridge.mjs +2 -2
- package/lib/typert.host.js +83 -11
- package/lib/typert.remote-client.d.ts +2 -0
- package/lib/typert.remote-client.d.ts.map +1 -1
- package/lib/typert.remote-client.js +77 -11
- 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/settings-dialog.js +65 -38
- package/lib/types/client/settings-dialog.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 +3 -1
- package/lib/types/host/account-models.mjs +16 -13
- package/lib/types/host/accounts.d.ts +3 -2
- package/lib/types/host/accounts.js +129 -22
- package/lib/types/host/accounts.js.map +1 -1
- package/lib/types/host/adapters.d.ts +1 -1
- package/lib/types/host/adapters.js +60 -11
- package/lib/types/host/adapters.js.map +1 -1
- 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 +272 -0
- package/lib/types/host/claude-native-oauth.js.map +1 -0
- package/lib/types/host/claude-own-route.d.ts +33 -0
- package/lib/types/host/claude-own-route.js +250 -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 +59 -21
- package/lib/types/host/cli-account-binding.js.map +1 -1
- package/lib/types/host/codex-models.js +4 -0
- 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 +1 -0
- package/lib/types/host/first-party-models.js +136 -47
- package/lib/types/host/first-party-models.js.map +1 -1
- package/lib/types/host/hermes-accounts.js +15 -1
- 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-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 +2 -0
- package/lib/types/host/index.js +17 -2
- 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 +18 -3
- package/lib/types/host/native-process.js.map +1 -1
- package/lib/types/host/native-spawn.mjs +32 -0
- 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 +15 -1
- package/lib/types/host/pi-omp-adapter.js.map +1 -1
- package/lib/types/host/private-launch.mjs +23 -0
- package/lib/types/host/routing.js +25 -2
- package/lib/types/host/routing.js.map +1 -1
- package/lib/types/host/runtime.js +17 -5
- package/lib/types/host/runtime.js.map +1 -1
- 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 +31 -0
- package/lib/types/host/windows-cli-installation.js +157 -0
- package/lib/types/host/windows-cli-installation.js.map +1 -0
- package/lib/types/host/windows-hidden-launch.mjs +49 -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/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 +49 -0
- package/lib/zcode-resume.mjs +2 -2
- package/package.json +1 -1
|
@@ -0,0 +1,121 @@
|
|
|
1
|
+
import { createHash } from 'node:crypto';
|
|
2
|
+
import { realpath, stat } from 'node:fs/promises';
|
|
3
|
+
import { isAbsolute } from 'node:path';
|
|
4
|
+
import { nativeLaunchArgv } from './native-launch.mjs';
|
|
5
|
+
const digest = (value) => createHash('sha256').update(JSON.stringify(value)).digest('hex');
|
|
6
|
+
/** No raw environment, configuration or account material is retained in the cache key. */
|
|
7
|
+
export async function nativeMetadataKey(executable, project, snapshot, signal) {
|
|
8
|
+
signal.throwIfAborted();
|
|
9
|
+
try {
|
|
10
|
+
// Use the same static launch plan as the process boundary. A fixed Bun shim
|
|
11
|
+
// can stay unchanged while its actual runtime or script is upgraded.
|
|
12
|
+
const launch = nativeLaunchArgv([executable]);
|
|
13
|
+
const identities = [];
|
|
14
|
+
for (const path of new Set([executable, ...launch.filter(isAbsolute)])) {
|
|
15
|
+
const entry = await realpath(path), identity = await stat(entry);
|
|
16
|
+
signal.throwIfAborted();
|
|
17
|
+
if (!identity.isFile())
|
|
18
|
+
return;
|
|
19
|
+
identities.push([entry, identity.dev, identity.ino, identity.size, identity.mtimeMs, identity.ctimeMs]);
|
|
20
|
+
}
|
|
21
|
+
const physicalProject = await realpath(project);
|
|
22
|
+
signal.throwIfAborted();
|
|
23
|
+
return digest({
|
|
24
|
+
launch,
|
|
25
|
+
project,
|
|
26
|
+
physicalProject,
|
|
27
|
+
identities,
|
|
28
|
+
environment: Object.entries(process.env).sort(([a], [b]) => a.localeCompare(b)),
|
|
29
|
+
snapshot,
|
|
30
|
+
});
|
|
31
|
+
}
|
|
32
|
+
catch {
|
|
33
|
+
signal.throwIfAborted();
|
|
34
|
+
// An unverifiable executable still follows the uncached native validation path.
|
|
35
|
+
return;
|
|
36
|
+
}
|
|
37
|
+
}
|
|
38
|
+
export const mimoMetadataKey = nativeMetadataKey;
|
|
39
|
+
function currentCredential(source, own) {
|
|
40
|
+
for (const path of source.sourceIds) {
|
|
41
|
+
const value = path === own.authPath
|
|
42
|
+
? own.auth[source.provider]
|
|
43
|
+
: {
|
|
44
|
+
type: 'api',
|
|
45
|
+
key: own.configurations.find((item) => item.path === path)?.value.provider?.[source.provider]
|
|
46
|
+
?.options?.apiKey,
|
|
47
|
+
};
|
|
48
|
+
if (value?.type !== 'api' || typeof value.key !== 'string' || !value.key)
|
|
49
|
+
continue;
|
|
50
|
+
const credential = { type: 'api', key: value.key };
|
|
51
|
+
if (digest(credential) === source.credentialHash)
|
|
52
|
+
return credential;
|
|
53
|
+
}
|
|
54
|
+
}
|
|
55
|
+
/** Only native capabilities are reused. Remote entitlement discovery must still run on every call. */
|
|
56
|
+
export class MimoMetadataCache {
|
|
57
|
+
ttlMs;
|
|
58
|
+
limit;
|
|
59
|
+
entries = new Map();
|
|
60
|
+
constructor(ttlMs = 30_000, limit = 16) {
|
|
61
|
+
this.ttlMs = ttlMs;
|
|
62
|
+
this.limit = limit;
|
|
63
|
+
}
|
|
64
|
+
get(key, own) {
|
|
65
|
+
if (!key)
|
|
66
|
+
return;
|
|
67
|
+
const entry = this.entries.get(key), now = Date.now();
|
|
68
|
+
if (!entry)
|
|
69
|
+
return;
|
|
70
|
+
if (now < entry.created || now - entry.created >= this.ttlMs) {
|
|
71
|
+
this.entries.delete(key);
|
|
72
|
+
return;
|
|
73
|
+
}
|
|
74
|
+
const sources = [];
|
|
75
|
+
for (const metadata of entry.sources) {
|
|
76
|
+
const credential = currentCredential(metadata, own);
|
|
77
|
+
if (!credential) {
|
|
78
|
+
this.entries.delete(key);
|
|
79
|
+
return;
|
|
80
|
+
}
|
|
81
|
+
const { credentialHash: _, ...source } = metadata;
|
|
82
|
+
sources.push({ ...structuredClone(source), credential });
|
|
83
|
+
}
|
|
84
|
+
return sources;
|
|
85
|
+
}
|
|
86
|
+
set(key, sources, own) {
|
|
87
|
+
if (!key || !sources.length)
|
|
88
|
+
return;
|
|
89
|
+
const metadata = [];
|
|
90
|
+
for (const source of sources) {
|
|
91
|
+
if (source.credential.type !== 'api')
|
|
92
|
+
return;
|
|
93
|
+
// A user-defined URL may itself carry a credential; such sources stay uncached.
|
|
94
|
+
try {
|
|
95
|
+
const url = new URL(source.baseUrl || '');
|
|
96
|
+
if (url.username || url.password || url.search || url.hash)
|
|
97
|
+
return;
|
|
98
|
+
}
|
|
99
|
+
catch {
|
|
100
|
+
return;
|
|
101
|
+
}
|
|
102
|
+
const { credential, ...capabilities } = source;
|
|
103
|
+
if (credential.key && JSON.stringify(capabilities).includes(credential.key))
|
|
104
|
+
return;
|
|
105
|
+
const entry = { ...structuredClone(capabilities), credentialHash: digest(credential) };
|
|
106
|
+
if (!currentCredential(entry, own))
|
|
107
|
+
return;
|
|
108
|
+
metadata.push(entry);
|
|
109
|
+
}
|
|
110
|
+
const now = Date.now();
|
|
111
|
+
for (const [id, entry] of this.entries)
|
|
112
|
+
if (now < entry.created || now - entry.created >= this.ttlMs)
|
|
113
|
+
this.entries.delete(id);
|
|
114
|
+
this.entries.delete(key);
|
|
115
|
+
this.entries.set(key, { created: now, sources: metadata });
|
|
116
|
+
while (this.entries.size > this.limit)
|
|
117
|
+
this.entries.delete(this.entries.keys().next().value);
|
|
118
|
+
}
|
|
119
|
+
}
|
|
120
|
+
export const mimoMetadataCache = new MimoMetadataCache();
|
|
121
|
+
//# sourceMappingURL=mimo-metadata-cache.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"mimo-metadata-cache.js","sourceRoot":"","sources":["../../../src/host/mimo-metadata-cache.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
/** Hash current bounded own files without retaining file content or following links. */
|
|
2
|
+
export declare function metadataFileFingerprint(path: string, signal: AbortSignal): Promise<string | undefined>;
|
|
3
|
+
/** Callers admit only validated public capabilities, never account status or raw CLI output. */
|
|
4
|
+
export declare class NativeCapabilityCache<T> {
|
|
5
|
+
private readonly ttlMs;
|
|
6
|
+
private readonly limit;
|
|
7
|
+
private readonly entries;
|
|
8
|
+
constructor(ttlMs?: number, limit?: number);
|
|
9
|
+
get(key: string | undefined): T | undefined;
|
|
10
|
+
set(key: string | undefined, value: T): void;
|
|
11
|
+
}
|
|
@@ -0,0 +1,94 @@
|
|
|
1
|
+
import { createHash } from 'node:crypto';
|
|
2
|
+
import { constants } from 'node:fs';
|
|
3
|
+
import { lstat, open } from 'node:fs/promises';
|
|
4
|
+
import { dirname } from 'node:path';
|
|
5
|
+
import { safePiOmpAncestors } from "./pi-omp-native.js";
|
|
6
|
+
/** Hash current bounded own files without retaining file content or following links. */
|
|
7
|
+
export async function metadataFileFingerprint(path, signal) {
|
|
8
|
+
let file;
|
|
9
|
+
let bytes;
|
|
10
|
+
try {
|
|
11
|
+
signal.throwIfAborted();
|
|
12
|
+
await safePiOmpAncestors(dirname(path));
|
|
13
|
+
const before = await lstat(path);
|
|
14
|
+
if (before.isSymbolicLink() || !before.isFile() || before.nlink !== 1 || before.size > 1_048_576)
|
|
15
|
+
return;
|
|
16
|
+
file = await open(path, constants.O_RDONLY | constants.O_NOFOLLOW | constants.O_NONBLOCK);
|
|
17
|
+
const opened = await file.stat();
|
|
18
|
+
if (!opened.isFile() ||
|
|
19
|
+
opened.dev !== before.dev ||
|
|
20
|
+
opened.ino !== before.ino ||
|
|
21
|
+
opened.nlink !== 1 ||
|
|
22
|
+
opened.size !== before.size ||
|
|
23
|
+
opened.size > 1_048_576 ||
|
|
24
|
+
opened.mtimeMs !== before.mtimeMs)
|
|
25
|
+
return;
|
|
26
|
+
bytes = Buffer.alloc(opened.size + 1);
|
|
27
|
+
let offset = 0;
|
|
28
|
+
while (offset < bytes.length) {
|
|
29
|
+
signal.throwIfAborted();
|
|
30
|
+
const read = await file.read(bytes, offset, bytes.length - offset, offset);
|
|
31
|
+
if (!read.bytesRead)
|
|
32
|
+
break;
|
|
33
|
+
offset += read.bytesRead;
|
|
34
|
+
}
|
|
35
|
+
const after = await file.stat(), current = await lstat(path);
|
|
36
|
+
signal.throwIfAborted();
|
|
37
|
+
if (current.isSymbolicLink() ||
|
|
38
|
+
current.dev !== opened.dev ||
|
|
39
|
+
current.ino !== opened.ino ||
|
|
40
|
+
current.nlink !== 1 ||
|
|
41
|
+
offset !== opened.size ||
|
|
42
|
+
after.size !== opened.size ||
|
|
43
|
+
current.size !== opened.size ||
|
|
44
|
+
after.mtimeMs !== opened.mtimeMs ||
|
|
45
|
+
current.mtimeMs !== opened.mtimeMs ||
|
|
46
|
+
after.ctimeMs !== opened.ctimeMs ||
|
|
47
|
+
current.ctimeMs !== opened.ctimeMs)
|
|
48
|
+
return;
|
|
49
|
+
return createHash('sha256').update(bytes.subarray(0, offset)).digest('hex');
|
|
50
|
+
}
|
|
51
|
+
catch (error) {
|
|
52
|
+
signal.throwIfAborted();
|
|
53
|
+
return error.code === 'ENOENT' ? 'missing' : undefined;
|
|
54
|
+
}
|
|
55
|
+
finally {
|
|
56
|
+
bytes?.fill(0);
|
|
57
|
+
await file?.close();
|
|
58
|
+
}
|
|
59
|
+
}
|
|
60
|
+
/** Callers admit only validated public capabilities, never account status or raw CLI output. */
|
|
61
|
+
export class NativeCapabilityCache {
|
|
62
|
+
ttlMs;
|
|
63
|
+
limit;
|
|
64
|
+
entries = new Map();
|
|
65
|
+
constructor(ttlMs = 30_000, limit = 16) {
|
|
66
|
+
this.ttlMs = ttlMs;
|
|
67
|
+
this.limit = limit;
|
|
68
|
+
}
|
|
69
|
+
get(key) {
|
|
70
|
+
if (!key)
|
|
71
|
+
return;
|
|
72
|
+
const entry = this.entries.get(key), now = Date.now();
|
|
73
|
+
if (!entry)
|
|
74
|
+
return;
|
|
75
|
+
if (now < entry.created || now - entry.created >= this.ttlMs) {
|
|
76
|
+
this.entries.delete(key);
|
|
77
|
+
return;
|
|
78
|
+
}
|
|
79
|
+
return structuredClone(entry.value);
|
|
80
|
+
}
|
|
81
|
+
set(key, value) {
|
|
82
|
+
if (!key)
|
|
83
|
+
return;
|
|
84
|
+
const now = Date.now();
|
|
85
|
+
for (const [id, entry] of this.entries)
|
|
86
|
+
if (now < entry.created || now - entry.created >= this.ttlMs)
|
|
87
|
+
this.entries.delete(id);
|
|
88
|
+
this.entries.delete(key);
|
|
89
|
+
this.entries.set(key, { created: now, value: structuredClone(value) });
|
|
90
|
+
while (this.entries.size > this.limit)
|
|
91
|
+
this.entries.delete(this.entries.keys().next().value);
|
|
92
|
+
}
|
|
93
|
+
}
|
|
94
|
+
//# sourceMappingURL=native-capability-cache.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"native-capability-cache.js","sourceRoot":"","sources":["../../../src/host/native-capability-cache.ts"],"names":[],"mappings":"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"}
|
|
@@ -1,9 +1,12 @@
|
|
|
1
1
|
// Inspect fixed launcher data; never ask a shell to interpret CLI arguments.
|
|
2
2
|
import { openSync, readSync, fstatSync, closeSync, realpathSync, statSync, existsSync } from 'node:fs'
|
|
3
|
-
import { dirname, extname, isAbsolute, resolve, sep, delimiter, join } from 'node:path'
|
|
3
|
+
import { basename, dirname, extname, isAbsolute, relative, resolve, sep, delimiter, join } from 'node:path'
|
|
4
4
|
import { homedir, userInfo } from 'node:os'
|
|
5
5
|
|
|
6
|
-
const invalid = () =>
|
|
6
|
+
const invalid = () => Object.assign(
|
|
7
|
+
new Error('CLI 启动入口无法确认,请配置原生程序或固定 Node/Bun 入口'),
|
|
8
|
+
{ code: 'CLI_LAUNCHER_UNSUPPORTED' },
|
|
9
|
+
)
|
|
7
10
|
const batch = (value) => /\.(?:cmd|bat)$/i.test(value)
|
|
8
11
|
function text(path, limit = 128 * 1024) {
|
|
9
12
|
const descriptor = openSync(path, 'r')
|
|
@@ -73,6 +76,45 @@ function runtimeProgram(runtime, platform, launcherDirectory) {
|
|
|
73
76
|
if (!candidate) throw new Error('未找到 Bun,请安装该 CLI 所需的 Bun 运行时')
|
|
74
77
|
return file(candidate)
|
|
75
78
|
}
|
|
79
|
+
/** npm's native bin shim is data, not a batch program to execute. */
|
|
80
|
+
function nativePackageBin(shim, suffix) {
|
|
81
|
+
const parts = suffix.replace(/\\/g, '/').split('/')
|
|
82
|
+
if (parts[0] !== 'node_modules' || parts.some((part) => !part || part === '.' || part === '..'))
|
|
83
|
+
throw invalid()
|
|
84
|
+
const scoped = parts[1]?.startsWith('@')
|
|
85
|
+
const name = parts.slice(1, scoped ? 3 : 2).join('/')
|
|
86
|
+
if (!/^(?:@[a-z0-9._-]+\/)?[a-z0-9._-]+$/.test(name)) throw invalid()
|
|
87
|
+
const root = fileDirectory(resolve(dirname(shim), ...parts.slice(0, scoped ? 3 : 2)))
|
|
88
|
+
const entry = file(resolve(dirname(shim), ...parts))
|
|
89
|
+
const inside = relative(root, entry)
|
|
90
|
+
if (!inside || inside === '..' || inside.startsWith('..' + sep) || isAbsolute(inside)) throw invalid()
|
|
91
|
+
const manifest = JSON.parse(text(join(root, 'package.json')))
|
|
92
|
+
const command = basename(shim, extname(shim))
|
|
93
|
+
const declared = typeof manifest.bin === 'string'
|
|
94
|
+
? name.split('/').at(-1) === command ? manifest.bin : undefined
|
|
95
|
+
: manifest.bin?.[command]
|
|
96
|
+
if (manifest.name !== name || typeof declared !== 'string' || isAbsolute(declared) ||
|
|
97
|
+
declared.replace(/\\/g, '/').split('/').includes('..') || file(resolve(root, declared)) !== entry)
|
|
98
|
+
throw invalid()
|
|
99
|
+
const descriptor = openSync(entry, 'r')
|
|
100
|
+
try {
|
|
101
|
+
const header = Buffer.alloc(64), signature = Buffer.alloc(4)
|
|
102
|
+
const size = fstatSync(descriptor).size
|
|
103
|
+
if (readSync(descriptor, header, 0, 64, 0) !== 64 || header.toString('ascii', 0, 2) !== 'MZ')
|
|
104
|
+
throw invalid()
|
|
105
|
+
const offset = header.readUInt32LE(0x3c)
|
|
106
|
+
if (offset < 64 || offset + 4 > size || readSync(descriptor, signature, 0, 4, offset) !== 4 ||
|
|
107
|
+
signature.toString('hex') !== '50450000') throw invalid()
|
|
108
|
+
} finally {
|
|
109
|
+
closeSync(descriptor)
|
|
110
|
+
}
|
|
111
|
+
return entry
|
|
112
|
+
}
|
|
113
|
+
function fileDirectory(path) {
|
|
114
|
+
const canonical = realpathSync(path)
|
|
115
|
+
if (!statSync(canonical).isDirectory()) throw invalid()
|
|
116
|
+
return canonical
|
|
117
|
+
}
|
|
76
118
|
function inspectBatch(executable, platform) {
|
|
77
119
|
const source = text(file(executable)).trim().replace(/\r\n/g, '\n')
|
|
78
120
|
// Nous' official fallback contains just a fixed interpreter and its encoded
|
|
@@ -101,8 +143,14 @@ function inspectBatch(executable, platform) {
|
|
|
101
143
|
// npm cmd-shim's standard final control prefix is launcher boilerplate;
|
|
102
144
|
// it is discarded, and nothing from it is executed by this module.
|
|
103
145
|
line = line.replace(/^endLocal & goto #_undefined_# 2>NUL \|\| title [^&\n]+ & /i, '')
|
|
146
|
+
const native = /^@?"%(?:~dp0[\\/]?|dp0%[\\/])([^"\n%]+\.exe)"\s+%\*$/i.exec(line)
|
|
147
|
+
if (native) {
|
|
148
|
+
entries.add(nativePackageBin(executable, native[1]))
|
|
149
|
+
runtimes.add('native')
|
|
150
|
+
continue
|
|
151
|
+
}
|
|
104
152
|
const command =
|
|
105
|
-
/^@?(?:(node|bun)|"%_prog%"|"%(?:~dp0
|
|
153
|
+
/^@?(?:(node|bun)|"%_prog%"|"%(?:~dp0[\\/]?|dp0%[\\/])(node|bun)\.exe")\s+"%(?:~dp0[\\/]?|dp0%[\\/])([^"\n%]+)"\s+%\*$/i.exec(
|
|
106
154
|
line,
|
|
107
155
|
)
|
|
108
156
|
if (command) {
|
|
@@ -112,7 +160,7 @@ function inspectBatch(executable, platform) {
|
|
|
112
160
|
if (command[1] || command[2]) runtimes.add((command[1] || command[2]).toLowerCase())
|
|
113
161
|
continue
|
|
114
162
|
}
|
|
115
|
-
const program = /^@?set "?_prog=(?:%(?:~dp0
|
|
163
|
+
const program = /^@?set "?_prog=(?:%(?:~dp0[\\/]?|dp0%[\\/]))?(node|bun)(?:\.exe)?"?$/i.exec(line)
|
|
116
164
|
if (program) {
|
|
117
165
|
runtimes.add(program[1].toLowerCase())
|
|
118
166
|
continue
|
|
@@ -121,7 +169,7 @@ function inspectBatch(executable, platform) {
|
|
|
121
169
|
/^@?(?:goto start|:find_dp0|:start|set dp0=%~dp0|exit \/b|setlocal|endlocal|call :find_dp0)$/i.test(
|
|
122
170
|
line,
|
|
123
171
|
) ||
|
|
124
|
-
/^@?if (?:not )?exist "%(?:~dp0
|
|
172
|
+
/^@?if (?:not )?exist "%(?:~dp0[\\/]?|dp0%[\\/])(?:node|bun)\.exe" \($/i.test(line) ||
|
|
125
173
|
/^\)(?: else \()?$/i.test(line) ||
|
|
126
174
|
/^@?set pathext=%pathext:;\.js;=;%$/i.test(line) ||
|
|
127
175
|
/^@?if (?:not )?defined node_path \($/i.test(line) ||
|
|
@@ -133,6 +181,7 @@ function inspectBatch(executable, platform) {
|
|
|
133
181
|
if (entries.size !== 1 || runtimes.size !== 1) throw invalid()
|
|
134
182
|
const entry = [...entries][0],
|
|
135
183
|
runtime = [...runtimes][0]
|
|
184
|
+
if (runtime === 'native') return { kind: 'native', argv: [entry] }
|
|
136
185
|
if (scriptRuntime(entry) !== runtime) throw invalid()
|
|
137
186
|
return { kind: runtime, argv: [runtimeProgram(runtime, platform, dirname(executable)), entry] }
|
|
138
187
|
}
|
|
@@ -151,10 +200,16 @@ export function resolveNativeEntry(executable, platform = process.platform) {
|
|
|
151
200
|
if (candidate) executable = candidate
|
|
152
201
|
}
|
|
153
202
|
if (!batch(executable)) return executable
|
|
154
|
-
|
|
203
|
+
let inspected
|
|
204
|
+
try {
|
|
205
|
+
inspected = inspectBatch(executable, platform)
|
|
206
|
+
} catch {
|
|
207
|
+
// A present but invalid shim is not an absent CLI. Never forward raw paths or script text.
|
|
208
|
+
throw invalid()
|
|
209
|
+
}
|
|
155
210
|
// Keep Bun's fixed shim identity: it may pin a bundled bun.exe beside the
|
|
156
211
|
// shim which cannot be recovered from only the package's JS path.
|
|
157
|
-
return inspected.kind === 'node' ? inspected.argv[1] : executable
|
|
212
|
+
return inspected.kind === 'node' ? inspected.argv[1] : inspected.kind === 'native' ? inspected.argv[0] : executable
|
|
158
213
|
}
|
|
159
214
|
|
|
160
215
|
/** Windows CreateProcess accepts real programs, not npm command files. */
|
|
@@ -1,3 +1,5 @@
|
|
|
1
1
|
import type { ProcessBackend } from './process.ts';
|
|
2
2
|
/** One normalization boundary for tasks, metadata and interactive account menus. */
|
|
3
|
-
export declare function nativeProcessBackend(backend: ProcessBackend, platform?: NodeJS.Platform
|
|
3
|
+
export declare function nativeProcessBackend(backend: ProcessBackend, platform?: NodeJS.Platform, options?: {
|
|
4
|
+
electron?: boolean;
|
|
5
|
+
}): ProcessBackend;
|
|
@@ -1,12 +1,17 @@
|
|
|
1
1
|
import { nativeLaunchArgv, resolveNativeEntry } from './native-launch.mjs';
|
|
2
|
+
import { win32 } from 'node:path';
|
|
3
|
+
import { fileURLToPath } from 'node:url';
|
|
4
|
+
import { isCurrentWindowsRuntime, needsWindowsHiddenLaunch, spawnWindowsHidden } from "./windows-hidden-process.js";
|
|
5
|
+
const privateLauncher = fileURLToPath(new URL('./private-launch.mjs', import.meta.url));
|
|
2
6
|
/** One normalization boundary for tasks, metadata and interactive account menus. */
|
|
3
|
-
export function nativeProcessBackend(backend, platform = process.platform) {
|
|
7
|
+
export function nativeProcessBackend(backend, platform = process.platform, options = {}) {
|
|
4
8
|
const normalize = (spec) => {
|
|
5
9
|
const argv = nativeLaunchArgv(spec.argv, platform);
|
|
6
10
|
return {
|
|
7
11
|
...spec,
|
|
8
12
|
argv,
|
|
9
|
-
...(argv[0] === process.execPath
|
|
13
|
+
...(argv[0] === process.execPath || (platform === 'win32' && isCurrentWindowsRuntime(argv[0]))
|
|
14
|
+
? { env: { ...spec.env, ELECTRON_RUN_AS_NODE: '1' } } : {}),
|
|
10
15
|
};
|
|
11
16
|
};
|
|
12
17
|
return {
|
|
@@ -14,7 +19,17 @@ export function nativeProcessBackend(backend, platform = process.platform) {
|
|
|
14
19
|
return resolveNativeEntry(await backend.resolveExecutable(resolveNativeEntry(name, platform)), platform);
|
|
15
20
|
},
|
|
16
21
|
spawn(spec) {
|
|
17
|
-
|
|
22
|
+
const normalized = normalize(spec);
|
|
23
|
+
const electron = options.electron ?? !!process.versions.electron;
|
|
24
|
+
// Fold only our exact private-umask helper into the background relay.
|
|
25
|
+
// Leaving another pipe relay beneath it would delay the native exit
|
|
26
|
+
// receipt until all descendants released their inherited output pipes.
|
|
27
|
+
if (platform === 'win32' && electron && isCurrentWindowsRuntime(normalized.argv[0]) &&
|
|
28
|
+
normalized.argv.length > 2 && win32.normalize(normalized.argv[1]).toLowerCase() === win32.normalize(privateLauncher).toLowerCase())
|
|
29
|
+
return spawnWindowsHidden(backend, { ...normalized, argv: nativeLaunchArgv(normalized.argv.slice(2), platform) }, { privateUmask: true });
|
|
30
|
+
return needsWindowsHiddenLaunch(normalized.argv, platform, electron)
|
|
31
|
+
? spawnWindowsHidden(backend, normalized)
|
|
32
|
+
: backend.spawn(normalized);
|
|
18
33
|
},
|
|
19
34
|
...(backend.spawnTerminal
|
|
20
35
|
? {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"native-process.js","sourceRoot":"","sources":["../../../src/host/native-process.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,gBAAgB,EAAE,kBAAkB,EAAE,MAAM,qBAAqB,CAAA;
|
|
1
|
+
{"version":3,"file":"native-process.js","sourceRoot":"","sources":["../../../src/host/native-process.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,gBAAgB,EAAE,kBAAkB,EAAE,MAAM,qBAAqB,CAAA;AAC1E,OAAO,EAAE,KAAK,EAAE,MAAM,WAAW,CAAA;AACjC,OAAO,EAAE,aAAa,EAAE,MAAM,UAAU,CAAA;AAExC,OAAO,EAAE,uBAAuB,EAAE,wBAAwB,EAAE,kBAAkB,EAAE,MAAM,6BAA6B,CAAA;AACnH,MAAM,eAAe,GAAG,aAAa,CAAC,IAAI,GAAG,CAAC,sBAAsB,EAAE,MAAM,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,CAAA;AAEvF,oFAAoF;AACpF,MAAM,UAAU,oBAAoB,CAClC,OAAuB,EACvB,QAAQ,GAAG,OAAO,CAAC,QAAQ,EAC3B,UAAkC,EAAE;IAEpC,MAAM,SAAS,GAAG,CAAiE,IAAO,EAAE,EAAE;QAC5F,MAAM,IAAI,GAAG,gBAAgB,CAAC,IAAI,CAAC,IAAI,EAAE,QAAQ,CAAC,CAAA;QAClD,OAAO;YACL,GAAG,IAAI;YACP,IAAI;YACJ,GAAG,CAAC,IAAI,CAAC,CAAC,CAAC,KAAK,OAAO,CAAC,QAAQ,IAAI,CAAC,QAAQ,KAAK,OAAO,IAAI,uBAAuB,CAAC,IAAI,CAAC,CAAC,CAAE,CAAC,CAAC;gBAC7F,CAAC,CAAC,EAAE,GAAG,EAAE,EAAE,GAAG,IAAI,CAAC,GAAG,EAAE,oBAAoB,EAAE,GAAG,EAAE,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;SAC9D,CAAA;IACH,CAAC,CAAA;IACD,OAAO;QACL,KAAK,CAAC,iBAAiB,CAAC,IAAI;YAC1B,OAAO,kBAAkB,CAAC,MAAM,OAAO,CAAC,iBAAiB,CAAC,kBAAkB,CAAC,IAAI,EAAE,QAAQ,CAAC,CAAC,EAAE,QAAQ,CAAC,CAAA;QAC1G,CAAC;QACD,KAAK,CAAC,IAAI;YACR,MAAM,UAAU,GAAG,SAAS,CAAC,IAAI,CAAC,CAAA;YAClC,MAAM,QAAQ,GAAG,OAAO,CAAC,QAAQ,IAAI,CAAC,CAAC,OAAO,CAAC,QAAQ,CAAC,QAAQ,CAAA;YAChE,sEAAsE;YACtE,oEAAoE;YACpE,uEAAuE;YACvE,IAAI,QAAQ,KAAK,OAAO,IAAI,QAAQ,IAAI,uBAAuB,CAAC,UAAU,CAAC,IAAI,CAAC,CAAC,CAAE,CAAC;gBAChF,UAAU,CAAC,IAAI,CAAC,MAAM,GAAG,CAAC,IAAI,KAAK,CAAC,SAAS,CAAC,UAAU,CAAC,IAAI,CAAC,CAAC,CAAE,CAAC,CAAC,WAAW,EAAE,KAAK,KAAK,CAAC,SAAS,CAAC,eAAe,CAAC,CAAC,WAAW,EAAE;gBACrI,OAAO,kBAAkB,CAAC,OAAO,EAAE,EAAE,GAAG,UAAU,EAAE,IAAI,EAAE,gBAAgB,CAAC,UAAU,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,CAAC,EAAE,QAAQ,CAAC,EAAE,EAAE,EAAE,YAAY,EAAE,IAAI,EAAE,CAAC,CAAA;YAC3I,OAAO,wBAAwB,CAAC,UAAU,CAAC,IAAI,EAAE,QAAQ,EAAE,QAAQ,CAAC;gBAClE,CAAC,CAAC,kBAAkB,CAAC,OAAO,EAAE,UAAU,CAAC;gBACzC,CAAC,CAAC,OAAO,CAAC,KAAK,CAAC,UAAU,CAAC,CAAA;QAC/B,CAAC;QACD,GAAG,CAAC,OAAO,CAAC,aAAa;YACvB,CAAC,CAAC;gBACE,aAAa,EAAE,CAAC,IAAiE,EAAE,EAAE,CACnF,OAAO,CAAC,aAAc,CAAC,SAAS,CAAC,IAAI,CAAC,CAAC;aAC1C;YACH,CAAC,CAAC,EAAE,CAAC;KACR,CAAA;AACH,CAAC"}
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
import { spawn } from 'node:child_process'
|
|
2
|
+
|
|
3
|
+
/** Native CLI descendants keep their pipes/ConPTY and the enclosing Host Job.
|
|
4
|
+
* Window presentation is per child: hiding a wrapper does not hide its children.
|
|
5
|
+
* Node ignores windowsHide on POSIX, so both platforms use this one boundary.
|
|
6
|
+
*/
|
|
7
|
+
export function spawnNativeProcess(executable, argv, options) {
|
|
8
|
+
return spawn(executable, argv, { ...options, windowsHide: true })
|
|
9
|
+
}
|
|
10
|
+
|
|
11
|
+
/** Relay ordinary background pipes as bytes with Node's stream backpressure.
|
|
12
|
+
* Numeric/inherited descriptors make libuv omit CREATE_NO_WINDOW on Windows.
|
|
13
|
+
* This must never be used for a ConPTY: its console handles stay inherited. */
|
|
14
|
+
export function forwardNativeStdio(child) {
|
|
15
|
+
const stopInput = () => {
|
|
16
|
+
process.stdin.unpipe(child.stdin)
|
|
17
|
+
process.stdin.destroy()
|
|
18
|
+
}
|
|
19
|
+
const fail = () => { child.kill('SIGTERM'); process.exitCode = 1 }
|
|
20
|
+
child.stdin.on('error', error => { stopInput(); if (error.code !== 'EPIPE') fail() })
|
|
21
|
+
child.stdin.once('close', stopInput)
|
|
22
|
+
child.once('exit', stopInput)
|
|
23
|
+
child.once('error', stopInput)
|
|
24
|
+
process.stdin.on('error', fail)
|
|
25
|
+
process.stdout.on('error', fail)
|
|
26
|
+
process.stderr.on('error', fail)
|
|
27
|
+
child.stdout.on('error', fail)
|
|
28
|
+
child.stderr.on('error', fail)
|
|
29
|
+
process.stdin.pipe(child.stdin)
|
|
30
|
+
child.stdout.pipe(process.stdout, { end: false })
|
|
31
|
+
child.stderr.pipe(process.stderr, { end: false })
|
|
32
|
+
}
|
|
@@ -1,13 +1,14 @@
|
|
|
1
1
|
// One verified Pi package for the Host, account UI, native catalog and RPC entry.
|
|
2
2
|
// Resolve installation metadata only; never execute an arbitrary shell launcher.
|
|
3
3
|
import { readFileSync, realpathSync, statSync } from 'node:fs'
|
|
4
|
-
import {
|
|
4
|
+
import { createHash } from 'node:crypto'
|
|
5
|
+
import { basename, dirname, isAbsolute, join, relative, resolve, sep } from 'node:path'
|
|
5
6
|
import { resolveNativeEntry } from './native-launch.mjs'
|
|
6
7
|
|
|
7
|
-
const versions = new Set(['1.0.2', '1.0.4'])
|
|
8
|
+
const versions = new Set(['1.0.2', '1.0.4', '1.1.0'])
|
|
8
9
|
const failure = () =>
|
|
9
10
|
Object.assign(
|
|
10
|
-
new Error('Pi 安装身份或原生接口不匹配;需要 Pi Coding Agent 1.0.2 或 1.0
|
|
11
|
+
new Error('Pi 安装身份或原生接口不匹配;需要 Pi Coding Agent 1.0.2、1.0.4 或 1.1.0,不能使用 OMP 入口'),
|
|
11
12
|
{ code: 'CLI_IDENTITY_MISMATCH' },
|
|
12
13
|
)
|
|
13
14
|
function metadata(path) {
|
|
@@ -15,6 +16,27 @@ function metadata(path) {
|
|
|
15
16
|
if (!info.isFile() || info.size > 128 * 1024) throw failure()
|
|
16
17
|
return readFileSync(path, 'utf8')
|
|
17
18
|
}
|
|
19
|
+
// Exact official Windows managed launcher inspected from Pi 1.1.0. It is read as
|
|
20
|
+
// installation metadata, never evaluated. Unknown bootstrap code fails closed.
|
|
21
|
+
const managedWindowsLauncherSHA256 = '3d8b27bb3f5c07543303b0ee774ce215e4d6ae2b0ae43311c4acf51f517ffd13'
|
|
22
|
+
function windowsManagedEntry(launcher) {
|
|
23
|
+
const source = metadata(launcher).trim().replace(/\r\n/g, '\n')
|
|
24
|
+
if (createHash('sha256').update(source).digest('hex') !== managedWindowsLauncherSHA256) throw failure()
|
|
25
|
+
const install = join(dirname(dirname(launcher)), 'install')
|
|
26
|
+
const version = metadata(join(install, 'current-version')).trim()
|
|
27
|
+
if (!versions.has(version)) throw failure()
|
|
28
|
+
const directory = resolve(install, 'releases', version, 'node_modules/@earendil-works/pi-coding-agent')
|
|
29
|
+
// A version pointer/package symlink must not select code outside this release.
|
|
30
|
+
if (realpathSync(directory) !== directory) throw failure()
|
|
31
|
+
const manifest = JSON.parse(metadata(join(directory, 'package.json')))
|
|
32
|
+
const bin = typeof manifest.bin === 'string' ? manifest.bin : manifest.bin?.pi
|
|
33
|
+
if (manifest.name !== '@earendil-works/pi-coding-agent' || manifest.version !== version ||
|
|
34
|
+
!['dist/cli.js', 'dist/bundle/cli.js'].includes(bin)) throw failure()
|
|
35
|
+
const entry = realpathSync(resolve(directory, bin))
|
|
36
|
+
const inside = relative(directory, entry)
|
|
37
|
+
if (!inside || inside === '..' || inside.startsWith('..' + sep) || isAbsolute(inside)) throw failure()
|
|
38
|
+
return entry
|
|
39
|
+
}
|
|
18
40
|
|
|
19
41
|
export function inspectPiInstallation(entry) {
|
|
20
42
|
try {
|
|
@@ -34,6 +56,8 @@ export function inspectPiInstallation(entry) {
|
|
|
34
56
|
}
|
|
35
57
|
}
|
|
36
58
|
executable = realpathSync(resolveNativeEntry(executable))
|
|
59
|
+
if (basename(executable).toLowerCase() === 'pi-launcher.js' && basename(dirname(executable)) === 'bin')
|
|
60
|
+
executable = windowsManagedEntry(executable)
|
|
37
61
|
let directory = dirname(executable)
|
|
38
62
|
for (let depth = 0; depth < 5; depth++, directory = dirname(directory)) {
|
|
39
63
|
let manifest
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { mkdir, mkdtemp, realpath, writeFile, lstat, open, rename, rm } from 'node:fs/promises';
|
|
1
|
+
import { mkdir, mkdtemp, realpath, writeFile, lstat, open, rename, rm, chmod } from 'node:fs/promises';
|
|
2
2
|
import { constants, existsSync } from 'node:fs';
|
|
3
3
|
import { createHash, randomUUID } from 'node:crypto';
|
|
4
4
|
import { dirname, join, resolve } from 'node:path';
|
|
@@ -22,6 +22,20 @@ async function privateDirectory(path) {
|
|
|
22
22
|
const info = await lstat(path);
|
|
23
23
|
if (info.isSymbolicLink() || !info.isDirectory())
|
|
24
24
|
throw new Error('Unsafe Pi/OMP state directory symlink');
|
|
25
|
+
if (process.platform === 'win32') {
|
|
26
|
+
// Node's POSIX directory descriptor/chmod path is not supported on Windows.
|
|
27
|
+
// Match account preparation: pin the path and inode around the path-based operation.
|
|
28
|
+
const canonical = await realpath(path);
|
|
29
|
+
await chmod(path, 0o700);
|
|
30
|
+
const current = await lstat(path);
|
|
31
|
+
if (current.isSymbolicLink() ||
|
|
32
|
+
!current.isDirectory() ||
|
|
33
|
+
info.dev !== current.dev ||
|
|
34
|
+
info.ino !== current.ino ||
|
|
35
|
+
(await realpath(path)) !== canonical)
|
|
36
|
+
throw new Error('Pi/OMP state directory changed while opening');
|
|
37
|
+
return canonical;
|
|
38
|
+
}
|
|
25
39
|
const handle = await open(path, constants.O_RDONLY | constants.O_DIRECTORY | constants.O_NOFOLLOW);
|
|
26
40
|
try {
|
|
27
41
|
const opened = await handle.stat();
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"pi-omp-adapter.js","sourceRoot":"","sources":["../../../src/host/pi-omp-adapter.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,KAAK,EAAE,OAAO,EAAE,QAAQ,EAAE,SAAS,EAAE,KAAK,EAAE,IAAI,EAAE,MAAM,EAAE,EAAE,EAAE,MAAM,kBAAkB,CAAA;
|
|
1
|
+
{"version":3,"file":"pi-omp-adapter.js","sourceRoot":"","sources":["../../../src/host/pi-omp-adapter.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
// Set a private file-creation mask without mutating the shared Harness process.
|
|
2
|
+
import { forwardNativeStdio, spawnNativeProcess } from './native-spawn.mjs'
|
|
3
|
+
import { nativeLaunchArgv } from './native-launch.mjs'
|
|
4
|
+
process.umask(0o077)
|
|
5
|
+
const [executable, ...argv] = nativeLaunchArgv(process.argv.slice(2))
|
|
6
|
+
// This helper is also used under POSIX PTYs, whose original handles must stay.
|
|
7
|
+
// Windows ConPTY account launch unwraps it in windows-account-launch.mjs.
|
|
8
|
+
const backgroundPipes = process.platform === 'win32'
|
|
9
|
+
const child = spawnNativeProcess(executable, argv, { env: process.env, stdio: backgroundPipes ? ['pipe', 'pipe', 'pipe'] : 'inherit' })
|
|
10
|
+
if (backgroundPipes) forwardNativeStdio(child)
|
|
11
|
+
let stopped = false
|
|
12
|
+
for (const signal of ['SIGTERM', 'SIGINT'])
|
|
13
|
+
process.on(signal, () => {
|
|
14
|
+
stopped = true
|
|
15
|
+
child.kill(signal)
|
|
16
|
+
})
|
|
17
|
+
child.on('error', () => {
|
|
18
|
+
process.stderr.write('CLI launch failed\n')
|
|
19
|
+
process.exitCode = 1
|
|
20
|
+
})
|
|
21
|
+
child.on('close', (code, signal) => {
|
|
22
|
+
process.exitCode = stopped || signal ? 143 : (code ?? 1)
|
|
23
|
+
})
|