@sheason/pi-coding-agent 0.74.1-sheason.0 → 0.78.0-sheason.0.6.0-alpha.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (516) hide show
  1. package/CHANGELOG.md +256 -4
  2. package/README.md +16 -8
  3. package/dist/bun/cli.d.ts.map +1 -1
  4. package/dist/bun/cli.js.map +1 -1
  5. package/dist/cli/args.d.ts +7 -2
  6. package/dist/cli/args.d.ts.map +1 -1
  7. package/dist/cli/args.js +49 -1
  8. package/dist/cli/args.js.map +1 -1
  9. package/dist/cli/config-selector.d.ts +2 -2
  10. package/dist/cli/config-selector.d.ts.map +1 -1
  11. package/dist/cli/config-selector.js +1 -1
  12. package/dist/cli/config-selector.js.map +1 -1
  13. package/dist/cli/file-processor.d.ts.map +1 -1
  14. package/dist/cli/file-processor.js +2 -3
  15. package/dist/cli/file-processor.js.map +1 -1
  16. package/dist/cli/initial-message.d.ts +1 -1
  17. package/dist/cli/initial-message.d.ts.map +1 -1
  18. package/dist/cli/initial-message.js.map +1 -1
  19. package/dist/cli/list-models.d.ts +1 -1
  20. package/dist/cli/list-models.d.ts.map +1 -1
  21. package/dist/cli/list-models.js.map +1 -1
  22. package/dist/cli/session-picker.d.ts +1 -1
  23. package/dist/cli/session-picker.d.ts.map +1 -1
  24. package/dist/cli/session-picker.js.map +1 -1
  25. package/dist/cli.d.ts.map +1 -1
  26. package/dist/cli.js +4 -6
  27. package/dist/cli.js.map +1 -1
  28. package/dist/config.d.ts.map +1 -1
  29. package/dist/config.js +61 -32
  30. package/dist/config.js.map +1 -1
  31. package/dist/core/agent-session-proxy.d.ts +268 -0
  32. package/dist/core/agent-session-proxy.d.ts.map +1 -0
  33. package/dist/core/agent-session-proxy.js +2 -0
  34. package/dist/core/agent-session-proxy.js.map +1 -0
  35. package/dist/core/agent-session-runtime.d.ts +10 -10
  36. package/dist/core/agent-session-runtime.d.ts.map +1 -1
  37. package/dist/core/agent-session-runtime.js +14 -14
  38. package/dist/core/agent-session-runtime.js.map +1 -1
  39. package/dist/core/agent-session-services.d.ts +8 -7
  40. package/dist/core/agent-session-services.d.ts.map +1 -1
  41. package/dist/core/agent-session-services.js +4 -2
  42. package/dist/core/agent-session-services.js.map +1 -1
  43. package/dist/core/agent-session.d.ts +60 -27
  44. package/dist/core/agent-session.d.ts.map +1 -1
  45. package/dist/core/agent-session.js +303 -177
  46. package/dist/core/agent-session.js.map +1 -1
  47. package/dist/core/auth-guidance.d.ts.map +1 -1
  48. package/dist/core/auth-guidance.js.map +1 -1
  49. package/dist/core/auth-storage.d.ts +1 -1
  50. package/dist/core/auth-storage.d.ts.map +1 -1
  51. package/dist/core/auth-storage.js +3 -2
  52. package/dist/core/auth-storage.js.map +1 -1
  53. package/dist/core/bash-executor.d.ts +1 -1
  54. package/dist/core/bash-executor.d.ts.map +1 -1
  55. package/dist/core/bash-executor.js.map +1 -1
  56. package/dist/core/compaction/branch-summarization.d.ts +3 -3
  57. package/dist/core/compaction/branch-summarization.d.ts.map +1 -1
  58. package/dist/core/compaction/branch-summarization.js.map +1 -1
  59. package/dist/core/compaction/compaction.d.ts +5 -5
  60. package/dist/core/compaction/compaction.d.ts.map +1 -1
  61. package/dist/core/compaction/compaction.js +41 -37
  62. package/dist/core/compaction/compaction.js.map +1 -1
  63. package/dist/core/compaction/index.d.ts +3 -3
  64. package/dist/core/compaction/index.d.ts.map +1 -1
  65. package/dist/core/compaction/index.js.map +1 -1
  66. package/dist/core/exec.d.ts.map +1 -1
  67. package/dist/core/exec.js.map +1 -1
  68. package/dist/core/export-html/index.d.ts +1 -1
  69. package/dist/core/export-html/index.d.ts.map +1 -1
  70. package/dist/core/export-html/index.js +8 -6
  71. package/dist/core/export-html/index.js.map +1 -1
  72. package/dist/core/export-html/template.js +23 -6
  73. package/dist/core/export-html/tool-renderer.d.ts +2 -2
  74. package/dist/core/export-html/tool-renderer.d.ts.map +1 -1
  75. package/dist/core/export-html/tool-renderer.js.map +1 -1
  76. package/dist/core/extensions/index.d.ts +8 -8
  77. package/dist/core/extensions/index.d.ts.map +1 -1
  78. package/dist/core/extensions/index.js.map +1 -1
  79. package/dist/core/extensions/loader.d.ts +2 -2
  80. package/dist/core/extensions/loader.d.ts.map +1 -1
  81. package/dist/core/extensions/loader.js +17 -34
  82. package/dist/core/extensions/loader.js.map +1 -1
  83. package/dist/core/extensions/runner.d.ts +12 -7
  84. package/dist/core/extensions/runner.d.ts.map +1 -1
  85. package/dist/core/extensions/runner.js +36 -2
  86. package/dist/core/extensions/runner.js.map +1 -1
  87. package/dist/core/extensions/types.d.ts +26 -24
  88. package/dist/core/extensions/types.d.ts.map +1 -1
  89. package/dist/core/extensions/types.js.map +1 -1
  90. package/dist/core/extensions/wrapper.d.ts +2 -2
  91. package/dist/core/extensions/wrapper.d.ts.map +1 -1
  92. package/dist/core/extensions/wrapper.js.map +1 -1
  93. package/dist/core/footer-data-provider.d.ts +3 -1
  94. package/dist/core/footer-data-provider.d.ts.map +1 -1
  95. package/dist/core/footer-data-provider.js +4 -0
  96. package/dist/core/footer-data-provider.js.map +1 -1
  97. package/dist/core/http-dispatcher.d.ts +21 -0
  98. package/dist/core/http-dispatcher.d.ts.map +1 -0
  99. package/dist/core/http-dispatcher.js +48 -0
  100. package/dist/core/http-dispatcher.js.map +1 -0
  101. package/dist/core/index.d.ts +8 -8
  102. package/dist/core/index.d.ts.map +1 -1
  103. package/dist/core/index.js.map +1 -1
  104. package/dist/core/keybindings.d.ts.map +1 -1
  105. package/dist/core/keybindings.js.map +1 -1
  106. package/dist/core/local-agent-session-proxy.d.ts +82 -0
  107. package/dist/core/local-agent-session-proxy.d.ts.map +1 -0
  108. package/dist/core/local-agent-session-proxy.js +531 -0
  109. package/dist/core/local-agent-session-proxy.js.map +1 -0
  110. package/dist/core/messages.d.ts +0 -9
  111. package/dist/core/messages.d.ts.map +1 -1
  112. package/dist/core/messages.js +0 -10
  113. package/dist/core/messages.js.map +1 -1
  114. package/dist/core/model-registry.d.ts +4 -4
  115. package/dist/core/model-registry.d.ts.map +1 -1
  116. package/dist/core/model-registry.js +72 -16
  117. package/dist/core/model-registry.js.map +1 -1
  118. package/dist/core/model-resolver.d.ts +1 -1
  119. package/dist/core/model-resolver.d.ts.map +1 -1
  120. package/dist/core/model-resolver.js +1 -1
  121. package/dist/core/model-resolver.js.map +1 -1
  122. package/dist/core/output-guard.d.ts +1 -0
  123. package/dist/core/output-guard.d.ts.map +1 -1
  124. package/dist/core/output-guard.js +52 -22
  125. package/dist/core/output-guard.js.map +1 -1
  126. package/dist/core/package-manager.d.ts +7 -1
  127. package/dist/core/package-manager.d.ts.map +1 -1
  128. package/dist/core/package-manager.js +129 -64
  129. package/dist/core/package-manager.js.map +1 -1
  130. package/dist/core/prompt-templates.d.ts +1 -1
  131. package/dist/core/prompt-templates.d.ts.map +1 -1
  132. package/dist/core/prompt-templates.js +12 -24
  133. package/dist/core/prompt-templates.js.map +1 -1
  134. package/dist/core/provider-display-names.d.ts.map +1 -1
  135. package/dist/core/provider-display-names.js +0 -1
  136. package/dist/core/provider-display-names.js.map +1 -1
  137. package/dist/core/resolve-config-value.d.ts +9 -1
  138. package/dist/core/resolve-config-value.d.ts.map +1 -1
  139. package/dist/core/resolve-config-value.js +134 -11
  140. package/dist/core/resolve-config-value.js.map +1 -1
  141. package/dist/core/resource-loader.d.ts +13 -10
  142. package/dist/core/resource-loader.d.ts.map +1 -1
  143. package/dist/core/resource-loader.js +41 -33
  144. package/dist/core/resource-loader.js.map +1 -1
  145. package/dist/core/sdk.d.ts +15 -13
  146. package/dist/core/sdk.d.ts.map +1 -1
  147. package/dist/core/sdk.js +24 -17
  148. package/dist/core/sdk.js.map +1 -1
  149. package/dist/core/session-manager.d.ts +20 -10
  150. package/dist/core/session-manager.d.ts.map +1 -1
  151. package/dist/core/session-manager.js +201 -106
  152. package/dist/core/session-manager.js.map +1 -1
  153. package/dist/core/settings-manager.d.ts +5 -0
  154. package/dist/core/settings-manager.d.ts.map +1 -1
  155. package/dist/core/settings-manager.js +31 -13
  156. package/dist/core/settings-manager.js.map +1 -1
  157. package/dist/core/skills.d.ts +2 -2
  158. package/dist/core/skills.d.ts.map +1 -1
  159. package/dist/core/skills.js +10 -27
  160. package/dist/core/skills.js.map +1 -1
  161. package/dist/core/slash-commands.d.ts +1 -1
  162. package/dist/core/slash-commands.d.ts.map +1 -1
  163. package/dist/core/slash-commands.js.map +1 -1
  164. package/dist/core/source-info.d.ts +1 -1
  165. package/dist/core/source-info.d.ts.map +1 -1
  166. package/dist/core/source-info.js.map +1 -1
  167. package/dist/core/system-prompt.d.ts +1 -1
  168. package/dist/core/system-prompt.d.ts.map +1 -1
  169. package/dist/core/system-prompt.js +16 -9
  170. package/dist/core/system-prompt.js.map +1 -1
  171. package/dist/core/telemetry.d.ts +1 -1
  172. package/dist/core/telemetry.d.ts.map +1 -1
  173. package/dist/core/telemetry.js.map +1 -1
  174. package/dist/core/tools/bash.d.ts +2 -2
  175. package/dist/core/tools/bash.d.ts.map +1 -1
  176. package/dist/core/tools/bash.js +55 -54
  177. package/dist/core/tools/bash.js.map +1 -1
  178. package/dist/core/tools/edit-diff.d.ts +3 -1
  179. package/dist/core/tools/edit-diff.d.ts.map +1 -1
  180. package/dist/core/tools/edit-diff.js +8 -1
  181. package/dist/core/tools/edit-diff.js.map +1 -1
  182. package/dist/core/tools/edit.d.ts +5 -3
  183. package/dist/core/tools/edit.d.ts.map +1 -1
  184. package/dist/core/tools/edit.js +51 -91
  185. package/dist/core/tools/edit.js.map +1 -1
  186. package/dist/core/tools/file-mutation-queue.d.ts.map +1 -1
  187. package/dist/core/tools/file-mutation-queue.js +27 -12
  188. package/dist/core/tools/file-mutation-queue.js.map +1 -1
  189. package/dist/core/tools/find.d.ts +2 -2
  190. package/dist/core/tools/find.d.ts.map +1 -1
  191. package/dist/core/tools/find.js +2 -3
  192. package/dist/core/tools/find.js.map +1 -1
  193. package/dist/core/tools/grep.d.ts +2 -2
  194. package/dist/core/tools/grep.d.ts.map +1 -1
  195. package/dist/core/tools/grep.js +3 -3
  196. package/dist/core/tools/grep.js.map +1 -1
  197. package/dist/core/tools/index.d.ts +17 -17
  198. package/dist/core/tools/index.d.ts.map +1 -1
  199. package/dist/core/tools/index.js.map +1 -1
  200. package/dist/core/tools/ls.d.ts +2 -2
  201. package/dist/core/tools/ls.d.ts.map +1 -1
  202. package/dist/core/tools/ls.js +10 -12
  203. package/dist/core/tools/ls.js.map +1 -1
  204. package/dist/core/tools/output-accumulator.d.ts +3 -1
  205. package/dist/core/tools/output-accumulator.d.ts.map +1 -1
  206. package/dist/core/tools/output-accumulator.js +9 -3
  207. package/dist/core/tools/output-accumulator.js.map +1 -1
  208. package/dist/core/tools/path-utils.d.ts +2 -0
  209. package/dist/core/tools/path-utils.d.ts.map +1 -1
  210. package/dist/core/tools/path-utils.js +39 -21
  211. package/dist/core/tools/path-utils.js.map +1 -1
  212. package/dist/core/tools/read.d.ts +2 -2
  213. package/dist/core/tools/read.d.ts.map +1 -1
  214. package/dist/core/tools/read.js +15 -15
  215. package/dist/core/tools/read.js.map +1 -1
  216. package/dist/core/tools/render-utils.d.ts +5 -2
  217. package/dist/core/tools/render-utils.d.ts.map +1 -1
  218. package/dist/core/tools/render-utils.js +17 -1
  219. package/dist/core/tools/render-utils.js.map +1 -1
  220. package/dist/core/tools/tool-definition-wrapper.d.ts +1 -1
  221. package/dist/core/tools/tool-definition-wrapper.d.ts.map +1 -1
  222. package/dist/core/tools/tool-definition-wrapper.js.map +1 -1
  223. package/dist/core/tools/truncate.d.ts.map +1 -1
  224. package/dist/core/tools/truncate.js +12 -2
  225. package/dist/core/tools/truncate.js.map +1 -1
  226. package/dist/core/tools/write.d.ts +1 -1
  227. package/dist/core/tools/write.d.ts.map +1 -1
  228. package/dist/core/tools/write.js +25 -41
  229. package/dist/core/tools/write.js.map +1 -1
  230. package/dist/d-pi-worker.d.ts +12 -0
  231. package/dist/d-pi-worker.d.ts.map +1 -0
  232. package/dist/d-pi-worker.js +9 -0
  233. package/dist/d-pi-worker.js.map +1 -0
  234. package/dist/index.d.ts +30 -28
  235. package/dist/index.d.ts.map +1 -1
  236. package/dist/index.js +5 -3
  237. package/dist/index.js.map +1 -1
  238. package/dist/main.d.ts +1 -1
  239. package/dist/main.d.ts.map +1 -1
  240. package/dist/main.js +100 -39
  241. package/dist/main.js.map +1 -1
  242. package/dist/migrations.d.ts.map +1 -1
  243. package/dist/migrations.js +118 -1
  244. package/dist/migrations.js.map +1 -1
  245. package/dist/modes/connect/auth-headers.d.ts +2 -0
  246. package/dist/modes/connect/auth-headers.d.ts.map +1 -0
  247. package/dist/modes/connect/auth-headers.js +2 -0
  248. package/dist/modes/connect/auth-headers.js.map +1 -0
  249. package/dist/modes/connect/client-extension-sync.d.ts +13 -0
  250. package/dist/modes/connect/client-extension-sync.d.ts.map +1 -0
  251. package/dist/modes/connect/client-extension-sync.js +51 -0
  252. package/dist/modes/connect/client-extension-sync.js.map +1 -0
  253. package/dist/modes/connect/connect-mode.d.ts +6 -0
  254. package/dist/modes/connect/connect-mode.d.ts.map +1 -0
  255. package/dist/modes/connect/connect-mode.js +29 -0
  256. package/dist/modes/connect/connect-mode.js.map +1 -0
  257. package/dist/modes/connect/remote-agent-session-proxy.d.ts +81 -0
  258. package/dist/modes/connect/remote-agent-session-proxy.d.ts.map +1 -0
  259. package/dist/modes/connect/remote-agent-session-proxy.js +326 -0
  260. package/dist/modes/connect/remote-agent-session-proxy.js.map +1 -0
  261. package/dist/modes/connect/sse-client.d.ts +18 -0
  262. package/dist/modes/connect/sse-client.d.ts.map +1 -0
  263. package/dist/modes/connect/sse-client.js +90 -0
  264. package/dist/modes/connect/sse-client.js.map +1 -0
  265. package/dist/modes/index.d.ts +5 -5
  266. package/dist/modes/index.d.ts.map +1 -1
  267. package/dist/modes/index.js.map +1 -1
  268. package/dist/modes/interactive/components/armin.d.ts.map +1 -1
  269. package/dist/modes/interactive/components/armin.js.map +1 -1
  270. package/dist/modes/interactive/components/assistant-message.d.ts.map +1 -1
  271. package/dist/modes/interactive/components/assistant-message.js.map +1 -1
  272. package/dist/modes/interactive/components/bash-execution.d.ts +1 -1
  273. package/dist/modes/interactive/components/bash-execution.d.ts.map +1 -1
  274. package/dist/modes/interactive/components/bash-execution.js.map +1 -1
  275. package/dist/modes/interactive/components/bordered-loader.d.ts +1 -1
  276. package/dist/modes/interactive/components/bordered-loader.d.ts.map +1 -1
  277. package/dist/modes/interactive/components/bordered-loader.js.map +1 -1
  278. package/dist/modes/interactive/components/branch-summary-message.d.ts +1 -1
  279. package/dist/modes/interactive/components/branch-summary-message.d.ts.map +1 -1
  280. package/dist/modes/interactive/components/branch-summary-message.js.map +1 -1
  281. package/dist/modes/interactive/components/compaction-summary-message.d.ts +1 -1
  282. package/dist/modes/interactive/components/compaction-summary-message.d.ts.map +1 -1
  283. package/dist/modes/interactive/components/compaction-summary-message.js.map +1 -1
  284. package/dist/modes/interactive/components/config-selector.d.ts +4 -4
  285. package/dist/modes/interactive/components/config-selector.d.ts.map +1 -1
  286. package/dist/modes/interactive/components/config-selector.js +8 -5
  287. package/dist/modes/interactive/components/config-selector.js.map +1 -1
  288. package/dist/modes/interactive/components/countdown-timer.d.ts +2 -2
  289. package/dist/modes/interactive/components/countdown-timer.d.ts.map +1 -1
  290. package/dist/modes/interactive/components/countdown-timer.js +2 -2
  291. package/dist/modes/interactive/components/countdown-timer.js.map +1 -1
  292. package/dist/modes/interactive/components/custom-editor.d.ts +1 -1
  293. package/dist/modes/interactive/components/custom-editor.d.ts.map +1 -1
  294. package/dist/modes/interactive/components/custom-editor.js.map +1 -1
  295. package/dist/modes/interactive/components/custom-message.d.ts +2 -2
  296. package/dist/modes/interactive/components/custom-message.d.ts.map +1 -1
  297. package/dist/modes/interactive/components/custom-message.js +0 -1
  298. package/dist/modes/interactive/components/custom-message.js.map +1 -1
  299. package/dist/modes/interactive/components/daxnuts.d.ts.map +1 -1
  300. package/dist/modes/interactive/components/daxnuts.js.map +1 -1
  301. package/dist/modes/interactive/components/diff.d.ts.map +1 -1
  302. package/dist/modes/interactive/components/diff.js.map +1 -1
  303. package/dist/modes/interactive/components/dynamic-border.d.ts.map +1 -1
  304. package/dist/modes/interactive/components/dynamic-border.js.map +1 -1
  305. package/dist/modes/interactive/components/earendil-announcement.d.ts.map +1 -1
  306. package/dist/modes/interactive/components/earendil-announcement.js.map +1 -1
  307. package/dist/modes/interactive/components/extension-editor.d.ts +1 -1
  308. package/dist/modes/interactive/components/extension-editor.d.ts.map +1 -1
  309. package/dist/modes/interactive/components/extension-editor.js +14 -6
  310. package/dist/modes/interactive/components/extension-editor.js.map +1 -1
  311. package/dist/modes/interactive/components/extension-input.d.ts.map +1 -1
  312. package/dist/modes/interactive/components/extension-input.js.map +1 -1
  313. package/dist/modes/interactive/components/extension-selector.d.ts.map +1 -1
  314. package/dist/modes/interactive/components/extension-selector.js.map +1 -1
  315. package/dist/modes/interactive/components/footer.d.ts +15 -4
  316. package/dist/modes/interactive/components/footer.d.ts.map +1 -1
  317. package/dist/modes/interactive/components/footer.js +126 -8
  318. package/dist/modes/interactive/components/footer.js.map +1 -1
  319. package/dist/modes/interactive/components/index.d.ts +31 -31
  320. package/dist/modes/interactive/components/index.d.ts.map +1 -1
  321. package/dist/modes/interactive/components/index.js.map +1 -1
  322. package/dist/modes/interactive/components/keybinding-hints.d.ts.map +1 -1
  323. package/dist/modes/interactive/components/keybinding-hints.js.map +1 -1
  324. package/dist/modes/interactive/components/login-dialog.d.ts +7 -1
  325. package/dist/modes/interactive/components/login-dialog.d.ts.map +1 -1
  326. package/dist/modes/interactive/components/login-dialog.js +28 -5
  327. package/dist/modes/interactive/components/login-dialog.js.map +1 -1
  328. package/dist/modes/interactive/components/model-selector.d.ts +2 -2
  329. package/dist/modes/interactive/components/model-selector.d.ts.map +1 -1
  330. package/dist/modes/interactive/components/model-selector.js.map +1 -1
  331. package/dist/modes/interactive/components/oauth-selector.d.ts +1 -1
  332. package/dist/modes/interactive/components/oauth-selector.d.ts.map +1 -1
  333. package/dist/modes/interactive/components/oauth-selector.js.map +1 -1
  334. package/dist/modes/interactive/components/scoped-models-selector.d.ts.map +1 -1
  335. package/dist/modes/interactive/components/scoped-models-selector.js.map +1 -1
  336. package/dist/modes/interactive/components/session-selector-search.d.ts +1 -1
  337. package/dist/modes/interactive/components/session-selector-search.d.ts.map +1 -1
  338. package/dist/modes/interactive/components/session-selector-search.js.map +1 -1
  339. package/dist/modes/interactive/components/session-selector.d.ts +3 -3
  340. package/dist/modes/interactive/components/session-selector.d.ts.map +1 -1
  341. package/dist/modes/interactive/components/session-selector.js.map +1 -1
  342. package/dist/modes/interactive/components/settings-selector.d.ts +3 -1
  343. package/dist/modes/interactive/components/settings-selector.d.ts.map +1 -1
  344. package/dist/modes/interactive/components/settings-selector.js +15 -0
  345. package/dist/modes/interactive/components/settings-selector.js.map +1 -1
  346. package/dist/modes/interactive/components/show-images-selector.d.ts.map +1 -1
  347. package/dist/modes/interactive/components/show-images-selector.js.map +1 -1
  348. package/dist/modes/interactive/components/skill-invocation-message.d.ts +1 -1
  349. package/dist/modes/interactive/components/skill-invocation-message.d.ts.map +1 -1
  350. package/dist/modes/interactive/components/skill-invocation-message.js.map +1 -1
  351. package/dist/modes/interactive/components/theme-selector.d.ts.map +1 -1
  352. package/dist/modes/interactive/components/theme-selector.js.map +1 -1
  353. package/dist/modes/interactive/components/thinking-selector.d.ts.map +1 -1
  354. package/dist/modes/interactive/components/thinking-selector.js.map +1 -1
  355. package/dist/modes/interactive/components/tool-execution.d.ts +1 -1
  356. package/dist/modes/interactive/components/tool-execution.d.ts.map +1 -1
  357. package/dist/modes/interactive/components/tool-execution.js.map +1 -1
  358. package/dist/modes/interactive/components/tree-selector.d.ts +1 -1
  359. package/dist/modes/interactive/components/tree-selector.d.ts.map +1 -1
  360. package/dist/modes/interactive/components/tree-selector.js.map +1 -1
  361. package/dist/modes/interactive/components/user-message-selector.d.ts.map +1 -1
  362. package/dist/modes/interactive/components/user-message-selector.js.map +1 -1
  363. package/dist/modes/interactive/components/user-message.d.ts.map +1 -1
  364. package/dist/modes/interactive/components/user-message.js.map +1 -1
  365. package/dist/modes/interactive/interactive-mode.d.ts +53 -7
  366. package/dist/modes/interactive/interactive-mode.d.ts.map +1 -1
  367. package/dist/modes/interactive/interactive-mode.js +1247 -205
  368. package/dist/modes/interactive/interactive-mode.js.map +1 -1
  369. package/dist/modes/interactive/theme/dark.json +5 -4
  370. package/dist/modes/interactive/theme/light.json +5 -4
  371. package/dist/modes/interactive/theme/theme.d.ts +22 -3
  372. package/dist/modes/interactive/theme/theme.d.ts.map +1 -1
  373. package/dist/modes/interactive/theme/theme.js +130 -69
  374. package/dist/modes/interactive/theme/theme.js.map +1 -1
  375. package/dist/modes/print-mode.d.ts +1 -1
  376. package/dist/modes/print-mode.d.ts.map +1 -1
  377. package/dist/modes/print-mode.js.map +1 -1
  378. package/dist/modes/rpc/rpc-client.d.ts +8 -5
  379. package/dist/modes/rpc/rpc-client.d.ts.map +1 -1
  380. package/dist/modes/rpc/rpc-client.js +65 -8
  381. package/dist/modes/rpc/rpc-client.js.map +1 -1
  382. package/dist/modes/rpc/rpc-mode.d.ts +2 -2
  383. package/dist/modes/rpc/rpc-mode.d.ts.map +1 -1
  384. package/dist/modes/rpc/rpc-mode.js +18 -4
  385. package/dist/modes/rpc/rpc-mode.js.map +1 -1
  386. package/dist/modes/rpc/rpc-types.d.ts +5 -4
  387. package/dist/modes/rpc/rpc-types.d.ts.map +1 -1
  388. package/dist/modes/rpc/rpc-types.js.map +1 -1
  389. package/dist/modes/serve/api-handlers.d.ts +4 -0
  390. package/dist/modes/serve/api-handlers.d.ts.map +1 -0
  391. package/dist/modes/serve/api-handlers.js +324 -0
  392. package/dist/modes/serve/api-handlers.js.map +1 -0
  393. package/dist/modes/serve/http-server.d.ts +14 -0
  394. package/dist/modes/serve/http-server.d.ts.map +1 -0
  395. package/dist/modes/serve/http-server.js +94 -0
  396. package/dist/modes/serve/http-server.js.map +1 -0
  397. package/dist/modes/serve/serve-mode.d.ts +10 -0
  398. package/dist/modes/serve/serve-mode.d.ts.map +1 -0
  399. package/dist/modes/serve/serve-mode.js +217 -0
  400. package/dist/modes/serve/serve-mode.js.map +1 -0
  401. package/dist/package-manager-cli.d.ts.map +1 -1
  402. package/dist/package-manager-cli.js +62 -7
  403. package/dist/package-manager-cli.js.map +1 -1
  404. package/dist/utils/ansi.d.ts.map +1 -1
  405. package/dist/utils/ansi.js +47 -72
  406. package/dist/utils/ansi.js.map +1 -1
  407. package/dist/utils/changelog.d.ts +1 -1
  408. package/dist/utils/changelog.d.ts.map +1 -1
  409. package/dist/utils/changelog.js.map +1 -1
  410. package/dist/utils/child-process.d.ts +5 -2
  411. package/dist/utils/child-process.d.ts.map +1 -1
  412. package/dist/utils/child-process.js +9 -7
  413. package/dist/utils/child-process.js.map +1 -1
  414. package/dist/utils/clipboard-image.d.ts.map +1 -1
  415. package/dist/utils/clipboard-image.js.map +1 -1
  416. package/dist/utils/clipboard-native.d.ts +3 -1
  417. package/dist/utils/clipboard-native.d.ts.map +1 -1
  418. package/dist/utils/clipboard-native.js +14 -8
  419. package/dist/utils/clipboard-native.js.map +1 -1
  420. package/dist/utils/clipboard.d.ts.map +1 -1
  421. package/dist/utils/clipboard.js.map +1 -1
  422. package/dist/utils/deprecation.d.ts +4 -0
  423. package/dist/utils/deprecation.d.ts.map +1 -0
  424. package/dist/utils/deprecation.js +13 -0
  425. package/dist/utils/deprecation.js.map +1 -0
  426. package/dist/utils/exif-orientation.d.ts +1 -1
  427. package/dist/utils/exif-orientation.d.ts.map +1 -1
  428. package/dist/utils/exif-orientation.js.map +1 -1
  429. package/dist/utils/html.d.ts +7 -0
  430. package/dist/utils/html.d.ts.map +1 -0
  431. package/dist/utils/html.js +40 -0
  432. package/dist/utils/html.js.map +1 -0
  433. package/dist/utils/image-convert.d.ts.map +1 -1
  434. package/dist/utils/image-convert.js.map +1 -1
  435. package/dist/utils/image-resize-core.d.ts +30 -0
  436. package/dist/utils/image-resize-core.d.ts.map +1 -0
  437. package/dist/utils/image-resize-core.js +124 -0
  438. package/dist/utils/image-resize-core.js.map +1 -0
  439. package/dist/utils/image-resize-worker.d.ts +2 -0
  440. package/dist/utils/image-resize-worker.d.ts.map +1 -0
  441. package/dist/utils/image-resize-worker.js +31 -0
  442. package/dist/utils/image-resize-worker.js.map +1 -0
  443. package/dist/utils/image-resize.d.ts +7 -27
  444. package/dist/utils/image-resize.d.ts.map +1 -1
  445. package/dist/utils/image-resize.js +75 -131
  446. package/dist/utils/image-resize.js.map +1 -1
  447. package/dist/utils/json.d.ts +3 -0
  448. package/dist/utils/json.d.ts.map +1 -0
  449. package/dist/utils/json.js +7 -0
  450. package/dist/utils/json.js.map +1 -0
  451. package/dist/utils/paths.d.ts +16 -1
  452. package/dist/utils/paths.d.ts.map +1 -1
  453. package/dist/utils/paths.js +49 -7
  454. package/dist/utils/paths.js.map +1 -1
  455. package/dist/utils/shell.d.ts.map +1 -1
  456. package/dist/utils/shell.js +6 -1
  457. package/dist/utils/shell.js.map +1 -1
  458. package/dist/utils/syntax-highlight.d.ts +12 -0
  459. package/dist/utils/syntax-highlight.d.ts.map +1 -0
  460. package/dist/utils/syntax-highlight.js +118 -0
  461. package/dist/utils/syntax-highlight.js.map +1 -0
  462. package/dist/utils/tools-manager.d.ts.map +1 -1
  463. package/dist/utils/tools-manager.js +4 -1
  464. package/dist/utils/tools-manager.js.map +1 -1
  465. package/dist/utils/version-check.d.ts +2 -1
  466. package/dist/utils/version-check.d.ts.map +1 -1
  467. package/dist/utils/version-check.js +9 -4
  468. package/dist/utils/version-check.js.map +1 -1
  469. package/dist/utils/windows-self-update.d.ts +3 -0
  470. package/dist/utils/windows-self-update.d.ts.map +1 -0
  471. package/dist/utils/windows-self-update.js +77 -0
  472. package/dist/utils/windows-self-update.js.map +1 -0
  473. package/docs/custom-provider.md +111 -21
  474. package/docs/development.md +1 -1
  475. package/docs/extensions.md +13 -7
  476. package/docs/index.md +13 -3
  477. package/docs/models.md +32 -13
  478. package/docs/packages.md +9 -6
  479. package/docs/providers.md +13 -5
  480. package/docs/quickstart.md +24 -1
  481. package/docs/rpc.md +2 -1
  482. package/docs/sdk.md +8 -0
  483. package/docs/session-format.md +1 -1
  484. package/docs/sessions.md +8 -0
  485. package/docs/settings.md +8 -6
  486. package/docs/skills.md +3 -4
  487. package/docs/terminal-setup.md +8 -0
  488. package/docs/termux.md +3 -3
  489. package/docs/tui.md +2 -2
  490. package/docs/usage.md +13 -2
  491. package/examples/extensions/README.md +1 -0
  492. package/examples/extensions/custom-provider-anthropic/index.ts +1 -1
  493. package/examples/extensions/custom-provider-anthropic/package-lock.json +2 -2
  494. package/examples/extensions/custom-provider-anthropic/package.json +2 -2
  495. package/examples/extensions/custom-provider-gitlab-duo/index.ts +54 -3
  496. package/examples/extensions/custom-provider-gitlab-duo/package.json +1 -1
  497. package/examples/extensions/custom-provider-gitlab-duo/test.ts +1 -1
  498. package/examples/extensions/doom-overlay/doom-component.ts +2 -2
  499. package/examples/extensions/doom-overlay/index.ts +3 -3
  500. package/examples/extensions/git-merge-and-resolve.ts +115 -0
  501. package/examples/extensions/input-transform-streaming.ts +39 -0
  502. package/examples/extensions/overlay-qa-tests.ts +97 -66
  503. package/examples/extensions/overlay-test.ts +7 -4
  504. package/examples/extensions/plan-mode/index.ts +1 -1
  505. package/examples/extensions/sandbox/package-lock.json +2 -2
  506. package/examples/extensions/sandbox/package.json +2 -2
  507. package/examples/extensions/subagent/README.md +3 -0
  508. package/examples/extensions/subagent/index.ts +42 -20
  509. package/examples/extensions/with-deps/package-lock.json +2 -2
  510. package/examples/extensions/with-deps/package.json +3 -3
  511. package/npm-shrinkwrap.json +1790 -0
  512. package/package.json +39 -32
  513. package/dist/utils/uuid.d.ts +0 -2
  514. package/dist/utils/uuid.d.ts.map +0 -1
  515. package/dist/utils/uuid.js +0 -40
  516. package/dist/utils/uuid.js.map +0 -1
