@jini-ai/daemon 0.6.9 → 0.6.11

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.
Files changed (41) hide show
  1. package/CHANGELOG.md +157 -0
  2. package/dist/agent-executor/contracts.d.ts +34 -11
  3. package/dist/agent-executor/event-translation.js +2 -0
  4. package/dist/agent-executor/events.d.ts +7 -15
  5. package/dist/agent-executor/events.js +142 -194
  6. package/dist/agent-executor/launch.d.ts +9 -3
  7. package/dist/agent-executor/launch.js +104 -8
  8. package/dist/agent-executor/live-session-state.d.ts +23 -0
  9. package/dist/agent-executor/live-session-state.js +155 -0
  10. package/dist/agent-executor/mcp-bridge.d.ts +3 -1
  11. package/dist/agent-executor/mcp-bridge.js +9 -2
  12. package/dist/agent-executor/message-relay.d.ts +39 -0
  13. package/dist/agent-executor/message-relay.js +56 -0
  14. package/dist/core/read-only-tools.d.ts +9 -4
  15. package/dist/core/read-only-tools.js +10 -7
  16. package/dist/core/tool-candidates.d.ts +8 -3
  17. package/dist/core/tool-candidates.js +39 -4
  18. package/dist/delegated-result-correlation.d.ts +26 -0
  19. package/dist/delegated-result-correlation.js +68 -0
  20. package/dist/delegated-tool-bridge.d.ts +5 -13
  21. package/dist/delegated-tool-bridge.js +19 -58
  22. package/dist/http/attachments.d.ts +13 -0
  23. package/dist/http/attachments.js +27 -1
  24. package/dist/http/delegated-tools.d.ts +3 -0
  25. package/dist/http/delegated-tools.js +2 -2
  26. package/dist/http/index.d.ts +2 -1
  27. package/dist/http/index.js +3 -1
  28. package/dist/http/message-relay.d.ts +21 -0
  29. package/dist/http/message-relay.js +44 -0
  30. package/dist/http/runs.d.ts +5 -2
  31. package/dist/http/runs.js +11 -5
  32. package/dist/index.d.ts +2 -0
  33. package/dist/index.js +1 -0
  34. package/dist/run-lifecycle.d.ts +20 -1
  35. package/dist/run-lifecycle.js +2 -16
  36. package/dist/tool-executor.js +5 -4
  37. package/dist/tool-result-diagnostics.d.ts +27 -0
  38. package/dist/tool-result-diagnostics.js +77 -0
  39. package/dist/tool-result-media.d.ts +27 -14
  40. package/dist/tool-result-media.js +51 -38
  41. package/package.json +14 -14
