@namzu/cli 26.3.0 → 27.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 (321) hide show
  1. package/CHANGELOG.md +214 -0
  2. package/README.md +49 -34
  3. package/dist/bin.js +7 -0
  4. package/dist/bin.js.map +1 -1
  5. package/dist/checkpoints/store.d.ts +17 -4
  6. package/dist/checkpoints/store.d.ts.map +1 -1
  7. package/dist/checkpoints/store.js +20 -5
  8. package/dist/checkpoints/store.js.map +1 -1
  9. package/dist/cli.js +2 -2
  10. package/dist/cli.js.map +1 -1
  11. package/dist/commands/acp.d.ts +23 -1
  12. package/dist/commands/acp.d.ts.map +1 -1
  13. package/dist/commands/acp.js +41 -2
  14. package/dist/commands/acp.js.map +1 -1
  15. package/dist/commands/drain.d.ts +69 -2
  16. package/dist/commands/drain.d.ts.map +1 -1
  17. package/dist/commands/drain.js +214 -134
  18. package/dist/commands/drain.js.map +1 -1
  19. package/dist/commands/eval.js +1 -1
  20. package/dist/commands/eval.js.map +1 -1
  21. package/dist/commands/provider-wait.d.ts +5 -5
  22. package/dist/commands/provider-wait.d.ts.map +1 -1
  23. package/dist/commands/provider-wait.js +2 -2
  24. package/dist/commands/resident.d.ts.map +1 -1
  25. package/dist/commands/resident.js +2 -1
  26. package/dist/commands/resident.js.map +1 -1
  27. package/dist/commands/run-flags.d.ts +7 -7
  28. package/dist/commands/run-flags.js +4 -4
  29. package/dist/commands/run-stream.d.ts +16 -12
  30. package/dist/commands/run-stream.d.ts.map +1 -1
  31. package/dist/commands/run-stream.js +142 -98
  32. package/dist/commands/run-stream.js.map +1 -1
  33. package/dist/commands/run.d.ts +6 -4
  34. package/dist/commands/run.d.ts.map +1 -1
  35. package/dist/commands/run.js +129 -45
  36. package/dist/commands/run.js.map +1 -1
  37. package/dist/commands/serve.js +2 -2
  38. package/dist/commands/serve.js.map +1 -1
  39. package/dist/commands/state.js +8 -8
  40. package/dist/commands/state.js.map +1 -1
  41. package/dist/config/load.d.ts +1 -1
  42. package/dist/config/load.d.ts.map +1 -1
  43. package/dist/config/load.js +17 -5
  44. package/dist/config/load.js.map +1 -1
  45. package/dist/config/run-limits.d.ts +20 -8
  46. package/dist/config/run-limits.d.ts.map +1 -1
  47. package/dist/config/run-limits.js +28 -46
  48. package/dist/config/run-limits.js.map +1 -1
  49. package/dist/config/schema.d.ts +44 -19
  50. package/dist/config/schema.d.ts.map +1 -1
  51. package/dist/config/schema.js.map +1 -1
  52. package/dist/config/tool-result-screens.js +1 -1
  53. package/dist/context/directories.d.ts +37 -0
  54. package/dist/context/directories.d.ts.map +1 -0
  55. package/dist/context/directories.js +69 -0
  56. package/dist/context/directories.js.map +1 -0
  57. package/dist/context/environment.d.ts +55 -0
  58. package/dist/context/environment.d.ts.map +1 -1
  59. package/dist/context/environment.js +96 -0
  60. package/dist/context/environment.js.map +1 -1
  61. package/dist/context/project-tracker.d.ts +3 -3
  62. package/dist/context/project-tracker.d.ts.map +1 -1
  63. package/dist/context/project-tracker.js +3 -3
  64. package/dist/context/project-tracker.js.map +1 -1
  65. package/dist/context/project.d.ts +1 -1
  66. package/dist/context/project.js +1 -1
  67. package/dist/context/sandbox.d.ts +22 -3
  68. package/dist/context/sandbox.d.ts.map +1 -1
  69. package/dist/context/sandbox.js +42 -4
  70. package/dist/context/sandbox.js.map +1 -1
  71. package/dist/doctor/checks/chain.d.ts +1 -1
  72. package/dist/doctor/checks/chain.js +5 -5
  73. package/dist/doctor/checks/chain.js.map +1 -1
  74. package/dist/doctor/checks/invariants.d.ts +2 -2
  75. package/dist/doctor/checks/invariants.js +5 -5
  76. package/dist/doctor/checks/invariants.js.map +1 -1
  77. package/dist/doctor/checks/logging.js +1 -1
  78. package/dist/doctor/checks/logging.js.map +1 -1
  79. package/dist/doctor/checks/sandbox.js +1 -1
  80. package/dist/doctor/checks/sandbox.js.map +1 -1
  81. package/dist/doctor/checks/session-export.d.ts +1 -1
  82. package/dist/doctor/checks/session-export.js +2 -2
  83. package/dist/doctor/checks/session-export.js.map +1 -1
  84. package/dist/doctor/checks/telemetry.d.ts +1 -1
  85. package/dist/doctor/checks/telemetry.js +1 -1
  86. package/dist/doctor/registry.js +2 -2
  87. package/dist/doctor/registry.js.map +1 -1
  88. package/dist/exit-codes.d.ts +2 -2
  89. package/dist/exit-codes.js +2 -2
  90. package/dist/integrations/mcp/servers.d.ts +1 -1
  91. package/dist/integrations/providers/chain-capabilities.d.ts +6 -6
  92. package/dist/integrations/providers/chain-capabilities.js +8 -8
  93. package/dist/integrations/providers/chain-capabilities.js.map +1 -1
  94. package/dist/integrations/providers/register.d.ts +1 -1
  95. package/dist/integrations/providers/register.js +1 -1
  96. package/dist/integrations/providers/registry.d.ts +1 -1
  97. package/dist/integrations/resident/inspection.d.ts +4 -1
  98. package/dist/integrations/resident/inspection.d.ts.map +1 -1
  99. package/dist/integrations/resident/inspection.js +53 -34
  100. package/dist/integrations/resident/inspection.js.map +1 -1
  101. package/dist/integrations/resident/learning-storage.d.ts +7 -2
  102. package/dist/integrations/resident/learning-storage.d.ts.map +1 -1
  103. package/dist/integrations/resident/learning-storage.js +12 -8
  104. package/dist/integrations/resident/learning-storage.js.map +1 -1
  105. package/dist/integrations/resident/runner-store.d.ts +1 -1
  106. package/dist/integrations/resident/runner-store.d.ts.map +1 -1
  107. package/dist/integrations/resident/runner-store.js +5 -2
  108. package/dist/integrations/resident/runner-store.js.map +1 -1
  109. package/dist/integrations/resident/runner-worker.js +1 -0
  110. package/dist/integrations/resident/runner-worker.js.map +1 -1
  111. package/dist/integrations/resident/session-log-reads.d.ts +37 -0
  112. package/dist/integrations/resident/session-log-reads.d.ts.map +1 -0
  113. package/dist/integrations/resident/session-log-reads.js +125 -0
  114. package/dist/integrations/resident/session-log-reads.js.map +1 -0
  115. package/dist/integrations/resident/session-step.d.ts +2 -0
  116. package/dist/integrations/resident/session-step.d.ts.map +1 -1
  117. package/dist/integrations/resident/session-step.js +15 -13
  118. package/dist/integrations/resident/session-step.js.map +1 -1
  119. package/dist/integrations/resident/storage.d.ts +23 -1
  120. package/dist/integrations/resident/storage.d.ts.map +1 -1
  121. package/dist/integrations/resident/storage.js +60 -17
  122. package/dist/integrations/resident/storage.js.map +1 -1
  123. package/dist/integrations/resident/tool-evidence.d.ts +4 -2
  124. package/dist/integrations/resident/tool-evidence.d.ts.map +1 -1
  125. package/dist/integrations/resident/tool-evidence.js +36 -30
  126. package/dist/integrations/resident/tool-evidence.js.map +1 -1
  127. package/dist/integrations/resident/verification.d.ts +2 -2
  128. package/dist/integrations/resident/verification.d.ts.map +1 -1
  129. package/dist/integrations/resident/verification.js +4 -4
  130. package/dist/integrations/resident/verification.js.map +1 -1
  131. package/dist/integrations/sessions/checkpoint-view.d.ts +13 -0
  132. package/dist/integrations/sessions/checkpoint-view.d.ts.map +1 -0
  133. package/dist/integrations/sessions/checkpoint-view.js +48 -0
  134. package/dist/integrations/sessions/checkpoint-view.js.map +1 -0
  135. package/dist/integrations/sessions/context-inventory.js +1 -1
  136. package/dist/integrations/sessions/context-inventory.js.map +1 -1
  137. package/dist/integrations/sessions/conversation-search.d.ts +16 -20
  138. package/dist/integrations/sessions/conversation-search.d.ts.map +1 -1
  139. package/dist/integrations/sessions/conversation-search.js +305 -731
  140. package/dist/integrations/sessions/conversation-search.js.map +1 -1
  141. package/dist/integrations/sessions/evidence-page-validation.d.ts +4 -4
  142. package/dist/integrations/sessions/evidence-page-validation.d.ts.map +1 -1
  143. package/dist/integrations/sessions/evidence-page-validation.js +1 -1
  144. package/dist/integrations/sessions/evidence-page-validation.js.map +1 -1
  145. package/dist/integrations/sessions/evidence-recall.d.ts +40 -2
  146. package/dist/integrations/sessions/evidence-recall.d.ts.map +1 -1
  147. package/dist/integrations/sessions/evidence-recall.js +41 -97
  148. package/dist/integrations/sessions/evidence-recall.js.map +1 -1
  149. package/dist/integrations/sessions/store.d.ts +153 -85
  150. package/dist/integrations/sessions/store.d.ts.map +1 -1
  151. package/dist/integrations/sessions/store.js +414 -484
  152. package/dist/integrations/sessions/store.js.map +1 -1
  153. package/dist/integrations/sessions/task-context.d.ts +15 -2
  154. package/dist/integrations/sessions/task-context.d.ts.map +1 -1
  155. package/dist/integrations/sessions/task-context.js +34 -11
  156. package/dist/integrations/sessions/task-context.js.map +1 -1
  157. package/dist/integrations/sessions/transcript-export.d.ts +13 -6
  158. package/dist/integrations/sessions/transcript-export.d.ts.map +1 -1
  159. package/dist/integrations/sessions/transcript-export.js +148 -263
  160. package/dist/integrations/sessions/transcript-export.js.map +1 -1
  161. package/dist/integrations/state/home.d.ts +4 -16
  162. package/dist/integrations/state/home.d.ts.map +1 -1
  163. package/dist/integrations/state/home.js +6 -42
  164. package/dist/integrations/state/home.js.map +1 -1
  165. package/dist/integrations/state/project.d.ts +6 -7
  166. package/dist/integrations/state/project.d.ts.map +1 -1
  167. package/dist/integrations/state/project.js +7 -9
  168. package/dist/integrations/state/project.js.map +1 -1
  169. package/dist/integrations/state/report.d.ts +27 -41
  170. package/dist/integrations/state/report.d.ts.map +1 -1
  171. package/dist/integrations/state/report.js +172 -464
  172. package/dist/integrations/state/report.js.map +1 -1
  173. package/dist/integrations/state/retention.d.ts +18 -0
  174. package/dist/integrations/state/retention.d.ts.map +1 -0
  175. package/dist/integrations/state/retention.js +18 -0
  176. package/dist/integrations/state/retention.js.map +1 -0
  177. package/dist/integrations/subagents/activity.d.ts +36 -31
  178. package/dist/integrations/subagents/activity.d.ts.map +1 -1
  179. package/dist/integrations/subagents/activity.js +27 -23
  180. package/dist/integrations/subagents/activity.js.map +1 -1
  181. package/dist/integrations/subagents/batches.d.ts +91 -0
  182. package/dist/integrations/subagents/batches.d.ts.map +1 -0
  183. package/dist/integrations/subagents/batches.js +172 -0
  184. package/dist/integrations/subagents/batches.js.map +1 -0
  185. package/dist/integrations/subagents/parent.d.ts +26 -11
  186. package/dist/integrations/subagents/parent.d.ts.map +1 -1
  187. package/dist/integrations/subagents/parent.js +13 -28
  188. package/dist/integrations/subagents/parent.js.map +1 -1
  189. package/dist/integrations/subagents/policy.d.ts +2 -2
  190. package/dist/integrations/subagents/policy.d.ts.map +1 -1
  191. package/dist/integrations/subagents/policy.js +2 -2
  192. package/dist/integrations/subagents/policy.js.map +1 -1
  193. package/dist/integrations/subagents/replay.d.ts +91 -26
  194. package/dist/integrations/subagents/replay.d.ts.map +1 -1
  195. package/dist/integrations/subagents/replay.js +216 -114
  196. package/dist/integrations/subagents/replay.js.map +1 -1
  197. package/dist/integrations/subagents/runtime.d.ts +50 -26
  198. package/dist/integrations/subagents/runtime.d.ts.map +1 -1
  199. package/dist/integrations/subagents/runtime.js +132 -126
  200. package/dist/integrations/subagents/runtime.js.map +1 -1
  201. package/dist/integrations/subagents/saved-agents.d.ts +57 -0
  202. package/dist/integrations/subagents/saved-agents.d.ts.map +1 -0
  203. package/dist/integrations/subagents/saved-agents.js +102 -0
  204. package/dist/integrations/subagents/saved-agents.js.map +1 -0
  205. package/dist/integrations/subagents/slash.d.ts +55 -0
  206. package/dist/integrations/subagents/slash.d.ts.map +1 -0
  207. package/dist/integrations/subagents/slash.js +45 -0
  208. package/dist/integrations/subagents/slash.js.map +1 -0
  209. package/dist/integrations/telemetry/session-export.d.ts +6 -6
  210. package/dist/integrations/telemetry/session-export.d.ts.map +1 -1
  211. package/dist/integrations/telemetry/session-export.js +2 -2
  212. package/dist/memory/presentation.d.ts +11 -0
  213. package/dist/memory/presentation.d.ts.map +1 -1
  214. package/dist/memory/presentation.js +25 -0
  215. package/dist/memory/presentation.js.map +1 -1
  216. package/dist/memory/store.d.ts +13 -7
  217. package/dist/memory/store.d.ts.map +1 -1
  218. package/dist/memory/store.js +37 -11
  219. package/dist/memory/store.js.map +1 -1
  220. package/dist/memory/typed.d.ts +116 -0
  221. package/dist/memory/typed.d.ts.map +1 -0
  222. package/dist/memory/typed.js +336 -0
  223. package/dist/memory/typed.js.map +1 -0
  224. package/dist/permissions/checks.d.ts +1 -1
  225. package/dist/permissions/checks.js +1 -1
  226. package/dist/permissions/headless-trust.d.ts +2 -2
  227. package/dist/permissions/headless-trust.d.ts.map +1 -1
  228. package/dist/permissions/headless-trust.js +3 -3
  229. package/dist/permissions/headless-trust.js.map +1 -1
  230. package/dist/permissions/mode.d.ts +4 -4
  231. package/dist/permissions/mode.js +1 -1
  232. package/dist/permissions/rules.d.ts +1 -1
  233. package/dist/permissions/rules.js +1 -1
  234. package/dist/termination.d.ts +75 -0
  235. package/dist/termination.d.ts.map +1 -0
  236. package/dist/termination.js +143 -0
  237. package/dist/termination.js.map +1 -0
  238. package/dist/tui/AgentExplorer.d.ts +2 -2
  239. package/dist/tui/AgentExplorer.js +4 -4
  240. package/dist/tui/AgentExplorer.js.map +1 -1
  241. package/dist/tui/App.d.ts +9 -1
  242. package/dist/tui/App.d.ts.map +1 -1
  243. package/dist/tui/App.js +452 -303
  244. package/dist/tui/App.js.map +1 -1
  245. package/dist/tui/LiveActivity.d.ts +1 -1
  246. package/dist/tui/LiveActivity.d.ts.map +1 -1
  247. package/dist/tui/PermissionOverlay.d.ts +8 -0
  248. package/dist/tui/PermissionOverlay.d.ts.map +1 -1
  249. package/dist/tui/PermissionOverlay.js +25 -2
  250. package/dist/tui/PermissionOverlay.js.map +1 -1
  251. package/dist/tui/Picker.js +1 -1
  252. package/dist/tui/agent.d.ts +208 -132
  253. package/dist/tui/agent.d.ts.map +1 -1
  254. package/dist/tui/agent.js +523 -313
  255. package/dist/tui/agent.js.map +1 -1
  256. package/dist/tui/conversation-evidence-view.js +3 -3
  257. package/dist/tui/conversation-evidence-view.js.map +1 -1
  258. package/dist/tui/conversation-history.d.ts +4 -21
  259. package/dist/tui/conversation-history.d.ts.map +1 -1
  260. package/dist/tui/conversation-history.js +4 -28
  261. package/dist/tui/conversation-history.js.map +1 -1
  262. package/dist/tui/index.d.ts.map +1 -1
  263. package/dist/tui/index.js +27 -1
  264. package/dist/tui/index.js.map +1 -1
  265. package/dist/tui/log-pane.js +1 -1
  266. package/dist/tui/markdownParser.d.ts +1 -1
  267. package/dist/tui/markdownParser.js +1 -1
  268. package/dist/tui/permission-review.d.ts +16 -0
  269. package/dist/tui/permission-review.d.ts.map +1 -1
  270. package/dist/tui/permission-review.js +25 -2
  271. package/dist/tui/permission-review.js.map +1 -1
  272. package/dist/tui/slashCommands.d.ts +29 -40
  273. package/dist/tui/slashCommands.d.ts.map +1 -1
  274. package/dist/tui/slashCommands.js +70 -61
  275. package/dist/tui/slashCommands.js.map +1 -1
  276. package/dist/tui/{run-interruption.d.ts → turn-interruption.d.ts} +4 -4
  277. package/dist/tui/turn-interruption.d.ts.map +1 -0
  278. package/dist/tui/{run-interruption.js → turn-interruption.js} +20 -20
  279. package/dist/tui/turn-interruption.js.map +1 -0
  280. package/dist/tui/turn-limits-settings.d.ts +39 -0
  281. package/dist/tui/turn-limits-settings.d.ts.map +1 -0
  282. package/dist/tui/{run-limits-settings.js → turn-limits-settings.js} +18 -18
  283. package/dist/tui/turn-limits-settings.js.map +1 -0
  284. package/dist/tui/types.d.ts +3 -3
  285. package/dist/tui/types.d.ts.map +1 -1
  286. package/dist/user-commands/store.d.ts +1 -1
  287. package/dist/user-commands/store.js +1 -1
  288. package/package.json +7 -7
  289. package/dist/integrations/sessions/compaction-evidence.d.ts +0 -5
  290. package/dist/integrations/sessions/compaction-evidence.d.ts.map +0 -1
  291. package/dist/integrations/sessions/compaction-evidence.js +0 -59
  292. package/dist/integrations/sessions/compaction-evidence.js.map +0 -1
  293. package/dist/integrations/sessions/database.d.ts +0 -5
  294. package/dist/integrations/sessions/database.d.ts.map +0 -1
  295. package/dist/integrations/sessions/database.js +0 -34
  296. package/dist/integrations/sessions/database.js.map +0 -1
  297. package/dist/integrations/sessions/paths.d.ts +0 -7
  298. package/dist/integrations/sessions/paths.d.ts.map +0 -1
  299. package/dist/integrations/sessions/paths.js +0 -14
  300. package/dist/integrations/sessions/paths.js.map +0 -1
  301. package/dist/integrations/sessions/run-discovery.d.ts +0 -24
  302. package/dist/integrations/sessions/run-discovery.d.ts.map +0 -1
  303. package/dist/integrations/sessions/run-discovery.js +0 -142
  304. package/dist/integrations/sessions/run-discovery.js.map +0 -1
  305. package/dist/integrations/sessions/turn-evidence.d.ts +0 -129
  306. package/dist/integrations/sessions/turn-evidence.d.ts.map +0 -1
  307. package/dist/integrations/sessions/turn-evidence.js +0 -517
  308. package/dist/integrations/sessions/turn-evidence.js.map +0 -1
  309. package/dist/integrations/subagents/history.d.ts +0 -26
  310. package/dist/integrations/subagents/history.d.ts.map +0 -1
  311. package/dist/integrations/subagents/history.js +0 -76
  312. package/dist/integrations/subagents/history.js.map +0 -1
  313. package/dist/integrations/subagents/runs.d.ts +0 -72
  314. package/dist/integrations/subagents/runs.d.ts.map +0 -1
  315. package/dist/integrations/subagents/runs.js +0 -155
  316. package/dist/integrations/subagents/runs.js.map +0 -1
  317. package/dist/tui/run-interruption.d.ts.map +0 -1
  318. package/dist/tui/run-interruption.js.map +0 -1
  319. package/dist/tui/run-limits-settings.d.ts +0 -39
  320. package/dist/tui/run-limits-settings.d.ts.map +0 -1
  321. package/dist/tui/run-limits-settings.js.map +0 -1
