@code-yeongyu/senpi-agent-core 2026.9.12 → 2026.9.13

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 (344) hide show
  1. package/README.md +4 -0
  2. package/dist/harness/agent-harness.d.ts +639 -384
  3. package/dist/harness/agent-harness.d.ts.map +1 -1
  4. package/dist/harness/agent-harness.js +5 -250
  5. package/dist/harness/agent-harness.js.map +1 -1
  6. package/dist/harness/compaction/branch-summarization.d.ts +12 -6
  7. package/dist/harness/compaction/branch-summarization.d.ts.map +1 -1
  8. package/dist/harness/compaction/branch-summarization.js +33 -27
  9. package/dist/harness/compaction/branch-summarization.js.map +1 -1
  10. package/dist/harness/compaction/compaction.d.ts +30 -8
  11. package/dist/harness/compaction/compaction.d.ts.map +1 -1
  12. package/dist/harness/compaction/compaction.js +53 -64
  13. package/dist/harness/compaction/compaction.js.map +1 -1
  14. package/dist/harness/config.d.ts +9 -0
  15. package/dist/harness/config.d.ts.map +1 -0
  16. package/dist/harness/config.js +35 -0
  17. package/dist/harness/config.js.map +1 -0
  18. package/dist/harness/context.d.ts +9 -0
  19. package/dist/harness/context.d.ts.map +1 -0
  20. package/dist/harness/context.js +13 -0
  21. package/dist/harness/context.js.map +1 -0
  22. package/dist/harness/env/nodejs.d.ts +25 -28
  23. package/dist/harness/env/nodejs.d.ts.map +1 -1
  24. package/dist/harness/env/nodejs.js +368 -125
  25. package/dist/harness/env/nodejs.js.map +1 -1
  26. package/dist/harness/events.d.ts +20 -38
  27. package/dist/harness/events.d.ts.map +1 -1
  28. package/dist/harness/events.js +233 -55
  29. package/dist/harness/events.js.map +1 -1
  30. package/dist/harness/execution/assistant.d.ts +42 -0
  31. package/dist/harness/execution/assistant.d.ts.map +1 -0
  32. package/dist/harness/execution/assistant.js +82 -0
  33. package/dist/harness/execution/assistant.js.map +1 -0
  34. package/dist/harness/execution/effect-gate.d.ts +22 -0
  35. package/dist/harness/execution/effect-gate.d.ts.map +1 -0
  36. package/dist/harness/execution/effect-gate.js +48 -0
  37. package/dist/harness/execution/effect-gate.js.map +1 -0
  38. package/dist/harness/execution/tools.d.ts +67 -0
  39. package/dist/harness/execution/tools.d.ts.map +1 -0
  40. package/dist/harness/execution/tools.js +121 -0
  41. package/dist/harness/execution/tools.js.map +1 -0
  42. package/dist/harness/hooks.d.ts +38 -0
  43. package/dist/harness/hooks.d.ts.map +1 -0
  44. package/dist/harness/hooks.js +404 -0
  45. package/dist/harness/hooks.js.map +1 -0
  46. package/dist/harness/messages.d.ts +2 -2
  47. package/dist/harness/messages.d.ts.map +1 -1
  48. package/dist/harness/messages.js.map +1 -1
  49. package/dist/harness/prompt-templates.d.ts +3 -2
  50. package/dist/harness/prompt-templates.d.ts.map +1 -1
  51. package/dist/harness/prompt-templates.js +17 -17
  52. package/dist/harness/prompt-templates.js.map +1 -1
  53. package/dist/harness/result.d.ts +93 -0
  54. package/dist/harness/result.d.ts.map +1 -1
  55. package/dist/harness/result.js +39 -0
  56. package/dist/harness/result.js.map +1 -1
  57. package/dist/harness/runtime/drive/boundary.d.ts +28 -0
  58. package/dist/harness/runtime/drive/boundary.d.ts.map +1 -0
  59. package/dist/harness/runtime/drive/boundary.js +173 -0
  60. package/dist/harness/runtime/drive/boundary.js.map +1 -0
  61. package/dist/harness/runtime/drive/checkpoint.d.ts +8 -0
  62. package/dist/harness/runtime/drive/checkpoint.d.ts.map +1 -0
  63. package/dist/harness/runtime/drive/checkpoint.js +133 -0
  64. package/dist/harness/runtime/drive/checkpoint.js.map +1 -0
  65. package/dist/harness/runtime/drive/deferred.d.ts +15 -0
  66. package/dist/harness/runtime/drive/deferred.d.ts.map +1 -0
  67. package/dist/harness/runtime/drive/deferred.js +179 -0
  68. package/dist/harness/runtime/drive/deferred.js.map +1 -0
  69. package/dist/harness/runtime/drive/generation.d.ts +8 -0
  70. package/dist/harness/runtime/drive/generation.d.ts.map +1 -0
  71. package/dist/harness/runtime/drive/generation.js +205 -0
  72. package/dist/harness/runtime/drive/generation.js.map +1 -0
  73. package/dist/harness/runtime/drive/reconcile.d.ts +5 -0
  74. package/dist/harness/runtime/drive/reconcile.d.ts.map +1 -0
  75. package/dist/harness/runtime/drive/reconcile.js +140 -0
  76. package/dist/harness/runtime/drive/reconcile.js.map +1 -0
  77. package/dist/harness/runtime/drive/recovery.d.ts +8 -0
  78. package/dist/harness/runtime/drive/recovery.d.ts.map +1 -0
  79. package/dist/harness/runtime/drive/recovery.js +85 -0
  80. package/dist/harness/runtime/drive/recovery.js.map +1 -0
  81. package/dist/harness/runtime/drive/response.d.ts +23 -0
  82. package/dist/harness/runtime/drive/response.d.ts.map +1 -0
  83. package/dist/harness/runtime/drive/response.js +394 -0
  84. package/dist/harness/runtime/drive/response.js.map +1 -0
  85. package/dist/harness/runtime/drive/retry.d.ts +4 -0
  86. package/dist/harness/runtime/drive/retry.d.ts.map +1 -0
  87. package/dist/harness/runtime/drive/retry.js +34 -0
  88. package/dist/harness/runtime/drive/retry.js.map +1 -0
  89. package/dist/harness/runtime/drive/structural.d.ts +32 -0
  90. package/dist/harness/runtime/drive/structural.d.ts.map +1 -0
  91. package/dist/harness/runtime/drive/structural.js +929 -0
  92. package/dist/harness/runtime/drive/structural.js.map +1 -0
  93. package/dist/harness/runtime/drive/terminal.d.ts +7 -0
  94. package/dist/harness/runtime/drive/terminal.d.ts.map +1 -0
  95. package/dist/harness/runtime/drive/terminal.js +49 -0
  96. package/dist/harness/runtime/drive/terminal.js.map +1 -0
  97. package/dist/harness/runtime/drive/tool-placement.d.ts +14 -0
  98. package/dist/harness/runtime/drive/tool-placement.d.ts.map +1 -0
  99. package/dist/harness/runtime/drive/tool-placement.js +244 -0
  100. package/dist/harness/runtime/drive/tool-placement.js.map +1 -0
  101. package/dist/harness/runtime/drive/tools.d.ts +6 -0
  102. package/dist/harness/runtime/drive/tools.d.ts.map +1 -0
  103. package/dist/harness/runtime/drive/tools.js +449 -0
  104. package/dist/harness/runtime/drive/tools.js.map +1 -0
  105. package/dist/harness/runtime/drive.d.ts +6 -0
  106. package/dist/harness/runtime/drive.d.ts.map +1 -0
  107. package/dist/harness/runtime/drive.js +93 -0
  108. package/dist/harness/runtime/drive.js.map +1 -0
  109. package/dist/harness/runtime/harness.d.ts +59 -0
  110. package/dist/harness/runtime/harness.d.ts.map +1 -0
  111. package/dist/harness/runtime/harness.js +302 -0
  112. package/dist/harness/runtime/harness.js.map +1 -0
  113. package/dist/harness/runtime/index.d.ts +2 -0
  114. package/dist/harness/runtime/index.d.ts.map +1 -0
  115. package/dist/harness/runtime/index.js +2 -0
  116. package/dist/harness/runtime/index.js.map +1 -0
  117. package/dist/harness/runtime/lane.d.ts +118 -0
  118. package/dist/harness/runtime/lane.d.ts.map +1 -0
  119. package/dist/harness/runtime/lane.js +1559 -0
  120. package/dist/harness/runtime/lane.js.map +1 -0
  121. package/dist/harness/runtime/progress.d.ts +15 -0
  122. package/dist/harness/runtime/progress.d.ts.map +1 -0
  123. package/dist/harness/runtime/progress.js +66 -0
  124. package/dist/harness/runtime/progress.js.map +1 -0
  125. package/dist/harness/runtime/reducer.d.ts +5 -0
  126. package/dist/harness/runtime/reducer.d.ts.map +1 -0
  127. package/dist/harness/runtime/reducer.js +240 -0
  128. package/dist/harness/runtime/reducer.js.map +1 -0
  129. package/dist/harness/runtime/restore.d.ts +24 -0
  130. package/dist/harness/runtime/restore.d.ts.map +1 -0
  131. package/dist/harness/runtime/restore.js +117 -0
  132. package/dist/harness/runtime/restore.js.map +1 -0
  133. package/dist/harness/runtime/transcript.d.ts +21 -0
  134. package/dist/harness/runtime/transcript.d.ts.map +1 -0
  135. package/dist/harness/runtime/transcript.js +72 -0
  136. package/dist/harness/runtime/transcript.js.map +1 -0
  137. package/dist/harness/runtime/types.d.ts +105 -0
  138. package/dist/harness/runtime/types.d.ts.map +1 -0
  139. package/dist/harness/runtime/types.js +50 -0
  140. package/dist/harness/runtime/types.js.map +1 -0
  141. package/dist/harness/session/commit.d.ts +53 -0
  142. package/dist/harness/session/commit.d.ts.map +1 -0
  143. package/dist/harness/session/commit.js +57 -0
  144. package/dist/harness/session/commit.js.map +1 -0
  145. package/dist/harness/session/context.d.ts +6 -19
  146. package/dist/harness/session/context.d.ts.map +1 -1
  147. package/dist/harness/session/context.js +31 -53
  148. package/dist/harness/session/context.js.map +1 -1
  149. package/dist/harness/session/fork-policy.d.ts +21 -0
  150. package/dist/harness/session/fork-policy.d.ts.map +1 -0
  151. package/dist/harness/session/fork-policy.js +55 -0
  152. package/dist/harness/session/fork-policy.js.map +1 -0
  153. package/dist/harness/session/fork.d.ts +16 -0
  154. package/dist/harness/session/fork.d.ts.map +1 -0
  155. package/dist/harness/session/fork.js +79 -0
  156. package/dist/harness/session/fork.js.map +1 -0
  157. package/dist/harness/session/in-memory-storage-state.d.ts +39 -0
  158. package/dist/harness/session/in-memory-storage-state.d.ts.map +1 -0
  159. package/dist/harness/session/in-memory-storage-state.js +269 -0
  160. package/dist/harness/session/in-memory-storage-state.js.map +1 -0
  161. package/dist/harness/session/index.d.ts +9 -5
  162. package/dist/harness/session/index.d.ts.map +1 -1
  163. package/dist/harness/session/index.js +7 -4
  164. package/dist/harness/session/index.js.map +1 -1
  165. package/dist/harness/session/jsonl/codec.d.ts +19 -8
  166. package/dist/harness/session/jsonl/codec.d.ts.map +1 -1
  167. package/dist/harness/session/jsonl/codec.js +34 -219
  168. package/dist/harness/session/jsonl/codec.js.map +1 -1
  169. package/dist/harness/session/jsonl/fork.d.ts +38 -0
  170. package/dist/harness/session/jsonl/fork.d.ts.map +1 -0
  171. package/dist/harness/session/jsonl/fork.js +266 -0
  172. package/dist/harness/session/jsonl/fork.js.map +1 -0
  173. package/dist/harness/session/jsonl/index.d.ts +4 -0
  174. package/dist/harness/session/jsonl/index.d.ts.map +1 -0
  175. package/dist/harness/session/jsonl/index.js +4 -0
  176. package/dist/harness/session/jsonl/index.js.map +1 -0
  177. package/dist/harness/session/jsonl/io.d.ts +14 -0
  178. package/dist/harness/session/jsonl/io.d.ts.map +1 -0
  179. package/dist/harness/session/jsonl/io.js +86 -0
  180. package/dist/harness/session/jsonl/io.js.map +1 -0
  181. package/dist/harness/session/jsonl/legacy-v3.d.ts +44 -0
  182. package/dist/harness/session/jsonl/legacy-v3.d.ts.map +1 -0
  183. package/dist/harness/session/jsonl/legacy-v3.js +454 -0
  184. package/dist/harness/session/jsonl/legacy-v3.js.map +1 -0
  185. package/dist/harness/session/jsonl/repo.d.ts +27 -24
  186. package/dist/harness/session/jsonl/repo.d.ts.map +1 -1
  187. package/dist/harness/session/jsonl/repo.js +276 -151
  188. package/dist/harness/session/jsonl/repo.js.map +1 -1
  189. package/dist/harness/session/jsonl/storage.d.ts +39 -41
  190. package/dist/harness/session/jsonl/storage.d.ts.map +1 -1
  191. package/dist/harness/session/jsonl/storage.js +175 -196
  192. package/dist/harness/session/jsonl/storage.js.map +1 -1
  193. package/dist/harness/session/jsonl/types.d.ts +23 -22
  194. package/dist/harness/session/jsonl/types.d.ts.map +1 -1
  195. package/dist/harness/session/jsonl/types.js +2 -1
  196. package/dist/harness/session/jsonl/types.js.map +1 -1
  197. package/dist/harness/session/memory.d.ts +44 -40
  198. package/dist/harness/session/memory.d.ts.map +1 -1
  199. package/dist/harness/session/memory.js +333 -115
  200. package/dist/harness/session/memory.js.map +1 -1
  201. package/dist/harness/session/mutation-line.d.ts +8 -0
  202. package/dist/harness/session/mutation-line.d.ts.map +1 -0
  203. package/dist/harness/session/mutation-line.js +22 -0
  204. package/dist/harness/session/mutation-line.js.map +1 -0
  205. package/dist/harness/session/session.d.ts +78 -51
  206. package/dist/harness/session/session.d.ts.map +1 -1
  207. package/dist/harness/session/session.js +327 -207
  208. package/dist/harness/session/session.js.map +1 -1
  209. package/dist/harness/session/testing/benchmark/datasets.d.ts +12 -0
  210. package/dist/harness/session/testing/benchmark/datasets.d.ts.map +1 -0
  211. package/dist/harness/session/testing/benchmark/datasets.js +24 -0
  212. package/dist/harness/session/testing/benchmark/datasets.js.map +1 -0
  213. package/dist/harness/session/testing/benchmark/session-repo.d.ts +42 -0
  214. package/dist/harness/session/testing/benchmark/session-repo.d.ts.map +1 -0
  215. package/dist/harness/session/testing/benchmark/session-repo.js +127 -0
  216. package/dist/harness/session/testing/benchmark/session-repo.js.map +1 -0
  217. package/dist/harness/session/testing/benchmark/storage.d.ts +25 -0
  218. package/dist/harness/session/testing/benchmark/storage.d.ts.map +1 -0
  219. package/dist/harness/session/testing/benchmark/storage.js +114 -0
  220. package/dist/harness/session/testing/benchmark/storage.js.map +1 -0
  221. package/dist/harness/session/testing/conformance/session-repo.d.ts +23 -0
  222. package/dist/harness/session/testing/conformance/session-repo.d.ts.map +1 -0
  223. package/dist/harness/session/testing/conformance/session-repo.js +809 -0
  224. package/dist/harness/session/testing/conformance/session-repo.js.map +1 -0
  225. package/dist/harness/session/testing/conformance/storage.d.ts +4 -0
  226. package/dist/harness/session/testing/conformance/storage.d.ts.map +1 -0
  227. package/dist/harness/session/testing/conformance/storage.js +600 -0
  228. package/dist/harness/session/testing/conformance/storage.js.map +1 -0
  229. package/dist/harness/session/testing/gating-storage.d.ts +26 -0
  230. package/dist/harness/session/testing/gating-storage.d.ts.map +1 -0
  231. package/dist/harness/session/testing/gating-storage.js +103 -0
  232. package/dist/harness/session/testing/gating-storage.js.map +1 -0
  233. package/dist/harness/session/testing/index.d.ts +9 -2
  234. package/dist/harness/session/testing/index.d.ts.map +1 -1
  235. package/dist/harness/session/testing/index.js +8 -1
  236. package/dist/harness/session/testing/index.js.map +1 -1
  237. package/dist/harness/session/testing/instrumented-storage.d.ts +11 -0
  238. package/dist/harness/session/testing/instrumented-storage.d.ts.map +1 -0
  239. package/dist/harness/session/testing/instrumented-storage.js +19 -0
  240. package/dist/harness/session/testing/instrumented-storage.js.map +1 -0
  241. package/dist/harness/session/testing/storage-decorator.d.ts +20 -0
  242. package/dist/harness/session/testing/storage-decorator.d.ts.map +1 -0
  243. package/dist/harness/session/testing/storage-decorator.js +40 -0
  244. package/dist/harness/session/testing/storage-decorator.js.map +1 -0
  245. package/dist/harness/session/testing/types.d.ts +5 -7
  246. package/dist/harness/session/testing/types.d.ts.map +1 -1
  247. package/dist/harness/session/testing/types.js.map +1 -1
  248. package/dist/harness/session/types.d.ts +425 -265
  249. package/dist/harness/session/types.d.ts.map +1 -1
  250. package/dist/harness/session/types.js +7 -7
  251. package/dist/harness/session/types.js.map +1 -1
  252. package/dist/harness/session/values.d.ts +95 -0
  253. package/dist/harness/session/values.d.ts.map +1 -0
  254. package/dist/harness/session/values.js +81 -0
  255. package/dist/harness/session/values.js.map +1 -0
  256. package/dist/harness/skills.d.ts +3 -2
  257. package/dist/harness/skills.d.ts.map +1 -1
  258. package/dist/harness/skills.js +29 -26
  259. package/dist/harness/skills.js.map +1 -1
  260. package/dist/harness/telemetry.d.ts +64 -43
  261. package/dist/harness/telemetry.d.ts.map +1 -1
  262. package/dist/harness/telemetry.js +45 -26
  263. package/dist/harness/telemetry.js.map +1 -1
  264. package/dist/harness/tools/bash.d.ts +4 -4
  265. package/dist/harness/tools/bash.d.ts.map +1 -1
  266. package/dist/harness/tools/bash.js +66 -93
  267. package/dist/harness/tools/bash.js.map +1 -1
  268. package/dist/harness/tools/edit.d.ts.map +1 -1
  269. package/dist/harness/tools/edit.js +17 -13
  270. package/dist/harness/tools/edit.js.map +1 -1
  271. package/dist/harness/tools/file-mutation-queue.d.ts +2 -1
  272. package/dist/harness/tools/file-mutation-queue.d.ts.map +1 -1
  273. package/dist/harness/tools/file-mutation-queue.js +5 -5
  274. package/dist/harness/tools/file-mutation-queue.js.map +1 -1
  275. package/dist/harness/tools/path-utils.d.ts +3 -2
  276. package/dist/harness/tools/path-utils.d.ts.map +1 -1
  277. package/dist/harness/tools/path-utils.js +5 -5
  278. package/dist/harness/tools/path-utils.js.map +1 -1
  279. package/dist/harness/tools/read.d.ts +2 -1
  280. package/dist/harness/tools/read.d.ts.map +1 -1
  281. package/dist/harness/tools/read.js +4 -6
  282. package/dist/harness/tools/read.js.map +1 -1
  283. package/dist/harness/tools/write.d.ts.map +1 -1
  284. package/dist/harness/tools/write.js +12 -8
  285. package/dist/harness/tools/write.js.map +1 -1
  286. package/dist/harness/types.d.ts +128 -45
  287. package/dist/harness/types.d.ts.map +1 -1
  288. package/dist/harness/types.js.map +1 -1
  289. package/dist/harness/utils/adaptive-publisher.d.ts +24 -0
  290. package/dist/harness/utils/adaptive-publisher.d.ts.map +1 -0
  291. package/dist/harness/utils/adaptive-publisher.js +79 -0
  292. package/dist/harness/utils/adaptive-publisher.js.map +1 -0
  293. package/dist/harness/utils/output-capture.d.ts +31 -0
  294. package/dist/harness/utils/output-capture.d.ts.map +1 -0
  295. package/dist/harness/utils/output-capture.js +217 -0
  296. package/dist/harness/utils/output-capture.js.map +1 -0
  297. package/dist/harness/utils/shell-output.d.ts +19 -5
  298. package/dist/harness/utils/shell-output.d.ts.map +1 -1
  299. package/dist/harness/utils/shell-output.js +65 -192
  300. package/dist/harness/utils/shell-output.js.map +1 -1
  301. package/dist/harness/utils/truncate.d.ts +1 -0
  302. package/dist/harness/utils/truncate.d.ts.map +1 -1
  303. package/dist/harness/utils/truncate.js +1 -1
  304. package/dist/harness/utils/truncate.js.map +1 -1
  305. package/dist/harness/utils/usage.d.ts +4 -0
  306. package/dist/harness/utils/usage.d.ts.map +1 -0
  307. package/dist/harness/utils/usage.js +33 -0
  308. package/dist/harness/utils/usage.js.map +1 -0
  309. package/dist/index.d.ts +4 -1
  310. package/dist/index.d.ts.map +1 -1
  311. package/dist/index.js +3 -6
  312. package/dist/index.js.map +1 -1
  313. package/dist/search/index.d.ts +24 -16
  314. package/dist/search/index.d.ts.map +1 -1
  315. package/dist/search/index.js +1 -1
  316. package/dist/search/index.js.map +1 -1
  317. package/dist/types.d.ts +2 -0
  318. package/dist/types.d.ts.map +1 -1
  319. package/dist/types.js.map +1 -1
  320. package/package.json +27 -6
  321. package/dist/harness/reducer.d.ts +0 -100
  322. package/dist/harness/reducer.d.ts.map +0 -1
  323. package/dist/harness/reducer.js +0 -420
  324. package/dist/harness/reducer.js.map +0 -1
  325. package/dist/harness/session/jsonl/errors.d.ts +0 -9
  326. package/dist/harness/session/jsonl/errors.d.ts.map +0 -1
  327. package/dist/harness/session/jsonl/errors.js +0 -18
  328. package/dist/harness/session/jsonl/errors.js.map +0 -1
  329. package/dist/harness/session/jsonl.d.ts +0 -3
  330. package/dist/harness/session/jsonl.d.ts.map +0 -1
  331. package/dist/harness/session/jsonl.js +0 -2
  332. package/dist/harness/session/jsonl.js.map +0 -1
  333. package/dist/harness/session/state.d.ts +0 -65
  334. package/dist/harness/session/state.d.ts.map +0 -1
  335. package/dist/harness/session/state.js +0 -320
  336. package/dist/harness/session/state.js.map +0 -1
  337. package/dist/harness/session/testing/conformance.d.ts +0 -4
  338. package/dist/harness/session/testing/conformance.d.ts.map +0 -1
  339. package/dist/harness/session/testing/conformance.js +0 -762
  340. package/dist/harness/session/testing/conformance.js.map +0 -1
  341. package/dist/search/scanning.d.ts +0 -29
  342. package/dist/search/scanning.d.ts.map +0 -1
  343. package/dist/search/scanning.js +0 -103
  344. package/dist/search/scanning.js.map +0 -1
