@farmslot/agent-runtime 0.15.1 → 0.17.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 +10 -0
- package/README.md +1 -1
- package/dist/native/acp-rpc.d.ts +2 -1
- package/dist/native/acp-rpc.d.ts.map +1 -1
- package/dist/native/acp-rpc.js +2 -2
- package/dist/native/acp-rpc.js.map +1 -1
- package/dist/native/acp.js +2 -2
- package/dist/native/acp.js.map +1 -1
- package/dist/native/claude.js +2 -2
- package/dist/native/claude.js.map +1 -1
- package/dist/native/client.d.ts +1 -0
- package/dist/native/client.d.ts.map +1 -1
- package/dist/native/client.js +10 -1
- package/dist/native/client.js.map +1 -1
- package/dist/native/codex.js +2 -2
- package/dist/native/codex.js.map +1 -1
- package/dist/native/host.js +4 -1
- package/dist/native/host.js.map +1 -1
- package/dist/native/index.d.ts +1 -1
- package/dist/native/index.d.ts.map +1 -1
- package/dist/native/index.js +1 -1
- package/dist/native/index.js.map +1 -1
- package/dist/native/ipc.d.ts +3 -2
- package/dist/native/ipc.d.ts.map +1 -1
- package/dist/native/ipc.js +5 -2
- package/dist/native/ipc.js.map +1 -1
- package/dist/native/manager.d.ts +9 -0
- package/dist/native/manager.d.ts.map +1 -1
- package/dist/native/manager.js +289 -18
- package/dist/native/manager.js.map +1 -1
- package/dist/native/process-tree.d.ts +2 -3
- package/dist/native/process-tree.d.ts.map +1 -1
- package/dist/native/process-tree.js +20 -4
- package/dist/native/process-tree.js.map +1 -1
- package/dist/native/process.d.ts +7 -1
- package/dist/native/process.d.ts.map +1 -1
- package/dist/native/process.js +13 -3
- package/dist/native/process.js.map +1 -1
- package/dist/native/stderr.d.ts +15 -0
- package/dist/native/stderr.d.ts.map +1 -0
- package/dist/native/stderr.js +65 -0
- package/dist/native/stderr.js.map +1 -0
- package/dist/native/storage.d.ts +3 -0
- package/dist/native/storage.d.ts.map +1 -1
- package/dist/native/storage.js +37 -0
- package/dist/native/storage.js.map +1 -1
- package/dist/native/supervisor.js +1 -0
- package/dist/native/supervisor.js.map +1 -1
- package/dist/native/types.d.ts +2 -0
- package/dist/native/types.d.ts.map +1 -1
- package/dist/native/worker-history.d.ts +11 -5
- package/dist/native/worker-history.d.ts.map +1 -1
- package/dist/native/worker-history.js +26 -4
- package/dist/native/worker-history.js.map +1 -1
- package/dist/native/worker-launch.d.ts +1 -0
- package/dist/native/worker-launch.d.ts.map +1 -1
- package/dist/native/worker-launch.js +2 -0
- package/dist/native/worker-launch.js.map +1 -1
- package/dist/native/worker-service.d.ts.map +1 -1
- package/dist/native/worker-service.js +4 -1
- package/dist/native/worker-service.js.map +1 -1
- package/dist/task-init/write.d.ts +2 -0
- package/dist/task-init/write.d.ts.map +1 -1
- package/dist/task-init/write.js +65 -9
- package/dist/task-init/write.js.map +1 -1
- package/package.json +2 -2
package/dist/native/ipc.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"ipc.js","sourceRoot":"","sources":["../../src/native/ipc.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,EAAE,eAAe,EAAE,MAAM,aAAa,CAAC;AAC1D,OAAO,EAAE,OAAO,EAAE,MAAM,UAAU,CAAC;AACnC,OAAO,EAAE,IAAI,EAAE,MAAM,WAAW,CAAC;AAQjC,OAAO,EACL,wBAAwB,EACxB,oBAAoB,EACpB,mBAAmB,EACnB,oBAAoB,EACpB,uBAAuB,EACvB,kBAAkB,EAClB,qBAAqB,EACrB,oBAAoB,EACpB,kBAAkB,EAClB,sBAAsB,GAGvB,MAAM,oBAAoB,CAAC;
|
|
1
|
+
{"version":3,"file":"ipc.js","sourceRoot":"","sources":["../../src/native/ipc.ts"],"names":[],"mappings":"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"}
|
package/dist/native/manager.d.ts
CHANGED
|
@@ -21,11 +21,16 @@ export declare class NativeSessionManager {
|
|
|
21
21
|
assertWorkerLease(owner: string, id: string, generation: string, leaseId: string, closing?: boolean): void;
|
|
22
22
|
closeWorker(owner: string, id: string, generation: string, leaseId: string): Promise<NativeSessionInfo>;
|
|
23
23
|
private assertWorkerNotCancelled;
|
|
24
|
+
private recordedLeaderAlive;
|
|
25
|
+
private recordedGroupAlive;
|
|
26
|
+
/** Explicit operator attestation covers legacy journals without descendant evidence. */
|
|
27
|
+
confirmWorkerStopped(owner: string, id: string, generation: string, leaseId: string): NativeSessionInfo;
|
|
24
28
|
private resumeCancellationPath;
|
|
25
29
|
cancelWorker(owner: string, id: string, leaseId: string, generation?: string, sourceLeaseId?: string, resumeCommandId?: string): Promise<NativeWorkerCancelResult>;
|
|
26
30
|
transferWorker(owner: string, id: string, generation: string, leaseId: string, launch: NativeWorkerLaunch): NativeSessionInfo;
|
|
27
31
|
private append;
|
|
28
32
|
private owned;
|
|
33
|
+
private reconcileMissingProcess;
|
|
29
34
|
private snapshot;
|
|
30
35
|
list(owner: string): NativeSessionInfo[];
|
|
31
36
|
read(owner: string, id: string, after?: number, limit?: number): {
|
|
@@ -34,11 +39,13 @@ export declare class NativeSessionManager {
|
|
|
34
39
|
cursor: number;
|
|
35
40
|
hasMore: boolean;
|
|
36
41
|
commands: {
|
|
42
|
+
leaseId?: string;
|
|
37
43
|
generation: string;
|
|
38
44
|
commandId: string;
|
|
39
45
|
state: import("@farmslot/protocol").NativeCommandState;
|
|
40
46
|
submitted: boolean;
|
|
41
47
|
accepted: boolean;
|
|
48
|
+
queued?: boolean;
|
|
42
49
|
outcome?: "completed" | "failed" | "interrupted";
|
|
43
50
|
}[];
|
|
44
51
|
pendingRequests: NativeSessionEvent[];
|
|
@@ -54,6 +61,8 @@ export declare class NativeSessionManager {
|
|
|
54
61
|
};
|
|
55
62
|
private assertAccountCurrent;
|
|
56
63
|
send(owner: string, id: string, commandId: string, text: string): Promise<NativeSessionSendResult>;
|
|
64
|
+
private submitCommand;
|
|
65
|
+
private scheduleQueuedInput;
|
|
57
66
|
respond(owner: string, id: string, requestId: string, response: NativeSessionResponse): Promise<void>;
|
|
58
67
|
interrupt(owner: string, id: string): Promise<void>;
|
|
59
68
|
close(owner: string, id: string): Promise<void>;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"manager.d.ts","sourceRoot":"","sources":["../../src/native/manager.ts"],"names":[],"mappings":"AAgBA,OAAO,KAAK,EACV,oBAAoB,EAEpB,yBAAyB,EACzB,yBAAyB,EACzB,kBAAkB,EAClB,iBAAiB,EACjB,qBAAqB,EACrB,uBAAuB,EACxB,MAAM,oBAAoB,CAAC;
|
|
1
|
+
{"version":3,"file":"manager.d.ts","sourceRoot":"","sources":["../../src/native/manager.ts"],"names":[],"mappings":"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"}
|
package/dist/native/manager.js
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { execFile } from 'node:child_process';
|
|
1
|
+
import { execFile, execFileSync } from 'node:child_process';
|
|
2
2
|
import { createHash, randomUUID } from 'node:crypto';
|
|
3
3
|
import { closeSync, constants, existsSync, fsyncSync, openSync, readdirSync, writeFileSync, } from 'node:fs';
|
|
4
4
|
import { access, realpath, stat } from 'node:fs/promises';
|
|
@@ -8,7 +8,7 @@ import { promisify } from 'node:util';
|
|
|
8
8
|
import { assertNativeProfileCurrent, nativeProfileEnvironment, requireNativeProfile, } from './account-profiles.js';
|
|
9
9
|
import { nativeRunnerDefinitions as adapters } from './registry.js';
|
|
10
10
|
import { hostReviewSandboxAvailable, reviewProcessSandbox } from './review-sandbox.js';
|
|
11
|
-
import { durableWrite, privateDirectory, readJournal, readJson } from './storage.js';
|
|
11
|
+
import { alive, durableWrite, matchesProcess, privateDirectory, processGroupAlive, processIdentityAlive, readJournal, readJson, } from './storage.js';
|
|
12
12
|
import { NativeWorkerHistory } from './worker-history.js';
|
|
13
13
|
import { nativeWorkerEnvironment, nativeWorkerLaunchDigest, validateNativeWorkerFilesystemPolicy, } from './worker-launch.js';
|
|
14
14
|
const exec = promisify(execFile);
|
|
@@ -121,14 +121,24 @@ export class NativeSessionManager {
|
|
|
121
121
|
continue;
|
|
122
122
|
let info;
|
|
123
123
|
let context;
|
|
124
|
+
let processes;
|
|
124
125
|
let pending = [];
|
|
125
126
|
const commands = new Map();
|
|
126
127
|
const events = [];
|
|
127
128
|
const workerHistory = new NativeWorkerHistory();
|
|
128
129
|
for (const entry of entries) {
|
|
129
130
|
workerHistory.observe(entry);
|
|
131
|
+
if (entry.info && info && entry.info.generation !== info.generation)
|
|
132
|
+
processes = undefined;
|
|
130
133
|
info = entry.info ?? info;
|
|
131
134
|
context = entry.context ?? context;
|
|
135
|
+
processes = entry.processes ?? processes;
|
|
136
|
+
if (entry.processesAdded) {
|
|
137
|
+
const identities = new Map((processes ?? []).map((process) => [`${process.pid}:${process.identity}`, process]));
|
|
138
|
+
for (const process of entry.processesAdded)
|
|
139
|
+
identities.set(`${process.pid}:${process.identity}`, process);
|
|
140
|
+
processes = [...identities.values()];
|
|
141
|
+
}
|
|
132
142
|
pending = entry.pending ?? pending;
|
|
133
143
|
for (const command of entry.commands ?? [])
|
|
134
144
|
commands.set(command.commandId, command);
|
|
@@ -143,6 +153,7 @@ export class NativeSessionManager {
|
|
|
143
153
|
workerHistory,
|
|
144
154
|
info,
|
|
145
155
|
context,
|
|
156
|
+
processes,
|
|
146
157
|
commands,
|
|
147
158
|
events,
|
|
148
159
|
pendingRequests: new Map(pending.map((event) => [event.request.id, event])),
|
|
@@ -151,6 +162,7 @@ export class NativeSessionManager {
|
|
|
151
162
|
this.persisted.set(record, {
|
|
152
163
|
info: JSON.stringify(info),
|
|
153
164
|
context: JSON.stringify(context),
|
|
165
|
+
processes,
|
|
154
166
|
pending: JSON.stringify(pending),
|
|
155
167
|
commands: new Map([...commands].map(([id, command]) => [id, JSON.stringify(command)])),
|
|
156
168
|
});
|
|
@@ -160,7 +172,7 @@ export class NativeSessionManager {
|
|
|
160
172
|
record.info.recovery =
|
|
161
173
|
'Native host stopped. Verify the old process group is stopped, then explicitly resume the saved native identity.';
|
|
162
174
|
for (const command of record.commands.values())
|
|
163
|
-
if (command.state === 'pending')
|
|
175
|
+
if (command.state === 'pending' && !command.queued)
|
|
164
176
|
command.state = 'unknown';
|
|
165
177
|
this.append(record, {
|
|
166
178
|
type: 'session.closed',
|
|
@@ -175,15 +187,24 @@ export class NativeSessionManager {
|
|
|
175
187
|
const info = JSON.stringify(record.info);
|
|
176
188
|
const context = JSON.stringify(record.context);
|
|
177
189
|
const pending = JSON.stringify([...record.pendingRequests.values()]);
|
|
190
|
+
const processes = record.processes;
|
|
178
191
|
const commands = [...record.commands.values()].filter((command) => previous.commands.get(command.commandId) !== JSON.stringify(command));
|
|
179
192
|
const entry = {
|
|
193
|
+
...(processes !== previous.processes && processes
|
|
194
|
+
? { processesAdded: processes.slice(previous.processes?.length ?? 0) }
|
|
195
|
+
: {}),
|
|
180
196
|
...(info !== previous.info ? { info: record.info } : {}),
|
|
181
197
|
...(context !== previous.context ? { context: record.context } : {}),
|
|
182
198
|
...(pending !== previous.pending ? { pending: [...record.pendingRequests.values()] } : {}),
|
|
183
199
|
...(commands.length ? { commands } : {}),
|
|
184
200
|
event,
|
|
185
201
|
};
|
|
186
|
-
if (!event &&
|
|
202
|
+
if (!event &&
|
|
203
|
+
!entry.info &&
|
|
204
|
+
!entry.context &&
|
|
205
|
+
!entry.pending &&
|
|
206
|
+
!entry.commands &&
|
|
207
|
+
!entry.processesAdded)
|
|
187
208
|
return;
|
|
188
209
|
const fd = openSync(join(this.root, `${record.info.id}.journal`), 'a', 0o600);
|
|
189
210
|
try {
|
|
@@ -202,7 +223,7 @@ export class NativeSessionManager {
|
|
|
202
223
|
}
|
|
203
224
|
for (const command of commands)
|
|
204
225
|
previous.commands.set(command.commandId, JSON.stringify(command));
|
|
205
|
-
this.persisted.set(record, { info, context, pending, commands: previous.commands });
|
|
226
|
+
this.persisted.set(record, { info, context, pending, processes, commands: previous.commands });
|
|
206
227
|
record.workerHistory.observe(entry);
|
|
207
228
|
}
|
|
208
229
|
create(owner, params, workerLaunch) {
|
|
@@ -261,6 +282,7 @@ export class NativeSessionManager {
|
|
|
261
282
|
record.info.runner === params.runner);
|
|
262
283
|
if (!previous || previous.info.ownerPrincipalId !== ownerPrincipalId)
|
|
263
284
|
throw new Error('Resume requires an owned native session');
|
|
285
|
+
this.reconcileMissingProcess(previous);
|
|
264
286
|
const unavailable = transport.adapter.resumeUnavailableReason?.(previous.info.version);
|
|
265
287
|
if (unavailable)
|
|
266
288
|
throw new Error(unavailable);
|
|
@@ -391,6 +413,16 @@ export class NativeSessionManager {
|
|
|
391
413
|
sending: false,
|
|
392
414
|
};
|
|
393
415
|
this.sessions.set(info.id, record);
|
|
416
|
+
for (const command of record.commands.values()) {
|
|
417
|
+
if (!command.queued)
|
|
418
|
+
continue;
|
|
419
|
+
if (command.leaseId !== info.workerLeaseId) {
|
|
420
|
+
command.queued = false;
|
|
421
|
+
command.state = 'failed';
|
|
422
|
+
}
|
|
423
|
+
else
|
|
424
|
+
command.generation = info.generation;
|
|
425
|
+
}
|
|
394
426
|
if (previous) {
|
|
395
427
|
const saved = this.persisted.get(previous);
|
|
396
428
|
if (saved)
|
|
@@ -419,6 +451,19 @@ export class NativeSessionManager {
|
|
|
419
451
|
info.processStopped = false;
|
|
420
452
|
this.persist(record);
|
|
421
453
|
},
|
|
454
|
+
onProcessSnapshot: (snapshot) => {
|
|
455
|
+
const known = new Map((record.processes ?? []).map((process) => [
|
|
456
|
+
`${process.pid}:${process.identity}`,
|
|
457
|
+
process,
|
|
458
|
+
]));
|
|
459
|
+
const count = known.size;
|
|
460
|
+
for (const process of snapshot)
|
|
461
|
+
known.set(`${process.pid}:${process.identity}`, process);
|
|
462
|
+
if (record.processes === undefined || known.size !== count) {
|
|
463
|
+
record.processes = [...known.values()];
|
|
464
|
+
this.persist(record);
|
|
465
|
+
}
|
|
466
|
+
},
|
|
422
467
|
executable: resolved.executable,
|
|
423
468
|
env: nativeEnvironment(resolved.executable, {
|
|
424
469
|
...environment,
|
|
@@ -439,6 +484,7 @@ export class NativeSessionManager {
|
|
|
439
484
|
if (info.state === 'starting')
|
|
440
485
|
info.state = 'idle';
|
|
441
486
|
this.persist(record);
|
|
487
|
+
this.scheduleQueuedInput(record);
|
|
442
488
|
return this.snapshot(record);
|
|
443
489
|
}
|
|
444
490
|
catch (error) {
|
|
@@ -498,6 +544,94 @@ export class NativeSessionManager {
|
|
|
498
544
|
if (existsSync(join(this.root, 'cancelled-workers', `${id}.json`)))
|
|
499
545
|
throw new Error('Native worker reservation was cancelled before launch');
|
|
500
546
|
}
|
|
547
|
+
recordedLeaderAlive(record) {
|
|
548
|
+
const pid = record.info.processPid;
|
|
549
|
+
if (!pid)
|
|
550
|
+
return false;
|
|
551
|
+
const identity = record.processes?.find((process) => process.pid === pid)?.identity;
|
|
552
|
+
if (identity)
|
|
553
|
+
return processIdentityAlive(pid, identity);
|
|
554
|
+
if (!record.info.processIdentity)
|
|
555
|
+
return alive(pid);
|
|
556
|
+
try {
|
|
557
|
+
return matchesProcess(pid, record.info.processIdentity);
|
|
558
|
+
}
|
|
559
|
+
catch (error) {
|
|
560
|
+
const probe = error;
|
|
561
|
+
// Presence with unreadable identity blocks cleanup without breaking reads.
|
|
562
|
+
if (probe.status === 1 || probe.code === 'EPERM' || probe.code === 'EACCES')
|
|
563
|
+
return true;
|
|
564
|
+
throw error;
|
|
565
|
+
}
|
|
566
|
+
}
|
|
567
|
+
recordedGroupAlive(record) {
|
|
568
|
+
const pid = record.info.processPid;
|
|
569
|
+
if (!pid || !processGroupAlive(pid))
|
|
570
|
+
return false;
|
|
571
|
+
const leader = record.processes?.find((process) => process.pid === pid);
|
|
572
|
+
// A new kernel birth identity proves PID reuse. PID allocation reserves
|
|
573
|
+
// live group/session IDs, so this current group cannot be the old group.
|
|
574
|
+
// A changed argv/environment token alone cannot prove this: exec keeps its PID.
|
|
575
|
+
if (leader && alive(pid) && !processIdentityAlive(pid, leader.identity) && alive(pid))
|
|
576
|
+
return false;
|
|
577
|
+
// Positive attribution to another native generation distinguishes a reused
|
|
578
|
+
// numeric group. Unknown groups still block; neither case receives a signal.
|
|
579
|
+
for (const candidate of this.sessions.values()) {
|
|
580
|
+
if (candidate === record ||
|
|
581
|
+
candidate.info.generation === record.info.generation ||
|
|
582
|
+
candidate.info.processPid !== pid ||
|
|
583
|
+
candidate.info.processStopped ||
|
|
584
|
+
!candidate.info.processIdentity)
|
|
585
|
+
continue;
|
|
586
|
+
try {
|
|
587
|
+
if (!matchesProcess(pid, candidate.info.processIdentity))
|
|
588
|
+
continue;
|
|
589
|
+
const observedGroup = execFileSync('ps', ['-p', String(pid), '-o', 'pgid='], {
|
|
590
|
+
encoding: 'utf8',
|
|
591
|
+
stdio: ['ignore', 'pipe', 'pipe'],
|
|
592
|
+
timeout: 5000,
|
|
593
|
+
});
|
|
594
|
+
if (Number(observedGroup.trim()) === pid &&
|
|
595
|
+
matchesProcess(pid, candidate.info.processIdentity))
|
|
596
|
+
return false;
|
|
597
|
+
}
|
|
598
|
+
catch (error) {
|
|
599
|
+
const probe = error;
|
|
600
|
+
if (probe.status === 1 || probe.code === 'EPERM' || probe.code === 'EACCES')
|
|
601
|
+
continue;
|
|
602
|
+
throw error;
|
|
603
|
+
}
|
|
604
|
+
}
|
|
605
|
+
return true;
|
|
606
|
+
}
|
|
607
|
+
/** Explicit operator attestation covers legacy journals without descendant evidence. */
|
|
608
|
+
confirmWorkerStopped(owner, id, generation, leaseId) {
|
|
609
|
+
this.assertWorkerLease(owner, id, generation, leaseId, true);
|
|
610
|
+
const record = this.owned(owner, id);
|
|
611
|
+
if (record.info.processStopped)
|
|
612
|
+
return this.snapshot(record);
|
|
613
|
+
const pid = record.info.processPid;
|
|
614
|
+
if (!pid ||
|
|
615
|
+
record.adapter ||
|
|
616
|
+
record.startup ||
|
|
617
|
+
!['closed', 'failed'].includes(record.info.state) ||
|
|
618
|
+
this.recordedLeaderAlive(record) ||
|
|
619
|
+
this.recordedGroupAlive(record))
|
|
620
|
+
throw new Error('Stop confirmation requires an absent native process and process group');
|
|
621
|
+
if (record.processes?.some((child) => processIdentityAlive(child.pid, child.identity)))
|
|
622
|
+
throw new Error('An observed native descendant is still alive; stop confirmation is refused');
|
|
623
|
+
this.append(record, {
|
|
624
|
+
type: 'session.closed',
|
|
625
|
+
status: 'failed',
|
|
626
|
+
text: 'Operator confirmed the missing native worker and its descendants are stopped',
|
|
627
|
+
data: {
|
|
628
|
+
processStopped: true,
|
|
629
|
+
processStopReason: 'process-missing-attested',
|
|
630
|
+
error: record.info.error,
|
|
631
|
+
},
|
|
632
|
+
});
|
|
633
|
+
return this.snapshot(record);
|
|
634
|
+
}
|
|
501
635
|
resumeCancellationPath(id, leaseId, commandId) {
|
|
502
636
|
if (!commandId.trim())
|
|
503
637
|
throw new Error('Native recovery command ID is required');
|
|
@@ -606,7 +740,10 @@ export class NativeSessionManager {
|
|
|
606
740
|
const stopped = ['closed', 'failed'].includes(record.info.state) &&
|
|
607
741
|
record.info.processStopped &&
|
|
608
742
|
Boolean(record.info.nativeSessionId);
|
|
609
|
-
if ((record.info.state !== 'idle' && !stopped) ||
|
|
743
|
+
if ((record.info.state !== 'idle' && !stopped) ||
|
|
744
|
+
record.sending ||
|
|
745
|
+
record.pendingRequests.size ||
|
|
746
|
+
[...record.commands.values()].some((command) => command.queued))
|
|
610
747
|
throw new Error('Native worker handoff requires an idle session or a confirmed stopped session with no pending requests');
|
|
611
748
|
record.workerHistory.assertNewLease(launch.leaseId);
|
|
612
749
|
record.info.workerLeaseId = launch.leaseId;
|
|
@@ -651,13 +788,30 @@ export class NativeSessionManager {
|
|
|
651
788
|
if (event.type === 'session.closed') {
|
|
652
789
|
if (event.data?.processStopped === true)
|
|
653
790
|
record.info.processStopped = true;
|
|
791
|
+
if (event.data?.exitCode === null || typeof event.data?.exitCode === 'number')
|
|
792
|
+
record.info.exitCode = event.data.exitCode;
|
|
793
|
+
if (event.data?.signal === null || typeof event.data?.signal === 'string')
|
|
794
|
+
record.info.signal = event.data.signal;
|
|
795
|
+
if (Array.isArray(event.data?.stderrTail))
|
|
796
|
+
record.info.stderrTail = event.data.stderrTail
|
|
797
|
+
.filter((line) => typeof line === 'string')
|
|
798
|
+
.slice(-50);
|
|
799
|
+
if (record.info.processStopped)
|
|
800
|
+
record.info.processStopReason =
|
|
801
|
+
event.data?.processStopReason === 'process-missing-attested'
|
|
802
|
+
? 'process-missing-attested'
|
|
803
|
+
: event.data?.processStopReason === 'process-missing'
|
|
804
|
+
? 'process-missing'
|
|
805
|
+
: 'process-exit';
|
|
654
806
|
record.info.state = event.status === 'failed' ? 'failed' : 'closed';
|
|
807
|
+
if (event.status === 'failed')
|
|
808
|
+
record.info.error = typeof event.data?.error === 'string' ? event.data.error : event.text;
|
|
655
809
|
if (event.status === 'failed')
|
|
656
810
|
record.info.recovery ??= record.info.nativeSessionId
|
|
657
811
|
? 'Native runner stopped. Explicitly resume the saved identity after verifying its process group is stopped.'
|
|
658
812
|
: 'Native runner stopped before its conversation identity was known. Automatic recovery is unavailable.';
|
|
659
813
|
for (const command of record.commands.values())
|
|
660
|
-
if (command.state === 'pending')
|
|
814
|
+
if (command.state === 'pending' && !command.queued)
|
|
661
815
|
command.state = 'unknown';
|
|
662
816
|
record.pendingRequests.clear();
|
|
663
817
|
}
|
|
@@ -679,13 +833,48 @@ export class NativeSessionManager {
|
|
|
679
833
|
}
|
|
680
834
|
}
|
|
681
835
|
this.persist(record, enriched);
|
|
836
|
+
if (event.type === 'turn.completed')
|
|
837
|
+
this.scheduleQueuedInput(record);
|
|
682
838
|
}
|
|
683
839
|
owned(owner, id) {
|
|
684
840
|
const record = this.sessions.get(id);
|
|
685
841
|
if (!record || record.info.ownerPrincipalId !== owner)
|
|
686
842
|
throw new Error('Native session not found for this principal');
|
|
843
|
+
this.reconcileMissingProcess(record);
|
|
687
844
|
return record;
|
|
688
845
|
}
|
|
846
|
+
reconcileMissingProcess(record) {
|
|
847
|
+
const pid = record.info.processPid;
|
|
848
|
+
// A live adapter owns descendant cleanup. A recovered journal has no
|
|
849
|
+
// adapter and needs absence of both the recorded PID and its group.
|
|
850
|
+
if (!pid ||
|
|
851
|
+
record.info.processStopped ||
|
|
852
|
+
record.adapter ||
|
|
853
|
+
record.startup ||
|
|
854
|
+
this.recordedLeaderAlive(record) ||
|
|
855
|
+
this.recordedGroupAlive(record))
|
|
856
|
+
return;
|
|
857
|
+
const recorded = record.processes;
|
|
858
|
+
if (!recorded) {
|
|
859
|
+
record.info.error ??=
|
|
860
|
+
'Native worker process is missing; descendant cleanup evidence is unavailable.';
|
|
861
|
+
this.persist(record);
|
|
862
|
+
return;
|
|
863
|
+
}
|
|
864
|
+
if (recorded.some((child) => processIdentityAlive(child.pid, child.identity)))
|
|
865
|
+
return;
|
|
866
|
+
record.info.processStopped = true;
|
|
867
|
+
record.info.error ??= 'Native worker process is missing; its exit was not observed.';
|
|
868
|
+
this.append(record, {
|
|
869
|
+
type: 'session.closed',
|
|
870
|
+
status: 'failed',
|
|
871
|
+
data: {
|
|
872
|
+
processStopped: true,
|
|
873
|
+
processStopReason: 'process-missing',
|
|
874
|
+
error: record.info.error,
|
|
875
|
+
},
|
|
876
|
+
});
|
|
877
|
+
}
|
|
689
878
|
snapshot(record) {
|
|
690
879
|
const unavailable = adapters[record.info.runner]?.adapter.resumeUnavailableReason?.(record.info.version);
|
|
691
880
|
return {
|
|
@@ -699,7 +888,10 @@ export class NativeSessionManager {
|
|
|
699
888
|
list(owner) {
|
|
700
889
|
return [...this.sessions.values()]
|
|
701
890
|
.filter((record) => record.info.ownerPrincipalId === owner)
|
|
702
|
-
.map((record) =>
|
|
891
|
+
.map((record) => {
|
|
892
|
+
this.reconcileMissingProcess(record);
|
|
893
|
+
return this.snapshot(record);
|
|
894
|
+
});
|
|
703
895
|
}
|
|
704
896
|
read(owner, id, after = 0, limit = 200) {
|
|
705
897
|
const record = this.owned(owner, id);
|
|
@@ -757,25 +949,46 @@ export class NativeSessionManager {
|
|
|
757
949
|
accepted: existing.accepted,
|
|
758
950
|
state: existing.state,
|
|
759
951
|
commandId,
|
|
952
|
+
...(existing.queued ? { queued: true } : {}),
|
|
760
953
|
};
|
|
761
954
|
}
|
|
762
|
-
if (!record.adapter ||
|
|
763
|
-
|
|
955
|
+
if (!record.adapter || ['starting', 'closing', 'closed', 'failed'].includes(record.info.state))
|
|
956
|
+
throw new Error('Native session cannot accept input in its current state');
|
|
957
|
+
if (record.info.state !== 'idle' ||
|
|
764
958
|
record.sending ||
|
|
765
959
|
[...record.commands.values()].some((command) => command.generation === record.info.generation &&
|
|
766
|
-
['pending', 'unknown', 'accepted'].includes(command.state)))
|
|
767
|
-
|
|
768
|
-
|
|
769
|
-
|
|
770
|
-
|
|
960
|
+
['pending', 'unknown', 'accepted'].includes(command.state))) {
|
|
961
|
+
const queued = {
|
|
962
|
+
text,
|
|
963
|
+
commandId,
|
|
964
|
+
generation: record.info.generation,
|
|
965
|
+
state: 'pending',
|
|
966
|
+
queued: true,
|
|
967
|
+
submitted: false,
|
|
968
|
+
accepted: false,
|
|
969
|
+
leaseId: record.info.workerLeaseId,
|
|
970
|
+
};
|
|
971
|
+
record.commands.set(commandId, queued);
|
|
972
|
+
this.persist(record);
|
|
973
|
+
return { commandId, queued: true, state: 'pending', submitted: false, accepted: false };
|
|
974
|
+
}
|
|
975
|
+
return this.submitCommand(record, {
|
|
771
976
|
text,
|
|
772
977
|
commandId,
|
|
773
978
|
generation: record.info.generation,
|
|
774
|
-
// Reserve uncertainty and the visible prompt together before touching stdin.
|
|
775
979
|
state: 'unknown',
|
|
776
980
|
submitted: true,
|
|
777
981
|
accepted: false,
|
|
778
|
-
|
|
982
|
+
leaseId: record.info.workerLeaseId,
|
|
983
|
+
});
|
|
984
|
+
}
|
|
985
|
+
async submitCommand(record, command) {
|
|
986
|
+
record.sending = true;
|
|
987
|
+
record.info.state = 'waiting';
|
|
988
|
+
const { text, commandId } = command;
|
|
989
|
+
command.queued = false;
|
|
990
|
+
command.state = 'unknown';
|
|
991
|
+
command.submitted = true;
|
|
779
992
|
record.commands.set(commandId, command);
|
|
780
993
|
try {
|
|
781
994
|
// A crash after this durable reservation must never trigger a resend.
|
|
@@ -794,8 +1007,50 @@ export class NativeSessionManager {
|
|
|
794
1007
|
}
|
|
795
1008
|
finally {
|
|
796
1009
|
record.sending = false;
|
|
1010
|
+
this.scheduleQueuedInput(record);
|
|
797
1011
|
}
|
|
798
1012
|
}
|
|
1013
|
+
scheduleQueuedInput(record) {
|
|
1014
|
+
queueMicrotask(() => {
|
|
1015
|
+
if (this.sessions.get(record.info.id) !== record ||
|
|
1016
|
+
!record.adapter ||
|
|
1017
|
+
record.info.state !== 'idle' ||
|
|
1018
|
+
record.sending ||
|
|
1019
|
+
record.pendingRequests.size)
|
|
1020
|
+
return;
|
|
1021
|
+
if ([...record.commands.values()].some((command) => command.generation === record.info.generation &&
|
|
1022
|
+
!command.queued &&
|
|
1023
|
+
['unknown', 'pending', 'accepted'].includes(command.state)))
|
|
1024
|
+
return;
|
|
1025
|
+
const next = [...record.commands.values()].find((command) => command.queued && command.generation === record.info.generation);
|
|
1026
|
+
if (!next)
|
|
1027
|
+
return;
|
|
1028
|
+
try {
|
|
1029
|
+
this.assertAccountCurrent(record);
|
|
1030
|
+
if (next.leaseId !== record.info.workerLeaseId)
|
|
1031
|
+
throw new Error('Queued input belongs to a different worker lease');
|
|
1032
|
+
}
|
|
1033
|
+
catch (error) {
|
|
1034
|
+
next.queued = false;
|
|
1035
|
+
next.state = 'failed';
|
|
1036
|
+
this.append(record, {
|
|
1037
|
+
type: 'error',
|
|
1038
|
+
commandId: next.commandId,
|
|
1039
|
+
text: error.message,
|
|
1040
|
+
});
|
|
1041
|
+
return;
|
|
1042
|
+
}
|
|
1043
|
+
void this.submitCommand(record, next).catch((error) => {
|
|
1044
|
+
// Delivery was reserved before touching stdin. Retain uncertainty and
|
|
1045
|
+
// expose the failure instead of retrying input that may have been sent.
|
|
1046
|
+
this.append(record, {
|
|
1047
|
+
type: 'error',
|
|
1048
|
+
commandId: next.commandId,
|
|
1049
|
+
text: `Queued input delivery failed: ${error.message}`,
|
|
1050
|
+
});
|
|
1051
|
+
});
|
|
1052
|
+
});
|
|
1053
|
+
}
|
|
799
1054
|
async respond(owner, id, requestId, response) {
|
|
800
1055
|
const record = this.owned(owner, id);
|
|
801
1056
|
this.assertAccountCurrent(record);
|
|
@@ -821,9 +1076,20 @@ export class NativeSessionManager {
|
|
|
821
1076
|
}
|
|
822
1077
|
async close(owner, id) {
|
|
823
1078
|
const record = this.owned(owner, id);
|
|
1079
|
+
const cancelQueued = () => {
|
|
1080
|
+
for (const command of record.commands.values()) {
|
|
1081
|
+
if (command.queued) {
|
|
1082
|
+
command.queued = false;
|
|
1083
|
+
command.state = 'failed';
|
|
1084
|
+
command.outcome = 'interrupted';
|
|
1085
|
+
}
|
|
1086
|
+
}
|
|
1087
|
+
this.persist(record);
|
|
1088
|
+
};
|
|
824
1089
|
if (record.info.state === 'closed' || record.info.state === 'failed') {
|
|
825
1090
|
if (record.info.processPid && !record.info.processStopped)
|
|
826
1091
|
throw new Error('Native process cleanup is unconfirmed; close outcome is unknown');
|
|
1092
|
+
cancelQueued();
|
|
827
1093
|
return;
|
|
828
1094
|
}
|
|
829
1095
|
record.info.state = 'closing';
|
|
@@ -836,13 +1102,18 @@ export class NativeSessionManager {
|
|
|
836
1102
|
catch (error) {
|
|
837
1103
|
// Startup rejection is expected after cancellation only when the process
|
|
838
1104
|
// adapter has independently confirmed that its entire owned tree stopped.
|
|
839
|
-
if (record.info.processStopped && ['closed', 'failed'].includes(record.info.state))
|
|
1105
|
+
if (record.info.processStopped && ['closed', 'failed'].includes(record.info.state)) {
|
|
1106
|
+
cancelQueued();
|
|
840
1107
|
return;
|
|
1108
|
+
}
|
|
841
1109
|
throw error;
|
|
842
1110
|
}
|
|
843
1111
|
}
|
|
844
1112
|
const adapter = record.adapter ?? (await record.startup);
|
|
845
1113
|
await adapter?.close();
|
|
1114
|
+
if (record.info.processPid && !record.info.processStopped)
|
|
1115
|
+
throw new Error('Native process cleanup is unconfirmed; close outcome is unknown');
|
|
1116
|
+
cancelQueued();
|
|
846
1117
|
if (!['closed', 'failed'].includes(this.owned(owner, id).info.state))
|
|
847
1118
|
this.append(record, { type: 'session.closed' });
|
|
848
1119
|
}
|