package/CHANGELOG.md CHANGED
@@ -1,3 +1,160 @@
1
+ ## 0.6.11
2
+
3
+ ### Patch Changes
4
+
5
+ - Mid-run message relay for MCP-bridged engines (Codex, ACP, Antigravity): `registerMessageRelayRoutes` on `@jini-ai/daemon/http`; mid-run messages queue instead of interrupting, and recovery waits on an uncertain probe.
6
+ - Site agents are confined to the site folder: Claude file tools are bounded to the site root and private temp dir, and attachments are staged inside the site (`stageAttachmentClaim`).
7
+ - Tool inputs apply a sole near-miss and declared input aliases; plugin-load outcomes are reported; `web_fetch` reads SVG/JS as text; `content_read` suggests its resource first; the browser falls back to system Chrome.
8
+ - Updated dependencies
9
+ - Updated dependencies
10
+ - Updated dependencies
11
+ - @jini-ai/core@0.6.11
12
+ - @jini-ai/protocol@0.6.11
13
+
14
+ ## 0.6.10
15
+
16
+ ### Patch Changes
17
+
18
+ - 4f52784: Stop advertising agents `AgentExecutor` cannot run.
19
+
20
+ The built-in `agents` feature scanned every runtime definition, but `AgentExecutor` rejects some of
21
+ them (`antigravity`, whose deferral is documented in that module). A consumer could therefore offer a
22
+ user an agent that failed the instant it was selected, with the mismatch visible nowhere.
23
+
24
+ - `@jini-ai/daemon` exports `isAgentExecutorSupported(def)` and `assessAgentExecutorCompatibility(def)`.
25
+ `run()` now consumes the latter instead of re-checking the conditions itself, so the discovery-time
26
+ answer and the run-time guards cannot drift apart. Error messages are unchanged.
27
+ - `@jini-ai/server`'s `agents` feature applies the predicate by default, and exports
28
+ `isExecutableDetectedAgent` for hosts that want it directly.
29
+
30
+ `antigravity`'s definition remains in `@jini-ai/agent-runtime` — the predicate is advisory, and a
31
+ non-`AgentExecutor` launch path can ignore it. An id with no registered def is kept rather than
32
+ dropped, so a host supplying its own `detector` is unaffected.
33
+
34
+ Note for anyone implementing something similar: the predicate deliberately takes the full
35
+ `RuntimeAgentDef`, not a projected `DetectedAgent`. That projection omits `maxPromptArgBytes`, and the
36
+ argv-bound defs (`aider`, `deepseek`) qualify solely through it — judging the projection would have
37
+ dropped two working agents while fixing one broken one.
38
+
39
+ - 8ff5653: Drive Antigravity (`agy`) — the 24th and last agent definition `AgentExecutor` rejected.
40
+
41
+ `AgentExecutor` drove 23 of 24 registered definitions. Antigravity was rejected by an explicit
42
+ `def.id === 'antigravity'` guard, for two reasons that are real but narrow:
43
+
44
+ - **`agy` can print an OAuth sign-in URL to stdout and still exit 0.** Streaming stdout live shows
45
+ that URL to the user as if it were the model's reply — a URL that carries the daemon operator's
46
+ `client_id`/`redirect_uri` into a chat transcript, and that is useless to click anyway (`agy -p`
47
+ print mode has no field to paste the resulting auth code into).
48
+ - **`agy` has no `--model` flag.** The model choice is written into one process-global
49
+ `~/.gemini/antigravity-cli/settings.json` that `agy` reads on its own startup, so two concurrent
50
+ runs race: run A writes model A, A spawns, B writes model B, and only _then_ does A's `agy` read
51
+ the file — so A silently executes on B's model.
52
+
53
+ Both are now met by **declarative `RuntimeAgentDef` fields the executor reads generically**, joining
54
+ the 14 optional behavior flags (`promptViaFile`, `authProbe`, …) that already work this way. There is
55
+ no agent-id branch anywhere in the dispatch path — a deliberate divergence from Open Design's own
56
+ daemon, which hardcodes the id twice.
57
+
58
+ New on `@jini-ai/agent-runtime`'s `RuntimeAgentDef`:
59
+
60
+ - `needsAgentLogFile?: boolean` — asks the caller to stage a temp path and pass it as
61
+ `RuntimeContext.agentLogFilePath` before `buildArgs` runs, mirroring `promptViaFile`. Staged by the
62
+ new `prepareAgentLogFile(def, label)` (the sibling of `preparePromptFileForAgent`; it creates only
63
+ the `0o700` containing directory, since the log file is output the CLI authors, not input we do).
64
+ - `stdoutPolicy?: RuntimeStdoutPolicy` — `{buffering: 'live'}` (the default, and every other
65
+ definition's behavior) or `{buffering: 'until-close', sanitize?}`. A discriminated union rather
66
+ than two flat fields on purpose: a sanitizer is only meaningful on the buffered path, because the
67
+ pattern to redact can straddle two `'data'` chunks. Two independent flags would let a definition
68
+ declare a sanitizer the caller could not honor — a confidentiality gap that _looks_ closed.
69
+ - `runtimeLock?: RuntimeLock` — a mutex around a process-global side effect `buildArgs` performs.
70
+ Acquired before `buildArgs`, released on whichever of `waitForHandoff` settling or process exit
71
+ comes first. Releasing on exit is load-bearing, not a fallback: a watcher that stops polling means
72
+ "I stopped watching", never "the child definitely didn't read the file".
73
+
74
+ All three are stripped from the `DetectedAgent` registry projection. They instruct whoever _spawns_
75
+ the CLI, not whoever lists agents — and two carry closures, which `JSON.stringify` would flatten into
76
+ a misleading `{"buffering":"until-close"}` / `{}` rather than omit.
77
+
78
+ In `@jini-ai/daemon`, `AgentExecutor` now stages a log file when `needsAgentLogFile` is set (released
79
+ on every pre-spawn, spawn-failure, and close path alongside the prompt file, through one composed
80
+ `cleanupStagedFiles` closure), calls `runtimeLock.acquire()` before `buildArgs`, and branches its
81
+ `streamFormat: 'plain'` stdout handling on `stdoutPolicy`. `assessAgentExecutorCompatibility` no
82
+ longer rejects anything by id, and `isAgentExecutorSupported` now accepts all 24 definitions.
83
+
84
+ **No behavior change for any other agent.** Antigravity is the only definition declaring any of the
85
+ three fields; the other four `streamFormat: 'plain'` definitions (`grok-build`, `aider`, `deepseek`,
86
+ `qwen`) keep streaming live, per chunk, which `aider`'s and `deepseek`'s own comments call out as
87
+ deliberate. That is pinned by an explicit regression test rather than left implied.
88
+
89
+ One thing worth knowing if you consume the run event stream: on the buffered path the raw `'stdout'`
90
+ echo is held back and sanitized too, not just the `'agent'`/`text_delta` copy. Emitting an
91
+ unsanitized raw echo while withholding the chat copy would leak the exact string the sanitizer exists
92
+ to remove to any subscriber. The opt-in byte journal still records raw bytes per chunk — that is its
93
+ documented contract, and it deliberately lives in a separate `EventLog` instance that is never
94
+ replayed to run-event subscribers.
95
+
96
+ - 3fe4d14: Store tool-result images once in media, preserve model-facing pixels, and provide opt-in digest-verified echo summaries and bounded image-safe diagnostics. Hosts with exact-byte journaling must inject a separate stdout blob/reference writer.
97
+
98
+ Preserve conflicting image representations during digest verification, and keep the required bridge executor authoritative when route dependencies supply optional settings.
99
+
100
+ - e16a907: Choose reported-cost semantics from agent definition metadata rather than a vendor id; absent metadata retains per-run behavior.
101
+ - 4f52784: Add `createRunScopedContextStore` and widen `ResolvedRunInput` with the executor's optional inputs.
102
+
103
+ **`createRunScopedContextStore<T>({ lifecycle })`** — bind/resolve/auto-evict keyed by run id, for
104
+ host-owned context that must survive the gap between starting a run and a later delegated call that
105
+ carries only that run's id. `resolve` fails closed (`RunContextNotBoundError`) rather than fabricating a
106
+ default, and bindings are evicted when the run reaches a terminal state.
107
+
108
+ `resolveRunInput` could already decode and stash such context, but it is handed no lifecycle and so
109
+ cannot register the eviction half — leaving a map that only grows and keeps stale authority resolvable.
110
+ Owning both halves together is the point. `T` is fully generic: this helper does not decode
111
+ `contextRef`, does not sign or verify anything, and has no notion of a principal. It is in-memory only,
112
+ and says so — after a restart every `resolve` fails, which is the correct posture rather than a gap.
113
+
114
+ **`ResolvedRunInput` now carries `permissionMode`, `model`, `reasoning`, and `credentialEnv`**, each
115
+ forwarded to `AgentExecutor.run()` only when present.
116
+
117
+ `permissionMode` is the load-bearing one and closes a real trap: every def with an auto-approve flag
118
+ (`bypassPermissions` / `--yolo` / `--dangerously-skip-permissions`) applies it by default when the field
119
+ is absent. A host that had been passing `'restricted'` to `AgentExecutor.run()` by hand and then adopted
120
+ `createDefaultRunStartHandler` would silently have started auto-approving every action — a security
121
+ regression wearing the clothes of a refactor. Existing behavior is unchanged: omitted fields are omitted
122
+ from the executor call, never passed as an explicit `undefined`.
123
+
124
+ - 4f52784: Add a `sidecar-strict` security mode and per-run MCP credential propagation.
125
+
126
+ For a daemon whose threat model is **another process running as the same OS user** rather than a
127
+ remote attacker, the existing `jini-local` mode is a no-op: `registerApiBearerAuthMiddleware`
128
+ short-circuits for any loopback peer before it reads the `Authorization` header, and a `127.0.0.1`
129
+ bind keeps remote hosts out while doing nothing about a co-resident process. A consumer that spawns a
130
+ Jini daemon holding real authority — starting agent runs, executing tools against a real database —
131
+ previously had to write its own middleware.
132
+
133
+ - `@jini-ai/http-kit` gains `requireStrictBearerToken`: fail-closed 503 when the named token env var
134
+ is unset, 401 on mismatch, **no loopback exemption and no disable flag**. Its `tokenEnvVar` is
135
+ required with no default, so this package never names a host's secret.
136
+ - `composeJiniKernel` gains `security: { mode: 'sidecar-strict', host, tokenEnvVar, exemptPaths? }`.
137
+ Purely additive — `host` and `jini-local` are unchanged by construction, since the modes are arms of
138
+ a discriminated union. The strict gate mounts ahead of the JSON body parser, so a caller it rejects
139
+ never has its body parsed.
140
+ - `@jini-ai/daemon`'s `McpJsonInjectionOptions` gains `credential?: (runId) => string | Promise<string>`
141
+ — a **resolver, not a string**, because injection options are built once before any run exists and a
142
+ boot-wide shared secret would defeat the point of scoping a credential to a run. It is delivered to
143
+ the child as `JINI_DAEMON_TOKEN`.
144
+ - `@jini-ai/mcp`'s `jini-mcp` reads that variable and attaches `Authorization` to every daemon call.
145
+ Optional throughout: with no credential, request headers and `.mcp.json` output are byte-identical
146
+ to before.
147
+
148
+ Also generalized: both existing bearer gates now compare tokens in constant time (`timingSafeEqual`)
149
+ and share one header-parsing helper, closing a timing side channel and removing a duplicated regex.
150
+
151
+ - Updated dependencies [22f0619]
152
+ - Updated dependencies [82ed2d3]
153
+ - Updated dependencies [3fe4d14]
154
+ - Updated dependencies [5a3de86]
155
+ - @jini-ai/core@0.6.10
156
+ - @jini-ai/protocol@0.6.10
157
+
1
158
  ## 0.6.9 — 2026-10-22
2
159
 
3
160
  - 2026-10-22: Memory fixes (bounded event log and tool-executor audit), chromeIntegration option, provider-plugin registration, coverage.
@@ -1,9 +1,11 @@
1
+ import type { DelegatedResultCorrelation } from '../delegated-result-correlation.js';
2
+ import type { StdoutJournalBlobPort } from '../tool-result-diagnostics.js';
1
3
  import type { MessageAttachmentImage } from '../attachment-content.js';
2
4
  import type { probeMcpBridge } from './mcp-bridge-probe.js';
3
5
  import type { spawn as nodeSpawn, ChildProcess } from 'node:child_process';
4
6
  import type { Principal } from '@jini-ai/core';
5
- import type { RunAgentPayload, RunErrorPayload } from '@jini-ai/protocol';
6
- import type { AgentRuntimeState, applyAgentLaunchEnv, ensureAgentCapabilities, resolveModelForLaunch, getAgentDef, resolveAgentLaunch, attachAcpSession, attachPiRpcSession, prepareAgentLogFile, preparePromptFileForAgent, AcpMcpServerInput, AcpPermissionHandler, PromptAugmenter } from '@jini-ai/agent-runtime';
7
+ import type { RunAgentPayload, RunErrorPayload, MessageRelayVia, RelayedUserMessage } from '@jini-ai/protocol';
8
+ import type { AgentRuntimeState, applyAgentLaunchEnv, ensureAgentCapabilities, assertClaudeFilesystemSupport, resolveModelForLaunch, getAgentDef, resolveAgentLaunch, attachAcpSession, attachPiRpcSession, prepareAgentLogFile, preparePromptFileForAgent, AcpMcpServerInput, AcpPermissionHandler, PromptAugmenter } from '@jini-ai/agent-runtime';
7
9
  import type { createCommandInvocation } from '@jini-ai/platform/command';
8
10
  import type { listProcessSnapshots, ProcessSnapshot, StopProcessesResult } from '@jini-ai/platform/process';
9
11
  import type { RunByteJournal } from '../continuation/journal.js';
@@ -92,7 +94,7 @@ export type AgentRuntimeEventTranslation = {
92
94
  readonly kind: 'ignored';
93
95
  };
94
96
  /** Machine-readable failure reasons `run()` can reject with — every one is preceded by a `lifecycle.finish({status:'failed'})` call (see index.ts module doc's Invariant section). */
95
- export type AgentExecutorErrorCode = 'NATIVE_TOOL_POLICY_UNSUPPORTED' | 'AGENT_MODEL_UNRESOLVED' | 'AGENT_PERMISSION_MODE_INVALID' | 'AGENT_NOT_FOUND' | 'AGENT_RUNTIME_UNSUPPORTED' | 'AGENT_BINARY_NOT_RESOLVED' | 'AGENT_SPAWN_FAILED' | 'AGENT_PROMPT_TOO_LARGE';
97
+ export type AgentExecutorErrorCode = 'FILESYSTEM_POLICY_UNSUPPORTED' | 'FILESYSTEM_POLICY_INVALID' | 'NATIVE_TOOL_POLICY_UNSUPPORTED' | 'AGENT_MODEL_UNRESOLVED' | 'AGENT_PERMISSION_MODE_INVALID' | 'AGENT_NOT_FOUND' | 'AGENT_RUNTIME_UNSUPPORTED' | 'AGENT_BINARY_NOT_RESOLVED' | 'AGENT_SPAWN_FAILED' | 'AGENT_PROMPT_TOO_LARGE';
96
98
  /** Thrown by `AgentExecutor.run()` on every failure path — never a bare `Error`, so callers can branch on `.code` instead of parsing `.message`. */
97
99
  export declare class AgentExecutorError extends Error {
98
100
  readonly code: AgentExecutorErrorCode;
@@ -102,6 +104,8 @@ export declare class AgentExecutorError extends Error {
102
104
  });
103
105
  }
