@workerdeck/protocol 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/build/index.d.mts CHANGED
@@ -20,8 +20,32 @@ type SessionState = 'attention' | 'working' | 'idle' | 'ended';
20
20
  declare const STATE_ORDER: readonly SessionState[];
21
21
  declare const STATE_LABELS: Record<SessionState, string>;
22
22
  declare function sessionState(info: SessionInfo): SessionState;
23
+ /**
24
+ * The sub-agents a list row draws as live.
25
+ *
26
+ * `sessionState` deliberately does **not** grow a `subagents` bucket — a fifth
27
+ * state would split `working` in two for every client that filters by it,
28
+ * including the ones that have not shipped this yet. Instead `working` *counts*
29
+ * them: a synchronous `Task` keeps the turn in flight so the status already
30
+ * says `working`, and a **background** agent — which outlives its turn on
31
+ * purpose — is the carve-out the extra arm in `sessionState` exists for.
32
+ * That is what makes "sub-agents are an annotation on a working row" true
33
+ * rather than assumed: the row is in the working bucket whichever kind is
34
+ * running, and this list only says more about it.
35
+ */
36
+ declare function runningSubagents(info: SessionInfo): SubagentInfo[];
37
+ /**
38
+ * A sub-agent's identity on one line: `Explore · find the auth check`.
39
+ *
40
+ * The same two fields `taskLabel` builds its transcript row from, minus the
41
+ * `Task(…)` wrapper — a list row is already inside a session, so naming the tool
42
+ * spends the width that the description needs. Falls back to the bare agent type,
43
+ * then to a generic word: a row with no label at all reads as a rendering bug,
44
+ * and an engine is free to send neither field.
45
+ */
46
+ declare function subagentLabel(sub: SubagentInfo): string;
23
47
  /** The facets a session can be grouped or sorted by. */
24
- type Facet = 'gateway' | 'adapter' | 'state';
48
+ type Facet = 'gateway' | 'adapter' | 'state' | 'project';
25
49
  type GroupBy = 'none' | Facet;
26
50
  type SortBy = 'recent' | 'name' | Facet;
