@coralai/sps-cli 0.15.12 → 0.16.1
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.md +65 -0
- package/dist/commands/monitorTick.d.ts.map +1 -1
- package/dist/commands/monitorTick.js +3 -1
- package/dist/commands/monitorTick.js.map +1 -1
- package/dist/commands/pipelineTick.d.ts.map +1 -1
- package/dist/commands/pipelineTick.js +16 -3
- package/dist/commands/pipelineTick.js.map +1 -1
- package/dist/commands/tick.d.ts +1 -0
- package/dist/commands/tick.d.ts.map +1 -1
- package/dist/commands/tick.js +73 -8
- package/dist/commands/tick.js.map +1 -1
- package/dist/commands/workerLaunch.d.ts.map +1 -1
- package/dist/commands/workerLaunch.js +16 -3
- package/dist/commands/workerLaunch.js.map +1 -1
- package/dist/engines/ExecutionEngine.d.ts +29 -32
- package/dist/engines/ExecutionEngine.d.ts.map +1 -1
- package/dist/engines/ExecutionEngine.js +247 -527
- package/dist/engines/ExecutionEngine.js.map +1 -1
- package/dist/engines/MonitorEngine.d.ts +14 -27
- package/dist/engines/MonitorEngine.d.ts.map +1 -1
- package/dist/engines/MonitorEngine.js +91 -313
- package/dist/engines/MonitorEngine.js.map +1 -1
- package/dist/main.js +0 -0
- package/dist/manager/completion-judge.d.ts +27 -0
- package/dist/manager/completion-judge.d.ts.map +1 -0
- package/dist/manager/completion-judge.js +94 -0
- package/dist/manager/completion-judge.js.map +1 -0
- package/dist/manager/pm-client.d.ts +10 -0
- package/dist/manager/pm-client.d.ts.map +1 -0
- package/dist/manager/pm-client.js +253 -0
- package/dist/manager/pm-client.js.map +1 -0
- package/dist/manager/post-actions.d.ts +60 -0
- package/dist/manager/post-actions.d.ts.map +1 -0
- package/dist/manager/post-actions.js +338 -0
- package/dist/manager/post-actions.js.map +1 -0
- package/dist/manager/recovery.d.ts +39 -0
- package/dist/manager/recovery.d.ts.map +1 -0
- package/dist/manager/recovery.js +135 -0
- package/dist/manager/recovery.js.map +1 -0
- package/dist/manager/resource-limiter.d.ts +44 -0
- package/dist/manager/resource-limiter.d.ts.map +1 -0
- package/dist/manager/resource-limiter.js +79 -0
- package/dist/manager/resource-limiter.js.map +1 -0
- package/dist/manager/supervisor.d.ts +88 -0
- package/dist/manager/supervisor.d.ts.map +1 -0
- package/dist/manager/supervisor.js +267 -0
- package/dist/manager/supervisor.js.map +1 -0
- package/package.json +1 -1
|
@@ -0,0 +1,79 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* ResourceLimiter — global worker resource control.
|
|
3
|
+
*
|
|
4
|
+
* Shared across all project runners in the tick process.
|
|
5
|
+
* Controls total worker count, launch stagger, and memory usage.
|
|
6
|
+
*/
|
|
7
|
+
import { freemem, totalmem } from 'node:os';
|
|
8
|
+
const DEFAULT_CONFIG = {
|
|
9
|
+
maxGlobalWorkers: 30,
|
|
10
|
+
staggerDelayMs: 5_000,
|
|
11
|
+
maxMemoryPercent: 80,
|
|
12
|
+
};
|
|
13
|
+
export class ResourceLimiter {
|
|
14
|
+
config;
|
|
15
|
+
activeCount = 0;
|
|
16
|
+
lastLaunchAt = 0;
|
|
17
|
+
constructor(config) {
|
|
18
|
+
this.config = { ...DEFAULT_CONFIG, ...config };
|
|
19
|
+
}
|
|
20
|
+
/**
|
|
21
|
+
* Try to acquire a worker slot.
|
|
22
|
+
* Returns true if launch is allowed, false if at capacity.
|
|
23
|
+
*/
|
|
24
|
+
tryAcquire() {
|
|
25
|
+
if (this.activeCount >= this.config.maxGlobalWorkers) {
|
|
26
|
+
return false;
|
|
27
|
+
}
|
|
28
|
+
if (this.memoryPercent() > this.config.maxMemoryPercent) {
|
|
29
|
+
return false;
|
|
30
|
+
}
|
|
31
|
+
this.activeCount++;
|
|
32
|
+
return true;
|
|
33
|
+
}
|
|
34
|
+
/**
|
|
35
|
+
* Release a worker slot (call when worker exits).
|
|
36
|
+
*/
|
|
37
|
+
release() {
|
|
38
|
+
if (this.activeCount > 0) {
|
|
39
|
+
this.activeCount--;
|
|
40
|
+
}
|
|
41
|
+
}
|
|
42
|
+
/**
|
|
43
|
+
* Enforce stagger delay between launches.
|
|
44
|
+
* Returns a promise that resolves when the delay has passed.
|
|
45
|
+
*/
|
|
46
|
+
async enforceStagger() {
|
|
47
|
+
const now = Date.now();
|
|
48
|
+
const elapsed = now - this.lastLaunchAt;
|
|
49
|
+
if (elapsed < this.config.staggerDelayMs) {
|
|
50
|
+
const wait = this.config.staggerDelayMs - elapsed;
|
|
51
|
+
await new Promise(r => setTimeout(r, wait));
|
|
52
|
+
}
|
|
53
|
+
this.lastLaunchAt = Date.now();
|
|
54
|
+
}
|
|
55
|
+
/**
|
|
56
|
+
* Get current resource stats.
|
|
57
|
+
*/
|
|
58
|
+
getStats() {
|
|
59
|
+
const mem = this.memoryPercent();
|
|
60
|
+
return {
|
|
61
|
+
active: this.activeCount,
|
|
62
|
+
max: this.config.maxGlobalWorkers,
|
|
63
|
+
memoryPercent: Math.round(mem),
|
|
64
|
+
canLaunch: this.activeCount < this.config.maxGlobalWorkers && mem <= this.config.maxMemoryPercent,
|
|
65
|
+
};
|
|
66
|
+
}
|
|
67
|
+
/**
|
|
68
|
+
* Override active count (used during Recovery to sync with actual state).
|
|
69
|
+
*/
|
|
70
|
+
setActiveCount(count) {
|
|
71
|
+
this.activeCount = count;
|
|
72
|
+
}
|
|
73
|
+
memoryPercent() {
|
|
74
|
+
const total = totalmem();
|
|
75
|
+
const free = freemem();
|
|
76
|
+
return ((total - free) / total) * 100;
|
|
77
|
+
}
|
|
78
|
+
}
|
|
79
|
+
//# sourceMappingURL=resource-limiter.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"resource-limiter.js","sourceRoot":"","sources":["../../src/manager/resource-limiter.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AACH,OAAO,EAAE,OAAO,EAAE,QAAQ,EAAE,MAAM,SAAS,CAAC;AAkB5C,MAAM,cAAc,GAAmB;IACrC,gBAAgB,EAAE,EAAE;IACpB,cAAc,EAAE,KAAK;IACrB,gBAAgB,EAAE,EAAE;CACrB,CAAC;AAEF,MAAM,OAAO,eAAe;IACT,MAAM,CAAiB;IAChC,WAAW,GAAG,CAAC,CAAC;IAChB,YAAY,GAAG,CAAC,CAAC;IAEzB,YAAY,MAAgC;QAC1C,IAAI,CAAC,MAAM,GAAG,EAAE,GAAG,cAAc,EAAE,GAAG,MAAM,EAAE,CAAC;IACjD,CAAC;IAED;;;OAGG;IACH,UAAU;QACR,IAAI,IAAI,CAAC,WAAW,IAAI,IAAI,CAAC,MAAM,CAAC,gBAAgB,EAAE,CAAC;YACrD,OAAO,KAAK,CAAC;QACf,CAAC;QACD,IAAI,IAAI,CAAC,aAAa,EAAE,GAAG,IAAI,CAAC,MAAM,CAAC,gBAAgB,EAAE,CAAC;YACxD,OAAO,KAAK,CAAC;QACf,CAAC;QACD,IAAI,CAAC,WAAW,EAAE,CAAC;QACnB,OAAO,IAAI,CAAC;IACd,CAAC;IAED;;OAEG;IACH,OAAO;QACL,IAAI,IAAI,CAAC,WAAW,GAAG,CAAC,EAAE,CAAC;YACzB,IAAI,CAAC,WAAW,EAAE,CAAC;QACrB,CAAC;IACH,CAAC;IAED;;;OAGG;IACH,KAAK,CAAC,cAAc;QAClB,MAAM,GAAG,GAAG,IAAI,CAAC,GAAG,EAAE,CAAC;QACvB,MAAM,OAAO,GAAG,GAAG,GAAG,IAAI,CAAC,YAAY,CAAC;QACxC,IAAI,OAAO,GAAG,IAAI,CAAC,MAAM,CAAC,cAAc,EAAE,CAAC;YACzC,MAAM,IAAI,GAAG,IAAI,CAAC,MAAM,CAAC,cAAc,GAAG,OAAO,CAAC;YAClD,MAAM,IAAI,OAAO,CAAC,CAAC,CAAC,EAAE,CAAC,UAAU,CAAC,CAAC,EAAE,IAAI,CAAC,CAAC,CAAC;QAC9C,CAAC;QACD,IAAI,CAAC,YAAY,GAAG,IAAI,CAAC,GAAG,EAAE,CAAC;IACjC,CAAC;IAED;;OAEG;IACH,QAAQ;QACN,MAAM,GAAG,GAAG,IAAI,CAAC,aAAa,EAAE,CAAC;QACjC,OAAO;YACL,MAAM,EAAE,IAAI,CAAC,WAAW;YACxB,GAAG,EAAE,IAAI,CAAC,MAAM,CAAC,gBAAgB;YACjC,aAAa,EAAE,IAAI,CAAC,KAAK,CAAC,GAAG,CAAC;YAC9B,SAAS,EAAE,IAAI,CAAC,WAAW,GAAG,IAAI,CAAC,MAAM,CAAC,gBAAgB,IAAI,GAAG,IAAI,IAAI,CAAC,MAAM,CAAC,gBAAgB;SAClG,CAAC;IACJ,CAAC;IAED;;OAEG;IACH,cAAc,CAAC,KAAa;QAC1B,IAAI,CAAC,WAAW,GAAG,KAAK,CAAC;IAC3B,CAAC;IAEO,aAAa;QACnB,MAAM,KAAK,GAAG,QAAQ,EAAE,CAAC;QACzB,MAAM,IAAI,GAAG,OAAO,EAAE,CAAC;QACvB,OAAO,CAAC,CAAC,KAAK,GAAG,IAAI,CAAC,GAAG,KAAK,CAAC,GAAG,GAAG,CAAC;IACxC,CAAC;CACF"}
|
|
@@ -0,0 +1,88 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* ProcessSupervisor — manages worker process lifecycle.
|
|
3
|
+
*
|
|
4
|
+
* Replaces ClaudePrintProvider's spawn logic with:
|
|
5
|
+
* - fd redirect (not Node pipe) for reliable output
|
|
6
|
+
* - Held child handles (no unref) for reliable exit detection
|
|
7
|
+
* - Three-layer env merge (system + global creds + project conf)
|
|
8
|
+
* - Exit callbacks that fire immediately in the tick process
|
|
9
|
+
*/
|
|
10
|
+
import { type ChildProcess } from 'node:child_process';
|
|
11
|
+
export interface SpawnOpts {
|
|
12
|
+
/** Unique worker ID: `${project}:${slot}:${seq}` */
|
|
13
|
+
id: string;
|
|
14
|
+
project: string;
|
|
15
|
+
seq: string;
|
|
16
|
+
slot: string;
|
|
17
|
+
worktree: string;
|
|
18
|
+
branch: string;
|
|
19
|
+
prompt: string;
|
|
20
|
+
outputFile: string;
|
|
21
|
+
tool: 'claude' | 'codex';
|
|
22
|
+
resumeSessionId?: string;
|
|
23
|
+
/** Called when child process exits. Return value is tracked as pending PostAction. */
|
|
24
|
+
onExit: (exitCode: number) => Promise<void> | void;
|
|
25
|
+
}
|
|
26
|
+
/** An exit event waiting to be processed */
|
|
27
|
+
export interface ExitEvent {
|
|
28
|
+
id: string;
|
|
29
|
+
exitCode: number;
|
|
30
|
+
handle: WorkerHandle;
|
|
31
|
+
}
|
|
32
|
+
export interface WorkerHandle {
|
|
33
|
+
id: string;
|
|
34
|
+
pid: number;
|
|
35
|
+
child: ChildProcess;
|
|
36
|
+
outputFile: string;
|
|
37
|
+
project: string;
|
|
38
|
+
seq: string;
|
|
39
|
+
slot: string;
|
|
40
|
+
branch: string;
|
|
41
|
+
worktree: string;
|
|
42
|
+
tool: 'claude' | 'codex';
|
|
43
|
+
exitCode: number | null;
|
|
44
|
+
sessionId: string | null;
|
|
45
|
+
startedAt: string;
|
|
46
|
+
exitedAt: string | null;
|
|
47
|
+
}
|
|
48
|
+
export declare class ProcessSupervisor {
|
|
49
|
+
/** Global env: process.env + ~/.jarvis.env (Layer 1+2) */
|
|
50
|
+
private globalEnv;
|
|
51
|
+
/** Active worker handles by ID */
|
|
52
|
+
private readonly workers;
|
|
53
|
+
/** Orphan PID poll timers (for Recovery) */
|
|
54
|
+
private readonly orphanTimers;
|
|
55
|
+
/** Pending PostAction promises (from exit callbacks) */
|
|
56
|
+
private readonly pendingActions;
|
|
57
|
+
constructor();
|
|
58
|
+
spawn(opts: SpawnOpts): WorkerHandle;
|
|
59
|
+
kill(id: string): Promise<void>;
|
|
60
|
+
get(id: string): WorkerHandle | undefined;
|
|
61
|
+
getByProject(project: string): WorkerHandle[];
|
|
62
|
+
getAll(): WorkerHandle[];
|
|
63
|
+
remove(id: string): void;
|
|
64
|
+
get activeCount(): number;
|
|
65
|
+
/**
|
|
66
|
+
* Wait for all pending PostAction promises to settle.
|
|
67
|
+
* Called by tick after each cycle to ensure exit callbacks complete.
|
|
68
|
+
*/
|
|
69
|
+
drainPendingActions(): Promise<void>;
|
|
70
|
+
/**
|
|
71
|
+
* Monitor a PID that we don't have a child handle for (tick restarted).
|
|
72
|
+
* Polls every 5s; when PID dies, calls onDead.
|
|
73
|
+
*/
|
|
74
|
+
monitorOrphanPid(id: string, pid: number, handle: Omit<WorkerHandle, 'child'>, onDead: (exitCode: number) => Promise<void> | void): void;
|
|
75
|
+
/**
|
|
76
|
+
* Infer exit code for an orphan worker by checking output file.
|
|
77
|
+
* If output contains a successful result, assume exit code 0.
|
|
78
|
+
*/
|
|
79
|
+
private inferExitCode;
|
|
80
|
+
private loadGlobalEnv;
|
|
81
|
+
private loadProjectEnv;
|
|
82
|
+
reloadGlobalEnv(): void;
|
|
83
|
+
private buildArgs;
|
|
84
|
+
private extractSessionId;
|
|
85
|
+
private parseShellFile;
|
|
86
|
+
private log;
|
|
87
|
+
}
|
|
88
|
+
//# sourceMappingURL=supervisor.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"supervisor.d.ts","sourceRoot":"","sources":["../../src/manager/supervisor.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AACH,OAAO,EAAS,KAAK,YAAY,EAAE,MAAM,oBAAoB,CAAC;AAS9D,MAAM,WAAW,SAAS;IACxB,oDAAoD;IACpD,EAAE,EAAE,MAAM,CAAC;IACX,OAAO,EAAE,MAAM,CAAC;IAChB,GAAG,EAAE,MAAM,CAAC;IACZ,IAAI,EAAE,MAAM,CAAC;IACb,QAAQ,EAAE,MAAM,CAAC;IACjB,MAAM,EAAE,MAAM,CAAC;IACf,MAAM,EAAE,MAAM,CAAC;IACf,UAAU,EAAE,MAAM,CAAC;IACnB,IAAI,EAAE,QAAQ,GAAG,OAAO,CAAC;IACzB,eAAe,CAAC,EAAE,MAAM,CAAC;IACzB,sFAAsF;IACtF,MAAM,EAAE,CAAC,QAAQ,EAAE,MAAM,KAAK,OAAO,CAAC,IAAI,CAAC,GAAG,IAAI,CAAC;CACpD;AAED,4CAA4C;AAC5C,MAAM,WAAW,SAAS;IACxB,EAAE,EAAE,MAAM,CAAC;IACX,QAAQ,EAAE,MAAM,CAAC;IACjB,MAAM,EAAE,YAAY,CAAC;CACtB;AAED,MAAM,WAAW,YAAY;IAC3B,EAAE,EAAE,MAAM,CAAC;IACX,GAAG,EAAE,MAAM,CAAC;IACZ,KAAK,EAAE,YAAY,CAAC;IACpB,UAAU,EAAE,MAAM,CAAC;IACnB,OAAO,EAAE,MAAM,CAAC;IAChB,GAAG,EAAE,MAAM,CAAC;IACZ,IAAI,EAAE,MAAM,CAAC;IACb,MAAM,EAAE,MAAM,CAAC;IACf,QAAQ,EAAE,MAAM,CAAC;IACjB,IAAI,EAAE,QAAQ,GAAG,OAAO,CAAC;IACzB,QAAQ,EAAE,MAAM,GAAG,IAAI,CAAC;IACxB,SAAS,EAAE,MAAM,GAAG,IAAI,CAAC;IACzB,SAAS,EAAE,MAAM,CAAC;IAClB,QAAQ,EAAE,MAAM,GAAG,IAAI,CAAC;CACzB;AAID,qBAAa,iBAAiB;IAC5B,0DAA0D;IAC1D,OAAO,CAAC,SAAS,CAAyB;IAC1C,kCAAkC;IAClC,OAAO,CAAC,QAAQ,CAAC,OAAO,CAAmC;IAC3D,4CAA4C;IAC5C,OAAO,CAAC,QAAQ,CAAC,YAAY,CAAqD;IAClF,wDAAwD;IACxD,OAAO,CAAC,QAAQ,CAAC,cAAc,CAAuB;;IAQtD,KAAK,CAAC,IAAI,EAAE,SAAS,GAAG,YAAY;IA+E9B,IAAI,CAAC,EAAE,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;IASrC,GAAG,CAAC,EAAE,EAAE,MAAM,GAAG,YAAY,GAAG,SAAS;IAIzC,YAAY,CAAC,OAAO,EAAE,MAAM,GAAG,YAAY,EAAE;IAI7C,MAAM,IAAI,YAAY,EAAE;IAIxB,MAAM,CAAC,EAAE,EAAE,MAAM,GAAG,IAAI;IASxB,IAAI,WAAW,IAAI,MAAM,CAExB;IAED;;;OAGG;IACG,mBAAmB,IAAI,OAAO,CAAC,IAAI,CAAC;IAQ1C;;;OAGG;IACH,gBAAgB,CACd,EAAE,EAAE,MAAM,EACV,GAAG,EAAE,MAAM,EACX,MAAM,EAAE,IAAI,CAAC,YAAY,EAAE,OAAO,CAAC,EACnC,MAAM,EAAE,CAAC,QAAQ,EAAE,MAAM,KAAK,OAAO,CAAC,IAAI,CAAC,GAAG,IAAI,GACjD,IAAI;IAqCP;;;OAGG;IACH,OAAO,CAAC,aAAa;IAerB,OAAO,CAAC,aAAa;IAUrB,OAAO,CAAC,cAAc;IA0BtB,eAAe,IAAI,IAAI;IAOvB,OAAO,CAAC,SAAS;IAYjB,OAAO,CAAC,gBAAgB;IAMxB,OAAO,CAAC,cAAc;IActB,OAAO,CAAC,GAAG;CAGZ"}
|
|
@@ -0,0 +1,267 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* ProcessSupervisor — manages worker process lifecycle.
|
|
3
|
+
*
|
|
4
|
+
* Replaces ClaudePrintProvider's spawn logic with:
|
|
5
|
+
* - fd redirect (not Node pipe) for reliable output
|
|
6
|
+
* - Held child handles (no unref) for reliable exit detection
|
|
7
|
+
* - Three-layer env merge (system + global creds + project conf)
|
|
8
|
+
* - Exit callbacks that fire immediately in the tick process
|
|
9
|
+
*/
|
|
10
|
+
import { spawn } from 'node:child_process';
|
|
11
|
+
import { openSync, closeSync, mkdirSync, readFileSync, existsSync } from 'node:fs';
|
|
12
|
+
import { resolve, dirname } from 'node:path';
|
|
13
|
+
import { homedir } from 'node:os';
|
|
14
|
+
import { isProcessAlive, killProcessGroup, parseClaudeSessionId, parseCodexSessionId } from '../providers/outputParser.js';
|
|
15
|
+
// ─── Supervisor ─────────────────────────────────────────────────
|
|
16
|
+
export class ProcessSupervisor {
|
|
17
|
+
/** Global env: process.env + ~/.jarvis.env (Layer 1+2) */
|
|
18
|
+
globalEnv;
|
|
19
|
+
/** Active worker handles by ID */
|
|
20
|
+
workers = new Map();
|
|
21
|
+
/** Orphan PID poll timers (for Recovery) */
|
|
22
|
+
orphanTimers = new Map();
|
|
23
|
+
/** Pending PostAction promises (from exit callbacks) */
|
|
24
|
+
pendingActions = [];
|
|
25
|
+
constructor() {
|
|
26
|
+
this.globalEnv = this.loadGlobalEnv();
|
|
27
|
+
}
|
|
28
|
+
// ─── Spawn ──────────────────────────────────────────────────
|
|
29
|
+
spawn(opts) {
|
|
30
|
+
// Load project conf (Layer 3) and merge
|
|
31
|
+
const projectEnv = this.loadProjectEnv(opts.project);
|
|
32
|
+
const env = { ...this.globalEnv, ...projectEnv };
|
|
33
|
+
// Build CLI args
|
|
34
|
+
const args = this.buildArgs(opts);
|
|
35
|
+
// Ensure output directory exists
|
|
36
|
+
mkdirSync(dirname(opts.outputFile), { recursive: true });
|
|
37
|
+
// fd redirect: OS kernel writes stdout/stderr directly to file
|
|
38
|
+
const fd = openSync(opts.outputFile, 'a');
|
|
39
|
+
let child;
|
|
40
|
+
try {
|
|
41
|
+
child = spawn(opts.tool === 'claude' ? 'claude' : 'codex', args, {
|
|
42
|
+
cwd: opts.worktree,
|
|
43
|
+
stdio: ['pipe', fd, fd],
|
|
44
|
+
detached: true,
|
|
45
|
+
env,
|
|
46
|
+
});
|
|
47
|
+
// Write prompt to stdin and close
|
|
48
|
+
child.stdin.write(opts.prompt);
|
|
49
|
+
child.stdin.end();
|
|
50
|
+
}
|
|
51
|
+
finally {
|
|
52
|
+
// Close fd on Node side — child inherits it, OS guarantees write
|
|
53
|
+
// Always close to prevent fd leak even if spawn throws (H4 fix)
|
|
54
|
+
closeSync(fd);
|
|
55
|
+
}
|
|
56
|
+
// DO NOT call child.unref() — tick process holds the handle
|
|
57
|
+
// This ensures exit callback fires reliably
|
|
58
|
+
const handle = {
|
|
59
|
+
id: opts.id,
|
|
60
|
+
pid: child.pid ?? 0,
|
|
61
|
+
child,
|
|
62
|
+
outputFile: opts.outputFile,
|
|
63
|
+
project: opts.project,
|
|
64
|
+
seq: opts.seq,
|
|
65
|
+
slot: opts.slot,
|
|
66
|
+
branch: opts.branch,
|
|
67
|
+
worktree: opts.worktree,
|
|
68
|
+
tool: opts.tool,
|
|
69
|
+
exitCode: null,
|
|
70
|
+
sessionId: opts.resumeSessionId || null,
|
|
71
|
+
startedAt: new Date().toISOString(),
|
|
72
|
+
exitedAt: null,
|
|
73
|
+
};
|
|
74
|
+
this.workers.set(opts.id, handle);
|
|
75
|
+
child.on('exit', (code) => {
|
|
76
|
+
handle.exitCode = code ?? 1;
|
|
77
|
+
handle.exitedAt = new Date().toISOString();
|
|
78
|
+
// Extract session ID for potential --resume retry
|
|
79
|
+
if (!handle.sessionId) {
|
|
80
|
+
handle.sessionId = this.extractSessionId(handle);
|
|
81
|
+
}
|
|
82
|
+
// Queue PostActions as tracked promise (not fire-and-forget)
|
|
83
|
+
const result = opts.onExit(handle.exitCode);
|
|
84
|
+
if (result && typeof result.then === 'function') {
|
|
85
|
+
const promise = result.catch(err => {
|
|
86
|
+
this.log(`PostActions error for ${opts.id}: ${err}`);
|
|
87
|
+
});
|
|
88
|
+
this.pendingActions.push(promise);
|
|
89
|
+
}
|
|
90
|
+
});
|
|
91
|
+
this.log(`Spawned ${opts.tool} for ${opts.id} (pid=${child.pid}), output=${opts.outputFile}`);
|
|
92
|
+
return handle;
|
|
93
|
+
}
|
|
94
|
+
// ─── Kill / Query ───────────────────────────────────────────
|
|
95
|
+
async kill(id) {
|
|
96
|
+
const handle = this.workers.get(id);
|
|
97
|
+
if (!handle)
|
|
98
|
+
return;
|
|
99
|
+
if (handle.pid > 0 && isProcessAlive(handle.pid)) {
|
|
100
|
+
await killProcessGroup(handle.pid);
|
|
101
|
+
}
|
|
102
|
+
this.workers.delete(id);
|
|
103
|
+
}
|
|
104
|
+
get(id) {
|
|
105
|
+
return this.workers.get(id);
|
|
106
|
+
}
|
|
107
|
+
getByProject(project) {
|
|
108
|
+
return Array.from(this.workers.values()).filter(w => w.project === project);
|
|
109
|
+
}
|
|
110
|
+
getAll() {
|
|
111
|
+
return Array.from(this.workers.values());
|
|
112
|
+
}
|
|
113
|
+
remove(id) {
|
|
114
|
+
this.workers.delete(id);
|
|
115
|
+
const timer = this.orphanTimers.get(id);
|
|
116
|
+
if (timer) {
|
|
117
|
+
clearInterval(timer);
|
|
118
|
+
this.orphanTimers.delete(id);
|
|
119
|
+
}
|
|
120
|
+
}
|
|
121
|
+
get activeCount() {
|
|
122
|
+
return this.workers.size;
|
|
123
|
+
}
|
|
124
|
+
/**
|
|
125
|
+
* Wait for all pending PostAction promises to settle.
|
|
126
|
+
* Called by tick after each cycle to ensure exit callbacks complete.
|
|
127
|
+
*/
|
|
128
|
+
async drainPendingActions() {
|
|
129
|
+
if (this.pendingActions.length === 0)
|
|
130
|
+
return;
|
|
131
|
+
await Promise.allSettled(this.pendingActions);
|
|
132
|
+
this.pendingActions.length = 0; // clear
|
|
133
|
+
}
|
|
134
|
+
// ─── Orphan PID Monitoring (Recovery mode) ──────────────────
|
|
135
|
+
/**
|
|
136
|
+
* Monitor a PID that we don't have a child handle for (tick restarted).
|
|
137
|
+
* Polls every 5s; when PID dies, calls onDead.
|
|
138
|
+
*/
|
|
139
|
+
monitorOrphanPid(id, pid, handle, onDead) {
|
|
140
|
+
// Store handle without child reference
|
|
141
|
+
const orphanHandle = { ...handle, child: null };
|
|
142
|
+
this.workers.set(id, orphanHandle);
|
|
143
|
+
const timer = setInterval(() => {
|
|
144
|
+
if (!isProcessAlive(pid)) {
|
|
145
|
+
clearInterval(timer);
|
|
146
|
+
this.orphanTimers.delete(id);
|
|
147
|
+
// Infer exit code from output file instead of hardcoding 1
|
|
148
|
+
const inferredCode = this.inferExitCode(orphanHandle);
|
|
149
|
+
orphanHandle.exitCode = inferredCode;
|
|
150
|
+
orphanHandle.exitedAt = new Date().toISOString();
|
|
151
|
+
// Try to extract session ID
|
|
152
|
+
if (!orphanHandle.sessionId) {
|
|
153
|
+
orphanHandle.sessionId = this.extractSessionId(orphanHandle);
|
|
154
|
+
}
|
|
155
|
+
this.log(`Orphan PID ${pid} (${id}) is dead (inferred exitCode=${inferredCode}), triggering completion check`);
|
|
156
|
+
// Track the promise like spawn exit callbacks
|
|
157
|
+
const result = onDead(inferredCode);
|
|
158
|
+
if (result && typeof result.then === 'function') {
|
|
159
|
+
const promise = result.catch(err => {
|
|
160
|
+
this.log(`PostActions error for orphan ${id}: ${err}`);
|
|
161
|
+
});
|
|
162
|
+
this.pendingActions.push(promise);
|
|
163
|
+
}
|
|
164
|
+
}
|
|
165
|
+
}, 5_000);
|
|
166
|
+
this.orphanTimers.set(id, timer);
|
|
167
|
+
this.log(`Monitoring orphan PID ${pid} for ${id} (5s poll)`);
|
|
168
|
+
}
|
|
169
|
+
/**
|
|
170
|
+
* Infer exit code for an orphan worker by checking output file.
|
|
171
|
+
* If output contains a successful result, assume exit code 0.
|
|
172
|
+
*/
|
|
173
|
+
inferExitCode(handle) {
|
|
174
|
+
if (!handle.outputFile)
|
|
175
|
+
return 1;
|
|
176
|
+
try {
|
|
177
|
+
const { extractLastAssistantText } = require('../providers/outputParser.js');
|
|
178
|
+
const lastText = extractLastAssistantText(handle.outputFile);
|
|
179
|
+
// If worker produced meaningful output and said "done", likely succeeded
|
|
180
|
+
if (/\b(done|完成|全部完成|已推送)\b|🎉/i.test(lastText)) {
|
|
181
|
+
return 0;
|
|
182
|
+
}
|
|
183
|
+
}
|
|
184
|
+
catch { /* can't read output */ }
|
|
185
|
+
return 1; // default to failure if can't determine
|
|
186
|
+
}
|
|
187
|
+
// ─── Environment Loading ────────────────────────────────────
|
|
188
|
+
loadGlobalEnv() {
|
|
189
|
+
const env = { ...process.env };
|
|
190
|
+
const envPath = resolve(homedir(), '.jarvis.env');
|
|
191
|
+
if (existsSync(envPath)) {
|
|
192
|
+
const parsed = this.parseShellFile(envPath);
|
|
193
|
+
Object.assign(env, parsed);
|
|
194
|
+
}
|
|
195
|
+
return env;
|
|
196
|
+
}
|
|
197
|
+
loadProjectEnv(project) {
|
|
198
|
+
const confPath = resolve(homedir(), '.projects', project, 'conf');
|
|
199
|
+
if (!existsSync(confPath))
|
|
200
|
+
return {};
|
|
201
|
+
// Source both files in one bash context so conf can reference jarvis.env vars
|
|
202
|
+
const envPath = resolve(homedir(), '.jarvis.env');
|
|
203
|
+
try {
|
|
204
|
+
const { execSync } = require('node:child_process');
|
|
205
|
+
const sources = [];
|
|
206
|
+
if (existsSync(envPath))
|
|
207
|
+
sources.push(`source "${envPath}" 2>/dev/null`);
|
|
208
|
+
sources.push(`source "${confPath}" 2>/dev/null`);
|
|
209
|
+
const output = execSync(`bash -c 'set -a; ${sources.join('; ')}; env'`, { encoding: 'utf-8', timeout: 5000 });
|
|
210
|
+
const result = {};
|
|
211
|
+
for (const line of output.split('\n')) {
|
|
212
|
+
const idx = line.indexOf('=');
|
|
213
|
+
if (idx > 0)
|
|
214
|
+
result[line.slice(0, idx)] = line.slice(idx + 1);
|
|
215
|
+
}
|
|
216
|
+
return result;
|
|
217
|
+
}
|
|
218
|
+
catch {
|
|
219
|
+
return this.parseShellFile(confPath);
|
|
220
|
+
}
|
|
221
|
+
}
|
|
222
|
+
reloadGlobalEnv() {
|
|
223
|
+
this.globalEnv = this.loadGlobalEnv();
|
|
224
|
+
this.log('Global environment reloaded');
|
|
225
|
+
}
|
|
226
|
+
// ─── Helpers ────────────────────────────────────────────────
|
|
227
|
+
buildArgs(opts) {
|
|
228
|
+
if (opts.tool === 'claude') {
|
|
229
|
+
const args = ['-p', '--verbose', '--output-format', 'stream-json', '--dangerously-skip-permissions'];
|
|
230
|
+
if (opts.resumeSessionId)
|
|
231
|
+
args.push('--resume', opts.resumeSessionId);
|
|
232
|
+
return args;
|
|
233
|
+
}
|
|
234
|
+
// codex
|
|
235
|
+
const args = ['exec', '--json'];
|
|
236
|
+
if (opts.resumeSessionId)
|
|
237
|
+
args.push('--resume', opts.resumeSessionId);
|
|
238
|
+
return args;
|
|
239
|
+
}
|
|
240
|
+
extractSessionId(handle) {
|
|
241
|
+
if (!handle.outputFile)
|
|
242
|
+
return null;
|
|
243
|
+
if (handle.tool === 'claude')
|
|
244
|
+
return parseClaudeSessionId(handle.outputFile);
|
|
245
|
+
return parseCodexSessionId(handle.outputFile);
|
|
246
|
+
}
|
|
247
|
+
parseShellFile(filePath) {
|
|
248
|
+
const result = {};
|
|
249
|
+
try {
|
|
250
|
+
const content = readFileSync(filePath, 'utf-8');
|
|
251
|
+
for (const line of content.split('\n')) {
|
|
252
|
+
const trimmed = line.trim();
|
|
253
|
+
if (!trimmed || trimmed.startsWith('#'))
|
|
254
|
+
continue;
|
|
255
|
+
const match = trimmed.match(/^(?:export\s+)?([A-Z_][A-Z0-9_]*)=["']?(.*?)["']?\s*$/);
|
|
256
|
+
if (match)
|
|
257
|
+
result[match[1]] = match[2];
|
|
258
|
+
}
|
|
259
|
+
}
|
|
260
|
+
catch { /* ignore */ }
|
|
261
|
+
return result;
|
|
262
|
+
}
|
|
263
|
+
log(msg) {
|
|
264
|
+
process.stderr.write(`[supervisor] ${msg}\n`);
|
|
265
|
+
}
|
|
266
|
+
}
|
|
267
|
+
//# sourceMappingURL=supervisor.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"supervisor.js","sourceRoot":"","sources":["../../src/manager/supervisor.ts"],"names":[],"mappings":"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"}
|