@bastani/atomic 0.8.28-alpha.1 → 0.8.28-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 (349) hide show
  1. package/CHANGELOG.md +53 -0
  2. package/README.md +120 -118
  3. package/dist/builtin/intercom/package.json +1 -1
  4. package/dist/builtin/mcp/package.json +1 -1
  5. package/dist/builtin/subagents/package.json +1 -1
  6. package/dist/builtin/web-access/package.json +1 -1
  7. package/dist/builtin/workflows/CHANGELOG.md +8 -0
  8. package/dist/builtin/workflows/builtin/open-claude-design.ts +150 -13
  9. package/dist/builtin/workflows/package.json +1 -1
  10. package/dist/builtin/workflows/src/tui/chat-surface.ts +32 -33
  11. package/dist/builtin/workflows/src/tui/run-detail.ts +11 -4
  12. package/dist/builtin/workflows/src/tui/status-list.ts +32 -2
  13. package/dist/cli/args.d.ts +4 -0
  14. package/dist/cli/args.d.ts.map +1 -1
  15. package/dist/cli/args.js +35 -0
  16. package/dist/cli/args.js.map +1 -1
  17. package/dist/cli/project-trust.d.ts +10 -0
  18. package/dist/cli/project-trust.d.ts.map +1 -0
  19. package/dist/cli/project-trust.js +36 -0
  20. package/dist/cli/project-trust.js.map +1 -0
  21. package/dist/cli/startup-ui.d.ts +7 -0
  22. package/dist/cli/startup-ui.d.ts.map +1 -0
  23. package/dist/cli/startup-ui.js +57 -0
  24. package/dist/cli/startup-ui.js.map +1 -0
  25. package/dist/config.d.ts.map +1 -1
  26. package/dist/config.js +24 -3
  27. package/dist/config.js.map +1 -1
  28. package/dist/core/agent-session-runtime.d.ts +3 -1
  29. package/dist/core/agent-session-runtime.d.ts.map +1 -1
  30. package/dist/core/agent-session-runtime.js +1 -0
  31. package/dist/core/agent-session-runtime.js.map +1 -1
  32. package/dist/core/agent-session-services.d.ts +2 -1
  33. package/dist/core/agent-session-services.d.ts.map +1 -1
  34. package/dist/core/agent-session-services.js +2 -2
  35. package/dist/core/agent-session-services.js.map +1 -1
  36. package/dist/core/agent-session.d.ts +5 -1
  37. package/dist/core/agent-session.d.ts.map +1 -1
  38. package/dist/core/agent-session.js +58 -20
  39. package/dist/core/agent-session.js.map +1 -1
  40. package/dist/core/auth-storage.d.ts.map +1 -1
  41. package/dist/core/auth-storage.js +4 -3
  42. package/dist/core/auth-storage.js.map +1 -1
  43. package/dist/core/compaction/branch-summarization.d.ts +3 -1
  44. package/dist/core/compaction/branch-summarization.d.ts.map +1 -1
  45. package/dist/core/compaction/branch-summarization.js +9 -3
  46. package/dist/core/compaction/branch-summarization.js.map +1 -1
  47. package/dist/core/compaction/compaction.d.ts.map +1 -1
  48. package/dist/core/compaction/compaction.js +18 -24
  49. package/dist/core/compaction/compaction.js.map +1 -1
  50. package/dist/core/compaction/utils.d.ts +1 -1
  51. package/dist/core/compaction/utils.d.ts.map +1 -1
  52. package/dist/core/compaction/utils.js +1 -1
  53. package/dist/core/compaction/utils.js.map +1 -1
  54. package/dist/core/experimental.d.ts +2 -0
  55. package/dist/core/experimental.d.ts.map +1 -0
  56. package/dist/core/experimental.js +5 -0
  57. package/dist/core/experimental.js.map +1 -0
  58. package/dist/core/export-html/template.js +19 -6
  59. package/dist/core/extensions/index.d.ts +1 -1
  60. package/dist/core/extensions/index.d.ts.map +1 -1
  61. package/dist/core/extensions/index.js.map +1 -1
  62. package/dist/core/extensions/loader.d.ts +1 -1
  63. package/dist/core/extensions/loader.d.ts.map +1 -1
  64. package/dist/core/extensions/loader.js +6 -4
  65. package/dist/core/extensions/loader.js.map +1 -1
  66. package/dist/core/extensions/runner.d.ts +11 -4
  67. package/dist/core/extensions/runner.d.ts.map +1 -1
  68. package/dist/core/extensions/runner.js +53 -3
  69. package/dist/core/extensions/runner.js.map +1 -1
  70. package/dist/core/extensions/types.d.ts +34 -4
  71. package/dist/core/extensions/types.d.ts.map +1 -1
  72. package/dist/core/extensions/types.js.map +1 -1
  73. package/dist/core/footer-data-provider.d.ts +2 -0
  74. package/dist/core/footer-data-provider.d.ts.map +1 -1
  75. package/dist/core/footer-data-provider.js +27 -1
  76. package/dist/core/footer-data-provider.js.map +1 -1
  77. package/dist/core/index.d.ts +1 -0
  78. package/dist/core/index.d.ts.map +1 -1
  79. package/dist/core/index.js +1 -0
  80. package/dist/core/index.js.map +1 -1
  81. package/dist/core/model-registry.d.ts.map +1 -1
  82. package/dist/core/model-registry.js +64 -7
  83. package/dist/core/model-registry.js.map +1 -1
  84. package/dist/core/model-resolver.d.ts.map +1 -1
  85. package/dist/core/model-resolver.js +1 -0
  86. package/dist/core/model-resolver.js.map +1 -1
  87. package/dist/core/output-guard.d.ts +1 -0
  88. package/dist/core/output-guard.d.ts.map +1 -1
  89. package/dist/core/output-guard.js +52 -22
  90. package/dist/core/output-guard.js.map +1 -1
  91. package/dist/core/package-manager.d.ts +1 -0
  92. package/dist/core/package-manager.d.ts.map +1 -1
  93. package/dist/core/package-manager.js +20 -8
  94. package/dist/core/package-manager.js.map +1 -1
  95. package/dist/core/project-trust.d.ts +15 -0
  96. package/dist/core/project-trust.d.ts.map +1 -0
  97. package/dist/core/project-trust.js +58 -0
  98. package/dist/core/project-trust.js.map +1 -0
  99. package/dist/core/prompt-templates.d.ts +5 -4
  100. package/dist/core/prompt-templates.d.ts.map +1 -1
  101. package/dist/core/prompt-templates.js +30 -29
  102. package/dist/core/prompt-templates.js.map +1 -1
  103. package/dist/core/provider-attribution.d.ts +4 -0
  104. package/dist/core/provider-attribution.d.ts.map +1 -0
  105. package/dist/core/provider-attribution.js +73 -0
  106. package/dist/core/provider-attribution.js.map +1 -0
  107. package/dist/core/provider-display-names.d.ts.map +1 -1
  108. package/dist/core/provider-display-names.js +3 -0
  109. package/dist/core/provider-display-names.js.map +1 -1
  110. package/dist/core/resolve-config-value.d.ts +9 -1
  111. package/dist/core/resolve-config-value.d.ts.map +1 -1
  112. package/dist/core/resolve-config-value.js +134 -11
  113. package/dist/core/resolve-config-value.js.map +1 -1
  114. package/dist/core/resource-loader.d.ts +12 -2
  115. package/dist/core/resource-loader.d.ts.map +1 -1
  116. package/dist/core/resource-loader.js +108 -18
  117. package/dist/core/resource-loader.js.map +1 -1
  118. package/dist/core/sdk.d.ts.map +1 -1
  119. package/dist/core/sdk.js +12 -42
  120. package/dist/core/sdk.js.map +1 -1
  121. package/dist/core/session-manager.d.ts +6 -7
  122. package/dist/core/session-manager.d.ts.map +1 -1
  123. package/dist/core/session-manager.js +99 -35
  124. package/dist/core/session-manager.js.map +1 -1
  125. package/dist/core/settings-manager.d.ts +15 -2
  126. package/dist/core/settings-manager.d.ts.map +1 -1
  127. package/dist/core/settings-manager.js +69 -10
  128. package/dist/core/settings-manager.js.map +1 -1
  129. package/dist/core/slash-commands.d.ts.map +1 -1
  130. package/dist/core/slash-commands.js +1 -0
  131. package/dist/core/slash-commands.js.map +1 -1
  132. package/dist/core/system-prompt.d.ts.map +1 -1
  133. package/dist/core/system-prompt.js +0 -3
  134. package/dist/core/system-prompt.js.map +1 -1
  135. package/dist/core/tools/bash.d.ts.map +1 -1
  136. package/dist/core/tools/bash.js +2 -1
  137. package/dist/core/tools/bash.js.map +1 -1
  138. package/dist/core/tools/edit.d.ts.map +1 -1
  139. package/dist/core/tools/edit.js +7 -10
  140. package/dist/core/tools/edit.js.map +1 -1
  141. package/dist/core/tools/find.d.ts.map +1 -1
  142. package/dist/core/tools/find.js +1 -1
  143. package/dist/core/tools/find.js.map +1 -1
  144. package/dist/core/tools/grep.d.ts.map +1 -1
  145. package/dist/core/tools/grep.js +1 -1
  146. package/dist/core/tools/grep.js.map +1 -1
  147. package/dist/core/tools/ls.d.ts.map +1 -1
  148. package/dist/core/tools/ls.js +1 -1
  149. package/dist/core/tools/ls.js.map +1 -1
  150. package/dist/core/tools/oversized-tool-result.d.ts +53 -0
  151. package/dist/core/tools/oversized-tool-result.d.ts.map +1 -0
  152. package/dist/core/tools/oversized-tool-result.js +206 -0
  153. package/dist/core/tools/oversized-tool-result.js.map +1 -0
  154. package/dist/core/tools/read.d.ts +12 -0
  155. package/dist/core/tools/read.d.ts.map +1 -1
  156. package/dist/core/tools/read.js +99 -34
  157. package/dist/core/tools/read.js.map +1 -1
  158. package/dist/core/tools/render-utils.d.ts +6 -0
  159. package/dist/core/tools/render-utils.d.ts.map +1 -1
  160. package/dist/core/tools/render-utils.js +17 -1
  161. package/dist/core/tools/render-utils.js.map +1 -1
  162. package/dist/core/tools/tool-definition-wrapper.d.ts +6 -0
  163. package/dist/core/tools/tool-definition-wrapper.d.ts.map +1 -1
  164. package/dist/core/tools/tool-definition-wrapper.js +2 -0
  165. package/dist/core/tools/tool-definition-wrapper.js.map +1 -1
  166. package/dist/core/tools/tool-limits.d.ts +25 -0
  167. package/dist/core/tools/tool-limits.d.ts.map +1 -0
  168. package/dist/core/tools/tool-limits.js +25 -0
  169. package/dist/core/tools/tool-limits.js.map +1 -0
  170. package/dist/core/tools/write.d.ts.map +1 -1
  171. package/dist/core/tools/write.js +1 -1
  172. package/dist/core/tools/write.js.map +1 -1
  173. package/dist/core/trust-manager.d.ts +31 -0
  174. package/dist/core/trust-manager.d.ts.map +1 -0
  175. package/dist/core/trust-manager.js +196 -0
  176. package/dist/core/trust-manager.js.map +1 -0
  177. package/dist/index.d.ts +9 -4
  178. package/dist/index.d.ts.map +1 -1
  179. package/dist/index.js +5 -1
  180. package/dist/index.js.map +1 -1
  181. package/dist/main.d.ts.map +1 -1
  182. package/dist/main.js +142 -30
  183. package/dist/main.js.map +1 -1
  184. package/dist/migrations.d.ts +3 -1
  185. package/dist/migrations.d.ts.map +1 -1
  186. package/dist/migrations.js +325 -7
  187. package/dist/migrations.js.map +1 -1
  188. package/dist/modes/index.d.ts +1 -1
  189. package/dist/modes/index.d.ts.map +1 -1
  190. package/dist/modes/index.js.map +1 -1
  191. package/dist/modes/interactive/components/bash-execution.d.ts.map +1 -1
  192. package/dist/modes/interactive/components/bash-execution.js +2 -2
  193. package/dist/modes/interactive/components/bash-execution.js.map +1 -1
  194. package/dist/modes/interactive/components/footer.d.ts.map +1 -1
  195. package/dist/modes/interactive/components/footer.js +6 -0
  196. package/dist/modes/interactive/components/footer.js.map +1 -1
  197. package/dist/modes/interactive/components/index.d.ts +1 -0
  198. package/dist/modes/interactive/components/index.d.ts.map +1 -1
  199. package/dist/modes/interactive/components/index.js +1 -0
  200. package/dist/modes/interactive/components/index.js.map +1 -1
  201. package/dist/modes/interactive/components/login-dialog.d.ts +1 -1
  202. package/dist/modes/interactive/components/login-dialog.d.ts.map +1 -1
  203. package/dist/modes/interactive/components/login-dialog.js +9 -16
  204. package/dist/modes/interactive/components/login-dialog.js.map +1 -1
  205. package/dist/modes/interactive/components/settings-selector.d.ts +3 -1
  206. package/dist/modes/interactive/components/settings-selector.d.ts.map +1 -1
  207. package/dist/modes/interactive/components/settings-selector.js +20 -0
  208. package/dist/modes/interactive/components/settings-selector.js.map +1 -1
  209. package/dist/modes/interactive/components/tool-execution.d.ts.map +1 -1
  210. package/dist/modes/interactive/components/tool-execution.js +22 -0
  211. package/dist/modes/interactive/components/tool-execution.js.map +1 -1
  212. package/dist/modes/interactive/components/trust-selector.d.ts +23 -0
  213. package/dist/modes/interactive/components/trust-selector.d.ts.map +1 -0
  214. package/dist/modes/interactive/components/trust-selector.js +85 -0
  215. package/dist/modes/interactive/components/trust-selector.js.map +1 -0
  216. package/dist/modes/interactive/components/user-message.d.ts.map +1 -1
  217. package/dist/modes/interactive/components/user-message.js +1 -1
  218. package/dist/modes/interactive/components/user-message.js.map +1 -1
  219. package/dist/modes/interactive/interactive-mode.d.ts +9 -0
  220. package/dist/modes/interactive/interactive-mode.d.ts.map +1 -1
  221. package/dist/modes/interactive/interactive-mode.js +130 -9
  222. package/dist/modes/interactive/interactive-mode.js.map +1 -1
  223. package/dist/modes/interactive/theme/theme.d.ts.map +1 -1
  224. package/dist/modes/interactive/theme/theme.js +10 -0
  225. package/dist/modes/interactive/theme/theme.js.map +1 -1
  226. package/dist/modes/print-mode.d.ts.map +1 -1
  227. package/dist/modes/print-mode.js +1 -0
  228. package/dist/modes/print-mode.js.map +1 -1
  229. package/dist/modes/rpc/rpc-client.d.ts +3 -0
  230. package/dist/modes/rpc/rpc-client.d.ts.map +1 -1
  231. package/dist/modes/rpc/rpc-client.js +50 -6
  232. package/dist/modes/rpc/rpc-client.js.map +1 -1
  233. package/dist/modes/rpc/rpc-mode.d.ts.map +1 -1
  234. package/dist/modes/rpc/rpc-mode.js +23 -4
  235. package/dist/modes/rpc/rpc-mode.js.map +1 -1
  236. package/dist/modes/rpc/rpc-types.d.ts +1 -0
  237. package/dist/modes/rpc/rpc-types.d.ts.map +1 -1
  238. package/dist/modes/rpc/rpc-types.js.map +1 -1
  239. package/dist/package-manager-cli.d.ts +6 -2
  240. package/dist/package-manager-cli.d.ts.map +1 -1
  241. package/dist/package-manager-cli.js +104 -10
  242. package/dist/package-manager-cli.js.map +1 -1
  243. package/dist/utils/changelog.d.ts +1 -0
  244. package/dist/utils/changelog.d.ts.map +1 -1
  245. package/dist/utils/changelog.js +72 -0
  246. package/dist/utils/changelog.js.map +1 -1
  247. package/dist/utils/deprecation.d.ts +4 -0
  248. package/dist/utils/deprecation.d.ts.map +1 -0
  249. package/dist/utils/deprecation.js +13 -0
  250. package/dist/utils/deprecation.js.map +1 -0
  251. package/dist/utils/git.d.ts.map +1 -1
  252. package/dist/utils/git.js +54 -22
  253. package/dist/utils/git.js.map +1 -1
  254. package/dist/utils/json.d.ts +3 -0
  255. package/dist/utils/json.d.ts.map +1 -0
  256. package/dist/utils/json.js +7 -0
  257. package/dist/utils/json.js.map +1 -0
  258. package/dist/utils/open-browser.d.ts +9 -0
  259. package/dist/utils/open-browser.d.ts.map +1 -0
  260. package/dist/utils/open-browser.js +22 -0
  261. package/dist/utils/open-browser.js.map +1 -0
  262. package/docs/containerization.md +111 -0
  263. package/docs/custom-provider.md +9 -9
  264. package/docs/development.md +1 -1
  265. package/docs/docs.json +2 -0
  266. package/docs/extensions.md +40 -4
  267. package/docs/index.md +2 -0
  268. package/docs/models.md +10 -10
  269. package/docs/packages.md +1 -1
  270. package/docs/prompt-templates.md +9 -2
  271. package/docs/providers.md +18 -5
  272. package/docs/quickstart.md +1 -0
  273. package/docs/rpc.md +3 -2
  274. package/docs/sdk.md +5 -0
  275. package/docs/security.md +56 -0
  276. package/docs/session-format.md +2 -2
  277. package/docs/sessions.md +8 -0
  278. package/docs/settings.md +21 -4
  279. package/docs/skills.md +1 -1
  280. package/docs/terminal-setup.md +44 -2
  281. package/docs/themes.md +1 -1
  282. package/docs/tmux.md +4 -2
  283. package/docs/tui.md +14 -5
  284. package/docs/usage.md +17 -3
  285. package/examples/README.md +1 -1
  286. package/examples/extensions/README.md +8 -5
  287. package/examples/extensions/bash-spawn-hook.ts +1 -1
  288. package/examples/extensions/built-in-tool-renderer.ts +1 -1
  289. package/examples/extensions/claude-rules.ts +1 -1
  290. package/examples/extensions/commands.ts +1 -1
  291. package/examples/extensions/custom-header.ts +1 -1
  292. package/examples/extensions/custom-provider-anthropic/index.ts +3 -3
  293. package/examples/extensions/custom-provider-anthropic/package-lock.json +4 -4
  294. package/examples/extensions/custom-provider-anthropic/package.json +6 -6
  295. package/examples/extensions/custom-provider-gitlab-duo/index.ts +55 -4
  296. package/examples/extensions/custom-provider-gitlab-duo/package.json +3 -3
  297. package/examples/extensions/doom-overlay/README.md +1 -1
  298. package/examples/extensions/doom-overlay/index.ts +2 -2
  299. package/examples/extensions/git-merge-and-resolve.ts +115 -0
  300. package/examples/extensions/gondolin/index.ts +523 -0
  301. package/examples/extensions/gondolin/package-lock.json +185 -0
  302. package/examples/extensions/gondolin/package.json +19 -0
  303. package/examples/extensions/handoff.ts +1 -1
  304. package/examples/extensions/hidden-thinking-label.ts +1 -1
  305. package/examples/extensions/inline-bash.ts +2 -2
  306. package/examples/extensions/input-transform-streaming.ts +39 -0
  307. package/examples/extensions/input-transform.ts +3 -3
  308. package/examples/extensions/interactive-shell.ts +2 -2
  309. package/examples/extensions/mac-system-theme.ts +2 -2
  310. package/examples/extensions/minimal-mode.ts +1 -1
  311. package/examples/extensions/modal-editor.ts +1 -1
  312. package/examples/extensions/model-status.ts +1 -1
  313. package/examples/extensions/overlay-qa-tests.ts +198 -179
  314. package/examples/extensions/overlay-test.ts +1 -1
  315. package/examples/extensions/pirate.ts +1 -1
  316. package/examples/extensions/preset.ts +14 -12
  317. package/examples/extensions/project-trust.ts +64 -0
  318. package/examples/extensions/prompt-customizer.ts +1 -1
  319. package/examples/extensions/qna.ts +1 -1
  320. package/examples/extensions/question.ts +1 -1
  321. package/examples/extensions/questionnaire.ts +1 -1
  322. package/examples/extensions/rainbow-editor.ts +1 -1
  323. package/examples/extensions/sandbox/index.ts +16 -14
  324. package/examples/extensions/sandbox/package-lock.json +90 -90
  325. package/examples/extensions/sandbox/package.json +17 -17
  326. package/examples/extensions/snake.ts +1 -1
  327. package/examples/extensions/space-invaders.ts +1 -1
  328. package/examples/extensions/ssh.ts +2 -2
  329. package/examples/extensions/subagent/README.md +13 -13
  330. package/examples/extensions/subagent/agents.ts +4 -2
  331. package/examples/extensions/subagent/index.ts +6 -6
  332. package/examples/extensions/summarize.ts +1 -1
  333. package/examples/extensions/tic-tac-toe.ts +1 -1
  334. package/examples/extensions/titlebar-spinner.ts +1 -1
  335. package/examples/extensions/todo.ts +1 -1
  336. package/examples/extensions/tool-override.ts +1 -1
  337. package/examples/extensions/tools.ts +6 -1
  338. package/examples/extensions/with-deps/package-lock.json +4 -4
  339. package/examples/extensions/with-deps/package.json +7 -7
  340. package/examples/extensions/working-indicator.ts +4 -4
  341. package/examples/extensions/working-message-test.ts +1 -1
  342. package/examples/sdk/01-minimal.ts +1 -1
  343. package/examples/sdk/03-custom-prompt.ts +1 -1
  344. package/examples/sdk/04-skills.ts +1 -1
  345. package/examples/sdk/06-extensions.ts +2 -2
  346. package/examples/sdk/08-prompt-templates.ts +1 -1
  347. package/examples/sdk/09-api-keys-and-oauth.ts +2 -2
  348. package/examples/sdk/README.md +2 -2
  349. package/package.json +4 -4