@@ -1,225 +1,345 @@
1
- import { uuidv7 } from "@earendil-works/pi-ai";
2
- import { SessionError } from "./types.js";
3
- function invalidPayload(reason) {
4
- throw new SessionError("invalid_payload", `Durable payload ${reason}`);
1
+ import { uuidv7 } from "@earendil-works/pi-ai/utils/uuid";
2
+ import { insertEntry } from "./commit.js";
3
+ import { MutationLine } from "./mutation-line.js";
4
+ import { appendList as appendListWrite, branchTip, deleteList as deleteListWrite, deleteValue as deleteValueWrite, entryLabel, sessionName, setValue as setValueWrite, } from "./values.js";
5
+ /** Durable session state is internally inconsistent and cannot be safely advanced. */
6
+ export class SessionInvariantError extends Error {
7
+ constructor(message) {
8
+ super(message);
9
+ this.name = "SessionInvariantError";
10
+ }
5
11
  }
6
- function assertValidLimit(limit) {
7
- if (limit !== undefined && (!Number.isInteger(limit) || limit <= 0)) {
8
- throw new SessionError("invalid_query", "limit must be a positive integer");
12
+ /** A requested Branch name is invalid. */
13
+ export class SessionInvalidBranchError extends Error {
14
+ constructor(branch, reason) {
15
+ super(`Invalid branch ${JSON.stringify(branch)}: ${reason}`);
16
+ this.name = "SessionInvalidBranchError";
17
+ this.branch = branch;
18
+ this.reason = reason;
9
19
  }
10
20
  }
11
- function assertValidCursor(afterSeq) {
12
- if (afterSeq !== undefined && (!Number.isInteger(afterSeq) || afterSeq < 0)) {
13
- throw new SessionError("invalid_query", "cursor sequence must be a non-negative integer");
21
+ /** A requested branch already exists. */
22
+ export class SessionBranchExistsError extends Error {
23
+ constructor(branch) {
24
+ super(`Branch already exists: ${branch}`);
25
+ this.name = "SessionBranchExistsError";
26
+ this.branch = branch;
14
27
  }
15
28
  }
16
- export function assertJsonSerializable(value) {
17
- const active = new WeakSet();
18
- const stack = [{ value }];
19
- while (stack.length > 0) {
20
- const frame = stack.pop();
21
- if ("exit" in frame) {
22
- active.delete(frame.exit);
23
- continue;
24
- }
25
- const candidate = frame.value;
26
- if (candidate === null || typeof candidate === "string" || typeof candidate === "boolean") {
27
- continue;
28
- }
29
- if (typeof candidate === "number") {
30
- if (!Number.isFinite(candidate))
31
- invalidPayload("contains a non-finite number");
32
- continue;
33
- }
34
- if (typeof candidate !== "object")
35
- invalidPayload(`contains ${typeof candidate}`);
36
- if (active.has(candidate))
37
- invalidPayload("contains a cycle");
38
- active.add(candidate);
39
- stack.push({ exit: candidate });
40
- if (Array.isArray(candidate)) {
41
- if (Object.getPrototypeOf(candidate) !== Array.prototype) {
42
- invalidPayload("contains a non-standard array");
43
- }
44
- if (Object.getOwnPropertySymbols(candidate).length > 0 ||
45
- Object.getOwnPropertyNames(candidate).length !== candidate.length + 1) {
46
- invalidPayload("contains an array with unsupported properties");
47
- }
48
- for (let index = candidate.length - 1; index >= 0; index--) {
49
- if (!Object.hasOwn(candidate, index))
50
- invalidPayload("contains a sparse array");
51
- const descriptor = Object.getOwnPropertyDescriptor(candidate, index);
52
- if (!("value" in descriptor))
53
- invalidPayload("contains an array accessor");
54
- stack.push({ value: descriptor.value });
29
+ /** A pending assistant message cannot be persisted as a session entry. */
30
+ export class SessionPendingAssistantMessageError extends Error {
31
+ constructor() {
32
+ super("Cannot persist a pending assistant message");
33
+ this.name = "SessionPendingAssistantMessageError";
34
+ }
35
+ }
36
+ /** A requested session entry target does not exist. */
37
+ export class SessionUnknownTargetError extends Error {
38
+ constructor(targetId) {
39
+ super(`Unknown target: ${targetId}`);
40
+ this.name = "SessionUnknownTargetError";
41
+ this.targetId = targetId;
42
+ }
43
+ }
44
+ class StorageBackedSessionMutation {
45
+ constructor(storage, release) {
46
+ this.active = true;
47
+ this.storage = storage;
48
+ this.release = release;
49
+ }
50
+ commit(writes, context) {
51
+ this.assertActive();
52
+ if (this.commitResult !== undefined)
53
+ return Promise.reject(new Error("SessionMutator commit already attempted"));
54
+ try {
55
+ for (const write of writes) {
56
+ if (write.kind === "entry" &&
57
+ write.entry.type === "message" &&
58
+ write.entry.message.role === "assistant" &&
59
+ write.entry.message.stopReason === "pending") {
60
+ throw new SessionPendingAssistantMessageError();
61
+ }
55
62
  }
56
- continue;
57
- }
58
- const prototype = Object.getPrototypeOf(candidate);
59
- if (prototype !== Object.prototype && prototype !== null) {
60
- invalidPayload("contains a non-plain object");
61
- }
62
- if (Object.getOwnPropertySymbols(candidate).length > 0) {
63
- invalidPayload("contains a symbol-keyed property");
63
+ this.commitResult = this.storage.commit(writes, context);
64
64
  }
65
- const keys = Object.keys(candidate);
66
- if (Object.getOwnPropertyNames(candidate).length !== keys.length) {
67
- invalidPayload("contains a non-enumerable property");
68
- }
69
- for (let index = keys.length - 1; index >= 0; index--) {
70
- const descriptor = Object.getOwnPropertyDescriptor(candidate, keys[index]);
71
- if (!("value" in descriptor))
72
- invalidPayload("contains an accessor");
73
- stack.push({ value: descriptor.value });
65
+ catch (error) {
66
+ this.commitResult = Promise.reject(error);
74
67
  }
68
+ return this.commitResult;
69
+ }
70
+ end(_context) {
71
+ if (this.endPromise !== undefined)
72
+ return this.endPromise;
73
+ this.active = false;
74
+ this.endPromise = this.settle().finally(this.release);
75
+ return this.endPromise;
76
+ }
77
+ getEntries(ids, context) {
78
+ this.assertActive();
79
+ return this.storage.getEntries(ids, context);
80
+ }
81
+ getStats(context) {
82
+ this.assertActive();
83
+ return this.storage.getStats(context);
84
+ }
85
+ getValue(address, context) {
86
+ this.assertActive();
87
+ return this.storage.getValue(address, context);
88
+ }
89
+ scanValues(prefix, context) {
90
+ this.assertActive();
91
+ return this.storage.scanValues(prefix, context);
92
+ }
93
+ readList(address, options, context) {
94
+ this.assertActive();
95
+ return this.storage.readList(address, options, context);
96
+ }
97
+ scanBranch(query, context) {
98
+ this.assertActive();
99
+ return this.storage.scanBranch(query, context);
100
+ }
101
+ settle() {
102
+ return (this.commitResult?.then(() => undefined, () => undefined) ?? Promise.resolve());
103
+ }
104
+ assertActive() {
105
+ if (!this.active)
106
+ throw new Error("SessionMutator cannot be used outside its mutation callback");
75
107
  }
76
108
  }
77
- export class Session {
78
- constructor(storage, options = {}) {
79
- this.storage = storage;
80
- this.idGenerator = options.idGenerator ?? { next: () => uuidv7() };
109
+ class StorageBackedBranch {
110
+ constructor(name, session) {
111
+ this.name = name;
112
+ this.session = session;
81
113
  }
82
- async getMetadata() {
83
- return this.storage.getMetadata();
114
+ getTipId(context) {
115
+ return this.session.getBranchTip(this.name, context);
84
116
  }
85
- view(lane) {
86
- if (lane === "main")
87
- return this;
88
- return {
89
- getLeafId: () => this.getLeafIdForLane(lane),
90
- getEntry: (id) => this.getEntry(id),
91
- getStats: () => this.getStats(),
92
- getName: () => this.getName(),
93
- setName: (name) => this.setName(name),
94
- getLabel: (targetId) => this.getLabel(targetId),
95
- setLabel: (targetId, label) => this.setLabel(targetId, label),
96
- findEntries: (query) => this.queryEntries(query),
97
- findEntry: async (query = {}) => (await this.queryEntries(query, 1))[0],
98
- findEntriesOnBranch: (query) => this.queryBranchEntries(lane, query),
99
- findEntryOnBranch: async (query = {}) => (await this.queryBranchEntries(lane, query, 1))[0],
100
- appendMessage: (message) => this.appendMessageToLane(lane, message),
101
- appendCustomEntry: (customType, data) => this.appendCustomEntryToLane(lane, customType, data),
102
- };
103
- }
104
- async getLeafId() {
105
- return this.getLeafIdForLane("main");
106
- }
107
- async getEntry(id) {
108
- return this.storage.getEntry(id);
109
- }
110
- async getStats() {
111
- return this.storage.getStats();
112
- }
113
- async getName() {
114
- return this.storage.getName();
115
- }
116
- async setName(name) {
117
- await this.storage.setName(name);
118
- }
119
- async getLabel(targetId) {
120
- return this.storage.getLabel(targetId);
121
- }
122
- async setLabel(targetId, label) {
123
- await this.storage.setLabel(targetId, label);
124
- }
125
- async findEntries(query) {
126
- return this.queryEntries(query);
127
- }
128
- async findEntry(query = {}) {
129
- return (await this.queryEntries(query, 1))[0];
130
- }
131
- async findEntriesOnBranch(query) {
132
- return this.queryBranchEntries("main", query);
133
- }
134
- async findEntryOnBranch(query = {}) {
135
- return (await this.queryBranchEntries("main", query, 1))[0];
136
- }
137
- async appendMessage(message) {
138
- return this.appendMessageToLane("main", message);
139
- }
140
- async appendCustomEntry(customType, data) {
141
- return this.appendCustomEntryToLane("main", customType, data);
142
- }
143
- async getLanes() {
144
- return this.storage.getLanes();
145
- }
146
- async createLane(lane, at) {
147
- await this.storage.createLane(lane, at);
148
- }
149
- async moveLane(lane, to) {
150
- await this.storage.moveLane(lane, to);
151
- }
152
- async appendEntry(entry, lane) {
153
- return this.commitEntry(entry, lane);
154
- }
155
- async appendRecord(record) {
156
- return this.commitRecord(record);
157
- }
158
- async findRecords(query) {
159
- return this.queryRecords(query);
160
- }
161
- async findOpenOperations(lane, options) {
162
- assertValidLimit(options?.limit);
163
- return this.storage.findOpenOperations(lane, options);
164
- }
165
- async getLog(options) {
166
- return this.queryLog(options);
167
- }
168
- /** Returns the lane's current leaf, or null when empty. Throws when the lane does not exist. */
169
- async getLeafIdForLane(lane) {
170
- const pointer = (await this.getLanes()).find((candidate) => candidate.lane === lane);
171
- if (!pointer)
172
- throw new SessionError("invalid_lane", `Lane not found: ${lane}`);
173
- return pointer.leafId;
174
- }
175
- async queryEntries(query = {}, resultLimit = query.limit) {
176
- assertValidLimit(query.limit);
177
- assertValidCursor(query.cursor?.afterSeq);
178
- return this.storage.findEntries(resultLimit === query.limit ? query : { ...query, limit: resultLimit });
179
- }
180
- /**
181
- * Queries from `query.start` toward the root, defaulting to the lane's current leaf.
182
- * `resultLimit` lets single-entry queries cap results without changing the caller's query.
183
- */
184
- async queryBranchEntries(defaultLane, query = {}, resultLimit = query.limit) {
185
- assertValidLimit(query.limit);
186
- assertValidCursor(query.cursor?.afterSeq);
187
- const start = query.start ?? (await this.getLeafIdForLane(defaultLane));
117
+ async findEntries(query, context) {
118
+ query ??= {};
119
+ const start = query.start ?? (await this.getTipId(context));
188
120
  if (start === null)
189
121
  return [];
190
- const storageQuery = resultLimit === query.limit ? query : { ...query, limit: resultLimit };
191
- return this.storage.findEntriesOnBranch({ ...storageQuery, start });
192
- }
193
- async queryRecords(query = {}) {
194
- assertValidLimit(query.limit);
195
- assertValidCursor(query.afterSeq);
196
- if (query.operationKind !== undefined && query.type !== "operation_started") {
197
- throw new SessionError("invalid_query", 'operationKind requires type "operation_started"');
122
+ return this.session.scanBranch({ ...query, start, order: query.order ?? "newestFirst" }, context);
123
+ }
124
+ async findEntry(query, context) {
125
+ query ??= {};
126
+ return (await this.findEntries({ ...query, limit: query.limit === undefined ? 1 : Math.min(query.limit, 1) }, context))[0];
127
+ }
128
+ appendMessage(message, context) {
129
+ return this.session.appendToBranch(this.name, { type: "message", message }, context);
130
+ }
131
+ appendCustomEntry(customType, data, context) {
132
+ return this.session.appendToBranch(this.name, { type: "custom", customType, ...(data === undefined ? {} : { data }) }, context);
133
+ }
134
+ }
135
+ /** Package-internal typed boundary shared by concrete session repositories. */
136
+ export class StorageBackedSession {
137
+ constructor(metadata, storage, options = {}) {
138
+ this.branches = new Map();
139
+ this.closedError = new Error("Session is closed");
140
+ this.state = "open";
141
+ this.metadata = metadata;
142
+ this.idGenerator = options.idGenerator ?? { next: uuidv7 };
143
+ this.storage = storage;
144
+ this.mutationLine = options.mutationLine ?? new MutationLine();
145
+ this.onClose = options.onClose;
146
+ }
147
+ async beginMutation(_context) {
148
+ this.assertOpen();
149
+ let grant;
150
+ let rejectGrant;
151
+ const granted = new Promise((resolve, reject) => {
152
+ grant = resolve;
153
+ rejectGrant = reject;
154
+ });
155
+ let release;
156
+ const finished = new Promise((resolve) => {
157
+ release = resolve;
158
+ });
159
+ const line = this.mutationLine.run(async () => {
160
+ grant(new StorageBackedSessionMutation(this.storage, release));
161
+ await finished;
162
+ });
163
+ void line.catch(rejectGrant);
164
+ return granted;
165
+ }
166
+ async mutate(mutation, context) {
167
+ const mutator = await this.beginMutation(context);
168
+ try {
169
+ return await mutation(mutator, context);
170
+ }
171
+ finally {
172
+ await mutator.end(context);
173
+ }
174
+ }
175
+ async getEntries(ids, context) {
176
+ this.assertOpen();
177
+ return this.storage.getEntries(ids, context);
178
+ }
179
+ async getEntry(id, context) {
180
+ return (await this.getEntries([id], context)).get(id);
181
+ }
182
+ async getValue(address, context) {
183
+ this.assertOpen();
184
+ return this.storage.getValue(address, context);
185
+ }
186
+ async scanValues(prefix, context) {
187
+ this.assertOpen();
188
+ return this.storage.scanValues(prefix, context);
189
+ }
190
+ async readList(address, options, context) {
191
+ this.assertOpen();
192
+ return this.storage.readList(address, options, context);
193
+ }
194
+ async scanBranch(query, context) {
195
+ this.assertOpen();
196
+ return this.storage.scanBranch(query, context);
197
+ }
198
+ async getStats(context) {
199
+ this.assertOpen();
200
+ return this.storage.getStats(context);
201
+ }
202
+ async getName(context) {
203
+ return (await this.getValue(sessionName, context))?.value;
204
+ }
205
+ async getLabel(targetId, context) {
206
+ return (await this.getValue(entryLabel(targetId), context))?.value;
207
+ }
208
+ async findEntries(query, context) {
209
+ query ??= {};
210
+ this.assertOpen();
211
+ const order = query.order ?? "desc";
212
+ if (query.cursor !== undefined) {
213
+ if (order === "asc" && query.cursor.seq === Number.MAX_SAFE_INTEGER)
214
+ return [];
215
+ if (order === "desc" && query.cursor.seq <= 1)
216
+ return [];
217
+ }
218
+ return this.storage.scanEntries({
219
+ type: query.type,
220
+ customType: query.customType,
221
+ order,
222
+ limit: query.limit,
223
+ ...(query.cursor === undefined
224
+ ? {}
225
+ : order === "asc"
226
+ ? { fromSeq: query.cursor.seq + 1 }
227
+ : { toSeq: query.cursor.seq - 1 }),
228
+ }, context);
229
+ }
230
+ async findEntry(query, context) {
231
+ query ??= {};
232
+ return (await this.findEntries({ ...query, limit: query.limit === undefined ? 1 : Math.min(query.limit, 1) }, context))[0];
233
+ }
234
+ async branch(name, context) {
235
+ this.assertValidBranchName(name);
236
+ if ((await this.getValue(branchTip(name), context)) === undefined)
237
+ return undefined;
238
+ return this.getOrCreateBranchObject(name);
239
+ }
240
+ async createBranch(name, at, context) {
241
+ this.assertOpen();
242
+ this.assertValidBranchName(name);
243
+ await this.mutate(async (mutator) => {
244
+ if ((await mutator.getValue(branchTip(name), context)) !== undefined) {
245
+ throw new SessionBranchExistsError(name);
246
+ }
247
+ if (at !== null && !(await mutator.getEntries([at], context)).has(at)) {
248
+ throw new SessionUnknownTargetError(at);
249
+ }
250
+ await mutator.commit([setValueWrite(branchTip(name), at)], context);
251
+ }, context);
252
+ return this.getOrCreateBranchObject(name);
253
+ }
254
+ setValue(address, next, context) {
255
+ return this.mutate(async (mutator) => {
256
+ await mutator.commit([setValueWrite(address, next)], context);
257
+ }, context);
258
+ }
259
+ deleteValue(address, context) {
260
+ return this.mutate(async (mutator) => {
261
+ await mutator.commit([deleteValueWrite(address)], context);
262
+ }, context);
263
+ }
264
+ appendList(address, element, context) {
265
+ return this.mutate(async (mutator) => {
266
+ await mutator.commit([appendListWrite(address, element)], context);
267
+ }, context);
268
+ }
269
+ deleteList(address, context) {
270
+ return this.mutate(async (mutator) => {
271
+ await mutator.commit([deleteListWrite(address)], context);
272
+ }, context);
273
+ }
274
+ setName(name, context) {
275
+ return name === undefined ? this.deleteValue(sessionName, context) : this.setValue(sessionName, name, context);
276
+ }
277
+ setLabel(targetId, label, context) {
278
+ const address = entryLabel(targetId);
279
+ return label === undefined ? this.deleteValue(address, context) : this.setValue(address, label, context);
280
+ }
281
+ close(context) {
282
+ if (this.closePromise !== undefined)
283
+ return this.closePromise;
284
+ this.state = "closing";
285
+ this.closePromise = this.mutationLine
286
+ .seal(this.closedError)
287
+ .then(() => this.storage.close(context))
288
+ .finally(() => {
289
+ this.state = "closed";
290
+ this.onClose?.();
291
+ });
292
+ return this.closePromise;
293
+ }
294
+ async getBranchTip(name, context) {
295
+ const stored = await this.getValue(branchTip(name), context);
296
+ if (stored === undefined)
297
+ throw new SessionInvariantError(`Unknown branch: ${name}`);
298
+ return stored.value;
299
+ }
300
+ async appendToBranch(name, entry, context) {
301
+ this.assertOpen();
302
+ if (entry.type === "message" && entry.message.role === "assistant" && entry.message.stopReason === "pending") {
303
+ throw new SessionPendingAssistantMessageError();
304
+ }
305
+ const id = this.idGenerator.next();
306
+ await this.mutate(async (mutator) => {
307
+ const tip = await mutator.getValue(branchTip(name), context);
308
+ if (tip === undefined)
309
+ throw new SessionInvariantError(`Unknown branch: ${name}`);
310
+ await mutator.commit([
311
+ insertEntry(entry.type === "message"
312
+ ? { id, parentId: tip.value, type: "message", message: entry.message }
313
+ : {
314
+ id,
315
+ parentId: tip.value,
316
+ type: "custom",
317
+ customType: entry.customType,
318
+ ...(entry.data === undefined ? {} : { data: entry.data }),
319
+ }),
320
+ setValueWrite(branchTip(name), id),
321
+ ], context);
322
+ }, context);
323
+ return id;
324
+ }
325
+ getOrCreateBranchObject(name) {
326
+ let branch = this.branches.get(name);
327
+ if (branch === undefined) {
328
+ branch = new StorageBackedBranch(name, this);
329
+ this.branches.set(name, branch);
198
330
  }
199
- return this.storage.findRecords(query);
200
- }
201
- async queryLog(options = {}) {
202
- assertValidLimit(options.limit);
203
- assertValidCursor(options.afterSeq);
204
- return this.storage.getLog(options);
205
- }
206
- async appendMessageToLane(lane, message) {
207
- const entry = await this.commitEntry({ type: "message", id: this.idGenerator.next(), message }, lane);
208
- return entry.id;
209
- }
210
- async appendCustomEntryToLane(lane, customType, data) {
211
- const entry = await this.commitEntry(data === undefined
212
- ? { type: "custom", id: this.idGenerator.next(), customType }
213
- : { type: "custom", id: this.idGenerator.next(), customType, data }, lane);
214
- return entry.id;
215
- }
216
- async commitEntry(entry, lane) {
217
- assertJsonSerializable(entry);
218
- return this.storage.appendEntry(entry, lane);
219
- }
220
- async commitRecord(record) {
221
- assertJsonSerializable(record);
222
- return this.storage.appendRecord(record);
331
+ return branch;
332
+ }
333
+ assertValidBranchName(name) {
334
+ if (name.length === 0)
335
+ throw new SessionInvalidBranchError(name, "branch name must not be empty");
336
+ if (name.includes("\u0000")) {
337
+ throw new SessionInvalidBranchError(name, "branch name must not contain \\u0000");
338
+ }
339
+ }
340
+ assertOpen() {
341
+ if (this.state !== "open")
342
+ throw this.closedError;
223
343
  }
224
344
  }
225
345
  //# sourceMappingURL=session.js.map