@code-yeongyu/senpi 2026.9.15-2 → 2026.9.16-2

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 (249) hide show
  1. package/CHANGELOG.md +48 -0
  2. package/README.md +1 -1
  3. package/dist/core/agent-session.d.ts +28 -0
  4. package/dist/core/agent-session.d.ts.map +1 -1
  5. package/dist/core/agent-session.js +111 -13
  6. package/dist/core/agent-session.js.map +1 -1
  7. package/dist/core/compaction/compaction.d.ts.map +1 -1
  8. package/dist/core/compaction/compaction.js +4 -2
  9. package/dist/core/compaction/compaction.js.map +1 -1
  10. package/dist/core/compaction/stream-watchdog.d.ts +56 -2
  11. package/dist/core/compaction/stream-watchdog.d.ts.map +1 -1
  12. package/dist/core/compaction/stream-watchdog.js +93 -15
  13. package/dist/core/compaction/stream-watchdog.js.map +1 -1
  14. package/dist/core/extensions/builtin/claude-sdk-oauth/session-binding.d.ts +6 -0
  15. package/dist/core/extensions/builtin/claude-sdk-oauth/session-binding.d.ts.map +1 -1
  16. package/dist/core/extensions/builtin/claude-sdk-oauth/session-binding.js +17 -0
  17. package/dist/core/extensions/builtin/claude-sdk-oauth/session-binding.js.map +1 -1
  18. package/dist/core/extensions/builtin/claude-sdk-oauth/session-continuity.d.ts +4 -1
  19. package/dist/core/extensions/builtin/claude-sdk-oauth/session-continuity.d.ts.map +1 -1
  20. package/dist/core/extensions/builtin/claude-sdk-oauth/session-continuity.js +31 -0
  21. package/dist/core/extensions/builtin/claude-sdk-oauth/session-continuity.js.map +1 -1
  22. package/dist/core/extensions/builtin/claude-sdk-oauth/session-reattach.d.ts +2 -0
  23. package/dist/core/extensions/builtin/claude-sdk-oauth/session-reattach.d.ts.map +1 -1
  24. package/dist/core/extensions/builtin/claude-sdk-oauth/session-reattach.js +16 -0
  25. package/dist/core/extensions/builtin/claude-sdk-oauth/session-reattach.js.map +1 -1
  26. package/dist/core/extensions/builtin/claude-sdk-oauth/session-registry-wiring.d.ts.map +1 -1
  27. package/dist/core/extensions/builtin/claude-sdk-oauth/session-registry-wiring.js +19 -8
  28. package/dist/core/extensions/builtin/claude-sdk-oauth/session-registry-wiring.js.map +1 -1
  29. package/dist/core/extensions/builtin/claude-sdk-oauth/session-stream.d.ts.map +1 -1
  30. package/dist/core/extensions/builtin/claude-sdk-oauth/session-stream.js +2 -1
  31. package/dist/core/extensions/builtin/claude-sdk-oauth/session-stream.js.map +1 -1
  32. package/dist/core/extensions/builtin/compaction/deterministic-fallback.d.ts +13 -1
  33. package/dist/core/extensions/builtin/compaction/deterministic-fallback.d.ts.map +1 -1
  34. package/dist/core/extensions/builtin/compaction/deterministic-fallback.js +66 -2
  35. package/dist/core/extensions/builtin/compaction/deterministic-fallback.js.map +1 -1
  36. package/dist/core/extensions/builtin/compaction/index.d.ts.map +1 -1
  37. package/dist/core/extensions/builtin/compaction/index.js +16 -10
  38. package/dist/core/extensions/builtin/compaction/index.js.map +1 -1
  39. package/dist/core/extensions/builtin/compaction/speculative-summary.d.ts.map +1 -1
  40. package/dist/core/extensions/builtin/compaction/speculative-summary.js +4 -2
  41. package/dist/core/extensions/builtin/compaction/speculative-summary.js.map +1 -1
  42. package/dist/core/extensions/builtin/compaction/speculative.d.ts +8 -1
  43. package/dist/core/extensions/builtin/compaction/speculative.d.ts.map +1 -1
  44. package/dist/core/extensions/builtin/compaction/speculative.js +31 -7
  45. package/dist/core/extensions/builtin/compaction/speculative.js.map +1 -1
  46. package/dist/core/extensions/builtin/compaction/transient-failure.d.ts.map +1 -1
  47. package/dist/core/extensions/builtin/compaction/transient-failure.js +6 -3
  48. package/dist/core/extensions/builtin/compaction/transient-failure.js.map +1 -1
  49. package/dist/core/extensions/kernel-tools-context.d.ts +13 -0
  50. package/dist/core/extensions/kernel-tools-context.d.ts.map +1 -0
  51. package/dist/core/extensions/kernel-tools-context.js +3 -0
  52. package/dist/core/extensions/kernel-tools-context.js.map +1 -0
  53. package/dist/core/extensions/runner.d.ts +19 -0
  54. package/dist/core/extensions/runner.d.ts.map +1 -1
  55. package/dist/core/extensions/runner.js +103 -1
  56. package/dist/core/extensions/runner.js.map +1 -1
  57. package/dist/core/extensions/types.d.ts +21 -0
  58. package/dist/core/extensions/types.d.ts.map +1 -1
  59. package/dist/core/extensions/types.js.map +1 -1
  60. package/dist/core/keybindings.d.ts +5 -0
  61. package/dist/core/keybindings.d.ts.map +1 -1
  62. package/dist/core/keybindings.js +1 -0
  63. package/dist/core/keybindings.js.map +1 -1
  64. package/dist/core/retry-fallback/settings.d.ts +3 -0
  65. package/dist/core/retry-fallback/settings.d.ts.map +1 -1
  66. package/dist/core/retry-fallback/settings.js.map +1 -1
  67. package/dist/core/sdk.d.ts.map +1 -1
  68. package/dist/core/sdk.js +1 -0
  69. package/dist/core/sdk.js.map +1 -1
  70. package/dist/core/session-manager.d.ts +27 -1
  71. package/dist/core/session-manager.d.ts.map +1 -1
  72. package/dist/core/session-manager.js +78 -5
  73. package/dist/core/session-manager.js.map +1 -1
  74. package/dist/core/session-resident-store.d.ts +33 -7
  75. package/dist/core/session-resident-store.d.ts.map +1 -1
  76. package/dist/core/session-resident-store.js +163 -14
  77. package/dist/core/session-resident-store.js.map +1 -1
  78. package/dist/core/session-write-reservation.d.ts +6 -0
  79. package/dist/core/session-write-reservation.d.ts.map +1 -1
  80. package/dist/core/session-write-reservation.js +19 -0
  81. package/dist/core/session-write-reservation.js.map +1 -1
  82. package/dist/core/settings-manager.d.ts +35 -1
  83. package/dist/core/settings-manager.d.ts.map +1 -1
  84. package/dist/core/settings-manager.js +62 -0
  85. package/dist/core/settings-manager.js.map +1 -1
  86. package/dist/core/slash-commands.d.ts.map +1 -1
  87. package/dist/core/slash-commands.js +2 -1
  88. package/dist/core/slash-commands.js.map +1 -1
  89. package/dist/core/tools/index.d.ts +1 -1
  90. package/dist/core/tools/index.d.ts.map +1 -1
  91. package/dist/core/tools/index.js +4 -3
  92. package/dist/core/tools/index.js.map +1 -1
  93. package/dist/core/tools/read.d.ts +3 -1
  94. package/dist/core/tools/read.d.ts.map +1 -1
  95. package/dist/core/tools/read.js +16 -2
  96. package/dist/core/tools/read.js.map +1 -1
  97. package/dist/index.d.ts +1 -0
  98. package/dist/index.d.ts.map +1 -1
  99. package/dist/index.js +1 -0
  100. package/dist/index.js.map +1 -1
  101. package/dist/modes/interactive/components/assistant-render-descriptors.d.ts.map +1 -1
  102. package/dist/modes/interactive/components/assistant-render-descriptors.js +12 -5
  103. package/dist/modes/interactive/components/assistant-render-descriptors.js.map +1 -1
  104. package/dist/modes/interactive/components/extension-input.d.ts +2 -0
  105. package/dist/modes/interactive/components/extension-input.d.ts.map +1 -1
  106. package/dist/modes/interactive/components/extension-input.js +5 -0
  107. package/dist/modes/interactive/components/extension-input.js.map +1 -1
  108. package/dist/modes/interactive/interactive-mode.d.ts +19 -2
  109. package/dist/modes/interactive/interactive-mode.d.ts.map +1 -1
  110. package/dist/modes/interactive/interactive-mode.js +66 -14
  111. package/dist/modes/interactive/interactive-mode.js.map +1 -1
  112. package/dist/modes/interactive/tips/catalog/session-tips.js +1 -1
  113. package/dist/modes/interactive/tips/catalog/session-tips.js.map +1 -1
  114. package/dist/modes/interactive/working-status.d.ts +3 -2
  115. package/dist/modes/interactive/working-status.d.ts.map +1 -1
  116. package/dist/modes/interactive/working-status.js +17 -4
  117. package/dist/modes/interactive/working-status.js.map +1 -1
  118. package/dist/modes/print-mode.d.ts +1 -1
  119. package/dist/modes/print-mode.d.ts.map +1 -1
  120. package/dist/modes/print-mode.js +5 -1
  121. package/dist/modes/print-mode.js.map +1 -1
  122. package/docs/extensions.md +5 -2
  123. package/docs/keybindings.md +1 -0
  124. package/docs/session-format.md +1 -1
  125. package/docs/sessions.md +3 -3
  126. package/docs/settings.md +31 -1
  127. package/docs/usage.md +1 -1
  128. package/node_modules/@code-yeongyu/senpi-codemode/CHANGELOG.md +35 -0
  129. package/node_modules/@code-yeongyu/senpi-codemode/README.md +24 -0
  130. package/node_modules/@code-yeongyu/senpi-codemode/package.json +4 -4
  131. package/node_modules/@code-yeongyu/senpi-codemode/src/bridge/http-server.ts +7 -1
  132. package/node_modules/@code-yeongyu/senpi-codemode/src/bridge/kernel-tools-protocol.ts +85 -0
  133. package/node_modules/@code-yeongyu/senpi-codemode/src/bridge/protocol.ts +6 -0
  134. package/node_modules/@code-yeongyu/senpi-codemode/src/bridges/agent-bridge.ts +30 -11
  135. package/node_modules/@code-yeongyu/senpi-codemode/src/extension/session-manager.ts +11 -0
  136. package/node_modules/@code-yeongyu/senpi-codemode/src/index.ts +10 -0
  137. package/node_modules/@code-yeongyu/senpi-codemode/src/kernels/jl/prelude.jl +46 -0
  138. package/node_modules/@code-yeongyu/senpi-codemode/src/kernels/jl/runner.jl +1 -1
  139. package/node_modules/@code-yeongyu/senpi-codemode/src/kernels/js/context-manager.ts +29 -0
  140. package/node_modules/@code-yeongyu/senpi-codemode/src/kernels/js/kernel-contract.ts +12 -0
  141. package/node_modules/@code-yeongyu/senpi-codemode/src/kernels/js/kernel-tools-context.d.ts +13 -0
  142. package/node_modules/@code-yeongyu/senpi-codemode/src/kernels/js/kernel-tools-context.js +7 -0
  143. package/node_modules/@code-yeongyu/senpi-codemode/src/kernels/js/kernel-tools-define.d.ts +10 -0
  144. package/node_modules/@code-yeongyu/senpi-codemode/src/kernels/js/kernel-tools-define.js +12 -0
  145. package/node_modules/@code-yeongyu/senpi-codemode/src/kernels/js/kernel-tools-errors.js +22 -0
  146. package/node_modules/@code-yeongyu/senpi-codemode/src/kernels/js/kernel-tools-errors.ts +26 -0
  147. package/node_modules/@code-yeongyu/senpi-codemode/src/kernels/js/kernel-tools-host.ts +134 -0
  148. package/node_modules/@code-yeongyu/senpi-codemode/src/kernels/js/kernel-tools-naming.js +28 -0
  149. package/node_modules/@code-yeongyu/senpi-codemode/src/kernels/js/kernel-tools-parse.d.ts +5 -0
  150. package/node_modules/@code-yeongyu/senpi-codemode/src/kernels/js/kernel-tools-parse.js +255 -0
  151. package/node_modules/@code-yeongyu/senpi-codemode/src/kernels/js/kernel-tools-pump.js +105 -0
  152. package/node_modules/@code-yeongyu/senpi-codemode/src/kernels/js/kernel-tools-registry.d.ts +27 -0
  153. package/node_modules/@code-yeongyu/senpi-codemode/src/kernels/js/kernel-tools-registry.js +127 -0
  154. package/node_modules/@code-yeongyu/senpi-codemode/src/kernels/js/kernel-tools-schema.js +69 -0
  155. package/node_modules/@code-yeongyu/senpi-codemode/src/kernels/js/kernel-tools-types.ts +42 -0
  156. package/node_modules/@code-yeongyu/senpi-codemode/src/kernels/js/prelude.ts +2 -0
  157. package/node_modules/@code-yeongyu/senpi-codemode/src/kernels/js/worker-core.js +26 -3
  158. package/node_modules/@code-yeongyu/senpi-codemode/src/kernels/js/worker-runtime.js +20 -8
  159. package/node_modules/@code-yeongyu/senpi-codemode/src/kernels/js/worker-slot.ts +6 -1
  160. package/node_modules/@code-yeongyu/senpi-codemode/src/kernels/js/worker-startup.ts +9 -7
  161. package/node_modules/@code-yeongyu/senpi-codemode/src/kernels/js/workpool.js +37 -0
  162. package/node_modules/@code-yeongyu/senpi-codemode/src/kernels/kernel-tools-unavailable.ts +5 -0
  163. package/node_modules/@code-yeongyu/senpi-codemode/src/kernels/py/kernel.ts +13 -0
  164. package/node_modules/@code-yeongyu/senpi-codemode/src/kernels/py/prelude.py +57 -3
  165. package/node_modules/@code-yeongyu/senpi-codemode/src/kernels/rb/prelude.rb +13 -2
  166. package/node_modules/@code-yeongyu/senpi-codemode/src/kernels/rb/workpool.rb +38 -0
  167. package/node_modules/@code-yeongyu/senpi-codemode/src/kernels/shared/subprocess-kernel.ts +13 -0
  168. package/node_modules/@code-yeongyu/senpi-codemode/src/kernels/shared/subprocess-queue.ts +2 -0
  169. package/node_modules/@code-yeongyu/senpi-codemode/src/prompt/eval-prompt-template.ts +4 -2
  170. package/node_modules/@code-yeongyu/senpi-codemode/src/tool/cell-handler.ts +31 -3
  171. package/node_modules/@code-yeongyu/senpi-codemode/src/tool/run-eval-cell.ts +52 -30
  172. package/node_modules/@code-yeongyu/senpi-codemode/src/tool/types.ts +2 -0
  173. package/node_modules/@earendil-works/pi-agent-core/dist/agent-loop.d.ts.map +1 -1
  174. package/node_modules/@earendil-works/pi-agent-core/dist/agent-loop.js +30 -3
  175. package/node_modules/@earendil-works/pi-agent-core/dist/agent-loop.js.map +1 -1
  176. package/node_modules/@earendil-works/pi-agent-core/dist/agent.d.ts +5 -0
  177. package/node_modules/@earendil-works/pi-agent-core/dist/agent.d.ts.map +1 -1
  178. package/node_modules/@earendil-works/pi-agent-core/dist/agent.js +2 -0
  179. package/node_modules/@earendil-works/pi-agent-core/dist/agent.js.map +1 -1
  180. package/node_modules/@earendil-works/pi-agent-core/dist/empty-assistant-recovery.d.ts.map +1 -1
  181. package/node_modules/@earendil-works/pi-agent-core/dist/empty-assistant-recovery.js +51 -12
  182. package/node_modules/@earendil-works/pi-agent-core/dist/empty-assistant-recovery.js.map +1 -1
  183. package/node_modules/@earendil-works/pi-agent-core/dist/harness/tools/read.d.ts +3 -0
  184. package/node_modules/@earendil-works/pi-agent-core/dist/harness/tools/read.d.ts.map +1 -1
  185. package/node_modules/@earendil-works/pi-agent-core/dist/harness/tools/read.js +18 -3
  186. package/node_modules/@earendil-works/pi-agent-core/dist/harness/tools/read.js.map +1 -1
  187. package/node_modules/@earendil-works/pi-agent-core/dist/harness/utils/read-folders/brace-scanner.d.ts +4 -0
  188. package/node_modules/@earendil-works/pi-agent-core/dist/harness/utils/read-folders/brace-scanner.d.ts.map +1 -0
  189. package/node_modules/@earendil-works/pi-agent-core/dist/harness/utils/read-folders/brace-scanner.js +268 -0
  190. package/node_modules/@earendil-works/pi-agent-core/dist/harness/utils/read-folders/brace-scanner.js.map +1 -0
  191. package/node_modules/@earendil-works/pi-agent-core/dist/harness/utils/read-folders/header-protection.d.ts +18 -0
  192. package/node_modules/@earendil-works/pi-agent-core/dist/harness/utils/read-folders/header-protection.d.ts.map +1 -0
  193. package/node_modules/@earendil-works/pi-agent-core/dist/harness/utils/read-folders/header-protection.js +69 -0
  194. package/node_modules/@earendil-works/pi-agent-core/dist/harness/utils/read-folders/header-protection.js.map +1 -0
  195. package/node_modules/@earendil-works/pi-agent-core/dist/harness/utils/read-folders/index.d.ts +27 -0
  196. package/node_modules/@earendil-works/pi-agent-core/dist/harness/utils/read-folders/index.d.ts.map +1 -0
  197. package/node_modules/@earendil-works/pi-agent-core/dist/harness/utils/read-folders/index.js +118 -0
  198. package/node_modules/@earendil-works/pi-agent-core/dist/harness/utils/read-folders/index.js.map +1 -0
  199. package/node_modules/@earendil-works/pi-agent-core/dist/harness/utils/read-folders/lexical-context.d.ts +21 -0
  200. package/node_modules/@earendil-works/pi-agent-core/dist/harness/utils/read-folders/lexical-context.d.ts.map +1 -0
  201. package/node_modules/@earendil-works/pi-agent-core/dist/harness/utils/read-folders/lexical-context.js +24 -0
  202. package/node_modules/@earendil-works/pi-agent-core/dist/harness/utils/read-folders/lexical-context.js.map +1 -0
  203. package/node_modules/@earendil-works/pi-agent-core/dist/harness/utils/read-folders/lexical-spans.d.ts +12 -0
  204. package/node_modules/@earendil-works/pi-agent-core/dist/harness/utils/read-folders/lexical-spans.d.ts.map +1 -0
  205. package/node_modules/@earendil-works/pi-agent-core/dist/harness/utils/read-folders/lexical-spans.js +92 -0
  206. package/node_modules/@earendil-works/pi-agent-core/dist/harness/utils/read-folders/lexical-spans.js.map +1 -0
  207. package/node_modules/@earendil-works/pi-agent-core/dist/harness/utils/read-folders/types.d.ts +47 -0
  208. package/node_modules/@earendil-works/pi-agent-core/dist/harness/utils/read-folders/types.d.ts.map +1 -0
  209. package/node_modules/@earendil-works/pi-agent-core/dist/harness/utils/read-folders/types.js +8 -0
  210. package/node_modules/@earendil-works/pi-agent-core/dist/harness/utils/read-folders/types.js.map +1 -0
  211. package/node_modules/@earendil-works/pi-agent-core/dist/harness/utils/segmented-read-view.d.ts +52 -0
  212. package/node_modules/@earendil-works/pi-agent-core/dist/harness/utils/segmented-read-view.d.ts.map +1 -0
  213. package/node_modules/@earendil-works/pi-agent-core/dist/harness/utils/segmented-read-view.js +155 -0
  214. package/node_modules/@earendil-works/pi-agent-core/dist/harness/utils/segmented-read-view.js.map +1 -0
  215. package/node_modules/@earendil-works/pi-agent-core/dist/index.d.ts +4 -0
  216. package/node_modules/@earendil-works/pi-agent-core/dist/index.d.ts.map +1 -1
  217. package/node_modules/@earendil-works/pi-agent-core/dist/index.js +3 -0
  218. package/node_modules/@earendil-works/pi-agent-core/dist/index.js.map +1 -1
  219. package/node_modules/@earendil-works/pi-agent-core/dist/stream-throughput-watchdog.d.ts +101 -0
  220. package/node_modules/@earendil-works/pi-agent-core/dist/stream-throughput-watchdog.d.ts.map +1 -0
  221. package/node_modules/@earendil-works/pi-agent-core/dist/stream-throughput-watchdog.js +178 -0
  222. package/node_modules/@earendil-works/pi-agent-core/dist/stream-throughput-watchdog.js.map +1 -0
  223. package/node_modules/@earendil-works/pi-agent-core/dist/types.d.ts +9 -0
  224. package/node_modules/@earendil-works/pi-agent-core/dist/types.d.ts.map +1 -1
  225. package/node_modules/@earendil-works/pi-agent-core/dist/types.js.map +1 -1
  226. package/node_modules/@earendil-works/pi-agent-core/package.json +3 -3
  227. package/node_modules/@earendil-works/pi-ai/dist/index.d.ts +1 -0
  228. package/node_modules/@earendil-works/pi-ai/dist/index.d.ts.map +1 -1
  229. package/node_modules/@earendil-works/pi-ai/dist/index.js +1 -0
  230. package/node_modules/@earendil-works/pi-ai/dist/index.js.map +1 -1
  231. package/node_modules/@earendil-works/pi-ai/dist/providers/data/.manifest.json +1 -1
  232. package/node_modules/@earendil-works/pi-ai/dist/providers/data/alibaba-token-plan.json +1 -1
  233. package/node_modules/@earendil-works/pi-ai/dist/providers/data/amazon-bedrock.json +1 -1
  234. package/node_modules/@earendil-works/pi-ai/dist/providers/data/fireworks.json +1 -1
  235. package/node_modules/@earendil-works/pi-ai/dist/providers/data/openrouter.json +1 -1
  236. package/node_modules/@earendil-works/pi-ai/dist/providers/data/qwen-token-plan.json +1 -1
  237. package/node_modules/@earendil-works/pi-ai/dist/utils/empty-response-errors.d.ts +15 -0
  238. package/node_modules/@earendil-works/pi-ai/dist/utils/empty-response-errors.d.ts.map +1 -0
  239. package/node_modules/@earendil-works/pi-ai/dist/utils/empty-response-errors.js +15 -0
  240. package/node_modules/@earendil-works/pi-ai/dist/utils/empty-response-errors.js.map +1 -0
  241. package/node_modules/@earendil-works/pi-ai/dist/utils/retry.d.ts +24 -0
  242. package/node_modules/@earendil-works/pi-ai/dist/utils/retry.d.ts.map +1 -1
  243. package/node_modules/@earendil-works/pi-ai/dist/utils/retry.js +92 -0
  244. package/node_modules/@earendil-works/pi-ai/dist/utils/retry.js.map +1 -1
  245. package/node_modules/@earendil-works/pi-ai/package.json +2 -2
  246. package/node_modules/@earendil-works/pi-pty/package.json +1 -1
  247. package/node_modules/@earendil-works/pi-telemetry/package.json +1 -1
  248. package/node_modules/@earendil-works/pi-tui/package.json +1 -1
  249. package/package.json +7 -7
