zidane 8.2.3 → 8.2.4

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 (166) hide show
  1. package/dist/{acp-oYRjlh71.js → acp-BIInKhVI.js} +6 -6
  2. package/dist/{acp-oYRjlh71.js.map → acp-BIInKhVI.js.map} +1 -1
  3. package/dist/acp-cli.js +4 -4
  4. package/dist/acp.d.ts +2 -2
  5. package/dist/acp.js +1 -1
  6. package/dist/{agent-CBQglXtH.js → agent-CmhCOmyO.js} +10 -5
  7. package/dist/{agent-CBQglXtH.js.map → agent-CmhCOmyO.js.map} +1 -1
  8. package/dist/agent.d.ts +1 -1
  9. package/dist/agent.js +1 -1
  10. package/dist/chat/pure.d.ts +4 -4
  11. package/dist/chat/pure.js +7 -7
  12. package/dist/chat.d.ts +3 -3
  13. package/dist/chat.js +16 -16
  14. package/dist/{cli-shared-E5m_pI8A.js → cli-shared-GOehTeqk.js} +2 -2
  15. package/dist/{cli-shared-E5m_pI8A.js.map → cli-shared-GOehTeqk.js.map} +1 -1
  16. package/dist/{client-core-EEEX_u6D.d.ts → client-core-Dz8hELs4.d.ts} +15 -5
  17. package/dist/client-core-Dz8hELs4.d.ts.map +1 -0
  18. package/dist/codemode-worker.js +1 -1
  19. package/dist/codemode.js +1 -1
  20. package/dist/{connection-loop-CpgfUmuw.d.ts → connection-loop-dm_TN-QD.d.ts} +3 -3
  21. package/dist/{connection-loop-CpgfUmuw.d.ts.map → connection-loop-dm_TN-QD.d.ts.map} +1 -1
  22. package/dist/contexts/daytona.d.ts +1 -1
  23. package/dist/contexts/e2b.d.ts +1 -1
  24. package/dist/{credentials-B9DfBJP9.js → credentials-DxOQmset.js} +2 -2
  25. package/dist/{credentials-B9DfBJP9.js.map → credentials-DxOQmset.js.map} +1 -1
  26. package/dist/daemon-cli.js +2 -2
  27. package/dist/{dispatcher-Bv9-c6I2.js → dispatcher-Dclv6HXn.js} +22 -18
  28. package/dist/dispatcher-Dclv6HXn.js.map +1 -0
  29. package/dist/{engine-XmoPPB6U.js → engine-C_U6kDfA.js} +6 -6
  30. package/dist/{engine-XmoPPB6U.js.map → engine-C_U6kDfA.js.map} +1 -1
  31. package/dist/{eval-CfQlBR81.js → eval-CIHIF_Ns.js} +3 -3
  32. package/dist/{eval-CfQlBR81.js.map → eval-CIHIF_Ns.js.map} +1 -1
  33. package/dist/eval.d.ts +1 -1
  34. package/dist/eval.js +1 -1
  35. package/dist/{executor-BhthPE1q.js → executor-BFaR2nfc.js} +3 -3
  36. package/dist/{executor-BhthPE1q.js.map → executor-BFaR2nfc.js.map} +1 -1
  37. package/dist/{extensions-BgBwogRW.js → extensions-DIbpUj5R.js} +3 -3
  38. package/dist/{extensions-BgBwogRW.js.map → extensions-DIbpUj5R.js.map} +1 -1
  39. package/dist/extensions.d.ts +1 -1
  40. package/dist/extensions.js +1 -1
  41. package/dist/{fold-rules-DSypi36k.d.ts → fold-rules-CMpWNPqk.d.ts} +2 -2
  42. package/dist/{fold-rules-DSypi36k.d.ts.map → fold-rules-CMpWNPqk.d.ts.map} +1 -1
  43. package/dist/{headless-R4pbpTkm.js → headless-Bs9Lb4vs.js} +4 -4
  44. package/dist/{headless-R4pbpTkm.js.map → headless-Bs9Lb4vs.js.map} +1 -1
  45. package/dist/headless.d.ts +1 -1
  46. package/dist/headless.js +1 -1
  47. package/dist/history-worker.js +1 -1
  48. package/dist/{host-scoped-settings-C-Nmb6vr.js → host-scoped-settings-DxxI_yRo.js} +2 -2
  49. package/dist/{host-scoped-settings-C-Nmb6vr.js.map → host-scoped-settings-DxxI_yRo.js.map} +1 -1
  50. package/dist/{host-signals-BFudPyCT.js → host-signals-CQ2jZR-2.js} +5 -5
  51. package/dist/{host-signals-BFudPyCT.js.map → host-signals-CQ2jZR-2.js.map} +1 -1
  52. package/dist/{index-DyQyDLX1.d.ts → index-4mDRyTGJ.d.ts} +1722 -1691
  53. package/dist/index-4mDRyTGJ.d.ts.map +1 -0
  54. package/dist/{index-CDS7YdUC.d.ts → index-Dlmu8HnG.d.ts} +5 -5
  55. package/dist/{index-CDS7YdUC.d.ts.map → index-Dlmu8HnG.d.ts.map} +1 -1
  56. package/dist/{index-AqRZ3gEz.d.ts → index-QsAN9yjZ.d.ts} +3 -3
  57. package/dist/{index-AqRZ3gEz.d.ts.map → index-QsAN9yjZ.d.ts.map} +1 -1
  58. package/dist/index.d.ts +3 -3
  59. package/dist/index.js +8 -8
  60. package/dist/ipc/remote.d.ts +5 -5
  61. package/dist/ipc/remote.js +3 -3
  62. package/dist/ipc.d.ts +5 -5
  63. package/dist/ipc.js +9 -9
  64. package/dist/{links-rFaWqS2Y.js → links-D5itfH8P.js} +10 -10
  65. package/dist/{links-rFaWqS2Y.js.map → links-D5itfH8P.js.map} +1 -1
  66. package/dist/{mcp-allowlist-CLXweyxk.js → mcp-allowlist-BbnTBKNN.js} +2 -2
  67. package/dist/{mcp-allowlist-CLXweyxk.js.map → mcp-allowlist-BbnTBKNN.js.map} +1 -1
  68. package/dist/mcp.d.ts +1 -1
  69. package/dist/{oauth-7_48zR7n.js → oauth-Ck3wQX4Q.js} +66 -32
  70. package/dist/oauth-Ck3wQX4Q.js.map +1 -0
  71. package/dist/output/stream-json.d.ts +1 -1
  72. package/dist/output/terminal.d.ts +1 -1
  73. package/dist/plugins.d.ts +1 -1
  74. package/dist/{prelude-HzY_JEGq.js → prelude-qjPUkw4f.js} +26 -2
  75. package/dist/prelude-qjPUkw4f.js.map +1 -0
  76. package/dist/{presets-DXeHsd24.js → presets-C4hkykN-.js} +2 -2
  77. package/dist/{presets-DXeHsd24.js.map → presets-C4hkykN-.js.map} +1 -1
  78. package/dist/presets.d.ts +1 -1
  79. package/dist/presets.js +1 -1
  80. package/dist/{protocol-BIv1Yuvl.js → protocol-Do_i6Ras.js} +3 -1
  81. package/dist/protocol-Do_i6Ras.js.map +1 -0
  82. package/dist/providers/anthropic.d.ts +1 -1
  83. package/dist/providers/arcee.d.ts +1 -1
  84. package/dist/providers/baseten.d.ts +1 -1
  85. package/dist/providers/cerebras.d.ts +1 -1
  86. package/dist/providers/google.d.ts +1 -1
  87. package/dist/providers/local.d.ts +1 -1
  88. package/dist/providers/neuralwatt.d.ts +1 -1
  89. package/dist/providers/openai-compat.d.ts +1 -1
  90. package/dist/providers/openai.d.ts +1 -1
  91. package/dist/providers/openrouter.d.ts +1 -1
  92. package/dist/providers/xai.d.ts +1 -1
  93. package/dist/providers.d.ts +1 -1
  94. package/dist/{registry-eourRLY2.js → registry-DxPP_tAt.js} +3 -3
  95. package/dist/{registry-eourRLY2.js.map → registry-DxPP_tAt.js.map} +1 -1
  96. package/dist/{remote-hosts-DY2J07ut.js → remote-hosts-BkOwRszu.js} +4 -4
  97. package/dist/{remote-hosts-DY2J07ut.js.map → remote-hosts-BkOwRszu.js.map} +1 -1
  98. package/dist/restate.d.ts +1 -1
  99. package/dist/{secret-shapes-BjW4l6U0.js → secret-shapes-HvaYVzwc.js} +10 -2
  100. package/dist/secret-shapes-HvaYVzwc.js.map +1 -0
  101. package/dist/session/sqlite.d.ts +1 -1
  102. package/dist/{session-7TUHs42_.js → session-CCsKXID6.js} +6 -2
  103. package/dist/session-CCsKXID6.js.map +1 -0
  104. package/dist/{session-factory-CMwIXE-7.js → session-factory-Ct7J9CK1.js} +6 -6
  105. package/dist/{session-factory-CMwIXE-7.js.map → session-factory-Ct7J9CK1.js.map} +1 -1
  106. package/dist/session.d.ts +2 -2
  107. package/dist/session.js +1 -1
  108. package/dist/{settings-keys-CPdmkTz7.js → settings-keys-QoGJ5n3e.js} +4 -4
  109. package/dist/{settings-keys-CPdmkTz7.js.map → settings-keys-QoGJ5n3e.js.map} +1 -1
  110. package/dist/{shell-path-B8b3EOtK.js → shell-path-BXXtRmEA.js} +4 -4
  111. package/dist/{shell-path-B8b3EOtK.js.map → shell-path-BXXtRmEA.js.map} +1 -1
  112. package/dist/skills.d.ts +1 -1
  113. package/dist/{spaces-CyjMh5Zf.js → spaces-C_x2bvEl.js} +14 -4
  114. package/dist/spaces-C_x2bvEl.js.map +1 -0
  115. package/dist/{store-L01W0gGI.js → store-BpkWIaSH.js} +10 -30
  116. package/dist/store-BpkWIaSH.js.map +1 -0
  117. package/dist/{todo-edits-BERpCRPj.js → todo-edits-DKoxu7Ss.js} +3 -3
  118. package/dist/{todo-edits-BERpCRPj.js.map → todo-edits-DKoxu7Ss.js.map} +1 -1
  119. package/dist/tools/fetch-url.d.ts +1 -1
  120. package/dist/tools/web-search.d.ts +1 -1
  121. package/dist/{tools-pZVFIJ_K.js → tools-FHEIKGkh.js} +2 -2
  122. package/dist/{tools-pZVFIJ_K.js.map → tools-FHEIKGkh.js.map} +1 -1
  123. package/dist/tools.d.ts +1 -1
  124. package/dist/tools.js +2 -2
  125. package/dist/{transcript-anchors-jHrg-r-H.js → transcript-anchors-D8jWLpe5.js} +10 -10
  126. package/dist/{transcript-anchors-jHrg-r-H.js.map → transcript-anchors-D8jWLpe5.js.map} +1 -1
  127. package/dist/{transcript-cache-DXdgVuoy.js → transcript-cache-CdHKtx9y.js} +4 -4
  128. package/dist/{transcript-cache-DXdgVuoy.js.map → transcript-cache-CdHKtx9y.js.map} +1 -1
  129. package/dist/{transcript-reconcile-CPdrNbbR.js → transcript-reconcile-D_SWw6dX.js} +11 -3
  130. package/dist/transcript-reconcile-D_SWw6dX.js.map +1 -0
  131. package/dist/tui.d.ts +7 -7
  132. package/dist/tui.js +24 -23
  133. package/dist/tui.js.map +1 -1
  134. package/dist/{turn-operations-DuGtKuc_.d.ts → turn-operations-Dbk3xPKu.d.ts} +11 -3
  135. package/dist/{turn-operations-DuGtKuc_.d.ts.map → turn-operations-Dbk3xPKu.d.ts.map} +1 -1
  136. package/dist/{types-C0PJmBaO.d.ts → types-CMXR7A0b.d.ts} +2 -2
  137. package/dist/{types-C0PJmBaO.d.ts.map → types-CMXR7A0b.d.ts.map} +1 -1
  138. package/dist/types-CzmghX7C.js.map +1 -1
  139. package/dist/types.d.ts +2 -2
  140. package/dist/{url-D8KZ7Edw.js → url-D4vG7lzO.js} +2 -2
  141. package/dist/{url-D8KZ7Edw.js.map → url-D4vG7lzO.js.map} +1 -1
  142. package/dist/{version-bd3DQJkc.js → version-DDRBX7K6.js} +2 -2
  143. package/dist/{version-bd3DQJkc.js.map → version-DDRBX7K6.js.map} +1 -1
  144. package/dist/{workspace-exec-stream-CyfYgqAh.js → workspace-exec-stream-iHv9cooF.js} +5 -5
  145. package/dist/{workspace-exec-stream-CyfYgqAh.js.map → workspace-exec-stream-iHv9cooF.js.map} +1 -1
  146. package/dist/{write-file-QYrcDdl3.js → write-file-ChtRPdEL.js} +3 -3
  147. package/dist/{write-file-QYrcDdl3.js.map → write-file-ChtRPdEL.js.map} +1 -1
  148. package/dist/{ws-CURQ2igk.js → ws-B2HB87nz.js} +6 -6
  149. package/dist/{ws-CURQ2igk.js.map → ws-B2HB87nz.js.map} +1 -1
  150. package/dist/{ws-client-BVljYbdb.js → ws-client-DPC9ZJHr.js} +4 -4
  151. package/dist/{ws-client-BVljYbdb.js.map → ws-client-DPC9ZJHr.js.map} +1 -1
  152. package/docs/CODEMODE.md +6 -0
  153. package/docs/IPC.md +2 -0
  154. package/docs/ONBOARDING.md +1 -1
  155. package/package.json +1 -1
  156. package/dist/client-core-EEEX_u6D.d.ts.map +0 -1
  157. package/dist/dispatcher-Bv9-c6I2.js.map +0 -1
  158. package/dist/index-DyQyDLX1.d.ts.map +0 -1
  159. package/dist/oauth-7_48zR7n.js.map +0 -1
  160. package/dist/prelude-HzY_JEGq.js.map +0 -1
  161. package/dist/protocol-BIv1Yuvl.js.map +0 -1
  162. package/dist/secret-shapes-BjW4l6U0.js.map +0 -1
  163. package/dist/session-7TUHs42_.js.map +0 -1
  164. package/dist/spaces-CyjMh5Zf.js.map +0 -1
  165. package/dist/store-L01W0gGI.js.map +0 -1
  166. package/dist/transcript-reconcile-CPdrNbbR.js.map +0 -1
@@ -43,8 +43,8 @@
43
43
  * `/// <reference types="zidane" />` or an `import type { ExtensionContext } from 'zidane'`
