zidane 5.14.5 → 6.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (198) hide show
  1. package/dist/{acp-BpFEbCMQ.js → acp-Irby04Us.js} +7 -8
  2. package/dist/{acp-BpFEbCMQ.js.map → acp-Irby04Us.js.map} +1 -1
  3. package/dist/acp-cli.js +7 -7
  4. package/dist/acp.d.ts +2 -3
  5. package/dist/acp.d.ts.map +1 -1
  6. package/dist/acp.js +1 -1
  7. package/dist/{agent-DyI0YsAR.js → agent-DkSmGkDM.js} +10873 -5437
  8. package/dist/agent-DkSmGkDM.js.map +1 -0
  9. package/dist/agent.d.ts +1 -2
  10. package/dist/agent.js +2 -2
  11. package/dist/{anthropic-cbfW2RGg.js → anthropic-CTHsdFG9.js} +5 -4
  12. package/dist/{anthropic-cbfW2RGg.js.map → anthropic-CTHsdFG9.js.map} +1 -1
  13. package/dist/{auth-D9uj0nNr.js → auth-BDSu_0t3.js} +13 -86
  14. package/dist/auth-BDSu_0t3.js.map +1 -0
  15. package/dist/chat/pure.d.ts +4 -4
  16. package/dist/chat/pure.js +4 -3
  17. package/dist/chat.d.ts +29 -8
  18. package/dist/chat.d.ts.map +1 -1
  19. package/dist/chat.js +9 -6
  20. package/dist/chat.js.map +1 -1
  21. package/dist/completion-core-CXYSVhZo.js +147 -0
  22. package/dist/completion-core-CXYSVhZo.js.map +1 -0
  23. package/dist/{context-breakdown-kO-pDsay.js → context-breakdown-Dzo25N45.js} +2 -23
  24. package/dist/context-breakdown-Dzo25N45.js.map +1 -0
  25. package/dist/contexts/daytona.d.ts +3 -3
  26. package/dist/contexts/daytona.js +1 -1
  27. package/dist/contexts/docker.d.ts +10 -2
  28. package/dist/contexts/docker.d.ts.map +1 -1
  29. package/dist/contexts/docker.js +142 -103
  30. package/dist/contexts/docker.js.map +1 -1
  31. package/dist/contexts/e2b.d.ts +2 -2
  32. package/dist/contexts/e2b.js +1 -1
  33. package/dist/contexts/sandbox.d.ts +1 -1
  34. package/dist/contexts/sandbox.js +4 -1
  35. package/dist/contexts/sandbox.js.map +1 -1
  36. package/dist/{contexts-Lzf5huID.js → contexts-Vone3qQQ.js} +26 -37
  37. package/dist/contexts-Vone3qQQ.js.map +1 -0
  38. package/dist/contexts.d.ts +3 -3
  39. package/dist/contexts.js +1 -1
  40. package/dist/errors.d.ts +1 -2
  41. package/dist/errors.js +1 -1
  42. package/dist/eval.d.ts +1 -1
  43. package/dist/eval.js +3 -3
  44. package/dist/exec-file-size-PXkr-MGA.js +63 -0
  45. package/dist/exec-file-size-PXkr-MGA.js.map +1 -0
  46. package/dist/extensions.d.ts +2 -0
  47. package/dist/extensions.js +2 -0
  48. package/dist/generate-data-WL_yGVL6.js +324 -0
  49. package/dist/generate-data-WL_yGVL6.js.map +1 -0
  50. package/dist/headless.d.ts +1 -1
  51. package/dist/headless.js +15 -10
  52. package/dist/headless.js.map +1 -1
  53. package/dist/index-B8UtiZy7.d.ts +14967 -0
  54. package/dist/index-B8UtiZy7.d.ts.map +1 -0
  55. package/dist/{index-B3ciFUZx.d.ts → index-DsPQbyUn.d.ts} +2 -2
  56. package/dist/index-DsPQbyUn.d.ts.map +1 -0
  57. package/dist/index.d.ts +6 -12
  58. package/dist/index.js +20 -43
  59. package/dist/index.js.map +1 -1
  60. package/dist/{logger-Ktm-lj1s.js → logger-DBX9uYOw.js} +108 -5
  61. package/dist/logger-DBX9uYOw.js.map +1 -0
  62. package/dist/login-DOF8pMVM.js +539 -0
  63. package/dist/login-DOF8pMVM.js.map +1 -0
  64. package/dist/{mcp-Dn5W65Lv.js → mcp-CcvuVXB9.js} +2 -2
  65. package/dist/{mcp-Dn5W65Lv.js.map → mcp-CcvuVXB9.js.map} +1 -1
  66. package/dist/mcp.d.ts +1 -1
  67. package/dist/mcp.js +1 -1
  68. package/dist/{messages-CozesxbB.js → messages-CwujiS74.js} +4 -4
  69. package/dist/messages-CwujiS74.js.map +1 -0
  70. package/dist/{openai-compat-FII_9wJP.js → openai-compat-BvgYGSR1.js} +5 -4
  71. package/dist/{openai-compat-FII_9wJP.js.map → openai-compat-BvgYGSR1.js.map} +1 -1
  72. package/dist/output/stream-json.d.ts +1 -2
  73. package/dist/output/stream-json.d.ts.map +1 -1
  74. package/dist/output/terminal.d.ts +1 -2
  75. package/dist/output/terminal.d.ts.map +1 -1
  76. package/dist/{glob-DluQFSw1.js → output-cap-kBUHBlnq.js} +50 -2
  77. package/dist/output-cap-kBUHBlnq.js.map +1 -0
  78. package/dist/presets.d.ts +1 -2
  79. package/dist/presets.js +1 -1
  80. package/dist/providers/anthropic.d.ts +1 -1
  81. package/dist/providers/anthropic.js +1 -1
  82. package/dist/providers/arcee.d.ts +1 -1
  83. package/dist/providers/arcee.js +1 -1
  84. package/dist/providers/baseten.d.ts +1 -1
  85. package/dist/providers/baseten.js +1 -1
  86. package/dist/providers/cerebras.d.ts +1 -1
  87. package/dist/providers/cerebras.js +1 -1
  88. package/dist/providers/local.d.ts +1 -1
  89. package/dist/providers/local.js +1 -1
  90. package/dist/providers/openai-compat.d.ts +1 -1
  91. package/dist/providers/openai-compat.js +1 -1
  92. package/dist/providers/openai.d.ts +1 -1
  93. package/dist/providers/openai.js +3 -3
  94. package/dist/providers/openrouter.d.ts +1 -1
  95. package/dist/providers/openrouter.js +1 -1
  96. package/dist/providers/xai.d.ts +1 -1
  97. package/dist/providers/xai.js +1 -1
  98. package/dist/{providers-DYXj2LcE.js → providers-z6LDMAr3.js} +3 -3
  99. package/dist/{providers-DYXj2LcE.js.map → providers-z6LDMAr3.js.map} +1 -1
  100. package/dist/providers.d.ts +1 -1
  101. package/dist/providers.js +4 -4
  102. package/dist/{read-state-BymF41Jb.js → read-state-Dq_TXUX1.js} +2 -2
  103. package/dist/{read-state-BymF41Jb.js.map → read-state-Dq_TXUX1.js.map} +1 -1
  104. package/dist/{interpolate-BtIgcCuz.js → resolve-Cr8JSL_O.js} +562 -136
  105. package/dist/resolve-Cr8JSL_O.js.map +1 -0
  106. package/dist/restate.d.ts +2 -2
  107. package/dist/restate.js +2 -2
  108. package/dist/{sandbox-Dgy-m6UF.d.ts → sandbox-CgjG2VvQ.d.ts} +2 -2
  109. package/dist/{sandbox-Dgy-m6UF.d.ts.map → sandbox-CgjG2VvQ.d.ts.map} +1 -1
  110. package/dist/session/sqlite.d.ts +1 -1
  111. package/dist/{session-BRCsZsXa.js → session-CsdDIPY8.js} +108 -3
  112. package/dist/session-CsdDIPY8.js.map +1 -0
  113. package/dist/session.d.ts +2 -2
  114. package/dist/session.js +3 -3
  115. package/dist/skills-Bsb0rvWI.js +295 -0
  116. package/dist/skills-Bsb0rvWI.js.map +1 -0
  117. package/dist/skills.d.ts +2 -3
  118. package/dist/skills.js +3 -24
  119. package/dist/{errors-CkTvg97v.d.ts → timeout-8vSIRjzl.d.ts} +10 -2
  120. package/dist/timeout-8vSIRjzl.d.ts.map +1 -0
  121. package/dist/{timeout-kGGSXagK.js → timeout-BDetbuN6.js} +59 -2
  122. package/dist/timeout-BDetbuN6.js.map +1 -0
  123. package/dist/tool-formatters-DY0TDb1r.d.ts +378 -0
  124. package/dist/tool-formatters-DY0TDb1r.d.ts.map +1 -0
  125. package/dist/tools/fetch-url.d.ts +1 -1
  126. package/dist/tools/web-search.d.ts +1 -1
  127. package/dist/tools.d.ts +2 -3
  128. package/dist/tools.js +3 -4
  129. package/dist/{transcript-anchors-BEKMYhfo.d.ts → transcript-anchors-Cb-bDbNH.d.ts} +231 -638
  130. package/dist/transcript-anchors-Cb-bDbNH.d.ts.map +1 -0
  131. package/dist/{transcript-anchors-DR4URysA.js → transcript-anchors-DSRPWjiH.js} +189 -984
  132. package/dist/transcript-anchors-DSRPWjiH.js.map +1 -0
  133. package/dist/tui.d.ts +329 -11
  134. package/dist/tui.d.ts.map +1 -1
  135. package/dist/tui.js +5367 -1418
  136. package/dist/tui.js.map +1 -1
  137. package/dist/{turn-operations-BhglWus_.d.ts → turn-operations-CgMROLsr.d.ts} +29 -4
  138. package/dist/turn-operations-CgMROLsr.d.ts.map +1 -0
  139. package/dist/{turn-operations-tG0vuBNc.js → turn-operations-Dq9Kx7m2.js} +321 -81
  140. package/dist/turn-operations-Dq9Kx7m2.js.map +1 -0
  141. package/dist/{types-BqdTeBaC.d.ts → types-BDccavwj.d.ts} +42 -1
  142. package/dist/types-BDccavwj.d.ts.map +1 -0
  143. package/dist/{types-CyVGdbia.js → types-BIarq1qE.js} +90 -2
  144. package/dist/types-BIarq1qE.js.map +1 -0
  145. package/dist/types.d.ts +5 -6
  146. package/dist/types.js +1 -1
  147. package/dist/{xai-D9tfkrIe.js → xai-B_e6TOA8.js} +2 -2
  148. package/dist/{xai-D9tfkrIe.js.map → xai-B_e6TOA8.js.map} +1 -1
  149. package/docs/EXECUTION_CONTEXT.md +16 -0
  150. package/docs/EXTENSIONS.md +1063 -0
  151. package/docs/SKILL.md +16 -0
  152. package/docs/TUI.md +4 -0
  153. package/package.json +12 -3
  154. package/dist/agent-DCtsviti.d.ts +0 -6955
  155. package/dist/agent-DCtsviti.d.ts.map +0 -1
  156. package/dist/agent-DyI0YsAR.js.map +0 -1
  157. package/dist/auth-D9uj0nNr.js.map +0 -1
  158. package/dist/context-breakdown-kO-pDsay.js.map +0 -1
  159. package/dist/contexts-Lzf5huID.js.map +0 -1
  160. package/dist/errors-CkTvg97v.d.ts.map +0 -1
  161. package/dist/glob-DluQFSw1.js.map +0 -1
  162. package/dist/glob-shell-rJMoCIGb.js +0 -21
  163. package/dist/glob-shell-rJMoCIGb.js.map +0 -1
  164. package/dist/index-B3ciFUZx.d.ts.map +0 -1
  165. package/dist/index-CIbemeZd.d.ts +0 -316
  166. package/dist/index-CIbemeZd.d.ts.map +0 -1
  167. package/dist/index-DsIW6pmv.d.ts +0 -2738
  168. package/dist/index-DsIW6pmv.d.ts.map +0 -1
  169. package/dist/interpolate-BtIgcCuz.js.map +0 -1
  170. package/dist/logger-Ktm-lj1s.js.map +0 -1
  171. package/dist/logger-mw-311EC.d.ts +0 -102
  172. package/dist/logger-mw-311EC.d.ts.map +0 -1
  173. package/dist/login-CCA-1lgK.js +0 -267
  174. package/dist/login-CCA-1lgK.js.map +0 -1
  175. package/dist/messages-CozesxbB.js.map +0 -1
  176. package/dist/policy-DcGlpaNs.d.ts +0 -129
  177. package/dist/policy-DcGlpaNs.d.ts.map +0 -1
  178. package/dist/presets-DtyUA1-S.js +0 -114
  179. package/dist/presets-DtyUA1-S.js.map +0 -1
  180. package/dist/run-summary-BExU5Flb.d.ts +0 -249
  181. package/dist/run-summary-BExU5Flb.d.ts.map +0 -1
  182. package/dist/session-BRCsZsXa.js.map +0 -1
  183. package/dist/shell-quote-BmnhZmdM.js +0 -33
  184. package/dist/shell-quote-BmnhZmdM.js.map +0 -1
  185. package/dist/skills.js.map +0 -1
  186. package/dist/timeout-CpFm0jJ6.d.ts +0 -10
  187. package/dist/timeout-CpFm0jJ6.d.ts.map +0 -1
  188. package/dist/timeout-kGGSXagK.js.map +0 -1
  189. package/dist/tool-formatters-CpCEWwKt.d.ts +0 -1525
  190. package/dist/tool-formatters-CpCEWwKt.d.ts.map +0 -1
  191. package/dist/tools-NSzbC6Nr.js +0 -1739
  192. package/dist/tools-NSzbC6Nr.js.map +0 -1
  193. package/dist/transcript-anchors-BEKMYhfo.d.ts.map +0 -1
  194. package/dist/transcript-anchors-DR4URysA.js.map +0 -1
  195. package/dist/turn-operations-BhglWus_.d.ts.map +0 -1
  196. package/dist/turn-operations-tG0vuBNc.js.map +0 -1
  197. package/dist/types-BqdTeBaC.d.ts.map +0 -1
  198. package/dist/types-CyVGdbia.js.map +0 -1