@@ -1,5 +1,5 @@
1
1
  import { randomBytes, randomUUID } from "crypto";
2
- import { appendFileSync, closeSync, existsSync, mkdirSync, openSync, readdirSync, readFileSync, readSync, statSync, writeFileSync, } from "fs";
2
+ import { appendFileSync, closeSync, existsSync, mkdirSync, openSync, readdirSync, readFileSync, readSync, rmSync, statSync, writeFileSync, } from "fs";
3
3
  import { readdir } from "fs/promises";
4
4
  import { join, resolve } from "path";
5
5
  import { StringDecoder } from "string_decoder";
@@ -8,7 +8,7 @@ import { normalizePath, resolvePath } from "../utils/paths.js";
8
8
  import { listSessionInfos, listSessionsFromDir } from "./session-discovery.js";
9
9
  import { materializeSessionEntries } from "./session-entry-materializer.js";
10
10
  import { ResidentStringStore } from "./session-resident-store.js";
11
- import { registerSessionWriter, reserveSessionWrite } from "./session-write-reservation.js";
11
+ import { hasOtherLiveSessionWriter, registerSessionWriter, reserveSessionWrite, unregisterSessionWriter, } from "./session-write-reservation.js";
12
12
  // Fork change: inlined UUIDv7 (upstream uses the `uuid` npm package). Keeps this
