@workerdeck/core 0.15.0 → 0.17.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -165,10 +165,32 @@ selectExecutor: () => new DeferredExecutor({
165
165
  for you — a `SessionStore` plus `POST /executions/:id/result` — but the mechanism is here, and works
166
166
  with no server at all.
167
167
 
168
+ `snapshot()` is the same value **without** the teardown: the runner stays live, attached and warm.
169
+ That separation is what makes a provider session survive a process restart, since it has no
170
+ engine-side store to resume from the way claude and codex do — the host writes the snapshot through
171
+ after each turn and rebuilds from the last one. The gate differs from `park()`'s in one direction
172
+ only: it refuses a turn in flight and pending *in-process* executions (whose results die with the
173
+ process), and allows the idle case `park()` exists to refuse.
174
+
168
175
  ## Rules you cannot infer from the types
169
176
 
170
177
  Things the compiler will not tell you, each of which has cost someone real time:
171
178
 
179
+ - **Truncation happens on the replay path, never at emit.** `subscribe(..., { truncateResults })`
180
+ hands out a copy; `#events` keeps the whole result, because the live path, the parking snapshot
181
+ and `Runner.eventAt` (which serves `GET /sessions/:id/events/:seq/result`) all read it. Refuse
182
+ the temptation to truncate into a snapshot: it would break the fetch for exactly the sessions
183
+ most likely to be read late.
184
+
185
+ - **Image refs happen there too — and on the live path as well.** `subscribe(..., { imageRefs })`
186
+ replaces a `tool_result`'s base64 `image` parts with `image_ref` addresses, and unlike truncation
187
+ it applies to live events as well as the replay, because a client's one render path is
188
+ ref-then-fetch. The same "never at emit" rule holds for the same reason: `#events` keeps every
189
+ byte, which is what the fetch route serves back. `SubscriberSet` (`src/lib/subscribers.ts`) is
190
+ where that per-subscriber decision lives — a subscriber is a listener *plus what it asked for*,
191
+ so the three runners no longer each own a copy of the answer. Consumers that subscribe with no
192
+ options — parking, notifications, the queue — see everything, as they do for every rule here.
193
+
172
194
  - **A declared MCP server that never connected is refused, not degraded.** If a profile's
173
195
  `session.mcpServers` names a server and it isn't there, `createEngineSession` throws. The old
174
196
  behaviour — start anyway, minus those tools — produced a session that reported perfectly healthy
package/build/index.d.mts CHANGED
@@ -1,10 +1,10 @@
1
- import { McpServerStatus, Options, Query, SDKMessage, SDKUserMessage, SessionMessage } from "@anthropic-ai/claude-agent-sdk";
1
+ import { McpServerStatus, Options, Query, SDKMessage, SDKSessionInfo, SDKUserMessage, SessionMessage } from "@anthropic-ai/claude-agent-sdk";
2
2
  import { ApiMessage, CreateSessionRequest, EngineCapabilities, McpServerConfigWire, McpServerStatusInfo, MessageAttachment, ModelOption, PermissionMode, PermissionRequest, ProfileEngine, ProfileInfo, SdkSessionSummary, SessionEvent, SessionEventBody, SessionInfo, SessionStatus, ToolCallRequestFrame, ToolExecutionBackend, ToolExecutionOutput } from "@workerdeck/protocol";
3
3
  import { LanguageModel, LanguageModel as LanguageModel$1, ModelMessage, Tool, Tool as Tool$1, ToolSet, ToolSet as ToolSet$1 } from "ai";
4
4
  import { SandboxEngine, SandboxVfs } from "@workerdeck/sandbox";
5
5
  import { Readable, Writable } from "node:stream";
6
6
 
7
- //#region src/attachments.d.ts
7
+ //#region src/lib/attachments.d.ts
8
8
  /**
9
9
  * An attachment plus its bytes — what the host hands a runner at send time.
10
10
  *
@@ -44,7 +44,7 @@ declare function attachmentContentBlocks(attachments: readonly AttachmentInput[]
44
44
  /** Strip the bytes: the log-safe half of an attachment. */
45
45
  declare function attachmentRef(attachment: AttachmentInput): MessageAttachment;
46
46
  //#endregion
47
- //#region src/tool-executor.d.ts
47
+ //#region src/executors/tool-executor.d.ts
48
48
  /**
49
49
  * Result of one tool execution, whenever it arrives. `failed` is a normal
50
50
  * outcome the agent loop adapts to — not an exception.
@@ -175,8 +175,54 @@ interface Runner {
175
175
  /** Begin the session. Idempotent; returns the run promise (resolves when the run ends). */
176
176
  start(): Promise<void>;
177
177
  info(): SessionInfo;
178
- /** Replay buffered events with seq > afterSeq, then deliver live events. Returns unsubscribe. */
179
- subscribe(listener: SessionEventListener, afterSeq?: number): () => void;
178
+ /** Replay buffered events with seq > afterSeq, then deliver live events. Returns unsubscribe.
179
+ *
180
+ * `coalesceReplay` drops state readings superseded later in the same replay —
181
+ * the fifty stale context/rate-limit polls a long session accumulates, which
182
+ * a client otherwise applies one by one and *renders*, counting its usage
183
+ * meters up through the session's history on every attach. Opt-in, and the
184
+ * default must stay off: it is only sound for a consumer whose handling of
185
+ * those events is last-write-wins, and `parking.ts` — which subscribes from
186
+ * seq 0 — branches on `status_changed` instead. Live events are never
187
+ * affected; this touches the buffered replay alone.
188
+ *
189
+ * `truncateResults` delivers an oversized `tool_result` block as its head plus
190
+ * the markers that say so (protocol's {@link TOOL_RESULT_HEAD_CHARS}), leaving
191
+ * the whole thing one fetch away. Measured, that is 68% of a long session's
192
+ * attach in three frames. Opt-in for the same reason and with one extra
193
+ * condition: **the opt-in must be issued by the unit that renders**, because
194
+ * `client` and `react` are separate packages an embedder can skew, and a
195
+ * client that asked for heads without knowing how to fetch the rest would show
196
+ * one as though it were the whole result. Live events are untouched — a result
197
+ * arriving while you watch is already on screen — and so is the stored log,
198
+ * which parking snapshots and the fetch route both read.
199
+ *
200
+ * `imageRefs` replaces a `tool_result`'s base64 image parts with `image_ref`
201
+ * addresses (protocol's {@link ImageRefPart}), their bytes one REST fetch
202
+ * away. Opt-in under the same rule — issued by the unit that renders — but
203
+ * unlike the other two it applies to **live events as well as the replay**,
204
+ * because the client's one render path is ref-then-fetch and bytes on a live
205
+ * event would only be discarded or pinned. Measured, this is 91% of all
206
+ * tool-result payload and 0% of what any client draws. The stored log keeps
207
+ * every byte, which is what the fetch route serves back. */
208
+ subscribe(listener: SessionEventListener, afterSeq?: number, options?: {
209
+ coalesceReplay?: boolean;
210
+ truncateResults?: boolean;
211
+ imageRefs?: boolean;
212
+ }): () => void;
213
+ /** One buffered event by seq, or undefined — the read side of the log the
214
+ * replay already walks.
215
+ *
216
+ * Optional, like every member added after `Runner` became public API: an
217
+ * out-of-tree runner that declines it declines only the on-demand tool result
218
+ * with it (the route 404s), which is exactly the degradation a runner with no
219
+ * `truncateResults` support wants anyway.
220
+ *
221
+ * Deliberately **not** a "give me the whole log" accessor. The one caller
222
+ * needs a single event by a seq a client is holding, and a method that handed
223
+ * out the array would invite a second copy of the bytes this feature exists
224
+ * to stop shipping. */
225
+ eventAt?(seq: number): SessionEvent | undefined;
180
226
  /** Queue a user message for the session (starts the next turn when idle).
181
227
  * `attachments` carry their bytes to the engine and their reference to the
182
228
  * event log (see {@link AttachmentInput}). */
@@ -215,13 +261,40 @@ interface Runner {
215
261
  * doesn't: the CLI owns its own process state).
216
262
  */
217
263
  park?(): RunnerSnapshot | undefined;
264
+ /**
265
+ * The same snapshot, taken **without ending anything** — the runner stays live,
266
+ * attached and warm.
267
+ *
268
+ * Park and snapshot are two operations that happen to produce the same value,
269
+ * and separating them is what makes restart-survival possible for an engine
270
+ * that has no on-disk session of its own. A park is for a session with nothing
271
+ * to do for possibly days; this is for one whose user is mid-conversation and
272
+ * whose process might be redeployed out from under it. The host writes it
273
+ * through after each turn — never on a shutdown hook, because a `kill -9` runs
274
+ * no hook and that is precisely the case worth surviving — and rebuilds from
275
+ * the last write through the ordinary `restore` path.
276
+ *
277
+ * Returns undefined when a snapshot would capture a half-happened turn: one in
278
+ * flight, or pending in-process executions whose results die with the process.
279
+ * Optional for the same reason `park()` is — claude and codex run behind a
280
+ * binary that owns its process state, and have engine-side resume instead.
281
+ */
282
+ snapshot?(): RunnerSnapshot | undefined;
218
283
  /** Emit a session_error and terminate. For host-enforced policy (e.g. requireApiKey). */
219
284
  fail(message: string): void;
220
285
  /** Terminate the session and any underlying engine process. */
221
286
  close(reason?: 'client' | 'server' | 'error'): void;
222
287
  }
223
288
  //#endregion
224
- //#region src/runner.d.ts
289
+ //#region src/lib/subscribers.d.ts
290
+ /** What a subscriber asked for. Absent fields mean the untransformed stream. */
291
+ type SubscribeOptions = {
292
+ coalesceReplay?: boolean;
293
+ truncateResults?: boolean;
294
+ imageRefs?: boolean;
295
+ };
296
+ //#endregion
297
+ //#region src/engines/claude/runner.d.ts
225
298
  type QueryFn = (params: {
226
299
  prompt: AsyncIterable<SDKUserMessage>;
227
300
  options?: Options;
@@ -229,6 +302,9 @@ type QueryFn = (params: {
229
302
  type HistoryFn = (sdkSessionId: string, options: {
230
303
  dir?: string;
231
304
  }) => Promise<SessionMessage[]>;
305
+ type SessionInfoFn = (sdkSessionId: string, options: {
306
+ dir?: string;
307
+ }) => Promise<SDKSessionInfo | undefined>;
232
308
  type SessionRunnerConfig = CreateSessionRequest & {
233
309
  /** Injectable query implementation (tests, instrumentation). Defaults to the SDK's query(). */queryFn?: QueryFn; /** Environment for the spawned Claude Code process. Defaults to process.env. */
234
310
  env?: Record<string, string | undefined>;
@@ -239,6 +315,10 @@ type SessionRunnerConfig = CreateSessionRequest & {
239
315
  * starts, so late-attaching clients get a full transcript. Default true. */
240
316
  backfillHistory?: boolean; /** Injectable history reader (tests). Defaults to the SDK's getSessionMessages. */
241
317
  historyFn?: HistoryFn;
318
+ /** Injectable session-metadata reader (tests). Defaults to the SDK's
319
+ * getSessionInfo — the only place the CLI's own session title is readable
320
+ * from, since no message on the stream carries it. */
321
+ sessionInfoFn?: SessionInfoFn;
242
322
  };
243
323
  /**
244
324
  * One live Agent SDK session: owns the query() call, the streaming input queue, the
@@ -284,14 +364,82 @@ declare class SessionRunner implements Runner {
284
364
  fail(message: string): void;
285
365
  /** Terminate the session and the underlying CLI subprocess. */
286
366
  close(reason?: 'client' | 'server' | 'error'): void;
367
+ /** See `Runner.eventAt`. A linear scan: the one caller is a reader pressing
368
+ * "show everything" on one row, so a per-runner seq index would be a map
369
+ * maintained on every emit to save a walk nobody makes twice a minute. */
370
+ eventAt(seq: number): SessionEvent | undefined;
287
371
  /**
288
372
  * Replay buffered events with seq > afterSeq, then deliver live events.
289
373
  * Returns an unsubscribe function.
374
+ *
375
+ * Replay honours the reset watermark: transcript content below the latest
376
+ * `conversation_reset` is skipped (the reducer would clear it again anyway,
377
+ * and a pre-reset client that never learned the reducer's case would render
378
+ * a conversation the engine has discarded), while state-bearing events —
379
+ * which are emitted once and never again — always replay. The reset event
380
+ * itself replays (the skip is strictly-below), which is what clears a
381
+ * reconnecting client still holding pre-reset rows; superseded resets are
382
+ * content below the newer one and are skipped with what they cleared.
290
383
  */
291
- subscribe(listener: SessionEventListener, afterSeq?: number): () => void;
384
+ subscribe(listener: SessionEventListener, afterSeq?: number, options?: SubscribeOptions): () => void;
292
385
  }
293
386
  //#endregion
294
- //#region src/ai-sdk-runner.d.ts
387
+ //#region src/lib/replay.d.ts
388
+ /**
389
+ * The one replay body, and what a socket receives from it.
390
+ *
391
+ * Every runner had a byte-identical copy of this loop — three spellings of four
392
+ * rules, one of which ("never drop the highest-seq event, whatever the rule
393
+ * says") is load-bearing and was three copies of a comment. Not a base class:
394
+ * the runners share nothing else, and a base class would have to own `#emit`,
395
+ * the most engine-specific method each of them has.
396
+ *
397
+ * The rules, in the order they are applied:
398
+ *
399
+ * 1. `afterSeq` — the caller already holds everything at or below it.
400
+ * 2. `resetSeq` — transcript *content* strictly below the latest
401
+ * `conversation_reset` is skipped, so a re-attach cannot resurrect a cleared
402
+ * conversation while state events still replay. Claude's alone; the other
403
+ * engines pass 0.
404
+ * 3. `coalesceReplay` — last-write-wins state readings superseded later in the
405
+ * same replay (`staleReplaySeqs`), plus everything `replayRetains` says the
406
+ * reducer reads and discards. Opt-in, and only sound for a consumer whose
407
+ * handling of those events is last-write-wins.
408
+ * 4. `imageRefs` — a base64 image part is delivered as an `image_ref` address
409
+ * (protocol's {@link imagePartRef}), its bytes one REST fetch away. Applied
410
+ * **before** rule 5, because it stamps indices from the stored part array
411
+ * which rule 5 then reshapes. Unlike rule 5 this also applies to the live
412
+ * path (see `SubscriberSet`), which is the one place these two rules differ.
413
+ * 5. `truncateResults` — a huge `tool_result` block is delivered as its head
414
+ * plus the markers that say so. **Never mutates the stored event**: the live
415
+ * path, the parking snapshot and the fetch route all need the whole thing,
416
+ * so this builds a copy and the log stays the log.
417
+ *
418
+ * The highest-seq event is delivered whatever rules 2 and 3 say — a client's
419
+ * replay hold waits for `state.lastSeq` to reach the attach's and would
420
+ * otherwise hang forever — but it is still *truncated* when rule 4 applies. A
421
+ * session that ends on a `find /` puts its 641 KB frame exactly there.
422
+ */
423
+ declare function replaySlice(events: readonly SessionEvent[], options: {
424
+ afterSeq: number;
425
+ resetSeq?: number;
426
+ coalesceReplay?: boolean;
427
+ truncateResults?: boolean;
428
+ imageRefs?: boolean;
429
+ }): SessionEvent[];
430
+ /**
431
+ * A copy of `event` whose oversized `tool_result` blocks carry their head and
432
+ * say so — or `event` itself, unchanged and un-copied, when nothing is over the
433
+ * budget. That identity matters: an attach is mostly small events, and a fresh
434
+ * object for every one of them would cost more than the feature saves.
435
+ *
436
+ * Blocks are measured and cut **individually**. A message answering three calls
437
+ * where one is a `find /` keeps the two small results whole, which is what makes
438
+ * the per-block marker (rather than a per-event one) honest.
439
+ */
440
+ declare function truncateResultBlocks(event: SessionEvent): SessionEvent;
441
+ //#endregion
442
+ //#region src/engines/provider/runner.d.ts
295
443
  /** `cwd` is optional for this engine: the loop has no host-filesystem coupling
296
444
  * (tools get scoped VFS handles instead). Defaults to process.cwd() for display. */
297
445
  type AiSdkRunnerConfig = Omit<CreateSessionRequest, 'cwd'> & {
@@ -428,6 +576,34 @@ declare class AiSdkRunner implements Runner {
428
576
  * or an already-closed/parked runner.
429
577
  */
430
578
  park(): RunnerSnapshot | undefined;
579
+ /**
580
+ * The same snapshot, taken without ending anything.
581
+ *
582
+ * `park()` and this are two operations that happen to produce the same value,
583
+ * and the difference is the whole point: `park()` *ends* the live runner
584
+ * (inert, listeners dropped, `onClose` called), which is right for deferred
585
+ * execution — the session has nothing to do for possibly days — and wrong for
586
+ * restart-survival, where the session is active and someone is mid-
587
+ * conversation. This one changes nothing at all: no status emit, no listener
588
+ * clear, no disposer. The host writes the value through to durable storage
589
+ * after each turn and keeps the runner live and warm, so a restart rebuilds
590
+ * from the last write through the existing `restore` path and the next message
591
+ * costs no wake.
592
+ *
593
+ * The gate is `park()`'s minus the requirement that there be something parked:
594
+ *
595
+ * - `#abort` set is refused for the reason it always was — a `generate()` in
596
+ * flight has produced messages that are not in the history yet, so the
597
+ * snapshot would be of a turn that half-happened.
598
+ * - Pending calls that are **not** all deferred are refused, which is
599
+ * `park()`'s rule wearing a different hat. An in-process execution's result
600
+ * is coming back to *this* runner and dies with the process; a restore would
601
+ * wait on it forever, and `state.dispatched` is what would stop the rebuilt
602
+ * runner from simply calling it again.
603
+ * - Idle with nothing pending — the case `park()` exists to refuse — is
604
+ * exactly the case this exists to allow.
605
+ */
606
+ snapshot(): RunnerSnapshot | undefined;
431
607
  sendMessage(text: string, attachments?: readonly AttachmentInput[]): void;
432
608
  /**
433
609
  * Deliver the result of an external (execute-less) tool call. Appends the
@@ -456,7 +632,11 @@ declare class AiSdkRunner implements Runner {
456
632
  setModel(model?: string): Promise<void>;
457
633
  fail(message: string): void;
458
634
  close(reason?: 'client' | 'server' | 'error'): void;
459
- subscribe(listener: SessionEventListener, afterSeq?: number): () => void;
635
+ /** See `Runner.eventAt`. A linear scan: the one caller is a reader pressing
636
+ * "show everything" on one row, so a per-runner seq index would be a map
637
+ * maintained on every emit to save a walk nobody makes twice a minute. */
638
+ eventAt(seq: number): SessionEvent | undefined;
639
+ subscribe(listener: SessionEventListener, afterSeq?: number, options?: SubscribeOptions): () => void;
460
640
  /**
461
641
  * Deliver the result of an execution this runner dispatched. Used by the host
462
642
  * when a backend settled out-of-band (a browser bridge answering later, a
@@ -477,7 +657,7 @@ declare class AiSdkRunner implements Runner {
477
657
  setTitle(title: string | undefined): void;
478
658
  }
479
659
  //#endregion
480
- //#region src/claude-auth.d.ts
660
+ //#region src/engines/claude/auth.d.ts
481
661
  /**
482
662
  * Credential presence for one Claude Code environment, as the CLI itself reports
483
663
  * it. 'unknown' means the check could not run at all (no binary, a CLI too old
@@ -515,7 +695,7 @@ declare function checkClaudeAuth(env: Record<string, string | undefined>, option
515
695
  timeoutMs?: number;
516
696
  }): Promise<ClaudeAuthStatus>;
517
697
  //#endregion
518
- //#region src/quickjs-executor.d.ts
698
+ //#region src/executors/quickjs-executor.d.ts
519
699
  /** Resolve a URL to text for the guest. Runs host-side with host authority —
520
700
  * this is where a credential may be attached, never inside the sandbox. */
521
701
  type HostFetch = (url: string, signal: AbortSignal) => Promise<string>;
@@ -548,7 +728,7 @@ declare class QuickJsExecutor implements ToolExecutor {
548
728
  * (not the bare parent). Only http(s) — no file:, data:, or other schemes. */
549
729
  declare function isHostAllowed(url: string, allowedHosts: string[]): boolean;
550
730
  //#endregion
551
- //#region src/pending-registry.d.ts
731
+ //#region src/lib/pending-registry.d.ts
552
732
  /**
553
733
  * One registry for every request that leaves the runner and must come back:
554
734
  * permission approvals, browser-bridged tool calls, and deferred executions.
@@ -610,7 +790,7 @@ declare class PendingRequestRegistry {
610
790
  cancelAll(reason: string, error: string, kind?: PendingKind): number;
611
791
  }
612
792
  //#endregion
613
- //#region src/browser-bridge-executor.d.ts
793
+ //#region src/executors/browser-bridge-executor.d.ts
614
794
  /** Answer a bridged call, as delivered by the client over the wire. */
615
795
  type BridgeAnswer = {
616
796
  output: ToolExecutionOutput;
@@ -664,7 +844,7 @@ declare class BrowserBridgeExecutor implements ToolExecutor {
664
844
  /** Map a registry outcome onto the executor's result contract. */
665
845
  declare function toExecutionResult(outcome: PendingOutcome<BridgeAnswer>): ToolExecutionResult;
666
846
  //#endregion
667
- //#region src/deferred-executor.d.ts
847
+ //#region src/executors/deferred-executor.d.ts
668
848
  /** A dispatched execution, as handed to the backend that will run it. */
669
849
  type DeferredDispatch = {
670
850
  /** Correlation id. The result is delivered under it — `POST
@@ -714,7 +894,7 @@ declare class DeferredExecutor implements ToolExecutor {
714
894
  dispatch(call: ToolExecutionCall): Promise<ToolExecutionDispatch>;
715
895
  }
716
896
  //#endregion
717
- //#region src/web-fetch.d.ts
897
+ //#region src/engines/provider/web-fetch.d.ts
718
898
  /**
719
899
  * `web_fetch` backend, close to Claude Code's original WebFetch: fetch a URL,
720
900
  * convert HTML to markdown, and (optionally) digest it with a model against the
@@ -760,7 +940,7 @@ declare function isPrivateAddress(address: string): boolean;
760
940
  */
761
941
  declare function htmlToMarkdown(html: string): string;
762
942
  //#endregion
763
- //#region src/tools.d.ts
943
+ //#region src/engines/provider/tools.d.ts
764
944
  /**
765
945
  * How much authority a tool carries, which decides where it may run.
766
946
  *
@@ -863,7 +1043,7 @@ declare function withHostTools(context: ToolContext, hostTools: Record<string, H
863
1043
 
864
1044
  kind?: string): ToolContext;
865
1045
  //#endregion
866
- //#region src/engine.d.ts
1046
+ //#region src/engines/provider/session.d.ts
867
1047
  type EngineSessionOptions = {
868
1048
  /** Resolved session config (profile defaults already applied). */config: AiSdkRunnerConfig; /** The profile that selected this engine, when there was one. */
869
1049
  profile?: ProfileInfo;
@@ -1014,7 +1194,7 @@ declare function connectMcpTools(servers: Record<string, McpServerConfigWire>, o
1014
1194
  required?: boolean;
1015
1195
  }): Promise<McpConnection>;
1016
1196
  //#endregion
1017
- //#region src/input-queue.d.ts
1197
+ //#region src/lib/input-queue.d.ts
1018
1198
  /**
1019
1199
  * Push-based single-consumer AsyncIterable bridging imperative sendMessage() calls
1020
1200
  * into the streaming `prompt` the Agent SDK consumes.
@@ -1026,7 +1206,7 @@ declare class InputQueue implements AsyncIterable<SDKUserMessage> {
1026
1206
  [Symbol.asyncIterator](): AsyncIterator<SDKUserMessage>;
1027
1207
  }
1028
1208
  //#endregion
1029
- //#region src/normalize.d.ts
1209
+ //#region src/lib/normalize.d.ts
1030
1210
  declare function toApiMessage(message: unknown): ApiMessage;
1031
1211
  /**
1032
1212
  * The CLI's MCP status, as `McpServerStatusInfo`.
@@ -1497,7 +1677,11 @@ declare class CodexRunner implements Runner {
1497
1677
  setModel(model?: string): Promise<void>;
1498
1678
  fail(message: string): void;
1499
1679
  close(reason?: 'client' | 'server' | 'error'): void;
1500
- subscribe(listener: SessionEventListener, afterSeq?: number): () => void;
1680
+ /** See `Runner.eventAt`. A linear scan: the one caller is a reader pressing
1681
+ * "show everything" on one row, so a per-runner seq index would be a map
1682
+ * maintained on every emit to save a walk nobody makes twice a minute. */
1683
+ eventAt(seq: number): SessionEvent | undefined;
1684
+ subscribe(listener: SessionEventListener, afterSeq?: number, options?: SubscribeOptions): () => void;
1501
1685
  /**
1502
1686
  * The session's MCP servers, live from the binary.
1503
1687
  *
@@ -1592,5 +1776,5 @@ declare class JsonRpcStdioConnection {
1592
1776
  */
1593
1777
  declare const providerAdapter: EngineAdapter;
1594
1778
  //#endregion
1595
- export { AiSdkRunner, type AiSdkRunnerConfig, type AiSdkSessionState, type AppServerConnectFn, type AppServerConnectOptions, type AppServerConnection, type AppServerHistoryTurn, type AppServerItem, type AppServerThreadListResponse, type AppServerThreadSummary, type AppServerTokenUsage, type AppServerTurn, type AppServerUserInput, type AttachmentInput, type AttachmentKind, type BridgeAnswer, BrowserBridgeExecutor, type BrowserBridgeExecutorOptions, CLAUDE_CATALOG, CODEX_CATALOG, type ClaudeAuthProbe, type ClaudeAuthStatus, CodexRunner, type CodexRunnerConfig, type DeferredDispatch, DeferredExecutor, type DeferredExecutorOptions, type EngineAdapter, type EngineAvailability, type EngineRunnerRequest, type EngineSessionOptions, type HistoryFn, type HostFetch, type HostToolDefinition, InputQueue, JsonRpcError, JsonRpcStdioConnection, type LanguageModel, type McpConnection, type ModelCatalog, type ParkedExecution, type PendingEntry, type PendingKind, type PendingOutcome, PendingRequestRegistry, type PendingToolCall, type PermissionDecision, type QueryFn, QuickJsExecutor, type QuickJsExecutorOptions, type RegisterOptions, type Runner, type RunnerSnapshot, SUPPORTED_ATTACHMENT_TYPES, type SessionEventListener, SessionRunner, type SessionRunnerConfig, type SettledBy, type Tool, type ToolCallOutput, type ToolContext, type ToolContextOptions, type ToolDefinition, type ToolExecutionCall, type ToolExecutionDispatch, type ToolExecutionResult, type ToolExecutor, type ToolSet, type ToolTrust, type WebFetchDigest, type WebFetchFn, type WebFetchOptions, type WebFetchResult, attachmentContentBlocks, attachmentKind, attachmentRef, checkClaudeAuth, claudeAdapter, codexAdapter, connectAppServer, connectMcpTools, createEngineSession, createToolContext, createWebFetch, getEngineAdapter, htmlToMarkdown, isHostAllowed, isPrivateAddress, listCodexSessions, mcpStatusInfo, modelOptionsFromSdk, normalizeMediaType, normalizeSdkMessage, providerAdapter, resolveBundledClaudeExecutable, resolveBundledCodexExecutable, toApiMessage, toExecutionResult, withHostTools, withMcpTools };
1779
+ export { AiSdkRunner, type AiSdkRunnerConfig, type AiSdkSessionState, type AppServerConnectFn, type AppServerConnectOptions, type AppServerConnection, type AppServerHistoryTurn, type AppServerItem, type AppServerThreadListResponse, type AppServerThreadSummary, type AppServerTokenUsage, type AppServerTurn, type AppServerUserInput, type AttachmentInput, type AttachmentKind, type BridgeAnswer, BrowserBridgeExecutor, type BrowserBridgeExecutorOptions, CLAUDE_CATALOG, CODEX_CATALOG, type ClaudeAuthProbe, type ClaudeAuthStatus, CodexRunner, type CodexRunnerConfig, type DeferredDispatch, DeferredExecutor, type DeferredExecutorOptions, type EngineAdapter, type EngineAvailability, type EngineRunnerRequest, type EngineSessionOptions, type HistoryFn, type HostFetch, type HostToolDefinition, InputQueue, JsonRpcError, JsonRpcStdioConnection, type LanguageModel, type McpConnection, type ModelCatalog, type ParkedExecution, type PendingEntry, type PendingKind, type PendingOutcome, PendingRequestRegistry, type PendingToolCall, type PermissionDecision, type QueryFn, QuickJsExecutor, type QuickJsExecutorOptions, type RegisterOptions, type Runner, type RunnerSnapshot, SUPPORTED_ATTACHMENT_TYPES, type SessionEventListener, SessionRunner, type SessionRunnerConfig, type SettledBy, type Tool, type ToolCallOutput, type ToolContext, type ToolContextOptions, type ToolDefinition, type ToolExecutionCall, type ToolExecutionDispatch, type ToolExecutionResult, type ToolExecutor, type ToolSet, type ToolTrust, type WebFetchDigest, type WebFetchFn, type WebFetchOptions, type WebFetchResult, attachmentContentBlocks, attachmentKind, attachmentRef, checkClaudeAuth, claudeAdapter, codexAdapter, connectAppServer, connectMcpTools, createEngineSession, createToolContext, createWebFetch, getEngineAdapter, htmlToMarkdown, isHostAllowed, isPrivateAddress, listCodexSessions, mcpStatusInfo, modelOptionsFromSdk, normalizeMediaType, normalizeSdkMessage, providerAdapter, replaySlice, resolveBundledClaudeExecutable, resolveBundledCodexExecutable, toApiMessage, toExecutionResult, truncateResultBlocks, withHostTools, withMcpTools };
1596
1780
  //# sourceMappingURL=index.d.mts.map