@@ -1 +1 @@
1
- {"version":3,"file":"migrations.d.ts","sourceRoot":"","sources":["../src/migrations.ts"],"names":[],"mappings":"AAAA;;GAEG;AAaH;;;;GAIG;AACH,wBAAgB,qBAAqB,IAAI,MAAM,EAAE,CAoDhD;AAED;;;;;;;;GAQG;AACH,wBAAgB,4BAA4B,IAAI,IAAI,CA+CnD;AA+ID;;GAEG;AACH,wBAAsB,uBAAuB,CAAC,QAAQ,EAAE,MAAM,EAAE,GAAG,OAAO,CAAC,IAAI,CAAC,CAqB/E;AAED;;;;GAIG;AACH,wBAAgB,aAAa,CAAC,GAAG,EAAE,MAAM,GAAG;IAC3C,qBAAqB,EAAE,MAAM,EAAE,CAAC;IAChC,mBAAmB,EAAE,MAAM,EAAE,CAAC;CAC9B,CAOA","sourcesContent":["/**\n * One-time migrations that run on startup.\n */\n\nimport chalk from \"chalk\";\nimport { existsSync, mkdirSync, readdirSync, readFileSync, renameSync, rmSync, writeFileSync } from \"fs\";\nimport { dirname, join } from \"path\";\nimport { CONFIG_DIR_NAME, getAgentDir, getBinDir } from \"./config.ts\";\nimport { migrateKeybindingsConfig } from \"./core/keybindings.ts\";\n\nconst MIGRATION_GUIDE_URL =\n\t\"https://github.com/earendil-works/pi-mono/blob/main/packages/coding-agent/CHANGELOG.md#extensions-migration\";\nconst EXTENSIONS_DOC_URL =\n\t\"https://github.com/earendil-works/pi-mono/blob/main/packages/coding-agent/docs/extensions.md\";\n\n/**\n * Migrate legacy oauth.json and settings.json apiKeys to auth.json.\n *\n * @returns Array of provider names that were migrated\n */\nexport function migrateAuthToAuthJson(): string[] {\n\tconst agentDir = getAgentDir();\n\tconst authPath = join(agentDir, \"auth.json\");\n\tconst oauthPath = join(agentDir, \"oauth.json\");\n\tconst settingsPath = join(agentDir, \"settings.json\");\n\n\t// Skip if auth.json already exists\n\tif (existsSync(authPath)) return [];\n\n\tconst migrated: Record<string, unknown> = {};\n\tconst providers: string[] = [];\n\n\t// Migrate oauth.json\n\tif (existsSync(oauthPath)) {\n\t\ttry {\n\t\t\tconst oauth = JSON.parse(readFileSync(oauthPath, \"utf-8\"));\n\t\t\tfor (const [provider, cred] of Object.entries(oauth)) {\n\t\t\t\tmigrated[provider] = { type: \"oauth\", ...(cred as object) };\n\t\t\t\tproviders.push(provider);\n\t\t\t}\n\t\t\trenameSync(oauthPath, `${oauthPath}.migrated`);\n\t\t} catch {\n\t\t\t// Skip on error\n\t\t}\n\t}\n\n\t// Migrate settings.json apiKeys\n\tif (existsSync(settingsPath)) {\n\t\ttry {\n\t\t\tconst content = readFileSync(settingsPath, \"utf-8\");\n\t\t\tconst settings = JSON.parse(content);\n\t\t\tif (settings.apiKeys && typeof settings.apiKeys === \"object\") {\n\t\t\t\tfor (const [provider, key] of Object.entries(settings.apiKeys)) {\n\t\t\t\t\tif (!migrated[provider] && typeof key === \"string\") {\n\t\t\t\t\t\tmigrated[provider] = { type: \"api_key\", key };\n\t\t\t\t\t\tproviders.push(provider);\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\tdelete settings.apiKeys;\n\t\t\t\twriteFileSync(settingsPath, JSON.stringify(settings, null, 2));\n\t\t\t}\n\t\t} catch {\n\t\t\t// Skip on error\n\t\t}\n\t}\n\n\tif (Object.keys(migrated).length > 0) {\n\t\tmkdirSync(dirname(authPath), { recursive: true });\n\t\twriteFileSync(authPath, JSON.stringify(migrated, null, 2), { mode: 0o600 });\n\t}\n\n\treturn providers;\n}\n\n/**\n * Migrate sessions from ~/.pi/agent/*.jsonl to proper session directories.\n *\n * Bug in v0.30.0: Sessions were saved to ~/.pi/agent/ instead of\n * ~/.pi/agent/sessions/<encoded-cwd>/. This migration moves them\n * to the correct location based on the cwd in their session header.\n *\n * See: https://github.com/earendil-works/pi-mono/issues/320\n */\nexport function migrateSessionsFromAgentRoot(): void {\n\tconst agentDir = getAgentDir();\n\n\t// Find all .jsonl files directly in agentDir (not in subdirectories)\n\tlet files: string[];\n\ttry {\n\t\tfiles = readdirSync(agentDir)\n\t\t\t.filter((f) => f.endsWith(\".jsonl\"))\n\t\t\t.map((f) => join(agentDir, f));\n\t} catch {\n\t\treturn;\n\t}\n\n\tif (files.length === 0) return;\n\n\tfor (const file of files) {\n\t\ttry {\n\t\t\t// Read first line to get session header\n\t\t\tconst content = readFileSync(file, \"utf8\");\n\t\t\tconst firstLine = content.split(\"\\n\")[0];\n\t\t\tif (!firstLine?.trim()) continue;\n\n\t\t\tconst header = JSON.parse(firstLine);\n\t\t\tif (header.type !== \"session\" || !header.cwd) continue;\n\n\t\t\tconst cwd: string = header.cwd;\n\n\t\t\t// Compute the correct session directory (same encoding as session-manager.ts)\n\t\t\tconst safePath = `--${cwd.replace(/^[/\\\\]/, \"\").replace(/[/\\\\:]/g, \"-\")}--`;\n\t\t\tconst correctDir = join(agentDir, \"sessions\", safePath);\n\n\t\t\t// Create directory if needed\n\t\t\tif (!existsSync(correctDir)) {\n\t\t\t\tmkdirSync(correctDir, { recursive: true });\n\t\t\t}\n\n\t\t\t// Move the file\n\t\t\tconst fileName = file.split(\"/\").pop() || file.split(\"\\\\\").pop();\n\t\t\tconst newPath = join(correctDir, fileName!);\n\n\t\t\tif (existsSync(newPath)) continue; // Skip if target exists\n\n\t\t\trenameSync(file, newPath);\n\t\t} catch {\n\t\t\t// Skip files that can't be migrated\n\t\t}\n\t}\n}\n\n/**\n * Migrate commands/ to prompts/ if needed.\n * Works for both regular directories and symlinks.\n */\nfunction migrateCommandsToPrompts(baseDir: string, label: string): boolean {\n\tconst commandsDir = join(baseDir, \"commands\");\n\tconst promptsDir = join(baseDir, \"prompts\");\n\n\tif (existsSync(commandsDir) && !existsSync(promptsDir)) {\n\t\ttry {\n\t\t\trenameSync(commandsDir, promptsDir);\n\t\t\tconsole.log(chalk.green(`Migrated ${label} commands/ → prompts/`));\n\t\t\treturn true;\n\t\t} catch (err) {\n\t\t\tconsole.log(\n\t\t\t\tchalk.yellow(\n\t\t\t\t\t`Warning: Could not migrate ${label} commands/ to prompts/: ${err instanceof Error ? err.message : err}`,\n\t\t\t\t),\n\t\t\t);\n\t\t}\n\t}\n\treturn false;\n}\n\nfunction migrateKeybindingsConfigFile(): void {\n\tconst configPath = join(getAgentDir(), \"keybindings.json\");\n\tif (!existsSync(configPath)) return;\n\n\ttry {\n\t\tconst parsed = JSON.parse(readFileSync(configPath, \"utf-8\")) as unknown;\n\t\tif (typeof parsed !== \"object\" || parsed === null || Array.isArray(parsed)) {\n\t\t\treturn;\n\t\t}\n\t\tconst { config, migrated } = migrateKeybindingsConfig(parsed as Record<string, unknown>);\n\t\tif (!migrated) return;\n\t\twriteFileSync(configPath, `${JSON.stringify(config, null, 2)}\\n`, \"utf-8\");\n\t} catch {\n\t\t// Ignore malformed files during migration\n\t}\n}\n\n/**\n * Move fd/rg binaries from tools/ to bin/ if they exist.\n */\nfunction migrateToolsToBin(): void {\n\tconst agentDir = getAgentDir();\n\tconst toolsDir = join(agentDir, \"tools\");\n\tconst binDir = getBinDir();\n\n\tif (!existsSync(toolsDir)) return;\n\n\tconst binaries = [\"fd\", \"rg\", \"fd.exe\", \"rg.exe\"];\n\tlet movedAny = false;\n\n\tfor (const bin of binaries) {\n\t\tconst oldPath = join(toolsDir, bin);\n\t\tconst newPath = join(binDir, bin);\n\n\t\tif (existsSync(oldPath)) {\n\t\t\tif (!existsSync(binDir)) {\n\t\t\t\tmkdirSync(binDir, { recursive: true });\n\t\t\t}\n\t\t\tif (!existsSync(newPath)) {\n\t\t\t\ttry {\n\t\t\t\t\trenameSync(oldPath, newPath);\n\t\t\t\t\tmovedAny = true;\n\t\t\t\t} catch {\n\t\t\t\t\t// Ignore errors\n\t\t\t\t}\n\t\t\t} else {\n\t\t\t\t// Target exists, just delete the old one\n\t\t\t\ttry {\n\t\t\t\t\trmSync?.(oldPath, { force: true });\n\t\t\t\t} catch {\n\t\t\t\t\t// Ignore\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n\n\tif (movedAny) {\n\t\tconsole.log(chalk.green(`Migrated managed binaries tools/ → bin/`));\n\t}\n}\n\n/**\n * Check for deprecated hooks/ and tools/ directories.\n * Note: tools/ may contain fd/rg binaries extracted by pi, so only warn if it has other files.\n */\nfunction checkDeprecatedExtensionDirs(baseDir: string, label: string): string[] {\n\tconst hooksDir = join(baseDir, \"hooks\");\n\tconst toolsDir = join(baseDir, \"tools\");\n\tconst warnings: string[] = [];\n\n\tif (existsSync(hooksDir)) {\n\t\twarnings.push(`${label} hooks/ directory found. Hooks have been renamed to extensions.`);\n\t}\n\n\tif (existsSync(toolsDir)) {\n\t\t// Check if tools/ contains anything other than fd/rg (which are auto-extracted binaries)\n\t\ttry {\n\t\t\tconst entries = readdirSync(toolsDir);\n\t\t\tconst customTools = entries.filter((e) => {\n\t\t\t\tconst lower = e.toLowerCase();\n\t\t\t\treturn (\n\t\t\t\t\tlower !== \"fd\" && lower !== \"rg\" && lower !== \"fd.exe\" && lower !== \"rg.exe\" && !e.startsWith(\".\") // Ignore .DS_Store and other hidden files\n\t\t\t\t);\n\t\t\t});\n\t\t\tif (customTools.length > 0) {\n\t\t\t\twarnings.push(\n\t\t\t\t\t`${label} tools/ directory contains custom tools. Custom tools have been merged into extensions.`,\n\t\t\t\t);\n\t\t\t}\n\t\t} catch {\n\t\t\t// Ignore read errors\n\t\t}\n\t}\n\n\treturn warnings;\n}\n\n/**\n * Run extension system migrations (commands→prompts) and collect warnings about deprecated directories.\n */\nfunction migrateExtensionSystem(cwd: string): string[] {\n\tconst agentDir = getAgentDir();\n\tconst projectDir = join(cwd, CONFIG_DIR_NAME);\n\n\t// Migrate commands/ to prompts/\n\tmigrateCommandsToPrompts(agentDir, \"Global\");\n\tmigrateCommandsToPrompts(projectDir, \"Project\");\n\n\t// Check for deprecated directories\n\tconst warnings = [\n\t\t...checkDeprecatedExtensionDirs(agentDir, \"Global\"),\n\t\t...checkDeprecatedExtensionDirs(projectDir, \"Project\"),\n\t];\n\n\treturn warnings;\n}\n\n/**\n * Print deprecation warnings and wait for keypress.\n */\nexport async function showDeprecationWarnings(warnings: string[]): Promise<void> {\n\tif (warnings.length === 0) return;\n\n\tfor (const warning of warnings) {\n\t\tconsole.log(chalk.yellow(`Warning: ${warning}`));\n\t}\n\tconsole.log(chalk.yellow(`\\nMove your extensions to the extensions/ directory.`));\n\tconsole.log(chalk.yellow(`Migration guide: ${MIGRATION_GUIDE_URL}`));\n\tconsole.log(chalk.yellow(`Documentation: ${EXTENSIONS_DOC_URL}`));\n\tconsole.log(chalk.dim(`\\nPress any key to continue...`));\n\n\tawait new Promise<void>((resolve) => {\n\t\tprocess.stdin.setRawMode?.(true);\n\t\tprocess.stdin.resume();\n\t\tprocess.stdin.once(\"data\", () => {\n\t\t\tprocess.stdin.setRawMode?.(false);\n\t\t\tprocess.stdin.pause();\n\t\t\tresolve();\n\t\t});\n\t});\n\tconsole.log();\n}\n\n/**\n * Run all migrations. Called once on startup.\n *\n * @returns Object with migration results and deprecation warnings\n */\nexport function runMigrations(cwd: string): {\n\tmigratedAuthProviders: string[];\n\tdeprecationWarnings: string[];\n} {\n\tconst migratedAuthProviders = migrateAuthToAuthJson();\n\tmigrateSessionsFromAgentRoot();\n\tmigrateToolsToBin();\n\tmigrateKeybindingsConfigFile();\n\tconst deprecationWarnings = migrateExtensionSystem(cwd);\n\treturn { migratedAuthProviders, deprecationWarnings };\n}\n"]}
1
+ {"version":3,"file":"migrations.d.ts","sourceRoot":"","sources":["../src/migrations.ts"],"names":[],"mappings":"AAAA;;GAEG;AAeH;;;;GAIG;AACH,wBAAgB,qBAAqB,IAAI,MAAM,EAAE,CAoDhD;AAqVD;;;;;;;;GAQG;AACH,wBAAgB,4BAA4B,IAAI,IAAI,CA+CnD;AAiJD;;GAEG;AACH,wBAAsB,uBAAuB,CAAC,QAAQ,EAAE,MAAM,EAAE,GAAG,OAAO,CAAC,IAAI,CAAC,CAqB/E;AAED;;;;GAIG;AACH,wBAAgB,aAAa,CAC5B,GAAG,EAAE,MAAM,EACX,OAAO,CAAC,EAAE;IAAE,cAAc,CAAC,EAAE,OAAO,CAAA;CAAE,GACpC;IACF,qBAAqB,EAAE,MAAM,EAAE,CAAC;IAChC,mBAAmB,EAAE,MAAM,EAAE,CAAC;CAC9B,CAQA","sourcesContent":["/**\n * One-time migrations that run on startup.\n */\n\nimport chalk from \"chalk\";\nimport { chmodSync, existsSync, mkdirSync, readdirSync, readFileSync, renameSync, rmSync, writeFileSync } from \"fs\";\nimport { dirname, join } from \"path\";\nimport { CONFIG_DIR_NAME, getAgentConfigPaths, getAgentDir, getBinDir } from \"./config.ts\";\nimport { migrateKeybindingsConfig } from \"./core/keybindings.ts\";\nimport { isLegacyEnvVarNameConfigValue } from \"./core/resolve-config-value.ts\";\nimport { stripJsonComments } from \"./utils/json.ts\";\n\nconst MIGRATION_GUIDE_URL =\n\t\"https://github.com/earendil-works/pi-mono/blob/main/packages/coding-agent/CHANGELOG.md#extensions-migration\";\nconst EXTENSIONS_DOC_URL =\n\t\"https://github.com/earendil-works/pi-mono/blob/main/packages/coding-agent/docs/extensions.md\";\n\n/**\n * Migrate legacy oauth.json and settings.json apiKeys to auth.json.\n *\n * @returns Array of provider names that were migrated\n */\nexport function migrateAuthToAuthJson(): string[] {\n\tconst agentDir = getAgentDir();\n\tconst authPath = join(agentDir, \"auth.json\");\n\tconst oauthPath = join(agentDir, \"oauth.json\");\n\tconst settingsPath = join(agentDir, \"settings.json\");\n\n\t// Skip if auth.json already exists\n\tif (existsSync(authPath)) return [];\n\n\tconst migrated: Record<string, unknown> = {};\n\tconst providers: string[] = [];\n\n\t// Migrate oauth.json\n\tif (existsSync(oauthPath)) {\n\t\ttry {\n\t\t\tconst oauth = JSON.parse(readFileSync(oauthPath, \"utf-8\"));\n\t\t\tfor (const [provider, cred] of Object.entries(oauth)) {\n\t\t\t\tmigrated[provider] = { type: \"oauth\", ...(cred as object) };\n\t\t\t\tproviders.push(provider);\n\t\t\t}\n\t\t\trenameSync(oauthPath, `${oauthPath}.migrated`);\n\t\t} catch {\n\t\t\t// Skip on error\n\t\t}\n\t}\n\n\t// Migrate settings.json apiKeys\n\tif (existsSync(settingsPath)) {\n\t\ttry {\n\t\t\tconst content = readFileSync(settingsPath, \"utf-8\");\n\t\t\tconst settings = JSON.parse(content);\n\t\t\tif (settings.apiKeys && typeof settings.apiKeys === \"object\") {\n\t\t\t\tfor (const [provider, key] of Object.entries(settings.apiKeys)) {\n\t\t\t\t\tif (!migrated[provider] && typeof key === \"string\") {\n\t\t\t\t\t\tmigrated[provider] = { type: \"api_key\", key };\n\t\t\t\t\t\tproviders.push(provider);\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\tdelete settings.apiKeys;\n\t\t\t\twriteFileSync(settingsPath, JSON.stringify(settings, null, 2));\n\t\t\t}\n\t\t} catch {\n\t\t\t// Skip on error\n\t\t}\n\t}\n\n\tif (Object.keys(migrated).length > 0) {\n\t\tmkdirSync(dirname(authPath), { recursive: true });\n\t\twriteFileSync(authPath, JSON.stringify(migrated, null, 2), { mode: 0o600 });\n\t}\n\n\treturn providers;\n}\n\ninterface ConfigValueMigration {\n\tlocation: string;\n\tfrom: string;\n\tto: string;\n}\n\nfunction migrateLegacyEnvVarString(value: string): string | undefined {\n\treturn isLegacyEnvVarNameConfigValue(value) && process.env[value] !== undefined ? `$${value}` : undefined;\n}\n\nfunction migrateStringProperty(\n\trecord: Record<string, unknown>,\n\tkey: string,\n\tlocation: string,\n\tmigrations: ConfigValueMigration[],\n): boolean {\n\tconst value = record[key];\n\tif (typeof value !== \"string\") return false;\n\tconst migrated = migrateLegacyEnvVarString(value);\n\tif (migrated === undefined) return false;\n\trecord[key] = migrated;\n\tmigrations.push({ location, from: value, to: migrated });\n\treturn true;\n}\n\nfunction migrateHeadersConfig(headers: unknown, location: string, migrations: ConfigValueMigration[]): boolean {\n\tif (typeof headers !== \"object\" || headers === null || Array.isArray(headers)) return false;\n\tconst headerRecord = headers as Record<string, unknown>;\n\tlet migrated = false;\n\tfor (const [key, value] of Object.entries(headerRecord)) {\n\t\tif (typeof value !== \"string\") continue;\n\t\tconst migratedValue = migrateLegacyEnvVarString(value);\n\t\tif (migratedValue === undefined) continue;\n\t\theaderRecord[key] = migratedValue;\n\t\tmigrations.push({ location: `${location}[${JSON.stringify(key)}]`, from: value, to: migratedValue });\n\t\tmigrated = true;\n\t}\n\treturn migrated;\n}\n\nfunction migrateAuthJsonConfigValues(agentDir: string): ConfigValueMigration[] {\n\tconst authPath = join(agentDir, \"auth.json\");\n\tif (!existsSync(authPath)) return [];\n\n\ttry {\n\t\tconst parsed = JSON.parse(readFileSync(authPath, \"utf-8\")) as unknown;\n\t\tif (typeof parsed !== \"object\" || parsed === null || Array.isArray(parsed)) return [];\n\t\tconst authData = parsed as Record<string, unknown>;\n\n\t\tconst migrations: ConfigValueMigration[] = [];\n\t\tfor (const [provider, credential] of Object.entries(authData)) {\n\t\t\tif (typeof credential !== \"object\" || credential === null || Array.isArray(credential)) continue;\n\t\t\tconst credentialRecord = credential as Record<string, unknown>;\n\t\t\tif (credentialRecord.type !== \"api_key\") continue;\n\t\t\tmigrateStringProperty(credentialRecord, \"key\", `auth.json[${JSON.stringify(provider)}].key`, migrations);\n\t\t}\n\n\t\tif (migrations.length === 0) return [];\n\t\twriteFileSync(authPath, `${JSON.stringify(parsed, null, 2)}\\n`, \"utf-8\");\n\t\tchmodSync(authPath, 0o600);\n\t\treturn migrations;\n\t} catch {\n\t\treturn [];\n\t}\n}\n\ninterface JsonRewriteContext {\n\ttype: \"object\" | \"array\";\n\tpath: string[];\n\tpendingKey?: string;\n}\n\nfunction isProviderConfigPath(parentPath: string[]): boolean {\n\treturn parentPath.length === 2 && parentPath[0] === \"providers\";\n}\n\nfunction isMigratableHeadersPath(parentPath: string[]): boolean {\n\tif (parentPath[0] !== \"providers\") return false;\n\t// providers.<provider>.headers\n\tif (parentPath.length === 3 && parentPath[2] === \"headers\") return true;\n\t// providers.<provider>.models[].headers\n\tif (parentPath.length === 4 && parentPath[2] === \"models\" && parentPath[3] === \"headers\") return true;\n\t// providers.<provider>.modelOverrides.<modelId>.headers\n\tif (parentPath.length === 5 && parentPath[2] === \"modelOverrides\" && parentPath[4] === \"headers\") return true;\n\treturn false;\n}\n\nfunction migrationReplacementForKey(key: string, value: string, parentPath: string[], migrations: ConfigValueMigration[]): string | undefined {\n\tif (key !== \"apiKey\" && !isMigratableHeadersPath(parentPath)) return undefined;\n\tif (key === \"apiKey\" && !isProviderConfigPath(parentPath)) return undefined;\n\n\tfor (const migration of migrations) {\n\t\tif (migration.from !== value) continue;\n\t\tif (key === \"apiKey\" && migration.location.endsWith(\".apiKey\")) return migration.to;\n\t\tif (isMigratableHeadersPath(parentPath) && migration.location.includes(\".headers[\") && migration.location.endsWith(`[${JSON.stringify(key)}]`)) {\n\t\t\treturn migration.to;\n\t\t}\n\t}\n\treturn undefined;\n}\n\nfunction skipJsoncTrivia(content: string, index: number): number {\n\tlet current = index;\n\twhile (current < content.length) {\n\t\tconst char = content[current];\n\t\tconst next = content[current + 1];\n\t\tif (char !== undefined && /\\s/.test(char)) {\n\t\t\tcurrent++;\n\t\t\tcontinue;\n\t\t}\n\t\tif (char === \"/\" && next === \"/\") {\n\t\t\tcurrent += 2;\n\t\t\twhile (current < content.length && content[current] !== \"\\n\") current++;\n\t\t\tcontinue;\n\t\t}\n\t\tif (char === \"/\" && next === \"*\") {\n\t\t\tcurrent += 2;\n\t\t\twhile (current < content.length && !(content[current] === \"*\" && content[current + 1] === \"/\")) current++;\n\t\t\tcurrent = Math.min(content.length, current + 2);\n\t\t\tcontinue;\n\t\t}\n\t\tbreak;\n\t}\n\treturn current;\n}\n\nfunction replaceMigratedJsonStringValues(content: string, migrations: ConfigValueMigration[]): string {\n\tif (migrations.length === 0) return content;\n\n\tlet result = \"\";\n\tlet index = 0;\n\tlet inLineComment = false;\n\tlet inBlockComment = false;\n\tconst stack: JsonRewriteContext[] = [];\n\n\tfunction consumePendingContainerPath(): string[] {\n\t\tconst parent = stack[stack.length - 1];\n\t\tif (!parent) return [];\n\t\tif (parent.type === \"object\" && parent.pendingKey !== undefined) {\n\t\t\tconst path = [...parent.path, parent.pendingKey];\n\t\t\tparent.pendingKey = undefined;\n\t\t\treturn path;\n\t\t}\n\t\treturn [...parent.path];\n\t}\n\n\twhile (index < content.length) {\n\t\tconst char = content[index]!;\n\t\tconst next = content[index + 1];\n\n\t\tif (inLineComment) {\n\t\t\tresult += char;\n\t\t\tindex++;\n\t\t\tif (char === \"\\n\") inLineComment = false;\n\t\t\tcontinue;\n\t\t}\n\n\t\tif (inBlockComment) {\n\t\t\tresult += char;\n\t\t\tif (char === \"*\" && next === \"/\") {\n\t\t\t\tresult += next;\n\t\t\t\tindex += 2;\n\t\t\t\tinBlockComment = false;\n\t\t\t} else {\n\t\t\t\tindex++;\n\t\t\t}\n\t\t\tcontinue;\n\t\t}\n\n\t\tif (char === \"/\" && next === \"/\") {\n\t\t\tresult += char + next;\n\t\t\tindex += 2;\n\t\t\tinLineComment = true;\n\t\t\tcontinue;\n\t\t}\n\n\t\tif (char === \"/\" && next === \"*\") {\n\t\t\tresult += char + next;\n\t\t\tindex += 2;\n\t\t\tinBlockComment = true;\n\t\t\tcontinue;\n\t\t}\n\n\t\tif (char === \"{\") {\n\t\t\tstack.push({ type: \"object\", path: consumePendingContainerPath() });\n\t\t\tresult += char;\n\t\t\tindex++;\n\t\t\tcontinue;\n\t\t}\n\n\t\tif (char === \"[\") {\n\t\t\tstack.push({ type: \"array\", path: consumePendingContainerPath() });\n\t\t\tresult += char;\n\t\t\tindex++;\n\t\t\tcontinue;\n\t\t}\n\n\t\tif (char === \"}\" || char === \"]\") {\n\t\t\tstack.pop();\n\t\t\tresult += char;\n\t\t\tindex++;\n\t\t\tcontinue;\n\t\t}\n\n\t\tif (char !== '\"') {\n\t\t\tresult += char;\n\t\t\tindex++;\n\t\t\tcontinue;\n\t\t}\n\n\t\tconst stringStart = index;\n\t\tindex++;\n\t\tlet escaped = false;\n\t\twhile (index < content.length) {\n\t\t\tconst current = content[index]!;\n\t\t\tindex++;\n\t\t\tif (escaped) {\n\t\t\t\tescaped = false;\n\t\t\t\tcontinue;\n\t\t\t}\n\t\t\tif (current === \"\\\\\") {\n\t\t\t\tescaped = true;\n\t\t\t\tcontinue;\n\t\t\t}\n\t\t\tif (current === '\"') break;\n\t\t}\n\n\t\tconst rawString = content.slice(stringStart, index);\n\t\tconst activeContext = stack[stack.length - 1];\n\t\tconst afterString = skipJsoncTrivia(content, index);\n\t\tconst isObjectKey = activeContext?.type === \"object\" && content[afterString] === \":\";\n\n\t\tif (isObjectKey) {\n\t\t\ttry {\n\t\t\t\tactiveContext.pendingKey = JSON.parse(rawString) as string;\n\t\t\t} catch {\n\t\t\t\tactiveContext.pendingKey = undefined;\n\t\t\t}\n\t\t\tresult += rawString;\n\t\t\tcontinue;\n\t\t}\n\n\t\ttry {\n\t\t\tconst value = JSON.parse(rawString) as unknown;\n\t\t\tconst key = activeContext?.type === \"object\" ? activeContext.pendingKey : undefined;\n\t\t\tif (typeof value === \"string\" && key !== undefined) {\n\t\t\t\tconst migrated = migrationReplacementForKey(key, value, activeContext.path, migrations);\n\t\t\t\tresult += migrated === undefined ? rawString : JSON.stringify(migrated);\n\t\t\t\tactiveContext.pendingKey = undefined;\n\t\t\t} else {\n\t\t\t\tresult += rawString;\n\t\t\t}\n\t\t} catch {\n\t\t\tresult += rawString;\n\t\t}\n\t}\n\n\treturn result;\n}\n\nfunction migrateModelsJsonConfigValues(agentDir: string): ConfigValueMigration[] {\n\tconst modelsPath = join(agentDir, \"models.json\");\n\tif (!existsSync(modelsPath)) return [];\n\n\ttry {\n\t\tconst content = readFileSync(modelsPath, \"utf-8\");\n\t\tconst parsed = JSON.parse(stripJsonComments(content)) as unknown;\n\t\tif (typeof parsed !== \"object\" || parsed === null || Array.isArray(parsed)) return [];\n\t\tconst modelsData = parsed as Record<string, unknown>;\n\t\tconst providers = modelsData.providers;\n\t\tif (typeof providers !== \"object\" || providers === null || Array.isArray(providers)) return [];\n\n\t\tconst migrations: ConfigValueMigration[] = [];\n\t\tfor (const [provider, providerConfig] of Object.entries(providers)) {\n\t\t\tif (typeof providerConfig !== \"object\" || providerConfig === null || Array.isArray(providerConfig)) continue;\n\t\t\tconst providerRecord = providerConfig as Record<string, unknown>;\n\t\t\tconst providerLocation = `models.json.providers[${JSON.stringify(provider)}]`;\n\t\t\tmigrateStringProperty(providerRecord, \"apiKey\", `${providerLocation}.apiKey`, migrations);\n\t\t\tmigrateHeadersConfig(providerRecord.headers, `${providerLocation}.headers`, migrations);\n\n\t\t\tif (Array.isArray(providerRecord.models)) {\n\t\t\t\tfor (let index = 0; index < providerRecord.models.length; index++) {\n\t\t\t\t\tconst modelConfig = providerRecord.models[index];\n\t\t\t\t\tif (typeof modelConfig !== \"object\" || modelConfig === null || Array.isArray(modelConfig)) continue;\n\t\t\t\t\tconst modelRecord = modelConfig as Record<string, unknown>;\n\t\t\t\t\tconst modelKey = typeof modelRecord.id === \"string\" ? JSON.stringify(modelRecord.id) : String(index);\n\t\t\t\t\tmigrateHeadersConfig(modelRecord.headers, `${providerLocation}.models[${modelKey}].headers`, migrations);\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tconst modelOverrides = providerRecord.modelOverrides;\n\t\t\tif (typeof modelOverrides === \"object\" && modelOverrides !== null && !Array.isArray(modelOverrides)) {\n\t\t\t\tfor (const [modelId, modelOverride] of Object.entries(modelOverrides)) {\n\t\t\t\t\tif (typeof modelOverride !== \"object\" || modelOverride === null || Array.isArray(modelOverride))\n\t\t\t\t\t\tcontinue;\n\t\t\t\t\tconst modelOverrideRecord = modelOverride as Record<string, unknown>;\n\t\t\t\t\tmigrateHeadersConfig(\n\t\t\t\t\t\tmodelOverrideRecord.headers,\n\t\t\t\t\t\t`${providerLocation}.modelOverrides[${JSON.stringify(modelId)}].headers`,\n\t\t\t\t\t\tmigrations,\n\t\t\t\t\t);\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\tif (migrations.length === 0) return [];\n\t\twriteFileSync(modelsPath, replaceMigratedJsonStringValues(content, migrations), \"utf-8\");\n\t\treturn migrations;\n\t} catch {\n\t\treturn [];\n\t}\n}\n\nfunction getAgentDirsForConfigMigration(): string[] {\n\tconst dirs = new Set<string>();\n\tfor (const path of [...getAgentConfigPaths(\"auth.json\"), ...getAgentConfigPaths(\"models.json\")]) {\n\t\tdirs.add(dirname(path));\n\t}\n\treturn [...dirs];\n}\n\nfunction migrateExplicitEnvVarConfigValues(): void {\n\tconst migrations = getAgentDirsForConfigMigration().flatMap((agentDir) => [\n\t\t...migrateAuthJsonConfigValues(agentDir),\n\t\t...migrateModelsJsonConfigValues(agentDir),\n\t]);\n\tif (migrations.length === 0) return;\n\n\tconst details = migrations.map((migration) => ` - ${migration.location}: ${migration.from} -> ${migration.to}`);\n\tconsole.log(\n\t\tchalk.yellow(\n\t\t\t[\n\t\t\t\t\"Warning: Migrated API key/header environment references to explicit $ENV_VAR syntax. Plain strings will be treated as literals.\",\n\t\t\t\t...details,\n\t\t\t].join(\"\\n\"),\n\t\t),\n\t);\n}\n\n/**\n * Migrate sessions from ~/.pi/agent/*.jsonl to proper session directories.\n *\n * Bug in v0.30.0: Sessions were saved to ~/.pi/agent/ instead of\n * ~/.pi/agent/sessions/<encoded-cwd>/. This migration moves them\n * to the correct location based on the cwd in their session header.\n *\n * See: https://github.com/earendil-works/pi-mono/issues/320\n */\nexport function migrateSessionsFromAgentRoot(): void {\n\tconst agentDir = getAgentDir();\n\n\t// Find all .jsonl files directly in agentDir (not in subdirectories)\n\tlet files: string[];\n\ttry {\n\t\tfiles = readdirSync(agentDir)\n\t\t\t.filter((f) => f.endsWith(\".jsonl\"))\n\t\t\t.map((f) => join(agentDir, f));\n\t} catch {\n\t\treturn;\n\t}\n\n\tif (files.length === 0) return;\n\n\tfor (const file of files) {\n\t\ttry {\n\t\t\t// Read first line to get session header\n\t\t\tconst content = readFileSync(file, \"utf8\");\n\t\t\tconst firstLine = content.split(\"\\n\")[0];\n\t\t\tif (!firstLine?.trim()) continue;\n\n\t\t\tconst header = JSON.parse(firstLine);\n\t\t\tif (header.type !== \"session\" || !header.cwd) continue;\n\n\t\t\tconst cwd: string = header.cwd;\n\n\t\t\t// Compute the correct session directory (same encoding as session-manager.ts)\n\t\t\tconst safePath = `--${cwd.replace(/^[/\\\\]/, \"\").replace(/[/\\\\:]/g, \"-\")}--`;\n\t\t\tconst correctDir = join(agentDir, \"sessions\", safePath);\n\n\t\t\t// Create directory if needed\n\t\t\tif (!existsSync(correctDir)) {\n\t\t\t\tmkdirSync(correctDir, { recursive: true });\n\t\t\t}\n\n\t\t\t// Move the file\n\t\t\tconst fileName = file.split(\"/\").pop() || file.split(\"\\\\\").pop();\n\t\t\tconst newPath = join(correctDir, fileName!);\n\n\t\t\tif (existsSync(newPath)) continue; // Skip if target exists\n\n\t\t\trenameSync(file, newPath);\n\t\t} catch {\n\t\t\t// Skip files that can't be migrated\n\t\t}\n\t}\n}\n\n/**\n * Migrate commands/ to prompts/ if needed.\n * Works for both regular directories and symlinks.\n */\nfunction migrateCommandsToPrompts(baseDir: string, label: string): boolean {\n\tconst commandsDir = join(baseDir, \"commands\");\n\tconst promptsDir = join(baseDir, \"prompts\");\n\n\tif (existsSync(commandsDir) && !existsSync(promptsDir)) {\n\t\ttry {\n\t\t\trenameSync(commandsDir, promptsDir);\n\t\t\tconsole.log(chalk.green(`Migrated ${label} commands/ → prompts/`));\n\t\t\treturn true;\n\t\t} catch (err) {\n\t\t\tconsole.log(\n\t\t\t\tchalk.yellow(\n\t\t\t\t\t`Warning: Could not migrate ${label} commands/ to prompts/: ${err instanceof Error ? err.message : err}`,\n\t\t\t\t),\n\t\t\t);\n\t\t}\n\t}\n\treturn false;\n}\n\nfunction migrateKeybindingsConfigFile(): void {\n\tconst configPath = join(getAgentDir(), \"keybindings.json\");\n\tif (!existsSync(configPath)) return;\n\n\ttry {\n\t\tconst parsed = JSON.parse(readFileSync(configPath, \"utf-8\")) as unknown;\n\t\tif (typeof parsed !== \"object\" || parsed === null || Array.isArray(parsed)) {\n\t\t\treturn;\n\t\t}\n\t\tconst { config, migrated } = migrateKeybindingsConfig(parsed as Record<string, unknown>);\n\t\tif (!migrated) return;\n\t\twriteFileSync(configPath, `${JSON.stringify(config, null, 2)}\\n`, \"utf-8\");\n\t} catch {\n\t\t// Ignore malformed files during migration\n\t}\n}\n\n/**\n * Move fd/rg binaries from tools/ to bin/ if they exist.\n */\nfunction migrateToolsToBin(): void {\n\tconst agentDir = getAgentDir();\n\tconst toolsDir = join(agentDir, \"tools\");\n\tconst binDir = getBinDir();\n\n\tif (!existsSync(toolsDir)) return;\n\n\tconst binaries = [\"fd\", \"rg\", \"fd.exe\", \"rg.exe\"];\n\tlet movedAny = false;\n\n\tfor (const bin of binaries) {\n\t\tconst oldPath = join(toolsDir, bin);\n\t\tconst newPath = join(binDir, bin);\n\n\t\tif (existsSync(oldPath)) {\n\t\t\tif (!existsSync(binDir)) {\n\t\t\t\tmkdirSync(binDir, { recursive: true });\n\t\t\t}\n\t\t\tif (!existsSync(newPath)) {\n\t\t\t\ttry {\n\t\t\t\t\trenameSync(oldPath, newPath);\n\t\t\t\t\tmovedAny = true;\n\t\t\t\t} catch {\n\t\t\t\t\t// Ignore errors\n\t\t\t\t}\n\t\t\t} else {\n\t\t\t\t// Target exists, just delete the old one\n\t\t\t\ttry {\n\t\t\t\t\trmSync?.(oldPath, { force: true });\n\t\t\t\t} catch {\n\t\t\t\t\t// Ignore\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n\n\tif (movedAny) {\n\t\tconsole.log(chalk.green(`Migrated managed binaries tools/ → bin/`));\n\t}\n}\n\n/**\n * Check for deprecated hooks/ and tools/ directories.\n * Note: tools/ may contain fd/rg binaries extracted by pi, so only warn if it has other files.\n */\nfunction checkDeprecatedExtensionDirs(baseDir: string, label: string): string[] {\n\tconst hooksDir = join(baseDir, \"hooks\");\n\tconst toolsDir = join(baseDir, \"tools\");\n\tconst warnings: string[] = [];\n\n\tif (existsSync(hooksDir)) {\n\t\twarnings.push(`${label} hooks/ directory found. Hooks have been renamed to extensions.`);\n\t}\n\n\tif (existsSync(toolsDir)) {\n\t\t// Check if tools/ contains anything other than fd/rg (which are auto-extracted binaries)\n\t\ttry {\n\t\t\tconst entries = readdirSync(toolsDir);\n\t\t\tconst customTools = entries.filter((e) => {\n\t\t\t\tconst lower = e.toLowerCase();\n\t\t\t\treturn (\n\t\t\t\t\tlower !== \"fd\" && lower !== \"rg\" && lower !== \"fd.exe\" && lower !== \"rg.exe\" && !e.startsWith(\".\") // Ignore .DS_Store and other hidden files\n\t\t\t\t);\n\t\t\t});\n\t\t\tif (customTools.length > 0) {\n\t\t\t\twarnings.push(\n\t\t\t\t\t`${label} tools/ directory contains custom tools. Custom tools have been merged into extensions.`,\n\t\t\t\t);\n\t\t\t}\n\t\t} catch {\n\t\t\t// Ignore read errors\n\t\t}\n\t}\n\n\treturn warnings;\n}\n\n/**\n * Run extension system migrations (commands→prompts) and collect warnings about deprecated directories.\n */\nfunction migrateExtensionSystem(cwd: string, options?: { projectTrusted?: boolean }): string[] {\n\tconst agentDir = getAgentDir();\n\tconst projectDir = join(cwd, CONFIG_DIR_NAME);\n\n\t// Migrate commands/ to prompts/\n\tmigrateCommandsToPrompts(agentDir, \"Global\");\n\tif (options?.projectTrusted !== false) {\n\t\tmigrateCommandsToPrompts(projectDir, \"Project\");\n\t}\n\n\t// Check for deprecated directories\n\tconst warnings = [\n\t\t...checkDeprecatedExtensionDirs(agentDir, \"Global\"),\n\t\t...(options?.projectTrusted === false ? [] : checkDeprecatedExtensionDirs(projectDir, \"Project\")),\n\t];\n\n\treturn warnings;\n}\n\n/**\n * Print deprecation warnings and wait for keypress.\n */\nexport async function showDeprecationWarnings(warnings: string[]): Promise<void> {\n\tif (warnings.length === 0) return;\n\n\tfor (const warning of warnings) {\n\t\tconsole.log(chalk.yellow(`Warning: ${warning}`));\n\t}\n\tconsole.log(chalk.yellow(`\\nMove your extensions to the extensions/ directory.`));\n\tconsole.log(chalk.yellow(`Migration guide: ${MIGRATION_GUIDE_URL}`));\n\tconsole.log(chalk.yellow(`Documentation: ${EXTENSIONS_DOC_URL}`));\n\tconsole.log(chalk.dim(`\\nPress any key to continue...`));\n\n\tawait new Promise<void>((resolve) => {\n\t\tprocess.stdin.setRawMode?.(true);\n\t\tprocess.stdin.resume();\n\t\tprocess.stdin.once(\"data\", () => {\n\t\t\tprocess.stdin.setRawMode?.(false);\n\t\t\tprocess.stdin.pause();\n\t\t\tresolve();\n\t\t});\n\t});\n\tconsole.log();\n}\n\n/**\n * Run all migrations. Called once on startup.\n *\n * @returns Object with migration results and deprecation warnings\n */\nexport function runMigrations(\n\tcwd: string,\n\toptions?: { projectTrusted?: boolean },\n): {\n\tmigratedAuthProviders: string[];\n\tdeprecationWarnings: string[];\n} {\n\tconst migratedAuthProviders = migrateAuthToAuthJson();\n\tmigrateExplicitEnvVarConfigValues();\n\tmigrateSessionsFromAgentRoot();\n\tmigrateToolsToBin();\n\tmigrateKeybindingsConfigFile();\n\tconst deprecationWarnings = migrateExtensionSystem(cwd, options);\n\treturn { migratedAuthProviders, deprecationWarnings };\n}\n"]}
@@ -2,10 +2,12 @@
2
2
  * One-time migrations that run on startup.
