@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
@@ -0,0 +1,217 @@
1
+ import { APP_NAME, getChangelogPath, VERSION } from "../../config.js";
2
+ import { KeybindingsManager } from "../../core/keybindings.js";
3
+ import { LocalAgentSessionProxy } from "../../core/local-agent-session-proxy.js";
4
+ import { getNewEntries, parseChangelog } from "../../utils/changelog.js";
5
+ import { formatKeyText } from "../interactive/components/keybinding-hints.js";
6
+ import { AgentHttpServer } from "./http-server.js";
7
+ const DEFAULT_PORT = 8080;
8
+ /** Get the display text for a keybinding (theme-independent). */
9
+ function keyText(kb, keybinding) {
10
+ const keys = kb.getKeys(keybinding);
11
+ if (keys.length === 0)
12
+ return "";
13
+ return formatKeyText(keys.join("/"));
14
+ }
15
+ /** Generate structured banner data for serve/connect. */
16
+ export function generateBanner(session) {
17
+ // Use the app's KeybindingsManager which includes app-specific bindings
18
+ const kb = KeybindingsManager.create();
19
+ const expandedHints = [
20
+ { key: keyText(kb, "app.interrupt"), description: "to interrupt" },
21
+ { key: keyText(kb, "app.clear"), description: "to clear" },
22
+ { key: `${keyText(kb, "app.clear")} twice`, description: "to exit" },
23
+ { key: keyText(kb, "app.exit"), description: "to exit (empty)" },
24
+ { key: keyText(kb, "app.suspend"), description: "to suspend" },
25
+ { key: keyText(kb, "tui.editor.deleteToLineEnd"), description: "to delete to end" },
26
+ { key: keyText(kb, "app.thinking.cycle"), description: "to cycle thinking level" },
27
+ {
28
+ key: `${keyText(kb, "app.model.cycleForward")}/${keyText(kb, "app.model.cycleBackward")}`,
29
+ description: "to cycle models",
30
+ },
31
+ { key: keyText(kb, "app.model.select"), description: "to select model" },
32
+ { key: keyText(kb, "app.tools.expand"), description: "to expand tools" },
33
+ { key: keyText(kb, "app.thinking.toggle"), description: "to expand thinking" },
34
+ { key: keyText(kb, "app.editor.external"), description: "for external editor" },
35
+ { key: "/", description: "for commands" },
36
+ { key: "!", description: "to run bash" },
37
+ { key: "!!", description: "to run bash (no context)" },
38
+ { key: keyText(kb, "app.message.followUp"), description: "to queue follow-up" },
39
+ { key: keyText(kb, "app.message.dequeue"), description: "to edit all queued messages" },
40
+ { key: keyText(kb, "app.clipboard.pasteImage"), description: "to paste image" },
41
+ { key: "drop files", description: "to attach" },
42
+ ];
43
+ const compactHints = [
44
+ { key: keyText(kb, "app.interrupt"), description: "interrupt" },
45
+ { key: `${keyText(kb, "app.clear")}/${keyText(kb, "app.exit")}`, description: "clear/exit" },
46
+ { key: "/", description: "commands" },
47
+ { key: "!", description: "bash" },
48
+ { key: keyText(kb, "app.tools.expand"), description: "more" },
49
+ ];
50
+ const compactOnboarding = `Press ${keyText(kb, "app.tools.expand")} to show full startup help and loaded resources.`;
51
+ const onboarding = `Pi can explain its own features and look up its docs. Ask it how to use or extend Pi.`;
52
+ // Gather loaded resources from the session
53
+ const loadedResources = [];
54
+ const rl = session.resourceLoader;
55
+ // Context files
56
+ const contextFiles = rl.getAgentsFiles().agentsFiles;
57
+ if (contextFiles.length > 0) {
58
+ loadedResources.push({
59
+ name: "Context",
60
+ compactList: contextFiles.map((f) => f.path).join(", "),
61
+ expandedList: contextFiles.map((f) => f.path).join("\n"),
62
+ });
63
+ }
64
+ // Skills
65
+ const skills = rl.getSkills().skills;
66
+ if (skills.length > 0) {
67
+ loadedResources.push({
68
+ name: "Skills",
69
+ compactList: skills
70
+ .map((s) => s.name)
71
+ .sort()
72
+ .join(", "),
73
+ expandedList: skills.map((s) => s.filePath).join("\n"),
74
+ });
75
+ }
76
+ // Prompts (templates)
77
+ const templates = session.promptTemplates;
78
+ if (templates.length > 0) {
79
+ loadedResources.push({
80
+ name: "Prompts",
81
+ compactList: templates
82
+ .map((t) => `/${t.name}`)
83
+ .sort()
84
+ .join(", "),
85
+ expandedList: templates.map((t) => t.filePath).join("\n"),
86
+ });
87
+ }
88
+ // Extensions — tool registration and events work, UI calls degrade to no-ops
89
+ const extensions = rl.getExtensions().extensions;
90
+ if (extensions.length > 0) {
91
+ loadedResources.push({
92
+ name: "Extensions",
93
+ compactList: extensions.map((e) => e.path.split("/").pop() ?? e.path).join(", "),
94
+ expandedList: extensions.map((e) => e.path).join("\n"),
95
+ });
96
+ }
97
+ // Themes (custom only)
98
+ const themes = rl.getThemes().themes.filter((t) => t.sourcePath);
99
+ if (themes.length > 0) {
100
+ loadedResources.push({
101
+ name: "Themes",
102
+ compactList: themes
103
+ .map((t) => t.name ?? "")
104
+ .filter(Boolean)
105
+ .sort()
106
+ .join(", "),
107
+ expandedList: themes.map((t) => t.sourcePath).join("\n"),
108
+ });
109
+ }
110
+ // Diagnostics
111
+ const diagnostics = [];
112
+ const skillDiagnostics = rl.getSkills().diagnostics;
113
+ if (skillDiagnostics.length > 0) {
114
+ diagnostics.push({ label: "Skill conflicts", entries: skillDiagnostics });
115
+ }
116
+ const promptDiagnostics = rl.getPrompts().diagnostics;
117
+ if (promptDiagnostics.length > 0) {
118
+ diagnostics.push({ label: "Prompt conflicts", entries: promptDiagnostics });
119
+ }
120
+ const extensionErrors = rl.getExtensions().errors;
121
+ if (extensionErrors.length > 0) {
122
+ diagnostics.push({
123
+ label: "Extension issues",
124
+ entries: extensionErrors.map((e) => ({
125
+ type: "error",
126
+ message: e.error,
127
+ path: e.path,
128
+ })),
129
+ });
130
+ }
131
+ // Changelog — only show new entries since last seen version (same logic as local mode)
132
+ let changelogMarkdown;
133
+ const lastVersion = session.settingsManager.getLastChangelogVersion();
134
+ const changelogEntries = parseChangelog(getChangelogPath());
135
+ if (lastVersion && changelogEntries.length > 0) {
136
+ const newEntries = getNewEntries(changelogEntries, lastVersion);
137
+ if (newEntries.length > 0) {
138
+ changelogMarkdown = newEntries.map((e) => e.content).join("\n\n");
139
+ }
140
+ }
141
+ return {
142
+ appName: APP_NAME,
143
+ version: VERSION,
144
+ expandedHints,
145
+ compactHints,
146
+ compactOnboarding,
147
+ onboarding,
148
+ loadedResources,
149
+ diagnostics,
150
+ changelogMarkdown,
151
+ };
152
+ }
153
+ export async function runServeMode(runtime, options = {}) {
154
+ const port = options.port ?? DEFAULT_PORT;
155
+ const proxy = new LocalAgentSessionProxy(runtime);
156
+ // Generate and set banner data for connect clients
157
+ proxy.setBanner(generateBanner(runtime.session));
158
+ const server = new AgentHttpServer(proxy);
159
+ // Bind extensions — no UI context (hasUI() === false), tool registration
160
+ // and event subscriptions work normally. UI calls degrade to no-ops.
161
+ const rebindSession = async () => {
162
+ const session = runtime.session;
163
+ await session.bindExtensions({
164
+ commandContextActions: {
165
+ waitForIdle: () => session.agent.waitForIdle(),
166
+ newSession: async (newSessionOptions) => runtime.newSession(newSessionOptions),
167
+ fork: async (entryId, forkOptions) => {
168
+ const result = await runtime.fork(entryId, forkOptions);
169
+ return { cancelled: result.cancelled };
170
+ },
171
+ navigateTree: async (targetId, navigateOptions) => {
172
+ const result = await session.navigateTree(targetId, {
173
+ summarize: navigateOptions?.summarize,
174
+ customInstructions: navigateOptions?.customInstructions,
175
+ replaceInstructions: navigateOptions?.replaceInstructions,
176
+ label: navigateOptions?.label,
177
+ });
178
+ return { cancelled: result.cancelled };
179
+ },
180
+ switchSession: async (sessionPath, switchOptions) => {
181
+ return runtime.switchSession(sessionPath, switchOptions);
182
+ },
183
+ reload: async () => {
184
+ await session.reload();
185
+ },
186
+ },
187
+ abortHandler: () => {
188
+ // No UI to reset in serve mode
189
+ },
190
+ onError: (err) => {
191
+ process.stderr.write(`[serve] Extension error (${err.extensionPath}): ${err.error}\n`);
192
+ },
193
+ });
194
+ };
195
+ // Set up beforeSessionInvalidate callback
196
+ runtime.setBeforeSessionInvalidate(() => {
197
+ // No UI to reset in serve mode
198
+ });
199
+ // Set up rebindSession — must call bindExtensions for each new session
200
+ // so extension event handlers (session_start, etc.) fire correctly.
201
+ // Also re-subscribe proxy listeners so SSE events keep flowing.
202
+ runtime.setRebindSession(async (session, reason) => {
203
+ proxy.resubscribe(reason);
204
+ await rebindSession();
205
+ // Update banner after session replacement
206
+ proxy.setBanner(generateBanner(session));
207
+ });
208
+ // Initial bind for the first session
209
+ await rebindSession();
210
+ await server.start(port);
211
+ // Log to stderr so stdout stays clean
212
+ process.stderr.write(`[serve] Listening on port ${port}\n`);
213
+ process.stderr.write(`[serve] Connect with: pi --mode connect --url http://localhost:${port}\n`);
214
+ // Keep process alive
215
+ return new Promise(() => { });
216
+ }
217
+ //# sourceMappingURL=serve-mode.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"serve-mode.js","sourceRoot":"","sources":["../../../src/modes/serve/serve-mode.ts"],"names":[],"mappings":"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","sourcesContent":["import { APP_NAME, getChangelogPath, VERSION } from \"../../config.ts\";\nimport type { AgentSession } from \"../../core/agent-session.ts\";\nimport type {\n\tBannerData,\n\tBannerKeyHint,\n\tLoadedResourceSection,\n\tResourceDiagnosticEntry,\n} from \"../../core/agent-session-proxy.ts\";\nimport type { AgentSessionRuntime } from \"../../core/agent-session-runtime.ts\";\nimport { type AppKeybinding, KeybindingsManager } from \"../../core/keybindings.ts\";\nimport { LocalAgentSessionProxy } from \"../../core/local-agent-session-proxy.ts\";\nimport { getNewEntries, parseChangelog } from \"../../utils/changelog.ts\";\nimport { formatKeyText } from \"../interactive/components/keybinding-hints.ts\";\nimport { AgentHttpServer } from \"./http-server.ts\";\n\nexport interface ServeModeOptions {\n\tport?: number;\n}\n\nconst DEFAULT_PORT = 8080;\n\n/** Get the display text for a keybinding (theme-independent). */\nfunction keyText(kb: KeybindingsManager, keybinding: string): string {\n\tconst keys = kb.getKeys(keybinding as AppKeybinding);\n\tif (keys.length === 0) return \"\";\n\treturn formatKeyText(keys.join(\"/\"));\n}\n\n/** Generate structured banner data for serve/connect. */\nexport function generateBanner(session: AgentSession): BannerData {\n\t// Use the app's KeybindingsManager which includes app-specific bindings\n\tconst kb = KeybindingsManager.create();\n\n\tconst expandedHints: BannerKeyHint[] = [\n\t\t{ key: keyText(kb, \"app.interrupt\"), description: \"to interrupt\" },\n\t\t{ key: keyText(kb, \"app.clear\"), description: \"to clear\" },\n\t\t{ key: `${keyText(kb, \"app.clear\")} twice`, description: \"to exit\" },\n\t\t{ key: keyText(kb, \"app.exit\"), description: \"to exit (empty)\" },\n\t\t{ key: keyText(kb, \"app.suspend\"), description: \"to suspend\" },\n\t\t{ key: keyText(kb, \"tui.editor.deleteToLineEnd\"), description: \"to delete to end\" },\n\t\t{ key: keyText(kb, \"app.thinking.cycle\"), description: \"to cycle thinking level\" },\n\t\t{\n\t\t\tkey: `${keyText(kb, \"app.model.cycleForward\")}/${keyText(kb, \"app.model.cycleBackward\")}`,\n\t\t\tdescription: \"to cycle models\",\n\t\t},\n\t\t{ key: keyText(kb, \"app.model.select\"), description: \"to select model\" },\n\t\t{ key: keyText(kb, \"app.tools.expand\"), description: \"to expand tools\" },\n\t\t{ key: keyText(kb, \"app.thinking.toggle\"), description: \"to expand thinking\" },\n\t\t{ key: keyText(kb, \"app.editor.external\"), description: \"for external editor\" },\n\t\t{ key: \"/\", description: \"for commands\" },\n\t\t{ key: \"!\", description: \"to run bash\" },\n\t\t{ key: \"!!\", description: \"to run bash (no context)\" },\n\t\t{ key: keyText(kb, \"app.message.followUp\"), description: \"to queue follow-up\" },\n\t\t{ key: keyText(kb, \"app.message.dequeue\"), description: \"to edit all queued messages\" },\n\t\t{ key: keyText(kb, \"app.clipboard.pasteImage\"), description: \"to paste image\" },\n\t\t{ key: \"drop files\", description: \"to attach\" },\n\t];\n\tconst compactHints: BannerKeyHint[] = [\n\t\t{ key: keyText(kb, \"app.interrupt\"), description: \"interrupt\" },\n\t\t{ key: `${keyText(kb, \"app.clear\")}/${keyText(kb, \"app.exit\")}`, description: \"clear/exit\" },\n\t\t{ key: \"/\", description: \"commands\" },\n\t\t{ key: \"!\", description: \"bash\" },\n\t\t{ key: keyText(kb, \"app.tools.expand\"), description: \"more\" },\n\t];\n\tconst compactOnboarding = `Press ${keyText(kb, \"app.tools.expand\")} to show full startup help and loaded resources.`;\n\tconst onboarding = `Pi can explain its own features and look up its docs. Ask it how to use or extend Pi.`;\n\n\t// Gather loaded resources from the session\n\tconst loadedResources: LoadedResourceSection[] = [];\n\tconst rl = session.resourceLoader;\n\n\t// Context files\n\tconst contextFiles = rl.getAgentsFiles().agentsFiles;\n\tif (contextFiles.length > 0) {\n\t\tloadedResources.push({\n\t\t\tname: \"Context\",\n\t\t\tcompactList: contextFiles.map((f) => f.path).join(\", \"),\n\t\t\texpandedList: contextFiles.map((f) => f.path).join(\"\\n\"),\n\t\t});\n\t}\n\n\t// Skills\n\tconst skills = rl.getSkills().skills;\n\tif (skills.length > 0) {\n\t\tloadedResources.push({\n\t\t\tname: \"Skills\",\n\t\t\tcompactList: skills\n\t\t\t\t.map((s) => s.name)\n\t\t\t\t.sort()\n\t\t\t\t.join(\", \"),\n\t\t\texpandedList: skills.map((s) => s.filePath).join(\"\\n\"),\n\t\t});\n\t}\n\n\t// Prompts (templates)\n\tconst templates = session.promptTemplates;\n\tif (templates.length > 0) {\n\t\tloadedResources.push({\n\t\t\tname: \"Prompts\",\n\t\t\tcompactList: templates\n\t\t\t\t.map((t) => `/${t.name}`)\n\t\t\t\t.sort()\n\t\t\t\t.join(\", \"),\n\t\t\texpandedList: templates.map((t) => t.filePath).join(\"\\n\"),\n\t\t});\n\t}\n\n\t// Extensions — tool registration and events work, UI calls degrade to no-ops\n\tconst extensions = rl.getExtensions().extensions;\n\tif (extensions.length > 0) {\n\t\tloadedResources.push({\n\t\t\tname: \"Extensions\",\n\t\t\tcompactList: extensions.map((e) => e.path.split(\"/\").pop() ?? e.path).join(\", \"),\n\t\t\texpandedList: extensions.map((e) => e.path).join(\"\\n\"),\n\t\t});\n\t}\n\n\t// Themes (custom only)\n\tconst themes = rl.getThemes().themes.filter((t) => t.sourcePath);\n\tif (themes.length > 0) {\n\t\tloadedResources.push({\n\t\t\tname: \"Themes\",\n\t\t\tcompactList: themes\n\t\t\t\t.map((t) => t.name ?? \"\")\n\t\t\t\t.filter(Boolean)\n\t\t\t\t.sort()\n\t\t\t\t.join(\", \"),\n\t\t\texpandedList: themes.map((t) => t.sourcePath!).join(\"\\n\"),\n\t\t});\n\t}\n\n\t// Diagnostics\n\tconst diagnostics: Array<{ label: string; entries: ResourceDiagnosticEntry[] }> = [];\n\n\tconst skillDiagnostics = rl.getSkills().diagnostics;\n\tif (skillDiagnostics.length > 0) {\n\t\tdiagnostics.push({ label: \"Skill conflicts\", entries: skillDiagnostics as ResourceDiagnosticEntry[] });\n\t}\n\n\tconst promptDiagnostics = rl.getPrompts().diagnostics;\n\tif (promptDiagnostics.length > 0) {\n\t\tdiagnostics.push({ label: \"Prompt conflicts\", entries: promptDiagnostics as ResourceDiagnosticEntry[] });\n\t}\n\n\tconst extensionErrors = rl.getExtensions().errors;\n\tif (extensionErrors.length > 0) {\n\t\tdiagnostics.push({\n\t\t\tlabel: \"Extension issues\",\n\t\t\tentries: extensionErrors.map((e) => ({\n\t\t\t\ttype: \"error\" as const,\n\t\t\t\tmessage: e.error,\n\t\t\t\tpath: e.path,\n\t\t\t})),\n\t\t});\n\t}\n\n\t// Changelog — only show new entries since last seen version (same logic as local mode)\n\tlet changelogMarkdown: string | undefined;\n\tconst lastVersion = session.settingsManager.getLastChangelogVersion();\n\tconst changelogEntries = parseChangelog(getChangelogPath());\n\tif (lastVersion && changelogEntries.length > 0) {\n\t\tconst newEntries = getNewEntries(changelogEntries, lastVersion);\n\t\tif (newEntries.length > 0) {\n\t\t\tchangelogMarkdown = newEntries.map((e) => e.content).join(\"\\n\\n\");\n\t\t}\n\t}\n\n\treturn {\n\t\tappName: APP_NAME,\n\t\tversion: VERSION,\n\t\texpandedHints,\n\t\tcompactHints,\n\t\tcompactOnboarding,\n\t\tonboarding,\n\t\tloadedResources,\n\t\tdiagnostics,\n\t\tchangelogMarkdown,\n\t};\n}\n\nexport async function runServeMode(runtime: AgentSessionRuntime, options: ServeModeOptions = {}): Promise<void> {\n\tconst port = options.port ?? DEFAULT_PORT;\n\tconst proxy = new LocalAgentSessionProxy(runtime);\n\n\t// Generate and set banner data for connect clients\n\tproxy.setBanner(generateBanner(runtime.session));\n\n\tconst server = new AgentHttpServer(proxy);\n\n\t// Bind extensions — no UI context (hasUI() === false), tool registration\n\t// and event subscriptions work normally. UI calls degrade to no-ops.\n\tconst rebindSession = async (): Promise<void> => {\n\t\tconst session = runtime.session;\n\t\tawait session.bindExtensions({\n\t\t\tcommandContextActions: {\n\t\t\t\twaitForIdle: () => session.agent.waitForIdle(),\n\t\t\t\tnewSession: async (newSessionOptions) => runtime.newSession(newSessionOptions),\n\t\t\t\tfork: async (entryId, forkOptions) => {\n\t\t\t\t\tconst result = await runtime.fork(entryId, forkOptions);\n\t\t\t\t\treturn { cancelled: result.cancelled };\n\t\t\t\t},\n\t\t\t\tnavigateTree: async (targetId, navigateOptions) => {\n\t\t\t\t\tconst result = await session.navigateTree(targetId, {\n\t\t\t\t\t\tsummarize: navigateOptions?.summarize,\n\t\t\t\t\t\tcustomInstructions: navigateOptions?.customInstructions,\n\t\t\t\t\t\treplaceInstructions: navigateOptions?.replaceInstructions,\n\t\t\t\t\t\tlabel: navigateOptions?.label,\n\t\t\t\t\t});\n\t\t\t\t\treturn { cancelled: result.cancelled };\n\t\t\t\t},\n\t\t\t\tswitchSession: async (sessionPath, switchOptions) => {\n\t\t\t\t\treturn runtime.switchSession(sessionPath, switchOptions);\n\t\t\t\t},\n\t\t\t\treload: async () => {\n\t\t\t\t\tawait session.reload();\n\t\t\t\t},\n\t\t\t},\n\t\t\tabortHandler: () => {\n\t\t\t\t// No UI to reset in serve mode\n\t\t\t},\n\t\t\tonError: (err) => {\n\t\t\t\tprocess.stderr.write(`[serve] Extension error (${err.extensionPath}): ${err.error}\\n`);\n\t\t\t},\n\t\t});\n\t};\n\n\t// Set up beforeSessionInvalidate callback\n\truntime.setBeforeSessionInvalidate(() => {\n\t\t// No UI to reset in serve mode\n\t});\n\n\t// Set up rebindSession — must call bindExtensions for each new session\n\t// so extension event handlers (session_start, etc.) fire correctly.\n\t// Also re-subscribe proxy listeners so SSE events keep flowing.\n\truntime.setRebindSession(async (session, reason) => {\n\t\tproxy.resubscribe(reason);\n\t\tawait rebindSession();\n\t\t// Update banner after session replacement\n\t\tproxy.setBanner(generateBanner(session));\n\t});\n\n\t// Initial bind for the first session\n\tawait rebindSession();\n\n\tawait server.start(port);\n\n\t// Log to stderr so stdout stays clean\n\tprocess.stderr.write(`[serve] Listening on port ${port}\\n`);\n\tprocess.stderr.write(`[serve] Connect with: pi --mode connect --url http://localhost:${port}\\n`);\n\n\t// Keep process alive\n\treturn new Promise(() => {});\n}\n"]}
@@ -1 +1 @@
1
- {"version":3,"file":"package-manager-cli.d.ts","sourceRoot":"","sources":["../src/package-manager-cli.ts"],"names":[],"mappings":"AAiBA,MAAM,MAAM,cAAc,GAAG,SAAS,GAAG,QAAQ,GAAG,QAAQ,GAAG,MAAM,CAAC;AAkUtE,wBAAsB,mBAAmB,CAAC,IAAI,EAAE,MAAM,EAAE,GAAG,OAAO,CAAC,OAAO,CAAC,CAoB1E;AAED,wBAAsB,oBAAoB,CAAC,IAAI,EAAE,MAAM,EAAE,GAAG,OAAO,CAAC,OAAO,CAAC,CAiK3E","sourcesContent":["import chalk from \"chalk\";\nimport { spawn } from \"child_process\";\nimport { selectConfig } from \"./cli/config-selector.js\";\nimport {\n\tAPP_NAME,\n\tgetAgentDir,\n\tgetSelfUpdateCommand,\n\tgetSelfUpdateUnavailableInstruction,\n\tPACKAGE_NAME,\n\ttype SelfUpdateCommand,\n\tVERSION,\n} from \"./config.js\";\nimport { DefaultPackageManager } from \"./core/package-manager.js\";\nimport { SettingsManager } from \"./core/settings-manager.js\";\nimport { shouldUseWindowsShell } from \"./utils/child-process.js\";\nimport { getLatestPiRelease, isNewerPackageVersion } from \"./utils/version-check.js\";\n\nexport type PackageCommand = \"install\" | \"remove\" | \"update\" | \"list\";\n\ntype UpdateTarget = { type: \"all\" } | { type: \"self\" } | { type: \"extensions\"; source?: string };\n\ninterface PackageCommandOptions {\n\tcommand: PackageCommand;\n\tsource?: string;\n\tupdateTarget?: UpdateTarget;\n\tlocal: boolean;\n\tforce: boolean;\n\thelp: boolean;\n\tinvalidOption?: string;\n\tinvalidArgument?: string;\n\tmissingOptionValue?: string;\n\tconflictingOptions?: string;\n}\n\nfunction reportSettingsErrors(settingsManager: SettingsManager, context: string): void {\n\tconst errors = settingsManager.drainErrors();\n\tfor (const { scope, error } of errors) {\n\t\tconsole.error(chalk.yellow(`Warning (${context}, ${scope} settings): ${error.message}`));\n\t\tif (error.stack) {\n\t\t\tconsole.error(chalk.dim(error.stack));\n\t\t}\n\t}\n}\n\nfunction getPackageCommandUsage(command: PackageCommand): string {\n\tswitch (command) {\n\t\tcase \"install\":\n\t\t\treturn `${APP_NAME} install <source> [-l]`;\n\t\tcase \"remove\":\n\t\t\treturn `${APP_NAME} remove <source> [-l]`;\n\t\tcase \"update\":\n\t\t\treturn `${APP_NAME} update [source|self|pi] [--self] [--extensions] [--extension <source>] [--force]`;\n\t\tcase \"list\":\n\t\t\treturn `${APP_NAME} list`;\n\t}\n}\n\nfunction printPackageCommandHelp(command: PackageCommand): void {\n\tswitch (command) {\n\t\tcase \"install\":\n\t\t\tconsole.log(`${chalk.bold(\"Usage:\")}\n ${getPackageCommandUsage(\"install\")}\n\nInstall a package and add it to settings.\n\nOptions:\n -l, --local Install project-locally (.pi/settings.json)\n\nExamples:\n ${APP_NAME} install npm:@foo/bar\n ${APP_NAME} install git:github.com/user/repo\n ${APP_NAME} install git:git@github.com:user/repo\n ${APP_NAME} install https://github.com/user/repo\n ${APP_NAME} install ssh://git@github.com/user/repo\n ${APP_NAME} install ./local/path\n`);\n\t\t\treturn;\n\n\t\tcase \"remove\":\n\t\t\tconsole.log(`${chalk.bold(\"Usage:\")}\n ${getPackageCommandUsage(\"remove\")}\n\nRemove a package and its source from settings.\nAlias: ${APP_NAME} uninstall <source> [-l]\n\nOptions:\n -l, --local Remove from project settings (.pi/settings.json)\n\nExamples:\n ${APP_NAME} remove npm:@foo/bar\n ${APP_NAME} uninstall npm:@foo/bar\n`);\n\t\t\treturn;\n\n\t\tcase \"update\":\n\t\t\tconsole.log(`${chalk.bold(\"Usage:\")}\n ${getPackageCommandUsage(\"update\")}\n\nUpdate pi and installed packages.\n\nOptions:\n --self Update pi only\n --extensions Update installed packages only\n --extension <source> Update one package only\n --force Reinstall pi even if the current version is latest\n\nShort forms:\n ${APP_NAME} update Update pi and all extensions\n ${APP_NAME} update <source> Update one package\n ${APP_NAME} update pi Update pi only (self works as alias to pi)\n`);\n\t\t\treturn;\n\n\t\tcase \"list\":\n\t\t\tconsole.log(`${chalk.bold(\"Usage:\")}\n ${getPackageCommandUsage(\"list\")}\n\nList installed packages from user and project settings.\n`);\n\t\t\treturn;\n\t}\n}\n\nfunction parsePackageCommand(args: string[]): PackageCommandOptions | undefined {\n\tconst [rawCommand, ...rest] = args;\n\tlet command: PackageCommand | undefined;\n\tif (rawCommand === \"uninstall\") {\n\t\tcommand = \"remove\";\n\t} else if (rawCommand === \"install\" || rawCommand === \"remove\" || rawCommand === \"update\" || rawCommand === \"list\") {\n\t\tcommand = rawCommand;\n\t}\n\tif (!command) {\n\t\treturn undefined;\n\t}\n\n\tlet local = false;\n\tlet force = false;\n\tlet help = false;\n\tlet invalidOption: string | undefined;\n\tlet invalidArgument: string | undefined;\n\tlet missingOptionValue: string | undefined;\n\tlet conflictingOptions: string | undefined;\n\tlet source: string | undefined;\n\tlet selfFlag = false;\n\tlet extensionsFlag = false;\n\tlet extensionFlagSource: string | undefined;\n\n\tfor (let index = 0; index < rest.length; index++) {\n\t\tconst arg = rest[index];\n\t\tif (arg === \"-h\" || arg === \"--help\") {\n\t\t\thelp = true;\n\t\t\tcontinue;\n\t\t}\n\n\t\tif (arg === \"-l\" || arg === \"--local\") {\n\t\t\tif (command === \"install\" || command === \"remove\") {\n\t\t\t\tlocal = true;\n\t\t\t} else {\n\t\t\t\tinvalidOption = invalidOption ?? arg;\n\t\t\t}\n\t\t\tcontinue;\n\t\t}\n\n\t\tif (arg === \"--self\") {\n\t\t\tif (command === \"update\") {\n\t\t\t\tselfFlag = true;\n\t\t\t} else {\n\t\t\t\tinvalidOption = invalidOption ?? arg;\n\t\t\t}\n\t\t\tcontinue;\n\t\t}\n\n\t\tif (arg === \"--extensions\") {\n\t\t\tif (command === \"update\") {\n\t\t\t\textensionsFlag = true;\n\t\t\t} else {\n\t\t\t\tinvalidOption = invalidOption ?? arg;\n\t\t\t}\n\t\t\tcontinue;\n\t\t}\n\n\t\tif (arg === \"--force\") {\n\t\t\tif (command === \"update\") {\n\t\t\t\tforce = true;\n\t\t\t} else {\n\t\t\t\tinvalidOption = invalidOption ?? arg;\n\t\t\t}\n\t\t\tcontinue;\n\t\t}\n\n\t\tif (arg === \"--extension\") {\n\t\t\tif (command !== \"update\") {\n\t\t\t\tinvalidOption = invalidOption ?? arg;\n\t\t\t\tcontinue;\n\t\t\t}\n\n\t\t\tconst value = rest[index + 1];\n\t\t\tif (!value || value.startsWith(\"-\")) {\n\t\t\t\tmissingOptionValue = missingOptionValue ?? arg;\n\t\t\t} else if (extensionFlagSource) {\n\t\t\t\tconflictingOptions = conflictingOptions ?? \"--extension can only be provided once\";\n\t\t\t\tindex++;\n\t\t\t} else {\n\t\t\t\textensionFlagSource = value;\n\t\t\t\tindex++;\n\t\t\t}\n\t\t\tcontinue;\n\t\t}\n\n\t\tif (arg.startsWith(\"-\")) {\n\t\t\tinvalidOption = invalidOption ?? arg;\n\t\t\tcontinue;\n\t\t}\n\n\t\tif (!source) {\n\t\t\tsource = arg;\n\t\t} else {\n\t\t\tinvalidArgument = invalidArgument ?? arg;\n\t\t}\n\t}\n\n\tlet updateTarget: UpdateTarget | undefined;\n\tif (command === \"update\") {\n\t\tif (extensionFlagSource) {\n\t\t\tif (selfFlag || extensionsFlag) {\n\t\t\t\tconflictingOptions = conflictingOptions ?? \"--extension cannot be combined with --self or --extensions\";\n\t\t\t}\n\t\t\tif (source) {\n\t\t\t\tconflictingOptions = conflictingOptions ?? \"--extension cannot be combined with a positional source\";\n\t\t\t}\n\t\t\tupdateTarget = { type: \"extensions\", source: extensionFlagSource };\n\t\t} else if (source) {\n\t\t\tconst sourceIsSelf = source === \"self\" || source === \"pi\";\n\t\t\tif (sourceIsSelf) {\n\t\t\t\tupdateTarget = extensionsFlag ? { type: \"all\" } : { type: \"self\" };\n\t\t\t} else {\n\t\t\t\tif (extensionsFlag || selfFlag) {\n\t\t\t\t\tconflictingOptions =\n\t\t\t\t\t\tconflictingOptions ?? \"positional update targets cannot be combined with --self or --extensions\";\n\t\t\t\t}\n\t\t\t\tupdateTarget = { type: \"extensions\", source };\n\t\t\t}\n\t\t} else if (selfFlag && extensionsFlag) {\n\t\t\tupdateTarget = { type: \"all\" };\n\t\t} else if (selfFlag) {\n\t\t\tupdateTarget = { type: \"self\" };\n\t\t} else if (extensionsFlag) {\n\t\t\tupdateTarget = { type: \"extensions\" };\n\t\t} else {\n\t\t\tupdateTarget = { type: \"all\" };\n\t\t}\n\t}\n\n\treturn {\n\t\tcommand,\n\t\tsource,\n\t\tupdateTarget,\n\t\tlocal,\n\t\tforce,\n\t\thelp,\n\t\tinvalidOption,\n\t\tinvalidArgument,\n\t\tmissingOptionValue,\n\t\tconflictingOptions,\n\t};\n}\n\nfunction updateTargetIncludesSelf(target: UpdateTarget): boolean {\n\treturn target.type === \"all\" || target.type === \"self\";\n}\n\nfunction updateTargetIncludesExtensions(target: UpdateTarget): boolean {\n\treturn target.type === \"all\" || target.type === \"extensions\";\n}\n\nfunction printSelfUpdateUnavailable(npmCommand?: string[], updatePackageName = PACKAGE_NAME): void {\n\tconsole.error(`error: ${APP_NAME} cannot self-update this installation.`);\n\tconsole.error(getSelfUpdateUnavailableInstruction(PACKAGE_NAME, npmCommand, updatePackageName));\n\n\tconst entrypoint = process.argv[1];\n\tif (entrypoint) {\n\t\tconsole.error(\"\");\n\t\tconsole.error(`Location of pi executable: ${entrypoint}`);\n\t}\n}\n\nfunction printSelfUpdateFallback(command: SelfUpdateCommand): void {\n\tconsole.error(chalk.dim(`If this keeps failing, run this command yourself: ${command.display}`));\n}\n\ninterface SelfUpdatePlan {\n\tpackageName: string;\n\tshouldRun: boolean;\n}\n\nasync function getSelfUpdatePlan(force: boolean): Promise<SelfUpdatePlan> {\n\tif (force) {\n\t\treturn { packageName: PACKAGE_NAME, shouldRun: true };\n\t}\n\n\ttry {\n\t\tconst latestRelease = await getLatestPiRelease(VERSION);\n\t\tconst packageName = latestRelease?.packageName ?? PACKAGE_NAME;\n\t\tif (!latestRelease || packageName !== PACKAGE_NAME || isNewerPackageVersion(latestRelease.version, VERSION)) {\n\t\t\treturn { packageName, shouldRun: true };\n\t\t}\n\t} catch {\n\t\treturn { packageName: PACKAGE_NAME, shouldRun: true };\n\t}\n\n\tconsole.log(chalk.green(`${APP_NAME} is already up to date (v${VERSION})`));\n\treturn { packageName: PACKAGE_NAME, shouldRun: false };\n}\n\nasync function runSelfUpdate(command: SelfUpdateCommand): Promise<void> {\n\tconsole.log(chalk.dim(`Updating ${APP_NAME} with ${command.display}...`));\n\tfor (const step of command.steps ?? [command]) {\n\t\tawait new Promise<void>((resolve, reject) => {\n\t\t\t// Windows package managers are commonly .cmd shims. Use the shell so Node can execute them.\n\t\t\tconst child = spawn(step.command, step.args, {\n\t\t\t\tstdio: \"inherit\",\n\t\t\t\tshell: shouldUseWindowsShell(step.command),\n\t\t\t});\n\t\t\tchild.on(\"error\", (error) => {\n\t\t\t\treject(error);\n\t\t\t});\n\t\t\tchild.on(\"close\", (code, signal) => {\n\t\t\t\tif (code === 0) {\n\t\t\t\t\tresolve();\n\t\t\t\t} else if (signal) {\n\t\t\t\t\treject(new Error(`${step.display} terminated by signal ${signal}`));\n\t\t\t\t} else {\n\t\t\t\t\treject(new Error(`${step.display} exited with code ${code ?? \"unknown\"}`));\n\t\t\t\t}\n\t\t\t});\n\t\t});\n\t}\n}\n\nexport async function handleConfigCommand(args: string[]): Promise<boolean> {\n\tif (args[0] !== \"config\") {\n\t\treturn false;\n\t}\n\n\tconst cwd = process.cwd();\n\tconst agentDir = getAgentDir();\n\tconst settingsManager = SettingsManager.create(cwd, agentDir);\n\treportSettingsErrors(settingsManager, \"config command\");\n\tconst packageManager = new DefaultPackageManager({ cwd, agentDir, settingsManager });\n\tconst resolvedPaths = await packageManager.resolve();\n\n\tawait selectConfig({\n\t\tresolvedPaths,\n\t\tsettingsManager,\n\t\tcwd,\n\t\tagentDir,\n\t});\n\n\tprocess.exit(0);\n}\n\nexport async function handlePackageCommand(args: string[]): Promise<boolean> {\n\tconst options = parsePackageCommand(args);\n\tif (!options) {\n\t\treturn false;\n\t}\n\n\tif (options.help) {\n\t\tprintPackageCommandHelp(options.command);\n\t\treturn true;\n\t}\n\n\tif (options.invalidOption) {\n\t\tconsole.error(chalk.red(`Unknown option ${options.invalidOption} for \"${options.command}\".`));\n\t\tconsole.error(chalk.dim(`Use \"${APP_NAME} --help\" or \"${getPackageCommandUsage(options.command)}\".`));\n\t\tprocess.exitCode = 1;\n\t\treturn true;\n\t}\n\n\tif (options.missingOptionValue) {\n\t\tconsole.error(chalk.red(`Missing value for ${options.missingOptionValue}.`));\n\t\tconsole.error(chalk.dim(`Usage: ${getPackageCommandUsage(options.command)}`));\n\t\tprocess.exitCode = 1;\n\t\treturn true;\n\t}\n\n\tif (options.invalidArgument) {\n\t\tconsole.error(chalk.red(`Unexpected argument ${options.invalidArgument}.`));\n\t\tconsole.error(chalk.dim(`Usage: ${getPackageCommandUsage(options.command)}`));\n\t\tprocess.exitCode = 1;\n\t\treturn true;\n\t}\n\n\tif (options.conflictingOptions) {\n\t\tconsole.error(chalk.red(options.conflictingOptions));\n\t\tconsole.error(chalk.dim(`Usage: ${getPackageCommandUsage(options.command)}`));\n\t\tprocess.exitCode = 1;\n\t\treturn true;\n\t}\n\n\tconst source = options.source;\n\tif ((options.command === \"install\" || options.command === \"remove\") && !source) {\n\t\tconsole.error(chalk.red(`Missing ${options.command} source.`));\n\t\tconsole.error(chalk.dim(`Usage: ${getPackageCommandUsage(options.command)}`));\n\t\tprocess.exitCode = 1;\n\t\treturn true;\n\t}\n\n\tconst cwd = process.cwd();\n\tconst agentDir = getAgentDir();\n\tconst settingsManager = SettingsManager.create(cwd, agentDir);\n\treportSettingsErrors(settingsManager, \"package command\");\n\tconst selfUpdateNpmCommand = settingsManager.getGlobalSettings().npmCommand;\n\n\tconst packageManager = new DefaultPackageManager({ cwd, agentDir, settingsManager });\n\n\tpackageManager.setProgressCallback((event) => {\n\t\tif (event.type === \"start\") {\n\t\t\tprocess.stdout.write(chalk.dim(`${event.message}\\n`));\n\t\t}\n\t});\n\n\ttry {\n\t\tswitch (options.command) {\n\t\t\tcase \"install\":\n\t\t\t\tawait packageManager.installAndPersist(source!, { local: options.local });\n\t\t\t\tconsole.log(chalk.green(`Installed ${source}`));\n\t\t\t\treturn true;\n\n\t\t\tcase \"remove\": {\n\t\t\t\tconst removed = await packageManager.removeAndPersist(source!, { local: options.local });\n\t\t\t\tif (!removed) {\n\t\t\t\t\tconsole.error(chalk.red(`No matching package found for ${source}`));\n\t\t\t\t\tprocess.exitCode = 1;\n\t\t\t\t\treturn true;\n\t\t\t\t}\n\t\t\t\tconsole.log(chalk.green(`Removed ${source}`));\n\t\t\t\treturn true;\n\t\t\t}\n\n\t\t\tcase \"list\": {\n\t\t\t\tconst configuredPackages = packageManager.listConfiguredPackages();\n\t\t\t\tconst userPackages = configuredPackages.filter((pkg) => pkg.scope === \"user\");\n\t\t\t\tconst projectPackages = configuredPackages.filter((pkg) => pkg.scope === \"project\");\n\n\t\t\t\tif (configuredPackages.length === 0) {\n\t\t\t\t\tconsole.log(chalk.dim(\"No packages installed.\"));\n\t\t\t\t\treturn true;\n\t\t\t\t}\n\n\t\t\t\tconst formatPackage = (pkg: (typeof configuredPackages)[number]) => {\n\t\t\t\t\tconst display = pkg.filtered ? `${pkg.source} (filtered)` : pkg.source;\n\t\t\t\t\tconsole.log(` ${display}`);\n\t\t\t\t\tif (pkg.installedPath) {\n\t\t\t\t\t\tconsole.log(chalk.dim(` ${pkg.installedPath}`));\n\t\t\t\t\t}\n\t\t\t\t};\n\n\t\t\t\tif (userPackages.length > 0) {\n\t\t\t\t\tconsole.log(chalk.bold(\"User packages:\"));\n\t\t\t\t\tfor (const pkg of userPackages) {\n\t\t\t\t\t\tformatPackage(pkg);\n\t\t\t\t\t}\n\t\t\t\t}\n\n\t\t\t\tif (projectPackages.length > 0) {\n\t\t\t\t\tif (userPackages.length > 0) console.log();\n\t\t\t\t\tconsole.log(chalk.bold(\"Project packages:\"));\n\t\t\t\t\tfor (const pkg of projectPackages) {\n\t\t\t\t\t\tformatPackage(pkg);\n\t\t\t\t\t}\n\t\t\t\t}\n\n\t\t\t\treturn true;\n\t\t\t}\n\n\t\t\tcase \"update\": {\n\t\t\t\tconst target = options.updateTarget ?? { type: \"all\" };\n\t\t\t\tif (updateTargetIncludesExtensions(target)) {\n\t\t\t\t\tconst updateSource = target.type === \"extensions\" ? target.source : undefined;\n\t\t\t\t\tawait packageManager.update(updateSource);\n\t\t\t\t\tif (updateSource) {\n\t\t\t\t\t\tconsole.log(chalk.green(`Updated ${updateSource}`));\n\t\t\t\t\t} else {\n\t\t\t\t\t\tconsole.log(chalk.green(\"Updated packages\"));\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\tif (updateTargetIncludesSelf(target)) {\n\t\t\t\t\tconst selfUpdatePlan = await getSelfUpdatePlan(options.force);\n\t\t\t\t\tif (!selfUpdatePlan.shouldRun) {\n\t\t\t\t\t\treturn true;\n\t\t\t\t\t}\n\t\t\t\t\tconst selfUpdateCommand = getSelfUpdateCommand(\n\t\t\t\t\t\tPACKAGE_NAME,\n\t\t\t\t\t\tselfUpdateNpmCommand,\n\t\t\t\t\t\tselfUpdatePlan.packageName,\n\t\t\t\t\t);\n\t\t\t\t\tif (!selfUpdateCommand) {\n\t\t\t\t\t\tprintSelfUpdateUnavailable(selfUpdateNpmCommand, selfUpdatePlan.packageName);\n\t\t\t\t\t\tprocess.exitCode = 1;\n\t\t\t\t\t\treturn true;\n\t\t\t\t\t}\n\t\t\t\t\ttry {\n\t\t\t\t\t\tawait runSelfUpdate(selfUpdateCommand);\n\t\t\t\t\t} catch (error: unknown) {\n\t\t\t\t\t\tconst message = error instanceof Error ? error.message : \"Unknown package command error\";\n\t\t\t\t\t\tconsole.error(chalk.red(`Error: ${message}`));\n\t\t\t\t\t\tprintSelfUpdateFallback(selfUpdateCommand);\n\t\t\t\t\t\tprocess.exitCode = 1;\n\t\t\t\t\t\treturn true;\n\t\t\t\t\t}\n\t\t\t\t\tconsole.log(chalk.green(`Updated ${APP_NAME}`));\n\t\t\t\t}\n\t\t\t\treturn true;\n\t\t\t}\n\t\t}\n\t} catch (error: unknown) {\n\t\tconst message = error instanceof Error ? error.message : \"Unknown package command error\";\n\t\tconsole.error(chalk.red(`Error: ${message}`));\n\t\tprocess.exitCode = 1;\n\t\treturn true;\n\t}\n}\n"]}
1
+ {"version":3,"file":"package-manager-cli.d.ts","sourceRoot":"","sources":["../src/package-manager-cli.ts"],"names":[],"mappings":"AAuBA,MAAM,MAAM,cAAc,GAAG,SAAS,GAAG,QAAQ,GAAG,QAAQ,GAAG,MAAM,CAAC;AAgXtE,wBAAsB,mBAAmB,CAAC,IAAI,EAAE,MAAM,EAAE,GAAG,OAAO,CAAC,OAAO,CAAC,CAoB1E;AAED,wBAAsB,oBAAoB,CAAC,IAAI,EAAE,MAAM,EAAE,GAAG,OAAO,CAAC,OAAO,CAAC,CAgL3E","sourcesContent":["import { Markdown, type MarkdownTheme } from \"@sheason/pi-tui\";\nimport chalk from \"chalk\";\nimport { selectConfig } from \"./cli/config-selector.ts\";\nimport {\n\tAPP_NAME,\n\tdetectInstallMethod,\n\tgetAgentDir,\n\tgetPackageDir,\n\tgetSelfUpdateCommand,\n\tgetSelfUpdateUnavailableInstruction,\n\tPACKAGE_NAME,\n\ttype SelfUpdateCommand,\n\tVERSION,\n} from \"./config.ts\";\nimport { DefaultPackageManager } from \"./core/package-manager.ts\";\nimport { SettingsManager } from \"./core/settings-manager.ts\";\nimport { spawnProcess } from \"./utils/child-process.ts\";\nimport { getLatestPiRelease, isNewerPackageVersion } from \"./utils/version-check.ts\";\nimport {\n\tcleanupWindowsSelfUpdateQuarantine,\n\tquarantineWindowsNativeDependencies,\n} from \"./utils/windows-self-update.ts\";\n\nexport type PackageCommand = \"install\" | \"remove\" | \"update\" | \"list\";\n\ntype UpdateTarget = { type: \"all\" } | { type: \"self\" } | { type: \"extensions\"; source?: string };\n\nconst SELF_UPDATE_NOTE_MARKDOWN_THEME: MarkdownTheme = {\n\theading: (text) => chalk.bold(chalk.yellow(text)),\n\tlink: (text) => chalk.cyan(text),\n\tlinkUrl: (text) => chalk.dim(text),\n\tcode: (text) => chalk.yellow(text),\n\tcodeBlock: (text) => chalk.dim(text),\n\tcodeBlockBorder: (text) => chalk.dim(text),\n\tquote: (text) => chalk.dim(text),\n\tquoteBorder: (text) => chalk.dim(text),\n\thr: (text) => chalk.dim(text),\n\tlistBullet: (text) => chalk.yellow(text),\n\tbold: (text) => chalk.bold(text),\n\titalic: (text) => chalk.italic(text),\n\tstrikethrough: (text) => chalk.strikethrough(text),\n\tunderline: (text) => chalk.underline(text),\n};\n\ninterface PackageCommandOptions {\n\tcommand: PackageCommand;\n\tsource?: string;\n\tupdateTarget?: UpdateTarget;\n\tlocal: boolean;\n\tforce: boolean;\n\thelp: boolean;\n\tinvalidOption?: string;\n\tinvalidArgument?: string;\n\tmissingOptionValue?: string;\n\tconflictingOptions?: string;\n}\n\nfunction reportSettingsErrors(settingsManager: SettingsManager, context: string): void {\n\tconst errors = settingsManager.drainErrors();\n\tfor (const { scope, error } of errors) {\n\t\tconsole.error(chalk.yellow(`Warning (${context}, ${scope} settings): ${error.message}`));\n\t\tif (error.stack) {\n\t\t\tconsole.error(chalk.dim(error.stack));\n\t\t}\n\t}\n}\n\nfunction getPackageCommandUsage(command: PackageCommand): string {\n\tswitch (command) {\n\t\tcase \"install\":\n\t\t\treturn `${APP_NAME} install <source> [-l]`;\n\t\tcase \"remove\":\n\t\t\treturn `${APP_NAME} remove <source> [-l]`;\n\t\tcase \"update\":\n\t\t\treturn `${APP_NAME} update [source|self|pi] [--self] [--extensions] [--extension <source>] [--force]`;\n\t\tcase \"list\":\n\t\t\treturn `${APP_NAME} list`;\n\t}\n}\n\nfunction printPackageCommandHelp(command: PackageCommand): void {\n\tswitch (command) {\n\t\tcase \"install\":\n\t\t\tconsole.log(`${chalk.bold(\"Usage:\")}\n ${getPackageCommandUsage(\"install\")}\n\nInstall a package and add it to settings.\n\nOptions:\n -l, --local Install project-locally (.pi/settings.json)\n\nExamples:\n ${APP_NAME} install npm:@foo/bar\n ${APP_NAME} install git:github.com/user/repo\n ${APP_NAME} install git:git@github.com:user/repo\n ${APP_NAME} install https://github.com/user/repo\n ${APP_NAME} install ssh://git@github.com/user/repo\n ${APP_NAME} install ./local/path\n`);\n\t\t\treturn;\n\n\t\tcase \"remove\":\n\t\t\tconsole.log(`${chalk.bold(\"Usage:\")}\n ${getPackageCommandUsage(\"remove\")}\n\nRemove a package and its source from settings.\nAlias: ${APP_NAME} uninstall <source> [-l]\n\nOptions:\n -l, --local Remove from project settings (.pi/settings.json)\n\nExamples:\n ${APP_NAME} remove npm:@foo/bar\n ${APP_NAME} uninstall npm:@foo/bar\n`);\n\t\t\treturn;\n\n\t\tcase \"update\":\n\t\t\tconsole.log(`${chalk.bold(\"Usage:\")}\n ${getPackageCommandUsage(\"update\")}\n\nUpdate pi and installed packages.\n\nOptions:\n --self Update pi only\n --extensions Update installed packages only\n --extension <source> Update one package only\n --force Reinstall pi even if the current version is latest\n\nShort forms:\n ${APP_NAME} update Update pi and all extensions\n ${APP_NAME} update <source> Update one package\n ${APP_NAME} update pi Update pi only (self works as alias to pi)\n`);\n\t\t\treturn;\n\n\t\tcase \"list\":\n\t\t\tconsole.log(`${chalk.bold(\"Usage:\")}\n ${getPackageCommandUsage(\"list\")}\n\nList installed packages from user and project settings.\n`);\n\t\t\treturn;\n\t}\n}\n\nfunction parsePackageCommand(args: string[]): PackageCommandOptions | undefined {\n\tconst [rawCommand, ...rest] = args;\n\tlet command: PackageCommand | undefined;\n\tif (rawCommand === \"uninstall\") {\n\t\tcommand = \"remove\";\n\t} else if (rawCommand === \"install\" || rawCommand === \"remove\" || rawCommand === \"update\" || rawCommand === \"list\") {\n\t\tcommand = rawCommand;\n\t}\n\tif (!command) {\n\t\treturn undefined;\n\t}\n\n\tlet local = false;\n\tlet force = false;\n\tlet help = false;\n\tlet invalidOption: string | undefined;\n\tlet invalidArgument: string | undefined;\n\tlet missingOptionValue: string | undefined;\n\tlet conflictingOptions: string | undefined;\n\tlet source: string | undefined;\n\tlet selfFlag = false;\n\tlet extensionsFlag = false;\n\tlet extensionFlagSource: string | undefined;\n\n\tfor (let index = 0; index < rest.length; index++) {\n\t\tconst arg = rest[index];\n\t\tif (arg === \"-h\" || arg === \"--help\") {\n\t\t\thelp = true;\n\t\t\tcontinue;\n\t\t}\n\n\t\tif (arg === \"-l\" || arg === \"--local\") {\n\t\t\tif (command === \"install\" || command === \"remove\") {\n\t\t\t\tlocal = true;\n\t\t\t} else {\n\t\t\t\tinvalidOption = invalidOption ?? arg;\n\t\t\t}\n\t\t\tcontinue;\n\t\t}\n\n\t\tif (arg === \"--self\") {\n\t\t\tif (command === \"update\") {\n\t\t\t\tselfFlag = true;\n\t\t\t} else {\n\t\t\t\tinvalidOption = invalidOption ?? arg;\n\t\t\t}\n\t\t\tcontinue;\n\t\t}\n\n\t\tif (arg === \"--extensions\") {\n\t\t\tif (command === \"update\") {\n\t\t\t\textensionsFlag = true;\n\t\t\t} else {\n\t\t\t\tinvalidOption = invalidOption ?? arg;\n\t\t\t}\n\t\t\tcontinue;\n\t\t}\n\n\t\tif (arg === \"--force\") {\n\t\t\tif (command === \"update\") {\n\t\t\t\tforce = true;\n\t\t\t} else {\n\t\t\t\tinvalidOption = invalidOption ?? arg;\n\t\t\t}\n\t\t\tcontinue;\n\t\t}\n\n\t\tif (arg === \"--extension\") {\n\t\t\tif (command !== \"update\") {\n\t\t\t\tinvalidOption = invalidOption ?? arg;\n\t\t\t\tcontinue;\n\t\t\t}\n\n\t\t\tconst value = rest[index + 1];\n\t\t\tif (!value || value.startsWith(\"-\")) {\n\t\t\t\tmissingOptionValue = missingOptionValue ?? arg;\n\t\t\t} else if (extensionFlagSource) {\n\t\t\t\tconflictingOptions = conflictingOptions ?? \"--extension can only be provided once\";\n\t\t\t\tindex++;\n\t\t\t} else {\n\t\t\t\textensionFlagSource = value;\n\t\t\t\tindex++;\n\t\t\t}\n\t\t\tcontinue;\n\t\t}\n\n\t\tif (arg.startsWith(\"-\")) {\n\t\t\tinvalidOption = invalidOption ?? arg;\n\t\t\tcontinue;\n\t\t}\n\n\t\tif (!source) {\n\t\t\tsource = arg;\n\t\t} else {\n\t\t\tinvalidArgument = invalidArgument ?? arg;\n\t\t}\n\t}\n\n\tlet updateTarget: UpdateTarget | undefined;\n\tif (command === \"update\") {\n\t\tif (extensionFlagSource) {\n\t\t\tif (selfFlag || extensionsFlag) {\n\t\t\t\tconflictingOptions = conflictingOptions ?? \"--extension cannot be combined with --self or --extensions\";\n\t\t\t}\n\t\t\tif (source) {\n\t\t\t\tconflictingOptions = conflictingOptions ?? \"--extension cannot be combined with a positional source\";\n\t\t\t}\n\t\t\tupdateTarget = { type: \"extensions\", source: extensionFlagSource };\n\t\t} else if (source) {\n\t\t\tconst sourceIsSelf = source === \"self\" || source === \"pi\";\n\t\t\tif (sourceIsSelf) {\n\t\t\t\tupdateTarget = extensionsFlag ? { type: \"all\" } : { type: \"self\" };\n\t\t\t} else {\n\t\t\t\tif (extensionsFlag || selfFlag) {\n\t\t\t\t\tconflictingOptions =\n\t\t\t\t\t\tconflictingOptions ?? \"positional update targets cannot be combined with --self or --extensions\";\n\t\t\t\t}\n\t\t\t\tupdateTarget = { type: \"extensions\", source };\n\t\t\t}\n\t\t} else if (selfFlag && extensionsFlag) {\n\t\t\tupdateTarget = { type: \"all\" };\n\t\t} else if (selfFlag) {\n\t\t\tupdateTarget = { type: \"self\" };\n\t\t} else if (extensionsFlag) {\n\t\t\tupdateTarget = { type: \"extensions\" };\n\t\t} else {\n\t\t\tupdateTarget = { type: \"all\" };\n\t\t}\n\t}\n\n\treturn {\n\t\tcommand,\n\t\tsource,\n\t\tupdateTarget,\n\t\tlocal,\n\t\tforce,\n\t\thelp,\n\t\tinvalidOption,\n\t\tinvalidArgument,\n\t\tmissingOptionValue,\n\t\tconflictingOptions,\n\t};\n}\n\nfunction updateTargetIncludesSelf(target: UpdateTarget): boolean {\n\treturn target.type === \"all\" || target.type === \"self\";\n}\n\nfunction updateTargetIncludesExtensions(target: UpdateTarget): boolean {\n\treturn target.type === \"all\" || target.type === \"extensions\";\n}\n\nfunction printSelfUpdateUnavailable(npmCommand?: string[], updatePackageName = PACKAGE_NAME): void {\n\tconsole.error(`error: ${APP_NAME} cannot self-update this installation.`);\n\tconsole.error(getSelfUpdateUnavailableInstruction(PACKAGE_NAME, npmCommand, updatePackageName));\n\n\tconst entrypoint = process.argv[1];\n\tif (entrypoint) {\n\t\tconsole.error(\"\");\n\t\tconsole.error(`Location of pi executable: ${entrypoint}`);\n\t}\n}\n\nfunction printSelfUpdateFallback(command: SelfUpdateCommand): void {\n\tconsole.error(chalk.dim(`If this keeps failing, run this command yourself: ${command.display}`));\n}\n\nfunction printSelfUpdateNote(note: string): void {\n\tconst trimmedNote = note.trim();\n\tif (!trimmedNote) {\n\t\treturn;\n\t}\n\n\tconsole.log();\n\tconsole.log(chalk.bold(chalk.yellow(\"Update note\")));\n\ttry {\n\t\tconst width = Math.max(20, process.stdout.columns ?? 80);\n\t\tconst renderedLines = new Markdown(trimmedNote, 0, 0, SELF_UPDATE_NOTE_MARKDOWN_THEME)\n\t\t\t.render(width)\n\t\t\t.map((line) => line.trimEnd());\n\t\tconsole.log(renderedLines.join(\"\\n\"));\n\t} catch {\n\t\tconsole.log(trimmedNote);\n\t}\n\tconsole.log();\n}\n\ninterface SelfUpdatePlan {\n\tpackageName: string;\n\tshouldRun: boolean;\n\tnote?: string;\n}\n\nasync function getSelfUpdatePlan(force: boolean): Promise<SelfUpdatePlan> {\n\tif (force) {\n\t\treturn { packageName: PACKAGE_NAME, shouldRun: true };\n\t}\n\n\ttry {\n\t\tconst latestRelease = await getLatestPiRelease(VERSION);\n\t\tconst packageName = latestRelease?.packageName ?? PACKAGE_NAME;\n\t\tif (!latestRelease || packageName !== PACKAGE_NAME || isNewerPackageVersion(latestRelease.version, VERSION)) {\n\t\t\treturn { packageName, shouldRun: true, ...(latestRelease?.note ? { note: latestRelease.note } : {}) };\n\t\t}\n\t} catch {\n\t\treturn { packageName: PACKAGE_NAME, shouldRun: true };\n\t}\n\n\tconsole.log(chalk.green(`${APP_NAME} is already up to date (v${VERSION})`));\n\treturn { packageName: PACKAGE_NAME, shouldRun: false };\n}\n\nasync function runSelfUpdate(command: SelfUpdateCommand): Promise<void> {\n\tconsole.log(chalk.dim(`Updating ${APP_NAME} with ${command.display}...`));\n\tfor (const step of command.steps ?? [command]) {\n\t\tawait new Promise<void>((resolve, reject) => {\n\t\t\tconst child = spawnProcess(step.command, step.args, {\n\t\t\t\tstdio: \"inherit\",\n\t\t\t});\n\t\t\tchild.on(\"error\", (error) => {\n\t\t\t\treject(error);\n\t\t\t});\n\t\t\tchild.on(\"close\", (code, signal) => {\n\t\t\t\tif (code === 0) {\n\t\t\t\t\tresolve();\n\t\t\t\t} else if (signal) {\n\t\t\t\t\treject(new Error(`${step.display} terminated by signal ${signal}`));\n\t\t\t\t} else {\n\t\t\t\t\treject(new Error(`${step.display} exited with code ${code ?? \"unknown\"}`));\n\t\t\t\t}\n\t\t\t});\n\t\t});\n\t}\n}\n\nfunction prepareWindowsNpmSelfUpdate(): void {\n\tif (process.platform !== \"win32\") {\n\t\treturn;\n\t}\n\n\tconst packageDir = getPackageDir();\n\tcleanupWindowsSelfUpdateQuarantine(packageDir);\n\tquarantineWindowsNativeDependencies(packageDir);\n}\n\nexport async function handleConfigCommand(args: string[]): Promise<boolean> {\n\tif (args[0] !== \"config\") {\n\t\treturn false;\n\t}\n\n\tconst cwd = process.cwd();\n\tconst agentDir = getAgentDir();\n\tconst settingsManager = SettingsManager.create(cwd, agentDir);\n\treportSettingsErrors(settingsManager, \"config command\");\n\tconst packageManager = new DefaultPackageManager({ cwd, agentDir, settingsManager });\n\tconst resolvedPaths = await packageManager.resolve();\n\n\tawait selectConfig({\n\t\tresolvedPaths,\n\t\tsettingsManager,\n\t\tcwd,\n\t\tagentDir,\n\t});\n\n\tprocess.exit(0);\n}\n\nexport async function handlePackageCommand(args: string[]): Promise<boolean> {\n\tconst options = parsePackageCommand(args);\n\tif (!options) {\n\t\treturn false;\n\t}\n\n\tif (options.help) {\n\t\tprintPackageCommandHelp(options.command);\n\t\treturn true;\n\t}\n\n\tif (options.invalidOption) {\n\t\tconsole.error(chalk.red(`Unknown option ${options.invalidOption} for \"${options.command}\".`));\n\t\tconsole.error(chalk.dim(`Use \"${APP_NAME} --help\" or \"${getPackageCommandUsage(options.command)}\".`));\n\t\tprocess.exitCode = 1;\n\t\treturn true;\n\t}\n\n\tif (options.missingOptionValue) {\n\t\tconsole.error(chalk.red(`Missing value for ${options.missingOptionValue}.`));\n\t\tconsole.error(chalk.dim(`Usage: ${getPackageCommandUsage(options.command)}`));\n\t\tprocess.exitCode = 1;\n\t\treturn true;\n\t}\n\n\tif (options.invalidArgument) {\n\t\tconsole.error(chalk.red(`Unexpected argument ${options.invalidArgument}.`));\n\t\tconsole.error(chalk.dim(`Usage: ${getPackageCommandUsage(options.command)}`));\n\t\tprocess.exitCode = 1;\n\t\treturn true;\n\t}\n\n\tif (options.conflictingOptions) {\n\t\tconsole.error(chalk.red(options.conflictingOptions));\n\t\tconsole.error(chalk.dim(`Usage: ${getPackageCommandUsage(options.command)}`));\n\t\tprocess.exitCode = 1;\n\t\treturn true;\n\t}\n\n\tconst source = options.source;\n\tif ((options.command === \"install\" || options.command === \"remove\") && !source) {\n\t\tconsole.error(chalk.red(`Missing ${options.command} source.`));\n\t\tconsole.error(chalk.dim(`Usage: ${getPackageCommandUsage(options.command)}`));\n\t\tprocess.exitCode = 1;\n\t\treturn true;\n\t}\n\n\tconst cwd = process.cwd();\n\tconst agentDir = getAgentDir();\n\tconst settingsManager = SettingsManager.create(cwd, agentDir);\n\treportSettingsErrors(settingsManager, \"package command\");\n\tconst selfUpdateNpmCommand = settingsManager.getGlobalSettings().npmCommand;\n\n\tconst packageManager = new DefaultPackageManager({ cwd, agentDir, settingsManager });\n\n\tpackageManager.setProgressCallback((event) => {\n\t\tif (event.type === \"start\") {\n\t\t\tprocess.stdout.write(chalk.dim(`${event.message}\\n`));\n\t\t}\n\t});\n\n\ttry {\n\t\tswitch (options.command) {\n\t\t\tcase \"install\":\n\t\t\t\tawait packageManager.installAndPersist(source!, { local: options.local });\n\t\t\t\tconsole.log(chalk.green(`Installed ${source}`));\n\t\t\t\treturn true;\n\n\t\t\tcase \"remove\": {\n\t\t\t\tconst removed = await packageManager.removeAndPersist(source!, { local: options.local });\n\t\t\t\tif (!removed) {\n\t\t\t\t\tconsole.error(chalk.red(`No matching package found for ${source}`));\n\t\t\t\t\tprocess.exitCode = 1;\n\t\t\t\t\treturn true;\n\t\t\t\t}\n\t\t\t\tconsole.log(chalk.green(`Removed ${source}`));\n\t\t\t\treturn true;\n\t\t\t}\n\n\t\t\tcase \"list\": {\n\t\t\t\tconst configuredPackages = packageManager.listConfiguredPackages();\n\t\t\t\tconst userPackages = configuredPackages.filter((pkg) => pkg.scope === \"user\");\n\t\t\t\tconst projectPackages = configuredPackages.filter((pkg) => pkg.scope === \"project\");\n\n\t\t\t\tif (configuredPackages.length === 0) {\n\t\t\t\t\tconsole.log(chalk.dim(\"No packages installed.\"));\n\t\t\t\t\treturn true;\n\t\t\t\t}\n\n\t\t\t\tconst formatPackage = (pkg: (typeof configuredPackages)[number]) => {\n\t\t\t\t\tconst display = pkg.filtered ? `${pkg.source} (filtered)` : pkg.source;\n\t\t\t\t\tconsole.log(` ${display}`);\n\t\t\t\t\tif (pkg.installedPath) {\n\t\t\t\t\t\tconsole.log(chalk.dim(` ${pkg.installedPath}`));\n\t\t\t\t\t}\n\t\t\t\t};\n\n\t\t\t\tif (userPackages.length > 0) {\n\t\t\t\t\tconsole.log(chalk.bold(\"User packages:\"));\n\t\t\t\t\tfor (const pkg of userPackages) {\n\t\t\t\t\t\tformatPackage(pkg);\n\t\t\t\t\t}\n\t\t\t\t}\n\n\t\t\t\tif (projectPackages.length > 0) {\n\t\t\t\t\tif (userPackages.length > 0) console.log();\n\t\t\t\t\tconsole.log(chalk.bold(\"Project packages:\"));\n\t\t\t\t\tfor (const pkg of projectPackages) {\n\t\t\t\t\t\tformatPackage(pkg);\n\t\t\t\t\t}\n\t\t\t\t}\n\n\t\t\t\treturn true;\n\t\t\t}\n\n\t\t\tcase \"update\": {\n\t\t\t\tconst target = options.updateTarget ?? { type: \"all\" };\n\t\t\t\tif (updateTargetIncludesExtensions(target)) {\n\t\t\t\t\tconst updateSource = target.type === \"extensions\" ? target.source : undefined;\n\t\t\t\t\tawait packageManager.update(updateSource);\n\t\t\t\t\tif (updateSource) {\n\t\t\t\t\t\tconsole.log(chalk.green(`Updated ${updateSource}`));\n\t\t\t\t\t} else {\n\t\t\t\t\t\tconsole.log(chalk.green(\"Updated packages\"));\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\tif (updateTargetIncludesSelf(target)) {\n\t\t\t\t\tconst selfUpdatePlan = await getSelfUpdatePlan(options.force);\n\t\t\t\t\tif (!selfUpdatePlan.shouldRun) {\n\t\t\t\t\t\treturn true;\n\t\t\t\t\t}\n\t\t\t\t\tconst installMethod = detectInstallMethod();\n\t\t\t\t\tif (process.platform === \"win32\" && installMethod !== \"npm\" && installMethod !== \"pnpm\") {\n\t\t\t\t\t\tconsole.error(\n\t\t\t\t\t\t\tchalk.red(`${APP_NAME} self-update on Windows is only supported for npm and pnpm installs.`),\n\t\t\t\t\t\t);\n\t\t\t\t\t\tconsole.error(chalk.dim(`Detected install method: ${installMethod}. Update ${APP_NAME} manually.`));\n\t\t\t\t\t\tprocess.exitCode = 1;\n\t\t\t\t\t\treturn true;\n\t\t\t\t\t}\n\t\t\t\t\tconst selfUpdateCommand = getSelfUpdateCommand(\n\t\t\t\t\t\tPACKAGE_NAME,\n\t\t\t\t\t\tselfUpdateNpmCommand,\n\t\t\t\t\t\tselfUpdatePlan.packageName,\n\t\t\t\t\t);\n\t\t\t\t\tif (!selfUpdateCommand) {\n\t\t\t\t\t\tprintSelfUpdateUnavailable(selfUpdateNpmCommand, selfUpdatePlan.packageName);\n\t\t\t\t\t\tprocess.exitCode = 1;\n\t\t\t\t\t\treturn true;\n\t\t\t\t\t}\n\t\t\t\t\tif (selfUpdatePlan.note) {\n\t\t\t\t\t\tprintSelfUpdateNote(selfUpdatePlan.note);\n\t\t\t\t\t}\n\t\t\t\t\ttry {\n\t\t\t\t\t\tif (installMethod === \"npm\") {\n\t\t\t\t\t\t\tprepareWindowsNpmSelfUpdate();\n\t\t\t\t\t\t}\n\t\t\t\t\t\tawait runSelfUpdate(selfUpdateCommand);\n\t\t\t\t\t} catch (error: unknown) {\n\t\t\t\t\t\tconst message = error instanceof Error ? error.message : \"Unknown package command error\";\n\t\t\t\t\t\tconsole.error(chalk.red(`Error: ${message}`));\n\t\t\t\t\t\tprintSelfUpdateFallback(selfUpdateCommand);\n\t\t\t\t\t\tprocess.exitCode = 1;\n\t\t\t\t\t\treturn true;\n\t\t\t\t\t}\n\t\t\t\t\tconsole.log(chalk.green(`Updated ${APP_NAME}`));\n\t\t\t\t}\n\t\t\t\treturn true;\n\t\t\t}\n\t\t}\n\t} catch (error: unknown) {\n\t\tconst message = error instanceof Error ? error.message : \"Unknown package command error\";\n\t\tconsole.error(chalk.red(`Error: ${message}`));\n\t\tprocess.exitCode = 1;\n\t\treturn true;\n\t}\n}\n"]}
@@ -1,11 +1,28 @@
1
+ import { Markdown } from "@sheason/pi-tui";
1
2
  import chalk from "chalk";