@@ -1,129 +0,0 @@
1
- //#region src/compact/policy.d.ts
2
- /**
3
- * Auto-compaction trigger policy + effective-context-window math.
4
- *
5
- * Core module (no chat / loop / provider-catalog dependency) so BOTH the
6
- * agent loop's loop-native auto-compaction AND the chat hosts share one
7
- * decision function. Previously `shouldAutoCompact` lived in `src/chat/`
8
- * and `effectiveContextWindow` in `src/chat/providers.ts`; the loop can't
9
- * import from `src/chat/`, so the policy lives here and chat re-exports it
10
- * for back-compat.
11
- *
12
- * Pure functions, no I/O. Same inputs -> same answer.
13
- */
14
- /**
15
- * Reserved output budget subtracted from the raw context window when
16
- * computing the effective ceiling for compaction / warning thresholds.
17
- *
18
- * Aligned with Claude Code's `COMPACT_MAX_OUTPUT_TOKENS = 20_000` — covers
19
- * p99.99 of summary + response output. A turn that consumed N input tokens
20
- * leaves `effectiveWindow - N` headroom for the next prompt's response; once
21
- * headroom shrinks below the threshold, auto-compaction fires.
22
- */
23
- declare const OUTPUT_RESERVE_TOKENS = 20000;
24
- /**
25
- * Effective context window — what the next user turn can actually pack
26
- * before the provider reserves space for the assistant's reply. Equals
27
- * `rawWindow - OUTPUT_RESERVE_TOKENS`, clamped to `>= 1` so a tiny
28
- * (or absurd) window doesn't yield zero / negative thresholds.
29
- *
30
- * Pass `null` through unchanged so callers can pipe a raw window lookup
31
- * directly without an intermediate check.
32
- */
33
- declare function effectiveContextWindow(rawWindow: number | null): number | null;
34
- /**
35
- * Default hysteresis floor for {@link shouldAutoCompact}. After a successful
36
- * compaction lands, the next compaction is suppressed until input usage
37
- * grows by at least this fraction of the effective context window beyond
38
- * the post-compact baseline.
39
- *
40
- * `0.1` = 10% of the window. Picked so the immediate post-compact bounce
41
- * (summary turn + restored attachments + re-emitted system prefix) never
42
- * re-fires the trigger by itself, but a meaningful chunk of new work
43
- * (one or two large tool reads) does. Tune via the predicate's
44
- * `minGrowthFraction` input if a host needs different ergonomics.
45
- */
46
- declare const AUTO_COMPACT_MIN_GROWTH_FRACTION = 0.1;
47
- /**
48
- * Inputs to {@link shouldAutoCompact}.
49
- *
50
- * Kept as a struct so the call site reads as the predicate it is, and so
51
- * future inputs (per-session opt-out, recent-compaction cooldown, …) land
52
- * without re-threading every consumer.
53
- */
54
- interface AutoCompactInput {
55
- /** User's master toggle. `false` → trigger never fires. */
56
- enabled: boolean;
57
- /**
58
- * Threshold expressed as a fraction of the effective context window
59
- * (e.g. `0.8` = 80%). Values outside the open interval `(0, 1)` are
60
- * rejected with `'invalid-threshold'` — `<= 0` is meaningless, and
61
- * `>= 1` would schedule the trigger for "after we've already
62
- * overflowed" which is too late to be useful.
63
- */
64
- threshold: number;
65
- /**
66
- * Latest input-token count from the last `turn:after`. Must be a
67
- * non-negative finite number; `NaN` / `±Infinity` / negative values
68
- * are treated as "no usable signal" and the trigger skips
69
- * conservatively (we'd rather defer compaction than fire on garbage).
70
- */
71
- inputTokens: number;
72
- /**
73
- * Model's raw context window. `null` for unknown / custom models — the
74
- * trigger skips since we can't compute a ratio.
75
- */
76
- rawContextWindow: number | null;
77
- /**
78
- * Whether a compaction is already in flight for this session. Passing it
79
- * through the predicate lets tests assert "doesn't double-fire" without
80
- * spinning up the agent loop.
81
- */
82
- alreadyCompacting?: boolean;
83
- /**
84
- * Input-token count observed immediately AFTER the most recent successful
85
- * compaction landed. Used together with {@link minGrowthFraction} to
86
- * suppress thrashing — after compaction lowers the prefix from 85% → 35%,
87
- * the next few turns drift back up; without hysteresis the trigger fires
88
- * again the instant the threshold is re-crossed, often before the model
89
- * has done any new work. Tracking the post-compact baseline lets the
90
- * predicate require meaningful new growth before re-firing.
91
- *
92
- * `undefined` (no compaction yet this session) → hysteresis disabled,
93
- * predicate behaves as before.
94
- */
95
- lastCompactedInputTokens?: number;
96
- /**
97
- * Minimum fraction of the effective context window that must be CONSUMED
98
- * by new content (i.e. `inputTokens - lastCompactedInputTokens`) before
99
- * a follow-up compaction fires. Expressed in the same units as
100
- * {@link threshold}, e.g. `0.1` = 10% of the window. Defaults to `0`
101
- * (no hysteresis) when omitted; chat hosts pick a value like `0.1`.
102
- *
103
- * Only consulted when {@link lastCompactedInputTokens} is set — first
104
- * compaction in a session always fires off the absolute threshold.
105
- */
106
- minGrowthFraction?: number;
107
- }
108
- type AutoCompactDecision = {
109
- kind: 'fire';
110
- usedFraction: number;
111
- effectiveWindow: number;
112
- } | {
113
- kind: 'skip';
114
- reason: 'disabled' | 'unknown-window' | 'invalid-threshold' | 'invalid-input-tokens' | 'under-threshold' | 'already-compacting' | 'cooldown';
115
- };
116
- /**
117
- * Decide whether auto-compaction should fire for the latest turn.
118
- *
119
- * Order of checks is deliberate: cheapest / most common skips first
120
- * (`disabled` is one boolean read; `unknown-window` is the predictable
121
- * miss for custom models), invariant violations next, then the actual
122
- * threshold math. `already-compacting` runs last so the diagnostic
123
- * surfaces correctly when the predicate is called inside an existing
124
- * compaction window.
125
- */
126
- declare function shouldAutoCompact(input: AutoCompactInput): AutoCompactDecision;
127
- //#endregion
128
- export { effectiveContextWindow as a, OUTPUT_RESERVE_TOKENS as i, AutoCompactDecision as n, shouldAutoCompact as o, AutoCompactInput as r, AUTO_COMPACT_MIN_GROWTH_FRACTION as t };
129
- //# sourceMappingURL=policy-DcGlpaNs.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"policy-DcGlpaNs.d.ts","names":[],"sources":["../src/compact/policy.ts"],"mappings":";;AAsBA;;;;AAAkC;AAWlC;;;;AAA+D;AAkB/D;;;;AAA6C;AAS7C;;;;;cAtCa,qBAAA;;;;;;;AA0FM;AAGnB;;iBAlFgB,sBAAA,CAAuB,SAAwB;;;;;;;;AAoFnC;AAY5B;;;;cA9Ea,gCAAA;;;;AA8EkE;;;;UArE9D,gBAAA;;EAEf,OAAA;;;;;;;;EAQA,SAAA;;;;;;;EAOA,WAAA;;;;;EAKA,gBAAA;;;;;;EAMA,iBAAA;;;;;;;;;;;;;EAaA,wBAAA;;;;;;;;;;;EAWA,iBAAA;AAAA;AAAA,KAGU,mBAAA;EACJ,IAAA;EAAc,YAAA;EAAsB,eAAA;AAAA;EACpC,IAAA;EAAc,MAAA;AAAA;;;;;;;;;;;iBAYN,iBAAA,CAAkB,KAAA,EAAO,gBAAA,GAAmB,mBAAmB"}
@@ -1,114 +0,0 @@
1
- import { r as waitTask, u as shell } from "./agent-DyI0YsAR.js";
2
- import { a as multiEdit, i as readFile, n as createSpawnTool, o as listFiles, r as shellKill, t as writeFile, u as edit } from "./tools-NSzbC6Nr.js";
3
- //#region src/presets/basic.ts
4
- /**
5
- * Core tools available in every basic preset (without spawn).
6
- *
7
- * `edit` and `multi_edit` ship in the basic set because surgical edits are the
8
- * default modality for production agents — `write_file` is for full overwrites.
9
- * `glob` and `grep` are exported but opt-in: not every agent needs codebase
10
- * search, and shipping them by default would force `tool:gate` work onto
11
- * consumers that prefer the model to use `shell` + classic Unix tools.
12
- */
13
- const basicTools = {
14
- shell,
15
- shellKill,
16
- waitTask,
17
- readFile,
18
- writeFile,
19
- listFiles,
20
- edit,
21
- multiEdit
22
- };
23
- var basic_default = definePreset({
24
- name: "basic",
25
- system: "You are a helpful assistant with access to shell, file reading, file writing, surgical and multi-edit tools, directory listing, and sub-agent spawning. Prefer `edit` / `multi_edit` for in-place changes and `write_file` for full file overwrites. Use them to accomplish tasks in the project directory.",
26
- get tools() {
27
- return {
28
- ...basicTools,
29
- spawn: createSpawnTool({ persist: true })
30
- };
31
- }
32
- });
33
- //#endregion
34
- //#region src/presets/index.ts
35
- /**
36
- * Identity helper for type inference when defining a preset.
37
- */
38
- function definePreset(config) {
39
- return config;
40
- }
41
- /**
42
- * Field-aware composition of presets. Right-most preset wins for scalar fields;
43
- * objects shallow-merge; arrays and hook handler lists concatenate. Designed so
44
- * stacking presets does the obvious thing without the spread-collision footgun:
45
- *
46
- * - `name`, `system`, `eager`, `skills` → last-defined wins
47
- * - `tools`, `toolAliases`, `behavior` → shallow-merge (later keys override)
48
- * - `behavior.dedupTools`, `behavior.toolBudgets` → **deep-merge** (per-tool-name; later wins on collision)
49
- * - `mcpServers` → concat with last-wins on `name` collision
50
- * - `hooks` → per-event concat; every handler fires
51
- *
52
- * `hooks` always emerges as `event → handler[]` so downstream registration
53
- * (in `createAgent`) sees a uniform shape. Order of handlers within an event
54
- * follows preset order: earlier presets register first.
55
- *
56
- * `mcpServers` is deduped by `name` because shipping two servers with the same
57
- * name would trip the connector at runtime — a later preset overriding an
58
- * earlier preset's `github` server is the practical intent.
59
- *
60
- * `behavior.dedupTools` and `behavior.toolBudgets` get the same per-key deep-merge
61
- * because they are tool-name-keyed records — a preset that ships a dedup hasher
62
- * for one tool should not erase a hasher another preset ships for a different
63
- * tool. Last-wins still applies on a per-tool collision so a downstream preset
64
- * can override an upstream preset's policy for one specific tool. Other
65
- * `behavior` fields keep last-wins semantics.
66
- */
67
- function composePresets(...presets) {
68
- const out = {};
69
- const hooksByEvent = {};
70
- const mcpByName = /* @__PURE__ */ new Map();
71
- for (const p of presets) {
72
- if (p.name !== void 0) out.name = p.name;
73
- if (p.system !== void 0) out.system = p.system;
74
- if (p.eager !== void 0) out.eager = p.eager;
75
- if (p.skills !== void 0) out.skills = p.skills;
76
- if (p.tools) out.tools = {
77
- ...out.tools,
78
- ...p.tools
79
- };
80
- if (p.toolAliases) out.toolAliases = {
81
- ...out.toolAliases,
82
- ...p.toolAliases
83
- };
84
- if (p.behavior) {
85
- const merged = {
86
- ...out.behavior,
87
- ...p.behavior
88
- };
89
- if (out.behavior?.dedupTools || p.behavior.dedupTools) merged.dedupTools = {
90
- ...out.behavior?.dedupTools,
91
- ...p.behavior.dedupTools
92
- };
93
- if (out.behavior?.toolBudgets || p.behavior.toolBudgets) merged.toolBudgets = {
94
- ...out.behavior?.toolBudgets,
95
- ...p.behavior.toolBudgets
96
- };
97
- out.behavior = merged;
98
- }
99
- if (p.mcpServers) for (const server of p.mcpServers) mcpByName.set(server.name, server);
100
- if (p.hooks) for (const [event, handler] of Object.entries(p.hooks)) {
101
- if (handler === void 0) continue;
102
- const list = Array.isArray(handler) ? handler : [handler];
103
- const key = event;
104
- (hooksByEvent[key] ??= []).push(...list);
105
- }
106
- }
107
- if (mcpByName.size > 0) out.mcpServers = [...mcpByName.values()];
108
- if (Object.keys(hooksByEvent).length > 0) out.hooks = hooksByEvent;
109
- return out;
110
- }
111
- //#endregion
112
- export { basic_default as i, definePreset as n, basicTools as r, composePresets as t };
113
-
114
- //# sourceMappingURL=presets-DtyUA1-S.js.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"presets-DtyUA1-S.js","names":[],"sources":["../src/presets/basic.ts","../src/presets/index.ts"],"sourcesContent":["import { definePreset } from '.'\nimport { edit, listFiles, multiEdit, readFile, shell, shellKill, waitTask, writeFile } from '../tools'\nimport { createSpawnTool } from '../tools/spawn'\n\n/**\n * Core tools available in every basic preset (without spawn).\n *\n * `edit` and `multi_edit` ship in the basic set because surgical edits are the\n * default modality for production agents — `write_file` is for full overwrites.\n * `glob` and `grep` are exported but opt-in: not every agent needs codebase\n * search, and shipping them by default would force `tool:gate` work onto\n * consumers that prefer the model to use `shell` + classic Unix tools.\n */\nexport const basicTools = { shell, shellKill, waitTask, readFile, writeFile, listFiles, edit, multiEdit }\n\nexport default definePreset({\n name: 'basic',\n system: 'You are a helpful assistant with access to shell, file reading, file writing, surgical and multi-edit tools, directory listing, and sub-agent spawning. Prefer `edit` / `multi_edit` for in-place changes and `write_file` for full file overwrites. Use them to accomplish tasks in the project directory.',\n // `tools` is a getter so each access (every `{ ...basic }` spread into\n // `createAgent`) mints a FRESH spawn tool. `createSpawnTool()` carries\n // per-instance state (running children, concurrency counter, child-stats\n // accumulator); a module-level singleton instance would be shared by every\n // agent in the process, breaking concurrent rollouts.\n //\n // `persist: true` shares the parent's session with every child agent — child\n // turns land in `session.turns` tagged with their own `runId`, and the run\n // itself is recorded in `session.runs` with `parentRunId` + `depth`. That's\n // what lets a reloaded TUI session reconstruct the full subagent tree (see\n // `eventsFromTurns` in `tui/store.ts`). Hosts that want children in-memory\n // only can construct their own preset with `createSpawnTool()`.\n get tools() {\n return { ...basicTools, spawn: createSpawnTool({ persist: true }) }\n },\n})\n","import type { AgentHooks, AgentOptions } from '../agent'\n\nexport type { AgentHookMap } from '../agent'\n\n/**\n * A preset is a reusable slice of `AgentOptions` — spread it into `createAgent()`\n * to configure tools, a default system prompt, aliases, behavior defaults, and\n * agent-lifetime hooks.\n *\n * `provider`, `execution`, `session`, and `mcpConnector` are excluded — they're\n * ambient / per-invocation runtime wiring (a custom `mcpConnector` is the MCP\n * connection seam, often closure-bound to a transport / auth provider), so\n * presets stay shareable and composable.\n *\n * ```ts\n * import { basic } from 'zidane/presets'\n * createAgent({ ...basic, provider })\n * ```\n *\n * ### Composing multiple presets\n *\n * Bare `...spread` is shallow — `{ ...a, ...b }` overwrites every key `b`\n * defines, including `hooks`. Use {@link composePresets} when you want\n * field-aware merging (per-event hook concat, tools shallow-merge, etc.):\n *\n * ```ts\n * createAgent({ ...composePresets(basic, telemetry, mine), provider })\n * ```\n */\nexport type Preset = Omit<Partial<AgentOptions>, 'provider' | 'execution' | 'session' | 'mcpConnector'>\n\n/**\n * Identity helper for type inference when defining a preset.\n */\nexport function definePreset(config: Preset): Preset {\n return config\n}\n\n/**\n * Field-aware composition of presets. Right-most preset wins for scalar fields;\n * objects shallow-merge; arrays and hook handler lists concatenate. Designed so\n * stacking presets does the obvious thing without the spread-collision footgun:\n *\n * - `name`, `system`, `eager`, `skills` → last-defined wins\n * - `tools`, `toolAliases`, `behavior` → shallow-merge (later keys override)\n * - `behavior.dedupTools`, `behavior.toolBudgets` → **deep-merge** (per-tool-name; later wins on collision)\n * - `mcpServers` → concat with last-wins on `name` collision\n * - `hooks` → per-event concat; every handler fires\n *\n * `hooks` always emerges as `event → handler[]` so downstream registration\n * (in `createAgent`) sees a uniform shape. Order of handlers within an event\n * follows preset order: earlier presets register first.\n *\n * `mcpServers` is deduped by `name` because shipping two servers with the same\n * name would trip the connector at runtime — a later preset overriding an\n * earlier preset's `github` server is the practical intent.\n *\n * `behavior.dedupTools` and `behavior.toolBudgets` get the same per-key deep-merge\n * because they are tool-name-keyed records — a preset that ships a dedup hasher\n * for one tool should not erase a hasher another preset ships for a different\n * tool. Last-wins still applies on a per-tool collision so a downstream preset\n * can override an upstream preset's policy for one specific tool. Other\n * `behavior` fields keep last-wins semantics.\n */\nexport function composePresets(...presets: Preset[]): Preset {\n const out: Preset = {}\n const hooksByEvent: { [K in keyof AgentHooks]?: AgentHooks[K][] } = {}\n // Keep mcpServers in source-order on first sight, but allow later\n // declarations to override earlier ones with the same `name`. A `Map`\n // keyed by name gives O(1) override + stable iteration.\n const mcpByName = new Map<string, NonNullable<Preset['mcpServers']>[number]>()\n\n for (const p of presets) {\n if (p.name !== undefined)\n out.name = p.name\n if (p.system !== undefined)\n out.system = p.system\n if (p.eager !== undefined)\n out.eager = p.eager\n if (p.skills !== undefined)\n out.skills = p.skills\n if (p.tools)\n out.tools = { ...out.tools, ...p.tools }\n if (p.toolAliases)\n out.toolAliases = { ...out.toolAliases, ...p.toolAliases }\n if (p.behavior) {\n // Top-level shallow-merge first; then deep-merge the two tool-name-keyed\n // sub-records so per-tool entries from earlier presets aren't clobbered.\n const merged: NonNullable<Preset['behavior']> = { ...out.behavior, ...p.behavior }\n if (out.behavior?.dedupTools || p.behavior.dedupTools) {\n merged.dedupTools = { ...out.behavior?.dedupTools, ...p.behavior.dedupTools }\n }\n if (out.behavior?.toolBudgets || p.behavior.toolBudgets) {\n merged.toolBudgets = { ...out.behavior?.toolBudgets, ...p.behavior.toolBudgets }\n }\n out.behavior = merged\n }\n if (p.mcpServers) {\n for (const server of p.mcpServers)\n mcpByName.set(server.name, server)\n }\n if (p.hooks) {\n for (const [event, handler] of Object.entries(p.hooks)) {\n if (handler === undefined)\n continue\n const list = Array.isArray(handler) ? handler : [handler]\n const key = event as keyof AgentHooks\n // Safe cast: we read the loose `AgentHookMap` shape (handler-or-array)\n // and re-emit only as arrays. Each `list` element matches the event's\n // handler signature by construction (the input was typed `AgentHookMap`).\n const bucket = (hooksByEvent[key] ??= []) as unknown[]\n bucket.push(...(list as unknown[]))\n }\n }\n }\n\n if (mcpByName.size > 0)\n out.mcpServers = [...mcpByName.values()]\n\n if (Object.keys(hooksByEvent).length > 0)\n out.hooks = hooksByEvent\n\n return out\n}\n\nexport { default as basic, basicTools } from './basic'\n"],"mappings":";;;;;;;;;;;;AAaA,MAAa,aAAa;CAAE;CAAO;CAAW;CAAU;CAAU;CAAW;CAAW;CAAM;AAAU;AAExG,IAAA,gBAAe,aAAa;CAC1B,MAAM;CACN,QAAQ;CAaR,IAAI,QAAQ;EACV,OAAO;GAAE,GAAG;GAAY,OAAO,gBAAgB,EAAE,SAAS,KAAK,CAAC;EAAE;CACpE;AACF,CAAC;;;;;;ACCD,SAAgB,aAAa,QAAwB;CACnD,OAAO;AACT;;;;;;;;;;;;;;;;;;;;;;;;;;;AA4BA,SAAgB,eAAe,GAAG,SAA2B;CAC3D,MAAM,MAAc,CAAC;CACrB,MAAM,eAA8D,CAAC;CAIrE,MAAM,4BAAY,IAAI,IAAuD;CAE7E,KAAK,MAAM,KAAK,SAAS;EACvB,IAAI,EAAE,SAAS,KAAA,GACb,IAAI,OAAO,EAAE;EACf,IAAI,EAAE,WAAW,KAAA,GACf,IAAI,SAAS,EAAE;EACjB,IAAI,EAAE,UAAU,KAAA,GACd,IAAI,QAAQ,EAAE;EAChB,IAAI,EAAE,WAAW,KAAA,GACf,IAAI,SAAS,EAAE;EACjB,IAAI,EAAE,OACJ,IAAI,QAAQ;GAAE,GAAG,IAAI;GAAO,GAAG,EAAE;EAAM;EACzC,IAAI,EAAE,aACJ,IAAI,cAAc;GAAE,GAAG,IAAI;GAAa,GAAG,EAAE;EAAY;EAC3D,IAAI,EAAE,UAAU;GAGd,MAAM,SAA0C;IAAE,GAAG,IAAI;IAAU,GAAG,EAAE;GAAS;GACjF,IAAI,IAAI,UAAU,cAAc,EAAE,SAAS,YACzC,OAAO,aAAa;IAAE,GAAG,IAAI,UAAU;IAAY,GAAG,EAAE,SAAS;GAAW;GAE9E,IAAI,IAAI,UAAU,eAAe,EAAE,SAAS,aAC1C,OAAO,cAAc;IAAE,GAAG,IAAI,UAAU;IAAa,GAAG,EAAE,SAAS;GAAY;GAEjF,IAAI,WAAW;EACjB;EACA,IAAI,EAAE,YACJ,KAAK,MAAM,UAAU,EAAE,YACrB,UAAU,IAAI,OAAO,MAAM,MAAM;EAErC,IAAI,EAAE,OACJ,KAAK,MAAM,CAAC,OAAO,YAAY,OAAO,QAAQ,EAAE,KAAK,GAAG;GACtD,IAAI,YAAY,KAAA,GACd;GACF,MAAM,OAAO,MAAM,QAAQ,OAAO,IAAI,UAAU,CAAC,OAAO;GACxD,MAAM,MAAM;GAKZ,CADgB,aAAa,SAAS,CAAC,GAChC,KAAK,GAAI,IAAkB;EACpC;CAEJ;CAEA,IAAI,UAAU,OAAO,GACnB,IAAI,aAAa,CAAC,GAAG,UAAU,OAAO,CAAC;CAEzC,IAAI,OAAO,KAAK,YAAY,EAAE,SAAS,GACrC,IAAI,QAAQ;CAEd,OAAO;AACT"}
@@ -1,249 +0,0 @@
1
- import { Tt as StreamOptions, r as AgentHooks } from "./agent-DCtsviti.js";
2
- import { Hookable } from "hookable";
3
-
4
- //#region src/cache-telemetry.d.ts
5
- /**
6
- * Snapshot of per-request dimensions that contribute to the provider-side
7
- * prompt cache key. Hashed at `turn:before` and stashed for diffing on the
8
- * next request.
9
- *
10
- * Hashes are FNV-1a 32-bit (cheap, no allocations on the hot path,
11
- * collision rate good enough for diff detection — we're not signing
12
- * anything). For verbose output the helper also captures byte lengths so
13
- * `system: 1024 → 1031` reads like a real diff line.
14
- */
15
- interface CacheDimensionSnapshot {
16
- /** Hash of `options.system` (with boundary marker preserved). */
17
- systemHash: number;
18
- /** Byte length of `options.system`. */
19
- systemBytes: number;
20
- /** Hash of the JSON-serialized `options.tools` array. */
21
- toolsHash: number;
22
- /** Number of tools in the array. */
23
- toolsCount: number;
24
- /** Model id. */
25
- model: string;
26
- /** Thinking level — `'off'` when absent. */
27
- thinking: string;
28
- /** Exact thinking budget — `0` when absent. */
29
- thinkingBudget: number;
30
- }
31
- /** Result of {@link diffCacheDimensions}. */
32
- interface CacheDimensionDiff {
33
- /** Dimension names whose hashes differ between the two snapshots. */
34
- changed: readonly CacheDimensionName[];
35
- /** Per-dimension details — only filled for changed dimensions. */
36
- details: Readonly<Partial<Record<CacheDimensionName, string>>>;
37
- }
38
- /** Cache-affecting dimension names. */
39
- type CacheDimensionName = 'system' | 'tools' | 'model' | 'thinking' | 'thinkingBudget';
40
- interface CacheBreakLoggerOptions {
41
- /**
42
- * Sink for log lines. Defaults to `console.error`. Use a {@link Logger} or
43
- * a test buffer here when you want the output to land somewhere other than
44
- * stderr.
45
- */
46
- log?: (line: string) => void;
47
- /**
48
- * When `true`, emit a log line on EVERY turn (not just cache breaks) with
49
- * the per-dimension hashes. Useful for offline correlation; off by default
50
- * to keep the logger zero-noise on happy paths.
51
- */
52
- verbose?: boolean;
53
- /**
54
- * Threshold for "this turn missed cache". The logger reports when
55
- * `cacheRead < expectedReadAtLeast` AND the dimensions differ from the
56
- * previous turn. Defaults to `1` — any cache read at all means the
57
- * provider matched some prefix, so a strict "did we get any cache?" check
58
- * is the right signal. Raise to detect partial-prefix breaks (e.g. the
59
- * tools cache hit but the system prompt didn't, which lowers `cacheRead`
60
- * without zeroing it).
61
- */
62
- expectedReadAtLeast?: number;
63
- }
64
- /**
65
- * FNV-1a-style 32-bit hash over UTF-16 code units. Pure, allocation-free,
66
- * ~10 ns per KB. Cryptographic strength is irrelevant here — we only need
67
- * change detection, and this has effectively zero collision risk for the
68
- * small number of dimensions tracked.
69
- *
70
- * Feeds the FULL char code into the mix (same as read-state's
71
- * `hashContent`) — masking to the low byte would collapse code points that
72
- * share a low byte, so a non-ASCII system-prompt change could hash
73
- * identically and silently hide a cache-dimension drift.
74
- *
75
- * Exported for tests; callers shouldn't typically import directly.
76
- */
77
- declare function fnv1a32(s: string): number;
78
- /**
79
- * Build a {@link CacheDimensionSnapshot} from a `turn:before` payload.
80
- *
81
- * Pure — exported so hosts can compute snapshots outside the logger (e.g.
82
- * stamping them onto custom telemetry spans). The hash is deterministic on
83
- * byte-identical inputs.
84
- */
85
- declare function snapshotCacheDimensions(options: StreamOptions): CacheDimensionSnapshot;
86
- /**
87
- * Compare two snapshots and return the list of dimensions whose bytes
88
- * differ. The `details` map carries a short human-readable description per
89
- * changed dimension (e.g. `system: 1024 → 1031 bytes`).
90
- *
91
- * Pure / no I/O. Use this in tests to assert the diff logic; the logger
92
- * itself just formats and emits the result.
93
- */
94
- declare function diffCacheDimensions(prev: CacheDimensionSnapshot, curr: CacheDimensionSnapshot): CacheDimensionDiff;
95
- /**
96
- * Install the cache-break logger on an agent's hook bus.
97
- *
98
- * Subscribes to `turn:before` (snapshot) + `turn:after` (compare with prior
99
- * snapshot, log breaks). Returns an `uninstall` fn that detaches both
100
- * listeners. Idempotent w.r.t. agent lifecycle — installs/uninstalls cleanly
101
- * across runs.
102
- *
103
- * Recommended setup:
104
- *
105
- * ```ts
106
- * const uninstall = installCacheBreakLogger(agent.hooks, {
107
- * log: line => logger.debug(line),
108
- * verbose: !!process.env.ZIDANE_DEBUG?.includes('cache'),
109
- * })
110
- * // ...
111
- * uninstall()
112
- * ```
113
- *
114
- * Performance: hashing runs on each `turn:before` and is bounded by the
115
- * input size (system + tools serialization). Disabled callers pay nothing
116
- * (don't install).
117
- */
118
- declare function installCacheBreakLogger(hooks: Hookable<AgentHooks>, options?: CacheBreakLoggerOptions): () => void;
119
- //#endregion
120
- //#region src/run-summary.d.ts
121
- interface RunSummaryTokens {
122
- input: number;
123
- output: number;
124
- cacheRead: number;
125
- cacheCreation: number;
126
- cost?: number;
127
- /** First observable byte from the provider, ms from run start. */
128
- ttftMs?: number;
129
- }
130
- interface RunSummaryByModel {
131
- modelId: string;
132
- input: number;
133
- output: number;
134
- cacheRead: number;
135
- cacheCreation: number;
136
- cost: number;
137
- turns: number;
138
- }
139
- interface RunSummaryError {
140
- kind: 'stream' | 'tool' | 'mcp-tool' | 'mcp' | 'spawn';
141
- message: string;
142
- errorType?: string;
143
- turnId?: string;
144
- callId?: string;
145
- server?: string;
146
- toolName?: string;
147
- childId?: string;
148
- statusCode?: number;
149
- requestId?: string;
150
- }
151
- interface RunSummaryBlock {
152
- callId: string;
153
- toolName: string;
154
- outcome: 'gate-block' | 'unknown' | 'invalid-input';
155
- reason?: string;
156
- }
157
- interface RunSummaryValidation {
158
- callId: string;
159
- toolName: string;
160
- reason: string;
161
- }
162
- interface RunSummaryBudget {
163
- kind: 'bytes' | 'tool-count';
164
- /** Tool name (for `'tool-count'`); absent for byte budgets. */
165
- toolName?: string;
166
- /** `mode` for `'tool-count'`; absent for byte budgets. */
167
- mode?: 'steer' | 'block';
168
- observed: number;
169
- limit: number;
170
- turnId?: string;
171
- }
172
- interface RunSummaryRepeatGuard {
173
- toolName: string;
174
- /** Observed repeat count that tripped the guard. */
175
- count: number;
176
- threshold: number;
177
- action: 'block' | 'steer' | 'abort';
178
- turnId?: string;
179
- }
180
- /**
181
- * Postmortem snapshot of one `agent.run()`. Strictly serializable — every
182
- * field round-trips through `JSON.stringify` / `JSON.parse` without loss
183
- * so a log aggregator can ingest it as-is.
184
- */
185
- interface RunSummary {
186
- runId?: string;
187
- parentRunId?: string;
188
- depth: number;
189
- agentName?: string;
190
- startedAt: number;
191
- endedAt: number;
192
- durationMs: number;
193
- status: 'completed' | 'aborted';
194
- turns: number;
195
- totals: RunSummaryTokens;
196
- byModel: RunSummaryByModel[];
197
- errors: RunSummaryError[];
198
- blocks: RunSummaryBlock[];
199
- validationRejects: RunSummaryValidation[];
200
- budgetEvents: RunSummaryBudget[];
201
- /**
202
- * Repeat-guard escalations. An `action: 'steer'` entry means the tool still
203
- * executed and got a steering message appended to its result. An
204
- * `action: 'abort'` entry means the guard terminated the run via the agent's
205
- * AbortController (the run finalizes as `'aborted'`).
206
- */
207
- repeatGuardEvents: RunSummaryRepeatGuard[];
208
- /** Counts of pairing repairs, keyed by repair mode. */
209
- pairingRepairs: Record<string, number>;
210
- /**
211
- * Postmortem snapshots of child runs that bubbled their stats up via
212
- * `spawn:complete`. Only present when the run actually spawned.
213
- */
214
- children?: RunSummary[];
215
- }
216
- interface RunSummaryCollectorOptions {
217
- /**
218
- * Called with the assembled {@link RunSummary} on every `agent:done`.
219
- * Synchronous — heavy I/O should be deferred (e.g. via `setImmediate`).
220
- */
221
- onSummary?: (summary: RunSummary) => void;
222
- }
223
- interface RunSummaryCollector {
224
- /** Install the collector's hook handlers. Returns an uninstall fn. */
225
- install: (hooks: Hookable<AgentHooks>) => () => void;
226
- /** Most-recent summary; `undefined` until the first `agent:done` fires. */
227
- latest: () => RunSummary | undefined;
228
- }
229
- /**
230
- * Build a run-summary collector. State is created fresh inside each
231
- * `install()` call, so a single collector instance can be installed
232
- * across multiple agents without attribution cross-talk. `latest()`
233
- * returns the most-recent summary across **any** install — install
234
- * per-agent collectors if you need separate post-run snapshots.
235
- *
236
- * @example
237
- * ```ts
238
- * const collector = createRunSummaryCollector({
239
- * onSummary: s => console.log(JSON.stringify(s)),
240
- * })
241
- * const uninstall = collector.install(agent.hooks)
242
- * try { await agent.run({ prompt }) }
243
- * finally { uninstall() }
244
- * ```
245
- */
246
- declare function createRunSummaryCollector(options?: RunSummaryCollectorOptions): RunSummaryCollector;
247
- //#endregion
248
- export { fnv1a32 as _, RunSummaryCollector as a, RunSummaryRepeatGuard as c, createRunSummaryCollector as d, CacheBreakLoggerOptions as f, diffCacheDimensions as g, CacheDimensionSnapshot as h, RunSummaryByModel as i, RunSummaryTokens as l, CacheDimensionName as m, RunSummaryBlock as n, RunSummaryCollectorOptions as o, CacheDimensionDiff as p, RunSummaryBudget as r, RunSummaryError as s, RunSummary as t, RunSummaryValidation as u, installCacheBreakLogger as v, snapshotCacheDimensions as y };
249
- //# sourceMappingURL=run-summary-BExU5Flb.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"run-summary-BExU5Flb.d.ts","names":[],"sources":["../src/cache-telemetry.ts","../src/run-summary.ts"],"mappings":";;;;AA8EA;;;;AAA8B;AAW9B;;;;;AAXA,UA1BiB,sBAAA;EAiDf;EA/CA,UAAA;EAyDmB;EAvDnB,WAAA;EA8Ec;EA5Ed,SAAA;;EAEA,UAAA;EA0E+B;EAxE/B,KAAA;EA2FqC;EAzFrC,QAAA;EAyFqF;EAvFrF,cAAA;AAAA;;UAIe,kBAAA;EAmFsE;EAjFrF,OAAA,WAAkB,kBAAA;EA0Ge;EAxGjC,OAAA,EAAS,QAAA,CAAS,OAAA,CAAQ,MAAA,CAAO,kBAAA;AAAA;;KAIvB,kBAAA;AAAA,UAWK,uBAAA;EA4FI;;;;;EAtFnB,GAAA,IAAO,IAAA;EAsFY;AAAA;AA2DrB;;;EA3IE,OAAA;EA4IO;;;;;;;;;EAlIP,mBAAA;AAAA;;;;AC7EF;;;;;;;;;;iBDoGgB,OAAA,CAAQ,CAAS;AC7FzB;AAGR;;;;;;AAHQ,iBDgHQ,uBAAA,CAAwB,OAAA,EAAS,aAAA,GAAgB,sBAAsB;;;;;;ACtGhF;AAGP;;iBD4HgB,mBAAA,CACd,IAAA,EAAM,sBAAA,EACN,IAAA,EAAM,sBAAA,GACL,kBAAA;;;;;;;;;;;;;ACrHQ;AAGX;;;;;;;;;AAIQ;iBDyKQ,uBAAA,CACd,KAAA,EAAO,QAAA,CAAS,UAAA,GAChB,OAAA,GAAS,uBAAA;;;UChNM,gBAAA;EACf,KAAA;EACA,MAAA;EACA,SAAA;EACA,aAAA;EACA,IAAA;EDmC0B;ECjC1B,MAAA;AAAA;AAAA,UAGe,iBAAA;EACf,OAAA;EACA,KAAA;EACA,MAAA;EACA,SAAA;EACA,aAAA;EACA,IAAA;EACA,KAAA;AAAA;AAAA,UAGe,eAAA;EACf,IAAA;EACA,OAAA;EACA,SAAA;EACA,MAAA;EACA,MAAA;EACA,MAAA;EACA,QAAA;EACA,OAAA;EACA,UAAA;EACA,SAAA;AAAA;AAAA,UAGe,eAAA;EACf,MAAA;EACA,QAAA;EACA,OAAA;EACA,MAAA;AAAA;AAAA,UAGe,oBAAA;EACf,MAAA;EACA,QAAA;EACA,MAAA;AAAA;AAAA,UAGe,gBAAA;EACf,IAAA;EDmGM;ECjGN,QAAA;EDkGmB;EChGnB,IAAA;EACA,QAAA;EACA,KAAA;EACA,MAAA;AAAA;AAAA,UAGe,qBAAA;EACf,QAAA;EDyFmB;ECvFnB,KAAA;EACA,SAAA;EACA,MAAA;EACA,MAAA;AAAA;;;;;;UAQe,UAAA;EACf,KAAA;EACA,WAAA;EACA,KAAA;EACA,SAAA;EACA,SAAA;EACA,OAAA;EACA,UAAA;EACA,MAAA;EACA,KAAA;EACA,MAAA,EAAQ,gBAAA;EACR,OAAA,EAAS,iBAAA;EACT,MAAA,EAAQ,eAAA;EACR,MAAA,EAAQ,eAAA;EACR,iBAAA,EAAmB,oBAAA;EACnB,YAAA,EAAc,gBAAA;EAjFd;;;AAEM;AAGR;;EAmFE,iBAAA,EAAmB,qBAAA;EAnFa;EAqFhC,cAAA,EAAgB,MAAA;EAnFhB;;;;EAwFA,QAAA,GAAW,UAAA;AAAA;AAAA,UAOI,0BAAA;EA1FV;AAGP;;;EA4FE,SAAA,IAAa,OAAA,EAAS,UAAU;AAAA;AAAA,UAGjB,mBAAA;EA5Ff;EA8FA,OAAA,GAAU,KAAA,EAAO,QAAA,CAAS,UAAA;EA5F1B;EA8FA,MAAA,QAAc,UAAA;AAAA;;;;;AAzFL;AAGX;;;;;;;;;AAIQ;AAGR;;iBAmGgB,yBAAA,CACd,OAAA,GAAS,0BAAA,GACR,mBAAmB"}
@@ -1 +0,0 @@
1
- {"version":3,"file":"session-BRCsZsXa.js","names":[],"sources":["../src/session/file-map.ts","../src/session/memory.ts","../src/session/remote.ts","../src/session/index.ts"],"sourcesContent":["/**\n * File-map session store.\n *\n * Wraps a narrow 3-method adapter (`get` / `save` / `delete`) that exchanges a flat\n * map of filename → string content. Useful for embedding zidane sessions inside\n * host-provided session backends that only speak in file maps (not zidane's native\n * `SessionStore` shape).\n *\n * Serialization format:\n * - `turns.jsonl` — one `SessionTurn` per line.\n * - `meta.json` — session metadata (id, agentId, status, runs, metadata, timestamps).\n *\n * JSONL for turns keeps history inspectable with tools like `jq` and resilient to\n * partial corruption — parse up to the first bad line and you still have a valid\n * prefix. Metadata lives in its own file so large turn logs don't bloat the\n * metadata path.\n *\n * Scope: each `createFileMapStore` handles a **single session** — the adapter's\n * file map holds at most one zidane session at a time. This matches how host SDKs\n * scope their session stores per conversation.\n *\n * Divergences from the built-in memory / sqlite stores:\n * - `appendTurns` / `updateStatus` / `updateRun` auto-create a minimal `SessionData`\n * record on first write, instead of silently no-oping when the session hasn't been\n * explicitly `save()`-ed. This matches the host-SDK integration path where\n * `createSession(...)` → `agent.run(...)` directly without an explicit `save()` call.\n * - `updateRun` inserts the run if not found in the cached record (rather than\n * silently dropping). Run records therefore always reach the adapter.\n */\n\nimport type { SessionData, SessionRun, SessionStore } from '.'\nimport type { SessionTurn } from '../types'\n\n/**\n * Host-provided file-map adapter. Three methods exchanging `Record<string, string>`\n * payloads — the whole persistence surface the wrapper needs.\n */\nexport interface FileMapAdapter {\n /** Load the current file map. Returns an empty `files` record when nothing is persisted. */\n get: () => Promise<{ files: Record<string, string> }>\n /** Replace the persisted file map. Full-rewrite semantics. */\n save: (files: Record<string, string>) => Promise<void>\n /** Delete all persisted state. */\n delete: () => Promise<void>\n}\n\nexport interface FileMapStoreOptions {\n /** Filename for the JSONL turns log. Default: `turns.jsonl`. */\n turnsFile?: string\n /** Filename for the metadata JSON. Default: `meta.json`. */\n metaFile?: string\n}\n\ninterface MetaShape {\n id: string\n agentId?: string\n /** Optional — absent on files written before projectRoot persistence. */\n projectRoot?: string\n runs: SessionRun[]\n status: SessionData['status']\n metadata: Record<string, unknown>\n createdAt: number\n updatedAt: number\n}\n\nfunction toMeta(data: SessionData): MetaShape {\n return {\n id: data.id,\n agentId: data.agentId,\n projectRoot: data.projectRoot,\n runs: data.runs,\n status: data.status,\n metadata: data.metadata,\n createdAt: data.createdAt,\n updatedAt: data.updatedAt,\n }\n}\n\nfunction toData(meta: MetaShape, turns: SessionTurn[]): SessionData {\n return {\n id: meta.id,\n agentId: meta.agentId,\n ...(typeof meta.projectRoot === 'string' ? { projectRoot: meta.projectRoot } : {}),\n turns,\n runs: meta.runs,\n status: meta.status,\n metadata: meta.metadata,\n createdAt: meta.createdAt,\n updatedAt: meta.updatedAt,\n }\n}\n\nfunction parseTurnsJsonl(jsonl: string): SessionTurn[] {\n if (!jsonl)\n return []\n const turns: SessionTurn[] = []\n for (const line of jsonl.split('\\n')) {\n const trimmed = line.trim()\n if (!trimmed)\n continue\n try {\n turns.push(JSON.parse(trimmed) as SessionTurn)\n }\n catch {\n // Skip malformed lines — preserves the valid prefix on partial corruption.\n }\n }\n return turns\n}\n\nfunction serializeTurnsJsonl(turns: SessionTurn[]): string {\n if (turns.length === 0)\n return ''\n return `${turns.map(t => JSON.stringify(t)).join('\\n')}\\n`\n}\n\n/**\n * Create a single-session `SessionStore` backed by a file-map adapter.\n *\n * @example\n * ```ts\n * const session = await createSession({\n * store: createFileMapStore(hostSessionStore),\n * })\n * ```\n */\nexport function createFileMapStore(\n adapter: FileMapAdapter,\n options: FileMapStoreOptions = {},\n): SessionStore {\n const turnsFile = options.turnsFile ?? 'turns.jsonl'\n const metaFile = options.metaFile ?? 'meta.json'\n\n // Cached view of the persisted session. Populated lazily on first access so the\n // factory itself doesn't do I/O.\n let cached: SessionData | null = null\n let hydrated = false\n // In-flight hydrate memo: concurrent first calls share one adapter.get()\n // instead of racing two reads (the loser's view would clobber the winner's\n // subsequent writes — a lost-update race).\n let hydrating: Promise<void> | null = null\n // Turns salvaged from turns.jsonl when meta.json was present but corrupt.\n // We can't trust the (unparseable) meta for the session id, so we hold the\n // turns aside and re-attach them when the next write establishes an id —\n // the alternative (treating the session as missing) would let that write\n // overwrite an intact turns.jsonl with an empty one.\n let recoveredTurns: SessionTurn[] | null = null\n\n async function hydrate(): Promise<void> {\n if (hydrated)\n return\n if (!hydrating) {\n hydrating = (async () => {\n const { files } = await adapter.get()\n const metaRaw = files[metaFile]\n if (metaRaw) {\n let meta: MetaShape | null = null\n try {\n meta = JSON.parse(metaRaw) as MetaShape\n }\n catch {\n meta = null\n }\n if (meta) {\n cached = toData(meta, parseTurnsJsonl(files[turnsFile] ?? ''))\n }\n else {\n recoveredTurns = parseTurnsJsonl(files[turnsFile] ?? '')\n console.error(`[zidane/file-map] ${metaFile} exists but is not valid JSON — preserving ${recoveredTurns.length} turn(s) from ${turnsFile} for the next write instead of treating the session as missing`)\n }\n }\n hydrated = true\n })().finally(() => {\n hydrating = null\n })\n }\n return hydrating\n }\n\n async function persist(data: SessionData): Promise<void> {\n const meta = toMeta(data)\n await adapter.save({\n [metaFile]: JSON.stringify(meta, null, 2),\n [turnsFile]: serializeTurnsJsonl(data.turns),\n })\n }\n\n // Ensure `cached` exists for `sessionId`, creating a minimal record when first written.\n // Returns false when `cached` already holds a different sessionId (request ignored).\n async function ensureCachedFor(sessionId: string): Promise<boolean> {\n await hydrate()\n if (cached) {\n return cached.id === sessionId\n }\n const now = Date.now()\n cached = {\n id: sessionId,\n // Re-attach turns salvaged from a corrupt-meta hydrate so the next\n // persist() doesn't destroy an intact turns.jsonl.\n turns: recoveredTurns ?? [],\n runs: [],\n status: 'idle',\n metadata: {},\n createdAt: now,\n updatedAt: now,\n }\n recoveredTurns = null\n hydrated = true\n return true\n }\n\n return {\n async load(sessionId: string): Promise<SessionData | null> {\n await hydrate()\n if (!cached || cached.id !== sessionId)\n return null\n return structuredClone(cached)\n },\n\n async save(data: SessionData): Promise<void> {\n cached = structuredClone(data)\n hydrated = true\n await persist(cached)\n },\n\n async delete(sessionId: string): Promise<void> {\n await hydrate()\n if (cached && cached.id !== sessionId)\n return\n cached = null\n await adapter.delete()\n },\n\n async list(filter): Promise<string[]> {\n await hydrate()\n if (!cached)\n return []\n if (filter?.agentId && cached.agentId !== filter.agentId)\n return []\n // file-map stores exactly one session, so the projectRoot filter\n // either keeps it (match / axis off) or drops it entirely.\n if (filter && 'projectRoot' in filter) {\n const v = filter.projectRoot\n if (v === null && cached.projectRoot != null)\n return []\n if (typeof v === 'string' && cached.projectRoot !== v)\n return []\n }\n return [cached.id]\n },\n\n async appendTurns(sessionId: string, turns: SessionTurn[]): Promise<void> {\n const ok = await ensureCachedFor(sessionId)\n if (!ok)\n return\n cached!.turns.push(...structuredClone(turns))\n cached!.updatedAt = Date.now()\n await persist(cached!)\n },\n\n async getTurns(sessionId: string, from = 0, limit?: number): Promise<SessionTurn[]> {\n await hydrate()\n if (!cached || cached.id !== sessionId)\n return []\n const slice = cached.turns.slice(from, limit !== undefined ? from + limit : undefined)\n return structuredClone(slice) as SessionTurn[]\n },\n\n async updateRun(sessionId: string, run: SessionRun): Promise<void> {\n const ok = await ensureCachedFor(sessionId)\n if (!ok)\n return\n const idx = cached!.runs.findIndex(r => r.id === run.id)\n if (idx >= 0)\n cached!.runs[idx] = structuredClone(run)\n else\n cached!.runs.push(structuredClone(run))\n cached!.updatedAt = Date.now()\n await persist(cached!)\n },\n\n async updateStatus(sessionId: string, status: SessionData['status']): Promise<void> {\n const ok = await ensureCachedFor(sessionId)\n if (!ok)\n return\n cached!.status = status\n cached!.updatedAt = Date.now()\n await persist(cached!)\n },\n }\n}\n","/**\n * In-memory session store.\n * Useful for development and testing. Data is lost when the process exits.\n */\n\nimport type { SessionData, SessionRun, SessionStore } from '.'\nimport type { SessionTurn } from '../types'\n\nexport function createMemoryStore(): SessionStore {\n const sessions = new Map<string, SessionData>()\n\n // Auto-create a minimal record when turns arrive for an unknown id. Mirrors\n // the file-map store: `createSession({store})` + `agent.run()` appends\n // turns without an explicit `save()` first — a get-or-no-op `appendTurns`\n // would silently lose that history. Deliberately scoped to `appendTurns`\n // only: a late `updateRun`/`updateStatus` racing a `delete()` must stay a\n // no-op rather than resurrect a deleted session.\n function ensureSession(sessionId: string): SessionData {\n let data = sessions.get(sessionId)\n if (!data) {\n const now = Date.now()\n data = {\n id: sessionId,\n turns: [],\n runs: [],\n status: 'idle',\n metadata: {},\n createdAt: now,\n updatedAt: now,\n }\n sessions.set(sessionId, data)\n }\n return data\n }\n\n return {\n async load(sessionId: string) {\n const data = sessions.get(sessionId)\n return data ? structuredClone(data) : null\n },\n\n async save(session: SessionData) {\n sessions.set(session.id, structuredClone(session))\n },\n\n async delete(sessionId: string) {\n sessions.delete(sessionId)\n },\n\n async list(filter) {\n let ids = Array.from(sessions.keys())\n if (filter?.agentId) {\n ids = ids.filter(id => sessions.get(id)?.agentId === filter.agentId)\n }\n // `projectRoot` mirrors the SQLite store's tri-state contract:\n // string → only sessions tagged with that root\n // null → only UNTAGGED sessions (legacy / pre-v3 rows)\n // undefined → axis ignored (tagged + untagged both returned)\n if (filter && 'projectRoot' in filter) {\n const v = filter.projectRoot\n if (v === null)\n ids = ids.filter(id => sessions.get(id)?.projectRoot == null)\n else if (typeof v === 'string')\n ids = ids.filter(id => sessions.get(id)?.projectRoot === v)\n }\n if (filter?.limit) {\n ids = ids.slice(0, filter.limit)\n }\n return ids\n },\n\n async appendTurns(sessionId: string, turns: SessionTurn[]) {\n const data = ensureSession(sessionId)\n data.turns.push(...structuredClone(turns))\n data.updatedAt = Date.now()\n },\n\n async getTurns(sessionId: string, from = 0, limit?: number) {\n const data = sessions.get(sessionId)\n if (!data)\n return []\n const sliced = data.turns.slice(from, limit !== undefined ? from + limit : undefined)\n return structuredClone(sliced) as SessionTurn[]\n },\n\n async updateRun(sessionId: string, run: SessionRun) {\n const data = sessions.get(sessionId)\n if (!data)\n return\n // Upsert — see the matching comment in sqlite.ts's\n // `txnUpdateRun` for the failure mode. tl;dr: the agent's\n // `startRun()` only updates in-memory state; the store first\n // sees the run via `updateRun()` at finalize time, so an\n // update-only impl silently drops every new run.\n const idx = data.runs.findIndex(r => r.id === run.id)\n if (idx >= 0)\n data.runs[idx] = structuredClone(run)\n else\n data.runs.push(structuredClone(run))\n data.updatedAt = Date.now()\n },\n\n async updateStatus(sessionId: string, status: SessionData['status']) {\n const data = sessions.get(sessionId)\n if (!data)\n return\n data.status = status\n data.updatedAt = Date.now()\n },\n }\n}\n","/**\n * Remote session store via HTTP API.\n *\n * Expects a REST API with:\n * GET {url}/sessions/{id} -> SessionData | 404\n * PUT {url}/sessions/{id} -> save SessionData\n * DELETE {url}/sessions/{id} -> delete\n * GET {url}/sessions?agentId=&limit=&projectRoot= -> { ids: string[] }\n * `projectRoot=__null__` is the wire encoding for \"untagged only\".\n * POST {url}/sessions/{id}/turns -> append turns\n * GET {url}/sessions/{id}/turns?from=&limit= -> SessionTurn[]\n * PUT {url}/sessions/{id}/runs/{runId} -> update run\n * PATCH {url}/sessions/{id} -> { status }\n */\n\nimport type { SessionData, SessionRun, SessionStore } from '.'\nimport type { SessionTurn } from '../types'\n\nexport interface RemoteStoreOptions {\n /** Base URL of the session API */\n url: string\n /** Optional headers (e.g. for authentication) */\n headers?: Record<string, string>\n /** Per-request timeout in ms. Default 30s — bounds a hung backend. */\n timeoutMs?: number\n}\n\nconst TRAILING_SLASH = /\\/$/\nconst DEFAULT_TIMEOUT_MS = 30_000\n\nexport function createRemoteStore(options: RemoteStoreOptions): SessionStore {\n const baseUrl = options.url.replace(TRAILING_SLASH, '')\n const timeoutMs = options.timeoutMs ?? DEFAULT_TIMEOUT_MS\n const defaultHeaders: Record<string, string> = {\n 'Content-Type': 'application/json',\n ...options.headers,\n }\n\n async function request(path: string, init?: RequestInit): Promise<Response> {\n const url = `${baseUrl}${path}`\n // Bound every call so a hung backend can't wedge the caller forever.\n const res = await fetch(url, {\n ...init,\n headers: { ...defaultHeaders, ...init?.headers },\n signal: init?.signal ?? AbortSignal.timeout(timeoutMs),\n })\n return res\n }\n\n /**\n * Parse a JSON response body, rethrowing parse failures with URL/status\n * context so a malformed backend reply produces a diagnosable error\n * instead of an opaque `Unexpected token` from deep in `res.json()`.\n */\n async function parseJson<T>(res: Response, path: string): Promise<T> {\n try {\n return await res.json() as T\n }\n catch (cause) {\n throw new Error(\n `Remote session: malformed JSON from ${path} (${res.status} ${res.statusText})`,\n { cause },\n )\n }\n }\n\n return {\n async load(sessionId: string) {\n const res = await request(`/sessions/${encodeURIComponent(sessionId)}`)\n if (!res.ok) {\n if (res.status === 404)\n return null\n throw new Error(`Remote session load failed: ${res.status} ${res.statusText}`)\n }\n return await parseJson<SessionData>(res, `/sessions/${sessionId}`)\n },\n\n async save(session: SessionData) {\n const res = await request(`/sessions/${encodeURIComponent(session.id)}`, {\n method: 'PUT',\n body: JSON.stringify(session),\n })\n if (!res.ok) {\n throw new Error(`Remote session save failed: ${res.status} ${res.statusText}`)\n }\n },\n\n async delete(sessionId: string) {\n const res = await request(`/sessions/${encodeURIComponent(sessionId)}`, {\n method: 'DELETE',\n })\n if (!res.ok && res.status !== 404) {\n throw new Error(`Remote session delete failed: ${res.status} ${res.statusText}`)\n }\n },\n\n async list(filter) {\n const params = new URLSearchParams()\n if (filter?.agentId)\n params.set('agentId', filter.agentId)\n if (filter?.limit)\n params.set('limit', String(filter.limit))\n if (filter && 'projectRoot' in filter) {\n const v = filter.projectRoot\n if (v === null)\n params.set('projectRoot', '__null__')\n else if (typeof v === 'string')\n params.set('projectRoot', v)\n }\n\n const query = params.toString()\n const path = query ? `/sessions?${query}` : '/sessions'\n const res = await request(path)\n\n if (!res.ok) {\n throw new Error(`Remote session list failed: ${res.status} ${res.statusText}`)\n }\n\n const body = await parseJson<{ ids: string[] }>(res, path)\n if (!Array.isArray(body?.ids)) {\n throw new TypeError(`Remote session list: expected { ids: string[] } from ${path}, got ${typeof body?.ids}`)\n }\n return body.ids\n },\n\n async appendTurns(sessionId: string, turns: SessionTurn[]) {\n const res = await request(`/sessions/${encodeURIComponent(sessionId)}/turns`, {\n method: 'POST',\n body: JSON.stringify(turns),\n })\n if (!res.ok) {\n throw new Error(`Remote appendTurns failed: ${res.status} ${res.statusText}`)\n }\n },\n\n async getTurns(sessionId: string, from = 0, limit?: number) {\n const params = new URLSearchParams()\n if (from)\n params.set('from', String(from))\n if (limit !== undefined)\n params.set('limit', String(limit))\n\n const query = params.toString()\n const path = `/sessions/${encodeURIComponent(sessionId)}/turns${query ? `?${query}` : ''}`\n const res = await request(path)\n\n if (!res.ok) {\n throw new Error(`Remote getTurns failed: ${res.status} ${res.statusText}`)\n }\n\n const turns = await parseJson<SessionTurn[]>(res, path)\n if (!Array.isArray(turns)) {\n throw new TypeError(`Remote getTurns: expected SessionTurn[] from ${path}, got ${typeof turns}`)\n }\n return turns\n },\n\n async updateRun(sessionId: string, run: SessionRun) {\n const res = await request(\n `/sessions/${encodeURIComponent(sessionId)}/runs/${encodeURIComponent(run.id)}`,\n {\n method: 'PUT',\n body: JSON.stringify(run),\n },\n )\n if (!res.ok) {\n throw new Error(`Remote updateRun failed: ${res.status} ${res.statusText}`)\n }\n },\n\n async updateStatus(sessionId: string, status: SessionData['status']) {\n const res = await request(`/sessions/${encodeURIComponent(sessionId)}`, {\n method: 'PATCH',\n body: JSON.stringify({ status }),\n })\n if (!res.ok) {\n throw new Error(`Remote updateStatus failed: ${res.status} ${res.statusText}`)\n }\n },\n }\n}\n","/**\n * Session management for agents.\n *\n * A session tracks identity, turn history, and run metadata.\n * Plug in any storage backend by implementing the SessionStore interface,\n * or use one of the built-in stores: memory, sqlite, remote.\n */\n\nimport type { SessionMessage, SessionTurn, TurnUsage } from '../types'\nimport type { ToWireMessagesOptions } from './messages'\nimport { toWireMessages } from './messages'\n\nexport type { SessionContentBlock, SessionMessage, SessionTurn } from '../types'\nexport { createFileMapStore } from './file-map'\n\n// ---------------------------------------------------------------------------\n// Types\n// ---------------------------------------------------------------------------\n\nexport interface SessionRun {\n id: string\n startedAt: number\n endedAt?: number\n prompt: string\n status: 'running' | 'completed' | 'aborted' | 'error'\n turns?: number\n tokensIn?: number\n tokensOut?: number\n error?: string\n /** Per-turn usage breakdown */\n turnUsage?: TurnUsage[]\n /** Total usage across all turns */\n totalUsage?: TurnUsage\n /** Estimated cost in USD */\n cost?: number\n /**\n * The run that spawned this one, when the agent is a subagent sharing its\n * parent's session. Undefined on top-level `agent.run()`. Consumers can walk\n * `runs` by `parentRunId` to reconstruct the subagent tree.\n */\n parentRunId?: string\n /**\n * Zero-based subagent depth. 0 = top-level run, 1 = direct child, …\n * Recorded here so hosts can query/filter by level without walking the tree.\n */\n depth?: number\n}\n\nexport interface SessionData {\n id: string\n agentId?: string\n /**\n * Absolute path of the project this session belongs to — typically\n * the git root resolved from `cwd` at creation time, falling back to\n * `cwd` itself when not in a git repo. Set ONCE on creation and never\n * mutated thereafter (the session \"belongs\" to that project forever).\n *\n * Used by the TUI's sessions list to filter rows by current project,\n * so the user only sees conversations relevant to where they are\n * working — without needing one `.{prefix}/` directory per project.\n *\n * `undefined` on pre-tagging legacy sessions; the chat layer treats\n * those as \"untagged\" and hides them unless `Settings.showAllProjects`\n * is on.\n */\n projectRoot?: string\n turns: SessionTurn[]\n runs: SessionRun[]\n status: 'idle' | 'running' | 'completed' | 'error'\n metadata: Record<string, unknown>\n createdAt: number\n updatedAt: number\n}\n\n// ---------------------------------------------------------------------------\n// SessionStore interface (pluggable backend)\n// ---------------------------------------------------------------------------\n\nexport interface SessionStore {\n /** Optional: generate a session ID server-side (e.g. a database-issued UUID). */\n generateSessionId?: () => string | Promise<string>\n\n /**\n * Optional: generate a turn ID server-side for session-managed user turns.\n *\n * Provider-loop assistant and tool-result turns use AgentClock.randomUUID()\n * instead, so durable-execution adapters can keep those IDs replay-stable.\n */\n generateTurnId?: () => string | Promise<string>\n\n /** Load a session by ID. Returns null if not found. */\n load: (sessionId: string) => Promise<SessionData | null>\n\n /** Save a session (create or update, full document). */\n save: (session: SessionData) => Promise<void>\n\n /** Delete a session. */\n delete: (sessionId: string) => Promise<void>\n\n /**\n * List session IDs, optionally filtered. `projectRoot` restricts to\n * sessions whose `SessionData.projectRoot` matches exactly — untagged\n * (legacy) sessions are NOT returned under that filter; pass `null`\n * explicitly to ask for untagged ones, or omit the field to ignore\n * the axis entirely. `agentId` filters by recorded agent; the two\n * conditions AND together when both are set.\n */\n list: (filter?: { agentId?: string, limit?: number, projectRoot?: string | null }) => Promise<string[]>\n\n /** Append new turns to a session (incremental, avoids full re-save). */\n appendTurns: (sessionId: string, turns: SessionTurn[]) => Promise<void>\n\n /** Return a slice of turns for a session. */\n getTurns: (sessionId: string, from?: number, limit?: number) => Promise<SessionTurn[]>\n\n /**\n * Persist a run record (called after completeRun / abortRun / errorRun).\n *\n * **Upsert semantics required.** The agent's run lifecycle calls\n * `session.startRun()` to register a new run in IN-MEMORY state and\n * then `updateRun()` at finalize. The store doesn't see the run any\n * earlier — `appendTurns` is the only intermediate call, and it\n * persists turns but not runs. An update-only implementation would\n * silently drop every newly-created run record at finalize, leaving\n * the on-disk `runs[]` missing entries that the persisted turns\n * reference (which `eventsFromTurns` then mis-classifies via\n * `ancestryOf` → broken depth, broken `child-N` labels, broken\n * `userPrompts` history).\n *\n * Implementations MUST insert when the id doesn't exist and update\n * when it does. The bundled `sqlite` / `memory` / `file-map` stores\n * all follow this contract; remote stores using HTTP PUT get upsert\n * for free via REST semantics.\n */\n updateRun: (sessionId: string, run: SessionRun) => Promise<void>\n\n /** Update the top-level status of a session. */\n updateStatus: (sessionId: string, status: SessionData['status']) => Promise<void>\n\n /**\n * Optional: release backend resources (e.g. close the SQLite handle).\n * Hosts should call this on teardown when present; stores backed by\n * memory or remote HTTP have nothing to release and may omit it.\n */\n close?: () => void\n}\n\n// ---------------------------------------------------------------------------\n// Session (live instance wrapping a SessionData)\n// ---------------------------------------------------------------------------\n\nexport interface Session {\n /** Session ID */\n readonly id: string\n\n /** Agent ID (optional label) */\n readonly agentId?: string\n\n /**\n * Project this session was created under — see {@link SessionData.projectRoot}.\n * Set once on creation; surfaces here for read-only inspection.\n */\n readonly projectRoot?: string\n\n /**\n * Raw persisted turn history — kept pristine for fidelity (the model's\n * reasoning chain stays intact across reloads).\n *\n * **DO NOT pass this directly to a provider request.** Mid-pair\n * persistence (interrupted runs, partial-result writes, compaction\n * boundaries) leaves orphan `tool_use` / `tool_result` blocks here that\n * every provider 400s on (`tool_result must be preceded by a tool_call\n * with the same toolCallId`). The agent's own loop repairs these\n * just-in-time at wire-send time and never writes the repair back to\n * `turns`.\n *\n * For provider requests built outside `agent.run()`, use\n * {@link Session.toMessages} — it applies the same defensive pairing\n * repair and resolves to a guaranteed-safe `SessionMessage[]`.\n */\n readonly turns: SessionTurn[]\n\n /**\n * True when this session has no turns yet.\n *\n * Use this as a first-prompt signal when setting up a run — e.g. writing initial\n * configuration only on fresh sessions. Equivalent to `turns.length === 0`.\n */\n readonly isEmpty: boolean\n\n /** Top-level session status */\n readonly status: SessionData['status']\n\n /** All runs in this session */\n readonly runs: SessionRun[]\n\n /** Arbitrary metadata */\n readonly metadata: Record<string, unknown>\n\n /**\n * Start tracking a new run. `extras.parentRunId` + `extras.depth` are\n * populated by the spawn tool when a child agent shares its parent's\n * session; regular top-level `agent.run()` calls omit them.\n */\n startRun: (runId: string, prompt?: string, extras?: { parentRunId?: string, depth?: number }) => void\n\n /** Mark a run as completed */\n completeRun: (runId: string, stats: { turns: number, tokensIn: number, tokensOut: number, turnUsage?: TurnUsage[], cost?: number }) => void\n\n /** Mark a run as aborted */\n /**\n * Optional `stats` lets the agent backfill the run's token totals when\n * the abort happened *after* the loop accumulated meaningful usage —\n * common when the user presses esc mid-streaming. Without it, the run\n * record reads `0 in / 0 out` on reload regardless of how much was\n * spent before the abort. Same shape as `completeRun`'s stats so the\n * persisted `totalUsage` aggregate stays consistent across paths.\n */\n abortRun: (runId: string, stats?: { turns: number, tokensIn: number, tokensOut: number, turnUsage?: TurnUsage[], cost?: number }) => void\n\n /** Mark a run as errored */\n /** Optional `stats` — same rationale as `abortRun.stats`. */\n errorRun: (runId: string, error: string, stats?: { turns: number, tokensIn: number, tokensOut: number, turnUsage?: TurnUsage[], cost?: number }) => void\n\n /** Append turns to in-memory history AND persist via store.appendTurns (if store present) */\n appendTurns: (turns: SessionTurn[]) => Promise<void>\n\n /** Replace all turns in-memory (does not persist — use save() for that) */\n setTurns: (turns: SessionTurn[]) => void\n\n /**\n * Replace all runs in-memory (does not persist — use save() for that).\n * Mirrors {@link setTurns} for the fork / restore case: callers that\n * bootstrap a session from an externally-derived snapshot (e.g.\n * `onForkTurn` copying parent runs into a child session) need this so\n * the cloned runs land in `data.runs` before the first `save()`.\n * Production agent runs continue to mutate runs via `startRun` /\n * `completeRun` / `updateRun`; this is the bulk-replace escape hatch.\n */\n setRuns: (runs: SessionRun[]) => void\n\n /** Update the session status in memory AND via store.updateStatus (if store present) */\n updateStatus: (status: SessionData['status']) => Promise<void>\n\n /** Persist an updated run record via store.updateRun (if store present) */\n updateRun: (run: SessionRun) => Promise<void>\n\n /** Generate a session-managed turn ID using store.generateTurnId if available, else crypto.randomUUID() */\n generateTurnId: () => string | Promise<string>\n\n /** Set metadata key */\n setMeta: (key: string, value: unknown) => void\n\n /** Persist the full session document to the store */\n save: () => Promise<void>\n\n /**\n * Project the session's persisted turns into wire-ready messages safe to\n * hand to any provider.\n *\n * The canonical answer to \"I need to send these turns to Anthropic /\n * OpenAI from outside `agent.run()`\" (sub-agent classifier, side-channel\n * summarizer, replay worker, …). Runs the same defensive pairing repair\n * the agent loop applies just-in-time at wire-send time\n * ({@link ensureToolResultPairing}), so orphan `tool_use` blocks and\n * dangling `tool_result`s never reach the provider as the 400\n * \"tool_result must be preceded by a tool_call with the same toolCallId\".\n *\n * Pass `provider` to also enforce the user-tail invariant\n * ({@link ensureEndsWithUserMessage}) — required for opus 4.7 / o-series\n * style models that reject assistant-prefill.\n *\n * Pure + idempotent. Resolves content refs only in the returned messages\n * and does NOT mutate `session.turns`. **Do not write the result back via\n * `setTurns` / `appendTurns`** — synthetic placeholders or resolved\n * payloads will contaminate persisted history.\n */\n toMessages: (options?: ToWireMessagesOptions) => Promise<SessionMessage[]>\n\n /** Serialize to SessionData */\n toJSON: () => SessionData\n\n /**\n * The backing store, when one was provided. Exposed so hosts can call\n * its optional `close()` on teardown (e.g. release the SQLite handle).\n */\n readonly store?: SessionStore\n}\n\n// ---------------------------------------------------------------------------\n// createSession\n// ---------------------------------------------------------------------------\n\nexport interface CreateSessionOptions {\n /** Session ID. If omitted and store provides generateSessionId, that is used. */\n id?: string\n /** Agent ID label */\n agentId?: string\n /**\n * Project tag — see {@link SessionData.projectRoot}. Stamped once on\n * creation; ignored when `_data` is set (restoring an existing\n * session preserves whatever was already persisted there). The TUI\n * resolves this from `findGitRoot(cwd) ?? cwd` so sessions started\n * from the same repo (no matter which subdir) share one tag.\n */\n projectRoot?: string\n /** Initial metadata */\n metadata?: Record<string, unknown>\n /** Storage backend (optional, enables save/load) */\n store?: SessionStore\n // @internal: restore from existing data (bypasses id/agentId/metadata options)\n _data?: SessionData\n}\n\n/**\n * Create a new session.\n * Async so stores that generate IDs server-side (e.g. a database) can be supported.\n */\nexport async function createSession(options: CreateSessionOptions = {}): Promise<Session> {\n const store = options.store\n const now = Date.now()\n\n let sessionId = options.id\n if (!sessionId && store?.generateSessionId) {\n sessionId = await store.generateSessionId()\n }\n if (!sessionId) {\n sessionId = generateId()\n }\n\n const data: SessionData = options._data ?? {\n id: sessionId,\n agentId: options.agentId,\n // Stamp the project tag at creation only — restored sessions (the\n // `_data` branch above) keep whatever was already persisted, even\n // if `options.projectRoot` differs. A session's project identity\n // is sticky for its lifetime; loading the same session from a\n // different cwd doesn't re-home it.\n ...(options.projectRoot ? { projectRoot: options.projectRoot } : {}),\n turns: [],\n runs: [],\n status: 'idle',\n metadata: options.metadata ?? {},\n createdAt: now,\n updatedAt: now,\n }\n\n function touch() {\n data.updatedAt = Date.now()\n }\n\n function findRun(runId: string): SessionRun | undefined {\n return data.runs.find(r => r.id === runId)\n }\n\n /**\n * Apply per-run usage stats onto a SessionRun. Shared by `completeRun`,\n * `abortRun`, and `errorRun` so the on-disk shape stays consistent across\n * exit paths — historically only `completeRun` filled these in, and\n * aborted/errored runs rendered `0 in / 0 out` on reload regardless of\n * how much was actually consumed.\n */\n function applyRunStats(run: SessionRun, stats: { turns: number, tokensIn: number, tokensOut: number, turnUsage?: TurnUsage[], cost?: number }) {\n run.turns = stats.turns\n run.tokensIn = stats.tokensIn\n run.tokensOut = stats.tokensOut\n if (stats.turnUsage) {\n run.turnUsage = stats.turnUsage\n const total = stats.turnUsage.reduce((acc, t) => ({\n input: acc.input + t.input,\n output: acc.output + t.output,\n cacheCreation: (acc.cacheCreation ?? 0) + (t.cacheCreation ?? 0),\n cacheRead: (acc.cacheRead ?? 0) + (t.cacheRead ?? 0),\n thinking: (acc.thinking ?? 0) + (t.thinking ?? 0),\n }), { input: 0, output: 0, cacheCreation: 0, cacheRead: 0, thinking: 0 })\n run.totalUsage = {\n input: total.input,\n output: total.output,\n ...(total.cacheCreation ? { cacheCreation: total.cacheCreation } : {}),\n ...(total.cacheRead ? { cacheRead: total.cacheRead } : {}),\n ...(total.thinking ? { thinking: total.thinking } : {}),\n }\n }\n if (stats.cost !== undefined)\n run.cost = stats.cost\n }\n\n const session: Session = {\n ...(store ? { store } : {}),\n get id() { return data.id },\n get agentId() { return data.agentId },\n get projectRoot() { return data.projectRoot },\n get turns() { return data.turns },\n get isEmpty() { return data.turns.length === 0 },\n get status() { return data.status },\n get runs() { return data.runs },\n get metadata() { return data.metadata },\n\n startRun(runId: string, prompt?: string, extras?: { parentRunId?: string, depth?: number }) {\n data.runs.push({\n id: runId,\n startedAt: Date.now(),\n prompt: prompt ?? '',\n status: 'running',\n ...(extras?.parentRunId ? { parentRunId: extras.parentRunId } : {}),\n ...(typeof extras?.depth === 'number' ? { depth: extras.depth } : {}),\n })\n touch()\n },\n\n completeRun(runId: string, stats: { turns: number, tokensIn: number, tokensOut: number, turnUsage?: TurnUsage[], cost?: number }) {\n const run = findRun(runId)\n if (run) {\n run.status = 'completed'\n run.endedAt = Date.now()\n applyRunStats(run, stats)\n }\n touch()\n },\n\n abortRun(runId: string, stats?: { turns: number, tokensIn: number, tokensOut: number, turnUsage?: TurnUsage[], cost?: number }) {\n const run = findRun(runId)\n if (run) {\n run.status = 'aborted'\n run.endedAt = Date.now()\n // Backfill tokens when available so an aborted run's session\n // ledger reflects actual consumption rather than `0 in / 0 out`.\n if (stats)\n applyRunStats(run, stats)\n }\n touch()\n },\n\n errorRun(runId: string, error: string, stats?: { turns: number, tokensIn: number, tokensOut: number, turnUsage?: TurnUsage[], cost?: number }) {\n const run = findRun(runId)\n if (run) {\n run.status = 'error'\n run.endedAt = Date.now()\n run.error = error\n if (stats)\n applyRunStats(run, stats)\n }\n touch()\n },\n\n async appendTurns(turns: SessionTurn[]) {\n data.turns.push(...turns)\n touch()\n if (store) {\n await store.appendTurns(data.id, turns)\n }\n },\n\n setTurns(turns: SessionTurn[]) {\n data.turns = turns\n touch()\n },\n\n setRuns(runs: SessionRun[]) {\n data.runs = runs\n touch()\n },\n\n async updateStatus(status: SessionData['status']) {\n data.status = status\n touch()\n if (store) {\n await store.updateStatus(data.id, status)\n }\n },\n\n async updateRun(run: SessionRun) {\n if (store) {\n await store.updateRun(data.id, run)\n }\n },\n\n generateTurnId() {\n if (store?.generateTurnId) {\n return store.generateTurnId()\n }\n return crypto.randomUUID()\n },\n\n setMeta(key: string, value: unknown) {\n data.metadata[key] = value\n touch()\n },\n\n async save() {\n if (!store) {\n throw new Error('No SessionStore configured. Pass a store to createSession() to enable persistence.')\n }\n await store.save(data)\n },\n\n toMessages(options?: ToWireMessagesOptions) {\n return toWireMessages(data.turns, options)\n },\n\n toJSON() {\n return structuredClone(data)\n },\n }\n\n return session\n}\n\n/**\n * Demote a persisted `'running'` status to `'idle'` (in place) and return the\n * data. A persisted `'running'` is necessarily stale: the run that set it lived\n * in another process (crash, kill -9, power loss) and cannot still be executing\n * in a freshly-loaded session. Call this on the result of a raw `store.load()`\n * so consumers don't render a ghost in-progress state or refuse a new run.\n * `loadSession` applies it automatically; direct `store.load()` callers (e.g.\n * the TUI) should run loaded data through this.\n */\nexport function demoteStaleRunningStatus(data: SessionData): SessionData {\n if (data.status === 'running')\n data.status = 'idle'\n return data\n}\n\n/**\n * Load an existing session from a store.\n */\nexport async function loadSession(store: SessionStore, sessionId: string): Promise<Session | null> {\n const loaded = await store.load(sessionId)\n if (!loaded)\n return null\n\n demoteStaleRunningStatus(loaded)\n\n return createSession({ store, _data: loaded })\n}\n\n// ---------------------------------------------------------------------------\n// Re-export stores\n// ---------------------------------------------------------------------------\n\nexport type { FileMapAdapter, FileMapStoreOptions } from './file-map'\nexport { createMemoryStore } from './memory'\nexport { autoDetectAndConvert, fromAnthropic, fromOpenAI, toAnthropic, toOpenAI, toWireMessages } from './messages'\nexport type { ToWireMessagesOptions } from './messages'\nexport { createRemoteStore } from './remote'\nexport type { RemoteStoreOptions } from './remote'\n\n// NOTE: `createSqliteStore` is intentionally NOT re-exported here. It lives behind\n// the dedicated `zidane/session/sqlite` subpath so that non-Bun consumers don't\n// transitively evaluate `bun:sqlite` when they import from `zidane/session`.\n\n// ---------------------------------------------------------------------------\n// Helpers\n// ---------------------------------------------------------------------------\n\nfunction generateId(): string {\n return `ses_${Date.now().toString(36)}_${Math.random().toString(36).slice(2, 8)}`\n}\n"],"mappings":"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"}