@myagentroam/agent 0.11.33 → 0.11.34

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 (856) hide show
  1. package/dist/cli/catalog-file.d.ts +78 -0
  2. package/dist/cli/catalog-file.js +102 -0
  3. package/dist/cli/codex-auth-file.d.ts +1 -1
  4. package/dist/cli/codex-auth-file.js +9 -10
  5. package/dist/cli/main.js +44 -54
  6. package/dist/error.d.ts +15 -0
  7. package/dist/error.js +74 -0
  8. package/dist/extensions/agents.d.ts +100 -0
  9. package/dist/extensions/agents.js +121 -0
  10. package/dist/extensions/capabilities.d.ts +4 -0
  11. package/dist/extensions/commands.d.ts +23 -0
  12. package/dist/extensions/commands.js +45 -0
  13. package/dist/extensions/compaction.d.ts +36 -0
  14. package/dist/extensions/contracts.d.ts +147 -0
  15. package/dist/extensions/data.d.ts +81 -0
  16. package/dist/extensions/data.js +78 -0
  17. package/dist/extensions/environment.d.ts +39 -0
  18. package/dist/extensions/environment.js +52 -0
  19. package/dist/extensions/files.d.ts +68 -0
  20. package/dist/extensions/files.js +26 -0
  21. package/dist/extensions/hooks.d.ts +32 -0
  22. package/dist/extensions/host-ports.d.ts +24 -0
  23. package/dist/extensions/manager.d.ts +42 -0
  24. package/dist/extensions/manager.js +457 -0
  25. package/dist/extensions/mcp.d.ts +116 -0
  26. package/dist/extensions/mcp.js +434 -0
  27. package/dist/extensions/model-request.d.ts +65 -0
  28. package/dist/extensions/model-request.js +197 -0
  29. package/dist/extensions/model-stream.d.ts +18 -0
  30. package/dist/extensions/model-stream.js +108 -0
  31. package/dist/extensions/models.d.ts +46 -0
  32. package/dist/extensions/models.js +7 -0
  33. package/dist/extensions/network.d.ts +40 -0
  34. package/dist/extensions/network.js +97 -0
  35. package/dist/extensions/operation.d.ts +32 -0
  36. package/dist/extensions/processes.d.ts +64 -0
  37. package/dist/extensions/processes.js +284 -0
  38. package/dist/extensions/prompt-composition.d.ts +38 -0
  39. package/dist/extensions/prompt-composition.js +100 -0
  40. package/dist/extensions/prompt-input.d.ts +30 -0
  41. package/dist/extensions/prompt-input.js +48 -0
  42. package/dist/extensions/prompts.d.ts +31 -0
  43. package/dist/extensions/prompts.js +88 -0
  44. package/dist/extensions/resources.d.ts +26 -0
  45. package/dist/extensions/resources.js +221 -0
  46. package/dist/extensions/services.d.ts +31 -0
  47. package/dist/extensions/services.js +61 -0
  48. package/dist/extensions/session-api.d.ts +6 -0
  49. package/dist/extensions/session-api.js +52 -0
  50. package/dist/extensions/session-input.d.ts +184 -0
  51. package/dist/extensions/session-input.js +422 -0
  52. package/dist/extensions/session-messages.d.ts +41 -0
  53. package/dist/extensions/session-messages.js +76 -0
  54. package/dist/extensions/session-tools.d.ts +32 -0
  55. package/dist/extensions/session-tools.js +208 -0
  56. package/dist/extensions/session.d.ts +60 -0
  57. package/dist/extensions/session.js +265 -0
  58. package/dist/extensions/settings.d.ts +76 -0
  59. package/dist/extensions/settings.js +115 -0
  60. package/dist/extensions/store.d.ts +10 -0
  61. package/dist/extensions/store.js +131 -0
  62. package/dist/extensions/tool-runtime.d.ts +16 -0
  63. package/dist/extensions/tools.d.ts +80 -0
  64. package/dist/extensions/tools.js +270 -0
  65. package/dist/extensions.d.ts +22 -0
  66. package/dist/host/contracts.d.ts +58 -0
  67. package/dist/host/contracts.js +18 -0
  68. package/dist/host/description.d.ts +19 -0
  69. package/dist/host/local-agent-host.d.ts +96 -0
  70. package/dist/host/local-agent-host.js +429 -0
  71. package/dist/host/local-exec-tool.d.ts +26 -0
  72. package/dist/host/local-exec-tool.js +686 -0
  73. package/dist/host/local-file-access.d.ts +30 -0
  74. package/dist/host/local-file-access.js +107 -0
  75. package/dist/host/local-network-access.d.ts +6 -0
  76. package/dist/host/local-network-access.js +101 -0
  77. package/dist/host/local-process-executor.d.ts +5 -0
  78. package/dist/host/local-process-executor.js +17 -0
  79. package/dist/host/local-session-environment.d.ts +18 -0
  80. package/dist/host/local-shell.d.ts +3 -0
  81. package/dist/host/local-tool-registry.d.ts +34 -0
  82. package/dist/host/local-tool-registry.js +134 -0
  83. package/dist/host/network.d.ts +5 -0
  84. package/dist/host/network.js +42 -0
  85. package/dist/host/process-control.d.ts +2 -0
  86. package/dist/host/process-control.js +26 -0
  87. package/dist/host/skill-contract.d.ts +6 -0
  88. package/dist/host.d.ts +17 -0
  89. package/dist/host.js +3 -0
  90. package/dist/index.d.ts +26 -51
  91. package/dist/index.js +9 -12
  92. package/dist/model/anthropic-messages.d.ts +10 -0
  93. package/dist/model/anthropic-messages.js +692 -0
  94. package/dist/model/anthropic-thinking.js +33 -0
  95. package/dist/model/configuration.d.ts +111 -0
  96. package/dist/model/configuration.js +201 -0
  97. package/dist/model/contracts.d.ts +229 -0
  98. package/dist/model/http.d.ts +13 -0
  99. package/dist/model/http.js +119 -0
  100. package/dist/model/image-contract.d.ts +10 -0
  101. package/dist/model/image.d.ts +9 -0
  102. package/dist/model/inline-media-budget.d.ts +7 -0
  103. package/dist/model/inline-media-budget.js +36 -0
  104. package/dist/model/input-images.d.ts +3 -0
  105. package/dist/model/input-images.js +16 -0
  106. package/dist/model/openai-responses.d.ts +59 -0
  107. package/dist/model/openai-responses.js +1586 -0
  108. package/dist/model/recovery.js +80 -0
  109. package/dist/model/request-configuration.d.ts +17 -0
  110. package/dist/model/request-configuration.js +47 -0
  111. package/dist/model/responses-event-projection.d.ts +24 -0
  112. package/dist/model/responses-event-projection.js +194 -0
  113. package/dist/model/responses-request.d.ts +5 -0
  114. package/dist/model/responses-request.js +363 -0
  115. package/dist/model/responses-session-cache.d.ts +33 -0
  116. package/dist/model/responses-session-cache.js +64 -0
  117. package/dist/model/runtime-credential.d.ts +1 -0
  118. package/dist/model/runtime-credential.js +1 -0
  119. package/dist/model/sse.js +281 -0
  120. package/dist/model/text-blocks.js +40 -0
  121. package/dist/model/tool-declarations.d.ts +4 -0
  122. package/dist/model/tool-definition-projection.d.ts +6 -0
  123. package/dist/model/tool-definition-projection.js +11 -0
  124. package/dist/model/tool-schema.d.ts +2 -0
  125. package/dist/model/tool-schema.js +17 -0
  126. package/dist/model/transport-test.d.ts +10 -0
  127. package/dist/model/transport-test.js +27 -0
  128. package/dist/model/usage-observer.d.ts +5 -0
  129. package/dist/model/usage.d.ts +40 -0
  130. package/dist/network/credential-runtime.d.ts +8 -0
  131. package/dist/network/credential-runtime.js +72 -0
  132. package/dist/network/credentials.d.ts +20 -0
  133. package/dist/network/credentials.js +18 -0
  134. package/dist/network/http.d.ts +20 -0
  135. package/dist/network/http.js +421 -0
  136. package/dist/network/product-user-agent.d.ts +5 -0
  137. package/dist/network/product-user-agent.js +22 -0
  138. package/dist/network/transport-error.d.ts +5 -0
  139. package/dist/network/transport-error.js +31 -0
  140. package/dist/process/contracts.d.ts +26 -0
  141. package/dist/prompts/index.d.ts +20 -0
  142. package/dist/prompts/index.js +49 -0
  143. package/dist/prompts/prompt-sections.d.ts +6 -0
  144. package/dist/prompts/prompt-sections.js +6 -0
  145. package/dist/prompts/read-context.js +152 -0
  146. package/dist/runtime/compaction/contracts.d.ts +23 -0
  147. package/dist/runtime/compaction/coordinator.js +88 -0
  148. package/dist/runtime/compaction/generate.d.ts +31 -0
  149. package/dist/runtime/compaction/generate.js +84 -0
  150. package/dist/runtime/compaction/history.d.ts +16 -0
  151. package/dist/runtime/compaction/operation.d.ts +30 -0
  152. package/dist/runtime/compaction/operation.js +131 -0
  153. package/dist/runtime/compaction/requests.d.ts +16 -0
  154. package/dist/runtime/compaction/requests.js +114 -0
  155. package/dist/runtime/compaction/retained-context.d.ts +6 -0
  156. package/dist/runtime/compaction/retained-context.js +48 -0
  157. package/dist/runtime/compaction/smart.d.ts +14 -0
  158. package/dist/runtime/compaction/smart.js +59 -0
  159. package/dist/runtime/context/contextual-blocks.d.ts +31 -0
  160. package/dist/runtime/context/contextual-blocks.js +158 -0
  161. package/dist/runtime/context/environment.d.ts +5 -0
  162. package/dist/runtime/context/gc-candidates-code.d.ts +6 -0
  163. package/dist/runtime/context/gc-candidates-code.js +102 -0
  164. package/dist/runtime/context/gc-candidates-exec.d.ts +6 -0
  165. package/dist/runtime/context/gc-candidates-exec.js +131 -0
  166. package/dist/runtime/context/gc-candidates-read-patch.d.ts +7 -0
  167. package/dist/runtime/context/gc-candidates-read-patch.js +118 -0
  168. package/dist/runtime/context/gc-candidates-subagent.d.ts +6 -0
  169. package/dist/runtime/context/gc-candidates-subagent.js +100 -0
  170. package/dist/runtime/context/gc-candidates-web.d.ts +6 -0
  171. package/dist/runtime/context/gc-candidates-web.js +58 -0
  172. package/dist/runtime/context/gc-candidates.d.ts +12 -0
  173. package/dist/runtime/context/gc-candidates.js +192 -0
  174. package/dist/runtime/context/gc-contracts.d.ts +57 -0
  175. package/dist/runtime/context/gc-economics.d.ts +48 -0
  176. package/dist/runtime/context/gc-economics.js +161 -0
  177. package/dist/runtime/context/gc-runtime.d.ts +43 -0
  178. package/dist/runtime/context/gc-tokens.d.ts +26 -0
  179. package/dist/runtime/context/gc-tokens.js +106 -0
  180. package/dist/runtime/context/gc.d.ts +7 -0
  181. package/dist/runtime/context/gc.js +552 -0
  182. package/dist/runtime/context/instructions.d.ts +37 -0
  183. package/dist/runtime/context/instructions.js +297 -0
  184. package/dist/runtime/context/normalize.d.ts +5 -0
  185. package/dist/runtime/context/projection.d.ts +23 -0
  186. package/dist/runtime/context/projection.js +284 -0
  187. package/dist/runtime/context/request-budget.d.ts +5 -0
  188. package/dist/runtime/context/request-budget.js +25 -0
  189. package/dist/runtime/context/restore.d.ts +27 -0
  190. package/dist/runtime/context/restore.js +186 -0
  191. package/dist/runtime/context/usage.d.ts +17 -0
  192. package/dist/runtime/context/usage.js +124 -0
  193. package/dist/runtime/context/world-state.d.ts +34 -0
  194. package/dist/runtime/context/world-state.js +232 -0
  195. package/dist/runtime/contracts.d.ts +29 -0
  196. package/dist/runtime/event-projection.d.ts +14 -0
  197. package/dist/runtime/event-projection.js +87 -0
  198. package/dist/runtime/events.d.ts +195 -0
  199. package/dist/runtime/execution-handle.d.ts +12 -0
  200. package/dist/runtime/execution-handle.js +1 -0
  201. package/dist/runtime/execution.d.ts +55 -0
  202. package/dist/runtime/execution.js +444 -0
  203. package/dist/runtime/model-progress.js +85 -0
  204. package/dist/runtime/resource-publication.d.ts +27 -0
  205. package/dist/runtime/resource-publication.js +60 -0
  206. package/dist/runtime/tool-round-contract.d.ts +19 -0
  207. package/dist/runtime/tool-round-contract.js +1 -0
  208. package/dist/runtime/wait.js +82 -0
  209. package/dist/sandbox/linux/bubblewrap-sandbox-executor.d.ts +1 -1
  210. package/dist/sandbox/linux/bubblewrap-sandbox-executor.js +8 -8
  211. package/dist/sdk/agent.d.ts +7 -0
  212. package/dist/sdk/agent.js +321 -0
  213. package/dist/sdk/execution-code-mode.d.ts +18 -0
  214. package/dist/sdk/execution-code-mode.js +51 -0
  215. package/dist/sdk/execution-compact-commit.d.ts +23 -0
  216. package/dist/sdk/execution-compact-commit.js +41 -0
  217. package/dist/sdk/execution-compact-extension.d.ts +12 -0
  218. package/dist/sdk/execution-compact-extension.js +46 -0
  219. package/dist/sdk/execution-compact-generation.d.ts +17 -0
  220. package/dist/sdk/execution-compact-generation.js +30 -0
  221. package/dist/sdk/execution-compaction-flight.d.ts +31 -0
  222. package/dist/sdk/execution-compaction-flight.js +50 -0
  223. package/dist/sdk/execution-compaction.d.ts +47 -0
  224. package/dist/sdk/execution-compaction.js +121 -0
  225. package/dist/sdk/execution-context-coordinator.d.ts +56 -0
  226. package/dist/sdk/execution-context-coordinator.js +102 -0
  227. package/dist/sdk/execution-input.d.ts +58 -0
  228. package/dist/sdk/execution-input.js +266 -0
  229. package/dist/sdk/execution-model-context.d.ts +52 -0
  230. package/dist/sdk/execution-model-context.js +156 -0
  231. package/dist/sdk/execution-model-lifecycle.d.ts +39 -0
  232. package/dist/sdk/execution-model-lifecycle.js +73 -0
  233. package/dist/sdk/execution-model-request.d.ts +40 -0
  234. package/dist/sdk/execution-model-request.js +45 -0
  235. package/dist/sdk/execution-round-preparation.d.ts +11 -0
  236. package/dist/sdk/execution-round-preparation.js +18 -0
  237. package/dist/sdk/execution-round-request.d.ts +30 -0
  238. package/dist/sdk/execution-round-request.js +31 -0
  239. package/dist/sdk/execution-tool-catalog.d.ts +46 -0
  240. package/dist/sdk/execution-tool-catalog.js +103 -0
  241. package/dist/sdk/execution-tool-scope.d.ts +67 -0
  242. package/dist/sdk/execution-tool-scope.js +147 -0
  243. package/dist/sdk/extension-agent-controller.d.ts +3 -0
  244. package/dist/sdk/extension-agent-controller.js +69 -0
  245. package/dist/sdk/extension-agents.d.ts +9 -0
  246. package/dist/sdk/extension-agents.js +58 -0
  247. package/dist/sdk/extension-models.d.ts +17 -0
  248. package/dist/sdk/extension-models.js +142 -0
  249. package/dist/sdk/extension-session-launch.d.ts +18 -0
  250. package/dist/sdk/extension-session-launch.js +73 -0
  251. package/dist/sdk/extension-session.d.ts +30 -0
  252. package/dist/sdk/extension-session.js +107 -0
  253. package/dist/sdk/extension-tool-runtime.d.ts +2 -0
  254. package/dist/sdk/extension-tool-runtime.js +14 -0
  255. package/dist/sdk/extension-tools.d.ts +16 -0
  256. package/dist/sdk/extension-tools.js +126 -0
  257. package/dist/sdk/model-input-projection.d.ts +4 -0
  258. package/dist/sdk/model-input-projection.js +27 -0
  259. package/dist/sdk/model-runtime.d.ts +21 -0
  260. package/dist/sdk/model-runtime.js +91 -0
  261. package/dist/sdk/native-steer.d.ts +20 -0
  262. package/dist/sdk/native-steer.js +84 -0
  263. package/dist/sdk/request-preparation.d.ts +9 -0
  264. package/dist/sdk/resource-input.d.ts +33 -0
  265. package/dist/sdk/resource-input.js +402 -0
  266. package/dist/sdk/session-catalog.d.ts +2 -0
  267. package/dist/sdk/session-catalog.js +12 -0
  268. package/dist/sdk/session-composition.d.ts +54 -0
  269. package/dist/sdk/session-composition.js +1 -0
  270. package/dist/sdk/session-execution-factory.d.ts +43 -0
  271. package/dist/sdk/session-execution-factory.js +937 -0
  272. package/dist/sdk/session-execution.d.ts +163 -0
  273. package/dist/sdk/session-execution.js +388 -0
  274. package/dist/sdk/session-extension-messages.d.ts +16 -0
  275. package/dist/sdk/session-extension-messages.js +64 -0
  276. package/dist/sdk/session-extension-prompt.d.ts +35 -0
  277. package/dist/sdk/session-extension-prompt.js +62 -0
  278. package/dist/sdk/session-maintenance.d.ts +25 -0
  279. package/dist/sdk/session-maintenance.js +205 -0
  280. package/dist/sdk/session-model-adapters.d.ts +28 -0
  281. package/dist/sdk/session-model-adapters.js +96 -0
  282. package/dist/sdk/session-open.d.ts +22 -0
  283. package/dist/sdk/session-open.js +44 -0
  284. package/dist/sdk/session-registry.d.ts +17 -0
  285. package/dist/sdk/session-registry.js +83 -0
  286. package/dist/sdk/session-runtime.d.ts +72 -0
  287. package/dist/sdk/session-runtime.js +205 -0
  288. package/dist/sdk/session.d.ts +3 -0
  289. package/dist/sdk/session.js +313 -0
  290. package/dist/sdk/subagent-backend.d.ts +3 -0
  291. package/dist/sdk/subagent-backend.js +49 -0
  292. package/dist/sdk/types.d.ts +80 -0
  293. package/dist/sdk/types.js +1 -0
  294. package/dist/session/catalog.d.ts +70 -0
  295. package/dist/session/catalog.js +194 -0
  296. package/dist/session/code-observation-contract.d.ts +40 -0
  297. package/dist/session/code-observation-contract.js +1 -0
  298. package/dist/session/code-observation-projection.d.ts +54 -0
  299. package/dist/session/code-observation-projection.js +165 -0
  300. package/dist/session/code-state.d.ts +27 -0
  301. package/dist/session/code-state.js +89 -0
  302. package/dist/session/context-gc-checkpoint.d.ts +26 -0
  303. package/dist/session/context-gc-checkpoint.js +935 -0
  304. package/dist/session/context-gc-contract.d.ts +141 -0
  305. package/dist/session/context-gc-contract.js +1 -0
  306. package/dist/session/context-gc-observations.d.ts +58 -0
  307. package/dist/session/context-gc-observations.js +187 -0
  308. package/dist/session/context-gc-replacements.d.ts +63 -0
  309. package/dist/session/context-gc-subagent.d.ts +54 -0
  310. package/dist/session/deferred-input.d.ts +5 -0
  311. package/dist/session/deferred-input.js +74 -0
  312. package/dist/session/extension-checkpoint.d.ts +8 -0
  313. package/dist/session/extension-checkpoint.js +30 -0
  314. package/dist/session/history-input-limits.d.ts +4 -0
  315. package/dist/session/history-input-limits.js +4 -0
  316. package/dist/session/inline-media-contract.d.ts +16 -0
  317. package/dist/session/inline-media-contract.js +1 -0
  318. package/dist/session/inline-media.d.ts +26 -0
  319. package/dist/session/inline-media.js +138 -0
  320. package/dist/session/model-request.d.ts +14 -0
  321. package/dist/session/model-request.js +1 -0
  322. package/dist/session/record-contract.d.ts +19 -0
  323. package/dist/session/record-contract.js +1 -0
  324. package/dist/session/record-projection.d.ts +6 -0
  325. package/dist/session/record-projection.js +80 -0
  326. package/dist/session/resource-contract.d.ts +9 -0
  327. package/dist/session/resource-contract.js +1 -0
  328. package/dist/session/rollback.d.ts +13 -0
  329. package/dist/session/rollback.js +46 -0
  330. package/dist/session/store/contracts.d.ts +160 -0
  331. package/dist/session/store/contracts.js +1 -0
  332. package/dist/session/store/current-state.d.ts +17 -0
  333. package/dist/session/store/current-state.js +53 -0
  334. package/dist/session/store/execution-state.d.ts +13 -0
  335. package/dist/session/store/execution-state.js +103 -0
  336. package/dist/session/store/index.d.ts +4 -0
  337. package/dist/session/store/index.js +2 -0
  338. package/dist/session/store/jsonl/directory-index.d.ts +26 -0
  339. package/dist/session/store/jsonl/directory-index.js +283 -0
  340. package/dist/session/store/jsonl/fs-durability.d.ts +3 -0
  341. package/dist/session/store/jsonl/fs-durability.js +17 -0
  342. package/dist/session/store/jsonl/history-replacement.d.ts +48 -0
  343. package/dist/session/store/jsonl/history-replacement.js +147 -0
  344. package/dist/session/store/jsonl/history.d.ts +25 -0
  345. package/dist/session/store/jsonl/history.js +181 -0
  346. package/dist/session/store/jsonl/images.d.ts +19 -0
  347. package/dist/session/store/jsonl/images.js +122 -0
  348. package/dist/session/store/jsonl/index-transaction.d.ts +13 -0
  349. package/dist/session/store/jsonl/index-transaction.js +87 -0
  350. package/dist/session/store/jsonl/jsonl-admission.d.ts +10 -0
  351. package/dist/session/store/jsonl/jsonl-admission.js +205 -0
  352. package/dist/session/store/jsonl/jsonl-codec.d.ts +11 -0
  353. package/dist/session/store/jsonl/jsonl-codec.js +138 -0
  354. package/dist/session/store/jsonl/jsonl-migration.d.ts +12 -0
  355. package/dist/session/store/jsonl/jsonl-migration.js +105 -0
  356. package/dist/session/store/jsonl/jsonl-store.d.ts +171 -0
  357. package/dist/session/store/jsonl/jsonl-store.js +2482 -0
  358. package/dist/session/store/jsonl/open-recovery.d.ts +13 -0
  359. package/dist/session/store/jsonl/open-recovery.js +131 -0
  360. package/dist/session/store/jsonl/read-pins.d.ts +4 -0
  361. package/dist/session/store/jsonl/read-pins.js +131 -0
  362. package/dist/session/store/jsonl/record-append.d.ts +16 -0
  363. package/dist/session/store/jsonl/record-append.js +49 -0
  364. package/dist/session/store/jsonl/records.d.ts +30 -0
  365. package/dist/session/store/jsonl/records.js +313 -0
  366. package/dist/session/store/jsonl/resources.d.ts +19 -0
  367. package/dist/session/store/jsonl/resources.js +209 -0
  368. package/dist/session/store/jsonl/store-pool.d.ts +12 -0
  369. package/dist/session/store/jsonl/store-pool.js +55 -0
  370. package/dist/session/store/jsonl/transaction-recovery.d.ts +48 -0
  371. package/dist/session/store/jsonl/transaction-recovery.js +374 -0
  372. package/dist/session/store/jsonl/tree-maintenance.d.ts +12 -0
  373. package/dist/session/store/jsonl/tree-maintenance.js +59 -0
  374. package/dist/session/store/types.d.ts +69 -0
  375. package/dist/session/store/types.js +1 -0
  376. package/dist/session/summary.d.ts +18 -0
  377. package/dist/session/summary.js +1 -0
  378. package/dist/session/todo.d.ts +11 -0
  379. package/dist/session/todo.js +30 -0
  380. package/dist/session/tool-result-resources.d.ts +27 -0
  381. package/dist/session/tool-result-resources.js +255 -0
  382. package/dist/session/types.js +1 -0
  383. package/dist/session/user-history.d.ts +17 -0
  384. package/dist/session/user-history.js +1 -0
  385. package/dist/session-store.d.ts +2 -0
  386. package/dist/session-store.js +1 -0
  387. package/dist/shared/auto-title.d.ts +3 -3
  388. package/dist/shared/auto-title.js +6 -6
  389. package/dist/shared/model-text.d.ts +8 -8
  390. package/dist/shared/model-text.js +8 -7
  391. package/dist/storage/file-lock.js +83 -0
  392. package/dist/subagent/contracts.d.ts +107 -0
  393. package/dist/subagent/contracts.js +1 -0
  394. package/dist/subagent/limits.d.ts +17 -0
  395. package/dist/subagent/limits.js +17 -0
  396. package/dist/subagent/model-update.js +81 -0
  397. package/dist/subagent/session-controller.d.ts +148 -0
  398. package/dist/subagent/session-controller.js +1761 -0
  399. package/dist/subagent/wait-targets.d.ts +10 -0
  400. package/dist/subagent/wait-targets.js +26 -0
  401. package/dist/subagent/wait.d.ts +26 -0
  402. package/dist/subagent/wait.js +73 -0
  403. package/dist/tools/agent/agent-cancel.d.ts +7 -0
  404. package/dist/tools/agent/agent-cancel.js +29 -0
  405. package/dist/tools/agent/agent-message.d.ts +7 -0
  406. package/dist/tools/agent/agent-message.js +57 -0
  407. package/dist/tools/agent/agent-start.d.ts +12 -0
  408. package/dist/tools/agent/agent-start.js +106 -0
  409. package/dist/tools/agent/agent-wait.d.ts +7 -0
  410. package/dist/tools/agent/agent-wait.js +91 -0
  411. package/dist/tools/agent/question.d.ts +7 -0
  412. package/dist/tools/agent/question.js +125 -0
  413. package/dist/tools/agent/skill.d.ts +11 -0
  414. package/dist/tools/agent/skill.js +38 -0
  415. package/dist/tools/agent/sleep.d.ts +9 -0
  416. package/dist/tools/agent/sleep.js +54 -0
  417. package/dist/tools/agent/smart-compact.d.ts +9 -0
  418. package/dist/tools/agent/smart-compact.js +23 -0
  419. package/dist/tools/agent/todo-read.d.ts +14 -0
  420. package/dist/tools/agent/todo-write.d.ts +14 -0
  421. package/dist/tools/agent/todo-write.js +66 -0
  422. package/dist/tools/agent/todo.d.ts +25 -0
  423. package/dist/tools/agent/todo.js +32 -0
  424. package/dist/tools/callers.d.ts +7 -0
  425. package/dist/tools/callers.js +39 -0
  426. package/dist/tools/code-mode/cells.d.ts +29 -0
  427. package/dist/tools/code-mode/cells.js +338 -0
  428. package/dist/tools/code-mode/dispatch.d.ts +20 -0
  429. package/dist/tools/code-mode/dispatch.js +80 -0
  430. package/dist/tools/code-mode/engine.d.ts +60 -0
  431. package/dist/tools/code-mode/engine.js +1 -0
  432. package/dist/tools/code-mode/index.d.ts +31 -0
  433. package/dist/tools/code-mode/index.js +751 -0
  434. package/dist/tools/code-mode/observations.d.ts +8 -0
  435. package/dist/tools/code-mode/observations.js +64 -0
  436. package/dist/tools/code-mode/worker.d.ts +1 -0
  437. package/dist/tools/contracts.d.ts +193 -0
  438. package/dist/tools/contracts.js +1 -0
  439. package/dist/tools/definition-projection.d.ts +1 -0
  440. package/dist/tools/definition-projection.js +1 -0
  441. package/dist/tools/execution-limits.d.ts +69 -0
  442. package/dist/tools/execution-limits.js +58 -0
  443. package/dist/tools/execution.d.ts +30 -0
  444. package/dist/tools/execution.js +191 -0
  445. package/dist/tools/local/apply-patch-parser.js +177 -0
  446. package/dist/tools/local/apply-patch.d.ts +19 -0
  447. package/dist/tools/local/apply-patch.js +489 -0
  448. package/dist/tools/local/exec.d.ts +28 -0
  449. package/dist/tools/local/exec.js +194 -0
  450. package/dist/tools/local/image-processing.js +146 -0
  451. package/dist/tools/local/read.d.ts +43 -0
  452. package/dist/tools/local/read.js +470 -0
  453. package/dist/tools/local/view-image.d.ts +15 -0
  454. package/dist/tools/local/view-image.js +317 -0
  455. package/dist/tools/mcp/catalog.js +220 -0
  456. package/dist/tools/mcp/history.d.ts +4 -0
  457. package/dist/tools/mcp/tool-search.d.ts +45 -0
  458. package/dist/tools/mcp/tool-search.js +294 -0
  459. package/dist/tools/output-projection.d.ts +18 -0
  460. package/dist/tools/output-projection.js +341 -0
  461. package/dist/tools/permission-contract.d.ts +25 -0
  462. package/dist/tools/permission-contract.js +1 -0
  463. package/dist/tools/permissions.d.ts +61 -0
  464. package/dist/tools/permissions.js +237 -0
  465. package/dist/tools/registry.d.ts +7 -0
  466. package/dist/tools/result-extension-contract.d.ts +37 -0
  467. package/dist/tools/result-extension-contract.js +32 -0
  468. package/dist/tools/result-extensions.d.ts +12 -0
  469. package/dist/tools/result-extensions.js +104 -0
  470. package/dist/tools/runtime-context.d.ts +89 -0
  471. package/dist/tools/runtime-context.js +1 -0
  472. package/dist/tools/runtime-resource-handles.js +28 -0
  473. package/dist/tools/runtime.js +77 -0
  474. package/dist/tools/scheduler.d.ts +12 -0
  475. package/dist/tools/shared/path-resolver.js +133 -0
  476. package/dist/tools/wait.d.ts +1 -0
  477. package/dist/tools/wait.js +1 -0
  478. package/package.json +15 -3
  479. package/dist/agent-core/error.d.ts +0 -15
  480. package/dist/agent-core/error.js +0 -74
  481. package/dist/agent-core/extensions/agents.d.ts +0 -79
  482. package/dist/agent-core/extensions/agents.js +0 -186
  483. package/dist/agent-core/extensions/compaction.d.ts +0 -48
  484. package/dist/agent-core/extensions/contracts.d.ts +0 -265
  485. package/dist/agent-core/extensions/data.d.ts +0 -84
  486. package/dist/agent-core/extensions/data.js +0 -83
  487. package/dist/agent-core/extensions/environment.d.ts +0 -27
  488. package/dist/agent-core/extensions/environment.js +0 -52
  489. package/dist/agent-core/extensions/files.d.ts +0 -64
  490. package/dist/agent-core/extensions/files.js +0 -26
  491. package/dist/agent-core/extensions/hooks.d.ts +0 -32
  492. package/dist/agent-core/extensions/manager.d.ts +0 -39
  493. package/dist/agent-core/extensions/manager.js +0 -458
  494. package/dist/agent-core/extensions/mcp.d.ts +0 -99
  495. package/dist/agent-core/extensions/mcp.js +0 -433
  496. package/dist/agent-core/extensions/model-request.d.ts +0 -56
  497. package/dist/agent-core/extensions/model-request.js +0 -197
  498. package/dist/agent-core/extensions/model-stream.d.ts +0 -9
  499. package/dist/agent-core/extensions/model-stream.js +0 -108
  500. package/dist/agent-core/extensions/models.d.ts +0 -43
  501. package/dist/agent-core/extensions/network.d.ts +0 -32
  502. package/dist/agent-core/extensions/network.js +0 -97
  503. package/dist/agent-core/extensions/operation.d.ts +0 -30
  504. package/dist/agent-core/extensions/processes.d.ts +0 -52
  505. package/dist/agent-core/extensions/processes.js +0 -284
  506. package/dist/agent-core/extensions/prompt-composition.d.ts +0 -24
  507. package/dist/agent-core/extensions/prompt-composition.js +0 -106
  508. package/dist/agent-core/extensions/prompt-input.d.ts +0 -23
  509. package/dist/agent-core/extensions/prompt-input.js +0 -48
  510. package/dist/agent-core/extensions/resources.d.ts +0 -27
  511. package/dist/agent-core/extensions/resources.js +0 -221
  512. package/dist/agent-core/extensions/services.d.ts +0 -31
  513. package/dist/agent-core/extensions/services.js +0 -61
  514. package/dist/agent-core/extensions/session-input.d.ts +0 -163
  515. package/dist/agent-core/extensions/session-input.js +0 -411
  516. package/dist/agent-core/extensions/session-messages.d.ts +0 -41
  517. package/dist/agent-core/extensions/session-messages.js +0 -76
  518. package/dist/agent-core/extensions/session.d.ts +0 -69
  519. package/dist/agent-core/extensions/session.js +0 -607
  520. package/dist/agent-core/extensions/settings.d.ts +0 -59
  521. package/dist/agent-core/extensions/settings.js +0 -115
  522. package/dist/agent-core/extensions/store.d.ts +0 -10
  523. package/dist/agent-core/extensions/store.js +0 -131
  524. package/dist/agent-core/extensions/tools.d.ts +0 -61
  525. package/dist/agent-core/extensions/tools.js +0 -269
  526. package/dist/agent-core/host/contracts.d.ts +0 -100
  527. package/dist/agent-core/host/contracts.js +0 -18
  528. package/dist/agent-core/host/local-agent-host.d.ts +0 -96
  529. package/dist/agent-core/host/local-agent-host.js +0 -425
  530. package/dist/agent-core/host/local-file-access.d.ts +0 -30
  531. package/dist/agent-core/host/local-file-access.js +0 -107
  532. package/dist/agent-core/host/local-network-access.d.ts +0 -6
  533. package/dist/agent-core/host/local-network-access.js +0 -101
  534. package/dist/agent-core/host/local-process-executor.d.ts +0 -29
  535. package/dist/agent-core/host/local-process-executor.js +0 -41
  536. package/dist/agent-core/host/local-session-environment.d.ts +0 -18
  537. package/dist/agent-core/host/local-shell.d.ts +0 -3
  538. package/dist/agent-core/host/network.d.ts +0 -4
  539. package/dist/agent-core/host/network.js +0 -6
  540. package/dist/agent-core/model/anthropic-messages.d.ts +0 -10
  541. package/dist/agent-core/model/anthropic-messages.js +0 -707
  542. package/dist/agent-core/model/anthropic-thinking.js +0 -33
  543. package/dist/agent-core/model/catalog-file.d.ts +0 -80
  544. package/dist/agent-core/model/catalog-file.js +0 -103
  545. package/dist/agent-core/model/configuration.d.ts +0 -127
  546. package/dist/agent-core/model/configuration.js +0 -168
  547. package/dist/agent-core/model/contracts.d.ts +0 -229
  548. package/dist/agent-core/model/http.d.ts +0 -27
  549. package/dist/agent-core/model/http.js +0 -534
  550. package/dist/agent-core/model/image.d.ts +0 -17
  551. package/dist/agent-core/model/openai-responses.d.ts +0 -77
  552. package/dist/agent-core/model/openai-responses.js +0 -2123
  553. package/dist/agent-core/model/product-user-agent.d.ts +0 -5
  554. package/dist/agent-core/model/product-user-agent.js +0 -22
  555. package/dist/agent-core/model/recovery.js +0 -80
  556. package/dist/agent-core/model/request-configuration.d.ts +0 -17
  557. package/dist/agent-core/model/request-configuration.js +0 -47
  558. package/dist/agent-core/model/runtime-credential.d.ts +0 -8
  559. package/dist/agent-core/model/runtime-credential.js +0 -72
  560. package/dist/agent-core/model/sse.js +0 -281
  561. package/dist/agent-core/model/text-blocks.js +0 -40
  562. package/dist/agent-core/model/tool-declarations.d.ts +0 -4
  563. package/dist/agent-core/model/transport-test.d.ts +0 -3
  564. package/dist/agent-core/model/transport-test.js +0 -23
  565. package/dist/agent-core/model/usage-observer.d.ts +0 -31
  566. package/dist/agent-core/prompts/index.d.ts +0 -20
  567. package/dist/agent-core/prompts/index.js +0 -49
  568. package/dist/agent-core/runtime/compaction/coordinator.js +0 -88
  569. package/dist/agent-core/runtime/compaction/generate.d.ts +0 -28
  570. package/dist/agent-core/runtime/compaction/generate.js +0 -84
  571. package/dist/agent-core/runtime/compaction/history.d.ts +0 -16
  572. package/dist/agent-core/runtime/compaction/operation.d.ts +0 -29
  573. package/dist/agent-core/runtime/compaction/operation.js +0 -131
  574. package/dist/agent-core/runtime/compaction/requests.d.ts +0 -16
  575. package/dist/agent-core/runtime/compaction/requests.js +0 -114
  576. package/dist/agent-core/runtime/compaction/retained-context.d.ts +0 -6
  577. package/dist/agent-core/runtime/compaction/retained-context.js +0 -47
  578. package/dist/agent-core/runtime/compaction/smart.d.ts +0 -14
  579. package/dist/agent-core/runtime/compaction/smart.js +0 -59
  580. package/dist/agent-core/runtime/context/contextual-blocks.d.ts +0 -30
  581. package/dist/agent-core/runtime/context/contextual-blocks.js +0 -146
  582. package/dist/agent-core/runtime/context/environment.d.ts +0 -5
  583. package/dist/agent-core/runtime/context/gc-runtime.d.ts +0 -38
  584. package/dist/agent-core/runtime/context/gc-tokens.d.ts +0 -25
  585. package/dist/agent-core/runtime/context/gc-tokens.js +0 -103
  586. package/dist/agent-core/runtime/context/gc.d.ts +0 -75
  587. package/dist/agent-core/runtime/context/gc.js +0 -1386
  588. package/dist/agent-core/runtime/context/instructions.d.ts +0 -37
  589. package/dist/agent-core/runtime/context/instructions.js +0 -297
  590. package/dist/agent-core/runtime/context/normalize.d.ts +0 -5
  591. package/dist/agent-core/runtime/context/projection.d.ts +0 -23
  592. package/dist/agent-core/runtime/context/projection.js +0 -284
  593. package/dist/agent-core/runtime/context/request-budget.d.ts +0 -4
  594. package/dist/agent-core/runtime/context/request-budget.js +0 -25
  595. package/dist/agent-core/runtime/context/restore.d.ts +0 -25
  596. package/dist/agent-core/runtime/context/restore.js +0 -186
  597. package/dist/agent-core/runtime/context/usage.d.ts +0 -17
  598. package/dist/agent-core/runtime/context/usage.js +0 -124
  599. package/dist/agent-core/runtime/context/world-state.d.ts +0 -33
  600. package/dist/agent-core/runtime/context/world-state.js +0 -232
  601. package/dist/agent-core/runtime/contracts.d.ts +0 -41
  602. package/dist/agent-core/runtime/event-projection.d.ts +0 -14
  603. package/dist/agent-core/runtime/event-projection.js +0 -87
  604. package/dist/agent-core/runtime/events.d.ts +0 -197
  605. package/dist/agent-core/runtime/execution-handle.d.ts +0 -12
  606. package/dist/agent-core/runtime/execution.d.ts +0 -50
  607. package/dist/agent-core/runtime/execution.js +0 -445
  608. package/dist/agent-core/runtime/model-progress.js +0 -85
  609. package/dist/agent-core/runtime/resource-publication.d.ts +0 -8
  610. package/dist/agent-core/runtime/resource-publication.js +0 -60
  611. package/dist/agent-core/sdk/agent.d.ts +0 -11
  612. package/dist/agent-core/sdk/agent.js +0 -474
  613. package/dist/agent-core/sdk/extension-agents.d.ts +0 -9
  614. package/dist/agent-core/sdk/extension-agents.js +0 -58
  615. package/dist/agent-core/sdk/extension-models.d.ts +0 -13
  616. package/dist/agent-core/sdk/extension-models.js +0 -137
  617. package/dist/agent-core/sdk/extension-session.d.ts +0 -30
  618. package/dist/agent-core/sdk/extension-session.js +0 -105
  619. package/dist/agent-core/sdk/extension-tools.d.ts +0 -16
  620. package/dist/agent-core/sdk/extension-tools.js +0 -126
  621. package/dist/agent-core/sdk/model-runtime.d.ts +0 -18
  622. package/dist/agent-core/sdk/model-runtime.js +0 -93
  623. package/dist/agent-core/sdk/native-steer.d.ts +0 -20
  624. package/dist/agent-core/sdk/native-steer.js +0 -84
  625. package/dist/agent-core/sdk/request-preparation.d.ts +0 -7
  626. package/dist/agent-core/sdk/resource-input.d.ts +0 -32
  627. package/dist/agent-core/sdk/resource-input.js +0 -403
  628. package/dist/agent-core/sdk/session.d.ts +0 -94
  629. package/dist/agent-core/sdk/session.js +0 -2377
  630. package/dist/agent-core/sdk/subagent-backend.d.ts +0 -3
  631. package/dist/agent-core/sdk/subagent-backend.js +0 -49
  632. package/dist/agent-core/sdk/types.d.ts +0 -81
  633. package/dist/agent-core/session/catalog.d.ts +0 -99
  634. package/dist/agent-core/session/catalog.js +0 -200
  635. package/dist/agent-core/session/context-gc-checkpoint.d.ts +0 -165
  636. package/dist/agent-core/session/context-gc-checkpoint.js +0 -935
  637. package/dist/agent-core/session/context-gc-observations.d.ts +0 -60
  638. package/dist/agent-core/session/context-gc-observations.js +0 -187
  639. package/dist/agent-core/session/context-gc-replacements.d.ts +0 -62
  640. package/dist/agent-core/session/context-gc-subagent.d.ts +0 -53
  641. package/dist/agent-core/session/deferred-input.d.ts +0 -5
  642. package/dist/agent-core/session/deferred-input.js +0 -74
  643. package/dist/agent-core/session/inline-media.d.ts +0 -45
  644. package/dist/agent-core/session/inline-media.js +0 -163
  645. package/dist/agent-core/session/rollback.d.ts +0 -13
  646. package/dist/agent-core/session/rollback.js +0 -46
  647. package/dist/agent-core/session/store/contracts.d.ts +0 -158
  648. package/dist/agent-core/session/store/current-state.d.ts +0 -17
  649. package/dist/agent-core/session/store/current-state.js +0 -53
  650. package/dist/agent-core/session/store/directory-index.d.ts +0 -18
  651. package/dist/agent-core/session/store/directory-index.js +0 -169
  652. package/dist/agent-core/session/store/execution-state.d.ts +0 -18
  653. package/dist/agent-core/session/store/execution-state.js +0 -175
  654. package/dist/agent-core/session/store/history.d.ts +0 -25
  655. package/dist/agent-core/session/store/history.js +0 -181
  656. package/dist/agent-core/session/store/images.d.ts +0 -19
  657. package/dist/agent-core/session/store/images.js +0 -110
  658. package/dist/agent-core/session/store/index.d.ts +0 -4
  659. package/dist/agent-core/session/store/index.js +0 -2
  660. package/dist/agent-core/session/store/jsonl-store.d.ts +0 -171
  661. package/dist/agent-core/session/store/jsonl-store.js +0 -2078
  662. package/dist/agent-core/session/store/records.d.ts +0 -23
  663. package/dist/agent-core/session/store/records.js +0 -261
  664. package/dist/agent-core/session/store/resources.d.ts +0 -26
  665. package/dist/agent-core/session/store/resources.js +0 -197
  666. package/dist/agent-core/session/store/types.d.ts +0 -82
  667. package/dist/agent-core/session/tool-result-resources.d.ts +0 -26
  668. package/dist/agent-core/session/tool-result-resources.js +0 -256
  669. package/dist/agent-core/session/transaction-recovery.d.ts +0 -16
  670. package/dist/agent-core/session/transaction-recovery.js +0 -135
  671. package/dist/agent-core/storage/file-lock.js +0 -83
  672. package/dist/agent-core/subagent/contracts.d.ts +0 -117
  673. package/dist/agent-core/subagent/model-update.js +0 -81
  674. package/dist/agent-core/subagent/scheduler.d.ts +0 -135
  675. package/dist/agent-core/subagent/scheduler.js +0 -369
  676. package/dist/agent-core/subagent/session-controller.d.ts +0 -138
  677. package/dist/agent-core/subagent/session-controller.js +0 -1594
  678. package/dist/agent-core/subagent/wait.d.ts +0 -14
  679. package/dist/agent-core/subagent/wait.js +0 -32
  680. package/dist/agent-core/tools/agent/agent-cancel.d.ts +0 -7
  681. package/dist/agent-core/tools/agent/agent-cancel.js +0 -29
  682. package/dist/agent-core/tools/agent/agent-message.d.ts +0 -7
  683. package/dist/agent-core/tools/agent/agent-message.js +0 -57
  684. package/dist/agent-core/tools/agent/agent-start.d.ts +0 -12
  685. package/dist/agent-core/tools/agent/agent-start.js +0 -106
  686. package/dist/agent-core/tools/agent/agent-wait.d.ts +0 -7
  687. package/dist/agent-core/tools/agent/agent-wait.js +0 -91
  688. package/dist/agent-core/tools/agent/question.d.ts +0 -7
  689. package/dist/agent-core/tools/agent/question.js +0 -125
  690. package/dist/agent-core/tools/agent/skill.d.ts +0 -11
  691. package/dist/agent-core/tools/agent/skill.js +0 -38
  692. package/dist/agent-core/tools/agent/sleep.d.ts +0 -12
  693. package/dist/agent-core/tools/agent/sleep.js +0 -54
  694. package/dist/agent-core/tools/agent/smart-compact.d.ts +0 -9
  695. package/dist/agent-core/tools/agent/smart-compact.js +0 -23
  696. package/dist/agent-core/tools/agent/todo-read.d.ts +0 -14
  697. package/dist/agent-core/tools/agent/todo-write.d.ts +0 -14
  698. package/dist/agent-core/tools/agent/todo-write.js +0 -66
  699. package/dist/agent-core/tools/agent/todo.d.ts +0 -26
  700. package/dist/agent-core/tools/agent/todo.js +0 -60
  701. package/dist/agent-core/tools/callers.d.ts +0 -6
  702. package/dist/agent-core/tools/callers.js +0 -39
  703. package/dist/agent-core/tools/code-mode/cells.d.ts +0 -29
  704. package/dist/agent-core/tools/code-mode/cells.js +0 -337
  705. package/dist/agent-core/tools/code-mode/dispatch.d.ts +0 -20
  706. package/dist/agent-core/tools/code-mode/dispatch.js +0 -80
  707. package/dist/agent-core/tools/code-mode/engine.d.ts +0 -60
  708. package/dist/agent-core/tools/code-mode/index.d.ts +0 -29
  709. package/dist/agent-core/tools/code-mode/index.js +0 -749
  710. package/dist/agent-core/tools/code-mode/observations.d.ts +0 -98
  711. package/dist/agent-core/tools/code-mode/observations.js +0 -228
  712. package/dist/agent-core/tools/code-mode/state.d.ts +0 -9
  713. package/dist/agent-core/tools/code-mode/state.js +0 -82
  714. package/dist/agent-core/tools/contracts.d.ts +0 -211
  715. package/dist/agent-core/tools/definition-projection.d.ts +0 -7
  716. package/dist/agent-core/tools/definition-projection.js +0 -26
  717. package/dist/agent-core/tools/execution-limits.d.ts +0 -69
  718. package/dist/agent-core/tools/execution-limits.js +0 -69
  719. package/dist/agent-core/tools/execution.d.ts +0 -46
  720. package/dist/agent-core/tools/execution.js +0 -191
  721. package/dist/agent-core/tools/local/apply-patch-parser.js +0 -177
  722. package/dist/agent-core/tools/local/apply-patch.d.ts +0 -19
  723. package/dist/agent-core/tools/local/apply-patch.js +0 -489
  724. package/dist/agent-core/tools/local/exec.d.ts +0 -53
  725. package/dist/agent-core/tools/local/exec.js +0 -877
  726. package/dist/agent-core/tools/local/image-processing.js +0 -146
  727. package/dist/agent-core/tools/local/read-context.js +0 -152
  728. package/dist/agent-core/tools/local/read.d.ts +0 -43
  729. package/dist/agent-core/tools/local/read.js +0 -470
  730. package/dist/agent-core/tools/local/registry.d.ts +0 -34
  731. package/dist/agent-core/tools/local/registry.js +0 -132
  732. package/dist/agent-core/tools/local/view-image.d.ts +0 -15
  733. package/dist/agent-core/tools/local/view-image.js +0 -317
  734. package/dist/agent-core/tools/local/workspace-tools.d.ts +0 -12
  735. package/dist/agent-core/tools/local/workspace-tools.js +0 -28
  736. package/dist/agent-core/tools/mcp/catalog.js +0 -220
  737. package/dist/agent-core/tools/mcp/history.d.ts +0 -4
  738. package/dist/agent-core/tools/mcp/tool-search.d.ts +0 -45
  739. package/dist/agent-core/tools/mcp/tool-search.js +0 -294
  740. package/dist/agent-core/tools/output-projection.d.ts +0 -18
  741. package/dist/agent-core/tools/output-projection.js +0 -341
  742. package/dist/agent-core/tools/permissions.d.ts +0 -85
  743. package/dist/agent-core/tools/permissions.js +0 -237
  744. package/dist/agent-core/tools/registry.d.ts +0 -7
  745. package/dist/agent-core/tools/result-extensions.d.ts +0 -46
  746. package/dist/agent-core/tools/result-extensions.js +0 -134
  747. package/dist/agent-core/tools/runtime-context.d.ts +0 -74
  748. package/dist/agent-core/tools/runtime-resource-handles.js +0 -28
  749. package/dist/agent-core/tools/runtime.js +0 -77
  750. package/dist/agent-core/tools/scheduler.d.ts +0 -12
  751. package/dist/agent-core/tools/shared/path-resolver.js +0 -133
  752. package/dist/agent-core/tools/wait.js +0 -82
  753. /package/dist/{agent-core/extensions/models.js → extensions/capabilities.js} +0 -0
  754. /package/dist/{agent-core/extensions → extensions}/compaction.js +0 -0
  755. /package/dist/{agent-core/model → extensions}/contracts.js +0 -0
  756. /package/dist/{agent-core/extensions → extensions}/hooks.js +0 -0
  757. /package/dist/{agent-core/runtime/context/contracts.js → extensions/host-ports.js} +0 -0
  758. /package/dist/{agent-core/extensions → extensions}/operation.js +0 -0
  759. /package/dist/{agent-core/runtime/contracts.js → extensions/tool-runtime.js} +0 -0
  760. /package/dist/{agent-core/extensions/contracts.js → extensions.js} +0 -0
  761. /package/dist/{agent-core/runtime/events.js → host/description.js} +0 -0
  762. /package/dist/{agent-core/host → host}/local-session-environment.js +0 -0
  763. /package/dist/{agent-core/host → host}/local-shell.js +0 -0
  764. /package/dist/{agent-core/runtime/execution-handle.js → host/skill-contract.js} +0 -0
  765. /package/dist/{agent-core/model → model}/anthropic-thinking.d.ts +0 -0
  766. /package/dist/{agent-core/model → model}/attempt-diagnostics.d.ts +0 -0
  767. /package/dist/{agent-core/model → model}/attempt-diagnostics.js +0 -0
  768. /package/dist/{agent-core/session/store → model}/contracts.js +0 -0
  769. /package/dist/{agent-core/sdk/types.js → model/image-contract.js} +0 -0
  770. /package/dist/{agent-core/model → model}/image.js +0 -0
  771. /package/dist/{agent-core/model → model}/native-context.d.ts +0 -0
  772. /package/dist/{agent-core/model → model}/native-context.js +0 -0
  773. /package/dist/{agent-core/model → model}/recovery.d.ts +0 -0
  774. /package/dist/{agent-core/model → model}/sse.d.ts +0 -0
  775. /package/dist/{agent-core/model → model}/text-blocks.d.ts +0 -0
  776. /package/dist/{agent-core/model → model}/tool-declarations.js +0 -0
  777. /package/dist/{agent-core/model → model}/tool-input.d.ts +0 -0
  778. /package/dist/{agent-core/model → model}/tool-input.js +0 -0
  779. /package/dist/{agent-core/model → model}/usage-observer.js +0 -0
  780. /package/dist/{agent-core/session/store/types.js → model/usage.js} +0 -0
  781. /package/dist/{agent-core/subagent → process}/contracts.js +0 -0
  782. /package/dist/{agent-core/prompts → prompts}/compact.d.ts +0 -0
  783. /package/dist/{agent-core/prompts → prompts}/compact.js +0 -0
  784. /package/dist/{agent-core/prompts → prompts}/core.d.ts +0 -0
  785. /package/dist/{agent-core/prompts → prompts}/core.js +0 -0
  786. /package/dist/{agent-core/prompts → prompts}/markup.d.ts +0 -0
  787. /package/dist/{agent-core/prompts → prompts}/markup.js +0 -0
  788. /package/dist/{agent-core/prompts → prompts}/modes.d.ts +0 -0
  789. /package/dist/{agent-core/prompts → prompts}/modes.js +0 -0
  790. /package/dist/{agent-core/prompts → prompts}/output.d.ts +0 -0
  791. /package/dist/{agent-core/prompts → prompts}/output.js +0 -0
  792. /package/dist/{agent-core/prompts → prompts}/permissions.d.ts +0 -0
  793. /package/dist/{agent-core/prompts → prompts}/permissions.js +0 -0
  794. /package/dist/{agent-core/tools/local → prompts}/read-context.d.ts +0 -0
  795. /package/dist/{agent-core/prompts → prompts}/resources.d.ts +0 -0
  796. /package/dist/{agent-core/prompts → prompts}/resources.js +0 -0
  797. /package/dist/{agent-core/prompts → prompts}/subagent.d.ts +0 -0
  798. /package/dist/{agent-core/prompts → prompts}/subagent.js +0 -0
  799. /package/dist/{agent-core/prompts → prompts}/workflow.d.ts +0 -0
  800. /package/dist/{agent-core/prompts → prompts}/workflow.js +0 -0
  801. /package/dist/{agent-core/runtime → runtime}/async-queue.d.ts +0 -0
  802. /package/dist/{agent-core/runtime → runtime}/async-queue.js +0 -0
  803. /package/dist/{agent-core/tools → runtime/compaction}/contracts.js +0 -0
  804. /package/dist/{agent-core/runtime → runtime}/compaction/coordinator.d.ts +0 -0
  805. /package/dist/{agent-core/runtime → runtime}/compaction/history.js +0 -0
  806. /package/dist/{agent-core/runtime → runtime}/context/contracts.d.ts +0 -0
  807. /package/dist/{agent-core/session/types.js → runtime/context/contracts.js} +0 -0
  808. /package/dist/{agent-core/runtime → runtime}/context/environment.js +0 -0
  809. /package/dist/{agent-core/tools/code-mode/engine.js → runtime/context/gc-contracts.js} +0 -0
  810. /package/dist/{agent-core/runtime → runtime}/context/gc-runtime.js +0 -0
  811. /package/dist/{agent-core/runtime → runtime}/context/normalize.js +0 -0
  812. /package/dist/{agent-core/tools/code-mode/worker.d.ts → runtime/contracts.js} +0 -0
  813. /package/dist/{agent-core/tools/runtime-context.js → runtime/events.js} +0 -0
  814. /package/dist/{agent-core/runtime → runtime}/execution-policy.d.ts +0 -0
  815. /package/dist/{agent-core/runtime → runtime}/execution-policy.js +0 -0
  816. /package/dist/{agent-core/runtime → runtime}/model-generation-timing.d.ts +0 -0
  817. /package/dist/{agent-core/runtime → runtime}/model-generation-timing.js +0 -0
  818. /package/dist/{agent-core/runtime → runtime}/model-progress.d.ts +0 -0
  819. /package/dist/{agent-core/runtime → runtime}/plan-output.d.ts +0 -0
  820. /package/dist/{agent-core/runtime → runtime}/plan-output.js +0 -0
  821. /package/dist/{agent-core/tools/public-metadata.d.ts → runtime/public-tool-metadata.d.ts} +0 -0
  822. /package/dist/{agent-core/tools/public-metadata.js → runtime/public-tool-metadata.js} +0 -0
  823. /package/dist/{agent-core/runtime → runtime}/token-budget.d.ts +0 -0
  824. /package/dist/{agent-core/runtime → runtime}/token-budget.js +0 -0
  825. /package/dist/{agent-core/tools → runtime}/wait.d.ts +0 -0
  826. /package/dist/{agent-core/sdk → sdk}/request-preparation.js +0 -0
  827. /package/dist/{agent-core/session → session}/context-gc-markup.d.ts +0 -0
  828. /package/dist/{agent-core/session → session}/context-gc-markup.js +0 -0
  829. /package/dist/{agent-core/session → session}/context-gc-replacements.js +0 -0
  830. /package/dist/{agent-core/session → session}/context-gc-subagent.js +0 -0
  831. /package/dist/{agent-core/session → session}/types.d.ts +0 -0
  832. /package/dist/{agent-core/storage → storage}/file-lock.d.ts +0 -0
  833. /package/dist/{agent-core/subagent → subagent}/model-update.d.ts +0 -0
  834. /package/dist/{agent-core/tools → tools}/agent/todo-read.js +0 -0
  835. /package/dist/{agent-core/tools → tools}/code-mode/quickjs-engine.d.ts +0 -0
  836. /package/dist/{agent-core/tools → tools}/code-mode/quickjs-engine.js +0 -0
  837. /package/dist/{agent-core/tools → tools}/code-mode/text-output.d.ts +0 -0
  838. /package/dist/{agent-core/tools → tools}/code-mode/text-output.js +0 -0
  839. /package/dist/{agent-core/tools → tools}/code-mode/worker.js +0 -0
  840. /package/dist/{agent-core/tools → tools}/file-change-diff.d.ts +0 -0
  841. /package/dist/{agent-core/tools → tools}/file-change-diff.js +0 -0
  842. /package/dist/{agent-core/tools → tools}/input-diagnostics/source-preview.d.ts +0 -0
  843. /package/dist/{agent-core/tools → tools}/input-diagnostics/source-preview.js +0 -0
  844. /package/dist/{agent-core/tools → tools}/input.d.ts +0 -0
  845. /package/dist/{agent-core/tools → tools}/input.js +0 -0
  846. /package/dist/{agent-core/tools → tools}/local/apply-patch-parser.d.ts +0 -0
  847. /package/dist/{agent-core/tools → tools}/local/image-processing.d.ts +0 -0
  848. /package/dist/{agent-core/tools → tools}/mcp/catalog.d.ts +0 -0
  849. /package/dist/{agent-core/tools → tools}/mcp/history.js +0 -0
  850. /package/dist/{agent-core/tools → tools}/registry.js +0 -0
  851. /package/dist/{agent-core/tools → tools}/runtime-resource-handles.d.ts +0 -0
  852. /package/dist/{agent-core/tools → tools}/runtime.d.ts +0 -0
  853. /package/dist/{agent-core/tools → tools}/scheduler.js +0 -0
  854. /package/dist/{agent-core/tools → tools}/shared/patch-result.d.ts +0 -0
  855. /package/dist/{agent-core/tools → tools}/shared/patch-result.js +0 -0
  856. /package/dist/{agent-core/tools → tools}/shared/path-resolver.d.ts +0 -0
