@namzu/cli 23.0.0 → 24.0.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/CHANGELOG.md +69 -0
- package/README.md +12 -0
- package/dist/cli.d.ts.map +1 -1
- package/dist/cli.js +17 -10
- package/dist/cli.js.map +1 -1
- package/dist/commands/resident-flags.d.ts +19 -0
- package/dist/commands/resident-flags.d.ts.map +1 -0
- package/dist/commands/resident-flags.js +153 -0
- package/dist/commands/resident-flags.js.map +1 -0
- package/dist/commands/resident.d.ts +20 -0
- package/dist/commands/resident.d.ts.map +1 -0
- package/dist/commands/resident.js +380 -0
- package/dist/commands/resident.js.map +1 -0
- package/dist/commands/upgrade.d.ts +1 -0
- package/dist/commands/upgrade.d.ts.map +1 -1
- package/dist/commands/upgrade.js +6 -3
- package/dist/commands/upgrade.js.map +1 -1
- package/dist/integrations/npm-invocation.d.ts +10 -0
- package/dist/integrations/npm-invocation.d.ts.map +1 -0
- package/dist/integrations/npm-invocation.js +23 -0
- package/dist/integrations/npm-invocation.js.map +1 -0
- package/dist/integrations/providers/credential-store.d.ts +8 -7
- package/dist/integrations/providers/credential-store.d.ts.map +1 -1
- package/dist/integrations/providers/credential-store.js +44 -17
- package/dist/integrations/providers/credential-store.js.map +1 -1
- package/dist/integrations/providers/discover.d.ts.map +1 -1
- package/dist/integrations/providers/discover.js +7 -2
- package/dist/integrations/providers/discover.js.map +1 -1
- package/dist/integrations/providers/harness-credentials.d.ts +2 -2
- package/dist/integrations/providers/harness-credentials.d.ts.map +1 -1
- package/dist/integrations/providers/harness-credentials.js +13 -8
- package/dist/integrations/providers/harness-credentials.js.map +1 -1
- package/dist/integrations/providers/setup.d.ts.map +1 -1
- package/dist/integrations/providers/setup.js +52 -5
- package/dist/integrations/providers/setup.js.map +1 -1
- package/dist/integrations/resident/foreground.d.ts +19 -0
- package/dist/integrations/resident/foreground.d.ts.map +1 -0
- package/dist/integrations/resident/foreground.js +95 -0
- package/dist/integrations/resident/foreground.js.map +1 -0
- package/dist/integrations/resident/lifecycle-errors.d.ts +9 -0
- package/dist/integrations/resident/lifecycle-errors.d.ts.map +1 -0
- package/dist/integrations/resident/lifecycle-errors.js +15 -0
- package/dist/integrations/resident/lifecycle-errors.js.map +1 -0
- package/dist/integrations/resident/owned-runner.d.ts +17 -0
- package/dist/integrations/resident/owned-runner.d.ts.map +1 -0
- package/dist/integrations/resident/owned-runner.js +91 -0
- package/dist/integrations/resident/owned-runner.js.map +1 -0
- package/dist/integrations/resident/runner-control.d.ts +47 -0
- package/dist/integrations/resident/runner-control.d.ts.map +1 -0
- package/dist/integrations/resident/runner-control.js +238 -0
- package/dist/integrations/resident/runner-control.js.map +1 -0
- package/dist/integrations/resident/runner-launch.d.ts +47 -0
- package/dist/integrations/resident/runner-launch.d.ts.map +1 -0
- package/dist/integrations/resident/runner-launch.js +140 -0
- package/dist/integrations/resident/runner-launch.js.map +1 -0
- package/dist/integrations/resident/runner-store.d.ts +44 -0
- package/dist/integrations/resident/runner-store.d.ts.map +1 -0
- package/dist/integrations/resident/runner-store.js +283 -0
- package/dist/integrations/resident/runner-store.js.map +1 -0
- package/dist/integrations/resident/runner-worker.d.ts +2 -0
- package/dist/integrations/resident/runner-worker.d.ts.map +1 -0
- package/dist/integrations/resident/runner-worker.js +143 -0
- package/dist/integrations/resident/runner-worker.js.map +1 -0
- package/dist/integrations/resident/session-step.d.ts +24 -0
- package/dist/integrations/resident/session-step.d.ts.map +1 -0
- package/dist/integrations/resident/session-step.js +366 -0
- package/dist/integrations/resident/session-step.js.map +1 -0
- package/dist/integrations/resident/storage.d.ts +17 -0
- package/dist/integrations/resident/storage.d.ts.map +1 -0
- package/dist/integrations/resident/storage.js +139 -0
- package/dist/integrations/resident/storage.js.map +1 -0
- package/dist/integrations/state/private-directory.d.ts +4 -2
- package/dist/integrations/state/private-directory.d.ts.map +1 -1
- package/dist/integrations/state/private-directory.js +6 -4
- package/dist/integrations/state/private-directory.js.map +1 -1
- package/dist/tui/agent.d.ts +10 -1
- package/dist/tui/agent.d.ts.map +1 -1
- package/dist/tui/agent.js +77 -18
- package/dist/tui/agent.js.map +1 -1
- package/dist/tui/exit-summary.d.ts +1 -1
- package/dist/tui/exit-summary.d.ts.map +1 -1
- package/dist/tui/exit-summary.js +17 -5
- package/dist/tui/exit-summary.js.map +1 -1
- package/package.json +5 -5
|
@@ -0,0 +1,140 @@
|
|
|
1
|
+
import { fork } from 'node:child_process';
|
|
2
|
+
import { createRequire } from 'node:module';
|
|
3
|
+
import { setTimeout as sleep } from 'node:timers/promises';
|
|
4
|
+
import { queryRunner } from './runner-control.js';
|
|
5
|
+
import { finishRunner, publicRunner, readRunner, readRunnerInstance, reserveRunner, } from './runner-store.js';
|
|
6
|
+
/** Launch the same installation with no terminal streams or on-disk credentials/config. */
|
|
7
|
+
export async function startResidentRunner(options) {
|
|
8
|
+
const { resident } = options;
|
|
9
|
+
const existing = readRunner(resident);
|
|
10
|
+
if (existing && (existing.phase === 'reserved' || existing.phase === 'running'))
|
|
11
|
+
throw new Error(`Runner ${existing.instanceId} already owns this resident. Use resident status or stop; a second start cannot reset its limit.`);
|
|
12
|
+
const agenda = await resident.agenda.read();
|
|
13
|
+
if (!agenda || agenda.paused || agenda.pursuits.some((p) => p.state.phase === 'running'))
|
|
14
|
+
throw new Error('Starting requires open admission and no unresolved pursuit claims.');
|
|
15
|
+
const owner = reserveRunner(resident, {
|
|
16
|
+
mode: 'background',
|
|
17
|
+
maxSteps: options.maxSteps,
|
|
18
|
+
pauseGeneration: agenda.pauseGeneration ?? 0,
|
|
19
|
+
});
|
|
20
|
+
const source = import.meta.url.endsWith('.ts');
|
|
21
|
+
const worker = new URL(`./runner-worker.${source ? 'ts' : 'js'}`, import.meta.url);
|
|
22
|
+
const launch = {
|
|
23
|
+
version: 1,
|
|
24
|
+
cwd: resident.cwd,
|
|
25
|
+
agentKey: resident.agentKey,
|
|
26
|
+
instanceId: owner.instanceId,
|
|
27
|
+
config: options.ctx.config,
|
|
28
|
+
flags: options.flags,
|
|
29
|
+
toolLoading: options.toolLoading,
|
|
30
|
+
contextProfile: options.contextProfile,
|
|
31
|
+
maxIdleMs: options.maxIdleMs,
|
|
32
|
+
};
|
|
33
|
+
let child;
|
|
34
|
+
try {
|
|
35
|
+
child = fork(worker, [], {
|
|
36
|
+
cwd: resident.cwd,
|
|
37
|
+
env: { ...process.env, NAMZU_HOME: resident.root },
|
|
38
|
+
detached: true,
|
|
39
|
+
stdio: ['ignore', 'ignore', 'ignore', 'ipc'],
|
|
40
|
+
execArgv: source ? ['--import', createRequire(import.meta.url).resolve('tsx')] : [],
|
|
41
|
+
});
|
|
42
|
+
}
|
|
43
|
+
catch (error) {
|
|
44
|
+
finishRunner(resident, owner, 'launch_failed');
|
|
45
|
+
throw error;
|
|
46
|
+
}
|
|
47
|
+
return await new Promise((resolve, reject) => {
|
|
48
|
+
let settled = false;
|
|
49
|
+
const finish = (error) => {
|
|
50
|
+
if (settled)
|
|
51
|
+
return;
|
|
52
|
+
settled = true;
|
|
53
|
+
clearTimeout(timer);
|
|
54
|
+
child.removeListener('message', message);
|
|
55
|
+
child.removeListener('exit', exited);
|
|
56
|
+
// Keep the error listener: asynchronous IPC teardown must not crash the launcher.
|
|
57
|
+
if (child.connected)
|
|
58
|
+
child.disconnect();
|
|
59
|
+
child.unref();
|
|
60
|
+
if (error)
|
|
61
|
+
reject(error);
|
|
62
|
+
else {
|
|
63
|
+
try {
|
|
64
|
+
const current = readRunnerInstance(resident, owner.instanceId);
|
|
65
|
+
if (!current)
|
|
66
|
+
throw new Error('Runner startup receipt disappeared.');
|
|
67
|
+
resolve(publicRunner(current));
|
|
68
|
+
}
|
|
69
|
+
catch (readError) {
|
|
70
|
+
reject(readError);
|
|
71
|
+
}
|
|
72
|
+
}
|
|
73
|
+
};
|
|
74
|
+
const message = (raw) => {
|
|
75
|
+
if (!raw || typeof raw !== 'object')
|
|
76
|
+
return;
|
|
77
|
+
const value = raw;
|
|
78
|
+
if (value.instanceId !== owner.instanceId)
|
|
79
|
+
return;
|
|
80
|
+
if (value.kind === 'error') {
|
|
81
|
+
finish(new Error(typeof value.message === 'string' ? value.message : 'Runner startup failed.'));
|
|
82
|
+
}
|
|
83
|
+
else if (value.kind === 'ready') {
|
|
84
|
+
// The child will not admit a model step before this explicit handoff.
|
|
85
|
+
child.send({ kind: 'go', instanceId: owner.instanceId }, (error) => finish(error ?? undefined));
|
|
86
|
+
}
|
|
87
|
+
};
|
|
88
|
+
const exited = () => finish(new Error('Resident worker exited before startup was acknowledged. Inspect resident status.'));
|
|
89
|
+
const timer = setTimeout(() => finish(new Error('Resident startup was not acknowledged. Ownership is retained; inspect resident status before retrying.')), 15_000);
|
|
90
|
+
child.on('message', message);
|
|
91
|
+
child.once('exit', exited);
|
|
92
|
+
child.on('error', (error) => {
|
|
93
|
+
if (!child.pid) {
|
|
94
|
+
try {
|
|
95
|
+
finishRunner(resident, owner, 'launch_failed');
|
|
96
|
+
}
|
|
97
|
+
catch {
|
|
98
|
+
/* Keep the exact-owner conflict visible in status. */
|
|
99
|
+
}
|
|
100
|
+
}
|
|
101
|
+
finish(error);
|
|
102
|
+
});
|
|
103
|
+
child.send(launch, (error) => {
|
|
104
|
+
if (error)
|
|
105
|
+
finish(error);
|
|
106
|
+
});
|
|
107
|
+
});
|
|
108
|
+
}
|
|
109
|
+
export async function residentRunnerStatus(resident) {
|
|
110
|
+
const record = readRunner(resident);
|
|
111
|
+
if (!record)
|
|
112
|
+
return { owner: null, live: null };
|
|
113
|
+
return {
|
|
114
|
+
owner: publicRunner(record),
|
|
115
|
+
live: record.phase === 'running' ? await queryRunner(record, 'status') : null,
|
|
116
|
+
};
|
|
117
|
+
}
|
|
118
|
+
/** Caller durably closes admission first. No signals are sent to recorded PIDs. */
|
|
119
|
+
export async function stopResidentRunner(resident, options) {
|
|
120
|
+
const record = options.owner;
|
|
121
|
+
const waitMs = options.waitMs ?? 5_000;
|
|
122
|
+
if (!record)
|
|
123
|
+
return { status: 'absent', owner: null };
|
|
124
|
+
if (record.phase === 'stopped')
|
|
125
|
+
return { status: 'drained', owner: publicRunner(record) };
|
|
126
|
+
if (record.phase === 'released')
|
|
127
|
+
return { status: 'unconfirmed', owner: publicRunner(record) };
|
|
128
|
+
if (record.phase === 'running')
|
|
129
|
+
await queryRunner(record, 'stop');
|
|
130
|
+
const deadline = Date.now() + waitMs;
|
|
131
|
+
while (true) {
|
|
132
|
+
const current = readRunnerInstance(resident, record.instanceId);
|
|
133
|
+
if (current?.phase === 'stopped')
|
|
134
|
+
return { status: 'drained', owner: publicRunner(current) };
|
|
135
|
+
if (!current || current.phase === 'released' || Date.now() >= deadline)
|
|
136
|
+
return { status: 'unconfirmed', owner: current ? publicRunner(current) : null };
|
|
137
|
+
await sleep(Math.min(50, Math.max(1, deadline - Date.now())));
|
|
138
|
+
}
|
|
139
|
+
}
|
|
140
|
+
//# sourceMappingURL=runner-launch.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"runner-launch.js","sourceRoot":"","sources":["../../../src/integrations/resident/runner-launch.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
import { type ProjectId, type TenantId } from '@namzu/sdk';
|
|
2
|
+
import type { CliResident } from './storage.js';
|
|
3
|
+
export interface RunnerRecord {
|
|
4
|
+
readonly version: 1;
|
|
5
|
+
readonly revision: number;
|
|
6
|
+
readonly instanceId: string;
|
|
7
|
+
readonly tenantId: TenantId;
|
|
8
|
+
readonly projectId: ProjectId;
|
|
9
|
+
readonly agentKey: string;
|
|
10
|
+
readonly cwd: string;
|
|
11
|
+
readonly mode: 'foreground' | 'background';
|
|
12
|
+
readonly phase: 'reserved' | 'running' | 'stopped' | 'released';
|
|
13
|
+
readonly reservedAt: number;
|
|
14
|
+
readonly maxSteps: number;
|
|
15
|
+
readonly pauseGeneration: number;
|
|
16
|
+
readonly pid: number | null;
|
|
17
|
+
readonly port: number | null;
|
|
18
|
+
/** Private authentication material; never include this in status output. */
|
|
19
|
+
readonly token: string;
|
|
20
|
+
readonly endedAt: number | null;
|
|
21
|
+
readonly outcome: string | null;
|
|
22
|
+
}
|
|
23
|
+
export interface ReserveRunnerOptions {
|
|
24
|
+
readonly mode: RunnerRecord['mode'];
|
|
25
|
+
readonly maxSteps: number;
|
|
26
|
+
readonly pauseGeneration: number;
|
|
27
|
+
}
|
|
28
|
+
/** An absent runner is a read-only result, never an instruction to initialize it. */
|
|
29
|
+
export declare function readRunner(resident: CliResident): RunnerRecord | null;
|
|
30
|
+
/** The original runner's final evidence remains visible after a successor starts. */
|
|
31
|
+
export declare function readRunnerInstance(resident: CliResident, instanceId: string): RunnerRecord | null;
|
|
32
|
+
/** Reserve one explicitly authorized invocation; an occupied owner is never stolen. */
|
|
33
|
+
export declare function reserveRunner(resident: CliResident, options: ReserveRunnerOptions): RunnerRecord;
|
|
34
|
+
export declare function attachRunning(resident: CliResident, expected: RunnerRecord, process: {
|
|
35
|
+
readonly pid: number;
|
|
36
|
+
readonly port: number | null;
|
|
37
|
+
}): RunnerRecord;
|
|
38
|
+
/** Publish only after the executor and its controls have drained. */
|
|
39
|
+
export declare function finishRunner(resident: CliResident, expected: RunnerRecord, outcome: string): RunnerRecord;
|
|
40
|
+
/** Explicit operator recovery of an exact owner; this is never proof of drainage. */
|
|
41
|
+
export declare function releaseRunner(resident: CliResident, expected: RunnerRecord): RunnerRecord;
|
|
42
|
+
/** Status reports retain ownership evidence without disclosing the control nonce. */
|
|
43
|
+
export declare function publicRunner(record: RunnerRecord): Omit<RunnerRecord, 'token'>;
|
|
44
|
+
//# sourceMappingURL=runner-store.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"runner-store.d.ts","sourceRoot":"","sources":["../../../src/integrations/resident/runner-store.ts"],"names":[],"mappings":"AAIA,OAAO,EAAE,KAAK,SAAS,EAAyB,KAAK,QAAQ,EAAc,MAAM,YAAY,CAAA;AAI7F,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,cAAc,CAAA;AAE/C,MAAM,WAAW,YAAY;IAC5B,QAAQ,CAAC,OAAO,EAAE,CAAC,CAAA;IACnB,QAAQ,CAAC,QAAQ,EAAE,MAAM,CAAA;IACzB,QAAQ,CAAC,UAAU,EAAE,MAAM,CAAA;IAC3B,QAAQ,CAAC,QAAQ,EAAE,QAAQ,CAAA;IAC3B,QAAQ,CAAC,SAAS,EAAE,SAAS,CAAA;IAC7B,QAAQ,CAAC,QAAQ,EAAE,MAAM,CAAA;IACzB,QAAQ,CAAC,GAAG,EAAE,MAAM,CAAA;IACpB,QAAQ,CAAC,IAAI,EAAE,YAAY,GAAG,YAAY,CAAA;IAC1C,QAAQ,CAAC,KAAK,EAAE,UAAU,GAAG,SAAS,GAAG,SAAS,GAAG,UAAU,CAAA;IAC/D,QAAQ,CAAC,UAAU,EAAE,MAAM,CAAA;IAC3B,QAAQ,CAAC,QAAQ,EAAE,MAAM,CAAA;IACzB,QAAQ,CAAC,eAAe,EAAE,MAAM,CAAA;IAChC,QAAQ,CAAC,GAAG,EAAE,MAAM,GAAG,IAAI,CAAA;IAC3B,QAAQ,CAAC,IAAI,EAAE,MAAM,GAAG,IAAI,CAAA;IAC5B,4EAA4E;IAC5E,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAA;IACtB,QAAQ,CAAC,OAAO,EAAE,MAAM,GAAG,IAAI,CAAA;IAC/B,QAAQ,CAAC,OAAO,EAAE,MAAM,GAAG,IAAI,CAAA;CAC/B;AAED,MAAM,WAAW,oBAAoB;IACpC,QAAQ,CAAC,IAAI,EAAE,YAAY,CAAC,MAAM,CAAC,CAAA;IACnC,QAAQ,CAAC,QAAQ,EAAE,MAAM,CAAA;IACzB,QAAQ,CAAC,eAAe,EAAE,MAAM,CAAA;CAChC;AA4KD,qFAAqF;AACrF,wBAAgB,UAAU,CAAC,QAAQ,EAAE,WAAW,GAAG,YAAY,GAAG,IAAI,CAGrE;AAED,qFAAqF;AACrF,wBAAgB,kBAAkB,CAAC,QAAQ,EAAE,WAAW,EAAE,UAAU,EAAE,MAAM,GAAG,YAAY,GAAG,IAAI,CAOjG;AAuBD,uFAAuF;AACvF,wBAAgB,aAAa,CAAC,QAAQ,EAAE,WAAW,EAAE,OAAO,EAAE,oBAAoB,GAAG,YAAY,CA+BhG;AAED,wBAAgB,aAAa,CAC5B,QAAQ,EAAE,WAAW,EACrB,QAAQ,EAAE,YAAY,EACtB,OAAO,EAAE;IAAE,QAAQ,CAAC,GAAG,EAAE,MAAM,CAAC;IAAC,QAAQ,CAAC,IAAI,EAAE,MAAM,GAAG,IAAI,CAAA;CAAE,GAC7D,YAAY,CASd;AAED,qEAAqE;AACrE,wBAAgB,YAAY,CAC3B,QAAQ,EAAE,WAAW,EACrB,QAAQ,EAAE,YAAY,EACtB,OAAO,EAAE,MAAM,GACb,YAAY,CAWd;AAED,qFAAqF;AACrF,wBAAgB,aAAa,CAAC,QAAQ,EAAE,WAAW,EAAE,QAAQ,EAAE,YAAY,GAAG,YAAY,CAWzF;AAED,qFAAqF;AACrF,wBAAgB,YAAY,CAAC,MAAM,EAAE,YAAY,GAAG,IAAI,CAAC,YAAY,EAAE,OAAO,CAAC,CAmB9E"}
|
|
@@ -0,0 +1,283 @@
|
|
|
1
|
+
import { randomBytes, randomUUID } from 'node:crypto';
|
|
2
|
+
import { lstatSync, readFileSync, readdirSync } from 'node:fs';
|
|
3
|
+
import { isAbsolute, join, resolve } from 'node:path';
|
|
4
|
+
import { isDeepStrictEqual } from 'node:util';
|
|
5
|
+
import { ResidentConflictError, isEntityId } from '@namzu/sdk';
|
|
6
|
+
import { publishPrivateJsonIfAbsent } from '../state/immutable-json.js';
|
|
7
|
+
import { ensurePrivateStateDirectory } from '../state/private-directory.js';
|
|
8
|
+
const UUID = /^[0-9a-f]{8}-(?:[0-9a-f]{4}-){3}[0-9a-f]{12}$/u;
|
|
9
|
+
const REVISION_NAME = /^([1-9][0-9]{0,15})\.json$/u;
|
|
10
|
+
const FIELDS = [
|
|
11
|
+
'version',
|
|
12
|
+
'revision',
|
|
13
|
+
'instanceId',
|
|
14
|
+
'tenantId',
|
|
15
|
+
'projectId',
|
|
16
|
+
'agentKey',
|
|
17
|
+
'cwd',
|
|
18
|
+
'mode',
|
|
19
|
+
'phase',
|
|
20
|
+
'reservedAt',
|
|
21
|
+
'maxSteps',
|
|
22
|
+
'pauseGeneration',
|
|
23
|
+
'pid',
|
|
24
|
+
'port',
|
|
25
|
+
'token',
|
|
26
|
+
'endedAt',
|
|
27
|
+
'outcome',
|
|
28
|
+
];
|
|
29
|
+
function integer(value, minimum) {
|
|
30
|
+
return typeof value === 'number' && Number.isSafeInteger(value) && value >= minimum;
|
|
31
|
+
}
|
|
32
|
+
function canonicalPath(value) {
|
|
33
|
+
return !value.includes('\0') && isAbsolute(value) && resolve(value) === value;
|
|
34
|
+
}
|
|
35
|
+
function location(resident) {
|
|
36
|
+
if (!isEntityId(resident.tenantId, 'tenant') ||
|
|
37
|
+
!isEntityId(resident.projectId, 'project') ||
|
|
38
|
+
!/^[a-z0-9][a-z0-9_-]{0,63}$/u.test(resident.agentKey) ||
|
|
39
|
+
!canonicalPath(resident.root) ||
|
|
40
|
+
!canonicalPath(resident.cwd)) {
|
|
41
|
+
throw new Error('Invalid resident scope for runner ownership.');
|
|
42
|
+
}
|
|
43
|
+
const base = join(resident.root, 'projects', resident.projectId, 'cli', 'residents', resident.agentKey);
|
|
44
|
+
if (resident.artifactsRoot !== join(base, 'attempts')) {
|
|
45
|
+
throw new Error('Resident runner path does not match its bound project and agent.');
|
|
46
|
+
}
|
|
47
|
+
return { base, runner: join(base, 'runner'), revisions: join(base, 'runner', 'revisions') };
|
|
48
|
+
}
|
|
49
|
+
function realDirectory(path) {
|
|
50
|
+
try {
|
|
51
|
+
const entry = lstatSync(path);
|
|
52
|
+
if (!entry.isDirectory() || entry.isSymbolicLink()) {
|
|
53
|
+
throw new Error(`Resident runner state requires a real directory: ${path}`);
|
|
54
|
+
}
|
|
55
|
+
return true;
|
|
56
|
+
}
|
|
57
|
+
catch (error) {
|
|
58
|
+
if (error.code === 'ENOENT')
|
|
59
|
+
return false;
|
|
60
|
+
throw error;
|
|
61
|
+
}
|
|
62
|
+
}
|
|
63
|
+
function revisions(resident) {
|
|
64
|
+
const paths = location(resident);
|
|
65
|
+
let current = resident.root;
|
|
66
|
+
if (!realDirectory(current))
|
|
67
|
+
return [];
|
|
68
|
+
for (const segment of [
|
|
69
|
+
'projects',
|
|
70
|
+
resident.projectId,
|
|
71
|
+
'cli',
|
|
72
|
+
'residents',
|
|
73
|
+
resident.agentKey,
|
|
74
|
+
'runner',
|
|
75
|
+
'revisions',
|
|
76
|
+
]) {
|
|
77
|
+
current = join(current, segment);
|
|
78
|
+
if (!realDirectory(current))
|
|
79
|
+
return [];
|
|
80
|
+
}
|
|
81
|
+
const numbers = [];
|
|
82
|
+
for (const entry of readdirSync(paths.revisions, { withFileTypes: true })) {
|
|
83
|
+
// Publication scratch names never establish ownership, even after a crash.
|
|
84
|
+
if (/^[1-9][0-9]{0,15}\.json\.candidate\.[0-9a-f-]+$/u.test(entry.name))
|
|
85
|
+
continue;
|
|
86
|
+
const match = REVISION_NAME.exec(entry.name);
|
|
87
|
+
const revision = match ? Number(match[1]) : Number.NaN;
|
|
88
|
+
if (!integer(revision, 1) || !entry.isFile() || entry.isSymbolicLink()) {
|
|
89
|
+
throw new Error(`Invalid resident runner revision entry: ${join(paths.revisions, entry.name)}`);
|
|
90
|
+
}
|
|
91
|
+
numbers.push(revision);
|
|
92
|
+
}
|
|
93
|
+
return numbers.sort((left, right) => right - left);
|
|
94
|
+
}
|
|
95
|
+
function checked(resident, raw, revision) {
|
|
96
|
+
if (raw === null || typeof raw !== 'object' || Array.isArray(raw)) {
|
|
97
|
+
throw new Error('Resident runner record must be an object.');
|
|
98
|
+
}
|
|
99
|
+
const value = raw;
|
|
100
|
+
if (Object.keys(value).length !== FIELDS.length || FIELDS.some((field) => !(field in value))) {
|
|
101
|
+
throw new Error('Resident runner record has missing or unsupported fields.');
|
|
102
|
+
}
|
|
103
|
+
if (value.version !== 1 ||
|
|
104
|
+
value.revision !== revision ||
|
|
105
|
+
!integer(value.revision, 1) ||
|
|
106
|
+
typeof value.instanceId !== 'string' ||
|
|
107
|
+
!UUID.test(value.instanceId) ||
|
|
108
|
+
value.tenantId !== resident.tenantId ||
|
|
109
|
+
value.projectId !== resident.projectId ||
|
|
110
|
+
value.agentKey !== resident.agentKey ||
|
|
111
|
+
value.cwd !== resident.cwd ||
|
|
112
|
+
(value.mode !== 'foreground' && value.mode !== 'background') ||
|
|
113
|
+
!['reserved', 'running', 'stopped', 'released'].includes(String(value.phase)) ||
|
|
114
|
+
!integer(value.reservedAt, 0) ||
|
|
115
|
+
!integer(value.maxSteps, 1) ||
|
|
116
|
+
!integer(value.pauseGeneration, 0) ||
|
|
117
|
+
(value.pid !== null && !integer(value.pid, 1)) ||
|
|
118
|
+
(value.port !== null && (!integer(value.port, 1) || value.port > 65_535)) ||
|
|
119
|
+
typeof value.token !== 'string' ||
|
|
120
|
+
!/^[0-9a-f]{64}$/u.test(value.token)) {
|
|
121
|
+
throw new Error('Resident runner version, revision, scope or ownership metadata is invalid.');
|
|
122
|
+
}
|
|
123
|
+
const terminal = value.phase === 'stopped' || value.phase === 'released';
|
|
124
|
+
if ((terminal
|
|
125
|
+
? !integer(value.endedAt, 0) ||
|
|
126
|
+
typeof value.outcome !== 'string' ||
|
|
127
|
+
!value.outcome.trim() ||
|
|
128
|
+
value.outcome.length > 8_000
|
|
129
|
+
: value.endedAt !== null || value.outcome !== null) ||
|
|
130
|
+
(value.phase === 'reserved' && (value.pid !== null || value.port !== null)) ||
|
|
131
|
+
(value.phase === 'running' && value.pid === null) ||
|
|
132
|
+
(value.pid === null && value.port !== null) ||
|
|
133
|
+
(value.mode === 'background' && value.pid !== null && value.port === null)) {
|
|
134
|
+
throw new Error('Resident runner phase and process metadata disagree.');
|
|
135
|
+
}
|
|
136
|
+
return Object.freeze(value);
|
|
137
|
+
}
|
|
138
|
+
function readRevision(resident, revision) {
|
|
139
|
+
const path = join(location(resident).revisions, `${revision}.json`);
|
|
140
|
+
try {
|
|
141
|
+
const entry = lstatSync(path);
|
|
142
|
+
if (!entry.isFile() || entry.isSymbolicLink() || entry.size > 64 * 1024) {
|
|
143
|
+
throw new Error('expected a bounded regular file without a symbolic link');
|
|
144
|
+
}
|
|
145
|
+
return checked(resident, JSON.parse(readFileSync(path, 'utf8')), revision);
|
|
146
|
+
}
|
|
147
|
+
catch (error) {
|
|
148
|
+
// JSON.parse diagnostics can quote private record bytes, including the
|
|
149
|
+
// control token. Keep filesystem/schema details, never parser excerpts.
|
|
150
|
+
const detail = error instanceof SyntaxError
|
|
151
|
+
? 'invalid JSON'
|
|
152
|
+
: error instanceof Error
|
|
153
|
+
? error.message
|
|
154
|
+
: 'unknown read failure';
|
|
155
|
+
throw new Error(`Cannot read resident runner revision ${path}: ${detail}. Refusing ownership recovery from damaged state.`);
|
|
156
|
+
}
|
|
157
|
+
}
|
|
158
|
+
/** An absent runner is a read-only result, never an instruction to initialize it. */
|
|
159
|
+
export function readRunner(resident) {
|
|
160
|
+
const head = revisions(resident)[0];
|
|
161
|
+
return head === undefined ? null : readRevision(resident, head);
|
|
162
|
+
}
|
|
163
|
+
/** The original runner's final evidence remains visible after a successor starts. */
|
|
164
|
+
export function readRunnerInstance(resident, instanceId) {
|
|
165
|
+
if (!UUID.test(instanceId))
|
|
166
|
+
throw new Error('Invalid resident runner instance ID.');
|
|
167
|
+
for (const revision of revisions(resident)) {
|
|
168
|
+
const record = readRevision(resident, revision);
|
|
169
|
+
if (record.instanceId === instanceId)
|
|
170
|
+
return record;
|
|
171
|
+
}
|
|
172
|
+
return null;
|
|
173
|
+
}
|
|
174
|
+
function publish(resident, expected, propose) {
|
|
175
|
+
const current = readRunner(resident);
|
|
176
|
+
if (!isDeepStrictEqual(current, expected))
|
|
177
|
+
throw new ResidentConflictError();
|
|
178
|
+
const next = (current?.revision ?? 0) + 1;
|
|
179
|
+
if (!integer(next, 1))
|
|
180
|
+
throw new Error('Resident runner revision overflow.');
|
|
181
|
+
const record = checked(resident, propose(next), next);
|
|
182
|
+
const paths = location(resident);
|
|
183
|
+
if (!realDirectory(paths.base))
|
|
184
|
+
throw new Error('Resident binding directory is missing.');
|
|
185
|
+
const runner = ensurePrivateStateDirectory(paths.base, 'runner');
|
|
186
|
+
const directory = ensurePrivateStateDirectory(runner, 'revisions');
|
|
187
|
+
publishPrivateJsonIfAbsent(join(directory, `${next}.json`), record);
|
|
188
|
+
// The helper reports EEXIST by preserving the winner. Equality proves whose
|
|
189
|
+
// complete proposal was published; never retry a stale operation on that owner.
|
|
190
|
+
if (!isDeepStrictEqual(readRevision(resident, next), record))
|
|
191
|
+
throw new ResidentConflictError();
|
|
192
|
+
return record;
|
|
193
|
+
}
|
|
194
|
+
/** Reserve one explicitly authorized invocation; an occupied owner is never stolen. */
|
|
195
|
+
export function reserveRunner(resident, options) {
|
|
196
|
+
if ((options.mode !== 'foreground' && options.mode !== 'background') ||
|
|
197
|
+
!integer(options.maxSteps, 1) ||
|
|
198
|
+
!integer(options.pauseGeneration, 0)) {
|
|
199
|
+
throw new Error('Invalid resident runner invocation limits or mode.');
|
|
200
|
+
}
|
|
201
|
+
const current = readRunner(resident);
|
|
202
|
+
if (current && current.phase !== 'stopped' && current.phase !== 'released') {
|
|
203
|
+
throw new ResidentConflictError();
|
|
204
|
+
}
|
|
205
|
+
return publish(resident, current, (revision) => ({
|
|
206
|
+
version: 1,
|
|
207
|
+
revision,
|
|
208
|
+
instanceId: randomUUID(),
|
|
209
|
+
tenantId: resident.tenantId,
|
|
210
|
+
projectId: resident.projectId,
|
|
211
|
+
agentKey: resident.agentKey,
|
|
212
|
+
cwd: resident.cwd,
|
|
213
|
+
mode: options.mode,
|
|
214
|
+
phase: 'reserved',
|
|
215
|
+
reservedAt: Date.now(),
|
|
216
|
+
maxSteps: options.maxSteps,
|
|
217
|
+
pauseGeneration: options.pauseGeneration,
|
|
218
|
+
pid: null,
|
|
219
|
+
port: null,
|
|
220
|
+
token: randomBytes(32).toString('hex'),
|
|
221
|
+
endedAt: null,
|
|
222
|
+
outcome: null,
|
|
223
|
+
}));
|
|
224
|
+
}
|
|
225
|
+
export function attachRunning(resident, expected, process) {
|
|
226
|
+
if (expected.phase !== 'reserved')
|
|
227
|
+
throw new ResidentConflictError();
|
|
228
|
+
return publish(resident, expected, (revision) => ({
|
|
229
|
+
...expected,
|
|
230
|
+
revision,
|
|
231
|
+
phase: 'running',
|
|
232
|
+
pid: process.pid,
|
|
233
|
+
port: process.port,
|
|
234
|
+
}));
|
|
235
|
+
}
|
|
236
|
+
/** Publish only after the executor and its controls have drained. */
|
|
237
|
+
export function finishRunner(resident, expected, outcome) {
|
|
238
|
+
if (expected.phase !== 'reserved' && expected.phase !== 'running') {
|
|
239
|
+
throw new ResidentConflictError();
|
|
240
|
+
}
|
|
241
|
+
return publish(resident, expected, (revision) => ({
|
|
242
|
+
...expected,
|
|
243
|
+
revision,
|
|
244
|
+
phase: 'stopped',
|
|
245
|
+
endedAt: Date.now(),
|
|
246
|
+
outcome,
|
|
247
|
+
}));
|
|
248
|
+
}
|
|
249
|
+
/** Explicit operator recovery of an exact owner; this is never proof of drainage. */
|
|
250
|
+
export function releaseRunner(resident, expected) {
|
|
251
|
+
if (expected.phase !== 'reserved' && expected.phase !== 'running') {
|
|
252
|
+
throw new ResidentConflictError();
|
|
253
|
+
}
|
|
254
|
+
return publish(resident, expected, (revision) => ({
|
|
255
|
+
...expected,
|
|
256
|
+
revision,
|
|
257
|
+
phase: 'released',
|
|
258
|
+
endedAt: Date.now(),
|
|
259
|
+
outcome: 'Operator explicitly released this owner after inspecting stopped executors.',
|
|
260
|
+
}));
|
|
261
|
+
}
|
|
262
|
+
/** Status reports retain ownership evidence without disclosing the control nonce. */
|
|
263
|
+
export function publicRunner(record) {
|
|
264
|
+
return {
|
|
265
|
+
version: record.version,
|
|
266
|
+
revision: record.revision,
|
|
267
|
+
instanceId: record.instanceId,
|
|
268
|
+
tenantId: record.tenantId,
|
|
269
|
+
projectId: record.projectId,
|
|
270
|
+
agentKey: record.agentKey,
|
|
271
|
+
cwd: record.cwd,
|
|
272
|
+
mode: record.mode,
|
|
273
|
+
phase: record.phase,
|
|
274
|
+
reservedAt: record.reservedAt,
|
|
275
|
+
maxSteps: record.maxSteps,
|
|
276
|
+
pauseGeneration: record.pauseGeneration,
|
|
277
|
+
pid: record.pid,
|
|
278
|
+
port: record.port,
|
|
279
|
+
endedAt: record.endedAt,
|
|
280
|
+
outcome: record.outcome,
|
|
281
|
+
};
|
|
282
|
+
}
|
|
283
|
+
//# sourceMappingURL=runner-store.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"runner-store.js","sourceRoot":"","sources":["../../../src/integrations/resident/runner-store.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"runner-worker.d.ts","sourceRoot":"","sources":["../../../src/integrations/resident/runner-worker.ts"],"names":[],"mappings":""}
|
|
@@ -0,0 +1,143 @@
|
|
|
1
|
+
import { realpath } from 'node:fs/promises';
|
|
2
|
+
import { openSessions } from '../sessions/store.js';
|
|
3
|
+
import { runOwnedResident } from './owned-runner.js';
|
|
4
|
+
import { finishRunner, readRunner } from './runner-store.js';
|
|
5
|
+
import { createResidentSessionStep } from './session-step.js';
|
|
6
|
+
import { lookupResident } from './storage.js';
|
|
7
|
+
// Internal child entrypoint. Launch parameters arrive only through the parent's
|
|
8
|
+
// IPC channel; credentials and resolved configuration are never copied to disk.
|
|
9
|
+
async function main() {
|
|
10
|
+
if (!process.send)
|
|
11
|
+
throw new Error('Resident workers must be started through namzu resident start.');
|
|
12
|
+
const controller = new AbortController();
|
|
13
|
+
let handedOff = false;
|
|
14
|
+
const stop = () => controller.abort(new Error('Resident worker interrupted before or during execution.'));
|
|
15
|
+
const disconnected = () => {
|
|
16
|
+
if (!handedOff)
|
|
17
|
+
stop();
|
|
18
|
+
};
|
|
19
|
+
process.on('disconnect', disconnected);
|
|
20
|
+
process.once('SIGINT', stop);
|
|
21
|
+
process.once('SIGTERM', stop);
|
|
22
|
+
let resident = null;
|
|
23
|
+
let owner = null;
|
|
24
|
+
let lifecycleStarted = false;
|
|
25
|
+
try {
|
|
26
|
+
const launch = await new Promise((resolve, reject) => {
|
|
27
|
+
const timer = setTimeout(() => reject(new Error('Resident startup parameters did not arrive.')), 15_000);
|
|
28
|
+
process.once('message', (message) => {
|
|
29
|
+
clearTimeout(timer);
|
|
30
|
+
if (!message ||
|
|
31
|
+
typeof message !== 'object' ||
|
|
32
|
+
message.version !== 1) {
|
|
33
|
+
reject(new Error('Invalid resident worker launch.'));
|
|
34
|
+
return;
|
|
35
|
+
}
|
|
36
|
+
resolve(message);
|
|
37
|
+
});
|
|
38
|
+
});
|
|
39
|
+
controller.signal.throwIfAborted();
|
|
40
|
+
resident = await lookupResident(launch.cwd, launch.agentKey);
|
|
41
|
+
if (!resident || resident.cwd !== launch.cwd || (await realpath(launch.cwd)) !== launch.cwd)
|
|
42
|
+
throw new Error('Resident execution directory changed before worker startup.');
|
|
43
|
+
const candidate = readRunner(resident);
|
|
44
|
+
if (candidate?.instanceId !== launch.instanceId || candidate.phase !== 'reserved')
|
|
45
|
+
throw new Error('Resident worker does not own this startup reservation.');
|
|
46
|
+
owner = candidate;
|
|
47
|
+
const sessions = await openSessions(resident.cwd);
|
|
48
|
+
if (sessions.projectId !== resident.projectId || sessions.tenantId !== resident.tenantId)
|
|
49
|
+
throw new Error('Resident project or tenant changed before worker startup.');
|
|
50
|
+
const ctx = {
|
|
51
|
+
config: launch.config,
|
|
52
|
+
formatter: { name: 'json', print() { }, info() { }, error() { } },
|
|
53
|
+
};
|
|
54
|
+
const step = createResidentSessionStep({
|
|
55
|
+
ctx,
|
|
56
|
+
cwd: resident.cwd,
|
|
57
|
+
sessions,
|
|
58
|
+
flags: launch.flags,
|
|
59
|
+
toolLoading: launch.toolLoading,
|
|
60
|
+
contextProfile: launch.contextProfile,
|
|
61
|
+
artifactsRoot: resident.artifactsRoot,
|
|
62
|
+
});
|
|
63
|
+
lifecycleStarted = true;
|
|
64
|
+
const result = await runOwnedResident({
|
|
65
|
+
resident,
|
|
66
|
+
owner,
|
|
67
|
+
step,
|
|
68
|
+
signal: controller.signal,
|
|
69
|
+
keepAlive: true,
|
|
70
|
+
maxIdleMs: launch.maxIdleMs,
|
|
71
|
+
ready: async (ready, signal) => {
|
|
72
|
+
await new Promise((resolve, reject) => {
|
|
73
|
+
const cleanup = () => {
|
|
74
|
+
clearTimeout(timer);
|
|
75
|
+
process.removeListener('message', go);
|
|
76
|
+
signal.removeEventListener('abort', aborted);
|
|
77
|
+
};
|
|
78
|
+
const aborted = () => {
|
|
79
|
+
cleanup();
|
|
80
|
+
reject(signal.reason);
|
|
81
|
+
};
|
|
82
|
+
const go = (message) => {
|
|
83
|
+
if (message &&
|
|
84
|
+
typeof message === 'object' &&
|
|
85
|
+
message.kind === 'go' &&
|
|
86
|
+
message.instanceId === ready.instanceId) {
|
|
87
|
+
handedOff = true;
|
|
88
|
+
cleanup();
|
|
89
|
+
resolve();
|
|
90
|
+
}
|
|
91
|
+
};
|
|
92
|
+
const timer = setTimeout(() => {
|
|
93
|
+
cleanup();
|
|
94
|
+
reject(new Error('Resident startup handoff timed out.'));
|
|
95
|
+
}, 15_000);
|
|
96
|
+
process.on('message', go);
|
|
97
|
+
signal.addEventListener('abort', aborted, { once: true });
|
|
98
|
+
if (signal.aborted) {
|
|
99
|
+
aborted();
|
|
100
|
+
return;
|
|
101
|
+
}
|
|
102
|
+
process.send?.({ kind: 'ready', instanceId: ready.instanceId }, (error) => {
|
|
103
|
+
if (error) {
|
|
104
|
+
cleanup();
|
|
105
|
+
reject(error);
|
|
106
|
+
}
|
|
107
|
+
});
|
|
108
|
+
});
|
|
109
|
+
},
|
|
110
|
+
});
|
|
111
|
+
return ['unresolved', 'contended'].includes(result.status)
|
|
112
|
+
? 1
|
|
113
|
+
: result.status === 'cancelled'
|
|
114
|
+
? 130
|
|
115
|
+
: 0;
|
|
116
|
+
}
|
|
117
|
+
catch (error) {
|
|
118
|
+
if (!lifecycleStarted && resident && owner?.phase === 'reserved') {
|
|
119
|
+
try {
|
|
120
|
+
finishRunner(resident, owner, 'startup_failed');
|
|
121
|
+
}
|
|
122
|
+
catch {
|
|
123
|
+
/* A successor is never released by this worker. */
|
|
124
|
+
}
|
|
125
|
+
}
|
|
126
|
+
if (process.connected)
|
|
127
|
+
await new Promise((resolve) => {
|
|
128
|
+
process.send?.({
|
|
129
|
+
kind: 'error',
|
|
130
|
+
instanceId: owner?.instanceId,
|
|
131
|
+
message: error instanceof Error ? error.message : String(error),
|
|
132
|
+
}, () => resolve());
|
|
133
|
+
});
|
|
134
|
+
return 1;
|
|
135
|
+
}
|
|
136
|
+
finally {
|
|
137
|
+
process.removeListener('disconnect', disconnected);
|
|
138
|
+
process.removeListener('SIGINT', stop);
|
|
139
|
+
process.removeListener('SIGTERM', stop);
|
|
140
|
+
}
|
|
141
|
+
}
|
|
142
|
+
void main().then((code) => process.exit(code), () => process.exit(1));
|
|
143
|
+
//# sourceMappingURL=runner-worker.js.map
|