@@ -1,14 +1,20 @@
1
+ import { uuidv7 } from "@sheason/pi-agent-core";
1
2
  import { randomUUID } from "crypto";
2
- import { appendFileSync, closeSync, existsSync, mkdirSync, openSync, readdirSync, readFileSync, readSync, statSync, writeFileSync, } from "fs";
3
+ import { appendFileSync, closeSync, existsSync, mkdirSync, openSync, readdirSync, readFileSync, readSync, renameSync, statSync, writeFileSync, } from "fs";
3
4
  import { readdir, readFile, stat } from "fs/promises";
4
5
  import { join, resolve } from "path";
5
6
  import { getAgentDir as getDefaultAgentDir, getSessionsDir } from "../config.js";
6
- import { uuidv7 } from "../utils/uuid.js";
7
+ import { canonicalizePath, normalizePath, resolvePath } from "../utils/paths.js";
7
8
  import { createBranchSummaryMessage, createCompactionSummaryMessage, createCustomMessage, } from "./messages.js";
8
9
  export const CURRENT_SESSION_VERSION = 3;
9
10
  function createSessionId() {
10
11
  return uuidv7();
11
12
  }
13
+ export function assertValidSessionId(id) {
14
+ if (!/^[A-Za-z0-9](?:[A-Za-z0-9._-]*[A-Za-z0-9])?$/.test(id)) {
15
+ throw new Error("Session id must be non-empty, contain only alphanumeric characters, '-', '_', and '.', and start and end with an alphanumeric character");
16
+ }
17
+ }
12
18
  /** Generate a unique short ID (8 hex chars, collision-checked) */
