@sammorrowdrums/mcpi 0.70.9 → 0.85.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 (888) hide show
  1. package/CHANGELOG.md +1623 -1
  2. package/LICENSE +21 -0
  3. package/README.md +196 -141
  4. package/dist/bun/cli.d.ts.map +1 -1
  5. package/dist/bun/cli.js +4 -0
  6. package/dist/bun/cli.js.map +1 -1
  7. package/dist/bun/register-bedrock.d.ts.map +1 -1
  8. package/dist/bun/register-bedrock.js +1 -1
  9. package/dist/bun/register-bedrock.js.map +1 -1
  10. package/dist/bun/restore-sandbox-env.d.ts +17 -0
  11. package/dist/bun/restore-sandbox-env.d.ts.map +1 -0
  12. package/dist/bun/restore-sandbox-env.js +36 -0
  13. package/dist/bun/restore-sandbox-env.js.map +1 -0
  14. package/dist/cli/args.d.ts +9 -2
  15. package/dist/cli/args.d.ts.map +1 -1
  16. package/dist/cli/args.js +116 -16
  17. package/dist/cli/args.js.map +1 -1
  18. package/dist/cli/auth-check.d.ts +19 -0
  19. package/dist/cli/auth-check.d.ts.map +1 -0
  20. package/dist/cli/auth-check.js +50 -0
  21. package/dist/cli/auth-check.js.map +1 -0
  22. package/dist/cli/auth-command.d.ts +24 -0
  23. package/dist/cli/auth-command.d.ts.map +1 -0
  24. package/dist/cli/auth-command.js +103 -0
  25. package/dist/cli/auth-command.js.map +1 -0
  26. package/dist/cli/config-selector.d.ts +6 -4
  27. package/dist/cli/config-selector.d.ts.map +1 -1
  28. package/dist/cli/config-selector.js +4 -4
  29. package/dist/cli/config-selector.js.map +1 -1
  30. package/dist/cli/credential-print.d.ts +13 -0
  31. package/dist/cli/credential-print.d.ts.map +1 -0
  32. package/dist/cli/credential-print.js +76 -0
  33. package/dist/cli/credential-print.js.map +1 -0
  34. package/dist/cli/experimental/auth.d.ts +16 -0
  35. package/dist/cli/experimental/auth.d.ts.map +1 -0
  36. package/dist/cli/experimental/auth.js +13 -0
  37. package/dist/cli/experimental/auth.js.map +1 -0
  38. package/dist/cli/experimental/cli.d.ts +6 -0
  39. package/dist/cli/experimental/cli.d.ts.map +1 -0
  40. package/dist/cli/experimental/cli.js +5 -0
  41. package/dist/cli/experimental/cli.js.map +1 -0
  42. package/dist/cli/experimental/command-options.d.ts +17 -0
  43. package/dist/cli/experimental/command-options.d.ts.map +1 -0
  44. package/dist/cli/experimental/command-options.js +35 -0
  45. package/dist/cli/experimental/command-options.js.map +1 -0
  46. package/dist/cli/experimental/command.d.ts +63 -0
  47. package/dist/cli/experimental/command.d.ts.map +1 -0
  48. package/dist/cli/experimental/command.js +130 -0
  49. package/dist/cli/experimental/command.js.map +1 -0
  50. package/dist/cli/experimental/commands/client.d.ts +13 -0
  51. package/dist/cli/experimental/commands/client.d.ts.map +1 -0
  52. package/dist/cli/experimental/commands/client.js +25 -0
  53. package/dist/cli/experimental/commands/client.js.map +1 -0
  54. package/dist/cli/experimental/commands/mcpi.d.ts +15 -0
  55. package/dist/cli/experimental/commands/mcpi.d.ts.map +1 -0
  56. package/dist/cli/experimental/commands/mcpi.js +28 -0
  57. package/dist/cli/experimental/commands/mcpi.js.map +1 -0
  58. package/dist/cli/experimental/commands/server.d.ts +13 -0
  59. package/dist/cli/experimental/commands/server.d.ts.map +1 -0
  60. package/dist/cli/experimental/commands/server.js +25 -0
  61. package/dist/cli/experimental/commands/server.js.map +1 -0
  62. package/dist/cli/experimental/transport-address.d.ts +10 -0
  63. package/dist/cli/experimental/transport-address.d.ts.map +1 -0
  64. package/dist/cli/experimental/transport-address.js +38 -0
  65. package/dist/cli/experimental/transport-address.js.map +1 -0
  66. package/dist/cli/file-processor.d.ts.map +1 -1
  67. package/dist/cli/file-processor.js +13 -26
  68. package/dist/cli/file-processor.js.map +1 -1
  69. package/dist/cli/initial-message.d.ts +1 -1
  70. package/dist/cli/initial-message.d.ts.map +1 -1
  71. package/dist/cli/initial-message.js.map +1 -1
  72. package/dist/cli/list-models.d.ts +2 -2
  73. package/dist/cli/list-models.d.ts.map +1 -1
  74. package/dist/cli/list-models.js +4 -4
  75. package/dist/cli/list-models.js.map +1 -1
  76. package/dist/cli/project-trust.d.ts +10 -0
  77. package/dist/cli/project-trust.d.ts.map +1 -0
  78. package/dist/cli/project-trust.js +48 -0
  79. package/dist/cli/project-trust.js.map +1 -0
  80. package/dist/cli/session-picker.d.ts +3 -2
  81. package/dist/cli/session-picker.d.ts.map +1 -1
  82. package/dist/cli/session-picker.js +5 -4
  83. package/dist/cli/session-picker.js.map +1 -1
  84. package/dist/cli/startup-ui.d.ts +20 -0
  85. package/dist/cli/startup-ui.d.ts.map +1 -0
  86. package/dist/cli/startup-ui.js +184 -0
  87. package/dist/cli/startup-ui.js.map +1 -0
  88. package/dist/cli.d.ts.map +1 -1
  89. package/dist/cli.js +6 -3
  90. package/dist/cli.js.map +1 -1
  91. package/dist/client/index.d.ts +3 -0
  92. package/dist/client/index.d.ts.map +1 -0
  93. package/dist/client/index.js +3 -0
  94. package/dist/client/index.js.map +1 -0
  95. package/dist/client/remote-session.d.ts +53 -0
  96. package/dist/client/remote-session.d.ts.map +1 -0
  97. package/dist/client/remote-session.js +340 -0
  98. package/dist/client/remote-session.js.map +1 -0
  99. package/dist/client/transcript.d.ts +12 -0
  100. package/dist/client/transcript.d.ts.map +1 -0
  101. package/dist/client/transcript.js +98 -0
  102. package/dist/client/transcript.js.map +1 -0
  103. package/dist/config.d.ts +34 -12
  104. package/dist/config.d.ts.map +1 -1
  105. package/dist/config.js +312 -61
  106. package/dist/config.js.map +1 -1
  107. package/dist/core/agent-session-runtime.d.ts +11 -9
  108. package/dist/core/agent-session-runtime.d.ts.map +1 -1
  109. package/dist/core/agent-session-runtime.js +16 -7
  110. package/dist/core/agent-session-runtime.js.map +1 -1
  111. package/dist/core/agent-session-services.d.ts +13 -12
  112. package/dist/core/agent-session-services.d.ts.map +1 -1
  113. package/dist/core/agent-session-services.js +34 -14
  114. package/dist/core/agent-session-services.js.map +1 -1
  115. package/dist/core/agent-session.d.ts +110 -53
  116. package/dist/core/agent-session.d.ts.map +1 -1
  117. package/dist/core/agent-session.js +658 -488
  118. package/dist/core/agent-session.js.map +1 -1
  119. package/dist/core/auth-guidance.d.ts.map +1 -1
  120. package/dist/core/auth-guidance.js.map +1 -1
  121. package/dist/core/auth-storage.d.ts +35 -104
  122. package/dist/core/auth-storage.d.ts.map +1 -1
  123. package/dist/core/auth-storage.js +272 -286
  124. package/dist/core/auth-storage.js.map +1 -1
  125. package/dist/core/bash-executor.d.ts +1 -1
  126. package/dist/core/bash-executor.d.ts.map +1 -1
  127. package/dist/core/bash-executor.js +11 -8
  128. package/dist/core/bash-executor.js.map +1 -1
  129. package/dist/core/cache-stats.d.ts +49 -0
  130. package/dist/core/cache-stats.d.ts.map +1 -0
  131. package/dist/core/cache-stats.js +101 -0
  132. package/dist/core/cache-stats.js.map +1 -0
  133. package/dist/core/compaction/branch-summarization.d.ts +16 -6
  134. package/dist/core/compaction/branch-summarization.d.ts.map +1 -1
  135. package/dist/core/compaction/branch-summarization.js +13 -10
  136. package/dist/core/compaction/branch-summarization.js.map +1 -1
  137. package/dist/core/compaction/compaction.d.ts +25 -9
  138. package/dist/core/compaction/compaction.d.ts.map +1 -1
  139. package/dist/core/compaction/compaction.js +163 -133
  140. package/dist/core/compaction/compaction.js.map +1 -1
  141. package/dist/core/compaction/index.d.ts +3 -3
  142. package/dist/core/compaction/index.d.ts.map +1 -1
  143. package/dist/core/compaction/index.js.map +1 -1
  144. package/dist/core/compaction/utils.d.ts +3 -3
  145. package/dist/core/compaction/utils.d.ts.map +1 -1
  146. package/dist/core/compaction/utils.js +7 -18
  147. package/dist/core/compaction/utils.js.map +1 -1
  148. package/dist/core/defaults.d.ts +1 -1
  149. package/dist/core/defaults.d.ts.map +1 -1
  150. package/dist/core/defaults.js.map +1 -1
  151. package/dist/core/env-overlay.d.ts +21 -0
  152. package/dist/core/env-overlay.d.ts.map +1 -0
  153. package/dist/core/env-overlay.js +25 -0
  154. package/dist/core/env-overlay.js.map +1 -0
  155. package/dist/core/exec.d.ts +8 -1
  156. package/dist/core/exec.d.ts.map +1 -1
  157. package/dist/core/exec.js +7 -1
  158. package/dist/core/exec.js.map +1 -1
  159. package/dist/core/experimental.d.ts +6 -0
  160. package/dist/core/experimental.d.ts.map +1 -0
  161. package/dist/core/experimental.js +8 -0
  162. package/dist/core/experimental.js.map +1 -0
  163. package/dist/core/export-html/ansi-to-html.d.ts.map +1 -1
  164. package/dist/core/export-html/ansi-to-html.js +1 -1
  165. package/dist/core/export-html/ansi-to-html.js.map +1 -1
  166. package/dist/core/export-html/index.d.ts +2 -2
  167. package/dist/core/export-html/index.d.ts.map +1 -1
  168. package/dist/core/export-html/index.js +8 -6
  169. package/dist/core/export-html/index.js.map +1 -1
  170. package/dist/core/export-html/template.css +53 -4
  171. package/dist/core/export-html/template.js +129 -35
  172. package/dist/core/export-html/tool-renderer.d.ts +2 -8
  173. package/dist/core/export-html/tool-renderer.d.ts.map +1 -1
  174. package/dist/core/export-html/tool-renderer.js +15 -2
  175. package/dist/core/export-html/tool-renderer.js.map +1 -1
  176. package/dist/core/export-html/vendor/marked.min.js +75 -3
  177. package/dist/core/extensions/index.d.ts +8 -8
  178. package/dist/core/extensions/index.d.ts.map +1 -1
  179. package/dist/core/extensions/index.js.map +1 -1
  180. package/dist/core/extensions/loader.d.ts +5 -7
  181. package/dist/core/extensions/loader.d.ts.map +1 -1
  182. package/dist/core/extensions/loader.js +160 -87
  183. package/dist/core/extensions/loader.js.map +1 -1
  184. package/dist/core/extensions/runner.d.ts +32 -13
  185. package/dist/core/extensions/runner.d.ts.map +1 -1
  186. package/dist/core/extensions/runner.js +192 -4
  187. package/dist/core/extensions/runner.js.map +1 -1
  188. package/dist/core/extensions/types.d.ts +217 -69
  189. package/dist/core/extensions/types.d.ts.map +1 -1
  190. package/dist/core/extensions/types.js.map +1 -1
  191. package/dist/core/extensions/wrapper.d.ts +3 -3
  192. package/dist/core/extensions/wrapper.d.ts.map +1 -1
  193. package/dist/core/extensions/wrapper.js +22 -3
  194. package/dist/core/extensions/wrapper.js.map +1 -1
  195. package/dist/core/footer-data-provider.d.ts +12 -0
  196. package/dist/core/footer-data-provider.d.ts.map +1 -1
  197. package/dist/core/footer-data-provider.js +30 -2
  198. package/dist/core/footer-data-provider.js.map +1 -1
  199. package/dist/core/http-dispatcher.d.ts +22 -0
  200. package/dist/core/http-dispatcher.d.ts.map +1 -0
  201. package/dist/core/http-dispatcher.js +96 -0
  202. package/dist/core/http-dispatcher.js.map +1 -0
  203. package/dist/core/index.d.ts +9 -8
  204. package/dist/core/index.d.ts.map +1 -1
  205. package/dist/core/index.js +1 -0
  206. package/dist/core/index.js.map +1 -1
  207. package/dist/core/keybindings.d.ts +79 -10
  208. package/dist/core/keybindings.d.ts.map +1 -1
  209. package/dist/core/keybindings.js +11 -10
  210. package/dist/core/keybindings.js.map +1 -1
  211. package/dist/core/messages.d.ts +2 -2
  212. package/dist/core/messages.d.ts.map +1 -1
  213. package/dist/core/messages.js.map +1 -1
  214. package/dist/core/model-config.d.ts +571 -0
  215. package/dist/core/model-config.d.ts.map +1 -0
  216. package/dist/core/model-config.js +254 -0
  217. package/dist/core/model-config.js.map +1 -0
  218. package/dist/core/model-registry.d.ts +23 -110
  219. package/dist/core/model-registry.d.ts.map +1 -1
  220. package/dist/core/model-registry.js +65 -616
  221. package/dist/core/model-registry.js.map +1 -1
  222. package/dist/core/model-resolver.d.ts +20 -7
  223. package/dist/core/model-resolver.d.ts.map +1 -1
  224. package/dist/core/model-resolver.js +139 -43
  225. package/dist/core/model-resolver.js.map +1 -1
  226. package/dist/core/model-runtime.d.ts +100 -0
  227. package/dist/core/model-runtime.d.ts.map +1 -0
  228. package/dist/core/model-runtime.js +602 -0
  229. package/dist/core/model-runtime.js.map +1 -0
  230. package/dist/core/models-store.d.ts +22 -0
  231. package/dist/core/models-store.d.ts.map +1 -0
  232. package/dist/core/models-store.js +113 -0
  233. package/dist/core/models-store.js.map +1 -0
  234. package/dist/core/output-guard.d.ts +1 -0
  235. package/dist/core/output-guard.d.ts.map +1 -1
  236. package/dist/core/output-guard.js +52 -22
  237. package/dist/core/output-guard.js.map +1 -1
  238. package/dist/core/package-manager.d.ts +21 -4
  239. package/dist/core/package-manager.d.ts.map +1 -1
  240. package/dist/core/package-manager.js +428 -191
  241. package/dist/core/package-manager.js.map +1 -1
  242. package/dist/core/pi-manifest.d.ts +8 -0
  243. package/dist/core/pi-manifest.d.ts.map +1 -0
  244. package/dist/core/pi-manifest.js +25 -0
  245. package/dist/core/pi-manifest.js.map +1 -0
  246. package/dist/core/project-trust.d.ts +15 -0
  247. package/dist/core/project-trust.d.ts.map +1 -0
  248. package/dist/core/project-trust.js +59 -0
  249. package/dist/core/project-trust.js.map +1 -0
  250. package/dist/core/prompt-templates.d.ts +4 -2
  251. package/dist/core/prompt-templates.d.ts.map +1 -1
  252. package/dist/core/prompt-templates.js +36 -50
  253. package/dist/core/prompt-templates.js.map +1 -1
  254. package/dist/core/provider-attribution.d.ts +4 -0
  255. package/dist/core/provider-attribution.d.ts.map +1 -0
  256. package/dist/core/provider-attribution.js +72 -0
  257. package/dist/core/provider-attribution.js.map +1 -0
  258. package/dist/core/provider-composer.d.ts +58 -0
  259. package/dist/core/provider-composer.d.ts.map +1 -0
  260. package/dist/core/provider-composer.js +396 -0
  261. package/dist/core/provider-composer.js.map +1 -0
  262. package/dist/core/radius.d.ts +2 -0
  263. package/dist/core/radius.d.ts.map +1 -0
  264. package/dist/core/radius.js +2 -0
  265. package/dist/core/radius.js.map +1 -0
  266. package/dist/core/remote-catalog-provider.d.ts +17 -0
  267. package/dist/core/remote-catalog-provider.d.ts.map +1 -0
  268. package/dist/core/remote-catalog-provider.js +137 -0
  269. package/dist/core/remote-catalog-provider.js.map +1 -0
  270. package/dist/core/resolve-config-value.d.ts +13 -6
  271. package/dist/core/resolve-config-value.d.ts.map +1 -1
  272. package/dist/core/resolve-config-value.js +143 -22
  273. package/dist/core/resolve-config-value.js.map +1 -1
  274. package/dist/core/resource-loader.d.ts +40 -12
  275. package/dist/core/resource-loader.d.ts.map +1 -1
  276. package/dist/core/resource-loader.js +236 -87
  277. package/dist/core/resource-loader.js.map +1 -1
  278. package/dist/core/runtime-credentials.d.ts +15 -0
  279. package/dist/core/runtime-credentials.d.ts.map +1 -0
  280. package/dist/core/runtime-credentials.js +39 -0
  281. package/dist/core/runtime-credentials.js.map +1 -0
  282. package/dist/core/sdk.d.ts +26 -25
  283. package/dist/core/sdk.d.ts.map +1 -1
  284. package/dist/core/sdk.js +56 -49
  285. package/dist/core/sdk.js.map +1 -1
  286. package/dist/core/session-manager.d.ts +42 -19
  287. package/dist/core/session-manager.d.ts.map +1 -1
  288. package/dist/core/session-manager.js +454 -223
  289. package/dist/core/session-manager.js.map +1 -1
  290. package/dist/core/settings-manager.d.ts +77 -8
  291. package/dist/core/settings-manager.d.ts.map +1 -1
  292. package/dist/core/settings-manager.js +255 -67
  293. package/dist/core/settings-manager.js.map +1 -1
  294. package/dist/core/skills.d.ts +2 -2
  295. package/dist/core/skills.d.ts.map +1 -1
  296. package/dist/core/skills.js +12 -34
  297. package/dist/core/skills.js.map +1 -1
  298. package/dist/core/slash-commands.d.ts +2 -1
  299. package/dist/core/slash-commands.d.ts.map +1 -1
  300. package/dist/core/slash-commands.js +4 -3
  301. package/dist/core/slash-commands.js.map +1 -1
  302. package/dist/core/source-info.d.ts +1 -1
  303. package/dist/core/source-info.d.ts.map +1 -1
  304. package/dist/core/source-info.js.map +1 -1
  305. package/dist/core/system-prompt.d.ts +1 -1
  306. package/dist/core/system-prompt.d.ts.map +1 -1
  307. package/dist/core/system-prompt.js +15 -25
  308. package/dist/core/system-prompt.js.map +1 -1
  309. package/dist/core/telemetry.d.ts +7 -1
  310. package/dist/core/telemetry.d.ts.map +1 -1
  311. package/dist/core/telemetry.js +7 -1
  312. package/dist/core/telemetry.js.map +1 -1
  313. package/dist/core/timings.d.ts +5 -3
  314. package/dist/core/timings.d.ts.map +1 -1
  315. package/dist/core/timings.js +26 -16
  316. package/dist/core/timings.js.map +1 -1
  317. package/dist/core/tools/bash.d.ts +11 -7
  318. package/dist/core/tools/bash.d.ts.map +1 -1
  319. package/dist/core/tools/bash.js +220 -188
  320. package/dist/core/tools/bash.js.map +1 -1
  321. package/dist/core/tools/edit-diff.d.ts +26 -5
  322. package/dist/core/tools/edit-diff.d.ts.map +1 -1
  323. package/dist/core/tools/edit-diff.js +110 -23
  324. package/dist/core/tools/edit-diff.js.map +1 -1
  325. package/dist/core/tools/edit.d.ts +11 -5
  326. package/dist/core/tools/edit.d.ts.map +1 -1
  327. package/dist/core/tools/edit.js +67 -100
  328. package/dist/core/tools/edit.js.map +1 -1
  329. package/dist/core/tools/file-mutation-queue.d.ts.map +1 -1
  330. package/dist/core/tools/file-mutation-queue.js +27 -12
  331. package/dist/core/tools/file-mutation-queue.js.map +1 -1
  332. package/dist/core/tools/find.d.ts +10 -3
  333. package/dist/core/tools/find.d.ts.map +1 -1
  334. package/dist/core/tools/find.js +41 -37
  335. package/dist/core/tools/find.js.map +1 -1
  336. package/dist/core/tools/grep.d.ts +7 -3
  337. package/dist/core/tools/grep.d.ts.map +1 -1
  338. package/dist/core/tools/grep.js +12 -8
  339. package/dist/core/tools/grep.js.map +1 -1
  340. package/dist/core/tools/index.d.ts +18 -18
  341. package/dist/core/tools/index.d.ts.map +1 -1
  342. package/dist/core/tools/index.js.map +1 -1
  343. package/dist/core/tools/ls.d.ts +7 -3
  344. package/dist/core/tools/ls.d.ts.map +1 -1
  345. package/dist/core/tools/ls.js +17 -15
  346. package/dist/core/tools/ls.js.map +1 -1
  347. package/dist/core/tools/output-accumulator.d.ts +52 -0
  348. package/dist/core/tools/output-accumulator.d.ts.map +1 -0
  349. package/dist/core/tools/output-accumulator.js +184 -0
  350. package/dist/core/tools/output-accumulator.js.map +1 -0
  351. package/dist/core/tools/path-utils.d.ts +2 -0
  352. package/dist/core/tools/path-utils.d.ts.map +1 -1
  353. package/dist/core/tools/path-utils.js +39 -21
  354. package/dist/core/tools/path-utils.js.map +1 -1
  355. package/dist/core/tools/read.d.ts +7 -3
  356. package/dist/core/tools/read.d.ts.map +1 -1
  357. package/dist/core/tools/read.js +101 -51
  358. package/dist/core/tools/read.js.map +1 -1
  359. package/dist/core/tools/render-utils.d.ts +5 -2
  360. package/dist/core/tools/render-utils.d.ts.map +1 -1
  361. package/dist/core/tools/render-utils.js +18 -2
  362. package/dist/core/tools/render-utils.js.map +1 -1
  363. package/dist/core/tools/tool-definition-wrapper.d.ts +2 -2
  364. package/dist/core/tools/tool-definition-wrapper.d.ts.map +1 -1
  365. package/dist/core/tools/tool-definition-wrapper.js +3 -3
  366. package/dist/core/tools/tool-definition-wrapper.js.map +1 -1
  367. package/dist/core/tools/truncate.d.ts.map +1 -1
  368. package/dist/core/tools/truncate.js +12 -2
  369. package/dist/core/tools/truncate.js.map +1 -1
  370. package/dist/core/tools/write.d.ts +6 -2
  371. package/dist/core/tools/write.d.ts.map +1 -1
  372. package/dist/core/tools/write.js +35 -45
  373. package/dist/core/tools/write.js.map +1 -1
  374. package/dist/core/trust-manager.d.ts +36 -0
  375. package/dist/core/trust-manager.d.ts.map +1 -0
  376. package/dist/core/trust-manager.js +202 -0
  377. package/dist/core/trust-manager.js.map +1 -0
  378. package/dist/core/usage-totals.d.ts +19 -0
  379. package/dist/core/usage-totals.d.ts.map +1 -0
  380. package/dist/core/usage-totals.js +52 -0
  381. package/dist/core/usage-totals.js.map +1 -0
  382. package/dist/extensions/index.d.ts +3 -0
  383. package/dist/extensions/index.d.ts.map +1 -0
  384. package/dist/extensions/index.js +3 -0
  385. package/dist/extensions/index.js.map +1 -0
  386. package/dist/extensions/llama/client.d.ts +61 -0
  387. package/dist/extensions/llama/client.d.ts.map +1 -0
  388. package/dist/extensions/llama/client.js +302 -0
  389. package/dist/extensions/llama/client.js.map +1 -0
  390. package/dist/extensions/llama/huggingface.d.ts +23 -0
  391. package/dist/extensions/llama/huggingface.d.ts.map +1 -0
  392. package/dist/extensions/llama/huggingface.js +141 -0
  393. package/dist/extensions/llama/huggingface.js.map +1 -0
  394. package/dist/extensions/llama/index.d.ts +3 -0
  395. package/dist/extensions/llama/index.d.ts.map +1 -0
  396. package/dist/extensions/llama/index.js +217 -0
  397. package/dist/extensions/llama/index.js.map +1 -0
  398. package/dist/extensions/llama/provider.d.ts +10 -0
  399. package/dist/extensions/llama/provider.d.ts.map +1 -0
  400. package/dist/extensions/llama/provider.js +121 -0
  401. package/dist/extensions/llama/provider.js.map +1 -0
  402. package/dist/extensions/llama/ui.d.ts +42 -0
  403. package/dist/extensions/llama/ui.d.ts.map +1 -0
  404. package/dist/extensions/llama/ui.js +416 -0
  405. package/dist/extensions/llama/ui.js.map +1 -0
  406. package/dist/index.d.ts +34 -27
  407. package/dist/index.d.ts.map +1 -1
  408. package/dist/index.js +11 -5
  409. package/dist/index.js.map +1 -1
  410. package/dist/main.d.ts +2 -2
  411. package/dist/main.d.ts.map +1 -1
  412. package/dist/main.js +311 -101
  413. package/dist/main.js.map +1 -1
  414. package/dist/migrations.d.ts +5 -5
  415. package/dist/migrations.d.ts.map +1 -1
  416. package/dist/migrations.js +10 -10
  417. package/dist/migrations.js.map +1 -1
  418. package/dist/modes/index.d.ts +6 -5
  419. package/dist/modes/index.d.ts.map +1 -1
  420. package/dist/modes/index.js.map +1 -1
  421. package/dist/modes/interactive/components/armin.d.ts +1 -1
  422. package/dist/modes/interactive/components/armin.d.ts.map +1 -1
  423. package/dist/modes/interactive/components/armin.js.map +1 -1
  424. package/dist/modes/interactive/components/assistant-message.d.ts +8 -3
  425. package/dist/modes/interactive/components/assistant-message.d.ts.map +1 -1
  426. package/dist/modes/interactive/components/assistant-message.js +55 -26
  427. package/dist/modes/interactive/components/assistant-message.js.map +1 -1
  428. package/dist/modes/interactive/components/bash-execution.d.ts +2 -2
  429. package/dist/modes/interactive/components/bash-execution.d.ts.map +1 -1
  430. package/dist/modes/interactive/components/bash-execution.js +4 -4
  431. package/dist/modes/interactive/components/bash-execution.js.map +1 -1
  432. package/dist/modes/interactive/components/bordered-loader.d.ts +2 -2
  433. package/dist/modes/interactive/components/bordered-loader.d.ts.map +1 -1
  434. package/dist/modes/interactive/components/bordered-loader.js +1 -1
  435. package/dist/modes/interactive/components/bordered-loader.js.map +1 -1
  436. package/dist/modes/interactive/components/branch-summary-message.d.ts +2 -2
  437. package/dist/modes/interactive/components/branch-summary-message.d.ts.map +1 -1
  438. package/dist/modes/interactive/components/branch-summary-message.js +1 -1
  439. package/dist/modes/interactive/components/branch-summary-message.js.map +1 -1
  440. package/dist/modes/interactive/components/compaction-summary-message.d.ts +2 -2
  441. package/dist/modes/interactive/components/compaction-summary-message.d.ts.map +1 -1
  442. package/dist/modes/interactive/components/compaction-summary-message.js +1 -1
  443. package/dist/modes/interactive/components/compaction-summary-message.js.map +1 -1
  444. package/dist/modes/interactive/components/config-selector.d.ts +37 -6
  445. package/dist/modes/interactive/components/config-selector.d.ts.map +1 -1
  446. package/dist/modes/interactive/components/config-selector.js +318 -34
  447. package/dist/modes/interactive/components/config-selector.js.map +1 -1
  448. package/dist/modes/interactive/components/countdown-timer.d.ts +3 -3
  449. package/dist/modes/interactive/components/countdown-timer.d.ts.map +1 -1
  450. package/dist/modes/interactive/components/countdown-timer.js +2 -2
  451. package/dist/modes/interactive/components/countdown-timer.js.map +1 -1
  452. package/dist/modes/interactive/components/custom-editor.d.ts +2 -2
  453. package/dist/modes/interactive/components/custom-editor.d.ts.map +1 -1
  454. package/dist/modes/interactive/components/custom-editor.js +9 -2
  455. package/dist/modes/interactive/components/custom-editor.js.map +1 -1
  456. package/dist/modes/interactive/components/custom-entry.d.ts +19 -0
  457. package/dist/modes/interactive/components/custom-entry.d.ts.map +1 -0
  458. package/dist/modes/interactive/components/custom-entry.js +52 -0
  459. package/dist/modes/interactive/components/custom-entry.js.map +1 -0
  460. package/dist/modes/interactive/components/custom-message.d.ts +6 -4
  461. package/dist/modes/interactive/components/custom-message.d.ts.map +1 -1
  462. package/dist/modes/interactive/components/custom-message.js +11 -3
  463. package/dist/modes/interactive/components/custom-message.js.map +1 -1
  464. package/dist/modes/interactive/components/daxnuts.d.ts +1 -1
  465. package/dist/modes/interactive/components/daxnuts.d.ts.map +1 -1
  466. package/dist/modes/interactive/components/daxnuts.js.map +1 -1
  467. package/dist/modes/interactive/components/diff.d.ts.map +1 -1
  468. package/dist/modes/interactive/components/diff.js.map +1 -1
  469. package/dist/modes/interactive/components/dynamic-border.d.ts +1 -1
  470. package/dist/modes/interactive/components/dynamic-border.d.ts.map +1 -1
  471. package/dist/modes/interactive/components/dynamic-border.js.map +1 -1
  472. package/dist/modes/interactive/components/extension-editor.d.ts +5 -4
  473. package/dist/modes/interactive/components/extension-editor.d.ts.map +1 -1
  474. package/dist/modes/interactive/components/extension-editor.js +19 -32
  475. package/dist/modes/interactive/components/extension-editor.js.map +1 -1
  476. package/dist/modes/interactive/components/extension-input.d.ts +1 -1
  477. package/dist/modes/interactive/components/extension-input.d.ts.map +1 -1
  478. package/dist/modes/interactive/components/extension-input.js +1 -1
  479. package/dist/modes/interactive/components/extension-input.js.map +1 -1
  480. package/dist/modes/interactive/components/extension-selector.d.ts +3 -1
  481. package/dist/modes/interactive/components/extension-selector.d.ts.map +1 -1
  482. package/dist/modes/interactive/components/extension-selector.js +7 -2
  483. package/dist/modes/interactive/components/extension-selector.js.map +1 -1
  484. package/dist/modes/interactive/components/first-time-setup.d.ts +25 -0
  485. package/dist/modes/interactive/components/first-time-setup.d.ts.map +1 -0
  486. package/dist/modes/interactive/components/first-time-setup.js +103 -0
  487. package/dist/modes/interactive/components/first-time-setup.js.map +1 -0
  488. package/dist/modes/interactive/components/footer.d.ts +9 -4
  489. package/dist/modes/interactive/components/footer.d.ts.map +1 -1
  490. package/dist/modes/interactive/components/footer.js +52 -31
  491. package/dist/modes/interactive/components/footer.js.map +1 -1
  492. package/dist/modes/interactive/components/index.d.ts +33 -31
  493. package/dist/modes/interactive/components/index.d.ts.map +1 -1
  494. package/dist/modes/interactive/components/index.js +2 -0
  495. package/dist/modes/interactive/components/index.js.map +1 -1
  496. package/dist/modes/interactive/components/keybinding-hints.d.ts +6 -1
  497. package/dist/modes/interactive/components/keybinding-hints.d.ts.map +1 -1
  498. package/dist/modes/interactive/components/keybinding-hints.js +20 -6
  499. package/dist/modes/interactive/components/keybinding-hints.js.map +1 -1
  500. package/dist/modes/interactive/components/login-dialog.d.ts +12 -6
  501. package/dist/modes/interactive/components/login-dialog.d.ts.map +1 -1
  502. package/dist/modes/interactive/components/login-dialog.js +46 -17
  503. package/dist/modes/interactive/components/login-dialog.js.map +1 -1
  504. package/dist/modes/interactive/components/markdown-transform.d.ts +3 -0
  505. package/dist/modes/interactive/components/markdown-transform.d.ts.map +1 -0
  506. package/dist/modes/interactive/components/markdown-transform.js +19 -0
  507. package/dist/modes/interactive/components/markdown-transform.js.map +1 -0
  508. package/dist/modes/interactive/components/mermaid.d.ts +11 -0
  509. package/dist/modes/interactive/components/mermaid.d.ts.map +1 -0
  510. package/dist/modes/interactive/components/mermaid.js +75 -0
  511. package/dist/modes/interactive/components/mermaid.js.map +1 -0
  512. package/dist/modes/interactive/components/model-selector.d.ts +13 -6
  513. package/dist/modes/interactive/components/model-selector.d.ts.map +1 -1
  514. package/dist/modes/interactive/components/model-selector.js +92 -44
  515. package/dist/modes/interactive/components/model-selector.js.map +1 -1
  516. package/dist/modes/interactive/components/oauth-selector.d.ts +7 -4
  517. package/dist/modes/interactive/components/oauth-selector.d.ts.map +1 -1
  518. package/dist/modes/interactive/components/oauth-selector.js +32 -28
  519. package/dist/modes/interactive/components/oauth-selector.js.map +1 -1
  520. package/dist/modes/interactive/components/scoped-models-selector.d.ts +5 -1
  521. package/dist/modes/interactive/components/scoped-models-selector.d.ts.map +1 -1
  522. package/dist/modes/interactive/components/scoped-models-selector.js +52 -14
  523. package/dist/modes/interactive/components/scoped-models-selector.js.map +1 -1
  524. package/dist/modes/interactive/components/session-selector-search.d.ts +1 -1
  525. package/dist/modes/interactive/components/session-selector-search.d.ts.map +1 -1
  526. package/dist/modes/interactive/components/session-selector-search.js +1 -1
  527. package/dist/modes/interactive/components/session-selector-search.js.map +1 -1
  528. package/dist/modes/interactive/components/session-selector.d.ts +4 -5
  529. package/dist/modes/interactive/components/session-selector.d.ts.map +1 -1
  530. package/dist/modes/interactive/components/session-selector.js +18 -16
  531. package/dist/modes/interactive/components/session-selector.js.map +1 -1
  532. package/dist/modes/interactive/components/settings-selector.d.ts +23 -2
  533. package/dist/modes/interactive/components/settings-selector.d.ts.map +1 -1
  534. package/dist/modes/interactive/components/settings-selector.js +322 -22
  535. package/dist/modes/interactive/components/settings-selector.js.map +1 -1
  536. package/dist/modes/interactive/components/show-images-selector.d.ts +1 -1
  537. package/dist/modes/interactive/components/show-images-selector.d.ts.map +1 -1
  538. package/dist/modes/interactive/components/show-images-selector.js +1 -1
  539. package/dist/modes/interactive/components/show-images-selector.js.map +1 -1
  540. package/dist/modes/interactive/components/skill-invocation-message.d.ts +2 -2
  541. package/dist/modes/interactive/components/skill-invocation-message.d.ts.map +1 -1
  542. package/dist/modes/interactive/components/skill-invocation-message.js +1 -1
  543. package/dist/modes/interactive/components/skill-invocation-message.js.map +1 -1
  544. package/dist/modes/interactive/components/status-indicator.d.ts +28 -0
  545. package/dist/modes/interactive/components/status-indicator.d.ts.map +1 -0
  546. package/dist/modes/interactive/components/status-indicator.js +60 -0
  547. package/dist/modes/interactive/components/status-indicator.js.map +1 -0
  548. package/dist/modes/interactive/components/theme-selector.d.ts +1 -1
  549. package/dist/modes/interactive/components/theme-selector.d.ts.map +1 -1
  550. package/dist/modes/interactive/components/theme-selector.js +1 -1
  551. package/dist/modes/interactive/components/theme-selector.js.map +1 -1
  552. package/dist/modes/interactive/components/thinking-selector.d.ts +2 -2
  553. package/dist/modes/interactive/components/thinking-selector.d.ts.map +1 -1
  554. package/dist/modes/interactive/components/thinking-selector.js +3 -2
  555. package/dist/modes/interactive/components/thinking-selector.js.map +1 -1
  556. package/dist/modes/interactive/components/tool-execution.d.ts +2 -2
  557. package/dist/modes/interactive/components/tool-execution.d.ts.map +1 -1
  558. package/dist/modes/interactive/components/tool-execution.js +33 -2
  559. package/dist/modes/interactive/components/tool-execution.js.map +1 -1
  560. package/dist/modes/interactive/components/tree-selector.d.ts +7 -2
  561. package/dist/modes/interactive/components/tree-selector.d.ts.map +1 -1
  562. package/dist/modes/interactive/components/tree-selector.js +179 -26
  563. package/dist/modes/interactive/components/tree-selector.js.map +1 -1
  564. package/dist/modes/interactive/components/trust-selector.d.ts +23 -0
  565. package/dist/modes/interactive/components/trust-selector.d.ts.map +1 -0
  566. package/dist/modes/interactive/components/trust-selector.js +91 -0
  567. package/dist/modes/interactive/components/trust-selector.js.map +1 -0
  568. package/dist/modes/interactive/components/user-message-selector.d.ts +1 -1
  569. package/dist/modes/interactive/components/user-message-selector.d.ts.map +1 -1
  570. package/dist/modes/interactive/components/user-message-selector.js +1 -1
  571. package/dist/modes/interactive/components/user-message-selector.js.map +1 -1
  572. package/dist/modes/interactive/components/user-message.d.ts +9 -3
  573. package/dist/modes/interactive/components/user-message.d.ts.map +1 -1
  574. package/dist/modes/interactive/components/user-message.js +26 -6
  575. package/dist/modes/interactive/components/user-message.js.map +1 -1
  576. package/dist/modes/interactive/components/visual-truncate.d.ts.map +1 -1
  577. package/dist/modes/interactive/components/visual-truncate.js +1 -1
  578. package/dist/modes/interactive/components/visual-truncate.js.map +1 -1
  579. package/dist/modes/interactive/external-editor.d.ts +12 -0
  580. package/dist/modes/interactive/external-editor.d.ts.map +1 -0
  581. package/dist/modes/interactive/external-editor.js +37 -0
  582. package/dist/modes/interactive/external-editor.js.map +1 -0
  583. package/dist/modes/interactive/interactive-mode.d.ts +104 -26
  584. package/dist/modes/interactive/interactive-mode.d.ts.map +1 -1
  585. package/dist/modes/interactive/interactive-mode.js +1565 -692
  586. package/dist/modes/interactive/interactive-mode.js.map +1 -1
  587. package/dist/modes/interactive/model-catalog-refresh.d.ts +7 -0
  588. package/dist/modes/interactive/model-catalog-refresh.d.ts.map +1 -0
  589. package/dist/modes/interactive/model-catalog-refresh.js +34 -0
  590. package/dist/modes/interactive/model-catalog-refresh.js.map +1 -0
  591. package/dist/modes/interactive/model-search.d.ts +12 -0
  592. package/dist/modes/interactive/model-search.d.ts.map +1 -0
  593. package/dist/modes/interactive/model-search.js +15 -0
  594. package/dist/modes/interactive/model-search.js.map +1 -0
  595. package/dist/modes/interactive/theme/dark.json +10 -5
  596. package/dist/modes/interactive/theme/light.json +10 -5
  597. package/dist/modes/interactive/theme/theme-controller.d.ts +40 -0
  598. package/dist/modes/interactive/theme/theme-controller.d.ts.map +1 -0
  599. package/dist/modes/interactive/theme/theme-controller.js +125 -0
  600. package/dist/modes/interactive/theme/theme-controller.js.map +1 -0
  601. package/dist/modes/interactive/theme/theme-schema.json +22 -5
  602. package/dist/modes/interactive/theme/theme.d.ts +48 -7
  603. package/dist/modes/interactive/theme/theme.d.ts.map +1 -1
  604. package/dist/modes/interactive/theme/theme.js +194 -76
  605. package/dist/modes/interactive/theme/theme.js.map +1 -1
  606. package/dist/modes/json-event.d.ts +31 -0
  607. package/dist/modes/json-event.d.ts.map +1 -0
  608. package/dist/modes/json-event.js +15 -0
  609. package/dist/modes/json-event.js.map +1 -0
  610. package/dist/modes/print-mode.d.ts +3 -3
  611. package/dist/modes/print-mode.d.ts.map +1 -1
  612. package/dist/modes/print-mode.js +16 -5
  613. package/dist/modes/print-mode.js.map +1 -1
  614. package/dist/modes/rpc/rpc-client.d.ts +33 -10
  615. package/dist/modes/rpc/rpc-client.d.ts.map +1 -1
  616. package/dist/modes/rpc/rpc-client.js +89 -11
  617. package/dist/modes/rpc/rpc-client.js.map +1 -1
  618. package/dist/modes/rpc/rpc-mode.d.ts +2 -2
  619. package/dist/modes/rpc/rpc-mode.d.ts.map +1 -1
  620. package/dist/modes/rpc/rpc-mode.js +69 -9
  621. package/dist/modes/rpc/rpc-mode.js.map +1 -1
  622. package/dist/modes/rpc/rpc-types.d.ts +43 -5
  623. package/dist/modes/rpc/rpc-types.d.ts.map +1 -1
  624. package/dist/modes/rpc/rpc-types.js.map +1 -1
  625. package/dist/package-manager-cli.d.ts +6 -2
  626. package/dist/package-manager-cli.d.ts.map +1 -1
  627. package/dist/package-manager-cli.js +527 -25
  628. package/dist/package-manager-cli.js.map +1 -1
  629. package/dist/path-migration.d.ts +13 -0
  630. package/dist/path-migration.d.ts.map +1 -0
  631. package/dist/path-migration.js +52 -0
  632. package/dist/path-migration.js.map +1 -0
  633. package/dist/rpc-entry.d.ts +3 -0
  634. package/dist/rpc-entry.d.ts.map +1 -0
  635. package/dist/rpc-entry.js +11 -0
  636. package/dist/rpc-entry.js.map +1 -0
  637. package/dist/server/create-harness.d.ts +26 -0
  638. package/dist/server/create-harness.d.ts.map +1 -0
  639. package/dist/server/create-harness.js +106 -0
  640. package/dist/server/create-harness.js.map +1 -0
  641. package/dist/utils/abort.d.ts +5 -0
  642. package/dist/utils/abort.d.ts.map +1 -0
  643. package/dist/utils/abort.js +48 -0
  644. package/dist/utils/abort.js.map +1 -0
  645. package/dist/utils/ansi.d.ts +2 -0
  646. package/dist/utils/ansi.d.ts.map +1 -0
  647. package/dist/utils/ansi.js +52 -0
  648. package/dist/utils/ansi.js.map +1 -0
  649. package/dist/utils/changelog.d.ts +2 -1
  650. package/dist/utils/changelog.d.ts.map +1 -1
  651. package/dist/utils/changelog.js +85 -0
  652. package/dist/utils/changelog.js.map +1 -1
  653. package/dist/utils/child-process.d.ts +12 -5
  654. package/dist/utils/child-process.d.ts.map +1 -1
  655. package/dist/utils/child-process.js +33 -5
  656. package/dist/utils/child-process.js.map +1 -1
  657. package/dist/utils/clipboard-image.d.ts.map +1 -1
  658. package/dist/utils/clipboard-image.js +4 -4
  659. package/dist/utils/clipboard-image.js.map +1 -1
  660. package/dist/utils/clipboard-native.d.ts +4 -1
  661. package/dist/utils/clipboard-native.d.ts.map +1 -1
  662. package/dist/utils/clipboard-native.js +14 -8
  663. package/dist/utils/clipboard-native.js.map +1 -1
  664. package/dist/utils/clipboard.d.ts +2 -0
  665. package/dist/utils/clipboard.d.ts.map +1 -1
  666. package/dist/utils/clipboard.js +129 -46
  667. package/dist/utils/clipboard.js.map +1 -1
  668. package/dist/utils/deprecation.d.ts +4 -0
  669. package/dist/utils/deprecation.d.ts.map +1 -0
  670. package/dist/utils/deprecation.js +13 -0
  671. package/dist/utils/deprecation.js.map +1 -0
  672. package/dist/utils/exif-orientation.d.ts +1 -1
  673. package/dist/utils/exif-orientation.d.ts.map +1 -1
  674. package/dist/utils/exif-orientation.js.map +1 -1
  675. package/dist/utils/git.d.ts.map +1 -1
  676. package/dist/utils/git.js +54 -22
  677. package/dist/utils/git.js.map +1 -1
  678. package/dist/utils/html.d.ts +7 -0
  679. package/dist/utils/html.d.ts.map +1 -0
  680. package/dist/utils/html.js +40 -0
  681. package/dist/utils/html.js.map +1 -0
  682. package/dist/utils/image-convert.d.ts +1 -0
  683. package/dist/utils/image-convert.d.ts.map +1 -1
  684. package/dist/utils/image-convert.js +21 -15
  685. package/dist/utils/image-convert.js.map +1 -1
  686. package/dist/utils/image-process.d.ts +18 -0
  687. package/dist/utils/image-process.d.ts.map +1 -0
  688. package/dist/utils/image-process.js +83 -0
  689. package/dist/utils/image-process.js.map +1 -0
  690. package/dist/utils/image-resize-core.d.ts +30 -0
  691. package/dist/utils/image-resize-core.d.ts.map +1 -0
  692. package/dist/utils/image-resize-core.js +124 -0
  693. package/dist/utils/image-resize-core.js.map +1 -0
  694. package/dist/utils/image-resize-worker.d.ts +2 -0
  695. package/dist/utils/image-resize-worker.d.ts.map +1 -0
  696. package/dist/utils/image-resize-worker.js +31 -0
  697. package/dist/utils/image-resize-worker.js.map +1 -0
  698. package/dist/utils/image-resize.d.ts +7 -27
  699. package/dist/utils/image-resize.d.ts.map +1 -1
  700. package/dist/utils/image-resize.js +75 -115
  701. package/dist/utils/image-resize.js.map +1 -1
  702. package/dist/utils/json.d.ts +3 -0
  703. package/dist/utils/json.d.ts.map +1 -0
  704. package/dist/utils/json.js +7 -0
  705. package/dist/utils/json.js.map +1 -0
  706. package/dist/utils/management-http.d.ts +23 -0
  707. package/dist/utils/management-http.d.ts.map +1 -0
  708. package/dist/utils/management-http.js +50 -0
  709. package/dist/utils/management-http.js.map +1 -0
  710. package/dist/utils/mime.d.ts +1 -0
  711. package/dist/utils/mime.d.ts.map +1 -1
  712. package/dist/utils/mime.js +100 -16
  713. package/dist/utils/mime.js.map +1 -1
  714. package/dist/utils/open-browser.d.ts +9 -0
  715. package/dist/utils/open-browser.d.ts.map +1 -0
  716. package/dist/utils/open-browser.js +22 -0
  717. package/dist/utils/open-browser.js.map +1 -0
  718. package/dist/utils/paths.d.ts +29 -1
  719. package/dist/utils/paths.d.ts.map +1 -1
  720. package/dist/utils/paths.js +102 -2
  721. package/dist/utils/paths.js.map +1 -1
  722. package/dist/utils/pi-user-agent.d.ts +2 -0
  723. package/dist/utils/pi-user-agent.d.ts.map +1 -0
  724. package/dist/utils/pi-user-agent.js +5 -0
  725. package/dist/utils/pi-user-agent.js.map +1 -0
  726. package/dist/utils/shell.d.ts +1 -0
  727. package/dist/utils/shell.d.ts.map +1 -1
  728. package/dist/utils/shell.js +18 -6
  729. package/dist/utils/shell.js.map +1 -1
  730. package/dist/utils/syntax-highlight.d.ts +12 -0
  731. package/dist/utils/syntax-highlight.d.ts.map +1 -0
  732. package/dist/utils/syntax-highlight.js +118 -0
  733. package/dist/utils/syntax-highlight.js.map +1 -0
  734. package/dist/utils/tool-result-images.d.ts +19 -0
  735. package/dist/utils/tool-result-images.d.ts.map +1 -0
  736. package/dist/utils/tool-result-images.js +45 -0
  737. package/dist/utils/tool-result-images.js.map +1 -0
  738. package/dist/utils/tools-manager.d.ts +10 -1
  739. package/dist/utils/tools-manager.d.ts.map +1 -1
  740. package/dist/utils/tools-manager.js +105 -36
  741. package/dist/utils/tools-manager.js.map +1 -1
  742. package/dist/utils/version-check.d.ts +19 -0
  743. package/dist/utils/version-check.d.ts.map +1 -0
  744. package/dist/utils/version-check.js +85 -0
  745. package/dist/utils/version-check.js.map +1 -0
  746. package/dist/utils/windows-self-update.d.ts +3 -0
  747. package/dist/utils/windows-self-update.d.ts.map +1 -0
  748. package/dist/utils/windows-self-update.js +77 -0
  749. package/dist/utils/windows-self-update.js.map +1 -0
  750. package/docs/compaction.md +39 -32
  751. package/docs/containerization.md +113 -0
  752. package/docs/custom-provider.md +212 -75
  753. package/docs/development.md +9 -9
  754. package/docs/docs.json +156 -0
  755. package/docs/environment-variables.md +186 -0
  756. package/docs/extensions.md +652 -140
  757. package/docs/index.md +81 -0
  758. package/docs/json.md +26 -15
  759. package/docs/keybindings.md +60 -21
  760. package/docs/llama-cpp.md +99 -0
  761. package/docs/models.md +168 -34
  762. package/docs/packages.md +46 -36
  763. package/docs/prompt-templates.md +13 -5
  764. package/docs/providers.md +147 -26
  765. package/docs/quickstart.md +167 -0
  766. package/docs/rpc.md +218 -36
  767. package/docs/sdk.md +190 -125
  768. package/docs/security.md +59 -0
  769. package/docs/{session.md → session-format.md} +48 -22
  770. package/docs/sessions.md +145 -0
  771. package/docs/settings.md +130 -25
  772. package/docs/shell-aliases.md +2 -2
  773. package/docs/skills.md +13 -14
  774. package/docs/terminal-setup.md +73 -16
  775. package/docs/termux.md +10 -10
  776. package/docs/themes.md +41 -16
  777. package/docs/tmux.md +6 -4
  778. package/docs/tui.md +85 -61
  779. package/docs/usage.md +302 -0
  780. package/docs/windows.md +2 -2
  781. package/examples/README.md +1 -1
  782. package/examples/extensions/README.md +12 -9
  783. package/examples/extensions/bash-spawn-hook.ts +2 -2
  784. package/examples/extensions/border-status-editor.ts +145 -0
  785. package/examples/extensions/built-in-tool-renderer.ts +2 -2
  786. package/examples/extensions/claude-rules.ts +1 -1
  787. package/examples/extensions/commands.ts +1 -1
  788. package/examples/extensions/custom-compaction.ts +6 -16
  789. package/examples/extensions/custom-footer.ts +1 -1
  790. package/examples/extensions/custom-header.ts +7 -7
  791. package/examples/extensions/custom-provider-anthropic/index.ts +15 -8
  792. package/examples/extensions/custom-provider-anthropic/package-lock.json +4 -4
  793. package/examples/extensions/custom-provider-anthropic/package.json +3 -3
  794. package/examples/extensions/custom-provider-gitlab-duo/index.ts +65 -9
  795. package/examples/extensions/custom-provider-gitlab-duo/package.json +2 -2
  796. package/examples/extensions/custom-provider-gitlab-duo/test.ts +2 -2
  797. package/examples/extensions/doom-overlay/README.md +1 -1
  798. package/examples/extensions/doom-overlay/doom-component.ts +4 -4
  799. package/examples/extensions/doom-overlay/doom-keys.ts +1 -1
  800. package/examples/extensions/doom-overlay/index.ts +5 -5
  801. package/examples/extensions/doom-overlay/wad-finder.ts +7 -3
  802. package/examples/extensions/dynamic-resources/dynamic.json +1 -1
  803. package/examples/extensions/entry-renderer.ts +41 -0
  804. package/examples/extensions/git-merge-and-resolve.ts +115 -0
  805. package/examples/extensions/github-issue-autocomplete.ts +2 -2
  806. package/examples/extensions/gondolin/index.ts +531 -0
  807. package/examples/extensions/gondolin/package-lock.json +185 -0
  808. package/examples/extensions/gondolin/package.json +19 -0
  809. package/examples/extensions/handoff.ts +50 -14
  810. package/examples/extensions/hidden-thinking-label.ts +1 -1
  811. package/examples/extensions/inline-bash.ts +2 -2
  812. package/examples/extensions/input-transform-streaming.ts +39 -0
  813. package/examples/extensions/input-transform.ts +2 -2
  814. package/examples/extensions/interactive-shell.ts +2 -2
  815. package/examples/extensions/kimi-deferred-tools.ts +61 -0
  816. package/examples/extensions/mac-system-theme.ts +2 -2
  817. package/examples/extensions/message-renderer.ts +3 -3
  818. package/examples/extensions/minimal-mode.ts +2 -2
  819. package/examples/extensions/modal-editor.ts +2 -2
  820. package/examples/extensions/model-status.ts +1 -1
  821. package/examples/extensions/notify.ts +3 -3
  822. package/examples/extensions/overlay-qa-tests.ts +242 -140
  823. package/examples/extensions/overlay-test.ts +9 -6
  824. package/examples/extensions/pirate.ts +1 -1
  825. package/examples/extensions/plan-mode/README.md +3 -2
  826. package/examples/extensions/plan-mode/index.ts +90 -40
  827. package/examples/extensions/preset.ts +16 -10
  828. package/examples/extensions/project-trust.ts +64 -0
  829. package/examples/extensions/prompt-customizer.ts +1 -1
  830. package/examples/extensions/provider-payload.ts +5 -5
  831. package/examples/extensions/qna.ts +4 -8
  832. package/examples/extensions/question.ts +41 -19
  833. package/examples/extensions/questionnaire.ts +50 -29
  834. package/examples/extensions/rainbow-editor.ts +1 -1
  835. package/examples/extensions/reload-runtime.ts +2 -2
  836. package/examples/extensions/rpc-demo.ts +1 -1
  837. package/examples/extensions/sandbox/index.ts +9 -9
  838. package/examples/extensions/sandbox/package-lock.json +7 -7
  839. package/examples/extensions/sandbox/package.json +3 -3
  840. package/examples/extensions/shutdown-command.ts +5 -5
  841. package/examples/extensions/snake.ts +2 -2
  842. package/examples/extensions/space-invaders.ts +2 -2
  843. package/examples/extensions/ssh.ts +2 -2
  844. package/examples/extensions/structured-output.ts +1 -1
  845. package/examples/extensions/subagent/README.md +18 -13
  846. package/examples/extensions/subagent/agents.ts +42 -11
  847. package/examples/extensions/subagent/index.ts +76 -30
  848. package/examples/extensions/summarize.ts +12 -19
  849. package/examples/extensions/tic-tac-toe.ts +2 -2
  850. package/examples/extensions/titlebar-spinner.ts +3 -3
  851. package/examples/extensions/todo.ts +2 -2
  852. package/examples/extensions/tool-override.ts +1 -1
  853. package/examples/extensions/tools.ts +7 -2
  854. package/examples/extensions/truncated-tool.ts +2 -2
  855. package/examples/extensions/with-deps/package-lock.json +4 -4
  856. package/examples/extensions/with-deps/package.json +4 -4
  857. package/examples/extensions/working-indicator.ts +4 -4
  858. package/examples/extensions/working-message-test.ts +1 -1
  859. package/examples/rpc-extension-ui.ts +11 -2
  860. package/examples/sdk/01-minimal.ts +15 -11
  861. package/examples/sdk/02-custom-model.ts +18 -18
  862. package/examples/sdk/03-custom-prompt.ts +25 -17
  863. package/examples/sdk/04-skills.ts +3 -3
  864. package/examples/sdk/05-tools.ts +8 -4
  865. package/examples/sdk/06-extensions.ts +13 -9
  866. package/examples/sdk/07-context-files.ts +2 -2
  867. package/examples/sdk/08-prompt-templates.ts +3 -3
  868. package/examples/sdk/09-api-keys-and-oauth.ts +19 -33
  869. package/examples/sdk/10-settings.ts +4 -4
  870. package/examples/sdk/11-sessions.ts +4 -0
  871. package/examples/sdk/12-full-control.ts +22 -21
  872. package/examples/sdk/README.md +23 -30
  873. package/npm-shrinkwrap.json +1818 -0
  874. package/package.json +117 -99
  875. package/dist/modes/interactive/assets/clankolas.png +0 -0
  876. package/dist/modes/interactive/components/auth-selector-status.d.ts +0 -20
  877. package/dist/modes/interactive/components/auth-selector-status.d.ts.map +0 -1
  878. package/dist/modes/interactive/components/auth-selector-status.js +0 -23
  879. package/dist/modes/interactive/components/auth-selector-status.js.map +0 -1
  880. package/dist/modes/interactive/components/earendil-announcement.d.ts +0 -5
  881. package/dist/modes/interactive/components/earendil-announcement.d.ts.map +0 -1
  882. package/dist/modes/interactive/components/earendil-announcement.js +0 -40
  883. package/dist/modes/interactive/components/earendil-announcement.js.map +0 -1
  884. package/docs/images/exy.png +0 -0
  885. package/docs/tree.md +0 -233
  886. package/examples/extensions/antigravity-image-gen.ts +0 -418
  887. package/examples/extensions/custom-provider-qwen-cli/index.ts +0 -345
  888. package/examples/extensions/custom-provider-qwen-cli/package.json +0 -16
