@parall/daemon 1.44.0 → 1.45.0
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/bundle/manifest.json +9 -9
- package/bundle/parall-claude-agent.js +336 -92
- package/bundle/parall-codex-agent.js +964 -1342
- package/bundle/parall-daemon.js +866 -311
- package/dist/cli.d.ts.map +1 -1
- package/dist/cli.js +229 -2
- package/dist/config.d.ts.map +1 -1
- package/dist/runtime-bin-resolver.d.ts +7 -1
- package/dist/runtime-bin-resolver.d.ts.map +1 -1
- package/dist/runtime-bin-resolver.js +57 -22
- package/dist/runtimes.d.ts +15 -4
- package/dist/runtimes.d.ts.map +1 -1
- package/dist/runtimes.js +60 -5
- package/dist/supervisor.d.ts.map +1 -1
- package/dist/supervisor.js +4 -1
- package/dist/win-lifecycle.d.ts +96 -0
- package/dist/win-lifecycle.d.ts.map +1 -0
- package/dist/win-lifecycle.js +229 -0
- package/dist/win-service.d.ts +119 -0
- package/dist/win-service.d.ts.map +1 -0
- package/dist/win-service.js +226 -0
- package/package.json +6 -6
package/dist/cli.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"cli.d.ts","sourceRoot":"","sources":["../src/cli.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"cli.d.ts","sourceRoot":"","sources":["../src/cli.ts"],"names":[],"mappings":"AAmkBA,wBAAsB,MAAM,CAAC,IAAI,EAAE,MAAM,EAAE,GAAG,OAAO,CAAC,YAAY,GAAG,SAAS,CAAC,CAuD9E"}
|
package/dist/cli.js
CHANGED
|
@@ -1,9 +1,11 @@
|
|
|
1
|
-
import { execSync, spawn } from 'node:child_process';
|
|
1
|
+
import { execFileSync, execSync, spawn } from 'node:child_process';
|
|
2
2
|
import * as fs from 'node:fs';
|
|
3
3
|
import * as os from 'node:os';
|
|
4
4
|
import * as path from 'node:path';
|
|
5
5
|
import * as readline from 'node:readline';
|
|
6
6
|
import { daemonConfigDir, daemonConfigPath } from './config.js';
|
|
7
|
+
import { WIN_TASK_NAME, buildLauncherCjs, buildLauncherVbs, buildTaskXml, encodeUtf16LeBom, winServicePaths, } from './win-service.js';
|
|
8
|
+
import { probePidIdentity, queryTaskDisabled, queryTaskExists, readTrackedPid, stopDaemonWindows, uninstallDaemonWindows, } from './win-lifecycle.js';
|
|
7
9
|
const CONFIG_DIR = daemonConfigDir();
|
|
8
10
|
const CONFIG_PATH = daemonConfigPath();
|
|
9
11
|
function readConfig() {
|
|
@@ -34,6 +36,188 @@ function isMacOS() {
|
|
|
34
36
|
function isLinux() {
|
|
35
37
|
return process.platform === 'linux';
|
|
36
38
|
}
|
|
39
|
+
function isWindows() {
|
|
40
|
+
return process.platform === 'win32';
|
|
41
|
+
}
|
|
42
|
+
// ---- Windows (Task Scheduler) service management ----
|
|
43
|
+
// Artifact generation lives in win-service.ts (pure strings); the
|
|
44
|
+
// stop/uninstall/probe state machines live in win-lifecycle.ts with
|
|
45
|
+
// injected exec/fs (fail-closed contract + unit tests). This section binds
|
|
46
|
+
// the real execFileSync/fs and owns install-time writes. All external
|
|
47
|
+
// commands run through argv arrays — no shell, so spaces / non-ASCII in
|
|
48
|
+
// %USERPROFILE% paths never need quoting here.
|
|
49
|
+
const SLEEP_SIGNAL = new Int32Array(new SharedArrayBuffer(4));
|
|
50
|
+
function sleepSync(ms) {
|
|
51
|
+
Atomics.wait(SLEEP_SIGNAL, 0, 0, ms);
|
|
52
|
+
}
|
|
53
|
+
/**
|
|
54
|
+
* Real-command binding for win-lifecycle: capture the exit code, never throw.
|
|
55
|
+
*
|
|
56
|
+
* Every call is bounded. schtasks talks to the Task Scheduler service over RPC
|
|
57
|
+
* and powershell.exe loads CIM — either can hang (a wedged service, a stalled
|
|
58
|
+
* WMI provider), and an unbounded execFileSync would block `stop` / `status` /
|
|
59
|
+
* `uninstall` forever with no way out. A timeout kills the child and surfaces
|
|
60
|
+
* as status=null → spawnError → 'indeterminate', which the fail-closed
|
|
61
|
+
* lifecycle already handles correctly (state is kept, exit is non-zero).
|
|
62
|
+
*/
|
|
63
|
+
const WIN_CMD_TIMEOUT_MS = 20_000;
|
|
64
|
+
function runWinCmd(file, args) {
|
|
65
|
+
try {
|
|
66
|
+
const stdout = execFileSync(file, args, {
|
|
67
|
+
encoding: 'utf8',
|
|
68
|
+
windowsHide: true,
|
|
69
|
+
stdio: ['ignore', 'pipe', 'ignore'],
|
|
70
|
+
timeout: WIN_CMD_TIMEOUT_MS,
|
|
71
|
+
});
|
|
72
|
+
return { code: 0, stdout };
|
|
73
|
+
}
|
|
74
|
+
catch (err) {
|
|
75
|
+
const e = err;
|
|
76
|
+
const code = typeof e.status === 'number' ? e.status : null;
|
|
77
|
+
return {
|
|
78
|
+
code,
|
|
79
|
+
stdout: String(e.stdout ?? ''),
|
|
80
|
+
spawnError: code === null ? String(e.message ?? err) : undefined,
|
|
81
|
+
};
|
|
82
|
+
}
|
|
83
|
+
}
|
|
84
|
+
function winDeps() {
|
|
85
|
+
return {
|
|
86
|
+
run: runWinCmd,
|
|
87
|
+
fs: {
|
|
88
|
+
readFile(p) {
|
|
89
|
+
try {
|
|
90
|
+
return fs.readFileSync(p, 'utf8');
|
|
91
|
+
}
|
|
92
|
+
catch {
|
|
93
|
+
return null;
|
|
94
|
+
}
|
|
95
|
+
},
|
|
96
|
+
unlink(p) {
|
|
97
|
+
try {
|
|
98
|
+
fs.unlinkSync(p);
|
|
99
|
+
return true;
|
|
100
|
+
}
|
|
101
|
+
catch (err) {
|
|
102
|
+
return err.code === 'ENOENT';
|
|
103
|
+
}
|
|
104
|
+
},
|
|
105
|
+
},
|
|
106
|
+
paths: winServicePaths(os.homedir()),
|
|
107
|
+
sleep: sleepSync,
|
|
108
|
+
now: () => Date.now(),
|
|
109
|
+
};
|
|
110
|
+
}
|
|
111
|
+
function reportWinProblems(problems) {
|
|
112
|
+
for (const problem of problems) {
|
|
113
|
+
console.error(`ERROR: ${problem}`);
|
|
114
|
+
}
|
|
115
|
+
console.error('State was left in place so nothing is orphaned; fix the cause and retry.');
|
|
116
|
+
}
|
|
117
|
+
function installServiceWindows() {
|
|
118
|
+
let npmEntry;
|
|
119
|
+
try {
|
|
120
|
+
npmEntry = fs.realpathSync(process.argv[1] ?? '');
|
|
121
|
+
}
|
|
122
|
+
catch {
|
|
123
|
+
console.error('Cannot resolve the daemon entry script; reinstall with `npm install -g @parall/daemon`.');
|
|
124
|
+
process.exit(1);
|
|
125
|
+
}
|
|
126
|
+
if (/[\\/]_npx[\\/]/.test(npmEntry)) {
|
|
127
|
+
console.warn('Warning: installing from an npx cache path. Run `npm install -g @parall/daemon` and re-run\n' +
|
|
128
|
+
'`parall-daemon service install`, or the service breaks when the npx cache is pruned\n' +
|
|
129
|
+
'(a completed self-update heals this by switching to the overlay bundle).');
|
|
130
|
+
}
|
|
131
|
+
const p = winServicePaths(os.homedir());
|
|
132
|
+
fs.mkdirSync(p.serviceDir, { recursive: true });
|
|
133
|
+
fs.mkdirSync(p.logDir, { recursive: true });
|
|
134
|
+
fs.writeFileSync(p.launcherCjs, buildLauncherCjs({
|
|
135
|
+
npmEntry,
|
|
136
|
+
overlayEntry: p.overlayEntry,
|
|
137
|
+
pidFile: p.pidFile,
|
|
138
|
+
logFile: p.logFile,
|
|
139
|
+
}));
|
|
140
|
+
// Pre-.cjs installs wrote a .js launcher; remove it so nothing stale can
|
|
141
|
+
// be referenced or mistaken for the active artifact.
|
|
142
|
+
try {
|
|
143
|
+
fs.unlinkSync(p.legacyLauncherJs);
|
|
144
|
+
}
|
|
145
|
+
catch { }
|
|
146
|
+
const wscriptExe = path.join(process.env.SystemRoot || 'C:\\Windows', 'System32', 'wscript.exe');
|
|
147
|
+
fs.writeFileSync(p.launcherVbs, encodeUtf16LeBom(buildLauncherVbs({ nodeExe: process.execPath, launcherCjs: p.launcherCjs })));
|
|
148
|
+
fs.writeFileSync(p.taskXml, encodeUtf16LeBom(buildTaskXml({ wscriptExe, launcherVbs: p.launcherVbs })));
|
|
149
|
+
// /F replaces an existing task; without it schtasks prompts interactively
|
|
150
|
+
// and a scripted install hangs.
|
|
151
|
+
const create = runWinCmd('schtasks', ['/Create', '/TN', WIN_TASK_NAME, '/XML', p.taskXml, '/F']);
|
|
152
|
+
if (create.code !== 0) {
|
|
153
|
+
console.error(`ERROR: could not register the Task Scheduler task (schtasks /Create exit ${create.code ?? 'spawn-failed'}).`);
|
|
154
|
+
console.error(` Task XML: ${p.taskXml}`);
|
|
155
|
+
process.exit(1);
|
|
156
|
+
}
|
|
157
|
+
// `/Run` triggers the task; it does not wait for the daemon, and install
|
|
158
|
+
// deliberately does not wait either. A healthy first launch may self-update
|
|
159
|
+
// and exit(42), which Task Scheduler only re-runs ~1 minute later
|
|
160
|
+
// (RestartOnFailure PT1M) — so any short liveness window here would report a
|
|
161
|
+
// perfectly good install as a failure. Registering + triggering is what this
|
|
162
|
+
// command owns; runtime health is `parall-daemon status` / `logs`.
|
|
163
|
+
const run = runWinCmd('schtasks', ['/Run', '/TN', WIN_TASK_NAME]);
|
|
164
|
+
if (run.code !== 0) {
|
|
165
|
+
console.error(`ERROR: the task registered but would not start (schtasks /Run exit ${run.code ?? 'spawn-failed'}).`);
|
|
166
|
+
console.error(` Start it from Task Scheduler, or check ${p.logFile}.`);
|
|
167
|
+
process.exit(1);
|
|
168
|
+
}
|
|
169
|
+
console.log(`Task Scheduler task installed: ${WIN_TASK_NAME} (artifacts in ${p.serviceDir})`);
|
|
170
|
+
console.log('Task registered and triggered. Check `parall-daemon status` for the daemon itself.');
|
|
171
|
+
console.log(`Logs: ${p.logFile}`);
|
|
172
|
+
}
|
|
173
|
+
function stopWindows() {
|
|
174
|
+
const result = stopDaemonWindows(winDeps());
|
|
175
|
+
if (!result.ok) {
|
|
176
|
+
reportWinProblems(result.problems);
|
|
177
|
+
process.exit(1);
|
|
178
|
+
}
|
|
179
|
+
console.log('Daemon stopped (Task Scheduler task disabled). Re-arm with `parall-daemon service install`.');
|
|
180
|
+
}
|
|
181
|
+
function statusWindows() {
|
|
182
|
+
const deps = winDeps();
|
|
183
|
+
const exists = queryTaskExists(deps);
|
|
184
|
+
if (exists === 'indeterminate') {
|
|
185
|
+
console.log('Service: unknown (schtasks query failed)');
|
|
186
|
+
}
|
|
187
|
+
else if (!exists) {
|
|
188
|
+
console.log('Service: not installed');
|
|
189
|
+
}
|
|
190
|
+
else {
|
|
191
|
+
const disabled = queryTaskDisabled(deps);
|
|
192
|
+
const suffix = disabled === true ? ', disabled' : disabled === 'indeterminate' ? ', state unknown' : '';
|
|
193
|
+
console.log(`Service: installed${suffix} (Task Scheduler: ${WIN_TASK_NAME})`);
|
|
194
|
+
}
|
|
195
|
+
const pid = readTrackedPid(deps);
|
|
196
|
+
if (pid === null) {
|
|
197
|
+
console.log('Daemon: stopped');
|
|
198
|
+
return;
|
|
199
|
+
}
|
|
200
|
+
switch (probePidIdentity(deps, pid)) {
|
|
201
|
+
case 'daemon':
|
|
202
|
+
console.log('Daemon: running');
|
|
203
|
+
console.log(`PID: ${pid}`);
|
|
204
|
+
break;
|
|
205
|
+
case 'not-daemon':
|
|
206
|
+
console.log('Daemon: stopped (stale pidfile)');
|
|
207
|
+
break;
|
|
208
|
+
case 'indeterminate':
|
|
209
|
+
console.log(`Daemon: unknown (could not verify pid ${pid} — process query failed)`);
|
|
210
|
+
break;
|
|
211
|
+
}
|
|
212
|
+
}
|
|
213
|
+
function serviceUninstallWindows() {
|
|
214
|
+
const result = uninstallDaemonWindows(winDeps());
|
|
215
|
+
if (!result.ok) {
|
|
216
|
+
reportWinProblems(result.problems);
|
|
217
|
+
process.exit(1);
|
|
218
|
+
}
|
|
219
|
+
console.log('Task Scheduler task uninstalled (logs kept).');
|
|
220
|
+
}
|
|
37
221
|
const PLIST_LABEL = 'com.parall.daemon';
|
|
38
222
|
function plistPath() {
|
|
39
223
|
return path.join(os.homedir(), 'Library', 'LaunchAgents', `${PLIST_LABEL}.plist`);
|
|
@@ -102,11 +286,20 @@ RestartSec=5
|
|
|
102
286
|
WantedBy=default.target`;
|
|
103
287
|
}
|
|
104
288
|
function installService() {
|
|
289
|
+
// A service-managed daemon (launchd / systemd / Task Scheduler) never
|
|
290
|
+
// inherits the installing shell's environment, so config.json is its only
|
|
291
|
+
// credential channel. `init` writes it; `service install` requires it.
|
|
105
292
|
const config = readConfig();
|
|
106
293
|
if (!config) {
|
|
107
294
|
console.error('No config found. Run `parall-daemon init` first.');
|
|
108
295
|
process.exit(1);
|
|
109
296
|
}
|
|
297
|
+
if (isWindows()) {
|
|
298
|
+
// Windows resolves its own entry (realpath of argv[1]); `which` in
|
|
299
|
+
// getDaemonBin is POSIX-only.
|
|
300
|
+
installServiceWindows();
|
|
301
|
+
return;
|
|
302
|
+
}
|
|
110
303
|
const bin = getDaemonBin();
|
|
111
304
|
if (isMacOS()) {
|
|
112
305
|
const dir = path.dirname(plistPath());
|
|
@@ -147,6 +340,10 @@ async function cmdInit() {
|
|
|
147
340
|
function cmdStatus() {
|
|
148
341
|
const config = readConfig();
|
|
149
342
|
console.log(`Config: ${config ? CONFIG_PATH : 'not configured'}`);
|
|
343
|
+
if (isWindows()) {
|
|
344
|
+
statusWindows();
|
|
345
|
+
return;
|
|
346
|
+
}
|
|
150
347
|
if (isMacOS()) {
|
|
151
348
|
try {
|
|
152
349
|
const output = execSync(`launchctl print gui/$(id -u)/${PLIST_LABEL} 2>&1`, {
|
|
@@ -173,6 +370,10 @@ function cmdStatus() {
|
|
|
173
370
|
}
|
|
174
371
|
}
|
|
175
372
|
function cmdStop() {
|
|
373
|
+
if (isWindows()) {
|
|
374
|
+
stopWindows();
|
|
375
|
+
return;
|
|
376
|
+
}
|
|
176
377
|
if (isMacOS()) {
|
|
177
378
|
execSync(`launchctl bootout gui/$(id -u) ${plistPath()} 2>/dev/null || true`, {
|
|
178
379
|
stdio: 'inherit',
|
|
@@ -191,6 +392,28 @@ function cmdLogs(lines) {
|
|
|
191
392
|
child.on('exit', (code) => process.exit(code ?? 0));
|
|
192
393
|
return;
|
|
193
394
|
}
|
|
395
|
+
if (isWindows()) {
|
|
396
|
+
const p = winServicePaths(os.homedir());
|
|
397
|
+
if (!fs.existsSync(p.logFile)) {
|
|
398
|
+
console.log('No log file found at', p.logFile);
|
|
399
|
+
return;
|
|
400
|
+
}
|
|
401
|
+
// The path is handed to PowerShell through the ENVIRONMENT, never through
|
|
402
|
+
// the script text: `$env:` expansion happens after parsing, so no quoting
|
|
403
|
+
// scheme (and no backtick / $() sequence in a profile path) can alter the
|
|
404
|
+
// command. -LiteralPath additionally stops `[ ]` being read as a wildcard.
|
|
405
|
+
// `lines` is dispatch-validated, but re-derive an integer here so this call
|
|
406
|
+
// site is provably interpolation-free on its own.
|
|
407
|
+
const tailCount = Number.parseInt(lines, 10);
|
|
408
|
+
const tail = Number.isInteger(tailCount) && tailCount > 0 ? tailCount : 50;
|
|
409
|
+
const child = spawn('powershell.exe', [
|
|
410
|
+
'-NoProfile',
|
|
411
|
+
'-Command',
|
|
412
|
+
`Get-Content -LiteralPath $env:PRLL_DAEMON_LOG_PATH -Tail ${tail} -Wait`,
|
|
413
|
+
], { stdio: 'inherit', env: { ...process.env, PRLL_DAEMON_LOG_PATH: p.logFile } });
|
|
414
|
+
child.on('exit', (code) => process.exit(code ?? 0));
|
|
415
|
+
return;
|
|
416
|
+
}
|
|
194
417
|
const logPath = path.join(os.homedir(), 'Library', 'Logs', 'parall-daemon.log');
|
|
195
418
|
if (!fs.existsSync(logPath)) {
|
|
196
419
|
console.log('No log file found at', logPath);
|
|
@@ -200,6 +423,10 @@ function cmdLogs(lines) {
|
|
|
200
423
|
child.on('exit', (code) => process.exit(code ?? 0));
|
|
201
424
|
}
|
|
202
425
|
function cmdServiceUninstall() {
|
|
426
|
+
if (isWindows()) {
|
|
427
|
+
serviceUninstallWindows();
|
|
428
|
+
return;
|
|
429
|
+
}
|
|
203
430
|
if (isMacOS()) {
|
|
204
431
|
execSync(`launchctl bootout gui/$(id -u) ${plistPath()} 2>/dev/null || true`);
|
|
205
432
|
if (fs.existsSync(plistPath()))
|
|
@@ -269,7 +496,7 @@ Usage:
|
|
|
269
496
|
parall-daemon stop Stop the background service
|
|
270
497
|
parall-daemon update [--check] Check for / apply daemon updates
|
|
271
498
|
parall-daemon logs [-n LINES] Tail daemon logs
|
|
272
|
-
parall-daemon service install Install as background service (launchd/systemd)
|
|
499
|
+
parall-daemon service install Install as background service (launchd/systemd/Task Scheduler)
|
|
273
500
|
parall-daemon service uninstall Uninstall background service
|
|
274
501
|
parall-daemon help Show this help
|
|
275
502
|
`.trim());
|
package/dist/config.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"config.d.ts","sourceRoot":"","sources":["../src/config.ts"],"names":[],"mappings":"AAGA,OAAO,EAAE,eAAe,EAAE,gBAAgB,EAAe,MAAM,mBAAmB,CAAC;AAEnF,OAAO,EAAE,eAAe,EAAE,gBAAgB,EAAE,CAAC;AAE7C;;;;;;;;;;;GAWG;AACH,MAAM,MAAM,kBAAkB,GAAG;IAC/B,MAAM,EAAE,MAAM,CAAC;IACf,qCAAqC;IACrC,MAAM,EAAE,MAAM,CAAC;IACf,2GAA2G;IAC3G,QAAQ,EAAE,MAAM,CAAC;IACjB,yFAAyF;IACzF,YAAY,EAAE,MAAM,CAAC;IACrB,kGAAkG;IAClG,cAAc,EAAE,MAAM,CAAC;IACvB,wEAAwE;IACxE,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,oDAAoD;IACpD,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,iFAAiF;IACjF,cAAc,EAAE,MAAM,CAAC;IACvB,iFAAiF;IACjF,mBAAmB,EAAE,MAAM,CAAC;IAC5B,oDAAoD;IACpD,gBAAgB,EAAE,MAAM,CAAC;IACzB,oFAAoF;IACpF,mBAAmB,EAAE,MAAM,CAAC;IAC5B;;;;;OAKG;IACH,kBAAkB,EAAE,MAAM,CAAC;IAC3B,qBAAqB,EAAE,MAAM,CAAC;IAC9B;;;;OAIG;IACH,0BAA0B,EAAE,MAAM,CAAC;IACnC,6BAA6B,EAAE,MAAM,CAAC;IACtC,yEAAyE;IACzE,YAAY,EAAE,MAAM,CAAC;IACrB,gFAAgF;IAChF,gBAAgB,EAAE,MAAM,CAAC;IACzB,4DAA4D;IAC5D,cAAc,EAAE,OAAO,CAAC;IACxB;;;;;;OAMG;IACH,oBAAoB,EAAE,MAAM,CAAC;IAC7B;;;;;OAKG;IACH,qBAAqB,EAAE,OAAO,CAAC;CAChC,CAAC;AAuBF,wBAAgB,gBAAgB,CAAC,GAAG,GAAE,MAAM,CAAC,UAAwB,GAAG,MAAM,CAE7E;
|
|
1
|
+
{"version":3,"file":"config.d.ts","sourceRoot":"","sources":["../src/config.ts"],"names":[],"mappings":"AAGA,OAAO,EAAE,eAAe,EAAE,gBAAgB,EAAe,MAAM,mBAAmB,CAAC;AAEnF,OAAO,EAAE,eAAe,EAAE,gBAAgB,EAAE,CAAC;AAE7C;;;;;;;;;;;GAWG;AACH,MAAM,MAAM,kBAAkB,GAAG;IAC/B,MAAM,EAAE,MAAM,CAAC;IACf,qCAAqC;IACrC,MAAM,EAAE,MAAM,CAAC;IACf,2GAA2G;IAC3G,QAAQ,EAAE,MAAM,CAAC;IACjB,yFAAyF;IACzF,YAAY,EAAE,MAAM,CAAC;IACrB,kGAAkG;IAClG,cAAc,EAAE,MAAM,CAAC;IACvB,wEAAwE;IACxE,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,oDAAoD;IACpD,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,iFAAiF;IACjF,cAAc,EAAE,MAAM,CAAC;IACvB,iFAAiF;IACjF,mBAAmB,EAAE,MAAM,CAAC;IAC5B,oDAAoD;IACpD,gBAAgB,EAAE,MAAM,CAAC;IACzB,oFAAoF;IACpF,mBAAmB,EAAE,MAAM,CAAC;IAC5B;;;;;OAKG;IACH,kBAAkB,EAAE,MAAM,CAAC;IAC3B,qBAAqB,EAAE,MAAM,CAAC;IAC9B;;;;OAIG;IACH,0BAA0B,EAAE,MAAM,CAAC;IACnC,6BAA6B,EAAE,MAAM,CAAC;IACtC,yEAAyE;IACzE,YAAY,EAAE,MAAM,CAAC;IACrB,gFAAgF;IAChF,gBAAgB,EAAE,MAAM,CAAC;IACzB,4DAA4D;IAC5D,cAAc,EAAE,OAAO,CAAC;IACxB;;;;;;OAMG;IACH,oBAAoB,EAAE,MAAM,CAAC;IAC7B;;;;;OAKG;IACH,qBAAqB,EAAE,OAAO,CAAC;CAChC,CAAC;AAuBF,wBAAgB,gBAAgB,CAAC,GAAG,GAAE,MAAM,CAAC,UAAwB,GAAG,MAAM,CAE7E;AA+BD,wBAAgB,yBAAyB,CACvC,GAAG,GAAE,MAAM,CAAC,UAAwB,GACnC,kBAAkB,CA+DpB;AASD,wDAAwD;AACxD,wBAAgB,gBAAgB,CAAC,YAAY,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,GAAG,MAAM,CAE9E;AAED;;mEAEmE;AACnE,wBAAgB,kBAAkB,CAAC,cAAc,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,GAAG,MAAM,CAElF;AAED,+EAA+E;AAC/E,wBAAgB,8BAA8B,CAAC,cAAc,EAAE,MAAM,GAAG,MAAM,CAE7E;AAED,uEAAuE;AACvE,wBAAgB,6BAA6B,CAAC,eAAe,EAAE,MAAM,GAAG,MAAM,CAE7E;AAED,iEAAiE;AACjE,wBAAgB,oBAAoB,CAAC,YAAY,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,GAAG,MAAM,CAElF;AAED,8EAA8E;AAC9E,wBAAgB,eAAe,CAAC,YAAY,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,GAAG,MAAM,CAE7E;AAED;;;;GAIG;AACH,wBAAgB,2BAA2B,CAAC,GAAG,GAAE,MAAM,CAAC,UAAwB,GAAG,OAAO,CAEzF;AAED,wBAAgB,YAAY,CAC1B,MAAM,EAAE,MAAM,EACd,aAAa,CAAC,EAAE,MAAM,EACtB,YAAY,CAAC,EAAE,MAAM,GACpB,MAAM,CAMR"}
|
|
@@ -2,10 +2,16 @@ type RuntimeBinLogger = {
|
|
|
2
2
|
info: (msg: string) => void;
|
|
3
3
|
warn: (msg: string) => void;
|
|
4
4
|
};
|
|
5
|
+
type RuntimePathPlan = {
|
|
6
|
+
primaryDirs: string[];
|
|
7
|
+
versionedFallbackDirs: string[];
|
|
8
|
+
};
|
|
5
9
|
/** Runtime types whose host CLI the resolver knows how to locate. */
|
|
6
10
|
export declare const DETECTABLE_RUNTIME_TYPES: readonly string[];
|
|
7
11
|
/** The env var `applyRuntimeBinaryEnv` publishes the resolved binary under. */
|
|
8
12
|
export declare function runtimeBinaryEnvVar(runtimeType: string): string | undefined;
|
|
9
|
-
export declare function applyRuntimeBinaryEnv(runtimeType: string, baseEnv: NodeJS.ProcessEnv, log: RuntimeBinLogger): NodeJS.ProcessEnv;
|
|
13
|
+
export declare function applyRuntimeBinaryEnv(runtimeType: string, baseEnv: NodeJS.ProcessEnv, log: RuntimeBinLogger, platform?: NodeJS.Platform): NodeJS.ProcessEnv;
|
|
14
|
+
export declare function candidatePathPlan(env: NodeJS.ProcessEnv, platform?: NodeJS.Platform): RuntimePathPlan;
|
|
15
|
+
export declare function commandCandidates(command: string, env: NodeJS.ProcessEnv, platform?: NodeJS.Platform): string[];
|
|
10
16
|
export {};
|
|
11
17
|
//# sourceMappingURL=runtime-bin-resolver.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"runtime-bin-resolver.d.ts","sourceRoot":"","sources":["../src/runtime-bin-resolver.ts"],"names":[],"mappings":"AAUA,KAAK,gBAAgB,GAAG;IACtB,IAAI,EAAE,CAAC,GAAG,EAAE,MAAM,KAAK,IAAI,CAAC;IAC5B,IAAI,EAAE,CAAC,GAAG,EAAE,MAAM,KAAK,IAAI,CAAC;CAC7B,CAAC;
|
|
1
|
+
{"version":3,"file":"runtime-bin-resolver.d.ts","sourceRoot":"","sources":["../src/runtime-bin-resolver.ts"],"names":[],"mappings":"AAUA,KAAK,gBAAgB,GAAG;IACtB,IAAI,EAAE,CAAC,GAAG,EAAE,MAAM,KAAK,IAAI,CAAC;IAC5B,IAAI,EAAE,CAAC,GAAG,EAAE,MAAM,KAAK,IAAI,CAAC;CAC7B,CAAC;AAEF,KAAK,eAAe,GAAG;IACrB,WAAW,EAAE,MAAM,EAAE,CAAC;IACtB,qBAAqB,EAAE,MAAM,EAAE,CAAC;CACjC,CAAC;AA2BF,qEAAqE;AACrE,eAAO,MAAM,wBAAwB,EAAE,SAAS,MAAM,EAAkC,CAAC;AAEzF,+EAA+E;AAC/E,wBAAgB,mBAAmB,CAAC,WAAW,EAAE,MAAM,GAAG,MAAM,GAAG,SAAS,CAE3E;AAKD,wBAAgB,qBAAqB,CACnC,WAAW,EAAE,MAAM,EACnB,OAAO,EAAE,MAAM,CAAC,UAAU,EAC1B,GAAG,EAAE,gBAAgB,EACrB,QAAQ,GAAE,MAAM,CAAC,QAA2B,GAC3C,MAAM,CAAC,UAAU,CAiDnB;AAuJD,wBAAgB,iBAAiB,CAC/B,GAAG,EAAE,MAAM,CAAC,UAAU,EACtB,QAAQ,GAAE,MAAM,CAAC,QAA2B,GAC3C,eAAe,CA6DjB;AAyED,wBAAgB,iBAAiB,CAC/B,OAAO,EAAE,MAAM,EACf,GAAG,EAAE,MAAM,CAAC,UAAU,EACtB,QAAQ,GAAE,MAAM,CAAC,QAA2B,GAC3C,MAAM,EAAE,CAcV"}
|
|
@@ -15,10 +15,10 @@ export function runtimeBinaryEnvVar(runtimeType) {
|
|
|
15
15
|
}
|
|
16
16
|
const RESOLUTION_CACHE_TTL_MS = 5 * 60_000;
|
|
17
17
|
const resolutionCache = new Map();
|
|
18
|
-
export function applyRuntimeBinaryEnv(runtimeType, baseEnv, log) {
|
|
18
|
+
export function applyRuntimeBinaryEnv(runtimeType, baseEnv, log, platform = process.platform) {
|
|
19
19
|
const env = { ...baseEnv };
|
|
20
20
|
const originalPath = env.PATH;
|
|
21
|
-
const pathPlan = cachedCandidatePathPlan(env);
|
|
21
|
+
const pathPlan = cachedCandidatePathPlan(env, platform);
|
|
22
22
|
const primaryPath = mergePath(pathPlan.primaryDirs, originalPath);
|
|
23
23
|
env.PATH = mergePath([...pathPlan.primaryDirs, ...pathPlan.versionedFallbackDirs], originalPath);
|
|
24
24
|
const spec = RUNTIME_BINARIES[runtimeType];
|
|
@@ -26,7 +26,7 @@ export function applyRuntimeBinaryEnv(runtimeType, baseEnv, log) {
|
|
|
26
26
|
return env;
|
|
27
27
|
const configured = env[spec.envVar]?.trim();
|
|
28
28
|
if (configured) {
|
|
29
|
-
const resolved = resolveRuntimeCommand(configured, env, originalPath, primaryPath, env.PATH);
|
|
29
|
+
const resolved = resolveRuntimeCommand(configured, env, originalPath, primaryPath, env.PATH, platform);
|
|
30
30
|
if (resolved) {
|
|
31
31
|
env[spec.envVar] = resolved.binaryPath;
|
|
32
32
|
env.PATH = anchorResolvedPath(env.PATH, resolved);
|
|
@@ -37,7 +37,7 @@ export function applyRuntimeBinaryEnv(runtimeType, baseEnv, log) {
|
|
|
37
37
|
}
|
|
38
38
|
return env;
|
|
39
39
|
}
|
|
40
|
-
const resolved = resolveRuntimeCommand(spec.command, env, originalPath, primaryPath, env.PATH);
|
|
40
|
+
const resolved = resolveRuntimeCommand(spec.command, env, originalPath, primaryPath, env.PATH, platform);
|
|
41
41
|
if (resolved) {
|
|
42
42
|
env[spec.envVar] = resolved.binaryPath;
|
|
43
43
|
env.PATH = anchorResolvedPath(env.PATH, resolved);
|
|
@@ -49,8 +49,8 @@ export function applyRuntimeBinaryEnv(runtimeType, baseEnv, log) {
|
|
|
49
49
|
}
|
|
50
50
|
return env;
|
|
51
51
|
}
|
|
52
|
-
function resolveRuntimeCommand(command, env, inheritedPath, primaryPath, fallbackPath) {
|
|
53
|
-
const cacheKey = `runtime\0${command}\0${primaryPath}\0${fallbackPath}\0${env.SHELL ?? ''}\0${env.HOME ?? ''}`;
|
|
52
|
+
function resolveRuntimeCommand(command, env, inheritedPath, primaryPath, fallbackPath, platform) {
|
|
53
|
+
const cacheKey = `runtime\0${command}\0${primaryPath}\0${fallbackPath}\0${env.SHELL ?? ''}\0${env.HOME ?? ''}\0${platform}`;
|
|
54
54
|
const cached = getCachedResolution(cacheKey);
|
|
55
55
|
if (cached)
|
|
56
56
|
return cached;
|
|
@@ -63,24 +63,24 @@ function resolveRuntimeCommand(command, env, inheritedPath, primaryPath, fallbac
|
|
|
63
63
|
setCachedResolution(cacheKey, resolved);
|
|
64
64
|
return resolved;
|
|
65
65
|
}
|
|
66
|
-
const fromInheritedPath = resolveFromPath(command, inheritedPath, env);
|
|
66
|
+
const fromInheritedPath = resolveFromPath(command, inheritedPath, env, platform);
|
|
67
67
|
if (fromInheritedPath) {
|
|
68
68
|
setCachedResolution(cacheKey, fromInheritedPath);
|
|
69
69
|
return fromInheritedPath;
|
|
70
70
|
}
|
|
71
71
|
if (runLoginShell) {
|
|
72
|
-
const fromShell = resolveFromLoginShell(command, { ...env, PATH: inheritedPath });
|
|
72
|
+
const fromShell = resolveFromLoginShell(command, { ...env, PATH: inheritedPath }, platform);
|
|
73
73
|
if (fromShell) {
|
|
74
74
|
setCachedResolution(cacheKey, fromShell);
|
|
75
75
|
return fromShell;
|
|
76
76
|
}
|
|
77
77
|
}
|
|
78
|
-
const fromPrimaryPath = resolveFromPath(command, primaryPath, env);
|
|
78
|
+
const fromPrimaryPath = resolveFromPath(command, primaryPath, env, platform);
|
|
79
79
|
if (fromPrimaryPath) {
|
|
80
80
|
setCachedResolution(cacheKey, fromPrimaryPath);
|
|
81
81
|
return fromPrimaryPath;
|
|
82
82
|
}
|
|
83
|
-
const fromFallbackPath = fallbackPath === primaryPath ? null : resolveFromPath(command, fallbackPath, env);
|
|
83
|
+
const fromFallbackPath = fallbackPath === primaryPath ? null : resolveFromPath(command, fallbackPath, env, platform);
|
|
84
84
|
if (fromFallbackPath) {
|
|
85
85
|
setCachedResolution(cacheKey, fromFallbackPath);
|
|
86
86
|
return fromFallbackPath;
|
|
@@ -99,12 +99,12 @@ function resolveDirectPath(command) {
|
|
|
99
99
|
const abs = path.isAbsolute(command) ? command : path.resolve(process.cwd(), command);
|
|
100
100
|
return isExecutable(abs) ? abs : null;
|
|
101
101
|
}
|
|
102
|
-
function resolveFromPath(command, pathValue, env) {
|
|
102
|
+
function resolveFromPath(command, pathValue, env, platform) {
|
|
103
103
|
if (!pathValue || command.includes('/') || command.includes('\\'))
|
|
104
104
|
return null;
|
|
105
105
|
const dirs = pathValue.split(path.delimiter).filter(Boolean);
|
|
106
106
|
for (const dir of dirs) {
|
|
107
|
-
for (const file of commandCandidates(command, env)) {
|
|
107
|
+
for (const file of commandCandidates(command, env, platform)) {
|
|
108
108
|
const candidate = path.join(dir, file);
|
|
109
109
|
if (isExecutable(candidate))
|
|
110
110
|
return { binaryPath: candidate, pathValue };
|
|
@@ -112,12 +112,17 @@ function resolveFromPath(command, pathValue, env) {
|
|
|
112
112
|
}
|
|
113
113
|
return null;
|
|
114
114
|
}
|
|
115
|
-
function resolveFromLoginShell(command, env) {
|
|
115
|
+
function resolveFromLoginShell(command, env, platform) {
|
|
116
|
+
// No POSIX login shell to consult on Windows — and a Git-Bash user's
|
|
117
|
+
// SHELL=...bash.exe must not pull this synchronous probe (execFileSync,
|
|
118
|
+
// up to ~2.5s × 3 shells) into the spawn path.
|
|
119
|
+
if (platform === 'win32')
|
|
120
|
+
return null;
|
|
116
121
|
if (command.includes('/') || command.includes('\\'))
|
|
117
122
|
return null;
|
|
118
123
|
const shells = unique([
|
|
119
124
|
env.SHELL?.trim(),
|
|
120
|
-
|
|
125
|
+
platform === 'darwin' ? '/bin/zsh' : undefined,
|
|
121
126
|
'/bin/bash',
|
|
122
127
|
'/bin/sh',
|
|
123
128
|
]);
|
|
@@ -158,17 +163,42 @@ function resolveFromLoginShell(command, env) {
|
|
|
158
163
|
// TTL as resolutions. A freshly installed version manager dir therefore shows
|
|
159
164
|
// up within one detection interval, same as everything else here.
|
|
160
165
|
const pathPlanCache = new Map();
|
|
161
|
-
function cachedCandidatePathPlan(env) {
|
|
162
|
-
const key = `${env.HOME ?? ''}\0${env.PRLL_DAEMON_RUNTIME_PATH ?? ''}\0${env.PRLL_DAEMON_EXTRA_PATH ?? ''}`;
|
|
166
|
+
function cachedCandidatePathPlan(env, platform) {
|
|
167
|
+
const key = `${env.HOME ?? ''}\0${env.PRLL_DAEMON_RUNTIME_PATH ?? ''}\0${env.PRLL_DAEMON_EXTRA_PATH ?? ''}\0${env.APPDATA ?? ''}\0${env.LOCALAPPDATA ?? ''}\0${env.PNPM_HOME ?? ''}\0${platform}`;
|
|
163
168
|
const hit = pathPlanCache.get(key);
|
|
164
169
|
if (hit && hit.expiresAt > Date.now())
|
|
165
170
|
return hit.value;
|
|
166
|
-
const value = candidatePathPlan(env);
|
|
171
|
+
const value = candidatePathPlan(env, platform);
|
|
167
172
|
pathPlanCache.set(key, { value, expiresAt: Date.now() + RESOLUTION_CACHE_TTL_MS });
|
|
168
173
|
return value;
|
|
169
174
|
}
|
|
170
|
-
function candidatePathPlan(env) {
|
|
175
|
+
export function candidatePathPlan(env, platform = process.platform) {
|
|
171
176
|
const home = env.HOME || os.homedir();
|
|
177
|
+
if (platform === 'win32') {
|
|
178
|
+
// Windows install layouts. HOME is rarely set there (os.homedir() reads
|
|
179
|
+
// USERPROFILE); APPDATA/LOCALAPPDATA are always present in real sessions
|
|
180
|
+
// but keep derived fallbacks for stripped service environments.
|
|
181
|
+
const appData = env.APPDATA || path.join(home, 'AppData', 'Roaming');
|
|
182
|
+
const localAppData = env.LOCALAPPDATA || path.join(home, 'AppData', 'Local');
|
|
183
|
+
const winPrimaryDirs = [
|
|
184
|
+
...splitPath(env.PRLL_DAEMON_RUNTIME_PATH),
|
|
185
|
+
...splitPath(env.PRLL_DAEMON_EXTRA_PATH),
|
|
186
|
+
path.dirname(process.execPath),
|
|
187
|
+
env.PNPM_HOME,
|
|
188
|
+
path.join(appData, 'npm'),
|
|
189
|
+
path.join(localAppData, 'pnpm'),
|
|
190
|
+
path.join(localAppData, 'Volta', 'bin'),
|
|
191
|
+
path.join(home, '.volta', 'bin'),
|
|
192
|
+
path.join(home, '.bun', 'bin'),
|
|
193
|
+
];
|
|
194
|
+
// No versioned fallback scan on Windows: nvm-windows exposes the active
|
|
195
|
+
// version through the nodejs junction already on PATH (and execPath's
|
|
196
|
+
// dir above). Exotic layouts use PRLL_DAEMON_RUNTIME_PATH.
|
|
197
|
+
return {
|
|
198
|
+
primaryDirs: unique(winPrimaryDirs).filter((dir) => !!dir && isDirectory(dir)),
|
|
199
|
+
versionedFallbackDirs: [],
|
|
200
|
+
};
|
|
201
|
+
}
|
|
172
202
|
const primaryDirs = [
|
|
173
203
|
...splitPath(env.PRLL_DAEMON_RUNTIME_PATH),
|
|
174
204
|
...splitPath(env.PRLL_DAEMON_EXTRA_PATH),
|
|
@@ -263,17 +293,22 @@ function mergePath(prependDirs, existing) {
|
|
|
263
293
|
function anchorResolvedPath(pathValue, resolution) {
|
|
264
294
|
return mergePath([path.dirname(resolution.binaryPath), ...splitPath(resolution.pathValue)], pathValue);
|
|
265
295
|
}
|
|
266
|
-
function commandCandidates(command, env) {
|
|
267
|
-
if (
|
|
296
|
+
export function commandCandidates(command, env, platform = process.platform) {
|
|
297
|
+
if (platform !== 'win32')
|
|
268
298
|
return [command];
|
|
269
299
|
const hasExt = /\.[^\\/]+$/.test(command);
|
|
270
300
|
if (hasExt)
|
|
271
301
|
return [command];
|
|
272
|
-
|
|
302
|
+
// PATHEXT-suffixed candidates ONLY, in PATHEXT order (fallback mirrors the
|
|
303
|
+
// Windows default order). A bare-name candidate must not be offered:
|
|
304
|
+
// accessSync(X_OK) passes for any readable file on Windows, so it would
|
|
305
|
+
// resolve to npm's extension-less sh shim sitting next to the .cmd — a
|
|
306
|
+
// file nothing on Windows can actually execute.
|
|
307
|
+
const exts = (env.PATHEXT || '.COM;.EXE;.BAT;.CMD')
|
|
273
308
|
.split(';')
|
|
274
309
|
.filter(Boolean)
|
|
275
310
|
.map((ext) => ext.toLowerCase());
|
|
276
|
-
return
|
|
311
|
+
return exts.map((ext) => `${command}${ext}`);
|
|
277
312
|
}
|
|
278
313
|
/** undefined = no cache entry; null = cached miss (see ResolutionCacheEntry). */
|
|
279
314
|
function getCachedResolution(cacheKey) {
|
package/dist/runtimes.d.ts
CHANGED
|
@@ -19,11 +19,22 @@ export interface AgentDirs {
|
|
|
19
19
|
*/
|
|
20
20
|
homeDir?: string;
|
|
21
21
|
}
|
|
22
|
+
/** Injectable resolution inputs — production callers pass nothing. */
|
|
23
|
+
export interface RuntimeAdapterResolveOptions {
|
|
24
|
+
env?: NodeJS.ProcessEnv;
|
|
25
|
+
entryPath?: string;
|
|
26
|
+
}
|
|
22
27
|
/**
|
|
23
|
-
* Resolve a runtime adapter
|
|
24
|
-
*
|
|
25
|
-
*
|
|
28
|
+
* Resolve a runtime adapter. Bridge bins resolve in three tiers:
|
|
29
|
+
* 1. overlay bundle (~/.parall-daemon/bundle/current/) — a self-updated
|
|
30
|
+
* daemon must load bridges from the same overlay to keep versions in sync;
|
|
31
|
+
* 2. entry-sibling bundle (bundledSiblingBin above) — the npm/CDN package's
|
|
32
|
+
* own flat bundle directory;
|
|
33
|
+
* 3. bare bin name via PATH — dev checkouts running from dist/, where the
|
|
34
|
+
* workspace bin links exist and neither bundle layout does.
|
|
35
|
+
* Tiers 1–2 spawn `node <abs js>` directly, which never depends on PATH or
|
|
36
|
+
* on Windows .cmd shims.
|
|
26
37
|
*/
|
|
27
|
-
export declare function getRuntimeAdapter(runtimeType: string): RuntimeAdapter;
|
|
38
|
+
export declare function getRuntimeAdapter(runtimeType: string, opts?: RuntimeAdapterResolveOptions): RuntimeAdapter;
|
|
28
39
|
export declare function assertAgentKey(apiKey: string): void;
|
|
29
40
|
//# sourceMappingURL=runtimes.d.ts.map
|
package/dist/runtimes.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"runtimes.d.ts","sourceRoot":"","sources":["../src/runtimes.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"runtimes.d.ts","sourceRoot":"","sources":["../src/runtimes.ts"],"names":[],"mappings":"AAIA,OAAO,EAAE,qBAAqB,EAAa,MAAM,oBAAoB,CAAC;AACtE,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,oBAAoB,CAAC;AAGzD,YAAY,EAAE,cAAc,EAAE,CAAC;AAC/B,OAAO,EAAE,qBAAqB,EAAE,CAAC;AAEjC,MAAM,WAAW,cAAc;IAC7B,GAAG,EAAE,MAAM,CAAC;IACZ,IAAI,EAAE,MAAM,EAAE,CAAC;IACf,QAAQ,CACN,OAAO,EAAE,MAAM,CAAC,UAAU,EAC1B,OAAO,EAAE,MAAM,EACf,KAAK,EAAE,MAAM,EACb,MAAM,EAAE,MAAM,EACd,IAAI,EAAE,SAAS,EACf,EAAE,CAAC,EAAE,cAAc,GAClB,MAAM,CAAC,UAAU,CAAC;CACtB;AAED,MAAM,WAAW,SAAS;IACxB,QAAQ,EAAE,MAAM,CAAC;IACjB,YAAY,EAAE,MAAM,CAAC;IACrB,UAAU,EAAE,MAAM,CAAC;IACnB;;;;;OAKG;IACH,OAAO,CAAC,EAAE,MAAM,CAAC;CAClB;AAqGD,sEAAsE;AACtE,MAAM,WAAW,4BAA4B;IAC3C,GAAG,CAAC,EAAE,MAAM,CAAC,UAAU,CAAC;IACxB,SAAS,CAAC,EAAE,MAAM,CAAC;CACpB;AA2CD;;;;;;;;;;GAUG;AACH,wBAAgB,iBAAiB,CAC/B,WAAW,EAAE,MAAM,EACnB,IAAI,CAAC,EAAE,4BAA4B,GAClC,cAAc,CAoBhB;AAED,wBAAgB,cAAc,CAAC,MAAM,EAAE,MAAM,GAAG,IAAI,CAInD"}
|
package/dist/runtimes.js
CHANGED
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import * as fs from 'node:fs';
|
|
2
2
|
import * as os from 'node:os';
|
|
3
3
|
import * as path from 'node:path';
|
|
4
|
+
import { fileURLToPath } from 'node:url';
|
|
4
5
|
import { clearAllProviderCreds, llmSource } from '@parall/agent-core';
|
|
5
6
|
import { resolveBundleDir } from './config.js';
|
|
6
7
|
export { clearAllProviderCreds };
|
|
@@ -93,17 +94,67 @@ const OVERLAY_BIN_NAMES = {
|
|
|
93
94
|
openclaw: 'parall-openclaw-agent.js',
|
|
94
95
|
};
|
|
95
96
|
/**
|
|
96
|
-
*
|
|
97
|
-
*
|
|
98
|
-
*
|
|
97
|
+
* Locate a bridge bundle shipped next to the daemon's own entry script.
|
|
98
|
+
* The npm package puts every bin in the same flat `bundle/` directory
|
|
99
|
+
* (parall-daemon.js beside parall-codex-agent.js), so the running entry's
|
|
100
|
+
* real directory is a complete bridge distribution. This is what makes bare
|
|
101
|
+
* `npx @parall/daemon` work on Windows, where the PATH fallback would hit an
|
|
102
|
+
* npm `.cmd` shim that Node refuses to spawn without a shell.
|
|
103
|
+
*
|
|
104
|
+
* The entry path must be realpath'd first: POSIX npm bins are symlinks into
|
|
105
|
+
* the package, and Windows setups may reach the bundle through a junction —
|
|
106
|
+
* dirname of the raw link points at a bin dir with no siblings (same class
|
|
107
|
+
* of bug as the browser-pod entrypoint guard, #1597). import.meta.url is the
|
|
108
|
+
* second candidate because a service launcher can import the daemon with
|
|
109
|
+
* argv[1] pointing outside the bundle.
|
|
99
110
|
*/
|
|
100
|
-
|
|
111
|
+
function bundledSiblingBin(overlayName, entryPath) {
|
|
112
|
+
const candidateDirs = [];
|
|
113
|
+
const entry = entryPath ?? process.argv[1];
|
|
114
|
+
if (entry) {
|
|
115
|
+
try {
|
|
116
|
+
candidateDirs.push(path.dirname(fs.realpathSync(entry)));
|
|
117
|
+
}
|
|
118
|
+
catch {
|
|
119
|
+
candidateDirs.push(path.dirname(path.resolve(entry)));
|
|
120
|
+
}
|
|
121
|
+
}
|
|
122
|
+
try {
|
|
123
|
+
candidateDirs.push(path.dirname(fileURLToPath(import.meta.url)));
|
|
124
|
+
}
|
|
125
|
+
catch {
|
|
126
|
+
// non-file module URL; skip
|
|
127
|
+
}
|
|
128
|
+
for (const dir of candidateDirs) {
|
|
129
|
+
const bin = path.join(dir, overlayName);
|
|
130
|
+
try {
|
|
131
|
+
if (fs.existsSync(bin))
|
|
132
|
+
return bin;
|
|
133
|
+
}
|
|
134
|
+
catch {
|
|
135
|
+
// unreadable dir; try the next candidate
|
|
136
|
+
}
|
|
137
|
+
}
|
|
138
|
+
return null;
|
|
139
|
+
}
|
|
140
|
+
/**
|
|
141
|
+
* Resolve a runtime adapter. Bridge bins resolve in three tiers:
|
|
142
|
+
* 1. overlay bundle (~/.parall-daemon/bundle/current/) — a self-updated
|
|
143
|
+
* daemon must load bridges from the same overlay to keep versions in sync;
|
|
144
|
+
* 2. entry-sibling bundle (bundledSiblingBin above) — the npm/CDN package's
|
|
145
|
+
* own flat bundle directory;
|
|
146
|
+
* 3. bare bin name via PATH — dev checkouts running from dist/, where the
|
|
147
|
+
* workspace bin links exist and neither bundle layout does.
|
|
148
|
+
* Tiers 1–2 spawn `node <abs js>` directly, which never depends on PATH or
|
|
149
|
+
* on Windows .cmd shims.
|
|
150
|
+
*/
|
|
151
|
+
export function getRuntimeAdapter(runtimeType, opts) {
|
|
101
152
|
const base = RUNTIME_ADAPTERS[runtimeType] ?? defaultAdapter;
|
|
102
153
|
const overlayName = OVERLAY_BIN_NAMES[runtimeType];
|
|
103
154
|
if (!overlayName)
|
|
104
155
|
return base;
|
|
105
156
|
try {
|
|
106
|
-
const bundleDir = resolveBundleDir();
|
|
157
|
+
const bundleDir = resolveBundleDir(opts?.env);
|
|
107
158
|
const overlayBin = path.join(bundleDir, 'current', overlayName);
|
|
108
159
|
if (fs.existsSync(overlayBin)) {
|
|
109
160
|
return { ...base, bin: process.execPath, args: [overlayBin] };
|
|
@@ -112,6 +163,10 @@ export function getRuntimeAdapter(runtimeType) {
|
|
|
112
163
|
catch {
|
|
113
164
|
// resolveBundleDir may fail in unusual setups; fall through
|
|
114
165
|
}
|
|
166
|
+
const siblingBin = bundledSiblingBin(overlayName, opts?.entryPath);
|
|
167
|
+
if (siblingBin) {
|
|
168
|
+
return { ...base, bin: process.execPath, args: [siblingBin] };
|
|
169
|
+
}
|
|
115
170
|
return base;
|
|
116
171
|
}
|
|
117
172
|
export function assertAgentKey(apiKey) {
|
package/dist/supervisor.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"supervisor.d.ts","sourceRoot":"","sources":["../src/supervisor.ts"],"names":[],"mappings":"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
|
|
1
|
+
{"version":3,"file":"supervisor.d.ts","sourceRoot":"","sources":["../src/supervisor.ts"],"names":[],"mappings":"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"}
|