@m4ike1/ion-coding-agent 0.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (1126) hide show
  1. package/CHANGELOG.md +5747 -0
  2. package/README.md +738 -0
  3. package/dist/bun/cli.d.ts +5 -0
  4. package/dist/bun/cli.d.ts.map +1 -0
  5. package/dist/bun/cli.js +5 -0
  6. package/dist/bun/cli.js.map +1 -0
  7. package/dist/bun/restore-sandbox-env.d.ts +17 -0
  8. package/dist/bun/restore-sandbox-env.d.ts.map +1 -0
  9. package/dist/bun/restore-sandbox-env.js +36 -0
  10. package/dist/bun/restore-sandbox-env.js.map +1 -0
  11. package/dist/bun/runtime-setup.d.ts +2 -0
  12. package/dist/bun/runtime-setup.d.ts.map +1 -0
  13. package/dist/bun/runtime-setup.js +9 -0
  14. package/dist/bun/runtime-setup.js.map +1 -0
  15. package/dist/bun/sandbox-env-setup.d.ts +2 -0
  16. package/dist/bun/sandbox-env-setup.d.ts.map +1 -0
  17. package/dist/bun/sandbox-env-setup.js +4 -0
  18. package/dist/bun/sandbox-env-setup.js.map +1 -0
  19. package/dist/bundle/chunks/anthropic-messages-RPVA4Z4Y.js +6 -0
  20. package/dist/bundle/chunks/anthropic.js +75 -0
  21. package/dist/bundle/chunks/azure-openai-responses-AJS3XTKL.js +2 -0
  22. package/dist/bundle/chunks/bedrock-converse-stream.js +78 -0
  23. package/dist/bundle/chunks/chunk-2MOZ6JBC.js +2 -0
  24. package/dist/bundle/chunks/chunk-3BIJ3AQO.js +12 -0
  25. package/dist/bundle/chunks/chunk-47K3I3YT.js +6 -0
  26. package/dist/bundle/chunks/chunk-4BN67GCJ.js +1664 -0
  27. package/dist/bundle/chunks/chunk-4PN6UIWX.js +2 -0
  28. package/dist/bundle/chunks/chunk-4TQA6ATT.js +4 -0
  29. package/dist/bundle/chunks/chunk-5NVSYJOG.js +2 -0
  30. package/dist/bundle/chunks/chunk-7OJL7DR5.js +2 -0
  31. package/dist/bundle/chunks/chunk-BEER2HEL.js +2 -0
  32. package/dist/bundle/chunks/chunk-CQX3HQAT.js +2 -0
  33. package/dist/bundle/chunks/chunk-FBMFFBV2.js +2 -0
  34. package/dist/bundle/chunks/chunk-GAZIWLQB.js +2 -0
  35. package/dist/bundle/chunks/chunk-HFYRAIWC.js +44 -0
  36. package/dist/bundle/chunks/chunk-IH7HUXWH.js +2 -0
  37. package/dist/bundle/chunks/chunk-LPP2XRBR.js +11 -0
  38. package/dist/bundle/chunks/chunk-LUTYILPM.js +25 -0
  39. package/dist/bundle/chunks/chunk-Q3ZNVFWD.js +42 -0
  40. package/dist/bundle/chunks/chunk-QNBVCBN3.js +2 -0
  41. package/dist/bundle/chunks/chunk-SWVWKUIA.js +2 -0
  42. package/dist/bundle/chunks/chunk-SY4QP6EI.js +2 -0
  43. package/dist/bundle/chunks/chunk-TVAWBPPS.js +2 -0
  44. package/dist/bundle/chunks/chunk-WPN6KEON.js +2 -0
  45. package/dist/bundle/chunks/chunk-WRID246J.js +2 -0
  46. package/dist/bundle/chunks/github-copilot.js +2 -0
  47. package/dist/bundle/chunks/google-generative-ai-S7SD5HC7.js +2 -0
  48. package/dist/bundle/chunks/google-vertex-NUNHA7QM.js +2 -0
  49. package/dist/bundle/chunks/https-proxy-agent-O2332S4O.js +13 -0
  50. package/dist/bundle/chunks/image-resize-worker.js +2 -0
  51. package/dist/bundle/chunks/ion-messages-KTW6MD7U.js +8 -0
  52. package/dist/bundle/chunks/kimi-coding.js +2 -0
  53. package/dist/bundle/chunks/lib-D4EQQPRR.js +9 -0
  54. package/dist/bundle/chunks/mistral-conversations-C7I3G2LA.js +5 -0
  55. package/dist/bundle/chunks/multipart-parser-PL2BXRDT.js +3 -0
  56. package/dist/bundle/chunks/node-7OQEATQA.js +2 -0
  57. package/dist/bundle/chunks/node-QIUI6CIW.js +16 -0
  58. package/dist/bundle/chunks/openai-codex-responses-2KRULDYR.js +10 -0
  59. package/dist/bundle/chunks/openai-codex.js +75 -0
  60. package/dist/bundle/chunks/openai-completions-64KX63FN.js +7 -0
  61. package/dist/bundle/chunks/openai-responses-QF3PPSTS.js +2 -0
  62. package/dist/bundle/chunks/openrouter-images-GQVXT3PO.js +2 -0
  63. package/dist/bundle/chunks/openrouter.js +75 -0
  64. package/dist/bundle/chunks/radius.js +75 -0
  65. package/dist/bundle/chunks/src-AZ7LBHGY.js +4 -0
  66. package/dist/bundle/chunks/xai.js +2 -0
  67. package/dist/bundle/cli.js +3 -0
  68. package/dist/bundle/index.js +2 -0
  69. package/dist/bundle/rpc-entry.js +3 -0
  70. package/dist/cli/args.d.ts +61 -0
  71. package/dist/cli/args.d.ts.map +1 -0
  72. package/dist/cli/args.js +440 -0
  73. package/dist/cli/args.js.map +1 -0
  74. package/dist/cli/auth-check.d.ts +19 -0
  75. package/dist/cli/auth-check.d.ts.map +1 -0
  76. package/dist/cli/auth-check.js +50 -0
  77. package/dist/cli/auth-check.js.map +1 -0
  78. package/dist/cli/auth-command.d.ts +24 -0
  79. package/dist/cli/auth-command.d.ts.map +1 -0
  80. package/dist/cli/auth-command.js +103 -0
  81. package/dist/cli/auth-command.js.map +1 -0
  82. package/dist/cli/config-selector.d.ts +16 -0
  83. package/dist/cli/config-selector.d.ts.map +1 -0
  84. package/dist/cli/config-selector.js +32 -0
  85. package/dist/cli/config-selector.js.map +1 -0
  86. package/dist/cli/credential-print.d.ts +13 -0
  87. package/dist/cli/credential-print.d.ts.map +1 -0
  88. package/dist/cli/credential-print.js +76 -0
  89. package/dist/cli/credential-print.js.map +1 -0
  90. package/dist/cli/file-processor.d.ts +15 -0
  91. package/dist/cli/file-processor.d.ts.map +1 -0
  92. package/dist/cli/file-processor.js +71 -0
  93. package/dist/cli/file-processor.js.map +1 -0
  94. package/dist/cli/initial-message.d.ts +18 -0
  95. package/dist/cli/initial-message.d.ts.map +1 -0
  96. package/dist/cli/initial-message.js +22 -0
  97. package/dist/cli/initial-message.js.map +1 -0
  98. package/dist/cli/list-models.d.ts +9 -0
  99. package/dist/cli/list-models.d.ts.map +1 -0
  100. package/dist/cli/list-models.js +98 -0
  101. package/dist/cli/list-models.js.map +1 -0
  102. package/dist/cli/project-trust.d.ts +10 -0
  103. package/dist/cli/project-trust.d.ts.map +1 -0
  104. package/dist/cli/project-trust.js +48 -0
  105. package/dist/cli/project-trust.js.map +1 -0
  106. package/dist/cli/session-picker.d.ts +10 -0
  107. package/dist/cli/session-picker.d.ts.map +1 -0
  108. package/dist/cli/session-picker.js +36 -0
  109. package/dist/cli/session-picker.js.map +1 -0
  110. package/dist/cli/setup.d.ts +2 -0
  111. package/dist/cli/setup.d.ts.map +1 -0
  112. package/dist/cli/setup.js +12 -0
  113. package/dist/cli/setup.js.map +1 -0
  114. package/dist/cli/startup-ui.d.ts +20 -0
  115. package/dist/cli/startup-ui.d.ts.map +1 -0
  116. package/dist/cli/startup-ui.js +185 -0
  117. package/dist/cli/startup-ui.js.map +1 -0
  118. package/dist/cli.d.ts +3 -0
  119. package/dist/cli.d.ts.map +1 -0
  120. package/dist/cli.js +6 -0
  121. package/dist/cli.js.map +1 -0
  122. package/dist/config.d.ts +122 -0
  123. package/dist/config.d.ts.map +1 -0
  124. package/dist/config.js +609 -0
  125. package/dist/config.js.map +1 -0
  126. package/dist/core/agent-session-runtime.d.ts +119 -0
  127. package/dist/core/agent-session-runtime.d.ts.map +1 -0
  128. package/dist/core/agent-session-runtime.js +317 -0
  129. package/dist/core/agent-session-runtime.js.map +1 -0
  130. package/dist/core/agent-session-services.d.ts +86 -0
  131. package/dist/core/agent-session-services.d.ts.map +1 -0
  132. package/dist/core/agent-session-services.js +134 -0
  133. package/dist/core/agent-session-services.js.map +1 -0
  134. package/dist/core/agent-session.d.ts +725 -0
  135. package/dist/core/agent-session.d.ts.map +1 -0
  136. package/dist/core/agent-session.js +2968 -0
  137. package/dist/core/agent-session.js.map +1 -0
  138. package/dist/core/auth-guidance.d.ts +5 -0
  139. package/dist/core/auth-guidance.d.ts.map +1 -0
  140. package/dist/core/auth-guidance.js +21 -0
  141. package/dist/core/auth-guidance.js.map +1 -0
  142. package/dist/core/auth-storage.d.ts +72 -0
  143. package/dist/core/auth-storage.d.ts.map +1 -0
  144. package/dist/core/auth-storage.js +426 -0
  145. package/dist/core/auth-storage.js.map +1 -0
  146. package/dist/core/bash-executor.d.ts +32 -0
  147. package/dist/core/bash-executor.d.ts.map +1 -0
  148. package/dist/core/bash-executor.js +111 -0
  149. package/dist/core/bash-executor.js.map +1 -0
  150. package/dist/core/cache-stats.d.ts +49 -0
  151. package/dist/core/cache-stats.d.ts.map +1 -0
  152. package/dist/core/cache-stats.js +101 -0
  153. package/dist/core/cache-stats.js.map +1 -0
  154. package/dist/core/compaction/branch-summarization.d.ts +98 -0
  155. package/dist/core/compaction/branch-summarization.d.ts.map +1 -0
  156. package/dist/core/compaction/branch-summarization.js +251 -0
  157. package/dist/core/compaction/branch-summarization.js.map +1 -0
  158. package/dist/core/compaction/compaction.d.ts +145 -0
  159. package/dist/core/compaction/compaction.d.ts.map +1 -0
  160. package/dist/core/compaction/compaction.js +690 -0
  161. package/dist/core/compaction/compaction.js.map +1 -0
  162. package/dist/core/compaction/index.d.ts +7 -0
  163. package/dist/core/compaction/index.d.ts.map +1 -0
  164. package/dist/core/compaction/index.js +7 -0
  165. package/dist/core/compaction/index.js.map +1 -0
  166. package/dist/core/compaction/utils.d.ts +38 -0
  167. package/dist/core/compaction/utils.d.ts.map +1 -0
  168. package/dist/core/compaction/utils.js +142 -0
  169. package/dist/core/compaction/utils.js.map +1 -0
  170. package/dist/core/defaults.d.ts +4 -0
  171. package/dist/core/defaults.d.ts.map +1 -0
  172. package/dist/core/defaults.js +11 -0
  173. package/dist/core/defaults.js.map +1 -0
  174. package/dist/core/diagnostics.d.ts +15 -0
  175. package/dist/core/diagnostics.d.ts.map +1 -0
  176. package/dist/core/diagnostics.js +2 -0
  177. package/dist/core/diagnostics.js.map +1 -0
  178. package/dist/core/event-bus.d.ts +9 -0
  179. package/dist/core/event-bus.d.ts.map +1 -0
  180. package/dist/core/event-bus.js +25 -0
  181. package/dist/core/event-bus.js.map +1 -0
  182. package/dist/core/exec.d.ts +29 -0
  183. package/dist/core/exec.d.ts.map +1 -0
  184. package/dist/core/exec.js +75 -0
  185. package/dist/core/exec.js.map +1 -0
  186. package/dist/core/experimental.d.ts +2 -0
  187. package/dist/core/experimental.d.ts.map +1 -0
  188. package/dist/core/experimental.js +4 -0
  189. package/dist/core/experimental.js.map +1 -0
  190. package/dist/core/export-html/ansi-to-html.d.ts +22 -0
  191. package/dist/core/export-html/ansi-to-html.d.ts.map +1 -0
  192. package/dist/core/export-html/ansi-to-html.js +249 -0
  193. package/dist/core/export-html/ansi-to-html.js.map +1 -0
  194. package/dist/core/export-html/index.d.ts +37 -0
  195. package/dist/core/export-html/index.d.ts.map +1 -0
  196. package/dist/core/export-html/index.js +226 -0
  197. package/dist/core/export-html/index.js.map +1 -0
  198. package/dist/core/export-html/template.css +1066 -0
  199. package/dist/core/export-html/template.html +55 -0
  200. package/dist/core/export-html/template.js +1871 -0
  201. package/dist/core/export-html/tool-renderer.d.ts +34 -0
  202. package/dist/core/export-html/tool-renderer.d.ts.map +1 -0
  203. package/dist/core/export-html/tool-renderer.js +108 -0
  204. package/dist/core/export-html/tool-renderer.js.map +1 -0
  205. package/dist/core/export-html/vendor/highlight.min.js +1213 -0
  206. package/dist/core/export-html/vendor/marked.min.js +78 -0
  207. package/dist/core/extensions/index.d.ts +12 -0
  208. package/dist/core/extensions/index.d.ts.map +1 -0
  209. package/dist/core/extensions/index.js +9 -0
  210. package/dist/core/extensions/index.js.map +1 -0
  211. package/dist/core/extensions/loader.d.ts +23 -0
  212. package/dist/core/extensions/loader.d.ts.map +1 -0
  213. package/dist/core/extensions/loader.js +655 -0
  214. package/dist/core/extensions/loader.js.map +1 -0
  215. package/dist/core/extensions/runner.d.ts +178 -0
  216. package/dist/core/extensions/runner.d.ts.map +1 -0
  217. package/dist/core/extensions/runner.js +1011 -0
  218. package/dist/core/extensions/runner.js.map +1 -0
  219. package/dist/core/extensions/types.d.ts +1375 -0
  220. package/dist/core/extensions/types.d.ts.map +1 -0
  221. package/dist/core/extensions/types.js +54 -0
  222. package/dist/core/extensions/types.js.map +1 -0
  223. package/dist/core/extensions/wrapper.d.ts +20 -0
  224. package/dist/core/extensions/wrapper.d.ts.map +1 -0
  225. package/dist/core/extensions/wrapper.js +41 -0
  226. package/dist/core/extensions/wrapper.js.map +1 -0
  227. package/dist/core/footer-data-provider.d.ts +64 -0
  228. package/dist/core/footer-data-provider.d.ts.map +1 -0
  229. package/dist/core/footer-data-provider.js +338 -0
  230. package/dist/core/footer-data-provider.js.map +1 -0
  231. package/dist/core/http-dispatcher.d.ts +22 -0
  232. package/dist/core/http-dispatcher.d.ts.map +1 -0
  233. package/dist/core/http-dispatcher.js +98 -0
  234. package/dist/core/http-dispatcher.js.map +1 -0
  235. package/dist/core/index.d.ts +13 -0
  236. package/dist/core/index.d.ts.map +1 -0
  237. package/dist/core/index.js +13 -0
  238. package/dist/core/index.js.map +1 -0
  239. package/dist/core/ion-manifest.d.ts +8 -0
  240. package/dist/core/ion-manifest.d.ts.map +1 -0
  241. package/dist/core/ion-manifest.js +26 -0
  242. package/dist/core/ion-manifest.js.map +1 -0
  243. package/dist/core/keybindings.d.ts +475 -0
  244. package/dist/core/keybindings.d.ts.map +1 -0
  245. package/dist/core/keybindings.js +321 -0
  246. package/dist/core/keybindings.js.map +1 -0
  247. package/dist/core/messages.d.ts +77 -0
  248. package/dist/core/messages.d.ts.map +1 -0
  249. package/dist/core/messages.js +123 -0
  250. package/dist/core/messages.js.map +1 -0
  251. package/dist/core/model-config.d.ts +591 -0
  252. package/dist/core/model-config.d.ts.map +1 -0
  253. package/dist/core/model-config.js +259 -0
  254. package/dist/core/model-config.js.map +1 -0
  255. package/dist/core/model-registry.d.ts +49 -0
  256. package/dist/core/model-registry.d.ts.map +1 -0
  257. package/dist/core/model-registry.js +115 -0
  258. package/dist/core/model-registry.js.map +1 -0
  259. package/dist/core/model-resolver.d.ts +124 -0
  260. package/dist/core/model-resolver.d.ts.map +1 -0
  261. package/dist/core/model-resolver.js +591 -0
  262. package/dist/core/model-resolver.js.map +1 -0
  263. package/dist/core/model-runtime.d.ts +101 -0
  264. package/dist/core/model-runtime.d.ts.map +1 -0
  265. package/dist/core/model-runtime.js +606 -0
  266. package/dist/core/model-runtime.js.map +1 -0
  267. package/dist/core/models-store.d.ts +22 -0
  268. package/dist/core/models-store.d.ts.map +1 -0
  269. package/dist/core/models-store.js +115 -0
  270. package/dist/core/models-store.js.map +1 -0
  271. package/dist/core/output-guard.d.ts +7 -0
  272. package/dist/core/output-guard.d.ts.map +1 -0
  273. package/dist/core/output-guard.js +89 -0
  274. package/dist/core/output-guard.js.map +1 -0
  275. package/dist/core/package-manager.d.ts +216 -0
  276. package/dist/core/package-manager.d.ts.map +1 -0
  277. package/dist/core/package-manager.js +2207 -0
  278. package/dist/core/package-manager.js.map +1 -0
  279. package/dist/core/project-trust.d.ts +15 -0
  280. package/dist/core/project-trust.d.ts.map +1 -0
  281. package/dist/core/project-trust.js +59 -0
  282. package/dist/core/project-trust.js.map +1 -0
  283. package/dist/core/prompt-templates.d.ts +54 -0
  284. package/dist/core/prompt-templates.d.ts.map +1 -0
  285. package/dist/core/prompt-templates.js +236 -0
  286. package/dist/core/prompt-templates.js.map +1 -0
  287. package/dist/core/provider-attribution.d.ts +4 -0
  288. package/dist/core/provider-attribution.d.ts.map +1 -0
  289. package/dist/core/provider-attribution.js +72 -0
  290. package/dist/core/provider-attribution.js.map +1 -0
  291. package/dist/core/provider-composer.d.ts +58 -0
  292. package/dist/core/provider-composer.d.ts.map +1 -0
  293. package/dist/core/provider-composer.js +402 -0
  294. package/dist/core/provider-composer.js.map +1 -0
  295. package/dist/core/radius.d.ts +2 -0
  296. package/dist/core/radius.d.ts.map +1 -0
  297. package/dist/core/radius.js +2 -0
  298. package/dist/core/radius.js.map +1 -0
  299. package/dist/core/remote-catalog-provider.d.ts +5 -0
  300. package/dist/core/remote-catalog-provider.d.ts.map +1 -0
  301. package/dist/core/remote-catalog-provider.js +137 -0
  302. package/dist/core/remote-catalog-provider.js.map +1 -0
  303. package/dist/core/resolve-config-value.d.ts +30 -0
  304. package/dist/core/resolve-config-value.d.ts.map +1 -0
  305. package/dist/core/resolve-config-value.js +247 -0
  306. package/dist/core/resolve-config-value.js.map +1 -0
  307. package/dist/core/resource-loader.d.ts +221 -0
  308. package/dist/core/resource-loader.d.ts.map +1 -0
  309. package/dist/core/resource-loader.js +875 -0
  310. package/dist/core/resource-loader.js.map +1 -0
  311. package/dist/core/runtime-credentials.d.ts +15 -0
  312. package/dist/core/runtime-credentials.d.ts.map +1 -0
  313. package/dist/core/runtime-credentials.js +39 -0
  314. package/dist/core/runtime-credentials.js.map +1 -0
  315. package/dist/core/sdk.d.ts +108 -0
  316. package/dist/core/sdk.d.ts.map +1 -0
  317. package/dist/core/sdk.js +285 -0
  318. package/dist/core/sdk.js.map +1 -0
  319. package/dist/core/session-cwd.d.ts +19 -0
  320. package/dist/core/session-cwd.d.ts.map +1 -0
  321. package/dist/core/session-cwd.js +38 -0
  322. package/dist/core/session-cwd.js.map +1 -0
  323. package/dist/core/session-export.d.ts +4 -0
  324. package/dist/core/session-export.d.ts.map +1 -0
  325. package/dist/core/session-export.js +32 -0
  326. package/dist/core/session-export.js.map +1 -0
  327. package/dist/core/session-index.d.ts +67 -0
  328. package/dist/core/session-index.d.ts.map +1 -0
  329. package/dist/core/session-index.js +376 -0
  330. package/dist/core/session-index.js.map +1 -0
  331. package/dist/core/session-manager.d.ts +376 -0
  332. package/dist/core/session-manager.d.ts.map +1 -0
  333. package/dist/core/session-manager.js +1587 -0
  334. package/dist/core/session-manager.js.map +1 -0
  335. package/dist/core/session-naming-runtime.d.ts +153 -0
  336. package/dist/core/session-naming-runtime.d.ts.map +1 -0
  337. package/dist/core/session-naming-runtime.js +336 -0
  338. package/dist/core/session-naming-runtime.js.map +1 -0
  339. package/dist/core/settings-diagnostics.d.ts +9 -0
  340. package/dist/core/settings-diagnostics.d.ts.map +1 -0
  341. package/dist/core/settings-diagnostics.js +21 -0
  342. package/dist/core/settings-diagnostics.js.map +1 -0
  343. package/dist/core/settings-manager.d.ts +375 -0
  344. package/dist/core/settings-manager.d.ts.map +1 -0
  345. package/dist/core/settings-manager.js +1110 -0
  346. package/dist/core/settings-manager.js.map +1 -0
  347. package/dist/core/skills.d.ts +60 -0
  348. package/dist/core/skills.d.ts.map +1 -0
  349. package/dist/core/skills.js +412 -0
  350. package/dist/core/skills.js.map +1 -0
  351. package/dist/core/slash-commands.d.ts +17 -0
  352. package/dist/core/slash-commands.d.ts.map +1 -0
  353. package/dist/core/slash-commands.js +33 -0
  354. package/dist/core/slash-commands.js.map +1 -0
  355. package/dist/core/source-info.d.ts +18 -0
  356. package/dist/core/source-info.d.ts.map +1 -0
  357. package/dist/core/source-info.js +19 -0
  358. package/dist/core/source-info.js.map +1 -0
  359. package/dist/core/system-prompt.d.ts +28 -0
  360. package/dist/core/system-prompt.d.ts.map +1 -0
  361. package/dist/core/system-prompt.js +118 -0
  362. package/dist/core/system-prompt.js.map +1 -0
  363. package/dist/core/telemetry.d.ts +3 -0
  364. package/dist/core/telemetry.d.ts.map +1 -0
  365. package/dist/core/telemetry.js +9 -0
  366. package/dist/core/telemetry.js.map +1 -0
  367. package/dist/core/timings.d.ts +10 -0
  368. package/dist/core/timings.d.ts.map +1 -0
  369. package/dist/core/timings.js +41 -0
  370. package/dist/core/timings.js.map +1 -0
  371. package/dist/core/tools/bash.d.ts +87 -0
  372. package/dist/core/tools/bash.d.ts.map +1 -0
  373. package/dist/core/tools/bash.js +295 -0
  374. package/dist/core/tools/bash.js.map +1 -0
  375. package/dist/core/tools/edit-diff.d.ts +101 -0
  376. package/dist/core/tools/edit-diff.d.ts.map +1 -0
  377. package/dist/core/tools/edit-diff.js +421 -0
  378. package/dist/core/tools/edit-diff.js.map +1 -0
  379. package/dist/core/tools/edit.d.ts +44 -0
  380. package/dist/core/tools/edit.d.ts.map +1 -0
  381. package/dist/core/tools/edit.js +147 -0
  382. package/dist/core/tools/edit.js.map +1 -0
  383. package/dist/core/tools/file-mutation-queue.d.ts +6 -0
  384. package/dist/core/tools/file-mutation-queue.d.ts.map +1 -0
  385. package/dist/core/tools/file-mutation-queue.js +52 -0
  386. package/dist/core/tools/file-mutation-queue.js.map +1 -0
  387. package/dist/core/tools/find.d.ts +42 -0
  388. package/dist/core/tools/find.d.ts.map +1 -0
  389. package/dist/core/tools/find.js +251 -0
  390. package/dist/core/tools/find.js.map +1 -0
  391. package/dist/core/tools/grep.d.ts +53 -0
  392. package/dist/core/tools/grep.d.ts.map +1 -0
  393. package/dist/core/tools/grep.js +463 -0
  394. package/dist/core/tools/grep.js.map +1 -0
  395. package/dist/core/tools/index.d.ts +49 -0
  396. package/dist/core/tools/index.d.ts.map +1 -0
  397. package/dist/core/tools/index.js +147 -0
  398. package/dist/core/tools/index.js.map +1 -0
  399. package/dist/core/tools/ls.d.ts +48 -0
  400. package/dist/core/tools/ls.d.ts.map +1 -0
  401. package/dist/core/tools/ls.js +224 -0
  402. package/dist/core/tools/ls.js.map +1 -0
  403. package/dist/core/tools/output-accumulator.d.ts +52 -0
  404. package/dist/core/tools/output-accumulator.d.ts.map +1 -0
  405. package/dist/core/tools/output-accumulator.js +184 -0
  406. package/dist/core/tools/output-accumulator.js.map +1 -0
  407. package/dist/core/tools/path-utils.d.ts +10 -0
  408. package/dist/core/tools/path-utils.d.ts.map +1 -0
  409. package/dist/core/tools/path-utils.js +99 -0
  410. package/dist/core/tools/path-utils.js.map +1 -0
  411. package/dist/core/tools/powershell.d.ts +16 -0
  412. package/dist/core/tools/powershell.d.ts.map +1 -0
  413. package/dist/core/tools/powershell.js +39 -0
  414. package/dist/core/tools/powershell.js.map +1 -0
  415. package/dist/core/tools/read.d.ts +39 -0
  416. package/dist/core/tools/read.d.ts.map +1 -0
  417. package/dist/core/tools/read.js +165 -0
  418. package/dist/core/tools/read.js.map +1 -0
  419. package/dist/core/tools/render-utils.d.ts +24 -0
  420. package/dist/core/tools/render-utils.d.ts.map +1 -0
  421. package/dist/core/tools/render-utils.js +65 -0
  422. package/dist/core/tools/render-utils.js.map +1 -0
  423. package/dist/core/tools/renderers/bash.d.ts +12 -0
  424. package/dist/core/tools/renderers/bash.d.ts.map +1 -0
  425. package/dist/core/tools/renderers/bash.js +130 -0
  426. package/dist/core/tools/renderers/bash.js.map +1 -0
  427. package/dist/core/tools/renderers/edit.d.ts +23 -0
  428. package/dist/core/tools/renderers/edit.d.ts.map +1 -0
  429. package/dist/core/tools/renderers/edit.js +167 -0
  430. package/dist/core/tools/renderers/edit.js.map +1 -0
  431. package/dist/core/tools/renderers/find.d.ts +10 -0
  432. package/dist/core/tools/renderers/find.d.ts.map +1 -0
  433. package/dist/core/tools/renderers/find.js +64 -0
  434. package/dist/core/tools/renderers/find.js.map +1 -0
  435. package/dist/core/tools/renderers/grep.d.ts +10 -0
  436. package/dist/core/tools/renderers/grep.d.ts.map +1 -0
  437. package/dist/core/tools/renderers/grep.js +69 -0
  438. package/dist/core/tools/renderers/grep.js.map +1 -0
  439. package/dist/core/tools/renderers/index.d.ts +29 -0
  440. package/dist/core/tools/renderers/index.d.ts.map +1 -0
  441. package/dist/core/tools/renderers/index.js +50 -0
  442. package/dist/core/tools/renderers/index.js.map +1 -0
  443. package/dist/core/tools/renderers/ls.d.ts +10 -0
  444. package/dist/core/tools/renderers/ls.d.ts.map +1 -0
  445. package/dist/core/tools/renderers/ls.js +66 -0
  446. package/dist/core/tools/renderers/ls.js.map +1 -0
  447. package/dist/core/tools/renderers/read.d.ts +11 -0
  448. package/dist/core/tools/renderers/read.d.ts.map +1 -0
  449. package/dist/core/tools/renderers/read.js +129 -0
  450. package/dist/core/tools/renderers/read.js.map +1 -0
  451. package/dist/core/tools/renderers/webfetch.d.ts +11 -0
  452. package/dist/core/tools/renderers/webfetch.d.ts.map +1 -0
  453. package/dist/core/tools/renderers/webfetch.js +89 -0
  454. package/dist/core/tools/renderers/webfetch.js.map +1 -0
  455. package/dist/core/tools/renderers/write.d.ts +10 -0
  456. package/dist/core/tools/renderers/write.d.ts.map +1 -0
  457. package/dist/core/tools/renderers/write.js +153 -0
  458. package/dist/core/tools/renderers/write.js.map +1 -0
  459. package/dist/core/tools/tool-definition-wrapper.d.ts +14 -0
  460. package/dist/core/tools/tool-definition-wrapper.d.ts.map +1 -0
  461. package/dist/core/tools/tool-definition-wrapper.js +36 -0
  462. package/dist/core/tools/tool-definition-wrapper.js.map +1 -0
  463. package/dist/core/tools/truncate.d.ts +70 -0
  464. package/dist/core/tools/truncate.d.ts.map +1 -0
  465. package/dist/core/tools/truncate.js +215 -0
  466. package/dist/core/tools/truncate.js.map +1 -0
  467. package/dist/core/tools/webextract.d.ts +36 -0
  468. package/dist/core/tools/webextract.d.ts.map +1 -0
  469. package/dist/core/tools/webextract.js +130 -0
  470. package/dist/core/tools/webextract.js.map +1 -0
  471. package/dist/core/tools/webfetch.d.ts +104 -0
  472. package/dist/core/tools/webfetch.d.ts.map +1 -0
  473. package/dist/core/tools/webfetch.js +231 -0
  474. package/dist/core/tools/webfetch.js.map +1 -0
  475. package/dist/core/tools/write.d.ts +30 -0
  476. package/dist/core/tools/write.d.ts.map +1 -0
  477. package/dist/core/tools/write.js +61 -0
  478. package/dist/core/tools/write.js.map +1 -0
  479. package/dist/core/trust-manager.d.ts +36 -0
  480. package/dist/core/trust-manager.d.ts.map +1 -0
  481. package/dist/core/trust-manager.js +203 -0
  482. package/dist/core/trust-manager.js.map +1 -0
  483. package/dist/core/usage-totals.d.ts +19 -0
  484. package/dist/core/usage-totals.d.ts.map +1 -0
  485. package/dist/core/usage-totals.js +52 -0
  486. package/dist/core/usage-totals.js.map +1 -0
  487. package/dist/core/webfetch/backend-exa.d.ts +65 -0
  488. package/dist/core/webfetch/backend-exa.d.ts.map +1 -0
  489. package/dist/core/webfetch/backend-exa.js +282 -0
  490. package/dist/core/webfetch/backend-exa.js.map +1 -0
  491. package/dist/core/webfetch/backend-firecrawl.d.ts +59 -0
  492. package/dist/core/webfetch/backend-firecrawl.d.ts.map +1 -0
  493. package/dist/core/webfetch/backend-firecrawl.js +339 -0
  494. package/dist/core/webfetch/backend-firecrawl.js.map +1 -0
  495. package/dist/core/webfetch/backend-undici.d.ts +21 -0
  496. package/dist/core/webfetch/backend-undici.d.ts.map +1 -0
  497. package/dist/core/webfetch/backend-undici.js +109 -0
  498. package/dist/core/webfetch/backend-undici.js.map +1 -0
  499. package/dist/core/webfetch/backend.d.ts +45 -0
  500. package/dist/core/webfetch/backend.d.ts.map +1 -0
  501. package/dist/core/webfetch/backend.js +9 -0
  502. package/dist/core/webfetch/backend.js.map +1 -0
  503. package/dist/core/webfetch/doc-store.d.ts +45 -0
  504. package/dist/core/webfetch/doc-store.d.ts.map +1 -0
  505. package/dist/core/webfetch/doc-store.js +57 -0
  506. package/dist/core/webfetch/doc-store.js.map +1 -0
  507. package/dist/core/webfetch/guardrails.d.ts +75 -0
  508. package/dist/core/webfetch/guardrails.d.ts.map +1 -0
  509. package/dist/core/webfetch/guardrails.js +195 -0
  510. package/dist/core/webfetch/guardrails.js.map +1 -0
  511. package/dist/core/webfetch/robots.d.ts +46 -0
  512. package/dist/core/webfetch/robots.d.ts.map +1 -0
  513. package/dist/core/webfetch/robots.js +153 -0
  514. package/dist/core/webfetch/robots.js.map +1 -0
  515. package/dist/core/webfetch/search-intent.d.ts +59 -0
  516. package/dist/core/webfetch/search-intent.d.ts.map +1 -0
  517. package/dist/core/webfetch/search-intent.js +89 -0
  518. package/dist/core/webfetch/search-intent.js.map +1 -0
  519. package/dist/core/webfetch/search-tags.d.ts +23 -0
  520. package/dist/core/webfetch/search-tags.d.ts.map +1 -0
  521. package/dist/core/webfetch/search-tags.js +118 -0
  522. package/dist/core/webfetch/search-tags.js.map +1 -0
  523. package/dist/env-compat.d.ts +2 -0
  524. package/dist/env-compat.d.ts.map +1 -0
  525. package/dist/env-compat.js +17 -0
  526. package/dist/env-compat.js.map +1 -0
  527. package/dist/extensions/cue/autocomplete.d.ts +126 -0
  528. package/dist/extensions/cue/autocomplete.d.ts.map +1 -0
  529. package/dist/extensions/cue/autocomplete.js +744 -0
  530. package/dist/extensions/cue/autocomplete.js.map +1 -0
  531. package/dist/extensions/cue/index.d.ts +3 -0
  532. package/dist/extensions/cue/index.d.ts.map +1 -0
  533. package/dist/extensions/cue/index.js +341 -0
  534. package/dist/extensions/cue/index.js.map +1 -0
  535. package/dist/extensions/index.d.ts +13 -0
  536. package/dist/extensions/index.d.ts.map +1 -0
  537. package/dist/extensions/index.js +18 -0
  538. package/dist/extensions/index.js.map +1 -0
  539. package/dist/extensions/llama/client.d.ts +67 -0
  540. package/dist/extensions/llama/client.d.ts.map +1 -0
  541. package/dist/extensions/llama/client.js +309 -0
  542. package/dist/extensions/llama/client.js.map +1 -0
  543. package/dist/extensions/llama/huggingface.d.ts +23 -0
  544. package/dist/extensions/llama/huggingface.d.ts.map +1 -0
  545. package/dist/extensions/llama/huggingface.js +141 -0
  546. package/dist/extensions/llama/huggingface.js.map +1 -0
  547. package/dist/extensions/llama/index.d.ts +3 -0
  548. package/dist/extensions/llama/index.d.ts.map +1 -0
  549. package/dist/extensions/llama/index.js +219 -0
  550. package/dist/extensions/llama/index.js.map +1 -0
  551. package/dist/extensions/llama/provider.d.ts +12 -0
  552. package/dist/extensions/llama/provider.d.ts.map +1 -0
  553. package/dist/extensions/llama/provider.js +146 -0
  554. package/dist/extensions/llama/provider.js.map +1 -0
  555. package/dist/extensions/llama/ui.d.ts +42 -0
  556. package/dist/extensions/llama/ui.d.ts.map +1 -0
  557. package/dist/extensions/llama/ui.js +416 -0
  558. package/dist/extensions/llama/ui.js.map +1 -0
  559. package/dist/index.d.ts +36 -0
  560. package/dist/index.d.ts.map +1 -0
  561. package/dist/index.js +48 -0
  562. package/dist/index.js.map +1 -0
  563. package/dist/main.d.ts +17 -0
  564. package/dist/main.d.ts.map +1 -0
  565. package/dist/main.js +820 -0
  566. package/dist/main.js.map +1 -0
  567. package/dist/migrations.d.ts +33 -0
  568. package/dist/migrations.d.ts.map +1 -0
  569. package/dist/migrations.js +288 -0
  570. package/dist/migrations.js.map +1 -0
  571. package/dist/modes/index.d.ts +10 -0
  572. package/dist/modes/index.d.ts.map +1 -0
  573. package/dist/modes/index.js +8 -0
  574. package/dist/modes/index.js.map +1 -0
  575. package/dist/modes/interactive/assets/clankolas.png +0 -0
  576. package/dist/modes/interactive/chat-viewport.d.ts +20 -0
  577. package/dist/modes/interactive/chat-viewport.d.ts.map +1 -0
  578. package/dist/modes/interactive/chat-viewport.js +28 -0
  579. package/dist/modes/interactive/chat-viewport.js.map +1 -0
  580. package/dist/modes/interactive/components/armin.d.ts +34 -0
  581. package/dist/modes/interactive/components/armin.d.ts.map +1 -0
  582. package/dist/modes/interactive/components/armin.js +333 -0
  583. package/dist/modes/interactive/components/armin.js.map +1 -0
  584. package/dist/modes/interactive/components/assistant-message.d.ts +26 -0
  585. package/dist/modes/interactive/components/assistant-message.d.ts.map +1 -0
  586. package/dist/modes/interactive/components/assistant-message.js +171 -0
  587. package/dist/modes/interactive/components/assistant-message.js.map +1 -0
  588. package/dist/modes/interactive/components/bash-execution.d.ts +34 -0
  589. package/dist/modes/interactive/components/bash-execution.d.ts.map +1 -0
  590. package/dist/modes/interactive/components/bash-execution.js +175 -0
  591. package/dist/modes/interactive/components/bash-execution.js.map +1 -0
  592. package/dist/modes/interactive/components/bordered-loader.d.ts +16 -0
  593. package/dist/modes/interactive/components/bordered-loader.d.ts.map +1 -0
  594. package/dist/modes/interactive/components/bordered-loader.js +54 -0
  595. package/dist/modes/interactive/components/bordered-loader.js.map +1 -0
  596. package/dist/modes/interactive/components/branch-summary-message.d.ts +16 -0
  597. package/dist/modes/interactive/components/branch-summary-message.d.ts.map +1 -0
  598. package/dist/modes/interactive/components/branch-summary-message.js +44 -0
  599. package/dist/modes/interactive/components/branch-summary-message.js.map +1 -0
  600. package/dist/modes/interactive/components/compaction-summary-message.d.ts +16 -0
  601. package/dist/modes/interactive/components/compaction-summary-message.d.ts.map +1 -0
  602. package/dist/modes/interactive/components/compaction-summary-message.js +45 -0
  603. package/dist/modes/interactive/components/compaction-summary-message.js.map +1 -0
  604. package/dist/modes/interactive/components/config-selector.d.ts +102 -0
  605. package/dist/modes/interactive/components/config-selector.d.ts.map +1 -0
  606. package/dist/modes/interactive/components/config-selector.js +770 -0
  607. package/dist/modes/interactive/components/config-selector.js.map +1 -0
  608. package/dist/modes/interactive/components/countdown-timer.d.ts +14 -0
  609. package/dist/modes/interactive/components/countdown-timer.d.ts.map +1 -0
  610. package/dist/modes/interactive/components/countdown-timer.js +33 -0
  611. package/dist/modes/interactive/components/countdown-timer.js.map +1 -0
  612. package/dist/modes/interactive/components/custom-editor.d.ts +30 -0
  613. package/dist/modes/interactive/components/custom-editor.d.ts.map +1 -0
  614. package/dist/modes/interactive/components/custom-editor.js +115 -0
  615. package/dist/modes/interactive/components/custom-editor.js.map +1 -0
  616. package/dist/modes/interactive/components/custom-entry.d.ts +19 -0
  617. package/dist/modes/interactive/components/custom-entry.d.ts.map +1 -0
  618. package/dist/modes/interactive/components/custom-entry.js +52 -0
  619. package/dist/modes/interactive/components/custom-entry.js.map +1 -0
  620. package/dist/modes/interactive/components/custom-message.d.ts +22 -0
  621. package/dist/modes/interactive/components/custom-message.d.ts.map +1 -0
  622. package/dist/modes/interactive/components/custom-message.js +87 -0
  623. package/dist/modes/interactive/components/custom-message.js.map +1 -0
  624. package/dist/modes/interactive/components/daxnuts.d.ts +23 -0
  625. package/dist/modes/interactive/components/daxnuts.d.ts.map +1 -0
  626. package/dist/modes/interactive/components/daxnuts.js +140 -0
  627. package/dist/modes/interactive/components/daxnuts.js.map +1 -0
  628. package/dist/modes/interactive/components/diff.d.ts +12 -0
  629. package/dist/modes/interactive/components/diff.d.ts.map +1 -0
  630. package/dist/modes/interactive/components/diff.js +133 -0
  631. package/dist/modes/interactive/components/diff.js.map +1 -0
  632. package/dist/modes/interactive/components/dynamic-border.d.ts +15 -0
  633. package/dist/modes/interactive/components/dynamic-border.d.ts.map +1 -0
  634. package/dist/modes/interactive/components/dynamic-border.js +21 -0
  635. package/dist/modes/interactive/components/dynamic-border.js.map +1 -0
  636. package/dist/modes/interactive/components/earendil-announcement.d.ts +5 -0
  637. package/dist/modes/interactive/components/earendil-announcement.d.ts.map +1 -0
  638. package/dist/modes/interactive/components/earendil-announcement.js +40 -0
  639. package/dist/modes/interactive/components/earendil-announcement.js.map +1 -0
  640. package/dist/modes/interactive/components/extension-editor.d.ts +21 -0
  641. package/dist/modes/interactive/components/extension-editor.d.ts.map +1 -0
  642. package/dist/modes/interactive/components/extension-editor.js +98 -0
  643. package/dist/modes/interactive/components/extension-editor.js.map +1 -0
  644. package/dist/modes/interactive/components/extension-input.d.ts +23 -0
  645. package/dist/modes/interactive/components/extension-input.d.ts.map +1 -0
  646. package/dist/modes/interactive/components/extension-input.js +61 -0
  647. package/dist/modes/interactive/components/extension-input.js.map +1 -0
  648. package/dist/modes/interactive/components/extension-selector.d.ts +26 -0
  649. package/dist/modes/interactive/components/extension-selector.d.ts.map +1 -0
  650. package/dist/modes/interactive/components/extension-selector.js +83 -0
  651. package/dist/modes/interactive/components/extension-selector.js.map +1 -0
  652. package/dist/modes/interactive/components/first-time-setup.d.ts +25 -0
  653. package/dist/modes/interactive/components/first-time-setup.d.ts.map +1 -0
  654. package/dist/modes/interactive/components/first-time-setup.js +103 -0
  655. package/dist/modes/interactive/components/first-time-setup.js.map +1 -0
  656. package/dist/modes/interactive/components/footer.d.ts +32 -0
  657. package/dist/modes/interactive/components/footer.d.ts.map +1 -0
  658. package/dist/modes/interactive/components/footer.js +230 -0
  659. package/dist/modes/interactive/components/footer.js.map +1 -0
  660. package/dist/modes/interactive/components/index.d.ts +34 -0
  661. package/dist/modes/interactive/components/index.d.ts.map +1 -0
  662. package/dist/modes/interactive/components/index.js +35 -0
  663. package/dist/modes/interactive/components/index.js.map +1 -0
  664. package/dist/modes/interactive/components/keybinding-hints.d.ts +13 -0
  665. package/dist/modes/interactive/components/keybinding-hints.d.ts.map +1 -0
  666. package/dist/modes/interactive/components/keybinding-hints.js +36 -0
  667. package/dist/modes/interactive/components/keybinding-hints.js.map +1 -0
  668. package/dist/modes/interactive/components/login-dialog.d.ts +52 -0
  669. package/dist/modes/interactive/components/login-dialog.d.ts.map +1 -0
  670. package/dist/modes/interactive/components/login-dialog.js +188 -0
  671. package/dist/modes/interactive/components/login-dialog.js.map +1 -0
  672. package/dist/modes/interactive/components/markdown-transform.d.ts +3 -0
  673. package/dist/modes/interactive/components/markdown-transform.d.ts.map +1 -0
  674. package/dist/modes/interactive/components/markdown-transform.js +19 -0
  675. package/dist/modes/interactive/components/markdown-transform.js.map +1 -0
  676. package/dist/modes/interactive/components/mermaid.d.ts +11 -0
  677. package/dist/modes/interactive/components/mermaid.d.ts.map +1 -0
  678. package/dist/modes/interactive/components/mermaid.js +75 -0
  679. package/dist/modes/interactive/components/mermaid.js.map +1 -0
  680. package/dist/modes/interactive/components/model-selector.d.ts +60 -0
  681. package/dist/modes/interactive/components/model-selector.d.ts.map +1 -0
  682. package/dist/modes/interactive/components/model-selector.js +361 -0
  683. package/dist/modes/interactive/components/model-selector.js.map +1 -0
  684. package/dist/modes/interactive/components/oauth-selector.d.ts +33 -0
  685. package/dist/modes/interactive/components/oauth-selector.d.ts.map +1 -0
  686. package/dist/modes/interactive/components/oauth-selector.js +163 -0
  687. package/dist/modes/interactive/components/oauth-selector.js.map +1 -0
  688. package/dist/modes/interactive/components/scoped-models-selector.d.ts +46 -0
  689. package/dist/modes/interactive/components/scoped-models-selector.d.ts.map +1 -0
  690. package/dist/modes/interactive/components/scoped-models-selector.js +326 -0
  691. package/dist/modes/interactive/components/scoped-models-selector.js.map +1 -0
  692. package/dist/modes/interactive/components/session-selector-search.d.ts +23 -0
  693. package/dist/modes/interactive/components/session-selector-search.d.ts.map +1 -0
  694. package/dist/modes/interactive/components/session-selector-search.js +155 -0
  695. package/dist/modes/interactive/components/session-selector-search.js.map +1 -0
  696. package/dist/modes/interactive/components/session-selector.d.ts +98 -0
  697. package/dist/modes/interactive/components/session-selector.d.ts.map +1 -0
  698. package/dist/modes/interactive/components/session-selector.js +891 -0
  699. package/dist/modes/interactive/components/session-selector.js.map +1 -0
  700. package/dist/modes/interactive/components/settings-selector.d.ts +98 -0
  701. package/dist/modes/interactive/components/settings-selector.d.ts.map +1 -0
  702. package/dist/modes/interactive/components/settings-selector.js +745 -0
  703. package/dist/modes/interactive/components/settings-selector.js.map +1 -0
  704. package/dist/modes/interactive/components/settings-submenu.d.ts +72 -0
  705. package/dist/modes/interactive/components/settings-submenu.d.ts.map +1 -0
  706. package/dist/modes/interactive/components/settings-submenu.js +165 -0
  707. package/dist/modes/interactive/components/settings-submenu.js.map +1 -0
  708. package/dist/modes/interactive/components/show-images-selector.d.ts +10 -0
  709. package/dist/modes/interactive/components/show-images-selector.d.ts.map +1 -0
  710. package/dist/modes/interactive/components/show-images-selector.js +39 -0
  711. package/dist/modes/interactive/components/show-images-selector.js.map +1 -0
  712. package/dist/modes/interactive/components/skill-invocation-message.d.ts +17 -0
  713. package/dist/modes/interactive/components/skill-invocation-message.d.ts.map +1 -0
  714. package/dist/modes/interactive/components/skill-invocation-message.js +47 -0
  715. package/dist/modes/interactive/components/skill-invocation-message.js.map +1 -0
  716. package/dist/modes/interactive/components/status-indicator.d.ts +30 -0
  717. package/dist/modes/interactive/components/status-indicator.d.ts.map +1 -0
  718. package/dist/modes/interactive/components/status-indicator.js +67 -0
  719. package/dist/modes/interactive/components/status-indicator.js.map +1 -0
  720. package/dist/modes/interactive/components/theme-selector.d.ts +11 -0
  721. package/dist/modes/interactive/components/theme-selector.d.ts.map +1 -0
  722. package/dist/modes/interactive/components/theme-selector.js +50 -0
  723. package/dist/modes/interactive/components/theme-selector.js.map +1 -0
  724. package/dist/modes/interactive/components/thinking-selector.d.ts +23 -0
  725. package/dist/modes/interactive/components/thinking-selector.d.ts.map +1 -0
  726. package/dist/modes/interactive/components/thinking-selector.js +109 -0
  727. package/dist/modes/interactive/components/thinking-selector.js.map +1 -0
  728. package/dist/modes/interactive/components/tool-execution.d.ts +80 -0
  729. package/dist/modes/interactive/components/tool-execution.d.ts.map +1 -0
  730. package/dist/modes/interactive/components/tool-execution.js +328 -0
  731. package/dist/modes/interactive/components/tool-execution.js.map +1 -0
  732. package/dist/modes/interactive/components/tree-selector.d.ts +94 -0
  733. package/dist/modes/interactive/components/tree-selector.d.ts.map +1 -0
  734. package/dist/modes/interactive/components/tree-selector.js +1245 -0
  735. package/dist/modes/interactive/components/tree-selector.js.map +1 -0
  736. package/dist/modes/interactive/components/trust-selector.d.ts +23 -0
  737. package/dist/modes/interactive/components/trust-selector.d.ts.map +1 -0
  738. package/dist/modes/interactive/components/trust-selector.js +91 -0
  739. package/dist/modes/interactive/components/trust-selector.js.map +1 -0
  740. package/dist/modes/interactive/components/user-message-selector.d.ts +30 -0
  741. package/dist/modes/interactive/components/user-message-selector.d.ts.map +1 -0
  742. package/dist/modes/interactive/components/user-message-selector.js +114 -0
  743. package/dist/modes/interactive/components/user-message-selector.js.map +1 -0
  744. package/dist/modes/interactive/components/user-message.d.ts +16 -0
  745. package/dist/modes/interactive/components/user-message.d.ts.map +1 -0
  746. package/dist/modes/interactive/components/user-message.js +49 -0
  747. package/dist/modes/interactive/components/user-message.js.map +1 -0
  748. package/dist/modes/interactive/components/visual-truncate.d.ts +24 -0
  749. package/dist/modes/interactive/components/visual-truncate.d.ts.map +1 -0
  750. package/dist/modes/interactive/components/visual-truncate.js +33 -0
  751. package/dist/modes/interactive/components/visual-truncate.js.map +1 -0
  752. package/dist/modes/interactive/external-editor.d.ts +12 -0
  753. package/dist/modes/interactive/external-editor.d.ts.map +1 -0
  754. package/dist/modes/interactive/external-editor.js +38 -0
  755. package/dist/modes/interactive/external-editor.js.map +1 -0
  756. package/dist/modes/interactive/interactive-mode.d.ts +471 -0
  757. package/dist/modes/interactive/interactive-mode.d.ts.map +1 -0
  758. package/dist/modes/interactive/interactive-mode.js +5735 -0
  759. package/dist/modes/interactive/interactive-mode.js.map +1 -0
  760. package/dist/modes/interactive/model-catalog-refresh.d.ts +7 -0
  761. package/dist/modes/interactive/model-catalog-refresh.d.ts.map +1 -0
  762. package/dist/modes/interactive/model-catalog-refresh.js +34 -0
  763. package/dist/modes/interactive/model-catalog-refresh.js.map +1 -0
  764. package/dist/modes/interactive/model-search.d.ts +12 -0
  765. package/dist/modes/interactive/model-search.d.ts.map +1 -0
  766. package/dist/modes/interactive/model-search.js +15 -0
  767. package/dist/modes/interactive/model-search.js.map +1 -0
  768. package/dist/modes/interactive/session-share.d.ts +16 -0
  769. package/dist/modes/interactive/session-share.d.ts.map +1 -0
  770. package/dist/modes/interactive/session-share.js +184 -0
  771. package/dist/modes/interactive/session-share.js.map +1 -0
  772. package/dist/modes/interactive/theme/dark.json +91 -0
  773. package/dist/modes/interactive/theme/light.json +90 -0
  774. package/dist/modes/interactive/theme/theme-controller.d.ts +41 -0
  775. package/dist/modes/interactive/theme/theme-controller.d.ts.map +1 -0
  776. package/dist/modes/interactive/theme/theme-controller.js +130 -0
  777. package/dist/modes/interactive/theme/theme-controller.js.map +1 -0
  778. package/dist/modes/interactive/theme/theme-json.d.ts +84 -0
  779. package/dist/modes/interactive/theme/theme-json.d.ts.map +1 -0
  780. package/dist/modes/interactive/theme/theme-json.js +130 -0
  781. package/dist/modes/interactive/theme/theme-json.js.map +1 -0
  782. package/dist/modes/interactive/theme/theme-schema.json +356 -0
  783. package/dist/modes/interactive/theme/theme.d.ts +131 -0
  784. package/dist/modes/interactive/theme/theme.d.ts.map +1 -0
  785. package/dist/modes/interactive/theme/theme.js +991 -0
  786. package/dist/modes/interactive/theme/theme.js.map +1 -0
  787. package/dist/modes/interactive/tui-renderer.d.ts +21 -0
  788. package/dist/modes/interactive/tui-renderer.d.ts.map +1 -0
  789. package/dist/modes/interactive/tui-renderer.js +66 -0
  790. package/dist/modes/interactive/tui-renderer.js.map +1 -0
  791. package/dist/modes/json-event.d.ts +34 -0
  792. package/dist/modes/json-event.d.ts.map +1 -0
  793. package/dist/modes/json-event.js +29 -0
  794. package/dist/modes/json-event.js.map +1 -0
  795. package/dist/modes/print-mode.d.ts +28 -0
  796. package/dist/modes/print-mode.d.ts.map +1 -0
  797. package/dist/modes/print-mode.js +142 -0
  798. package/dist/modes/print-mode.js.map +1 -0
  799. package/dist/modes/rpc/jsonl.d.ts +17 -0
  800. package/dist/modes/rpc/jsonl.d.ts.map +1 -0
  801. package/dist/modes/rpc/jsonl.js +49 -0
  802. package/dist/modes/rpc/jsonl.js.map +1 -0
  803. package/dist/modes/rpc/rpc-client.d.ts +254 -0
  804. package/dist/modes/rpc/rpc-client.d.ts.map +1 -0
  805. package/dist/modes/rpc/rpc-client.js +495 -0
  806. package/dist/modes/rpc/rpc-client.js.map +1 -0
  807. package/dist/modes/rpc/rpc-mode.d.ts +20 -0
  808. package/dist/modes/rpc/rpc-mode.d.ts.map +1 -0
  809. package/dist/modes/rpc/rpc-mode.js +657 -0
  810. package/dist/modes/rpc/rpc-mode.js.map +1 -0
  811. package/dist/modes/rpc/rpc-types.d.ts +469 -0
  812. package/dist/modes/rpc/rpc-types.d.ts.map +1 -0
  813. package/dist/modes/rpc/rpc-types.js +8 -0
  814. package/dist/modes/rpc/rpc-types.js.map +1 -0
  815. package/dist/package-manager-cli.d.ts +9 -0
  816. package/dist/package-manager-cli.d.ts.map +1 -0
  817. package/dist/package-manager-cli.js +961 -0
  818. package/dist/package-manager-cli.js.map +1 -0
  819. package/dist/rpc-entry.d.ts +3 -0
  820. package/dist/rpc-entry.d.ts.map +1 -0
  821. package/dist/rpc-entry.js +12 -0
  822. package/dist/rpc-entry.js.map +1 -0
  823. package/dist/utils/abort.d.ts +5 -0
  824. package/dist/utils/abort.d.ts.map +1 -0
  825. package/dist/utils/abort.js +48 -0
  826. package/dist/utils/abort.js.map +1 -0
  827. package/dist/utils/ansi.d.ts +2 -0
  828. package/dist/utils/ansi.d.ts.map +1 -0
  829. package/dist/utils/ansi.js +52 -0
  830. package/dist/utils/ansi.js.map +1 -0
  831. package/dist/utils/changelog.d.ts +22 -0
  832. package/dist/utils/changelog.d.ts.map +1 -0
  833. package/dist/utils/changelog.js +165 -0
  834. package/dist/utils/changelog.js.map +1 -0
  835. package/dist/utils/child-process.d.ts +18 -0
  836. package/dist/utils/child-process.d.ts.map +1 -0
  837. package/dist/utils/child-process.js +106 -0
  838. package/dist/utils/child-process.js.map +1 -0
  839. package/dist/utils/clipboard-command.d.ts +7 -0
  840. package/dist/utils/clipboard-command.d.ts.map +1 -0
  841. package/dist/utils/clipboard-command.js +45 -0
  842. package/dist/utils/clipboard-command.js.map +1 -0
  843. package/dist/utils/clipboard-image.d.ts +11 -0
  844. package/dist/utils/clipboard-image.d.ts.map +1 -0
  845. package/dist/utils/clipboard-image.js +228 -0
  846. package/dist/utils/clipboard-image.js.map +1 -0
  847. package/dist/utils/clipboard.d.ts +4 -0
  848. package/dist/utils/clipboard.d.ts.map +1 -0
  849. package/dist/utils/clipboard.js +84 -0
  850. package/dist/utils/clipboard.js.map +1 -0
  851. package/dist/utils/deprecation.d.ts +4 -0
  852. package/dist/utils/deprecation.d.ts.map +1 -0
  853. package/dist/utils/deprecation.js +13 -0
  854. package/dist/utils/deprecation.js.map +1 -0
  855. package/dist/utils/exif-orientation.d.ts +5 -0
  856. package/dist/utils/exif-orientation.d.ts.map +1 -0
  857. package/dist/utils/exif-orientation.js +157 -0
  858. package/dist/utils/exif-orientation.js.map +1 -0
  859. package/dist/utils/frontmatter.d.ts +8 -0
  860. package/dist/utils/frontmatter.d.ts.map +1 -0
  861. package/dist/utils/frontmatter.js +27 -0
  862. package/dist/utils/frontmatter.js.map +1 -0
  863. package/dist/utils/fs-watch.d.ts +5 -0
  864. package/dist/utils/fs-watch.d.ts.map +1 -0
  865. package/dist/utils/fs-watch.js +25 -0
  866. package/dist/utils/fs-watch.js.map +1 -0
  867. package/dist/utils/git.d.ts +26 -0
  868. package/dist/utils/git.d.ts.map +1 -0
  869. package/dist/utils/git.js +195 -0
  870. package/dist/utils/git.js.map +1 -0
  871. package/dist/utils/html.d.ts +7 -0
  872. package/dist/utils/html.d.ts.map +1 -0
  873. package/dist/utils/html.js +40 -0
  874. package/dist/utils/html.js.map +1 -0
  875. package/dist/utils/image-convert.d.ts +10 -0
  876. package/dist/utils/image-convert.d.ts.map +1 -0
  877. package/dist/utils/image-convert.js +45 -0
  878. package/dist/utils/image-convert.js.map +1 -0
  879. package/dist/utils/image-process.d.ts +18 -0
  880. package/dist/utils/image-process.d.ts.map +1 -0
  881. package/dist/utils/image-process.js +83 -0
  882. package/dist/utils/image-process.js.map +1 -0
  883. package/dist/utils/image-resize-core.d.ts +30 -0
  884. package/dist/utils/image-resize-core.d.ts.map +1 -0
  885. package/dist/utils/image-resize-core.js +124 -0
  886. package/dist/utils/image-resize-core.js.map +1 -0
  887. package/dist/utils/image-resize-worker.d.ts +2 -0
  888. package/dist/utils/image-resize-worker.d.ts.map +1 -0
  889. package/dist/utils/image-resize-worker.js +31 -0
  890. package/dist/utils/image-resize-worker.js.map +1 -0
  891. package/dist/utils/image-resize.d.ts +16 -0
  892. package/dist/utils/image-resize.d.ts.map +1 -0
  893. package/dist/utils/image-resize.js +97 -0
  894. package/dist/utils/image-resize.js.map +1 -0
  895. package/dist/utils/ion-user-agent.d.ts +2 -0
  896. package/dist/utils/ion-user-agent.d.ts.map +1 -0
  897. package/dist/utils/ion-user-agent.js +5 -0
  898. package/dist/utils/ion-user-agent.js.map +1 -0
  899. package/dist/utils/json.d.ts +3 -0
  900. package/dist/utils/json.d.ts.map +1 -0
  901. package/dist/utils/json.js +7 -0
  902. package/dist/utils/json.js.map +1 -0
  903. package/dist/utils/management-http.d.ts +25 -0
  904. package/dist/utils/management-http.d.ts.map +1 -0
  905. package/dist/utils/management-http.js +54 -0
  906. package/dist/utils/management-http.js.map +1 -0
  907. package/dist/utils/mime.d.ts +3 -0
  908. package/dist/utils/mime.d.ts.map +1 -0
  909. package/dist/utils/mime.js +110 -0
  910. package/dist/utils/mime.js.map +1 -0
  911. package/dist/utils/open-browser.d.ts +9 -0
  912. package/dist/utils/open-browser.d.ts.map +1 -0
  913. package/dist/utils/open-browser.js +22 -0
  914. package/dist/utils/open-browser.js.map +1 -0
  915. package/dist/utils/paths.d.ts +34 -0
  916. package/dist/utils/paths.d.ts.map +1 -0
  917. package/dist/utils/paths.js +114 -0
  918. package/dist/utils/paths.js.map +1 -0
  919. package/dist/utils/photon.d.ts +21 -0
  920. package/dist/utils/photon.d.ts.map +1 -0
  921. package/dist/utils/photon.js +121 -0
  922. package/dist/utils/photon.js.map +1 -0
  923. package/dist/utils/shell.d.ts +34 -0
  924. package/dist/utils/shell.d.ts.map +1 -0
  925. package/dist/utils/shell.js +216 -0
  926. package/dist/utils/shell.js.map +1 -0
  927. package/dist/utils/sleep.d.ts +5 -0
  928. package/dist/utils/sleep.d.ts.map +1 -0
  929. package/dist/utils/sleep.js +17 -0
  930. package/dist/utils/sleep.js.map +1 -0
  931. package/dist/utils/syntax-highlight.d.ts +13 -0
  932. package/dist/utils/syntax-highlight.d.ts.map +1 -0
  933. package/dist/utils/syntax-highlight.js +177 -0
  934. package/dist/utils/syntax-highlight.js.map +1 -0
  935. package/dist/utils/text.d.ts +8 -0
  936. package/dist/utils/text.d.ts.map +1 -0
  937. package/dist/utils/text.js +9 -0
  938. package/dist/utils/text.js.map +1 -0
  939. package/dist/utils/tool-result-images.d.ts +19 -0
  940. package/dist/utils/tool-result-images.d.ts.map +1 -0
  941. package/dist/utils/tool-result-images.js +45 -0
  942. package/dist/utils/tool-result-images.js.map +1 -0
  943. package/dist/utils/tools-manager.d.ts +19 -0
  944. package/dist/utils/tools-manager.d.ts.map +1 -0
  945. package/dist/utils/tools-manager.js +382 -0
  946. package/dist/utils/tools-manager.js.map +1 -0
  947. package/dist/utils/version-check.d.ts +19 -0
  948. package/dist/utils/version-check.d.ts.map +1 -0
  949. package/dist/utils/version-check.js +79 -0
  950. package/dist/utils/version-check.js.map +1 -0
  951. package/dist/utils/windows-self-update.d.ts +3 -0
  952. package/dist/utils/windows-self-update.d.ts.map +1 -0
  953. package/dist/utils/windows-self-update.js +77 -0
  954. package/dist/utils/windows-self-update.js.map +1 -0
  955. package/docs/browser-extension.md +108 -0
  956. package/docs/compaction.md +444 -0
  957. package/docs/containerization.md +156 -0
  958. package/docs/custom-provider.md +777 -0
  959. package/docs/development.md +90 -0
  960. package/docs/docs.json +164 -0
  961. package/docs/environment-variables.md +101 -0
  962. package/docs/extensions.md +3033 -0
  963. package/docs/images/doom-extension.png +0 -0
  964. package/docs/images/exy.png +0 -0
  965. package/docs/images/interactive-mode.png +0 -0
  966. package/docs/images/tree-view.png +0 -0
  967. package/docs/index.md +85 -0
  968. package/docs/json.md +98 -0
  969. package/docs/keybindings.md +239 -0
  970. package/docs/llama-cpp.md +101 -0
  971. package/docs/models.md +574 -0
  972. package/docs/packages.md +228 -0
  973. package/docs/prompt-templates.md +96 -0
  974. package/docs/providers.md +321 -0
  975. package/docs/quickstart.md +168 -0
  976. package/docs/rpc.md +1618 -0
  977. package/docs/sdk.md +1226 -0
  978. package/docs/security.md +59 -0
  979. package/docs/session-format.md +450 -0
  980. package/docs/sessions.md +145 -0
  981. package/docs/settings.md +408 -0
  982. package/docs/shell-aliases.md +13 -0
  983. package/docs/skills.md +241 -0
  984. package/docs/terminal-setup.md +192 -0
  985. package/docs/termux.md +126 -0
  986. package/docs/themes.md +322 -0
  987. package/docs/tmux.md +63 -0
  988. package/docs/tui.md +961 -0
  989. package/docs/usage.md +327 -0
  990. package/docs/webfetch.md +119 -0
  991. package/docs/windows.md +39 -0
  992. package/examples/README.md +28 -0
  993. package/examples/extensions/README.md +213 -0
  994. package/examples/extensions/auto-commit-on-exit.ts +49 -0
  995. package/examples/extensions/bash-spawn-hook.ts +30 -0
  996. package/examples/extensions/bookmark.ts +50 -0
  997. package/examples/extensions/border-status-editor.ts +150 -0
  998. package/examples/extensions/built-in-tool-renderer.ts +249 -0
  999. package/examples/extensions/claude-rules.ts +86 -0
  1000. package/examples/extensions/commands.ts +72 -0
  1001. package/examples/extensions/confirm-destructive.ts +59 -0
  1002. package/examples/extensions/custom-compaction.ts +117 -0
  1003. package/examples/extensions/custom-footer.ts +64 -0
  1004. package/examples/extensions/custom-header.ts +73 -0
  1005. package/examples/extensions/custom-provider-anthropic/index.ts +611 -0
  1006. package/examples/extensions/custom-provider-anthropic/package-lock.json +24 -0
  1007. package/examples/extensions/custom-provider-anthropic/package.json +19 -0
  1008. package/examples/extensions/custom-provider-gitlab-duo/index.ts +405 -0
  1009. package/examples/extensions/custom-provider-gitlab-duo/package.json +16 -0
  1010. package/examples/extensions/custom-provider-gitlab-duo/test.ts +82 -0
  1011. package/examples/extensions/dirty-repo-guard.ts +56 -0
  1012. package/examples/extensions/doom-overlay/README.md +46 -0
  1013. package/examples/extensions/doom-overlay/doom/build/doom.js +21 -0
  1014. package/examples/extensions/doom-overlay/doom/build/doom.wasm +0 -0
  1015. package/examples/extensions/doom-overlay/doom/build.sh +152 -0
  1016. package/examples/extensions/doom-overlay/doom/doomgeneric_pi.c +72 -0
  1017. package/examples/extensions/doom-overlay/doom-component.ts +132 -0
  1018. package/examples/extensions/doom-overlay/doom-engine.ts +173 -0
  1019. package/examples/extensions/doom-overlay/doom-keys.ts +104 -0
  1020. package/examples/extensions/doom-overlay/index.ts +74 -0
  1021. package/examples/extensions/doom-overlay/wad-finder.ts +55 -0
  1022. package/examples/extensions/dynamic-resources/SKILL.md +8 -0
  1023. package/examples/extensions/dynamic-resources/dynamic.json +81 -0
  1024. package/examples/extensions/dynamic-resources/dynamic.md +5 -0
  1025. package/examples/extensions/dynamic-resources/index.ts +15 -0
  1026. package/examples/extensions/dynamic-tools.ts +74 -0
  1027. package/examples/extensions/entry-renderer.ts +41 -0
  1028. package/examples/extensions/event-bus.ts +43 -0
  1029. package/examples/extensions/file-trigger.ts +41 -0
  1030. package/examples/extensions/git-checkpoint.ts +53 -0
  1031. package/examples/extensions/git-merge-and-resolve.ts +115 -0
  1032. package/examples/extensions/github-issue-autocomplete.ts +185 -0
  1033. package/examples/extensions/gondolin/index.ts +531 -0
  1034. package/examples/extensions/gondolin/package-lock.json +185 -0
  1035. package/examples/extensions/gondolin/package.json +19 -0
  1036. package/examples/extensions/handoff.ts +190 -0
  1037. package/examples/extensions/hello.ts +26 -0
  1038. package/examples/extensions/hidden-thinking-label.ts +53 -0
  1039. package/examples/extensions/inline-bash.ts +94 -0
  1040. package/examples/extensions/input-transform-streaming.ts +39 -0
  1041. package/examples/extensions/input-transform.ts +43 -0
  1042. package/examples/extensions/interactive-shell.ts +196 -0
  1043. package/examples/extensions/kimi-deferred-tools.ts +61 -0
  1044. package/examples/extensions/mac-system-theme.ts +47 -0
  1045. package/examples/extensions/message-renderer.ts +59 -0
  1046. package/examples/extensions/minimal-mode.ts +426 -0
  1047. package/examples/extensions/modal-editor.ts +85 -0
  1048. package/examples/extensions/model-status.ts +31 -0
  1049. package/examples/extensions/notify.ts +57 -0
  1050. package/examples/extensions/overlay-qa-tests.ts +1450 -0
  1051. package/examples/extensions/overlay-test.ts +153 -0
  1052. package/examples/extensions/permission-gate.ts +34 -0
  1053. package/examples/extensions/pirate.ts +47 -0
  1054. package/examples/extensions/plan-mode/README.md +66 -0
  1055. package/examples/extensions/plan-mode/index.ts +390 -0
  1056. package/examples/extensions/plan-mode/utils.ts +168 -0
  1057. package/examples/extensions/preset.ts +436 -0
  1058. package/examples/extensions/project-trust.ts +64 -0
  1059. package/examples/extensions/prompt-customizer.ts +97 -0
  1060. package/examples/extensions/protected-paths.ts +30 -0
  1061. package/examples/extensions/provider-payload.ts +18 -0
  1062. package/examples/extensions/qna.ts +118 -0
  1063. package/examples/extensions/question.ts +278 -0
  1064. package/examples/extensions/questionnaire.ts +440 -0
  1065. package/examples/extensions/rainbow-editor.ts +88 -0
  1066. package/examples/extensions/reload-runtime.ts +37 -0
  1067. package/examples/extensions/rpc-demo.ts +118 -0
  1068. package/examples/extensions/sandbox/index.ts +321 -0
  1069. package/examples/extensions/sandbox/package-lock.json +92 -0
  1070. package/examples/extensions/sandbox/package.json +19 -0
  1071. package/examples/extensions/send-user-message.ts +97 -0
  1072. package/examples/extensions/session-name.ts +27 -0
  1073. package/examples/extensions/shutdown-command.ts +63 -0
  1074. package/examples/extensions/snake.ts +343 -0
  1075. package/examples/extensions/space-invaders.ts +560 -0
  1076. package/examples/extensions/ssh.ts +220 -0
  1077. package/examples/extensions/status-line.ts +32 -0
  1078. package/examples/extensions/structured-output.ts +65 -0
  1079. package/examples/extensions/subagent/README.md +177 -0
  1080. package/examples/extensions/subagent/agents/planner.md +37 -0
  1081. package/examples/extensions/subagent/agents/reviewer.md +35 -0
  1082. package/examples/extensions/subagent/agents/scout.md +50 -0
  1083. package/examples/extensions/subagent/agents/worker.md +24 -0
  1084. package/examples/extensions/subagent/agents.ts +157 -0
  1085. package/examples/extensions/subagent/index.ts +1038 -0
  1086. package/examples/extensions/subagent/prompts/implement-and-review.md +10 -0
  1087. package/examples/extensions/subagent/prompts/implement.md +10 -0
  1088. package/examples/extensions/subagent/prompts/scout-and-plan.md +9 -0
  1089. package/examples/extensions/summarize.ts +199 -0
  1090. package/examples/extensions/system-prompt-header.ts +17 -0
  1091. package/examples/extensions/tic-tac-toe.ts +1008 -0
  1092. package/examples/extensions/timed-confirm.ts +70 -0
  1093. package/examples/extensions/titlebar-spinner.ts +58 -0
  1094. package/examples/extensions/todo.ts +297 -0
  1095. package/examples/extensions/tool-override.ts +144 -0
  1096. package/examples/extensions/tools.ts +146 -0
  1097. package/examples/extensions/trigger-compact.ts +50 -0
  1098. package/examples/extensions/truncated-tool.ts +195 -0
  1099. package/examples/extensions/widget-placement.ts +9 -0
  1100. package/examples/extensions/with-deps/index.ts +32 -0
  1101. package/examples/extensions/with-deps/package-lock.json +31 -0
  1102. package/examples/extensions/with-deps/package.json +22 -0
  1103. package/examples/extensions/working-indicator.ts +123 -0
  1104. package/examples/extensions/working-message-test.ts +25 -0
  1105. package/examples/plugins/ion-example-plugin/README.md +38 -0
  1106. package/examples/plugins/ion-example-plugin/package.json +10 -0
  1107. package/examples/plugins/ion-example-plugin/src/contract.ts +13 -0
  1108. package/examples/plugins/ion-example-plugin/src/session.ts +23 -0
  1109. package/examples/plugins/ion-example-plugin/src/tui.ts +31 -0
  1110. package/examples/rpc-extension-ui.ts +641 -0
  1111. package/examples/sdk/01-minimal.ts +26 -0
  1112. package/examples/sdk/02-custom-model.ts +49 -0
  1113. package/examples/sdk/03-custom-prompt.ts +70 -0
  1114. package/examples/sdk/04-skills.ts +55 -0
  1115. package/examples/sdk/05-tools.ts +48 -0
  1116. package/examples/sdk/06-extensions.ts +94 -0
  1117. package/examples/sdk/07-context-files.ts +42 -0
  1118. package/examples/sdk/08-prompt-templates.ts +51 -0
  1119. package/examples/sdk/09-api-keys-and-oauth.ts +34 -0
  1120. package/examples/sdk/10-settings.ts +53 -0
  1121. package/examples/sdk/11-sessions.ts +52 -0
  1122. package/examples/sdk/12-full-control.ts +74 -0
  1123. package/examples/sdk/13-session-runtime.ts +67 -0
  1124. package/examples/sdk/README.md +140 -0
  1125. package/npm-shrinkwrap.json +1912 -0
  1126. package/package.json +108 -0