@@ -1,129 +0,0 @@
1
- import { type ProjectId, type RunId, type SessionId, type UserMessage } from '@namzu/sdk';
2
- declare const FORMAT: "namzu.cli-turn-evidence.v1";
3
- export type ConversationOrigin = {
4
- readonly kind: 'new';
5
- } | {
6
- /**
7
- * Immutable turn boundary copied from the source conversation. The
8
- * references are flattened, so later source turns and deeper fork chains
9
- * cannot change what this conversation inherited.
10
- */
11
- readonly kind: 'fork';
12
- readonly sourceSessionId: SessionId;
13
- readonly copiedMessages: number;
14
- readonly turns: readonly ConversationTurnReference[];
15
- } | {
16
- /**
17
- * The copied model history has no stable turn boundary yet. The source
18
- * is kept so a later lineage migration has evidence to work from, while
19
- * the current exporter refuses instead of guessing.
20
- */
21
- readonly kind: 'fork-unresolved';
22
- readonly sourceSessionId: SessionId;
23
- readonly copiedMessages: number;
24
- };
25
- export interface ConversationTurnReference {
26
- readonly sessionId: SessionId;
27
- readonly turnId: string;
28
- }
29
- export type ConversationTurnOutcome = 'completed' | 'stopped' | 'failed' | 'cancelled';
30
- export interface ConversationOriginRecord {
31
- readonly format: typeof FORMAT;
32
- readonly type: 'conversation_started';
33
- readonly projectId: ProjectId;
34
- readonly sessionId: SessionId;
35
- readonly recordedAt: number;
36
- readonly origin: ConversationOrigin;
37
- }
38
- export interface ConversationTurnStartedRecord {
39
- readonly format: typeof FORMAT;
40
- readonly type: 'turn_started';
41
- readonly projectId: ProjectId;
42
- readonly sessionId: SessionId;
43
- readonly turnId: string;
44
- readonly runId: RunId;
45
- readonly recordedAt: number;
46
- /** What the operator saw, before `@file` mentions were expanded. */
47
- readonly displayText: string;
48
- /** Exactly what the provider received, including expanded mentions. */
49
- readonly user: UserMessage;
50
- }
51
- export interface ConversationTurnSettledRecord {
52
- readonly format: typeof FORMAT;
53
- readonly type: 'turn_settled';
54
- readonly projectId: ProjectId;
55
- readonly sessionId: SessionId;
56
- readonly turnId: string;
57
- readonly runId: RunId;
58
- readonly recordedAt: number;
59
- readonly outcome: ConversationTurnOutcome;
60
- /** Raw assistant Markdown accumulated by the host; may be empty. */
61
- readonly assistantText: string;
62
- }
63
- export type ConversationEvidenceRecord = ConversationOriginRecord | ConversationTurnStartedRecord | ConversationTurnSettledRecord;
64
- export interface ConversationTurnEvidence {
65
- readonly started: ConversationTurnStartedRecord;
66
- readonly settled?: ConversationTurnSettledRecord;
67
- }
68
- export interface ConversationLineageTurn {
69
- readonly reference: ConversationTurnReference;
70
- readonly evidence: ConversationTurnEvidence;
71
- }
72
- export type ConversationEvidenceRead = {
73
- readonly kind: 'not-recorded';
74
- } | {
75
- readonly kind: 'available';
76
- readonly origin: ConversationOriginRecord;
77
- readonly turns: readonly ConversationTurnEvidence[];
78
- };
79
- export type ConversationLineageRead = {
80
- readonly kind: 'unavailable';
81
- readonly detail: string;
82
- } | {
83
- readonly kind: 'available';
84
- readonly origin: ConversationOriginRecord;
85
- /** Turns physically recorded in the requested conversation. */
86
- readonly localTurns: readonly ConversationTurnEvidence[];
87
- /** Inherited turns followed by local turns, at the immutable fork boundary. */
88
- readonly turns: readonly ConversationLineageTurn[];
89
- };
90
- export declare class ConversationEvidenceCorruptionError extends Error {
91
- constructor(message: string);
92
- }
93
- export interface DiskConversationEvidenceOptions {
94
- readonly root: string;
95
- readonly projectId: ProjectId;
96
- readonly now?: () => number;
97
- }
98
- export declare class DiskConversationEvidence {
99
- private readonly paths;
100
- private readonly projectId;
101
- private readonly now;
102
- private tail;
103
- constructor(options: DiskConversationEvidenceOptions);
104
- recordOrigin(sessionId: SessionId, origin: ConversationOrigin): Promise<void>;
105
- recordTurnStarted(input: {
106
- readonly sessionId: SessionId;
107
- readonly runId: RunId;
108
- readonly displayText: string;
109
- readonly user: UserMessage;
110
- }): Promise<ConversationTurnStartedRecord>;
111
- recordTurnSettled(input: {
112
- readonly sessionId: SessionId;
113
- readonly turnId: string;
114
- readonly runId: RunId;
115
- readonly outcome: ConversationTurnOutcome;
116
- readonly assistantText: string;
117
- }): Promise<ConversationTurnSettledRecord>;
118
- read(sessionId: SessionId): Promise<ConversationEvidenceRead>;
119
- /** Resolve and verify the immutable turn sequence visible to one conversation. */
120
- resolveLineage(sessionId: SessionId): Promise<ConversationLineageRead>;
121
- private serialize;
122
- private path;
123
- private append;
124
- private requireAvailable;
125
- private readUnlocked;
126
- private resolveReferencesUnlocked;
127
- }
128
- export {};
129
- //# sourceMappingURL=turn-evidence.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"turn-evidence.d.ts","sourceRoot":"","sources":["../../../src/integrations/sessions/turn-evidence.ts"],"names":[],"mappings":"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"}
@@ -1,517 +0,0 @@
1
- import { ensurePrivateStateDirectory } from '../state/private-directory.js';
2
- import { CliPathBuilder } from './paths.js';
3
- /**
4
- * Durable correlation between one CLI conversation and the SDK runs that
5
- * carried its turns.
6
- *
7
- * The SDK already owns run events and the verified survivor snapshot. This
8
- * file deliberately does not copy either. It records the fact the SDK cannot
9
- * infer: which exact user message the operator submitted as this turn, and
10
- * which caller-chosen run id was reserved for it before execution began.
11
- */
12
- import { randomUUID } from 'node:crypto';
13
- import { open, readFile } from 'node:fs/promises';
14
- import { join } from 'node:path';
15
- import { isDeepStrictEqual } from 'node:util';
16
- import { asGoalId, asProjectId, asRunId, asSessionId, isModelContentOmission, isProjectInstructionMessageSource, isRuntimeContextMessageSource, } from '@namzu/sdk';
17
- const FORMAT = 'namzu.cli-turn-evidence.v1';
18
- const FILE = 'turns.jsonl';
19
- export class ConversationEvidenceCorruptionError extends Error {
20
- constructor(message) {
21
- super(message);
22
- this.name = 'ConversationEvidenceCorruptionError';
23
- }
24
- }
25
- export class DiskConversationEvidence {
26
- paths;
27
- projectId;
28
- now;
29
- tail = Promise.resolve();
30
- constructor(options) {
31
- this.paths = new CliPathBuilder(options.root);
32
- this.projectId = options.projectId;
33
- this.now = options.now ?? Date.now;
34
- }
35
- async recordOrigin(sessionId, origin) {
36
- return await this.serialize(async () => {
37
- const record = {
38
- format: FORMAT,
39
- type: 'conversation_started',
40
- projectId: this.projectId,
41
- sessionId,
42
- recordedAt: this.now(),
43
- origin,
44
- };
45
- ensurePrivateStateDirectory(ensurePrivateStateDirectory(this.paths.rootDir(), 'sessions'), sessionId);
46
- const path = this.path(sessionId);
47
- let handle;
48
- try {
49
- handle = await open(path, 'wx', 0o600);
50
- await handle.writeFile(`${JSON.stringify(record)}\n`, 'utf-8');
51
- await handle.sync();
52
- }
53
- finally {
54
- await handle?.close();
55
- }
56
- const readBack = await this.readUnlocked(sessionId);
57
- if (readBack.kind !== 'available' || !isDeepStrictEqual(readBack.origin, record)) {
58
- throw new Error(`Conversation origin was not durably verified in ${path}.`);
59
- }
60
- });
61
- }
62
- async recordTurnStarted(input) {
63
- return await this.serialize(async () => {
64
- const before = await this.requireAvailable(input.sessionId);
65
- if (before.turns.some((turn) => turn.started.runId === input.runId)) {
66
- throw new ConversationEvidenceCorruptionError(`Run ${input.runId} is already bound in conversation ${input.sessionId}.`);
67
- }
68
- const record = {
69
- format: FORMAT,
70
- type: 'turn_started',
71
- projectId: this.projectId,
72
- sessionId: input.sessionId,
73
- turnId: `turn_${randomUUID().replaceAll('-', '')}`,
74
- runId: input.runId,
75
- recordedAt: this.now(),
76
- displayText: input.displayText,
77
- user: input.user,
78
- };
79
- await this.append(input.sessionId, record);
80
- const readBack = await this.requireAvailable(input.sessionId);
81
- const persisted = readBack.turns.find((turn) => turn.started.turnId === record.turnId)?.started;
82
- if (!isDeepStrictEqual(persisted, record)) {
83
- throw new Error(`Turn ${record.turnId} was not durably verified before run ${record.runId}.`);
84
- }
85
- return record;
86
- });
87
- }
88
- async recordTurnSettled(input) {
89
- return await this.serialize(async () => {
90
- const before = await this.requireAvailable(input.sessionId);
91
- const turn = before.turns.find((candidate) => candidate.started.turnId === input.turnId);
92
- if (!turn || turn.started.runId !== input.runId) {
93
- throw new ConversationEvidenceCorruptionError(`Turn ${input.turnId} is not bound to run ${input.runId} in conversation ${input.sessionId}.`);
94
- }
95
- if (turn.settled) {
96
- throw new ConversationEvidenceCorruptionError(`Turn ${input.turnId} already has a settlement record.`);
97
- }
98
- const record = {
99
- format: FORMAT,
100
- type: 'turn_settled',
101
- projectId: this.projectId,
102
- sessionId: input.sessionId,
103
- turnId: input.turnId,
104
- runId: input.runId,
105
- recordedAt: this.now(),
106
- outcome: input.outcome,
107
- assistantText: input.assistantText,
108
- };
109
- await this.append(input.sessionId, record);
110
- const readBack = await this.requireAvailable(input.sessionId);
111
- const persisted = readBack.turns.find((candidate) => candidate.started.turnId === record.turnId)?.settled;
112
- if (!isDeepStrictEqual(persisted, record)) {
113
- throw new Error(`Settlement for turn ${record.turnId} was not durably verified.`);
114
- }
115
- return record;
116
- });
117
- }
118
- async read(sessionId) {
119
- await this.tail;
120
- return await this.readUnlocked(sessionId);
121
- }
122
- /** Resolve and verify the immutable turn sequence visible to one conversation. */
123
- async resolveLineage(sessionId) {
124
- await this.tail;
125
- const resolved = await this.resolveReferencesUnlocked(sessionId, new Set());
126
- if (resolved.kind === 'unavailable')
127
- return resolved;
128
- const current = await this.readUnlocked(sessionId);
129
- if (current.kind !== 'available') {
130
- return {
131
- kind: 'unavailable',
132
- detail: `conversation ${sessionId} has no origin record`,
133
- };
134
- }
135
- const cache = new Map([[sessionId, current]]);
136
- const turns = [];
137
- for (const reference of resolved.references) {
138
- let owner = cache.get(reference.sessionId);
139
- if (!owner) {
140
- owner = await this.readUnlocked(reference.sessionId);
141
- cache.set(reference.sessionId, owner);
142
- }
143
- if (owner.kind !== 'available') {
144
- throw new ConversationEvidenceCorruptionError(`Fork lineage for conversation ${sessionId} names missing conversation ${reference.sessionId}.`);
145
- }
146
- const evidence = owner.turns.find((turn) => turn.started.turnId === reference.turnId);
147
- if (!evidence) {
148
- throw new ConversationEvidenceCorruptionError(`Fork lineage for conversation ${sessionId} names missing local turn ${reference.turnId} in ${reference.sessionId}.`);
149
- }
150
- turns.push({ reference, evidence });
151
- }
152
- return {
153
- kind: 'available',
154
- origin: current.origin,
155
- localTurns: current.turns,
156
- turns,
157
- };
158
- }
159
- async serialize(operation) {
160
- const result = this.tail.then(operation);
161
- this.tail = result.then(() => undefined, () => undefined);
162
- return await result;
163
- }
164
- path(sessionId) {
165
- return join(this.paths.sessionDir(this.projectId, sessionId), FILE);
166
- }
167
- async append(sessionId, record) {
168
- const path = this.path(sessionId);
169
- let handle;
170
- try {
171
- handle = await open(path, 'a', 0o600);
172
- await handle.writeFile(`${JSON.stringify(record)}\n`, 'utf-8');
173
- await handle.sync();
174
- }
175
- finally {
176
- await handle?.close();
177
- }
178
- }
179
- async requireAvailable(sessionId) {
180
- const evidence = await this.readUnlocked(sessionId);
181
- if (evidence.kind !== 'available') {
182
- throw new ConversationEvidenceCorruptionError(`Conversation ${sessionId} has no origin record.`);
183
- }
184
- return evidence;
185
- }
186
- async readUnlocked(sessionId) {
187
- const path = this.path(sessionId);
188
- let raw;
189
- try {
190
- raw = await readFile(path, 'utf-8');
191
- }
192
- catch (error) {
193
- if (isMissing(error))
194
- return { kind: 'not-recorded' };
195
- throw error;
196
- }
197
- if (raw.length === 0 || !raw.endsWith('\n')) {
198
- throw new ConversationEvidenceCorruptionError(`Conversation evidence in ${path} is empty or has a torn final record.`);
199
- }
200
- const records = raw
201
- .slice(0, -1)
202
- .split('\n')
203
- .map((line, index) => parseRecord(line, index + 1, path, this.projectId, sessionId));
204
- const origin = records[0];
205
- if (origin?.type !== 'conversation_started') {
206
- throw new ConversationEvidenceCorruptionError(`Conversation evidence in ${path} does not start with its origin.`);
207
- }
208
- if (records.slice(1).some((record) => record.type === 'conversation_started')) {
209
- throw new ConversationEvidenceCorruptionError(`Conversation evidence in ${path} contains more than one origin.`);
210
- }
211
- const turns = [];
212
- const byTurn = new Map();
213
- const runIds = new Set();
214
- for (const record of records.slice(1)) {
215
- if (record.type === 'turn_started') {
216
- if (byTurn.has(record.turnId) || runIds.has(record.runId)) {
217
- throw new ConversationEvidenceCorruptionError(`Conversation evidence in ${path} reuses turn ${record.turnId} or run ${record.runId}.`);
218
- }
219
- const turn = { started: record };
220
- turns.push(turn);
221
- byTurn.set(record.turnId, turn);
222
- runIds.add(record.runId);
223
- continue;
224
- }
225
- if (record.type === 'turn_settled') {
226
- const turn = byTurn.get(record.turnId);
227
- if (!turn || turn.started.runId !== record.runId || turn.settled) {
228
- throw new ConversationEvidenceCorruptionError(`Conversation evidence in ${path} has an orphan, mismatched, or duplicate settlement for turn ${record.turnId}.`);
229
- }
230
- turn.settled = record;
231
- }
232
- }
233
- return { kind: 'available', origin, turns };
234
- }
235
- async resolveReferencesUnlocked(sessionId, visiting) {
236
- if (visiting.has(sessionId)) {
237
- throw new ConversationEvidenceCorruptionError(`Fork lineage contains a cycle through conversation ${sessionId}.`);
238
- }
239
- visiting.add(sessionId);
240
- try {
241
- const evidence = await this.readUnlocked(sessionId);
242
- if (evidence.kind !== 'available') {
243
- return {
244
- kind: 'unavailable',
245
- detail: `conversation ${sessionId} has no origin record`,
246
- };
247
- }
248
- const local = evidence.turns.map((turn) => ({
249
- sessionId,
250
- turnId: turn.started.turnId,
251
- }));
252
- const origin = evidence.origin.origin;
253
- if (origin.kind === 'new')
254
- return { kind: 'available', references: local };
255
- if (origin.kind === 'fork-unresolved') {
256
- return {
257
- kind: 'unavailable',
258
- detail: `conversation ${sessionId} has an unresolved copied prefix from ${origin.sourceSessionId}`,
259
- };
260
- }
261
- const source = await this.resolveReferencesUnlocked(origin.sourceSessionId, visiting);
262
- if (source.kind === 'unavailable')
263
- return source;
264
- if (origin.turns.length > source.references.length ||
265
- origin.turns.some((reference, index) => !sameReference(reference, source.references[index]))) {
266
- throw new ConversationEvidenceCorruptionError(`Fork lineage for conversation ${sessionId} is not a prefix of source ${origin.sourceSessionId}.`);
267
- }
268
- return { kind: 'available', references: [...origin.turns, ...local] };
269
- }
270
- finally {
271
- visiting.delete(sessionId);
272
- }
273
- }
274
- }
275
- function parseRecord(line, lineNumber, path, projectId, sessionId) {
276
- let value;
277
- try {
278
- value = JSON.parse(line);
279
- }
280
- catch (error) {
281
- throw new ConversationEvidenceCorruptionError(`Conversation evidence in ${path} has invalid JSON at line ${lineNumber}: ${error instanceof Error ? error.message : String(error)}`);
282
- }
283
- if (!isObject(value) || value.format !== FORMAT) {
284
- throw new ConversationEvidenceCorruptionError(`Conversation evidence in ${path} has an unsupported record at line ${lineNumber}.`);
285
- }
286
- let recordProjectId;
287
- let recordSessionId;
288
- try {
289
- recordProjectId = asProjectId(requiredString(value.projectId, 'projectId'));
290
- recordSessionId = asSessionId(requiredString(value.sessionId, 'sessionId'));
291
- }
292
- catch (error) {
293
- throw invalidRecord(path, lineNumber, error);
294
- }
295
- if (recordProjectId !== projectId || recordSessionId !== sessionId) {
296
- throw new ConversationEvidenceCorruptionError(`Conversation evidence in ${path} is attributed to a different project or session at line ${lineNumber}.`);
297
- }
298
- const recordedAt = requiredTimestamp(value.recordedAt);
299
- switch (value.type) {
300
- case 'conversation_started':
301
- return {
302
- format: FORMAT,
303
- type: 'conversation_started',
304
- projectId: recordProjectId,
305
- sessionId: recordSessionId,
306
- recordedAt,
307
- origin: parseOrigin(value.origin, path, lineNumber, recordSessionId),
308
- };
309
- case 'turn_started': {
310
- let runId;
311
- try {
312
- runId = asRunId(requiredString(value.runId, 'runId'));
313
- }
314
- catch (error) {
315
- throw invalidRecord(path, lineNumber, error);
316
- }
317
- const turnId = requiredString(value.turnId, 'turnId');
318
- if (!/^turn_[a-z0-9]+$/.test(turnId))
319
- throw invalidRecord(path, lineNumber, 'turnId');
320
- return {
321
- format: FORMAT,
322
- type: 'turn_started',
323
- projectId: recordProjectId,
324
- sessionId: recordSessionId,
325
- turnId,
326
- runId,
327
- recordedAt,
328
- displayText: requiredString(value.displayText, 'displayText'),
329
- user: parseUserMessage(value.user, path, lineNumber),
330
- };
331
- }
332
- case 'turn_settled': {
333
- let runId;
334
- try {
335
- runId = asRunId(requiredString(value.runId, 'runId'));
336
- }
337
- catch (error) {
338
- throw invalidRecord(path, lineNumber, error);
339
- }
340
- const turnId = requiredString(value.turnId, 'turnId');
341
- if (!/^turn_[a-z0-9]+$/.test(turnId))
342
- throw invalidRecord(path, lineNumber, 'turnId');
343
- const outcome = value.outcome;
344
- if (!['completed', 'stopped', 'failed', 'cancelled'].includes(String(outcome))) {
345
- throw invalidRecord(path, lineNumber, 'outcome');
346
- }
347
- return {
348
- format: FORMAT,
349
- type: 'turn_settled',
350
- projectId: recordProjectId,
351
- sessionId: recordSessionId,
352
- turnId,
353
- runId,
354
- recordedAt,
355
- outcome: outcome,
356
- assistantText: requiredString(value.assistantText, 'assistantText'),
357
- };
358
- }
359
- default:
360
- throw new ConversationEvidenceCorruptionError(`Conversation evidence in ${path} has unknown record type ${String(value.type)} at line ${lineNumber}.`);
361
- }
362
- }
363
- function parseOrigin(value, path, line, sessionId) {
364
- if (!isObject(value))
365
- throw invalidRecord(path, line, 'origin');
366
- if (value.kind === 'new')
367
- return { kind: 'new' };
368
- if (value.kind !== 'fork' && value.kind !== 'fork-unresolved') {
369
- throw invalidRecord(path, line, 'origin.kind');
370
- }
371
- let sourceSessionId;
372
- try {
373
- sourceSessionId = asSessionId(requiredString(value.sourceSessionId, 'sourceSessionId'));
374
- }
375
- catch (error) {
376
- throw invalidRecord(path, line, error);
377
- }
378
- if (!Number.isSafeInteger(value.copiedMessages) || Number(value.copiedMessages) < 0) {
379
- throw invalidRecord(path, line, 'copiedMessages');
380
- }
381
- if (sourceSessionId === sessionId)
382
- throw invalidRecord(path, line, 'sourceSessionId');
383
- if (value.kind === 'fork') {
384
- if (!Array.isArray(value.turns))
385
- throw invalidRecord(path, line, 'turns');
386
- const seen = new Set();
387
- const turns = value.turns.map((entry) => {
388
- if (!isObject(entry))
389
- throw invalidRecord(path, line, 'turn reference');
390
- let owner;
391
- try {
392
- owner = asSessionId(requiredString(entry.sessionId, 'turn.sessionId'));
393
- }
394
- catch (error) {
395
- throw invalidRecord(path, line, error);
396
- }
397
- const turnId = requiredString(entry.turnId, 'turn.turnId');
398
- if (!/^turn_[a-z0-9]+$/.test(turnId))
399
- throw invalidRecord(path, line, 'turn.turnId');
400
- const key = `${owner}\0${turnId}`;
401
- if (seen.has(key))
402
- throw invalidRecord(path, line, 'duplicate turn reference');
403
- seen.add(key);
404
- return { sessionId: owner, turnId };
405
- });
406
- return {
407
- kind: 'fork',
408
- sourceSessionId,
409
- copiedMessages: Number(value.copiedMessages),
410
- turns,
411
- };
412
- }
413
- return {
414
- kind: 'fork-unresolved',
415
- sourceSessionId,
416
- copiedMessages: Number(value.copiedMessages),
417
- };
418
- }
419
- function parseUserMessage(value, path, line) {
420
- if (!isObject(value) || value.role !== 'user' || typeof value.content !== 'string') {
421
- throw invalidRecord(path, line, 'user');
422
- }
423
- if (value.timestamp !== undefined && !Number.isFinite(value.timestamp)) {
424
- throw invalidRecord(path, line, 'user.timestamp');
425
- }
426
- if (value.attachments !== undefined) {
427
- if (!Array.isArray(value.attachments))
428
- throw invalidRecord(path, line, 'user.attachments');
429
- for (const attachment of value.attachments)
430
- validateAttachment(attachment, path, line);
431
- }
432
- if (value.source !== undefined) {
433
- if (isObject(value.source) && value.source.type === 'project-instructions') {
434
- if (!isProjectInstructionMessageSource(value.source)) {
435
- throw invalidRecord(path, line, 'user.source');
436
- }
437
- }
438
- else if (isObject(value.source) && value.source.type === 'runtime-context') {
439
- if (!isRuntimeContextMessageSource(value.source)) {
440
- throw invalidRecord(path, line, 'user.source');
441
- }
442
- }
443
- else if (!isObject(value.source) ||
444
- value.source.type !== 'goal-round' ||
445
- typeof value.source.goalId !== 'string' ||
446
- typeof value.source.objective !== 'string' ||
447
- !Number.isSafeInteger(value.source.goalRevision) ||
448
- Number(value.source.goalRevision) < 1 ||
449
- !Number.isSafeInteger(value.source.round) ||
450
- Number(value.source.round) < 1 ||
451
- !Number.isSafeInteger(value.source.maxGoalRounds) ||
452
- Number(value.source.maxGoalRounds) < 1) {
453
- throw invalidRecord(path, line, 'user.source');
454
- }
455
- else {
456
- try {
457
- asGoalId(value.source.goalId);
458
- }
459
- catch {
460
- throw invalidRecord(path, line, 'user.source.goalId');
461
- }
462
- }
463
- }
464
- return value;
465
- }
466
- function validateAttachment(value, path, line) {
467
- if (!isObject(value) || typeof value.mediaType !== 'string') {
468
- throw invalidRecord(path, line, 'attachment');
469
- }
470
- if (value.type === 'stored') {
471
- if (typeof value.ref !== 'string' ||
472
- (value.kind !== 'image' && value.kind !== 'document') ||
473
- (value.name !== undefined && typeof value.name !== 'string') ||
474
- (value.citations !== undefined && typeof value.citations !== 'boolean')) {
475
- throw invalidRecord(path, line, 'stored attachment');
476
- }
477
- return;
478
- }
479
- if (typeof value.data !== 'string')
480
- throw invalidRecord(path, line, 'inline attachment');
481
- if (value.type === 'document') {
482
- if ((value.name !== undefined && typeof value.name !== 'string') ||
483
- (value.citations !== undefined && typeof value.citations !== 'boolean')) {
484
- throw invalidRecord(path, line, 'document attachment');
485
- }
486
- return;
487
- }
488
- if (value.type !== undefined && value.type !== 'image') {
489
- throw invalidRecord(path, line, 'attachment.type');
490
- }
491
- if (value.modelOmission !== undefined && !isModelContentOmission(value.modelOmission)) {
492
- throw invalidRecord(path, line, 'attachment.modelOmission');
493
- }
494
- }
495
- function requiredString(value, field) {
496
- if (typeof value !== 'string')
497
- throw new TypeError(`${field} must be a string`);
498
- return value;
499
- }
500
- function requiredTimestamp(value) {
501
- if (!Number.isFinite(value) || Number(value) < 0)
502
- throw new TypeError('recordedAt must be a timestamp');
503
- return Number(value);
504
- }
505
- function invalidRecord(path, line, detail) {
506
- return new ConversationEvidenceCorruptionError(`Conversation evidence in ${path} has an invalid record at line ${line}: ${detail instanceof Error ? detail.message : String(detail)}.`);
507
- }
508
- function isObject(value) {
509
- return typeof value === 'object' && value !== null && !Array.isArray(value);
510
- }
511
- function sameReference(left, right) {
512
- return left.sessionId === right?.sessionId && left.turnId === right?.turnId;
513
- }
514
- function isMissing(error) {
515
- return isObject(error) && error.code === 'ENOENT';
516
- }
517
- //# sourceMappingURL=turn-evidence.js.map