3
3
  */
4
4
  import chalk from "chalk";
5
- import { existsSync, mkdirSync, readdirSync, readFileSync, renameSync, rmSync, writeFileSync } from "fs";
5
+ import { chmodSync, existsSync, mkdirSync, readdirSync, readFileSync, renameSync, rmSync, writeFileSync } from "fs";
6
6
  import { dirname, join } from "path";
7
- import { CONFIG_DIR_NAME, getAgentDir, getBinDir } from "./config.js";
7
+ import { CONFIG_DIR_NAME, getAgentConfigPaths, getAgentDir, getBinDir } from "./config.js";
8
8
  import { migrateKeybindingsConfig } from "./core/keybindings.js";
9
+ import { isLegacyEnvVarNameConfigValue } from "./core/resolve-config-value.js";
10
+ import { stripJsonComments } from "./utils/json.js";
9
11
  const MIGRATION_GUIDE_URL = "https://github.com/earendil-works/pi-mono/blob/main/packages/coding-agent/CHANGELOG.md#extensions-migration";
10
12
  const EXTENSIONS_DOC_URL = "https://github.com/earendil-works/pi-mono/blob/main/packages/coding-agent/docs/extensions.md";
11
13
  /**
@@ -63,6 +65,319 @@ export function migrateAuthToAuthJson() {
63
65
  }
64
66
  return providers;
65
67
  }
68
+ function migrateLegacyEnvVarString(value) {
69
+ return isLegacyEnvVarNameConfigValue(value) && process.env[value] !== undefined ? `$${value}` : undefined;
70
+ }
71
+ function migrateStringProperty(record, key, location, migrations) {
72
+ const value = record[key];
73
+ if (typeof value !== "string")
74
+ return false;
75
+ const migrated = migrateLegacyEnvVarString(value);
76
+ if (migrated === undefined)
77
+ return false;
78
+ record[key] = migrated;
79
+ migrations.push({ location, from: value, to: migrated });
80
+ return true;
81
+ }
82
+ function migrateHeadersConfig(headers, location, migrations) {
83
+ if (typeof headers !== "object" || headers === null || Array.isArray(headers))
84
+ return false;
85
+ const headerRecord = headers;
86
+ let migrated = false;
87
+ for (const [key, value] of Object.entries(headerRecord)) {
88
+ if (typeof value !== "string")
89
+ continue;
90
+ const migratedValue = migrateLegacyEnvVarString(value);
91
+ if (migratedValue === undefined)
92
+ continue;
93
+ headerRecord[key] = migratedValue;
94
+ migrations.push({ location: `${location}[${JSON.stringify(key)}]`, from: value, to: migratedValue });
95
+ migrated = true;
96
+ }
97
+ return migrated;
98
+ }
99
+ function migrateAuthJsonConfigValues(agentDir) {
100
+ const authPath = join(agentDir, "auth.json");
101
+ if (!existsSync(authPath))
102
+ return [];
103
+ try {
104
+ const parsed = JSON.parse(readFileSync(authPath, "utf-8"));
105
+ if (typeof parsed !== "object" || parsed === null || Array.isArray(parsed))
106
+ return [];
107
+ const authData = parsed;
108
+ const migrations = [];
109
+ for (const [provider, credential] of Object.entries(authData)) {
110
+ if (typeof credential !== "object" || credential === null || Array.isArray(credential))
111
+ continue;
112
+ const credentialRecord = credential;
113
+ if (credentialRecord.type !== "api_key")
114
+ continue;
115
+ migrateStringProperty(credentialRecord, "key", `auth.json[${JSON.stringify(provider)}].key`, migrations);
116
+ }
117
+ if (migrations.length === 0)
118
+ return [];
119
+ writeFileSync(authPath, `${JSON.stringify(parsed, null, 2)}\n`, "utf-8");
120
+ chmodSync(authPath, 0o600);
121
+ return migrations;
122
+ }
123
+ catch {
124
+ return [];
125
+ }
126
+ }
127
+ function isProviderConfigPath(parentPath) {
128
+ return parentPath.length === 2 && parentPath[0] === "providers";
129
+ }
130
+ function isMigratableHeadersPath(parentPath) {
131
+ if (parentPath[0] !== "providers")
132
+ return false;
133
+ // providers.<provider>.headers
134
+ if (parentPath.length === 3 && parentPath[2] === "headers")
135
+ return true;
136
+ // providers.<provider>.models[].headers
137
+ if (parentPath.length === 4 && parentPath[2] === "models" && parentPath[3] === "headers")
138
+ return true;
139
+ // providers.<provider>.modelOverrides.<modelId>.headers
140
+ if (parentPath.length === 5 && parentPath[2] === "modelOverrides" && parentPath[4] === "headers")
141
+ return true;
142
+ return false;
143
+ }
144
+ function migrationReplacementForKey(key, value, parentPath, migrations) {
145
+ if (key !== "apiKey" && !isMigratableHeadersPath(parentPath))
146
+ return undefined;
147
+ if (key === "apiKey" && !isProviderConfigPath(parentPath))
148
+ return undefined;
149
+ for (const migration of migrations) {
150
+ if (migration.from !== value)
151
+ continue;
152
+ if (key === "apiKey" && migration.location.endsWith(".apiKey"))
153
+ return migration.to;
154
+ if (isMigratableHeadersPath(parentPath) && migration.location.includes(".headers[") && migration.location.endsWith(`[${JSON.stringify(key)}]`)) {
155
+ return migration.to;
156
+ }
157
+ }
158
+ return undefined;
159
+ }
160
+ function skipJsoncTrivia(content, index) {
161
+ let current = index;
162
+ while (current < content.length) {
163
+ const char = content[current];
164
+ const next = content[current + 1];
165
+ if (char !== undefined && /\s/.test(char)) {
166
+ current++;
167
+ continue;
168
+ }
169
+ if (char === "/" && next === "/") {
170
+ current += 2;
171
+ while (current < content.length && content[current] !== "\n")
172
+ current++;
173
+ continue;
174
+ }
175
+ if (char === "/" && next === "*") {
176
+ current += 2;
177
+ while (current < content.length && !(content[current] === "*" && content[current + 1] === "/"))
178
+ current++;
179
+ current = Math.min(content.length, current + 2);
180
+ continue;
181
+ }
182
+ break;
183
+ }
184
+ return current;
185
+ }
186
+ function replaceMigratedJsonStringValues(content, migrations) {
187
+ if (migrations.length === 0)
188
+ return content;
189
+ let result = "";
190
+ let index = 0;
191
+ let inLineComment = false;
192
+ let inBlockComment = false;
193
+ const stack = [];
194
+ function consumePendingContainerPath() {
195
+ const parent = stack[stack.length - 1];
196
+ if (!parent)
197
+ return [];
198
+ if (parent.type === "object" && parent.pendingKey !== undefined) {
199
+ const path = [...parent.path, parent.pendingKey];
200
+ parent.pendingKey = undefined;
201
+ return path;
202
+ }
203
+ return [...parent.path];
204
+ }
205
+ while (index < content.length) {
206
+ const char = content[index];
207
+ const next = content[index + 1];
208
+ if (inLineComment) {
209
+ result += char;
210
+ index++;
211
+ if (char === "\n")
212
+ inLineComment = false;
213
+ continue;
214
+ }
215
+ if (inBlockComment) {
216
+ result += char;
217
+ if (char === "*" && next === "/") {
218
+ result += next;
219
+ index += 2;
220
+ inBlockComment = false;
221
+ }
222
+ else {
223
+ index++;
224
+ }
225
+ continue;
226
+ }
227
+ if (char === "/" && next === "/") {
228
+ result += char + next;
229
+ index += 2;
230
+ inLineComment = true;
231
+ continue;
232
+ }
233
+ if (char === "/" && next === "*") {
234
+ result += char + next;
235
+ index += 2;
236
+ inBlockComment = true;
237
+ continue;
238
+ }
239
+ if (char === "{") {
240
+ stack.push({ type: "object", path: consumePendingContainerPath() });
241
+ result += char;
242
+ index++;
243
+ continue;
244
+ }
245
+ if (char === "[") {
246
+ stack.push({ type: "array", path: consumePendingContainerPath() });
247
+ result += char;
248
+ index++;
249
+ continue;
250
+ }
251
+ if (char === "}" || char === "]") {
252
+ stack.pop();
253
+ result += char;
254
+ index++;
255
+ continue;
256
+ }
257
+ if (char !== '"') {
258
+ result += char;
259
+ index++;
260
+ continue;
261
+ }
262
+ const stringStart = index;
263
+ index++;
264
+ let escaped = false;
265
+ while (index < content.length) {
266
+ const current = content[index];
267
+ index++;
268
+ if (escaped) {
269
+ escaped = false;
270
+ continue;
271
+ }
272
+ if (current === "\\") {
273
+ escaped = true;
274
+ continue;
275
+ }
276
+ if (current === '"')
277
+ break;
278
+ }
279
+ const rawString = content.slice(stringStart, index);
280
+ const activeContext = stack[stack.length - 1];
281
+ const afterString = skipJsoncTrivia(content, index);
282
+ const isObjectKey = activeContext?.type === "object" && content[afterString] === ":";
283
+ if (isObjectKey) {
284
+ try {
285
+ activeContext.pendingKey = JSON.parse(rawString);
286
+ }
287
+ catch {
288
+ activeContext.pendingKey = undefined;
289
+ }
290
+ result += rawString;
291
+ continue;
292
+ }
293
+ try {
294
+ const value = JSON.parse(rawString);
295
+ const key = activeContext?.type === "object" ? activeContext.pendingKey : undefined;
296
+ if (typeof value === "string" && key !== undefined) {
297
+ const migrated = migrationReplacementForKey(key, value, activeContext.path, migrations);
298
+ result += migrated === undefined ? rawString : JSON.stringify(migrated);
299
+ activeContext.pendingKey = undefined;
300
+ }
301
+ else {
302
+ result += rawString;
303
+ }
304
+ }
305
+ catch {
306
+ result += rawString;
307
+ }
308
+ }
309
+ return result;
310
+ }
311
+ function migrateModelsJsonConfigValues(agentDir) {
312
+ const modelsPath = join(agentDir, "models.json");
313
+ if (!existsSync(modelsPath))
314
+ return [];
315
+ try {
316
+ const content = readFileSync(modelsPath, "utf-8");
317
+ const parsed = JSON.parse(stripJsonComments(content));
318
+ if (typeof parsed !== "object" || parsed === null || Array.isArray(parsed))
319
+ return [];
320
+ const modelsData = parsed;
321
+ const providers = modelsData.providers;
322
+ if (typeof providers !== "object" || providers === null || Array.isArray(providers))
323
+ return [];
324
+ const migrations = [];
325
+ for (const [provider, providerConfig] of Object.entries(providers)) {
326
+ if (typeof providerConfig !== "object" || providerConfig === null || Array.isArray(providerConfig))
327
+ continue;
328
+ const providerRecord = providerConfig;
329
+ const providerLocation = `models.json.providers[${JSON.stringify(provider)}]`;
330
+ migrateStringProperty(providerRecord, "apiKey", `${providerLocation}.apiKey`, migrations);
331
+ migrateHeadersConfig(providerRecord.headers, `${providerLocation}.headers`, migrations);
332
+ if (Array.isArray(providerRecord.models)) {
333
+ for (let index = 0; index < providerRecord.models.length; index++) {
334
+ const modelConfig = providerRecord.models[index];
335
+ if (typeof modelConfig !== "object" || modelConfig === null || Array.isArray(modelConfig))
336
+ continue;
337
+ const modelRecord = modelConfig;
338
+ const modelKey = typeof modelRecord.id === "string" ? JSON.stringify(modelRecord.id) : String(index);
339
+ migrateHeadersConfig(modelRecord.headers, `${providerLocation}.models[${modelKey}].headers`, migrations);
340
+ }
341
+ }
342
+ const modelOverrides = providerRecord.modelOverrides;
343
+ if (typeof modelOverrides === "object" && modelOverrides !== null && !Array.isArray(modelOverrides)) {
344
+ for (const [modelId, modelOverride] of Object.entries(modelOverrides)) {
345
+ if (typeof modelOverride !== "object" || modelOverride === null || Array.isArray(modelOverride))
346
+ continue;
347
+ const modelOverrideRecord = modelOverride;
348
+ migrateHeadersConfig(modelOverrideRecord.headers, `${providerLocation}.modelOverrides[${JSON.stringify(modelId)}].headers`, migrations);
349
+ }
350
+ }
351
+ }
352
+ if (migrations.length === 0)
353
+ return [];
354
+ writeFileSync(modelsPath, replaceMigratedJsonStringValues(content, migrations), "utf-8");
355
+ return migrations;
356
+ }
357
+ catch {
358
+ return [];
359
+ }
360
+ }
361
+ function getAgentDirsForConfigMigration() {
362
+ const dirs = new Set();
363
+ for (const path of [...getAgentConfigPaths("auth.json"), ...getAgentConfigPaths("models.json")]) {
364
+ dirs.add(dirname(path));
365
+ }
366
+ return [...dirs];
367
+ }
368
+ function migrateExplicitEnvVarConfigValues() {
369
+ const migrations = getAgentDirsForConfigMigration().flatMap((agentDir) => [
370
+ ...migrateAuthJsonConfigValues(agentDir),
371
+ ...migrateModelsJsonConfigValues(agentDir),
372
+ ]);
373
+ if (migrations.length === 0)
374
+ return;
375
+ const details = migrations.map((migration) => ` - ${migration.location}: ${migration.from} -> ${migration.to}`);
376
+ console.log(chalk.yellow([
377
+ "Warning: Migrated API key/header environment references to explicit $ENV_VAR syntax. Plain strings will be treated as literals.",
378
+ ...details,
379
+ ].join("\n")));
380
+ }
66
381
  /**
67
382
  * Migrate sessions from ~/.pi/agent/*.jsonl to proper session directories.
68
383
  *
@@ -228,16 +543,18 @@ function checkDeprecatedExtensionDirs(baseDir, label) {
228
543
  /**
229
544
  * Run extension system migrations (commands→prompts) and collect warnings about deprecated directories.
230
545
  */