2
- import { spawn } from "child_process";
3
3
  import { selectConfig } from "./cli/config-selector.js";
4
- import { APP_NAME, getAgentDir, getSelfUpdateCommand, getSelfUpdateUnavailableInstruction, PACKAGE_NAME, VERSION, } from "./config.js";
4
+ import { APP_NAME, detectInstallMethod, getAgentDir, getPackageDir, getSelfUpdateCommand, getSelfUpdateUnavailableInstruction, PACKAGE_NAME, VERSION, } from "./config.js";
5
5
  import { DefaultPackageManager } from "./core/package-manager.js";
6
6
  import { SettingsManager } from "./core/settings-manager.js";
7
- import { shouldUseWindowsShell } from "./utils/child-process.js";
7
+ import { spawnProcess } from "./utils/child-process.js";
8
8
  import { getLatestPiRelease, isNewerPackageVersion } from "./utils/version-check.js";
9
+ import { cleanupWindowsSelfUpdateQuarantine, quarantineWindowsNativeDependencies, } from "./utils/windows-self-update.js";
10
+ const SELF_UPDATE_NOTE_MARKDOWN_THEME = {
11
+ heading: (text) => chalk.bold(chalk.yellow(text)),
12
+ link: (text) => chalk.cyan(text),
13
+ linkUrl: (text) => chalk.dim(text),
14
+ code: (text) => chalk.yellow(text),
15
+ codeBlock: (text) => chalk.dim(text),
16
+ codeBlockBorder: (text) => chalk.dim(text),
17
+ quote: (text) => chalk.dim(text),
18
+ quoteBorder: (text) => chalk.dim(text),
19
+ hr: (text) => chalk.dim(text),
20
+ listBullet: (text) => chalk.yellow(text),
21
+ bold: (text) => chalk.bold(text),
22
+ italic: (text) => chalk.italic(text),
23
+ strikethrough: (text) => chalk.strikethrough(text),
24
+ underline: (text) => chalk.underline(text),
25
+ };
9
26
  function reportSettingsErrors(settingsManager, context) {
10
27
  const errors = settingsManager.drainErrors();
11
28
  for (const { scope, error } of errors) {
@@ -252,6 +269,25 @@ function printSelfUpdateUnavailable(npmCommand, updatePackageName = PACKAGE_NAME
252
269
  function printSelfUpdateFallback(command) {
253
270
  console.error(chalk.dim(`If this keeps failing, run this command yourself: ${command.display}`));
254
271
  }
272
+ function printSelfUpdateNote(note) {
273
+ const trimmedNote = note.trim();
274
+ if (!trimmedNote) {
275
+ return;
276
+ }
277
+ console.log();
278
+ console.log(chalk.bold(chalk.yellow("Update note")));
279
+ try {
280
+ const width = Math.max(20, process.stdout.columns ?? 80);
281
+ const renderedLines = new Markdown(trimmedNote, 0, 0, SELF_UPDATE_NOTE_MARKDOWN_THEME)
282
+ .render(width)
283
+ .map((line) => line.trimEnd());
284
+ console.log(renderedLines.join("\n"));
285
+ }
286
+ catch {
287
+ console.log(trimmedNote);
288
+ }
289
+ console.log();
290
+ }
255
291
  async function getSelfUpdatePlan(force) {
256
292
  if (force) {
257
293
  return { packageName: PACKAGE_NAME, shouldRun: true };
@@ -260,7 +296,7 @@ async function getSelfUpdatePlan(force) {
260
296
  const latestRelease = await getLatestPiRelease(VERSION);
261
297
  const packageName = latestRelease?.packageName ?? PACKAGE_NAME;
262
298
  if (!latestRelease || packageName !== PACKAGE_NAME || isNewerPackageVersion(latestRelease.version, VERSION)) {
263
- return { packageName, shouldRun: true };
299
+ return { packageName, shouldRun: true, ...(latestRelease?.note ? { note: latestRelease.note } : {}) };
264
300
  }
265
301
  }
266
302
  catch {
@@ -273,10 +309,8 @@ async function runSelfUpdate(command) {
273
309
  console.log(chalk.dim(`Updating ${APP_NAME} with ${command.display}...`));
274
310
  for (const step of command.steps ?? [command]) {
275
311
  await new Promise((resolve, reject) => {
276
- // Windows package managers are commonly .cmd shims. Use the shell so Node can execute them.
277
- const child = spawn(step.command, step.args, {
312
+ const child = spawnProcess(step.command, step.args, {
278
313
  stdio: "inherit",
279
- shell: shouldUseWindowsShell(step.command),
280
314
  });
281
315
  child.on("error", (error) => {
282
316
  reject(error);
@@ -295,6 +329,14 @@ async function runSelfUpdate(command) {
295
329
  });
296
330
  }
297
331
  }
332
+ function prepareWindowsNpmSelfUpdate() {
333
+ if (process.platform !== "win32") {
334
+ return;
335
+ }
336
+ const packageDir = getPackageDir();
337
+ cleanupWindowsSelfUpdateQuarantine(packageDir);
338
+ quarantineWindowsNativeDependencies(packageDir);
339
+ }
298
340
  export async function handleConfigCommand(args) {
299
341
  if (args[0] !== "config") {
300
342
  return false;
@@ -428,13 +470,26 @@ export async function handlePackageCommand(args) {
428
470
  if (!selfUpdatePlan.shouldRun) {
429
471
  return true;
430
472
  }
473
+ const installMethod = detectInstallMethod();
474
+ if (process.platform === "win32" && installMethod !== "npm" && installMethod !== "pnpm") {
475
+ console.error(chalk.red(`${APP_NAME} self-update on Windows is only supported for npm and pnpm installs.`));
476
+ console.error(chalk.dim(`Detected install method: ${installMethod}. Update ${APP_NAME} manually.`));
477
+ process.exitCode = 1;
478
+ return true;
479
+ }
431
480
  const selfUpdateCommand = getSelfUpdateCommand(PACKAGE_NAME, selfUpdateNpmCommand, selfUpdatePlan.packageName);
432
481
  if (!selfUpdateCommand) {
433
482
  printSelfUpdateUnavailable(selfUpdateNpmCommand, selfUpdatePlan.packageName);
434
483
  process.exitCode = 1;
435
484
  return true;
436
485
  }
486
+ if (selfUpdatePlan.note) {
487
+ printSelfUpdateNote(selfUpdatePlan.note);
488
+ }
437
489
  try {
490
+ if (installMethod === "npm") {
491
+ prepareWindowsNpmSelfUpdate();
492
+ }
438
493
  await runSelfUpdate(selfUpdateCommand);
439
494
  }
440
495
  catch (error) {