@@ -1,14 +1,22 @@
1
+ import { uuidv7 } from "@sammorrowdrums/mcpi-ai";
1
2
  import { randomUUID } from "crypto";
2
- import { appendFileSync, closeSync, existsSync, mkdirSync, openSync, readdirSync, readFileSync, readSync, statSync, writeFileSync, } from "fs";
3
- import { readdir, readFile, stat } from "fs/promises";
3
+ import { appendFileSync, closeSync, createReadStream, existsSync, mkdirSync, openSync, readdirSync, readSync, statSync, writeFileSync, } from "fs";
4
+ import { readdir, stat } from "fs/promises";
4
5
  import { join, resolve } from "path";
5
- import { v7 as uuidv7 } from "uuid";
6
- import { getAgentDir as getDefaultAgentDir, getSessionsDir } from "../config.js";
6
+ import { createInterface } from "readline";
7
+ import { StringDecoder } from "string_decoder";
8
+ import { APP_NAME, getSessionsDir } from "../config.js";
9
+ import { normalizePath, resolvePath } from "../utils/paths.js";
7
10
  import { createBranchSummaryMessage, createCompactionSummaryMessage, createCustomMessage, } from "./messages.js";
8
11
  export const CURRENT_SESSION_VERSION = 3;
9
12
  function createSessionId() {
10
13
  return uuidv7();
11
14
  }