27
51
  type ViewConfig = {
@@ -29,6 +53,16 @@ type ViewConfig = {
29
53
  gateways: string[];
30
54
  adapters: string[];
31
55
  states: SessionState[];
56
+ /**
57
+ * Empty = no filter. Keys are {@link projectKey} output — never names, which
58
+ * are neither unique (two repos both called "api") nor stable (editing
59
+ * `.workerdeck.json` renames every session at once and must not empty a
60
+ * saved filter). Optional, unlike its three siblings, because stored view
61
+ * configs predate it: a config restored from `localStorage`/`globalState`
62
+ * without the key must keep filtering, so absent and empty mean the same
63
+ * thing.
64
+ */
65
+ projects?: string[];
32
66
  /** Show only sessions inside the host's own folders. Inert where there is no
33
67
  * such notion (no folder open, a dashboard with no workspace), which is why it
34
68
  * can default on. */
@@ -74,7 +108,51 @@ type SessionGroup = {
74
108
  /** The adapters actually present, for the filter chips — derived rather than
75
109
  * enumerated, so a new engine needs no change here. */
76
110
  declare function adaptersOf(rows: readonly SessionRow[]): string[];
111
+ /**
112
+ * The projects actually present, as `{ key, label }` for a filter control —
113
+ * derived like {@link adaptersOf}, and paired because the two halves differ:
114
+ * the *key* is what {@link ViewConfig.projects} holds (gateway-qualified root,
115
+ * so a rename regroups nothing) and the *label* is what a person picks by.
116
+ *
117
+ * Sorted by label, deduped by key. Two projects with the same name on two
118
+ * gateways therefore stay two entries wearing one word — which is honest: they
119
+ * really are two different directories, and the alternative is a filter that
120
+ * silently selects both.
121
+ */
122
+ declare function projectsOf(rows: readonly SessionRow[]): {
123
+ key: string;
124
+ label: string;
125
+ }[];
77
126
  declare function sessionLabel(info: SessionInfo): string;
127
+ /**
128
+ * The project facet's grouping key: gateway id + the project root, falling
129
+ * back to the session's cwd when no project is declared.
130
+ *
131
+ * The root and not the name, because a name is not a key (two repos can both
132
+ * be called "api", and a rename must regroup nothing); qualified by gateway,
133
+ * because a remote gateway's identical-looking path is another machine's
134
+ * directory — the same rule `ScopeRoot` states. The cwd fallback is what makes
135
+ * grouping by project useful before anyone has written a `.workerdeck.json`:
136
+ * undeclared sessions group by their folder, declared ones by their root, and
137
+ * a session in `packages/ui` joins its repo's group the moment the file
138
+ * exists. Sessions with no cwd at all (a filesystem-less engine) share one
139
+ * per-gateway bucket — see {@link projectLabel}.
140
+ */
141
+ declare function projectKey(row: SessionRow): string;
142
+ /**
143
+ * What a project group (or a row's project slot) is called: the declared name,
144
+ * else the cwd's basename — the exact string clients rendered before this
145
+ * feature existed, so an undeclared project looks like today. 'No project' is
146
+ * only ever the no-cwd case (a sandboxed provider session), where there is no
147
+ * folder to name.
148
+ *
149
+ * Takes only the `info` it reads, so a surface holding a bare `SessionInfo` —
150
+ * a row component, an iOS cell — can call it without inventing the rest of a
151
+ * `SessionRow`. That matters more than it looks: this string is what a client
152
+ * renders *in place of* the cwd basename it used to draw, and two spellings of
153
+ * it would put the list and its group headers on different names.
154
+ */
155
+ declare function projectLabel(row: Pick<SessionRow, 'info'>): string;
78
156
  /**
79
157
  * This session is a job run — the queue created it, and `JobInfo.sessionId`
80
158
  * points at it.
@@ -136,6 +214,72 @@ declare function hasFacetFilter(config: ViewConfig): boolean;
136
214
  * choices are a layout preference and survive. */
137
215
  declare function clearFilters(config: ViewConfig): ViewConfig;
138
216
  //#endregion
217
+ //#region src/usage.d.ts
218
+ /**
219
+ * What one session was last told about the plan's windows: the transcript's own
220
+ * rate-limit state, and the event clock of the newest reading in it.
221
+ *
222
+ * Deliberately structural rather than `TranscriptState` — protocol may not
223
+ * import a client — and it is exactly the two fields the reducer keeps.
224
+ */
225
+ type SessionUsage = {
226
+ /** Keyed by `rateLimitType`, as the reducer stores it. */rateLimits?: Record<string, RateLimitInfo>;
227
+ /** Epoch ms of the newest `rate_limit` event this session saw — one clock for
228
+ * the whole map, which is all the reducer records. */
229
+ updatedAt?: number;
230
+ };
231
+ /**
232
+ * The usage a client should render: the gateway's per-profile state where it has
233
+ * the window, this session's own reading where it does not.
234
+ *
235
+ * Why the profile wins outright rather than by comparing timestamps: the
236
+ * gateway's `ProfileUsageTracker` is fed from **every** session on the profile —
237
+ * including this one, from seq 0 — and keeps the newest reading per window by
238
+ * the event's own `ts`. So for any window it holds, it holds a reading at least
239
+ * as new as the one in this transcript, and a timestamp comparison could only
240
+ * ever go wrong: the reducer keeps a *single* `updatedAt` for the whole map, so
241
+ * a `five_hour` reading from this morning is dated with the afternoon's
242
+ * `seven_day` event and would beat a genuinely fresher profile entry.
243
+ *
244
+ * The session half is not a fallback for correctness but for *coverage*: the
245
+ * profile map is in-memory, so a restarted gateway serves nothing until a
246
+ * session reports again, and a session with no profile has no account state at
247
+ * all. In both cases the transcript's reading is the only one there is, and it
248
+ * is dated honestly (see {@link SessionUsage.updatedAt}) rather than as now.
249
+ *
250
+ * Absent stays absent throughout: a window nobody has reported is **unknown,
251
+ * never 0%**, and this returns an empty map rather than inventing entries.
252
+ */
253
+ declare function mergeUsage(session: SessionUsage, profile: ProfileUsage | undefined): ProfileUsage;
254
+ /** One window as a surface draws it: the reading, its own date, and whether the
255
+ * gateway is the one that zeroed it. */
256
+ type UsageWindowRow = {
257
+ key: string;
258
+ info: RateLimitInfo; /** Epoch ms of the reading. Absent only for a hand-built state with no clock. */
259
+ updatedAt?: number;
260
+ inferredReset?: boolean;
261
+ };
262
+ /**
263
+ * The windows in reading order: the session window, the weekly one, then the
264
+ * per-model weeklies alphabetically.
265
+ *
266
+ * Discovered rather than hardcoded — the engine's set of windows is an open
267
+ * union and has grown before — but ordered, so the first two always mean the
268
+ * same thing wherever they are drawn. A window with no `utilization` is
269
+ * **unknown, not zero**, and is dropped entirely rather than rendered as an
270
+ * empty bar that reads as "plenty left".
271
+ *
272
+ * Here rather than in a client because two surfaces now render the same windows
273
+ * from different sources — the session panel from its merged state, the
274
+ * dashboard's profile page straight off `ProfileInfo.usage` — and a list that
275
+ * ordered or filtered differently would be the same account described two ways.
276
+ */
277
+ declare function orderUsageWindows(usage: ProfileUsage | undefined): UsageWindowRow[];
278
+ /** The flat `rateLimitType → reading` map every existing renderer takes, out of
279
+ * the dated form. Undefined in, undefined out — so a surface can keep telling
280
+ * "no reading" apart from "an empty one". */
281
+ declare function usageInfos(usage: ProfileUsage | undefined): Record<string, RateLimitInfo> | undefined;
282
+ //#endregion
139
283
  //#region src/watermarks.d.ts
140
284
  /**
141
285
  * "What had you seen, and when" — per session, across reloads.
@@ -263,12 +407,171 @@ type ToolResultBlock = {
263
407
  [key: string]: unknown;
264
408
  }>;
265
409
  is_error?: boolean;
410
+ /**
411
+ * This block carries only the **head** of the result: the replay truncated it
412
+ * (see {@link TOOL_RESULT_HEAD_CHARS}), and the whole thing is one fetch away
413
+ * at `GET /sessions/:id/events/:seq/result?toolUseId=`.
414
+ *
415
+ * On the **block**, never the event, and that is the same argument
416
+ * `user_message.patch` has to make in reverse: the patch sits on the event and
417
+ * its doc must therefore caveat "only when the message carries exactly one
418
+ * `tool_result` block — with two, nothing says which one it belongs to". A
419
+ * message answering three calls truncates whichever of them is large, so
420
+ * paying that caveat a second time would make the marker unusable exactly
421
+ * when it matters. {@link FilePatch.truncated} is the shipped precedent.
422
+ *
423
+ * Only ever set on a **replay** a client asked for (`truncateResults`), so a
424
+ * client that has never heard of this field cannot receive one — which is why
425
+ * this is additive at protocol 7 rather than a bump. Absent means the block is
426
+ * whole.
427
+ */
428
+ truncated?: boolean;
429
+ /** How many characters the untruncated result had. Set iff `truncated`.
430
+ *
431
+ * A client cannot compute it — it holds the head — and the number is not
432
+ * cosmetic: a collapsed row spells "… +N chars", and `height.ts` sizes the row
433
+ * by wrapping **that exact string**, so a count derived from the head would be
434
+ * both a lie and a different pixel height. */
435
+ total_chars?: number;
266
436
  };
437
+ /**
438
+ * How much of a tool result a truncating replay keeps.
439
+ *
440
+ * Chosen against the two clients' *own* budgets, and the relationship is the
441
+ * whole point: the terminal theme shows ~400 characters collapsed and ~2,000
442
+ * open, so at 8,000 the collapsed and open states are **byte-identical to an
443
+ * untruncated attach** and only the uncapped "show everything" press ever
444
+ * fetches. That collapses the entire feature to one press, and it is asserted
445
+ * in a test rather than trusted — lowered below the open budget, this would
446
+ * silently clip the open state with no marker, which is the one failure this
447
+ * design must not have.
448
+ *
449
+ * Measured justification: on one 1,270-row session three `tool_result` frames
450
+ * were 641 / 463 / 396 KB, 68% of a 3.1 MB attach. The cut is *structural* —
451
+ * proportional to the thing that is actually large, wherever in the log it sits
452
+ * — which a row window is not.
453
+ */
454
+ declare const TOOL_RESULT_HEAD_CHARS = 8000;
455
+ /**
456
+ * A base64 image part, delivered as an address instead of its bytes.
457
+ *
458
+ * The **seventh** rule of the family, and the first written *after* its
459
+ * measurement rather than before it. Across 214 local sessions, 91% of all
460
+ * tool-result payload is base64 image data — 489 MB against 44 MB of text — and
461
+ * **no client renders a byte of it**: `blockText` in the reducer and
462
+ * `joinedText` on iOS both fold a `tool_result` to its text parts, and both
463
+ * clients draw a tool's picture from a host *path* (`savedPath` → `/produced`,
464
+ * `/fs/read`), never from block content. So it is `replayRetains`' argument at
465
+ * nine times the size of the case that rule was written for: bytes whose entire
466
+ * effect on the reader is `return base`.
467
+ *
468
+ * A **new part type rather than a hollowed-out `image`**, and that is the one
469
+ * judgement here worth stating. `headOf`'s shape-preservation rule — "a
470
+ * truncation is a shorter result, never a different kind of one" — cuts the
471
+ * other way for pixels: a head *is* a valid shorter text, but an image with no
472
+ * bytes is not a smaller image, and spelling it `{ type: 'image', source }` with
473
+ * no `data` invites precisely the failure shape-preservation exists to prevent,
474
+ * a renderer that trusts `source.data` drawing `data:;base64,undefined`. An
475
+ * unfamiliar type instead falls through every fold that already exists, exactly
476
+ * as the CLI's own `tool_reference` part does: no `text`, so it contributes
477
+ * nothing, and an unaware consumer renders what it renders today, which is
478
+ * nothing. That is this family's safe failure.
479
+ *
480
+ * Only ever produced for a socket that asked (`imageRefs`), so a client that has
481
+ * never heard of this type cannot receive one — which is why this is additive at
482
+ * protocol 7, the same argument {@link ToolResultBlock.truncated} makes. Unlike
483
+ * truncation it applies to **live events as well as replays**: the client's one
484
+ * render path is ref-then-fetch, so bytes on a live event would either be
485
+ * discarded (335 KB median, once per attached watcher) or need a second
486
+ * decode-from-event path pinning megabytes inside the transcript cache — the
487
+ * disease relocated rather than cured.
488
+ */
489
+ type ImageRefPart = {
490
+ type: 'image_ref';
491
+ /** The stored part's own media type (`image/png`, `image/jpeg` and
492
+ * `image/webp` are the three observed), or `application/octet-stream` when it
493
+ * had none. Never the membership test — that is `image` plus a base64 source. */
494
+ media_type: string;
495
+ /** Decoded size, which a client cannot compute from an address it has not
496
+ * fetched yet. Not cosmetic: the placeholder spells it, and in the terminal
497
+ * theme a rendered string *is* a row height. */
498
+ bytes: number;
499
+ /**
500
+ * Index of this part in the **stored** block's content array, and the address
501
+ * a fetch is made with.
502
+ *
503
+ * A stamped field rather than the position it arrives at, because that
504
+ * position is not stable: `headOf` builds a truncated head by keeping text
505
+ * parts up to budget and dropping every other part, so a block that is both
506
+ * over the text budget and image-bearing has its parts renumbered the moment
507
+ * the two rules compose. Stamped, the address survives any later reshaping —
508
+ * and the route verifies it against the stored block rather than trusting it.
509
+ */
510
+ part_index: number;
511
+ };
512
+ /**
513
+ * Project one `tool_result` content part onto its {@link ImageRefPart}, or
514
+ * `undefined` when the part is not a base64 image and must be delivered as it
515
+ * stands.
516
+ *
517
+ * The rule's **one spelling**, shared by the transform that replaces parts
518
+ * (core), the route that serves them back (server) and the property test that
519
+ * proves the fold is otherwise unchanged (react) — the same reason every other
520
+ * member of this family lives here rather than in whichever package applies it.
521
+ *
522
+ * Deliberately narrow. The corpus holds exactly two non-text part kinds: this
523
+ * one, and the CLI's `tool_reference`, of which every instance across 214
524
+ * sessions totals 122 KB. A "drop non-text parts" rule would sweep those in for
525
+ * no measurable gain, and narrowness is this family's standing habit.
526
+ */
527
+ declare function imagePartRef(part: {
528
+ type?: string;
529
+ [key: string]: unknown;
530
+ }, index: number): ImageRefPart | undefined;
267
531
  /** Forward-compatible fallback for block types this protocol version doesn't model. */
268
532
  type UnknownBlock = {
269
533
  type: string;
270
534
  [key: string]: unknown;
271
535
  };
536
+ /**
537
+ * One hunk of a file edit, in unified-diff terms.
538
+ *
539
+ * The numbers are the engine's own, not the client's: `newStart` is where this
540
+ * hunk begins in the file *after* the edit, which is what a reader needs to jump
541
+ * to the change. A client cannot compute them — it has never seen the file — so
542
+ * a diff rendered without this is a diff with no line numbers.
543
+ */
544
+ type PatchHunk = {
545
+ oldStart: number;
546
+ oldLines: number;
547
+ newStart: number;
548
+ newLines: number;
549
+ /** Body lines, each prefixed ' ' (context), '-' (removed) or '+' (added), as
550
+ * unified diff spells them. The prefix is part of the string. */
551
+ lines: string[];
552
+ };
553
+ /**
554
+ * What a file-editing tool changed — the renderable half of an engine's edit
555
+ * output, and deliberately only that half.
556
+ *
557
+ * Both engines can say far more: the Claude SDK's `FileEditOutput` carries
558
+ * `originalFile`, the **entire** contents of the file before the edit. That must
559
+ * not travel here. This log is replayed to every attaching client and captured
560
+ * into parking snapshots, so a whole file on every edit is paid for again on
561
+ * every attach, forever — the same reason attachment bytes are references (see
562
+ * {@link MessageAttachment}) rather than inline base64.
563
+ *
564
+ * So the runner projects the engine's output down to the hunks, which is exactly
565
+ * what a diff renders and nothing more.
566
+ */
567
+ type FilePatch = {
568
+ /** Absolute path the engine reported, when it named one. */path?: string; /** `create` when the file did not exist before this edit. */
569
+ kind?: 'create' | 'update';
570
+ hunks: PatchHunk[];
571
+ /** Hunks were dropped to keep the event small. A renderer must say so rather
572
+ * than present a partial diff as the whole change. */
573
+ truncated?: boolean;
574
+ };
272
575
  type ContentBlock = TextBlock | ThinkingBlock | ToolUseBlock | ToolResultBlock | UnknownBlock;
273
576
  /**
274
577
  * A file the user attached to a message — a photo, a screenshot, a document.
@@ -567,6 +870,28 @@ type SessionEventBody = /** SDK init handshake: what this session actually is. *
567
870
  | {
568
871
  type: 'plan_info';
569
872
  subscriptionType: string;
873
+ }
874
+ /**
875
+ * The engine started a **fresh conversation inside the same session** — the
876
+ * CLI's `/clear`, a plan-mode exit, and whatever fresh-conversation flows the
877
+ * SDK grows. The session id, registry row, workspace and scope are all
878
+ * unchanged; only the conversation is new. Clients empty the transcript and
879
+ * keep every session-scoped fact (models, commands, skills, produced files,
880
+ * rate limits, cwd, permission mode).
881
+ *
882
+ * The server's replay honours it too: an attach after a reset does not
883
+ * resurrect the cleared rows, because the runner skips *transcript content*
884
+ * below the latest reset (see {@link transcriptContent}) while still
885
+ * replaying every state-bearing event. `SessionInfo.activityCount` stays
886
+ * monotonic across a reset on purpose — it is an unread cursor, not an item
887
+ * count, and winding it back would kill every stored watermark above it.
888
+ */
889
+ | {
890
+ type: 'conversation_reset';
891
+ /** The engine session id the fresh conversation runs under (the SDK's
892
+ * `new_conversation_id`), when the engine reported one. The follow-up
893
+ * `system_init` remains authoritative. */
894
+ sdkSessionId?: string;
570
895
  } | {
571
896
  type: 'assistant_message';
572
897
  message: ApiMessage; /** Set when the message was produced inside a subagent (Task tool). */
@@ -583,6 +908,16 @@ type SessionEventBody = /** SDK init handshake: what this session actually is. *
583
908
  * `message.content` carries the typed text only — the attachment bytes went
584
909
  * to the model, not into this log. */
585
910
  attachments?: MessageAttachment[];
911
+ /**
912
+ * What a file-editing tool changed, when this message carries that tool's
913
+ * result (see {@link FilePatch}). Set by the runner from the engine's own
914
+ * structured output — never derived by a client from the result text.
915
+ *
916
+ * Only when the message carries exactly one `tool_result` block, which is
917
+ * what both engines send: with two, there is nothing that says which one
918
+ * the patch belongs to, and guessing would attach a diff to the wrong call.
919
+ */
920
+ patch?: FilePatch;
586
921
  uuid?: string;
587
922
  }
588
923
  /** Raw Anthropic streaming event (message_start/content_block_delta/...); emitted only
@@ -924,6 +1259,37 @@ type ProfileSessionDefaults = {
924
1259
  mcpServers?: string[]; /** Prepended to the session's system prompt. */
925
1260
  instructions?: string;
926
1261
  };
1262
+ /**
1263
+ * One rate-limit window of a profile's plan, as the *gateway* last saw it — the
1264
+ * newest {@link RateLimitInfo} any session on the profile reported, across every
1265
+ * session, live or since closed. The profile is the account boundary (one config
1266
+ * dir / codex home / provider key = one plan), so this is the single usage state
1267
+ * per account, where a session's own transcript only knows what *it* was last
1268
+ * told.
1269
+ *
1270
+ * Two rules a client must keep:
1271
+ * - An absent window (or an absent {@link ProfileInfo.usage} entirely) is
1272
+ * **unknown, not 0%** — render nothing, exactly as for session-level readings.
1273
+ * The map is in-memory and starts empty on a cold server.
1274
+ * - `inferredReset` marks a reading the server zeroed at serve time because the
1275
+ * reading's own `resetsAt` passed with nothing newer: the pre-reset number is
1276
+ * then provably wrong, and 0 is the truthful *floor* (the account may have
1277
+ * been used outside this gateway since). Distinguishable on the wire from an
1278
+ * engine-reported 0, which carries no flag.
1279
+ */
1280
+ type ProfileUsageWindow = {
1281
+ /** The reading, exactly as the session event carried it — except after an
1282
+ * elapsed reset, when `utilization` is 0 and `resetsAt` is dropped (the old
1283
+ * one names the *previous* window; a countdown from it would be nonsense). */
1284
+ info: RateLimitInfo;
1285
+ /** Epoch ms of the event that carried the reading — honest for "Updated …"
1286
+ * lines even when the served utilization is inferred. */
1287
+ updatedAt: number; /** Present (true) only on the served-as-0 inference described above. */
1288
+ inferredReset?: boolean;
1289
+ };
1290
+ /** Per-window plan usage, keyed by `rateLimitType` ('five_hour', 'seven_day',
1291
+ * ...) — the same keying as a transcript's rate-limit state. */
1292
+ type ProfileUsage = Record<string, ProfileUsageWindow>;
927
1293
  type ProfileInfo = {
928
1294
  /** Unique name, used as {@link CreateSessionRequest.profile}. */name: string;
929
1295
  /** Engine this profile runs on. Defaults to 'claude' when absent, so profiles
@@ -961,6 +1327,11 @@ type ProfileInfo = {
961
1327
  /** Response-only: one operator-actionable line, present only when
962
1328
  * `available === false`. */
963
1329
  unavailableReason?: string;
1330
+ /** Response-only: the plan's rate-limit windows as last reported by any
1331
+ * session on this profile (see {@link ProfileUsageWindow}). Absent = unknown
1332
+ * — no session has reported yet (API-key sessions never do), or the server
1333
+ * restarted. **Display-only**, like `available`: never a gate. */
1334
+ usage?: ProfileUsage;
964
1335
  /** Response-only, computed by the server: this profile came from the profile
965
1336
  * store and can be edited or deleted through the API. Profiles declared in
966
1337
  * server options are absent/false — they are code. Ignored on the way in. */
@@ -1128,6 +1499,178 @@ type CreateSessionRequest = {
1128
1499
  */
1129
1500
  scope?: Record<string, string>;
1130
1501
  };
1502
+ /**
1503
+ * One sub-agent (a `Task` call and the sidechain it spawned), as a *list* surface
1504
+ * sees it — without attaching.
1505
+ *
1506
+ * Sub-agent work is otherwise attach-only: it exists on the wire as
1507
+ * `parentToolUseId` on three event bodies, and is reconstructed into rows by the
1508
+ * react reducer and grouped per-Task by `terminalBlocks`. A sessions list never
1509
+ * attaches (one live attach per session, owned by the panel), so it reads
1510
+ * `SessionInfo` over REST and would otherwise have no way to know a session has
1511
+ * six agents running inside one turn.
1512
+ *
1513
+ * This is a **runner-owned rollup computed at read time**, exactly like
1514
+ * {@link SessionInfo.pendingPermissionCount}: it is not an event, it is not
1515
+ * persisted separately, and it therefore rides the REST list, the WS attach
1516
+ * snapshot and parking snapshots for free. Only the claude engine produces it —
1517
+ * codex and provider emit `parentToolUseId: null` on every event, so an empty
1518
+ * list there is the truth rather than a gap.
1519
+ *
1520
+ * It is deliberately **not** the input to `taskSummary`. That string is spelled
1521
+ * from the absorbed transcript items and must stay that way, so a transcript
1522
+ * replayed tomorrow spells the same line from the same items it holds today.
1523
+ */
1524
+ type SubagentInfo = {
1525
+ /** The `tool_use` id of the `Task` call that spawned it — the same id its
1526
+ * nested events carry as `parentToolUseId`, and therefore the handle a client
1527
+ * uses to jump to that Task's row. */
1528
+ toolUseId: string; /** The Task input's `subagent_type` (e.g. "Explore"), when it named one. */
1529
+ agentType?: string;
1530
+ /** The Task input's short `description`, clipped by the runner. Together with
1531
+ * `agentType` this is what makes two parallel sub-agents tell apart in a list;
1532
+ * a row reading only `Task` answers nothing. */
1533
+ description?: string;
1534
+ /**
1535
+ * `running` until the Task's own `tool_result` arrives, then `done`/`failed`
1536
+ * from that result's `is_error`. A turn that ends without that result — an
1537
+ * interrupt, a session error, a turn or budget cap — settles what is still
1538
+ * running as `failed`: the report never came, which is the one thing `done`
1539
+ * could have claimed, and a `running` badge on an idle session would be a
1540
+ * lie a list re-renders at every poll.
1541
+ *
1542
+ * Deliberately **narrower than `taskFailed`** in `@workerdeck/ui`'s
1543
+ * `tool-run.ts`, which reddens a Task row when *any child call* failed. That is
1544
+ * right for a transcript row the reader can expand — the failure is one press
1545
+ * away and hiding it would be worse. It is wrong for a list: a grep that
1546
+ * matched nothing inside an otherwise successful Explore agent would put
1547
+ * `failed` beside the session's name with nothing to open. So this reports the
1548
+ * sub-agent's own outcome. If you are here to "fix" the inconsistency, this is
1549
+ * the reason it exists.
1550
+ */
1551
+ status: 'running' | 'done' | 'failed'; /** Epoch ms the `Task` call was emitted. */
1552
+ startedAt: number;
1553
+ /** Tool calls the sub-agent has made so far — its progress reading while
1554
+ * running, counted from nested `tool_use` blocks. */
1555
+ toolCount: number;
1556
+ };
1557
+ /**
1558
+ * How many *settled* sub-agents {@link SessionInfo.subagents} keeps behind the
1559
+ * running ones. Small on purpose: the point of the tail is that a list row does
1560
+ * not go blank the instant a run finishes, not that it is a history.
1561
+ */
1562
+ declare const SUBAGENT_HISTORY = 8;
1563
+ /**
1564
+ * A project's icon, as declared by its `.workerdeck.json` — either a named
1565
+ * glyph or a reference to an image the gateway serves.
1566
+ *
1567
+ * A discriminated union rather than one stringly field, because the two arms
1568
+ * have opposite render paths: a glyph is looked up in the client's own icon
1569
+ * set with no I/O, an image is a fetch. Collapsing them would put "is this a
1570
+ * name or an address" back on every renderer, which is the inference this
1571
+ * family keeps refusing (`ImageRefPart` is a new part type, never a
1572
+ * hollowed-out `image`, for the same reason).
1573
+ *
1574
+ * `glyph.name` is a lucide icon name, validated by the gateway for *shape*
1575
+ * only (lowercase kebab-case): the gateway has no lucide catalog and must not
1576
+ * grow one — icon sets version independently of this protocol. A client whose
1577
+ * set lacks the name renders its no-project fallback rather than erroring;
1578
+ * an unknown name is a stale row, never withheld state.
1579
+ *
1580
+ * `image` carries an **address, never bytes** — the attachment-bytes rule.
1581
+ * `SessionInfo` rides every row of `GET /sessions`, which clients poll at 1.2s
1582
+ * while anything is working, so an inlined base64 icon would be paid for on
1583
+ * every poll of every session forever (the same argument that keeps
1584
+ * `originalFile` off {@link FilePatch} and message bytes off events). The
1585
+ * bytes come from `GET {basePath}/sessions/:id/project/icon` — session-scoped
1586
+ * on purpose, so the fetch rides the same `canSee` gate as every other
1587
+ * `/sessions/:id/*` route and a scoped principal's miss is the uniform 404. A
1588
+ * project-keyed route would need the project root in the URL, and a route
1589
+ * addressed by host paths is an existence oracle for the gateway's
1590
+ * filesystem. `hash` (sha256 hex of the bytes) is the cross-session cache
1591
+ * key: two sessions in one project serve identical bytes, so a client caches
1592
+ * by hash rather than by URL and fetches once per project, not once per
1593
+ * session. The route answers with `ETag: "<hash>"` and honors
1594
+ * `If-None-Match`.
1595
+ */
1596
+ type ProjectIcon = {
1597
+ type: 'glyph';
1598
+ name: string;
1599
+ } | {
1600
+ type: 'image';
1601
+ mediaType: 'image/png' | 'image/svg+xml';
1602
+ hash: string;
1603
+ };
1604
+ /**
1605
+ * Project identity for a session — what a `.workerdeck.json` in the session's
1606
+ * ancestry declares, resolved by the **gateway** and shipped on
1607
+ * {@link SessionInfo.project}.
1608
+ *
1609
+ * The gateway reads the file, not each client: the iOS app and a browser
1610
+ * pointed at a remote gateway have no access to that filesystem, so a
1611
+ * per-client reader would make the feature exist on exactly one client.
1612
+ * Discovery is an ancestor walk from the session's `cwd` upward — nearest
1613
+ * `.workerdeck.json` wins, so a session started in `packages/ui` still says
1614
+ * "WorkerDeck" — over the *realpath'd* cwd, which is what makes `root`
1615
+ * canonical below.
1616
+ *
1617
+ * The file's schema, stated here because this type is its wire projection
1618
+ * (clients never read the file; the gateway is its only parser):
1619
+ *
1620
+ * ```json
1621
+ * { "name": "WorkerDeck", "icon": "layers" }
1622
+ * { "name": "WorkerDeck", "icon": "./docs/assets/icon.png" }
1623
+ * ```
1624
+ *
1625
+ * Both keys optional, unknown keys ignored (forward compatibility). An empty
1626
+ * `{}` still marks its directory as the project root — grouping is the point,
1627
+ * and the name falls back to the root's basename. `icon` is one string with a
1628
+ * total classification rule: a value ending in `.png`/`.svg`
1629
+ * (case-insensitive) is a repo-relative image path — relative only, since the
1630
+ * file is checked into a repo that clones onto other machines, where an
1631
+ * absolute path is wrong by construction — and anything else must be a
1632
+ * lucide-shaped glyph name (`^[a-z0-9]+(-[a-z0-9]+)*$`) or it is ignored. The
1633
+ * two shapes cannot collide (a glyph name contains no dot), so the rule is a
1634
+ * classification, not a guess. Every degradation degrades *fieldwise and
1635
+ * silently*: a malformed or oversized file is skipped and the walk continues
1636
+ * to an ancestor (a broken nested file must not shadow the repo root's valid
1637
+ * one), a junk name falls back to the basename, a junk or escaping icon is
1638
+ * dropped — a session must never fail, or even warn, because of a display
1639
+ * declaration.
1640
+ *
1641
+ * `root` — the canonical (realpath'd) absolute directory holding the file, on
1642
+ * the **gateway's** filesystem — is the grouping key: two sessions are in the
1643
+ * same project iff same root *on the same gateway* (a remote gateway's
1644
+ * identical-looking path is another machine's directory — the `ScopeRoot`
1645
+ * argument). A *name* is not a key: two repos can both be called "api".
1646
+ * Canonicalizing at discovery is what makes two differently-spelled cwds of
1647
+ * one project agree on it.
1648
+ *
1649
+ * Resolved at **serve time** from a TTL cache, never persisted — the same
1650
+ * placement argument as the profile tracker's 0%-after-reset inference: it is
1651
+ * a function of the gateway's current filesystem, and a copy captured into a
1652
+ * parking record would replay a stale name forever. Editing the file shows up
1653
+ * on every session in the project within the TTL, with no migration and no
1654
+ * event.
1655
+ *
1656
+ * Additive at protocol **7**: an optional field on `SessionInfo`, where
1657
+ * absent means exactly what today's wire means (no project declared — render
1658
+ * the folder basename), an old client ignores it, and a new client against an
1659
+ * old gateway sees absent. The icon route is likewise unreachable by
1660
+ * accident: a client only fetches it when this gateway told it an image
1661
+ * exists.
1662
+ */
1663
+ type ProjectInfo = {
1664
+ /** Display name — the file's `name`, else the root's basename. Never empty. */name: string;
1665
+ /** Canonical absolute path of the directory holding `.workerdeck.json`, on
1666
+ * the gateway's filesystem. The grouping key (per gateway); an opaque string
1667
+ * to clients beyond equality and display. */
1668
+ root: string;
1669
+ /** Absent = the file declared none (or declared one the gateway refused —
1670
+ * malformed, escaping, oversized — which a client cannot and must not
1671
+ * distinguish). */
1672
+ icon?: ProjectIcon;
1673
+ };
1131
1674
  type SessionInfo = {
1132
1675
  /** Server-assigned id (stable across SDK session forks/resumes). */id: string; /** Underlying Agent SDK session id, once known; use for `resume`. */
1133
1676
  sdkSessionId?: string;
@@ -1158,6 +1701,22 @@ type SessionInfo = {
1158
1701
  createdAt: number; /** Highest event seq emitted so far; attach with `afterSeq` to catch up. */
1159
1702
  lastSeq: number;
1160
1703
  pendingPermissionCount: number;
1704
+ /**
1705
+ * Sub-agents this session has running, plus a short tail of settled ones — see
1706
+ * {@link SubagentInfo}. Absent on an engine that has no sidechains and on an
1707
+ * older server; **absent and empty mean the same thing to a client**, so render
1708
+ * nothing rather than "0 sub-agents".
1709
+ *
1710
+ * Bounded on purpose. This rides every row of `GET /sessions`, which a busy
1711
+ * client polls at 1.2s, and it is captured into parking snapshots — the same
1712
+ * attachment-bytes rule that keeps whole files off {@link FilePatch}. Every
1713
+ * *running* sub-agent is always present (they are the live reading and there
1714
+ * are never many at once); settled ones are kept newest-first to
1715
+ * {@link SUBAGENT_HISTORY} and then dropped, so a day-long session with two
1716
+ * hundred Tasks does not grow an unbounded field. A client must therefore not
1717
+ * treat this as the session's full Task history — the transcript is that.
1718
+ */
1719
+ subagents?: SubagentInfo[];
1161
1720
  meta?: Record<string, unknown>; /** Display title: `meta.title` if the host set one, else derived (e.g. first prompt). */
1162
1721
  title?: string; /** Cumulative cost across all turns so far (sum of turn_result totals). */
1163
1722
  totalCostUsd?: number; /** Cumulative turn count across the session. */
@@ -1172,6 +1731,13 @@ type SessionInfo = {
1172
1731
  * `lastSeq` cannot either — it counts every event, and with token streaming on
1173
1732
  * that is hundreds per reply. Absent on an older server; a client should fall
1174
1733
  * back to `numTurns` rather than showing nothing.
1734
+ *
1735
+ * Monotonic for the session's whole life, **including across a
1736
+ * `conversation_reset`**: after a `/clear` this deliberately exceeds the
1737
+ * number of rows a fresh attach renders. It is an unread *cursor* diffed
1738
+ * against stored monotonic watermarks (see `watermarks.ts`) — resetting it to
1739
+ * the new row count would leave every stored mark above it, and that
1740
+ * session's badge dead until the count caught back up.
1175
1741
  */
1176
1742
  activityCount?: number; /** Epoch ms of the most recent emitted event. */
1177
1743
  lastActivityAt?: number;
@@ -1179,6 +1745,15 @@ type SessionInfo = {
1179
1745
  * {@link CreateSessionRequest.scope}. Echoed by the runner, re-stamped by the
1180
1746
  * gateway, and never editable. */
1181
1747
  scope?: Record<string, string>;
1748
+ /**
1749
+ * Project identity discovered from the session's `cwd` — see
1750
+ * {@link ProjectInfo}. Stamped by the **gateway at serve time** (runners
1751
+ * never set it; a runner-echoed value would be persisted into parking
1752
+ * records and replay a stale name forever). Absent = no `.workerdeck.json`
1753
+ * in the cwd's ancestry, and also = an older gateway: both mean "render the
1754
+ * folder basename", which is exactly today's behaviour.
1755
+ */
1756
+ project?: ProjectInfo;
1182
1757
  };
1183
1758
  /**
1184
1759
  * How many transcript rows an event materializes — the unit behind
@@ -1196,6 +1771,167 @@ type SessionInfo = {
1196
1771
  * reducer's row rule changes, change this with it.
1197
1772
  */
1198
1773
  declare function transcriptActivity(body: SessionEventBody): number;
1774
+ /**
1775
+ * Whether an event is **transcript content** — whether the reducer
1776
+ * (`@workerdeck/react`'s `transcript.ts`, and its Swift mirror) mutates
1777
+ * `items` when it applies it. The rule behind `conversation_reset`'s replay
1778
+ * semantics: the runner keeps its whole event log, but `subscribe()` skips
1779
+ * content below the latest reset so an attaching client does not resurrect a
1780
+ * cleared conversation — while every *state-bearing* event (`system_init`,
1781
+ * `capabilities`, `skills`, `status_changed`, usage and rate-limit readings,
1782
+ * `file_produced`, permission bookkeeping) still replays, because a fresh
1783
+ * attacher with no model list and no cwd is broken, not cleared.
1784
+ *
1785
+ * Deliberately **broader than `transcriptActivity() > 0`**: stream deltas,
1786
+ * tool results (synthetic user messages) and execution lifecycle events count
1787
+ * zero rows but still mutate items — replaying them across a reset would leave
1788
+ * orphaned deltas and results with no parent message.
1789
+ *
1790
+ * `conversation_reset` itself is content under this rule, and that is load-
1791
+ * bearing twice: a *superseded* reset (below a newer one) is skipped with the
1792
+ * conversation it cleared, while the latest reset always replays (the skip is
1793
+ * strictly-below), which is what clears a reconnecting client that still holds
1794
+ * pre-reset rows.
1795
+ *
1796
+ * Lives here beside {@link transcriptActivity} for the same reason: the
1797
+ * reducer owns the rule and the runners filter with it, and the two sides may
1798
+ * not import each other. If the reducer's items-mutating set changes, change
1799
+ * this with it. Unknown/future event types are NOT content — the safe failure
1800
+ * is replaying a stale row, never withholding state.
1801
+ */
1802
+ declare function transcriptContent(body: SessionEventBody): boolean;
1803
+ /**
1804
+ * The dedupe key for an event that is **last-write-wins** on replay, or
1805
+ * `undefined` for one that must always be delivered.
1806
+ *
1807
+ * The problem: the runner polls context usage and the plan's rate limits after
1808
+ * every turn, so a fifty-turn session's log holds fifty context readings and
1809
+ * fifty per rate-limit window. Replaying all of them is not merely wasteful —
1810
+ * it is *visible*. A client applies each in turn, so opening a session shows
1811
+ * the usage meters counting up from the session's first reading to its last
1812
+ * over the length of the replay, announcing history as if it were news.
1813
+ *
1814
+ * The fix is a backwards scan over the buffered log keeping the first
1815
+ * occurrence of each key, which is `staleReplaySeqs` in `@workerdeck/core`.
1816
+ * The key is per *window* for rate limits, not per event type: the reducer
1817
+ * stores them keyed by window ("so five_hour and seven_day updates don't
1818
+ * clobber each other"), so a single key would keep only the most recently
1819
+ * polled window and silently drop the others.
1820
+ *
1821
+ * **This is a claim about the reducer**, which is why it lives here rather
1822
+ * than in core: only the server coalesces, but only `@workerdeck/react` can
1823
+ * prove the rule correct, and neither package may import the other. The
1824
+ * property that must hold is that coalescing is *unobservable* — folding the
1825
+ * full log and the coalesced log through `applyEvent` yields identical state.
1826
+ * `packages/react/test/replay-coalesce.test.ts` asserts exactly that, over
1827
+ * every event kind. Extend the rule only with a case that test still passes.
1828
+ *
1829
+ * Three kinds are deliberately **excluded** despite looking eligible:
1830
+ *
1831
+ * - `capabilities` — `defaultModel: event.defaultModel ?? base.defaultModel`
1832
+ * is a fallback *merge*, so a later event without one would erase an earlier
1833
+ * event's. (It is also emitted once per session, so there is nothing to win.)
1834
+ * - `model_changed` — `undefined` means "reset to the server default" and the
1835
+ * reducer *keeps* the last known model, so the last event alone is not the
1836
+ * same as the fold.
1837
+ * - `system_init` — pure replace for the reducer, but the server's
1838
+ * `watchAuthSource` reads the **first** one to decide an auth policy, and
1839
+ * parking treats each as a resume point.
1840
+ *
1841
+ * Coalescing never drops the highest-seq event, and that is load-bearing
1842
+ * rather than incidental: the globally-last event is by definition the last of
1843
+ * its own key, so it always survives. `useClaudeSession`'s replay hold waits
1844
+ * for `state.lastSeq` to reach the attach's `session.lastSeq`, and would hang
1845
+ * on a blank panel forever if a coalescer could swallow the final event.
1846
+ */
1847
+ declare function replayCoalesceKey(body: SessionEventBody): string | undefined;
1848
+ /**
1849
+ * Does a **replay** have to deliver this event, or may it be dropped outright?
1850
+ *
1851
+ * The fifth of the family, and the closest relative of {@link snapshotRetains} —
1852
+ * the same claim ("no client can tell") pointed at the wire instead of at a
1853
+ * store. The difference from {@link replayCoalesceKey} is that this is not
1854
+ * last-write-wins: there is nothing to keep. These are events the reducer reads
1855
+ * and *discards*, so a replay that sends them is spending the reader's network
1856
+ * on frames whose whole effect is `return base`.
1857
+ *
1858
+ * Today that is exactly one thing, and it is the second-largest item in a real
1859
+ * attach: the `stream_delta`s the reducer does not model. Measured over one
1860
+ * 1,270-row session, the delta run was 774 KB, and **~85% of it was frames the
1861
+ * reducer throws away** — `input_json_delta` (a tool call's arguments, streamed
1862
+ * character by character, 383 KB), `signature_delta` (encrypted-thinking
1863
+ * signatures, 153 KB) and the `message_start`/`content_block_start`/`_stop`
1864
+ * scaffolding (244 KB). The reducer models two delta kinds, `text_delta` and
1865
+ * `thinking_delta`; everything else falls through its switch untouched.
1866
+ *
1867
+ * What is deliberately **not** dropped, though the arithmetic would allow it:
1868
+ *
1869
+ * - `thinking_delta` — the Claude SDK delivers thinking blocks whose `thinking`
1870
+ * is `''`, and the reducer backfills them from the accumulated streamed text
1871
+ * (`streamedThinking`). Dropping these erases every thought from a replayed
1872
+ * transcript. This is the same carve-out `snapshotRetains` documents, and it
1873
+ * is the reason that rule is provider-engine-only.
1874
+ * - `text_delta` — superseded by the `assistant_message` that follows it, which
1875
+ * filters the streaming id and rebuilds from the full content blocks. It could
1876
+ * go, but only with a lookahead proving the message arrived, and at 24 KB in
1877
+ * the measured session it is not worth a rule that has to be right about
1878
+ * supersession. A merge is likewise not worth it: a *drop* needs no synthesized
1879
+ * event and therefore no invented seq.
1880
+ *
1881
+ * A live event is never affected — this is about the buffered replay alone — and
1882
+ * the caller must never drop the log's highest-seq event whatever this says, for
1883
+ * the reason {@link replayCoalesceKey} gives: the replay hold waits for
1884
+ * `state.lastSeq` to reach the attach's `session.lastSeq` and would hang on a
1885
+ * blank panel forever.
1886
+ *
1887
+ * The property is the family's usual one and is a test rather than an argument:
1888
+ * folding the full log and the retained log through `applyEvent` yields
1889
+ * identical state (`packages/react/test/replay-retain.test.ts`).
1890
+ */
1891
+ declare function replayRetains(body: SessionEventBody): boolean;
1892
+ /**
1893
+ * Does a `RunnerSnapshot` keep this event in its persisted log?
1894
+ *
1895
+ * The fourth of the same family, and the same shape of claim as
1896
+ * {@link replayCoalesceKey}: which events a *store* may drop without any client
1897
+ * being able to tell. It exists because a snapshot embeds the whole event log,
1898
+ * and a log is mostly stream deltas — a four-character token rides a ~180-byte
1899
+ * JSON envelope, so the delta run is tens of times the size of the text it
1900
+ * spells, sitting on disk *beside* the `assistant_message` that respells it in
1901
+ * full. That was affordable while a snapshot was written once, at a park. It is
1902
+ * not affordable written after every turn, which is what restart-survival needs.
1903
+ *
1904
+ * So: everything is retained except `stream_delta`. The reason that is safe is
1905
+ * not that deltas are unimportant but that they are **superseded by
1906
+ * construction**. The reducer upserts them under one constant id and the
1907
+ * following `assistant_message` filters exactly that id out and rebuilds from
1908
+ * the full content blocks — and a snapshot may only be taken at a rest point,
1909
+ * where the stream loop has exited and flushed. Both exits flush, including the
1910
+ * error path: an interrupted turn pushes its half-finished buffers into a
1911
+ * durable `assistant_message` before it emits the failed `turn_result`. There is
1912
+ * no rest state in which a delta is the only record of anything.
1913
+ *
1914
+ * **Provider engine only**, and this is the carve-out that must not be lost:
1915
+ * against a *Claude* log the rule would be wrong. The Claude SDK delivers
1916
+ * thinking blocks whose text is `''`, with the human-readable summary existing
1917
+ * only in the delta stream, and the reducer carries the streamed text over to
1918
+ * fill them (`transcript.ts`, the `streamedThinking` backfill). Dropping deltas
1919
+ * there would silently erase every thought from a restored transcript. Today
1920
+ * that is unreachable rather than merely avoided — only the provider engine
1921
+ * implements `park()`/`snapshot()` at all, and `#restore` refuses a snapshot
1922
+ * from another engine — but an engine that gains one inherits this obligation.
1923
+ *
1924
+ * Two properties hold it up, both of which are tests rather than arguments:
1925
+ * folding the full log and the retained log through `applyEvent` yields
1926
+ * identical state (`packages/react/test/snapshot-retain.test.ts`, the same
1927
+ * property `replay-coalesce.test.ts` asserts), and the retained log's last event
1928
+ * still carries the snapshot's own `seq`. The second matters more than it looks:
1929
+ * `transcriptActivity(stream_delta)` is 0, so the count `#restore` recomputes
1930
+ * from the log is bit-identical — a client's unread cursor cannot move — and the
1931
+ * replay hold waits for `state.lastSeq` to reach the attach's `lastSeq`, which a
1932
+ * rule that could drop the final event would hang forever.
1933
+ */
1934
+ declare function snapshotRetains(body: SessionEventBody): boolean;
1199
1935
  /**
1200
1936
  * A session in an engine's on-disk store (independent of this server's registry):
1201
1937
  * the Agent SDK's session files, or a codex profile's CODEX_HOME threads. Listed
@@ -1631,5 +2367,5 @@ type QueueStatsResponse = {
1631
2367
  stats: QueueStats;
1632
2368
  };
1633
2369
  //#endregion
1634
- export { ApiMessage, AttachedFrame, ClientFrame, ContentBlock, ContextUsage, ContextUsageCategory, CreateJobRequest, CreateJobResponse, CreateProfileRequest, CreateSessionRequest, CreateSessionResponse, DEFAULT_VIEW_CONFIG, ENGINE_CAPABILITIES, EngineCapabilities, ErrorResponse, Facet, FindHostFilesResponse, GetJobResponse, GetProfileResponse, GetSessionResponse, GroupBy, HostDirEntry, HostFileMatch, HostFileRoot, JobEvent, JobInfo, JobProgress, JobResult, JobStatus, JobUsage, ListHostDirResponse, ListHostRootsResponse, ListJobsResponse, ListProfilesResponse, ListSdkSessionsResponse, ListSessionFilesResponse, ListSessionsResponse, McpServerActionRequest, McpServerConfigWire, McpServerStatusInfo, McpServerToolInfo, McpServersResponse, MessageAttachment, ModelOption, PROTOCOL_VERSION, PROVIDER_PERMISSION_MODES, PermissionDecisionSource, PermissionMode, PermissionRequest, ProfileConfigSnapshot, ProfileDefaults, ProfileEngine, ProfileInfo, ProfileSessionDefaults, ProviderConfig, QuestionBehavior, QueueServerFrame, QueueStats, QueueStatsResponse, RateLimitInfo, ReadHostFileResponse, ResolvePermissionRequest, ResolvePermissionResponse, STATE_LABELS, STATE_ORDER, SaveProfileResponse, ScopeRoot, SdkSessionSummary, ServerFrame, SessionCapability, SessionCommand, SessionEvent, SessionEventBody, SessionFileInfo, SessionGroup, SessionInfo, SessionNotification, SessionNotificationType, SessionRow, SessionState, SessionStatus, SessionWebhookConfig, SkillInfo, SlashCommandInfo, SortBy, SubmitExecutionResultRequest, SubmitExecutionResultResponse, SubsetSummary, TextBlock, ThinkingBlock, ToolCallRequestFrame, ToolExecutionBackend, ToolExecutionOutput, ToolExecutionStatus, ToolResultBlock, ToolUseBlock, UnknownBlock, UpdateProfileRequest, UpdateSessionRequest, UpdateSessionResponse, UploadAttachmentResponse, UserQuestion, UserQuestionOption, ViewConfig, Watermark, WatermarkStore, Watermarks, WebhookConfig, WorkspaceScope, WriteHostFileRequest, WriteHostFileResponse, adaptersOf, clearFilters, filterRows, groupRows, hasFacetFilter, inScope, isJobRun, scopeActive, sessionLabel, sessionState, subsetSummary, supportsPermissionMode, transcriptActivity, unseenCount, watermarkKey };
2370
+ export { ApiMessage, AttachedFrame, ClientFrame, ContentBlock, ContextUsage, ContextUsageCategory, CreateJobRequest, CreateJobResponse, CreateProfileRequest, CreateSessionRequest, CreateSessionResponse, DEFAULT_VIEW_CONFIG, ENGINE_CAPABILITIES, EngineCapabilities, ErrorResponse, Facet, FilePatch, FindHostFilesResponse, GetJobResponse, GetProfileResponse, GetSessionResponse, GroupBy, HostDirEntry, HostFileMatch, HostFileRoot, ImageRefPart, JobEvent, JobInfo, JobProgress, JobResult, JobStatus, JobUsage, ListHostDirResponse, ListHostRootsResponse, ListJobsResponse, ListProfilesResponse, ListSdkSessionsResponse, ListSessionFilesResponse, ListSessionsResponse, McpServerActionRequest, McpServerConfigWire, McpServerStatusInfo, McpServerToolInfo, McpServersResponse, MessageAttachment, ModelOption, PROTOCOL_VERSION, PROVIDER_PERMISSION_MODES, PatchHunk, PermissionDecisionSource, PermissionMode, PermissionRequest, ProfileConfigSnapshot, ProfileDefaults, ProfileEngine, ProfileInfo, ProfileSessionDefaults, ProfileUsage, ProfileUsageWindow, ProjectIcon, ProjectInfo, ProviderConfig, QuestionBehavior, QueueServerFrame, QueueStats, QueueStatsResponse, RateLimitInfo, ReadHostFileResponse, ResolvePermissionRequest, ResolvePermissionResponse, STATE_LABELS, STATE_ORDER, SUBAGENT_HISTORY, SaveProfileResponse, ScopeRoot, SdkSessionSummary, ServerFrame, SessionCapability, SessionCommand, SessionEvent, SessionEventBody, SessionFileInfo, SessionGroup, SessionInfo, SessionNotification, SessionNotificationType, SessionRow, SessionState, SessionStatus, SessionUsage, SessionWebhookConfig, SkillInfo, SlashCommandInfo, SortBy, SubagentInfo, SubmitExecutionResultRequest, SubmitExecutionResultResponse, SubsetSummary, TOOL_RESULT_HEAD_CHARS, TextBlock, ThinkingBlock, ToolCallRequestFrame, ToolExecutionBackend, ToolExecutionOutput, ToolExecutionStatus, ToolResultBlock, ToolUseBlock, UnknownBlock, UpdateProfileRequest, UpdateSessionRequest, UpdateSessionResponse, UploadAttachmentResponse, UsageWindowRow, UserQuestion, UserQuestionOption, ViewConfig, Watermark, WatermarkStore, Watermarks, WebhookConfig, WorkspaceScope, WriteHostFileRequest, WriteHostFileResponse, adaptersOf, clearFilters, filterRows, groupRows, hasFacetFilter, imagePartRef, inScope, isJobRun, mergeUsage, orderUsageWindows, projectKey, projectLabel, projectsOf, replayCoalesceKey, replayRetains, runningSubagents, scopeActive, sessionLabel, sessionState, snapshotRetains, subagentLabel, subsetSummary, supportsPermissionMode, transcriptActivity, transcriptContent, unseenCount, usageInfos, watermarkKey };
1635
2371
  //# sourceMappingURL=index.d.mts.map