13
19
  function generateId(byId) {
14
20
  for (let i = 0; i < 100; i++) {
@@ -137,10 +143,9 @@ export function buildSessionContext(entries, leafId, byId) {
137
143
  const path = [];
138
144
  let current = leaf;
139
145
  while (current) {
140
- path.push(current);
146
+ path.unshift(current);
141
147
  current = current.parentId ? byId.get(current.parentId) : undefined;
142
148
  }
143
- path.reverse();
144
149
  // Extract settings and find compaction
145
150
  let thinkingLevel = "off";
146
151
  let model = null;
@@ -210,9 +215,14 @@ export function buildSessionContext(entries, leafId, byId) {
210
215
  * Compute the default session directory for a cwd.
211
216
  * Encodes cwd into a safe directory name under ~/.pi/agent/sessions/.
212
217
  */
218
+ function getDefaultSessionDirPath(cwd, agentDir = getDefaultAgentDir()) {
219
+ const resolvedCwd = resolvePath(cwd);
220
+ const resolvedAgentDir = resolvePath(agentDir);
221
+ const safePath = `--${resolvedCwd.replace(/^[/\\]/, "").replace(/[/\\:]/g, "-")}--`;
222
+ return join(resolvedAgentDir, "sessions", safePath);
223
+ }
213
224
  export function getDefaultSessionDir(cwd, agentDir = getDefaultAgentDir()) {
214
- const safePath = `--${cwd.replace(/^[/\\]/, "").replace(/[/\\:]/g, "-")}--`;
215
- const sessionDir = join(agentDir, "sessions", safePath);
225
+ const sessionDir = getDefaultSessionDirPath(cwd, agentDir);
216
226
  if (!existsSync(sessionDir)) {
217
227
  mkdirSync(sessionDir, { recursive: true });
218
228
  }
@@ -220,9 +230,10 @@ export function getDefaultSessionDir(cwd, agentDir = getDefaultAgentDir()) {
220
230
  }
221
231
  /** Exported for testing */
222
232
  export function loadEntriesFromFile(filePath) {
223
- if (!existsSync(filePath))
233
+ const resolvedFilePath = normalizePath(filePath);
234
+ if (!existsSync(resolvedFilePath))
224
235
  return [];
225
- const content = readFileSync(filePath, "utf8");
236
+ const content = readFileSync(resolvedFilePath, "utf8");
226
237
  const entries = [];
227
238
  const lines = content.trim().split("\n");
228
239
  for (const line of lines) {
@@ -245,45 +256,7 @@ export function loadEntriesFromFile(filePath) {
245
256
  }
246
257
  return entries;
247
258
  }
248
- function readSessionHeaderFromFile(filePath) {
249
- if (!existsSync(filePath))
250
- return undefined;
251
- try {
252
- const fd = openSync(filePath, "r");
253
- try {
254
- let offset = 0;
255
- let firstLine = "";
256
- const buffer = Buffer.alloc(4096);
257
- while (firstLine.length < 1024 * 1024) {
258
- const bytesRead = readSync(fd, buffer, 0, buffer.length, offset);
259
- if (bytesRead === 0)
260
- break;
261
- offset += bytesRead;
262
- const chunk = buffer.toString("utf8", 0, bytesRead);
263
- const newline = chunk.indexOf("\n");
264
- if (newline >= 0) {
265
- firstLine += chunk.slice(0, newline);
266
- break;
267
- }
268
- firstLine += chunk;
269
- }
270
- if (!firstLine.trim())
271
- return undefined;
272
- const header = JSON.parse(firstLine);
273
- if (header.type !== "session" || typeof header.id !== "string") {
274
- return undefined;
275
- }
276
- return header;
277
- }
278
- finally {
279
- closeSync(fd);
280
- }
281
- }
282
- catch {
283
- return undefined;
284
- }
285
- }
286
- function isValidSessionFile(filePath) {
259
+ function readSessionHeader(filePath) {
287
260
  try {
288
261
  const fd = openSync(filePath, "r");
289
262
  const buffer = Buffer.alloc(512);
@@ -291,22 +264,39 @@ function isValidSessionFile(filePath) {
291
264
  closeSync(fd);
292
265
  const firstLine = buffer.toString("utf8", 0, bytesRead).split("\n")[0];
293
266
  if (!firstLine)
294
- return false;
267
+ return null;
295
268
  const header = JSON.parse(firstLine);
296
- return header.type === "session" && typeof header.id === "string";
269
+ if (header.type !== "session" || typeof header.id !== "string") {
270
+ return null;
271
+ }
272
+ return header;
297
273
  }
298
274
  catch {
275
+ return null;
276
+ }
277
+ }
278
+ function getSessionHeaderCwd(header) {
279
+ const cwd = header.cwd;
280
+ return typeof cwd === "string" ? cwd : undefined;
281
+ }
282
+ function sessionCwdMatches(cwd, resolvedCwd) {
283
+ if (cwd === undefined || cwd === "") {
299
284
  return false;
300
285
  }
286
+ return canonicalizePath(resolvePath(cwd)) === canonicalizePath(resolvedCwd);
301
287
  }
302
288
  /** Exported for testing */
303
- export function findMostRecentSession(sessionDir) {
289
+ export function findMostRecentSession(sessionDir, cwd) {
290
+ const resolvedSessionDir = normalizePath(sessionDir);
291
+ const resolvedCwd = cwd ? resolvePath(cwd) : undefined;
304
292
  try {
305
- const files = readdirSync(sessionDir)
293
+ const files = readdirSync(resolvedSessionDir)
306
294
  .filter((f) => f.endsWith(".jsonl"))
307
- .map((f) => join(sessionDir, f))
308
- .filter(isValidSessionFile)
309
- .map((path) => ({ path, mtime: statSync(path).mtime }))
295
+ .map((f) => join(resolvedSessionDir, f))
296
+ .map((path) => ({ path, header: readSessionHeader(path) }))
297
+ .filter((file) => file.header !== null &&
298
+ (!resolvedCwd || sessionCwdMatches(getSessionHeaderCwd(file.header), resolvedCwd)))
299
+ .map(({ path }) => ({ path, mtime: statSync(path).mtime }))
310
300
  .sort((a, b) => b.mtime.getTime() - a.mtime.getTime());
311
301
  return files[0]?.path || null;
312
302
  }
@@ -427,6 +417,40 @@ async function buildSessionInfo(filePath) {
427
417
  return null;
428
418
  }
429
419
  }
420
+ const MAX_CONCURRENT_SESSION_INFO_LOADS = 10;
421
+ async function buildSessionInfosWithConcurrency(files, onLoaded) {
422
+ const results = new Array(files.length).fill(null);
423
+ const inFlight = new Set();
424
+ let nextIndex = 0;
425
+ const startNext = () => {
426
+ const index = nextIndex++;
427
+ const file = files[index];
428
+ if (!file)
429
+ return;
430
+ let task;
431
+ task = buildSessionInfo(file)
432
+ .then((info) => {
433
+ results[index] = info;
434
+ })
435
+ .catch(() => {
436
+ results[index] = null;
437
+ })
438
+ .finally(() => {
439
+ inFlight.delete(task);
440
+ onLoaded();
441
+ });
442
+ inFlight.add(task);
443
+ };
444
+ while (nextIndex < files.length || inFlight.size > 0) {
445
+ while (nextIndex < files.length && inFlight.size < MAX_CONCURRENT_SESSION_INFO_LOADS) {
446
+ startNext();
447
+ }
448
+ if (inFlight.size > 0) {
449
+ await Promise.race(inFlight);
450
+ }
451
+ }
452
+ return results;
453
+ }
430
454
  async function listSessionsFromDir(dir, onProgress, progressOffset = 0, progressTotal) {
431
455
  const sessions = [];
432
456
  if (!existsSync(dir)) {
@@ -437,12 +461,10 @@ async function listSessionsFromDir(dir, onProgress, progressOffset = 0, progress
437
461
  const files = dirEntries.filter((f) => f.endsWith(".jsonl")).map((f) => join(dir, f));
438
462
  const total = progressTotal ?? files.length;
439
463
  let loaded = 0;
440
- const results = await Promise.all(files.map(async (file) => {
441
- const info = await buildSessionInfo(file);
464
+ const results = await buildSessionInfosWithConcurrency(files, () => {
442
465
  loaded++;
443
466
  onProgress?.(progressOffset + loaded, total);
444
- return info;
445
- }));
467
+ });
446
468
  for (const info of results) {
447
469
  if (info) {
448
470
  sessions.push(info);
@@ -477,23 +499,23 @@ export class SessionManager {
477
499
  labelsById = new Map();
478
500
  labelTimestampsById = new Map();
479
501
  leafId = null;
480
- constructor(cwd, sessionDir, sessionFile, persist) {
481
- this.cwd = cwd;
482
- this.sessionDir = sessionDir;
502
+ constructor(cwd, sessionDir, sessionFile, persist, newSessionOptions) {
503
+ this.cwd = resolvePath(cwd);
504
+ this.sessionDir = normalizePath(sessionDir);
483
505
  this.persist = persist;
484
- if (persist && sessionDir && !existsSync(sessionDir)) {
485
- mkdirSync(sessionDir, { recursive: true });
506
+ if (persist && this.sessionDir && !existsSync(this.sessionDir)) {
507
+ mkdirSync(this.sessionDir, { recursive: true });
486
508
  }
487
509
  if (sessionFile) {
488
510
  this.setSessionFile(sessionFile);
489
511
  }
490
512
  else {
491
- this.newSession();
513
+ this.newSession(newSessionOptions);
492
514
  }
493
515
  }
494
516
  /** Switch to a different session file (used for resume and branching) */
495
517
  setSessionFile(sessionFile) {
496
- this.sessionFile = resolve(sessionFile);
518
+ this.sessionFile = resolvePath(sessionFile);
497
519
  if (existsSync(this.sessionFile)) {
498
520
  this.fileEntries = loadEntriesFromFile(this.sessionFile);
499
521
  // If file was empty or corrupted (no valid header), truncate and start fresh
@@ -521,6 +543,9 @@ export class SessionManager {
521
543
  }
522
544
  }
523
545
  newSession(options) {
546
+ if (options?.id !== undefined) {
547
+ assertValidSessionId(options.id);
548
+ }
524
549
  this.sessionId = options?.id ?? createSessionId();
525
550
  const timestamp = new Date().toISOString();
526
551
  const header = {
@@ -570,14 +595,56 @@ export class SessionManager {
570
595
  const content = `${this.fileEntries.map((e) => JSON.stringify(e)).join("\n")}\n`;
571
596
  writeFileSync(this.sessionFile, content);
572
597
  }
573
- isPersisted() {
574
- return this.persist;
575
- }
576
- flushPendingEntries() {
598
+ /** Rewrite the session file atomically (write to temp + rename). */
599
+ _rewriteFileAtomic() {
577
600
  if (!this.persist || !this.sessionFile)
578
601
  return;
579
- this._rewriteFile();
580
- this.flushed = true;
602
+ const content = `${this.fileEntries.map((e) => JSON.stringify(e)).join("\n")}\n`;
603
+ const tmpFile = `${this.sessionFile}.tmp`;
604
+ writeFileSync(tmpFile, content);
605
+ renameSync(tmpFile, this.sessionFile);
606
+ }
607
+ /**
608
+ * After compaction, prune entries before firstKeptEntryId from the current branch.
609
+ * Rewrites the JSONL file with only the kept entries.
610
+ * This releases memory and prevents unbounded file growth.
611
+ *
612
+ * Only the current branch (leaf → root) is preserved. Branches that diverge
613
+ * from entries before firstKeptEntryId are discarded — this matches the
614
+ * semantics of compaction (old context is summarized away and no longer needed).
615
+ */
616
+ pruneAfterCompaction() {
617
+ // 1. Get current branch (leaf → root, chronological order)
618
+ const branch = this.getBranch();
619
+ if (branch.length === 0)
620
+ return;
621
+ // 2. Find the latest compaction entry on the branch
622
+ const compactionIdx = branch.findIndex((e) => e.type === "compaction");
623
+ if (compactionIdx === -1)
624
+ return; // No compaction, nothing to prune
625
+ const compaction = branch[compactionIdx];
626
+ // 3. Find firstKeptEntryId in the branch
627
+ const firstKeptIdx = branch.findIndex((e) => e.id === compaction.firstKeptEntryId);
628
+ if (firstKeptIdx === -1)
629
+ return; // Can't find kept entry, don't prune
630
+ // Nothing to prune if firstKeptEntryId is the first entry
631
+ if (firstKeptIdx === 0)
632
+ return;
633
+ // 4. Collect entries to keep: header + entries from firstKeptIdx onward
634
+ const header = this.fileEntries.find((e) => e.type === "session");
635
+ const keptEntries = branch.slice(firstKeptIdx);
636
+ // 5. Fix parent chain: first kept entry becomes root (parentId = null)
637
+ if (keptEntries.length > 0 && keptEntries[0].parentId !== null) {
638
+ keptEntries[0].parentId = null;
639
+ }
640
+ // 6. Replace fileEntries and rebuild index
641
+ this.fileEntries = header ? [header, ...keptEntries] : [...keptEntries];
642
+ this._buildIndex();
643
+ // 7. Rewrite file atomically
644
+ this._rewriteFileAtomic();
645
+ }
646
+ isPersisted() {
647
+ return this.persist;
581
648
  }
582
649
  getCwd() {
583
650
  return this.cwd;
@@ -585,6 +652,9 @@ export class SessionManager {
585
652
  getSessionDir() {
586
653
  return this.sessionDir;
587
654
  }
655
+ usesDefaultSessionDir() {
656
+ return this.sessionDir === getDefaultSessionDirPath(this.cwd);
657
+ }
588
658
  getSessionId() {
589
659
  return this.sessionId;
590
660
  }
@@ -596,12 +666,26 @@ export class SessionManager {
596
666
  return;
597
667
  const hasAssistant = this.fileEntries.some((e) => e.type === "message" && e.message.role === "assistant");
598
668
  if (!hasAssistant) {
599
- // Mark as not flushed so when assistant arrives, all entries get written
600
- this.flushed = false;
669
+ if (this.flushed) {
670
+ appendFileSync(this.sessionFile, `${JSON.stringify(entry)}\n`);
671
+ }
672
+ else {
673
+ // Mark as not flushed so when assistant arrives, all entries get written
674
+ this.flushed = false;
675
+ }
601
676
  return;
602
677
  }
603
678
  if (!this.flushed) {
604
- this.flushPendingEntries();
679
+ const fd = openSync(this.sessionFile, "wx");
680
+ try {
681
+ for (const e of this.fileEntries) {
682
+ writeFileSync(fd, `${JSON.stringify(e)}\n`);
683
+ }
684
+ }
685
+ finally {
686
+ closeSync(fd);
687
+ }
688
+ this.flushed = true;
605
689
  }
606
690
  else {
607
691
  appendFileSync(this.sessionFile, `${JSON.stringify(entry)}\n`);
@@ -799,10 +883,10 @@ export class SessionManager {
799
883
  const startId = fromId ?? this.leafId;
800
884
  let current = startId ? this.byId.get(startId) : undefined;
801
885
  while (current) {
802
- path.push(current);
886
+ path.unshift(current);
803
887
  current = current.parentId ? this.byId.get(current.parentId) : undefined;
804
888
  }
805
- return path.reverse();
889
+ return path;
806
890
  }
807
891
  /**
808
892
  * Build the session context (what gets sent to the LLM).
@@ -1009,9 +1093,9 @@ export class SessionManager {
1009
1093
  * @param cwd Working directory (stored in session header)
1010
1094
  * @param sessionDir Optional session directory. If omitted, uses default (~/.pi/agent/sessions/<encoded-cwd>/).
1011
1095
  */
1012
- static create(cwd, sessionDir) {
1013
- const dir = sessionDir ?? getDefaultSessionDir(cwd);
1014
- return new SessionManager(cwd, dir, undefined, true);
1096
+ static create(cwd, sessionDir, options) {
1097
+ const dir = sessionDir ? normalizePath(sessionDir) : getDefaultSessionDir(cwd);
1098
+ return new SessionManager(cwd, dir, undefined, true, options);
1015
1099
  }
1016
1100
  /**
1017
1101
  * Open a specific session file.
@@ -1020,12 +1104,14 @@ export class SessionManager {
1020
1104
  * @param cwdOverride Optional cwd override instead of the session header cwd.
1021
1105
  */
1022
1106
  static open(path, sessionDir, cwdOverride) {
1107
+ const resolvedPath = resolvePath(path);
1023
1108
  // Extract cwd from session header if possible, otherwise use process.cwd()
1024
- const header = cwdOverride === undefined ? readSessionHeaderFromFile(path) : undefined;
1109
+ const entries = loadEntriesFromFile(resolvedPath);
1110
+ const header = entries.find((e) => e.type === "session");
1025
1111
  const cwd = cwdOverride ?? header?.cwd ?? process.cwd();
1026
1112
  // If no sessionDir provided, derive from file's parent directory
1027
- const dir = sessionDir ?? resolve(path, "..");
1028
- return new SessionManager(cwd, dir, path, true);
1113
+ const dir = sessionDir ? normalizePath(sessionDir) : resolve(resolvedPath, "..");
1114
+ return new SessionManager(cwd, dir, resolvedPath, true);
1029
1115
  }
1030
1116
  /**
1031
1117
  * Continue the most recent session, or create new if none.
@@ -1033,8 +1119,9 @@ export class SessionManager {
1033
1119
  * @param sessionDir Optional session directory. If omitted, uses default (~/.pi/agent/sessions/<encoded-cwd>/).
1034
1120
  */
1035
1121
  static continueRecent(cwd, sessionDir) {
1036
- const dir = sessionDir ?? getDefaultSessionDir(cwd);
1037
- const mostRecent = findMostRecentSession(dir);
1122
+ const dir = sessionDir ? normalizePath(sessionDir) : getDefaultSessionDir(cwd);
1123
+ const filterCwd = sessionDir !== undefined && dir !== getDefaultSessionDirPath(cwd);
1124
+ const mostRecent = findMostRecentSession(dir, filterCwd ? cwd : undefined);
1038
1125
  if (mostRecent) {
1039
1126
  return new SessionManager(cwd, dir, mostRecent, true);
1040
1127
  }
@@ -1051,21 +1138,26 @@ export class SessionManager {
1051
1138
  * @param targetCwd Target working directory (where the new session will be stored)
1052
1139
  * @param sessionDir Optional session directory. If omitted, uses default for targetCwd.
1053
1140
  */
1054
- static forkFrom(sourcePath, targetCwd, sessionDir) {
1055
- const sourceEntries = loadEntriesFromFile(sourcePath);
1141
+ static forkFrom(sourcePath, targetCwd, sessionDir, options) {
1142
+ const resolvedSourcePath = resolvePath(sourcePath);
1143
+ const resolvedTargetCwd = resolvePath(targetCwd);
1144
+ const sourceEntries = loadEntriesFromFile(resolvedSourcePath);
1056
1145
  if (sourceEntries.length === 0) {
1057
- throw new Error(`Cannot fork: source session file is empty or invalid: ${sourcePath}`);
1146
+ throw new Error(`Cannot fork: source session file is empty or invalid: ${resolvedSourcePath}`);
1058
1147
  }
1059
1148
  const sourceHeader = sourceEntries.find((e) => e.type === "session");
1060
1149
  if (!sourceHeader) {
1061
- throw new Error(`Cannot fork: source session has no header: ${sourcePath}`);
1150
+ throw new Error(`Cannot fork: source session has no header: ${resolvedSourcePath}`);
1062
1151
  }
1063
- const dir = sessionDir ?? getDefaultSessionDir(targetCwd);
1152
+ const dir = sessionDir ? normalizePath(sessionDir) : getDefaultSessionDir(resolvedTargetCwd);
1064
1153
  if (!existsSync(dir)) {
1065
1154
  mkdirSync(dir, { recursive: true });
1066
1155
  }
1067
1156
  // Create new session file with new ID but forked content
1068
- const newSessionId = createSessionId();
1157
+ if (options?.id !== undefined) {
1158
+ assertValidSessionId(options.id);
1159
+ }
1160
+ const newSessionId = options?.id ?? createSessionId();
1069
1161
  const timestamp = new Date().toISOString();
1070
1162
  const fileTimestamp = timestamp.replace(/[:.]/g, "-");
1071
1163
  const newSessionFile = join(dir, `${fileTimestamp}_${newSessionId}.jsonl`);
@@ -1075,17 +1167,17 @@ export class SessionManager {
1075
1167
  version: CURRENT_SESSION_VERSION,
1076
1168
  id: newSessionId,
1077
1169
  timestamp,
1078
- cwd: targetCwd,
1079
- parentSession: sourcePath,
1170
+ cwd: resolvedTargetCwd,
1171
+ parentSession: resolvedSourcePath,
1080
1172
  };
1081
- appendFileSync(newSessionFile, `${JSON.stringify(newHeader)}\n`);
1173
+ writeFileSync(newSessionFile, `${JSON.stringify(newHeader)}\n`, { flag: "wx" });
1082
1174
  // Copy all non-header entries from source
1083
1175
  for (const entry of sourceEntries) {
1084
1176
  if (entry.type !== "session") {
1085
1177
  appendFileSync(newSessionFile, `${JSON.stringify(entry)}\n`);
1086
1178
  }
1087
1179
  }
1088
- return new SessionManager(targetCwd, dir, newSessionFile, true);
1180
+ return new SessionManager(resolvedTargetCwd, dir, newSessionFile, true);
1089
1181
  }
1090
1182
  /**
1091
1183
  * List all sessions for a directory.
@@ -1094,16 +1186,21 @@ export class SessionManager {
1094
1186
  * @param onProgress Optional callback for progress updates (loaded, total)
1095
1187
  */
1096
1188
  static async list(cwd, sessionDir, onProgress) {
1097
- const dir = sessionDir ?? getDefaultSessionDir(cwd);
1098
- const sessions = await listSessionsFromDir(dir, onProgress);
1189
+ const dir = sessionDir ? normalizePath(sessionDir) : getDefaultSessionDir(cwd);
1190
+ const filterCwd = sessionDir !== undefined && dir !== getDefaultSessionDirPath(cwd);
1191
+ const resolvedCwd = resolvePath(cwd);
1192
+ const sessions = (await listSessionsFromDir(dir, onProgress)).filter((session) => !filterCwd || sessionCwdMatches(session.cwd, resolvedCwd));
1099
1193
  sessions.sort((a, b) => b.modified.getTime() - a.modified.getTime());
1100
1194
  return sessions;
1101
1195
  }
1102
- /**
1103
- * List all sessions across all project directories.
1104
- * @param onProgress Optional callback for progress updates (loaded, total)
1105
- */
1106
- static async listAll(onProgress) {
1196
+ static async listAll(sessionDirOrOnProgress, onProgress) {
1197
+ const customSessionDir = typeof sessionDirOrOnProgress === "string" ? normalizePath(sessionDirOrOnProgress) : undefined;
1198
+ const progress = typeof sessionDirOrOnProgress === "function" ? sessionDirOrOnProgress : onProgress;
1199
+ if (customSessionDir) {
1200
+ const sessions = await listSessionsFromDir(customSessionDir, progress);
1201
+ sessions.sort((a, b) => b.modified.getTime() - a.modified.getTime());
1202
+ return sessions;
1203
+ }
1107
1204
  const sessionsDir = getSessionsDir();
1108
1205
  try {
1109
1206
  if (!existsSync(sessionsDir)) {
@@ -1128,12 +1225,10 @@ export class SessionManager {
1128
1225
  let loaded = 0;
1129
1226
  const sessions = [];
1130
1227
  const allFiles = dirFiles.flat();
1131
- const results = await Promise.all(allFiles.map(async (file) => {
1132
- const info = await buildSessionInfo(file);
1228
+ const results = await buildSessionInfosWithConcurrency(allFiles, () => {
1133
1229
  loaded++;
1134
- onProgress?.(loaded, totalFiles);
1135
- return info;
1136
- }));
1230
+ progress?.(loaded, totalFiles);
1231
+ });
1137
1232
  for (const info of results) {
1138
1233
  if (info) {
1139
1234
  sessions.push(info);