15
+ export function assertValidSessionId(id) {
16
+ if (!/^[A-Za-z0-9](?:[A-Za-z0-9._-]*[A-Za-z0-9])?$/.test(id)) {
17
+ throw new Error("Session id must be non-empty, contain only alphanumeric characters, '-', '_', and '.', and start and end with an alphanumeric character");
18
+ }
19
+ }
12
20
  /** Generate a unique short ID (8 hex chars, collision-checked) */
13
21
  function generateId(byId) {
14
22
  for (let i = 0; i < 100; i++) {
@@ -104,46 +112,40 @@ export function getLatestCompactionEntry(entries) {
104
112
  }
105
113
  return null;
106
114
  }
107
- /**
108
- * Build the session context from entries using tree traversal.
109
- * If leafId is provided, walks from that entry to root.
110
- * Handles compaction and branch summaries along the path.
111
- */
112
- export function buildSessionContext(entries, leafId, byId) {
113
- // Build uuid index if not available
114
- if (!byId) {
115
- byId = new Map();
116
- for (const entry of entries) {
117
- byId.set(entry.id, entry);
118
- }
115
+ function buildEntryIndex(entries, byId) {
116
+ if (byId)
117
+ return byId;
118
+ const index = new Map();
119
+ for (const entry of entries) {
120
+ index.set(entry.id, entry);
119
121
  }
120
- // Find leaf
122
+ return index;
123
+ }
124
+ function buildSessionPath(entries, leafId, byId) {
125
+ const index = buildEntryIndex(entries, byId);
121
126
  let leaf;
122
127
  if (leafId === null) {
123
- // Explicitly null - return no messages (navigated to before first entry)
124
- return { messages: [], thinkingLevel: "off", model: null };
128
+ return [];
125
129
  }
126
130
  if (leafId) {
127
- leaf = byId.get(leafId);
131
+ leaf = index.get(leafId);
128
132
  }
133
+ leaf ??= entries[entries.length - 1];
129
134
  if (!leaf) {
130
- // Fallback to last entry (when leafId is undefined)
131
- leaf = entries[entries.length - 1];
132
- }
133
- if (!leaf) {
134
- return { messages: [], thinkingLevel: "off", model: null };
135
+ return [];
135
136
  }
136
- // Walk from leaf to root, collecting path
137
137
  const path = [];
138
138
  let current = leaf;
139
139
  while (current) {
140
- path.unshift(current);
141
- current = current.parentId ? byId.get(current.parentId) : undefined;
140
+ path.push(current);
141
+ current = current.parentId ? index.get(current.parentId) : undefined;
142
142
  }
143
- // Extract settings and find compaction
143
+ path.reverse();
144
+ return path;
145
+ }
146
+ function getSessionContextSettings(path) {
144
147
  let thinkingLevel = "off";
145
148
  let model = null;
146
- let compaction = null;
147
149
  for (const entry of path) {
148
150
  if (entry.type === "thinking_level_change") {
149
151
  thinkingLevel = entry.thinkingLevel;
@@ -154,86 +156,157 @@ export function buildSessionContext(entries, leafId, byId) {
154
156
  else if (entry.type === "message" && entry.message.role === "assistant") {
155
157
  model = { provider: entry.message.provider, modelId: entry.message.model };
156
158
  }
157
- else if (entry.type === "compaction") {
158
- compaction = entry;
159
- }
160
159
  }
161
- // Build messages and collect corresponding entries
162
- // When there's a compaction, we need to:
163
- // 1. Emit summary first (entry = compaction)
164
- // 2. Emit kept messages (from firstKeptEntryId up to compaction)
165
- // 3. Emit messages after compaction
166
- const messages = [];
167
- const appendMessage = (entry) => {
168
- if (entry.type === "message") {
169
- messages.push(entry.message);
170
- }
171
- else if (entry.type === "custom_message") {
172
- messages.push(createCustomMessage(entry.customType, entry.content, entry.display, entry.details, entry.timestamp));
173
- }
174
- else if (entry.type === "branch_summary" && entry.summary) {
175
- messages.push(createBranchSummaryMessage(entry.summary, entry.fromId, entry.timestamp));
176
- }
177
- };
178
- if (compaction) {
179
- // Emit summary first
180
- messages.push(createCompactionSummaryMessage(compaction.summary, compaction.tokensBefore, compaction.timestamp));
181
- // Find compaction index in path
182
- const compactionIdx = path.findIndex((e) => e.type === "compaction" && e.id === compaction.id);
183
- // Emit kept messages (before compaction, starting from firstKeptEntryId)
184
- let foundFirstKept = false;
185
- for (let i = 0; i < compactionIdx; i++) {
186
- const entry = path[i];
187
- if (entry.id === compaction.firstKeptEntryId) {
188
- foundFirstKept = true;
189
- }
190
- if (foundFirstKept) {
191
- appendMessage(entry);
192
- }
160
+ return { thinkingLevel, model };
161
+ }
162
+ /**
163
+ * Project one selected session entry into LLM/runtime messages.
164
+ * Plain custom entries are display/state entries and do not participate in context.
165
+ */
166
+ export function sessionEntryToContextMessages(entry) {
167
+ if (entry.type === "message") {
168
+ const message = entry.message;
169
+ // Session files are parsed without validation; old versions, forks, or
170
+ // hand-edited files can contain messages with null/missing content.
171
+ if ((message.role === "user" || message.role === "assistant" || message.role === "toolResult") &&
172
+ message.content == null) {
173
+ return [{ ...message, content: [] }];
193
174
  }
194
- // Emit messages after compaction
195
- for (let i = compactionIdx + 1; i < path.length; i++) {
196
- const entry = path[i];
197
- appendMessage(entry);
175
+ return [message];
176
+ }
177
+ if (entry.type === "custom_message") {
178
+ return [
179
+ createCustomMessage(entry.customType, entry.content ?? [], entry.display, entry.details, entry.timestamp),
180
+ ];
181
+ }
182
+ if (entry.type === "branch_summary" && entry.summary) {
183
+ return [createBranchSummaryMessage(entry.summary, entry.fromId, entry.timestamp)];
184
+ }
185
+ if (entry.type === "compaction") {
186
+ return [createCompactionSummaryMessage(entry.summary, entry.tokensBefore, entry.timestamp)];
187
+ }
188
+ return [];
189
+ }
190
+ /**
191
+ * Build the active, compaction-aware session entry list.
192
+ *
193
+ * This follows the current leaf path. If the path contains compaction entries,
194
+ * the latest compaction is represented by the compaction entry itself, followed
195
+ * by the kept entries starting at firstKeptEntryId and all entries after the
196
+ * compaction entry. Older summarized entries are omitted.
197
+ */
198
+ export function buildContextEntries(entries, leafId, byId) {
199
+ const path = buildSessionPath(entries, leafId, byId);
200
+ let compaction = null;
201
+ for (const entry of path) {
202
+ if (entry.type === "compaction") {
203
+ compaction = entry;
198
204
  }
199
205
  }
200
- else {
201
- // No compaction - emit all messages, handle branch summaries and custom messages
202
- for (const entry of path) {
203
- appendMessage(entry);
206
+ if (!compaction) {
207
+ return path;
208
+ }
209
+ const compactionIdx = path.findIndex((entry) => entry.id === compaction.id);
210
+ if (compactionIdx < 0) {
211
+ return path;
212
+ }
213
+ const contextEntries = [compaction];
214
+ let foundFirstKept = false;
215
+ for (let i = 0; i < compactionIdx; i++) {
216
+ const entry = path[i];
217
+ if (entry.id === compaction.firstKeptEntryId) {
218
+ foundFirstKept = true;
219
+ }
220
+ if (foundFirstKept) {
221
+ contextEntries.push(entry);
204
222
  }
205
223
  }
224
+ contextEntries.push(...path.slice(compactionIdx + 1));
225
+ return contextEntries;
226
+ }
227
+ /**
228
+ * Build the session context from entries using tree traversal.
229
+ * If leafId is provided, walks from that entry to root.
230
+ * Handles compaction and branch summaries along the path.
231
+ */
232
+ export function buildSessionContext(entries, leafId, byId) {
233
+ const path = buildSessionPath(entries, leafId, byId);
234
+ const { thinkingLevel, model } = getSessionContextSettings(path);
235
+ const messages = buildContextEntries(entries, leafId, byId).flatMap(sessionEntryToContextMessages);
206
236
  return { messages, thinkingLevel, model };
207
237
  }
208
238
  /**
209
239
  * Compute the default session directory for a cwd.
210
- * Encodes cwd into a safe directory name under ~/.pi/agent/sessions/.
240
+ * Encodes cwd into a safe directory name under the mcpi state sessions directory.
211
241
  */
212
- export function getDefaultSessionDir(cwd, agentDir = getDefaultAgentDir()) {
213
- const safePath = `--${cwd.replace(/^[/\\]/, "").replace(/[/\\:]/g, "-")}--`;
214
- const sessionDir = join(agentDir, "sessions", safePath);
242
+ function getDefaultSessionDirPath(cwd, agentDir) {
243
+ const resolvedCwd = resolvePath(cwd);
244
+ const resolvedSessionsDir = agentDir ? join(resolvePath(agentDir), "sessions") : getSessionsDir();
245
+ const safePath = `--${resolvedCwd.replace(/^[/\\]/, "").replace(/[/\\:]/g, "-")}--`;
246
+ return join(resolvedSessionsDir, safePath);
247
+ }
248
+ export function getDefaultSessionDir(cwd, agentDir) {
249
+ const sessionDir = getDefaultSessionDirPath(cwd, agentDir);
215
250
  if (!existsSync(sessionDir)) {
216
251
  mkdirSync(sessionDir, { recursive: true });
217
252
  }
218
253
  return sessionDir;
219
254
  }
255
+ const SESSION_READ_BUFFER_SIZE = 1024 * 1024;
256
+ const SESSION_HEADER_READ_BUFFER_SIZE = 4096;
257
+ /** Bound synchronous header discovery while allowing large cwd and custom metadata fields. */
258
+ const MAX_SESSION_HEADER_SCAN_BYTES = 1024 * 1024;
259
+ class SessionHeaderScanLimitError extends Error {
260
+ constructor(filePath) {
261
+ super(`Session header exceeds ${MAX_SESSION_HEADER_SCAN_BYTES}-byte scan limit: ${filePath}`);
262
+ this.name = "SessionHeaderScanLimitError";
263
+ }
264
+ }
265
+ function parseSessionEntryLine(line) {
266
+ if (!line.trim())
267
+ return null;
268
+ try {
269
+ return JSON.parse(line);
270
+ }
271
+ catch {
272
+ // Skip malformed lines
273
+ return null;
274
+ }
275
+ }
220
276
  /** Exported for testing */
221
277
  export function loadEntriesFromFile(filePath) {
222
- if (!existsSync(filePath))
278
+ const resolvedFilePath = normalizePath(filePath);
279
+ if (!existsSync(resolvedFilePath))
223
280
  return [];
224
- const content = readFileSync(filePath, "utf8");
225
281
  const entries = [];
226
- const lines = content.trim().split("\n");
227
- for (const line of lines) {
228
- if (!line.trim())
229
- continue;
230
- try {
231
- const entry = JSON.parse(line);
232
- entries.push(entry);
233
- }
234
- catch {
235
- // Skip malformed lines
282
+ const fd = openSync(resolvedFilePath, "r");
283
+ try {
284
+ const decoder = new StringDecoder("utf8");
285
+ const buffer = Buffer.allocUnsafe(SESSION_READ_BUFFER_SIZE);
286
+ let pending = "";
287
+ while (true) {
288
+ const bytesRead = readSync(fd, buffer, 0, buffer.length, null);
289
+ if (bytesRead === 0)
290
+ break;
291
+ pending += decoder.write(buffer.subarray(0, bytesRead));
292
+ let lineStart = 0;
293
+ let newlineIndex = pending.indexOf("\n", lineStart);
294
+ while (newlineIndex !== -1) {
295
+ const entry = parseSessionEntryLine(pending.slice(lineStart, newlineIndex));
296
+ if (entry)
297
+ entries.push(entry);
298
+ lineStart = newlineIndex + 1;
299
+ newlineIndex = pending.indexOf("\n", lineStart);
300
+ }
301
+ pending = pending.slice(lineStart);
236
302
  }
303
+ pending += decoder.end();
304
+ const finalEntry = parseSessionEntryLine(pending);
305
+ if (finalEntry)
306
+ entries.push(finalEntry);
307
+ }
308
+ finally {
309
+ closeSync(fd);
237
310
  }
238
311
  // Validate session header
239
312
  if (entries.length === 0)
@@ -244,34 +317,97 @@ export function loadEntriesFromFile(filePath) {
244
317
  }
245
318
  return entries;
246
319
  }
247
- function isValidSessionFile(filePath) {
320
+ /**
321
+ * Inspect a physical line while searching for the first parsed session entry.
322
+ * Blank and malformed lines are skipped to match loadEntriesFromFile().
323
+ * Returns undefined to keep scanning, null for a parsed non-header entry, or the header.
324
+ */
325
+ function parseSessionHeaderCandidate(line) {
326
+ if (!line.trim())
327
+ return undefined;
328
+ const entry = parseSessionEntryLine(line);
329
+ if (!entry)
330
+ return undefined;
331
+ if (entry.type !== "session" || typeof entry.id !== "string")
332
+ return null;
333
+ return entry;
334
+ }
335
+ function readSessionHeader(filePath) {
336
+ const fd = openSync(filePath, "r");
248
337
  try {
249
- const fd = openSync(filePath, "r");
250
- const buffer = Buffer.alloc(512);
251
- const bytesRead = readSync(fd, buffer, 0, 512, 0);
338
+ const decoder = new StringDecoder("utf8");
339
+ const buffer = Buffer.allocUnsafe(SESSION_HEADER_READ_BUFFER_SIZE);
340
+ const lineChunks = [];
341
+ let scannedBytes = 0;
342
+ while (scannedBytes < MAX_SESSION_HEADER_SCAN_BYTES) {
343
+ const readLength = Math.min(buffer.length, MAX_SESSION_HEADER_SCAN_BYTES - scannedBytes);
344
+ const bytesRead = readSync(fd, buffer, 0, readLength, null);
345
+ if (bytesRead === 0) {
346
+ lineChunks.push(decoder.end());
347
+ return parseSessionHeaderCandidate(lineChunks.join("")) ?? null;
348
+ }
349
+ scannedBytes += bytesRead;
350
+ const chunk = decoder.write(buffer.subarray(0, bytesRead));
351
+ let lineStart = 0;
352
+ let newlineIndex = chunk.indexOf("\n", lineStart);
353
+ while (newlineIndex !== -1) {
354
+ lineChunks.push(chunk.slice(lineStart, newlineIndex));
355
+ const header = parseSessionHeaderCandidate(lineChunks.join(""));
356
+ if (header !== undefined)
357
+ return header;
358
+ lineChunks.length = 0;
359
+ lineStart = newlineIndex + 1;
360
+ newlineIndex = chunk.indexOf("\n", lineStart);
361
+ }
362
+ lineChunks.push(chunk.slice(lineStart));
363
+ }
364
+ // Probe for EOF so a final header without a newline is allowed when it ends
365
+ // exactly at the scan limit. Any additional byte exceeds the bounded scan.
366
+ const probe = Buffer.allocUnsafe(1);
367
+ if (readSync(fd, probe, 0, probe.length, null) === 0) {
368
+ lineChunks.push(decoder.end());
369
+ return parseSessionHeaderCandidate(lineChunks.join("")) ?? null;
370
+ }
371
+ throw new SessionHeaderScanLimitError(filePath);
372
+ }
373
+ finally {
252
374
  closeSync(fd);
253
- const firstLine = buffer.toString("utf8", 0, bytesRead).split("\n")[0];
254
- if (!firstLine)
255
- return false;
256
- const header = JSON.parse(firstLine);
257
- return header.type === "session" && typeof header.id === "string";
375
+ }
376
+ }
377
+ function readSessionHeaderForDiscovery(filePath) {
378
+ try {
379
+ return readSessionHeader(filePath);
258
380
  }
259
381
  catch {
260
- return false;
382
+ // Discovery is best-effort: unreadable or oversized files are not sessions,
383
+ // and one corrupt file must not prevent other sessions from being found.
384
+ return null;
261
385
  }
262
386
  }
387
+ function getSessionHeaderCwd(header) {
388
+ const cwd = header.cwd;
389
+ return typeof cwd === "string" ? cwd : undefined;
390
+ }
391
+ function sessionCwdMatches(cwd, resolvedCwd) {
392
+ return cwd !== undefined && cwd !== "" && resolvePath(cwd) === resolvedCwd;
393
+ }
263
394
  /** Exported for testing */
264
- export function findMostRecentSession(sessionDir) {
395
+ export function findMostRecentSession(sessionDir, cwd) {
396
+ const resolvedSessionDir = normalizePath(sessionDir);
397
+ const resolvedCwd = cwd ? resolvePath(cwd) : undefined;
265
398
  try {
266
- const files = readdirSync(sessionDir)
399
+ const files = readdirSync(resolvedSessionDir)
267
400
  .filter((f) => f.endsWith(".jsonl"))
268
- .map((f) => join(sessionDir, f))
269
- .filter(isValidSessionFile)
270
- .map((path) => ({ path, mtime: statSync(path).mtime }))
401
+ .map((f) => join(resolvedSessionDir, f))
402
+ .map((path) => ({ path, header: readSessionHeaderForDiscovery(path) }))
403
+ .filter((file) => file.header !== null &&
404
+ (!resolvedCwd || sessionCwdMatches(getSessionHeaderCwd(file.header), resolvedCwd)))
405
+ .map(({ path }) => ({ path, mtime: statSync(path).mtime }))
271
406
  .sort((a, b) => b.mtime.getTime() - a.mtime.getTime());
272
407
  return files[0]?.path || null;
273
408
  }
274
409
  catch {
410
+ // Directory access and stat races make recent-session discovery unavailable.
275
411
  return null;
276
412
  }
277
413
  }
@@ -288,73 +424,53 @@ function extractTextContent(message) {
288
424
  .map((block) => block.text)
289
425
  .join(" ");
290
426
  }
291
- function getLastActivityTime(entries) {
292
- let lastActivityTime;
293
- for (const entry of entries) {
294
- if (entry.type !== "message")
295
- continue;
296
- const message = entry.message;
297
- if (!isMessageWithContent(message))
298
- continue;
299
- if (message.role !== "user" && message.role !== "assistant")
300
- continue;
301
- const msgTimestamp = message.timestamp;
302
- if (typeof msgTimestamp === "number") {
303
- lastActivityTime = Math.max(lastActivityTime ?? 0, msgTimestamp);
304
- continue;
305
- }
306
- const entryTimestamp = entry.timestamp;
307
- if (typeof entryTimestamp === "string") {
308
- const t = new Date(entryTimestamp).getTime();
309
- if (!Number.isNaN(t)) {
310
- lastActivityTime = Math.max(lastActivityTime ?? 0, t);
311
- }
312
- }
313
- }
314
- return lastActivityTime;
315
- }
316
- function getSessionModifiedDate(entries, header, statsMtime) {
317
- const lastActivityTime = getLastActivityTime(entries);
318
- if (typeof lastActivityTime === "number" && lastActivityTime > 0) {
319
- return new Date(lastActivityTime);
427
+ function getMessageActivityTime(entry) {
428
+ const message = entry.message;
429
+ if (!isMessageWithContent(message))
430
+ return undefined;
431
+ if (message.role !== "user" && message.role !== "assistant")
432
+ return undefined;
433
+ const msgTimestamp = message.timestamp;
434
+ if (typeof msgTimestamp === "number") {
435
+ return msgTimestamp;
320
436
  }
321
- const headerTime = typeof header.timestamp === "string" ? new Date(header.timestamp).getTime() : NaN;
322
- return !Number.isNaN(headerTime) ? new Date(headerTime) : statsMtime;
437
+ const t = new Date(entry.timestamp).getTime();
438
+ return Number.isNaN(t) ? undefined : t;
323
439
  }
324
440
  async function buildSessionInfo(filePath) {
325
441
  try {
326
- const content = await readFile(filePath, "utf8");
327
- const entries = [];
328
- const lines = content.trim().split("\n");
329
- for (const line of lines) {
330
- if (!line.trim())
331
- continue;
332
- try {
333
- entries.push(JSON.parse(line));
334
- }
335
- catch {
336
- // Skip malformed lines
337
- }
338
- }
339
- if (entries.length === 0)
340
- return null;
341
- const header = entries[0];
342
- if (header.type !== "session")
343
- return null;
344
442
  const stats = await stat(filePath);
443
+ let header = null;
345
444
  let messageCount = 0;
346
445
  let firstMessage = "";
347
446
  const allMessages = [];
348
447
  let name;
349
- for (const entry of entries) {
448
+ let lastActivityTime;
449
+ const rl = createInterface({
450
+ input: createReadStream(filePath, { encoding: "utf8" }),
451
+ crlfDelay: Infinity,
452
+ });
453
+ for await (const line of rl) {
454
+ const entry = parseSessionEntryLine(line);
455
+ if (!entry)
456
+ continue;
457
+ if (!header) {
458
+ if (entry.type !== "session")
459
+ return null;
460
+ header = entry;
461
+ continue;
462
+ }
350
463
  // Extract session name (use latest, including explicit clears)
351
464
  if (entry.type === "session_info") {
352
- const infoEntry = entry;
353
- name = infoEntry.name?.trim() || undefined;
465
+ name = entry.name?.trim() || undefined;
354
466
  }
355
467
  if (entry.type !== "message")
356
468
  continue;
357
469
  messageCount++;
470
+ const activityTime = getMessageActivityTime(entry);
471
+ if (typeof activityTime === "number") {
472
+ lastActivityTime = Math.max(lastActivityTime ?? 0, activityTime);
473
+ }
358
474
  const message = entry.message;
359
475
  if (!isMessageWithContent(message))
360
476
  continue;
@@ -368,9 +484,16 @@ async function buildSessionInfo(filePath) {
368
484
  firstMessage = textContent;
369
485
  }
370
486
  }
487
+ if (!header)
488
+ return null;
371
489
  const cwd = typeof header.cwd === "string" ? header.cwd : "";
372
490
  const parentSessionPath = header.parentSession;
373
- const modified = getSessionModifiedDate(entries, header, stats.mtime);
491
+ const headerTime = typeof header.timestamp === "string" ? new Date(header.timestamp).getTime() : NaN;
492
+ const modified = typeof lastActivityTime === "number" && lastActivityTime > 0
493
+ ? new Date(lastActivityTime)
494
+ : !Number.isNaN(headerTime)
495
+ ? new Date(headerTime)
496
+ : stats.mtime;
374
497
  return {
375
498
  path: filePath,
376
499
  id: header.id,
@@ -388,6 +511,40 @@ async function buildSessionInfo(filePath) {
388
511
  return null;
389
512
  }
390
513
  }
514
+ const MAX_CONCURRENT_SESSION_INFO_LOADS = 10;
515
+ async function buildSessionInfosWithConcurrency(files, onLoaded) {
516
+ const results = new Array(files.length).fill(null);
517
+ const inFlight = new Set();
518
+ let nextIndex = 0;
519
+ const startNext = () => {
520
+ const index = nextIndex++;
521
+ const file = files[index];
522
+ if (!file)
523
+ return;
524
+ let task;
525
+ task = buildSessionInfo(file)
526
+ .then((info) => {
527
+ results[index] = info;
528
+ })
529
+ .catch(() => {
530
+ results[index] = null;
531
+ })
532
+ .finally(() => {
533
+ inFlight.delete(task);
534
+ onLoaded();
535
+ });
536
+ inFlight.add(task);
537
+ };
538
+ while (nextIndex < files.length || inFlight.size > 0) {
539
+ while (nextIndex < files.length && inFlight.size < MAX_CONCURRENT_SESSION_INFO_LOADS) {
540
+ startNext();
541
+ }
542
+ if (inFlight.size > 0) {
543
+ await Promise.race(inFlight);
544
+ }
545
+ }
546
+ return results;
547
+ }
391
548
  async function listSessionsFromDir(dir, onProgress, progressOffset = 0, progressTotal) {
392
549
  const sessions = [];
393
550
  if (!existsSync(dir)) {
@@ -398,12 +555,10 @@ async function listSessionsFromDir(dir, onProgress, progressOffset = 0, progress
398
555
  const files = dirEntries.filter((f) => f.endsWith(".jsonl")).map((f) => join(dir, f));
399
556
  const total = progressTotal ?? files.length;
400
557
  let loaded = 0;
401
- const results = await Promise.all(files.map(async (file) => {
402
- const info = await buildSessionInfo(file);
558
+ const results = await buildSessionInfosWithConcurrency(files, () => {
403
559
  loaded++;
404
560
  onProgress?.(progressOffset + loaded, total);
405
- return info;
406
- }));
561
+ });
407
562
  for (const info of results) {
408
563
  if (info) {
409
564
  sessions.push(info);
@@ -438,29 +593,35 @@ export class SessionManager {
438
593
  labelsById = new Map();
439
594
  labelTimestampsById = new Map();
440
595
  leafId = null;
441
- constructor(cwd, sessionDir, sessionFile, persist) {
442
- this.cwd = cwd;
443
- this.sessionDir = sessionDir;
596
+ constructor(cwd, sessionDir, sessionFile, persist, newSessionOptions, preloadedFileEntries) {
597
+ this.cwd = resolvePath(cwd);
598
+ this.sessionDir = normalizePath(sessionDir);
444
599
  this.persist = persist;
445
- if (persist && sessionDir && !existsSync(sessionDir)) {
446
- mkdirSync(sessionDir, { recursive: true });
600
+ if (persist && this.sessionDir && !existsSync(this.sessionDir)) {
601
+ mkdirSync(this.sessionDir, { recursive: true });
447
602
  }
448
603
  if (sessionFile) {
449
- this.setSessionFile(sessionFile);
604
+ this._setSessionFile(sessionFile, preloadedFileEntries);
450
605
  }
451
606
  else {
452
- this.newSession();
607
+ this.newSession(newSessionOptions);
453
608
  }
454
609
  }
455
610
  /** Switch to a different session file (used for resume and branching) */
456
611
  setSessionFile(sessionFile) {
457
- this.sessionFile = resolve(sessionFile);
612
+ this._setSessionFile(sessionFile);
613
+ }
614
+ _setSessionFile(sessionFile, preloadedFileEntries) {
615
+ this.sessionFile = resolvePath(sessionFile);
458
616
  if (existsSync(this.sessionFile)) {
459
- this.fileEntries = loadEntriesFromFile(this.sessionFile);
460
- // If file was empty or corrupted (no valid header), truncate and start fresh
461
- // to avoid appending messages without a session header (which breaks the session)
617
+ this.fileEntries = preloadedFileEntries ?? loadEntriesFromFile(this.sessionFile);
618
+ // If file was empty, initialize it with a valid session header. If it was
619
+ // non-empty but did not parse as an mcpi session, fail without modifying it.
462
620
  if (this.fileEntries.length === 0) {
463
621
  const explicitPath = this.sessionFile;
622
+ if (statSync(explicitPath).size > 0) {
623
+ throw new Error(`Session file is not a valid ${APP_NAME} session: ${explicitPath}`);
624
+ }
464
625
  this.newSession();
465
626
  this.sessionFile = explicitPath;
466
627
  this._rewriteFile();
@@ -482,6 +643,9 @@ export class SessionManager {
482
643
  }
483
644
  }
484
645
  newSession(options) {
646
+ if (options?.id !== undefined) {
647
+ assertValidSessionId(options.id);
648
+ }
485
649
  this.sessionId = options?.id ?? createSessionId();
486
650
  const timestamp = new Date().toISOString();
487
651
  const header = {
@@ -495,6 +659,7 @@ export class SessionManager {
495
659
  this.fileEntries = [header];
496
660
  this.byId.clear();
497
661
  this.labelsById.clear();
662
+ this.labelTimestampsById.clear();
498
663
  this.leafId = null;
499
664
  this.flushed = false;
500
665
  if (this.persist) {
@@ -528,8 +693,15 @@ export class SessionManager {
528
693
  _rewriteFile() {
529
694
  if (!this.persist || !this.sessionFile)
530
695
  return;
531
- const content = `${this.fileEntries.map((e) => JSON.stringify(e)).join("\n")}\n`;
532
- writeFileSync(this.sessionFile, content);
696
+ const fd = openSync(this.sessionFile, "w");
697
+ try {
698
+ for (const entry of this.fileEntries) {
699
+ writeFileSync(fd, `${JSON.stringify(entry)}\n`);
700
+ }
701
+ }
702
+ finally {
703
+ closeSync(fd);
704
+ }
533
705
  }
534
706
  isPersisted() {
535
707
  return this.persist;
@@ -540,6 +712,9 @@ export class SessionManager {
540
712
  getSessionDir() {
541
713
  return this.sessionDir;
542
714
  }
715
+ usesDefaultSessionDir() {
716
+ return this.sessionDir === getDefaultSessionDirPath(this.cwd);
717
+ }
543
718
  getSessionId() {
544
719
  return this.sessionId;
545
720
  }
@@ -551,13 +726,24 @@ export class SessionManager {
551
726
  return;
552
727
  const hasAssistant = this.fileEntries.some((e) => e.type === "message" && e.message.role === "assistant");
553
728
  if (!hasAssistant) {
554
- // Mark as not flushed so when assistant arrives, all entries get written
555
- this.flushed = false;
729
+ if (this.flushed) {
730
+ appendFileSync(this.sessionFile, `${JSON.stringify(entry)}\n`);
731
+ }
732
+ else {
733
+ // Mark as not flushed so when assistant arrives, all entries get written
734
+ this.flushed = false;
735
+ }
556
736
  return;
557
737
  }
558
738
  if (!this.flushed) {
559
- for (const e of this.fileEntries) {
560
- appendFileSync(this.sessionFile, `${JSON.stringify(e)}\n`);
739
+ const fd = openSync(this.sessionFile, "wx");
740
+ try {
741
+ for (const e of this.fileEntries) {
742
+ writeFileSync(fd, `${JSON.stringify(e)}\n`);
743
+ }
744
+ }
745
+ finally {
746
+ closeSync(fd);
561
747
  }
562
748
  this.flushed = true;
563
749
  }
@@ -614,7 +800,7 @@ export class SessionManager {
614
800
  return entry.id;
615
801
  }
616
802
  /** Append a compaction summary as child of current leaf, then advance leaf. Returns entry id. */
617
- appendCompaction(summary, firstKeptEntryId, tokensBefore, details, fromHook) {
803
+ appendCompaction(summary, firstKeptEntryId, tokensBefore, details, fromHook, usage) {
618
804
  const entry = {
619
805
  type: "compaction",
620
806
  id: generateId(this.byId),
@@ -624,6 +810,7 @@ export class SessionManager {
624
810
  firstKeptEntryId,
625
811
  tokensBefore,
626
812
  details,
813
+ usage,
627
814
  fromHook,
628
815
  };
629
816
  this._appendEntry(entry);
@@ -644,12 +831,13 @@ export class SessionManager {
644
831
  }
645
832
  /** Append a session info entry (e.g., display name). Returns entry id. */
646
833
  appendSessionInfo(name) {
834
+ const sanitizedName = name.replace(/[\r\n]+/g, " ").trim();
647
835
  const entry = {
648
836
  type: "session_info",
649
837
  id: generateId(this.byId),
650
838
  parentId: this.leafId,
651
839
  timestamp: new Date().toISOString(),
652
- name: name.trim(),
840
+ name: sanitizedName,
653
841
  };
654
842
  this._appendEntry(entry);
655
843
  return entry.id;
@@ -757,11 +945,19 @@ export class SessionManager {
757
945
  const startId = fromId ?? this.leafId;
758
946
  let current = startId ? this.byId.get(startId) : undefined;
759
947
  while (current) {
760
- path.unshift(current);
948
+ path.push(current);
761
949
  current = current.parentId ? this.byId.get(current.parentId) : undefined;
762
950
  }
951
+ path.reverse();
763
952
  return path;
764
953
  }
954
+ /**
955
+ * Build the active, compaction-aware entry list for context/rendering.
956
+ * Uses tree traversal from current leaf.
957
+ */
958
+ buildContextEntries() {
959
+ return buildContextEntries(this.getEntries(), this.leafId, this.byId);
960
+ }
765
961
  /**
766
962
  * Build the session context (what gets sent to the LLM).
767
963
  * Uses tree traversal from current leaf.
@@ -854,7 +1050,7 @@ export class SessionManager {
854
1050
  * Same as branch(), but also appends a branch_summary entry that captures
855
1051
  * context from the abandoned conversation path.
856
1052
  */
857
- branchWithSummary(branchFromId, summary, details, fromHook) {
1053
+ branchWithSummary(branchFromId, summary, details, fromHook, usage) {
858
1054
  if (branchFromId !== null && !this.byId.has(branchFromId)) {
859
1055
  throw new Error(`Entry ${branchFromId} not found`);
860
1056
  }
@@ -867,6 +1063,7 @@ export class SessionManager {
867
1063
  fromId: branchFromId ?? "root",
868
1064
  summary,
869
1065
  details,
1066
+ usage,
870
1067
  fromHook,
871
1068
  };
872
1069
  this._appendEntry(entry);
@@ -883,8 +1080,17 @@ export class SessionManager {
883
1080
  if (path.length === 0) {
884
1081
  throw new Error(`Entry ${leafId} not found`);
885
1082
  }
886
- // Filter out LabelEntry from path - we'll recreate them from the resolved map
887
- const pathWithoutLabels = path.filter((e) => e.type !== "label");
1083
+ // Filter out LabelEntry from path - we'll recreate them from the resolved map.
1084
+ // Because labels are real tree entries, later entries can be children of labels;
1085
+ // removing labels requires re-chaining the retained path to avoid orphaned subtrees.
1086
+ const pathWithoutLabels = [];
1087
+ let pathParentId = null;
1088
+ for (const entry of path) {
1089
+ if (entry.type === "label")
1090
+ continue;
1091
+ pathWithoutLabels.push({ ...entry, parentId: pathParentId });
1092
+ pathParentId = entry.id;
1093
+ }
888
1094
  const newSessionId = createSessionId();
889
1095
  const timestamp = new Date().toISOString();
890
1096
  const fileTimestamp = timestamp.replace(/[:.]/g, "-");
@@ -965,11 +1171,11 @@ export class SessionManager {
965
1171
  /**
966
1172
  * Create a new session.
967
1173
  * @param cwd Working directory (stored in session header)
968
- * @param sessionDir Optional session directory. If omitted, uses default (~/.pi/agent/sessions/<encoded-cwd>/).
1174
+ * @param sessionDir Optional session directory. If omitted, uses the mcpi state sessions directory.
969
1175
  */
970
- static create(cwd, sessionDir) {
971
- const dir = sessionDir ?? getDefaultSessionDir(cwd);
972
- return new SessionManager(cwd, dir, undefined, true);
1176
+ static create(cwd, sessionDir, options) {
1177
+ const dir = sessionDir ? normalizePath(sessionDir) : getDefaultSessionDir(cwd);
1178
+ return new SessionManager(cwd, dir, undefined, true, options);
973
1179
  }
974
1180
  /**
975
1181
  * Open a specific session file.
@@ -978,30 +1184,45 @@ export class SessionManager {
978
1184
  * @param cwdOverride Optional cwd override instead of the session header cwd.
979
1185
  */
980
1186
  static open(path, sessionDir, cwdOverride) {
981
- // Extract cwd from session header if possible, otherwise use process.cwd()
982
- const entries = loadEntriesFromFile(path);
983
- const header = entries.find((e) => e.type === "session");
984
- const cwd = cwdOverride ?? header?.cwd ?? process.cwd();
1187
+ const resolvedPath = resolvePath(path);
1188
+ let header = null;
1189
+ let preloadedFileEntries;
1190
+ if (cwdOverride === undefined && existsSync(resolvedPath)) {
1191
+ try {
1192
+ header = readSessionHeader(resolvedPath);
1193
+ }
1194
+ catch (error) {
1195
+ if (!(error instanceof SessionHeaderScanLimitError))
1196
+ throw error;
1197
+ // The bounded scan is only a discovery optimization. A full load remains
1198
+ // authoritative for legacy files with very large headers or prefixes.
1199
+ preloadedFileEntries = loadEntriesFromFile(resolvedPath);
1200
+ const firstEntry = preloadedFileEntries[0];
1201
+ header = firstEntry?.type === "session" ? firstEntry : null;
1202
+ }
1203
+ }
1204
+ const cwd = cwdOverride ?? (header ? getSessionHeaderCwd(header) : undefined) ?? process.cwd();
985
1205
  // If no sessionDir provided, derive from file's parent directory
986
- const dir = sessionDir ?? resolve(path, "..");
987
- return new SessionManager(cwd, dir, path, true);
1206
+ const dir = sessionDir ? normalizePath(sessionDir) : resolve(resolvedPath, "..");
1207
+ return new SessionManager(cwd, dir, resolvedPath, true, undefined, preloadedFileEntries);
988
1208
  }
989
1209
  /**
990
1210
  * Continue the most recent session, or create new if none.
991
1211
  * @param cwd Working directory
992
- * @param sessionDir Optional session directory. If omitted, uses default (~/.pi/agent/sessions/<encoded-cwd>/).
1212
+ * @param sessionDir Optional session directory. If omitted, uses the mcpi state sessions directory.
993
1213
  */
994
1214
  static continueRecent(cwd, sessionDir) {
995
- const dir = sessionDir ?? getDefaultSessionDir(cwd);
996
- const mostRecent = findMostRecentSession(dir);
1215
+ const dir = sessionDir ? normalizePath(sessionDir) : getDefaultSessionDir(cwd);
1216
+ const filterCwd = sessionDir !== undefined && dir !== getDefaultSessionDirPath(cwd);
1217
+ const mostRecent = findMostRecentSession(dir, filterCwd ? cwd : undefined);
997
1218
  if (mostRecent) {
998
1219
  return new SessionManager(cwd, dir, mostRecent, true);
999
1220
  }
1000
1221
  return new SessionManager(cwd, dir, undefined, true);
1001
1222
  }
1002
1223
  /** Create an in-memory session (no file persistence) */
1003
- static inMemory(cwd = process.cwd()) {
1004
- return new SessionManager(cwd, "", undefined, false);
1224
+ static inMemory(cwd = process.cwd(), options) {
1225
+ return new SessionManager(cwd, "", undefined, false, options);
1005
1226
  }
1006
1227
  /**
1007
1228
  * Fork a session from another project directory into the current project.
@@ -1010,21 +1231,26 @@ export class SessionManager {
1010
1231
  * @param targetCwd Target working directory (where the new session will be stored)
1011
1232
  * @param sessionDir Optional session directory. If omitted, uses default for targetCwd.
1012
1233
  */
1013
- static forkFrom(sourcePath, targetCwd, sessionDir) {
1014
- const sourceEntries = loadEntriesFromFile(sourcePath);
1234
+ static forkFrom(sourcePath, targetCwd, sessionDir, options) {
1235
+ const resolvedSourcePath = resolvePath(sourcePath);
1236
+ const resolvedTargetCwd = resolvePath(targetCwd);
1237
+ const sourceEntries = loadEntriesFromFile(resolvedSourcePath);
1015
1238
  if (sourceEntries.length === 0) {
1016
- throw new Error(`Cannot fork: source session file is empty or invalid: ${sourcePath}`);
1239
+ throw new Error(`Cannot fork: source session file is empty or invalid: ${resolvedSourcePath}`);
1017
1240
  }
1018
1241
  const sourceHeader = sourceEntries.find((e) => e.type === "session");
1019
1242
  if (!sourceHeader) {
1020
- throw new Error(`Cannot fork: source session has no header: ${sourcePath}`);
1243
+ throw new Error(`Cannot fork: source session has no header: ${resolvedSourcePath}`);
1021
1244
  }
1022
- const dir = sessionDir ?? getDefaultSessionDir(targetCwd);
1245
+ const dir = sessionDir ? normalizePath(sessionDir) : getDefaultSessionDir(resolvedTargetCwd);
1023
1246
  if (!existsSync(dir)) {
1024
1247
  mkdirSync(dir, { recursive: true });
1025
1248
  }
1026
1249
  // Create new session file with new ID but forked content
1027
- const newSessionId = createSessionId();
1250
+ if (options?.id !== undefined) {
1251
+ assertValidSessionId(options.id);
1252
+ }
1253
+ const newSessionId = options?.id ?? createSessionId();
1028
1254
  const timestamp = new Date().toISOString();
1029
1255
  const fileTimestamp = timestamp.replace(/[:.]/g, "-");
1030
1256
  const newSessionFile = join(dir, `${fileTimestamp}_${newSessionId}.jsonl`);
@@ -1034,42 +1260,49 @@ export class SessionManager {
1034
1260
  version: CURRENT_SESSION_VERSION,
1035
1261
  id: newSessionId,
1036
1262
  timestamp,
1037
- cwd: targetCwd,
1038
- parentSession: sourcePath,
1263
+ cwd: resolvedTargetCwd,
1264
+ parentSession: resolvedSourcePath,
1039
1265
  };
1040
- appendFileSync(newSessionFile, `${JSON.stringify(newHeader)}\n`);
1266
+ writeFileSync(newSessionFile, `${JSON.stringify(newHeader)}\n`, { flag: "wx" });
1041
1267
  // Copy all non-header entries from source
1042
1268
  for (const entry of sourceEntries) {
1043
1269
  if (entry.type !== "session") {
1044
1270
  appendFileSync(newSessionFile, `${JSON.stringify(entry)}\n`);
1045
1271
  }
1046
1272
  }
1047
- return new SessionManager(targetCwd, dir, newSessionFile, true);
1273
+ return new SessionManager(resolvedTargetCwd, dir, newSessionFile, true);
1048
1274
  }
1049
1275
  /**
1050
1276
  * List all sessions for a directory.
1051
1277
  * @param cwd Working directory (used to compute default session directory)
1052
- * @param sessionDir Optional session directory. If omitted, uses default (~/.pi/agent/sessions/<encoded-cwd>/).
1278
+ * @param sessionDir Optional session directory. If omitted, uses the mcpi state sessions directory.
1053
1279
  * @param onProgress Optional callback for progress updates (loaded, total)
1054
1280
  */
1055
1281
  static async list(cwd, sessionDir, onProgress) {
1056
- const dir = sessionDir ?? getDefaultSessionDir(cwd);
1057
- const sessions = await listSessionsFromDir(dir, onProgress);
1282
+ const dir = sessionDir ? normalizePath(sessionDir) : getDefaultSessionDir(cwd);
1283
+ const filterCwd = sessionDir !== undefined && dir !== getDefaultSessionDirPath(cwd);
1284
+ const resolvedCwd = resolvePath(cwd);
1285
+ const sessions = (await listSessionsFromDir(dir, onProgress)).filter((session) => !filterCwd || sessionCwdMatches(session.cwd, resolvedCwd));
1058
1286
  sessions.sort((a, b) => b.modified.getTime() - a.modified.getTime());
1059
1287
  return sessions;
1060
1288
  }
1061
- /**
1062
- * List all sessions across all project directories.
1063
- * @param onProgress Optional callback for progress updates (loaded, total)
1064
- */
1065
- static async listAll(onProgress) {
1289
+ static async listAll(sessionDirOrOnProgress, onProgress) {
1290
+ const customSessionDir = typeof sessionDirOrOnProgress === "string" ? normalizePath(sessionDirOrOnProgress) : undefined;
1291
+ const progress = typeof sessionDirOrOnProgress === "function" ? sessionDirOrOnProgress : onProgress;
1292
+ if (customSessionDir) {
1293
+ const sessions = await listSessionsFromDir(customSessionDir, progress);
1294
+ sessions.sort((a, b) => b.modified.getTime() - a.modified.getTime());
1295
+ return sessions;
1296
+ }
1066
1297
  const sessionsDir = getSessionsDir();
1067
1298
  try {
1068
1299
  if (!existsSync(sessionsDir)) {
1069
1300
  return [];
1070
1301
  }
1071
1302
  const entries = await readdir(sessionsDir, { withFileTypes: true });
1072
- const dirs = entries.filter((e) => e.isDirectory()).map((e) => join(sessionsDir, e.name));
1303
+ const dirs = entries
1304
+ .filter((entry) => entry.isDirectory() || entry.isSymbolicLink())
1305
+ .map((entry) => join(sessionsDir, entry.name));
1073
1306
  // Count total files first for accurate progress
1074
1307
  let totalFiles = 0;
1075
1308
  const dirFiles = [];
@@ -1087,12 +1320,10 @@ export class SessionManager {
1087
1320
  let loaded = 0;
1088
1321
  const sessions = [];
1089
1322
  const allFiles = dirFiles.flat();
1090
- const results = await Promise.all(allFiles.map(async (file) => {
1091
- const info = await buildSessionInfo(file);
1323
+ const results = await buildSessionInfosWithConcurrency(allFiles, () => {
1092
1324
  loaded++;
1093
- onProgress?.(loaded, totalFiles);
1094
- return info;
1095
- }));
1325
+ progress?.(loaded, totalFiles);
1326
+ });
1096
1327
  for (const info of results) {
1097
1328
  if (info) {
1098
1329
  sessions.push(info);