104
106
  export interface AgentExecutorRunInput {
107
+ /** Host-selected mandatory filesystem boundary; no user grant may widen it. */
108
+ readonly filesystemRoot?: string;
105
109
  readonly runId: string;
106
110
  readonly agentId: string;
107
111
  readonly prompt: string;
@@ -203,28 +207,35 @@ export interface AgentExecutor {
203
207
  * underlying run is always already transitioned to `'failed'` via
204
208
  * `lifecycle.finish()` before this rejects (see index.ts module doc's Invariant).
205
209
  */
206
- run(requiredArgs: Pick<AgentExecutorRunInput, "runId" | "agentId" | "prompt" | "cwd">, optionalArgs?: Pick<AgentExecutorRunInput, "model" | "reasoning" | "nativeToolAccess" | "nativeCapabilities" | "cliParity" | "permissionMode" | "imagePaths" | "imageContents" | "extraAllowedDirs" | "uploadRoot" | "credentialEnv" | "env" | "resumeSessionId" | "newSessionId" | "disallowedTools" | "allowedTools" | "settingSources" | "settings" | "chromeIntegration">): Promise<void>;
210
+ run(requiredArgs: Pick<AgentExecutorRunInput, "runId" | "agentId" | "prompt" | "cwd">, optionalArgs?: Pick<AgentExecutorRunInput, "filesystemRoot" | "model" | "reasoning" | "nativeToolAccess" | "nativeCapabilities" | "cliParity" | "permissionMode" | "imagePaths" | "imageContents" | "extraAllowedDirs" | "uploadRoot" | "credentialEnv" | "env" | "resumeSessionId" | "newSessionId" | "disallowedTools" | "allowedTools" | "settingSources" | "settings" | "chromeIntegration">): Promise<void>;
207
211
  /**
208
212
  * Delivers a message the human sent while `runId` is going straight into its live agent process
209
- * (see {@link UserMessageDelivery} for each outcome). A stream-json agent is interrupted first and
210
- * gets the message once the CLI acknowledges the interrupt, so this settles in milliseconds (at
211
- * most `INTERRUPT_ACK_TIMEOUT_MS`); it never waits on the agent's reply.
213
+ * (see {@link UserMessageDelivery} for each outcome). A stream-json agent queues the message
214
+ * directly without interrupting tools. This settles on write acceptance; consumption is reported
215
+ * separately by UUID receipts. It never waits on the agent's reply.
212
216
  * Optional `imageContents` contains host-authorized pixels, encoded exactly as in an idle send.
213
217
  */
214
218
  sendUserMessage(requiredArgs: {
215
219
  readonly runId: string;
216
220
  readonly text: string;
221
+ readonly id?: string;
222
+ readonly attachmentIds?: readonly string[];
217
223
  }, optionalArgs?: {
218
224
  readonly imageContents?: readonly MessageAttachmentImage[];
219
225
  }): Promise<UserMessageDelivery>;
226
+ /** Trusted transport supplies the credential-bound run, never model arguments. No I/O or waiting. */
227
+ claimUserMessages(input: {
228
+ readonly runId: string;
229
+ readonly via: MessageRelayVia;
230
+ }, options?: Record<string, never>): readonly RelayedUserMessage[];
220
231
  }
221
232
  /**
222
233
  * What {@link AgentExecutor.sendUserMessage} did with a mid-run message:
223
- * - `'delivered'` — the running turn was interrupted and the message written into the live
234
+ * - `'delivered'` — the message was queued without interruption into the live
224
235
  * session; the agent answers it next, in the same process and session.
225
236
  * - `'unsupported'` — the run is live, but its agent has no way to take input mid-run (its prompt
226
237
  * is plain text or an RPC request). Queue attachment turns intact after the reply; text-only
227
- * turns may retain the interrupt-and-resume fallback.
238
+ * turns retain the next-turn queue fallback.
228
239
  * - `'not-running'` — no live process will accept it: an unknown run, a finished one, or one whose
229
240
  * last turn already ended and closed stdin. The run is ending; the host should send it next.
230
241
  */
@@ -271,8 +282,14 @@ export interface StdinCloseHandle {
271
282
  closeStdinOnce(): void;
272
283
  /** 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`). */
273
284
  recordSentBytes(content: string): void;
274
- /** Interrupts this child's turn, then writes a mid-run user message into its open stdin — see {@link AgentExecutor.sendUserMessage}. */
275
- sendUserMessage(text: string, imageContents?: readonly MessageAttachmentImage[]): Promise<UserMessageDelivery>;
285
+ /** Queues a mid-run user message into this child's open stdin — see {@link AgentExecutor.sendUserMessage}. */
286
+ sendUserMessage(input: {
287
+ text: string;
288
+ id?: string;
289
+ attachmentIds?: readonly string[];
290
+ }, options?: {
291
+ imageContents?: readonly MessageAttachmentImage[];
292
+ }): Promise<UserMessageDelivery>;
276
293
  }
277
294
  /**
278
295
  * Gap 3 (capability-routed continuation transport) — host-owned config for the
@@ -600,6 +617,10 @@ export interface FailureClassificationContext {
600
617
  */
601
618
  export type ClassifyFailure = (context: FailureClassificationContext) => boolean | Promise<boolean>;
602
619
  export interface CreateAgentExecutorOptions {
620
+ /** Negotiated v1 only; share with bridge/lifecycle. Absent preserves legacy diagnostics/echoes. */
621
+ readonly delegatedResultCorrelation?: DelegatedResultCorrelation;
622
+ /** Required with correlation + byte journal: exact stdout blobs and durable reference records. */
623
+ readonly stdoutJournalBlobs?: StdoutJournalBlobPort;
603
624
  /** Host environment snapshot; baseline spawn keys and source config paths are allowlisted. */
604
625
  readonly hostEnv?: NodeJS.ProcessEnv;
605
626
  readonly runtimeState?: AgentRuntimeState;
@@ -616,6 +637,8 @@ export interface CreateAgentExecutorOptions {
616
637
  readonly resolveAgentLaunch?: typeof resolveAgentLaunch;
617
638
  /** @default the real `@jini-ai/agent-runtime` once-per-binary `--help` capability probe */
618
639
  readonly ensureAgentCapabilities?: typeof ensureAgentCapabilities;
640
+ /** Bounded version/enforcement probe; replaceable for offline host tests. */
641
+ readonly assertClaudeFilesystemSupport?: typeof assertClaudeFilesystemSupport;
619
642
  /** @default the real `@jini-ai/agent-runtime` PATH-env composer */
620
643
  readonly applyAgentLaunchEnv?: typeof applyAgentLaunchEnv;
621
644
  /** @default the real `@jini-ai/platform` cross-platform invocation builder */
@@ -101,6 +101,7 @@ function translateToolInputDeltaEvent(rawEvent) {
101
101
  };
102
102
  }
103
103
  export function translateToolResultEvent({ rawEvent }) {
104
+ const delegatedToolUseId = asOptionalString(rawEvent.delegatedToolUseId);
104
105
  const isError = typeof rawEvent.isError === 'boolean' ? rawEvent.isError : undefined;
105
106
  return {
106
107
  kind: 'agent',
@@ -108,6 +109,7 @@ export function translateToolResultEvent({ rawEvent }) {
108
109
  type: 'tool_result',
109
110
  toolUseId: asString(rawEvent.toolUseId),
110
111
  content: asString(rawEvent.content),
112
+ ...(delegatedToolUseId !== undefined ? { delegatedToolUseId } : {}),
111
113
  ...(isError !== undefined ? { isError } : {}),
112
114
  },
113
115
  };
@@ -1,3 +1,6 @@
1
+ import type { DelegatedResultCorrelation } from '../delegated-result-correlation.js';
2
+ import type { StdoutJournalBlobPort } from '../tool-result-diagnostics.js';
3
+ import { type RunMessageRelay } from './message-relay.js';
1
4
  import type { probeMcpBridge } from './mcp-bridge-probe.js';
2
5
  import type { ModelCatalogSnapshot } from '@jini-ai/agent-runtime';
3
6
  import type { ChildProcess } from 'node:child_process';
@@ -24,6 +27,9 @@ export declare function defaultCleanupFailureSink(context: AgentCleanupFailureCo
24
27
  */
25
28
  export declare const DEFAULT_BUFFERED_STDOUT_MAX_BYTES: number;
26
29
  interface WireChildLifecycleContext extends TerminateChildTreeDeps {
30
+ readonly registerMessageRelay?: (relay: RunMessageRelay) => void;
31
+ readonly delegatedResultCorrelation?: DelegatedResultCorrelation;
32
+ readonly stdoutJournalBlobs?: StdoutJournalBlobPort;
27
33
  readonly startingModel?: string;
28
34
  readonly modelCatalog?: ModelCatalogSnapshot;
29
35
  readonly runId: string;
@@ -121,21 +127,6 @@ interface WireChildLifecycleContext extends TerminateChildTreeDeps {
121
127
  * @overallScore 100/100
122
128
  */
123
129
  export declare function wireChildLifecycle(ctx: WireChildLifecycleContext): StdinCloseHandle;
124
- /**
125
- * Whether a def's live process can take another user message mid-run: only a stream-json stdin
126
- * transport keeps stdin open for more JSONL user lines (see `RuntimeAgentDef.promptInputFormat`).
127
- * Deliberately not `resolveContinuationTransport`: that answers how a tool result gets back, and
128
- * reports `'mcp-callback'` for Claude even though its stdin takes user lines all the same.
129
- */
130
- export declare function acceptsMidRunUserMessages({ def }: {
131
- readonly def: RuntimeAgentDef;
132
- }): boolean;
133
- /**
134
- * How long a mid-run message waits for the CLI to acknowledge its interrupt before being written
135
- * anyway. Claude Code acks within milliseconds (it answers before the aborted turn's own result);
136
- * the ceiling only bounds an agent that ignores control requests.
137
- */
138
- export declare const INTERRUPT_ACK_TIMEOUT_MS = 5000;
139
130
  /**
140
131
  * Writes the initial user turn to the child's stdin per `def.promptInputFormat`
141
132
  * (both branches only run for `promptViaStdin: true` defs — the only shape
@@ -170,6 +161,7 @@ interface RunAcpDispatchInput {
170
161
  readonly mcpBridge: McpBridgeDelivery | null;
171
162
  }
172
163
  interface RunAcpDispatchDeps extends TerminateChildTreeDeps {
164
+ readonly registerMessageRelay?: (relay: RunMessageRelay) => void;
173
165
  readonly lifecycle: RunLifecycle;
174
166
  readonly attachAcpSession: typeof attachAcpSession;
175
167
  readonly onPermissionRequest: AcpPermissionHandler | undefined;