@jini-ai/daemon 0.5.4 → 0.6.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/agent-executor/contracts.d.ts +37 -5
- package/dist/agent-executor/event-translation.js +4 -0
- package/dist/agent-executor/events.d.ts +17 -2
- package/dist/agent-executor/events.js +245 -8
- package/dist/agent-executor/index.d.ts +2 -2
- package/dist/agent-executor/index.js +1 -1
- package/dist/agent-executor/launch.d.ts +11 -2
- package/dist/agent-executor/launch.js +62 -15
- package/dist/agent-executor/mcp-bridge.js +19 -6
- package/dist/agent-executor.d.ts +1 -1
- package/dist/agent-executor.js +1 -1
- package/dist/http/index.d.ts +5 -4
- package/dist/http/index.js +3 -2
- package/dist/http/research-tavily.adapter.d.ts +6 -0
- package/dist/http/research-tavily.adapter.js +109 -0
- package/dist/http/research.d.ts +20 -2
- package/dist/http/research.js +64 -149
- package/dist/http/route-manifest.js +2 -2
- package/dist/http/runs.d.ts +27 -2
- package/dist/http/runs.js +36 -1
- package/package.json +13 -13
|
@@ -2,7 +2,7 @@ import type { MessageAttachmentImage } from '../attachment-content.js';
|
|
|
2
2
|
import type { spawn as nodeSpawn, ChildProcess } from 'node:child_process';
|
|
3
3
|
import type { Principal } from '@jini-ai/core';
|
|
4
4
|
import type { RunAgentPayload, RunErrorPayload } from '@jini-ai/protocol';
|
|
5
|
-
import type { applyAgentLaunchEnv, ensureAgentCapabilities, resolveModelForLaunch, getAgentDef, resolveAgentLaunch, attachAcpSession, attachPiRpcSession, prepareAgentLogFile, preparePromptFileForAgent, AcpMcpServerInput, AcpPermissionHandler, PromptAugmenter } from '@jini-ai/agent-runtime';
|
|
5
|
+
import type { AgentRuntimeState, applyAgentLaunchEnv, ensureAgentCapabilities, resolveModelForLaunch, getAgentDef, resolveAgentLaunch, attachAcpSession, attachPiRpcSession, prepareAgentLogFile, preparePromptFileForAgent, AcpMcpServerInput, AcpPermissionHandler, PromptAugmenter } from '@jini-ai/agent-runtime';
|
|
6
6
|
import type { createCommandInvocation, listProcessSnapshots, ProcessSnapshot, StopProcessesResult } from '@jini-ai/platform';
|
|
7
7
|
import type { RunByteJournal } from '../continuation/journal.js';
|
|
8
8
|
import type { RunRetrySideEffectState } from '../run/core/index.js';
|
|
@@ -194,7 +194,27 @@ export interface AgentExecutor {
|
|
|
194
194
|
* `lifecycle.finish()` before this rejects (see index.ts module doc's Invariant).
|
|
195
195
|
*/
|
|
196
196
|
run(requiredArgs: Pick<AgentExecutorRunInput, "runId" | "agentId" | "prompt" | "cwd">, optionalArgs?: Pick<AgentExecutorRunInput, "model" | "reasoning" | "permissionMode" | "imagePaths" | "imageContents" | "extraAllowedDirs" | "uploadRoot" | "credentialEnv" | "env" | "resumeSessionId" | "newSessionId" | "disallowedTools" | "allowedTools" | "settingSources" | "settings">): Promise<void>;
|
|
197
|
+
/**
|
|
198
|
+
* Delivers a message the human sent while `runId` is going straight into its live agent process
|
|
199
|
+
* (see {@link UserMessageDelivery} for each outcome). A stream-json agent is interrupted first and
|
|
200
|
+
* gets the message once the CLI acknowledges the interrupt, so this settles in milliseconds (at
|
|
201
|
+
* most `INTERRUPT_ACK_TIMEOUT_MS`); it never waits on the agent's reply.
|
|
202
|
+
*/
|
|
203
|
+
sendUserMessage(requiredArgs: {
|
|
204
|
+
readonly runId: string;
|
|
205
|
+
readonly text: string;
|
|
206
|
+
}): Promise<UserMessageDelivery>;
|
|
197
207
|
}
|
|
208
|
+
/**
|
|
209
|
+
* What {@link AgentExecutor.sendUserMessage} did with a mid-run message:
|
|
210
|
+
* - `'delivered'` — the running turn was interrupted and the message written into the live
|
|
211
|
+
* session; the agent answers it next, in the same process and session.
|
|
212
|
+
* - `'unsupported'` — the run is live, but its agent has no way to take input mid-run (its prompt
|
|
213
|
+
* is plain text or an RPC request). The host should interrupt and send it as the next turn.
|
|
214
|
+
* - `'not-running'` — no live process will accept it: an unknown run, a finished one, or one whose
|
|
215
|
+
* last turn already ended and closed stdin. The run is ending; the host should send it next.
|
|
216
|
+
*/
|
|
217
|
+
export type UserMessageDelivery = 'delivered' | 'unsupported' | 'not-running';
|
|
198
218
|
/** Process discovery is a getter; process collection and stopping accept explicit host inputs. */
|
|
199
219
|
export type CollectProcessTreePidsPort = (args: {
|
|
200
220
|
readonly processes: ProcessSnapshot[];
|
|
@@ -212,11 +232,11 @@ export interface TerminateChildTreeDeps {
|
|
|
212
232
|
* Which step reported a contained failure through `onCleanupFailure` (SEC-007).
|
|
213
233
|
*
|
|
214
234
|
* The first three come from {@link terminateChildTreeBestEffort} (process-tree teardown). The last
|
|
215
|
-
*
|
|
216
|
-
*
|
|
217
|
-
* transition, and
|
|
235
|
+
* three cover tool cancellation, staged-file removal and the host's own `classifyFailure`.
|
|
236
|
+
* These fallible steps between a child's `'close'` and `finish()` must never prevent the terminal
|
|
237
|
+
* transition, and none may fail silently either. See each close handler.
|
|
218
238
|
*/
|
|
219
|
-
export type AgentCleanupFailurePhase = 'cancel' | 'acp-attach-failure' | 'pi-rpc-attach-failure' | 'staged-file-cleanup' | 'failure-classification';
|
|
239
|
+
export type AgentCleanupFailurePhase = 'cancel' | 'acp-attach-failure' | 'pi-rpc-attach-failure' | 'tool-cancellation' | 'staged-file-cleanup' | 'failure-classification';
|
|
220
240
|
export interface AgentCleanupFailureContext {
|
|
221
241
|
readonly runId: string;
|
|
222
242
|
readonly phase: AgentCleanupFailurePhase;
|
|
@@ -237,6 +257,8 @@ export interface StdinCloseHandle {
|
|
|
237
257
|
closeStdinOnce(): void;
|
|
238
258
|
/** Journals a sent-to-stdin byte chunk, queued through the same FIFO {@link wireChildLifecycle} already uses for emitted events. No-op when no journal was configured (see `CreateAgentExecutorOptions.journal`). */
|
|
239
259
|
recordSentBytes(content: string): void;
|
|
260
|
+
/** Interrupts this child's turn, then writes a mid-run user message into its open stdin — see {@link AgentExecutor.sendUserMessage}. */
|
|
261
|
+
sendUserMessage(text: string): Promise<UserMessageDelivery>;
|
|
240
262
|
}
|
|
241
263
|
/**
|
|
242
264
|
* Gap 3 (capability-routed continuation transport) — host-owned config for the
|
|
@@ -374,6 +396,13 @@ export interface McpJsonInjectionOptions {
|
|
|
374
396
|
readonly removeDir?: ({ path }: {
|
|
375
397
|
readonly path: string;
|
|
376
398
|
}) => Promise<void>;
|
|
399
|
+
/** `'codex-toml'` only. Links the run home's sessions/archived_sessions to the operator's
|
|
400
|
+
* persistent rollout store. Config and auth remain isolated and are removed after the run.
|
|
401
|
+
* @default Native mkdir (0700) and directory symlinks; errors fail staging before spawn. */
|
|
402
|
+
readonly linkSessionStore?: (required: {
|
|
403
|
+
runHome: string;
|
|
404
|
+
sourceHome: string;
|
|
405
|
+
}, optional?: {}) => Promise<void>;
|
|
377
406
|
}
|
|
378
407
|
/** One `.mcp.json` `mcpServers` entry — the shape Claude Code's own config schema expects. */
|
|
379
408
|
export interface McpJsonServerEntry {
|
|
@@ -542,6 +571,9 @@ export interface FailureClassificationContext {
|
|
|
542
571
|
*/
|
|
543
572
|
export type ClassifyFailure = (context: FailureClassificationContext) => boolean | Promise<boolean>;
|
|
544
573
|
export interface CreateAgentExecutorOptions {
|
|
574
|
+
/** Host environment snapshot; baseline spawn keys and source config paths are allowlisted. */
|
|
575
|
+
readonly hostEnv?: NodeJS.ProcessEnv;
|
|
576
|
+
readonly runtimeState?: AgentRuntimeState;
|
|
545
577
|
readonly lifecycle: RunLifecycle;
|
|
546
578
|
/** Resolves/pins the concrete starting model against the actual launch scope. */
|
|
547
579
|
readonly resolveModelForLaunch?: typeof resolveModelForLaunch;
|
|
@@ -39,11 +39,15 @@ function translateUsagePayload(rawEvent) {
|
|
|
39
39
|
const rawUsage = isRecord(rawEvent.usage) ? rawEvent.usage : undefined;
|
|
40
40
|
const usage = extractUsageTokens({ rawUsage: rawUsage });
|
|
41
41
|
const costUsd = asOptionalNumber(rawEvent.costUsd);
|
|
42
|
+
const cumulativeCostUsd = asOptionalNumber(rawEvent.cumulativeCostUsd);
|
|
43
|
+
const costSessionId = asOptionalString(rawEvent.costSessionId);
|
|
42
44
|
const durationMs = asOptionalNumber(rawEvent.durationMs);
|
|
43
45
|
return {
|
|
44
46
|
type: 'usage',
|
|
45
47
|
...(usage !== undefined ? { usage } : {}),
|
|
46
48
|
...(costUsd !== undefined ? { costUsd } : {}),
|
|
49
|
+
...(cumulativeCostUsd !== undefined ? { cumulativeCostUsd } : {}),
|
|
50
|
+
...(costSessionId !== undefined ? { costSessionId } : {}),
|
|
47
51
|
...(durationMs !== undefined ? { durationMs } : {}),
|
|
48
52
|
};
|
|
49
53
|
}
|
|
@@ -118,6 +118,21 @@ interface WireChildLifecycleContext extends TerminateChildTreeDeps {
|
|
|
118
118
|
* @overallScore 100/100
|
|
119
119
|
*/
|
|
120
120
|
export declare function wireChildLifecycle(ctx: WireChildLifecycleContext): StdinCloseHandle;
|
|
121
|
+
/**
|
|
122
|
+
* Whether a def's live process can take another user message mid-run: only a stream-json stdin
|
|
123
|
+
* transport keeps stdin open for more JSONL user lines (see `RuntimeAgentDef.promptInputFormat`).
|
|
124
|
+
* Deliberately not `resolveContinuationTransport`: that answers how a tool result gets back, and
|
|
125
|
+
* reports `'mcp-callback'` for Claude even though its stdin takes user lines all the same.
|
|
126
|
+
*/
|
|
127
|
+
export declare function acceptsMidRunUserMessages({ def }: {
|
|
128
|
+
readonly def: RuntimeAgentDef;
|
|
129
|
+
}): boolean;
|
|
130
|
+
/**
|
|
131
|
+
* How long a mid-run message waits for the CLI to acknowledge its interrupt before being written
|
|
132
|
+
* anyway. Claude Code acks within milliseconds (it answers before the aborted turn's own result);
|
|
133
|
+
* the ceiling only bounds an agent that ignores control requests.
|
|
134
|
+
*/
|
|
135
|
+
export declare const INTERRUPT_ACK_TIMEOUT_MS = 5000;
|
|
121
136
|
/**
|
|
122
137
|
* Writes the initial user turn to the child's stdin per `def.promptInputFormat`
|
|
123
138
|
* (both branches only run for `promptViaStdin: true` defs — the only shape
|
|
@@ -125,8 +140,8 @@ export declare function wireChildLifecycle(ctx: WireChildLifecycleContext): Stdi
|
|
|
125
140
|
* - `'text'` (default): the raw prompt buffer, then stdin is closed —
|
|
126
141
|
* matches `RuntimeAgentDef.promptInputFormat`'s own doc.
|
|
127
142
|
* - `'stream-json'`: one JSONL line wrapping the prompt as an Anthropic
|
|
128
|
-
* user message; stdin is deliberately left open
|
|
129
|
-
*
|
|
143
|
+
* user message; stdin is deliberately left open so a message the human
|
|
144
|
+
* sends mid-run can follow it (`StdinCloseHandle.sendUserMessage`), and
|
|
130
145
|
* {@link wireChildLifecycle}'s `turn_end` handling closes it once the
|
|
131
146
|
* agent's own stream reports the turn ended.
|
|
132
147
|
* @param def - The resolved agent def (only `.promptInputFormat` is read).
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { randomUUID } from 'node:crypto';
|
|
1
2
|
import { createModelReceiptTracker } from './model-receipts.js';
|
|
2
3
|
import { messageContentWithImages } from '../attachment-content.js';
|
|
3
4
|
import { redactSecrets, } from '@jini-ai/core';
|
|
@@ -8,7 +9,7 @@ import { resolveContinuationTransport, } from '../continuation/continuation-tran
|
|
|
8
9
|
import { resultContent, } from '../delegated-tool-bridge.js';
|
|
9
10
|
import { extractResultMedia, } from '../tool-result-media.js';
|
|
10
11
|
import { translateAgentRuntimeEvent, translateAcpError, applyAgentTranslationSideEffects, } from './event-translation.js';
|
|
11
|
-
import { errorMessage, } from './values.js';
|
|
12
|
+
import { errorMessage, isRecord, } from './values.js';
|
|
12
13
|
import { MCP_BRIDGE_UNAVAILABLE, unavailableJiniBridgeStatus, bridgeUnavailableMessage, } from './mcp-bridge.js';
|
|
13
14
|
/** Carry PID only on structured status so the host can record its OS start identity early.
|
|
14
15
|
* A PID alone is never proof of death; hosts verify PID reuse before native continuation. */
|
|
@@ -25,7 +26,7 @@ function statusWithChildIdentity({ payload, childPid }, _optional = {}) {
|
|
|
25
26
|
* parser's own documented behavior. Never called for `streamFormat:
|
|
26
27
|
* 'plain'` — `wireChildLifecycle` handles that format inline with no
|
|
27
28
|
* parser at all (see `ChildDrivenStreamFormat`'s doc).
|
|
28
|
-
* @param def - The resolved agent def (
|
|
29
|
+
* @param def - The resolved agent def (`.eventParser` and `.usageCostBasis` configure parser behavior).
|
|
29
30
|
* @param streamFormat - `def.streamFormat`, already narrowed by {@link isSupportedStreamFormat}.
|
|
30
31
|
* @param onEvent - Sink the parser calls once per parsed (or malformed-raw) event.
|
|
31
32
|
* @returns A `{feed, flush}` handle for the chosen parser.
|
|
@@ -35,7 +36,7 @@ function statusWithChildIdentity({ payload, childPid }, _optional = {}) {
|
|
|
35
36
|
function createStreamHandlerForDef(def, streamFormat, onEvent) {
|
|
36
37
|
switch (streamFormat) {
|
|
37
38
|
case 'claude-stream-json':
|
|
38
|
-
return createClaudeStreamHandler({ onEvent: onEvent });
|
|
39
|
+
return createClaudeStreamHandler({ onEvent: onEvent }, { costBasis: def.usageCostBasis ?? 'run' });
|
|
39
40
|
case 'copilot-stream-json':
|
|
40
41
|
return createCopilotStreamHandler({ onEvent: onEvent });
|
|
41
42
|
case 'qoder-stream-json':
|
|
@@ -68,7 +69,7 @@ export function defaultCleanupFailureSink(context) {
|
|
|
68
69
|
/**
|
|
69
70
|
* Reports a contained post-close failure through the host's sink, absorbing a throwing sink.
|
|
70
71
|
*
|
|
71
|
-
* A diagnostic sink is host code too, and the whole point of
|
|
72
|
+
* A diagnostic sink is host code too, and the whole point of these callers is that nothing
|
|
72
73
|
* between `'close'` and `finish()` can strand the run — a sink that throws must not reintroduce
|
|
73
74
|
* exactly that. Same reasoning `run-lifecycle.ts`'s `handleInactivityTimeout` already applies to its
|
|
74
75
|
* own `onInternalError`.
|
|
@@ -273,6 +274,37 @@ export function wireChildLifecycle(ctx) {
|
|
|
273
274
|
// consumed by a turn-end injection decision. See `ContinuationOptions`'s doc for why this is
|
|
274
275
|
// only ever acted on when a host has explicitly allowlisted the tool's name.
|
|
275
276
|
let pendingToolUse;
|
|
277
|
+
// Observe the canonical lifecycle, including delegated calls that bypass the CLI parser.
|
|
278
|
+
// A single latest tool_use cannot represent parallel tools at an interrupt boundary.
|
|
279
|
+
const unresolvedToolCalls = new Set();
|
|
280
|
+
const interruptedToolCalls = new Set();
|
|
281
|
+
const toolSubscription = lifecycle.stream({ runId, onEvent: (event) => {
|
|
282
|
+
if (event.kind !== 'agent')
|
|
283
|
+
return;
|
|
284
|
+
if (event.payload.type === 'tool_use')
|
|
285
|
+
unresolvedToolCalls.add(event.payload.id);
|
|
286
|
+
if (event.payload.type === 'tool_result')
|
|
287
|
+
unresolvedToolCalls.delete(event.payload.toolUseId);
|
|
288
|
+
} }).catch(error => {
|
|
289
|
+
// Observing tools is fallible I/O too: report it, but never strand close/finish on a replay
|
|
290
|
+
// failure or leave an unhandled rejection while the child is still running.
|
|
291
|
+
reportPostCloseFailure(ctx.onCleanupFailure, { runId, phase: 'tool-cancellation', pid: child.pid, error });
|
|
292
|
+
return null;
|
|
293
|
+
});
|
|
294
|
+
/** Run on the same FIFO as parsed results, after the aborted segment has drained.
|
|
295
|
+
* O(t) in unresolved calls; completed results are never replaced with cancellation. */
|
|
296
|
+
async function cancelUnresolvedToolCalls(ids) {
|
|
297
|
+
await toolSubscription;
|
|
298
|
+
for (const toolUseId of ids ?? [...unresolvedToolCalls]) {
|
|
299
|
+
if (!unresolvedToolCalls.has(toolUseId))
|
|
300
|
+
continue;
|
|
301
|
+
await lifecycle.emit({ runId, input: { event: 'agent', data: {
|
|
302
|
+
type: 'tool_result', toolUseId, content: 'Tool execution cancelled.', isError: true,
|
|
303
|
+
} } }).catch(error => {
|
|
304
|
+
reportPostCloseFailure(ctx.onCleanupFailure, { runId, phase: 'tool-cancellation', pid: child.pid, error });
|
|
305
|
+
});
|
|
306
|
+
}
|
|
307
|
+
}
|
|
276
308
|
// Bridge guard (see `expectsJiniBridge`): checked on the first init frame only. Once the bridge is
|
|
277
309
|
// found unavailable, the child is being stopped and nothing it still prints is forwarded.
|
|
278
310
|
let bridgeChecked = !ctx.expectsJiniBridge;
|
|
@@ -311,6 +343,71 @@ export function wireChildLifecycle(ctx) {
|
|
|
311
343
|
stdinClosed = true;
|
|
312
344
|
child.stdin?.end();
|
|
313
345
|
}
|
|
346
|
+
// Mid-run interrupts (see `sendUserMessage` below): each sent `interrupt` control request waits
|
|
347
|
+
// here, by request id, for the CLI's `control_response`. Settled with `true` on the ack, `false`
|
|
348
|
+
// when the process exits first. Bounded by the mid-run messages in flight on this one run.
|
|
349
|
+
const pendingInterruptAcks = new Map();
|
|
350
|
+
// Set once this run has interrupted its agent: from then on a turn the interrupt aborted
|
|
351
|
+
// (`aborted_*` stop reason) is not the run's last — the message that follows starts a new one.
|
|
352
|
+
let interruptSent = false;
|
|
353
|
+
// Claude Code's background tasks still running (a subagent or shell it started in the
|
|
354
|
+
// background), from its latest `background_tasks_changed` line, which lists them all. While any
|
|
355
|
+
// runs, an `end_turn` is not the run's end: the CLI keeps going until they finish and reports on
|
|
356
|
+
// them, so stdin must stay open for mid-run messages. Closing it there (2026-10-10, plannie chat)
|
|
357
|
+
// made every message sent while two subagents worked come back 'not-running' and wait for the run
|
|
358
|
+
// to end — and at EOF the CLI stops background tasks at its own wait ceiling (10 minutes).
|
|
359
|
+
let backgroundTaskCount = 0;
|
|
360
|
+
// Set when a turn ended and stdin stayed open only for background tasks: no turn is running, so a
|
|
361
|
+
// mid-run message has nothing to interrupt, and the last task finishing closes stdin (below).
|
|
362
|
+
let heldForBackgroundTasks = false;
|
|
363
|
+
// stdout carry-over for the control lines below; holds at most the current partial line.
|
|
364
|
+
let controlScanBuffer = '';
|
|
365
|
+
/** Resolves the waiting interrupt this `control_response` line acknowledges, if any. @complexity O(line length). */
|
|
366
|
+
function settleInterruptAck(line) {
|
|
367
|
+
const requestId = controlResponseRequestId({ line: line });
|
|
368
|
+
const settle = requestId === undefined ? undefined : pendingInterruptAcks.get(requestId);
|
|
369
|
+
if (!settle)
|
|
370
|
+
return;
|
|
371
|
+
pendingInterruptAcks.delete(requestId);
|
|
372
|
+
settle(true);
|
|
373
|
+
}
|
|
374
|
+
/**
|
|
375
|
+
* Tracks a `background_tasks_changed` line. The last background task finishing while stdin is
|
|
376
|
+
* held only for them closes it, exactly as the turn end would have: the CLI then answers what it
|
|
377
|
+
* still owes (the tasks' report) and exits. @complexity O(line length).
|
|
378
|
+
*/
|
|
379
|
+
function updateBackgroundTasks(line) {
|
|
380
|
+
const count = backgroundTaskListLength({ line: line });
|
|
381
|
+
if (count === undefined)
|
|
382
|
+
return;
|
|
383
|
+
backgroundTaskCount = count;
|
|
384
|
+
if (count === 0 && heldForBackgroundTasks) {
|
|
385
|
+
heldForBackgroundTasks = false;
|
|
386
|
+
closeStdinOnce();
|
|
387
|
+
}
|
|
388
|
+
}
|
|
389
|
+
/**
|
|
390
|
+
* Reads the stdout lines a mid-run message depends on: interrupt acks and background-task
|
|
391
|
+
* changes. Only agents that take mid-run messages are scanned. A chunk with no newline is only
|
|
392
|
+
* appended, so a long line split across many chunks is split once, not once per chunk.
|
|
393
|
+
* @complexity O(chunk length) amortized.
|
|
394
|
+
*/
|
|
395
|
+
function scanControlLines(text) {
|
|
396
|
+
if (!acceptsMidRunUserMessages({ def: def }))
|
|
397
|
+
return;
|
|
398
|
+
controlScanBuffer += text;
|
|
399
|
+
if (!text.includes('\n'))
|
|
400
|
+
return;
|
|
401
|
+
const lines = controlScanBuffer.split('\n');
|
|
402
|
+
controlScanBuffer = lines.pop() ?? '';
|
|
403
|
+
for (const line of lines) {
|
|
404
|
+
// Both checked: either word can also appear inside the other kind of line's text.
|
|
405
|
+
if (line.includes('"control_response"'))
|
|
406
|
+
settleInterruptAck(line);
|
|
407
|
+
if (line.includes('"background_tasks_changed"'))
|
|
408
|
+
updateBackgroundTasks(line);
|
|
409
|
+
}
|
|
410
|
+
}
|
|
314
411
|
/**
|
|
315
412
|
* Writes a structured (never string-concatenated — see `ContinuationOptions`'s doc on the
|
|
316
413
|
* prompt-injection stakes here) tool_result JSONL line, mirroring the shape
|
|
@@ -330,6 +427,26 @@ export function wireChildLifecycle(ctx) {
|
|
|
330
427
|
if (journal)
|
|
331
428
|
enqueueEmit(() => journal.record({ runId: runId, entry: sentJournalEntry(content) }));
|
|
332
429
|
}
|
|
430
|
+
/**
|
|
431
|
+
* Whether a `turn_end` leaves stdin open for a live agent that takes mid-run messages — and why:
|
|
432
|
+
* `'background-tasks'` when only background tasks keep the run going (no turn runs until the next
|
|
433
|
+
* message or task report), `'turn-continues'` for the reasons below, `'close'` otherwise. Open
|
|
434
|
+
* because the run is not over: a `tool_use` stop (the CLI runs the tool itself and carries on, and a
|
|
435
|
+
* message sent while the tool runs must still reach it), any end while an interrupt still waits
|
|
436
|
+
* for its ack (the message is about to be written), and the end of a turn an interrupt aborted
|
|
437
|
+
* (the message written after it starts the next turn), and any end while background tasks still
|
|
438
|
+
* run (see `backgroundTaskCount`). Every other end closes stdin, so the CLI exits once it has
|
|
439
|
+
* answered everything written before EOF.
|
|
440
|
+
*/
|
|
441
|
+
function stdinHoldAfterTurnEnd(stopReason) {
|
|
442
|
+
if (!acceptsMidRunUserMessages({ def: def }))
|
|
443
|
+
return 'close';
|
|
444
|
+
if (stopReason === 'tool_use' || pendingInterruptAcks.size > 0)
|
|
445
|
+
return 'turn-continues';
|
|
446
|
+
if (interruptSent && stopReason !== undefined && stopReason.startsWith('aborted'))
|
|
447
|
+
return 'turn-continues';
|
|
448
|
+
return backgroundTaskCount > 0 ? 'background-tasks' : 'close';
|
|
449
|
+
}
|
|
333
450
|
/**
|
|
334
451
|
* Decides, per `turn_end`, whether to auto-resolve a pending tool_use through the injected
|
|
335
452
|
* `ToolExecutor` and keep stdin open (gap 3), or close stdin exactly as every version of this
|
|
@@ -337,6 +454,11 @@ export function wireChildLifecycle(ctx) {
|
|
|
337
454
|
* unconfigured or the pending tool isn't allowlisted).
|
|
338
455
|
*/
|
|
339
456
|
function handleTurnEnd(stopReason) {
|
|
457
|
+
if (stopReason?.startsWith('aborted'))
|
|
458
|
+
enqueueEmit(async () => {
|
|
459
|
+
await cancelUnresolvedToolCalls([...interruptedToolCalls]);
|
|
460
|
+
interruptedToolCalls.clear();
|
|
461
|
+
});
|
|
340
462
|
const toolUse = pendingToolUse;
|
|
341
463
|
const shouldInject = stopReason === 'tool_use' &&
|
|
342
464
|
toolUse !== undefined &&
|
|
@@ -344,7 +466,10 @@ export function wireChildLifecycle(ctx) {
|
|
|
344
466
|
resolveContinuationTransport({ def: def }) === 'stdin-injection' &&
|
|
345
467
|
continuation.autonomousToolNames.has(toolUse.name);
|
|
346
468
|
if (!shouldInject) {
|
|
347
|
-
|
|
469
|
+
const hold = stdinHoldAfterTurnEnd(stopReason);
|
|
470
|
+
heldForBackgroundTasks = hold === 'background-tasks';
|
|
471
|
+
if (hold === 'close')
|
|
472
|
+
closeStdinOnce();
|
|
348
473
|
return;
|
|
349
474
|
}
|
|
350
475
|
pendingToolUse = undefined;
|
|
@@ -497,6 +622,10 @@ export function wireChildLifecycle(ctx) {
|
|
|
497
622
|
return;
|
|
498
623
|
}
|
|
499
624
|
enqueueEmit(() => lifecycle.emit({ runId: runId, input: { event: 'stdout', data: { chunk: text } } }));
|
|
625
|
+
// Before the parser: an ack and the aborted turn's end can share a chunk, and the turn end must
|
|
626
|
+
// see that no interrupt is still waiting (see `stdinHoldAfterTurnEnd`); a background task
|
|
627
|
+
// starting and the turn's end can share one too.
|
|
628
|
+
scanControlLines(text);
|
|
500
629
|
// Non-null: `streamHandler` is only ever null when `streamFormat === 'plain'` (see its
|
|
501
630
|
// construction above), the branch this statement is provably unreachable from.
|
|
502
631
|
streamHandler.feed({ chunk: text });
|
|
@@ -522,6 +651,9 @@ export function wireChildLifecycle(ctx) {
|
|
|
522
651
|
void terminateChildTreeBestEffort(ctx, child, runId, 'cancel', ctx.onCleanupFailure);
|
|
523
652
|
} });
|
|
524
653
|
child.on('close', (code, signal) => {
|
|
654
|
+
for (const settle of pendingInterruptAcks.values())
|
|
655
|
+
settle(false);
|
|
656
|
+
pendingInterruptAcks.clear();
|
|
525
657
|
void (async () => {
|
|
526
658
|
// Not wrapped in try/catch: all 4 supported parser factories'
|
|
527
659
|
// flush() implementations already internally guard their own
|
|
@@ -536,6 +668,11 @@ export function wireChildLifecycle(ctx) {
|
|
|
536
668
|
// `finish()`'s `'end'` event, exactly like every live-path emit already is.
|
|
537
669
|
flushBufferedStdout();
|
|
538
670
|
await emitQueue;
|
|
671
|
+
if (cancelRequested)
|
|
672
|
+
await cancelUnresolvedToolCalls();
|
|
673
|
+
const subscribedTools = await toolSubscription;
|
|
674
|
+
if (subscribedTools?.kind === 'ok')
|
|
675
|
+
subscribedTools.unsubscribe();
|
|
539
676
|
unsubscribeCancel();
|
|
540
677
|
// Both of the next two steps are guarded: neither a failed cleanup nor a rejecting host
|
|
541
678
|
// classifier may prevent the terminal transition below — see each helper's own doc.
|
|
@@ -554,14 +691,114 @@ export function wireChildLifecycle(ctx) {
|
|
|
554
691
|
await lifecycle.finish({ runId, status, code, signal: signal ?? null, resumable }, { ...(capturedSessionId !== undefined ? { sessionRef: capturedSessionId } : {}) });
|
|
555
692
|
})();
|
|
556
693
|
});
|
|
694
|
+
/**
|
|
695
|
+
* A mid-run message: first an `interrupt` control request on the still-open stdin, so the agent
|
|
696
|
+
* stops generating (or abandons the tool it is running) at once instead of finishing its whole
|
|
697
|
+
* reply; then, once the CLI acknowledges, the message as the next user line, which the CLI
|
|
698
|
+
* answers straight away in the same session; then the run's own `user_message` event through the
|
|
699
|
+
* same FIFO as the agent's output, so the message sits in the stream where it took effect.
|
|
700
|
+
* An ack that never comes (an agent that ignores control requests) only delays the write by
|
|
701
|
+
* {@link INTERRUPT_ACK_TIMEOUT_MS}: the CLI then folds the line in at its next step. Once
|
|
702
|
+
* `turn_end` has closed stdin, or the process exits before the ack, there is no session left to
|
|
703
|
+
* reach — `'not-running'`. Between turns, while stdin is held only for background tasks, there is
|
|
704
|
+
* no generation to stop: the line is written at once and starts the next turn.
|
|
705
|
+
*/
|
|
706
|
+
async function sendUserMessage(text) {
|
|
707
|
+
if (!acceptsMidRunUserMessages({ def: def }))
|
|
708
|
+
return 'unsupported';
|
|
709
|
+
const stdin = child.stdin;
|
|
710
|
+
if (stdinClosed || !stdin)
|
|
711
|
+
return 'not-running';
|
|
712
|
+
if (heldForBackgroundTasks) {
|
|
713
|
+
heldForBackgroundTasks = false;
|
|
714
|
+
writeUserMessage(stdin, text);
|
|
715
|
+
return 'delivered';
|
|
716
|
+
}
|
|
717
|
+
const requestId = `jini-interrupt-${randomUUID()}`;
|
|
718
|
+
interruptSent = true;
|
|
719
|
+
// Capture before requesting the interrupt. Its result can precede the acknowledgement, or
|
|
720
|
+
// arrive after the next segment starts: neither ordering may cancel that segment's new tools.
|
|
721
|
+
enqueueEmit(async () => {
|
|
722
|
+
await toolSubscription;
|
|
723
|
+
for (const id of interruptedToolCalls)
|
|
724
|
+
if (!unresolvedToolCalls.has(id))
|
|
725
|
+
interruptedToolCalls.delete(id);
|
|
726
|
+
for (const id of unresolvedToolCalls)
|
|
727
|
+
interruptedToolCalls.add(id);
|
|
728
|
+
});
|
|
729
|
+
const acked = new Promise((resolve) => pendingInterruptAcks.set(requestId, resolve));
|
|
730
|
+
stdin.write(`${JSON.stringify({ type: 'control_request', request_id: requestId, request: { subtype: 'interrupt' } })}\n`, 'utf8');
|
|
731
|
+
let timer;
|
|
732
|
+
const timedOut = new Promise((resolve) => {
|
|
733
|
+
timer = setTimeout(() => resolve(true), INTERRUPT_ACK_TIMEOUT_MS);
|
|
734
|
+
});
|
|
735
|
+
const processAlive = await Promise.race([acked, timedOut]);
|
|
736
|
+
clearTimeout(timer);
|
|
737
|
+
pendingInterruptAcks.delete(requestId);
|
|
738
|
+
if (!processAlive || stdinClosed)
|
|
739
|
+
return 'not-running';
|
|
740
|
+
writeUserMessage(stdin, text);
|
|
741
|
+
return 'delivered';
|
|
742
|
+
}
|
|
743
|
+
/** Writes a mid-run message as the next user line, journals it, and emits its `user_message` run event. */
|
|
744
|
+
function writeUserMessage(stdin, text) {
|
|
745
|
+
stdin.write(`${JSON.stringify(streamJsonUserMessage({ content: [{ type: 'text', text: text }] }))}\n`, 'utf8');
|
|
746
|
+
if (journal)
|
|
747
|
+
enqueueEmit(() => journal.record({ runId: runId, entry: sentJournalEntry(text) }));
|
|
748
|
+
enqueueEmit(() => lifecycle.emit({ runId: runId, input: { event: 'agent', data: { type: 'user_message', id: randomUUID(), text: text } } }));
|
|
749
|
+
}
|
|
557
750
|
return {
|
|
558
751
|
closeStdinOnce,
|
|
559
752
|
recordSentBytes(content) {
|
|
560
753
|
if (journal)
|
|
561
754
|
enqueueEmit(() => journal.record({ runId: runId, entry: sentJournalEntry(content) }));
|
|
562
755
|
},
|
|
756
|
+
sendUserMessage,
|
|
563
757
|
};
|
|
564
758
|
}
|
|
759
|
+
/**
|
|
760
|
+
* Whether a def's live process can take another user message mid-run: only a stream-json stdin
|
|
761
|
+
* transport keeps stdin open for more JSONL user lines (see `RuntimeAgentDef.promptInputFormat`).
|
|
762
|
+
* Deliberately not `resolveContinuationTransport`: that answers how a tool result gets back, and
|
|
763
|
+
* reports `'mcp-callback'` for Claude even though its stdin takes user lines all the same.
|
|
764
|
+
*/
|
|
765
|
+
export function acceptsMidRunUserMessages({ def }) {
|
|
766
|
+
return def.promptViaStdin === true && def.promptInputFormat === 'stream-json';
|
|
767
|
+
}
|
|
768
|
+
/**
|
|
769
|
+
* How long a mid-run message waits for the CLI to acknowledge its interrupt before being written
|
|
770
|
+
* anyway. Claude Code acks within milliseconds (it answers before the aborted turn's own result);
|
|
771
|
+
* the ceiling only bounds an agent that ignores control requests.
|
|
772
|
+
*/
|
|
773
|
+
export const INTERRUPT_ACK_TIMEOUT_MS = 5_000;
|
|
774
|
+
/** The `request_id` of a stream-json `control_response` line, or `undefined` for anything else. */
|
|
775
|
+
function controlResponseRequestId({ line }) {
|
|
776
|
+
try {
|
|
777
|
+
const parsed = JSON.parse(line);
|
|
778
|
+
if (!isRecord(parsed) || parsed.type !== 'control_response' || !isRecord(parsed.response))
|
|
779
|
+
return undefined;
|
|
780
|
+
return typeof parsed.response.request_id === 'string' ? parsed.response.request_id : undefined;
|
|
781
|
+
}
|
|
782
|
+
catch {
|
|
783
|
+
return undefined;
|
|
784
|
+
}
|
|
785
|
+
}
|
|
786
|
+
/** How many tasks a `background_tasks_changed` line lists, or `undefined` for any other line. */
|
|
787
|
+
function backgroundTaskListLength({ line }) {
|
|
788
|
+
try {
|
|
789
|
+
const parsed = JSON.parse(line);
|
|
790
|
+
if (!isRecord(parsed) || parsed.type !== 'system' || parsed.subtype !== 'background_tasks_changed')
|
|
791
|
+
return undefined;
|
|
792
|
+
return Array.isArray(parsed.tasks) ? parsed.tasks.length : undefined;
|
|
793
|
+
}
|
|
794
|
+
catch {
|
|
795
|
+
return undefined;
|
|
796
|
+
}
|
|
797
|
+
}
|
|
798
|
+
/** The stream-json stdin envelope for one user message — the initial prompt and every mid-run one. */
|
|
799
|
+
function streamJsonUserMessage({ content }) {
|
|
800
|
+
return { type: 'user', message: { role: 'user', content: content } };
|
|
801
|
+
}
|
|
565
802
|
/**
|
|
566
803
|
* Wires an ACP child to a run. Unlike the JSON-stream path, ACP owns the
|
|
567
804
|
* prompt protocol and reports its parsed events through `attachAcpSession`'s
|
|
@@ -773,8 +1010,8 @@ function wirePiRpcLifecycle(ctx) {
|
|
|
773
1010
|
* - `'text'` (default): the raw prompt buffer, then stdin is closed —
|
|
774
1011
|
* matches `RuntimeAgentDef.promptInputFormat`'s own doc.
|
|
775
1012
|
* - `'stream-json'`: one JSONL line wrapping the prompt as an Anthropic
|
|
776
|
-
* user message; stdin is deliberately left open
|
|
777
|
-
*
|
|
1013
|
+
* user message; stdin is deliberately left open so a message the human
|
|
1014
|
+
* sends mid-run can follow it (`StdinCloseHandle.sendUserMessage`), and
|
|
778
1015
|
* {@link wireChildLifecycle}'s `turn_end` handling closes it once the
|
|
779
1016
|
* agent's own stream reports the turn ended.
|
|
780
1017
|
* @param def - The resolved agent def (only `.promptInputFormat` is read).
|
|
@@ -789,7 +1026,7 @@ export function writePromptToStdin(def, child, prompt, handle) {
|
|
|
789
1026
|
if (!stdin)
|
|
790
1027
|
return;
|
|
791
1028
|
if (def.promptInputFormat === 'stream-json') {
|
|
792
|
-
const line = JSON.stringify({
|
|
1029
|
+
const line = JSON.stringify(streamJsonUserMessage({ content: messageContentWithImages({ prompt, images: handle.imageContents ?? [] }, {}) }));
|
|
793
1030
|
stdin.write(`${line}\n`, 'utf8');
|
|
794
1031
|
handle.recordSentBytes(prompt);
|
|
795
1032
|
return;
|
|
@@ -89,8 +89,8 @@
|
|
|
89
89
|
* a second, independently-built (and rejected) classifier that once lived in
|
|
90
90
|
* this module.
|
|
91
91
|
*/
|
|
92
|
-
export { type SupportedStreamFormat, type AgentExecutorCompatibility, type AgentRuntimeEventTranslation, type AgentExecutorErrorCode, AgentExecutorError, type AgentExecutorRunInput, type AgentExecutor, type CollectProcessTreePidsPort, type StopProcessesPort, type AgentCleanupFailurePhase, type AgentCleanupFailureContext, type ContinuationOptions, type McpJsonInjectionOptions, type McpBridgeDelivery, type PreparedCodexHome, type PreparedClaudeConfigDir, type ClaudeConfigDirSeams, type ClaudeConfigDirIsolationOptions, type FailureClassificationContext, type ClassifyFailure, type CreateAgentExecutorOptions, type SystemPromptOverlayDelivery, type PreparedSystemPromptOverlayFile, type SpawnAgentChildProcessResult, } from './contracts.js';
|
|
93
|
-
export { isSupportedStreamFormat, assessAgentExecutorCompatibility, isAgentExecutorSupported, resolveDefAndStreamFormat, resolveImageDeliveryAndArgvBudget, resolveRunEnv, resolveLaunch, stagePromptFile, stageLogFile, computeChildEnv, computeRuntimeContext, buildAgentBuildArgsOptions, resolveSystemPromptOverlayDelivery, buildRunArgs, prepareSystemPromptOverlayFileIfNeeded, guardWindowsCommandLineBudget, spawnAgentChildProcess, isStdinDrivenFormat, confirmChildSpawned, createAgentExecutor, } from './launch.js';
|
|
92
|
+
export { type SupportedStreamFormat, type AgentExecutorCompatibility, type AgentRuntimeEventTranslation, type AgentExecutorErrorCode, AgentExecutorError, type AgentExecutorRunInput, type AgentExecutor, type UserMessageDelivery, type CollectProcessTreePidsPort, type StopProcessesPort, type AgentCleanupFailurePhase, type AgentCleanupFailureContext, type ContinuationOptions, type McpJsonInjectionOptions, type McpBridgeDelivery, type PreparedCodexHome, type PreparedClaudeConfigDir, type ClaudeConfigDirSeams, type ClaudeConfigDirIsolationOptions, type FailureClassificationContext, type ClassifyFailure, type CreateAgentExecutorOptions, type SystemPromptOverlayDelivery, type PreparedSystemPromptOverlayFile, type SpawnAgentChildProcessResult, } from './contracts.js';
|
|
93
|
+
export { isSupportedStreamFormat, assessAgentExecutorCompatibility, isAgentExecutorSupported, resolveDefAndStreamFormat, resolveImageDeliveryAndArgvBudget, resolveRunEnv, selectAgentExecutorHostEnv, resolveLaunch, stagePromptFile, stageLogFile, computeChildEnv, computeRuntimeContext, buildAgentBuildArgsOptions, resolveSystemPromptOverlayDelivery, buildRunArgs, prepareSystemPromptOverlayFileIfNeeded, guardWindowsCommandLineBudget, spawnAgentChildProcess, isStdinDrivenFormat, confirmChildSpawned, createAgentExecutor, } from './launch.js';
|
|
94
94
|
export { extractUsageTokens, translateStatusEvent, translateToolResultEvent, translateErrorEvent, translateTurnEndEvent, translateAgentRuntimeEvent, applyAgentTranslationSideEffects, } from './event-translation.js';
|
|
95
95
|
export { MCP_BRIDGE_UNAVAILABLE, unavailableJiniBridgeStatus, buildMcpJsonServerEntry, mergeMcpJsonContent, buildAcpMcpBridgeServers, mergeEnvContentMcpConfig, mergeEnvContentInstructions, buildCodexMcpServerToml, buildCodexHomeConfigToml, resolveSourceCodexHomeDir, buildMcpBridgeDelivery, resolveSourceClaudeConfigDir, resolveMcpBridgeForRun, writeMcpJsonIfNeeded, prepareCodexHomeIfNeeded, prepareClaudeConfigDirIfNeeded, } from './mcp-bridge.js';
|
|
96
96
|
export { DEFAULT_BUFFERED_STDOUT_MAX_BYTES, runAcpDispatch, runPiRpcDispatch, } from './events.js';
|
|
@@ -90,7 +90,7 @@
|
|
|
90
90
|
* this module.
|
|
91
91
|
*/
|
|
92
92
|
export { AgentExecutorError, } from './contracts.js';
|
|
93
|
-
export { isSupportedStreamFormat, assessAgentExecutorCompatibility, isAgentExecutorSupported, resolveDefAndStreamFormat, resolveImageDeliveryAndArgvBudget, resolveRunEnv, resolveLaunch, stagePromptFile, stageLogFile, computeChildEnv, computeRuntimeContext, buildAgentBuildArgsOptions, resolveSystemPromptOverlayDelivery, buildRunArgs, prepareSystemPromptOverlayFileIfNeeded, guardWindowsCommandLineBudget, spawnAgentChildProcess, isStdinDrivenFormat, confirmChildSpawned, createAgentExecutor, } from './launch.js';
|
|
93
|
+
export { isSupportedStreamFormat, assessAgentExecutorCompatibility, isAgentExecutorSupported, resolveDefAndStreamFormat, resolveImageDeliveryAndArgvBudget, resolveRunEnv, selectAgentExecutorHostEnv, resolveLaunch, stagePromptFile, stageLogFile, computeChildEnv, computeRuntimeContext, buildAgentBuildArgsOptions, resolveSystemPromptOverlayDelivery, buildRunArgs, prepareSystemPromptOverlayFileIfNeeded, guardWindowsCommandLineBudget, spawnAgentChildProcess, isStdinDrivenFormat, confirmChildSpawned, createAgentExecutor, } from './launch.js';
|
|
94
94
|
export { extractUsageTokens, translateStatusEvent, translateToolResultEvent, translateErrorEvent, translateTurnEndEvent, translateAgentRuntimeEvent, applyAgentTranslationSideEffects, } from './event-translation.js';
|
|
95
95
|
export { MCP_BRIDGE_UNAVAILABLE, unavailableJiniBridgeStatus, buildMcpJsonServerEntry, mergeMcpJsonContent, buildAcpMcpBridgeServers, mergeEnvContentMcpConfig, mergeEnvContentInstructions, buildCodexMcpServerToml, buildCodexHomeConfigToml, resolveSourceCodexHomeDir, buildMcpBridgeDelivery, resolveSourceClaudeConfigDir, resolveMcpBridgeForRun, writeMcpJsonIfNeeded, prepareCodexHomeIfNeeded, prepareClaudeConfigDirIfNeeded, } from './mcp-bridge.js';
|
|
96
96
|
export { DEFAULT_BUFFERED_STDOUT_MAX_BYTES, runAcpDispatch, runPiRpcDispatch, } from './events.js';
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { spawn as nodeSpawn, type ChildProcess } from 'node:child_process';
|
|
2
|
-
import { getAgentDef, resolveAgentLaunch, prepareAgentLogFile, preparePromptFileForAgent, type AgentLaunchResolution, type PreparedAgentLogFile, type PreparedPromptFile, type RuntimeAgentDef, type RuntimeBuildOptions, type RuntimeContext } from '@jini-ai/agent-runtime';
|
|
2
|
+
import { type AgentRuntimeState, getAgentDef, resolveAgentLaunch, prepareAgentLogFile, preparePromptFileForAgent, type AgentLaunchResolution, type PreparedAgentLogFile, type PreparedPromptFile, type RuntimeAgentDef, type RuntimeBuildOptions, type RuntimeContext } from '@jini-ai/agent-runtime';
|
|
3
3
|
import { createCommandInvocation } from '@jini-ai/platform';
|
|
4
4
|
import { type ImagePromptDelivery } from '../image-prompt-delivery.js';
|
|
5
5
|
import { type SupportedStreamFormat, type ChildDrivenStreamFormat, type AgentExecutorCompatibility, type AgentExecutorRunInput, type AgentExecutor, type McpBridgeDelivery, type CreateAgentExecutorOptions, type FailBeforeSpawn, type SystemPromptOverlayDelivery, type PreparedSystemPromptOverlayFile, type SpawnAgentChildProcessResult } from './contracts.js';
|
|
@@ -53,6 +53,13 @@ export declare function assessAgentExecutorCompatibility({ def }: {
|
|
|
53
53
|
export declare function isAgentExecutorSupported({ def }: {
|
|
54
54
|
readonly def: RuntimeAgentDef;
|
|
55
55
|
}): boolean;
|
|
56
|
+
/** Snapshot only host configuration used by spawn and config staging; credentials stay per-run.
|
|
57
|
+
* Returns an independent allowlisted record. @complexity O(1), fixed key list. */
|
|
58
|
+
export declare function selectAgentExecutorHostEnv({ env }: {
|
|
59
|
+
env: NodeJS.ProcessEnv;
|
|
60
|
+
}, { runtimeState }?: {
|
|
61
|
+
runtimeState?: AgentRuntimeState;
|
|
62
|
+
}): NodeJS.ProcessEnv;
|
|
56
63
|
interface ResolvedDefAndFormat {
|
|
57
64
|
readonly def: RuntimeAgentDef;
|
|
58
65
|
readonly streamFormat: SupportedStreamFormat;
|
|
@@ -236,6 +243,8 @@ export declare function resolveSystemPromptOverlayDelivery(input: {
|
|
|
236
243
|
readonly overlay: string | null | undefined;
|
|
237
244
|
readonly prompt: string;
|
|
238
245
|
readonly resumeSessionId: string | null | undefined;
|
|
246
|
+
}, { state }?: {
|
|
247
|
+
state?: AgentRuntimeState;
|
|
239
248
|
}): SystemPromptOverlayDelivery;
|
|
240
249
|
/**
|
|
241
250
|
* Phase 9b: calls the def's `buildArgs`, releasing staged resources and failing the run on a throw.
|
|
@@ -370,6 +379,6 @@ export declare function confirmChildSpawned({ input, deps }: {
|
|
|
370
379
|
* @complexity `run()`'s own setup is O(1); steady-state cost is the chosen stream parser's.
|
|
371
380
|
* @overallScore 100/100
|
|
372
381
|
*/
|
|
373
|
-
export declare function createAgentExecutor(requiredArgs: Pick<CreateAgentExecutorOptions, "lifecycle">, optionalArgs?: Pick<CreateAgentExecutorOptions, "getAgentDef" | "resolveAgentLaunch" | "resolveModelForLaunch" | "ensureAgentCapabilities" | "applyAgentLaunchEnv" | "createCommandInvocation" | "spawn" | "attachAcpSession" | "acpPermissionHandler" | "attachPiRpcSession" | "preparePromptFileForAgent" | "prepareAgentLogFile" | "listProcessSnapshots" | "collectProcessTreePids" | "stopProcesses" | "onCleanupFailure" | "journal" | "continuation" | "classifyFailure" | "mcpJsonInjection" | "claudeConfigDirIsolation" | "claudeConfigDirIsolationEnabled" | "bufferedStdoutMaxBytes" | "promptAugmenter">): AgentExecutor;
|
|
382
|
+
export declare function createAgentExecutor(requiredArgs: Pick<CreateAgentExecutorOptions, "lifecycle">, optionalArgs?: Pick<CreateAgentExecutorOptions, "runtimeState" | "hostEnv" | "getAgentDef" | "resolveAgentLaunch" | "resolveModelForLaunch" | "ensureAgentCapabilities" | "applyAgentLaunchEnv" | "createCommandInvocation" | "spawn" | "attachAcpSession" | "acpPermissionHandler" | "attachPiRpcSession" | "preparePromptFileForAgent" | "prepareAgentLogFile" | "listProcessSnapshots" | "collectProcessTreePids" | "stopProcesses" | "onCleanupFailure" | "journal" | "continuation" | "classifyFailure" | "mcpJsonInjection" | "claudeConfigDirIsolation" | "claudeConfigDirIsolationEnabled" | "bufferedStdoutMaxBytes" | "promptAugmenter">): AgentExecutor;
|
|
374
383
|
export {};
|
|
375
384
|
//# sourceMappingURL=launch.d.ts.map
|