44
44
  * (type-only imports don't need a runtime resolution) to recover it.
45
45
  */
46
- import { C as TaskExitInfo, g as ExecutionHandle, h as ExecutionContext, m as ExecResult, n as IsolationPolicy, v as ListFilesEntry, y as ListFilesOptions } from "./isolation-CbGNAEhQ.js";
47
46
  import { m as RunErrorDetail, u as ClassifiedError } from "./timeout-BcfGsZZG.js";
47
+ import { C as TaskExitInfo, g as ExecutionHandle, h as ExecutionContext, m as ExecResult, n as IsolationPolicy, v as ListFilesEntry, y as ListFilesOptions } from "./isolation-CbGNAEhQ.js";
48
48
  import { a as getOAuthApiKey, n as OAuthCallbackPageRenderer, r as OAuthProviderInterface } from "./oauth-callback-page-B3Xo3X2J.js";
49
49
  import { Hookable } from "hookable";
50
50
  import { AssistantMessage, AssistantMessageEventStream, Message, Model, SimpleStreamOptions, TranscriptContext } from "@earendil-works/pi-ai";
@@ -76,1870 +76,1883 @@ interface ProviderDiagnostic {
76
76
  retryAfter?: string;
77
77
  }
78
78
  //#endregion
79
- //#region src/providers/model-catalog.d.ts
80
- /**
81
- * Model catalog override — the one seam for replacing model metadata.
82
- *
83
- * zidane resolves model metadata (output ceiling, pricing, context window,
84
- * reasoning support) from pi-ai's bundled registry. That registry is a
85
- * snapshot: it can't know a gateway alias, a private deployment, a model
86
- * released after our dependency pin, or a non-Anthropic model served over the
87
- * Anthropic wire. Without a seam, consumers either patch our source (the
88
- * `EXTRA_COST_RATES` table in `cost.ts` exists because of exactly that) or
89
- * mutate pi-ai's unfrozen catalog behind our back.
90
- *
91
- * Two ways to supply one, both first-class:
92
- *
93
- * - `behavior.modelCatalog` — per agent, and per run like every other
94
- * behavior field. No process-wide state, so two agents can carry
95
- * different catalogs.
96
- * - {@link setModelCatalog} — process-wide default. Also the only source
97
- * the chat/TUI layer can see (the model picker resolves metadata before
98
- * any agent exists).
99
- *
100
- * Resolution, first hit wins: run behavior → agent behavior → global →
101
- * pi-ai's bundled registry → local fallback tables.
102
- *
103
- * Everything stays keyed by `(provider, modelId)`: nothing is flattened
104
- * across providers, and overriding one provider leaves the others fully
105
- * bundled. The provider key is the pi-ai registry id, which is usually the
106
- * factory name (`anthropic`, `cerebras`, `openrouter`, …) — with one
107
- * exception: the Codex provider stores model records under `openai-codex` and
108
- * prices them under `openai`, and accepts an entry keyed EITHER way — on the
109
- * wire via {@link aliasCatalogProviders} and in the host layer via the
110
- * descriptor's key set, so an override can't half-apply.
111
- *
112
- * Two operational notes:
113
- *
114
- * - **Serialization.** The table form is plain JSON; the `{ get, list }`
115
- * form holds functions. A durable / replay runtime that snapshots
116
- * `behavior` can only round-trip the table form — build the source form
117
- * inside the process that runs the agent, or install it with
118
- * {@link setModelCatalog} at boot.
119
- * - **Multi-tenancy.** {@link setModelCatalog} is process-wide, so in a
120
- * shared server it applies to every tenant. Pass `behavior.modelCatalog`
121
- * per agent / per run instead; the global is for a deployment-wide
122
- * correction and for the host's model picker.
123
- */
124
- /**
125
- * Size class of a model within its provider's lineup. Drives the automatic
126
- * text model (titles, suggestions): the smallest current model of the
127
- * session's provider. Bundled models get it from a family heuristic
128
- * (`src/chat/text-model.ts`); a catalog entry's value wins over it.
129
- */
130
- type ModelTier = 'small' | 'medium' | 'large';
79
+ //#region src/session/artifacts.d.ts
80
+ /** Built-in kinds. Open set — extensions add their own. */
81
+ declare const ARTIFACT_KINDS: {
82
+ readonly pullRequest: "pull_request";
83
+ readonly branch: "branch";
84
+ readonly commit: "commit";
85
+ readonly file: "file";
86
+ };
131
87
  /**
132
- * Metadata for one model. Every field is optional and merges FIELD-LEVEL over
133
- * the bundled entry, so `{ maxTokens: 128000 }` corrects the ceiling and
134
- * leaves pricing and context window to the registry.
88
+ * Reserved tool-result metadata namespace. Tools (and extension
89
+ * `detect` hooks) emit `metadata.artifacts = ArtifactInput[]` and the
90
+ * loop lifts each entry into the session's artifact store.
135
91
  */
136
- interface ModelCatalogEntry {
137
- /** Model id. Required only for entries surfaced through {@link ModelCatalogSource.list}. */
138
- id?: string;
139
- /** Display name for pickers. */
140
- name?: string;
141
- /** Max output tokens — the provider's `max_tokens` default and hard clamp. */
142
- maxTokens?: number;
143
- /** Total context window, in tokens (drives the host-layer context gauge). */
144
- contextWindow?: number;
145
- /** Whether the model supports reasoning/thinking. */
146
- reasoning?: boolean;
147
- /** Accepted input modalities. */
148
- input?: readonly ('text' | 'image')[];
92
+ declare const ARTIFACTS_METADATA_KEY = "artifacts";
93
+ /** Maximum size of an artifact `meta` value, in bytes of its JSON encoding. Larger values are dropped. */
94
+ declare const ARTIFACT_META_MAX_BYTES = 16384;
95
+ /** Maximum number of artifacts kept per session. Stores evict the oldest `file` artifacts first. */
96
+ declare const ARTIFACTS_PER_SESSION_CAP = 200;
97
+ /** A recorded output of a session, such as a pull request, a branch, a commit or a file. */
98
+ interface SessionArtifact {
99
+ /** Stable id (uuid). Preserved across upserts of the same `(kind, uri)`. */
100
+ id: string;
101
+ /** Id of the session the artifact belongs to. */
102
+ sessionId: string;
149
103
  /**
150
- * Per-MTok rates used for cost estimation. Merges PER-RATE over the bundled
151
- * rates, so `{ cost: { output: 30 } }` corrects the output rate and keeps the
152
- * registry's input / cache rates rather than zeroing them.
104
+ * Run that produced it. A `persist`-spawned subagent shares the parent
105
+ * session and records under its OWN run id (detection reaches it via the
106
+ * `child:tool:transform` bubble; see `presets/artifacts.ts`).
153
107
  */
154
- cost?: {
155
- input?: number;
156
- output?: number;
157
- cacheRead?: number;
158
- cacheWrite?: number;
159
- };
160
- /** Size class; overrides the family heuristic. */
161
- tier?: ModelTier;
162
- }
163
- /**
164
- * Programmatic catalog. Both members are optional and both fall through on
165
- * `undefined`, which is what keeps overrides scoped to the providers you
166
- * actually own.
167
- */
168
- interface ModelCatalogSource {
108
+ runId?: string;
109
+ /** Tool-result turn that produced it — the transcript anchor. */
110
+ turnId?: string;
111
+ /** Open kind string. Built-ins in {@link ARTIFACT_KINDS}. */
112
+ kind: string;
113
+ /** Canonical locator: PR URL, `git:<repo>#<branch>`, `file://<abs path>`, … */
114
+ uri: string;
115
+ /** Human line. Always present — the rendering fallback for unknown kinds. */
116
+ label: string;
169
117
  /**
170
- * Resolve one model. Return `undefined` to fall through to the bundled
171
- * entry for that `(provider, modelId)`.
118
+ * Project the artifact landed in, resolved at emission time from where
119
+ * the thing actually is (a worktree, a sibling repo), defaulting to the
120
+ * session's own `projectRoot`. Drives "everything produced from this
121
+ * repo" queries.
172
122
  */
173
- get?: (provider: string, modelId: string) => ModelCatalogEntry | undefined;
123
+ projectRoot?: string;
124
+ /** Kind-specific payload, ≤ {@link ARTIFACT_META_MAX_BYTES}. */
125
+ meta?: JsonValue;
126
+ /** Creation time as epoch milliseconds. */
127
+ createdAt: number;
128
+ /** Last update time as epoch milliseconds. */
129
+ updatedAt: number;
130
+ }
131
+ /** What a producer hands to `session.addArtifact` / the metadata namespace. */
132
+ interface SessionArtifactInput {
133
+ /** Open kind string. See `ARTIFACT_KINDS` for the built-in ones. */
134
+ kind: string;
135
+ /** Canonical locator of the artifact. */
136
+ uri: string;
137
+ /** Human-readable line shown for the artifact. */
138
+ label: string;
139
+ /** Project the artifact landed in. Default: the session project. */
140
+ projectRoot?: string;
141
+ /** Kind-specific payload, at most `ARTIFACT_META_MAX_BYTES`. */
142
+ meta?: JsonValue;
143
+ }
144
+ /** Filter for listing artifacts. Fields combine with AND. */
145
+ interface ArtifactFilter {
146
+ /** Only artifacts of this session. */
147
+ sessionId?: string;
174
148
  /**
175
- * Enumerate a provider's models (model pickers, `modelsForDescriptor`).
176
- *
177
- * - `undefined` → use the bundled list for that provider (the default).
178
- * - `[…]` → you own that provider's list; bundled entries are not
179
- * consulted, so this both adds and hides.
180
- * - `[]` → you own it and it has no models (hides the picker).
149
+ * Tri-state like `SessionStore.list`: string → that project only,
150
+ * `null` → artifacts with no project, omitted → axis ignored.
181
151
  */
182
- list?: (provider: string) => readonly ModelCatalogEntry[] | undefined;
152
+ projectRoot?: string | null;
153
+ /** Only artifacts of this kind. */
154
+ kind?: string;
155
+ /** Exact locator match — reverse lookup ("who produced PR #123?"). Pair with `kind`. */
156
+ uri?: string;
157
+ /** Only artifacts with `updatedAt >= since`. */
158
+ since?: number;
159
+ /** Maximum number of artifacts to return. */
160
+ limit?: number;
183
161
  }
184
162
  /**
185
- * A catalog: either a {@link ModelCatalogSource} or the table shorthand —
186
- * a plain record keyed `"<provider>:<modelId>"`.
187
- *
188
- * The table form is a pure OVERLAY: entries patch or add models, and each
189
- * provider keeps every bundled model the table doesn't name. Hiding bundled
190
- * models requires the `list` function, so the easy path can't accidentally
191
- * blank a provider's picker.
192
- *
193
- * ```ts
194
- * setModelCatalog({ 'openai:gpt-5.6': { maxTokens: 128000 } })
195
- * ```
163
+ * Validate + normalize a raw input (typically from tool-result metadata,
164
+ * i.e. an untrusted boundary). Returns `null` when the entry is unusable
165
+ * — missing kind/uri/label or oversized in a way truncation can't fix.
166
+ * `label` is clipped, `meta` is dropped (not the artifact) when it exceeds
167
+ * the byte bound.
168
+ * @param raw - Untrusted value, typically from tool-result metadata.
196
169
  */
197
- type ModelCatalog = ModelCatalogSource | Readonly<Record<string, ModelCatalogEntry>>;
170
+ declare function normalizeArtifactInput(raw: unknown): SessionArtifactInput | null;
198
171
  /**
199
- * Install (or clear, with `null`) the process-wide catalog. Latest call wins.
200
- *
201
- * Prefer `behavior.modelCatalog` when you can: it needs no global state and
202
- * scopes to one agent or one run. Use this for a deployment-wide correction,
203
- * or when the host's model picker must see the override too.
204
- *
205
- * @param catalog - Catalog to install, or `null` to clear it.
172
+ * Apply an upsert to an existing row: identity fields (`id`, `runId`,
173
+ * `turnId`, `createdAt`) stay, `label` refreshes, `meta` and `projectRoot`
174
+ * refresh when the incoming artifact has them, and `updatedAt` becomes the
175
+ * later of the two. Shared by every store so the
176
+ * merge semantics can't drift.
177
+ * @param existing - Stored artifact.
178
+ * @param incoming - Artifact being upserted.
206
179
  */
207
- declare function setModelCatalog(catalog: ModelCatalog | null): void;
208
- /** The process-wide catalog, normalized to source form. */
209
- declare function getModelCatalog(): ModelCatalogSource | undefined;
210
- //#endregion
211
- //#region src/thinking-levels.d.ts
180
+ declare function mergeArtifact(existing: SessionArtifact, incoming: SessionArtifact): SessionArtifact;
212
181
  /**
213
- * Thinking / extended-reasoning configuration. Dependency-free, so the
214
- * browser-safe surfaces (`zidane/chat/pure`) can validate a stored effort.
215
- *
216
- * - `'off'` — no thinking.
217
- * - `'minimal' | 'low' | 'medium' | 'high' | 'xhigh' | 'max'` — explicit
218
- * effort tier. Maps to provider-specific reasoning controls (Anthropic
219
- * `output_config.effort`; OpenAI-compatible providers clamp to their
220
- * supported tiers).
221
- * - `'adaptive'` — let the model decide per-turn whether and how much to think.
222
- * Anthropic-only (`thinking.type='adaptive'`). Other providers fall back to
223
- * no reasoning when this value is supplied.
182
+ * Which artifacts to evict so a session stays at or under `cap` after
183
+ * one more insert. `file` artifacts go first (noisiest, cheapest to
184
+ * regenerate), oldest first within a kind; ties keep the caller's order
185
+ * (stable sort), so pass rows in insertion order. Pure — callers delete
186
+ * the returned ids.
187
+ * @param current - Artifacts currently stored for the session, in insertion order.
188
+ * @param cap - Maximum number of artifacts per session.
224
189
  */
225
- declare const THINKING_LEVELS: readonly ["off", "minimal", "low", "medium", "high", "xhigh", "max", "adaptive"];
226
- /** One of the {@link THINKING_LEVELS} strings: how much the model reasons before it answers. */
227
- type ThinkingLevel = (typeof THINKING_LEVELS)[number];
190
+ declare function selectArtifactEvictions(current: readonly SessionArtifact[], cap?: number): string[];
228
191
  /**
229
- * Type guard for canonical `ThinkingLevel` strings (e.g. `metadata.effort` read off a persisted session).
192
+ * Tests an artifact against a filter. An undefined filter matches everything. `limit` is not applied here.
230
193
  *
231
- * @param value - Any value, usually a string read from storage or settings.
194
+ * @param artifact - Artifact to test.
195
+ * @param filter - Filter to apply.
232
196
  */
233
- declare function isThinkingLevel(value: unknown): value is ThinkingLevel;
234
- //#endregion
235
- //#region src/mcp/transport.d.ts
197
+ declare function matchesArtifactFilter(artifact: SessionArtifact, filter: ArtifactFilter | undefined): boolean;
236
198
  /**
237
- * Line-splitting core shared by the two stderr pumps: the Node-stream one
238
- * below (host stdio children) and the async-iterable one in
239
- * `./context-transport.ts` (children living in an execution context).
240
- * Same buffering, same overlong-line cap, same fire-and-forget `mcp:warn`.
241
- * @param serverName - Server name reported in each `mcp:warn` payload.
242
- * @param hooks - Agent hooks to fire `mcp:warn` on. Lines are dropped when `undefined`.
199
+ * Newest first, stable on id.
200
+ * @param artifacts - Artifacts to sort. The array is sorted in place.
243
201
  */
244
- declare function createStderrLineEmitter(serverName: string, hooks: Hookable<AgentHooks> | undefined): {
245
- push: (text: string) => void;
246
- flush: () => void;
247
- };
248
- /**
249
- * Reads a stdio child's stderr to the end and fires `mcp:warn` for each non-empty line. Does nothing when the transport has no stderr stream.
250
- *
251
- * @param transport - Transport that may expose a `stderr` stream.
252
- * @param serverName - Server name reported in each `mcp:warn` payload.
253
- * @param hooks - Agent hooks to fire `mcp:warn` on.
202
+ declare function sortArtifacts(artifacts: SessionArtifact[]): SessionArtifact[];
203
+ //#endregion
204
+ //#region src/session/messages-pairing.d.ts
205
+ /**
206
+ * Placeholder content inserted into a synthetic `tool_result` when the harness
207
+ * has to repair an orphan `tool_use`. Exported so downstream consumers
208
+ * (training-data collectors, HFI submission) can reject any payload containing
209
+ * it — the marker satisfies the wire-level pairing contract structurally but
210
+ * the content itself is fake and would poison fine-tuning data.
254
211
  */
255
- declare function attachStderrWarnPump(transport: {
256
- stderr?: {
257
- on: (event: string, listener: (...args: unknown[]) => void) => unknown;
258
- } | null;
259
- }, serverName: string, hooks: Hookable<AgentHooks> | undefined): void;
212
+ declare const SYNTHETIC_TOOL_RESULT_PLACEHOLDER = "[Tool result missing due to internal error]";
260
213
  /**
261
- * The execution context + live handle a `scope: 'context'` stdio server is
262
- * spawned into. Supplied by the agent once its handle exists; absent for
263
- * host-only setups, which is why every field is required here but the
264
- * binding itself is optional at the call site.
214
+ * Replacement text for an assistant message whose every content block was
215
+ * stripped during pairing repair (e.g. the only blocks were orphan
216
+ * `tool_call`s). Providers reject empty `content` arrays — the marker keeps
217
+ * the turn shape valid while signaling "this assistant turn lost its
218
+ * outputs" to the model so it can recover.
265
219
  */
266
- interface McpExecutionBinding {
267
- /** Execution context that hosts the server process. */
268
- context: ExecutionContext;
220
+ declare const TOOL_USE_INTERRUPTED_MARKER = "[Tool use interrupted]";
221
+ /**
222
+ * Replacement text for a user message whose every content block was a
223
+ * `tool_result` with no matching upstream `tool_call` (e.g. the assistant
224
+ * pair was stripped by an earlier compaction). Same role as
225
+ * {@link TOOL_USE_INTERRUPTED_MARKER} on the user side.
226
+ */
227
+ declare const ORPHANED_TOOL_RESULT_MARKER = "[Orphaned tool result removed due to conversation resume]";
228
+ /**
229
+ * Classification of a single repair the pairing pass performed. Surfaced via
230
+ * {@link EnsureToolResultPairingOptions.onRepair} so consumers can wire
231
+ * telemetry, debug logs, or strict-mode rejection without re-implementing the
232
+ * walk.
233
+ *
234
+ * Each entry corresponds to one of the corruption modes documented on
235
+ * {@link ensureToolResultPairing}.
236
+ */
237
+ type PairingRepairMode = 'orphan-tool-use-prepend' | 'orphan-tool-use-append' | 'orphan-tool-result-strip' | 'duplicate-tool-use-strip' | 'duplicate-tool-result-strip' | 'empty-assistant-marker' | 'duplicate-tool-use-remint';
238
+ /** One repair made by {@link ensureToolResultPairing}. */
239
+ interface PairingRepair {
240
+ /** Which repair was performed. See {@link PairingRepairMode}. */
241
+ mode: PairingRepairMode;
242
+ /** Tool-use / tool-result id this repair concerns. Absent for empty-marker repairs. */
243
+ callId?: string;
244
+ /** Zero-based index into the INPUT `messages` array where the corruption was found. */
245
+ messageIndex: number;
246
+ }
247
+ /** Options for {@link ensureToolResultPairing}. */
248
+ interface EnsureToolResultPairingOptions {
269
249
  /**
270
- * Resolve the execution handle, invoked ONLY when a `scope: 'context'`
271
- * stdio server actually builds its transport.
272
- *
273
- * Lazy on purpose. An eagerly-resolved handle would make merely *having* a
274
- * context-scoped server in the config force a sandbox spawn — including
275
- * for sub-agents, which inherit `mcpServers` but reuse the parent's live
276
- * connection through `nonOwningMcpConnector` and never touch this binding.
277
- * That would cold-boot a fresh sandbox per `spawn()` for nothing. Deferring
278
- * also means the agent needs no ordering special case: the handle is
279
- * created at the moment of first use, which is necessarily before the
280
- * `execStream` call that needs it.
250
+ * Fired once per repair the pass performed. Synchronous so the loop can
251
+ * stay on its hot path. Throwing from the callback aborts the pass —
252
+ * consumers wanting fail-fast (strict mode) can re-throw with their own
253
+ * typed error.
281
254
  */
282
- getHandle: () => Promise<ExecutionHandle>;
255
+ onRepair?: (repair: PairingRepair) => void;
283
256
  }
284
- //#endregion
285
- //#region src/mcp/origin-pinned-fetch.d.ts
286
257
  /**
287
- * The transport-reachability rule for a remote MCP endpoint: HTTPS anywhere,
288
- * plaintext HTTP only when it stays on the machine, nothing else.
258
+ * Defensive repair pass that rewrites a message list so it satisfies the
259
+ * wire-level `tool_use` ↔ `tool_result` adjacency contract every modern
260
+ * provider enforces.
289
261
  *
290
- * THE single encoding of that policy. It's enforced at two points on opposite
291
- * sides of the plugin boundary — once when validating a plugin's `mcp.json`
292
- * (`plugins/mcp.ts`), and again per redirect hop inside
293
- * {@link originPinnedFetch} — and those two must never disagree. If they did,
294
- * a URL the loader refused could still be reached by redirect, which is the
295
- * exact hole the pinning exists to close. Relaxing the rule (private ranges,
296
- * `*.localhost`, …) is then a one-line change that both sites inherit.
262
+ * Anthropic 400s on orphans with `'tool_use' ids were found without
263
+ * 'tool_result' blocks immediately after` (and its inverse, `tool_result
264
+ * must be preceded by a tool_call with the same toolCallId`). OpenAI's
265
+ * Chat Completions API rejects most mismatches with a 400 too.
297
266
  *
298
- * Scheme and host only. Authoring rules that apply to a CONFIGURED url but
299
- * have no meaning for a redirect target — no userinfo, no fragment — stay with
300
- * the loader.
301
- * @param url - Endpoint to check.
302
- */
303
- declare function isAllowedRemoteUrl(url: URL): boolean;
304
- /**
305
- * The fetch shape this wrapper supports — deliberately narrower than
306
- * `typeof fetch`, matching the MCP SDK's `FetchLike`.
267
+ * Six repair modes — modeled after Anthropic's Claude Code defenses:
307
268
  *
308
- * A `Request` input is NOT accepted: the wrapper rebuilds each hop from
309
- * `init`, so it would silently drop a Request's method, headers and body and
310
- * issue a bare credential-less GET. Narrowing the type makes that shape
311
- * unrepresentable rather than a quiet failure on a security-relevant helper.
312
- * Both SDK transports only ever pass a URL plus init.
313
- */
314
- type PinnedFetch = (url: string | URL, init?: RequestInit) => Promise<Response>;
315
- /**
316
- * Wrap `baseFetch` so `headerNames` are dropped on any hop that leaves the
317
- * origin of `configuredUrl`, and so a redirect cannot downgrade the session
318
- * to cleartext.
269
+ * | # | Corruption | Repair |
270
+ * |---|------------|--------|
271
+ * | 1 | assistant `tool_use` whose next user msg lacks a matching `tool_result` | **Prepend** a synthetic `tool_result` block carrying {@link SYNTHETIC_TOOL_RESULT_PLACEHOLDER} with `isError: true` |
272
+ * | 2 | assistant `tool_use` followed by nothing (or by a non-user msg) | **Insert** a new synthetic user message with the same placeholder |
273
+ * | 3 | user `tool_result` with no preceding assistant `tool_call` | **Strip** the orphan block; if it empties the msg, replace with {@link ORPHANED_TOOL_RESULT_MARKER} text block |
274
+ * | 4 | duplicate `tool_call.id` across assistant messages (CC-1212) | **Strip** later instances + their matching tool_results |
275
+ * | 5 | duplicate `tool_result.callId` within a single user message | **Dedupe** by `callId`, keep first |
276
+ * | 6 | assistant message emptied by mode-4 stripping | **Replace** content with {@link TOOL_USE_INTERRUPTED_MARKER} text block |
319
277
  *
320
- * `authorization` is ALWAYS protected, whether or not the caller listed it.
321
- * The MCP SDK's OAuth provider injects that header per request rather than
322
- * through `McpServerConfig.headers` — `bootstrapServer` attaches a provider to
323
- * a flagless server whenever stored tokens exist — so a strip list derived
324
- * only from the configured header names would leave the bearer token exposed
325
- * on exactly the servers that have one.
326
- * @param configuredUrl - Configured server URL. Its origin is the pinned origin.
327
- * @param headerNames - Configured header names to drop when a redirect leaves the pinned origin.
328
- * @param baseFetch - Fetch implementation to wrap. Default: the global `fetch`.
278
+ * **Repair, not drop.** Dropping orphan blocks would (a) silently rewrite
279
+ * history the model had reasoned over and (b) cascade — dropping an assistant
280
+ * tool_call would orphan its tool_result, which would then get dropped too,
281
+ * removing any trace of "what the model tried to do" from the transcript. This
282
+ * pass preserves the model's tool_use shape and patches the dangling result
283
+ * with an `is_error` placeholder so the model sees "I tried X, the result was
284
+ * lost" and can retry intelligently.
285
+ *
286
+ * Adjacency contract: `tool_result` blocks must live in the user message
287
+ * IMMEDIATELY following the assistant message that emitted the matching
288
+ * `tool_use`. The pass enforces strict adjacency — a tool_result two
289
+ * messages downstream of its tool_call is still an orphan.
290
+ *
291
+ * Idempotent: returns the input reference unchanged when no repairs were
292
+ * necessary. Re-running on already-repaired output is a no-op.
293
+ *
294
+ * Pure: does not mutate input messages or their content arrays — every
295
+ * repair allocates a fresh array / object.
296
+ * @param messages - Wire messages to repair. They are not modified.
297
+ * @param options - Repair callback. See {@link EnsureToolResultPairingOptions}.
329
298
  */
330
- declare function originPinnedFetch(configuredUrl: string, headerNames: readonly string[], baseFetch?: PinnedFetch): PinnedFetch;
331
- //#endregion
332
- //#region src/mcp/server-config.d.ts
299
+ declare function ensureToolResultPairing(messages: SessionMessage[], options?: EnsureToolResultPairingOptions): SessionMessage[];
300
+ /** Result of {@link remintDuplicateToolCallIds}. */
301
+ interface RemintResult {
302
+ /** Tool calls with duplicate ids replaced. Same reference when unchanged. */
303
+ toolCalls: Array<{
304
+ id: string;
305
+ name: string;
306
+ input: Record<string, unknown>;
307
+ }>;
308
+ /** Assistant content with matching `tool_call` block ids rewritten. Same reference when unchanged. */
309
+ content: SessionContentBlock[];
310
+ /** One entry per re-minted occurrence, in emission order. */
311
+ reminted: Array<{
312
+ oldId: string;
313
+ newId: string;
314
+ }>;
315
+ }
333
316
  /**
334
- * The config a transport is actually built from.
317
+ * Re-mint tool-call ids that collide with ids already present in the
318
+ * transcript (or with an earlier sibling in the same turn), BEFORE the turn
319
+ * is persisted and its tools dispatched.
335
320
  *
336
- * `${VAR}` placeholders resolve HERE, not at normalize time — see
337
- * {@link expandMcpConfigEnv} for why (config writers round-trip normalized
338
- * configs to disk; expanded secrets must never ride along).
321
+ * Why this exists: some providers/serving stacks emit non-globally-unique
322
+ * tool_use ids (per-turn counters like `call_0`, retry-replay duplicates,
323
+ * Kimi-K2.6 on Fireworks). The wire-time pairing pass
324
+ * ({@link ensureToolResultPairing}) can only STRIP such duplicates — which
325
+ * erases the model's tool calls and results from the wire view, stalls
326
+ * progress, and re-accumulates repairs quadratically because the persisted
327
+ * session keeps the corrupted ids. Re-minting at persist time keeps the
328
+ * pairing intact instead: the call, its execution, and its tool_result all
329
+ * carry the fresh id, so the pairing pass has nothing to strip on any later
330
+ * turn.
339
331
  *
340
- * A `preExpanded` config skips the pass entirely. The Agent Plugins loader
341
- * has already substituted the only two placeholders that spec permits, in
342
- * only the three fields it permits, so a second pass would both widen the
343
- * scope (into `command` / `url` / `headers`) and let an ambient
344
- * `PLUGIN_ROOT` env var reach text the spec says stays literal. See
345
- * {@link McpServerConfig.preExpanded}.
346
- * @param config - Normalized server config.
332
+ * Fresh ids are `${oldId}_r{n}` with `n` bumped until unique — deterministic
333
+ * shape, Anthropic-wire-safe charset (given a safe input id), and visibly
334
+ * traceable back to the original.
335
+ *
336
+ * Alignment contract: `toolCalls` and the `tool_call` blocks inside
337
+ * `content` are two views of the same emission and MUST be in the same
338
+ * order (true for every provider — both are built from one source array).
339
+ * Occurrences are matched positionally per old id so intra-turn duplicates
340
+ * map to distinct fresh ids on both views.
341
+ *
342
+ * Pure: returns the input references unchanged when no id collides.
343
+ * @param toolCalls - Tool calls of the new assistant turn.
344
+ * @param content - Content blocks of the same turn, with `tool_call` blocks in the same order as `toolCalls`.
345
+ * @param priorIds - Tool call ids already in the transcript.
347
346
  */
348
- declare function resolveTransportConfig(config: McpServerConfig): McpServerConfig;
347
+ declare function remintDuplicateToolCallIds(toolCalls: ReadonlyArray<{
348
+ id: string;
349
+ name: string;
350
+ input: Record<string, unknown>;
351
+ }>, content: readonly SessionContentBlock[], priorIds: ReadonlySet<string>): RemintResult;
349
352
  /**
350
- * Expand environment-variable placeholders in one config string. The
351
- * `:-default` form follows shell semantics — the default substitutes when
352
- * the variable is unset OR EMPTY (that's what `:-` means in every shell,
353
- * and what users pasting the form expect; empty-but-set without a default
354
- * still expands to the empty string, as `${VAR}` does in a shell). An
355
- * unset variable without a default is left VERBATIM (matching Claude
356
- * Code) — a literal `${…}` failing loudly at the server beats an empty
357
- * token failing mysteriously — and a debug-gated warning names the
358
- * missing variable.
359
- * @param value - String that may contain `${VAR}`, `${VAR:-default}` or `${env:VAR}`.
360
- * @param env - Variables to resolve against. Default: `process.env`.
353
+ * Classification of a single deletion {@link dropInvalidToolPairings}
354
+ * performed. Surfaced via `onDrop` for telemetry.
361
355
  */
362
- declare function expandEnvPlaceholders(value: string, env?: Record<string, string | undefined>): string;
356
+ type PairingDropKind = 'duplicate-tool-call' | 'duplicate-tool-result' | 'orphan-tool-result' | 'empty-turn';
357
+ /** One deletion made by {@link dropInvalidToolPairings}. */
358
+ interface PairingDrop {
359
+ /** What was dropped. See {@link PairingDropKind}. */
360
+ kind: PairingDropKind;
361
+ /** Tool-call / tool-result id the drop concerns. Absent for empty-turn drops. */
362
+ callId?: string;
363
+ /** Zero-based index into the INPUT `turns` array. */
364
+ index: number;
365
+ }
363
366
  /**
364
- * Expanded COPY of a server config for runtime use — `${VAR}` placeholders
365
- * resolved across every string field that can carry secrets or
366
- * machine-specific paths (command, args, env/header values, url, cwd).
367
+ * Drop-only normalization of persisted history: delete structurally invalid
368
+ * tool blocks so the transcript never re-triggers wire-time pairing repairs
369
+ * turn after turn.
367
370
  *
368
- * Deliberately NOT part of `normalizeMcpServers`: normalized configs are
369
- * round-tripped back to disk by config writers (e.g. the Claude import
370
- * copies parsed entries into zidane-owned `mcps.json`), and expanding
371
- * there would MATERIALIZE resolved tokens into files. Expansion happens
372
- * only at the transport boundary ({@link createTransport}, the login
373
- * flow's mirror) — secrets exist in the connecting process's memory and
374
- * nowhere else.
375
- * @param config - Server config to expand.
376
- * @param env - Variables to resolve against. Default: `process.env`.
371
+ * Unlike {@link ensureToolResultPairing} — which SYNTHESIZES placeholder
372
+ * content and must therefore stay wire-only (fabricated results would poison
373
+ * persisted history and training data) — this pass performs pure deletions of
374
+ * blocks that are provably invalid regardless of interpretation:
375
+ *
376
+ * | Corruption | Action |
377
+ * |------------|--------|
378
+ * | duplicate `tool_call` id within one run lane (across or within turns) | drop the later instance |
379
+ * | duplicate `tool_result.callId` within one turn | drop the later instance |
380
+ * | `tool_result` with no matching `tool_call` in the immediately preceding same-lane assistant turn | drop the block |
381
+ * | turn emptied by the drops above (reasoning-only remainders count as empty) | drop the whole turn |
382
+ *
383
+ * Duplicate detection is scoped to the WIRE-VIEW lane: tool_call ids only
384
+ * collide when both instances reach one model request. By default a turn's
385
+ * lane is its raw `runId` — correct for parent/subagent interleaving, where
386
+ * providers minting per-conversation counter ids (`call_0`, `call_1`)
387
+ * legitimately reuse the same id across lanes. Callers that know the run
388
+ * topology (see `createSession`) pass `laneForRun` to widen lanes to true
389
+ * wire views: all depth-0 runs share the main conversation view, and a
390
+ * resumed subagent shares its resume-chain ancestors' view — duplicates
391
+ * across those runIds DO reach a single request (wire-time
392
+ * `ensureToolResultPairing` mode 4 would strip them on every send) and are
393
+ * healed here.
394
+ *
395
+ * Orphan `tool_use` blocks (a call whose result was never persisted —
396
+ * interrupted run) are deliberately KEPT: they are authentic model output,
397
+ * and the wire-time pass patches them with a synthetic result on every send
398
+ * without touching history.
399
+ *
400
+ * Deletions cascade by design: dropping a duplicate `tool_call` orphans its
401
+ * `tool_result`, which is then dropped too; a turn emptied by either is
402
+ * removed entirely.
403
+ *
404
+ * Safe to persist: deterministic, idempotent (re-running on healed output is
405
+ * a no-op returning the same reference), and fabricates nothing.
406
+ *
407
+ * Pure: does not mutate input turns or their content arrays.
408
+ * @param turns - Persisted turns, oldest first. They are not modified.
409
+ * @param options - `onDrop` is called once per deletion. `laneForRun` maps a `runId` to its wire-view lane.
377
410
  */
378
- declare function expandMcpConfigEnv(config: McpServerConfig, env?: Record<string, string | undefined>): McpServerConfig;
411
+ declare function dropInvalidToolPairings<T extends {
412
+ role: string;
413
+ content: SessionContentBlock[];
414
+ runId?: string;
415
+ }>(turns: T[], options?: {
416
+ onDrop?: (drop: PairingDrop) => void;
417
+ /**
418
+ * Map a turn's `runId` to its wire-view lane. Turns whose lanes differ
419
+ * never share a model request, so their tool_call ids may legitimately
420
+ * collide. Defaults to the raw `runId` (undefined runIds share one
421
+ * lane) — the conservative choice when run topology is unknown.
422
+ */
423
+ laneForRun?: (runId: string | undefined) => string;
424
+ }): T[];
425
+ //#endregion
426
+ //#region src/session/messages.d.ts
379
427
  /**
380
- * A config from a source that must never read this process's environment
381
- * (a machine's project file, `docs/MACHINES.md`): every `${VAR}` placeholder
382
- * resolved NOW to its `:-default`, else to the empty string, so the
383
- * transport's own expansion has nothing of this process's secrets to put
384
- * into a command, an env value, a URL or a header.
385
- * @param config - Server config to strip.
428
+ * Converts an Anthropic wire message into a {@link SessionMessage}.
429
+ *
430
+ * @param msg - Anthropic message with a string or block-array `content`.
386
431
  */
387
- declare function withoutEnvPlaceholders(config: McpServerConfig): McpServerConfig;
432
+ declare function fromAnthropic(msg: {
433
+ role: string;
434
+ content: unknown;
435
+ }): SessionMessage;
388
436
  /**
389
- * Unprivileged TCP port: the loopback listener can't bind below 1024 without root.
390
- * @param port - Value to check.
437
+ * Converts an OpenAI wire message into a {@link SessionMessage}.
438
+ *
439
+ * @param msg - OpenAI message with a string or part-array `content`.
391
440
  */
392
- declare function isValidCallbackPort(port: unknown): port is number;
441
+ declare function fromOpenAI(msg: {
442
+ role: string;
443
+ content: unknown;
444
+ }): SessionMessage;
445
+ /** What a wire builder should do with a reasoning block for a given target. */
446
+ type ReasoningWireAction = 'keep' | 'drop' | 'strip-signature';
393
447
  /**
394
- * The loopback redirect a pinned `oauth.callbackPort` produces: the URL to
395
- * register with the provider. Pass the same `callbackPath` given to
396
- * `loginMcpServer`, if any.
397
- * @param config - Server config. Only `oauth.callbackPort` is read.
398
- * @param callbackPath - Path of the callback URL.
399
- * @returns The redirect URL, or `undefined` when no callback port is pinned.
448
+ * Provider a history is sent to, as {@link reasoningWireAction} tells them
449
+ * apart. A Gemini-wire target is its signature scope, so an extension's
450
+ * `googleCompatible` route keeps only the signatures it minted.
400
451
  */
401
- declare function pinnedMcpRedirectUri(config: Pick<McpServerConfig, 'oauth'>, callbackPath?: string): string | undefined;
452
+ type ReasoningWireTarget = 'anthropic' | 'openai' | GeminiSignatureScope;
402
453
  /**
403
- * Normalize MCP server configs from any common shape to `McpServerConfig[]`.
454
+ * Single source of truth for whether a signature-bearing reasoning block
455
+ * (`thinking` / `redacted_thinking`) may be forwarded to a provider. The
456
+ * wire builders ({@link toAnthropic}, the OpenAI and Google message shapers)
457
+ * and the host-facing {@link sanitizeHistoryForProvider} apply this same
458
+ * policy — keeping them one function means the sanitizer can never drift
459
+ * from what the wire actually sends.
404
460
  *
405
- * Accepts:
406
- * - `McpServerConfig[]` — zidane native (pass-through).
407
- * - `McpServerConfig` — a single config object (wrapped to a 1-element array).
408
- * - `Record<string, RawShape>` — name-keyed map (common in host-SDK configs), where the key is the server name.
409
- * - Mixed shapes with `type` vs `transport`, `httpUrl`/`sseUrl` vs `url`.
461
+ * Rules, each driven by an API constraint hit in production:
410
462
  *
411
- * Returns `[]` when `input` is nullish. Throws a descriptive error when the transport
412
- * cannot be inferred from a given entry, or when the input shape is unsupported.
413
- * @param input - Server configs in any of the accepted shapes, or nullish.
414
- */
415
- declare function normalizeMcpServers(input: unknown): McpServerConfig[];
416
- //#endregion
417
- //#region src/mcp/tool-meta.d.ts
418
- /**
419
- * Non-owning view of a live MCP connection: the SAME tools and
420
- * instructions, but a no-op `close`. Handed to consumers that must never
421
- * tear down transports they don't own — the loop's per-call
422
- * `ToolContext.mcpConnection` and child agents spawned off the parent's
423
- * connection — because only the owning agent's destroy path may close the
424
- * real thing, and a doc comment alone is too weak a guard. Single shared
425
- * builder so the call sites can't drift when this shape grows a field.
426
- * @param connection - Connection to view. Only its `tools` and `instructions` are read.
463
+ * - target `anthropic`:
464
+ * - `redacted_thinking` → keep (native Anthropic block; must be echoed).
465
+ * - `thinking` tagged `openai`, `google` or `google-vertex` → drop
466
+ * (OpenAI `encrypted_content` and Gemini thought signatures are not
467
+ * valid Anthropic HMACs; 400s).
468
+ * - unsigned `thinking` → drop (`ThinkingBlockParam` requires a
469
+ * signature; unsigned blocks come from non-signing producers).
470
+ * - signed but UNTAGGED `thinking` (pre-tagging sessions) → keep: it is
471
+ * most plausibly legacy Anthropic output, and the signature-400
472
+ * recovery converges if it is not.
473
+ *
474
+ * - target `openai` or a Gemini-wire scope (`google`, `google-vertex`, a
475
+ * `googleCompatible` route's):
476
+ * - `redacted_thinking` → drop (Anthropic-only block type).
477
+ * - `thinking` tagged `anthropic` → drop (an Anthropic HMAC is valid
478
+ * nowhere else).
479
+ * - `thinking` signed by any other producer, or signed but UNTAGGED →
480
+ * strip-signature: there is no signature-error recovery on these paths,
481
+ * so forwarding a possibly-foreign signature risks an unrecoverable
482
+ * 400. The reasoning text survives; only the opaque signature is
483
+ * withheld. Gemini's are kept only for the route that issued them.
484
+ * @param block - A `thinking` or `redacted_thinking` block.
485
+ * @param target - Provider the history is sent to.
427
486
  */
428
- declare function nonOwningMcpView(connection: Pick<McpConnection, 'tools' | 'instructions'>): McpConnection;
487
+ declare function reasoningWireAction(block: {
488
+ type: 'thinking';
489
+ signature?: string;
490
+ signatureProducer?: SignatureProducer;
491
+ } | {
492
+ type: 'redacted_thinking';
493
+ }, target: ReasoningWireTarget): ReasoningWireAction;
429
494
  /**
430
- * Recover a discovered tool's `{ server, toolName }` from its namespaced name
431
- * (`mcp_<server>_<tool>`). Both server and tool names can contain underscores,
432
- * so this matches against the known server list by longest server-name prefix
433
- * rather than splitting blindly. Tools that match no configured server (custom
434
- * connectors with a different naming scheme) fall back to
435
- * `{ server: '', toolName: <namespacedName> }`.
436
- * @param namespacedName - Tool name of the form `mcp_<server>_<tool>`.
437
- * @param servers - Configured servers to match the prefix against.
495
+ * Host-facing history sanitizer — applies {@link reasoningWireAction} to a
496
+ * turn set BEFORE it is handed to an agent targeting `target`. The in-loop
497
+ * wire builders already enforce the same policy per call, so this is for
498
+ * hosts that seed history from an external durable store (or hydrate
499
+ * pre-provenance-tagging sessions) and want the poison removed from their
500
+ * source of truth in one call instead of re-deriving block semantics.
501
+ *
502
+ * Returns new turn objects only where something changed (unchanged turns
503
+ * pass through by reference). A turn whose content empties keeps the same
504
+ * neutral marker the wire repair uses, so role boundaries stay intact.
505
+ * @param turns - Turns to sanitize.
506
+ * @param target - Provider the history is sent to.
438
507
  */
439
- declare function deriveMcpToolMeta(namespacedName: string, servers: readonly McpServerConfig[]): McpToolMeta;
508
+ declare function sanitizeHistoryForProvider<T extends {
509
+ content: SessionContentBlock[];
510
+ }>(turns: readonly T[], target: ReasoningWireTarget): {
511
+ turns: T[];
512
+ removed: number;
513
+ stripped: number;
514
+ };
440
515
  /**
441
- * Apply an {@link McpToolWrap} to every entry of a discovered-tool map,
442
- * resolving each tool's {@link McpToolMeta} from `servers`. Returns a fresh
443
- * map; the input is untouched. Used by the agent to apply the
444
- * `AgentOptions.mcpToolWrap` hook to discovered tools.
445
- * @param tools - Discovered tools keyed by namespaced name.
446
- * @param wrap - Wrapper applied to each tool.
447
- * @param servers - Configured servers used to resolve each tool's metadata.
516
+ * Converts a {@link SessionMessage} into an Anthropic wire message. Foreign reasoning blocks are dropped following {@link reasoningWireAction}.
517
+ *
518
+ * @param msg - Message to convert.
448
519
  */
449
- declare function wrapDiscoveredMcpTools(tools: Record<string, ToolDef>, wrap: McpToolWrap, servers: readonly McpServerConfig[]): Record<string, ToolDef>;
450
- //#endregion
451
- //#region src/mcp/tool-result.d.ts
520
+ declare function toAnthropic(msg: SessionMessage): {
521
+ role: string;
522
+ content: unknown;
523
+ };
452
524
  /**
453
- * Lossy flattener — converts MCP `CallToolResult.content` blocks to a single
454
- * string. Text blocks are extracted; non-text blocks are JSON-stringified.
525
+ * Converts a {@link SessionMessage} into an OpenAI wire message.
455
526
  *
456
- * Use this only at UI / log boundaries that require a string. The agent
457
- * loop itself routes through {@link normalizeMcpBlocks} so image blocks
458
- * survive into provider-native tool_result content (Anthropic blocks,
459
- * OpenAI companion-user-message).
460
- * @param content - `CallToolResult.content` from an MCP tool call. Anything other than an array gives an empty string.
527
+ * @param msg - Message to convert.
461
528
  */
462
- declare function resultToString(content: unknown): string;
529
+ declare function toOpenAI(msg: SessionMessage): {
530
+ role: string;
531
+ content: unknown;
532
+ };
463
533
  /**
464
- * Normalize MCP `CallToolResult.content` to zidane's {@link ToolResultContent[]} shape.
534
+ * Drop ASSISTANT turns whose every `tool_call` block is unresolved
535
+ * (no matching `tool_result` block anywhere later in the transcript).
536
+ * Tool_call blocks with at least one matching tool_result are kept — modes
537
+ * 1/3 of {@link ensureToolResultPairing} handle the partial-pair case at
538
+ * wire-send time.
465
539
  *
466
- * Handles the MCP content block types:
467
- * - `text` → preserved as `{type:'text', text}`
468
- * - `image` → preserved as `{type:'image', mediaType, data}` (MCP uses `mimeType`)
469
- * - `audio` → `{type:'audio', mediaType, data}`; mediaType reconciled/sniffed when
470
- * the declared `mimeType` is missing or not an `audio/*` type
471
- * - `video` → `{type:'video', mediaType, data}` (non-standard, by analogy)
472
- * - `resource` with embedded text → flattened to a text block
473
- * - `resource` with embedded blob → routed to image/audio/video by sniffing bytes
474
- * first, with declared `mimeType` as a fallback when bytes are unidentifiable
475
- * (it's OPTIONAL on EmbeddedResource per the MCP spec, and often imprecise)
476
- * - Any unrecognized block → JSON-stringified fallback text block (lossy but safe)
540
+ * Use case: session resume. A turn that emitted three `tool_use` blocks but
541
+ * never persisted the matching `tool_result` turn (process death, crash,
542
+ * `kill -9`) leaves the transcript with an orphan that Anthropic rejects on
543
+ * the FIRST API call after reload. Dropping the whole assistant turn — not
544
+ * just the orphan blocks — preserves text-only turns that legitimately
545
+ * carry reasoning the model wants to see again.
477
546
  *
478
- * Returns `null` when the input is not an array — callers should fall back to an empty
479
- * result in that case.
480
- * @param content - `CallToolResult.content` from an MCP tool call.
547
+ * Does NOT mint fresh ids: re-id'ing on every resume would cause
548
+ * exponential transcript growth across repeated resumes of an interrupted
549
+ * session.
550
+ *
551
+ * Pure: returns the input reference unchanged when no turn was dropped.
552
+ * @param turns - Turns of the session, oldest first.
481
553
  */
482
- declare function normalizeMcpBlocks(content: unknown): ToolResultContent[] | null;
483
- //#endregion
484
- //#region src/mcp/index.d.ts
485
- /** A live connection to a set of MCP servers: the discovered tools and a way to close every transport. */
486
- interface McpConnection {
487
- /** Discovered tools keyed by namespaced name, `mcp_<server>_<tool>`. */
488
- tools: Record<string, ToolDef>;
489
- /**
490
- * Per-server `instructions` payload from the MCP `initialize` handshake,
491
- * keyed by server name. Each server may return free-form guidance the
492
- * model is meant to read alongside the tool catalog — typical content
493
- * is "the database is already provisioned, use `apply_migration`
494
- * directly" or "always wrap SELECTs in a transaction". The agent
495
- * renders these into a system-prompt section when
496
- * `behavior.surfaceMcpInstructions` is on (default).
497
- *
498
- * Servers that omit the field, return an empty string, or fail to
499
- * connect contribute no entry. Lazy-connected servers contribute an
500
- * entry only once their first connect resolves — until then the model
501
- * never sees their instructions, matching the schema-loading semantics
502
- * of `lazyConnect`.
503
- *
504
- * Map (not Record) so insertion order matches server config order and
505
- * the rendered section is byte-stable for the cache breakpoint.
506
- *
507
- * Optional so custom `mcpConnector` implementations may omit it; the
508
- * framework's own `connectMcpServers` always returns a Map (possibly
509
- * empty).
510
- */
511
- instructions?: Map<string, string>;
512
- /** Closes every server connection. Servers that fail to close in time are force-stopped. */
513
- close: () => Promise<void>;
514
- }
554
+ declare function filterUnresolvedToolUses<T extends {
555
+ role: string;
556
+ content: SessionContentBlock[];
557
+ }>(turns: T[]): T[];
515
558
  /**
516
- * Optional knobs threaded into per-server bootstrap. Reserved for runtime
517
- * concerns the agent shell injects (credential storage, OAuth providers);
518
- * the `McpServerConfig` shape stays pure data.
559
+ * Classification of a session's tail state for resume purposes.
560
+ *
561
+ * - `'clean'` — the trailing turn is a user message (the model would respond
562
+ * next), or the transcript is empty. Safe to resume by appending a fresh
563
+ * user prompt.
564
+ * - `'interrupted'` — the trailing turn is an assistant message that has at
565
+ * least one `tool_call` block with no matching `tool_result` anywhere
566
+ * later. The run was almost certainly killed between persisting the
567
+ * assistant turn and persisting its tool-results turn. Hosts that want
568
+ * Claude-Code-style auto-resume can detect this and inject a
569
+ * `"Continue from where you left off."` user message before the next run.
570
+ * - `'completed'` — the trailing turn is an assistant message with no
571
+ * orphan tool_calls. The model considers itself done. Hosts that want to
572
+ * resume must supply a new prompt; auto-continuation here would be a
573
+ * non-sequitur.
519
574
  */
520
- interface ConnectMcpServersOptions {
575
+ type TurnInterruptionState = 'clean' | 'interrupted' | 'completed';
576
+ /**
577
+ * Inspect a session's trailing turn to classify whether the run was
578
+ * interrupted mid-tool-call. Pure / synchronous — does not modify the input.
579
+ *
580
+ * Pair with {@link filterUnresolvedToolUses} on the resume path: filter
581
+ * first so the result reflects the post-cleanup state (a turn whose orphans
582
+ * were stripped reads as 'completed', not 'interrupted').
583
+ * @param turns - Turns of the session, oldest first.
584
+ */
585
+ declare function detectTurnInterruption<T extends {
586
+ role: string;
587
+ content: SessionContentBlock[];
588
+ }>(turns: T[]): TurnInterruptionState;
589
+ /**
590
+ * Guarantee a message list ends with a `role: 'user'` message, appending a
591
+ * synthetic directive when it doesn't.
592
+ *
593
+ * Why: Anthropic's API (and several OpenAI-compat reasoning models — opus
594
+ * 4.7, the o-series translation layers on Bedrock/Vertex) rejects requests
595
+ * whose final message is `role: 'assistant'` with
596
+ * "This model does not support assistant message prefill. The conversation
597
+ * must end with a user message."
598
+ *
599
+ * Triggers in zidane:
600
+ * - Compaction over a session whose last turn is the agent's response
601
+ * (the common case — autocompact fires right after `agent.run()`).
602
+ * - Schema enforcement after an assistant text turn (no `tool_use`, so
603
+ * `ensureToolResultPairing` doesn't synthesize a user tail).
604
+ * - `context:transform` hooks that strip the trailing user turn.
605
+ *
606
+ * The pair-repair pass {@link ensureToolResultPairing} already covers the
607
+ * orphan-`tool_use` case via mode 2; this helper closes the plain-text
608
+ * assistant-tail case. They compose: run pair-repair first, then this
609
+ * pass, so an assistant turn with orphan tool_uses gets its synthetic
610
+ * `tool_result` user turn AND this pass is a no-op (the synthetic turn
611
+ * is already user-role).
612
+ *
613
+ * Empty input passes through unchanged — the caller's "nothing to send"
614
+ * guard is responsible for that case; we don't materialize a conversation
615
+ * out of an empty list.
616
+ *
617
+ * Idempotent: returns the input reference unchanged when the list is
618
+ * already user-terminated (or empty).
619
+ *
620
+ * @param messages Wire-ready message list.
621
+ * @param provider Provider whose `userMessage()` shape we use so the
622
+ * synthetic turn matches the wire format the rest of
623
+ * the list already follows.
624
+ * @param directive Text to put in the synthetic user message. Defaults
625
+ * to {@link DEFAULT_USER_TAIL_DIRECTIVE} ("Continue.").
626
+ * Compaction overrides this with a summary-specific cue.
627
+ */
628
+ declare function ensureEndsWithUserMessage(messages: SessionMessage[], provider: Provider, directive?: string): SessionMessage[];
629
+ /** Options for {@link toWireMessages}. */
630
+ interface ToWireMessagesOptions {
521
631
  /**
522
- * Execution context binding for servers declaring `scope: 'context'`.
523
- * Safe to pass unconditionally: the binding is lazy, and its
524
- * `getHandle()` is invoked only when a context-scoped stdio server
525
- * actually builds its transport — host-only configs never touch it, so
526
- * no spawn cost is paid for merely supplying it. Omitting it simply
527
- * makes any `scope: 'context'` server fail bootstrap with a pointed
528
- * error.
632
+ * Pairing-repair telemetry. Fires once per repair the underlying
633
+ * {@link ensureToolResultPairing} pass performs. Mirrors the
634
+ * `pairing:repair` hook surface so consumers can wire structured logging
635
+ * without an agent instance.
529
636
  */
530
- execution?: McpExecutionBinding;
637
+ onRepair?: (repair: PairingRepair) => void;
531
638
  /**
532
- * Build a non-interactive `OAuthClientProvider` for a given server. Called
533
- * lazily — only invoked when the bootstrap actually needs auth (explicit
534
- * `auth: 'oauth'` flag, or a UnauthorizedError that meets the auto-detect
535
- * criteria). Return `undefined` to opt this server out of OAuth even if it
536
- * was requested (e.g. the host doesn't have a credential store for it).
537
- *
538
- * "Non-interactive" — the provider must NOT trigger a browser flow during
539
- * bootstrap. Use a `redirectUri` of `undefined` so the SDK reads stored
540
- * tokens, refreshes on expiry, and throws `UnauthorizedError` if tokens
541
- * are missing or refresh fails. The host then surfaces an
542
- * `mcp:auth:required` event so the user can opt in to interactive login.
639
+ * When set, also runs {@link ensureEndsWithUserMessage} so the result is
640
+ * safe for assistant-prefill-rejecting models (opus 4.7, o-series
641
+ * translation layers). Omit to skip — pure pairing repair only.
543
642
  */
544
- buildAuthProvider?: (config: McpServerConfig) => OAuthClientProvider | undefined;
643
+ provider?: Provider;
644
+ /**
645
+ * Override for the synthetic user-tail directive. Only consulted when
646
+ * `provider` is set. Defaults to {@link DEFAULT_USER_TAIL_DIRECTIVE}.
647
+ */
648
+ userTailDirective?: string;
649
+ /**
650
+ * Resolve persisted content references into provider-native payload bytes.
651
+ * The returned data is wire-only and must not be written back to turns.
652
+ */
653
+ resolveContentRef?: ResolveContentRef;
545
654
  }
546
655
  /**
547
- * Internal: shape received by the `_clientFactory` test-injection seam.
548
- * Mirrors the subset of `TolerantClientOptions` the bootstrap path forwards
549
- * so a mock client can opt into the same lifecycle wiring (warning sink,
550
- * future seams) instead of silently bypassing it.
656
+ * Build a wire-ready `SessionMessage[]` from raw persisted `SessionTurn[]`.
657
+ *
658
+ * **The canonical "I want to send these to a provider" projection.** Use
659
+ * this — not raw `session.turns` / `store.getTurns()` — when constructing a
660
+ * provider request outside `agent.run()`. The agent's own wire pipeline
661
+ * (`executeTurn` in `src/loop-turn.ts`) applies the same repair just-in-time;
662
+ * downstream consumers that bypass the loop hit `tool_result must be
663
+ * preceded by a tool_call` 400s precisely because they shipped raw turns.
664
+ *
665
+ * Pipeline:
666
+ * 1. Filter out turns that never reach the model (`system` and `command`
667
+ * roles).
668
+ * 2. Resolve content refs with `options.resolveContentRef`.
669
+ * 3. {@link ensureToolResultPairing} — repairs all six orphan / dup
670
+ * corruption modes: synthetic placeholders for orphan tool_use blocks
671
+ * (preserves the model's tool_use shape), strips for duplicates and
672
+ * orphan tool_results.
673
+ * 4. {@link ensureEndsWithUserMessage} when `options.provider` is set —
674
+ * guards against assistant-tail prefill rejection (opus 4.7, o-series).
675
+ *
676
+ * Pure + idempotent. Does not mutate the input turns. Re-running on the
677
+ * output is a no-op.
678
+ *
679
+ * **Do not feed the result back into `session.setTurns` / `appendTurns`.**
680
+ * The repair can insert `SYNTHETIC_TOOL_RESULT_PLACEHOLDER` / `[Orphaned
681
+ * tool result removed …]` markers; round-tripping those into persisted
682
+ * state contaminates the session's reasoning history and defeats the
683
+ * "don't rewrite the past" invariant the wire-only repair was designed
684
+ * around.
685
+ * @param turns - Persisted turns, oldest first.
686
+ * @param options - Repair and tail options. See {@link ToWireMessagesOptions}.
551
687
  */
552
- interface McpClientFactoryOptions {
553
- /** See `TolerantClientOptions.onWarning`. */
554
- onWarning?: (message: string) => void;
688
+ declare function toWireMessages(turns: readonly {
689
+ role: 'user' | 'assistant' | 'system' | 'command';
690
+ content: SessionContentBlock[];
691
+ }[], options?: ToWireMessagesOptions): Promise<SessionMessage[]>;
692
+ /**
693
+ * Converts a wire message of unknown provider into a {@link SessionMessage}. Block types decide between {@link fromAnthropic} and {@link fromOpenAI}. Anthropic is the default.
694
+ *
695
+ * @param msg - Anthropic or OpenAI wire message.
696
+ */
697
+ declare function autoDetectAndConvert(msg: {
698
+ role: string;
699
+ content: unknown;
700
+ }): SessionMessage;
701
+ //#endregion
702
+ //#region src/session/metadata-merge.d.ts
703
+ /** Options for `SessionStore.saveMeta`. */
704
+ interface SaveMetaOptions {
705
+ /**
706
+ * The metadata keys this writer changed. When set, the store merges only
707
+ * these keys into the metadata it already holds (an `undefined` value
708
+ * removes the key) instead of replacing the whole record, so a stale copy
709
+ * of the session can't write back keys another writer changed since.
710
+ * Omitted: the whole `metadata` record is written.
711
+ */
712
+ metaKeys?: readonly string[];
555
713
  }
556
- type McpClientFactory = (opts?: McpClientFactoryOptions) => Client;
557
714
  /**
558
- * Connect to MCP servers and discover their tools.
715
+ * The metadata a `saveMeta` should store: `incoming` wholesale without
716
+ * `keys`, otherwise `stored` with only `keys` taken from `incoming`.
559
717
  *
560
- * Each tool is namespaced as `mcp_{serverName}_{toolName}` to avoid
561
- * collisions with agent tools or tools from other servers.
718
+ * @param stored - Metadata the store holds now; when absent, `incoming` is stored as is.
719
+ * @param incoming - Metadata the writer sends.
720
+ * @param keys - Keys the writer changed (`SaveMetaOptions.metaKeys`); an `undefined` value in `incoming` removes the key.
721
+ */
722
+ declare function mergeSessionMetadata(stored: SessionData['metadata'] | undefined, incoming: SessionData['metadata'], keys: readonly string[] | undefined): SessionData['metadata'];
723
+ //#endregion
724
+ //#region src/session/file-map.d.ts
725
+ /**
726
+ * Host-provided file-map adapter. Three methods exchanging `Record<string, string>`
727
+ * payloads — the whole persistence surface the wrapper needs.
728
+ */
729
+ interface FileMapAdapter {
730
+ /** Load the current file map. Returns an empty `files` record when nothing is persisted. */
731
+ get: () => Promise<{
732
+ files: Record<string, string>;
733
+ }>;
734
+ /** Replace the persisted file map. Full-rewrite semantics. */
735
+ save: (files: Record<string, string>) => Promise<void>;
736
+ /** Delete all persisted state. */
737
+ delete: () => Promise<void>;
738
+ }
739
+ /** Options for {@link createFileMapStore}. */
740
+ interface FileMapStoreOptions {
741
+ /** Filename for the JSONL turns log. Default: `turns.jsonl`. */
742
+ turnsFile?: string;
743
+ /** Filename for the metadata JSON. Default: `meta.json`. */
744
+ metaFile?: string;
745
+ }
746
+ /**
747
+ * Create a single-session `SessionStore` backed by a file-map adapter.
562
748
  *
563
- * @param configs - Array of MCP server configurations
564
- * @param _clientFactory - Internal: override client construction for testing
565
- * @param hooks - Optional agent hooks for firing mcp:connect, mcp:error, mcp:close events
566
- * @param options - Optional bootstrap knobs (e.g. OAuth provider injection)
749
+ * @param adapter - Host adapter that loads, saves and deletes the file map.
750
+ * @param options - File names to use. See {@link FileMapStoreOptions}.
567
751
  * @example
568
752
  * ```ts
569
- * import { connectMcpServers } from 'zidane/mcp'
570
- *
571
- * const connection = await connectMcpServers([
572
- * { name: 'fs', transport: 'stdio', command: 'npx', args: ['-y', '@modelcontextprotocol/server-filesystem', '.'] },
573
- * ])
574
- * console.log(Object.keys(connection.tools))
575
- * await connection.close()
753
+ * const session = await createSession({
754
+ * store: createFileMapStore(hostSessionStore),
755
+ * })
576
756
  * ```
577
757
  */
578
- declare function connectMcpServers(configs: McpServerConfig[], _clientFactory?: McpClientFactory, hooks?: Hookable<AgentHooks>, options?: ConnectMcpServersOptions): Promise<McpConnection>;
758
+ declare function createFileMapStore(adapter: FileMapAdapter, options?: FileMapStoreOptions): SessionStore;
579
759
  //#endregion
580
- //#region src/session/artifacts.d.ts
581
- /** Built-in kinds. Open set — extensions add their own. */
582
- declare const ARTIFACT_KINDS: {
583
- readonly pullRequest: "pull_request";
584
- readonly branch: "branch";
585
- readonly commit: "commit";
586
- readonly file: "file";
587
- };
760
+ //#region src/session/memory.d.ts
588
761
  /**
589
- * Reserved tool-result metadata namespace. Tools (and extension
590
- * `detect` hooks) emit `metadata.artifacts = ArtifactInput[]` and the
591
- * loop lifts each entry into the session's artifact store.
762
+ * Creates an in-memory {@link SessionStore}. Nothing is persisted.
763
+ *
764
+ * @example
765
+ * ```ts
766
+ * import { createMemoryStore, createSession } from 'zidane/session'
767
+ *
768
+ * const session = await createSession({ store: createMemoryStore() })
769
+ * ```
592
770
  */
593
- declare const ARTIFACTS_METADATA_KEY = "artifacts";
594
- /** Maximum size of an artifact `meta` value, in bytes of its JSON encoding. Larger values are dropped. */
595
- declare const ARTIFACT_META_MAX_BYTES = 16384;
596
- /** Maximum number of artifacts kept per session. Stores evict the oldest `file` artifacts first. */
597
- declare const ARTIFACTS_PER_SESSION_CAP = 200;
598
- /** A recorded output of a session, such as a pull request, a branch, a commit or a file. */
599
- interface SessionArtifact {
600
- /** Stable id (uuid). Preserved across upserts of the same `(kind, uri)`. */
601
- id: string;
602
- /** Id of the session the artifact belongs to. */
603
- sessionId: string;
604
- /**
605
- * Run that produced it. A `persist`-spawned subagent shares the parent
606
- * session and records under its OWN run id (detection reaches it via the
607
- * `child:tool:transform` bubble; see `presets/artifacts.ts`).
608
- */
609
- runId?: string;
610
- /** Tool-result turn that produced it — the transcript anchor. */
611
- turnId?: string;
612
- /** Open kind string. Built-ins in {@link ARTIFACT_KINDS}. */
613
- kind: string;
614
- /** Canonical locator: PR URL, `git:<repo>#<branch>`, `file://<abs path>`, … */
615
- uri: string;
616
- /** Human line. Always present — the rendering fallback for unknown kinds. */
617
- label: string;
618
- /**
619
- * Project the artifact landed in, resolved at emission time from where
620
- * the thing actually is (a worktree, a sibling repo), defaulting to the
621
- * session's own `projectRoot`. Drives "everything produced from this
622
- * repo" queries.
623
- */
624
- projectRoot?: string;
625
- /** Kind-specific payload, ≤ {@link ARTIFACT_META_MAX_BYTES}. */
626
- meta?: JsonValue;
627
- /** Creation time as epoch milliseconds. */
628
- createdAt: number;
629
- /** Last update time as epoch milliseconds. */
630
- updatedAt: number;
631
- }
632
- /** What a producer hands to `session.addArtifact` / the metadata namespace. */
633
- interface SessionArtifactInput {
634
- /** Open kind string. See `ARTIFACT_KINDS` for the built-in ones. */
635
- kind: string;
636
- /** Canonical locator of the artifact. */
637
- uri: string;
638
- /** Human-readable line shown for the artifact. */
639
- label: string;
640
- /** Project the artifact landed in. Default: the session project. */
641
- projectRoot?: string;
642
- /** Kind-specific payload, at most `ARTIFACT_META_MAX_BYTES`. */
643
- meta?: JsonValue;
644
- }
645
- /** Filter for listing artifacts. Fields combine with AND. */
646
- interface ArtifactFilter {
647
- /** Only artifacts of this session. */
648
- sessionId?: string;
649
- /**
650
- * Tri-state like `SessionStore.list`: string → that project only,
651
- * `null` → artifacts with no project, omitted → axis ignored.
652
- */
653
- projectRoot?: string | null;
654
- /** Only artifacts of this kind. */
655
- kind?: string;
656
- /** Exact locator match — reverse lookup ("who produced PR #123?"). Pair with `kind`. */
657
- uri?: string;
658
- /** Only artifacts with `updatedAt >= since`. */
659
- since?: number;
660
- /** Maximum number of artifacts to return. */
661
- limit?: number;
771
+ declare function createMemoryStore(): SessionStore;
772
+ //#endregion
773
+ //#region src/session/remote.d.ts
774
+ /** Options for {@link createRemoteStore}. */
775
+ interface RemoteStoreOptions {
776
+ /** Base URL of the session API */
777
+ url: string;
778
+ /** Optional headers (e.g. for authentication) */
779
+ headers?: Record<string, string>;
780
+ /** Per-request timeout in ms. Default 30s — bounds a hung backend. */
781
+ timeoutMs?: number;
662
782
  }
663
783
  /**
664
- * Validate + normalize a raw input (typically from tool-result metadata,
665
- * i.e. an untrusted boundary). Returns `null` when the entry is unusable
666
- * — missing kind/uri/label or oversized in a way truncation can't fix.
667
- * `label` is clipped, `meta` is dropped (not the artifact) when it exceeds
668
- * the byte bound.
669
- * @param raw - Untrusted value, typically from tool-result metadata.
784
+ * Creates a {@link SessionStore} that talks to a REST session API over HTTP. See the module comment for the endpoints it calls.
785
+ *
786
+ * @param options - API base URL, headers and timeout.
787
+ * @example
788
+ * ```ts
789
+ * import { createRemoteStore, createSession } from 'zidane/session'
790
+ *
791
+ * const store = createRemoteStore({ url: 'https://api.example.com', headers: { authorization: 'Bearer token' } })
792
+ * const session = await createSession({ store })
793
+ * ```
670
794
  */
671
- declare function normalizeArtifactInput(raw: unknown): SessionArtifactInput | null;
795
+ declare function createRemoteStore(options: RemoteStoreOptions): SessionStore;
796
+ //#endregion
797
+ //#region src/session/index.d.ts
672
798
  /**
673
- * Apply an upsert to an existing row: identity fields (`id`, `runId`,
674
- * `turnId`, `createdAt`) stay, `label` refreshes, `meta` and `projectRoot`
675
- * refresh when the incoming artifact has them, and `updatedAt` becomes the
676
- * later of the two. Shared by every store so the
677
- * merge semantics can't drift.
678
- * @param existing - Stored artifact.
679
- * @param incoming - Artifact being upserted.
799
+ * Run `fn` with `session` bound as the active extension session for the
800
+ * duration of the call (and every async continuation it spawns). Uses
801
+ * `AsyncLocalStorage.run` rather than `enterWith` so concurrent agents in the
802
+ * same process (e.g. the GUI's multi-session host) never observe each other's
803
+ * session through `currentExtensionSession()`.
804
+ * @param session - Session to bind. When `undefined`, `fn` runs without a binding.
805
+ * @param fn - Function to run with the binding in place.
680
806
  */
681
- declare function mergeArtifact(existing: SessionArtifact, incoming: SessionArtifact): SessionArtifact;
807
+ declare function withExtensionSession<T>(session: Session | undefined, fn: () => T): T;
682
808
  /**
683
- * Which artifacts to evict so a session stays at or under `cap` after
684
- * one more insert. `file` artifacts go first (noisiest, cheapest to
685
- * regenerate), oldest first within a kind; ties keep the caller's order
686
- * (stable sort), so pass rows in insertion order. Pure — callers delete
687
- * the returned ids.
688
- * @param current - Artifacts currently stored for the session, in insertion order.
689
- * @param cap - Maximum number of artifacts per session.
809
+ * Returns the session bound by {@link withExtensionSession} for the current async context, or `undefined` when none is bound.
690
810
  */
691
- declare function selectArtifactEvictions(current: readonly SessionArtifact[], cap?: number): string[];
811
+ declare function currentExtensionSession(): Session | undefined;
692
812
  /**
693
- * Tests an artifact against a filter. An undefined filter matches everything. `limit` is not applied here.
813
+ * Reads one value an extension stored in the session metadata. Returns a copy, or `undefined` when the session, extension or key is missing or a name is unsafe.
694
814
  *
695
- * @param artifact - Artifact to test.
696
- * @param filter - Filter to apply.
697
- */
698
- declare function matchesArtifactFilter(artifact: SessionArtifact, filter: ArtifactFilter | undefined): boolean;
699
- /**
700
- * Newest first, stable on id.
701
- * @param artifacts - Artifacts to sort. The array is sorted in place.
702
- */
703
- declare function sortArtifacts(artifacts: SessionArtifact[]): SessionArtifact[];
704
- //#endregion
705
- //#region src/session/messages-pairing.d.ts
706
- /**
707
- * Placeholder content inserted into a synthetic `tool_result` when the harness
708
- * has to repair an orphan `tool_use`. Exported so downstream consumers
709
- * (training-data collectors, HFI submission) can reject any payload containing
710
- * it — the marker satisfies the wire-level pairing contract structurally but
711
- * the content itself is fake and would poison fine-tuning data.
815
+ * @param session - Session to read, if any.
816
+ * @param extensionName - Name of the extension that owns the value.
817
+ * @param key - Key under the extension namespace.
712
818
  */
713
- declare const SYNTHETIC_TOOL_RESULT_PLACEHOLDER = "[Tool result missing due to internal error]";
819
+ declare function getExtensionSessionState<T = JsonValue>(session: Session | undefined, extensionName: string, key: string): T | undefined;
714
820
  /**
715
- * Replacement text for an assistant message whose every content block was
716
- * stripped during pairing repair (e.g. the only blocks were orphan
717
- * `tool_call`s). Providers reject empty `content` arrays — the marker keeps
718
- * the turn shape valid while signaling "this assistant turn lost its
719
- * outputs" to the model so it can recover.
821
+ * Stores a JSON value under an extension namespace in the session metadata and saves the session when it has a store. Does nothing without a session.
822
+ *
823
+ * Throws when a name is unsafe or the value exceeds the size limits (16 KiB per item, 64 KiB for all extension state).
824
+ *
825
+ * @param session - Session to write, if any.
826
+ * @param extensionName - Name of the extension that owns the value.
827
+ * @param key - Key under the extension namespace.
828
+ * @param value - JSON value to store. It is copied.
720
829
  */
721
- declare const TOOL_USE_INTERRUPTED_MARKER = "[Tool use interrupted]";
830
+ declare function setExtensionSessionState(session: Session | undefined, extensionName: string, key: string, value: JsonValue): Promise<void>;
722
831
  /**
723
- * Replacement text for a user message whose every content block was a
724
- * `tool_result` with no matching upstream `tool_call` (e.g. the assistant
725
- * pair was stripped by an earlier compaction). Same role as
726
- * {@link TOOL_USE_INTERRUPTED_MARKER} on the user side.
832
+ * Removes one value from an extension namespace in the session metadata and saves the session when it has a store. Does nothing when the value does not exist.
833
+ *
834
+ * @param session - Session to modify, if any.
835
+ * @param extensionName - Name of the extension that owns the value.
836
+ * @param key - Key to remove.
727
837
  */
728
- declare const ORPHANED_TOOL_RESULT_MARKER = "[Orphaned tool result removed due to conversation resume]";
838
+ declare function deleteExtensionSessionState(session: Session | undefined, extensionName: string, key: string): Promise<void>;
729
839
  /**
730
- * Classification of a single repair the pairing pass performed. Surfaced via
731
- * {@link EnsureToolResultPairingOptions.onRepair} so consumers can wire
732
- * telemetry, debug logs, or strict-mode rejection without re-implementing the
733
- * walk.
840
+ * Transitive `resumedFromRunId` chain starting at `runId` (inclusive).
734
841
  *
735
- * Each entry corresponds to one of the corruption modes documented on
736
- * {@link ensureToolResultPairing}.
842
+ * A resumed run only persists the turns IT produced — the turns it was
843
+ * seeded with still carry the original run's id. So reconstructing a
844
+ * resumed child's full conversation means collecting turns from every run
845
+ * in its resume lineage, not just the latest link. Cycle-guarded (a
846
+ * malformed chain terminates instead of looping).
847
+ * @param runs - Run records of the session.
848
+ * @param runId - Run to start from.
737
849
  */
738
- type PairingRepairMode = 'orphan-tool-use-prepend' | 'orphan-tool-use-append' | 'orphan-tool-result-strip' | 'duplicate-tool-use-strip' | 'duplicate-tool-result-strip' | 'empty-assistant-marker' | 'duplicate-tool-use-remint';
739
- /** One repair made by {@link ensureToolResultPairing}. */
740
- interface PairingRepair {
741
- /** Which repair was performed. See {@link PairingRepairMode}. */
742
- mode: PairingRepairMode;
743
- /** Tool-use / tool-result id this repair concerns. Absent for empty-marker repairs. */
744
- callId?: string;
745
- /** Zero-based index into the INPUT `messages` array where the corruption was found. */
746
- messageIndex: number;
747
- }
748
- /** Options for {@link ensureToolResultPairing}. */
749
- interface EnsureToolResultPairingOptions {
850
+ declare function resumeChainRunIds(runs: readonly SessionRun[], runId: string): Set<string>;
851
+ /** Record of one agent run inside a session. */
852
+ interface SessionRun {
853
+ /** Run id. */
854
+ id: string;
855
+ /** Start time as epoch milliseconds. */
856
+ startedAt: number;
857
+ /** End time as epoch milliseconds. Absent while the run is in progress. */
858
+ endedAt?: number;
859
+ /** Prompt the run started with. */
860
+ prompt: string;
861
+ /** Run state. A persisted `running` run whose process died is shown as `aborted` on load. */
862
+ status: 'running' | 'completed' | 'aborted' | 'error';
863
+ /** Number of turns the run produced. */
864
+ turns?: number;
865
+ /** Input tokens used by the run. */
866
+ tokensIn?: number;
867
+ /** Output tokens used by the run. */
868
+ tokensOut?: number;
869
+ /** Error message when the run failed. */
870
+ error?: string;
871
+ /** What `error`'s one line leaves out (the provider's own text, a limit's reset). */
872
+ errorDetail?: RunErrorDetail;
873
+ /** Per-turn usage breakdown */
874
+ turnUsage?: TurnUsage[];
875
+ /** Total usage across all turns */
876
+ totalUsage?: TurnUsage;
877
+ /** Estimated cost in USD */
878
+ cost?: number;
750
879
  /**
751
- * Fired once per repair the pass performed. Synchronous so the loop can
752
- * stay on its hot path. Throwing from the callback aborts the pass —
753
- * consumers wanting fail-fast (strict mode) can re-throw with their own
754
- * typed error.
755
- */
756
- onRepair?: (repair: PairingRepair) => void;
880
+ * The run that spawned this one, when the agent is a subagent sharing its
881
+ * parent's session. Undefined on top-level `agent.run()`. Consumers can walk
882
+ * `runs` by `parentRunId` to reconstruct the subagent tree.
883
+ */
884
+ parentRunId?: string;
885
+ /**
886
+ * The prior run this one continues (see `AgentRunOptions.resumeRunId`).
887
+ * Set when a stopped/failed subagent run was resumed — consumers can
888
+ * chain runs by `resumedFromRunId` to render “child-4 (resumes child-2)”
889
+ * style markers. Absent on normal runs.
890
+ */
891
+ resumedFromRunId?: string;
892
+ /**
893
+ * Host-assigned display label (e.g. the spawn tool's `child-3`), persisted
894
+ * so label → run resolution is a stored fact instead of a positional
895
+ * guess. Positional `child-N` numbering can desynchronize from announced
896
+ * labels (concurrent spawns `startRun` out of reservation order, a
897
+ * pre-`startRun` throw advances the counter without a run, and reload
898
+ * ordering ties break lexicographically) — resolving by stored label is
899
+ * immune to all three. Absent on top-level runs and legacy sessions.
900
+ */
901
+ label?: string;
902
+ /**
903
+ * The `spawn` tool call that started this run, in the parent's turn (see
904
+ * `AgentRunOptions.parentCallId`): pairs a child with its call exactly,
905
+ * where parallel calls share a task. Absent on top-level runs and older
906
+ * sessions.
907
+ */
908
+ parentCallId?: string;
909
+ /**
910
+ * Zero-based subagent depth. 0 = top-level run, 1 = direct child, …
911
+ * Recorded here so hosts can query/filter by level without walking the tree.
912
+ */
913
+ depth?: number;
914
+ /**
915
+ * How this run was initiated when not a plain user prompt. `command` marks
916
+ * a sub-run driven from a `/` command's `ctx.runAgent`; `display` is the
917
+ * short line the transcript shows instead of the full injected prompt
918
+ * (which often embeds bulky material like a diff). Presentation-only —
919
+ * the wire/model payload is unaffected. Absent on normal runs.
920
+ */
921
+ origin?: {
922
+ kind: 'command';
923
+ display?: string;
924
+ };
925
+ /**
926
+ * The host's agent profile the run ran as (see `AgentRunOptions.runAgent`),
927
+ * so a transcript can name it per run. Absent when the host passes none.
928
+ */
929
+ agent?: SessionRunAgent;
757
930
  }
758
- /**
759
- * Defensive repair pass that rewrites a message list so it satisfies the
760
- * wire-level `tool_use` ↔ `tool_result` adjacency contract every modern
761
- * provider enforces.
762
- *
763
- * Anthropic 400s on orphans with `'tool_use' ids were found without
764
- * 'tool_result' blocks immediately after` (and its inverse, `tool_result
765
- * must be preceded by a tool_call with the same toolCallId`). OpenAI's
766
- * Chat Completions API rejects most mismatches with a 400 too.
767
- *
768
- * Six repair modes — modeled after Anthropic's Claude Code defenses:
769
- *
770
- * | # | Corruption | Repair |
771
- * |---|------------|--------|
772
- * | 1 | assistant `tool_use` whose next user msg lacks a matching `tool_result` | **Prepend** a synthetic `tool_result` block carrying {@link SYNTHETIC_TOOL_RESULT_PLACEHOLDER} with `isError: true` |
773
- * | 2 | assistant `tool_use` followed by nothing (or by a non-user msg) | **Insert** a new synthetic user message with the same placeholder |
774
- * | 3 | user `tool_result` with no preceding assistant `tool_call` | **Strip** the orphan block; if it empties the msg, replace with {@link ORPHANED_TOOL_RESULT_MARKER} text block |
775
- * | 4 | duplicate `tool_call.id` across assistant messages (CC-1212) | **Strip** later instances + their matching tool_results |
776
- * | 5 | duplicate `tool_result.callId` within a single user message | **Dedupe** by `callId`, keep first |
777
- * | 6 | assistant message emptied by mode-4 stripping | **Replace** content with {@link TOOL_USE_INTERRUPTED_MARKER} text block |
778
- *
779
- * **Repair, not drop.** Dropping orphan blocks would (a) silently rewrite
780
- * history the model had reasoned over and (b) cascade — dropping an assistant
781
- * tool_call would orphan its tool_result, which would then get dropped too,
782
- * removing any trace of "what the model tried to do" from the transcript. This
783
- * pass preserves the model's tool_use shape and patches the dangling result
784
- * with an `is_error` placeholder so the model sees "I tried X, the result was
785
- * lost" and can retry intelligently.
786
- *
787
- * Adjacency contract: `tool_result` blocks must live in the user message
788
- * IMMEDIATELY following the assistant message that emitted the matching
789
- * `tool_use`. The pass enforces strict adjacency — a tool_result two
790
- * messages downstream of its tool_call is still an orphan.
791
- *
792
- * Idempotent: returns the input reference unchanged when no repairs were
793
- * necessary. Re-running on already-repaired output is a no-op.
794
- *
795
- * Pure: does not mutate input messages or their content arrays — every
796
- * repair allocates a fresh array / object.
797
- * @param messages - Wire messages to repair. They are not modified.
798
- * @param options - Repair callback. See {@link EnsureToolResultPairingOptions}.
799
- */
800
- declare function ensureToolResultPairing(messages: SessionMessage[], options?: EnsureToolResultPairingOptions): SessionMessage[];
801
- /** Result of {@link remintDuplicateToolCallIds}. */
802
- interface RemintResult {
803
- /** Tool calls with duplicate ids replaced. Same reference when unchanged. */
804
- toolCalls: Array<{
805
- id: string;
806
- name: string;
807
- input: Record<string, unknown>;
808
- }>;
809
- /** Assistant content with matching `tool_call` block ids rewritten. Same reference when unchanged. */
810
- content: SessionContentBlock[];
811
- /** One entry per re-minted occurrence, in emission order. */
812
- reminted: Array<{
813
- oldId: string;
814
- newId: string;
815
- }>;
931
+ /** A host agent profile as a run record names it. */
932
+ interface SessionRunAgent {
933
+ /** Profile id. */
934
+ id: string;
935
+ /** Display name. */
936
+ label: string;
816
937
  }
817
- /**
818
- * Re-mint tool-call ids that collide with ids already present in the
819
- * transcript (or with an earlier sibling in the same turn), BEFORE the turn
820
- * is persisted and its tools dispatched.
821
- *
822
- * Why this exists: some providers/serving stacks emit non-globally-unique
823
- * tool_use ids (per-turn counters like `call_0`, retry-replay duplicates,
824
- * Kimi-K2.6 on Fireworks). The wire-time pairing pass
825
- * ({@link ensureToolResultPairing}) can only STRIP such duplicates — which
826
- * erases the model's tool calls and results from the wire view, stalls
827
- * progress, and re-accumulates repairs quadratically because the persisted
828
- * session keeps the corrupted ids. Re-minting at persist time keeps the
829
- * pairing intact instead: the call, its execution, and its tool_result all
830
- * carry the fresh id, so the pairing pass has nothing to strip on any later
831
- * turn.
832
- *
833
- * Fresh ids are `${oldId}_r{n}` with `n` bumped until unique — deterministic
834
- * shape, Anthropic-wire-safe charset (given a safe input id), and visibly
835
- * traceable back to the original.
836
- *
837
- * Alignment contract: `toolCalls` and the `tool_call` blocks inside
838
- * `content` are two views of the same emission and MUST be in the same
839
- * order (true for every provider — both are built from one source array).
840
- * Occurrences are matched positionally per old id so intra-turn duplicates
841
- * map to distinct fresh ids on both views.
842
- *
843
- * Pure: returns the input references unchanged when no id collides.
844
- * @param toolCalls - Tool calls of the new assistant turn.
845
- * @param content - Content blocks of the same turn, with `tool_call` blocks in the same order as `toolCalls`.
846
- * @param priorIds - Tool call ids already in the transcript.
847
- */
848
- declare function remintDuplicateToolCallIds(toolCalls: ReadonlyArray<{
938
+ /** A session's turns and runs: what a history edit reads and writes (`SessionStore.mutateHistory`). */
939
+ interface SessionHistory {
940
+ /** The session's turns, in order. */
941
+ turns: SessionTurn[];
942
+ /** The session's runs, in order. */
943
+ runs: SessionRun[];
944
+ }
945
+ /** Persisted form of a session: identity, turns, runs and metadata. */
946
+ interface SessionData {
947
+ /** Session id. */
849
948
  id: string;
850
- name: string;
851
- input: Record<string, unknown>;
852
- }>, content: readonly SessionContentBlock[], priorIds: ReadonlySet<string>): RemintResult;
949
+ /** Label of the agent profile that owns the session. */
950
+ agentId?: string;
951
+ /**
952
+ * Absolute path of the project this session belongs to — typically
953
+ * the git root resolved from `cwd` at creation time, falling back to
954
+ * `cwd` itself when not in a git repo. Set ONCE on creation and never
955
+ * mutated thereafter (the session "belongs" to that project forever).
956
+ *
957
+ * Used by the TUI's sessions list to filter rows by current project,
958
+ * so the user only sees conversations relevant to where they are
959
+ * working — without needing one `.{prefix}/` directory per project.
960
+ *
961
+ * `undefined` on pre-tagging legacy sessions; the chat layer treats
962
+ * those as "untagged" and hides them unless `Settings.showAllProjects`
963
+ * is on.
964
+ */
965
+ projectRoot?: string;
966
+ /** Turn history, oldest first. */
967
+ turns: SessionTurn[];
968
+ /** Records of the runs in this session. */
969
+ runs: SessionRun[];
970
+ /** Session state. A persisted `running` status is stale after a restart and is shown as `idle` on load. */
971
+ status: 'idle' | 'running' | 'completed' | 'error';
972
+ /** Free-form metadata, such as the title, model and extension state. */
973
+ metadata: Record<string, unknown>;
974
+ /** Creation time as epoch milliseconds. */
975
+ createdAt: number;
976
+ /** Last update time as epoch milliseconds. */
977
+ updatedAt: number;
978
+ }
853
979
  /**
854
- * Classification of a single deletion {@link dropInvalidToolPairings}
855
- * performed. Surfaced via `onDrop` for telemetry.
980
+ * Compact per-session summary returned by {@link SessionStore.listMeta}.
981
+ * Raw facts only — presentation (title derivation, fallback strings)
982
+ * stays in the chat layer (`listSessionMeta` / `deriveSessionTitle`).
856
983
  */
857
- type PairingDropKind = 'duplicate-tool-call' | 'duplicate-tool-result' | 'orphan-tool-result' | 'empty-turn';
858
- /** One deletion made by {@link dropInvalidToolPairings}. */
859
- interface PairingDrop {
860
- /** What was dropped. See {@link PairingDropKind}. */
861
- kind: PairingDropKind;
862
- /** Tool-call / tool-result id the drop concerns. Absent for empty-turn drops. */
863
- callId?: string;
864
- /** Zero-based index into the INPUT `turns` array. */
865
- index: number;
984
+ interface SessionMetaRow {
985
+ /** Session id. */
986
+ id: string;
987
+ /** Header metadata (may carry a stored `title`). */
988
+ metadata: Record<string, unknown>;
989
+ /** Absent for untagged (legacy) sessions. */
990
+ projectRoot?: string;
991
+ /** Last update time as epoch milliseconds. */
992
+ updatedAt: number;
993
+ /**
994
+ * The store's change counter for this session: bumped by every write to
995
+ * it (in the write's own transaction), so it only grows, whatever
996
+ * `updatedAt` a writer stamps. Absent from stores that keep none.
997
+ */
998
+ rev?: number;
999
+ /** Number of turns. */
1000
+ turnCount: number;
1001
+ /** Count of `role: 'user'` turns. */
1002
+ userMessageCount: number;
1003
+ /** Number of run records. */
1004
+ runCount: number;
1005
+ /**
1006
+ * First `role: 'user'` turn — the title-derivation source. Stores may
1007
+ * omit it when `metadata.title` is already set (no derivation needed).
1008
+ */
1009
+ firstUserTurn?: SessionTurn;
1010
+ /**
1011
+ * Header fields consumers like the daemon's `sessions.list` need to
1012
+ * build full rows without a per-session `load()`. Optional (additive
1013
+ * contract extension) — callers fall back to `load()` when absent.
1014
+ */
1015
+ agentId?: string;
1016
+ /** Creation time as epoch milliseconds. */
1017
+ createdAt?: number;
1018
+ /** Session state. */
1019
+ status?: SessionData['status'];
1020
+ /**
1021
+ * Number of artifacts recorded for the session. Optional (additive):
1022
+ * only stores implementing the artifact methods populate it; consumers
1023
+ * treat absence as "unknown", not zero.
1024
+ */
1025
+ artifactCount?: number;
866
1026
  }
867
1027
  /**
868
- * Drop-only normalization of persisted history: delete structurally invalid
869
- * tool blocks so the transcript never re-triggers wire-time pairing repairs
870
- * turn after turn.
871
- *
872
- * Unlike {@link ensureToolResultPairing} — which SYNTHESIZES placeholder
873
- * content and must therefore stay wire-only (fabricated results would poison
874
- * persisted history and training data) — this pass performs pure deletions of
875
- * blocks that are provably invalid regardless of interpretation:
876
- *
877
- * | Corruption | Action |
878
- * |------------|--------|
879
- * | duplicate `tool_call` id within one run lane (across or within turns) | drop the later instance |
880
- * | duplicate `tool_result.callId` within one turn | drop the later instance |
881
- * | `tool_result` with no matching `tool_call` in the immediately preceding same-lane assistant turn | drop the block |
882
- * | turn emptied by the drops above (reasoning-only remainders count as empty) | drop the whole turn |
883
- *
884
- * Duplicate detection is scoped to the WIRE-VIEW lane: tool_call ids only
885
- * collide when both instances reach one model request. By default a turn's
886
- * lane is its raw `runId` — correct for parent/subagent interleaving, where
887
- * providers minting per-conversation counter ids (`call_0`, `call_1`)
888
- * legitimately reuse the same id across lanes. Callers that know the run
889
- * topology (see `createSession`) pass `laneForRun` to widen lanes to true
890
- * wire views: all depth-0 runs share the main conversation view, and a
891
- * resumed subagent shares its resume-chain ancestors' view — duplicates
892
- * across those runIds DO reach a single request (wire-time
893
- * `ensureToolResultPairing` mode 4 would strip them on every send) and are
894
- * healed here.
895
- *
896
- * Orphan `tool_use` blocks (a call whose result was never persisted —
897
- * interrupted run) are deliberately KEPT: they are authentic model output,
898
- * and the wire-time pass patches them with a synthetic result on every send
899
- * without touching history.
900
- *
901
- * Deletions cascade by design: dropping a duplicate `tool_call` orphans its
902
- * `tool_result`, which is then dropped too; a turn emptied by either is
903
- * removed entirely.
904
- *
905
- * Safe to persist: deterministic, idempotent (re-running on healed output is
906
- * a no-op returning the same reference), and fabricates nothing.
907
- *
908
- * Pure: does not mutate input turns or their content arrays.
909
- * @param turns - Persisted turns, oldest first. They are not modified.
910
- * @param options - `onDrop` is called once per deletion. `laneForRun` maps a `runId` to its wire-view lane.
1028
+ * Storage backend for sessions. Implement it to persist sessions somewhere else, or use a bundled store: memory, SQLite, remote or file map.
911
1029
  */
912
- declare function dropInvalidToolPairings<T extends {
913
- role: string;
914
- content: SessionContentBlock[];
915
- runId?: string;
916
- }>(turns: T[], options?: {
917
- onDrop?: (drop: PairingDrop) => void;
1030
+ interface SessionStore {
1031
+ /** Optional: generate a session ID server-side (e.g. a database-issued UUID). */
1032
+ generateSessionId?: () => string | Promise<string>;
918
1033
  /**
919
- * Map a turn's `runId` to its wire-view lane. Turns whose lanes differ
920
- * never share a model request, so their tool_call ids may legitimately
921
- * collide. Defaults to the raw `runId` (undefined runIds share one
922
- * lane) — the conservative choice when run topology is unknown.
1034
+ * Optional: generate a turn ID server-side for session-managed user turns.
1035
+ *
1036
+ * Provider-loop assistant and tool-result turns use AgentClock.randomUUID()
1037
+ * instead, so durable-execution adapters can keep those IDs replay-stable.
923
1038
  */
924
- laneForRun?: (runId: string | undefined) => string;
925
- }): T[];
926
- //#endregion
927
- //#region src/session/messages.d.ts
928
- /**
929
- * Converts an Anthropic wire message into a {@link SessionMessage}.
930
- *
931
- * @param msg - Anthropic message with a string or block-array `content`.
932
- */
933
- declare function fromAnthropic(msg: {
934
- role: string;
935
- content: unknown;
936
- }): SessionMessage;
937
- /**
938
- * Converts an OpenAI wire message into a {@link SessionMessage}.
939
- *
940
- * @param msg - OpenAI message with a string or part-array `content`.
941
- */
942
- declare function fromOpenAI(msg: {
943
- role: string;
944
- content: unknown;
945
- }): SessionMessage;
946
- /** What a wire builder should do with a reasoning block for a given target. */
947
- type ReasoningWireAction = 'keep' | 'drop' | 'strip-signature';
1039
+ generateTurnId?: () => string | Promise<string>;
1040
+ /** Load a session by ID. Returns null if not found. */
1041
+ load: (sessionId: string) => Promise<SessionData | null>;
1042
+ /**
1043
+ * Save a session (create or update, full document). Bulk overwrite:
1044
+ * turns and runs on disk are replaced by the caller's snapshot, so a
1045
+ * stale snapshot silently discards anything another writer appended.
1046
+ * `Session.save()` only routes here when the turn list was explicitly
1047
+ * replaced (`setTurns` / `setRuns` / load-time heal); everything else
1048
+ * goes through {@link saveMeta}.
1049
+ */
1050
+ save: (session: SessionData) => Promise<void>;
1051
+ /**
1052
+ * Optional: persist header fields only (agentId, projectRoot, status,
1053
+ * metadata, timestamps) plus an UPSERT of the runs present in the
1054
+ * snapshot — never deletes turns or runs. This is what metadata writes
1055
+ * (title, model, todos, extension state) need.
1056
+ *
1057
+ * Scope of the guarantee: TURNS appended by a concurrent process survive.
1058
+ * The header itself is still last-writer-wins — `status` and `agentId`
1059
+ * are written wholesale from the caller's snapshot, and so is `metadata`
1060
+ * unless `options.metaKeys` names the changed keys (`Session.save()`
1061
+ * always does; stores merge them with {@link mergeSessionMetadata}), and every run in the snapshot is upserted as-is (a reader
1062
+ * that loaded through `loadSession` carries the in-memory stale-running
1063
+ * demotion, so it can write `idle` / `aborted` over a live owner's marker
1064
+ * until the owner's next write). Readers that only need one key should
1065
+ * prefer a keyed patch (the host's `patchSessionMeta`) over `save()`.
1066
+ * Stores that omit it fall back to `save`, keeping the historical bulk
1067
+ * semantics.
1068
+ */
1069
+ saveMeta?: (session: SessionData, options?: SaveMetaOptions) => Promise<void>;
1070
+ /** Delete a session. */
1071
+ delete: (sessionId: string) => Promise<void>;
1072
+ /**
1073
+ * List session IDs, optionally filtered. `projectRoot` restricts to
1074
+ * sessions whose `SessionData.projectRoot` matches exactly — untagged
1075
+ * (legacy) sessions are NOT returned under that filter; pass `null`
1076
+ * explicitly to ask for untagged ones, or omit the field to ignore
1077
+ * the axis entirely. `agentId` filters by recorded agent; the two
1078
+ * conditions AND together when both are set.
1079
+ */
1080
+ list: (filter?: {
1081
+ agentId?: string;
1082
+ limit?: number;
1083
+ projectRoot?: string | null;
1084
+ }) => Promise<string[]>;
1085
+ /**
1086
+ * Optional: list session summaries without materializing full sessions.
1087
+ *
1088
+ * The generic fallback (`listSessionMeta` in `zidane/chat`) is `list()`
1089
+ * + `load()` per id — O(every turn in the store) because each `load`
1090
+ * parses the full turn history just to count rows and derive a title.
1091
+ * Stores that can answer from an index (SQL aggregates, a denormalized
1092
+ * header) should implement this; the sqlite store turns a multi-hundred-
1093
+ * ms TUI boot cost into a single query.
1094
+ *
1095
+ * Same filter contract and ordering (most recently updated first) as
1096
+ * {@link list}.
1097
+ */
1098
+ listMeta?: (filter?: {
1099
+ agentId?: string;
1100
+ limit?: number;
1101
+ projectRoot?: string | null;
1102
+ }) => Promise<SessionMetaRow[]>;
1103
+ /**
1104
+ * Optional: one session's header row WITHOUT materializing turns.
1105
+ * Hot-path reads (the cross-process run guard checks `status` +
1106
+ * `updatedAt` on every prompt send) must not pay a multi-MB turn parse
1107
+ * on long sessions. Callers fall back to `load()` when absent.
1108
+ */
1109
+ getMeta?: (sessionId: string) => Promise<SessionMetaRow | null>;
1110
+ /** Append new turns to a session (incremental, avoids full re-save). */
1111
+ appendTurns: (sessionId: string, turns: SessionTurn[]) => Promise<void>;
1112
+ /** Return a slice of turns for a session. */
1113
+ getTurns: (sessionId: string, from?: number, limit?: number) => Promise<SessionTurn[]>;
1114
+ /**
1115
+ * Optional: rewrite a session's history as ONE atomic read-modify-write,
1116
+ * so turns appended between the read and the write can't be erased (a
1117
+ * `load()` + `save()` pair can). `mutate` gets the current turns and
1118
+ * runs and returns the next ones, or `null` to leave them untouched; a
1119
+ * throw inside it aborts without writing. Runs are written only when it
1120
+ * returns a different `runs` array. History edits (delete / edit a turn,
1121
+ * rewind) use it when present and fall back to `load()` + `save()`.
1122
+ */
1123
+ mutateHistory?: (sessionId: string, mutate: (history: SessionHistory) => SessionHistory | null) => Promise<'ok' | 'no-session' | 'unchanged'>;
1124
+ /**
1125
+ * Optional: the turns-only form of {@link SessionStore.mutateHistory}.
1126
+ * When `mutateHistory` is absent, edits that leave the runs alone (delete
1127
+ * or edit a turn) use it; a rewind falls back to `load()` + `save()`.
1128
+ * @deprecated Implement `mutateHistory` instead.
1129
+ */
1130
+ mutateTurns?: (sessionId: string, mutate: (turns: SessionTurn[]) => SessionTurn[] | null) => Promise<'ok' | 'no-session' | 'unchanged'>;
1131
+ /**
1132
+ * Persist a run record (called at run start with `status: 'running'`, and
1133
+ * after completeRun / abortRun / errorRun).
1134
+ *
1135
+ * **Upsert semantics required.** The agent's run lifecycle calls
1136
+ * `session.startRun()` to register a new run in IN-MEMORY state and
1137
+ * then `updateRun()`. The store doesn't see the run before the first
1138
+ * `updateRun()` — `appendTurns` persists turns but not runs. An
1139
+ * update-only implementation would silently drop every newly-created
1140
+ * run record, leaving
1141
+ * the on-disk `runs[]` missing entries that the persisted turns
1142
+ * reference (which `eventsFromTurns` then mis-classifies via
1143
+ * `ancestryOf` → broken depth, broken `child-N` labels, broken
1144
+ * `userPrompts` history).
1145
+ *
1146
+ * Implementations MUST insert when the id doesn't exist and update
1147
+ * when it does. The bundled `sqlite` / `memory` / `file-map` stores
1148
+ * all follow this contract; remote stores using HTTP PUT get upsert
1149
+ * for free via REST semantics.
1150
+ */
1151
+ updateRun: (sessionId: string, run: SessionRun) => Promise<void>;
1152
+ /**
1153
+ * Update the top-level status of a session.
1154
+ *
1155
+ * `preserveUpdatedAt` (default false) writes the status WITHOUT
1156
+ * touching `updatedAt` — for pure-read heals (`loadSession`'s stale
1157
+ * `'running'` demotion) that must not reorder recency-sorted session
1158
+ * lists. Best-effort contract: stores that don't manage `updatedAt`
1159
+ * themselves (memory, file-map, remote) may ignore the option; the
1160
+ * sqlite store honors it.
1161
+ */
1162
+ updateStatus: (sessionId: string, status: SessionData['status'], options?: {
1163
+ preserveUpdatedAt?: boolean;
1164
+ }) => Promise<void>;
1165
+ /**
1166
+ * Optional: record an artifact (see `./artifacts.ts`). Upsert on
1167
+ * `(sessionId, kind, uri)` — an existing row keeps its `id` / `runId` /
1168
+ * `turnId` / `createdAt` and refreshes `label` / `meta` / `updatedAt`
1169
+ * (`mergeArtifact`). Resolves to the canonical stored row. Unknown
1170
+ * session ids are a no-op returning `null` (no ghost headers; same
1171
+ * posture as `updateRun`). Implementations enforce
1172
+ * `ARTIFACTS_PER_SESSION_CAP` via `selectArtifactEvictions`.
1173
+ *
1174
+ * Every artifact method is optional: stores that don't implement them
1175
+ * (file-map, remote, third-party) keep working — `Session.addArtifact`
1176
+ * degrades to a no-op and listings come back empty.
1177
+ */
1178
+ upsertArtifact?: (artifact: SessionArtifact) => Promise<SessionArtifact | null>;
1179
+ /**
1180
+ * Optional: list artifacts, newest `updatedAt` first. `filter.sessionId`
1181
+ * scopes to one session; `filter.projectRoot` follows the tri-state
1182
+ * contract of {@link list}; omit both for every artifact in the store.
1183
+ */
1184
+ listArtifacts?: (filter?: ArtifactFilter) => Promise<SessionArtifact[]>;
1185
+ /** Optional: remove one artifact. Unknown ids are a no-op. */
1186
+ deleteArtifact?: (sessionId: string, artifactId: string) => Promise<void>;
1187
+ /**
1188
+ * Optional: release backend resources (e.g. close the SQLite handle).
1189
+ * Hosts should call this on teardown when present; stores backed by
1190
+ * memory or remote HTTP have nothing to release and may omit it.
1191
+ */
1192
+ close?: () => void;
1193
+ }
948
1194
  /**
949
- * Provider a history is sent to, as {@link reasoningWireAction} tells them
950
- * apart. A Gemini-wire target is its signature scope, so an extension's
951
- * `googleCompatible` route keeps only the signatures it minted.
1195
+ * A live session: the turn history and run records of one conversation, with an optional store that persists them.
952
1196
  */
953
- type ReasoningWireTarget = 'anthropic' | 'openai' | GeminiSignatureScope;
954
- /**
955
- * Single source of truth for whether a signature-bearing reasoning block
956
- * (`thinking` / `redacted_thinking`) may be forwarded to a provider. The
957
- * wire builders ({@link toAnthropic}, the OpenAI and Google message shapers)
958
- * and the host-facing {@link sanitizeHistoryForProvider} apply this same
959
- * policy — keeping them one function means the sanitizer can never drift
960
- * from what the wire actually sends.
961
- *
962
- * Rules, each driven by an API constraint hit in production:
963
- *
964
- * - target `anthropic`:
965
- * - `redacted_thinking` → keep (native Anthropic block; must be echoed).
966
- * - `thinking` tagged `openai`, `google` or `google-vertex` → drop
967
- * (OpenAI `encrypted_content` and Gemini thought signatures are not
968
- * valid Anthropic HMACs; 400s).
969
- * - unsigned `thinking` → drop (`ThinkingBlockParam` requires a
970
- * signature; unsigned blocks come from non-signing producers).
971
- * - signed but UNTAGGED `thinking` (pre-tagging sessions) → keep: it is
972
- * most plausibly legacy Anthropic output, and the signature-400
973
- * recovery converges if it is not.
974
- *
975
- * - target `openai` or a Gemini-wire scope (`google`, `google-vertex`, a
976
- * `googleCompatible` route's):
977
- * - `redacted_thinking` → drop (Anthropic-only block type).
978
- * - `thinking` tagged `anthropic` → drop (an Anthropic HMAC is valid
979
- * nowhere else).
980
- * - `thinking` signed by any other producer, or signed but UNTAGGED →
981
- * strip-signature: there is no signature-error recovery on these paths,
982
- * so forwarding a possibly-foreign signature risks an unrecoverable
983
- * 400. The reasoning text survives; only the opaque signature is
984
- * withheld. Gemini's are kept only for the route that issued them.
985
- * @param block - A `thinking` or `redacted_thinking` block.
986
- * @param target - Provider the history is sent to.
987
- */
988
- declare function reasoningWireAction(block: {
989
- type: 'thinking';
990
- signature?: string;
991
- signatureProducer?: SignatureProducer;
992
- } | {
993
- type: 'redacted_thinking';
994
- }, target: ReasoningWireTarget): ReasoningWireAction;
995
- /**
996
- * Host-facing history sanitizer — applies {@link reasoningWireAction} to a
997
- * turn set BEFORE it is handed to an agent targeting `target`. The in-loop
998
- * wire builders already enforce the same policy per call, so this is for
999
- * hosts that seed history from an external durable store (or hydrate
1000
- * pre-provenance-tagging sessions) and want the poison removed from their
1001
- * source of truth in one call instead of re-deriving block semantics.
1002
- *
1003
- * Returns new turn objects only where something changed (unchanged turns
1004
- * pass through by reference). A turn whose content empties keeps the same
1005
- * neutral marker the wire repair uses, so role boundaries stay intact.
1006
- * @param turns - Turns to sanitize.
1007
- * @param target - Provider the history is sent to.
1008
- */
1009
- declare function sanitizeHistoryForProvider<T extends {
1010
- content: SessionContentBlock[];
1011
- }>(turns: readonly T[], target: ReasoningWireTarget): {
1012
- turns: T[];
1013
- removed: number;
1014
- stripped: number;
1015
- };
1016
- /**
1017
- * Converts a {@link SessionMessage} into an Anthropic wire message. Foreign reasoning blocks are dropped following {@link reasoningWireAction}.
1018
- *
1019
- * @param msg - Message to convert.
1020
- */
1021
- declare function toAnthropic(msg: SessionMessage): {
1022
- role: string;
1023
- content: unknown;
1024
- };
1025
- /**
1026
- * Converts a {@link SessionMessage} into an OpenAI wire message.
1027
- *
1028
- * @param msg - Message to convert.
1029
- */
1030
- declare function toOpenAI(msg: SessionMessage): {
1031
- role: string;
1032
- content: unknown;
1033
- };
1034
- /**
1035
- * Drop ASSISTANT turns whose every `tool_call` block is unresolved
1036
- * (no matching `tool_result` block anywhere later in the transcript).
1037
- * Tool_call blocks with at least one matching tool_result are kept — modes
1038
- * 1/3 of {@link ensureToolResultPairing} handle the partial-pair case at
1039
- * wire-send time.
1040
- *
1041
- * Use case: session resume. A turn that emitted three `tool_use` blocks but
1042
- * never persisted the matching `tool_result` turn (process death, crash,
1043
- * `kill -9`) leaves the transcript with an orphan that Anthropic rejects on
1044
- * the FIRST API call after reload. Dropping the whole assistant turn — not
1045
- * just the orphan blocks — preserves text-only turns that legitimately
1046
- * carry reasoning the model wants to see again.
1047
- *
1048
- * Does NOT mint fresh ids: re-id'ing on every resume would cause
1049
- * exponential transcript growth across repeated resumes of an interrupted
1050
- * session.
1051
- *
1052
- * Pure: returns the input reference unchanged when no turn was dropped.
1053
- * @param turns - Turns of the session, oldest first.
1054
- */
1055
- declare function filterUnresolvedToolUses<T extends {
1056
- role: string;
1057
- content: SessionContentBlock[];
1058
- }>(turns: T[]): T[];
1059
- /**
1060
- * Classification of a session's tail state for resume purposes.
1061
- *
1062
- * - `'clean'` — the trailing turn is a user message (the model would respond
1063
- * next), or the transcript is empty. Safe to resume by appending a fresh
1064
- * user prompt.
1065
- * - `'interrupted'` — the trailing turn is an assistant message that has at
1066
- * least one `tool_call` block with no matching `tool_result` anywhere
1067
- * later. The run was almost certainly killed between persisting the
1068
- * assistant turn and persisting its tool-results turn. Hosts that want
1069
- * Claude-Code-style auto-resume can detect this and inject a
1070
- * `"Continue from where you left off."` user message before the next run.
1071
- * - `'completed'` — the trailing turn is an assistant message with no
1072
- * orphan tool_calls. The model considers itself done. Hosts that want to
1073
- * resume must supply a new prompt; auto-continuation here would be a
1074
- * non-sequitur.
1075
- */
1076
- type TurnInterruptionState = 'clean' | 'interrupted' | 'completed';
1077
- /**
1078
- * Inspect a session's trailing turn to classify whether the run was
1079
- * interrupted mid-tool-call. Pure / synchronous — does not modify the input.
1080
- *
1081
- * Pair with {@link filterUnresolvedToolUses} on the resume path: filter
1082
- * first so the result reflects the post-cleanup state (a turn whose orphans
1083
- * were stripped reads as 'completed', not 'interrupted').
1084
- * @param turns - Turns of the session, oldest first.
1085
- */
1086
- declare function detectTurnInterruption<T extends {
1087
- role: string;
1088
- content: SessionContentBlock[];
1089
- }>(turns: T[]): TurnInterruptionState;
1090
- /**
1091
- * Guarantee a message list ends with a `role: 'user'` message, appending a
1092
- * synthetic directive when it doesn't.
1093
- *
1094
- * Why: Anthropic's API (and several OpenAI-compat reasoning models — opus
1095
- * 4.7, the o-series translation layers on Bedrock/Vertex) rejects requests
1096
- * whose final message is `role: 'assistant'` with
1097
- * "This model does not support assistant message prefill. The conversation
1098
- * must end with a user message."
1099
- *
1100
- * Triggers in zidane:
1101
- * - Compaction over a session whose last turn is the agent's response
1102
- * (the common case — autocompact fires right after `agent.run()`).
1103
- * - Schema enforcement after an assistant text turn (no `tool_use`, so
1104
- * `ensureToolResultPairing` doesn't synthesize a user tail).
1105
- * - `context:transform` hooks that strip the trailing user turn.
1106
- *
1107
- * The pair-repair pass {@link ensureToolResultPairing} already covers the
1108
- * orphan-`tool_use` case via mode 2; this helper closes the plain-text
1109
- * assistant-tail case. They compose: run pair-repair first, then this
1110
- * pass, so an assistant turn with orphan tool_uses gets its synthetic
1111
- * `tool_result` user turn AND this pass is a no-op (the synthetic turn
1112
- * is already user-role).
1113
- *
1114
- * Empty input passes through unchanged — the caller's "nothing to send"
1115
- * guard is responsible for that case; we don't materialize a conversation
1116
- * out of an empty list.
1117
- *
1118
- * Idempotent: returns the input reference unchanged when the list is
1119
- * already user-terminated (or empty).
1120
- *
1121
- * @param messages Wire-ready message list.
1122
- * @param provider Provider whose `userMessage()` shape we use so the
1123
- * synthetic turn matches the wire format the rest of
1124
- * the list already follows.
1125
- * @param directive Text to put in the synthetic user message. Defaults
1126
- * to {@link DEFAULT_USER_TAIL_DIRECTIVE} ("Continue.").
1127
- * Compaction overrides this with a summary-specific cue.
1128
- */
1129
- declare function ensureEndsWithUserMessage(messages: SessionMessage[], provider: Provider, directive?: string): SessionMessage[];
1130
- /** Options for {@link toWireMessages}. */
1131
- interface ToWireMessagesOptions {
1132
- /**
1133
- * Pairing-repair telemetry. Fires once per repair the underlying
1134
- * {@link ensureToolResultPairing} pass performs. Mirrors the
1135
- * `pairing:repair` hook surface so consumers can wire structured logging
1136
- * without an agent instance.
1137
- */
1138
- onRepair?: (repair: PairingRepair) => void;
1197
+ interface Session {
1198
+ /** Session ID */
1199
+ readonly id: string;
1200
+ /** Agent ID (optional label) */
1201
+ readonly agentId?: string;
1139
1202
  /**
1140
- * When set, also runs {@link ensureEndsWithUserMessage} so the result is
1141
- * safe for assistant-prefill-rejecting models (opus 4.7, o-series
1142
- * translation layers). Omit to skip — pure pairing repair only.
1203
+ * Re-label the session's agent profile (in memory; persisted by the
1204
+ * next `save()`). Sessions remember their profile — pickers restore it
1205
+ * on activation and other windows converge on it via `sessions.touch`.
1143
1206
  */
1144
- provider?: Provider;
1207
+ setAgentId: (agentId: string) => void;
1145
1208
  /**
1146
- * Override for the synthetic user-tail directive. Only consulted when
1147
- * `provider` is set. Defaults to {@link DEFAULT_USER_TAIL_DIRECTIVE}.
1209
+ * Project this session was created under — see {@link SessionData.projectRoot}.
1210
+ * Set once on creation; surfaces here for read-only inspection.
1148
1211
  */
1149
- userTailDirective?: string;
1212
+ readonly projectRoot?: string;
1150
1213
  /**
1151
- * Resolve persisted content references into provider-native payload bytes.
1152
- * The returned data is wire-only and must not be written back to turns.
1214
+ * Raw persisted turn history — kept pristine for fidelity (the model's
1215
+ * reasoning chain stays intact across reloads).
1216
+ *
1217
+ * **DO NOT pass this directly to a provider request.** Mid-pair
1218
+ * persistence (interrupted runs, partial-result writes, compaction
1219
+ * boundaries) leaves orphan `tool_use` / `tool_result` blocks here that
1220
+ * every provider 400s on (`tool_result must be preceded by a tool_call
1221
+ * with the same toolCallId`). The agent's own loop repairs these
1222
+ * just-in-time at wire-send time and never writes the repair back to
1223
+ * `turns`.
1224
+ *
1225
+ * For provider requests built outside `agent.run()`, use
1226
+ * {@link Session.toMessages} — it applies the same defensive pairing
1227
+ * repair and resolves to a guaranteed-safe `SessionMessage[]`.
1153
1228
  */
1154
- resolveContentRef?: ResolveContentRef;
1155
- }
1156
- /**
1157
- * Build a wire-ready `SessionMessage[]` from raw persisted `SessionTurn[]`.
1158
- *
1159
- * **The canonical "I want to send these to a provider" projection.** Use
1160
- * this — not raw `session.turns` / `store.getTurns()` — when constructing a
1161
- * provider request outside `agent.run()`. The agent's own wire pipeline
1162
- * (`executeTurn` in `src/loop-turn.ts`) applies the same repair just-in-time;
1163
- * downstream consumers that bypass the loop hit `tool_result must be
1164
- * preceded by a tool_call` 400s precisely because they shipped raw turns.
1165
- *
1166
- * Pipeline:
1167
- * 1. Filter out turns that never reach the model (`system` and `command`
1168
- * roles).
1169
- * 2. Resolve content refs with `options.resolveContentRef`.
1170
- * 3. {@link ensureToolResultPairing} — repairs all six orphan / dup
1171
- * corruption modes: synthetic placeholders for orphan tool_use blocks
1172
- * (preserves the model's tool_use shape), strips for duplicates and
1173
- * orphan tool_results.
1174
- * 4. {@link ensureEndsWithUserMessage} when `options.provider` is set —
1175
- * guards against assistant-tail prefill rejection (opus 4.7, o-series).
1176
- *
1177
- * Pure + idempotent. Does not mutate the input turns. Re-running on the
1178
- * output is a no-op.
1179
- *
1180
- * **Do not feed the result back into `session.setTurns` / `appendTurns`.**
1181
- * The repair can insert `SYNTHETIC_TOOL_RESULT_PLACEHOLDER` / `[Orphaned
1182
- * tool result removed …]` markers; round-tripping those into persisted
1183
- * state contaminates the session's reasoning history and defeats the
1184
- * "don't rewrite the past" invariant the wire-only repair was designed
1185
- * around.
1186
- * @param turns - Persisted turns, oldest first.
1187
- * @param options - Repair and tail options. See {@link ToWireMessagesOptions}.
1188
- */
1189
- declare function toWireMessages(turns: readonly {
1190
- role: 'user' | 'assistant' | 'system' | 'command';
1191
- content: SessionContentBlock[];
1192
- }[], options?: ToWireMessagesOptions): Promise<SessionMessage[]>;
1193
- /**
1194
- * Converts a wire message of unknown provider into a {@link SessionMessage}. Block types decide between {@link fromAnthropic} and {@link fromOpenAI}. Anthropic is the default.
1195
- *
1196
- * @param msg - Anthropic or OpenAI wire message.
1197
- */
1198
- declare function autoDetectAndConvert(msg: {
1199
- role: string;
1200
- content: unknown;
1201
- }): SessionMessage;
1202
- //#endregion
1203
- //#region src/session/metadata-merge.d.ts
1204
- /** Options for `SessionStore.saveMeta`. */
1205
- interface SaveMetaOptions {
1229
+ readonly turns: SessionTurn[];
1206
1230
  /**
1207
- * The metadata keys this writer changed. When set, the store merges only
1208
- * these keys into the metadata it already holds (an `undefined` value
1209
- * removes the key) instead of replacing the whole record, so a stale copy
1210
- * of the session can't write back keys another writer changed since.
1211
- * Omitted: the whole `metadata` record is written.
1231
+ * True when this session has no turns yet.
1232
+ *
1233
+ * Use this as a first-prompt signal when setting up a run — e.g. writing initial
1234
+ * configuration only on fresh sessions. Equivalent to `turns.length === 0`.
1212
1235
  */
1213
- metaKeys?: readonly string[];
1214
- }
1215
- /**
1216
- * The metadata a `saveMeta` should store: `incoming` wholesale without
1217
- * `keys`, otherwise `stored` with only `keys` taken from `incoming`.
1218
- *
1219
- * @param stored - Metadata the store holds now; when absent, `incoming` is stored as is.
1220
- * @param incoming - Metadata the writer sends.
1221
- * @param keys - Keys the writer changed (`SaveMetaOptions.metaKeys`); an `undefined` value in `incoming` removes the key.
1222
- */
1223
- declare function mergeSessionMetadata(stored: SessionData['metadata'] | undefined, incoming: SessionData['metadata'], keys: readonly string[] | undefined): SessionData['metadata'];
1224
- //#endregion
1225
- //#region src/session/file-map.d.ts
1226
- /**
1227
- * Host-provided file-map adapter. Three methods exchanging `Record<string, string>`
1228
- * payloads — the whole persistence surface the wrapper needs.
1229
- */
1230
- interface FileMapAdapter {
1231
- /** Load the current file map. Returns an empty `files` record when nothing is persisted. */
1232
- get: () => Promise<{
1233
- files: Record<string, string>;
1234
- }>;
1235
- /** Replace the persisted file map. Full-rewrite semantics. */
1236
- save: (files: Record<string, string>) => Promise<void>;
1237
- /** Delete all persisted state. */
1238
- delete: () => Promise<void>;
1236
+ readonly isEmpty: boolean;
1237
+ /** Top-level session status */
1238
+ readonly status: SessionData['status'];
1239
+ /** All runs in this session */
1240
+ readonly runs: SessionRun[];
1241
+ /** Arbitrary metadata */
1242
+ readonly metadata: Record<string, unknown>;
1243
+ /** Creation time as epoch milliseconds. */
1244
+ readonly createdAt: number;
1245
+ /** Last update time as epoch milliseconds. */
1246
+ readonly updatedAt: number;
1247
+ /**
1248
+ * Start tracking a new run. `extras.parentRunId` + `extras.depth` are
1249
+ * populated by the spawn tool when a child agent shares its parent's
1250
+ * session; regular top-level `agent.run()` calls omit them.
1251
+ */
1252
+ startRun: (runId: string, prompt?: string, extras?: {
1253
+ parentRunId?: string;
1254
+ depth?: number;
1255
+ resumedFromRunId?: string;
1256
+ label?: string;
1257
+ parentCallId?: string;
1258
+ agent?: SessionRunAgent;
1259
+ }) => void;
1260
+ /** Mark a run as completed */
1261
+ completeRun: (runId: string, stats: {
1262
+ turns: number;
1263
+ tokensIn: number;
1264
+ tokensOut: number;
1265
+ turnUsage?: TurnUsage[];
1266
+ cost?: number;
1267
+ }) => void;
1268
+ /**
1269
+ * Mark a run as aborted. Optional `stats` lets the agent backfill the run's token totals when
1270
+ * the abort happened *after* the loop accumulated meaningful usage —
1271
+ * common when the user presses esc mid-streaming. Without it, the run
1272
+ * record reads `0 in / 0 out` on reload regardless of how much was
1273
+ * spent before the abort. Same shape as `completeRun`'s stats so the
1274
+ * persisted `totalUsage` aggregate stays consistent across paths.
1275
+ */
1276
+ abortRun: (runId: string, stats?: {
1277
+ turns: number;
1278
+ tokensIn: number;
1279
+ tokensOut: number;
1280
+ turnUsage?: TurnUsage[];
1281
+ cost?: number;
1282
+ }) => void;
1283
+ /** Mark a run as errored. Optional `stats` — same rationale as `abortRun.stats`. */
1284
+ errorRun: (runId: string, error: string, stats?: {
1285
+ turns: number;
1286
+ tokensIn: number;
1287
+ tokensOut: number;
1288
+ turnUsage?: TurnUsage[];
1289
+ cost?: number;
1290
+ }, detail?: RunErrorDetail) => void;
1291
+ /** Append turns to in-memory history AND persist via store.appendTurns (if store present) */
1292
+ appendTurns: (turns: SessionTurn[]) => Promise<void>;
1293
+ /** Replace all turns in-memory (does not persist — use save() for that) */
1294
+ setTurns: (turns: SessionTurn[]) => void;
1295
+ /**
1296
+ * Replace all runs in-memory (does not persist — use save() for that).
1297
+ * Mirrors {@link setTurns} for the fork / restore case: callers that
1298
+ * bootstrap a session from an externally-derived snapshot (e.g.
1299
+ * `onForkTurn` copying parent runs into a child session) need this so
1300
+ * the cloned runs land in `data.runs` before the first `save()`.
1301
+ * Production agent runs continue to mutate runs via `startRun` /
1302
+ * `completeRun` / `updateRun`; this is the bulk-replace escape hatch.
1303
+ */
1304
+ setRuns: (runs: SessionRun[]) => void;
1305
+ /** Update the session status in memory AND via store.updateStatus (if store present) */
1306
+ updateStatus: (status: SessionData['status']) => Promise<void>;
1307
+ /** Persist an updated run record via store.updateRun (if store present) */
1308
+ updateRun: (run: SessionRun) => Promise<void>;
1309
+ /** Generate a session-managed turn ID using store.generateTurnId if available, else crypto.randomUUID() */
1310
+ generateTurnId: () => string | Promise<string>;
1311
+ /** Set metadata key. `touch: false` keeps `updatedAt` (a rename or a favorite is not activity). */
1312
+ setMeta: (key: string, value: unknown, options?: {
1313
+ touch?: boolean;
1314
+ }) => void;
1315
+ /**
1316
+ * Record an artifact this session produced. Fills `id`, timestamps and
1317
+ * defaults `projectRoot` to the session's own; `origin` ties it to the
1318
+ * producing run/turn for transcript anchoring. Resolves to the stored
1319
+ * row, or `undefined` when there is no store or the store doesn't
1320
+ * implement artifacts (never throws for that case — emission is
1321
+ * best-effort by contract).
1322
+ */
1323
+ addArtifact: (input: SessionArtifactInput, origin?: {
1324
+ runId?: string;
1325
+ turnId?: string;
1326
+ }) => Promise<SessionArtifact | undefined>;
1327
+ /** This session's artifacts, newest first. Empty when unsupported. */
1328
+ listArtifacts: (filter?: Pick<ArtifactFilter, 'kind' | 'since' | 'limit'>) => Promise<SessionArtifact[]>;
1329
+ /**
1330
+ * Persist the session to the store. When the store implements `saveMeta`,
1331
+ * this writes the header, the changed metadata keys and the runs, and leaves
1332
+ * turns alone, unless `setTurns` or `setRuns` replaced them. In every other
1333
+ * case it overwrites the whole document through `store.save`. Throws when
1334
+ * the session has no store.
1335
+ */
1336
+ save: () => Promise<void>;
1337
+ /**
1338
+ * Project the session's persisted turns into wire-ready messages safe to
1339
+ * hand to any provider.
1340
+ *
1341
+ * The canonical answer to "I need to send these turns to Anthropic /
1342
+ * OpenAI from outside `agent.run()`" (sub-agent classifier, side-channel
1343
+ * summarizer, replay worker, …). Runs the same defensive pairing repair
1344
+ * the agent loop applies just-in-time at wire-send time
1345
+ * ({@link ensureToolResultPairing}), so orphan `tool_use` blocks and
1346
+ * dangling `tool_result`s never reach the provider as the 400
1347
+ * "tool_result must be preceded by a tool_call with the same toolCallId".
1348
+ *
1349
+ * Pass `provider` to also enforce the user-tail invariant
1350
+ * ({@link ensureEndsWithUserMessage}) — required for opus 4.7 / o-series
1351
+ * style models that reject assistant-prefill.
1352
+ *
1353
+ * Pure + idempotent. Resolves content refs only in the returned messages
1354
+ * and does NOT mutate `session.turns`. **Do not write the result back via
1355
+ * `setTurns` / `appendTurns`** — synthetic placeholders or resolved
1356
+ * payloads will contaminate persisted history.
1357
+ */
1358
+ toMessages: (options?: ToWireMessagesOptions) => Promise<SessionMessage[]>;
1359
+ /** Serialize to SessionData */
1360
+ toJSON: () => SessionData;
1361
+ /**
1362
+ * The backing store, when one was provided. Exposed so hosts can call
1363
+ * its optional `close()` on teardown (e.g. release the SQLite handle).
1364
+ */
1365
+ readonly store?: SessionStore;
1239
1366
  }
1240
- /** Options for {@link createFileMapStore}. */
1241
- interface FileMapStoreOptions {
1242
- /** Filename for the JSONL turns log. Default: `turns.jsonl`. */
1243
- turnsFile?: string;
1244
- /** Filename for the metadata JSON. Default: `meta.json`. */
1245
- metaFile?: string;
1367
+ /** Options for {@link createSession}. */
1368
+ interface CreateSessionOptions {
1369
+ /** Session ID. If omitted and store provides generateSessionId, that is used. */
1370
+ id?: string;
1371
+ /** Agent ID label */
1372
+ agentId?: string;
1373
+ /**
1374
+ * Project tag — see {@link SessionData.projectRoot}. Stamped once on
1375
+ * creation; ignored when `_data` is set (restoring an existing
1376
+ * session preserves whatever was already persisted there). The chat
1377
+ * layer's session factory stamps `projectRootOf(cwd)` so sessions
1378
+ * started from the same repo — any subdir, any linked worktree — share
1379
+ * one tag.
1380
+ */
1381
+ projectRoot?: string;
1382
+ /** Initial metadata */
1383
+ metadata?: Record<string, unknown>;
1384
+ /** Storage backend (optional, enables save/load) */
1385
+ store?: SessionStore;
1386
+ /**
1387
+ * Observability hook for the load-time pairing heal: fired once per block
1388
+ * or turn `dropInvalidToolPairings` deleted while restoring `_data`.
1389
+ * Deletions are permanent once the session is saved, so hosts that alert
1390
+ * on wire-time `pairing:repair` events should wire this to the same sink.
1391
+ * Only fires on the `_data` restore path; fresh sessions never heal.
1392
+ */
1393
+ onPairingDrop?: (drop: PairingDrop) => void;
1394
+ /**
1395
+ * @internal: restore from existing data (bypasses id/agentId/metadata
1396
+ * options). The session ALIASES this object for its lifetime — every
1397
+ * mutation (appendTurns, run records, updatedAt) writes through to it,
1398
+ * and the load-time pairing heal may replace its `turns` array in place
1399
+ * before the session is returned. Callers must not retain independent
1400
+ * ownership expectations.
1401
+ */
1402
+ _data?: SessionData;
1246
1403
  }
1247
1404
  /**
1248
- * Create a single-session `SessionStore` backed by a file-map adapter.
1249
- *
1250
- * @param adapter - Host adapter that loads, saves and deletes the file map.
1251
- * @param options - File names to use. See {@link FileMapStoreOptions}.
1252
- * @example
1253
- * ```ts
1254
- * const session = await createSession({
1255
- * store: createFileMapStore(hostSessionStore),
1256
- * })
1257
- * ```
1258
- */
1259
- declare function createFileMapStore(adapter: FileMapAdapter, options?: FileMapStoreOptions): SessionStore;
1260
- //#endregion
1261
- //#region src/session/memory.d.ts
1262
- /**
1263
- * Creates an in-memory {@link SessionStore}. Nothing is persisted.
1264
- *
1405
+ * Create a new session.
1406
+ * Async so stores that generate IDs server-side (e.g. a database) can be supported.
1407
+ * @param options - Session identity, metadata and store. See {@link CreateSessionOptions}.
1265
1408
  * @example
1266
1409
  * ```ts
1267
1410
  * import { createMemoryStore, createSession } from 'zidane/session'
1268
1411
  *
1269
- * const session = await createSession({ store: createMemoryStore() })
1412
+ * const session = await createSession({ agentId: 'reviewer', store: createMemoryStore() })
1413
+ * console.log(session.id, session.turns.length)
1270
1414
  * ```
1271
1415
  */
1272
- declare function createMemoryStore(): SessionStore;
1273
- //#endregion
1274
- //#region src/session/remote.d.ts
1275
- /** Options for {@link createRemoteStore}. */
1276
- interface RemoteStoreOptions {
1277
- /** Base URL of the session API */
1278
- url: string;
1279
- /** Optional headers (e.g. for authentication) */
1280
- headers?: Record<string, string>;
1281
- /** Per-request timeout in ms. Default 30s — bounds a hung backend. */
1282
- timeoutMs?: number;
1283
- }
1416
+ declare function createSession(options?: CreateSessionOptions): Promise<Session>;
1284
1417
  /**
1285
- * Creates a {@link SessionStore} that talks to a REST session API over HTTP. See the module comment for the endpoints it calls.
1286
- *
1287
- * @param options - API base URL, headers and timeout.
1288
- * @example
1289
- * ```ts
1290
- * import { createRemoteStore, createSession } from 'zidane/session'
1418
+ * Demote a persisted `'running'` status to `'idle'` (in place) and return the
1419
+ * data. A persisted `'running'` is necessarily stale: the run that set it lived
1420
+ * in another process (crash, kill -9, power loss) and cannot still be executing
1421
+ * in a freshly-loaded session. Call this on the result of a raw `store.load()`
1422
+ * so consumers don't render a ghost in-progress state or refuse a new run.
1423
+ * `loadSession` applies it automatically; direct `store.load()` callers (e.g.
1424
+ * the TUI) should run loaded data through this.
1291
1425
  *
1292
- * const store = createRemoteStore({ url: 'https://api.example.com', headers: { authorization: 'Bearer token' } })
1293
- * const session = await createSession({ store })
1294
- * ```
1426
+ * Run RECORDS get the same treatment: the agent persists each record at
1427
+ * run start with `status: 'running'` (crash durability — see the
1428
+ * `SessionStore.updateRun` contract), so a freshly-loaded session may
1429
+ * carry `'running'` runs that died with their process. They demote to
1430
+ * `'aborted'` so replay renders a truthful "aborted" state instead of a
1431
+ * perpetually-in-flight run.
1432
+ * @param data - Loaded session data. It is modified in place.
1295
1433
  */
1296
- declare function createRemoteStore(options: RemoteStoreOptions): SessionStore;
1297
- //#endregion
1298
- //#region src/session/index.d.ts
1299
- /**
1300
- * Run `fn` with `session` bound as the active extension session for the
1301
- * duration of the call (and every async continuation it spawns). Uses
1302
- * `AsyncLocalStorage.run` rather than `enterWith` so concurrent agents in the
1303
- * same process (e.g. the GUI's multi-session host) never observe each other's
1304
- * session through `currentExtensionSession()`.
1305
- * @param session - Session to bind. When `undefined`, `fn` runs without a binding.
1306
- * @param fn - Function to run with the binding in place.
1307
- */
1308
- declare function withExtensionSession<T>(session: Session | undefined, fn: () => T): T;
1434
+ declare function demoteStaleRunningStatus(data: SessionData): SessionData;
1435
+ /** Options for {@link loadSession}. */
1436
+ interface LoadSessionOptions {
1437
+ /** Forwarded to `createSession` — see {@link CreateSessionOptions.onPairingDrop}. */
1438
+ onPairingDrop?: (drop: PairingDrop) => void;
1439
+ /**
1440
+ * Write a load-time pairing heal back to the store (default true). Pass
1441
+ * `false` from READERS — a window mirroring a session another process
1442
+ * runs (daemon mode) — because the persist is a bulk turn overwrite and
1443
+ * the owner's next load heals and persists it anyway.
1444
+ */
1445
+ persistHeal?: boolean;
1446
+ }
1309
1447
  /**
1310
- * Returns the session bound by {@link withExtensionSession} for the current async context, or `undefined` when none is bound.
1448
+ * Load an existing session from a store.
1449
+ * @param store - Store to load from.
1450
+ * @param sessionId - Id of the session to load.
1451
+ * @param options - Load options. See {@link LoadSessionOptions}.
1452
+ * @returns The session, or `null` when the store has no session with that id.
1311
1453
  */
1312
- declare function currentExtensionSession(): Session | undefined;
1454
+ declare function loadSession(store: SessionStore, sessionId: string, options?: LoadSessionOptions): Promise<Session | null>;
1455
+ //#endregion
1456
+ //#region src/providers/model-catalog.d.ts
1313
1457
  /**
1314
- * Reads one value an extension stored in the session metadata. Returns a copy, or `undefined` when the session, extension or key is missing or a name is unsafe.
1458
+ * Model catalog override — the one seam for replacing model metadata.
1315
1459
  *
1316
- * @param session - Session to read, if any.
1317
- * @param extensionName - Name of the extension that owns the value.
1318
- * @param key - Key under the extension namespace.
1319
- */
1320
- declare function getExtensionSessionState<T = JsonValue>(session: Session | undefined, extensionName: string, key: string): T | undefined;
1321
- /**
1322
- * Stores a JSON value under an extension namespace in the session metadata and saves the session when it has a store. Does nothing without a session.
1460
+ * zidane resolves model metadata (output ceiling, pricing, context window,
1461
+ * reasoning support) from pi-ai's bundled registry. That registry is a
1462
+ * snapshot: it can't know a gateway alias, a private deployment, a model
1463
+ * released after our dependency pin, or a non-Anthropic model served over the
1464
+ * Anthropic wire. Without a seam, consumers either patch our source (the
1465
+ * `EXTRA_COST_RATES` table in `cost.ts` exists because of exactly that) or
1466
+ * mutate pi-ai's unfrozen catalog behind our back.
1323
1467
  *
1324
- * Throws when a name is unsafe or the value exceeds the size limits (16 KiB per item, 64 KiB for all extension state).
1468
+ * Two ways to supply one, both first-class:
1325
1469
  *
1326
- * @param session - Session to write, if any.
1327
- * @param extensionName - Name of the extension that owns the value.
1328
- * @param key - Key under the extension namespace.
1329
- * @param value - JSON value to store. It is copied.
1470
+ * - `behavior.modelCatalog` — per agent, and per run like every other
1471
+ * behavior field. No process-wide state, so two agents can carry
1472
+ * different catalogs.
1473
+ * - {@link setModelCatalog} — process-wide default. Also the only source
1474
+ * the chat/TUI layer can see (the model picker resolves metadata before
1475
+ * any agent exists).
1476
+ *
1477
+ * Resolution, first hit wins: run behavior → agent behavior → global →
1478
+ * pi-ai's bundled registry → local fallback tables.
1479
+ *
1480
+ * Everything stays keyed by `(provider, modelId)`: nothing is flattened
1481
+ * across providers, and overriding one provider leaves the others fully
1482
+ * bundled. The provider key is the pi-ai registry id, which is usually the
1483
+ * factory name (`anthropic`, `cerebras`, `openrouter`, …) — with one
1484
+ * exception: the Codex provider stores model records under `openai-codex` and
1485
+ * prices them under `openai`, and accepts an entry keyed EITHER way — on the
1486
+ * wire via {@link aliasCatalogProviders} and in the host layer via the
1487
+ * descriptor's key set, so an override can't half-apply.
1488
+ *
1489
+ * Two operational notes:
1490
+ *
1491
+ * - **Serialization.** The table form is plain JSON; the `{ get, list }`
1492
+ * form holds functions. A durable / replay runtime that snapshots
1493
+ * `behavior` can only round-trip the table form — build the source form
1494
+ * inside the process that runs the agent, or install it with
1495
+ * {@link setModelCatalog} at boot.
1496
+ * - **Multi-tenancy.** {@link setModelCatalog} is process-wide, so in a
1497
+ * shared server it applies to every tenant. Pass `behavior.modelCatalog`
1498
+ * per agent / per run instead; the global is for a deployment-wide
1499
+ * correction and for the host's model picker.
1330
1500
  */
1331
- declare function setExtensionSessionState(session: Session | undefined, extensionName: string, key: string, value: JsonValue): Promise<void>;
1332
1501
  /**
1333
- * Removes one value from an extension namespace in the session metadata and saves the session when it has a store. Does nothing when the value does not exist.
1334
- *
1335
- * @param session - Session to modify, if any.
1336
- * @param extensionName - Name of the extension that owns the value.
1337
- * @param key - Key to remove.
1502
+ * Size class of a model within its provider's lineup. Drives the automatic
1503
+ * text model (titles, suggestions): the smallest current model of the
1504
+ * session's provider. Bundled models get it from a family heuristic
1505
+ * (`src/chat/text-model.ts`); a catalog entry's value wins over it.
1338
1506
  */
1339
- declare function deleteExtensionSessionState(session: Session | undefined, extensionName: string, key: string): Promise<void>;
1507
+ type ModelTier = 'small' | 'medium' | 'large';
1340
1508
  /**
1341
- * Transitive `resumedFromRunId` chain starting at `runId` (inclusive).
1342
- *
1343
- * A resumed run only persists the turns IT produced — the turns it was
1344
- * seeded with still carry the original run's id. So reconstructing a
1345
- * resumed child's full conversation means collecting turns from every run
1346
- * in its resume lineage, not just the latest link. Cycle-guarded (a
1347
- * malformed chain terminates instead of looping).
1348
- * @param runs - Run records of the session.
1349
- * @param runId - Run to start from.
1509
+ * Metadata for one model. Every field is optional and merges FIELD-LEVEL over
1510
+ * the bundled entry, so `{ maxTokens: 128000 }` corrects the ceiling and
1511
+ * leaves pricing and context window to the registry.
1350
1512
  */
1351
- declare function resumeChainRunIds(runs: readonly SessionRun[], runId: string): Set<string>;
1352
- /** Record of one agent run inside a session. */
1353
- interface SessionRun {
1354
- /** Run id. */
1355
- id: string;
1356
- /** Start time as epoch milliseconds. */
1357
- startedAt: number;
1358
- /** End time as epoch milliseconds. Absent while the run is in progress. */
1359
- endedAt?: number;
1360
- /** Prompt the run started with. */
1361
- prompt: string;
1362
- /** Run state. A persisted `running` run whose process died is shown as `aborted` on load. */
1363
- status: 'running' | 'completed' | 'aborted' | 'error';
1364
- /** Number of turns the run produced. */
1365
- turns?: number;
1366
- /** Input tokens used by the run. */
1367
- tokensIn?: number;
1368
- /** Output tokens used by the run. */
1369
- tokensOut?: number;
1370
- /** Error message when the run failed. */
1371
- error?: string;
1372
- /** What `error`'s one line leaves out (the provider's own text, a limit's reset). */
1373
- errorDetail?: RunErrorDetail;
1374
- /** Per-turn usage breakdown */
1375
- turnUsage?: TurnUsage[];
1376
- /** Total usage across all turns */
1377
- totalUsage?: TurnUsage;
1378
- /** Estimated cost in USD */
1379
- cost?: number;
1380
- /**
1381
- * The run that spawned this one, when the agent is a subagent sharing its
1382
- * parent's session. Undefined on top-level `agent.run()`. Consumers can walk
1383
- * `runs` by `parentRunId` to reconstruct the subagent tree.
1384
- */
1385
- parentRunId?: string;
1386
- /**
1387
- * The prior run this one continues (see `AgentRunOptions.resumeRunId`).
1388
- * Set when a stopped/failed subagent run was resumed — consumers can
1389
- * chain runs by `resumedFromRunId` to render “child-4 (resumes child-2)”
1390
- * style markers. Absent on normal runs.
1391
- */
1392
- resumedFromRunId?: string;
1393
- /**
1394
- * Host-assigned display label (e.g. the spawn tool's `child-3`), persisted
1395
- * so label → run resolution is a stored fact instead of a positional
1396
- * guess. Positional `child-N` numbering can desynchronize from announced
1397
- * labels (concurrent spawns `startRun` out of reservation order, a
1398
- * pre-`startRun` throw advances the counter without a run, and reload
1399
- * ordering ties break lexicographically) — resolving by stored label is
1400
- * immune to all three. Absent on top-level runs and legacy sessions.
1401
- */
1402
- label?: string;
1403
- /**
1404
- * The `spawn` tool call that started this run, in the parent's turn (see
1405
- * `AgentRunOptions.parentCallId`): pairs a child with its call exactly,
1406
- * where parallel calls share a task. Absent on top-level runs and older
1407
- * sessions.
1408
- */
1409
- parentCallId?: string;
1410
- /**
1411
- * Zero-based subagent depth. 0 = top-level run, 1 = direct child, …
1412
- * Recorded here so hosts can query/filter by level without walking the tree.
1413
- */
1414
- depth?: number;
1513
+ interface ModelCatalogEntry {
1514
+ /** Model id. Required only for entries surfaced through {@link ModelCatalogSource.list}. */
1515
+ id?: string;
1516
+ /** Display name for pickers. */
1517
+ name?: string;
1518
+ /** Max output tokens — the provider's `max_tokens` default and hard clamp. */
1519
+ maxTokens?: number;
1520
+ /** Total context window, in tokens (drives the host-layer context gauge). */
1521
+ contextWindow?: number;
1522
+ /** Whether the model supports reasoning/thinking. */
1523
+ reasoning?: boolean;
1524
+ /** Accepted input modalities. */
1525
+ input?: readonly ('text' | 'image')[];
1415
1526
  /**
1416
- * How this run was initiated when not a plain user prompt. `command` marks
1417
- * a sub-run driven from a `/` command's `ctx.runAgent`; `display` is the
1418
- * short line the transcript shows instead of the full injected prompt
1419
- * (which often embeds bulky material like a diff). Presentation-only —
1420
- * the wire/model payload is unaffected. Absent on normal runs.
1527
+ * Per-MTok rates used for cost estimation. Merges PER-RATE over the bundled
1528
+ * rates, so `{ cost: { output: 30 } }` corrects the output rate and keeps the
1529
+ * registry's input / cache rates rather than zeroing them.
1421
1530
  */
1422
- origin?: {
1423
- kind: 'command';
1424
- display?: string;
1531
+ cost?: {
1532
+ input?: number;
1533
+ output?: number;
1534
+ cacheRead?: number;
1535
+ cacheWrite?: number;
1425
1536
  };
1537
+ /** Size class; overrides the family heuristic. */
1538
+ tier?: ModelTier;
1426
1539
  }
1427
- /** A session's turns and runs: what a history edit reads and writes (`SessionStore.mutateHistory`). */
1428
- interface SessionHistory {
1429
- /** The session's turns, in order. */
1430
- turns: SessionTurn[];
1431
- /** The session's runs, in order. */
1432
- runs: SessionRun[];
1433
- }
1434
- /** Persisted form of a session: identity, turns, runs and metadata. */
1435
- interface SessionData {
1436
- /** Session id. */
1437
- id: string;
1438
- /** Label of the agent profile that owns the session. */
1439
- agentId?: string;
1540
+ /**
1541
+ * Programmatic catalog. Both members are optional and both fall through on
1542
+ * `undefined`, which is what keeps overrides scoped to the providers you
1543
+ * actually own.
1544
+ */
1545
+ interface ModelCatalogSource {
1440
1546
  /**
1441
- * Absolute path of the project this session belongs to — typically
1442
- * the git root resolved from `cwd` at creation time, falling back to
1443
- * `cwd` itself when not in a git repo. Set ONCE on creation and never
1444
- * mutated thereafter (the session "belongs" to that project forever).
1445
- *
1446
- * Used by the TUI's sessions list to filter rows by current project,
1447
- * so the user only sees conversations relevant to where they are
1448
- * working — without needing one `.{prefix}/` directory per project.
1547
+ * Resolve one model. Return `undefined` to fall through to the bundled
1548
+ * entry for that `(provider, modelId)`.
1549
+ */
1550
+ get?: (provider: string, modelId: string) => ModelCatalogEntry | undefined;
1551
+ /**
1552
+ * Enumerate a provider's models (model pickers, `modelsForDescriptor`).
1449
1553
  *
1450
- * `undefined` on pre-tagging legacy sessions; the chat layer treats
1451
- * those as "untagged" and hides them unless `Settings.showAllProjects`
1452
- * is on.
1554
+ * - `undefined` → use the bundled list for that provider (the default).
1555
+ * - `[…]` → you own that provider's list; bundled entries are not
1556
+ * consulted, so this both adds and hides.
1557
+ * - `[]` → you own it and it has no models (hides the picker).
1453
1558
  */
1454
- projectRoot?: string;
1455
- /** Turn history, oldest first. */
1456
- turns: SessionTurn[];
1457
- /** Records of the runs in this session. */
1458
- runs: SessionRun[];
1459
- /** Session state. A persisted `running` status is stale after a restart and is shown as `idle` on load. */
1460
- status: 'idle' | 'running' | 'completed' | 'error';
1461
- /** Free-form metadata, such as the title, model and extension state. */
1462
- metadata: Record<string, unknown>;
1463
- /** Creation time as epoch milliseconds. */
1464
- createdAt: number;
1465
- /** Last update time as epoch milliseconds. */
1466
- updatedAt: number;
1559
+ list?: (provider: string) => readonly ModelCatalogEntry[] | undefined;
1467
1560
  }
1468
1561
  /**
1469
- * Compact per-session summary returned by {@link SessionStore.listMeta}.
1470
- * Raw facts only — presentation (title derivation, fallback strings)
1471
- * stays in the chat layer (`listSessionMeta` / `deriveSessionTitle`).
1562
+ * A catalog: either a {@link ModelCatalogSource} or the table shorthand —
1563
+ * a plain record keyed `"<provider>:<modelId>"`.
1564
+ *
1565
+ * The table form is a pure OVERLAY: entries patch or add models, and each
1566
+ * provider keeps every bundled model the table doesn't name. Hiding bundled
1567
+ * models requires the `list` function, so the easy path can't accidentally
1568
+ * blank a provider's picker.
1569
+ *
1570
+ * ```ts
1571
+ * setModelCatalog({ 'openai:gpt-5.6': { maxTokens: 128000 } })
1572
+ * ```
1472
1573
  */
1473
- interface SessionMetaRow {
1474
- /** Session id. */
1475
- id: string;
1476
- /** Header metadata (may carry a stored `title`). */
1477
- metadata: Record<string, unknown>;
1478
- /** Absent for untagged (legacy) sessions. */
1479
- projectRoot?: string;
1480
- /** Last update time as epoch milliseconds. */
1481
- updatedAt: number;
1482
- /**
1483
- * The store's change counter for this session: bumped by every write to
1484
- * it (in the write's own transaction), so it only grows, whatever
1485
- * `updatedAt` a writer stamps. Absent from stores that keep none.
1486
- */
1487
- rev?: number;
1488
- /** Number of turns. */
1489
- turnCount: number;
1490
- /** Count of `role: 'user'` turns. */
1491
- userMessageCount: number;
1492
- /** Number of run records. */
1493
- runCount: number;
1494
- /**
1495
- * First `role: 'user'` turn — the title-derivation source. Stores may
1496
- * omit it when `metadata.title` is already set (no derivation needed).
1497
- */
1498
- firstUserTurn?: SessionTurn;
1499
- /**
1500
- * Header fields consumers like the daemon's `sessions.list` need to
1501
- * build full rows without a per-session `load()`. Optional (additive
1502
- * contract extension) — callers fall back to `load()` when absent.
1503
- */
1504
- agentId?: string;
1505
- /** Creation time as epoch milliseconds. */
1506
- createdAt?: number;
1507
- /** Session state. */
1508
- status?: SessionData['status'];
1509
- /**
1510
- * Number of artifacts recorded for the session. Optional (additive):
1511
- * only stores implementing the artifact methods populate it; consumers
1512
- * treat absence as "unknown", not zero.
1513
- */
1514
- artifactCount?: number;
1515
- }
1574
+ type ModelCatalog = ModelCatalogSource | Readonly<Record<string, ModelCatalogEntry>>;
1516
1575
  /**
1517
- * Storage backend for sessions. Implement it to persist sessions somewhere else, or use a bundled store: memory, SQLite, remote or file map.
1576
+ * Install (or clear, with `null`) the process-wide catalog. Latest call wins.
1577
+ *
1578
+ * Prefer `behavior.modelCatalog` when you can: it needs no global state and
1579
+ * scopes to one agent or one run. Use this for a deployment-wide correction,
1580
+ * or when the host's model picker must see the override too.
1581
+ *
1582
+ * @param catalog - Catalog to install, or `null` to clear it.
1518
1583
  */
1519
- interface SessionStore {
1520
- /** Optional: generate a session ID server-side (e.g. a database-issued UUID). */
1521
- generateSessionId?: () => string | Promise<string>;
1522
- /**
1523
- * Optional: generate a turn ID server-side for session-managed user turns.
1524
- *
1525
- * Provider-loop assistant and tool-result turns use AgentClock.randomUUID()
1526
- * instead, so durable-execution adapters can keep those IDs replay-stable.
1527
- */
1528
- generateTurnId?: () => string | Promise<string>;
1529
- /** Load a session by ID. Returns null if not found. */
1530
- load: (sessionId: string) => Promise<SessionData | null>;
1531
- /**
1532
- * Save a session (create or update, full document). Bulk overwrite:
1533
- * turns and runs on disk are replaced by the caller's snapshot, so a
1534
- * stale snapshot silently discards anything another writer appended.
1535
- * `Session.save()` only routes here when the turn list was explicitly
1536
- * replaced (`setTurns` / `setRuns` / load-time heal); everything else
1537
- * goes through {@link saveMeta}.
1538
- */
1539
- save: (session: SessionData) => Promise<void>;
1540
- /**
1541
- * Optional: persist header fields only (agentId, projectRoot, status,
1542
- * metadata, timestamps) plus an UPSERT of the runs present in the
1543
- * snapshot — never deletes turns or runs. This is what metadata writes
1544
- * (title, model, todos, extension state) need.
1545
- *
1546
- * Scope of the guarantee: TURNS appended by a concurrent process survive.
1547
- * The header itself is still last-writer-wins — `status` and `agentId`
1548
- * are written wholesale from the caller's snapshot, and so is `metadata`
1549
- * unless `options.metaKeys` names the changed keys (`Session.save()`
1550
- * always does; stores merge them with {@link mergeSessionMetadata}), and every run in the snapshot is upserted as-is (a reader
1551
- * that loaded through `loadSession` carries the in-memory stale-running
1552
- * demotion, so it can write `idle` / `aborted` over a live owner's marker
1553
- * until the owner's next write). Readers that only need one key should
1554
- * prefer a keyed patch (the host's `patchSessionMeta`) over `save()`.
1555
- * Stores that omit it fall back to `save`, keeping the historical bulk
1556
- * semantics.
1557
- */
1558
- saveMeta?: (session: SessionData, options?: SaveMetaOptions) => Promise<void>;
1559
- /** Delete a session. */
1560
- delete: (sessionId: string) => Promise<void>;
1561
- /**
1562
- * List session IDs, optionally filtered. `projectRoot` restricts to
1563
- * sessions whose `SessionData.projectRoot` matches exactly — untagged
1564
- * (legacy) sessions are NOT returned under that filter; pass `null`
1565
- * explicitly to ask for untagged ones, or omit the field to ignore
1566
- * the axis entirely. `agentId` filters by recorded agent; the two
1567
- * conditions AND together when both are set.
1568
- */
1569
- list: (filter?: {
1570
- agentId?: string;
1571
- limit?: number;
1572
- projectRoot?: string | null;
1573
- }) => Promise<string[]>;
1584
+ declare function setModelCatalog(catalog: ModelCatalog | null): void;
1585
+ /** The process-wide catalog, normalized to source form. */
1586
+ declare function getModelCatalog(): ModelCatalogSource | undefined;
1587
+ //#endregion
1588
+ //#region src/thinking-levels.d.ts
1589
+ /**
1590
+ * Thinking / extended-reasoning configuration. Dependency-free, so the
1591
+ * browser-safe surfaces (`zidane/chat/pure`) can validate a stored effort.
1592
+ *
1593
+ * - `'off'` — no thinking.
1594
+ * - `'minimal' | 'low' | 'medium' | 'high' | 'xhigh' | 'max'` — explicit
1595
+ * effort tier. Maps to provider-specific reasoning controls (Anthropic
1596
+ * `output_config.effort`; OpenAI-compatible providers clamp to their
1597
+ * supported tiers).
1598
+ * - `'adaptive'` — let the model decide per-turn whether and how much to think.
1599
+ * Anthropic-only (`thinking.type='adaptive'`). Other providers fall back to
1600
+ * no reasoning when this value is supplied.
1601
+ */
1602
+ declare const THINKING_LEVELS: readonly ["off", "minimal", "low", "medium", "high", "xhigh", "max", "adaptive"];
1603
+ /** One of the {@link THINKING_LEVELS} strings: how much the model reasons before it answers. */
1604
+ type ThinkingLevel = (typeof THINKING_LEVELS)[number];
1605
+ /**
1606
+ * Type guard for canonical `ThinkingLevel` strings (e.g. `metadata.effort` read off a persisted session).
1607
+ *
1608
+ * @param value - Any value, usually a string read from storage or settings.
1609
+ */
1610
+ declare function isThinkingLevel(value: unknown): value is ThinkingLevel;
1611
+ //#endregion
1612
+ //#region src/mcp/transport.d.ts
1613
+ /**
1614
+ * Line-splitting core shared by the two stderr pumps: the Node-stream one
1615
+ * below (host stdio children) and the async-iterable one in
1616
+ * `./context-transport.ts` (children living in an execution context).
1617
+ * Same buffering, same overlong-line cap, same fire-and-forget `mcp:warn`.
1618
+ * @param serverName - Server name reported in each `mcp:warn` payload.
1619
+ * @param hooks - Agent hooks to fire `mcp:warn` on. Lines are dropped when `undefined`.
1620
+ */
1621
+ declare function createStderrLineEmitter(serverName: string, hooks: Hookable<AgentHooks> | undefined): {
1622
+ push: (text: string) => void;
1623
+ flush: () => void;
1624
+ };
1625
+ /**
1626
+ * Reads a stdio child's stderr to the end and fires `mcp:warn` for each non-empty line. Does nothing when the transport has no stderr stream.
1627
+ *
1628
+ * @param transport - Transport that may expose a `stderr` stream.
1629
+ * @param serverName - Server name reported in each `mcp:warn` payload.
1630
+ * @param hooks - Agent hooks to fire `mcp:warn` on.
1631
+ */
1632
+ declare function attachStderrWarnPump(transport: {
1633
+ stderr?: {
1634
+ on: (event: string, listener: (...args: unknown[]) => void) => unknown;
1635
+ } | null;
1636
+ }, serverName: string, hooks: Hookable<AgentHooks> | undefined): void;
1637
+ /**
1638
+ * The execution context + live handle a `scope: 'context'` stdio server is
1639
+ * spawned into. Supplied by the agent once its handle exists; absent for
1640
+ * host-only setups, which is why every field is required here but the
1641
+ * binding itself is optional at the call site.
1642
+ */
1643
+ interface McpExecutionBinding {
1644
+ /** Execution context that hosts the server process. */
1645
+ context: ExecutionContext;
1574
1646
  /**
1575
- * Optional: list session summaries without materializing full sessions.
1576
- *
1577
- * The generic fallback (`listSessionMeta` in `zidane/chat`) is `list()`
1578
- * + `load()` per id — O(every turn in the store) because each `load`
1579
- * parses the full turn history just to count rows and derive a title.
1580
- * Stores that can answer from an index (SQL aggregates, a denormalized
1581
- * header) should implement this; the sqlite store turns a multi-hundred-
1582
- * ms TUI boot cost into a single query.
1647
+ * Resolve the execution handle, invoked ONLY when a `scope: 'context'`
1648
+ * stdio server actually builds its transport.
1583
1649
  *
1584
- * Same filter contract and ordering (most recently updated first) as
1585
- * {@link list}.
1586
- */
1587
- listMeta?: (filter?: {
1588
- agentId?: string;
1589
- limit?: number;
1590
- projectRoot?: string | null;
1591
- }) => Promise<SessionMetaRow[]>;
1592
- /**
1593
- * Optional: one session's header row WITHOUT materializing turns.
1594
- * Hot-path reads (the cross-process run guard checks `status` +
1595
- * `updatedAt` on every prompt send) must not pay a multi-MB turn parse
1596
- * on long sessions. Callers fall back to `load()` when absent.
1597
- */
1598
- getMeta?: (sessionId: string) => Promise<SessionMetaRow | null>;
1599
- /** Append new turns to a session (incremental, avoids full re-save). */
1600
- appendTurns: (sessionId: string, turns: SessionTurn[]) => Promise<void>;
1601
- /** Return a slice of turns for a session. */
1602
- getTurns: (sessionId: string, from?: number, limit?: number) => Promise<SessionTurn[]>;
1603
- /**
1604
- * Optional: rewrite a session's history as ONE atomic read-modify-write,
1605
- * so turns appended between the read and the write can't be erased (a
1606
- * `load()` + `save()` pair can). `mutate` gets the current turns and
1607
- * runs and returns the next ones, or `null` to leave them untouched; a
1608
- * throw inside it aborts without writing. Runs are written only when it
1609
- * returns a different `runs` array. History edits (delete / edit a turn,
1610
- * rewind) use it when present and fall back to `load()` + `save()`.
1611
- */
1612
- mutateHistory?: (sessionId: string, mutate: (history: SessionHistory) => SessionHistory | null) => Promise<'ok' | 'no-session' | 'unchanged'>;
1613
- /**
1614
- * Optional: the turns-only form of {@link SessionStore.mutateHistory}.
1615
- * When `mutateHistory` is absent, edits that leave the runs alone (delete
1616
- * or edit a turn) use it; a rewind falls back to `load()` + `save()`.
1617
- * @deprecated Implement `mutateHistory` instead.
1650
+ * Lazy on purpose. An eagerly-resolved handle would make merely *having* a
1651
+ * context-scoped server in the config force a sandbox spawn — including
1652
+ * for sub-agents, which inherit `mcpServers` but reuse the parent's live
1653
+ * connection through `nonOwningMcpConnector` and never touch this binding.
1654
+ * That would cold-boot a fresh sandbox per `spawn()` for nothing. Deferring
1655
+ * also means the agent needs no ordering special case: the handle is
1656
+ * created at the moment of first use, which is necessarily before the
1657
+ * `execStream` call that needs it.
1618
1658
  */
1619
- mutateTurns?: (sessionId: string, mutate: (turns: SessionTurn[]) => SessionTurn[] | null) => Promise<'ok' | 'no-session' | 'unchanged'>;
1620
- /**
1621
- * Persist a run record (called at run start with `status: 'running'`, and
1622
- * after completeRun / abortRun / errorRun).
1623
- *
1624
- * **Upsert semantics required.** The agent's run lifecycle calls
1625
- * `session.startRun()` to register a new run in IN-MEMORY state and
1626
- * then `updateRun()`. The store doesn't see the run before the first
1627
- * `updateRun()` — `appendTurns` persists turns but not runs. An
1628
- * update-only implementation would silently drop every newly-created
1629
- * run record, leaving
1630
- * the on-disk `runs[]` missing entries that the persisted turns
1631
- * reference (which `eventsFromTurns` then mis-classifies via
1632
- * `ancestryOf` → broken depth, broken `child-N` labels, broken
1633
- * `userPrompts` history).
1634
- *
1635
- * Implementations MUST insert when the id doesn't exist and update
1636
- * when it does. The bundled `sqlite` / `memory` / `file-map` stores
1637
- * all follow this contract; remote stores using HTTP PUT get upsert
1638
- * for free via REST semantics.
1639
- */
1640
- updateRun: (sessionId: string, run: SessionRun) => Promise<void>;
1641
- /**
1642
- * Update the top-level status of a session.
1643
- *
1644
- * `preserveUpdatedAt` (default false) writes the status WITHOUT
1645
- * touching `updatedAt` — for pure-read heals (`loadSession`'s stale
1646
- * `'running'` demotion) that must not reorder recency-sorted session
1647
- * lists. Best-effort contract: stores that don't manage `updatedAt`
1648
- * themselves (memory, file-map, remote) may ignore the option; the
1649
- * sqlite store honors it.
1650
- */
1651
- updateStatus: (sessionId: string, status: SessionData['status'], options?: {
1652
- preserveUpdatedAt?: boolean;
1653
- }) => Promise<void>;
1654
- /**
1655
- * Optional: record an artifact (see `./artifacts.ts`). Upsert on
1656
- * `(sessionId, kind, uri)` — an existing row keeps its `id` / `runId` /
1657
- * `turnId` / `createdAt` and refreshes `label` / `meta` / `updatedAt`
1658
- * (`mergeArtifact`). Resolves to the canonical stored row. Unknown
1659
- * session ids are a no-op returning `null` (no ghost headers; same
1660
- * posture as `updateRun`). Implementations enforce
1661
- * `ARTIFACTS_PER_SESSION_CAP` via `selectArtifactEvictions`.
1662
- *
1663
- * Every artifact method is optional: stores that don't implement them
1664
- * (file-map, remote, third-party) keep working — `Session.addArtifact`
1665
- * degrades to a no-op and listings come back empty.
1666
- */
1667
- upsertArtifact?: (artifact: SessionArtifact) => Promise<SessionArtifact | null>;
1668
- /**
1669
- * Optional: list artifacts, newest `updatedAt` first. `filter.sessionId`
1670
- * scopes to one session; `filter.projectRoot` follows the tri-state
1671
- * contract of {@link list}; omit both for every artifact in the store.
1672
- */
1673
- listArtifacts?: (filter?: ArtifactFilter) => Promise<SessionArtifact[]>;
1674
- /** Optional: remove one artifact. Unknown ids are a no-op. */
1675
- deleteArtifact?: (sessionId: string, artifactId: string) => Promise<void>;
1676
- /**
1677
- * Optional: release backend resources (e.g. close the SQLite handle).
1678
- * Hosts should call this on teardown when present; stores backed by
1679
- * memory or remote HTTP have nothing to release and may omit it.
1680
- */
1681
- close?: () => void;
1659
+ getHandle: () => Promise<ExecutionHandle>;
1682
1660
  }
1661
+ //#endregion
1662
+ //#region src/mcp/origin-pinned-fetch.d.ts
1683
1663
  /**
1684
- * A live session: the turn history and run records of one conversation, with an optional store that persists them.
1664
+ * The transport-reachability rule for a remote MCP endpoint: HTTPS anywhere,
1665
+ * plaintext HTTP only when it stays on the machine, nothing else.
1666
+ *
1667
+ * THE single encoding of that policy. It's enforced at two points on opposite
1668
+ * sides of the plugin boundary — once when validating a plugin's `mcp.json`
1669
+ * (`plugins/mcp.ts`), and again per redirect hop inside
1670
+ * {@link originPinnedFetch} — and those two must never disagree. If they did,
1671
+ * a URL the loader refused could still be reached by redirect, which is the
1672
+ * exact hole the pinning exists to close. Relaxing the rule (private ranges,
1673
+ * `*.localhost`, …) is then a one-line change that both sites inherit.
1674
+ *
1675
+ * Scheme and host only. Authoring rules that apply to a CONFIGURED url but
1676
+ * have no meaning for a redirect target — no userinfo, no fragment — stay with
1677
+ * the loader.
1678
+ * @param url - Endpoint to check.
1685
1679
  */
1686
- interface Session {
1687
- /** Session ID */
1688
- readonly id: string;
1689
- /** Agent ID (optional label) */
1690
- readonly agentId?: string;
1691
- /**
1692
- * Re-label the session's agent profile (in memory; persisted by the
1693
- * next `save()`). Sessions remember their profile — pickers restore it
1694
- * on activation and other windows converge on it via `sessions.touch`.
1695
- */
1696
- setAgentId: (agentId: string) => void;
1697
- /**
1698
- * Project this session was created under — see {@link SessionData.projectRoot}.
1699
- * Set once on creation; surfaces here for read-only inspection.
1700
- */
1701
- readonly projectRoot?: string;
1702
- /**
1703
- * Raw persisted turn history — kept pristine for fidelity (the model's
1704
- * reasoning chain stays intact across reloads).
1705
- *
1706
- * **DO NOT pass this directly to a provider request.** Mid-pair
1707
- * persistence (interrupted runs, partial-result writes, compaction
1708
- * boundaries) leaves orphan `tool_use` / `tool_result` blocks here that
1709
- * every provider 400s on (`tool_result must be preceded by a tool_call
1710
- * with the same toolCallId`). The agent's own loop repairs these
1711
- * just-in-time at wire-send time and never writes the repair back to
1712
- * `turns`.
1713
- *
1714
- * For provider requests built outside `agent.run()`, use
1715
- * {@link Session.toMessages} — it applies the same defensive pairing
1716
- * repair and resolves to a guaranteed-safe `SessionMessage[]`.
1717
- */
1718
- readonly turns: SessionTurn[];
1719
- /**
1720
- * True when this session has no turns yet.
1721
- *
1722
- * Use this as a first-prompt signal when setting up a run — e.g. writing initial
1723
- * configuration only on fresh sessions. Equivalent to `turns.length === 0`.
1724
- */
1725
- readonly isEmpty: boolean;
1726
- /** Top-level session status */
1727
- readonly status: SessionData['status'];
1728
- /** All runs in this session */
1729
- readonly runs: SessionRun[];
1730
- /** Arbitrary metadata */
1731
- readonly metadata: Record<string, unknown>;
1732
- /** Creation time as epoch milliseconds. */
1733
- readonly createdAt: number;
1734
- /** Last update time as epoch milliseconds. */
1735
- readonly updatedAt: number;
1736
- /**
1737
- * Start tracking a new run. `extras.parentRunId` + `extras.depth` are
1738
- * populated by the spawn tool when a child agent shares its parent's
1739
- * session; regular top-level `agent.run()` calls omit them.
1740
- */
1741
- startRun: (runId: string, prompt?: string, extras?: {
1742
- parentRunId?: string;
1743
- depth?: number;
1744
- resumedFromRunId?: string;
1745
- label?: string;
1746
- parentCallId?: string;
1747
- }) => void;
1748
- /** Mark a run as completed */
1749
- completeRun: (runId: string, stats: {
1750
- turns: number;
1751
- tokensIn: number;
1752
- tokensOut: number;
1753
- turnUsage?: TurnUsage[];
1754
- cost?: number;
1755
- }) => void;
1756
- /**
1757
- * Mark a run as aborted. Optional `stats` lets the agent backfill the run's token totals when
1758
- * the abort happened *after* the loop accumulated meaningful usage —
1759
- * common when the user presses esc mid-streaming. Without it, the run
1760
- * record reads `0 in / 0 out` on reload regardless of how much was
1761
- * spent before the abort. Same shape as `completeRun`'s stats so the
1762
- * persisted `totalUsage` aggregate stays consistent across paths.
1763
- */
1764
- abortRun: (runId: string, stats?: {
1765
- turns: number;
1766
- tokensIn: number;
1767
- tokensOut: number;
1768
- turnUsage?: TurnUsage[];
1769
- cost?: number;
1770
- }) => void;
1771
- /** Mark a run as errored. Optional `stats` — same rationale as `abortRun.stats`. */
1772
- errorRun: (runId: string, error: string, stats?: {
1773
- turns: number;
1774
- tokensIn: number;
1775
- tokensOut: number;
1776
- turnUsage?: TurnUsage[];
1777
- cost?: number;
1778
- }, detail?: RunErrorDetail) => void;
1779
- /** Append turns to in-memory history AND persist via store.appendTurns (if store present) */
1780
- appendTurns: (turns: SessionTurn[]) => Promise<void>;
1781
- /** Replace all turns in-memory (does not persist — use save() for that) */
1782
- setTurns: (turns: SessionTurn[]) => void;
1783
- /**
1784
- * Replace all runs in-memory (does not persist — use save() for that).
1785
- * Mirrors {@link setTurns} for the fork / restore case: callers that
1786
- * bootstrap a session from an externally-derived snapshot (e.g.
1787
- * `onForkTurn` copying parent runs into a child session) need this so
1788
- * the cloned runs land in `data.runs` before the first `save()`.
1789
- * Production agent runs continue to mutate runs via `startRun` /
1790
- * `completeRun` / `updateRun`; this is the bulk-replace escape hatch.
1791
- */
1792
- setRuns: (runs: SessionRun[]) => void;
1793
- /** Update the session status in memory AND via store.updateStatus (if store present) */
1794
- updateStatus: (status: SessionData['status']) => Promise<void>;
1795
- /** Persist an updated run record via store.updateRun (if store present) */
1796
- updateRun: (run: SessionRun) => Promise<void>;
1797
- /** Generate a session-managed turn ID using store.generateTurnId if available, else crypto.randomUUID() */
1798
- generateTurnId: () => string | Promise<string>;
1799
- /** Set metadata key. `touch: false` keeps `updatedAt` (a rename or a favorite is not activity). */
1800
- setMeta: (key: string, value: unknown, options?: {
1801
- touch?: boolean;
1802
- }) => void;
1803
- /**
1804
- * Record an artifact this session produced. Fills `id`, timestamps and
1805
- * defaults `projectRoot` to the session's own; `origin` ties it to the
1806
- * producing run/turn for transcript anchoring. Resolves to the stored
1807
- * row, or `undefined` when there is no store or the store doesn't
1808
- * implement artifacts (never throws for that case — emission is
1809
- * best-effort by contract).
1810
- */
1811
- addArtifact: (input: SessionArtifactInput, origin?: {
1812
- runId?: string;
1813
- turnId?: string;
1814
- }) => Promise<SessionArtifact | undefined>;
1815
- /** This session's artifacts, newest first. Empty when unsupported. */
1816
- listArtifacts: (filter?: Pick<ArtifactFilter, 'kind' | 'since' | 'limit'>) => Promise<SessionArtifact[]>;
1817
- /**
1818
- * Persist the session to the store. When the store implements `saveMeta`,
1819
- * this writes the header, the changed metadata keys and the runs, and leaves
1820
- * turns alone, unless `setTurns` or `setRuns` replaced them. In every other
1821
- * case it overwrites the whole document through `store.save`. Throws when
1822
- * the session has no store.
1823
- */
1824
- save: () => Promise<void>;
1680
+ declare function isAllowedRemoteUrl(url: URL): boolean;
1681
+ /**
1682
+ * The fetch shape this wrapper supports — deliberately narrower than
1683
+ * `typeof fetch`, matching the MCP SDK's `FetchLike`.
1684
+ *
1685
+ * A `Request` input is NOT accepted: the wrapper rebuilds each hop from
1686
+ * `init`, so it would silently drop a Request's method, headers and body and
1687
+ * issue a bare credential-less GET. Narrowing the type makes that shape
1688
+ * unrepresentable rather than a quiet failure on a security-relevant helper.
1689
+ * Both SDK transports only ever pass a URL plus init.
1690
+ */
1691
+ type PinnedFetch = (url: string | URL, init?: RequestInit) => Promise<Response>;
1692
+ /**
1693
+ * Wrap `baseFetch` so `headerNames` are dropped on any hop that leaves the
1694
+ * origin of `configuredUrl`, and so a redirect cannot downgrade the session
1695
+ * to cleartext.
1696
+ *
1697
+ * `authorization` is ALWAYS protected, whether or not the caller listed it.
1698
+ * The MCP SDK's OAuth provider injects that header per request rather than
1699
+ * through `McpServerConfig.headers` — `bootstrapServer` attaches a provider to
1700
+ * a flagless server whenever stored tokens exist — so a strip list derived
1701
+ * only from the configured header names would leave the bearer token exposed
1702
+ * on exactly the servers that have one.
1703
+ * @param configuredUrl - Configured server URL. Its origin is the pinned origin.
1704
+ * @param headerNames - Configured header names to drop when a redirect leaves the pinned origin.
1705
+ * @param baseFetch - Fetch implementation to wrap. Default: the global `fetch`.
1706
+ */
1707
+ declare function originPinnedFetch(configuredUrl: string, headerNames: readonly string[], baseFetch?: PinnedFetch): PinnedFetch;
1708
+ //#endregion
1709
+ //#region src/mcp/server-config.d.ts
1710
+ /**
1711
+ * The config a transport is actually built from.
1712
+ *
1713
+ * `${VAR}` placeholders resolve HERE, not at normalize time — see
1714
+ * {@link expandMcpConfigEnv} for why (config writers round-trip normalized
1715
+ * configs to disk; expanded secrets must never ride along).
1716
+ *
1717
+ * A `preExpanded` config skips the pass entirely. The Agent Plugins loader
1718
+ * has already substituted the only two placeholders that spec permits, in
1719
+ * only the three fields it permits, so a second pass would both widen the
1720
+ * scope (into `command` / `url` / `headers`) and let an ambient
1721
+ * `PLUGIN_ROOT` env var reach text the spec says stays literal. See
1722
+ * {@link McpServerConfig.preExpanded}.
1723
+ * @param config - Normalized server config.
1724
+ */
1725
+ declare function resolveTransportConfig(config: McpServerConfig): McpServerConfig;
1726
+ /**
1727
+ * Expand environment-variable placeholders in one config string. The
1728
+ * `:-default` form follows shell semantics — the default substitutes when
1729
+ * the variable is unset OR EMPTY (that's what `:-` means in every shell,
1730
+ * and what users pasting the form expect; empty-but-set without a default
1731
+ * still expands to the empty string, as `${VAR}` does in a shell). An
1732
+ * unset variable without a default is left VERBATIM (matching Claude
1733
+ * Code) — a literal `${…}` failing loudly at the server beats an empty
1734
+ * token failing mysteriously — and a debug-gated warning names the
1735
+ * missing variable.
1736
+ * @param value - String that may contain `${VAR}`, `${VAR:-default}` or `${env:VAR}`.
1737
+ * @param env - Variables to resolve against. Default: `process.env`.
1738
+ */
1739
+ declare function expandEnvPlaceholders(value: string, env?: Record<string, string | undefined>): string;
1740
+ /**
1741
+ * Expanded COPY of a server config for runtime use — `${VAR}` placeholders
1742
+ * resolved across every string field that can carry secrets or
1743
+ * machine-specific paths (command, args, env/header values, url, cwd).
1744
+ *
1745
+ * Deliberately NOT part of `normalizeMcpServers`: normalized configs are
1746
+ * round-tripped back to disk by config writers (e.g. the Claude import
1747
+ * copies parsed entries into zidane-owned `mcps.json`), and expanding
1748
+ * there would MATERIALIZE resolved tokens into files. Expansion happens
1749
+ * only at the transport boundary ({@link createTransport}, the login
1750
+ * flow's mirror) — secrets exist in the connecting process's memory and
1751
+ * nowhere else.
1752
+ * @param config - Server config to expand.
1753
+ * @param env - Variables to resolve against. Default: `process.env`.
1754
+ */
1755
+ declare function expandMcpConfigEnv(config: McpServerConfig, env?: Record<string, string | undefined>): McpServerConfig;
1756
+ /**
1757
+ * A config from a source that must never read this process's environment
1758
+ * (a machine's project file, `docs/MACHINES.md`): every `${VAR}` placeholder
1759
+ * resolved NOW to its `:-default`, else to the empty string, so the
1760
+ * transport's own expansion has nothing of this process's secrets to put
1761
+ * into a command, an env value, a URL or a header.
1762
+ * @param config - Server config to strip.
1763
+ */
1764
+ declare function withoutEnvPlaceholders(config: McpServerConfig): McpServerConfig;
1765
+ /**
1766
+ * Unprivileged TCP port: the loopback listener can't bind below 1024 without root.
1767
+ * @param port - Value to check.
1768
+ */
1769
+ declare function isValidCallbackPort(port: unknown): port is number;
1770
+ /**
1771
+ * The loopback redirect a pinned `oauth.callbackPort` produces: the URL to
1772
+ * register with the provider. Pass the same `callbackPath` given to
1773
+ * `loginMcpServer`, if any.
1774
+ * @param config - Server config. Only `oauth.callbackPort` is read.
1775
+ * @param callbackPath - Path of the callback URL.
1776
+ * @returns The redirect URL, or `undefined` when no callback port is pinned.
1777
+ */
1778
+ declare function pinnedMcpRedirectUri(config: Pick<McpServerConfig, 'oauth'>, callbackPath?: string): string | undefined;
1779
+ /**
1780
+ * Normalize MCP server configs from any common shape to `McpServerConfig[]`.
1781
+ *
1782
+ * Accepts:
1783
+ * - `McpServerConfig[]` — zidane native (pass-through).
1784
+ * - `McpServerConfig` — a single config object (wrapped to a 1-element array).
1785
+ * - `Record<string, RawShape>` — name-keyed map (common in host-SDK configs), where the key is the server name.
1786
+ * - Mixed shapes with `type` vs `transport`, `httpUrl`/`sseUrl` vs `url`.
1787
+ *
1788
+ * Returns `[]` when `input` is nullish. Throws a descriptive error when the transport
1789
+ * cannot be inferred from a given entry, or when the input shape is unsupported.
1790
+ * @param input - Server configs in any of the accepted shapes, or nullish.
1791
+ */
1792
+ declare function normalizeMcpServers(input: unknown): McpServerConfig[];
1793
+ //#endregion
1794
+ //#region src/mcp/tool-meta.d.ts
1795
+ /**
1796
+ * Non-owning view of a live MCP connection: the SAME tools and
1797
+ * instructions, but a no-op `close`. Handed to consumers that must never
1798
+ * tear down transports they don't own — the loop's per-call
1799
+ * `ToolContext.mcpConnection` and child agents spawned off the parent's
1800
+ * connection — because only the owning agent's destroy path may close the
1801
+ * real thing, and a doc comment alone is too weak a guard. Single shared
1802
+ * builder so the call sites can't drift when this shape grows a field.
1803
+ * @param connection - Connection to view. Only its `tools` and `instructions` are read.
1804
+ */
1805
+ declare function nonOwningMcpView(connection: Pick<McpConnection, 'tools' | 'instructions'>): McpConnection;
1806
+ /**
1807
+ * Recover a discovered tool's `{ server, toolName }` from its namespaced name
1808
+ * (`mcp_<server>_<tool>`). Both server and tool names can contain underscores,
1809
+ * so this matches against the known server list by longest server-name prefix
1810
+ * rather than splitting blindly. Tools that match no configured server (custom
1811
+ * connectors with a different naming scheme) fall back to
1812
+ * `{ server: '', toolName: <namespacedName> }`.
1813
+ * @param namespacedName - Tool name of the form `mcp_<server>_<tool>`.
1814
+ * @param servers - Configured servers to match the prefix against.
1815
+ */
1816
+ declare function deriveMcpToolMeta(namespacedName: string, servers: readonly McpServerConfig[]): McpToolMeta;
1817
+ /**
1818
+ * Apply an {@link McpToolWrap} to every entry of a discovered-tool map,
1819
+ * resolving each tool's {@link McpToolMeta} from `servers`. Returns a fresh
1820
+ * map; the input is untouched. Used by the agent to apply the
1821
+ * `AgentOptions.mcpToolWrap` hook to discovered tools.
1822
+ * @param tools - Discovered tools keyed by namespaced name.
1823
+ * @param wrap - Wrapper applied to each tool.
1824
+ * @param servers - Configured servers used to resolve each tool's metadata.
1825
+ */
1826
+ declare function wrapDiscoveredMcpTools(tools: Record<string, ToolDef>, wrap: McpToolWrap, servers: readonly McpServerConfig[]): Record<string, ToolDef>;
1827
+ //#endregion
1828
+ //#region src/mcp/tool-result.d.ts
1829
+ /**
1830
+ * Lossy flattener — converts MCP `CallToolResult.content` blocks to a single
1831
+ * string. Text blocks are extracted; non-text blocks are JSON-stringified.
1832
+ *
1833
+ * Use this only at UI / log boundaries that require a string. The agent
1834
+ * loop itself routes through {@link normalizeMcpBlocks} so image blocks
1835
+ * survive into provider-native tool_result content (Anthropic blocks,
1836
+ * OpenAI companion-user-message).
1837
+ * @param content - `CallToolResult.content` from an MCP tool call. Anything other than an array gives an empty string.
1838
+ */
1839
+ declare function resultToString(content: unknown): string;
1840
+ /**
1841
+ * Normalize MCP `CallToolResult.content` to zidane's {@link ToolResultContent[]} shape.
1842
+ *
1843
+ * Handles the MCP content block types:
1844
+ * - `text` → preserved as `{type:'text', text}`
1845
+ * - `image` → preserved as `{type:'image', mediaType, data}` (MCP uses `mimeType`)
1846
+ * - `audio` → `{type:'audio', mediaType, data}`; mediaType reconciled/sniffed when
1847
+ * the declared `mimeType` is missing or not an `audio/*` type
1848
+ * - `video` → `{type:'video', mediaType, data}` (non-standard, by analogy)
1849
+ * - `resource` with embedded text → flattened to a text block
1850
+ * - `resource` with embedded blob → routed to image/audio/video by sniffing bytes
1851
+ * first, with declared `mimeType` as a fallback when bytes are unidentifiable
1852
+ * (it's OPTIONAL on EmbeddedResource per the MCP spec, and often imprecise)
1853
+ * - Any unrecognized block → JSON-stringified fallback text block (lossy but safe)
1854
+ *
1855
+ * Returns `null` when the input is not an array — callers should fall back to an empty
1856
+ * result in that case.
1857
+ * @param content - `CallToolResult.content` from an MCP tool call.
1858
+ */
1859
+ declare function normalizeMcpBlocks(content: unknown): ToolResultContent[] | null;
1860
+ //#endregion
1861
+ //#region src/mcp/index.d.ts
1862
+ /** A live connection to a set of MCP servers: the discovered tools and a way to close every transport. */
1863
+ interface McpConnection {
1864
+ /** Discovered tools keyed by namespaced name, `mcp_<server>_<tool>`. */
1865
+ tools: Record<string, ToolDef>;
1825
1866
  /**
1826
- * Project the session's persisted turns into wire-ready messages safe to
1827
- * hand to any provider.
1867
+ * Per-server `instructions` payload from the MCP `initialize` handshake,
1868
+ * keyed by server name. Each server may return free-form guidance the
1869
+ * model is meant to read alongside the tool catalog — typical content
1870
+ * is "the database is already provisioned, use `apply_migration`
1871
+ * directly" or "always wrap SELECTs in a transaction". The agent
1872
+ * renders these into a system-prompt section when
1873
+ * `behavior.surfaceMcpInstructions` is on (default).
1828
1874
  *
1829
- * The canonical answer to "I need to send these turns to Anthropic /
1830
- * OpenAI from outside `agent.run()`" (sub-agent classifier, side-channel
1831
- * summarizer, replay worker, …). Runs the same defensive pairing repair
1832
- * the agent loop applies just-in-time at wire-send time
1833
- * ({@link ensureToolResultPairing}), so orphan `tool_use` blocks and
1834
- * dangling `tool_result`s never reach the provider as the 400
1835
- * "tool_result must be preceded by a tool_call with the same toolCallId".
1875
+ * Servers that omit the field, return an empty string, or fail to
1876
+ * connect contribute no entry. Lazy-connected servers contribute an
1877
+ * entry only once their first connect resolves — until then the model
1878
+ * never sees their instructions, matching the schema-loading semantics
1879
+ * of `lazyConnect`.
1836
1880
  *
1837
- * Pass `provider` to also enforce the user-tail invariant
1838
- * ({@link ensureEndsWithUserMessage}) — required for opus 4.7 / o-series
1839
- * style models that reject assistant-prefill.
1881
+ * Map (not Record) so insertion order matches server config order and
1882
+ * the rendered section is byte-stable for the cache breakpoint.
1840
1883
  *
1841
- * Pure + idempotent. Resolves content refs only in the returned messages
1842
- * and does NOT mutate `session.turns`. **Do not write the result back via
1843
- * `setTurns` / `appendTurns`** — synthetic placeholders or resolved
1844
- * payloads will contaminate persisted history.
1845
- */
1846
- toMessages: (options?: ToWireMessagesOptions) => Promise<SessionMessage[]>;
1847
- /** Serialize to SessionData */
1848
- toJSON: () => SessionData;
1849
- /**
1850
- * The backing store, when one was provided. Exposed so hosts can call
1851
- * its optional `close()` on teardown (e.g. release the SQLite handle).
1884
+ * Optional so custom `mcpConnector` implementations may omit it; the
1885
+ * framework's own `connectMcpServers` always returns a Map (possibly
1886
+ * empty).
1852
1887
  */
1853
- readonly store?: SessionStore;
1888
+ instructions?: Map<string, string>;
1889
+ /** Closes every server connection. Servers that fail to close in time are force-stopped. */
1890
+ close: () => Promise<void>;
1854
1891
  }
1855
- /** Options for {@link createSession}. */
1856
- interface CreateSessionOptions {
1857
- /** Session ID. If omitted and store provides generateSessionId, that is used. */
1858
- id?: string;
1859
- /** Agent ID label */
1860
- agentId?: string;
1861
- /**
1862
- * Project tag — see {@link SessionData.projectRoot}. Stamped once on
1863
- * creation; ignored when `_data` is set (restoring an existing
1864
- * session preserves whatever was already persisted there). The chat
1865
- * layer's session factory stamps `projectRootOf(cwd)` so sessions
1866
- * started from the same repo — any subdir, any linked worktree — share
1867
- * one tag.
1868
- */
1869
- projectRoot?: string;
1870
- /** Initial metadata */
1871
- metadata?: Record<string, unknown>;
1872
- /** Storage backend (optional, enables save/load) */
1873
- store?: SessionStore;
1892
+ /**
1893
+ * Optional knobs threaded into per-server bootstrap. Reserved for runtime
1894
+ * concerns the agent shell injects (credential storage, OAuth providers);
1895
+ * the `McpServerConfig` shape stays pure data.
1896
+ */
1897
+ interface ConnectMcpServersOptions {
1874
1898
  /**
1875
- * Observability hook for the load-time pairing heal: fired once per block
1876
- * or turn `dropInvalidToolPairings` deleted while restoring `_data`.
1877
- * Deletions are permanent once the session is saved, so hosts that alert
1878
- * on wire-time `pairing:repair` events should wire this to the same sink.
1879
- * Only fires on the `_data` restore path; fresh sessions never heal.
1899
+ * Execution context binding for servers declaring `scope: 'context'`.
1900
+ * Safe to pass unconditionally: the binding is lazy, and its
1901
+ * `getHandle()` is invoked only when a context-scoped stdio server
1902
+ * actually builds its transport — host-only configs never touch it, so
1903
+ * no spawn cost is paid for merely supplying it. Omitting it simply
1904
+ * makes any `scope: 'context'` server fail bootstrap with a pointed
1905
+ * error.
1880
1906
  */
1881
- onPairingDrop?: (drop: PairingDrop) => void;
1907
+ execution?: McpExecutionBinding;
1882
1908
  /**
1883
- * @internal: restore from existing data (bypasses id/agentId/metadata
1884
- * options). The session ALIASES this object for its lifetime — every
1885
- * mutation (appendTurns, run records, updatedAt) writes through to it,
1886
- * and the load-time pairing heal may replace its `turns` array in place
1887
- * before the session is returned. Callers must not retain independent
1888
- * ownership expectations.
1909
+ * Build a non-interactive `OAuthClientProvider` for a given server. Called
1910
+ * lazily — only invoked when the bootstrap actually needs auth (explicit
1911
+ * `auth: 'oauth'` flag, or a UnauthorizedError that meets the auto-detect
1912
+ * criteria). Return `undefined` to opt this server out of OAuth even if it
1913
+ * was requested (e.g. the host doesn't have a credential store for it).
1914
+ *
1915
+ * "Non-interactive" — the provider must NOT trigger a browser flow during
1916
+ * bootstrap. Use a `redirectUri` of `undefined` so the SDK reads stored
1917
+ * tokens, refreshes on expiry, and throws `UnauthorizedError` if tokens
1918
+ * are missing or refresh fails. The host then surfaces an
1919
+ * `mcp:auth:required` event so the user can opt in to interactive login.
1889
1920
  */
1890
- _data?: SessionData;
1921
+ buildAuthProvider?: (config: McpServerConfig) => OAuthClientProvider | undefined;
1891
1922
  }
1892
1923
  /**
1893
- * Create a new session.
1894
- * Async so stores that generate IDs server-side (e.g. a database) can be supported.
1895
- * @param options - Session identity, metadata and store. See {@link CreateSessionOptions}.
1924
+ * Internal: shape received by the `_clientFactory` test-injection seam.
1925
+ * Mirrors the subset of `TolerantClientOptions` the bootstrap path forwards
1926
+ * so a mock client can opt into the same lifecycle wiring (warning sink,
1927
+ * future seams) instead of silently bypassing it.
1928
+ */
1929
+ interface McpClientFactoryOptions {
1930
+ /** See `TolerantClientOptions.onWarning`. */
1931
+ onWarning?: (message: string) => void;
1932
+ }
1933
+ type McpClientFactory = (opts?: McpClientFactoryOptions) => Client;
1934
+ /**
1935
+ * Connect to MCP servers and discover their tools.
1936
+ *
1937
+ * Each tool is namespaced as `mcp_{serverName}_{toolName}` to avoid
1938
+ * collisions with agent tools or tools from other servers.
1939
+ *
1940
+ * @param configs - Array of MCP server configurations
1941
+ * @param _clientFactory - Internal: override client construction for testing
1942
+ * @param hooks - Optional agent hooks for firing mcp:connect, mcp:error, mcp:close events
1943
+ * @param options - Optional bootstrap knobs (e.g. OAuth provider injection)
1896
1944
  * @example
1897
1945
  * ```ts
1898
- * import { createMemoryStore, createSession } from 'zidane/session'
1946
+ * import { connectMcpServers } from 'zidane/mcp'
1899
1947
  *
1900
- * const session = await createSession({ agentId: 'reviewer', store: createMemoryStore() })
1901
- * console.log(session.id, session.turns.length)
1948
+ * const connection = await connectMcpServers([
1949
+ * { name: 'fs', transport: 'stdio', command: 'npx', args: ['-y', '@modelcontextprotocol/server-filesystem', '.'] },
1950
+ * ])
1951
+ * console.log(Object.keys(connection.tools))
1952
+ * await connection.close()
1902
1953
  * ```
1903
1954
  */
1904
- declare function createSession(options?: CreateSessionOptions): Promise<Session>;
1905
- /**
1906
- * Demote a persisted `'running'` status to `'idle'` (in place) and return the
1907
- * data. A persisted `'running'` is necessarily stale: the run that set it lived
1908
- * in another process (crash, kill -9, power loss) and cannot still be executing
1909
- * in a freshly-loaded session. Call this on the result of a raw `store.load()`
1910
- * so consumers don't render a ghost in-progress state or refuse a new run.
1911
- * `loadSession` applies it automatically; direct `store.load()` callers (e.g.
1912
- * the TUI) should run loaded data through this.
1913
- *
1914
- * Run RECORDS get the same treatment: the agent persists each record at
1915
- * run start with `status: 'running'` (crash durability — see the
1916
- * `SessionStore.updateRun` contract), so a freshly-loaded session may
1917
- * carry `'running'` runs that died with their process. They demote to
1918
- * `'aborted'` so replay renders a truthful "aborted" state instead of a
1919
- * perpetually-in-flight run.
1920
- * @param data - Loaded session data. It is modified in place.
1921
- */
1922
- declare function demoteStaleRunningStatus(data: SessionData): SessionData;
1923
- /** Options for {@link loadSession}. */
1924
- interface LoadSessionOptions {
1925
- /** Forwarded to `createSession` — see {@link CreateSessionOptions.onPairingDrop}. */
1926
- onPairingDrop?: (drop: PairingDrop) => void;
1927
- /**
1928
- * Write a load-time pairing heal back to the store (default true). Pass
1929
- * `false` from READERS — a window mirroring a session another process
1930
- * runs (daemon mode) — because the persist is a bulk turn overwrite and
1931
- * the owner's next load heals and persists it anyway.
1932
- */
1933
- persistHeal?: boolean;
1934
- }
1935
- /**
1936
- * Load an existing session from a store.
1937
- * @param store - Store to load from.
1938
- * @param sessionId - Id of the session to load.
1939
- * @param options - Load options. See {@link LoadSessionOptions}.
1940
- * @returns The session, or `null` when the store has no session with that id.
1941
- */
1942
- declare function loadSession(store: SessionStore, sessionId: string, options?: LoadSessionOptions): Promise<Session | null>;
1955
+ declare function connectMcpServers(configs: McpServerConfig[], _clientFactory?: McpClientFactory, hooks?: Hookable<AgentHooks>, options?: ConnectMcpServersOptions): Promise<McpConnection>;
1943
1956
  //#endregion
1944
1957
  //#region src/skills/types.d.ts
1945
1958
  /**
@@ -5901,6 +5914,11 @@ interface AgentRunOptions {
5901
5914
  * numbering read a stored fact instead of deriving it positionally.
5902
5915
  */
5903
5916
  runLabel?: string;
5917
+ /**
5918
+ * The host's agent profile this run runs as, persisted onto the resulting
5919
+ * `SessionRun.agent` so a transcript can name it per run.
5920
+ */
5921
+ runAgent?: SessionRunAgent;
5904
5922
  /**
5905
5923
  * Zero-based subagent depth. 0 = top-level `agent.run()`, 1 = first-level
5906
5924
  * child spawned by a parent agent, and so on. Used by the spawn tool to
@@ -14539,6 +14557,10 @@ declare function compactPath(path: string, maxWidth?: number, home?: string): st
14539
14557
  //#region src/chat/run-receipt.d.ts
14540
14558
  /** What a finished run cost and how long it took, as shown on its receipt row. */
14541
14559
  interface RunReceipt {
14560
+ /** The agent profile the run ran as. */
14561
+ agent?: string;
14562
+ /** The previous run ran as another agent: the user switched before this run. */
14563
+ agentSwitched?: boolean;
14542
14564
  /** Model that produced the LAST turn — the one the answer came from. */
14543
14565
  modelId?: string;
14544
14566
  /** The provider that served that turn, so its name reads as the model picker's. */
@@ -14565,6 +14587,8 @@ interface RunReceipt {
14565
14587
  }
14566
14588
  /** Leads the turn count: one cycle = one model round trip. */
14567
14589
  declare const RUN_RECEIPT_TURN_GLYPH = "↻";
14590
+ /** Leads the agent when the run switched to it from the previous run's. */
14591
+ declare const RUN_RECEIPT_SWITCH_GLYPH = "⇄";
14568
14592
  /**
14569
14593
  * `1.2k` / `48k` / `1.3M` — token counts are read at a glance, not counted.
14570
14594
  *
@@ -14585,8 +14609,9 @@ declare const formatCostUsd: typeof fmtCost;
14585
14609
  *
14586
14610
  * @param run - The run record.
14587
14611
  * @param now - Epoch milliseconds used as the end time of a run still in progress.
14612
+ * @param previous - The session's top-level run before this one, to tell an agent switch.
14588
14613
  */
14589
- declare function runReceiptFromRun(run: SessionRun, now?: number): RunReceipt;
14614
+ declare function runReceiptFromRun(run: SessionRun, now?: number, previous?: SessionRun): RunReceipt;
14590
14615
  /**
14591
14616
  * `42 tk/s`; one decimal under 10 so a slow model is not shown as `0 tk/s`.
14592
14617
  *
@@ -14594,7 +14619,7 @@ declare function runReceiptFromRun(run: SessionRun, now?: number): RunReceipt;
14594
14619
  */
14595
14620
  declare function formatTokensPerSecond(tps: number): string;
14596
14621
  /** What a cell IS, so renderers can tint by meaning rather than by position. */
14597
- type RunReceiptCellKind = 'model' | 'duration' | 'turns' | 'cost' | 'tokens' | 'speed';
14622
+ type RunReceiptCellKind = 'agent' | 'model' | 'duration' | 'turns' | 'cost' | 'tokens' | 'speed';
14598
14623
  /** Sub-parts of a cell that want their own tint — the two token arrows. */
14599
14624
  type RunReceiptSegmentKind = 'tokens-in' | 'tokens-out';
14600
14625
  /** One part of a `tokens` cell, so renderers can color input and output differently. */
@@ -16397,6 +16422,12 @@ interface Settings {
16397
16422
  * Takes effect on the next agent build. Default: on.
16398
16423
  */
16399
16424
  imageGeneration: boolean;
16425
+ /**
16426
+ * Give the agent the `web_search` tool (Anthropic's native search where the
16427
+ * provider offers it). Off removes it from every session, its subagents and
16428
+ * `/side` sessions; a change rebuilds live agents. Default: on.
16429
+ */
16430
+ webSearch: boolean;
16400
16431
  /**
16401
16432
  * Default model of `generate_image`, as `"providerKey/modelId"`
16402
16433
  * (e.g. `"openrouter/google/gemini-3-pro-image"`). Empty string = the first
@@ -30547,5 +30578,5 @@ declare const basicTools: {
30547
30578
  /** Default preset with the shell, file, edit and `spawn` tools and a general-purpose system prompt. The `spawn` tool is created fresh on every access, so each agent gets its own subagent state. */
30548
30579
  declare const _default: Preset;
30549
30580
  //#endregion
30550
- export { MetricsHooksOptions as $, ImageData as $C, originPinnedFetch as $D, ToWireMessagesOptions as $E, loadGoogleWireKit as $S, ToolDescriptionOverride as $T, formatTaskStatus as $_, ReferenceMatch as $a, AgentHookBus as $b, ExtensionReferenceCardFact as $c, stripShellInterpolations as $d, ChipColorMap as $f, normalizePanelLoadContext as $g, defaultSessionModel as $h, TRAILER as $i, ExtensionSessionSummary as $l, AgentComposition as $m, EvalWorkspaceFile as $n, branchKind as $o, ConfirmQuestion as $p, edit as $r, readGithubPulls as $s, buildZidaneSkillEditSkill as $t, ExtensionSubagentDef as $u, EnvironmentState as $v, McpToolHookContext as $w, ASSISTANT_TOOL_CALLS_TAG as $x, activeSnapshotFor as $y, SqlValue as A, OAuthParams as AC, SessionArtifactInput as AD, SessionData as AE, mistral as AS, StreamUsageSnapshot as AT, RunReceiptSegmentKind as A_, DecisionError as Aa, storedCredentialsOf as Ab, ExtensionGuiPanel as Ac, PluginManifest as Ad, RECOMMENDED_SKILL_SOURCES as Af, normalizePaletteRunResult as Ag, OpenInTarget as Ah, createRunSummaryCollector as Ai, SessionBadgeEntry as Al, SchemaInput as Am, CreateEvalAgentOptions as An, discoverExtensions as Ao, CommandArgSuggestion as Ap, SkillsUseToolOptions as Ar, GithubClientOptions as As, resolveLegacySessionDir as At, resolveExtensionConfig as Au, defaultEnvironmentKind as Av, DecisionUsage as Aw, ProviderDecisions as Ax, enabledModelOptions as Ay, MutationValidationHooksOptions as B, resolveOAuthApiKey as BC, resultToString as BD, loadSession as BE, GoogleRouteName as BS, ToolResultDocumentRefContent as BT, runReceiptFromRun as B_, AgentOptions as Ba, ContextBreakdownContributionContext as Bb, ExtensionModalNode as Bc, skillTokenWeights as Bd, groupSkillPicks as Bf, PanelFocus as Bg, ToolCallDisplay as Bh, selectRecentFiles as Bi, ExtensionHudWriter as Bl, LoggingHookSet as Bm, EvalCaseResult as Bn, ExtensionMcpHost as Bo, CommandStepContext as Bp, RECORD_ARTIFACT_TOOL as Br, githubTokenSource as Bs, renderStaleReadNotice as Bt, ExtensionBadgeActions as Bu, EnvironmentAvailability as Bv, ChildSpawnIdentity as Bw, planZaiReasoning as Bx, piIdOf as By, statsByModel as C, AnthropicBedrockConfig as CC, remintDuplicateToolCallIds as CD, SkillDiagnostic as CE, openai as CS, SessionTurn as CT, ModelNamer as C_, composePresets as Ca, readProviderCredentials as Cb, ExtensionContext as Cc, loadAgentPlugin as Cd, sanitizeSkillName as Cf, PaletteRunResult as Cg, EditHunk as Ch, RunSummaryByModel as Ci, ExtensionToolResultPatch as Cl, createInteractionTools as Cm, defineEval as Cn, readExtensionInstallProvenance as Co, collectReferences as Cp, writeFile as Cr, pullFromMeta as Cs, PersistOutcome as Ct, StoredExtensionConfigItem as Cu, EnvironmentDescriptor as Cv, DecisionRefusalAnswer as Cw, HistoryRepair as Cx, ProviderFactoryOptions as Cy, sqliteStoreFile as D, PromptCacheKeyOption as DC, ARTIFACT_META_MAX_BYTES as DD, CreateSessionOptions as DE, neuralwatt as DS, StepThinkingDecay as DT, RunReceiptCell as D_, ToolSearchToolOptions as Da, setPreferredCredential as Db, ExtensionCustomRendererEntry as Dc, PluginAuthor as Dd, SkillBrowseErrorCode as Df, groupPaletteRows as Dg, InteractionMode as Dh, RunSummaryRepeatGuard as Di, GuiContributions as Dl, pendingInteractionsFromTurns as Dm, createReusableExecutionContext as Dn, ENTRY_CANDIDATES as Do, resolveCompletionSubmit as Dp, validateToolArgs as Dr, viewForRead as Ds, maybePersistToolResult as Dt, coerceExtensionConfigInput as Du, EnvironmentSettingsChange as Dv, DecisionScoreQuestion as Dw, ProviderDecisionAvailability as Dx, cerebrasDescriptor as Dy, createSqliteSessionStore as E, PromptCacheKeyContext as EC, ARTIFACT_KINDS as ED, SkillsConfig as EE, NeuralwattParams as ES, StaleReadPolicy as ET, RunReceipt as E_, LazyToolEntry as Ea, setCredentialLabel as Eb, ExtensionCustomRenderer as Ec, LoadedPlugin as Ed, SkillBrowseError as Ef, fuzzyMatch as Eg, EditPayload as Eh, RunSummaryError as Ei, ExtensionTuiSurface as El, makeRequestInteraction as Em, ReusableExecutionContext as En, registerExtensionHostModules as Eo, mergeSuggestions as Ep, ValidationResult as Er, viewForIssueRead as Es, cleanupPersistedSession as Et, clampExtensionConfigNumber as Eu, EnvironmentSettings as Ev, DecisionScoreLevel as Ew, ProviderCapabilities as Ex, anthropicDescriptor as Ey, createSqliteDriver as F, isOAuthAccessToken as FC, sortArtifacts as FD, createSession as FE, GOOGLE_EXTRA_MODELS as FS, ToolHookContext as FT, formatRunReceiptLine as F_, Agent as Fa, ContextSegmentFile as Fb, ExtensionMcpConfigTransform as Fc, parseSchemaId as Fd, SkillSourceInfo as Ff, ExtensionPanelScope as Fg, SessionHeader as Fh, PostCompactRestoreOptions as Fi, ExtensionComposerBadgeOptions as Fl, ConsoleSinkOptions as Fm, EvalAgentRunStats as Fn, DiscoverAndBuildExtensionRegistryOptions as Fo, CommandInvocation as Fp, createSkillsReadTool as Fr, configureGithubClient as Fs, INTERRUPT_MESSAGE_FOR_TOOL_USE as Ft, BadgeActionEffect as Fu, ENVIRONMENT_METADATA_KEY as Fv, AutoCompact as Fw, ToolCall as Fx, modelOptionsFor as Fy, normalizeProviders as G, planAnthropicThinking as GC, expandMcpConfigEnv as GD, createRemoteStore as GE, GoogleVertexParams as GS, ToolResultVideoContent as GT, compactPath as G_, BuildExtensionRegistryOptions as Ga, ContextExactCounts as Gb, ExtensionPaletteProviderEntry as Gc, parseAllowedToolPattern as Gd, installAllowedToolsGate as Gf, PanelLoadContext as Gg, SessionKnobs as Gh, compactConversation as Gi, MAX_COMPOSER_BADGES as Gl, createLoggingHooks as Gm, EvalRunReporterOptions as Gn, EXTENSION_BUS_MAX_PAYLOAD_BYTES as Go, executeCommand as Gp, InteractionToolOptions as Gr, GithubPullRead as Gs, EXTENSION_EDIT_METADATA_KEY as Gt, builtinBadgeEffect as Gu, EnvironmentExecution as Gv, DEFAULT_AGENT_CLOCK as Gw, SchemaSanitizeProfile as Gx, OUTPUT_RESERVE_TOKENS as Gy, MutationValidationResult as H, AnthropicThinkingPlan as HC, nonOwningMcpView as HD, setExtensionSessionState as HE, GoogleStreamFn as HS, ToolResultImageRefContent as HT, SpawnEndSummary as H_, McpConnector as Ha, ContextBreakdownOptions as Hb, ExtensionPaletteCommand as Hc, SkillValidationResult as Hd, skillPickKey as Hf, PanelItem as Hg, DEFAULT_SPACE_ID as Hh, CompactOptions as Hi, ExtensionNotifyOptions as Hl, RingBufferSink as Hm, EvalDefinitionContext as Hn, defineExtension as Ho, commandBlockToEvent as Hp, readFile as Hr, GithubStateStore as Hs, createFileGithubStateStore as Ht, badgeMenu as Hu, EnvironmentConfig as Hv, CompactFunction as Hw, XaiParams as Hx, AUTO_COMPACT_MIN_GROWTH_FRACTION as Hy, createSqliteWriteQueue as I, pinnedAccountMissingError as IC, ConnectMcpServersOptions as ID, currentExtensionSession as IE, GoogleCompatibleRoute as IS, ToolOutcome as IT, formatTokenCount as I_, AgentCacheChange as Ia, ContextSegmentOrigin as Ib, ExtensionMcpServerInfo as Ic, defineSkill as Id, SkillSourceListing as If, PANEL_CONTENT_LIMITS as Ig, SessionMeta as Ih, RecentFile as Ii, ExtensionHud as Il, LogLevel as Im, EvalAgentStats as In, discoverAndBuildExtensionRegistry as Io, CommandOutputBlock as Ip, shellKill as Ir, createGithubClient as Is, SHELL_CASCADE_CANCEL_MESSAGE as It, BadgeActionsMatch as Iu, EnvironmentAction as Iv, AutoCompactConfig as Iw, ToolResult as Ix, modelSupportsReasoning as Iy, Histogram as J, openrouterImageModels as JC, pinnedMcpRedirectUri as JD, FileMapStoreOptions as JE, classifyGoogleError as JS, toolOutputBudgetByteLength as JT, fmtTokens as J_, disposeExtensionRegistry as Ja, ContextItem as Jb, ExtensionPaths as Jc, validateSkillForWrite as Jd, StorageMode as Jf, PanelMarkdownItem as Jg, SpaceModelDefault as Jh, BASE_INSTRUCTIONS as Ji, ExtensionHostRuntimeBridge as Jl, jsonSink as Jm, EvalRunUsage as Jn, ExtensionBusEnvelope as Jo, useInteractionsActions as Jp, glob as Jr, KnownGithubPull as Js, SKILL_EDIT_METADATA_KEY as Jt, normalizeBadgeEffect as Ju, EnvironmentPrepareInput as Jv, FrozenPromptSections as Jw, sanitizeToolSpecs as Jx, ProviderUsageCredits as Jy, resolveModelTargets as K, resolveThinkingBinding as KC, isValidCallbackPort as KD, createMemoryStore as KE, GoogleWireKit as KS, TurnFinishReason as KT, describeSpawnEnd as K_, ExtensionCatalogPartition as Ka, ContextExtensionRow as Kb, ExtensionPaletteRunResult as Kc, validateResourcePath as Kd, ResolveStorageDirsOptions as Kf, PanelLoadContextInput as Kg, Space as Kh, CompactInvalidInputError as Ki, createExtensionHud as Kl, createRingBufferSink as Km, EvalRunSummary as Kn, ExtensionBus as Ko, parseCommandInvocation as Kp, createInteractionTool as Kr, GithubPullRef as Ks, EditSessionTarget as Kt, extensionBadgeActions as Ku, EnvironmentExecutionInput as Kv, DedupHasher as Kw, SchemaSanitizeResult as Kx, effectiveContextWindow as Ky, isSqliteBusyError as L, readAccountOAuthCredential as LC, McpConnection as LD, deleteExtensionSessionState as LE, GoogleExtraModel as LS, ToolResultAudioContent as LT, formatTokensPerSecond as L_, AgentCacheImpact as La, ContextSegmentsInput as Lb, ExtensionMcpSurface as Lc, writeSkillToDisk as Ld, SkillSourceSkill as Lf, PanelAction as Lg, Settings as Lh, buildPostCompactAttachments as Li, ExtensionHudBadge as Ll, LogRecord as Lm, createEvalAgent as Ln, ExtensionPromptBridge as Lo, CommandSpawnResult as Lp, CreateShellToolOptions as Lr, githubApiBase as Ls, TOOL_USE_CANCELLED_MESSAGE as Lt, BadgeMenuItem as Lu, EnvironmentActionInput as Lv, CacheTtl as Lw, ToolSpec as Lx, modelsForDescriptor as Ly, SqliteDriver as M, credentialsFilePath as MC, mergeArtifact as MD, SessionMetaRow as ME, LocalParams as MS, SystemPromptSnapshot as MT, formatCostUsd as M_, DecisionInvalidResponseError as Ma, AgentAccent as Mb, ExtensionKeybinding as Mc, SUPPORTED_AGENT_PLUGINS_VERSIONS as Md, SkillInstallTarget as Mf, rankPaletteItems as Mg, Picked as Mh, estimateTokens as Mi, isBadgeColor as Ml, isStandardSchema as Mm, EvalAgentMcpServers as Mn, isExtensionDefinition as Mo, CommandExecution as Mp, SkillsRunScriptToolOptions as Mr, GithubRequest as Ms, resolvePersistDir as Mt, sanitizeExtensionConfigActionPatch as Mu, isEnvironmentEnabled as Mv, AgentClock as Mw, StreamCallbacks as Mx, getModelInfo as My, SqliteStatement as N, credentialsFromParams as NC, normalizeArtifactInput as ND, SessionRun as NE, local as NS, ThinkingDecay as NT, formatRunDuration as N_, DecisionTimeoutError as Na, accentColor as Nb, ExtensionKeybindingDispatchContext as Nc, agentPluginsSchemaId as Nd, SkillPick as Nf, ExtensionPanel as Ng, Screen as Nh, utf8ByteLength as Ni, ExtensionBannerOptions as Nl, resolveSchemaInput as Nm, EvalAgentRunOptions as Nn, parseExtensionScanPathEnv as No, CommandGenerateDataOptions as Np, createSkillsRunScriptTool as Nr, classifyGithubAnswer as Ns, resolveSessionDir as Nt, toWireConfigSchema as Nu, readEnvironmentSettings as Nv, AgentRunOptions as Nw, StreamOptions as Nx, localDescriptor as Ny, ReadonlySqliteSessionStore as O, derivePromptCacheKey as OC, ArtifactFilter as OD, LoadSessionOptions as OE, planNeuralwattReasoning as OS, StreamHookContext as OT, RunReceiptCellKind as O_, createToolSearchTool as Oa, setProviderCredential as Ob, ExtensionDefinition as Oc, PluginComponentStatus as Od, browseSkillSource as Of, isPaletteContext as Og, ModelApproval as Oh, RunSummaryTokens as Oi, LoadedExtension as Ol, serializeInteractionResponse as Om, artifactPath as On, ExtensionScanEntry as Oo, Command as Op, TailTruncateOptions as Or, GithubAnswer as Os, migrateSessionArtifactDirs as Ot, isValidExtensionConfigItem as Ou, EnvironmentSettingsWrite as Ov, DecisionStartHookContext as Ow, ProviderDecisionRequest as Ox, credKeyOf as Oy, SqliteWriteQueue as P, extractRuntimeCredentials as PC, selectArtifactEvictions as PD, SessionStore as PE, GOOGLE_DEFAULT_MODEL as PS, ToolBatchExecutor as PT, formatRunReceiptCells as P_, DecisionUnsupportedError as Pa, ContextSegment as Pb, ExtensionManifest as Pc, isSupportedAgentPluginsVersion as Pd, SkillPickGroup as Pf, ExtensionPanelEntry as Pg, SessionEnvironmentSummary as Ph, PostCompactAttachments as Pi, ExtensionComposerBadge as Pl, zodToJsonSchema as Pm, EvalAgentRunResult as Pn, scanExtensionDirectories as Po, CommandInteraction as Pp, SkillsReadToolOptions as Pr, clockTime as Ps, resolveTasksDir as Pt, BadgeAction as Pu, resolveProviderConfig as Pv, AgentStats as Pw, TokenCountPayload as Px, modelLabel as Py, MetricsHookSet as Q, ImageAspectRatio as QC, isAllowedRemoteUrl as QD, ReasoningWireAction as QE, googleVertex as QS, ToolDef as QT, formatElapsed as Q_, partitionExtensionCatalog as Qa, buildContextBreakdown as Qb, ExtensionReferenceCard as Qc, interpolateShellCommands as Qd, ChipColor as Qf, normalizePanelContent as Qg, defaultSessionKnobs as Qh, NO_TOOLS_PREAMBLE as Qi, ExtensionSessionControl as Ql, nextLogLevel as Qm, EvalVariantSummary as Qn, artifactKindLabel as Qo, AnswerValue as Qp, createGenerateImageTool as Qr, readGithubPull as Qs, buildZidaneExtensionSkill as Qt, ChildAgent as Qu, EnvironmentRequest as Qv, McpServerConfig as Qw, openrouter as Qx, UsageTone as Qy, MutationValidationBatch as R, readOAuthCredentials as RC, connectMcpServers as RD, demoteStaleRunningStatus as RE, GoogleParams as RS, ToolResultContent as RT, hasRunReceipt as R_, AgentCompactOptions as Ra, buildContextSegments as Rb, ExtensionMcpToolResult as Rc, writeSkillsToDisk as Rd, githubAvatarUrl as Rf, PanelContent as Rg, SpawnEndInfo as Rh, selectFilesFromReadState as Ri, ExtensionHudState as Rl, LogSink as Rm, EvalArtifacts as Rn, ExtensionPromptDelivery as Ro, CommandSpawnTask as Rp, createShellTool as Rr, githubClient as Rs, TOOL_USE_SKIPPED_MESSAGE as Rt, BadgeTarget as Ru, EnvironmentActionResult as Rv, ChildRunStats as Rw, TurnResult as Rx, openaiDescriptor as Ry, formatTokenUsage as S, applyAnthropicCacheBreakpoints as SC, ensureToolResultPairing as SD, SkillConfig as SE, mapCodexStopReason as SS, SessionMessage as ST, truncateTitle as S_, Preset as Sa, readProviderCredentialPair as Sb, ExtensionComposerSurface as Sc, defaultPluginDataRoot as Sd, SkillPathCandidate as Sf, PaletteProvider as Sg, EditDiffDisplay as Sh, RunSummaryBudget as Si, ExtensionToolResultMetadataRegistration as Sl, createAutomaticInteractionResponse as Sm, clearRegisteredEvals as Sn, parseExtensionInstallSource as So, applyInsert as Sp, runHeadless as Sr, pullChecks as Ss, PersistInput as St, ExtensionConfigValueItem as Su, toggleKeyed as Sv, DecisionQuestions as Sw, snapshotCacheDimensions as Sx, ProviderDescriptor as Sy, SqliteStoreFile as T, AnthropicParams as TC, ARTIFACTS_PER_SESSION_CAP as TD, SkillSource as TE, NEURALWATT_DEFAULT_MODEL as TS, SpawnQueuedContext as TT, RUN_RECEIPT_TURN_GLYPH as T_, createAgent as Ta, removeStoredCredential as Tb, ExtensionContributions as Tc, LoadAgentPluginOptions as Td, BrowseSkillSourceOptions as Tf, createPaletteRanker as Tg, EditOutcomeKind as Th, RunSummaryCollectorOptions as Ti, ExtensionToolVerdict as Tl, isModelInteraction as Tm, llmJudge as Tn, updateInstalledExtension as To, mergeReferences as Tp, waitTask as Tr, pullStateLook as Ts, buildPersistedStub as Tt, WireExtensionConfigSchema as Tu, EnvironmentSecrets as Tv, DecisionScoreAnswer as Tw, Provider as Tx, ProviderUsageReport as Ty, SuccessfulMutationOutcome as U, THINKING_BINDING_SETTING_ENV as UC, wrapDiscoveredMcpTools as UD, withExtensionSession as UE, GoogleStreamOptions as US, ToolResultMetadata as UT, ageStep as U_, McpToolMeta as Ua, ContextCategory as Ub, ExtensionPaletteItem as Uc, isToolAllowedByUnion as Ud, skillPickOf as Uf, PanelKeyValueItem as Ug, DEFAULT_SPACE_NAME as Uh, CompactResult as Ui, ExtensionNotifyTone as Ul, consoleSink as Um, EvalRunMetricAggregate as Un, buildExtensionPreset as Uo, commandBlocksToContent as Up, multiEdit as Ur, createMemoryGithubStateStore as Us, isGhRateLimitError as Ut, badgePromptText as Uu, EnvironmentConfigField as Uv, CompactHookContext as Uw, xai as Ux, AutoCompactDecision as Uy, MutationValidationMutation as V, writeOAuthCredentials as VC, deriveMcpToolMeta as VD, resumeChainRunIds as VE, GoogleSharedParams as VS, ToolResultImageContent as VT, AgeStep as V_, AgentToolState as Va, ContextBreakdownContributor as Vb, ExtensionOrderedContribution as Vc, SkillValidationIssue as Vd, skillCategory as Vf, PanelIcon as Vg, TranscriptDensity as Vh, CompactEndEvent as Vi, ExtensionNotification as Vl, LoggingHooksOptions as Vm, EvalDefinition as Vn, createMcpSurface as Vo, CommandStepFn as Vp, recordArtifact as Vr, normalizeGithubHost as Vs, applyCompactSummaryCutoff as Vt, artifactBadgeTarget as Vu, EnvironmentAvailabilityInput as Vv, CompactEndHookContext as Vw, zai as Vx, restoreModelOptions as Vy, createMutationValidationHooks as W, ThinkingBindingBehavior as WC, expandEnvPlaceholders as WD, RemoteStoreOptions as WE, GoogleStreams as WS, ToolResultTextContent as WT, ageString as W_, McpToolWrap as Wa, ContextCategoryId as Wb, ExtensionPaletteProvider as Wc, matchesAllowedTool as Wd, IMPLICITLY_ALLOWED_SKILL_TOOLS as Wf, PanelKeyValueRow as Wg, SPACE_METADATA_KEY as Wh, CompactStartEvent as Wi, ExtensionStatusOptions as Wl, createLogger as Wm, EvalRunReporter as Wn, composeExtensionPreset as Wo, commandSteps as Wp, listFiles as Wr, GithubPull as Ws, rateLimitResetFromJson as Wt, builtinBadgeActions as Wu, EnvironmentConfigValue as Wv, CompactStartHookContext as Ww, SchemaSanitizeOptions as Wx, AutoCompactInput as Wy, Meter as X, GOOGLE_IMAGE_MODELS as XC, withoutEnvPlaceholders as XD, SaveMetaOptions as XE, google as XS, toolResultToText as XT, formatCount as X_, filterRegistryPlugins as Xa, ContextSnapshot as Xb, ExtensionPromptTransform as Xc, resolveSkills as Xd, resolveStorageDirs as Xf, PanelSection as Xg, activeSpaceOf as Xh, CompactPromptBuilder as Xi, ExtensionModelEntry as Xl, filterLogRecords as Xm, EvalScorer as Xn, serializedPayloadBytes as Xo, ASK_USER_TOOL as Xp, GenerateImageToolOptions as Xr, githubPullConfirmedAt as Xs, ZIDANE_EXTENSION_SKILL_NAME as Xt, runBadgeAction as Xu, EnvironmentProvider as Xv, JsonValue as Xw, OpenRouterParams as Xx, ProviderUsageStatus as Xy, InstrumentOptions as Y, OPENAI_IMAGE_MODELS as YC, resolveTransportConfig as YD, createFileMapStore as YE, fromGooglePiAssistantMessage as YS, toolOutputByteLength as YT, formatCostLabel as Y_, filterExtensionRegistry as Ya, ContextMcpGroup as Yb, ExtensionPermission as Yc, validateSkillName as Yd, StorageSlot as Yf, PanelRowItem as Yg, SpacesSettings as Yh, CompactDirection as Yi, ExtensionHostRuntimeImpl as Yl, LOG_LEVEL_CYCLE as Ym, EvalScore as Yn, createExtensionBus as Yo, useInteractionsQueue as Yp, DEFAULT_IMAGE_DIR as Yr, clearGithubPullMemory as Ys, SkillEditMarker as Yt, normalizeBadgeTarget as Yu, EnvironmentPrepareResult as Yv, GeometricThinkingDecay as Yw, OPENROUTER_DEFAULT_MODEL as Yx, ProviderUsageSnapshot as Yy, MetricAttributes as Z, IMAGE_ASPECT_RATIOS as ZC, PinnedFetch as ZD, mergeSessionMetadata as ZE, googleCompatible as ZS, ToolContext as ZT, formatDuration as Z_, mergeContributions as Za, ContextUsageSplit as Zb, ExtensionProviderMiddleware as Zc, InterpolateShellCommandsOptions as Zd, BUILTIN_THEMES as Zf, isExtensionPanelScope as Zg, defaultSessionAgent as Zh, CompactPromptOptions as Zi, ExtensionRuntimeSurface as Zl, formatLogLine as Zm, EvalScorerContext as Zn, BUILTIN_ARTIFACT_KINDS as Zo, AUTOMATIC_INTERACTION_INSTRUCTION as Zp, ImageModelSource as Zr, queueGithubPull as Zs, ZIDANE_SKILL_EDIT_SKILL_NAME as Zt, sessionBadgeTarget as Zu, EnvironmentRegistry as Zv, McpOAuthClientConfig as Zw, normalizeOpenRouterModelId as Zx, ProviderUsageWindow as Zy, sectionDigests as _, buildAnthropicClientOptions as _C, PairingRepairMode as _D, ToolStateView as _E, userMessage as _S, RetryConfig as _T, sessionEventExcerpt as __, defaultRepeatGuardTracked as _a, credentialsPath as _b, ExtensionBehaviorTransform as _c, expandPluginVars as _d, parseSkillContent as _f, PaletteContext as _g, profileTools as _h, providerTranscriptFormatForProvider as _i, ExtensionToolPolicy as _l, QuestionResponse as _m, functionalityMetric as _n, InstallExtensionFromSpecOptions as _o, CompletionContext as _p, efficiencyMetricValues as _r, githubPullView as _s, OAuthCallbackOptions as _t, ExtensionConfigNumberItem as _u, rememberableChain as _v, DecisionInputKind as _w, CacheSystemSection as _x, detectAuth as _y, StartSpan as a, CerebrasParams as aC, fromAnthropic as aD, ReadStateMap as aE, ModelCatalog as aO, TOOL_RESULTS_TAG as aS, ProgressNudgeKind as aT, SESSION_EVENT_STATUS_STYLE as a_, ANCHOR_PREVIEW_MAX_CHARS as aa, showsAccount as ab, ExtensionApiVersion as ac, SubagentDef as ad, SkillInstallOptions as af, resolveSessionSpace as ag, BuiltInPrompt as ah, HeadlessResult as ai, ExtensionRunSettledEvent as al, InteractionsActions as am, withZidaneExtensionSkill as an, findReferences as ao, ThemeSelect as ap, TrajectoryStepKind as ar, renderArtifactRow as as, McpCredentialEntry as at, createExtensionHostRuntimeBridge as au, buildRunModel as av, ProviderImages as aw, ActiveSkill as ax, availableEnvironmentActions as ay, TokenUsageLike as b, resolveAnthropicBetas as bC, TOOL_USE_INTERRUPTED_MARKER as bD, stagedToolState as bE, OpenAIParams as bS, SessionEndStatus as bT, shortSessionId as b_, localReliabilityBehavior as ba, readCredentials as bb, ExtensionBusSurface as bc, validatePluginManifest as bd, skillCatalogEntry as bf, PaletteItem as bg, singleAgentRegistry as bh, RunSummary as bi, ExtensionToolRendererEntry as bl, TextQuestion as bm, formatEvalRunSummary as bn, installExtensionFromSpec as bo, CompletionReference as bp, normalizeMetric as br, isPullFresh as bs, PERSISTED_STUB_PREFIX as bt, ExtensionConfigSurface as bu, sanitizeModelChain as bv, DecisionPredicateQuestion as bw, hashMessages as bx, ModelInfo as by, TracingHooksOptions as c, baseten as cC, sanitizeHistoryForProvider as cD, hydrateReadStateFromSession as cE, ModelTier as cO, assistantMessage as cS, PromptDocumentPart as cT, SessionEventStatus as c_, SummaryToTurnInput as ca, ApiKeyCredential as cb, ExtensionArtifactQuery as cc, createSpawnTool as cd, installSkillFromSpec as cf, spaceMetadata as cg, DEFAULT_PERSIST_EXCLUDE_TOOLS as ch, OpenAIChatContentPart as ci, ExtensionRuntimeEnv as cl, PlanDecision as cm, RegisterEvalTestsOptions as cn, ExtensionFetchResult as co, resolveTheme as cp, EFFICIENCY_METRICS as cr, BUILTIN_REFERENCE_PROVIDERS as cs, McpOAuthProviderOptions as ct, ExtensionConfigActionResult as cu, chainPositionOf as cv, DecisionAnswer as cw, SkillActivationStateOptions as cx, readSessionEnvironment as cy, FrozenSystemPrompt as d, arcee as dC, toWireMessages as dD, resolveReadStateMap as dE, formatTools as dS, PromptTextPart as dT, WORKER_REPORT_FRAGMENT as d_, stripImagesFromTurns as da, PreferCredentialResult as db, ExtensionArtifactRow as dc, SpawnModelEntry as dd, readSkillProvenance as df, spaceSwitchItems as dg, availableAgents as dh, exitCodeForHeadlessResult as di, ExtensionSessionStateSurface as dl, PlanResponse as dm, runEvalCase as dn, ExtensionInstallErrorCode as do, createPathAutocompleteProvider as dp, MetricDirection as dr, GITHUB_PULL_PROVIDER_ID as ds, createMemoryMcpCredentialStore as dt, ExtensionConfigCategory as du, filterChainFallbacks as dv, DecisionChoiceAnswer as dw, CacheBreakLoggerOptions as dx, verifyEnvironment as dy, resolveGoogleModel as eC, TurnInterruptionState as eD, ToolDescriptionTarget as eE, McpExecutionBinding as eO, OAIMessage as eS, McpToolSchema as eT, panelBadgeText as e_, buildCompactPrompt as ea, formatBalance as eb, ArtifactDetectHookOptions as ec, SpawnTaskInput as ed, SKILL_PROVENANCE_FILE as ef, findSpace as eg, AgentProfile as eh, FormattedHeadlessResult as ei, ExtensionReferencePattern as el, CreateInteractionToolsOptions as em, editSessionMetadata as en, ReferenceProviderWire as eo, DEFAULT_THEME as ep, EvalWorkspaceOptions as er, commitKind as es, UpDownCounter as et, ExtensionSessionsSurface as eu, formatTaskSummary as ev, ImageModelInfo as ew, AgentHookHandlers as ex, EnvironmentTeardownResult as ey, SectionChangeNote as f, anthropic as fC, EnsureToolResultPairingOptions as fD, DEFAULT_MAX_VALUE_BYTES as fE, mapOAIFinishReason as fS, PromptVideoPart as fT, isMainSession as f_, summaryToTurn as fa, PreferredCredentialTarget as fb, ExtensionArtifactRowFact as fc, createModelSearchTool as fd, SourcedScanPath as ff, spacesEnabled as fg, builtInPromptOf as fh, formatHeadlessResult as fi, ExtensionSkillPolicy as fl, PlanStep as fm, buildEvalRunSummary as fn, ExtensionInstallIo as fo, resolveInlineSuggestion as fp, MetricEmitter as fr, fetchGithubPullRequest as fs, hasAuthorizationHeader as ft, ExtensionConfigChangeBehavior as fu, modelPickKey as fv, DecisionChoiceQuestion as fw, CacheDimensionDiff as fx, workspacePath as fy, sectionDigest as g, classifyAnthropicError as gC, PairingRepair as gD, ToolStateStore as gE, toolResultsMessage as gS, ResolveContentRefBlock as gT, sessionDirLabel as g_, defaultRepeatGuardNormalize as ga, applyApiKeyEnv as gb, ExtensionBadgeTone as gc, PLUGIN_MCP_FILE as gd, parseFrontmatter as gf, PALETTE_RESULT_MAX as gg, profileComposition as gh, installHeadlessEventAdapter as gi, ExtensionToolCatalogTransform as gl, QuestionRequest as gm, fileExistsOneOf as gn, ExtensionInstallSource as go, ActiveTrigger as gp, defineMetrics as gr, githubPullUrl as gs, OAuthCallbackHandle as gt, ExtensionConfigModelItem as gu, providerKeySetChanged as gv, DecisionInput as gw, CachePromptSections as gx, ProviderKey as gy, latestSystemSnapshot as h, resolveAnthropicMaxOutput as hC, PairingDropKind as hD, ToolStateOp as hE, toOAIMessages as hS, ResolveContentRef as hT, renderSessionEventXml as h_, generateStructuredData as ha, StoredCredential as hb, ExtensionBadgeIcon as hc, PLUGIN_SKILLS_DIR as hd, inferSource as hf, PALETTE_RECENT_GROUP as hg, compositionTools as hh, headlessEventToJsonl as hi, ExtensionStorageSurface as hl, QuestionPayload as hm, fileExists as hn, ExtensionInstallScope as ho, patchInlineGhost as hp, computeEvalTagScores as hr, githubPullReferenceProvider as hs, McpOAuthCallbackPageRenderer as ht, ExtensionConfigItemBase as hu, positionKeyed as hv, DecisionFailureReason as hw, CacheDriftInfo as hx, ProviderAuth as hy, Span as i, cursor as iC, filterUnresolvedToolUses as iD, ReadStateEntry as iE, isThinkingLevel as iO, OpenAICompatParams as iS, OAuthRefreshHookContext as iT, ProjectBrief as i_, buildUpToCompactPrompt as ia, resetLabel as ib, ExtensionAgentPluginOptions as ic, SpawnToolState as id, SkillInstallErrorCode as if, readSessionSpaceId as ig, BUILTIN_AGENTS as ih, HeadlessOutputFormat as ii, ExtensionRegistry as il, InteractionResponse as im, resolveExtensionDocsDir as in, createReferenceResolver as io, ThemeColors as ip, TrajectoryStep as ir, refreshArtifact as is, loginMcpServer as it, createArtifactsSurface as iu, ModelChainEntry as iv, ProviderImageResponse as iw, ActivationVia as ix, assertEnvironmentReady as iy, SqliteDatabaseLike as j, ResolveOAuthApiKeyOptions as jC, matchesArtifactFilter as jD, SessionHistory as jE, planMistralReasoning as jS, SystemFreezeOptions as jT, fitRunReceiptCells as j_, DecisionHttpError as ja, writeCredentials as jb, ExtensionGuiSurface as jc, PluginSchemaKind as jd, RecommendedSkillSource as jf, pushPaletteRecent as jg, Owner as jh, BYTES_PER_TOKEN as ji, TuiContributions as jl, StandardSchemaLike as jm, EvalAgent as jn, inlineLoadedExtension as jo, CommandAttachment as jp, createSkillsUseTool as jr, GithubIdentity as js, resolveMcpWarningsDir as jt, resolveExtensionConfigValue as ju, describeEnvironments as jv, AgentBehavior as jw, ProviderMeta as jx, getContextWindow as jy, createReadonlySqliteSessionStore as k, resolvePromptCacheKey as kC, SessionArtifact as kD, Session as kE, MistralParams as kS, StreamProgressHookContext as kT, RunReceiptSegment as k_, DEFAULT_DECISION_TIMEOUT_MS as ka, storedCredentialById as kb, ExtensionFooterHint as kc, PluginDiagnostic as kd, clearSkillSourceCache as kf, normalizePaletteItems as kg, ModelApprovalChoice as kh, RunSummaryValidation as ki, LoadedPluginRecord as kl, InferSchemaOutput as km, relativeArtifactPath as kn, defaultExtensionScanPaths as ko, CommandAgentResult as kp, tailTruncate as kr, GithubClient as ks, resolveLegacyPersistDir as kt, isValidExtensionConfigValue as ku, applyEnvironmentSettingsChange as kv, DecisionSuccess as kw, ProviderDecisionResponse as kx, defaultModelOf as ky, createTracingHooks as l, planBasetenReasoning as lC, toAnthropic as lD, hydrateReadStateFromSessionAsync as lE, getModelCatalog as lO, buildAssistantContent as lS, PromptImagePart as lT, SessionEventStatusStyle as l_, anchorPreviewFor as la, CredentialsFile as lb, ExtensionArtifactRendererEntry as lc, withIsolatedSpawnTool as ld, listSkillCandidates as lf, spaceModelDefault as lg, PLAN_AGENT as lh, OpenAIChatMessage as li, ExtensionSessionBadge as ll, PlanPayload as lm, createEvalRunReporter as ln, ExtensionInstallCandidate as lo, InlineAutocompleteContext as lp, EvalMetric as lr, GITHUB_ISSUE_PROVIDER_ID as ls, McpStaticClient as lt, ExtensionConfigActionStatus as lu, chainsEqual as lv, DecisionAnswerFor as lw, createSkillActivationState as lx, resolveExecution as ly, catalogChangeNotes as m, defaultAnthropicMaxTokens as mC, PairingDrop as mD, ToolStateController as mE, openaiCompat as mS, RepeatGuardToolMatcher as mT, parseSessionEventXml as m_, GenerateStructuredDataOptions as ma, SetProviderCredentialOptions as mb, ExtensionBadgeColor as mc, matchModelEntries as md, getDefaultScanPaths as mf, PALETTE_RECENTS_MAX as mg, compositionFits as mh, formattedHeadlessTurnEventToJsonl as mi, ExtensionStorageScope as ml, QuestionChoice as mm, fileContentQuality as mn, ExtensionInstallResult as mo, InlineGhost as mp, MetricSpecMap as mr, githubIssueView as ms, saveMcpClientSecret as mt, ExtensionConfigItem as mu, pickPrimaryKeyed as mv, DecisionFailure as mw, CacheDimensionSnapshot as mx, ProviderAccount as my, basicTools as n, toGooglePiMessages as nC, detectTurnInterruption as nD, ToolMap as nE, createStderrLineEmitter as nO, OpenAICompatAuthHeader as nS, ModelTargetSpec as nT, resolvePanelLoadContext as n_, buildFullCompactPrompt as na, formatUsagePercent as nb, ArtifactResolveOptions as nc, SpawnTool as nd, SkillInstallCandidate as nf, newSpaceId as ng, BUILD_AGENT as nh, HeadlessErrorInfo as ni, ExtensionReferenceSurface as nl, InteractionOrigin as nm, extensionScaffold as nn, ReferenceResolverOptions as no, SyntaxTokenStyle as np, MetricStats as nr, parseShortstat as ns, LoginMcpServerOptions as nt, ExtensionWorkspacePair as nu, shortId as nv, ProviderImageAvailability as nw, AgentHooks as nx, LOCAL_ENVIRONMENT as ny, TracingConventions as o, cerebras as oC, fromOpenAI as oD, getReadState as oE, ModelCatalogEntry as oO, applyOAICacheBreakpoints as oS, ProgressNudgeMessage as oT, SESSION_ROLE_KEY as o_, CompactScope as oa, updatedLabel as ob, ExtensionArtifactDetection as oc, SubagentOverride as od, SkillInstallResult as of, sessionSpaceFilter as og, DEFAULT_AGENT_ID as oh, HeadlessStatus as oi, ExtensionRunSettledHandler as ol, PRESENT_PLAN_TOOL as om, withZidaneSkillEditSkill as on, referenceProviderWires as oo, ThemeSurfaces as op, buildTrajectory as or, resolveArtifactKind as os, McpCredentialStore as ot, createWorkspaceSurface as ou, chainAccountConflict as ov, AgentDecide as ow, DeactivationReason as ox, createEnvironmentRegistry as oy, announcedDigest as p, cacheWriteTtlMultiplier as pC, ORPHANED_TOOL_RESULT_MARKER as pD, StagedToolState as pE, openAICompatPromptMessage as pS, RepeatGuardConfig as pT, orchestratedBy as p_, truncateHeadForPtlRetry as pa, ProviderCredential as pb, ExtensionArtifactsSurface as pc, formatModelLine as pd, discoverSkills as pf, PALETTE_LIMITS as pg, compositionByKey as ph, formatHeadlessTurnEvent as pi, ExtensionSource as pl, Question as pm, fileContains as pn, ExtensionInstallProvenance as po, tokenEndingAtCursor as pp, MetricSpec as pr, githubIssueReferenceProvider as ps, mcpOAuthProviderFor as pt, ExtensionConfigEnumItem as pu, pickChainPrimary as pv, DecisionEndHookContext as pw, CacheDimensionName as px, AuthMethod as py, Counter as q, XAI_IMAGE_MODELS as qC, normalizeMcpServers as qD, FileMapAdapter as qE, GoogleWireModel as qS, TurnUsage as qT, fmtCost as q_, buildExtensionRegistry as qa, ContextExtensionSection as qb, ExtensionPaletteWhen as qc, validateResourcePathReal as qd, StorageDirs as qf, PanelLoadScope as qg, SpaceIcon as qh, CompactPromptTooLongError as qi, ExtensionArtifactScope as ql, fanoutSink as qm, EvalRunSummaryCase as qn, ExtensionBusChannel as qo, InteractionsProvider as qp, grep as qr, GithubPullState as qs, ExtensionEditMarker as qt, mergeBadgeMenu as qu, EnvironmentNotReadyError as qv, DedupToolConfig as qw, sanitizeToolSchema as qx, shouldAutoCompact as qy, GEN_AI_ATTRIBUTES as r, CursorParams as rC, ensureEndsWithUserMessage as rD, HydrateReadStateOptions as rE, ThinkingLevel as rO, OpenAICompatHttpError as rS, NestedToolCallRecord as rT, ORCHESTRATED_BY_KEY as r_, buildTailCompactPrompt as ra, mostConstrainedWindow as rb, EMPTY_EXTENSION_REGISTRY as rc, SpawnToolOptions as rd, SkillInstallError as rf, normalizeSpaces as rg, BUILD_CODEMODE_AGENT as rh, HeadlessEvent as ri, ExtensionReferenceView as rl, InteractionRequest as rm, readSkillEditMarker as rn, compileReferencePattern as ro, Theme as rp, Trajectory as rr, pullRequestKind as rs, LoginMcpServerResult as rt, ExtensionWorkspaceSurface as ru, spawnStartParts as rv, ProviderImageRequest as rw, DecideHookContext as rx, SessionEnvironment as ry, TracingHookSet as s, BasetenParams as sC, reasoningWireAction as sD, hashContent as sE, ModelCatalogSource as sO, applyOAIToolCacheBreakpoint as sS, PromptAudioPart as sT, SessionEvent as s_, CompactionSlice as sa, usageTone as sb, ExtensionArtifactKindRegistration as sc, SubagentRegistry as sd, SkillInstallSpec as sf, spaceIdForNewSession as sg, DEFAULT_BUDGET_EXCLUDE_TOOLS as sh, HeadlessUsage as si, ExtensionRunTransform as sl, PendingInteractionEntry as sm, EvalTestRunner as sn, referenceProviders as so, resolveChipColor as sp, formatTrajectoryLine as sr, sessionBadges as ss, McpOAuthProvider as st, ExtensionConfigActionItem as su, chainEntryKey as sv, AgentDecisionsOptions as sw, SkillActivationState as sx, environmentActionSummaries as sy, _default as t, resolveVertexAuth as tC, autoDetectAndConvert as tD, ToolDescriptions as tE, attachStderrWarnPump as tO, OAITool as tS, ModelTarget as tT, panelShowsIn as t_, buildFromCompactPrompt as ta, formatCredits as tb, createArtifactDetectHook as tc, SpawnTaskOutcome as td, SkillCandidateDetail as tf, newSessionModel as tg, AgentRegistry as th, FormattedHeadlessTurnEvent as ti, ExtensionReferenceProvider as tl, HOST_INTERACTION_ID_PREFIX as tm, extensionDirForCwd as tn, ReferenceResolver as to, SyntaxStyles as tp, EvalWorkspaceSnapshot as tr, fileKind as ts, createMetricsHooks as tt, ExtensionWorkspaceOps as tu, previewLine as tv, MAX_IMAGES_PER_REQUEST as tw, AgentHookMap as tx, EnvironmentVerifyResult as ty, FROZEN_PROMPT_SECTION_KINDS as u, ArceeParams as uC, toOpenAI as uD, readStateKey as uE, setModelCatalog as uO, classifyOpenAICompatError as uS, PromptPart as uT, SessionEventTone as u_, sliceForCompaction as ua, OAuthCredential as ub, ExtensionArtifactRendererRegistration as uc, isSpawnTool as ud, parseSkillInstallSpec as uf, spaceOfSwitchItem as ug, ProfileSwitchNoteContext as uh, ProviderTranscriptFormat as ui, ExtensionSessionBadgeCardRow as ul, PlanRequest as um, registerEvalTests as un, ExtensionInstallError as uo, InlineAutocompleteProvider as up, EvalMetricError as ur, GITHUB_PULL_COLORS as us, clearMcpSignIn as ut, ExtensionConfigBooleanItem as uu, chainsEqualKeyed as uv, DecisionAnswers as uw, CacheBreakInfo as ux, runSessionEnvironmentAction as uy, systemSnapshotTurn as v, credentialIdentity as vC, RemintResult as vD, createToolStateController as vE, OpenAICompatStreamError as vS, RunHookMap as vT, sessionEventLabel as v_, normalizeShellCommand as va, ensureCredentialIds as vb, ExtensionBusEmitOptions as vc, ManifestValidation as vd, parseSkillFile as vf, PaletteGroup as vg, resolveAgentId as vh, transcriptToOpenAIMessages as vi, ExtensionToolRenderProps as vl, QuestionType as vm, statusCompleted as vn, InstalledExtensionTargetOptions as vo, CompletionItem as vp, emitEfficiencyMetrics as vr, githubRateLimitText as vs, OAuthCallbackResult as vt, ExtensionConfigScope as vu, reorderKeyed as vv, DecisionOutcome as vw, diffCacheDimensions as vx, BUILTIN_PROVIDERS as vy, SqliteSessionStoreOptions as w, AnthropicContextManagement as wC, ARTIFACTS_METADATA_KEY as wD, SkillResource as wE, toPiMessages as wS, SpawnHookContext as wT, RUN_RECEIPT_GLYPH as w_, definePreset as wa, removeProviderCredential as wb, ExtensionContextTransform as wc, AgentPluginsVersion as wd, skillCandidatesFromPaths as wf, RankedPaletteItem as wg, EditOutcome as wh, RunSummaryCollector as wi, ExtensionToolResultTransform as wl, isInteractionTool as wm, LlmJudgeOptions as wn, removeInstalledExtension as wo, findActiveTrigger as wp, WAIT_TASK_TIMED_OUT_PREFIX as wr, pullMeta as ws, SessionArtifactDirMigration as wt, WireExtensionConfigItem as wu, EnvironmentFieldDescriptor as wv, DecisionRequest as ww, InputTransformation as wx, ProviderUsageProbe as wy, flattenTurns as x, EXTENDED_CACHE_TTL_BETA as xC, dropInvalidToolPairings as xD, ShellInterpolationApproval as xE, classifyOpenAIError as xS, SessionHookContext as xT, sideSessionParent as x_, _default$1 as xa, readProviderCredential as xb, ExtensionCapability as xc, PLUGIN_MANIFEST_FILE as xd, SKILL_CANDIDATE_MAX_DEPTH as xf, PaletteItemKind as xg, ApprovalMode as xh, RunSummaryBlock as xi, ExtensionToolRendererRegistration as xl, buildResumedToolResultsTurn as xm, buildRegisteredEvals as xn, listExtensionCandidates as xo, CompletionSubmitContext as xp, HeadlessOptions as xr, parseGithubRefKey as xs, PERSISTENCE_PREVIEW_BYTES as xt, ExtensionConfigValue as xu, toggleChainEntry as xv, DecisionQuestion as xw, installCacheBreakLogger as xx, ModelOption as xy, ModelUsage as y, resolveAnthropicAuthShape as yC, SYNTHETIC_TOOL_RESULT_PLACEHOLDER as yD, isToolStateOps as yE, consumeSSE as yS, SessionContentBlock as yT, sessionEventMeta as y_, stableStringify as ya, providerFactoryOptions as yb, ExtensionBusMessage as yc, parsePluginManifest as yd, buildCatalog as yf, PaletteHost as yg, sessionComposition as yh, transcriptToProviderMessages as yi, ExtensionToolRenderer as yl, SelectQuestion as ym, formatEvalCaseSummary as yn, fetchExtensionSource as yo, CompletionProvider as yp, finalizeEvalMetrics as yr, githubRefKey as ys, startOAuthCallback as yt, ExtensionConfigStringItem as yu, restoreChainFallbacks as yv, DecisionPredicateAnswer as yw, fnv1a32 as yx, CustomField as yy, MutationValidationFailure as z, registerCustomOAuthProvider as zC, normalizeMcpBlocks as zD, getExtensionSessionState as zE, GoogleRequestAuth as zS, ToolResultDocumentContent as zT, nameFromModelId as z_, AgentCompactResult as za, ContextBreakdown as zb, ExtensionModal as zc, SkillTokenWeights as zd, githubPreviewImageUrl as zf, PanelCustomItem as zg, StreamEvent as zh, selectFilesFromSession as zi, ExtensionHudStatus as zl, Logger as zm, EvalCaseOptions as zn, createExtensionPromptBridge as zo, CommandStep as zp, shell as zr, githubTokenFingerprint as zs, collectNewlyStaleReadPaths as zt, BadgeTargetKind as zu, EnvironmentActionSummary as zv, ChildSpawnHookContext as zw, ZaiParams as zx, openrouterDescriptor as zy };
30551
- //# sourceMappingURL=index-DyQyDLX1.d.ts.map
30581
+ export { MetricsHooksOptions as $, ImageAspectRatio as $C, ensureToolResultPairing as $D, ModelCatalogSource as $E, googleVertex as $S, ToolDef as $T, formatElapsed as $_, ReferenceMatch as $a, buildContextBreakdown as $b, ExtensionReferenceCardFact as $c, stripShellInterpolations as $d, ChipColorMap as $f, normalizePanelLoadContext as $g, defaultSessionModel as $h, TRAILER as $i, ExtensionSessionSummary as $l, AgentComposition as $m, EvalWorkspaceFile as $n, branchKind as $o, ConfirmQuestion as $p, edit as $r, readGithubPulls as $s, buildZidaneSkillEditSkill as $t, ExtensionSubagentDef as $u, EnvironmentRequest as $v, McpServerConfig as $w, openrouter as $x, UsageTone as $y, SqlValue as A, resolvePromptCacheKey as AC, ToWireMessagesOptions as AD, connectMcpServers as AE, MistralParams as AS, StreamProgressHookContext as AT, RunReceiptSegment as A_, DecisionError as Aa, storedCredentialById as Ab, ExtensionGuiPanel as Ac, PluginManifest as Ad, RECOMMENDED_SKILL_SOURCES as Af, normalizePaletteRunResult as Ag, OpenInTarget as Ah, createRunSummaryCollector as Ai, SessionBadgeEntry as Al, SchemaInput as Am, CreateEvalAgentOptions as An, discoverExtensions as Ao, CommandArgSuggestion as Ap, SkillsUseToolOptions as Ar, GithubClientOptions as As, resolveLegacySessionDir as At, resolveExtensionConfig as Au, applyEnvironmentSettingsChange as Av, DecisionSuccess as Aw, ProviderDecisionResponse as Ax, defaultModelOf as Ay, MutationValidationHooksOptions as B, registerCustomOAuthProvider as BC, toAnthropic as BD, pinnedMcpRedirectUri as BE, GoogleRequestAuth as BS, ToolResultDocumentContent as BT, nameFromModelId as B_, AgentOptions as Ba, ContextBreakdown as Bb, ExtensionModalNode as Bc, skillTokenWeights as Bd, groupSkillPicks as Bf, PanelFocus as Bg, ToolCallDisplay as Bh, selectRecentFiles as Bi, ExtensionHudWriter as Bl, LoggingHookSet as Bm, EvalCaseResult as Bn, ExtensionMcpHost as Bo, CommandStepContext as Bp, RECORD_ARTIFACT_TOOL as Br, githubTokenSource as Bs, renderStaleReadNotice as Bt, ExtensionBadgeActions as Bu, EnvironmentActionSummary as Bv, ChildSpawnHookContext as Bw, ZaiParams as Bx, openrouterDescriptor as By, statsByModel as C, applyAnthropicCacheBreakpoints as CC, createMemoryStore as CD, SkillConfig as CE, mapCodexStopReason as CS, SessionMessage as CT, ModelNamer as C_, composePresets as Ca, readProviderCredentialPair as Cb, ExtensionContext as Cc, loadAgentPlugin as Cd, sanitizeSkillName as Cf, PaletteRunResult as Cg, EditHunk as Ch, RunSummaryByModel as Ci, ExtensionToolResultPatch as Cl, createInteractionTools as Cm, defineEval as Cn, readExtensionInstallProvenance as Co, collectReferences as Cp, writeFile as Cr, pullFromMeta as Cs, PersistOutcome as Ct, StoredExtensionConfigItem as Cu, toggleKeyed as Cv, DecisionQuestions as Cw, snapshotCacheDimensions as Cx, ProviderDescriptor as Cy, sqliteStoreFile as D, PromptCacheKeyContext as DC, SaveMetaOptions as DD, SkillsConfig as DE, NeuralwattParams as DS, StaleReadPolicy as DT, RunReceipt as D_, ToolSearchToolOptions as Da, setCredentialLabel as Db, ExtensionCustomRendererEntry as Dc, PluginAuthor as Dd, SkillBrowseErrorCode as Df, groupPaletteRows as Dg, InteractionMode as Dh, RunSummaryRepeatGuard as Di, GuiContributions as Dl, pendingInteractionsFromTurns as Dm, createReusableExecutionContext as Dn, ENTRY_CANDIDATES as Do, resolveCompletionSubmit as Dp, validateToolArgs as Dr, viewForRead as Ds, maybePersistToolResult as Dt, coerceExtensionConfigInput as Du, EnvironmentSettings as Dv, DecisionScoreLevel as Dw, ProviderCapabilities as Dx, anthropicDescriptor as Dy, createSqliteSessionStore as E, AnthropicParams as EC, createFileMapStore as ED, SkillSource as EE, NEURALWATT_DEFAULT_MODEL as ES, SpawnQueuedContext as ET, RUN_RECEIPT_TURN_GLYPH as E_, LazyToolEntry as Ea, removeStoredCredential as Eb, ExtensionCustomRenderer as Ec, LoadedPlugin as Ed, SkillBrowseError as Ef, fuzzyMatch as Eg, EditPayload as Eh, RunSummaryError as Ei, ExtensionTuiSurface as El, makeRequestInteraction as Em, ReusableExecutionContext as En, registerExtensionHostModules as Eo, mergeSuggestions as Ep, ValidationResult as Er, viewForIssueRead as Es, cleanupPersistedSession as Et, clampExtensionConfigNumber as Eu, EnvironmentSecrets as Ev, DecisionScoreAnswer as Ew, Provider as Ex, ProviderUsageReport as Ey, createSqliteDriver as F, extractRuntimeCredentials as FC, filterUnresolvedToolUses as FD, wrapDiscoveredMcpTools as FE, GOOGLE_DEFAULT_MODEL as FS, ToolBatchExecutor as FT, formatRunReceiptCells as F_, Agent as Fa, ContextSegment as Fb, ExtensionMcpConfigTransform as Fc, parseSchemaId as Fd, SkillSourceInfo as Ff, ExtensionPanelScope as Fg, SessionHeader as Fh, PostCompactRestoreOptions as Fi, ExtensionComposerBadgeOptions as Fl, ConsoleSinkOptions as Fm, EvalAgentRunStats as Fn, DiscoverAndBuildExtensionRegistryOptions as Fo, CommandInvocation as Fp, createSkillsReadTool as Fr, configureGithubClient as Fs, INTERRUPT_MESSAGE_FOR_TOOL_USE as Ft, BadgeActionEffect as Fu, resolveProviderConfig as Fv, AgentStats as Fw, TokenCountPayload as Fx, modelLabel as Fy, normalizeProviders as G, ThinkingBindingBehavior as GC, PairingDrop as GD, originPinnedFetch as GE, GoogleStreams as GS, ToolResultTextContent as GT, ageString as G_, BuildExtensionRegistryOptions as Ga, ContextCategoryId as Gb, ExtensionPaletteProviderEntry as Gc, parseAllowedToolPattern as Gd, installAllowedToolsGate as Gf, PanelLoadContext as Gg, SessionKnobs as Gh, compactConversation as Gi, MAX_COMPOSER_BADGES as Gl, createLoggingHooks as Gm, EvalRunReporterOptions as Gn, EXTENSION_BUS_MAX_PAYLOAD_BYTES as Go, executeCommand as Gp, InteractionToolOptions as Gr, GithubPullRead as Gs, EXTENSION_EDIT_METADATA_KEY as Gt, builtinBadgeEffect as Gu, EnvironmentConfigValue as Gv, CompactStartHookContext as Gw, SchemaSanitizeOptions as Gx, AutoCompactInput as Gy, MutationValidationResult as H, writeOAuthCredentials as HC, toWireMessages as HD, withoutEnvPlaceholders as HE, GoogleSharedParams as HS, ToolResultImageContent as HT, AgeStep as H_, McpConnector as Ha, ContextBreakdownContributor as Hb, ExtensionPaletteCommand as Hc, SkillValidationResult as Hd, skillPickKey as Hf, PanelItem as Hg, DEFAULT_SPACE_ID as Hh, CompactOptions as Hi, ExtensionNotifyOptions as Hl, RingBufferSink as Hm, EvalDefinitionContext as Hn, defineExtension as Ho, commandBlockToEvent as Hp, readFile as Hr, GithubStateStore as Hs, createFileGithubStateStore as Ht, badgeMenu as Hu, EnvironmentAvailabilityInput as Hv, CompactEndHookContext as Hw, zai as Hx, restoreModelOptions as Hy, createSqliteWriteQueue as I, isOAuthAccessToken as IC, fromAnthropic as ID, expandEnvPlaceholders as IE, GOOGLE_EXTRA_MODELS as IS, ToolHookContext as IT, formatRunReceiptLine as I_, AgentCacheChange as Ia, ContextSegmentFile as Ib, ExtensionMcpServerInfo as Ic, defineSkill as Id, SkillSourceListing as If, PANEL_CONTENT_LIMITS as Ig, SessionMeta as Ih, RecentFile as Ii, ExtensionHud as Il, LogLevel as Im, EvalAgentStats as In, discoverAndBuildExtensionRegistry as Io, CommandOutputBlock as Ip, shellKill as Ir, createGithubClient as Is, SHELL_CASCADE_CANCEL_MESSAGE as It, BadgeActionsMatch as Iu, ENVIRONMENT_METADATA_KEY as Iv, AutoCompact as Iw, ToolCall as Ix, modelOptionsFor as Iy, Histogram as J, XAI_IMAGE_MODELS as JC, PairingRepairMode as JD, createStderrLineEmitter as JE, GoogleWireModel as JS, TurnUsage as JT, fmtCost as J_, disposeExtensionRegistry as Ja, ContextExtensionSection as Jb, ExtensionPaths as Jc, validateSkillForWrite as Jd, StorageMode as Jf, PanelMarkdownItem as Jg, SpaceModelDefault as Jh, BASE_INSTRUCTIONS as Ji, ExtensionHostRuntimeBridge as Jl, jsonSink as Jm, EvalRunUsage as Jn, ExtensionBusEnvelope as Jo, useInteractionsActions as Jp, glob as Jr, KnownGithubPull as Js, SKILL_EDIT_METADATA_KEY as Jt, normalizeBadgeEffect as Ju, EnvironmentNotReadyError as Jv, DedupToolConfig as Jw, sanitizeToolSchema as Jx, shouldAutoCompact as Jy, resolveModelTargets as K, planAnthropicThinking as KC, PairingDropKind as KD, McpExecutionBinding as KE, GoogleVertexParams as KS, ToolResultVideoContent as KT, compactPath as K_, ExtensionCatalogPartition as Ka, ContextExactCounts as Kb, ExtensionPaletteRunResult as Kc, validateResourcePath as Kd, ResolveStorageDirsOptions as Kf, PanelLoadContextInput as Kg, Space as Kh, CompactInvalidInputError as Ki, createExtensionHud as Kl, createRingBufferSink as Km, EvalRunSummary as Kn, ExtensionBus as Ko, parseCommandInvocation as Kp, createInteractionTool as Kr, GithubPullRef as Ks, EditSessionTarget as Kt, extensionBadgeActions as Ku, EnvironmentExecution as Kv, DEFAULT_AGENT_CLOCK as Kw, SchemaSanitizeProfile as Kx, OUTPUT_RESERVE_TOKENS as Ky, isSqliteBusyError as L, pinnedAccountMissingError as LC, fromOpenAI as LD, expandMcpConfigEnv as LE, GoogleCompatibleRoute as LS, ToolOutcome as LT, formatTokenCount as L_, AgentCacheImpact as La, ContextSegmentOrigin as Lb, ExtensionMcpSurface as Lc, writeSkillToDisk as Ld, SkillSourceSkill as Lf, PanelAction as Lg, Settings as Lh, buildPostCompactAttachments as Li, ExtensionHudBadge as Ll, LogRecord as Lm, createEvalAgent as Ln, ExtensionPromptBridge as Lo, CommandSpawnResult as Lp, CreateShellToolOptions as Lr, githubApiBase as Ls, TOOL_USE_CANCELLED_MESSAGE as Lt, BadgeMenuItem as Lu, EnvironmentAction as Lv, AutoCompactConfig as Lw, ToolResult as Lx, modelSupportsReasoning as Ly, SqliteDriver as M, ResolveOAuthApiKeyOptions as MC, autoDetectAndConvert as MD, resultToString as ME, planMistralReasoning as MS, SystemFreezeOptions as MT, fitRunReceiptCells as M_, DecisionInvalidResponseError as Ma, writeCredentials as Mb, ExtensionKeybinding as Mc, SUPPORTED_AGENT_PLUGINS_VERSIONS as Md, SkillInstallTarget as Mf, rankPaletteItems as Mg, Picked as Mh, estimateTokens as Mi, isBadgeColor as Ml, isStandardSchema as Mm, EvalAgentMcpServers as Mn, isExtensionDefinition as Mo, CommandExecution as Mp, SkillsRunScriptToolOptions as Mr, GithubRequest as Ms, resolvePersistDir as Mt, sanitizeExtensionConfigActionPatch as Mu, describeEnvironments as Mv, AgentBehavior as Mw, ProviderMeta as Mx, getContextWindow as My, SqliteStatement as N, credentialsFilePath as NC, detectTurnInterruption as ND, deriveMcpToolMeta as NE, LocalParams as NS, SystemPromptSnapshot as NT, formatCostUsd as N_, DecisionTimeoutError as Na, AgentAccent as Nb, ExtensionKeybindingDispatchContext as Nc, agentPluginsSchemaId as Nd, SkillPick as Nf, ExtensionPanel as Ng, Screen as Nh, utf8ByteLength as Ni, ExtensionBannerOptions as Nl, resolveSchemaInput as Nm, EvalAgentRunOptions as Nn, parseExtensionScanPathEnv as No, CommandGenerateDataOptions as Np, createSkillsRunScriptTool as Nr, classifyGithubAnswer as Ns, resolveSessionDir as Nt, toWireConfigSchema as Nu, isEnvironmentEnabled as Nv, AgentClock as Nw, StreamCallbacks as Nx, getModelInfo as Ny, ReadonlySqliteSessionStore as O, PromptCacheKeyOption as OC, mergeSessionMetadata as OD, ConnectMcpServersOptions as OE, neuralwatt as OS, StepThinkingDecay as OT, RunReceiptCell as O_, createToolSearchTool as Oa, setPreferredCredential as Ob, ExtensionDefinition as Oc, PluginComponentStatus as Od, browseSkillSource as Of, isPaletteContext as Og, ModelApproval as Oh, RunSummaryTokens as Oi, LoadedExtension as Ol, serializeInteractionResponse as Om, artifactPath as On, ExtensionScanEntry as Oo, Command as Op, TailTruncateOptions as Or, GithubAnswer as Os, migrateSessionArtifactDirs as Ot, isValidExtensionConfigItem as Ou, EnvironmentSettingsChange as Ov, DecisionScoreQuestion as Ow, ProviderDecisionAvailability as Ox, cerebrasDescriptor as Oy, SqliteWriteQueue as P, credentialsFromParams as PC, ensureEndsWithUserMessage as PD, nonOwningMcpView as PE, local as PS, ThinkingDecay as PT, formatRunDuration as P_, DecisionUnsupportedError as Pa, accentColor as Pb, ExtensionManifest as Pc, isSupportedAgentPluginsVersion as Pd, SkillPickGroup as Pf, ExtensionPanelEntry as Pg, SessionEnvironmentSummary as Ph, PostCompactAttachments as Pi, ExtensionComposerBadge as Pl, zodToJsonSchema as Pm, EvalAgentRunResult as Pn, scanExtensionDirectories as Po, CommandInteraction as Pp, SkillsReadToolOptions as Pr, clockTime as Ps, resolveTasksDir as Pt, BadgeAction as Pu, readEnvironmentSettings as Pv, AgentRunOptions as Pw, StreamOptions as Px, localDescriptor as Py, MetricsHookSet as Q, IMAGE_ASPECT_RATIOS as QC, dropInvalidToolPairings as QD, ModelCatalogEntry as QE, googleCompatible as QS, ToolContext as QT, formatDuration as Q_, partitionExtensionCatalog as Qa, ContextUsageSplit as Qb, ExtensionReferenceCard as Qc, interpolateShellCommands as Qd, ChipColor as Qf, normalizePanelContent as Qg, defaultSessionKnobs as Qh, NO_TOOLS_PREAMBLE as Qi, ExtensionSessionControl as Ql, nextLogLevel as Qm, EvalVariantSummary as Qn, artifactKindLabel as Qo, AnswerValue as Qp, createGenerateImageTool as Qr, readGithubPull as Qs, buildZidaneExtensionSkill as Qt, ChildAgent as Qu, EnvironmentRegistry as Qv, McpOAuthClientConfig as Qw, normalizeOpenRouterModelId as Qx, ProviderUsageWindow as Qy, MutationValidationBatch as R, readAccountOAuthCredential as RC, reasoningWireAction as RD, isValidCallbackPort as RE, GoogleExtraModel as RS, ToolResultAudioContent as RT, formatTokensPerSecond as R_, AgentCompactOptions as Ra, ContextSegmentsInput as Rb, ExtensionMcpToolResult as Rc, writeSkillsToDisk as Rd, githubAvatarUrl as Rf, PanelContent as Rg, SpawnEndInfo as Rh, selectFilesFromReadState as Ri, ExtensionHudState as Rl, LogSink as Rm, EvalArtifacts as Rn, ExtensionPromptDelivery as Ro, CommandSpawnTask as Rp, createShellTool as Rr, githubClient as Rs, TOOL_USE_SKIPPED_MESSAGE as Rt, BadgeTarget as Ru, EnvironmentActionInput as Rv, CacheTtl as Rw, ToolSpec as Rx, modelsForDescriptor as Ry, formatTokenUsage as S, EXTENDED_CACHE_TTL_BETA as SC, createRemoteStore as SD, ShellInterpolationApproval as SE, classifyOpenAIError as SS, SessionHookContext as ST, truncateTitle as S_, Preset as Sa, readProviderCredential as Sb, ExtensionComposerSurface as Sc, defaultPluginDataRoot as Sd, SkillPathCandidate as Sf, PaletteProvider as Sg, EditDiffDisplay as Sh, RunSummaryBudget as Si, ExtensionToolResultMetadataRegistration as Sl, createAutomaticInteractionResponse as Sm, clearRegisteredEvals as Sn, parseExtensionInstallSource as So, applyInsert as Sp, runHeadless as Sr, pullChecks as Ss, PersistInput as St, ExtensionConfigValueItem as Su, toggleChainEntry as Sv, DecisionQuestion as Sw, installCacheBreakLogger as Sx, ModelOption as Sy, SqliteStoreFile as T, AnthropicContextManagement as TC, FileMapStoreOptions as TD, SkillResource as TE, toPiMessages as TS, SpawnHookContext as TT, RUN_RECEIPT_SWITCH_GLYPH as T_, createAgent as Ta, removeProviderCredential as Tb, ExtensionContributions as Tc, LoadAgentPluginOptions as Td, BrowseSkillSourceOptions as Tf, createPaletteRanker as Tg, EditOutcomeKind as Th, RunSummaryCollectorOptions as Ti, ExtensionToolVerdict as Tl, isModelInteraction as Tm, llmJudge as Tn, updateInstalledExtension as To, mergeReferences as Tp, waitTask as Tr, pullStateLook as Ts, buildPersistedStub as Tt, WireExtensionConfigSchema as Tu, EnvironmentFieldDescriptor as Tv, DecisionRequest as Tw, InputTransformation as Tx, ProviderUsageProbe as Ty, SuccessfulMutationOutcome as U, AnthropicThinkingPlan as UC, EnsureToolResultPairingOptions as UD, PinnedFetch as UE, GoogleStreamFn as US, ToolResultImageRefContent as UT, SpawnEndSummary as U_, McpToolMeta as Ua, ContextBreakdownOptions as Ub, ExtensionPaletteItem as Uc, isToolAllowedByUnion as Ud, skillPickOf as Uf, PanelKeyValueItem as Ug, DEFAULT_SPACE_NAME as Uh, CompactResult as Ui, ExtensionNotifyTone as Ul, consoleSink as Um, EvalRunMetricAggregate as Un, buildExtensionPreset as Uo, commandBlocksToContent as Up, multiEdit as Ur, createMemoryGithubStateStore as Us, isGhRateLimitError as Ut, badgePromptText as Uu, EnvironmentConfig as Uv, CompactFunction as Uw, XaiParams as Ux, AUTO_COMPACT_MIN_GROWTH_FRACTION as Uy, MutationValidationMutation as V, resolveOAuthApiKey as VC, toOpenAI as VD, resolveTransportConfig as VE, GoogleRouteName as VS, ToolResultDocumentRefContent as VT, runReceiptFromRun as V_, AgentToolState as Va, ContextBreakdownContributionContext as Vb, ExtensionOrderedContribution as Vc, SkillValidationIssue as Vd, skillCategory as Vf, PanelIcon as Vg, TranscriptDensity as Vh, CompactEndEvent as Vi, ExtensionNotification as Vl, LoggingHooksOptions as Vm, EvalDefinition as Vn, createMcpSurface as Vo, CommandStepFn as Vp, recordArtifact as Vr, normalizeGithubHost as Vs, applyCompactSummaryCutoff as Vt, artifactBadgeTarget as Vu, EnvironmentAvailability as Vv, ChildSpawnIdentity as Vw, planZaiReasoning as Vx, piIdOf as Vy, createMutationValidationHooks as W, THINKING_BINDING_SETTING_ENV as WC, ORPHANED_TOOL_RESULT_MARKER as WD, isAllowedRemoteUrl as WE, GoogleStreamOptions as WS, ToolResultMetadata as WT, ageStep as W_, McpToolWrap as Wa, ContextCategory as Wb, ExtensionPaletteProvider as Wc, matchesAllowedTool as Wd, IMPLICITLY_ALLOWED_SKILL_TOOLS as Wf, PanelKeyValueRow as Wg, SPACE_METADATA_KEY as Wh, CompactStartEvent as Wi, ExtensionStatusOptions as Wl, createLogger as Wm, EvalRunReporter as Wn, composeExtensionPreset as Wo, commandSteps as Wp, listFiles as Wr, GithubPull as Ws, rateLimitResetFromJson as Wt, builtinBadgeActions as Wu, EnvironmentConfigField as Wv, CompactHookContext as Ww, xai as Wx, AutoCompactDecision as Wy, Meter as X, OPENAI_IMAGE_MODELS as XC, SYNTHETIC_TOOL_RESULT_PLACEHOLDER as XD, isThinkingLevel as XE, fromGooglePiAssistantMessage as XS, toolOutputByteLength as XT, formatCostLabel as X_, filterRegistryPlugins as Xa, ContextMcpGroup as Xb, ExtensionPromptTransform as Xc, resolveSkills as Xd, resolveStorageDirs as Xf, PanelSection as Xg, activeSpaceOf as Xh, CompactPromptBuilder as Xi, ExtensionModelEntry as Xl, filterLogRecords as Xm, EvalScorer as Xn, serializedPayloadBytes as Xo, ASK_USER_TOOL as Xp, GenerateImageToolOptions as Xr, githubPullConfirmedAt as Xs, ZIDANE_EXTENSION_SKILL_NAME as Xt, runBadgeAction as Xu, EnvironmentPrepareResult as Xv, GeometricThinkingDecay as Xw, OPENROUTER_DEFAULT_MODEL as Xx, ProviderUsageSnapshot as Xy, InstrumentOptions as Y, openrouterImageModels as YC, RemintResult as YD, ThinkingLevel as YE, classifyGoogleError as YS, toolOutputBudgetByteLength as YT, fmtTokens as Y_, filterExtensionRegistry as Ya, ContextItem as Yb, ExtensionPermission as Yc, validateSkillName as Yd, StorageSlot as Yf, PanelRowItem as Yg, SpacesSettings as Yh, CompactDirection as Yi, ExtensionHostRuntimeImpl as Yl, LOG_LEVEL_CYCLE as Ym, EvalScore as Yn, createExtensionBus as Yo, useInteractionsQueue as Yp, DEFAULT_IMAGE_DIR as Yr, clearGithubPullMemory as Ys, SkillEditMarker as Yt, normalizeBadgeTarget as Yu, EnvironmentPrepareInput as Yv, FrozenPromptSections as Yw, sanitizeToolSpecs as Yx, ProviderUsageCredits as Yy, MetricAttributes as Z, GOOGLE_IMAGE_MODELS as ZC, TOOL_USE_INTERRUPTED_MARKER as ZD, ModelCatalog as ZE, google as ZS, toolResultToText as ZT, formatCount as Z_, mergeContributions as Za, ContextSnapshot as Zb, ExtensionProviderMiddleware as Zc, InterpolateShellCommandsOptions as Zd, BUILTIN_THEMES as Zf, isExtensionPanelScope as Zg, defaultSessionAgent as Zh, CompactPromptOptions as Zi, ExtensionRuntimeSurface as Zl, formatLogLine as Zm, EvalScorerContext as Zn, BUILTIN_ARTIFACT_KINDS as Zo, AUTOMATIC_INTERACTION_INSTRUCTION as Zp, ImageModelSource as Zr, queueGithubPull as Zs, ZIDANE_SKILL_EDIT_SKILL_NAME as Zt, sessionBadgeTarget as Zu, EnvironmentProvider as Zv, JsonValue as Zw, OpenRouterParams as Zx, ProviderUsageStatus as Zy, sectionDigests as _, classifyAnthropicError as _C, loadSession as _D, ToolStateStore as _E, toolResultsMessage as _S, ResolveContentRefBlock as _T, sessionEventExcerpt as __, defaultRepeatGuardTracked as _a, applyApiKeyEnv as _b, ExtensionBehaviorTransform as _c, expandPluginVars as _d, parseSkillContent as _f, PaletteContext as _g, profileTools as _h, providerTranscriptFormatForProvider as _i, ExtensionToolPolicy as _l, QuestionResponse as _m, functionalityMetric as _n, InstallExtensionFromSpecOptions as _o, CompletionContext as _p, efficiencyMetricValues as _r, githubPullView as _s, OAuthCallbackOptions as _t, ExtensionConfigNumberItem as _u, providerKeySetChanged as _v, DecisionInput as _w, CachePromptSections as _x, ProviderKey as _y, StartSpan as a, cursor as aC, Session as aD, ReadStateEntry as aE, ArtifactFilter as aO, OpenAICompatParams as aS, OAuthRefreshHookContext as aT, SESSION_EVENT_STATUS_STYLE as a_, ANCHOR_PREVIEW_MAX_CHARS as aa, resetLabel as ab, ExtensionApiVersion as ac, SubagentDef as ad, SkillInstallOptions as af, resolveSessionSpace as ag, BuiltInPrompt as ah, HeadlessResult as ai, ExtensionRunSettledEvent as al, InteractionsActions as am, withZidaneExtensionSkill as an, findReferences as ao, ThemeSelect as ap, TrajectoryStepKind as ar, renderArtifactRow as as, McpCredentialEntry as at, createExtensionHostRuntimeBridge as au, ModelChainEntry as av, ProviderImageResponse as aw, ActivationVia as ax, assertEnvironmentReady as ay, TokenUsageLike as b, resolveAnthropicAuthShape as bC, withExtensionSession as bD, isToolStateOps as bE, consumeSSE as bS, SessionContentBlock as bT, shortSessionId as b_, localReliabilityBehavior as ba, providerFactoryOptions as bb, ExtensionBusSurface as bc, validatePluginManifest as bd, skillCatalogEntry as bf, PaletteItem as bg, singleAgentRegistry as bh, RunSummary as bi, ExtensionToolRendererEntry as bl, TextQuestion as bm, formatEvalRunSummary as bn, installExtensionFromSpec as bo, CompletionReference as bp, normalizeMetric as br, isPullFresh as bs, PERSISTED_STUB_PREFIX as bt, ExtensionConfigSurface as bu, restoreChainFallbacks as bv, DecisionPredicateAnswer as bw, fnv1a32 as bx, CustomField as by, TracingHooksOptions as c, BasetenParams as cC, SessionMetaRow as cD, hashContent as cE, matchesArtifactFilter as cO, applyOAIToolCacheBreakpoint as cS, PromptAudioPart as cT, SessionEventStatus as c_, SummaryToTurnInput as ca, usageTone as cb, ExtensionArtifactQuery as cc, createSpawnTool as cd, installSkillFromSpec as cf, spaceMetadata as cg, DEFAULT_PERSIST_EXCLUDE_TOOLS as ch, OpenAIChatContentPart as ci, ExtensionRuntimeEnv as cl, PlanDecision as cm, RegisterEvalTestsOptions as cn, ExtensionFetchResult as co, resolveTheme as cp, EFFICIENCY_METRICS as cr, BUILTIN_REFERENCE_PROVIDERS as cs, McpOAuthProviderOptions as ct, ExtensionConfigActionResult as cu, chainEntryKey as cv, AgentDecisionsOptions as cw, SkillActivationState as cx, environmentActionSummaries as cy, FrozenSystemPrompt as d, ArceeParams as dC, SessionStore as dD, readStateKey as dE, selectArtifactEvictions as dO, classifyOpenAICompatError as dS, PromptPart as dT, WORKER_REPORT_FRAGMENT as d_, stripImagesFromTurns as da, OAuthCredential as db, ExtensionArtifactRow as dc, SpawnModelEntry as dd, readSkillProvenance as df, spaceSwitchItems as dg, availableAgents as dh, exitCodeForHeadlessResult as di, ExtensionSessionStateSurface as dl, PlanResponse as dm, runEvalCase as dn, ExtensionInstallErrorCode as do, createPathAutocompleteProvider as dp, MetricDirection as dr, GITHUB_PULL_PROVIDER_ID as ds, createMemoryMcpCredentialStore as dt, ExtensionConfigCategory as du, chainsEqualKeyed as dv, DecisionAnswers as dw, CacheBreakInfo as dx, runSessionEnvironmentAction as dy, loadGoogleWireKit as eC, ModelTier as eD, ToolDescriptionOverride as eE, remintDuplicateToolCallIds as eO, ASSISTANT_TOOL_CALLS_TAG as eS, McpToolHookContext as eT, panelBadgeText as e_, buildCompactPrompt as ea, activeSnapshotFor as eb, ArtifactDetectHookOptions as ec, SpawnTaskInput as ed, SKILL_PROVENANCE_FILE as ef, findSpace as eg, AgentProfile as eh, FormattedHeadlessResult as ei, ExtensionReferencePattern as el, CreateInteractionToolsOptions as em, editSessionMetadata as en, ReferenceProviderWire as eo, DEFAULT_THEME as ep, EvalWorkspaceOptions as er, commitKind as es, UpDownCounter as et, ExtensionSessionsSurface as eu, formatTaskStatus as ev, ImageData as ew, AgentHookBus as ex, EnvironmentState as ey, SectionChangeNote as f, arcee as fC, createSession as fD, resolveReadStateMap as fE, sortArtifacts as fO, formatTools as fS, PromptTextPart as fT, isMainSession as f_, summaryToTurn as fa, PreferCredentialResult as fb, ExtensionArtifactRowFact as fc, createModelSearchTool as fd, SourcedScanPath as ff, spacesEnabled as fg, builtInPromptOf as fh, formatHeadlessResult as fi, ExtensionSkillPolicy as fl, PlanStep as fm, buildEvalRunSummary as fn, ExtensionInstallIo as fo, resolveInlineSuggestion as fp, MetricEmitter as fr, fetchGithubPullRequest as fs, hasAuthorizationHeader as ft, ExtensionConfigChangeBehavior as fu, filterChainFallbacks as fv, DecisionChoiceAnswer as fw, CacheBreakLoggerOptions as fx, verifyEnvironment as fy, sectionDigest as g, resolveAnthropicMaxOutput as gC, getExtensionSessionState as gD, ToolStateOp as gE, toOAIMessages as gS, ResolveContentRef as gT, sessionDirLabel as g_, defaultRepeatGuardNormalize as ga, StoredCredential as gb, ExtensionBadgeTone as gc, PLUGIN_MCP_FILE as gd, parseFrontmatter as gf, PALETTE_RESULT_MAX as gg, profileComposition as gh, installHeadlessEventAdapter as gi, ExtensionToolCatalogTransform as gl, QuestionRequest as gm, fileExistsOneOf as gn, ExtensionInstallSource as go, ActiveTrigger as gp, defineMetrics as gr, githubPullUrl as gs, OAuthCallbackHandle as gt, ExtensionConfigModelItem as gu, positionKeyed as gv, DecisionFailureReason as gw, CacheDriftInfo as gx, ProviderAuth as gy, latestSystemSnapshot as h, defaultAnthropicMaxTokens as hC, demoteStaleRunningStatus as hD, ToolStateController as hE, openaiCompat as hS, RepeatGuardToolMatcher as hT, renderSessionEventXml as h_, generateStructuredData as ha, SetProviderCredentialOptions as hb, ExtensionBadgeIcon as hc, PLUGIN_SKILLS_DIR as hd, inferSource as hf, PALETTE_RECENT_GROUP as hg, compositionTools as hh, headlessEventToJsonl as hi, ExtensionStorageSurface as hl, QuestionPayload as hm, fileExists as hn, ExtensionInstallScope as ho, patchInlineGhost as hp, computeEvalTagScores as hr, githubPullReferenceProvider as hs, McpOAuthCallbackPageRenderer as ht, ExtensionConfigItemBase as hu, pickPrimaryKeyed as hv, DecisionFailure as hw, CacheDimensionSnapshot as hx, ProviderAccount as hy, Span as i, CursorParams as iC, LoadSessionOptions as iD, HydrateReadStateOptions as iE, ARTIFACT_META_MAX_BYTES as iO, OpenAICompatHttpError as iS, NestedToolCallRecord as iT, ProjectBrief as i_, buildUpToCompactPrompt as ia, mostConstrainedWindow as ib, ExtensionAgentPluginOptions as ic, SpawnToolState as id, SkillInstallErrorCode as if, readSessionSpaceId as ig, BUILTIN_AGENTS as ih, HeadlessOutputFormat as ii, ExtensionRegistry as il, InteractionResponse as im, resolveExtensionDocsDir as in, createReferenceResolver as io, ThemeColors as ip, TrajectoryStep as ir, refreshArtifact as is, loginMcpServer as it, createArtifactsSurface as iu, spawnStartParts as iv, ProviderImageRequest as iw, DecideHookContext as ix, SessionEnvironment as iy, SqliteDatabaseLike as j, OAuthParams as jC, TurnInterruptionState as jD, normalizeMcpBlocks as jE, mistral as jS, StreamUsageSnapshot as jT, RunReceiptSegmentKind as j_, DecisionHttpError as ja, storedCredentialsOf as jb, ExtensionGuiSurface as jc, PluginSchemaKind as jd, RecommendedSkillSource as jf, pushPaletteRecent as jg, Owner as jh, BYTES_PER_TOKEN as ji, TuiContributions as jl, StandardSchemaLike as jm, EvalAgent as jn, inlineLoadedExtension as jo, CommandAttachment as jp, createSkillsUseTool as jr, GithubIdentity as js, resolveMcpWarningsDir as jt, resolveExtensionConfigValue as ju, defaultEnvironmentKind as jv, DecisionUsage as jw, ProviderDecisions as jx, enabledModelOptions as jy, createReadonlySqliteSessionStore as k, derivePromptCacheKey as kC, ReasoningWireAction as kD, McpConnection as kE, planNeuralwattReasoning as kS, StreamHookContext as kT, RunReceiptCellKind as k_, DEFAULT_DECISION_TIMEOUT_MS as ka, setProviderCredential as kb, ExtensionFooterHint as kc, PluginDiagnostic as kd, clearSkillSourceCache as kf, normalizePaletteItems as kg, ModelApprovalChoice as kh, RunSummaryValidation as ki, LoadedPluginRecord as kl, InferSchemaOutput as km, relativeArtifactPath as kn, defaultExtensionScanPaths as ko, CommandAgentResult as kp, tailTruncate as kr, GithubClient as ks, resolveLegacyPersistDir as kt, isValidExtensionConfigValue as ku, EnvironmentSettingsWrite as kv, DecisionStartHookContext as kw, ProviderDecisionRequest as kx, credKeyOf as ky, createTracingHooks as l, baseten as lC, SessionRun as lD, hydrateReadStateFromSession as lE, mergeArtifact as lO, assistantMessage as lS, PromptDocumentPart as lT, SessionEventStatusStyle as l_, anchorPreviewFor as la, ApiKeyCredential as lb, ExtensionArtifactRendererEntry as lc, withIsolatedSpawnTool as ld, listSkillCandidates as lf, spaceModelDefault as lg, PLAN_AGENT as lh, OpenAIChatMessage as li, ExtensionSessionBadge as ll, PlanPayload as lm, createEvalRunReporter as ln, ExtensionInstallCandidate as lo, InlineAutocompleteContext as lp, EvalMetric as lr, GITHUB_ISSUE_PROVIDER_ID as ls, McpStaticClient as lt, ExtensionConfigActionStatus as lu, chainPositionOf as lv, DecisionAnswer as lw, SkillActivationStateOptions as lx, readSessionEnvironment as ly, catalogChangeNotes as m, cacheWriteTtlMultiplier as mC, deleteExtensionSessionState as mD, StagedToolState as mE, openAICompatPromptMessage as mS, RepeatGuardConfig as mT, parseSessionEventXml as m_, GenerateStructuredDataOptions as ma, ProviderCredential as mb, ExtensionBadgeColor as mc, matchModelEntries as md, getDefaultScanPaths as mf, PALETTE_RECENTS_MAX as mg, compositionFits as mh, formattedHeadlessTurnEventToJsonl as mi, ExtensionStorageScope as ml, QuestionChoice as mm, fileContentQuality as mn, ExtensionInstallResult as mo, InlineGhost as mp, MetricSpecMap as mr, githubIssueView as ms, saveMcpClientSecret as mt, ExtensionConfigItem as mu, pickChainPrimary as mv, DecisionEndHookContext as mw, CacheDimensionName as mx, AuthMethod as my, basicTools as n, resolveVertexAuth as nC, setModelCatalog as nD, ToolDescriptions as nE, ARTIFACTS_PER_SESSION_CAP as nO, OAITool as nS, ModelTarget as nT, resolvePanelLoadContext as n_, buildFullCompactPrompt as na, formatCredits as nb, ArtifactResolveOptions as nc, SpawnTool as nd, SkillInstallCandidate as nf, newSpaceId as ng, BUILD_AGENT as nh, HeadlessErrorInfo as ni, ExtensionReferenceSurface as nl, InteractionOrigin as nm, extensionScaffold as nn, ReferenceResolverOptions as no, SyntaxTokenStyle as np, MetricStats as nr, parseShortstat as ns, LoginMcpServerOptions as nt, ExtensionWorkspacePair as nu, previewLine as nv, MAX_IMAGES_PER_REQUEST as nw, AgentHookMap as nx, EnvironmentVerifyResult as ny, TracingConventions as o, CerebrasParams as oC, SessionData as oD, ReadStateMap as oE, SessionArtifact as oO, TOOL_RESULTS_TAG as oS, ProgressNudgeKind as oT, SESSION_ROLE_KEY as o_, CompactScope as oa, showsAccount as ob, ExtensionArtifactDetection as oc, SubagentOverride as od, SkillInstallResult as of, sessionSpaceFilter as og, DEFAULT_AGENT_ID as oh, HeadlessStatus as oi, ExtensionRunSettledHandler as ol, PRESENT_PLAN_TOOL as om, withZidaneSkillEditSkill as on, referenceProviderWires as oo, ThemeSurfaces as op, buildTrajectory as or, resolveArtifactKind as os, McpCredentialStore as ot, createWorkspaceSurface as ou, buildRunModel as ov, ProviderImages as ow, ActiveSkill as ox, availableEnvironmentActions as oy, announcedDigest as p, anthropic as pC, currentExtensionSession as pD, DEFAULT_MAX_VALUE_BYTES as pE, mapOAIFinishReason as pS, PromptVideoPart as pT, orchestratedBy as p_, truncateHeadForPtlRetry as pa, PreferredCredentialTarget as pb, ExtensionArtifactsSurface as pc, formatModelLine as pd, discoverSkills as pf, PALETTE_LIMITS as pg, compositionByKey as ph, formatHeadlessTurnEvent as pi, ExtensionSource as pl, Question as pm, fileContains as pn, ExtensionInstallProvenance as po, tokenEndingAtCursor as pp, MetricSpec as pr, githubIssueReferenceProvider as ps, mcpOAuthProviderFor as pt, ExtensionConfigEnumItem as pu, modelPickKey as pv, DecisionChoiceQuestion as pw, CacheDimensionDiff as px, workspacePath as py, Counter as q, resolveThinkingBinding as qC, PairingRepair as qD, attachStderrWarnPump as qE, GoogleWireKit as qS, TurnFinishReason as qT, describeSpawnEnd as q_, buildExtensionRegistry as qa, ContextExtensionRow as qb, ExtensionPaletteWhen as qc, validateResourcePathReal as qd, StorageDirs as qf, PanelLoadScope as qg, SpaceIcon as qh, CompactPromptTooLongError as qi, ExtensionArtifactScope as ql, fanoutSink as qm, EvalRunSummaryCase as qn, ExtensionBusChannel as qo, InteractionsProvider as qp, grep as qr, GithubPullState as qs, ExtensionEditMarker as qt, mergeBadgeMenu as qu, EnvironmentExecutionInput as qv, DedupHasher as qw, SchemaSanitizeResult as qx, effectiveContextWindow as qy, GEN_AI_ATTRIBUTES as r, toGooglePiMessages as rC, CreateSessionOptions as rD, ToolMap as rE, ARTIFACT_KINDS as rO, OpenAICompatAuthHeader as rS, ModelTargetSpec as rT, ORCHESTRATED_BY_KEY as r_, buildTailCompactPrompt as ra, formatUsagePercent as rb, EMPTY_EXTENSION_REGISTRY as rc, SpawnToolOptions as rd, SkillInstallError as rf, normalizeSpaces as rg, BUILD_CODEMODE_AGENT as rh, HeadlessEvent as ri, ExtensionReferenceView as rl, InteractionRequest as rm, readSkillEditMarker as rn, compileReferencePattern as ro, Theme as rp, Trajectory as rr, pullRequestKind as rs, LoginMcpServerResult as rt, ExtensionWorkspaceSurface as ru, shortId as rv, ProviderImageAvailability as rw, AgentHooks as rx, LOCAL_ENVIRONMENT as ry, TracingHookSet as s, cerebras as sC, SessionHistory as sD, getReadState as sE, SessionArtifactInput as sO, applyOAICacheBreakpoints as sS, ProgressNudgeMessage as sT, SessionEvent as s_, CompactionSlice as sa, updatedLabel as sb, ExtensionArtifactKindRegistration as sc, SubagentRegistry as sd, SkillInstallSpec as sf, spaceIdForNewSession as sg, DEFAULT_BUDGET_EXCLUDE_TOOLS as sh, HeadlessUsage as si, ExtensionRunTransform as sl, PendingInteractionEntry as sm, EvalTestRunner as sn, referenceProviders as so, resolveChipColor as sp, formatTrajectoryLine as sr, sessionBadges as ss, McpOAuthProvider as st, ExtensionConfigActionItem as su, chainAccountConflict as sv, AgentDecide as sw, DeactivationReason as sx, createEnvironmentRegistry as sy, _default as t, resolveGoogleModel as tC, getModelCatalog as tD, ToolDescriptionTarget as tE, ARTIFACTS_METADATA_KEY as tO, OAIMessage as tS, McpToolSchema as tT, panelShowsIn as t_, buildFromCompactPrompt as ta, formatBalance as tb, createArtifactDetectHook as tc, SpawnTaskOutcome as td, SkillCandidateDetail as tf, newSessionModel as tg, AgentRegistry as th, FormattedHeadlessTurnEvent as ti, ExtensionReferenceProvider as tl, HOST_INTERACTION_ID_PREFIX as tm, extensionDirForCwd as tn, ReferenceResolver as to, SyntaxStyles as tp, EvalWorkspaceSnapshot as tr, fileKind as ts, createMetricsHooks as tt, ExtensionWorkspaceOps as tu, formatTaskSummary as tv, ImageModelInfo as tw, AgentHookHandlers as tx, EnvironmentTeardownResult as ty, FROZEN_PROMPT_SECTION_KINDS as u, planBasetenReasoning as uC, SessionRunAgent as uD, hydrateReadStateFromSessionAsync as uE, normalizeArtifactInput as uO, buildAssistantContent as uS, PromptImagePart as uT, SessionEventTone as u_, sliceForCompaction as ua, CredentialsFile as ub, ExtensionArtifactRendererRegistration as uc, isSpawnTool as ud, parseSkillInstallSpec as uf, spaceOfSwitchItem as ug, ProfileSwitchNoteContext as uh, ProviderTranscriptFormat as ui, ExtensionSessionBadgeCardRow as ul, PlanRequest as um, registerEvalTests as un, ExtensionInstallError as uo, InlineAutocompleteProvider as up, EvalMetricError as ur, GITHUB_PULL_COLORS as us, clearMcpSignIn as ut, ExtensionConfigBooleanItem as uu, chainsEqual as uv, DecisionAnswerFor as uw, createSkillActivationState as ux, resolveExecution as uy, systemSnapshotTurn as v, buildAnthropicClientOptions as vC, resumeChainRunIds as vD, ToolStateView as vE, userMessage as vS, RetryConfig as vT, sessionEventLabel as v_, normalizeShellCommand as va, credentialsPath as vb, ExtensionBusEmitOptions as vc, ManifestValidation as vd, parseSkillFile as vf, PaletteGroup as vg, resolveAgentId as vh, transcriptToOpenAIMessages as vi, ExtensionToolRenderProps as vl, QuestionType as vm, statusCompleted as vn, InstalledExtensionTargetOptions as vo, CompletionItem as vp, emitEfficiencyMetrics as vr, githubRateLimitText as vs, OAuthCallbackResult as vt, ExtensionConfigScope as vu, rememberableChain as vv, DecisionInputKind as vw, CacheSystemSection as vx, detectAuth as vy, SqliteSessionStoreOptions as w, AnthropicBedrockConfig as wC, FileMapAdapter as wD, SkillDiagnostic as wE, openai as wS, SessionTurn as wT, RUN_RECEIPT_GLYPH as w_, definePreset as wa, readProviderCredentials as wb, ExtensionContextTransform as wc, AgentPluginsVersion as wd, skillCandidatesFromPaths as wf, RankedPaletteItem as wg, EditOutcome as wh, RunSummaryCollector as wi, ExtensionToolResultTransform as wl, isInteractionTool as wm, LlmJudgeOptions as wn, removeInstalledExtension as wo, findActiveTrigger as wp, WAIT_TASK_TIMED_OUT_PREFIX as wr, pullMeta as ws, SessionArtifactDirMigration as wt, WireExtensionConfigItem as wu, EnvironmentDescriptor as wv, DecisionRefusalAnswer as ww, HistoryRepair as wx, ProviderFactoryOptions as wy, flattenTurns as x, resolveAnthropicBetas as xC, RemoteStoreOptions as xD, stagedToolState as xE, OpenAIParams as xS, SessionEndStatus as xT, sideSessionParent as x_, _default$1 as xa, readCredentials as xb, ExtensionCapability as xc, PLUGIN_MANIFEST_FILE as xd, SKILL_CANDIDATE_MAX_DEPTH as xf, PaletteItemKind as xg, ApprovalMode as xh, RunSummaryBlock as xi, ExtensionToolRendererRegistration as xl, buildResumedToolResultsTurn as xm, buildRegisteredEvals as xn, listExtensionCandidates as xo, CompletionSubmitContext as xp, HeadlessOptions as xr, parseGithubRefKey as xs, PERSISTENCE_PREVIEW_BYTES as xt, ExtensionConfigValue as xu, sanitizeModelChain as xv, DecisionPredicateQuestion as xw, hashMessages as xx, ModelInfo as xy, ModelUsage as y, credentialIdentity as yC, setExtensionSessionState as yD, createToolStateController as yE, OpenAICompatStreamError as yS, RunHookMap as yT, sessionEventMeta as y_, stableStringify as ya, ensureCredentialIds as yb, ExtensionBusMessage as yc, parsePluginManifest as yd, buildCatalog as yf, PaletteHost as yg, sessionComposition as yh, transcriptToProviderMessages as yi, ExtensionToolRenderer as yl, SelectQuestion as ym, formatEvalCaseSummary as yn, fetchExtensionSource as yo, CompletionProvider as yp, finalizeEvalMetrics as yr, githubRefKey as ys, startOAuthCallback as yt, ExtensionConfigStringItem as yu, reorderKeyed as yv, DecisionOutcome as yw, diffCacheDimensions as yx, BUILTIN_PROVIDERS as yy, MutationValidationFailure as z, readOAuthCredentials as zC, sanitizeHistoryForProvider as zD, normalizeMcpServers as zE, GoogleParams as zS, ToolResultContent as zT, hasRunReceipt as z_, AgentCompactResult as za, buildContextSegments as zb, ExtensionModal as zc, SkillTokenWeights as zd, githubPreviewImageUrl as zf, PanelCustomItem as zg, StreamEvent as zh, selectFilesFromSession as zi, ExtensionHudStatus as zl, Logger as zm, EvalCaseOptions as zn, createExtensionPromptBridge as zo, CommandStep as zp, shell as zr, githubTokenFingerprint as zs, collectNewlyStaleReadPaths as zt, BadgeTargetKind as zu, EnvironmentActionResult as zv, ChildRunStats as zw, TurnResult as zx, openaiDescriptor as zy };
30582
+ //# sourceMappingURL=index-4mDRyTGJ.d.ts.map