@jini-ai/daemon 0.1.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/LICENSE +201 -0
- package/dist/agent-executor.d.ts +458 -0
- package/dist/agent-executor.d.ts.map +1 -0
- package/dist/agent-executor.js +1277 -0
- package/dist/agent-executor.js.map +1 -0
- package/dist/artifacts/index.d.ts +14 -0
- package/dist/artifacts/index.d.ts.map +1 -0
- package/dist/artifacts/index.js +14 -0
- package/dist/artifacts/index.js.map +1 -0
- package/dist/artifacts/manifest.d.ts +90 -0
- package/dist/artifacts/manifest.d.ts.map +1 -0
- package/dist/artifacts/manifest.js +229 -0
- package/dist/artifacts/manifest.js.map +1 -0
- package/dist/artifacts/publication-guard.d.ts +28 -0
- package/dist/artifacts/publication-guard.d.ts.map +1 -0
- package/dist/artifacts/publication-guard.js +77 -0
- package/dist/artifacts/publication-guard.js.map +1 -0
- package/dist/artifacts/runtime-compat.d.ts +37 -0
- package/dist/artifacts/runtime-compat.d.ts.map +1 -0
- package/dist/artifacts/runtime-compat.js +33 -0
- package/dist/artifacts/runtime-compat.js.map +1 -0
- package/dist/artifacts/store.d.ts +85 -0
- package/dist/artifacts/store.d.ts.map +1 -0
- package/dist/artifacts/store.js +92 -0
- package/dist/artifacts/store.js.map +1 -0
- package/dist/artifacts/stub-guard.d.ts +73 -0
- package/dist/artifacts/stub-guard.d.ts.map +1 -0
- package/dist/artifacts/stub-guard.js +198 -0
- package/dist/artifacts/stub-guard.js.map +1 -0
- package/dist/artifacts/text-suppression.d.ts +68 -0
- package/dist/artifacts/text-suppression.d.ts.map +1 -0
- package/dist/artifacts/text-suppression.js +184 -0
- package/dist/artifacts/text-suppression.js.map +1 -0
- package/dist/close-status.d.ts +86 -0
- package/dist/close-status.d.ts.map +1 -0
- package/dist/close-status.js +91 -0
- package/dist/close-status.js.map +1 -0
- package/dist/continuation/continuation-transport.d.ts +41 -0
- package/dist/continuation/continuation-transport.d.ts.map +1 -0
- package/dist/continuation/continuation-transport.js +18 -0
- package/dist/continuation/continuation-transport.js.map +1 -0
- package/dist/continuation/index.d.ts +4 -0
- package/dist/continuation/index.d.ts.map +1 -0
- package/dist/continuation/index.js +4 -0
- package/dist/continuation/index.js.map +1 -0
- package/dist/continuation/journal.d.ts +37 -0
- package/dist/continuation/journal.d.ts.map +1 -0
- package/dist/continuation/journal.js +23 -0
- package/dist/continuation/journal.js.map +1 -0
- package/dist/continuation/run-start-handler.d.ts +75 -0
- package/dist/continuation/run-start-handler.d.ts.map +1 -0
- package/dist/continuation/run-start-handler.js +32 -0
- package/dist/continuation/run-start-handler.js.map +1 -0
- package/dist/delegated-tool-bridge.d.ts +53 -0
- package/dist/delegated-tool-bridge.d.ts.map +1 -0
- package/dist/delegated-tool-bridge.js +92 -0
- package/dist/delegated-tool-bridge.js.map +1 -0
- package/dist/event-log.d.ts +134 -0
- package/dist/event-log.d.ts.map +1 -0
- package/dist/event-log.js +108 -0
- package/dist/event-log.js.map +1 -0
- package/dist/frontend-capability-tools.d.ts +102 -0
- package/dist/frontend-capability-tools.d.ts.map +1 -0
- package/dist/frontend-capability-tools.js +68 -0
- package/dist/frontend-capability-tools.js.map +1 -0
- package/dist/frontend-session-registry.d.ts +127 -0
- package/dist/frontend-session-registry.d.ts.map +1 -0
- package/dist/frontend-session-registry.js +180 -0
- package/dist/frontend-session-registry.js.map +1 -0
- package/dist/index.d.ts +38 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +38 -0
- package/dist/index.js.map +1 -0
- package/dist/legacy-data-migration.d.ts +104 -0
- package/dist/legacy-data-migration.d.ts.map +1 -0
- package/dist/legacy-data-migration.js +239 -0
- package/dist/legacy-data-migration.js.map +1 -0
- package/dist/routines/index.d.ts +12 -0
- package/dist/routines/index.d.ts.map +1 -0
- package/dist/routines/index.js +12 -0
- package/dist/routines/index.js.map +1 -0
- package/dist/routines/routine-store.d.ts +77 -0
- package/dist/routines/routine-store.d.ts.map +1 -0
- package/dist/routines/routine-store.js +162 -0
- package/dist/routines/routine-store.js.map +1 -0
- package/dist/routines/schedule.d.ts +72 -0
- package/dist/routines/schedule.d.ts.map +1 -0
- package/dist/routines/schedule.js +263 -0
- package/dist/routines/schedule.js.map +1 -0
- package/dist/routines/scheduler.d.ts +34 -0
- package/dist/routines/scheduler.d.ts.map +1 -0
- package/dist/routines/scheduler.js +330 -0
- package/dist/routines/scheduler.js.map +1 -0
- package/dist/routines/types.d.ts +131 -0
- package/dist/routines/types.d.ts.map +1 -0
- package/dist/routines/types.js +9 -0
- package/dist/routines/types.js.map +1 -0
- package/dist/run/core/failure-taxonomy.d.ts +27 -0
- package/dist/run/core/failure-taxonomy.d.ts.map +1 -0
- package/dist/run/core/failure-taxonomy.js +16 -0
- package/dist/run/core/failure-taxonomy.js.map +1 -0
- package/dist/run/core/index.d.ts +5 -0
- package/dist/run/core/index.d.ts.map +1 -0
- package/dist/run/core/index.js +5 -0
- package/dist/run/core/index.js.map +1 -0
- package/dist/run/core/result.d.ts +25 -0
- package/dist/run/core/result.d.ts.map +1 -0
- package/dist/run/core/result.js +52 -0
- package/dist/run/core/result.js.map +1 -0
- package/dist/run/core/retry.d.ts +106 -0
- package/dist/run/core/retry.d.ts.map +1 -0
- package/dist/run/core/retry.js +210 -0
- package/dist/run/core/retry.js.map +1 -0
- package/dist/run/diagnostics/diagnostics.d.ts +86 -0
- package/dist/run/diagnostics/diagnostics.d.ts.map +1 -0
- package/dist/run/diagnostics/diagnostics.js +211 -0
- package/dist/run/diagnostics/diagnostics.js.map +1 -0
- package/dist/run/diagnostics/index.d.ts +3 -0
- package/dist/run/diagnostics/index.d.ts.map +1 -0
- package/dist/run/diagnostics/index.js +3 -0
- package/dist/run/diagnostics/index.js.map +1 -0
- package/dist/run/index.d.ts +16 -0
- package/dist/run/index.d.ts.map +1 -0
- package/dist/run/index.js +16 -0
- package/dist/run/index.js.map +1 -0
- package/dist/run-lifecycle.d.ts +118 -0
- package/dist/run-lifecycle.d.ts.map +1 -0
- package/dist/run-lifecycle.js +451 -0
- package/dist/run-lifecycle.js.map +1 -0
- package/dist/terminal-session.d.ts +139 -0
- package/dist/terminal-session.d.ts.map +1 -0
- package/dist/terminal-session.js +316 -0
- package/dist/terminal-session.js.map +1 -0
- package/dist/tokens.d.ts +9 -0
- package/dist/tokens.d.ts.map +1 -0
- package/dist/tokens.js +19 -0
- package/dist/tokens.js.map +1 -0
- package/dist/tool-executor.d.ts +97 -0
- package/dist/tool-executor.d.ts.map +1 -0
- package/dist/tool-executor.js +198 -0
- package/dist/tool-executor.js.map +1 -0
- package/package.json +51 -0
|
@@ -0,0 +1,451 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* `RunLifecycle` — start/stream/cancel/resume a run keyed on an opaque
|
|
3
|
+
* `contextRef` (extraction-plan §2.1: runs key on an opaque `contextRef`,
|
|
4
|
+
* never a product-record identifier), generalized from OD's `design.runs` service
|
|
5
|
+
* (`apps/daemon/src/runtimes/runs.ts` + the terminal-decision half of
|
|
6
|
+
* `apps/daemon/src/runtimes/start-chat-run.ts`, `arch/server-startserver-endgame`
|
|
7
|
+
* branch — see `source-map.md` for exact line citations).
|
|
8
|
+
*
|
|
9
|
+
* Scope boundary: this module owns the run *state machine* and its event
|
|
10
|
+
* log — create, transition, emit, replay, cancellation-intent propagation,
|
|
11
|
+
* idempotent start/finish, resume. It does not spawn or signal a subprocess;
|
|
12
|
+
* that is `@jini-ai/agent-runtime`'s job (extraction-plan task 7). A driver
|
|
13
|
+
* (today: this package's tests; later: agent-runtime) calls `emit()` for
|
|
14
|
+
* agent/stdout/stderr/error events, observes cancellation via
|
|
15
|
+
* `onCancelRequested`, and calls `finish()` once it knows the real outcome.
|
|
16
|
+
*/
|
|
17
|
+
import { randomUUID } from 'node:crypto';
|
|
18
|
+
import { RUN_PROTOCOL_VERSION, isTerminalRunState } from '@jini-ai/protocol';
|
|
19
|
+
import { createInactivityWatchdog } from './close-status.js';
|
|
20
|
+
/** Vocabulary-firewall bridge: `RunState` uses `'cancelled'` (extraction-plan §12 C5's own cited canary), `RunEndPayload.status` uses `'canceled'`. Both live in `@jini-ai/protocol`, which is out of scope for this task — bridged here rather than fixed upstream. */
|
|
21
|
+
const TERMINAL_OUTCOME_TO_END_STATUS = {
|
|
22
|
+
succeeded: 'succeeded',
|
|
23
|
+
failed: 'failed',
|
|
24
|
+
cancelled: 'canceled',
|
|
25
|
+
};
|
|
26
|
+
function toPublicStatus(record) {
|
|
27
|
+
const status = {
|
|
28
|
+
id: record.status.id,
|
|
29
|
+
state: record.status.state,
|
|
30
|
+
startedAt: record.status.startedAt,
|
|
31
|
+
updatedAt: record.status.updatedAt,
|
|
32
|
+
};
|
|
33
|
+
if (record.status.endedAt !== undefined) {
|
|
34
|
+
return { ...status, endedAt: record.status.endedAt };
|
|
35
|
+
}
|
|
36
|
+
return status;
|
|
37
|
+
}
|
|
38
|
+
/**
|
|
39
|
+
* Bridges `@jini-ai/daemon`'s own `EventLogEntry` (`{id, event, data, recordedAt}`) to
|
|
40
|
+
* `@jini-ai/protocol`'s canonical `RunEvent` envelope. `EventLogEntry` carries no `runId` of its
|
|
41
|
+
* own (the log is already scoped by the `runId` parameter every `EventLog` method takes), so
|
|
42
|
+
* this is the one place that stamps it onto the outgoing envelope.
|
|
43
|
+
*/
|
|
44
|
+
function toRunEvent(runId, entry) {
|
|
45
|
+
return {
|
|
46
|
+
runId,
|
|
47
|
+
eventId: `${runId}:${entry.id}`,
|
|
48
|
+
opaqueCursor: entry.id,
|
|
49
|
+
protocolVersion: RUN_PROTOCOL_VERSION,
|
|
50
|
+
ts: entry.recordedAt,
|
|
51
|
+
kind: entry.event,
|
|
52
|
+
payload: entry.data,
|
|
53
|
+
durability: 'durable',
|
|
54
|
+
};
|
|
55
|
+
}
|
|
56
|
+
function isRecord(value) {
|
|
57
|
+
return typeof value === 'object' && value !== null && !Array.isArray(value);
|
|
58
|
+
}
|
|
59
|
+
function terminalStateFromEndEntry(entry) {
|
|
60
|
+
if (!isRecord(entry.data))
|
|
61
|
+
return { state: 'failed', resumable: false };
|
|
62
|
+
const status = entry.data.status;
|
|
63
|
+
const state = status === 'succeeded' ? 'succeeded' : status === 'canceled' ? 'cancelled' : 'failed';
|
|
64
|
+
return { state, resumable: entry.data.resumable === true };
|
|
65
|
+
}
|
|
66
|
+
/**
|
|
67
|
+
* Creates the in-process `RunLifecycle` reference implementation.
|
|
68
|
+
*
|
|
69
|
+
* @param input.eventLog - The durable `EventLog` port this lifecycle appends to and replays from.
|
|
70
|
+
* @returns A `RunLifecycle` backed by an in-memory run registry plus the injected `EventLog`.
|
|
71
|
+
* @complexity Per-call complexities documented on each method; the registry itself is a `Map` keyed by `runId` (O(1) lookup).
|
|
72
|
+
* @overallScore 100/100
|
|
73
|
+
*/
|
|
74
|
+
export function createRunLifecycle(input) {
|
|
75
|
+
const { eventLog } = input;
|
|
76
|
+
const runs = new Map();
|
|
77
|
+
const idempotencyIndex = new Map();
|
|
78
|
+
let hydration = null;
|
|
79
|
+
function requireRun(runId) {
|
|
80
|
+
const record = runs.get(runId);
|
|
81
|
+
if (!record) {
|
|
82
|
+
throw new Error(`RunLifecycle: unknown run "${runId}"`);
|
|
83
|
+
}
|
|
84
|
+
return record;
|
|
85
|
+
}
|
|
86
|
+
/**
|
|
87
|
+
* A subscriber is a transport-owned callback (e.g. an SSE writer) outside this module's
|
|
88
|
+
* control. One subscriber throwing (a dead socket, a broken client) must never abort the
|
|
89
|
+
* fan-out to the others, nor propagate out through `emit()`/`finish()` into driver code that
|
|
90
|
+
* has nothing to do with that transport — see CR-R1 in
|
|
91
|
+
* `ADS-memory/reports/code-review/CR-backend-coverage-push-2026-07-20.md`.
|
|
92
|
+
*/
|
|
93
|
+
function notifySubscribers(record, event) {
|
|
94
|
+
for (const subscriber of record.subscribers) {
|
|
95
|
+
try {
|
|
96
|
+
subscriber(event);
|
|
97
|
+
}
|
|
98
|
+
catch {
|
|
99
|
+
// Isolated by design — see the function doc above.
|
|
100
|
+
}
|
|
101
|
+
}
|
|
102
|
+
}
|
|
103
|
+
async function appendEvent(runId, record, event, data) {
|
|
104
|
+
const entry = await eventLog.append({ runId, event, data });
|
|
105
|
+
const runEvent = toRunEvent(runId, entry);
|
|
106
|
+
notifySubscribers(record, runEvent);
|
|
107
|
+
return runEvent;
|
|
108
|
+
}
|
|
109
|
+
function resolveTerminalWaiters(record) {
|
|
110
|
+
const waiters = record.terminalWaiters.splice(0, record.terminalWaiters.length);
|
|
111
|
+
const status = toPublicStatus(record);
|
|
112
|
+
for (const resolve of waiters) {
|
|
113
|
+
resolve(status);
|
|
114
|
+
}
|
|
115
|
+
}
|
|
116
|
+
/**
|
|
117
|
+
* Fires when a run's inactivity watchdog times out with no intervening
|
|
118
|
+
* `emit()`/`finish()`. Classified as a resumable failure (`code: null,
|
|
119
|
+
* signal: null`), mirroring OD's own timeout/inactivity classification
|
|
120
|
+
* (`isResumableFailure` in the researched `run-failure-classification.ts`
|
|
121
|
+
* treats timeout/inactivity as one of only two resumable categories).
|
|
122
|
+
* A run that already reached a terminal state before the timer fired
|
|
123
|
+
* (a normal race with `finish()`) is left untouched.
|
|
124
|
+
*/
|
|
125
|
+
async function handleInactivityTimeout(runId) {
|
|
126
|
+
const record = runs.get(runId);
|
|
127
|
+
if (!record || isTerminalRunState(record.status.state)) {
|
|
128
|
+
return;
|
|
129
|
+
}
|
|
130
|
+
try {
|
|
131
|
+
await lifecycle.finish({ runId, status: 'failed', code: null, signal: null, resumable: true });
|
|
132
|
+
}
|
|
133
|
+
catch (error) {
|
|
134
|
+
const context = { source: 'inactivity-timeout', runId, error };
|
|
135
|
+
try {
|
|
136
|
+
if (input.onInternalError) {
|
|
137
|
+
input.onInternalError(context);
|
|
138
|
+
}
|
|
139
|
+
else {
|
|
140
|
+
// eslint-disable-next-line no-console
|
|
141
|
+
console.error(`[@jini-ai/daemon] internal error (inactivity-timeout, runId=${runId})`, error);
|
|
142
|
+
}
|
|
143
|
+
}
|
|
144
|
+
catch (sinkError) {
|
|
145
|
+
// A diagnostic sink must not turn a contained timer failure into another unhandled
|
|
146
|
+
// rejection.
|
|
147
|
+
// eslint-disable-next-line no-console
|
|
148
|
+
console.error(`[@jini-ai/daemon] internal error sink failed (inactivity-timeout, runId=${runId})`, sinkError);
|
|
149
|
+
}
|
|
150
|
+
}
|
|
151
|
+
}
|
|
152
|
+
const lifecycle = {
|
|
153
|
+
async rehydrate() {
|
|
154
|
+
if (hydration)
|
|
155
|
+
return hydration;
|
|
156
|
+
hydration = (async () => {
|
|
157
|
+
const rehydratedNonTerminalRunIds = [];
|
|
158
|
+
for (const runId of await eventLog.listRunIds()) {
|
|
159
|
+
if (runs.has(runId))
|
|
160
|
+
continue;
|
|
161
|
+
const replay = await eventLog.replay(runId, null);
|
|
162
|
+
if (replay.kind !== 'ok' || replay.entries.length === 0)
|
|
163
|
+
continue;
|
|
164
|
+
const entries = replay.entries;
|
|
165
|
+
const startEntry = entries.find((entry) => entry.event === 'start');
|
|
166
|
+
const endEntry = [...entries].reverse().find((entry) => entry.event === 'end');
|
|
167
|
+
const startData = startEntry && isRecord(startEntry.data) ? startEntry.data : null;
|
|
168
|
+
const firstEntry = entries[0];
|
|
169
|
+
const lastEntry = entries[entries.length - 1];
|
|
170
|
+
const terminal = endEntry === undefined ? null : terminalStateFromEndEntry(endEntry);
|
|
171
|
+
const contextRef = typeof startData?.contextRef === 'string' ? startData.contextRef : undefined;
|
|
172
|
+
const idempotencyKey = typeof startData?.idempotencyKey === 'string' ? startData.idempotencyKey : undefined;
|
|
173
|
+
const record = {
|
|
174
|
+
contextRef,
|
|
175
|
+
status: {
|
|
176
|
+
id: runId,
|
|
177
|
+
state: terminal?.state ?? 'running',
|
|
178
|
+
startedAt: startEntry?.recordedAt ?? firstEntry.recordedAt,
|
|
179
|
+
updatedAt: lastEntry.recordedAt,
|
|
180
|
+
endedAt: endEntry?.recordedAt,
|
|
181
|
+
},
|
|
182
|
+
resumable: terminal?.resumable ?? false,
|
|
183
|
+
cancelRequested: false,
|
|
184
|
+
lastCancelRequest: undefined,
|
|
185
|
+
cancelListeners: new Set(),
|
|
186
|
+
subscribers: new Set(),
|
|
187
|
+
terminalWaiters: [],
|
|
188
|
+
terminalEndEntry: endEntry,
|
|
189
|
+
watchdog: undefined,
|
|
190
|
+
startPromise: undefined,
|
|
191
|
+
finishPromise: undefined,
|
|
192
|
+
};
|
|
193
|
+
runs.set(runId, record);
|
|
194
|
+
if (idempotencyKey !== undefined)
|
|
195
|
+
idempotencyIndex.set(idempotencyKey, runId);
|
|
196
|
+
if (terminal === null)
|
|
197
|
+
rehydratedNonTerminalRunIds.push(runId);
|
|
198
|
+
}
|
|
199
|
+
// A process restart cannot retain an in-memory child process or cancellation listener.
|
|
200
|
+
// Persist an honest terminal outcome instead of advertising an orphaned run as still live.
|
|
201
|
+
for (const runId of rehydratedNonTerminalRunIds) {
|
|
202
|
+
await lifecycle.finish({ runId, status: 'failed', code: null, signal: null, resumable: true });
|
|
203
|
+
}
|
|
204
|
+
})();
|
|
205
|
+
return hydration;
|
|
206
|
+
},
|
|
207
|
+
async start(startInput) {
|
|
208
|
+
if (startInput.idempotencyKey !== undefined) {
|
|
209
|
+
const existingRunId = idempotencyIndex.get(startInput.idempotencyKey);
|
|
210
|
+
if (existingRunId) {
|
|
211
|
+
const existing = requireRun(existingRunId);
|
|
212
|
+
await existing.startPromise;
|
|
213
|
+
return { run: toPublicStatus(existing), started: false };
|
|
214
|
+
}
|
|
215
|
+
}
|
|
216
|
+
const runId = startInput.runId ?? randomUUID();
|
|
217
|
+
if (runs.has(runId)) {
|
|
218
|
+
throw new Error(`RunLifecycle: run "${runId}" already exists`);
|
|
219
|
+
}
|
|
220
|
+
const now = Date.now();
|
|
221
|
+
const record = {
|
|
222
|
+
contextRef: startInput.contextRef,
|
|
223
|
+
status: { id: runId, state: 'running', startedAt: now, updatedAt: now, endedAt: undefined },
|
|
224
|
+
resumable: false,
|
|
225
|
+
cancelRequested: false,
|
|
226
|
+
lastCancelRequest: undefined,
|
|
227
|
+
cancelListeners: new Set(),
|
|
228
|
+
subscribers: new Set(),
|
|
229
|
+
terminalWaiters: [],
|
|
230
|
+
terminalEndEntry: undefined,
|
|
231
|
+
watchdog: undefined,
|
|
232
|
+
startPromise: undefined,
|
|
233
|
+
finishPromise: undefined,
|
|
234
|
+
};
|
|
235
|
+
runs.set(runId, record);
|
|
236
|
+
if (startInput.idempotencyKey !== undefined) {
|
|
237
|
+
idempotencyIndex.set(startInput.idempotencyKey, runId);
|
|
238
|
+
}
|
|
239
|
+
const startPayload = {
|
|
240
|
+
runId,
|
|
241
|
+
contextRef: startInput.contextRef,
|
|
242
|
+
...(startInput.agentId !== undefined ? { agentId: startInput.agentId } : {}),
|
|
243
|
+
...(startInput.idempotencyKey !== undefined ? { idempotencyKey: startInput.idempotencyKey } : {}),
|
|
244
|
+
};
|
|
245
|
+
const startPromise = appendEvent(runId, record, 'start', startPayload).then(() => undefined);
|
|
246
|
+
record.startPromise = startPromise;
|
|
247
|
+
try {
|
|
248
|
+
await startPromise;
|
|
249
|
+
record.startPromise = undefined;
|
|
250
|
+
}
|
|
251
|
+
catch (error) {
|
|
252
|
+
runs.delete(runId);
|
|
253
|
+
if (startInput.idempotencyKey !== undefined &&
|
|
254
|
+
idempotencyIndex.get(startInput.idempotencyKey) === runId) {
|
|
255
|
+
idempotencyIndex.delete(startInput.idempotencyKey);
|
|
256
|
+
}
|
|
257
|
+
throw error;
|
|
258
|
+
}
|
|
259
|
+
if (startInput.inactivityTimeoutMs !== undefined) {
|
|
260
|
+
record.watchdog = createInactivityWatchdog({
|
|
261
|
+
timeoutMs: startInput.inactivityTimeoutMs,
|
|
262
|
+
onTimeout: () => {
|
|
263
|
+
void handleInactivityTimeout(runId);
|
|
264
|
+
},
|
|
265
|
+
});
|
|
266
|
+
}
|
|
267
|
+
return { run: toPublicStatus(record), started: true };
|
|
268
|
+
},
|
|
269
|
+
async get(runId) {
|
|
270
|
+
const record = runs.get(runId);
|
|
271
|
+
return record ? toPublicStatus(record) : undefined;
|
|
272
|
+
},
|
|
273
|
+
async list(contextRef) {
|
|
274
|
+
const all = Array.from(runs.values());
|
|
275
|
+
const filtered = contextRef === undefined ? all : all.filter((record) => record.contextRef === contextRef);
|
|
276
|
+
return filtered.map(toPublicStatus);
|
|
277
|
+
},
|
|
278
|
+
async cancel(request) {
|
|
279
|
+
const record = requireRun(request.runId);
|
|
280
|
+
await record.startPromise;
|
|
281
|
+
if (record.finishPromise) {
|
|
282
|
+
return record.finishPromise;
|
|
283
|
+
}
|
|
284
|
+
if (isTerminalRunState(record.status.state)) {
|
|
285
|
+
return toPublicStatus(record);
|
|
286
|
+
}
|
|
287
|
+
record.cancelRequested = true;
|
|
288
|
+
record.lastCancelRequest = request;
|
|
289
|
+
record.status.updatedAt = Date.now();
|
|
290
|
+
for (const listener of record.cancelListeners) {
|
|
291
|
+
listener(request);
|
|
292
|
+
}
|
|
293
|
+
return toPublicStatus(record);
|
|
294
|
+
},
|
|
295
|
+
/**
|
|
296
|
+
* Registers a cancel-intent listener. If `cancel()` was already called
|
|
297
|
+
* for this run before this subscription, the listener fires immediately
|
|
298
|
+
* with the original request (mirrors `AbortSignal`'s `aborted`+`addEventListener`
|
|
299
|
+
* pairing) — otherwise a driver that attaches after the cancel already
|
|
300
|
+
* happened would silently never learn about it, since a plain
|
|
301
|
+
* subscribe-for-future-events registry has no memory of past firings.
|
|
302
|
+
*/
|
|
303
|
+
onCancelRequested(runId, listener) {
|
|
304
|
+
const record = requireRun(runId);
|
|
305
|
+
if (record.cancelRequested && record.lastCancelRequest) {
|
|
306
|
+
listener(record.lastCancelRequest);
|
|
307
|
+
}
|
|
308
|
+
record.cancelListeners.add(listener);
|
|
309
|
+
return () => record.cancelListeners.delete(listener);
|
|
310
|
+
},
|
|
311
|
+
async emit(runId, driverInput) {
|
|
312
|
+
const record = requireRun(runId);
|
|
313
|
+
await record.startPromise;
|
|
314
|
+
if (record.finishPromise || isTerminalRunState(record.status.state)) {
|
|
315
|
+
throw new Error(`RunLifecycle: cannot emit "${driverInput.event}" on terminal run "${runId}" — drivers must stop emitting once finish() has been called`);
|
|
316
|
+
}
|
|
317
|
+
record.watchdog?.noteActivity();
|
|
318
|
+
return appendEvent(runId, record, driverInput.event, driverInput.data);
|
|
319
|
+
},
|
|
320
|
+
async finish(finishInput) {
|
|
321
|
+
const record = requireRun(finishInput.runId);
|
|
322
|
+
await record.startPromise;
|
|
323
|
+
if (record.finishPromise) {
|
|
324
|
+
return record.finishPromise;
|
|
325
|
+
}
|
|
326
|
+
if (isTerminalRunState(record.status.state)) {
|
|
327
|
+
return toPublicStatus(record);
|
|
328
|
+
}
|
|
329
|
+
const finishing = (async () => {
|
|
330
|
+
const endPayload = {
|
|
331
|
+
code: finishInput.code,
|
|
332
|
+
signal: finishInput.signal,
|
|
333
|
+
status: TERMINAL_OUTCOME_TO_END_STATUS[finishInput.status],
|
|
334
|
+
resumable: finishInput.resumable,
|
|
335
|
+
...(finishInput.sessionRef !== undefined ? { sessionRef: finishInput.sessionRef } : {}),
|
|
336
|
+
};
|
|
337
|
+
const endEntry = await eventLog.append({ runId: finishInput.runId, event: 'end', data: endPayload });
|
|
338
|
+
// Commit the in-memory terminal transition only after its durable end entry exists. Until
|
|
339
|
+
// then `finishPromise` reserves the transition and blocks emits/concurrent finishes.
|
|
340
|
+
record.watchdog?.cancel();
|
|
341
|
+
record.status.state = finishInput.status;
|
|
342
|
+
record.status.updatedAt = endEntry.recordedAt;
|
|
343
|
+
record.status.endedAt = endEntry.recordedAt;
|
|
344
|
+
record.resumable = finishInput.resumable;
|
|
345
|
+
record.terminalEndEntry = endEntry;
|
|
346
|
+
const endEvent = toRunEvent(finishInput.runId, endEntry);
|
|
347
|
+
notifySubscribers(record, endEvent);
|
|
348
|
+
resolveTerminalWaiters(record);
|
|
349
|
+
return toPublicStatus(record);
|
|
350
|
+
})();
|
|
351
|
+
record.finishPromise = finishing;
|
|
352
|
+
try {
|
|
353
|
+
return await finishing;
|
|
354
|
+
}
|
|
355
|
+
finally {
|
|
356
|
+
if (record.finishPromise === finishing) {
|
|
357
|
+
record.finishPromise = undefined;
|
|
358
|
+
}
|
|
359
|
+
}
|
|
360
|
+
},
|
|
361
|
+
async resume(runId) {
|
|
362
|
+
const record = requireRun(runId);
|
|
363
|
+
const eligible = isTerminalRunState(record.status.state) && record.resumable;
|
|
364
|
+
if (!eligible) {
|
|
365
|
+
return { run: toPublicStatus(record), resumed: false };
|
|
366
|
+
}
|
|
367
|
+
const now = Date.now();
|
|
368
|
+
record.status.state = 'running';
|
|
369
|
+
record.status.updatedAt = now;
|
|
370
|
+
record.status.endedAt = undefined;
|
|
371
|
+
record.resumable = false;
|
|
372
|
+
record.cancelRequested = false;
|
|
373
|
+
record.lastCancelRequest = undefined;
|
|
374
|
+
record.terminalEndEntry = undefined;
|
|
375
|
+
// No protocol event is emitted here: none of RunProtocolEvent's six
|
|
376
|
+
// kinds represents "resumed" (extraction-plan scope decision — see
|
|
377
|
+
// source-map.md). The event log's cursor sequence continues
|
|
378
|
+
// unbroken; only RunStatus.state changes.
|
|
379
|
+
return { run: toPublicStatus(record), resumed: true };
|
|
380
|
+
},
|
|
381
|
+
async waitForTerminal(runId) {
|
|
382
|
+
const record = requireRun(runId);
|
|
383
|
+
if (isTerminalRunState(record.status.state)) {
|
|
384
|
+
return toPublicStatus(record);
|
|
385
|
+
}
|
|
386
|
+
return new Promise((resolve) => {
|
|
387
|
+
record.terminalWaiters.push(resolve);
|
|
388
|
+
});
|
|
389
|
+
},
|
|
390
|
+
async stream(runId, onEvent, options = {}) {
|
|
391
|
+
const record = runs.get(runId);
|
|
392
|
+
if (!record) {
|
|
393
|
+
return { kind: 'unknown-run' };
|
|
394
|
+
}
|
|
395
|
+
await record.startPromise;
|
|
396
|
+
// Subscribe before awaiting the durable replay. Any event appended while the replay query is
|
|
397
|
+
// in flight is buffered, then delivered after the replay entries, so a reconnect cannot lose
|
|
398
|
+
// the narrow replay→subscribe interval or observe the live event ahead of older history.
|
|
399
|
+
let replaying = true;
|
|
400
|
+
const bufferedLiveEvents = [];
|
|
401
|
+
const subscriber = (event) => {
|
|
402
|
+
if (replaying)
|
|
403
|
+
bufferedLiveEvents.push(event);
|
|
404
|
+
else
|
|
405
|
+
onEvent(event);
|
|
406
|
+
};
|
|
407
|
+
record.subscribers.add(subscriber);
|
|
408
|
+
try {
|
|
409
|
+
const replay = await eventLog.replay(runId, options.afterCursor ?? null);
|
|
410
|
+
if (replay.kind !== 'ok') {
|
|
411
|
+
record.subscribers.delete(subscriber);
|
|
412
|
+
return replay;
|
|
413
|
+
}
|
|
414
|
+
const deliveredEventIds = new Set();
|
|
415
|
+
for (const entry of replay.entries) {
|
|
416
|
+
const event = toRunEvent(runId, entry);
|
|
417
|
+
deliveredEventIds.add(event.eventId);
|
|
418
|
+
onEvent(event);
|
|
419
|
+
}
|
|
420
|
+
for (const event of bufferedLiveEvents) {
|
|
421
|
+
if (!deliveredEventIds.has(event.eventId)) {
|
|
422
|
+
deliveredEventIds.add(event.eventId);
|
|
423
|
+
onEvent(event);
|
|
424
|
+
}
|
|
425
|
+
}
|
|
426
|
+
replaying = false;
|
|
427
|
+
const terminal = isTerminalRunState(record.status.state);
|
|
428
|
+
if (terminal && record.terminalEndEntry) {
|
|
429
|
+
const terminalEvent = toRunEvent(runId, record.terminalEndEntry);
|
|
430
|
+
if (!deliveredEventIds.has(terminalEvent.eventId)) {
|
|
431
|
+
deliveredEventIds.add(terminalEvent.eventId);
|
|
432
|
+
onEvent(terminalEvent);
|
|
433
|
+
}
|
|
434
|
+
}
|
|
435
|
+
if (terminal) {
|
|
436
|
+
record.subscribers.delete(subscriber);
|
|
437
|
+
return { kind: 'ok', unsubscribe: () => { } };
|
|
438
|
+
}
|
|
439
|
+
return { kind: 'ok', unsubscribe: () => record.subscribers.delete(subscriber) };
|
|
440
|
+
}
|
|
441
|
+
catch (error) {
|
|
442
|
+
// Subscription is installed before durable replay to close the replay→live race. Any
|
|
443
|
+
// replay I/O or consumer callback failure must therefore remove it before propagating.
|
|
444
|
+
record.subscribers.delete(subscriber);
|
|
445
|
+
throw error;
|
|
446
|
+
}
|
|
447
|
+
},
|
|
448
|
+
};
|
|
449
|
+
return lifecycle;
|
|
450
|
+
}
|
|
451
|
+
//# sourceMappingURL=run-lifecycle.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"run-lifecycle.js","sourceRoot":"","sources":["../src/run-lifecycle.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,139 @@
|
|
|
1
|
+
import type { Principal, ToolPolicy, ToolRegistration } from '@jini-ai/core';
|
|
2
|
+
import { type PtySpawn, type TerminalService, type TerminalSseSink } from '@jini-ai/platform';
|
|
3
|
+
export type { TerminalSseSink } from '@jini-ai/platform';
|
|
4
|
+
/** The `ToolRegistry` id `terminal.create` executes through — see module doc §2. */
|
|
5
|
+
export declare const TERMINAL_CREATE_TOOL_ID = "terminal.create";
|
|
6
|
+
/**
|
|
7
|
+
* Deny-by-default `ToolPolicy` for `terminal.create`. Matching
|
|
8
|
+
* `db-ops.ts`'s `denyAllDaemonDbPolicy` / `@jini-ai/deploy`'s
|
|
9
|
+
* `denyAllDeployPublishPolicy` precedent: spawning an interactive shell is
|
|
10
|
+
* strictly more dangerous than any of those (it is not one bounded
|
|
11
|
+
* operation but an open-ended session), so a host must explicitly opt in
|
|
12
|
+
* with its own policy rather than getting a working shell spawner for free
|
|
13
|
+
* merely by registering the tool.
|
|
14
|
+
*/
|
|
15
|
+
export declare const denyAllTerminalCreatePolicy: ToolPolicy;
|
|
16
|
+
/**
|
|
17
|
+
* The real, `node-pty`-backed {@link PtySpawn}. Dynamically imports
|
|
18
|
+
* `node-pty` (mirroring OD's origin `await import('node-pty')`, not a
|
|
19
|
+
* static top-level import) so a host process whose platform/environment
|
|
20
|
+
* lacks a usable `node-pty` addon can still boot — only an actual
|
|
21
|
+
* `terminal.create` call fails, cleanly, rather than crashing at
|
|
22
|
+
* module-eval time. Before the first spawn, repairs `node-pty`'s bundled
|
|
23
|
+
* `spawn-helper` binary's executable bit (pnpm unpacks it non-executable —
|
|
24
|
+
* see `@jini-ai/platform`'s `terminal.ts` module doc for the full story) via
|
|
25
|
+
* that package's own `spawnHelperCandidatePaths`/`ensureSpawnHelperExecutable`,
|
|
26
|
+
* but with the resolver anchored at **this** module
|
|
27
|
+
* (`createRequire(import.meta.url)` here, not `@jini-ai/platform`'s own
|
|
28
|
+
* default): `@jini-ai/platform` deliberately does not depend on `node-pty`, so
|
|
29
|
+
* its default `require.resolve('node-pty')` would not find the copy this
|
|
30
|
+
* package (`@jini-ai/daemon`) actually declares — this is exactly the
|
|
31
|
+
* resolver injection seam `spawnHelperCandidatePaths` was built for.
|
|
32
|
+
*/
|
|
33
|
+
export declare function loadRealSpawnPty(): Promise<PtySpawn>;
|
|
34
|
+
/** The public, principal-neutral session snapshot this module exposes — deliberately its own shape rather than re-exporting `@jini-ai/platform`'s `TerminalSession` verbatim, since that type carries an OD-shaped per-session grouping key (see `@jini-ai/platform`'s `terminal.ts`) this module replaces entirely with the caller-supplied `resourceRef` (see {@link CreateTerminalSessionOptions}), tracked only in this module's own metadata and never forwarded to `@jini-ai/platform` at all — this package's own identifier-neutrality lint (`__tests__/identifier-lint.test.ts`) forbids that origin field's exact name from appearing anywhere in this package's source. */
|
|
35
|
+
export interface TerminalSessionInfo {
|
|
36
|
+
readonly id: string;
|
|
37
|
+
readonly resourceRef: string | null;
|
|
38
|
+
readonly cwd: string;
|
|
39
|
+
readonly shell: string;
|
|
40
|
+
readonly cols: number;
|
|
41
|
+
readonly rows: number;
|
|
42
|
+
readonly status: 'running' | 'exited';
|
|
43
|
+
readonly createdAt: number;
|
|
44
|
+
readonly updatedAt: number;
|
|
45
|
+
readonly exitCode: number | null;
|
|
46
|
+
readonly signal: string | null;
|
|
47
|
+
}
|
|
48
|
+
export interface CreateTerminalSessionOptions {
|
|
49
|
+
/** Opaque grouping/scoping reference (e.g. what `@jini-ai/http`'s `workspace-root.ts` resolved `cwd` from) — tracked by this module only, never forwarded to `@jini-ai/platform`. */
|
|
50
|
+
readonly resourceRef?: string | null;
|
|
51
|
+
readonly cwd: string;
|
|
52
|
+
readonly cols?: number;
|
|
53
|
+
readonly rows?: number;
|
|
54
|
+
readonly shell?: string | null;
|
|
55
|
+
}
|
|
56
|
+
export interface TerminalSessionListFilter {
|
|
57
|
+
readonly resourceRef?: string;
|
|
58
|
+
}
|
|
59
|
+
export type TerminalSessionAccessResult = {
|
|
60
|
+
readonly status: 'not-found';
|
|
61
|
+
} | {
|
|
62
|
+
readonly status: 'ok';
|
|
63
|
+
readonly session: TerminalSessionInfo;
|
|
64
|
+
};
|
|
65
|
+
/**
|
|
66
|
+
* Result of a `write`/`resize`/`kill` call. `'not-found'` covers both "no
|
|
67
|
+
* such session" and "this session belongs to a different principal" —
|
|
68
|
+
* identically, never distinguishably — see {@link checkOwnership}'s doc.
|
|
69
|
+
* `'ok'` with `ok: false` covers a session that exists and is owned by the
|
|
70
|
+
* caller but could not actually perform the action (already exited, killed
|
|
71
|
+
* by a racing call, or the underlying pty call itself failed) — mirroring
|
|
72
|
+
* `@jini-ai/platform`'s own `write`/`resize`/`kill` boolean-return contract.
|
|
73
|
+
*/
|
|
74
|
+
export type TerminalSessionActionResult = {
|
|
75
|
+
readonly status: 'not-found';
|
|
76
|
+
} | {
|
|
77
|
+
readonly status: 'ok';
|
|
78
|
+
readonly ok: boolean;
|
|
79
|
+
readonly session: TerminalSessionInfo | null;
|
|
80
|
+
};
|
|
81
|
+
export type TerminalSessionAttachResult = 'attached' | 'ended' | 'not-found';
|
|
82
|
+
export interface TerminalSessionManager {
|
|
83
|
+
/** The one call gated through `ToolExecutor` (see module doc §2) — this method is what `createTerminalToolRegistrations`'s handler calls, never invoked directly by a route. */
|
|
84
|
+
create(principal: Principal, options: CreateTerminalSessionOptions): Promise<TerminalSessionInfo>;
|
|
85
|
+
get(principal: Principal, id: string): TerminalSessionAccessResult;
|
|
86
|
+
/** Sessions the given principal owns, optionally narrowed by `resourceRef`. Never returns another principal's sessions. */
|
|
87
|
+
list(principal: Principal, filter?: TerminalSessionListFilter): readonly TerminalSessionInfo[];
|
|
88
|
+
write(principal: Principal, id: string, input: string): Promise<TerminalSessionActionResult>;
|
|
89
|
+
resize(principal: Principal, id: string, cols: number, rows: number): Promise<TerminalSessionActionResult>;
|
|
90
|
+
kill(principal: Principal, id: string, signal?: string): Promise<TerminalSessionActionResult>;
|
|
91
|
+
/** Replays scrollback after `lastEventId` and attaches `sink` for live output — ownership-checked the same as `write`/`resize`/`kill`, since reading a session's output is exactly as sensitive as writing to it. */
|
|
92
|
+
attach(principal: Principal, id: string, lastEventId: number, sink: TerminalSseSink): TerminalSessionAttachResult;
|
|
93
|
+
/** No ownership check: removing a sink that was never attached (e.g. a foreign/unknown id) is already a safe no-op at the `@jini-ai/platform` layer, and detach carries no capability of its own. */
|
|
94
|
+
detach(id: string, sink: TerminalSseSink): void;
|
|
95
|
+
shutdownActive(options?: {
|
|
96
|
+
graceMs?: number;
|
|
97
|
+
}): Promise<void>;
|
|
98
|
+
}
|
|
99
|
+
export interface CreateTerminalSessionManagerOptions {
|
|
100
|
+
/** Injected for tests (a fake session manager without a real pty) or an alternate host wiring. @default a fresh `@jini-ai/platform` `TerminalService` backed by {@link loadRealSpawnPty}. */
|
|
101
|
+
readonly terminalService?: TerminalService;
|
|
102
|
+
/** @default {@link loadRealSpawnPty} */
|
|
103
|
+
readonly loadSpawnPty?: () => Promise<PtySpawn>;
|
|
104
|
+
readonly maxEvents?: number;
|
|
105
|
+
readonly maxBufferBytes?: number;
|
|
106
|
+
readonly exitTailBytes?: number;
|
|
107
|
+
readonly flushIntervalMs?: number;
|
|
108
|
+
readonly flushThresholdBytes?: number;
|
|
109
|
+
readonly ttlMs?: number;
|
|
110
|
+
readonly shutdownGraceMs?: number;
|
|
111
|
+
}
|
|
112
|
+
/**
|
|
113
|
+
* Builds the reference `TerminalSessionManager`: an in-process wrapper
|
|
114
|
+
* around a `@jini-ai/platform` `TerminalService` adding session ownership,
|
|
115
|
+
* the kill/write/resize lock, and (via {@link createTerminalToolRegistrations})
|
|
116
|
+
* `ToolExecutor` gating for creation. See module doc for the full design.
|
|
117
|
+
*/
|
|
118
|
+
export declare function createTerminalSessionManager(options?: CreateTerminalSessionManagerOptions): TerminalSessionManager;
|
|
119
|
+
export interface CreateTerminalToolRegistrationsOptions {
|
|
120
|
+
readonly manager: TerminalSessionManager;
|
|
121
|
+
/** @default {@link denyAllTerminalCreatePolicy} — see its doc for why a permissive default was rejected. */
|
|
122
|
+
readonly policy?: ToolPolicy;
|
|
123
|
+
readonly requiresConfirmation?: boolean;
|
|
124
|
+
readonly timeoutMs?: number;
|
|
125
|
+
}
|
|
126
|
+
export interface TerminalToolRegistrations {
|
|
127
|
+
readonly create: ToolRegistration;
|
|
128
|
+
}
|
|
129
|
+
/**
|
|
130
|
+
* Builds the `{descriptor, handler, policy}` triple a host registers
|
|
131
|
+
* against `@jini-ai/core`'s `ToolRegistry` so `terminal.create` becomes
|
|
132
|
+
* reachable only via `ToolExecutor.execute(principal, run,
|
|
133
|
+
* 'terminal.create', input)` — never by a route calling
|
|
134
|
+
* `manager.create()` directly, which would bypass authorization and the
|
|
135
|
+
* audit trail (matching `db-ops.ts`'s `createDaemonDbToolRegistrations`
|
|
136
|
+
* precedent).
|
|
137
|
+
*/
|
|
138
|
+
export declare function createTerminalToolRegistrations(options: CreateTerminalToolRegistrationsOptions): TerminalToolRegistrations;
|
|
139
|
+
//# sourceMappingURL=terminal-session.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"terminal-session.d.ts","sourceRoot":"","sources":["../src/terminal-session.ts"],"names":[],"mappings":"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"}
|