@@ -0,0 +1,1587 @@
1
+ import { uuidv7 } from "@m4ike1/ion-ai";
2
+ import { randomUUID } from "crypto";
3
+ import { appendFileSync, closeSync, createReadStream, existsSync, mkdirSync, openSync, readdirSync, readSync, statSync, writeFileSync, } from "fs";
4
+ import { readdir, stat } from "fs/promises";
5
+ import { basename, join, resolve } from "path";
6
+ import { createInterface } from "readline";
7
+ import { StringDecoder } from "string_decoder";
8
+ import { APP_NAME, getCacheDir, getSessionsDir } from "../config.js";
9
+ import { normalizePath, resolvePath } from "../utils/paths.js";
10
+ import { createBranchSummaryMessage, createCompactionSummaryMessage, createCustomMessage, } from "./messages.js";
11
+ import { SessionIndex } from "./session-index.js";
12
+ export const CURRENT_SESSION_VERSION = 3;
13
+ function createSessionId() {
14
+ return uuidv7();
15
+ }
16
+ export function assertValidSessionId(id) {
17
+ if (!/^[A-Za-z0-9](?:[A-Za-z0-9._-]*[A-Za-z0-9])?$/.test(id)) {
18
+ throw new Error("Session id must be non-empty, contain only alphanumeric characters, '-', '_', and '.', and start and end with an alphanumeric character");
19
+ }
20
+ }
21
+ /** Generate a unique short ID (8 hex chars, collision-checked) */
22
+ function generateId(byId) {
23
+ for (let i = 0; i < 100; i++) {
24
+ const id = randomUUID().slice(0, 8);
25
+ if (!byId.has(id))
26
+ return id;
27
+ }
28
+ // Fallback to full UUID if somehow we have collisions
29
+ return randomUUID();
30
+ }
31
+ /** Migrate v1 → v2: add id/parentId tree structure. Mutates in place. */
32
+ function migrateV1ToV2(entries) {
33
+ const ids = new Set();
34
+ let prevId = null;
35
+ for (const entry of entries) {
36
+ if (entry.type === "session") {
37
+ entry.version = 2;
38
+ continue;
39
+ }
40
+ entry.id = generateId(ids);
41
+ entry.parentId = prevId;
42
+ prevId = entry.id;
43
+ // Convert firstKeptEntryIndex to firstKeptEntryId for compaction
44
+ if (entry.type === "compaction") {
45
+ const comp = entry;
46
+ if (typeof comp.firstKeptEntryIndex === "number") {
47
+ const targetEntry = entries[comp.firstKeptEntryIndex];
48
+ if (targetEntry && targetEntry.type !== "session") {
49
+ comp.firstKeptEntryId = targetEntry.id;
50
+ }
51
+ delete comp.firstKeptEntryIndex;
52
+ }
53
+ }
54
+ }
55
+ }
56
+ /** Migrate v2 → v3: rename hookMessage role to custom. Mutates in place. */
57
+ function migrateV2ToV3(entries) {
58
+ for (const entry of entries) {
59
+ if (entry.type === "session") {
60
+ entry.version = 3;
61
+ continue;
62
+ }
63
+ // Update message entries with hookMessage role
64
+ if (entry.type === "message") {
65
+ const msgEntry = entry;
66
+ if (msgEntry.message && msgEntry.message.role === "hookMessage") {
67
+ msgEntry.message.role = "custom";
68
+ }
69
+ }
70
+ }
71
+ }
72
+ /**
73
+ * Run all necessary migrations to bring entries to current version.
74
+ * Mutates entries in place. Returns true if any migration was applied.
75
+ */
76
+ function migrateToCurrentVersion(entries) {
77
+ const header = entries.find((e) => e.type === "session");
78
+ const version = header?.version ?? 1;
79
+ if (version >= CURRENT_SESSION_VERSION)
80
+ return false;
81
+ if (version < 2)
82
+ migrateV1ToV2(entries);
83
+ if (version < 3)
84
+ migrateV2ToV3(entries);
85
+ return true;
86
+ }
87
+ /** Exported for testing */
88
+ export function migrateSessionEntries(entries) {
89
+ migrateToCurrentVersion(entries);
90
+ }
91
+ /** Exported for compaction.test.ts */
92
+ export function parseSessionEntries(content) {
93
+ const entries = [];
94
+ const lines = content.trim().split("\n");
95
+ for (const line of lines) {
96
+ if (!line.trim())
97
+ continue;
98
+ try {
99
+ const entry = JSON.parse(line);
100
+ entries.push(entry);
101
+ }
102
+ catch {
103
+ // Skip malformed lines
104
+ }
105
+ }
106
+ return entries;
107
+ }
108
+ export function getLatestCompactionEntry(entries) {
109
+ for (let i = entries.length - 1; i >= 0; i--) {
110
+ if (entries[i].type === "compaction") {
111
+ return entries[i];
112
+ }
113
+ }
114
+ return null;
115
+ }
116
+ function buildEntryIndex(entries, byId) {
117
+ if (byId)
118
+ return byId;
119
+ const index = new Map();
120
+ for (const entry of entries) {
121
+ index.set(entry.id, entry);
122
+ }
123
+ return index;
124
+ }
125
+ function buildSessionPath(entries, leafId, byId) {
126
+ const index = buildEntryIndex(entries, byId);
127
+ let leaf;
128
+ if (leafId === null) {
129
+ return [];
130
+ }
131
+ if (leafId) {
132
+ leaf = index.get(leafId);
133
+ }
134
+ leaf ??= entries[entries.length - 1];
135
+ if (!leaf) {
136
+ return [];
137
+ }
138
+ const path = [];
139
+ let current = leaf;
140
+ while (current) {
141
+ path.push(current);
142
+ current = current.parentId ? index.get(current.parentId) : undefined;
143
+ }
144
+ path.reverse();
145
+ return path;
146
+ }
147
+ function getSessionContextSettings(path) {
148
+ let thinkingLevel = "off";
149
+ let model = null;
150
+ for (const entry of path) {
151
+ if (entry.type === "thinking_level_change") {
152
+ thinkingLevel = entry.thinkingLevel;
153
+ }
154
+ else if (entry.type === "model_change") {
155
+ model = { provider: entry.provider, modelId: entry.modelId };
156
+ }
157
+ else if (entry.type === "message" && entry.message.role === "assistant") {
158
+ model = { provider: entry.message.provider, modelId: entry.message.model };
159
+ }
160
+ }
161
+ return { thinkingLevel, model };
162
+ }
163
+ /**
164
+ * Project one selected session entry into LLM/runtime messages.
165
+ * Plain custom entries are display/state entries and do not participate in context.
166
+ */
167
+ export function sessionEntryToContextMessages(entry) {
168
+ if (entry.type === "message") {
169
+ const message = entry.message;
170
+ // Session files are parsed without validation; old versions, forks, or
171
+ // hand-edited files can contain messages with null/missing content.
172
+ if ((message.role === "user" || message.role === "assistant" || message.role === "toolResult") &&
173
+ message.content == null) {
174
+ return [{ ...message, content: [] }];
175
+ }
176
+ return [message];
177
+ }
178
+ if (entry.type === "custom_message") {
179
+ return [
180
+ createCustomMessage(entry.customType, entry.content ?? [], entry.display, entry.details, entry.timestamp),
181
+ ];
182
+ }
183
+ if (entry.type === "branch_summary" && entry.summary) {
184
+ return [createBranchSummaryMessage(entry.summary, entry.fromId, entry.timestamp)];
185
+ }
186
+ if (entry.type === "compaction") {
187
+ return [createCompactionSummaryMessage(entry.summary, entry.tokensBefore, entry.timestamp)];
188
+ }
189
+ return [];
190
+ }
191
+ /**
192
+ * Build the active, compaction-aware session entry list.
193
+ *
194
+ * This follows the current leaf path. If the path contains compaction entries,
195
+ * the latest compaction is represented by the compaction entry itself, followed
196
+ * by the kept entries starting at firstKeptEntryId and all entries after the
197
+ * compaction entry. Older summarized entries are omitted.
198
+ */
199
+ export function buildContextEntries(entries, leafId, byId) {
200
+ const path = buildSessionPath(entries, leafId, byId);
201
+ let compaction = null;
202
+ for (const entry of path) {
203
+ if (entry.type === "compaction") {
204
+ compaction = entry;
205
+ }
206
+ }
207
+ if (!compaction) {
208
+ return path;
209
+ }
210
+ const compactionIdx = path.findIndex((entry) => entry.id === compaction.id);
211
+ if (compactionIdx < 0) {
212
+ return path;
213
+ }
214
+ const contextEntries = [compaction];
215
+ let foundFirstKept = false;
216
+ for (let i = 0; i < compactionIdx; i++) {
217
+ const entry = path[i];
218
+ if (entry.id === compaction.firstKeptEntryId) {
219
+ foundFirstKept = true;
220
+ }
221
+ if (foundFirstKept) {
222
+ contextEntries.push(entry);
223
+ }
224
+ }
225
+ contextEntries.push(...path.slice(compactionIdx + 1));
226
+ return contextEntries;
227
+ }
228
+ /**
229
+ * Build the session context from entries using tree traversal.
230
+ * If leafId is provided, walks from that entry to root.
231
+ * Handles compaction and branch summaries along the path.
232
+ */
233
+ export function buildSessionContext(entries, leafId, byId) {
234
+ const path = buildSessionPath(entries, leafId, byId);
235
+ const { thinkingLevel, model } = getSessionContextSettings(path);
236
+ const messages = buildContextEntries(entries, leafId, byId).flatMap(sessionEntryToContextMessages);
237
+ return { messages, thinkingLevel, model };
238
+ }
239
+ function cwdToTreeRelative(cwd) {
240
+ const resolved = resolvePath(cwd);
241
+ let relative = resolved;
242
+ if (/^[a-zA-Z]:[/\\]/.test(relative)) {
243
+ relative = relative[0] + relative.slice(2).replace(/^[/\\]+/, "/");
244
+ }
245
+ relative = relative.replace(/^[/\\]+/, "");
246
+ if (relative === "")
247
+ return "_root";
248
+ relative = relative.replace(/:/g, "_");
249
+ return relative;
250
+ }
251
+ function resolveSessionsBase(base) {
252
+ if (!base)
253
+ return getSessionsDir();
254
+ const resolved = resolvePath(base);
255
+ if (basename(resolved) === "sessions")
256
+ return resolved;
257
+ return join(resolved, "sessions");
258
+ }
259
+ /**
260
+ * Compute the default session directory for a cwd.
261
+ * Uses real tree sessions/<projectAbs>/ (e.g., sessions/home/user/project).
262
+ */
263
+ export function getDefaultSessionDirPath(cwd, base) {
264
+ const sessionsBase = resolveSessionsBase(base);
265
+ const relative = cwdToTreeRelative(cwd);
266
+ return join(sessionsBase, relative);
267
+ }
268
+ /** Legacy flat sanitized path (--home-...--) — deprecated, kept for reading. */
269
+ export function getLegacyDefaultSessionDirPath(cwd, base) {
270
+ const sessionsBase = resolveSessionsBase(base);
271
+ const resolvedCwd = resolvePath(cwd);
272
+ const safePath = `--${resolvedCwd.replace(/^[/\\]/, "").replace(/[/\\:]/g, "-")}--`;
273
+ return join(sessionsBase, safePath);
274
+ }
275
+ export function getDefaultSessionDir(cwd, base) {
276
+ const sessionDir = getDefaultSessionDirPath(cwd, base);
277
+ if (!existsSync(sessionDir)) {
278
+ mkdirSync(sessionDir, { recursive: true });
279
+ }
280
+ return sessionDir;
281
+ }
282
+ const SESSION_READ_BUFFER_SIZE = 1024 * 1024;
283
+ const SESSION_HEADER_READ_BUFFER_SIZE = 4096;
284
+ /** Bound synchronous header discovery while allowing large cwd and custom metadata fields. */
285
+ const MAX_SESSION_HEADER_SCAN_BYTES = 1024 * 1024;
286
+ class SessionHeaderScanLimitError extends Error {
287
+ constructor(filePath) {
288
+ super(`Session header exceeds ${MAX_SESSION_HEADER_SCAN_BYTES}-byte scan limit: ${filePath}`);
289
+ this.name = "SessionHeaderScanLimitError";
290
+ }
291
+ }
292
+ /** Parse one JSONL line into a session entry; null for blank or malformed lines. Exported for the session index. */
293
+ export function parseSessionEntryLine(line) {
294
+ if (!line.trim())
295
+ return null;
296
+ try {
297
+ return JSON.parse(line);
298
+ }
299
+ catch {
300
+ // Skip malformed lines
301
+ return null;
302
+ }
303
+ }
304
+ /** Exported for testing */
305
+ export function loadEntriesFromFile(filePath) {
306
+ const resolvedFilePath = normalizePath(filePath);
307
+ if (!existsSync(resolvedFilePath))
308
+ return [];
309
+ const entries = [];
310
+ let pending = "";
311
+ const fd = openSync(resolvedFilePath, "r");
312
+ try {
313
+ const decoder = new StringDecoder("utf8");
314
+ const buffer = Buffer.allocUnsafe(SESSION_READ_BUFFER_SIZE);
315
+ while (true) {
316
+ const bytesRead = readSync(fd, buffer, 0, buffer.length, null);
317
+ if (bytesRead === 0)
318
+ break;
319
+ pending += decoder.write(buffer.subarray(0, bytesRead));
320
+ let lineStart = 0;
321
+ let newlineIndex = pending.indexOf("\n", lineStart);
322
+ while (newlineIndex !== -1) {
323
+ const entry = parseSessionEntryLine(pending.slice(lineStart, newlineIndex));
324
+ if (entry)
325
+ entries.push(entry);
326
+ lineStart = newlineIndex + 1;
327
+ newlineIndex = pending.indexOf("\n", lineStart);
328
+ }
329
+ pending = pending.slice(lineStart);
330
+ }
331
+ pending += decoder.end();
332
+ const finalEntry = parseSessionEntryLine(pending);
333
+ if (finalEntry)
334
+ entries.push(finalEntry);
335
+ }
336
+ finally {
337
+ closeSync(fd);
338
+ }
339
+ // Validate session header before repairing the file.
340
+ if (entries.length === 0)
341
+ return entries;
342
+ const header = entries[0];
343
+ if (header.type !== "session" || typeof header.id !== "string") {
344
+ return [];
345
+ }
346
+ if (pending)
347
+ appendFileSync(resolvedFilePath, "\n");
348
+ return entries;
349
+ }
350
+ /**
351
+ * Inspect a physical line while searching for the first parsed session entry.
352
+ * Blank and malformed lines are skipped to match loadEntriesFromFile().
353
+ * Returns undefined to keep scanning, null for a parsed non-header entry, or the header.
354
+ */
355
+ function parseSessionHeaderCandidate(line) {
356
+ if (!line.trim())
357
+ return undefined;
358
+ const entry = parseSessionEntryLine(line);
359
+ if (!entry)
360
+ return undefined;
361
+ if (entry.type !== "session" || typeof entry.id !== "string")
362
+ return null;
363
+ return entry;
364
+ }
365
+ function readSessionHeader(filePath) {
366
+ const fd = openSync(filePath, "r");
367
+ try {
368
+ const decoder = new StringDecoder("utf8");
369
+ const buffer = Buffer.allocUnsafe(SESSION_HEADER_READ_BUFFER_SIZE);
370
+ const lineChunks = [];
371
+ let scannedBytes = 0;
372
+ while (scannedBytes < MAX_SESSION_HEADER_SCAN_BYTES) {
373
+ const readLength = Math.min(buffer.length, MAX_SESSION_HEADER_SCAN_BYTES - scannedBytes);
374
+ const bytesRead = readSync(fd, buffer, 0, readLength, null);
375
+ if (bytesRead === 0) {
376
+ lineChunks.push(decoder.end());
377
+ return parseSessionHeaderCandidate(lineChunks.join("")) ?? null;
378
+ }
379
+ scannedBytes += bytesRead;
380
+ const chunk = decoder.write(buffer.subarray(0, bytesRead));
381
+ let lineStart = 0;
382
+ let newlineIndex = chunk.indexOf("\n", lineStart);
383
+ while (newlineIndex !== -1) {
384
+ lineChunks.push(chunk.slice(lineStart, newlineIndex));
385
+ const header = parseSessionHeaderCandidate(lineChunks.join(""));
386
+ if (header !== undefined)
387
+ return header;
388
+ lineChunks.length = 0;
389
+ lineStart = newlineIndex + 1;
390
+ newlineIndex = chunk.indexOf("\n", lineStart);
391
+ }
392
+ lineChunks.push(chunk.slice(lineStart));
393
+ }
394
+ // Probe for EOF so a final header without a newline is allowed when it ends
395
+ // exactly at the scan limit. Any additional byte exceeds the bounded scan.
396
+ const probe = Buffer.allocUnsafe(1);
397
+ if (readSync(fd, probe, 0, probe.length, null) === 0) {
398
+ lineChunks.push(decoder.end());
399
+ return parseSessionHeaderCandidate(lineChunks.join("")) ?? null;
400
+ }
401
+ throw new SessionHeaderScanLimitError(filePath);
402
+ }
403
+ finally {
404
+ closeSync(fd);
405
+ }
406
+ }
407
+ function readSessionHeaderForDiscovery(filePath) {
408
+ try {
409
+ return readSessionHeader(filePath);
410
+ }
411
+ catch {
412
+ // Discovery is best-effort: unreadable or oversized files are not sessions,
413
+ // and one corrupt file must not prevent other sessions from being found.
414
+ return null;
415
+ }
416
+ }
417
+ function getSessionHeaderCwd(header) {
418
+ const cwd = header.cwd;
419
+ return typeof cwd === "string" ? cwd : undefined;
420
+ }
421
+ function sessionCwdMatches(cwd, resolvedCwd) {
422
+ return cwd !== undefined && cwd !== "" && resolvePath(cwd) === resolvedCwd;
423
+ }
424
+ /** Exported for testing */
425
+ export function findMostRecentSession(sessionDir, cwd) {
426
+ const resolvedSessionDir = normalizePath(sessionDir);
427
+ const resolvedCwd = cwd ? resolvePath(cwd) : undefined;
428
+ try {
429
+ const files = readdirSync(resolvedSessionDir)
430
+ .filter((f) => f.endsWith(".jsonl"))
431
+ .map((f) => join(resolvedSessionDir, f))
432
+ .map((path) => ({ path, header: readSessionHeaderForDiscovery(path) }))
433
+ .filter((file) => file.header !== null &&
434
+ (!resolvedCwd || sessionCwdMatches(getSessionHeaderCwd(file.header), resolvedCwd)))
435
+ .map(({ path }) => ({ path, mtime: statSync(path).mtime }))
436
+ .sort((a, b) => b.mtime.getTime() - a.mtime.getTime());
437
+ return files[0]?.path || null;
438
+ }
439
+ catch {
440
+ // Directory access and stat races make recent-session discovery unavailable.
441
+ return null;
442
+ }
443
+ }
444
+ function isMessageWithContent(message) {
445
+ return typeof message.role === "string" && "content" in message;
446
+ }
447
+ /**
448
+ * Single index database in XDG cache (state/cache). Memoized per process;
449
+ * null means indexing is unavailable and the JSONL scan is the only path.
450
+ * Legacy per-directory DBs remain readable but new writes go to cache.
451
+ */
452
+ const indexHandles = new Map();
453
+ function indexHandleForSessionDir(_sessionDir) {
454
+ const dbPath = join(getCacheDir(), "index.db");
455
+ if (!indexHandles.has(dbPath)) {
456
+ if (!existsSync(getCacheDir())) {
457
+ try {
458
+ mkdirSync(getCacheDir(), { recursive: true });
459
+ }
460
+ catch { }
461
+ }
462
+ indexHandles.set(dbPath, existsSync(getCacheDir()) ? SessionIndex.open(dbPath) : null);
463
+ }
464
+ return indexHandles.get(dbPath) ?? null;
465
+ }
466
+ /** Concatenated text blocks of a message. Exported for the session index. */
467
+ export function extractTextContent(message) {
468
+ const content = message.content;
469
+ if (typeof content === "string") {
470
+ return content;
471
+ }
472
+ return content
473
+ .filter((block) => block.type === "text")
474
+ .map((block) => block.text)
475
+ .join(" ");
476
+ }
477
+ function getMessageActivityTime(entry) {
478
+ const message = entry.message;
479
+ if (!isMessageWithContent(message))
480
+ return undefined;
481
+ if (message.role !== "user" && message.role !== "assistant")
482
+ return undefined;
483
+ const msgTimestamp = message.timestamp;
484
+ if (typeof msgTimestamp === "number") {
485
+ return msgTimestamp;
486
+ }
487
+ const t = new Date(entry.timestamp).getTime();
488
+ return Number.isNaN(t) ? undefined : t;
489
+ }
490
+ async function buildSessionInfo(filePath, index) {
491
+ try {
492
+ const stats = await stat(filePath);
493
+ // Parse each file at most once per process: repeated session-picker opens
494
+ // only pay stat() calls until a file actually changes.
495
+ const cached = sessionInfoCache.get(filePath);
496
+ if (cached && cached.mtimeMs === stats.mtimeMs && cached.size === stats.size) {
497
+ return cached.info;
498
+ }
499
+ // Across processes, the persistent index serves listing without parsing.
500
+ if (index) {
501
+ const indexed = index.getFreshSession(filePath, stats.size, stats.mtimeMs);
502
+ if (indexed) {
503
+ return {
504
+ path: filePath,
505
+ id: indexed.sessionId,
506
+ cwd: indexed.cwd,
507
+ name: indexed.name,
508
+ parentSessionPath: indexed.parentSessionPath,
509
+ created: new Date(indexed.createdMs),
510
+ modified: new Date(indexed.modifiedMs),
511
+ messageCount: indexed.messageCount,
512
+ firstMessage: indexed.firstMessage,
513
+ allMessagesText: indexed.searchText,
514
+ };
515
+ }
516
+ }
517
+ let header = null;
518
+ let messageCount = 0;
519
+ let firstMessage = "";
520
+ const allMessages = [];
521
+ let name;
522
+ let lastActivityTime;
523
+ const rl = createInterface({
524
+ input: createReadStream(filePath, { encoding: "utf8" }),
525
+ crlfDelay: Infinity,
526
+ });
527
+ for await (const line of rl) {
528
+ const entry = parseSessionEntryLine(line);
529
+ if (!entry)
530
+ continue;
531
+ if (!header) {
532
+ if (entry.type !== "session")
533
+ return null;
534
+ header = entry;
535
+ continue;
536
+ }
537
+ // Extract session name (use latest, including explicit clears)
538
+ if (entry.type === "session_info") {
539
+ name = entry.name?.trim() || undefined;
540
+ }
541
+ if (entry.type !== "message")
542
+ continue;
543
+ messageCount++;
544
+ const activityTime = getMessageActivityTime(entry);
545
+ if (typeof activityTime === "number") {
546
+ lastActivityTime = Math.max(lastActivityTime ?? 0, activityTime);
547
+ }
548
+ const message = entry.message;
549
+ if (!isMessageWithContent(message))
550
+ continue;
551
+ if (message.role !== "user" && message.role !== "assistant")
552
+ continue;
553
+ const textContent = extractTextContent(message);
554
+ if (!textContent)
555
+ continue;
556
+ allMessages.push(textContent);
557
+ if (!firstMessage && message.role === "user") {
558
+ firstMessage = textContent;
559
+ }
560
+ }
561
+ if (!header)
562
+ return null;
563
+ const cwd = typeof header.cwd === "string" ? header.cwd : "";
564
+ const parentSessionPath = header.parentSession;
565
+ const headerTime = typeof header.timestamp === "string" ? new Date(header.timestamp).getTime() : NaN;
566
+ const modified = typeof lastActivityTime === "number" && lastActivityTime > 0
567
+ ? new Date(lastActivityTime)
568
+ : !Number.isNaN(headerTime)
569
+ ? new Date(headerTime)
570
+ : stats.mtime;
571
+ const allMessagesText = allMessages.join(" ");
572
+ const info = {
573
+ path: filePath,
574
+ id: header.id,
575
+ cwd,
576
+ name,
577
+ parentSessionPath,
578
+ created: new Date(header.timestamp),
579
+ modified,
580
+ messageCount,
581
+ firstMessage: firstMessage || "(no messages)",
582
+ allMessagesText: allMessagesText.length > MAX_ALL_MESSAGES_TEXT_LENGTH
583
+ ? allMessagesText.slice(0, MAX_ALL_MESSAGES_TEXT_LENGTH)
584
+ : allMessagesText,
585
+ };
586
+ cacheSessionInfo(filePath, stats, info);
587
+ index?.indexFile(filePath, { size: stats.size, mtimeMs: stats.mtimeMs }, {
588
+ sessionId: header.id,
589
+ cwd,
590
+ name,
591
+ parentSessionPath: parentSessionPath,
592
+ createdMs: new Date(header.timestamp).getTime() || 0,
593
+ modifiedMs: modified.getTime(),
594
+ messageCount,
595
+ firstMessage: firstMessage || "(no messages)",
596
+ searchText: info.allMessagesText,
597
+ });
598
+ return info;
599
+ }
600
+ catch {
601
+ return null;
602
+ }
603
+ }
604
+ const MAX_CONCURRENT_SESSION_INFO_LOADS = 10;
605
+ /**
606
+ * Bound the search text collected per session: very long sessions otherwise
607
+ * dominate listing time and memory. Fuzzy search still matches on the head of
608
+ * the transcript, which is where titles and topics are established.
609
+ */
610
+ const MAX_ALL_MESSAGES_TEXT_LENGTH = 16_384;
611
+ /** In-process cache so repeated session listings only pay stat() per file. */
612
+ const SESSION_INFO_CACHE_LIMIT = 2000;
613
+ const sessionInfoCache = new Map();
614
+ function cacheSessionInfo(filePath, stats, info) {
615
+ if (sessionInfoCache.size >= SESSION_INFO_CACHE_LIMIT && !sessionInfoCache.has(filePath)) {
616
+ sessionInfoCache.clear();
617
+ }
618
+ sessionInfoCache.set(filePath, { mtimeMs: stats.mtimeMs, size: stats.size, info });
619
+ }
620
+ async function buildSessionInfosWithConcurrency(files, onLoaded, index) {
621
+ const results = new Array(files.length).fill(null);
622
+ const inFlight = new Set();
623
+ let nextIndex = 0;
624
+ const startNext = () => {
625
+ const fileIndex = nextIndex++;
626
+ const file = files[fileIndex];
627
+ if (!file)
628
+ return;
629
+ let task;
630
+ task = buildSessionInfo(file, index)
631
+ .then((info) => {
632
+ results[fileIndex] = info;
633
+ })
634
+ .catch(() => {
635
+ results[fileIndex] = null;
636
+ })
637
+ .finally(() => {
638
+ inFlight.delete(task);
639
+ onLoaded();
640
+ });
641
+ inFlight.add(task);
642
+ };
643
+ while (nextIndex < files.length || inFlight.size > 0) {
644
+ while (nextIndex < files.length && inFlight.size < MAX_CONCURRENT_SESSION_INFO_LOADS) {
645
+ startNext();
646
+ }
647
+ if (inFlight.size > 0) {
648
+ await Promise.race(inFlight);
649
+ }
650
+ }
651
+ return results;
652
+ }
653
+ async function listSessionsFromDir(dir, onProgress, progressOffset = 0, progressTotal, index) {
654
+ const sessions = [];
655
+ if (!existsSync(dir)) {
656
+ return sessions;
657
+ }
658
+ try {
659
+ const dirEntries = await readdir(dir);
660
+ const files = dirEntries.filter((f) => f.endsWith(".jsonl")).map((f) => join(dir, f));
661
+ const total = progressTotal ?? files.length;
662
+ let loaded = 0;
663
+ const results = await buildSessionInfosWithConcurrency(files, () => {
664
+ loaded++;
665
+ onProgress?.(progressOffset + loaded, total);
666
+ }, index);
667
+ for (const info of results) {
668
+ if (info) {
669
+ sessions.push(info);
670
+ }
671
+ }
672
+ }
673
+ catch {
674
+ // Return empty list on error
675
+ }
676
+ return sessions;
677
+ }
678
+ async function collectAllSessionFiles(sessionsDir) {
679
+ if (!existsSync(sessionsDir))
680
+ return [];
681
+ const files = [];
682
+ const stack = [sessionsDir];
683
+ while (stack.length > 0) {
684
+ const dir = stack.pop();
685
+ let entries;
686
+ try {
687
+ entries = await readdir(dir, { withFileTypes: true });
688
+ }
689
+ catch {
690
+ continue;
691
+ }
692
+ for (const entry of entries) {
693
+ const full = join(dir, entry.name);
694
+ if (entry.isFile() && entry.name.endsWith(".jsonl")) {
695
+ files.push(full);
696
+ }
697
+ else if (entry.isDirectory() || entry.isSymbolicLink()) {
698
+ stack.push(full);
699
+ }
700
+ }
701
+ }
702
+ return files;
703
+ }
704
+ /**
705
+ * Manages conversation sessions as append-only trees stored in JSONL files.
706
+ *
707
+ * Each session entry has an id and parentId forming a tree structure. The "leaf"
708
+ * pointer tracks the current position. Appending creates a child of the current leaf.
709
+ * Branching moves the leaf to an earlier entry, allowing new branches without
710
+ * modifying history.
711
+ *
712
+ * Use buildSessionContext() to get the resolved message list for the LLM, which
713
+ * handles compaction summaries and follows the path from root to current leaf.
714
+ */
715
+ export class SessionManager {
716
+ sessionId = "";
717
+ sessionFile;
718
+ sessionDir;
719
+ cwd;
720
+ persist;
721
+ flushed = false;
722
+ fileEntries = [];
723
+ byId = new Map();
724
+ labelsById = new Map();
725
+ labelTimestampsById = new Map();
726
+ leafId = null;
727
+ constructor(cwd, sessionDir, sessionFile, persist, newSessionOptions, preloadedFileEntries) {
728
+ this.cwd = resolvePath(cwd);
729
+ this.sessionDir = normalizePath(sessionDir);
730
+ this.persist = persist;
731
+ if (persist && this.sessionDir && !existsSync(this.sessionDir)) {
732
+ mkdirSync(this.sessionDir, { recursive: true });
733
+ }
734
+ if (sessionFile) {
735
+ this._setSessionFile(sessionFile, preloadedFileEntries);
736
+ }
737
+ else if (preloadedFileEntries?.length) {
738
+ this._loadEntries(preloadedFileEntries, newSessionOptions);
739
+ }
740
+ else {
741
+ this.newSession(newSessionOptions);
742
+ }
743
+ }
744
+ /** Switch to a different session file (used for resume and branching) */
745
+ setSessionFile(sessionFile) {
746
+ this._setSessionFile(sessionFile);
747
+ }
748
+ _setSessionFile(sessionFile, preloadedFileEntries) {
749
+ this.sessionFile = resolvePath(sessionFile);
750
+ if (existsSync(this.sessionFile)) {
751
+ const entries = preloadedFileEntries ?? loadEntriesFromFile(this.sessionFile);
752
+ // If file was empty, initialize it with a valid session header. If it was
753
+ // non-empty but did not parse as a ion session, fail without modifying it.
754
+ if (entries.length === 0) {
755
+ const explicitPath = this.sessionFile;
756
+ if (statSync(explicitPath).size > 0) {
757
+ throw new Error(`Session file is not a valid ${APP_NAME} session: ${explicitPath}`);
758
+ }
759
+ this.newSession();
760
+ this.sessionFile = explicitPath;
761
+ this._rewriteFile();
762
+ this.flushed = true;
763
+ return;
764
+ }
765
+ this._loadEntries(entries);
766
+ this.flushed = true;
767
+ }
768
+ else {
769
+ const explicitPath = this.sessionFile;
770
+ this.newSession();
771
+ this.sessionFile = explicitPath; // preserve explicit path from --session flag
772
+ }
773
+ }
774
+ newSession(options) {
775
+ if (options?.id !== undefined) {
776
+ assertValidSessionId(options.id);
777
+ }
778
+ this.sessionId = options?.id ?? createSessionId();
779
+ const timestamp = new Date().toISOString();
780
+ const header = {
781
+ type: "session",
782
+ version: CURRENT_SESSION_VERSION,
783
+ id: this.sessionId,
784
+ timestamp,
785
+ cwd: this.cwd,
786
+ parentSession: options?.parentSession,
787
+ };
788
+ this.fileEntries = [header];
789
+ this.byId.clear();
790
+ this.labelsById.clear();
791
+ this.labelTimestampsById.clear();
792
+ this.leafId = null;
793
+ this.flushed = false;
794
+ if (this.persist) {
795
+ const fileTimestamp = timestamp.replace(/[:.]/g, "-");
796
+ this.sessionFile = join(this.getSessionDir(), `${fileTimestamp}_${this.sessionId}.jsonl`);
797
+ }
798
+ return this.sessionFile;
799
+ }
800
+ _loadEntries(entries, options) {
801
+ const header = entries.find((e) => e.type === "session");
802
+ if (header) {
803
+ this.fileEntries = entries;
804
+ this.sessionId = header.id;
805
+ if (migrateToCurrentVersion(this.fileEntries)) {
806
+ this._rewriteFile();
807
+ }
808
+ }
809
+ else {
810
+ this.newSession(options);
811
+ this.fileEntries = this.fileEntries.concat(entries);
812
+ }
813
+ this._buildIndex();
814
+ }
815
+ _buildIndex() {
816
+ this.byId.clear();
817
+ this.labelsById.clear();
818
+ this.labelTimestampsById.clear();
819
+ this.leafId = null;
820
+ for (const entry of this.fileEntries) {
821
+ if (entry.type === "session")
822
+ continue;
823
+ this.byId.set(entry.id, entry);
824
+ this.leafId = entry.id;
825
+ if (entry.type === "label") {
826
+ if (entry.label) {
827
+ this.labelsById.set(entry.targetId, entry.label);
828
+ this.labelTimestampsById.set(entry.targetId, entry.timestamp);
829
+ }
830
+ else {
831
+ this.labelsById.delete(entry.targetId);
832
+ this.labelTimestampsById.delete(entry.targetId);
833
+ }
834
+ }
835
+ }
836
+ }
837
+ _rewriteFile() {
838
+ if (!this.persist || !this.sessionFile)
839
+ return;
840
+ const fd = openSync(this.sessionFile, "w");
841
+ try {
842
+ for (const entry of this.fileEntries) {
843
+ writeFileSync(fd, `${JSON.stringify(entry)}\n`);
844
+ }
845
+ }
846
+ finally {
847
+ closeSync(fd);
848
+ }
849
+ }
850
+ isPersisted() {
851
+ return this.persist;
852
+ }
853
+ getCwd() {
854
+ return this.cwd;
855
+ }
856
+ getSessionDir() {
857
+ return this.sessionDir;
858
+ }
859
+ usesDefaultSessionDir() {
860
+ return (this.sessionDir === getDefaultSessionDirPath(this.cwd) ||
861
+ this.sessionDir === getLegacyDefaultSessionDirPath(this.cwd));
862
+ }
863
+ getSessionId() {
864
+ return this.sessionId;
865
+ }
866
+ getSessionFile() {
867
+ return this.sessionFile;
868
+ }
869
+ _persist(entry) {
870
+ if (!this.persist || !this.sessionFile)
871
+ return;
872
+ const hasAssistant = this.fileEntries.some((e) => e.type === "message" && e.message.role === "assistant");
873
+ if (!hasAssistant) {
874
+ if (this.flushed) {
875
+ appendFileSync(this.sessionFile, `${JSON.stringify(entry)}\n`);
876
+ }
877
+ else {
878
+ // Mark as not flushed so when assistant arrives, all entries get written
879
+ this.flushed = false;
880
+ }
881
+ return;
882
+ }
883
+ if (!this.flushed) {
884
+ const fd = openSync(this.sessionFile, "wx");
885
+ try {
886
+ for (const e of this.fileEntries) {
887
+ writeFileSync(fd, `${JSON.stringify(e)}\n`);
888
+ }
889
+ }
890
+ finally {
891
+ closeSync(fd);
892
+ }
893
+ this.flushed = true;
894
+ }
895
+ else {
896
+ appendFileSync(this.sessionFile, `${JSON.stringify(entry)}\n`);
897
+ }
898
+ }
899
+ _appendEntry(entry) {
900
+ this.fileEntries.push(entry);
901
+ this.byId.set(entry.id, entry);
902
+ this.leafId = entry.id;
903
+ this._persist(entry);
904
+ }
905
+ /** Append a message as child of current leaf, then advance leaf. Returns entry id.
906
+ * Does not allow writing CompactionSummaryMessage and BranchSummaryMessage directly.
907
+ * Reason: we want these to be top-level entries in the session, not message session entries,
908
+ * so it is easier to find them.
909
+ * These need to be appended via appendCompaction() and appendBranchSummary() methods.
910
+ */
911
+ appendMessage(message) {
912
+ const entry = {
913
+ type: "message",
914
+ id: generateId(this.byId),
915
+ parentId: this.leafId,
916
+ timestamp: new Date().toISOString(),
917
+ message,
918
+ };
919
+ this._appendEntry(entry);
920
+ return entry.id;
921
+ }
922
+ /** Append a thinking level change as child of current leaf, then advance leaf. Returns entry id. */
923
+ appendThinkingLevelChange(thinkingLevel) {
924
+ const entry = {
925
+ type: "thinking_level_change",
926
+ id: generateId(this.byId),
927
+ parentId: this.leafId,
928
+ timestamp: new Date().toISOString(),
929
+ thinkingLevel,
930
+ };
931
+ this._appendEntry(entry);
932
+ return entry.id;
933
+ }
934
+ /** Append a model change as child of current leaf, then advance leaf. Returns entry id. */
935
+ appendModelChange(provider, modelId) {
936
+ const entry = {
937
+ type: "model_change",
938
+ id: generateId(this.byId),
939
+ parentId: this.leafId,
940
+ timestamp: new Date().toISOString(),
941
+ provider,
942
+ modelId,
943
+ };
944
+ this._appendEntry(entry);
945
+ return entry.id;
946
+ }
947
+ /** Append a compaction summary as child of current leaf, then advance leaf. Returns entry id. */
948
+ appendCompaction(summary, firstKeptEntryId, tokensBefore, details, fromHook, usage) {
949
+ const entry = {
950
+ type: "compaction",
951
+ id: generateId(this.byId),
952
+ parentId: this.leafId,
953
+ timestamp: new Date().toISOString(),
954
+ summary,
955
+ firstKeptEntryId,
956
+ tokensBefore,
957
+ details,
958
+ usage,
959
+ fromHook,
960
+ };
961
+ this._appendEntry(entry);
962
+ return entry.id;
963
+ }
964
+ /** Append a custom entry (for extensions) as child of current leaf, then advance leaf. Returns entry id. */
965
+ appendCustomEntry(customType, data) {
966
+ const entry = {
967
+ type: "custom",
968
+ customType,
969
+ data,
970
+ id: generateId(this.byId),
971
+ parentId: this.leafId,
972
+ timestamp: new Date().toISOString(),
973
+ };
974
+ this._appendEntry(entry);
975
+ return entry.id;
976
+ }
977
+ /** Append a session info entry (e.g., display name). Returns entry id. */
978
+ appendSessionInfo(name) {
979
+ const sanitizedName = name.replace(/[\r\n]+/g, " ").trim();
980
+ const entry = {
981
+ type: "session_info",
982
+ id: generateId(this.byId),
983
+ parentId: this.leafId,
984
+ timestamp: new Date().toISOString(),
985
+ name: sanitizedName,
986
+ };
987
+ this._appendEntry(entry);
988
+ return entry.id;
989
+ }
990
+ /** Get the current session name from the latest session_info entry, if any. */
991
+ getSessionName() {
992
+ // Walk entries in reverse to find the latest session_info entry.
993
+ // Empty names explicitly clear the session title.
994
+ const entries = this.getEntries();
995
+ for (let i = entries.length - 1; i >= 0; i--) {
996
+ const entry = entries[i];
997
+ if (entry.type === "session_info") {
998
+ const raw = entry.name?.trim();
999
+ if (!raw)
1000
+ return undefined;
1001
+ // Strip legacy ":name " prefix stored by a past bug.
1002
+ return raw.replace(/^[:/]name\s+/, "");
1003
+ }
1004
+ }
1005
+ return undefined;
1006
+ }
1007
+ /**
1008
+ * Append a custom message entry (for extensions) that participates in LLM context.
1009
+ * @param customType Extension identifier for filtering on reload
1010
+ * @param content Message content (string or TextContent/ImageContent array)
1011
+ * @param display Whether to show in TUI (true = styled display, false = hidden)
1012
+ * @param details Optional extension-specific metadata (not sent to LLM)
1013
+ * @returns Entry id
1014
+ */
1015
+ appendCustomMessageEntry(customType, content, display, details) {
1016
+ const entry = {
1017
+ type: "custom_message",
1018
+ customType,
1019
+ content,
1020
+ display,
1021
+ details,
1022
+ id: generateId(this.byId),
1023
+ parentId: this.leafId,
1024
+ timestamp: new Date().toISOString(),
1025
+ };
1026
+ this._appendEntry(entry);
1027
+ return entry.id;
1028
+ }
1029
+ // =========================================================================
1030
+ // Tree Traversal
1031
+ // =========================================================================
1032
+ getLeafId() {
1033
+ return this.leafId;
1034
+ }
1035
+ getLeafEntry() {
1036
+ return this.leafId ? this.byId.get(this.leafId) : undefined;
1037
+ }
1038
+ getEntry(id) {
1039
+ return this.byId.get(id);
1040
+ }
1041
+ /**
1042
+ * Get all direct children of an entry.
1043
+ */
1044
+ getChildren(parentId) {
1045
+ const children = [];
1046
+ for (const entry of this.byId.values()) {
1047
+ if (entry.parentId === parentId) {
1048
+ children.push(entry);
1049
+ }
1050
+ }
1051
+ return children;
1052
+ }
1053
+ /**
1054
+ * Get the label for an entry, if any.
1055
+ */
1056
+ getLabel(id) {
1057
+ return this.labelsById.get(id);
1058
+ }
1059
+ /**
1060
+ * Set or clear a label on an entry.
1061
+ * Labels are user-defined markers for bookmarking/navigation.
1062
+ * Pass undefined or empty string to clear the label.
1063
+ */
1064
+ appendLabelChange(targetId, label) {
1065
+ if (!this.byId.has(targetId)) {
1066
+ throw new Error(`Entry ${targetId} not found`);
1067
+ }
1068
+ const entry = {
1069
+ type: "label",
1070
+ id: generateId(this.byId),
1071
+ parentId: this.leafId,
1072
+ timestamp: new Date().toISOString(),
1073
+ targetId,
1074
+ label,
1075
+ };
1076
+ this._appendEntry(entry);
1077
+ if (label) {
1078
+ this.labelsById.set(targetId, label);
1079
+ this.labelTimestampsById.set(targetId, entry.timestamp);
1080
+ }
1081
+ else {
1082
+ this.labelsById.delete(targetId);
1083
+ this.labelTimestampsById.delete(targetId);
1084
+ }
1085
+ return entry.id;
1086
+ }
1087
+ /**
1088
+ * Walk from entry to root, returning all entries in path order.
1089
+ * Includes all entry types (messages, compaction, model changes, etc.).
1090
+ * Use buildSessionContext() to get the resolved messages for the LLM.
1091
+ */
1092
+ getBranch(fromId) {
1093
+ const path = [];
1094
+ const startId = fromId ?? this.leafId;
1095
+ let current = startId ? this.byId.get(startId) : undefined;
1096
+ while (current) {
1097
+ path.push(current);
1098
+ current = current.parentId ? this.byId.get(current.parentId) : undefined;
1099
+ }
1100
+ path.reverse();
1101
+ return path;
1102
+ }
1103
+ /**
1104
+ * Build the active, compaction-aware entry list for context/rendering.
1105
+ * Uses tree traversal from current leaf.
1106
+ */
1107
+ buildContextEntries() {
1108
+ return buildContextEntries(this.getEntries(), this.leafId, this.byId);
1109
+ }
1110
+ /**
1111
+ * Build the session context (what gets sent to the LLM).
1112
+ * Uses tree traversal from current leaf.
1113
+ */
1114
+ buildSessionContext() {
1115
+ return buildSessionContext(this.getEntries(), this.leafId, this.byId);
1116
+ }
1117
+ /**
1118
+ * Get session header.
1119
+ */
1120
+ getHeader() {
1121
+ const h = this.fileEntries.find((e) => e.type === "session");
1122
+ return h ? h : null;
1123
+ }
1124
+ /**
1125
+ * Get all session entries (excludes header). Returns a shallow copy.
1126
+ * The session is append-only: use appendXXX() to add entries, branch() to
1127
+ * change the leaf pointer. Entries cannot be modified or deleted.
1128
+ */
1129
+ getEntries() {
1130
+ return this.fileEntries.filter((e) => e.type !== "session");
1131
+ }
1132
+ /**
1133
+ * Get the session as a tree structure. Returns a shallow defensive copy of all entries.
1134
+ * A well-formed session has exactly one root (first entry with parentId === null).
1135
+ * Orphaned entries (broken parent chain) are also returned as roots.
1136
+ */
1137
+ getTree() {
1138
+ const entries = this.getEntries();
1139
+ const nodeMap = new Map();
1140
+ const roots = [];
1141
+ // Create nodes with resolved labels
1142
+ for (const entry of entries) {
1143
+ const label = this.labelsById.get(entry.id);
1144
+ const labelTimestamp = this.labelTimestampsById.get(entry.id);
1145
+ nodeMap.set(entry.id, { entry, children: [], label, labelTimestamp });
1146
+ }
1147
+ // Build tree
1148
+ for (const entry of entries) {
1149
+ const node = nodeMap.get(entry.id);
1150
+ if (entry.parentId === null || entry.parentId === entry.id) {
1151
+ roots.push(node);
1152
+ }
1153
+ else {
1154
+ const parent = nodeMap.get(entry.parentId);
1155
+ if (parent) {
1156
+ parent.children.push(node);
1157
+ }
1158
+ else {
1159
+ // Orphan - treat as root
1160
+ roots.push(node);
1161
+ }
1162
+ }
1163
+ }
1164
+ // Sort children by timestamp (oldest first, newest at bottom)
1165
+ // Use iterative approach to avoid stack overflow on deep trees
1166
+ const stack = [...roots];
1167
+ while (stack.length > 0) {
1168
+ const node = stack.pop();
1169
+ node.children.sort((a, b) => new Date(a.entry.timestamp).getTime() - new Date(b.entry.timestamp).getTime());
1170
+ stack.push(...node.children);
1171
+ }
1172
+ return roots;
1173
+ }
1174
+ // =========================================================================
1175
+ // Branching
1176
+ // =========================================================================
1177
+ /**
1178
+ * Start a new branch from an earlier entry.
1179
+ * Moves the leaf pointer to the specified entry. The next appendXXX() call
1180
+ * will create a child of that entry, forming a new branch. Existing entries
1181
+ * are not modified or deleted.
1182
+ */
1183
+ branch(branchFromId) {
1184
+ if (!this.byId.has(branchFromId)) {
1185
+ throw new Error(`Entry ${branchFromId} not found`);
1186
+ }
1187
+ this.leafId = branchFromId;
1188
+ }
1189
+ /**
1190
+ * Reset the leaf pointer to null (before any entries).
1191
+ * The next appendXXX() call will create a new root entry (parentId = null).
1192
+ * Use this when navigating to re-edit the first user message.
1193
+ */
1194
+ resetLeaf() {
1195
+ this.leafId = null;
1196
+ }
1197
+ /**
1198
+ * Start a new branch with a summary of the abandoned path.
1199
+ * Same as branch(), but also appends a branch_summary entry that captures
1200
+ * context from the abandoned conversation path.
1201
+ */
1202
+ branchWithSummary(branchFromId, summary, details, fromHook, usage) {
1203
+ if (branchFromId !== null && !this.byId.has(branchFromId)) {
1204
+ throw new Error(`Entry ${branchFromId} not found`);
1205
+ }
1206
+ const fromId = this.leafId ?? "root";
1207
+ this.leafId = branchFromId;
1208
+ const entry = {
1209
+ type: "branch_summary",
1210
+ id: generateId(this.byId),
1211
+ parentId: branchFromId,
1212
+ timestamp: new Date().toISOString(),
1213
+ fromId,
1214
+ summary,
1215
+ details,
1216
+ usage,
1217
+ fromHook,
1218
+ };
1219
+ this._appendEntry(entry);
1220
+ return entry.id;
1221
+ }
1222
+ /**
1223
+ * Create a new session file containing only the path from root to the specified leaf.
1224
+ * Useful for extracting a single conversation path from a branched session.
1225
+ * Returns the new session file path, or undefined if not persisting.
1226
+ */
1227
+ createBranchedSession(leafId) {
1228
+ const previousSessionFile = this.sessionFile;
1229
+ const path = this.getBranch(leafId);
1230
+ if (path.length === 0) {
1231
+ throw new Error(`Entry ${leafId} not found`);
1232
+ }
1233
+ // Filter out LabelEntry from path - we'll recreate them from the resolved map.
1234
+ // Because labels are real tree entries, later entries can be children of labels;
1235
+ // removing labels requires re-chaining the retained path to avoid orphaned subtrees.
1236
+ const pathWithoutLabels = [];
1237
+ const replacementByLabelId = new Map();
1238
+ const pendingLabelIds = [];
1239
+ let pathParentId = null;
1240
+ for (const entry of path) {
1241
+ if (entry.type === "label") {
1242
+ pendingLabelIds.push(entry.id);
1243
+ continue;
1244
+ }
1245
+ for (const labelId of pendingLabelIds) {
1246
+ replacementByLabelId.set(labelId, entry.id);
1247
+ }
1248
+ pendingLabelIds.length = 0;
1249
+ pathWithoutLabels.push(entry.type === "compaction"
1250
+ ? {
1251
+ ...entry,
1252
+ parentId: pathParentId,
1253
+ firstKeptEntryId: replacementByLabelId.get(entry.firstKeptEntryId) ?? entry.firstKeptEntryId,
1254
+ }
1255
+ : { ...entry, parentId: pathParentId });
1256
+ pathParentId = entry.id;
1257
+ }
1258
+ const newSessionId = createSessionId();
1259
+ const timestamp = new Date().toISOString();
1260
+ const fileTimestamp = timestamp.replace(/[:.]/g, "-");
1261
+ const newSessionFile = join(this.getSessionDir(), `${fileTimestamp}_${newSessionId}.jsonl`);
1262
+ const header = {
1263
+ type: "session",
1264
+ version: CURRENT_SESSION_VERSION,
1265
+ id: newSessionId,
1266
+ timestamp,
1267
+ cwd: this.cwd,
1268
+ parentSession: this.persist ? previousSessionFile : undefined,
1269
+ };
1270
+ // Collect labels for entries in the path
1271
+ const pathEntryIds = new Set(pathWithoutLabels.map((e) => e.id));
1272
+ const labelsToWrite = [];
1273
+ for (const [targetId, label] of this.labelsById) {
1274
+ if (pathEntryIds.has(targetId)) {
1275
+ labelsToWrite.push({ targetId, label, timestamp: this.labelTimestampsById.get(targetId) });
1276
+ }
1277
+ }
1278
+ if (this.persist) {
1279
+ // Build label entries
1280
+ const lastEntryId = pathWithoutLabels[pathWithoutLabels.length - 1]?.id || null;
1281
+ let parentId = lastEntryId;
1282
+ const labelEntries = [];
1283
+ for (const { targetId, label, timestamp: labelTimestamp } of labelsToWrite) {
1284
+ const labelEntry = {
1285
+ type: "label",
1286
+ id: generateId(new Set(pathEntryIds)),
1287
+ parentId,
1288
+ timestamp: labelTimestamp,
1289
+ targetId,
1290
+ label,
1291
+ };
1292
+ pathEntryIds.add(labelEntry.id);
1293
+ labelEntries.push(labelEntry);
1294
+ parentId = labelEntry.id;
1295
+ }
1296
+ this.fileEntries = [header, ...pathWithoutLabels, ...labelEntries];
1297
+ this.sessionId = newSessionId;
1298
+ this.sessionFile = newSessionFile;
1299
+ this._buildIndex();
1300
+ // Only write the file now if it contains an assistant message.
1301
+ // Otherwise defer to _persist(), which creates the file on the
1302
+ // first assistant response, matching the newSession() contract
1303
+ // and avoiding the duplicate-header bug when _persist()'s
1304
+ // no-assistant guard later resets flushed to false.
1305
+ const hasAssistant = this.fileEntries.some((e) => e.type === "message" && e.message.role === "assistant");
1306
+ if (hasAssistant) {
1307
+ this._rewriteFile();
1308
+ this.flushed = true;
1309
+ }
1310
+ else {
1311
+ this.flushed = false;
1312
+ }
1313
+ return newSessionFile;
1314
+ }
1315
+ // In-memory mode: replace current session with the path + labels
1316
+ const labelEntries = [];
1317
+ let parentId = pathWithoutLabels[pathWithoutLabels.length - 1]?.id || null;
1318
+ for (const { targetId, label, timestamp: labelTimestamp } of labelsToWrite) {
1319
+ const labelEntry = {
1320
+ type: "label",
1321
+ id: generateId(new Set([...pathEntryIds, ...labelEntries.map((e) => e.id)])),
1322
+ parentId,
1323
+ timestamp: labelTimestamp,
1324
+ targetId,
1325
+ label,
1326
+ };
1327
+ labelEntries.push(labelEntry);
1328
+ parentId = labelEntry.id;
1329
+ }
1330
+ this.fileEntries = [header, ...pathWithoutLabels, ...labelEntries];
1331
+ this.sessionId = newSessionId;
1332
+ this._buildIndex();
1333
+ return undefined;
1334
+ }
1335
+ /**
1336
+ * Create a new session.
1337
+ * @param cwd Working directory (stored in session header)
1338
+ * @param sessionDir Optional session directory. If omitted, uses default (~/.ion/agent/sessions/<encoded-cwd>/).
1339
+ */
1340
+ static create(cwd, sessionDir, options) {
1341
+ const dir = sessionDir ? normalizePath(sessionDir) : getDefaultSessionDir(cwd);
1342
+ return new SessionManager(cwd, dir, undefined, true, options);
1343
+ }
1344
+ /**
1345
+ * Open a specific session file.
1346
+ * @param path Path to session file
1347
+ * @param sessionDir Optional session directory for /new or /branch. If omitted, derives from file's parent.
1348
+ * @param cwdOverride Optional cwd override instead of the session header cwd.
1349
+ */
1350
+ static open(path, sessionDir, cwdOverride) {
1351
+ const resolvedPath = resolvePath(path);
1352
+ let header = null;
1353
+ let preloadedFileEntries;
1354
+ if (cwdOverride === undefined && existsSync(resolvedPath)) {
1355
+ try {
1356
+ header = readSessionHeader(resolvedPath);
1357
+ }
1358
+ catch (error) {
1359
+ if (!(error instanceof SessionHeaderScanLimitError))
1360
+ throw error;
1361
+ // The bounded scan is only a discovery optimization. A full load remains
1362
+ // authoritative for legacy files with very large headers or prefixes.
1363
+ preloadedFileEntries = loadEntriesFromFile(resolvedPath);
1364
+ const firstEntry = preloadedFileEntries[0];
1365
+ header = firstEntry?.type === "session" ? firstEntry : null;
1366
+ }
1367
+ }
1368
+ const cwd = cwdOverride ?? (header ? getSessionHeaderCwd(header) : undefined) ?? process.cwd();
1369
+ // If no sessionDir provided, derive from file's parent directory
1370
+ const dir = sessionDir ? normalizePath(sessionDir) : resolve(resolvedPath, "..");
1371
+ return new SessionManager(cwd, dir, resolvedPath, true, undefined, preloadedFileEntries);
1372
+ }
1373
+ /**
1374
+ * Continue the most recent session, or create new if none.
1375
+ * @param cwd Working directory
1376
+ * @param sessionDir Optional session directory. If omitted, uses default (tree) with legacy flat fallback.
1377
+ */
1378
+ static continueRecent(cwd, sessionDir) {
1379
+ if (sessionDir) {
1380
+ const dir = normalizePath(sessionDir);
1381
+ const filterCwd = dir !== getDefaultSessionDirPath(cwd) && dir !== getLegacyDefaultSessionDirPath(cwd);
1382
+ const mostRecent = findMostRecentSession(dir, filterCwd ? cwd : undefined);
1383
+ if (mostRecent) {
1384
+ return new SessionManager(cwd, dir, mostRecent, true);
1385
+ }
1386
+ return new SessionManager(cwd, dir, undefined, true);
1387
+ }
1388
+ const treeDir = getDefaultSessionDir(cwd);
1389
+ const legacyDir = getLegacyDefaultSessionDirPath(cwd);
1390
+ let mostRecent = null;
1391
+ let chosenDir = treeDir;
1392
+ const candidates = [
1393
+ { dir: treeDir, file: findMostRecentSession(treeDir) },
1394
+ ...(treeDir === legacyDir ? [] : [{ dir: legacyDir, file: findMostRecentSession(legacyDir) }]),
1395
+ ];
1396
+ let bestMtime = -1;
1397
+ for (const { dir, file } of candidates) {
1398
+ if (!file)
1399
+ continue;
1400
+ try {
1401
+ const m = statSync(file).mtimeMs;
1402
+ if (m > bestMtime) {
1403
+ bestMtime = m;
1404
+ mostRecent = file;
1405
+ chosenDir = dir;
1406
+ }
1407
+ }
1408
+ catch { }
1409
+ }
1410
+ if (mostRecent) {
1411
+ return new SessionManager(cwd, chosenDir, mostRecent, true);
1412
+ }
1413
+ return new SessionManager(cwd, treeDir, undefined, true);
1414
+ }
1415
+ /** Create an in-memory session (no file persistence), optionally from entries held outside the filesystem. */
1416
+ static inMemory(cwd = process.cwd(), options, entries) {
1417
+ return new SessionManager(cwd, "", undefined, false, options, entries);
1418
+ }
1419
+ /**
1420
+ * Fork a session from another project directory into the current project.
1421
+ * Creates a new session in the target cwd with the full history from the source session.
1422
+ * @param sourcePath Path to the source session file
1423
+ * @param targetCwd Target working directory (where the new session will be stored)
1424
+ * @param sessionDir Optional session directory. If omitted, uses default for targetCwd.
1425
+ */
1426
+ static forkFrom(sourcePath, targetCwd, sessionDir, options) {
1427
+ const resolvedSourcePath = resolvePath(sourcePath);
1428
+ const resolvedTargetCwd = resolvePath(targetCwd);
1429
+ const sourceEntries = loadEntriesFromFile(resolvedSourcePath);
1430
+ if (sourceEntries.length === 0) {
1431
+ throw new Error(`Cannot fork: source session file is empty or invalid: ${resolvedSourcePath}`);
1432
+ }
1433
+ const sourceHeader = sourceEntries.find((e) => e.type === "session");
1434
+ if (!sourceHeader) {
1435
+ throw new Error(`Cannot fork: source session has no header: ${resolvedSourcePath}`);
1436
+ }
1437
+ const dir = sessionDir ? normalizePath(sessionDir) : getDefaultSessionDir(resolvedTargetCwd);
1438
+ if (!existsSync(dir)) {
1439
+ mkdirSync(dir, { recursive: true });
1440
+ }
1441
+ // Create new session file with new ID but forked content
1442
+ if (options?.id !== undefined) {
1443
+ assertValidSessionId(options.id);
1444
+ }
1445
+ const newSessionId = options?.id ?? createSessionId();
1446
+ const timestamp = new Date().toISOString();
1447
+ const fileTimestamp = timestamp.replace(/[:.]/g, "-");
1448
+ const newSessionFile = join(dir, `${fileTimestamp}_${newSessionId}.jsonl`);
1449
+ // Write new header pointing to source as parent, with updated cwd
1450
+ const newHeader = {
1451
+ type: "session",
1452
+ version: CURRENT_SESSION_VERSION,
1453
+ id: newSessionId,
1454
+ timestamp,
1455
+ cwd: resolvedTargetCwd,
1456
+ parentSession: resolvedSourcePath,
1457
+ };
1458
+ writeFileSync(newSessionFile, `${JSON.stringify(newHeader)}\n`, { flag: "wx" });
1459
+ // Copy all non-header entries from source
1460
+ for (const entry of sourceEntries) {
1461
+ if (entry.type !== "session") {
1462
+ appendFileSync(newSessionFile, `${JSON.stringify(entry)}\n`);
1463
+ }
1464
+ }
1465
+ return new SessionManager(resolvedTargetCwd, dir, newSessionFile, true);
1466
+ }
1467
+ /**
1468
+ * Full-text search across all session messages. Ensures every discovered
1469
+ * session file is indexed (cheap for already-indexed files), then runs the
1470
+ * FTS query. Returns ranked matches with snippets; empty when indexing is
1471
+ * unavailable or nothing matches.
1472
+ */
1473
+ static async search(query, limit = 50) {
1474
+ const trimmed = query.trim();
1475
+ if (!trimmed)
1476
+ return [];
1477
+ const sessionsDir = getSessionsDir();
1478
+ const index = indexHandleForSessionDir(sessionsDir);
1479
+ if (!index)
1480
+ return [];
1481
+ try {
1482
+ if (!existsSync(sessionsDir))
1483
+ return [];
1484
+ const allFiles = await collectAllSessionFiles(sessionsDir);
1485
+ index.prune(new Set(allFiles));
1486
+ await buildSessionInfosWithConcurrency(allFiles, () => { }, index);
1487
+ return index.search(trimmed, limit);
1488
+ }
1489
+ catch {
1490
+ return [];
1491
+ }
1492
+ }
1493
+ /**
1494
+ * List all sessions for a directory.
1495
+ * @param cwd Working directory (used to compute default session directory)
1496
+ * @param sessionDir Optional session directory. If omitted, uses default tree with legacy flat fallback.
1497
+ * @param onProgress Optional callback for progress updates (loaded, total)
1498
+ */
1499
+ static async list(cwd, sessionDir, onProgress) {
1500
+ if (sessionDir) {
1501
+ const dir = normalizePath(sessionDir);
1502
+ const filterCwd = dir !== getDefaultSessionDirPath(cwd) && dir !== getLegacyDefaultSessionDirPath(cwd);
1503
+ const resolvedCwd = resolvePath(cwd);
1504
+ const sessions = (await listSessionsFromDir(dir, onProgress, 0, undefined, indexHandleForSessionDir(dir))).filter((session) => !filterCwd || sessionCwdMatches(session.cwd, resolvedCwd));
1505
+ sessions.sort((a, b) => b.modified.getTime() - a.modified.getTime());
1506
+ return sessions;
1507
+ }
1508
+ const treeDir = getDefaultSessionDirPath(cwd);
1509
+ const legacyDir = getLegacyDefaultSessionDirPath(cwd);
1510
+ const dirs = treeDir === legacyDir ? [treeDir] : [treeDir, legacyDir];
1511
+ const all = [];
1512
+ const seen = new Set();
1513
+ for (const dir of dirs) {
1514
+ const sessions = await listSessionsFromDir(dir, undefined, 0, undefined, indexHandleForSessionDir(dir));
1515
+ for (const s of sessions) {
1516
+ if (!seen.has(s.path)) {
1517
+ seen.add(s.path);
1518
+ all.push(s);
1519
+ }
1520
+ }
1521
+ }
1522
+ // Report progress as single batch for compat
1523
+ if (onProgress)
1524
+ onProgress(all.length, all.length);
1525
+ const resolvedCwd = resolvePath(cwd);
1526
+ const filtered = all.filter((session) => sessionCwdMatches(session.cwd, resolvedCwd));
1527
+ // For default tree case, files are already scoped, but legacy filtering needs cwd match; tree files also have correct cwd, so filter anyway
1528
+ // Keep original semantics: only filter when sessionDir was custom; for default we want all sessions in that project's dirs (tree+legacy)
1529
+ // Since both dirs are already per-project, no need to filter further, but keep for safety
1530
+ filtered.sort((a, b) => b.modified.getTime() - a.modified.getTime());
1531
+ return filtered;
1532
+ }
1533
+ static async listAll(sessionDirOrOnProgress, onProgress) {
1534
+ const customSessionDir = typeof sessionDirOrOnProgress === "string" ? normalizePath(sessionDirOrOnProgress) : undefined;
1535
+ const progress = typeof sessionDirOrOnProgress === "function" ? sessionDirOrOnProgress : onProgress;
1536
+ if (customSessionDir) {
1537
+ // For custom, collect recursively if it's a base, otherwise just direct files
1538
+ const allFiles = await collectAllSessionFiles(customSessionDir);
1539
+ // Fallback to direct list if no recursive files but direct exists (flat)
1540
+ const files = allFiles.length > 0 ? allFiles : [];
1541
+ if (files.length === 0) {
1542
+ const sessions = await listSessionsFromDir(customSessionDir, progress, 0, undefined, indexHandleForSessionDir(customSessionDir));
1543
+ sessions.sort((a, b) => b.modified.getTime() - a.modified.getTime());
1544
+ return sessions;
1545
+ }
1546
+ const index = indexHandleForSessionDir(customSessionDir);
1547
+ index?.prune(new Set(files));
1548
+ let loaded = 0;
1549
+ const results = await buildSessionInfosWithConcurrency(files, () => {
1550
+ loaded++;
1551
+ progress?.(loaded, files.length);
1552
+ }, index);
1553
+ const sessions = [];
1554
+ for (const info of results)
1555
+ if (info)
1556
+ sessions.push(info);
1557
+ sessions.sort((a, b) => b.modified.getTime() - a.modified.getTime());
1558
+ return sessions;
1559
+ }
1560
+ const sessionsDir = getSessionsDir();
1561
+ try {
1562
+ if (!existsSync(sessionsDir)) {
1563
+ return [];
1564
+ }
1565
+ const allFiles = await collectAllSessionFiles(sessionsDir);
1566
+ let loaded = 0;
1567
+ const sessions = [];
1568
+ const index = indexHandleForSessionDir(sessionsDir);
1569
+ index?.prune(new Set(allFiles));
1570
+ const results = await buildSessionInfosWithConcurrency(allFiles, () => {
1571
+ loaded++;
1572
+ progress?.(loaded, allFiles.length);
1573
+ }, index);
1574
+ for (const info of results) {
1575
+ if (info) {
1576
+ sessions.push(info);
1577
+ }
1578
+ }
1579
+ sessions.sort((a, b) => b.modified.getTime() - a.modified.getTime());
1580
+ return sessions;
1581
+ }
1582
+ catch {
1583
+ return [];
1584
+ }
1585
+ }
1586
+ }
1587
+ //# sourceMappingURL=session-manager.js.map