@@ -1,2078 +0,0 @@
1
- import { randomUUID } from 'node:crypto';
2
- import { rollbackBoundaryIndex } from '../rollback.js';
3
- import { inlineMediaHistory } from '../inline-media.js';
4
- import { lstat, mkdir, readFile, readdir, rename, rm, stat, writeFile } from 'node:fs/promises';
5
- import { basename, join } from 'node:path';
6
- import { isDeepStrictEqual } from 'node:util';
7
- import { MarAgentError } from '../../error.js';
8
- import { isModelImageUrl } from '../../model/image.js';
9
- import { cloneCoreJson } from '../../extensions/data.js';
10
- import { acquireFileLock } from '../../storage/file-lock.js';
11
- import { todoItemsFromSnapshot } from '../../tools/agent/todo.js';
12
- import { applyCodeModeStateMutations, parseCodeModeStateMutations, restoreCodeModeState } from '../../tools/code-mode/state.js';
13
- import { contextGcBaseFromRecords, contextGcCheckpointIntervalEligible, latestValidContextGcCheckpoint, normalizeContextGcReplacements, sameContextGcBase, validateContextGcCheckpoint } from '../context-gc-checkpoint.js';
14
- import { bindToolResultResources, cleanupUnreferencedToolResources, completeToolResultResources, copyToolResultResources, readToolResultResource, toolResultResourceFiles, writeToolResultResource } from '../tool-result-resources.js';
15
- import { beginSessionStorageTransaction, isUnjournaledTransactionFile, recoverSessionStorageTransaction } from '../transaction-recovery.js';
16
- import { extensionCheckpointFromPayload, indexExtensionCheckpoint, restoreExtensionCheckpoint, updateSessionCurrentState } from './current-state.js';
17
- import { decodeSessionListCursor, encodeSessionListCursor, mergeSessionDerivedCache, normalizeSessionSource, persistSessionIndex, readSessionIndex, sessionListFilter, sessionMatchesFilter, sessionTreeIds } from './directory-index.js';
18
- import { deriveExecutionState, executionModelFromRecord, isCompactCheckpoint, isNativeUserTurn, sameResumeIndex, userMessagePreviewFromRecord } from './execution-state.js';
19
- import { forkedPayload, renameIfExists, restoreRenamedFiles, retainedSessionTitle, stageSessionSegments, stageUnreferencedImages } from './history.js';
20
- import { MAX_INPUT_IMAGES, copyGeneratedImages, generatedImageFileNames, inputImageReference, inputImageReferences, readInputImageBytes } from './images.js';
21
- import { persistResource, setResourceUrl, readResource, copyResources, resourceFiles, completeResources, recoverResources } from './resources.js';
22
- import { MAX_SEGMENT_BYTES, appendRecordBytes, readRecordPageFromTail, readRecords, readRecordsFromHead, readRecordsFromTail, repairSegmentTail, segmentNumberFromPath } from './records.js';
23
- const MAX_CONTEXTUAL_WORLD_STATE_BYTES = 8 * 1024 * 1024;
24
- const CONTEXTUAL_WORLD_STATE_FILE = 'context-world-state.json';
25
- /** SDK-owned JSONL history with per-HOME in-process sharing and cross-process file locks. */
26
- export class JsonlSessionStore {
27
- static #instances = new Map();
28
- static #opening = new Map();
29
- #shared;
30
- #maintenance = new WeakMap();
31
- #leaseClosed = false;
32
- constructor(shared) {
33
- this.#shared = shared;
34
- }
35
- static async open(home) {
36
- const root = join(home, '.mar', 'agent');
37
- const existing = JsonlSessionStore.#instances.get(root);
38
- if (existing) {
39
- existing.references++;
40
- return new JsonlSessionStore(existing);
41
- }
42
- const pending = JsonlSessionStore.#opening.get(root);
43
- if (pending) {
44
- const shared = await pending;
45
- shared.references++;
46
- return new JsonlSessionStore(shared);
47
- }
48
- const opening = JsonlSessionStore.#openExclusive(root);
49
- JsonlSessionStore.#opening.set(root, opening);
50
- try {
51
- const shared = await opening;
52
- JsonlSessionStore.#instances.set(root, shared);
53
- return new JsonlSessionStore(shared);
54
- }
55
- finally {
56
- JsonlSessionStore.#opening.delete(root);
57
- }
58
- }
59
- /** Create a missing index only without Session directories; recover journals and marked creations. */
60
- static async #openExclusive(root) {
61
- const directory = join(root, 'sessions');
62
- const path = join(directory, 'index.json');
63
- await mkdir(directory, { recursive: true });
64
- const release = await acquireFileLock(join(directory, 'index.lock'));
65
- let index;
66
- try {
67
- const disk = await readSessionIndex(path);
68
- if (disk)
69
- index = disk;
70
- else {
71
- const entries = await readdir(directory, { withFileTypes: true });
72
- if (entries.some((entry) => entry.isDirectory()))
73
- throw new MarAgentError('MAR_AGENT_SESSION_CORRUPT', 'Session index is missing.');
74
- index = { version: 1, revision: 0, sessions: [] };
75
- await persistSessionIndex(path, index);
76
- }
77
- }
78
- finally {
79
- await release();
80
- }
81
- for (const session of index.sessions) {
82
- const directory = join(root, 'sessions', session.id);
83
- let names;
84
- try {
85
- names = await readdir(directory);
86
- }
87
- catch (error) {
88
- if (error.code === 'ENOENT')
89
- continue;
90
- throw error;
91
- }
92
- if (!names.includes('storage-transaction.json') &&
93
- !names.some(isUnjournaledTransactionFile) &&
94
- !names.some((name) => /^context-world-state\.json\.\d+\.[0-9a-f-]+\.(?:rollback|clear)-backup$/u.test(name)))
95
- continue;
96
- let releaseSession;
97
- try {
98
- releaseSession = await acquireFileLock(join(directory, 'lock'), 'Session already has a writer.', 0);
99
- }
100
- catch (error) {
101
- if (error instanceof MarAgentError && error.code === 'MAR_AGENT_SESSION_LOCKED')
102
- continue;
103
- throw error;
104
- }
105
- try {
106
- // The index may have changed while waiting for the Session lock.
107
- const latest = await readSessionIndex(path);
108
- const current = latest?.sessions.find((item) => item.id === session.id);
109
- if (!current)
110
- continue;
111
- await recoverSessionStorageTransaction(directory, current.storageTransactionId);
112
- await recoverContextualWorldStateTransactions(root, current);
113
- }
114
- finally {
115
- await releaseSession();
116
- }
117
- }
118
- // A creation marker distinguishes our unpublished directories from unrelated files.
119
- for (const entry of await readdir(directory, { withFileTypes: true })) {
120
- if (!entry.isDirectory() || !/^[0-9a-f-]{36}$/iu.test(entry.name))
121
- continue;
122
- const candidate = join(directory, entry.name);
123
- const marker = join(candidate, 'publication-pending');
124
- try {
125
- if (!(await lstat(marker)).isFile())
126
- continue;
127
- }
128
- catch (error) {
129
- if (error.code === 'ENOENT')
130
- continue;
131
- throw error;
132
- }
133
- let releaseSession;
134
- try {
135
- releaseSession = await acquireFileLock(join(candidate, 'lock'), 'Session already has a writer.', 0);
136
- }
137
- catch (error) {
138
- if (error instanceof MarAgentError && error.code === 'MAR_AGENT_SESSION_LOCKED')
139
- continue;
140
- throw error;
141
- }
142
- let unpublished = false;
143
- try {
144
- const latest = await readSessionIndex(path);
145
- if (!latest)
146
- throw new MarAgentError('MAR_AGENT_SESSION_CORRUPT', 'Session index is missing.');
147
- unpublished = !latest.sessions.some((session) => session.id === entry.name);
148
- if (!unpublished)
149
- await rm(marker, { force: true });
150
- }
151
- finally {
152
- await releaseSession();
153
- }
154
- if (unpublished)
155
- await rm(candidate, { recursive: true, force: true });
156
- }
157
- return {
158
- root,
159
- index,
160
- indexOperations: Promise.resolve(),
161
- pendingSessions: new Map(),
162
- references: 1,
163
- closed: false,
164
- indexDirty: false,
165
- dirtySessionVersions: new Map(),
166
- derivedOnlyDirtySessions: new Set(),
167
- pendingPublishIds: new Set(),
168
- codeStateWrites: new Map(),
169
- recordWrites: new Map(),
170
- writerLeases: new Map(),
171
- segments: new Map(),
172
- executionModelReads: new Map(),
173
- historyPagePositions: new Map()
174
- };
175
- }
176
- /** Merge dirty metadata with disk membership; only createdIds publish locally new entries. */
177
- async #saveIndex(deletedIds, createdIds = []) {
178
- return this.#serializeIndexOperation(() => this.#commitIndex(deletedIds, createdIds));
179
- }
180
- async #serializeIndexOperation(operation) {
181
- const next = this.#shared.indexOperations.then(operation, operation);
182
- this.#shared.indexOperations = next.then(() => undefined, () => undefined);
183
- return next;
184
- }
185
- async #commitIndex(deletedIds, createdIds = []) {
186
- const release = await acquireFileLock(join(this.#shared.root, 'sessions', 'index.lock'));
187
- const path = join(this.#shared.root, 'sessions', 'index.json');
188
- try {
189
- const disk = await readSessionIndex(path);
190
- if (!disk)
191
- throw new MarAgentError('MAR_AGENT_SESSION_CORRUPT', 'Session index is missing.');
192
- const dirty = new Map(this.#shared.dirtySessionVersions);
193
- const derivedOnly = new Set(this.#shared.derivedOnlyDirtySessions);
194
- const sessions = new Map(disk.sessions.map((session) => [session.id, session]));
195
- const created = new Set(createdIds);
196
- for (const session of this.#shared.index.sessions) {
197
- const current = sessions.get(session.id);
198
- // Disk membership is authoritative: a stale in-memory snapshot cannot revive a deletion.
199
- if (created.has(session.id) || (current && dirty.has(session.id)))
200
- sessions.set(session.id, current && derivedOnly.has(session.id)
201
- ? mergeSessionDerivedCache(current, session)
202
- : structuredClone(session));
203
- }
204
- for (const deletedId of typeof deletedIds === 'string' ? [deletedIds] : (deletedIds ?? []))
205
- sessions.delete(deletedId);
206
- const updated = {
207
- version: 1,
208
- revision: createdIds.length > 0 ||
209
- deletedIds !== undefined ||
210
- [...dirty.keys()].some((id) => !derivedOnly.has(id))
211
- ? Math.max(disk.revision, this.#shared.index.revision) + 1
212
- : disk.revision,
213
- sessions: [...sessions.values()]
214
- };
215
- await persistSessionIndex(path, updated);
216
- for (const [id, version] of dirty) {
217
- // A different creation still needs its own index transaction to publish its directory.
218
- if (this.#shared.pendingPublishIds.has(id) && !created.has(id))
219
- continue;
220
- if (this.#shared.dirtySessionVersions.get(id) === version) {
221
- this.#shared.dirtySessionVersions.delete(id);
222
- this.#shared.derivedOnlyDirtySessions.delete(id);
223
- }
224
- }
225
- for (const id of created)
226
- this.#shared.pendingPublishIds.delete(id);
227
- const pending = this.#shared.index.sessions.filter((session) => this.#shared.dirtySessionVersions.has(session.id) &&
228
- (sessions.has(session.id) || this.#shared.pendingPublishIds.has(session.id)));
229
- const replacements = new Map(pending.map((session) => [session.id, session]));
230
- const published = new Set(updated.sessions.map((session) => session.id));
231
- this.#shared.index = {
232
- ...updated,
233
- sessions: [
234
- ...updated.sessions.map((session) => replacements.get(session.id) ?? session),
235
- ...pending.filter((session) => !published.has(session.id))
236
- ]
237
- };
238
- this.#shared.indexDirty = this.#shared.dirtySessionVersions.size > 0;
239
- }
240
- finally {
241
- await release();
242
- }
243
- }
244
- async #refreshIndex() {
245
- return this.#serializeIndexOperation(() => this.#readCurrentIndex());
246
- }
247
- async #readCurrentIndex() {
248
- const disk = await readSessionIndex(join(this.#shared.root, 'sessions', 'index.json'));
249
- if (!disk)
250
- throw new MarAgentError('MAR_AGENT_SESSION_CORRUPT', 'Session index is missing.');
251
- // A local unflushed revision may exceed another writer's committed revision.
252
- // Always refresh membership from disk, then overlay only our pending changes.
253
- const local = new Map(this.#shared.index.sessions.map((session) => [session.id, session]));
254
- const published = new Set(disk.sessions.map((session) => session.id));
255
- this.#shared.index = {
256
- ...disk,
257
- revision: this.#shared.indexDirty || this.#shared.pendingPublishIds.size > 0
258
- ? Math.max(disk.revision, this.#shared.index.revision)
259
- : disk.revision,
260
- sessions: disk.sessions
261
- .map((session) => {
262
- const current = local.get(session.id);
263
- if (!current || !this.#shared.dirtySessionVersions.has(session.id))
264
- return session;
265
- return this.#shared.derivedOnlyDirtySessions.has(session.id)
266
- ? mergeSessionDerivedCache(session, current)
267
- : current;
268
- })
269
- .concat(this.#shared.index.sessions.filter((session) => this.#shared.pendingPublishIds.has(session.id) && !published.has(session.id)))
270
- };
271
- }
272
- /** Hold the new Session lock and mark its directory until JSONL and index publication finish. */
273
- async #beginUnpublishedSession(sessionId) {
274
- const directory = join(this.#shared.root, 'sessions', sessionId);
275
- await mkdir(directory);
276
- const release = await acquireFileLock(join(directory, 'lock'), 'Session already has a writer.', 0);
277
- try {
278
- await writeFile(join(directory, 'publication-pending'), '1', {
279
- mode: 0o600,
280
- flag: 'wx',
281
- flush: true
282
- });
283
- }
284
- catch (error) {
285
- await release();
286
- await rm(directory, { recursive: true, force: true });
287
- throw error;
288
- }
289
- return { directory, release };
290
- }
291
- async createSession(input) {
292
- this.#assertOpen();
293
- const source = normalizeSessionSource(input.source);
294
- if (source.type !== 'subagent')
295
- return this.#createSession(input, source);
296
- // Publish under the parent's existing serial domain so tree admission cannot miss a child.
297
- return this.#serializeRecordOperation(source.parentSessionId, async () => {
298
- this.#assertOpen();
299
- if (this.#shared.writerLeases.get(source.parentSessionId)?.maintenance)
300
- throw new MarAgentError('MAR_AGENT_SESSION_LOCKED', 'Session is under maintenance.');
301
- await this.getSession(source.parentSessionId);
302
- return this.#createSession(input, source);
303
- });
304
- }
305
- /** Append the durable creation record before making this Session visible in the index. */
306
- async #createSession(input, source) {
307
- const id = randomUUID();
308
- const now = new Date().toISOString();
309
- const meta = {
310
- id,
311
- title: input.title ?? 'New session',
312
- workspace: input.workspace,
313
- createdAt: now,
314
- lastActivityAt: now,
315
- source,
316
- nextSequence: 1,
317
- automaticTitlePending: input.title === undefined,
318
- resume: {
319
- version: 1,
320
- userTurns: 0,
321
- todoRevision: 0,
322
- executionModelIndexed: true,
323
- firstUserMessageIndexed: true
324
- },
325
- segments: []
326
- };
327
- const publication = await this.#beginUnpublishedSession(id);
328
- this.#shared.segments.set(id, 1);
329
- this.#shared.pendingSessions.set(id, meta);
330
- let discard = false;
331
- try {
332
- try {
333
- await this.append(id, {
334
- type: 'session.created',
335
- payload: {
336
- title: meta.title,
337
- workspace: meta.workspace,
338
- automaticTitle: input.title === undefined,
339
- source: meta.source
340
- }
341
- });
342
- }
343
- catch (error) {
344
- this.#shared.pendingSessions.delete(id);
345
- this.#shared.segments.delete(id);
346
- discard = true;
347
- throw error;
348
- }
349
- this.#shared.pendingSessions.delete(id);
350
- this.#shared.index.sessions.unshift(meta);
351
- this.#shared.pendingPublishIds.add(id);
352
- this.#markIndexDirty(id);
353
- try {
354
- await this.#saveIndex(undefined, [id]);
355
- }
356
- catch (error) {
357
- // A failed lock release can follow a committed index rename; do not unpublish that Session.
358
- // If the index cannot be read, leave the disk marker for recovery and keep the original error.
359
- const disk = await readSessionIndex(join(this.#shared.root, 'sessions', 'index.json')).catch(() => undefined);
360
- if (disk?.sessions.some((session) => session.id === id)) {
361
- this.#shared.pendingPublishIds.delete(id);
362
- this.#shared.dirtySessionVersions.delete(id);
363
- this.#shared.indexDirty = this.#shared.dirtySessionVersions.size > 0;
364
- }
365
- else {
366
- // Keep the marker until disk membership can be checked during recovery.
367
- this.#shared.index.sessions = this.#shared.index.sessions.filter((item) => item.id !== id);
368
- this.#shared.segments.delete(id);
369
- this.#shared.pendingPublishIds.delete(id);
370
- this.#shared.dirtySessionVersions.delete(id);
371
- this.#shared.indexDirty = this.#shared.dirtySessionVersions.size > 0;
372
- throw error;
373
- }
374
- }
375
- await rm(join(publication.directory, 'publication-pending'), { force: true });
376
- return meta;
377
- }
378
- finally {
379
- try {
380
- await publication.release();
381
- }
382
- finally {
383
- if (discard)
384
- await rm(publication.directory, { recursive: true, force: true });
385
- }
386
- }
387
- }
388
- #sessionDirectory(sessionId) {
389
- this.#assertOpen();
390
- if (!this.#shared.index.sessions.some((session) => session.id === sessionId) &&
391
- !this.#shared.pendingSessions.has(sessionId))
392
- throw new MarAgentError('MAR_AGENT_SESSION_NOT_FOUND', 'Session was not found.');
393
- return join(this.#shared.root, 'sessions', sessionId);
394
- }
395
- async readContextualWorldState(sessionId) {
396
- const path = join(this.#sessionDirectory(sessionId), CONTEXTUAL_WORLD_STATE_FILE);
397
- try {
398
- const envelope = JSON.parse(await readFile(path, 'utf8'));
399
- const meta = this.#shared.index.sessions.find((item) => item.id === sessionId);
400
- if (envelope.version !== 1 ||
401
- !Number.isSafeInteger(envelope.historySequence) ||
402
- envelope.historySequence < 1 ||
403
- meta === undefined ||
404
- envelope.historySequence >= meta.nextSequence)
405
- return undefined;
406
- return envelope.state;
407
- }
408
- catch {
409
- return undefined;
410
- }
411
- }
412
- async writeContextualWorldState(sessionId, state) {
413
- const directory = this.#sessionDirectory(sessionId);
414
- const meta = this.#shared.index.sessions.find((item) => item.id === sessionId);
415
- if (!meta)
416
- throw new MarAgentError('MAR_AGENT_SESSION_NOT_FOUND', 'Session was not found.');
417
- const path = join(directory, CONTEXTUAL_WORLD_STATE_FILE);
418
- const temporary = `${path}.${randomUUID()}.tmp`;
419
- const serialized = JSON.stringify({
420
- version: 1,
421
- historySequence: meta.nextSequence - 1,
422
- state
423
- });
424
- if (Buffer.byteLength(serialized) > MAX_CONTEXTUAL_WORLD_STATE_BYTES)
425
- throw new MarAgentError('MAR_AGENT_HOST_LIMIT_EXCEEDED', 'Contextual world state exceeds the storage limit.');
426
- try {
427
- await writeFile(temporary, serialized, { mode: 0o600, flag: 'wx' });
428
- await rename(temporary, path);
429
- }
430
- finally {
431
- await rm(temporary, { force: true });
432
- }
433
- }
434
- /** Mark each image pending before publication; turn.user or lease recovery resolves ownership. */
435
- async persistInputImages(sessionId, images) {
436
- this.#assertOpen();
437
- if (images.length === 0)
438
- return [];
439
- if (images.length > MAX_INPUT_IMAGES)
440
- throw new MarAgentError('MAR_AGENT_HOST_LIMIT_EXCEEDED', 'Too many image inputs were provided.');
441
- const resources = [];
442
- let total = 0;
443
- for (const image of images) {
444
- if ((image.url !== undefined && !isModelImageUrl(image.url)) ||
445
- (image.urlExpiresAt !== undefined &&
446
- (!Number.isSafeInteger(image.urlExpiresAt) ||
447
- image.urlExpiresAt <= 0 ||
448
- image.url === undefined)))
449
- throw new MarAgentError('MAR_AGENT_SESSION_INPUT_INVALID', 'Image model URL is invalid.');
450
- let resource = await this.persistResource(sessionId, image);
451
- if (image.url !== undefined && image.urlExpiresAt !== undefined)
452
- resource = await this.setResourceUrl(sessionId, resource.resourceId, {
453
- url: image.url,
454
- urlExpiresAt: image.urlExpiresAt
455
- });
456
- total += resource.byteSize;
457
- if (resource.byteSize > 5 * 1024 * 1024 || total > 10 * 1024 * 1024)
458
- throw new MarAgentError('MAR_AGENT_HOST_LIMIT_EXCEEDED', 'Image input exceeds the supported size limit.');
459
- resources.push({
460
- ...resource,
461
- resourceInputVersion: 1,
462
- name: image.name,
463
- fileName: `${resource.resourceId}.bin`
464
- });
465
- }
466
- return resources;
467
- }
468
- async persistResource(sessionId, image) {
469
- this.#assertOpen();
470
- return this.#serializeRecordOperation(sessionId, () => persistResource(join(this.#sessionDirectory(sessionId), 'resources'), image));
471
- }
472
- async setResourceUrl(sessionId, resourceId, published) {
473
- this.#assertOpen();
474
- return this.#serializeRecordOperation(sessionId, () => setResourceUrl(join(this.#sessionDirectory(sessionId), 'resources'), resourceId, published));
475
- }
476
- async readResource(sessionId, resourceId) {
477
- this.#assertOpen();
478
- const directory = join(this.#sessionDirectory(sessionId), 'resources');
479
- if (!/^[a-f0-9]{64}$/u.test(resourceId))
480
- return undefined;
481
- return this.#serializeRecordOperation(sessionId, async () => {
482
- let pending = false;
483
- try {
484
- await lstat(join(directory, `.${resourceId}.pending`));
485
- pending = true;
486
- }
487
- catch (cause) {
488
- if (cause.code !== 'ENOENT')
489
- throw new MarAgentError('MAR_AGENT_IMAGE_UNAVAILABLE', 'Session image resource is unavailable.', {
490
- cause
491
- });
492
- }
493
- if (pending &&
494
- (this.#shared.writerLeases.get(sessionId)?.appendFailure !== undefined ||
495
- !resourceFiles(await this.#readRecords(sessionId)).has(`${resourceId}.bin`)))
496
- return undefined;
497
- return readResource(directory, resourceId);
498
- });
499
- }
500
- async writeToolResultResource(sessionId, text) {
501
- this.#assertOpen();
502
- if (!this.#shared.index.sessions.some((item) => item.id === sessionId))
503
- throw new MarAgentError('MAR_AGENT_SESSION_NOT_FOUND', 'Session was not found.');
504
- return writeToolResultResource(this.#sessionDirectory(sessionId), text);
505
- }
506
- async readToolResultResource(sessionId, input) {
507
- this.#assertOpen();
508
- await this.#refreshIndex();
509
- if (!this.#shared.index.sessions.some((item) => item.id === sessionId))
510
- throw new MarAgentError('MAR_AGENT_SESSION_NOT_FOUND', 'Session was not found.');
511
- return readToolResultResource(this.#sessionDirectory(sessionId), sessionId, input, async (sequence) => {
512
- await this.#refreshIndex();
513
- return (await this.readPage(sessionId, { beforeSequence: sequence + 1, limit: 1 })).records.find((record) => record.sequence === sequence);
514
- });
515
- }
516
- async readInputImages(sessionId, value) {
517
- this.#assertOpen();
518
- const references = inputImageReferences(Array.isArray(value) ? value.filter((item) => item?.resourceInputVersion === 1) : undefined);
519
- if (references.length === 0)
520
- return [];
521
- const images = [];
522
- for (const reference of references) {
523
- if (reference.resourceId === undefined)
524
- throw new MarAgentError('MAR_AGENT_SESSION_CORRUPT', 'Session resource identity is missing.');
525
- images.push({
526
- resourceInputVersion: 1,
527
- mimeType: reference.mimeType,
528
- byteSize: reference.byteSize,
529
- resourceId: reference.resourceId,
530
- ...(reference.url === undefined ? {} : { url: reference.url }),
531
- ...(reference.urlExpiresAt === undefined ? {} : { urlExpiresAt: reference.urlExpiresAt })
532
- });
533
- }
534
- return images;
535
- }
536
- async readInputImage(sessionId, input) {
537
- this.#assertOpen();
538
- if (!Number.isSafeInteger(input.sequence) ||
539
- input.sequence < 1 ||
540
- input.sequence >= Number.MAX_SAFE_INTEGER ||
541
- !Number.isSafeInteger(input.imageIndex) ||
542
- input.imageIndex < 0)
543
- return undefined;
544
- const page = await this.readPage(sessionId, {
545
- limit: 1,
546
- beforeSequence: input.sequence + 1
547
- });
548
- const record = page.records[0];
549
- if (record?.sequence !== input.sequence ||
550
- record.type !== 'turn.user' ||
551
- !isObject(record.payload))
552
- return undefined;
553
- if (!Array.isArray(record.payload.images) || input.imageIndex >= record.payload.images.length)
554
- return undefined;
555
- if (record.payload.images[input.imageIndex]?.resourceInputVersion !== 1)
556
- return undefined;
557
- const reference = inputImageReference(record.payload.images[input.imageIndex]);
558
- if (reference === undefined)
559
- return undefined;
560
- if (reference.resourceId === undefined)
561
- throw new MarAgentError('MAR_AGENT_SESSION_CORRUPT', 'Session resource identity is missing.');
562
- const data = await readInputImageBytes(join(this.#sessionDirectory(sessionId), 'resources'), reference);
563
- return {
564
- name: reference.name,
565
- mimeType: reference.mimeType,
566
- byteSize: reference.byteSize,
567
- fileName: reference.fileName,
568
- sha256: reference.sha256,
569
- dataBase64: data.toString('base64')
570
- };
571
- }
572
- async forkSession(sourceSessionId, input) {
573
- this.#assertOpen();
574
- const release = await this.acquireSessionLease(sourceSessionId);
575
- try {
576
- const source = this.#shared.index.sessions.find((item) => item.id === sourceSessionId);
577
- if (!source)
578
- throw new MarAgentError('MAR_AGENT_SESSION_NOT_FOUND', 'Session was not found.');
579
- const records = await this.read(sourceSessionId);
580
- const boundaryIndex = input.boundaryTurnId === null
581
- ? -1
582
- : records.findLastIndex((record) => record.turnId === input.boundaryTurnId);
583
- if (input.boundaryTurnId !== null && boundaryIndex < 0)
584
- throw new MarAgentError('MAR_AGENT_REWIND_TARGET_INVALID', 'Session rewind target was not found.');
585
- const createdAt = new Date().toISOString();
586
- const target = {
587
- id: randomUUID(),
588
- title: input.title,
589
- workspace: source.workspace,
590
- createdAt,
591
- lastActivityAt: createdAt,
592
- source: { type: 'user' },
593
- nextSequence: 1,
594
- automaticTitlePending: false,
595
- resume: {
596
- version: 1,
597
- userTurns: 0,
598
- todoRevision: 0,
599
- executionModelIndexed: true,
600
- firstUserMessageIndexed: true
601
- },
602
- segments: []
603
- };
604
- const publication = await this.#beginUnpublishedSession(target.id);
605
- this.#shared.segments.set(target.id, 1);
606
- this.#shared.pendingSessions.set(target.id, target);
607
- let discard = false;
608
- try {
609
- const copied = [
610
- {
611
- schemaVersion: 1,
612
- recordId: randomUUID(),
613
- sequence: 1,
614
- timestamp: createdAt,
615
- sessionId: target.id,
616
- type: 'session.created',
617
- payload: {
618
- title: target.title,
619
- workspace: target.workspace,
620
- automaticTitle: false,
621
- source: target.source
622
- }
623
- }
624
- ];
625
- const retained = input.boundaryTurnId === null ? [] : records.slice(1, boundaryIndex + 1);
626
- const inlineState = inlineMediaHistory(retained).state;
627
- const stateAnchor = inlineState &&
628
- retained.findLast((record) => record.type === 'resource.window' || record.type === 'compact.completed');
629
- const forkIdentities = new Map();
630
- for (const record of retained) {
631
- if (record.type === 'context.gc.completed' || record.type === 'responses.continuation')
632
- continue;
633
- const identity = { recordId: randomUUID(), sequence: copied.length + 1 };
634
- forkIdentities.set(record.recordId, identity);
635
- copied.push({
636
- schemaVersion: 1,
637
- ...identity,
638
- sessionId: target.id,
639
- type: record.type,
640
- payload: forkedPayload(record.type, record === stateAnchor
641
- ? record.type === 'resource.window'
642
- ? inlineState
643
- : {
644
- ...record.payload,
645
- inlineMediaState: inlineState
646
- }
647
- : record.payload, sourceSessionId, target.id, input.title, forkIdentities),
648
- ...(record.executionId === undefined ? {} : { executionId: record.executionId }),
649
- ...(record.turnId === undefined ? {} : { turnId: record.turnId }),
650
- timestamp: record.timestamp
651
- });
652
- }
653
- // A fork is unpublished until every segment and referenced image is durable.
654
- const staged = await stageSessionSegments(this.#sessionDirectory(target.id), copied, 'fork');
655
- for (const file of staged.files)
656
- await rename(file.temporaryPath, file.path);
657
- target.segments = staged.segments;
658
- target.nextSequence = copied.length + 1;
659
- this.#shared.segments.set(target.id, staged.segments.length);
660
- for (const record of copied)
661
- this.#applyRecordToResumeIndex(target, record);
662
- await copyToolResultResources(this.#sessionDirectory(sourceSessionId), this.#sessionDirectory(target.id), copied);
663
- await copyGeneratedImages(this.#sessionDirectory(sourceSessionId), this.#sessionDirectory(target.id), generatedImageFileNames(retained));
664
- await copyResources(this.#sessionDirectory(sourceSessionId), this.#sessionDirectory(target.id), retained);
665
- target.lastActivityAt = target.createdAt;
666
- this.#shared.pendingSessions.delete(target.id);
667
- this.#shared.index = {
668
- version: 1,
669
- revision: this.#shared.index.revision + 1,
670
- sessions: [target, ...this.#shared.index.sessions]
671
- };
672
- this.#shared.pendingPublishIds.add(target.id);
673
- this.#markIndexDirty(target.id);
674
- await this.#saveIndex(undefined, [target.id]);
675
- await rm(join(publication.directory, 'publication-pending'), { force: true });
676
- return {
677
- id: target.id,
678
- title: target.title,
679
- workspace: target.workspace,
680
- createdAt: target.createdAt,
681
- lastActivityAt: target.createdAt,
682
- source: target.source
683
- };
684
- }
685
- catch (error) {
686
- this.#shared.pendingSessions.delete(target.id);
687
- const disk = await readSessionIndex(join(this.#shared.root, 'sessions', 'index.json'));
688
- if (disk?.sessions.some((session) => session.id === target.id))
689
- return {
690
- id: target.id,
691
- title: target.title,
692
- workspace: target.workspace,
693
- createdAt: target.createdAt,
694
- lastActivityAt: target.createdAt,
695
- source: target.source
696
- };
697
- const publishedIndex = this.#shared.index.sessions.findIndex((item) => item.id === target.id);
698
- if (publishedIndex >= 0) {
699
- this.#shared.index.sessions.splice(publishedIndex, 1);
700
- this.#shared.index.revision++;
701
- this.#shared.pendingPublishIds.delete(target.id);
702
- this.#shared.dirtySessionVersions.delete(target.id);
703
- this.#shared.indexDirty = this.#shared.dirtySessionVersions.size > 0;
704
- }
705
- this.#shared.segments.delete(target.id);
706
- discard = true;
707
- throw error;
708
- }
709
- finally {
710
- try {
711
- await publication.release();
712
- }
713
- finally {
714
- if (discard)
715
- await rm(publication.directory, { recursive: true, force: true });
716
- }
717
- }
718
- }
719
- finally {
720
- await release();
721
- }
722
- }
723
- /** Replace history under a journal; the indexed transaction ID decides the commit side. */
724
- async rollbackSession(sessionId, input) {
725
- this.#assertOpen();
726
- const release = await this.acquireSessionLease(sessionId);
727
- try {
728
- const meta = this.#shared.index.sessions.find((item) => item.id === sessionId);
729
- if (!meta)
730
- throw new MarAgentError('MAR_AGENT_SESSION_NOT_FOUND', 'Session was not found.');
731
- const records = await this.read(sessionId);
732
- if (records[0]?.type !== 'session.created')
733
- throw new MarAgentError('MAR_AGENT_SESSION_CORRUPT', 'Session history is corrupt.');
734
- const boundaryIndex = rollbackBoundaryIndex(records, input);
735
- const retained = records
736
- .slice(0, boundaryIndex + 1)
737
- .filter((record) => record.type !== 'responses.continuation');
738
- return await this.#replaceHistory(meta, retained, { kind: 'rollback' });
739
- }
740
- finally {
741
- await release();
742
- }
743
- }
744
- async updateTitle(sessionId, title, input = {}, owner) {
745
- this.#assertOpen();
746
- const normalized = title.trim();
747
- if (!normalized)
748
- throw new MarAgentError('MAR_AGENT_TOOL_INPUT_INVALID', 'Session title is required.');
749
- const release = await this.acquireSessionLease(sessionId, owner);
750
- try {
751
- const meta = this.#shared.index.sessions.find((item) => item.id === sessionId);
752
- if (input.expectedTitle !== undefined && meta.title !== input.expectedTitle)
753
- return false;
754
- if (input.automatic || input.executionId !== undefined) {
755
- const records = await this.read(sessionId);
756
- const latestTitle = records.findLast((record) => record.type === 'session.title.updated');
757
- if (input.automatic &&
758
- (records[0]?.payload?.automaticTitle !== true ||
759
- latestTitle?.payload?.automatic === false))
760
- return false;
761
- if (input.executionId !== undefined &&
762
- records.findLast((record) => record.type === 'turn.user')?.executionId !==
763
- input.executionId)
764
- return false;
765
- }
766
- await this.append(sessionId, {
767
- type: 'session.title.updated',
768
- payload: { title: normalized, automatic: input.automatic === true },
769
- ...(input.executionId ? { executionId: input.executionId } : {}),
770
- ...(input.turnId ? { turnId: input.turnId } : {})
771
- });
772
- return true;
773
- }
774
- finally {
775
- await release();
776
- }
777
- }
778
- /** Reset history with the same recovery journal while preserving the Session identity. */
779
- async clearSession(sessionId, maintenance) {
780
- this.#assertOpen();
781
- const holding = maintenance ?? (await this.acquireSessionMaintenance(sessionId, 'clear'));
782
- this.#assertMaintenance(sessionId, 'clear', holding);
783
- let failed = false;
784
- try {
785
- const meta = this.#shared.index.sessions.find((item) => item.id === sessionId);
786
- if (!meta)
787
- throw new MarAgentError('MAR_AGENT_SESSION_NOT_FOUND', 'Session was not found.');
788
- const records = await this.read(sessionId);
789
- if (records[0]?.type !== 'session.created')
790
- throw new MarAgentError('MAR_AGENT_SESSION_CORRUPT', 'Session history is corrupt.');
791
- const clearedAt = new Date().toISOString();
792
- const retained = [
793
- {
794
- schemaVersion: 1,
795
- recordId: randomUUID(),
796
- sequence: 1,
797
- timestamp: meta.createdAt,
798
- sessionId,
799
- type: 'session.created',
800
- payload: {
801
- title: meta.title,
802
- workspace: meta.workspace,
803
- automaticTitle: meta.automaticTitlePending === true,
804
- source: normalizeSessionSource(meta.source)
805
- }
806
- }
807
- ];
808
- return await this.#replaceHistory(meta, retained, { kind: 'clear', clearedAt });
809
- }
810
- catch (error) {
811
- failed = true;
812
- throw error;
813
- }
814
- finally {
815
- if (!maintenance) {
816
- const releasing = holding.release();
817
- if (failed)
818
- await releasing.catch(() => undefined);
819
- else
820
- await releasing;
821
- }
822
- }
823
- }
824
- /** Called only while rollback or clear holds the maintenance lease. */
825
- async #replaceHistory(meta, retained, operation) {
826
- const sessionId = meta.id;
827
- const staged = await stageSessionSegments(this.#sessionDirectory(sessionId), retained);
828
- const transactionId = randomUUID();
829
- const targetNextSequence = operation.kind === 'clear' ? 2 : (retained.at(-1)?.sequence ?? 0) + 1;
830
- const contextualWorldStatePath = join(this.#sessionDirectory(sessionId), CONTEXTUAL_WORLD_STATE_FILE);
831
- const contextualWorldStateBackup = `${contextualWorldStatePath}.${targetNextSequence}.${transactionId}.${operation.kind}-backup`;
832
- let contextualWorldStateStaged = false;
833
- let generatedTrash = [];
834
- let resourceTrash = [];
835
- const originalMeta = structuredClone(meta);
836
- const originalIndexRevision = this.#shared.index.revision;
837
- const originalSegment = this.#shared.segments.get(sessionId);
838
- const originalPaths = await this.#segmentPaths(sessionId);
839
- const backups = originalPaths.map((path) => ({
840
- path,
841
- backup: `${path}.${transactionId}.${operation.kind}-backup`
842
- }));
843
- const transaction = {
844
- version: 1,
845
- id: transactionId,
846
- kind: operation.kind,
847
- originalSegments: originalPaths.map((path) => basename(path)),
848
- stagedSegments: staged.files.map((item) => ({
849
- path: basename(item.path),
850
- temporary: basename(item.temporaryPath)
851
- })),
852
- sidecarBackup: basename(contextualWorldStateBackup)
853
- };
854
- const installedPaths = [];
855
- let committed = false;
856
- try {
857
- await beginSessionStorageTransaction(this.#sessionDirectory(sessionId), transaction);
858
- contextualWorldStateStaged = await renameIfExists(contextualWorldStatePath, contextualWorldStateBackup);
859
- generatedTrash = await stageUnreferencedImages(this.#sessionDirectory(sessionId), 'generated_images', operation.kind === 'rollback' ? new Set(generatedImageFileNames(retained)) : new Set(), transactionId);
860
- resourceTrash.push(...(await stageUnreferencedImages(this.#sessionDirectory(sessionId), 'resources', operation.kind === 'rollback' ? resourceFiles(retained) : new Set(), transactionId)), ...(await stageUnreferencedImages(this.#sessionDirectory(sessionId), 'tool_results', operation.kind === 'rollback' ? toolResultResourceFiles(retained) : new Set(), transactionId)));
861
- for (const item of backups)
862
- await rename(item.path, item.backup);
863
- for (const item of staged.files) {
864
- await rename(item.temporaryPath, item.path);
865
- installedPaths.push(item.path);
866
- }
867
- if (operation.kind === 'rollback') {
868
- const state = deriveExecutionState(retained);
869
- const completedAt = new Date().toISOString();
870
- meta.title = retainedSessionTitle(retained, meta.title);
871
- meta.lastActivityAt = completedAt;
872
- meta.nextSequence = targetNextSequence;
873
- meta.storageTransactionId = transactionId;
874
- meta.automaticTitlePending = state.automaticTitlePending;
875
- meta.resume = state.resume;
876
- }
877
- else {
878
- meta.lastActivityAt = operation.clearedAt;
879
- meta.nextSequence = targetNextSequence;
880
- meta.storageTransactionId = transactionId;
881
- meta.resume = { version: 1, userTurns: 0, todoRevision: 0, firstUserMessageIndexed: true };
882
- }
883
- meta.segments = staged.segments;
884
- this.#shared.segments.set(sessionId, operation.kind === 'clear' ? 1 : (staged.segments.at(-1)?.number ?? 1));
885
- this.#shared.index.revision++;
886
- this.#markIndexDirty(sessionId);
887
- await this.#saveIndex();
888
- committed = true;
889
- await recoverSessionStorageTransaction(this.#sessionDirectory(sessionId), transactionId);
890
- return {
891
- id: meta.id,
892
- title: meta.title,
893
- workspace: meta.workspace,
894
- createdAt: meta.createdAt,
895
- lastActivityAt: meta.lastActivityAt,
896
- source: normalizeSessionSource(meta.source)
897
- };
898
- }
899
- catch (error) {
900
- if (!committed) {
901
- committed = await this.#storageTransactionCommitted(sessionId, transactionId);
902
- if (committed) {
903
- this.#shared.dirtySessionVersions.delete(sessionId);
904
- this.#shared.indexDirty = this.#shared.dirtySessionVersions.size > 0;
905
- await recoverSessionStorageTransaction(this.#sessionDirectory(sessionId), transactionId);
906
- }
907
- }
908
- if (!committed) {
909
- await Promise.all(installedPaths.map((path) => rm(path, { force: true }))).catch(() => undefined);
910
- await restoreRenamedFiles(backups.map((item) => ({ from: item.backup, to: item.path })));
911
- if (contextualWorldStateStaged)
912
- await restoreRenamedFiles([
913
- { from: contextualWorldStateBackup, to: contextualWorldStatePath }
914
- ]);
915
- await restoreRenamedFiles([...generatedTrash, ...resourceTrash]);
916
- restoreSessionMeta(meta, originalMeta);
917
- this.#shared.index.revision = originalIndexRevision;
918
- if (originalSegment === undefined)
919
- this.#shared.segments.delete(sessionId);
920
- else
921
- this.#shared.segments.set(sessionId, originalSegment);
922
- this.#markIndexDirty(sessionId);
923
- await recoverSessionStorageTransaction(this.#sessionDirectory(sessionId), originalMeta.storageTransactionId);
924
- }
925
- throw error;
926
- }
927
- finally {
928
- await Promise.all(staged.files.map((item) => rm(item.temporaryPath, { force: true }))).catch(() => undefined);
929
- }
930
- }
931
- async getSession(sessionId) {
932
- this.#assertOpen();
933
- await this.#refreshIndex();
934
- const meta = this.#shared.index.sessions.find((item) => item.id === sessionId);
935
- if (!meta)
936
- throw new MarAgentError('MAR_AGENT_SESSION_NOT_FOUND', 'Session was not found.');
937
- return {
938
- id: meta.id,
939
- title: meta.title,
940
- workspace: meta.workspace,
941
- createdAt: meta.createdAt,
942
- lastActivityAt: meta.lastActivityAt,
943
- source: normalizeSessionSource(meta.source),
944
- automaticTitlePending: meta.automaticTitlePending === true
945
- };
946
- }
947
- /** Serialize physical writes and honor cancellation before entering the writer. */
948
- async append(sessionId, input, options = {}) {
949
- this.#assertOpen();
950
- options.signal?.throwIfAborted();
951
- return this.#serializeRecordOperation(sessionId, () => {
952
- options.signal?.throwIfAborted();
953
- return this.#appendRecord(sessionId, input);
954
- });
955
- }
956
- async #serializeRecordOperation(sessionId, action) {
957
- const operation = (this.#shared.recordWrites.get(sessionId) ?? Promise.resolve())
958
- .catch(() => undefined)
959
- .then(action);
960
- this.#shared.recordWrites.set(sessionId, operation);
961
- try {
962
- return await operation;
963
- }
964
- finally {
965
- if (this.#shared.recordWrites.get(sessionId) === operation)
966
- this.#shared.recordWrites.delete(sessionId);
967
- }
968
- }
969
- async #appendRecord(sessionId, input) {
970
- this.#assertOpen();
971
- const writer = this.#shared.writerLeases.get(sessionId);
972
- if (writer?.appendFailure)
973
- throw writer.appendFailure.error;
974
- const before = this.#shared.index.sessions.find((item) => item.id === sessionId) ??
975
- this.#shared.pendingSessions.get(sessionId);
976
- if (!before)
977
- throw new MarAgentError('MAR_AGENT_SESSION_NOT_FOUND', 'Session was not found.');
978
- const published = !this.#shared.pendingSessions.has(sessionId);
979
- const record = {
980
- schemaVersion: 1,
981
- recordId: randomUUID(),
982
- sequence: before.nextSequence,
983
- timestamp: input.timestamp ?? new Date().toISOString(),
984
- sessionId,
985
- ...(input.executionId ? { executionId: input.executionId } : {}),
986
- ...(input.turnId ? { turnId: input.turnId } : {}),
987
- type: input.type,
988
- payload: input.payload
989
- };
990
- JSON.stringify(record); // Reject malformed payloads before binding resources.
991
- await bindToolResultResources(this.#sessionDirectory(sessionId), record, (sequence) => this.#readRecordAtSequence(before, sequence), true);
992
- const serialized = `${JSON.stringify(record)}\n`;
993
- let segment = await this.#currentSegment(sessionId);
994
- let path = this.#segmentPath(sessionId, segment);
995
- try {
996
- const current = await stat(path);
997
- if (current.size > 0 && current.size + Buffer.byteLength(serialized) > MAX_SEGMENT_BYTES) {
998
- segment += 1;
999
- this.#shared.segments.set(sessionId, segment);
1000
- path = this.#segmentPath(sessionId, segment);
1001
- }
1002
- }
1003
- catch {
1004
- // The first append creates the first segment.
1005
- }
1006
- try {
1007
- await appendRecordBytes(path, serialized, (error) => {
1008
- if (writer)
1009
- writer.appendFailure = { error };
1010
- });
1011
- }
1012
- catch (error) {
1013
- // A failed write/sync/close can leave a complete record on disk.
1014
- const current = this.#shared.index.sessions.find((item) => item.id === sessionId) ?? before;
1015
- if (current.resume?.userTurns !== undefined) {
1016
- delete current.resume.userTurns;
1017
- if (published)
1018
- this.#markIndexDirty(sessionId);
1019
- }
1020
- const lease = this.#shared.writerLeases.get(sessionId);
1021
- if (lease) {
1022
- delete lease.codeState;
1023
- delete lease.extensionCheckpoints;
1024
- }
1025
- throw error;
1026
- }
1027
- // Index refreshes and commits can replace metadata during file I/O. Publish all
1028
- // durable-record metadata onto the current entry without another await boundary.
1029
- const meta = this.#shared.index.sessions.find((item) => item.id === sessionId) ??
1030
- this.#shared.pendingSessions.get(sessionId);
1031
- if (!meta)
1032
- throw new MarAgentError('MAR_AGENT_SESSION_NOT_FOUND', 'Session was not found.');
1033
- meta.nextSequence = record.sequence + 1;
1034
- const segmentMetadata = meta.segments ?? (meta.segments = []);
1035
- const known = segmentMetadata.find((item) => item.number === segment);
1036
- if (known) {
1037
- known.lastSequence = record.sequence;
1038
- known.bytes += Buffer.byteLength(serialized);
1039
- }
1040
- else
1041
- segmentMetadata.push({
1042
- number: segment,
1043
- firstSequence: record.sequence,
1044
- lastSequence: record.sequence,
1045
- bytes: Buffer.byteLength(serialized)
1046
- });
1047
- meta.lastActivityAt = record.timestamp;
1048
- this.#applyRecordToResumeIndex(meta, record);
1049
- if (published) {
1050
- this.#shared.index.revision++;
1051
- this.#markIndexDirty(sessionId);
1052
- }
1053
- updateSessionCurrentState(this.#shared.writerLeases.get(sessionId), record.type, serialized);
1054
- await completeToolResultResources(this.#sessionDirectory(sessionId), record);
1055
- await completeResources(join(this.#sessionDirectory(sessionId), 'resources'), record);
1056
- return record;
1057
- }
1058
- async read(sessionId) {
1059
- return this.#serializeRecordOperation(sessionId, () => this.#readRecords(sessionId));
1060
- }
1061
- async #readRecords(sessionId) {
1062
- this.#assertOpen();
1063
- try {
1064
- const records = [];
1065
- for (const path of await this.#segmentPaths(sessionId))
1066
- records.push(...(await readRecords(path)));
1067
- return records;
1068
- }
1069
- catch (cause) {
1070
- if (cause instanceof MarAgentError)
1071
- throw cause;
1072
- throw new MarAgentError('MAR_AGENT_SESSION_NOT_FOUND', 'Session was not found.', { cause });
1073
- }
1074
- }
1075
- async readCodeModeState(sessionId) {
1076
- return this.#serializeRecordOperation(sessionId, () => this.#readCodeModeState(sessionId));
1077
- }
1078
- async #readCodeModeState(sessionId) {
1079
- this.#assertOpen();
1080
- const lease = this.#shared.writerLeases.get(sessionId);
1081
- if (lease?.owner === undefined)
1082
- return restoreCodeModeState(await this.#readRecords(sessionId));
1083
- lease.codeState ??= restoreCodeModeState(await this.#readRecords(sessionId));
1084
- return applyCodeModeStateMutations(lease.codeState, []);
1085
- }
1086
- async readExtensionCheckpoint(sessionId, extensionId, key) {
1087
- return this.#serializeRecordOperation(sessionId, () => this.#readExtensionCheckpoint(sessionId, extensionId, key));
1088
- }
1089
- async #readExtensionCheckpoint(sessionId, extensionId, key) {
1090
- this.#assertOpen();
1091
- const lease = this.#shared.writerLeases.get(sessionId);
1092
- if (lease?.owner === undefined)
1093
- return restoreExtensionCheckpoint(await this.#readRecords(sessionId), extensionId, key);
1094
- if (!lease.extensionCheckpoints) {
1095
- const index = new Map();
1096
- for (const record of await this.#readRecords(sessionId))
1097
- if (record.type === 'extension.checkpoint.updated')
1098
- indexExtensionCheckpoint(index, record.payload);
1099
- lease.extensionCheckpoints = index;
1100
- }
1101
- return extensionCheckpointFromPayload(lease.extensionCheckpoints.get(extensionId)?.get(key));
1102
- }
1103
- async writeExtensionCheckpoint(sessionId, extensionId, key, value, expectedRevision, input) {
1104
- if (typeof key !== 'string' ||
1105
- (expectedRevision !== undefined &&
1106
- (!Number.isSafeInteger(expectedRevision) || expectedRevision < 0)))
1107
- throw new MarAgentError('MAR_AGENT_EXTENSION_DATA_INVALID', 'Checkpoint key or expected revision is invalid.');
1108
- const copied = value === undefined ? undefined : cloneCoreJson(value);
1109
- input.signal.throwIfAborted();
1110
- const release = await this.acquireSessionWriteLease(sessionId, input.owner);
1111
- try {
1112
- return await this.#serializeRecordOperation(sessionId, async () => {
1113
- const current = await this.#readExtensionCheckpoint(sessionId, extensionId, key);
1114
- if (expectedRevision !== undefined && expectedRevision !== current.revision)
1115
- throw new MarAgentError('MAR_AGENT_EXTENSION_DATA_CONFLICT', 'Checkpoint revision changed before commit.');
1116
- input.signal.throwIfAborted();
1117
- const revision = current.revision + 1;
1118
- await this.#appendRecord(sessionId, {
1119
- type: 'extension.checkpoint.updated',
1120
- payload: {
1121
- extensionId,
1122
- key,
1123
- revision,
1124
- ...(copied === undefined ? { deleted: true } : { value: copied })
1125
- },
1126
- ...(input.executionId ? { executionId: input.executionId } : {}),
1127
- ...(input.turnId ? { turnId: input.turnId } : {})
1128
- });
1129
- return { revision, ...(copied === undefined ? {} : { value: cloneCoreJson(copied) }) };
1130
- });
1131
- }
1132
- finally {
1133
- await release();
1134
- }
1135
- }
1136
- async commitCodeModeState(sessionId, mutations, input) {
1137
- const operation = (this.#shared.codeStateWrites.get(sessionId) ?? Promise.resolve())
1138
- .catch(() => undefined)
1139
- .then(async () => {
1140
- const parsed = parseCodeModeStateMutations(mutations);
1141
- if (parsed.length === 0)
1142
- return this.readCodeModeState(sessionId);
1143
- const current = await this.readCodeModeState(sessionId);
1144
- if (input.expectedState && !isDeepStrictEqual(current, input.expectedState))
1145
- throw new MarAgentError('MAR_AGENT_CODE_STATE_CONFLICT', 'Session state changed while this cell was running.');
1146
- const state = applyCodeModeStateMutations(current, parsed);
1147
- await this.append(sessionId, {
1148
- type: 'code.state.updated',
1149
- payload: { mutations: parsed },
1150
- executionId: input.executionId,
1151
- turnId: input.turnId
1152
- });
1153
- return state;
1154
- });
1155
- this.#shared.codeStateWrites.set(sessionId, operation);
1156
- try {
1157
- return await operation;
1158
- }
1159
- finally {
1160
- if (this.#shared.codeStateWrites.get(sessionId) === operation)
1161
- this.#shared.codeStateWrites.delete(sessionId);
1162
- }
1163
- }
1164
- async readExecutionState(sessionId) {
1165
- this.#assertOpen();
1166
- const meta = this.#shared.index.sessions.find((item) => item.id === sessionId);
1167
- if (!meta)
1168
- throw new MarAgentError('MAR_AGENT_SESSION_NOT_FOUND', 'Session was not found.');
1169
- if (meta.resume?.version !== 1 ||
1170
- typeof meta.automaticTitlePending !== 'boolean' ||
1171
- meta.resume.compactSequence === undefined)
1172
- return this.#rebuildExecutionState(meta);
1173
- try {
1174
- const contextRecords = await this.#readFromSequence(meta, meta.resume.compactSequence);
1175
- if (contextRecords[0]?.sequence !== meta.resume.compactSequence ||
1176
- !isCompactCheckpoint(contextRecords[0]) ||
1177
- contextRecords.some((record, index) => index > 0 && isCompactCheckpoint(record)))
1178
- return this.#rebuildExecutionState(meta);
1179
- const todo = await this.#readIndexedTodo(meta, contextRecords);
1180
- if (!todo)
1181
- return this.#rebuildExecutionState(meta);
1182
- return {
1183
- automaticTitlePending: meta.automaticTitlePending,
1184
- todo,
1185
- contextRecords
1186
- };
1187
- }
1188
- catch {
1189
- return this.#rebuildExecutionState(meta);
1190
- }
1191
- }
1192
- /** Compare the planned sequence inside the existing record writer queue. */
1193
- async commitContextGc(sessionId, draft, planningRecords) {
1194
- this.#assertOpen();
1195
- const records = planningRecords ?? (await this.readExecutionState(sessionId)).contextRecords;
1196
- return this.#serializeRecordOperation(sessionId, async () => {
1197
- const meta = this.#shared.index.sessions.find((item) => item.id === sessionId);
1198
- if (!meta)
1199
- throw new MarAgentError('MAR_AGENT_SESSION_NOT_FOUND', 'Session was not found.');
1200
- const boundarySequence = meta.nextSequence - 1;
1201
- if (boundarySequence !== draft.boundarySequence)
1202
- throw new MarAgentError('MAR_AGENT_SESSION_CORRUPT', 'Context GC projection changed before checkpoint commit.');
1203
- if (records.at(-1)?.sequence !== boundarySequence ||
1204
- records.at(-1)?.sessionId !== sessionId ||
1205
- !sameContextGcBase(contextGcBaseFromRecords(records, boundarySequence), draft.base))
1206
- throw new MarAgentError('MAR_AGENT_SESSION_CORRUPT', 'Context GC planning boundary is invalid.');
1207
- const previous = latestValidContextGcCheckpoint(records, boundarySequence);
1208
- if ((!draft.inlineMedia || draft.inlineMedia.reason === 'TEXT_GC') &&
1209
- !contextGcCheckpointIntervalEligible(draft.trigger, previous?.payload.trigger))
1210
- throw new MarAgentError('MAR_AGENT_SESSION_CORRUPT', 'Context GC checkpoint interval validation failed.');
1211
- const plannedReplacements = normalizeContextGcReplacements(draft.replacements);
1212
- if (!plannedReplacements || (plannedReplacements.length === 0 && !draft.inlineMedia))
1213
- throw new MarAgentError('MAR_AGENT_SESSION_CORRUPT', 'Context GC checkpoint must contain a replacement.');
1214
- const replacements = normalizeContextGcReplacements([
1215
- ...(previous?.payload.replacements ?? []),
1216
- ...plannedReplacements
1217
- ]);
1218
- if (!replacements ||
1219
- (previous &&
1220
- isDeepStrictEqual(replacements, previous.payload.replacements) &&
1221
- (!draft.inlineMedia ||
1222
- isDeepStrictEqual(draft.inlineMedia, previous.payload.inlineMedia))))
1223
- throw new MarAgentError('MAR_AGENT_SESSION_CORRUPT', 'Context GC replacement map is invalid.');
1224
- const payload = {
1225
- ...structuredClone(draft),
1226
- checkpointId: randomUUID(),
1227
- generation: (previous?.payload.generation ?? 0) + 1,
1228
- replacements
1229
- };
1230
- const candidate = {
1231
- schemaVersion: 1,
1232
- recordId: randomUUID(),
1233
- sequence: boundarySequence + 1,
1234
- timestamp: new Date().toISOString(),
1235
- sessionId,
1236
- type: 'context.gc.completed',
1237
- payload
1238
- };
1239
- if (Buffer.byteLength(JSON.stringify(payload)) >= MAX_SEGMENT_BYTES ||
1240
- validateContextGcCheckpoint(records, candidate, meta.workspace, previous?.payload.replacements) === undefined)
1241
- throw new MarAgentError('MAR_AGENT_SESSION_CORRUPT', 'Context GC checkpoint validation failed.');
1242
- const turnId = records.findLast((record) => record.type === 'execution.header')?.turnId;
1243
- return this.#appendRecord(sessionId, {
1244
- type: 'context.gc.completed',
1245
- ...(turnId === undefined ? {} : { turnId }),
1246
- payload
1247
- });
1248
- });
1249
- }
1250
- async readPage(sessionId, input = {}) {
1251
- const meta = this.#shared.index.sessions.find((item) => item.id === sessionId);
1252
- if (!meta)
1253
- throw new MarAgentError('MAR_AGENT_SESSION_NOT_FOUND', 'Session was not found.');
1254
- const before = input.beforeSequence ?? Number.POSITIVE_INFINITY;
1255
- const limit = Math.min(1000, Math.max(1, input.limit ?? 100));
1256
- const page = [];
1257
- let hasEarlier = false;
1258
- const paths = (await this.#segmentPaths(sessionId)).reverse();
1259
- for (const [pathIndex, path] of paths.entries()) {
1260
- const segmentNumber = segmentNumberFromPath(path);
1261
- const segment = meta.segments?.find((item) => item.number === segmentNumber);
1262
- if (segment !== undefined && segment.firstSequence >= before)
1263
- continue;
1264
- const needed = limit - page.length;
1265
- const window = await readRecordPageFromTail(path, before, needed, this.#shared.historyPagePositions);
1266
- page.unshift(...window.records);
1267
- if (window.hasEarlier) {
1268
- hasEarlier = true;
1269
- break;
1270
- }
1271
- if (page.length >= limit) {
1272
- hasEarlier = pathIndex < paths.length - 1;
1273
- break;
1274
- }
1275
- }
1276
- const previousBeforeSequence = hasEarlier ? page[0]?.sequence : undefined;
1277
- return { records: page, ...(previousBeforeSequence ? { previousBeforeSequence } : {}) };
1278
- }
1279
- async compact(sessionId, input, options = {}) {
1280
- if (!input.summary.trim())
1281
- throw new MarAgentError('MAR_AGENT_TOOL_INPUT_INVALID', 'Compact summary is required.');
1282
- const meta = this.#shared.index.sessions.find((item) => item.id === sessionId);
1283
- if (!meta)
1284
- throw new MarAgentError('MAR_AGENT_SESSION_NOT_FOUND', 'Session was not found.');
1285
- return this.append(sessionId, {
1286
- type: 'compact.completed',
1287
- payload: {
1288
- summary: input.summary,
1289
- ...(input.pendingInputs?.length ? { pendingInputs: input.pendingInputs } : {}),
1290
- ...(input.snapshotRecordId === undefined
1291
- ? {}
1292
- : { snapshotRecordId: input.snapshotRecordId }),
1293
- ...(input.snapshotMessageCount === undefined
1294
- ? {}
1295
- : { snapshotMessageCount: input.snapshotMessageCount }),
1296
- ...(input.replacementHistory === undefined
1297
- ? {}
1298
- : { replacementHistory: input.replacementHistory }),
1299
- ...(input.retainedModelContext?.length
1300
- ? { retainedModelContext: input.retainedModelContext }
1301
- : {}),
1302
- ...(input.inlineMediaState ? { inlineMediaState: input.inlineMediaState } : {}),
1303
- ...(input.environment === undefined ? {} : { environment: input.environment }),
1304
- boundarySequence: meta.nextSequence - 1,
1305
- automatic: input.automatic === true,
1306
- ...(input.modelId === undefined ? {} : { modelId: input.modelId }),
1307
- ...(input.contextWindowTokens === undefined
1308
- ? {}
1309
- : { contextWindowTokens: input.contextWindowTokens }),
1310
- ...(input.usage === undefined ? {} : { usage: input.usage })
1311
- },
1312
- ...(input.executionId ? { executionId: input.executionId } : {}),
1313
- ...(input.turnId ? { turnId: input.turnId } : {})
1314
- }, options);
1315
- }
1316
- /** A warm cell retains physical writer ownership between Executions of the same Agent. */
1317
- async acquireSessionLease(sessionId, owner) {
1318
- return this.#serializeRecordOperation(sessionId, async () => {
1319
- this.#assertOpen();
1320
- let lease = this.#shared.writerLeases.get(sessionId);
1321
- if (lease) {
1322
- if (lease.maintenance || lease.executing || owner === undefined || lease.owner !== owner)
1323
- throw new MarAgentError('MAR_AGENT_SESSION_LOCKED', 'Session already has a writer.');
1324
- if (lease.appendFailure)
1325
- throw lease.appendFailure.error;
1326
- lease.executing = true;
1327
- }
1328
- else {
1329
- const release = await this.#acquireSessionLease(sessionId);
1330
- lease = { owner, executing: true, retained: 0, release };
1331
- this.#shared.writerLeases.set(sessionId, lease);
1332
- }
1333
- const current = lease;
1334
- let released = false;
1335
- return () => this.#serializeRecordOperation(sessionId, async () => {
1336
- if (released)
1337
- return;
1338
- released = true;
1339
- current.executing = false;
1340
- await this.#releaseUnusedWriter(sessionId, current);
1341
- });
1342
- });
1343
- }
1344
- hasRetainedSessionLease(sessionId, owner) {
1345
- const lease = this.#shared.writerLeases.get(sessionId);
1346
- return lease?.owner === owner && lease.retained > 0;
1347
- }
1348
- async acquireSessionMaintenance(sessionId, kind, owner) {
1349
- this.#assertOpen();
1350
- const acquired = new Map();
1351
- let sessionIds = [];
1352
- let released = false;
1353
- const holding = Object.freeze({
1354
- get sessionIds() {
1355
- return sessionIds;
1356
- },
1357
- release: async () => {
1358
- if (released)
1359
- return;
1360
- released = true;
1361
- this.#maintenance.delete(holding);
1362
- let failure;
1363
- for (const [id, writer] of [...acquired].reverse()) {
1364
- try {
1365
- await this.#serializeRecordOperation(id, async () => {
1366
- delete writer.maintenance;
1367
- await this.#releaseUnusedWriter(id, writer);
1368
- });
1369
- }
1370
- catch (error) {
1371
- failure ??= { error };
1372
- }
1373
- }
1374
- if (failure)
1375
- throw failure.error;
1376
- }
1377
- });
1378
- try {
1379
- // Re-read membership after acquiring writers; never hand the SDK a pre-lock tree snapshot.
1380
- for (;;) {
1381
- const tree = kind === 'delete' ? await this.sessionTree(sessionId) : [sessionId];
1382
- for (const id of tree.toReversed()) {
1383
- if (acquired.has(id))
1384
- continue;
1385
- await this.#serializeRecordOperation(id, async () => {
1386
- this.#assertOpen();
1387
- let writer = this.#shared.writerLeases.get(id);
1388
- if (writer &&
1389
- (writer.maintenance ||
1390
- owner === undefined ||
1391
- writer.owner !== owner ||
1392
- (kind === 'clear' && writer.executing)))
1393
- throw new MarAgentError('MAR_AGENT_SESSION_LOCKED', 'Session already has a writer.');
1394
- if (!writer) {
1395
- // Deleting a stale index entry must not recreate its missing directory.
1396
- const release = kind === 'delete' && !(await sessionDirectoryExists(this.#sessionDirectory(id)))
1397
- ? async () => { }
1398
- : await this.#acquireSessionLease(id);
1399
- writer = { owner, executing: false, retained: 0, release };
1400
- this.#shared.writerLeases.set(id, writer);
1401
- }
1402
- writer.maintenance = holding;
1403
- acquired.set(id, writer);
1404
- });
1405
- }
1406
- const current = kind === 'clear' ? tree : await this.sessionTree(sessionId);
1407
- if (current.every((id) => acquired.has(id))) {
1408
- sessionIds = Object.freeze(current);
1409
- break;
1410
- }
1411
- }
1412
- this.#maintenance.set(holding, { sessionId, kind });
1413
- return holding;
1414
- }
1415
- catch (error) {
1416
- await holding.release().catch(() => undefined);
1417
- throw error;
1418
- }
1419
- }
1420
- #assertMaintenance(sessionId, kind, holding) {
1421
- const current = this.#maintenance.get(holding);
1422
- if (current?.sessionId !== sessionId || current.kind !== kind)
1423
- throw new MarAgentError('MAR_AGENT_SESSION_LOCKED', 'Session maintenance ownership is invalid.');
1424
- }
1425
- /** Native writes join their Agent's sole writer, without admitting another Execution. */
1426
- async acquireSessionWriteLease(sessionId, owner) {
1427
- return this.#serializeRecordOperation(sessionId, async () => {
1428
- this.#assertOpen();
1429
- let lease = this.#shared.writerLeases.get(sessionId);
1430
- if (lease && (lease.maintenance || lease.owner !== owner))
1431
- throw new MarAgentError('MAR_AGENT_SESSION_LOCKED', 'Session already has a writer.');
1432
- if (lease?.appendFailure)
1433
- throw lease.appendFailure.error;
1434
- if (!lease) {
1435
- const release = await this.#acquireSessionLease(sessionId);
1436
- lease = { owner, executing: false, retained: 0, release };
1437
- this.#shared.writerLeases.set(sessionId, lease);
1438
- }
1439
- lease.retained++;
1440
- const current = lease;
1441
- let released = false;
1442
- return () => this.#serializeRecordOperation(sessionId, async () => {
1443
- if (released)
1444
- return;
1445
- released = true;
1446
- current.retained--;
1447
- await this.#releaseUnusedWriter(sessionId, current);
1448
- });
1449
- });
1450
- }
1451
- async retainSessionLease(sessionId, owner) {
1452
- return this.#serializeRecordOperation(sessionId, async () => {
1453
- const lease = this.#shared.writerLeases.get(sessionId);
1454
- if (!lease || lease.maintenance || !lease.executing || lease.owner !== owner)
1455
- throw new MarAgentError('MAR_AGENT_SESSION_LOCKED', 'Retained work requires its originating Session writer.');
1456
- lease.retained++;
1457
- let released = false;
1458
- return () => this.#serializeRecordOperation(sessionId, async () => {
1459
- if (released)
1460
- return;
1461
- released = true;
1462
- lease.retained--;
1463
- await this.#releaseUnusedWriter(sessionId, lease);
1464
- });
1465
- });
1466
- }
1467
- async #releaseUnusedWriter(sessionId, lease) {
1468
- if (lease.maintenance || lease.executing || lease.retained)
1469
- return;
1470
- try {
1471
- await lease.release();
1472
- }
1473
- finally {
1474
- delete lease.codeState;
1475
- delete lease.extensionCheckpoints;
1476
- this.#shared.writerLeases.delete(sessionId);
1477
- }
1478
- }
1479
- /** Recover files under the sole writer lock; flush dirty index state before releasing it. */
1480
- async #acquireSessionLease(sessionId) {
1481
- this.#assertOpen();
1482
- await this.#refreshIndex();
1483
- if (!this.#shared.index.sessions.some((item) => item.id === sessionId))
1484
- throw new MarAgentError('MAR_AGENT_SESSION_NOT_FOUND', 'Session was not found.');
1485
- const path = join(this.#shared.root, 'sessions', sessionId, 'lock');
1486
- const release = await acquireFileLock(path, 'Session already has a writer.', 0);
1487
- try {
1488
- const disk = await readSessionIndex(join(this.#shared.root, 'sessions', 'index.json'));
1489
- if (!disk)
1490
- throw new MarAgentError('MAR_AGENT_SESSION_CORRUPT', 'Session index is missing.');
1491
- const current = disk.sessions.find((item) => item.id === sessionId);
1492
- if (!current)
1493
- throw new MarAgentError('MAR_AGENT_SESSION_NOT_FOUND', 'Session was not found.');
1494
- await recoverSessionStorageTransaction(this.#sessionDirectory(sessionId), current.storageTransactionId);
1495
- await recoverContextualWorldStateTransactions(this.#shared.root, current);
1496
- await this.#refreshIndex();
1497
- await this.#reconcileTail(sessionId);
1498
- }
1499
- catch (error) {
1500
- await release();
1501
- throw error;
1502
- }
1503
- return async () => {
1504
- try {
1505
- if (this.#shared.indexDirty)
1506
- await this.#saveIndex();
1507
- }
1508
- finally {
1509
- await release();
1510
- }
1511
- };
1512
- }
1513
- async list(input = {}) {
1514
- this.#assertOpen();
1515
- await this.#refreshIndex();
1516
- const filter = sessionListFilter(input);
1517
- const start = decodeSessionListCursor(input.cursor, this.#shared.index.revision, filter);
1518
- const limit = Math.min(200, Math.max(1, input.limit ?? 50));
1519
- const ordered = this.#shared.index.sessions
1520
- .filter((session) => sessionMatchesFilter(session, filter))
1521
- .sort((a, b) => b.lastActivityAt.localeCompare(a.lastActivityAt));
1522
- const sessions = ordered.slice(start, start + limit).map((session) => ({
1523
- id: session.id,
1524
- title: session.title,
1525
- ...(session.resume?.firstUserMessagePreview === undefined
1526
- ? {}
1527
- : { firstUserMessagePreview: session.resume.firstUserMessagePreview }),
1528
- workspace: session.workspace,
1529
- createdAt: session.createdAt,
1530
- lastActivityAt: session.lastActivityAt,
1531
- source: normalizeSessionSource(session.source),
1532
- ...(session.resume?.modelId === undefined
1533
- ? {}
1534
- : {
1535
- modelId: session.resume.modelId,
1536
- ...(session.resume.modelName === undefined
1537
- ? {}
1538
- : { modelName: session.resume.modelName }),
1539
- ...(session.resume.reasoningEffort === undefined
1540
- ? {}
1541
- : { reasoningEffort: session.resume.reasoningEffort })
1542
- })
1543
- }));
1544
- const next = start + limit < ordered.length
1545
- ? encodeSessionListCursor(this.#shared.index.revision, start + limit, filter)
1546
- : undefined;
1547
- return { sessions, ...(next ? { nextCursor: next } : {}) };
1548
- }
1549
- async listSubagentChildren(parentSessionId) {
1550
- this.#assertOpen();
1551
- await this.#refreshIndex();
1552
- return this.#shared.index.sessions
1553
- .map((session) => ({ session, source: normalizeSessionSource(session.source) }))
1554
- .filter((item) => item.source.type === 'subagent' && item.source.parentSessionId === parentSessionId)
1555
- .map(({ session, source }) => ({
1556
- id: session.id,
1557
- title: session.title,
1558
- workspace: session.workspace,
1559
- createdAt: session.createdAt,
1560
- lastActivityAt: session.lastActivityAt,
1561
- source,
1562
- ...(session.resume?.modelId === undefined
1563
- ? {}
1564
- : {
1565
- modelId: session.resume.modelId,
1566
- ...(session.resume.modelName === undefined
1567
- ? {}
1568
- : { modelName: session.resume.modelName }),
1569
- ...(session.resume.reasoningEffort === undefined
1570
- ? {}
1571
- : { reasoningEffort: session.resume.reasoningEffort })
1572
- })
1573
- }));
1574
- }
1575
- async executionConfiguration(sessionId) {
1576
- this.#assertOpen();
1577
- await this.#refreshIndex();
1578
- let meta = this.#shared.index.sessions.find((session) => session.id === sessionId);
1579
- if (meta === undefined)
1580
- throw new MarAgentError('MAR_AGENT_SESSION_NOT_FOUND', 'Session was not found.');
1581
- if (meta.resume?.executionModelIndexed !== true) {
1582
- await this.#ensureExecutionModelIndexed(sessionId);
1583
- meta = this.#shared.index.sessions.find((session) => session.id === sessionId);
1584
- if (meta === undefined)
1585
- throw new MarAgentError('MAR_AGENT_SESSION_NOT_FOUND', 'Session was not found.');
1586
- }
1587
- return meta.resume?.modelId === undefined
1588
- ? undefined
1589
- : {
1590
- modelId: meta.resume.modelId,
1591
- ...(meta.resume.modelName === undefined ? {} : { modelName: meta.resume.modelName }),
1592
- ...(meta.resume.reasoningEffort === undefined
1593
- ? {}
1594
- : { reasoningEffort: meta.resume.reasoningEffort })
1595
- };
1596
- }
1597
- async sessionTree(sessionId) {
1598
- this.#assertOpen();
1599
- await this.#refreshIndex();
1600
- if (!this.#shared.index.sessions.some((session) => session.id === sessionId))
1601
- throw new MarAgentError('MAR_AGENT_SESSION_NOT_FOUND', 'Session was not found.');
1602
- return sessionTreeIds(this.#shared.index.sessions, sessionId);
1603
- }
1604
- #applyRecordToResumeIndex(meta, record) {
1605
- if (record.type === 'turn.user')
1606
- meta.automaticTitlePending = false;
1607
- if (record.type === 'session.title.updated' && isObject(record.payload)) {
1608
- if (typeof record.payload.title === 'string')
1609
- meta.title = record.payload.title;
1610
- meta.automaticTitlePending = false;
1611
- }
1612
- const resume = meta.resume;
1613
- if (resume?.version !== 1 || !Number.isSafeInteger(resume.todoRevision))
1614
- return;
1615
- if (resume.userTurns !== undefined && isNativeUserTurn(record))
1616
- resume.userTurns++;
1617
- if (resume.firstUserMessageIndexed === true && resume.firstUserMessagePreview === undefined) {
1618
- const preview = userMessagePreviewFromRecord(record);
1619
- if (preview !== undefined)
1620
- resume.firstUserMessagePreview = preview;
1621
- }
1622
- const executionModel = executionModelFromRecord(record);
1623
- if (executionModel !== undefined) {
1624
- resume.executionModelIndexed = true;
1625
- resume.modelId = executionModel.modelId;
1626
- if (executionModel.modelName === undefined)
1627
- delete resume.modelName;
1628
- else
1629
- resume.modelName = executionModel.modelName;
1630
- if (executionModel.reasoningEffort === undefined)
1631
- delete resume.reasoningEffort;
1632
- else
1633
- resume.reasoningEffort = executionModel.reasoningEffort;
1634
- }
1635
- if (isCompactCheckpoint(record))
1636
- resume.compactSequence = record.sequence;
1637
- if (record.type !== 'todo.updated' || !todoItemsFromSnapshot(record.payload))
1638
- return;
1639
- resume.todoSequence = record.sequence;
1640
- resume.todoRevision++;
1641
- }
1642
- async #readIndexedTodo(meta, contextRecords) {
1643
- const resume = meta.resume;
1644
- if (resume?.version !== 1 ||
1645
- !Number.isSafeInteger(resume.todoRevision) ||
1646
- resume.todoRevision < 0)
1647
- return undefined;
1648
- const latestContextTodo = contextRecords.findLast((record) => record.type === 'todo.updated' && todoItemsFromSnapshot(record.payload) !== undefined);
1649
- if (latestContextTodo &&
1650
- (resume.todoSequence === undefined || latestContextTodo.sequence !== resume.todoSequence))
1651
- return undefined;
1652
- if (resume.todoSequence === undefined)
1653
- return resume.todoRevision === 0 ? { revision: 0, items: [] } : undefined;
1654
- if (resume.todoRevision === 0)
1655
- return undefined;
1656
- const record = contextRecords.find((item) => item.sequence === resume.todoSequence) ??
1657
- (await this.#readRecordAtSequence(meta, resume.todoSequence));
1658
- if (record?.type !== 'todo.updated')
1659
- return undefined;
1660
- const items = todoItemsFromSnapshot(record.payload);
1661
- return items ? { revision: resume.todoRevision, items } : undefined;
1662
- }
1663
- async #readRecordAtSequence(meta, sequence) {
1664
- const segment = meta.segments?.find((item) => item.firstSequence <= sequence && item.lastSequence >= sequence);
1665
- if (!segment)
1666
- return undefined;
1667
- return (await readRecords(this.#segmentPath(meta.id, segment.number))).find((record) => record.sequence === sequence);
1668
- }
1669
- async #readFromSequence(meta, sequence) {
1670
- const segments = (meta.segments ?? [])
1671
- .filter((item) => item.lastSequence >= sequence)
1672
- .sort((left, right) => left.number - right.number);
1673
- if (segments.length === 0)
1674
- throw new MarAgentError('MAR_AGENT_SESSION_CORRUPT', 'Session resume index is invalid.');
1675
- const records = [];
1676
- for (const segment of segments)
1677
- records.push(...(await readRecords(this.#segmentPath(meta.id, segment.number))).filter((record) => record.sequence >= sequence));
1678
- return records;
1679
- }
1680
- async #rebuildExecutionState(meta) {
1681
- const state = deriveExecutionState(await this.read(meta.id));
1682
- if (meta.automaticTitlePending !== state.automaticTitlePending ||
1683
- !sameResumeIndex(meta.resume, state.resume)) {
1684
- meta.automaticTitlePending = state.automaticTitlePending;
1685
- meta.resume = state.resume;
1686
- this.#shared.index.revision++;
1687
- this.#markIndexDirty(meta.id);
1688
- }
1689
- return {
1690
- automaticTitlePending: state.automaticTitlePending,
1691
- todo: state.todo,
1692
- contextRecords: state.contextRecords
1693
- };
1694
- }
1695
- /** Counts native input records, not the post-Compact model context. */
1696
- async userTurnCount(sessionId) {
1697
- return this.#serializeRecordOperation(sessionId, async () => {
1698
- this.#assertOpen();
1699
- await this.#refreshIndex();
1700
- const before = this.#shared.index.sessions.find((session) => session.id === sessionId);
1701
- if (!before)
1702
- throw new MarAgentError('MAR_AGENT_SESSION_NOT_FOUND', 'Session was not found.');
1703
- const indexed = before.resume?.userTurns;
1704
- if (indexed !== undefined && this.#shared.writerLeases.has(sessionId))
1705
- return indexed;
1706
- const nextSequence = before.nextSequence;
1707
- const transactionId = before.storageTransactionId;
1708
- const paths = await this.#segmentPaths(sessionId);
1709
- let count = indexed ?? 0;
1710
- let lastSequence = 0;
1711
- let reachedPrefix = false;
1712
- if (indexed !== undefined) {
1713
- // No local writer: a previous writer may have committed bytes but not its index.
1714
- for (const path of [...paths].reverse()) {
1715
- for await (const record of readRecordsFromTail(path)) {
1716
- lastSequence = Math.max(lastSequence, record.sequence);
1717
- if (record.sequence < nextSequence) {
1718
- reachedPrefix = true;
1719
- break;
1720
- }
1721
- if (isNativeUserTurn(record))
1722
- count++;
1723
- }
1724
- if (reachedPrefix)
1725
- break;
1726
- }
1727
- }
1728
- if (indexed === undefined || lastSequence < nextSequence - 1) {
1729
- count = 0;
1730
- lastSequence = 0;
1731
- for (const path of paths) {
1732
- for await (const record of readRecordsFromHead(path)) {
1733
- lastSequence = record.sequence;
1734
- if (isNativeUserTurn(record))
1735
- count++;
1736
- }
1737
- }
1738
- }
1739
- await this.#refreshIndex();
1740
- const current = this.#shared.index.sessions.find((session) => session.id === sessionId);
1741
- if (!current)
1742
- throw new MarAgentError('MAR_AGENT_SESSION_NOT_FOUND', 'Session was not found.');
1743
- if (current.storageTransactionId !== transactionId) {
1744
- // The indexed prefix no longer belongs to this history. Fall back to the
1745
- // ordinary physical read boundary without caching or a conflict error.
1746
- count = 0;
1747
- for (const path of await this.#segmentPaths(sessionId))
1748
- for await (const record of readRecordsFromHead(path))
1749
- if (isNativeUserTurn(record))
1750
- count++;
1751
- return count;
1752
- }
1753
- if (current.nextSequence === nextSequence &&
1754
- lastSequence === nextSequence - 1 &&
1755
- current.resume?.userTurns === undefined) {
1756
- (current.resume ??= { version: 1, todoRevision: 0 }).userTurns = count;
1757
- this.#markIndexDirty(sessionId, true);
1758
- }
1759
- return count;
1760
- });
1761
- }
1762
- async firstUserMessagePreview(sessionId) {
1763
- this.#assertOpen();
1764
- await this.#refreshIndex();
1765
- await this.#ensureFirstUserMessageIndexed(sessionId);
1766
- return this.#shared.index.sessions.find((session) => session.id === sessionId)?.resume
1767
- ?.firstUserMessagePreview;
1768
- }
1769
- async #ensureFirstUserMessageIndexed(sessionId) {
1770
- for (;;) {
1771
- const before = this.#shared.index.sessions.find((session) => session.id === sessionId);
1772
- if (before === undefined)
1773
- throw new MarAgentError('MAR_AGENT_SESSION_NOT_FOUND', 'Session was not found.');
1774
- if (before.resume?.firstUserMessageIndexed === true)
1775
- return;
1776
- const nextSequence = before.nextSequence;
1777
- const transactionId = before.storageTransactionId;
1778
- let preview;
1779
- try {
1780
- for (const path of await this.#segmentPaths(sessionId)) {
1781
- for await (const record of readRecordsFromHead(path)) {
1782
- preview = userMessagePreviewFromRecord(record);
1783
- if (preview !== undefined)
1784
- break;
1785
- }
1786
- if (preview !== undefined)
1787
- break;
1788
- }
1789
- }
1790
- catch (error) {
1791
- if (error.code !== 'ENOENT' &&
1792
- !(error instanceof MarAgentError && error.code === 'MAR_AGENT_SESSION_NOT_FOUND'))
1793
- throw error;
1794
- }
1795
- await this.#refreshIndex();
1796
- const current = this.#shared.index.sessions.find((session) => session.id === sessionId);
1797
- if (current === undefined)
1798
- throw new MarAgentError('MAR_AGENT_SESSION_NOT_FOUND', 'Session was not found.');
1799
- if (current.resume?.firstUserMessageIndexed === true)
1800
- return;
1801
- if (current.nextSequence !== nextSequence || current.storageTransactionId !== transactionId)
1802
- continue;
1803
- const resume = (current.resume ??= { version: 1, todoRevision: 0 });
1804
- resume.firstUserMessageIndexed = true;
1805
- if (preview !== undefined)
1806
- resume.firstUserMessagePreview = preview;
1807
- // Derived preview caches do not change list membership, ordering or filters.
1808
- this.#markIndexDirty(sessionId, true);
1809
- return;
1810
- }
1811
- }
1812
- async #ensureExecutionModelIndexed(sessionId) {
1813
- const pending = this.#shared.executionModelReads.get(sessionId);
1814
- if (pending !== undefined)
1815
- return pending;
1816
- const read = this.#backfillExecutionModel(sessionId).finally(() => {
1817
- if (this.#shared.executionModelReads.get(sessionId) === read)
1818
- this.#shared.executionModelReads.delete(sessionId);
1819
- });
1820
- this.#shared.executionModelReads.set(sessionId, read);
1821
- return read;
1822
- }
1823
- async #backfillExecutionModel(sessionId) {
1824
- for (;;) {
1825
- const before = this.#shared.index.sessions.find((session) => session.id === sessionId);
1826
- if (before === undefined)
1827
- throw new MarAgentError('MAR_AGENT_SESSION_NOT_FOUND', 'Session was not found.');
1828
- if (before.resume?.executionModelIndexed === true)
1829
- return;
1830
- const nextSequence = before.nextSequence;
1831
- const transactionId = before.storageTransactionId;
1832
- const model = await this.#readLatestExecutionModel(sessionId);
1833
- // Refresh can replace metadata objects while unrelated sessions are being read.
1834
- // Merge only into the current entry, and retry if the authoritative history changed.
1835
- await this.#refreshIndex();
1836
- const current = this.#shared.index.sessions.find((session) => session.id === sessionId);
1837
- if (current === undefined)
1838
- throw new MarAgentError('MAR_AGENT_SESSION_NOT_FOUND', 'Session was not found.');
1839
- if (current.resume?.executionModelIndexed === true)
1840
- return;
1841
- if (current.nextSequence !== nextSequence || current.storageTransactionId !== transactionId)
1842
- continue;
1843
- // A missing resume index stays incomplete (no compact boundary); execution
1844
- // recovery will rebuild it separately instead of doing so during discovery.
1845
- const resume = (current.resume ??= { version: 1, todoRevision: 0 });
1846
- resume.executionModelIndexed = true;
1847
- delete resume.modelId;
1848
- delete resume.modelName;
1849
- delete resume.reasoningEffort;
1850
- if (model !== undefined)
1851
- Object.assign(resume, model);
1852
- this.#shared.index.revision++;
1853
- this.#markIndexDirty(sessionId);
1854
- return;
1855
- }
1856
- }
1857
- async #readLatestExecutionModel(sessionId) {
1858
- try {
1859
- for (const path of (await this.#segmentPaths(sessionId)).reverse())
1860
- for await (const record of readRecordsFromTail(path)) {
1861
- const model = executionModelFromRecord(record);
1862
- if (model !== undefined)
1863
- return model;
1864
- }
1865
- return undefined;
1866
- }
1867
- catch (error) {
1868
- if (error.code === 'ENOENT' ||
1869
- (error instanceof MarAgentError && error.code === 'MAR_AGENT_SESSION_NOT_FOUND'))
1870
- return undefined;
1871
- throw error;
1872
- }
1873
- }
1874
- async delete(sessionId, maintenance) {
1875
- this.#assertOpen();
1876
- const holding = maintenance ?? (await this.acquireSessionMaintenance(sessionId, 'delete'));
1877
- this.#assertMaintenance(sessionId, 'delete', holding);
1878
- const tree = holding.sessionIds;
1879
- let failed = false;
1880
- try {
1881
- const deleted = await sessionDirectoryExists(join(this.#shared.root, 'sessions', sessionId));
1882
- for (const id of tree.toReversed()) {
1883
- await rm(join(this.#shared.root, 'sessions', id), { recursive: true, force: true });
1884
- this.#shared.segments.delete(id);
1885
- }
1886
- const deletedSet = new Set(tree);
1887
- this.#shared.index.sessions = this.#shared.index.sessions.filter((session) => !deletedSet.has(session.id));
1888
- this.#shared.index.revision++;
1889
- await this.#saveIndex(tree);
1890
- return { deleted };
1891
- }
1892
- catch (error) {
1893
- failed = true;
1894
- throw error;
1895
- }
1896
- finally {
1897
- if (!maintenance) {
1898
- const releasing = holding.release();
1899
- if (failed)
1900
- await releasing.catch(() => undefined);
1901
- else
1902
- await releasing;
1903
- }
1904
- }
1905
- }
1906
- #assertOpen() {
1907
- if (this.#leaseClosed || this.#shared.closed)
1908
- throw new MarAgentError('MAR_AGENT_DISPOSED', 'Session store is closed.');
1909
- }
1910
- #markIndexDirty(sessionId, derivedOnly = false) {
1911
- if (!derivedOnly)
1912
- this.#shared.derivedOnlyDirtySessions.delete(sessionId);
1913
- else if (!this.#shared.dirtySessionVersions.has(sessionId))
1914
- this.#shared.derivedOnlyDirtySessions.add(sessionId);
1915
- this.#shared.indexDirty = true;
1916
- this.#shared.dirtySessionVersions.set(sessionId, (this.#shared.dirtySessionVersions.get(sessionId) ?? 0) + 1);
1917
- }
1918
- async #storageTransactionCommitted(sessionId, transactionId) {
1919
- const disk = await readSessionIndex(join(this.#shared.root, 'sessions', 'index.json'));
1920
- return (disk?.sessions.some((session) => session.id === sessionId && session.storageTransactionId === transactionId) ?? false);
1921
- }
1922
- #segmentPath(sessionId, segment) {
1923
- return join(this.#shared.root, 'sessions', sessionId, `events-${String(segment).padStart(6, '0')}.jsonl`);
1924
- }
1925
- async #segmentPaths(sessionId) {
1926
- const directory = join(this.#shared.root, 'sessions', sessionId);
1927
- const names = (await readdir(directory))
1928
- .filter((name) => /^events-\d{6}\.jsonl$/.test(name))
1929
- .sort();
1930
- if (names.length === 0)
1931
- throw new MarAgentError('MAR_AGENT_SESSION_NOT_FOUND', 'Session was not found.');
1932
- return names.map((name) => join(directory, name));
1933
- }
1934
- async #currentSegment(sessionId) {
1935
- const cached = this.#shared.segments.get(sessionId);
1936
- if (cached !== undefined)
1937
- return cached;
1938
- const meta = this.#shared.index.sessions.find((item) => item.id === sessionId);
1939
- const indexed = meta?.segments?.at(-1)?.number;
1940
- if (indexed !== undefined) {
1941
- this.#shared.segments.set(sessionId, indexed);
1942
- return indexed;
1943
- }
1944
- const paths = await this.#segmentPaths(sessionId);
1945
- const match = /events-(\d{6})\.jsonl$/.exec(paths.at(-1));
1946
- const segment = Number(match?.[1] ?? 1);
1947
- this.#shared.segments.set(sessionId, segment);
1948
- return segment;
1949
- }
1950
- /** Repair the last segment and pending images under the lease, then sync sequence metadata. */
1951
- async #reconcileTail(sessionId) {
1952
- const paths = await this.#segmentPaths(sessionId);
1953
- const latestPath = paths.at(-1);
1954
- await repairSegmentTail(latestPath);
1955
- const records = await readRecords(latestPath);
1956
- await recoverResources(join(this.#sessionDirectory(sessionId), 'resources'), () => this.#readRecords(sessionId));
1957
- await cleanupUnreferencedToolResources(this.#sessionDirectory(sessionId), () => this.#readRecords(sessionId));
1958
- const last = records.at(-1);
1959
- const match = /events-(\d{6})\.jsonl$/.exec(latestPath);
1960
- const segment = Number(match?.[1] ?? 1);
1961
- this.#shared.segments.set(sessionId, segment);
1962
- if (last === undefined)
1963
- throw new MarAgentError('MAR_AGENT_SESSION_CORRUPT', 'Session history is corrupt.');
1964
- const bytes = (await stat(latestPath)).size;
1965
- const firstSequence = records[0].sequence;
1966
- // Tail recovery must publish onto metadata that is current after all file I/O.
1967
- const meta = this.#shared.index.sessions.find((item) => item.id === sessionId);
1968
- const known = meta.segments?.find((item) => item.number === segment);
1969
- const titleRecord = records.findLast((record) => record.type === 'session.title.updated' &&
1970
- typeof record.payload.title === 'string');
1971
- const recoveredTitle = titleRecord?.payload?.title;
1972
- const changed = meta.nextSequence !== last.sequence + 1 ||
1973
- known?.bytes !== bytes ||
1974
- (recoveredTitle !== undefined && meta.title !== recoveredTitle);
1975
- meta.nextSequence = last.sequence + 1;
1976
- if (recoveredTitle !== undefined)
1977
- meta.title = recoveredTitle;
1978
- meta.lastActivityAt =
1979
- meta.lastActivityAt < last.timestamp ? last.timestamp : meta.lastActivityAt;
1980
- if (!meta.segments)
1981
- meta.segments = [];
1982
- if (known) {
1983
- known.firstSequence = firstSequence;
1984
- known.lastSequence = last.sequence;
1985
- known.bytes = bytes;
1986
- }
1987
- else
1988
- meta.segments.push({ number: segment, firstSequence, lastSequence: last.sequence, bytes });
1989
- if (changed) {
1990
- delete meta.automaticTitlePending;
1991
- delete meta.resume;
1992
- this.#shared.index.revision++;
1993
- this.#markIndexDirty(sessionId);
1994
- }
1995
- }
1996
- async close() {
1997
- if (this.#leaseClosed)
1998
- return;
1999
- this.#leaseClosed = true;
2000
- this.#shared.references--;
2001
- if (this.#shared.references > 0)
2002
- return;
2003
- if (this.#shared.indexDirty)
2004
- await this.#saveIndex();
2005
- this.#shared.closed = true;
2006
- JsonlSessionStore.#instances.delete(this.#shared.root);
2007
- }
2008
- }
2009
- async function sessionDirectoryExists(path) {
2010
- try {
2011
- await lstat(path);
2012
- return true;
2013
- }
2014
- catch (error) {
2015
- if (error.code === 'ENOENT')
2016
- return false;
2017
- throw error;
2018
- }
2019
- }
2020
- async function recoverContextualWorldStateTransactions(root, meta) {
2021
- const directory = join(root, 'sessions', meta.id);
2022
- let names;
2023
- try {
2024
- names = await readdir(directory);
2025
- }
2026
- catch (error) {
2027
- if (error.code === 'ENOENT')
2028
- return;
2029
- throw error;
2030
- }
2031
- const pattern = /^context-world-state\.json\.(\d+)\.[0-9a-f-]+\.(?:rollback|clear)-backup$/u;
2032
- const backups = names.filter((name) => pattern.test(name));
2033
- if (backups.length === 0)
2034
- return;
2035
- const eventNames = names.filter((name) => /^events-\d{6}\.jsonl$/u.test(name)).sort();
2036
- const latestEventName = eventNames.at(-1);
2037
- if (latestEventName === undefined)
2038
- throw new MarAgentError('MAR_AGENT_SESSION_CORRUPT', 'Session history is corrupt.');
2039
- const latestRecords = await readRecords(join(directory, latestEventName));
2040
- const actualNextSequence = (latestRecords.at(-1)?.sequence ?? 0) + 1;
2041
- const canonical = join(directory, CONTEXTUAL_WORLD_STATE_FILE);
2042
- for (const name of backups) {
2043
- const match = pattern.exec(name);
2044
- const backup = join(directory, name);
2045
- const targetNextSequence = Number(match[1]);
2046
- if (actualNextSequence === targetNextSequence || (await sessionDirectoryExists(canonical)))
2047
- await rm(backup, { force: true });
2048
- else
2049
- await rename(backup, canonical);
2050
- }
2051
- }
2052
- function restoreSessionMeta(meta, original) {
2053
- meta.id = original.id;
2054
- meta.title = original.title;
2055
- meta.workspace = original.workspace;
2056
- meta.createdAt = original.createdAt;
2057
- meta.lastActivityAt = original.lastActivityAt;
2058
- if (original.source === undefined)
2059
- delete meta.source;
2060
- else
2061
- meta.source = structuredClone(original.source);
2062
- meta.nextSequence = original.nextSequence;
2063
- if (original.automaticTitlePending === undefined)
2064
- delete meta.automaticTitlePending;
2065
- else
2066
- meta.automaticTitlePending = original.automaticTitlePending;
2067
- if (original.resume === undefined)
2068
- delete meta.resume;
2069
- else
2070
- meta.resume = structuredClone(original.resume);
2071
- if (original.segments === undefined)
2072
- delete meta.segments;
2073
- else
2074
- meta.segments = structuredClone(original.segments);
2075
- }
2076
- function isObject(value) {
2077
- return value !== null && typeof value === 'object' && !Array.isArray(value);
2078
- }