231
- function migrateExtensionSystem(cwd) {
546
+ function migrateExtensionSystem(cwd, options) {
232
547
  const agentDir = getAgentDir();
233
548
  const projectDir = join(cwd, CONFIG_DIR_NAME);
234
549
  // Migrate commands/ to prompts/
235
550
  migrateCommandsToPrompts(agentDir, "Global");
236
- migrateCommandsToPrompts(projectDir, "Project");
551
+ if (options?.projectTrusted !== false) {
552
+ migrateCommandsToPrompts(projectDir, "Project");
553
+ }
237
554
  // Check for deprecated directories
238
555
  const warnings = [
239
556
  ...checkDeprecatedExtensionDirs(agentDir, "Global"),
240
- ...checkDeprecatedExtensionDirs(projectDir, "Project"),
557
+ ...(options?.projectTrusted === false ? [] : checkDeprecatedExtensionDirs(projectDir, "Project")),
241
558
  ];
242
559
  return warnings;
243
560
  }
@@ -270,12 +587,13 @@ export async function showDeprecationWarnings(warnings) {
270
587
  *
271
588
  * @returns Object with migration results and deprecation warnings
272
589
  */
273
- export function runMigrations(cwd) {
590
+ export function runMigrations(cwd, options) {
274
591
  const migratedAuthProviders = migrateAuthToAuthJson();
592
+ migrateExplicitEnvVarConfigValues();
275
593
  migrateSessionsFromAgentRoot();
276
594
  migrateToolsToBin();
277
595
  migrateKeybindingsConfigFile();
278
- const deprecationWarnings = migrateExtensionSystem(cwd);
596
+ const deprecationWarnings = migrateExtensionSystem(cwd, options);
279
597
  return { migratedAuthProviders, deprecationWarnings };
280
598
  }
281
599
  //# sourceMappingURL=migrations.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"migrations.js","sourceRoot":"","sources":["../src/migrations.ts"],"names":[],"mappings":"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","sourcesContent":["/**\n * One-time migrations that run on startup.\n */\n\nimport chalk from \"chalk\";\nimport { existsSync, mkdirSync, readdirSync, readFileSync, renameSync, rmSync, writeFileSync } from \"fs\";\nimport { dirname, join } from \"path\";\nimport { CONFIG_DIR_NAME, getAgentDir, getBinDir } from \"./config.ts\";\nimport { migrateKeybindingsConfig } from \"./core/keybindings.ts\";\n\nconst MIGRATION_GUIDE_URL =\n\t\"https://github.com/earendil-works/pi-mono/blob/main/packages/coding-agent/CHANGELOG.md#extensions-migration\";\nconst EXTENSIONS_DOC_URL =\n\t\"https://github.com/earendil-works/pi-mono/blob/main/packages/coding-agent/docs/extensions.md\";\n\n/**\n * Migrate legacy oauth.json and settings.json apiKeys to auth.json.\n *\n * @returns Array of provider names that were migrated\n */\nexport function migrateAuthToAuthJson(): string[] {\n\tconst agentDir = getAgentDir();\n\tconst authPath = join(agentDir, \"auth.json\");\n\tconst oauthPath = join(agentDir, \"oauth.json\");\n\tconst settingsPath = join(agentDir, \"settings.json\");\n\n\t// Skip if auth.json already exists\n\tif (existsSync(authPath)) return [];\n\n\tconst migrated: Record<string, unknown> = {};\n\tconst providers: string[] = [];\n\n\t// Migrate oauth.json\n\tif (existsSync(oauthPath)) {\n\t\ttry {\n\t\t\tconst oauth = JSON.parse(readFileSync(oauthPath, \"utf-8\"));\n\t\t\tfor (const [provider, cred] of Object.entries(oauth)) {\n\t\t\t\tmigrated[provider] = { type: \"oauth\", ...(cred as object) };\n\t\t\t\tproviders.push(provider);\n\t\t\t}\n\t\t\trenameSync(oauthPath, `${oauthPath}.migrated`);\n\t\t} catch {\n\t\t\t// Skip on error\n\t\t}\n\t}\n\n\t// Migrate settings.json apiKeys\n\tif (existsSync(settingsPath)) {\n\t\ttry {\n\t\t\tconst content = readFileSync(settingsPath, \"utf-8\");\n\t\t\tconst settings = JSON.parse(content);\n\t\t\tif (settings.apiKeys && typeof settings.apiKeys === \"object\") {\n\t\t\t\tfor (const [provider, key] of Object.entries(settings.apiKeys)) {\n\t\t\t\t\tif (!migrated[provider] && typeof key === \"string\") {\n\t\t\t\t\t\tmigrated[provider] = { type: \"api_key\", key };\n\t\t\t\t\t\tproviders.push(provider);\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\tdelete settings.apiKeys;\n\t\t\t\twriteFileSync(settingsPath, JSON.stringify(settings, null, 2));\n\t\t\t}\n\t\t} catch {\n\t\t\t// Skip on error\n\t\t}\n\t}\n\n\tif (Object.keys(migrated).length > 0) {\n\t\tmkdirSync(dirname(authPath), { recursive: true });\n\t\twriteFileSync(authPath, JSON.stringify(migrated, null, 2), { mode: 0o600 });\n\t}\n\n\treturn providers;\n}\n\n/**\n * Migrate sessions from ~/.pi/agent/*.jsonl to proper session directories.\n *\n * Bug in v0.30.0: Sessions were saved to ~/.pi/agent/ instead of\n * ~/.pi/agent/sessions/<encoded-cwd>/. This migration moves them\n * to the correct location based on the cwd in their session header.\n *\n * See: https://github.com/earendil-works/pi-mono/issues/320\n */\nexport function migrateSessionsFromAgentRoot(): void {\n\tconst agentDir = getAgentDir();\n\n\t// Find all .jsonl files directly in agentDir (not in subdirectories)\n\tlet files: string[];\n\ttry {\n\t\tfiles = readdirSync(agentDir)\n\t\t\t.filter((f) => f.endsWith(\".jsonl\"))\n\t\t\t.map((f) => join(agentDir, f));\n\t} catch {\n\t\treturn;\n\t}\n\n\tif (files.length === 0) return;\n\n\tfor (const file of files) {\n\t\ttry {\n\t\t\t// Read first line to get session header\n\t\t\tconst content = readFileSync(file, \"utf8\");\n\t\t\tconst firstLine = content.split(\"\\n\")[0];\n\t\t\tif (!firstLine?.trim()) continue;\n\n\t\t\tconst header = JSON.parse(firstLine);\n\t\t\tif (header.type !== \"session\" || !header.cwd) continue;\n\n\t\t\tconst cwd: string = header.cwd;\n\n\t\t\t// Compute the correct session directory (same encoding as session-manager.ts)\n\t\t\tconst safePath = `--${cwd.replace(/^[/\\\\]/, \"\").replace(/[/\\\\:]/g, \"-\")}--`;\n\t\t\tconst correctDir = join(agentDir, \"sessions\", safePath);\n\n\t\t\t// Create directory if needed\n\t\t\tif (!existsSync(correctDir)) {\n\t\t\t\tmkdirSync(correctDir, { recursive: true });\n\t\t\t}\n\n\t\t\t// Move the file\n\t\t\tconst fileName = file.split(\"/\").pop() || file.split(\"\\\\\").pop();\n\t\t\tconst newPath = join(correctDir, fileName!);\n\n\t\t\tif (existsSync(newPath)) continue; // Skip if target exists\n\n\t\t\trenameSync(file, newPath);\n\t\t} catch {\n\t\t\t// Skip files that can't be migrated\n\t\t}\n\t}\n}\n\n/**\n * Migrate commands/ to prompts/ if needed.\n * Works for both regular directories and symlinks.\n */\nfunction migrateCommandsToPrompts(baseDir: string, label: string): boolean {\n\tconst commandsDir = join(baseDir, \"commands\");\n\tconst promptsDir = join(baseDir, \"prompts\");\n\n\tif (existsSync(commandsDir) && !existsSync(promptsDir)) {\n\t\ttry {\n\t\t\trenameSync(commandsDir, promptsDir);\n\t\t\tconsole.log(chalk.green(`Migrated ${label} commands/ → prompts/`));\n\t\t\treturn true;\n\t\t} catch (err) {\n\t\t\tconsole.log(\n\t\t\t\tchalk.yellow(\n\t\t\t\t\t`Warning: Could not migrate ${label} commands/ to prompts/: ${err instanceof Error ? err.message : err}`,\n\t\t\t\t),\n\t\t\t);\n\t\t}\n\t}\n\treturn false;\n}\n\nfunction migrateKeybindingsConfigFile(): void {\n\tconst configPath = join(getAgentDir(), \"keybindings.json\");\n\tif (!existsSync(configPath)) return;\n\n\ttry {\n\t\tconst parsed = JSON.parse(readFileSync(configPath, \"utf-8\")) as unknown;\n\t\tif (typeof parsed !== \"object\" || parsed === null || Array.isArray(parsed)) {\n\t\t\treturn;\n\t\t}\n\t\tconst { config, migrated } = migrateKeybindingsConfig(parsed as Record<string, unknown>);\n\t\tif (!migrated) return;\n\t\twriteFileSync(configPath, `${JSON.stringify(config, null, 2)}\\n`, \"utf-8\");\n\t} catch {\n\t\t// Ignore malformed files during migration\n\t}\n}\n\n/**\n * Move fd/rg binaries from tools/ to bin/ if they exist.\n */\nfunction migrateToolsToBin(): void {\n\tconst agentDir = getAgentDir();\n\tconst toolsDir = join(agentDir, \"tools\");\n\tconst binDir = getBinDir();\n\n\tif (!existsSync(toolsDir)) return;\n\n\tconst binaries = [\"fd\", \"rg\", \"fd.exe\", \"rg.exe\"];\n\tlet movedAny = false;\n\n\tfor (const bin of binaries) {\n\t\tconst oldPath = join(toolsDir, bin);\n\t\tconst newPath = join(binDir, bin);\n\n\t\tif (existsSync(oldPath)) {\n\t\t\tif (!existsSync(binDir)) {\n\t\t\t\tmkdirSync(binDir, { recursive: true });\n\t\t\t}\n\t\t\tif (!existsSync(newPath)) {\n\t\t\t\ttry {\n\t\t\t\t\trenameSync(oldPath, newPath);\n\t\t\t\t\tmovedAny = true;\n\t\t\t\t} catch {\n\t\t\t\t\t// Ignore errors\n\t\t\t\t}\n\t\t\t} else {\n\t\t\t\t// Target exists, just delete the old one\n\t\t\t\ttry {\n\t\t\t\t\trmSync?.(oldPath, { force: true });\n\t\t\t\t} catch {\n\t\t\t\t\t// Ignore\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n\n\tif (movedAny) {\n\t\tconsole.log(chalk.green(`Migrated managed binaries tools/ → bin/`));\n\t}\n}\n\n/**\n * Check for deprecated hooks/ and tools/ directories.\n * Note: tools/ may contain fd/rg binaries extracted by pi, so only warn if it has other files.\n */\nfunction checkDeprecatedExtensionDirs(baseDir: string, label: string): string[] {\n\tconst hooksDir = join(baseDir, \"hooks\");\n\tconst toolsDir = join(baseDir, \"tools\");\n\tconst warnings: string[] = [];\n\n\tif (existsSync(hooksDir)) {\n\t\twarnings.push(`${label} hooks/ directory found. Hooks have been renamed to extensions.`);\n\t}\n\n\tif (existsSync(toolsDir)) {\n\t\t// Check if tools/ contains anything other than fd/rg (which are auto-extracted binaries)\n\t\ttry {\n\t\t\tconst entries = readdirSync(toolsDir);\n\t\t\tconst customTools = entries.filter((e) => {\n\t\t\t\tconst lower = e.toLowerCase();\n\t\t\t\treturn (\n\t\t\t\t\tlower !== \"fd\" && lower !== \"rg\" && lower !== \"fd.exe\" && lower !== \"rg.exe\" && !e.startsWith(\".\") // Ignore .DS_Store and other hidden files\n\t\t\t\t);\n\t\t\t});\n\t\t\tif (customTools.length > 0) {\n\t\t\t\twarnings.push(\n\t\t\t\t\t`${label} tools/ directory contains custom tools. Custom tools have been merged into extensions.`,\n\t\t\t\t);\n\t\t\t}\n\t\t} catch {\n\t\t\t// Ignore read errors\n\t\t}\n\t}\n\n\treturn warnings;\n}\n\n/**\n * Run extension system migrations (commands→prompts) and collect warnings about deprecated directories.\n */\nfunction migrateExtensionSystem(cwd: string): string[] {\n\tconst agentDir = getAgentDir();\n\tconst projectDir = join(cwd, CONFIG_DIR_NAME);\n\n\t// Migrate commands/ to prompts/\n\tmigrateCommandsToPrompts(agentDir, \"Global\");\n\tmigrateCommandsToPrompts(projectDir, \"Project\");\n\n\t// Check for deprecated directories\n\tconst warnings = [\n\t\t...checkDeprecatedExtensionDirs(agentDir, \"Global\"),\n\t\t...checkDeprecatedExtensionDirs(projectDir, \"Project\"),\n\t];\n\n\treturn warnings;\n}\n\n/**\n * Print deprecation warnings and wait for keypress.\n */\nexport async function showDeprecationWarnings(warnings: string[]): Promise<void> {\n\tif (warnings.length === 0) return;\n\n\tfor (const warning of warnings) {\n\t\tconsole.log(chalk.yellow(`Warning: ${warning}`));\n\t}\n\tconsole.log(chalk.yellow(`\\nMove your extensions to the extensions/ directory.`));\n\tconsole.log(chalk.yellow(`Migration guide: ${MIGRATION_GUIDE_URL}`));\n\tconsole.log(chalk.yellow(`Documentation: ${EXTENSIONS_DOC_URL}`));\n\tconsole.log(chalk.dim(`\\nPress any key to continue...`));\n\n\tawait new Promise<void>((resolve) => {\n\t\tprocess.stdin.setRawMode?.(true);\n\t\tprocess.stdin.resume();\n\t\tprocess.stdin.once(\"data\", () => {\n\t\t\tprocess.stdin.setRawMode?.(false);\n\t\t\tprocess.stdin.pause();\n\t\t\tresolve();\n\t\t});\n\t});\n\tconsole.log();\n}\n\n/**\n * Run all migrations. Called once on startup.\n *\n * @returns Object with migration results and deprecation warnings\n */\nexport function runMigrations(cwd: string): {\n\tmigratedAuthProviders: string[];\n\tdeprecationWarnings: string[];\n} {\n\tconst migratedAuthProviders = migrateAuthToAuthJson();\n\tmigrateSessionsFromAgentRoot();\n\tmigrateToolsToBin();\n\tmigrateKeybindingsConfigFile();\n\tconst deprecationWarnings = migrateExtensionSystem(cwd);\n\treturn { migratedAuthProviders, deprecationWarnings };\n}\n"]}
1
+ {"version":3,"file":"migrations.js","sourceRoot":"","sources":["../src/migrations.ts"],"names":[],"mappings":"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","sourcesContent":["/**\n * One-time migrations that run on startup.\n */\n\nimport chalk from \"chalk\";\nimport { chmodSync, existsSync, mkdirSync, readdirSync, readFileSync, renameSync, rmSync, writeFileSync } from \"fs\";\nimport { dirname, join } from \"path\";\nimport { CONFIG_DIR_NAME, getAgentConfigPaths, getAgentDir, getBinDir } from \"./config.ts\";\nimport { migrateKeybindingsConfig } from \"./core/keybindings.ts\";\nimport { isLegacyEnvVarNameConfigValue } from \"./core/resolve-config-value.ts\";\nimport { stripJsonComments } from \"./utils/json.ts\";\n\nconst MIGRATION_GUIDE_URL =\n\t\"https://github.com/earendil-works/pi-mono/blob/main/packages/coding-agent/CHANGELOG.md#extensions-migration\";\nconst EXTENSIONS_DOC_URL =\n\t\"https://github.com/earendil-works/pi-mono/blob/main/packages/coding-agent/docs/extensions.md\";\n\n/**\n * Migrate legacy oauth.json and settings.json apiKeys to auth.json.\n *\n * @returns Array of provider names that were migrated\n */\nexport function migrateAuthToAuthJson(): string[] {\n\tconst agentDir = getAgentDir();\n\tconst authPath = join(agentDir, \"auth.json\");\n\tconst oauthPath = join(agentDir, \"oauth.json\");\n\tconst settingsPath = join(agentDir, \"settings.json\");\n\n\t// Skip if auth.json already exists\n\tif (existsSync(authPath)) return [];\n\n\tconst migrated: Record<string, unknown> = {};\n\tconst providers: string[] = [];\n\n\t// Migrate oauth.json\n\tif (existsSync(oauthPath)) {\n\t\ttry {\n\t\t\tconst oauth = JSON.parse(readFileSync(oauthPath, \"utf-8\"));\n\t\t\tfor (const [provider, cred] of Object.entries(oauth)) {\n\t\t\t\tmigrated[provider] = { type: \"oauth\", ...(cred as object) };\n\t\t\t\tproviders.push(provider);\n\t\t\t}\n\t\t\trenameSync(oauthPath, `${oauthPath}.migrated`);\n\t\t} catch {\n\t\t\t// Skip on error\n\t\t}\n\t}\n\n\t// Migrate settings.json apiKeys\n\tif (existsSync(settingsPath)) {\n\t\ttry {\n\t\t\tconst content = readFileSync(settingsPath, \"utf-8\");\n\t\t\tconst settings = JSON.parse(content);\n\t\t\tif (settings.apiKeys && typeof settings.apiKeys === \"object\") {\n\t\t\t\tfor (const [provider, key] of Object.entries(settings.apiKeys)) {\n\t\t\t\t\tif (!migrated[provider] && typeof key === \"string\") {\n\t\t\t\t\t\tmigrated[provider] = { type: \"api_key\", key };\n\t\t\t\t\t\tproviders.push(provider);\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\tdelete settings.apiKeys;\n\t\t\t\twriteFileSync(settingsPath, JSON.stringify(settings, null, 2));\n\t\t\t}\n\t\t} catch {\n\t\t\t// Skip on error\n\t\t}\n\t}\n\n\tif (Object.keys(migrated).length > 0) {\n\t\tmkdirSync(dirname(authPath), { recursive: true });\n\t\twriteFileSync(authPath, JSON.stringify(migrated, null, 2), { mode: 0o600 });\n\t}\n\n\treturn providers;\n}\n\ninterface ConfigValueMigration {\n\tlocation: string;\n\tfrom: string;\n\tto: string;\n}\n\nfunction migrateLegacyEnvVarString(value: string): string | undefined {\n\treturn isLegacyEnvVarNameConfigValue(value) && process.env[value] !== undefined ? `$${value}` : undefined;\n}\n\nfunction migrateStringProperty(\n\trecord: Record<string, unknown>,\n\tkey: string,\n\tlocation: string,\n\tmigrations: ConfigValueMigration[],\n): boolean {\n\tconst value = record[key];\n\tif (typeof value !== \"string\") return false;\n\tconst migrated = migrateLegacyEnvVarString(value);\n\tif (migrated === undefined) return false;\n\trecord[key] = migrated;\n\tmigrations.push({ location, from: value, to: migrated });\n\treturn true;\n}\n\nfunction migrateHeadersConfig(headers: unknown, location: string, migrations: ConfigValueMigration[]): boolean {\n\tif (typeof headers !== \"object\" || headers === null || Array.isArray(headers)) return false;\n\tconst headerRecord = headers as Record<string, unknown>;\n\tlet migrated = false;\n\tfor (const [key, value] of Object.entries(headerRecord)) {\n\t\tif (typeof value !== \"string\") continue;\n\t\tconst migratedValue = migrateLegacyEnvVarString(value);\n\t\tif (migratedValue === undefined) continue;\n\t\theaderRecord[key] = migratedValue;\n\t\tmigrations.push({ location: `${location}[${JSON.stringify(key)}]`, from: value, to: migratedValue });\n\t\tmigrated = true;\n\t}\n\treturn migrated;\n}\n\nfunction migrateAuthJsonConfigValues(agentDir: string): ConfigValueMigration[] {\n\tconst authPath = join(agentDir, \"auth.json\");\n\tif (!existsSync(authPath)) return [];\n\n\ttry {\n\t\tconst parsed = JSON.parse(readFileSync(authPath, \"utf-8\")) as unknown;\n\t\tif (typeof parsed !== \"object\" || parsed === null || Array.isArray(parsed)) return [];\n\t\tconst authData = parsed as Record<string, unknown>;\n\n\t\tconst migrations: ConfigValueMigration[] = [];\n\t\tfor (const [provider, credential] of Object.entries(authData)) {\n\t\t\tif (typeof credential !== \"object\" || credential === null || Array.isArray(credential)) continue;\n\t\t\tconst credentialRecord = credential as Record<string, unknown>;\n\t\t\tif (credentialRecord.type !== \"api_key\") continue;\n\t\t\tmigrateStringProperty(credentialRecord, \"key\", `auth.json[${JSON.stringify(provider)}].key`, migrations);\n\t\t}\n\n\t\tif (migrations.length === 0) return [];\n\t\twriteFileSync(authPath, `${JSON.stringify(parsed, null, 2)}\\n`, \"utf-8\");\n\t\tchmodSync(authPath, 0o600);\n\t\treturn migrations;\n\t} catch {\n\t\treturn [];\n\t}\n}\n\ninterface JsonRewriteContext {\n\ttype: \"object\" | \"array\";\n\tpath: string[];\n\tpendingKey?: string;\n}\n\nfunction isProviderConfigPath(parentPath: string[]): boolean {\n\treturn parentPath.length === 2 && parentPath[0] === \"providers\";\n}\n\nfunction isMigratableHeadersPath(parentPath: string[]): boolean {\n\tif (parentPath[0] !== \"providers\") return false;\n\t// providers.<provider>.headers\n\tif (parentPath.length === 3 && parentPath[2] === \"headers\") return true;\n\t// providers.<provider>.models[].headers\n\tif (parentPath.length === 4 && parentPath[2] === \"models\" && parentPath[3] === \"headers\") return true;\n\t// providers.<provider>.modelOverrides.<modelId>.headers\n\tif (parentPath.length === 5 && parentPath[2] === \"modelOverrides\" && parentPath[4] === \"headers\") return true;\n\treturn false;\n}\n\nfunction migrationReplacementForKey(key: string, value: string, parentPath: string[], migrations: ConfigValueMigration[]): string | undefined {\n\tif (key !== \"apiKey\" && !isMigratableHeadersPath(parentPath)) return undefined;\n\tif (key === \"apiKey\" && !isProviderConfigPath(parentPath)) return undefined;\n\n\tfor (const migration of migrations) {\n\t\tif (migration.from !== value) continue;\n\t\tif (key === \"apiKey\" && migration.location.endsWith(\".apiKey\")) return migration.to;\n\t\tif (isMigratableHeadersPath(parentPath) && migration.location.includes(\".headers[\") && migration.location.endsWith(`[${JSON.stringify(key)}]`)) {\n\t\t\treturn migration.to;\n\t\t}\n\t}\n\treturn undefined;\n}\n\nfunction skipJsoncTrivia(content: string, index: number): number {\n\tlet current = index;\n\twhile (current < content.length) {\n\t\tconst char = content[current];\n\t\tconst next = content[current + 1];\n\t\tif (char !== undefined && /\\s/.test(char)) {\n\t\t\tcurrent++;\n\t\t\tcontinue;\n\t\t}\n\t\tif (char === \"/\" && next === \"/\") {\n\t\t\tcurrent += 2;\n\t\t\twhile (current < content.length && content[current] !== \"\\n\") current++;\n\t\t\tcontinue;\n\t\t}\n\t\tif (char === \"/\" && next === \"*\") {\n\t\t\tcurrent += 2;\n\t\t\twhile (current < content.length && !(content[current] === \"*\" && content[current + 1] === \"/\")) current++;\n\t\t\tcurrent = Math.min(content.length, current + 2);\n\t\t\tcontinue;\n\t\t}\n\t\tbreak;\n\t}\n\treturn current;\n}\n\nfunction replaceMigratedJsonStringValues(content: string, migrations: ConfigValueMigration[]): string {\n\tif (migrations.length === 0) return content;\n\n\tlet result = \"\";\n\tlet index = 0;\n\tlet inLineComment = false;\n\tlet inBlockComment = false;\n\tconst stack: JsonRewriteContext[] = [];\n\n\tfunction consumePendingContainerPath(): string[] {\n\t\tconst parent = stack[stack.length - 1];\n\t\tif (!parent) return [];\n\t\tif (parent.type === \"object\" && parent.pendingKey !== undefined) {\n\t\t\tconst path = [...parent.path, parent.pendingKey];\n\t\t\tparent.pendingKey = undefined;\n\t\t\treturn path;\n\t\t}\n\t\treturn [...parent.path];\n\t}\n\n\twhile (index < content.length) {\n\t\tconst char = content[index]!;\n\t\tconst next = content[index + 1];\n\n\t\tif (inLineComment) {\n\t\t\tresult += char;\n\t\t\tindex++;\n\t\t\tif (char === \"\\n\") inLineComment = false;\n\t\t\tcontinue;\n\t\t}\n\n\t\tif (inBlockComment) {\n\t\t\tresult += char;\n\t\t\tif (char === \"*\" && next === \"/\") {\n\t\t\t\tresult += next;\n\t\t\t\tindex += 2;\n\t\t\t\tinBlockComment = false;\n\t\t\t} else {\n\t\t\t\tindex++;\n\t\t\t}\n\t\t\tcontinue;\n\t\t}\n\n\t\tif (char === \"/\" && next === \"/\") {\n\t\t\tresult += char + next;\n\t\t\tindex += 2;\n\t\t\tinLineComment = true;\n\t\t\tcontinue;\n\t\t}\n\n\t\tif (char === \"/\" && next === \"*\") {\n\t\t\tresult += char + next;\n\t\t\tindex += 2;\n\t\t\tinBlockComment = true;\n\t\t\tcontinue;\n\t\t}\n\n\t\tif (char === \"{\") {\n\t\t\tstack.push({ type: \"object\", path: consumePendingContainerPath() });\n\t\t\tresult += char;\n\t\t\tindex++;\n\t\t\tcontinue;\n\t\t}\n\n\t\tif (char === \"[\") {\n\t\t\tstack.push({ type: \"array\", path: consumePendingContainerPath() });\n\t\t\tresult += char;\n\t\t\tindex++;\n\t\t\tcontinue;\n\t\t}\n\n\t\tif (char === \"}\" || char === \"]\") {\n\t\t\tstack.pop();\n\t\t\tresult += char;\n\t\t\tindex++;\n\t\t\tcontinue;\n\t\t}\n\n\t\tif (char !== '\"') {\n\t\t\tresult += char;\n\t\t\tindex++;\n\t\t\tcontinue;\n\t\t}\n\n\t\tconst stringStart = index;\n\t\tindex++;\n\t\tlet escaped = false;\n\t\twhile (index < content.length) {\n\t\t\tconst current = content[index]!;\n\t\t\tindex++;\n\t\t\tif (escaped) {\n\t\t\t\tescaped = false;\n\t\t\t\tcontinue;\n\t\t\t}\n\t\t\tif (current === \"\\\\\") {\n\t\t\t\tescaped = true;\n\t\t\t\tcontinue;\n\t\t\t}\n\t\t\tif (current === '\"') break;\n\t\t}\n\n\t\tconst rawString = content.slice(stringStart, index);\n\t\tconst activeContext = stack[stack.length - 1];\n\t\tconst afterString = skipJsoncTrivia(content, index);\n\t\tconst isObjectKey = activeContext?.type === \"object\" && content[afterString] === \":\";\n\n\t\tif (isObjectKey) {\n\t\t\ttry {\n\t\t\t\tactiveContext.pendingKey = JSON.parse(rawString) as string;\n\t\t\t} catch {\n\t\t\t\tactiveContext.pendingKey = undefined;\n\t\t\t}\n\t\t\tresult += rawString;\n\t\t\tcontinue;\n\t\t}\n\n\t\ttry {\n\t\t\tconst value = JSON.parse(rawString) as unknown;\n\t\t\tconst key = activeContext?.type === \"object\" ? activeContext.pendingKey : undefined;\n\t\t\tif (typeof value === \"string\" && key !== undefined) {\n\t\t\t\tconst migrated = migrationReplacementForKey(key, value, activeContext.path, migrations);\n\t\t\t\tresult += migrated === undefined ? rawString : JSON.stringify(migrated);\n\t\t\t\tactiveContext.pendingKey = undefined;\n\t\t\t} else {\n\t\t\t\tresult += rawString;\n\t\t\t}\n\t\t} catch {\n\t\t\tresult += rawString;\n\t\t}\n\t}\n\n\treturn result;\n}\n\nfunction migrateModelsJsonConfigValues(agentDir: string): ConfigValueMigration[] {\n\tconst modelsPath = join(agentDir, \"models.json\");\n\tif (!existsSync(modelsPath)) return [];\n\n\ttry {\n\t\tconst content = readFileSync(modelsPath, \"utf-8\");\n\t\tconst parsed = JSON.parse(stripJsonComments(content)) as unknown;\n\t\tif (typeof parsed !== \"object\" || parsed === null || Array.isArray(parsed)) return [];\n\t\tconst modelsData = parsed as Record<string, unknown>;\n\t\tconst providers = modelsData.providers;\n\t\tif (typeof providers !== \"object\" || providers === null || Array.isArray(providers)) return [];\n\n\t\tconst migrations: ConfigValueMigration[] = [];\n\t\tfor (const [provider, providerConfig] of Object.entries(providers)) {\n\t\t\tif (typeof providerConfig !== \"object\" || providerConfig === null || Array.isArray(providerConfig)) continue;\n\t\t\tconst providerRecord = providerConfig as Record<string, unknown>;\n\t\t\tconst providerLocation = `models.json.providers[${JSON.stringify(provider)}]`;\n\t\t\tmigrateStringProperty(providerRecord, \"apiKey\", `${providerLocation}.apiKey`, migrations);\n\t\t\tmigrateHeadersConfig(providerRecord.headers, `${providerLocation}.headers`, migrations);\n\n\t\t\tif (Array.isArray(providerRecord.models)) {\n\t\t\t\tfor (let index = 0; index < providerRecord.models.length; index++) {\n\t\t\t\t\tconst modelConfig = providerRecord.models[index];\n\t\t\t\t\tif (typeof modelConfig !== \"object\" || modelConfig === null || Array.isArray(modelConfig)) continue;\n\t\t\t\t\tconst modelRecord = modelConfig as Record<string, unknown>;\n\t\t\t\t\tconst modelKey = typeof modelRecord.id === \"string\" ? JSON.stringify(modelRecord.id) : String(index);\n\t\t\t\t\tmigrateHeadersConfig(modelRecord.headers, `${providerLocation}.models[${modelKey}].headers`, migrations);\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tconst modelOverrides = providerRecord.modelOverrides;\n\t\t\tif (typeof modelOverrides === \"object\" && modelOverrides !== null && !Array.isArray(modelOverrides)) {\n\t\t\t\tfor (const [modelId, modelOverride] of Object.entries(modelOverrides)) {\n\t\t\t\t\tif (typeof modelOverride !== \"object\" || modelOverride === null || Array.isArray(modelOverride))\n\t\t\t\t\t\tcontinue;\n\t\t\t\t\tconst modelOverrideRecord = modelOverride as Record<string, unknown>;\n\t\t\t\t\tmigrateHeadersConfig(\n\t\t\t\t\t\tmodelOverrideRecord.headers,\n\t\t\t\t\t\t`${providerLocation}.modelOverrides[${JSON.stringify(modelId)}].headers`,\n\t\t\t\t\t\tmigrations,\n\t\t\t\t\t);\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\tif (migrations.length === 0) return [];\n\t\twriteFileSync(modelsPath, replaceMigratedJsonStringValues(content, migrations), \"utf-8\");\n\t\treturn migrations;\n\t} catch {\n\t\treturn [];\n\t}\n}\n\nfunction getAgentDirsForConfigMigration(): string[] {\n\tconst dirs = new Set<string>();\n\tfor (const path of [...getAgentConfigPaths(\"auth.json\"), ...getAgentConfigPaths(\"models.json\")]) {\n\t\tdirs.add(dirname(path));\n\t}\n\treturn [...dirs];\n}\n\nfunction migrateExplicitEnvVarConfigValues(): void {\n\tconst migrations = getAgentDirsForConfigMigration().flatMap((agentDir) => [\n\t\t...migrateAuthJsonConfigValues(agentDir),\n\t\t...migrateModelsJsonConfigValues(agentDir),\n\t]);\n\tif (migrations.length === 0) return;\n\n\tconst details = migrations.map((migration) => ` - ${migration.location}: ${migration.from} -> ${migration.to}`);\n\tconsole.log(\n\t\tchalk.yellow(\n\t\t\t[\n\t\t\t\t\"Warning: Migrated API key/header environment references to explicit $ENV_VAR syntax. Plain strings will be treated as literals.\",\n\t\t\t\t...details,\n\t\t\t].join(\"\\n\"),\n\t\t),\n\t);\n}\n\n/**\n * Migrate sessions from ~/.pi/agent/*.jsonl to proper session directories.\n *\n * Bug in v0.30.0: Sessions were saved to ~/.pi/agent/ instead of\n * ~/.pi/agent/sessions/<encoded-cwd>/. This migration moves them\n * to the correct location based on the cwd in their session header.\n *\n * See: https://github.com/earendil-works/pi-mono/issues/320\n */\nexport function migrateSessionsFromAgentRoot(): void {\n\tconst agentDir = getAgentDir();\n\n\t// Find all .jsonl files directly in agentDir (not in subdirectories)\n\tlet files: string[];\n\ttry {\n\t\tfiles = readdirSync(agentDir)\n\t\t\t.filter((f) => f.endsWith(\".jsonl\"))\n\t\t\t.map((f) => join(agentDir, f));\n\t} catch {\n\t\treturn;\n\t}\n\n\tif (files.length === 0) return;\n\n\tfor (const file of files) {\n\t\ttry {\n\t\t\t// Read first line to get session header\n\t\t\tconst content = readFileSync(file, \"utf8\");\n\t\t\tconst firstLine = content.split(\"\\n\")[0];\n\t\t\tif (!firstLine?.trim()) continue;\n\n\t\t\tconst header = JSON.parse(firstLine);\n\t\t\tif (header.type !== \"session\" || !header.cwd) continue;\n\n\t\t\tconst cwd: string = header.cwd;\n\n\t\t\t// Compute the correct session directory (same encoding as session-manager.ts)\n\t\t\tconst safePath = `--${cwd.replace(/^[/\\\\]/, \"\").replace(/[/\\\\:]/g, \"-\")}--`;\n\t\t\tconst correctDir = join(agentDir, \"sessions\", safePath);\n\n\t\t\t// Create directory if needed\n\t\t\tif (!existsSync(correctDir)) {\n\t\t\t\tmkdirSync(correctDir, { recursive: true });\n\t\t\t}\n\n\t\t\t// Move the file\n\t\t\tconst fileName = file.split(\"/\").pop() || file.split(\"\\\\\").pop();\n\t\t\tconst newPath = join(correctDir, fileName!);\n\n\t\t\tif (existsSync(newPath)) continue; // Skip if target exists\n\n\t\t\trenameSync(file, newPath);\n\t\t} catch {\n\t\t\t// Skip files that can't be migrated\n\t\t}\n\t}\n}\n\n/**\n * Migrate commands/ to prompts/ if needed.\n * Works for both regular directories and symlinks.\n */\nfunction migrateCommandsToPrompts(baseDir: string, label: string): boolean {\n\tconst commandsDir = join(baseDir, \"commands\");\n\tconst promptsDir = join(baseDir, \"prompts\");\n\n\tif (existsSync(commandsDir) && !existsSync(promptsDir)) {\n\t\ttry {\n\t\t\trenameSync(commandsDir, promptsDir);\n\t\t\tconsole.log(chalk.green(`Migrated ${label} commands/ → prompts/`));\n\t\t\treturn true;\n\t\t} catch (err) {\n\t\t\tconsole.log(\n\t\t\t\tchalk.yellow(\n\t\t\t\t\t`Warning: Could not migrate ${label} commands/ to prompts/: ${err instanceof Error ? err.message : err}`,\n\t\t\t\t),\n\t\t\t);\n\t\t}\n\t}\n\treturn false;\n}\n\nfunction migrateKeybindingsConfigFile(): void {\n\tconst configPath = join(getAgentDir(), \"keybindings.json\");\n\tif (!existsSync(configPath)) return;\n\n\ttry {\n\t\tconst parsed = JSON.parse(readFileSync(configPath, \"utf-8\")) as unknown;\n\t\tif (typeof parsed !== \"object\" || parsed === null || Array.isArray(parsed)) {\n\t\t\treturn;\n\t\t}\n\t\tconst { config, migrated } = migrateKeybindingsConfig(parsed as Record<string, unknown>);\n\t\tif (!migrated) return;\n\t\twriteFileSync(configPath, `${JSON.stringify(config, null, 2)}\\n`, \"utf-8\");\n\t} catch {\n\t\t// Ignore malformed files during migration\n\t}\n}\n\n/**\n * Move fd/rg binaries from tools/ to bin/ if they exist.\n */\nfunction migrateToolsToBin(): void {\n\tconst agentDir = getAgentDir();\n\tconst toolsDir = join(agentDir, \"tools\");\n\tconst binDir = getBinDir();\n\n\tif (!existsSync(toolsDir)) return;\n\n\tconst binaries = [\"fd\", \"rg\", \"fd.exe\", \"rg.exe\"];\n\tlet movedAny = false;\n\n\tfor (const bin of binaries) {\n\t\tconst oldPath = join(toolsDir, bin);\n\t\tconst newPath = join(binDir, bin);\n\n\t\tif (existsSync(oldPath)) {\n\t\t\tif (!existsSync(binDir)) {\n\t\t\t\tmkdirSync(binDir, { recursive: true });\n\t\t\t}\n\t\t\tif (!existsSync(newPath)) {\n\t\t\t\ttry {\n\t\t\t\t\trenameSync(oldPath, newPath);\n\t\t\t\t\tmovedAny = true;\n\t\t\t\t} catch {\n\t\t\t\t\t// Ignore errors\n\t\t\t\t}\n\t\t\t} else {\n\t\t\t\t// Target exists, just delete the old one\n\t\t\t\ttry {\n\t\t\t\t\trmSync?.(oldPath, { force: true });\n\t\t\t\t} catch {\n\t\t\t\t\t// Ignore\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n\n\tif (movedAny) {\n\t\tconsole.log(chalk.green(`Migrated managed binaries tools/ → bin/`));\n\t}\n}\n\n/**\n * Check for deprecated hooks/ and tools/ directories.\n * Note: tools/ may contain fd/rg binaries extracted by pi, so only warn if it has other files.\n */\nfunction checkDeprecatedExtensionDirs(baseDir: string, label: string): string[] {\n\tconst hooksDir = join(baseDir, \"hooks\");\n\tconst toolsDir = join(baseDir, \"tools\");\n\tconst warnings: string[] = [];\n\n\tif (existsSync(hooksDir)) {\n\t\twarnings.push(`${label} hooks/ directory found. Hooks have been renamed to extensions.`);\n\t}\n\n\tif (existsSync(toolsDir)) {\n\t\t// Check if tools/ contains anything other than fd/rg (which are auto-extracted binaries)\n\t\ttry {\n\t\t\tconst entries = readdirSync(toolsDir);\n\t\t\tconst customTools = entries.filter((e) => {\n\t\t\t\tconst lower = e.toLowerCase();\n\t\t\t\treturn (\n\t\t\t\t\tlower !== \"fd\" && lower !== \"rg\" && lower !== \"fd.exe\" && lower !== \"rg.exe\" && !e.startsWith(\".\") // Ignore .DS_Store and other hidden files\n\t\t\t\t);\n\t\t\t});\n\t\t\tif (customTools.length > 0) {\n\t\t\t\twarnings.push(\n\t\t\t\t\t`${label} tools/ directory contains custom tools. Custom tools have been merged into extensions.`,\n\t\t\t\t);\n\t\t\t}\n\t\t} catch {\n\t\t\t// Ignore read errors\n\t\t}\n\t}\n\n\treturn warnings;\n}\n\n/**\n * Run extension system migrations (commands→prompts) and collect warnings about deprecated directories.\n */\nfunction migrateExtensionSystem(cwd: string, options?: { projectTrusted?: boolean }): string[] {\n\tconst agentDir = getAgentDir();\n\tconst projectDir = join(cwd, CONFIG_DIR_NAME);\n\n\t// Migrate commands/ to prompts/\n\tmigrateCommandsToPrompts(agentDir, \"Global\");\n\tif (options?.projectTrusted !== false) {\n\t\tmigrateCommandsToPrompts(projectDir, \"Project\");\n\t}\n\n\t// Check for deprecated directories\n\tconst warnings = [\n\t\t...checkDeprecatedExtensionDirs(agentDir, \"Global\"),\n\t\t...(options?.projectTrusted === false ? [] : checkDeprecatedExtensionDirs(projectDir, \"Project\")),\n\t];\n\n\treturn warnings;\n}\n\n/**\n * Print deprecation warnings and wait for keypress.\n */\nexport async function showDeprecationWarnings(warnings: string[]): Promise<void> {\n\tif (warnings.length === 0) return;\n\n\tfor (const warning of warnings) {\n\t\tconsole.log(chalk.yellow(`Warning: ${warning}`));\n\t}\n\tconsole.log(chalk.yellow(`\\nMove your extensions to the extensions/ directory.`));\n\tconsole.log(chalk.yellow(`Migration guide: ${MIGRATION_GUIDE_URL}`));\n\tconsole.log(chalk.yellow(`Documentation: ${EXTENSIONS_DOC_URL}`));\n\tconsole.log(chalk.dim(`\\nPress any key to continue...`));\n\n\tawait new Promise<void>((resolve) => {\n\t\tprocess.stdin.setRawMode?.(true);\n\t\tprocess.stdin.resume();\n\t\tprocess.stdin.once(\"data\", () => {\n\t\t\tprocess.stdin.setRawMode?.(false);\n\t\t\tprocess.stdin.pause();\n\t\t\tresolve();\n\t\t});\n\t});\n\tconsole.log();\n}\n\n/**\n * Run all migrations. Called once on startup.\n *\n * @returns Object with migration results and deprecation warnings\n */\nexport function runMigrations(\n\tcwd: string,\n\toptions?: { projectTrusted?: boolean },\n): {\n\tmigratedAuthProviders: string[];\n\tdeprecationWarnings: string[];\n} {\n\tconst migratedAuthProviders = migrateAuthToAuthJson();\n\tmigrateExplicitEnvVarConfigValues();\n\tmigrateSessionsFromAgentRoot();\n\tmigrateToolsToBin();\n\tmigrateKeybindingsConfigFile();\n\tconst deprecationWarnings = migrateExtensionSystem(cwd, options);\n\treturn { migratedAuthProviders, deprecationWarnings };\n}\n"]}
@@ -5,5 +5,5 @@ export { InteractiveMode, type InteractiveModeOptions } from "./interactive/inte
5
5
  export { type PrintModeOptions, runPrintMode } from "./print-mode.ts";
6
6
  export { type ModelInfo, RpcClient, type RpcClientOptions, type RpcEventListener } from "./rpc/rpc-client.ts";
7
7
  export { runRpcMode } from "./rpc/rpc-mode.ts";
8
- export type { RpcCommand, RpcEvent, RpcResponse, RpcSessionState } from "./rpc/rpc-types.ts";
8
+ export type { RpcCommand, RpcEvent, RpcExtensionUIRequest, RpcExtensionUIResponse, RpcResponse, RpcSessionState, } from "./rpc/rpc-types.ts";
9
9
  //# sourceMappingURL=index.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/modes/index.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,OAAO,EAAE,eAAe,EAAE,KAAK,sBAAsB,EAAE,MAAM,mCAAmC,CAAC;AACjG,OAAO,EAAE,KAAK,gBAAgB,EAAE,YAAY,EAAE,MAAM,iBAAiB,CAAC;AACtE,OAAO,EAAE,KAAK,SAAS,EAAE,SAAS,EAAE,KAAK,gBAAgB,EAAE,KAAK,gBAAgB,EAAE,MAAM,qBAAqB,CAAC;AAC9G,OAAO,EAAE,UAAU,EAAE,MAAM,mBAAmB,CAAC;AAC/C,YAAY,EAAE,UAAU,EAAE,QAAQ,EAAE,WAAW,EAAE,eAAe,EAAE,MAAM,oBAAoB,CAAC","sourcesContent":["/**\n * Run modes for the coding agent.\n */\n\nexport { InteractiveMode, type InteractiveModeOptions } from \"./interactive/interactive-mode.ts\";\nexport { type PrintModeOptions, runPrintMode } from \"./print-mode.ts\";\nexport { type ModelInfo, RpcClient, type RpcClientOptions, type RpcEventListener } from \"./rpc/rpc-client.ts\";\nexport { runRpcMode } from \"./rpc/rpc-mode.ts\";\nexport type { RpcCommand, RpcEvent, RpcResponse, RpcSessionState } from \"./rpc/rpc-types.ts\";\n"]}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/modes/index.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,OAAO,EAAE,eAAe,EAAE,KAAK,sBAAsB,EAAE,MAAM,mCAAmC,CAAC;AACjG,OAAO,EAAE,KAAK,gBAAgB,EAAE,YAAY,EAAE,MAAM,iBAAiB,CAAC;AACtE,OAAO,EAAE,KAAK,SAAS,EAAE,SAAS,EAAE,KAAK,gBAAgB,EAAE,KAAK,gBAAgB,EAAE,MAAM,qBAAqB,CAAC;AAC9G,OAAO,EAAE,UAAU,EAAE,MAAM,mBAAmB,CAAC;AAC/C,YAAY,EACX,UAAU,EACV,QAAQ,EACR,qBAAqB,EACrB,sBAAsB,EACtB,WAAW,EACX,eAAe,GACf,MAAM,oBAAoB,CAAC","sourcesContent":["/**\n * Run modes for the coding agent.\n */\n\nexport { InteractiveMode, type InteractiveModeOptions } from \"./interactive/interactive-mode.ts\";\nexport { type PrintModeOptions, runPrintMode } from \"./print-mode.ts\";\nexport { type ModelInfo, RpcClient, type RpcClientOptions, type RpcEventListener } from \"./rpc/rpc-client.ts\";\nexport { runRpcMode } from \"./rpc/rpc-mode.ts\";\nexport type {\n\tRpcCommand,\n\tRpcEvent,\n\tRpcExtensionUIRequest,\n\tRpcExtensionUIResponse,\n\tRpcResponse,\n\tRpcSessionState,\n} from \"./rpc/rpc-types.ts\";\n"]}
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/modes/index.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,OAAO,EAAE,eAAe,EAA+B,MAAM,mCAAmC,CAAC;AACjG,OAAO,EAAyB,YAAY,EAAE,MAAM,iBAAiB,CAAC;AACtE,OAAO,EAAkB,SAAS,EAAgD,MAAM,qBAAqB,CAAC;AAC9G,OAAO,EAAE,UAAU,EAAE,MAAM,mBAAmB,CAAC","sourcesContent":["/**\n * Run modes for the coding agent.\n */\n\nexport { InteractiveMode, type InteractiveModeOptions } from \"./interactive/interactive-mode.ts\";\nexport { type PrintModeOptions, runPrintMode } from \"./print-mode.ts\";\nexport { type ModelInfo, RpcClient, type RpcClientOptions, type RpcEventListener } from \"./rpc/rpc-client.ts\";\nexport { runRpcMode } from \"./rpc/rpc-mode.ts\";\nexport type { RpcCommand, RpcEvent, RpcResponse, RpcSessionState } from \"./rpc/rpc-types.ts\";\n"]}
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/modes/index.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,OAAO,EAAE,eAAe,EAA+B,MAAM,mCAAmC,CAAC;AACjG,OAAO,EAAyB,YAAY,EAAE,MAAM,iBAAiB,CAAC;AACtE,OAAO,EAAkB,SAAS,EAAgD,MAAM,qBAAqB,CAAC;AAC9G,OAAO,EAAE,UAAU,EAAE,MAAM,mBAAmB,CAAC","sourcesContent":["/**\n * Run modes for the coding agent.\n */\n\nexport { InteractiveMode, type InteractiveModeOptions } from \"./interactive/interactive-mode.ts\";\nexport { type PrintModeOptions, runPrintMode } from \"./print-mode.ts\";\nexport { type ModelInfo, RpcClient, type RpcClientOptions, type RpcEventListener } from \"./rpc/rpc-client.ts\";\nexport { runRpcMode } from \"./rpc/rpc-mode.ts\";\nexport type {\n\tRpcCommand,\n\tRpcEvent,\n\tRpcExtensionUIRequest,\n\tRpcExtensionUIResponse,\n\tRpcResponse,\n\tRpcSessionState,\n} from \"./rpc/rpc-types.ts\";\n"]}