@pellux/goodvibes-sdk 0.18.40 → 0.18.41
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/dist/_internal/platform/core/orchestrator.d.ts.map +1 -1
- package/dist/_internal/platform/core/orchestrator.js +10 -0
- package/dist/_internal/platform/tools/exec/runtime.d.ts +13 -0
- package/dist/_internal/platform/tools/exec/runtime.d.ts.map +1 -1
- package/dist/_internal/platform/tools/exec/runtime.js +65 -4
- package/dist/_internal/platform/tools/exec/schema.d.ts +17 -0
- package/dist/_internal/platform/tools/exec/schema.d.ts.map +1 -1
- package/dist/_internal/platform/tools/exec/schema.js +10 -0
- package/dist/_internal/platform/tools/shared/process-manager.d.ts +20 -2
- package/dist/_internal/platform/tools/shared/process-manager.d.ts.map +1 -1
- package/dist/_internal/platform/tools/shared/process-manager.js +59 -10
- package/dist/_internal/platform/version.js +1 -1
- package/package.json +1 -1
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"orchestrator.d.ts","sourceRoot":"","sources":["../../../../src/_internal/platform/core/orchestrator.ts"],"names":[],"mappings":"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
|
|
1
|
+
{"version":3,"file":"orchestrator.d.ts","sourceRoot":"","sources":["../../../../src/_internal/platform/core/orchestrator.ts"],"names":[],"mappings":"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"}
|
|
@@ -243,6 +243,16 @@ export class Orchestrator {
|
|
|
243
243
|
clearTimeout(this.autoSpawnTimeout);
|
|
244
244
|
this.autoSpawnTimeout = null;
|
|
245
245
|
}
|
|
246
|
+
// Clear the thinking-animation interval immediately on abort so the Node
|
|
247
|
+
// event loop is not kept alive by a leaked timer. stopThinking() also
|
|
248
|
+
// clears this in the finally block, but abort() can be called from
|
|
249
|
+
// outside the turn loop (e.g. user keypress during startup) where
|
|
250
|
+
// stopThinking() may never be reached.
|
|
251
|
+
if (this.animInterval !== null) {
|
|
252
|
+
clearInterval(this.animInterval);
|
|
253
|
+
this.animInterval = null;
|
|
254
|
+
}
|
|
255
|
+
this.isThinking = false;
|
|
246
256
|
}
|
|
247
257
|
/**
|
|
248
258
|
* Dispose long-lived runtime attachments owned by this orchestrator.
|
|
@@ -1,7 +1,20 @@
|
|
|
1
1
|
import type { Tool } from '../../types/tools.js';
|
|
2
2
|
import { OverflowHandler } from '../shared/overflow.js';
|
|
3
|
+
import type { ExecCommandResult } from './schema.js';
|
|
3
4
|
import { ProcessManager } from '../shared/process-manager.js';
|
|
4
5
|
import type { FeatureFlagManager } from '../../runtime/feature-flags/index.js';
|
|
6
|
+
/**
|
|
7
|
+
* Classify whether a failed exec result is retryable.
|
|
8
|
+
*
|
|
9
|
+
* Retryable: network errors (ECONNRESET, ENOTFOUND, ETIMEDOUT), lock/busy
|
|
10
|
+
* (EBUSY, ENOMEM, ECONNREFUSED), HTTP-gateway-style exit codes (124=timeout,
|
|
11
|
+
* 28=curl timeout). Terminal: permission denied (EACCES), missing binary
|
|
12
|
+
* (ENOENT), syntax errors.
|
|
13
|
+
*
|
|
14
|
+
* @param result - The failed command result.
|
|
15
|
+
* @param allowed - Optional allowlist of error category strings.
|
|
16
|
+
*/
|
|
17
|
+
export declare function isRetryableExecResult(result: ExecCommandResult, allowed?: ReadonlyArray<'network' | 'lock' | 'busy' | 'oom'>): boolean;
|
|
5
18
|
export declare function createExecTool(processManager: ProcessManager, options?: {
|
|
6
19
|
readonly featureFlags?: Pick<FeatureFlagManager, 'isEnabled'> | null;
|
|
7
20
|
readonly overflowHandler?: OverflowHandler;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"runtime.d.ts","sourceRoot":"","sources":["../../../../../src/_internal/platform/tools/exec/runtime.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,IAAI,EAAE,MAAM,sBAAsB,CAAC;AAGjD,OAAO,EAAqB,eAAe,EAAE,MAAM,uBAAuB,CAAC;
|
|
1
|
+
{"version":3,"file":"runtime.d.ts","sourceRoot":"","sources":["../../../../../src/_internal/platform/tools/exec/runtime.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,IAAI,EAAE,MAAM,sBAAsB,CAAC;AAGjD,OAAO,EAAqB,eAAe,EAAE,MAAM,uBAAuB,CAAC;AAC3E,OAAO,KAAK,EAA+B,iBAAiB,EAAiB,MAAM,aAAa,CAAC;AACjG,OAAO,EAAE,cAAc,EAAE,MAAM,8BAA8B,CAAC;AAG9D,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,sCAAsC,CAAC;AAwZ/E;;;;;;;;;;GAUG;AACH,wBAAgB,qBAAqB,CACnC,MAAM,EAAE,iBAAiB,EACzB,OAAO,CAAC,EAAE,aAAa,CAAC,SAAS,GAAG,MAAM,GAAG,MAAM,GAAG,KAAK,CAAC,GAC3D,OAAO,CA2CT;AA2ID,wBAAgB,cAAc,CAC5B,cAAc,EAAE,cAAc,EAC9B,OAAO,GAAE;IACP,QAAQ,CAAC,YAAY,CAAC,EAAE,IAAI,CAAC,kBAAkB,EAAE,WAAW,CAAC,GAAG,IAAI,CAAC;IACrE,QAAQ,CAAC,eAAe,CAAC,EAAE,eAAe,CAAC;CACvC,GACL,IAAI,CAqEN"}
|
|
@@ -52,10 +52,12 @@ function resolveCwd(cwd, workingDirectory) {
|
|
|
52
52
|
function sleep(ms) {
|
|
53
53
|
return new Promise((r) => setTimeout(r, ms));
|
|
54
54
|
}
|
|
55
|
-
function computeRetryDelay(attempt, delayMs, backoff) {
|
|
55
|
+
function computeRetryDelay(attempt, delayMs, backoff, maxDelayMs = 30_000) {
|
|
56
56
|
if (backoff === 'fixed')
|
|
57
57
|
return delayMs;
|
|
58
|
-
|
|
58
|
+
// Full jitter: random in [0, min(base * 2^attempt, maxDelay)] — avoids thundering herd
|
|
59
|
+
const cap = Math.min(delayMs * Math.pow(2, attempt), maxDelayMs);
|
|
60
|
+
return Math.random() * cap;
|
|
59
61
|
}
|
|
60
62
|
function buildCleanEnv() {
|
|
61
63
|
return Object.fromEntries(Object.entries(process.env).filter(([, v]) => v !== undefined));
|
|
@@ -110,7 +112,7 @@ function initProgressFile(cmdStr, workingDirectory) {
|
|
|
110
112
|
}
|
|
111
113
|
import { copyFileSync, renameSync, unlinkSync, rmSync, cpSync, writeFileSync, mkdirSync, appendFileSync } from 'node:fs';
|
|
112
114
|
import { summarizeError } from '../../utils/error-display.js';
|
|
113
|
-
function spawnBackground(processManager, cmd, cwd, env) {
|
|
115
|
+
async function spawnBackground(processManager, cmd, cwd, env) {
|
|
114
116
|
return processManager.spawn(cmd, cwd, env);
|
|
115
117
|
}
|
|
116
118
|
function handleBgSpecialCommand(processManager, cmd) {
|
|
@@ -356,13 +358,66 @@ async function runUntil(_processManager, overflowHandler, cmdStr, cmdInput, cwd,
|
|
|
356
358
|
...(stderrResult.truncated && { stderr_truncated: true }),
|
|
357
359
|
};
|
|
358
360
|
}
|
|
361
|
+
/**
|
|
362
|
+
* Classify whether a failed exec result is retryable.
|
|
363
|
+
*
|
|
364
|
+
* Retryable: network errors (ECONNRESET, ENOTFOUND, ETIMEDOUT), lock/busy
|
|
365
|
+
* (EBUSY, ENOMEM, ECONNREFUSED), HTTP-gateway-style exit codes (124=timeout,
|
|
366
|
+
* 28=curl timeout). Terminal: permission denied (EACCES), missing binary
|
|
367
|
+
* (ENOENT), syntax errors.
|
|
368
|
+
*
|
|
369
|
+
* @param result - The failed command result.
|
|
370
|
+
* @param allowed - Optional allowlist of error category strings.
|
|
371
|
+
*/
|
|
372
|
+
export function isRetryableExecResult(result, allowed) {
|
|
373
|
+
// Timed-out commands are never auto-retried — callers must decide
|
|
374
|
+
if (result.timed_out)
|
|
375
|
+
return false;
|
|
376
|
+
const combined = `${result.stdout}\n${result.stderr}`;
|
|
377
|
+
// Terminal errors — always skip retry
|
|
378
|
+
const TERMINAL_PATTERNS = [
|
|
379
|
+
/ENOENT/, // missing binary / file
|
|
380
|
+
/EACCES/, // permission denied
|
|
381
|
+
/Permission denied/, // shell-level perm error
|
|
382
|
+
/command not found/, // bash: command not found
|
|
383
|
+
/syntax error/i, // shell syntax
|
|
384
|
+
/No such file or directory/,
|
|
385
|
+
];
|
|
386
|
+
for (const pat of TERMINAL_PATTERNS) {
|
|
387
|
+
if (pat.test(combined))
|
|
388
|
+
return false;
|
|
389
|
+
}
|
|
390
|
+
// Map error categories to patterns
|
|
391
|
+
const CATEGORY_PATTERNS = {
|
|
392
|
+
network: [/ECONNRESET/, /ENOTFOUND/, /ETIMEDOUT/, /EHOSTUNREACH/, /ENETUNREACH/],
|
|
393
|
+
lock: [/ECONNREFUSED/, /EAGAIN/],
|
|
394
|
+
busy: [/EBUSY/, /Resource temporarily unavailable/],
|
|
395
|
+
oom: [/ENOMEM/, /Cannot allocate memory/, /Out of memory/],
|
|
396
|
+
};
|
|
397
|
+
const effectiveAllowed = allowed ?? ['network', 'lock', 'busy'];
|
|
398
|
+
for (const category of effectiveAllowed) {
|
|
399
|
+
const patterns = CATEGORY_PATTERNS[category] ?? [];
|
|
400
|
+
for (const pat of patterns) {
|
|
401
|
+
if (pat.test(combined))
|
|
402
|
+
return true;
|
|
403
|
+
}
|
|
404
|
+
}
|
|
405
|
+
// Exit code 124 = timeout via `timeout` command; 75 = tempfail (sysexits.h)
|
|
406
|
+
const retryableExitCodes = [124, 75];
|
|
407
|
+
if (result.exit_code !== null && retryableExitCodes.includes(result.exit_code)) {
|
|
408
|
+
return effectiveAllowed.includes('network') || effectiveAllowed.includes('busy');
|
|
409
|
+
}
|
|
410
|
+
return false;
|
|
411
|
+
}
|
|
359
412
|
async function runWithRetry(processManager, overflowHandler, featureFlags, cmdStr, cmdInput, workingDirectory, globalTimeout) {
|
|
360
413
|
if (!cmdInput.retry) {
|
|
361
414
|
return runCommand(processManager, overflowHandler, featureFlags, cmdStr, cmdInput, workingDirectory, globalTimeout);
|
|
362
415
|
}
|
|
363
416
|
const maxRetries = Math.min(cmdInput.retry.max ?? 3, 10);
|
|
364
417
|
const delayMs = cmdInput.retry.delay_ms ?? 1000;
|
|
418
|
+
const maxDelayMs = cmdInput.retry.max_delay_ms ?? 30_000;
|
|
365
419
|
const backoff = cmdInput.retry.backoff ?? 'exponential';
|
|
420
|
+
const retryOn = cmdInput.retry.on;
|
|
366
421
|
let lastResult;
|
|
367
422
|
for (let attempt = 0; attempt <= maxRetries; attempt++) {
|
|
368
423
|
lastResult = await runCommand(processManager, overflowHandler, featureFlags, cmdStr, cmdInput, workingDirectory, globalTimeout);
|
|
@@ -370,7 +425,13 @@ async function runWithRetry(processManager, overflowHandler, featureFlags, cmdSt
|
|
|
370
425
|
return { ...lastResult, retries: attempt };
|
|
371
426
|
}
|
|
372
427
|
if (attempt < maxRetries) {
|
|
373
|
-
|
|
428
|
+
// Classify error: if we can determine it's terminal, stop immediately
|
|
429
|
+
if (!isRetryableExecResult(lastResult, retryOn)) {
|
|
430
|
+
logger.debug('exec: terminal error — not retrying', { cmd: cmdStr, attempt, stderr: lastResult.stderr.slice(0, 200) });
|
|
431
|
+
return { ...lastResult, retries: attempt };
|
|
432
|
+
}
|
|
433
|
+
const delay = computeRetryDelay(attempt, delayMs, backoff, maxDelayMs);
|
|
434
|
+
logger.debug('exec: retrying after jittered delay', { cmd: cmdStr, attempt, delay: Math.round(delay) });
|
|
374
435
|
await sleep(delay);
|
|
375
436
|
}
|
|
376
437
|
}
|
|
@@ -74,11 +74,24 @@ export declare const EXEC_TOOL_SCHEMA: {
|
|
|
74
74
|
readonly minimum: 0;
|
|
75
75
|
readonly description: "Base delay between retries in ms. Default: 1000.";
|
|
76
76
|
};
|
|
77
|
+
readonly max_delay_ms: {
|
|
78
|
+
readonly type: "integer";
|
|
79
|
+
readonly minimum: 0;
|
|
80
|
+
readonly description: "Max jitter cap for exponential backoff in ms. Default: 30000.";
|
|
81
|
+
};
|
|
77
82
|
readonly backoff: {
|
|
78
83
|
readonly type: "string";
|
|
79
84
|
readonly enum: readonly ["fixed", "exponential"];
|
|
80
85
|
readonly description: "Backoff strategy. Default: exponential.";
|
|
81
86
|
};
|
|
87
|
+
readonly on: {
|
|
88
|
+
readonly type: "array";
|
|
89
|
+
readonly items: {
|
|
90
|
+
readonly type: "string";
|
|
91
|
+
readonly enum: readonly ["network", "lock", "busy", "oom"];
|
|
92
|
+
};
|
|
93
|
+
readonly description: "Error categories to retry on. Default: [\"network\", \"lock\", \"busy\"].";
|
|
94
|
+
};
|
|
82
95
|
};
|
|
83
96
|
};
|
|
84
97
|
readonly until: {
|
|
@@ -189,7 +202,11 @@ export interface ExecExpect {
|
|
|
189
202
|
export interface ExecRetry {
|
|
190
203
|
max?: number;
|
|
191
204
|
delay_ms?: number;
|
|
205
|
+
/** Max jitter cap for exponential backoff. Default: 30000. */
|
|
206
|
+
max_delay_ms?: number;
|
|
192
207
|
backoff?: 'fixed' | 'exponential';
|
|
208
|
+
/** Error categories to retry on. Default: ['network', 'lock', 'busy']. */
|
|
209
|
+
on?: ReadonlyArray<'network' | 'lock' | 'busy' | 'oom'>;
|
|
193
210
|
}
|
|
194
211
|
export interface ExecUntil {
|
|
195
212
|
pattern: string;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"schema.d.ts","sourceRoot":"","sources":["../../../../../src/_internal/platform/tools/exec/schema.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AACH,eAAO,MAAM,gBAAgB
|
|
1
|
+
{"version":3,"file":"schema.d.ts","sourceRoot":"","sources":["../../../../../src/_internal/platform/tools/exec/schema.ts"],"names":[],"mappings":"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"}
|
|
@@ -73,11 +73,21 @@ export const EXEC_TOOL_SCHEMA = {
|
|
|
73
73
|
minimum: 0,
|
|
74
74
|
description: 'Base delay between retries in ms. Default: 1000.',
|
|
75
75
|
},
|
|
76
|
+
max_delay_ms: {
|
|
77
|
+
type: 'integer',
|
|
78
|
+
minimum: 0,
|
|
79
|
+
description: 'Max jitter cap for exponential backoff in ms. Default: 30000.',
|
|
80
|
+
},
|
|
76
81
|
backoff: {
|
|
77
82
|
type: 'string',
|
|
78
83
|
enum: ['fixed', 'exponential'],
|
|
79
84
|
description: 'Backoff strategy. Default: exponential.',
|
|
80
85
|
},
|
|
86
|
+
on: {
|
|
87
|
+
type: 'array',
|
|
88
|
+
items: { type: 'string', enum: ['network', 'lock', 'busy', 'oom'] },
|
|
89
|
+
description: 'Error categories to retry on. Default: ["network", "lock", "busy"].',
|
|
90
|
+
},
|
|
81
91
|
},
|
|
82
92
|
},
|
|
83
93
|
until: {
|
|
@@ -14,6 +14,17 @@ export interface BackgroundProcess {
|
|
|
14
14
|
stderr: string[];
|
|
15
15
|
exitCode: number | null;
|
|
16
16
|
done: boolean;
|
|
17
|
+
/**
|
|
18
|
+
* Timestamp (ms since epoch) when SIGKILL was scheduled after a timeout.
|
|
19
|
+
* Null if the process completed normally or SIGKILL was never scheduled.
|
|
20
|
+
*/
|
|
21
|
+
killDeadline: number | null;
|
|
22
|
+
}
|
|
23
|
+
export interface SpawnOptions {
|
|
24
|
+
/** Abort the process if it hasn't completed within this many ms. Default: 60000. */
|
|
25
|
+
timeout_ms?: number;
|
|
26
|
+
/** Grace period (ms) between SIGTERM and SIGKILL after timeout. Default: 5000. */
|
|
27
|
+
sigterm_grace_ms?: number;
|
|
17
28
|
}
|
|
18
29
|
export interface BgCommandResult {
|
|
19
30
|
cmd: string;
|
|
@@ -31,9 +42,16 @@ export declare class ProcessManager {
|
|
|
31
42
|
private newId;
|
|
32
43
|
/**
|
|
33
44
|
* Spawn a background process and start collecting its output.
|
|
34
|
-
*
|
|
45
|
+
*
|
|
46
|
+
* @param cmd Shell command to run via /bin/sh -c.
|
|
47
|
+
* @param cwd Working directory (undefined = inherit).
|
|
48
|
+
* @param env Extra env vars merged with the current process env.
|
|
49
|
+
* @param opts Timeout and SIGKILL grace configuration.
|
|
50
|
+
*
|
|
51
|
+
* @returns A BgCommandResult with the process_id and pid, or rejects if
|
|
52
|
+
* the binary is missing (ENOENT) or exec permission is denied (EACCES).
|
|
35
53
|
*/
|
|
36
|
-
spawn(cmd: string, cwd: string | undefined, env: Record<string, string> | undefined): BgCommandResult
|
|
54
|
+
spawn(cmd: string, cwd: string | undefined, env: Record<string, string> | undefined, opts?: SpawnOptions): Promise<BgCommandResult>;
|
|
37
55
|
/** Get the status record for a background process, or undefined if not found. */
|
|
38
56
|
getStatus(id: string): BackgroundProcess | undefined;
|
|
39
57
|
/** Get the accumulated stdout/stderr for a background process. */
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"process-manager.d.ts","sourceRoot":"","sources":["../../../../../src/_internal/platform/tools/shared/process-manager.ts"],"names":[],"mappings":"AAAA,qFAAqF;AAErF;;;;;GAKG;AAIH,MAAM,WAAW,iBAAiB;IAChC,EAAE,EAAE,MAAM,CAAC;IACX,GAAG,EAAE,MAAM,CAAC;IACZ,GAAG,EAAE,MAAM,CAAC;IACZ,SAAS,EAAE,MAAM,CAAC;IAClB,MAAM,EAAE,MAAM,EAAE,CAAC;IACjB,MAAM,EAAE,MAAM,EAAE,CAAC;IACjB,QAAQ,EAAE,MAAM,GAAG,IAAI,CAAC;IACxB,IAAI,EAAE,OAAO,CAAC;
|
|
1
|
+
{"version":3,"file":"process-manager.d.ts","sourceRoot":"","sources":["../../../../../src/_internal/platform/tools/shared/process-manager.ts"],"names":[],"mappings":"AAAA,qFAAqF;AAErF;;;;;GAKG;AAIH,MAAM,WAAW,iBAAiB;IAChC,EAAE,EAAE,MAAM,CAAC;IACX,GAAG,EAAE,MAAM,CAAC;IACZ,GAAG,EAAE,MAAM,CAAC;IACZ,SAAS,EAAE,MAAM,CAAC;IAClB,MAAM,EAAE,MAAM,EAAE,CAAC;IACjB,MAAM,EAAE,MAAM,EAAE,CAAC;IACjB,QAAQ,EAAE,MAAM,GAAG,IAAI,CAAC;IACxB,IAAI,EAAE,OAAO,CAAC;IACd;;;OAGG;IACH,YAAY,EAAE,MAAM,GAAG,IAAI,CAAC;CAC7B;AAID,MAAM,WAAW,YAAY;IAC3B,oFAAoF;IACpF,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,kFAAkF;IAClF,gBAAgB,CAAC,EAAE,MAAM,CAAC;CAC3B;AAID,MAAM,WAAW,eAAe;IAC9B,GAAG,EAAE,MAAM,CAAC;IACZ,SAAS,EAAE,MAAM,GAAG,IAAI,CAAC;IACzB,MAAM,EAAE,MAAM,CAAC;IACf,MAAM,EAAE,MAAM,CAAC;IACf,OAAO,EAAE,OAAO,CAAC;IACjB,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,GAAG,CAAC,EAAE,MAAM,CAAC;CACd;AAID,qBAAa,cAAc;IACzB,OAAO,CAAC,QAAQ,CAAK;IACrB,OAAO,CAAC,UAAU,CAAwC;IAC1D,OAAO,CAAC,MAAM,CAAmD;IAIjE,OAAO,CAAC,KAAK;IAMb;;;;;;;;;;OAUG;IACG,KAAK,CACT,GAAG,EAAE,MAAM,EACX,GAAG,EAAE,MAAM,GAAG,SAAS,EACvB,GAAG,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,GAAG,SAAS,EACvC,IAAI,CAAC,EAAE,YAAY,GAClB,OAAO,CAAC,eAAe,CAAC;IA2F3B,iFAAiF;IACjF,SAAS,CAAC,EAAE,EAAE,MAAM,GAAG,iBAAiB,GAAG,SAAS;IAIpD,kEAAkE;IAClE,SAAS,CAAC,EAAE,EAAE,MAAM,GAAG;QAAE,MAAM,EAAE,MAAM,CAAC;QAAC,MAAM,EAAE,MAAM,CAAA;KAAE,GAAG,SAAS;IASrE;;;OAGG;IACH,IAAI,CAAC,EAAE,EAAE,MAAM,GAAG,OAAO;IAczB,yEAAyE;IACzE,IAAI,IAAI,KAAK,CAAC;QAAE,EAAE,EAAE,MAAM,CAAC;QAAC,GAAG,EAAE,MAAM,CAAC;QAAC,GAAG,EAAE,MAAM,CAAC;QAAC,MAAM,EAAE,MAAM,CAAA;KAAE,CAAC;IASvE;;;OAGG;IACH,aAAa,CAAC,GAAG,EAAE,MAAM,GAAG,eAAe,GAAG,IAAI;CAmDnD"}
|
|
@@ -11,9 +11,18 @@ export class ProcessManager {
|
|
|
11
11
|
// ─── Public API ─────────────────────────────────────────────────────────────
|
|
12
12
|
/**
|
|
13
13
|
* Spawn a background process and start collecting its output.
|
|
14
|
-
*
|
|
14
|
+
*
|
|
15
|
+
* @param cmd Shell command to run via /bin/sh -c.
|
|
16
|
+
* @param cwd Working directory (undefined = inherit).
|
|
17
|
+
* @param env Extra env vars merged with the current process env.
|
|
18
|
+
* @param opts Timeout and SIGKILL grace configuration.
|
|
19
|
+
*
|
|
20
|
+
* @returns A BgCommandResult with the process_id and pid, or rejects if
|
|
21
|
+
* the binary is missing (ENOENT) or exec permission is denied (EACCES).
|
|
15
22
|
*/
|
|
16
|
-
spawn(cmd, cwd, env) {
|
|
23
|
+
async spawn(cmd, cwd, env, opts) {
|
|
24
|
+
const timeoutMs = opts?.timeout_ms ?? 60_000;
|
|
25
|
+
const sigtermGraceMs = opts?.sigterm_grace_ms ?? 5_000;
|
|
17
26
|
const id = this.newId();
|
|
18
27
|
const entry = {
|
|
19
28
|
id,
|
|
@@ -24,20 +33,31 @@ export class ProcessManager {
|
|
|
24
33
|
stderr: [],
|
|
25
34
|
exitCode: null,
|
|
26
35
|
done: false,
|
|
36
|
+
killDeadline: null,
|
|
27
37
|
};
|
|
28
38
|
this._processes.set(id, entry);
|
|
29
39
|
const cleanEnv = Object.fromEntries(Object.entries(process.env).filter(([, v]) => v !== undefined));
|
|
30
40
|
const mergedEnv = { ...cleanEnv, ...env };
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
41
|
+
let proc;
|
|
42
|
+
try {
|
|
43
|
+
proc = Bun.spawn(['/bin/sh', '-c', cmd], {
|
|
44
|
+
cwd,
|
|
45
|
+
env: mergedEnv,
|
|
46
|
+
stdout: 'pipe',
|
|
47
|
+
stderr: 'pipe',
|
|
48
|
+
});
|
|
49
|
+
}
|
|
50
|
+
catch (spawnErr) {
|
|
51
|
+
// Surface ENOENT / EACCES immediately — callers should not retry these
|
|
52
|
+
this._processes.delete(id);
|
|
53
|
+
throw spawnErr;
|
|
54
|
+
}
|
|
37
55
|
entry.pid = proc.pid;
|
|
38
56
|
this._procs.set(id, proc);
|
|
39
|
-
// Async collection
|
|
40
|
-
|
|
57
|
+
// Async collection with timeout escalation — SIGTERM then SIGKILL
|
|
58
|
+
// Cast stdout/stderr to ReadableStream — Bun guarantees these are ReadableStream
|
|
59
|
+
// when stdout/stderr is set to 'pipe', but the return type is a union.
|
|
60
|
+
const collectionPromise = (async () => {
|
|
41
61
|
const [stdoutText, stderrText] = await Promise.all([
|
|
42
62
|
new Response(proc.stdout).text(),
|
|
43
63
|
new Response(proc.stderr).text(),
|
|
@@ -48,6 +68,35 @@ export class ProcessManager {
|
|
|
48
68
|
entry.done = true;
|
|
49
69
|
this._procs.delete(id);
|
|
50
70
|
})();
|
|
71
|
+
// Timeout watchdog: SIGTERM → wait grace → SIGKILL
|
|
72
|
+
const timeoutHandle = setTimeout(async () => {
|
|
73
|
+
if (entry.done)
|
|
74
|
+
return;
|
|
75
|
+
try {
|
|
76
|
+
proc.kill('SIGTERM');
|
|
77
|
+
}
|
|
78
|
+
catch { /* already exited */ }
|
|
79
|
+
entry.killDeadline = Date.now() + sigtermGraceMs;
|
|
80
|
+
await new Promise((r) => setTimeout(r, sigtermGraceMs));
|
|
81
|
+
if (!entry.done) {
|
|
82
|
+
try {
|
|
83
|
+
proc.kill('SIGKILL');
|
|
84
|
+
}
|
|
85
|
+
catch { /* already exited */ }
|
|
86
|
+
}
|
|
87
|
+
}, timeoutMs);
|
|
88
|
+
// Reject the spawn promise if the process errors immediately (ENOENT/EACCES
|
|
89
|
+
// on the child process level) — the outer try/catch handles Bun.spawn throws;
|
|
90
|
+
// this handles async failures surfaced via proc.exited rejecting.
|
|
91
|
+
void collectionPromise.catch(() => {
|
|
92
|
+
clearTimeout(timeoutHandle);
|
|
93
|
+
entry.done = true;
|
|
94
|
+
this._procs.delete(id);
|
|
95
|
+
});
|
|
96
|
+
// Clear the timeout watchdog once the process completes naturally
|
|
97
|
+
void collectionPromise.then(() => {
|
|
98
|
+
clearTimeout(timeoutHandle);
|
|
99
|
+
});
|
|
51
100
|
return {
|
|
52
101
|
cmd,
|
|
53
102
|
exit_code: null,
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { readFileSync } from 'node:fs';
|
|
2
2
|
import { join } from 'node:path';
|
|
3
|
-
let version = '0.18.
|
|
3
|
+
let version = '0.18.41';
|
|
4
4
|
try {
|
|
5
5
|
const pkg = JSON.parse(readFileSync(join(import.meta.dir, '..', '..', 'package.json'), 'utf-8'));
|
|
6
6
|
version = pkg.version ?? version;
|