13
13
  // package self-contained so consumers don't need a transitive `uuid` install.
14
14
  function uuidv7() {
@@ -587,6 +587,12 @@ export class SessionManager {
587
587
  if (persist && this.sessionDir && !existsSync(this.sessionDir)) {
588
588
  mkdirSync(this.sessionDir, { recursive: true });
589
589
  }
590
+ // Lazily resolved: the session id only exists once the header loads or
591
+ // newSession() runs. Unpersisted sessions disable eviction entirely —
592
+ // dropping strings with no backing would lose them.
593
+ this.residentStore.configure({
594
+ blobsDir: () => this.persist && this.sessionId ? join(this.sessionDir, "resident-blobs", this.sessionId) : undefined,
595
+ });
590
596
  if (sessionFile) {
591
597
  this._setSessionFile(sessionFile, preloadedFileEntries);
592
598
  }
@@ -646,6 +652,10 @@ export class SessionManager {
646
652
  this.fileEntries = entries;
647
653
  const header = this.fileEntries.find((e) => e.type === "session");
648
654
  this.sessionId = header?.id ?? createSessionId();
655
+ // Blobs left under this id by a process that is gone are a disposable cache:
656
+ // the JSONL is the authority for every entry and this store rewrites what it
657
+ // evicts, so clearing them bounds the directory to one process lifetime.
658
+ this._releaseBlobsDirUnlessShared();
649
659
  if (migrateToCurrentVersion(this.fileEntries)) {
650
660
  this._rewriteFile();
651
661
  }
@@ -674,6 +684,10 @@ export class SessionManager {
674
684
  if (options?.id !== undefined) {
675
685
  assertValidSessionId(options.id);
676
686
  }
687
+ // Capture the previous backing before the id changes: the blobsDir
688
+ // provider resolves against the new id after this assignment, so clear()
689
+ // below would otherwise leak the old session's blob directory on disk.
690
+ const previousBlobsDir = this.residentStore.resolvedBlobsDir();
677
691
  this.sessionId = options?.id ?? createSessionId();
678
692
  const timestamp = new Date().toISOString();
679
693
  const header = {
@@ -688,6 +702,9 @@ export class SessionManager {
688
702
  this.mirrorTrimmed = false;
689
703
  this.fullEntryCount = 0;
690
704
  this.residentStore.clear();
705
+ if (previousBlobsDir) {
706
+ this._removeBlobsDir(previousBlobsDir);
707
+ }
691
708
  this.byId.clear();
692
709
  this.entryOrdersById.clear();
693
710
  this.messageEntryPositions = new WeakMap();
@@ -803,6 +820,13 @@ export class SessionManager {
803
820
  getSessionFile() {
804
821
  return this.sessionFile;
805
822
  }
823
+ /**
824
+ * Exposes the resident store for out-of-band string lifecycles such as the
825
+ * agent's runtime message state (tokenized while idle, hydrated per turn).
826
+ */
827
+ getResidentStore() {
828
+ return this.residentStore;
829
+ }
806
830
  getResidentStoreStats() {
807
831
  return this.residentStore.stats();
808
832
  }
@@ -1024,6 +1048,35 @@ export class SessionManager {
1024
1048
  this._trimMirrorAfterCompaction(entry);
1025
1049
  return entry.id;
1026
1050
  }
1051
+ /**
1052
+ * Release what outlives this manager in the process: the shared host's write
1053
+ * grant and the blob directory backing its resident mirror. The session JSONL
1054
+ * is untouched - it is the authority the next reader loads from. Idempotent.
1055
+ */
1056
+ dispose() {
1057
+ unregisterSessionWriter(this);
1058
+ this._releaseBlobsDirUnlessShared();
1059
+ }
1060
+ /**
1061
+ * The blob directory is keyed by session id, so every live manager over the same
1062
+ * session file hydrates from it. Removing it while one of them is still reading
1063
+ * would cost that manager a full JSONL recovery per evicted string, so the last
1064
+ * owner to let go is the one that clears it.
1065
+ */
1066
+ _releaseBlobsDirUnlessShared() {
1067
+ const blobsDir = this.residentStore.resolvedBlobsDir();
1068
+ if (!blobsDir)
1069
+ return;
1070
+ if (this.sessionFile && hasOtherLiveSessionWriter(this.sessionFile, this))
1071
+ return;
1072
+ this._removeBlobsDir(blobsDir);
1073
+ }
1074
+ _removeBlobsDir(dir) {
1075
+ try {
1076
+ rmSync(dir, { force: true, recursive: true });
1077
+ }
1078
+ catch { }
1079
+ }
1027
1080
  _trimMirrorAfterCompaction(compaction) {
1028
1081
  if (!this.persist)
1029
1082
  return;
@@ -1042,7 +1095,7 @@ export class SessionManager {
1042
1095
  entry.parentId = parentId;
1043
1096
  parentId = entry.type === "session" ? null : entry.id;
1044
1097
  }
1045
- this.residentStore.clear();
1098
+ this.residentStore.spillResident();
1046
1099
  this.mirrorTrimmed = true;
1047
1100
  this.fileEntries = [header, ...retained]
1048
1101
  .filter((entry) => entry !== undefined)
@@ -1280,6 +1333,17 @@ export class SessionManager {
1280
1333
  getEntryCount() {
1281
1334
  return this.fullEntryCount;
1282
1335
  }
1336
+ /**
1337
+ * Release the memoized materialized views. Materialized entries hold the full
1338
+ * persisted strings, so views kept between turns pin the whole session text
1339
+ * in memory even while nothing runs. The next read rebuilds them from the
1340
+ * bounded resident store.
1341
+ */
1342
+ dropMaterializedCaches() {
1343
+ this.entriesCache = null;
1344
+ this.branchCache = null;
1345
+ this.compactEntriesCache = null;
1346
+ }
1283
1347
  _materializeEntries(entries) {
1284
1348
  return materializeSessionEntries(entries, {
1285
1349
  residentStore: this.residentStore,
@@ -1503,11 +1567,19 @@ export class SessionManager {
1503
1567
  parentId = labelEntry.id;
1504
1568
  }
1505
1569
  reserveSessionWrite(newSessionFile);
1570
+ // Materialize the branched entries while the previous backing is still
1571
+ // readable, then clear: re-externalizing tokenized entries after clear()
1572
+ // would bake sentinel tokens into the new branched JSONL.
1573
+ const branchedEntries = this._materializeEntries([...pathWithoutLabels, ...labelEntries]);
1574
+ const previousBlobsDir = this.residentStore.resolvedBlobsDir();
1506
1575
  this.residentStore.clear();
1576
+ if (previousBlobsDir) {
1577
+ this._removeBlobsDir(previousBlobsDir);
1578
+ }
1507
1579
  this.mirrorTrimmed = false;
1508
- this.fileEntries = [header, ...pathWithoutLabels, ...labelEntries].map((entry) => this.residentStore.externalize(entry));
1509
1580
  this.sessionId = newSessionId;
1510
1581
  this.sessionFile = newSessionFile;
1582
+ this.fileEntries = [header, ...branchedEntries.map((entry) => this.residentStore.externalize(entry))];
1511
1583
  this._buildIndex();
1512
1584
  this.mutationCount++;
1513
1585
  // Only write the file now if it contains an assistant message.
@@ -1540,8 +1612,9 @@ export class SessionManager {
1540
1612
  labelEntries.push(labelEntry);
1541
1613
  parentId = labelEntry.id;
1542
1614
  }
1615
+ const branchedEntries = this._materializeEntries([...pathWithoutLabels, ...labelEntries]);
1543
1616
  this.residentStore.clear();
1544
- this.fileEntries = [header, ...pathWithoutLabels, ...labelEntries].map((entry) => this.residentStore.externalize(entry));
1617
+ this.fileEntries = [header, ...branchedEntries.map((entry) => this.residentStore.externalize(entry))];
1545
1618
  this.sessionId = newSessionId;
1546
1619
  this._buildIndex();
1547
1620
  this.mutationCount++;