@phi-code-admin/phi-code 0.74.3 → 0.75.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (655) hide show
  1. package/CHANGELOG.md +1186 -4
  2. package/README.md +478 -379
  3. package/dist/bun/cli.d.ts +3 -0
  4. package/dist/bun/cli.d.ts.map +1 -0
  5. package/dist/bun/cli.js +9 -0
  6. package/dist/bun/cli.js.map +1 -0
  7. package/dist/bun/register-bedrock.d.ts +2 -0
  8. package/dist/bun/register-bedrock.d.ts.map +1 -0
  9. package/dist/bun/register-bedrock.js +4 -0
  10. package/dist/bun/register-bedrock.js.map +1 -0
  11. package/dist/bun/restore-sandbox-env.d.ts +13 -0
  12. package/dist/bun/restore-sandbox-env.d.ts.map +1 -0
  13. package/dist/bun/restore-sandbox-env.js +32 -0
  14. package/dist/bun/restore-sandbox-env.js.map +1 -0
  15. package/dist/cli/args.d.ts +12 -7
  16. package/dist/cli/args.d.ts.map +1 -1
  17. package/dist/cli/args.js +87 -45
  18. package/dist/cli/args.js.map +1 -1
  19. package/dist/cli/config-selector.d.ts.map +1 -1
  20. package/dist/cli/config-selector.js.map +1 -1
  21. package/dist/cli/file-processor.d.ts.map +1 -1
  22. package/dist/cli/file-processor.js +4 -0
  23. package/dist/cli/file-processor.js.map +1 -1
  24. package/dist/cli/initial-message.d.ts +18 -0
  25. package/dist/cli/initial-message.d.ts.map +1 -0
  26. package/dist/cli/initial-message.js +22 -0
  27. package/dist/cli/initial-message.js.map +1 -0
  28. package/dist/cli/list-models.d.ts.map +1 -1
  29. package/dist/cli/list-models.js +7 -1
  30. package/dist/cli/list-models.js.map +1 -1
  31. package/dist/cli/session-picker.d.ts.map +1 -1
  32. package/dist/cli/session-picker.js +2 -1
  33. package/dist/cli/session-picker.js.map +1 -1
  34. package/dist/cli.d.ts.map +1 -1
  35. package/dist/cli.js +9 -5
  36. package/dist/cli.js.map +1 -1
  37. package/dist/config.d.ts +24 -0
  38. package/dist/config.d.ts.map +1 -1
  39. package/dist/config.js +226 -30
  40. package/dist/config.js.map +1 -1
  41. package/dist/core/agent-session-runtime.d.ts +117 -0
  42. package/dist/core/agent-session-runtime.d.ts.map +1 -0
  43. package/dist/core/agent-session-runtime.js +300 -0
  44. package/dist/core/agent-session-runtime.js.map +1 -0
  45. package/dist/core/agent-session-services.d.ts +86 -0
  46. package/dist/core/agent-session-services.d.ts.map +1 -0
  47. package/dist/core/agent-session-services.js +117 -0
  48. package/dist/core/agent-session-services.js.map +1 -0
  49. package/dist/core/agent-session.d.ts +63 -82
  50. package/dist/core/agent-session.d.ts.map +1 -1
  51. package/dist/core/agent-session.js +674 -628
  52. package/dist/core/agent-session.js.map +1 -1
  53. package/dist/core/api-key-store.d.ts +87 -0
  54. package/dist/core/api-key-store.d.ts.map +1 -0
  55. package/dist/core/api-key-store.js +168 -0
  56. package/dist/core/api-key-store.js.map +1 -0
  57. package/dist/core/auth-guidance.d.ts +5 -0
  58. package/dist/core/auth-guidance.d.ts.map +1 -0
  59. package/dist/core/auth-guidance.js +21 -0
  60. package/dist/core/auth-guidance.js.map +1 -0
  61. package/dist/core/auth-storage.d.ts +12 -5
  62. package/dist/core/auth-storage.d.ts.map +1 -1
  63. package/dist/core/auth-storage.js +34 -8
  64. package/dist/core/auth-storage.js.map +1 -1
  65. package/dist/core/bash-executor.d.ts +0 -15
  66. package/dist/core/bash-executor.d.ts.map +1 -1
  67. package/dist/core/bash-executor.js +28 -129
  68. package/dist/core/bash-executor.js.map +1 -1
  69. package/dist/core/compaction/branch-summarization.d.ts +2 -0
  70. package/dist/core/compaction/branch-summarization.d.ts.map +1 -1
  71. package/dist/core/compaction/branch-summarization.js +3 -2
  72. package/dist/core/compaction/branch-summarization.js.map +1 -1
  73. package/dist/core/compaction/compaction.d.ts +4 -4
  74. package/dist/core/compaction/compaction.d.ts.map +1 -1
  75. package/dist/core/compaction/compaction.js +32 -27
  76. package/dist/core/compaction/compaction.js.map +1 -1
  77. package/dist/core/compaction/index.d.ts.map +1 -1
  78. package/dist/core/compaction/utils.d.ts.map +1 -1
  79. package/dist/core/compaction/utils.js.map +1 -1
  80. package/dist/core/config-watcher.d.ts +47 -0
  81. package/dist/core/config-watcher.d.ts.map +1 -0
  82. package/dist/core/config-watcher.js +135 -0
  83. package/dist/core/config-watcher.js.map +1 -0
  84. package/dist/core/default-models.json +80 -0
  85. package/dist/core/defaults.d.ts.map +1 -1
  86. package/dist/core/diagnostics.d.ts.map +1 -1
  87. package/dist/core/event-bus.d.ts.map +1 -1
  88. package/dist/core/event-bus.js.map +1 -1
  89. package/dist/core/exec.d.ts.map +1 -1
  90. package/dist/core/exec.js +7 -3
  91. package/dist/core/exec.js.map +1 -1
  92. package/dist/core/export-html/ansi-to-html.d.ts.map +1 -1
  93. package/dist/core/export-html/ansi-to-html.js +1 -1
  94. package/dist/core/export-html/ansi-to-html.js.map +1 -1
  95. package/dist/core/export-html/index.d.ts +7 -4
  96. package/dist/core/export-html/index.d.ts.map +1 -1
  97. package/dist/core/export-html/index.js +15 -13
  98. package/dist/core/export-html/index.js.map +1 -1
  99. package/dist/core/export-html/template.css +112 -17
  100. package/dist/core/export-html/template.html +1 -0
  101. package/dist/core/export-html/template.js +312 -64
  102. package/dist/core/export-html/tool-renderer.d.ts +9 -10
  103. package/dist/core/export-html/tool-renderer.d.ts.map +1 -1
  104. package/dist/core/export-html/tool-renderer.js +61 -16
  105. package/dist/core/export-html/tool-renderer.js.map +1 -1
  106. package/dist/core/extensions/index.d.ts +5 -4
  107. package/dist/core/extensions/index.d.ts.map +1 -1
  108. package/dist/core/extensions/index.js +2 -2
  109. package/dist/core/extensions/index.js.map +1 -1
  110. package/dist/core/extensions/loader.d.ts +0 -1
  111. package/dist/core/extensions/loader.d.ts.map +1 -1
  112. package/dist/core/extensions/loader.js +98 -18
  113. package/dist/core/extensions/loader.js.map +1 -1
  114. package/dist/core/extensions/runner.d.ts +27 -14
  115. package/dist/core/extensions/runner.d.ts.map +1 -1
  116. package/dist/core/extensions/runner.js +299 -115
  117. package/dist/core/extensions/runner.js.map +1 -1
  118. package/dist/core/extensions/types.d.ts +200 -44
  119. package/dist/core/extensions/types.d.ts.map +1 -1
  120. package/dist/core/extensions/types.js +10 -0
  121. package/dist/core/extensions/types.js.map +1 -1
  122. package/dist/core/extensions/wrapper.d.ts +4 -11
  123. package/dist/core/extensions/wrapper.d.ts.map +1 -1
  124. package/dist/core/extensions/wrapper.js +7 -87
  125. package/dist/core/extensions/wrapper.js.map +1 -1
  126. package/dist/core/footer-data-provider.d.ts +22 -2
  127. package/dist/core/footer-data-provider.d.ts.map +1 -1
  128. package/dist/core/footer-data-provider.js +225 -49
  129. package/dist/core/footer-data-provider.js.map +1 -1
  130. package/dist/core/index.d.ts +5 -2
  131. package/dist/core/index.d.ts.map +1 -1
  132. package/dist/core/index.js +5 -2
  133. package/dist/core/index.js.map +1 -1
  134. package/dist/core/keybindings.d.ts +348 -50
  135. package/dist/core/keybindings.d.ts.map +1 -1
  136. package/dist/core/keybindings.js +276 -132
  137. package/dist/core/keybindings.js.map +1 -1
  138. package/dist/core/messages.d.ts.map +1 -1
  139. package/dist/core/messages.js.map +1 -1
  140. package/dist/core/model-registry.d.ts +41 -5
  141. package/dist/core/model-registry.d.ts.map +1 -1
  142. package/dist/core/model-registry.js +316 -136
  143. package/dist/core/model-registry.js.map +1 -1
  144. package/dist/core/model-resolver.d.ts +6 -0
  145. package/dist/core/model-resolver.d.ts.map +1 -1
  146. package/dist/core/model-resolver.js +70 -37
  147. package/dist/core/model-resolver.js.map +1 -1
  148. package/dist/core/output-guard.d.ts +6 -0
  149. package/dist/core/output-guard.d.ts.map +1 -0
  150. package/dist/core/output-guard.js +59 -0
  151. package/dist/core/output-guard.js.map +1 -0
  152. package/dist/core/package-manager.d.ts +49 -7
  153. package/dist/core/package-manager.d.ts.map +1 -1
  154. package/dist/core/package-manager.js +655 -122
  155. package/dist/core/package-manager.js.map +1 -1
  156. package/dist/core/prompt-templates.d.ts +12 -10
  157. package/dist/core/prompt-templates.d.ts.map +1 -1
  158. package/dist/core/prompt-templates.js +37 -38
  159. package/dist/core/prompt-templates.js.map +1 -1
  160. package/dist/core/provider-display-names.d.ts +2 -0
  161. package/dist/core/provider-display-names.d.ts.map +1 -0
  162. package/dist/core/provider-display-names.js +33 -0
  163. package/dist/core/provider-display-names.js.map +1 -0
  164. package/dist/core/resolve-config-value.d.ts +6 -0
  165. package/dist/core/resolve-config-value.d.ts.map +1 -1
  166. package/dist/core/resolve-config-value.js +75 -8
  167. package/dist/core/resolve-config-value.js.map +1 -1
  168. package/dist/core/resource-loader.d.ts +18 -8
  169. package/dist/core/resource-loader.d.ts.map +1 -1
  170. package/dist/core/resource-loader.js +217 -123
  171. package/dist/core/resource-loader.js.map +1 -1
  172. package/dist/core/sdk.d.ts +25 -8
  173. package/dist/core/sdk.d.ts.map +1 -1
  174. package/dist/core/sdk.js +84 -37
  175. package/dist/core/sdk.js.map +1 -1
  176. package/dist/core/session-cwd.d.ts +19 -0
  177. package/dist/core/session-cwd.d.ts.map +1 -0
  178. package/dist/core/session-cwd.js +38 -0
  179. package/dist/core/session-cwd.js.map +1 -0
  180. package/dist/core/session-manager.d.ts +11 -1
  181. package/dist/core/session-manager.d.ts.map +1 -1
  182. package/dist/core/session-manager.js +42 -27
  183. package/dist/core/session-manager.js.map +1 -1
  184. package/dist/core/settings-manager.d.ts +34 -5
  185. package/dist/core/settings-manager.d.ts.map +1 -1
  186. package/dist/core/settings-manager.js +113 -13
  187. package/dist/core/settings-manager.js.map +1 -1
  188. package/dist/core/skills.d.ts +13 -11
  189. package/dist/core/skills.d.ts.map +1 -1
  190. package/dist/core/skills.js +59 -19
  191. package/dist/core/skills.js.map +1 -1
  192. package/dist/core/slash-commands.d.ts +2 -3
  193. package/dist/core/slash-commands.d.ts.map +1 -1
  194. package/dist/core/slash-commands.js +9 -6
  195. package/dist/core/slash-commands.js.map +1 -1
  196. package/dist/core/source-info.d.ts +18 -0
  197. package/dist/core/source-info.d.ts.map +1 -0
  198. package/dist/core/source-info.js +19 -0
  199. package/dist/core/source-info.js.map +1 -0
  200. package/dist/core/system-prompt.d.ts +3 -3
  201. package/dist/core/system-prompt.d.ts.map +1 -1
  202. package/dist/core/system-prompt.js +16 -55
  203. package/dist/core/system-prompt.js.map +1 -1
  204. package/dist/core/telemetry.d.ts +3 -0
  205. package/dist/core/telemetry.d.ts.map +1 -0
  206. package/dist/core/telemetry.js +9 -0
  207. package/dist/core/telemetry.js.map +1 -0
  208. package/dist/core/timings.d.ts +1 -0
  209. package/dist/core/timings.d.ts.map +1 -1
  210. package/dist/core/timings.js +6 -0
  211. package/dist/core/timings.js.map +1 -1
  212. package/dist/core/tools/bash.d.ts +27 -14
  213. package/dist/core/tools/bash.d.ts.map +1 -1
  214. package/dist/core/tools/bash.js +301 -208
  215. package/dist/core/tools/bash.js.map +1 -1
  216. package/dist/core/tools/edit-diff.d.ts +23 -1
  217. package/dist/core/tools/edit-diff.d.ts.map +1 -1
  218. package/dist/core/tools/edit-diff.js +154 -59
  219. package/dist/core/tools/edit-diff.js.map +1 -1
  220. package/dist/core/tools/edit.d.ts +22 -12
  221. package/dist/core/tools/edit.d.ts.map +1 -1
  222. package/dist/core/tools/edit.js +243 -65
  223. package/dist/core/tools/edit.js.map +1 -1
  224. package/dist/core/tools/file-mutation-queue.d.ts +6 -0
  225. package/dist/core/tools/file-mutation-queue.d.ts.map +1 -0
  226. package/dist/core/tools/file-mutation-queue.js +37 -0
  227. package/dist/core/tools/file-mutation-queue.js.map +1 -0
  228. package/dist/core/tools/find.d.ts +10 -14
  229. package/dist/core/tools/find.d.ts.map +1 -1
  230. package/dist/core/tools/find.js +202 -110
  231. package/dist/core/tools/find.js.map +1 -1
  232. package/dist/core/tools/grep.d.ts +14 -22
  233. package/dist/core/tools/grep.d.ts.map +1 -1
  234. package/dist/core/tools/grep.js +100 -35
  235. package/dist/core/tools/grep.js.map +1 -1
  236. package/dist/core/tools/index.d.ts +27 -60
  237. package/dist/core/tools/index.d.ts.map +1 -1
  238. package/dist/core/tools/index.js +96 -45
  239. package/dist/core/tools/index.js.map +1 -1
  240. package/dist/core/tools/ls.d.ts +8 -11
  241. package/dist/core/tools/ls.d.ts.map +1 -1
  242. package/dist/core/tools/ls.js +66 -15
  243. package/dist/core/tools/ls.js.map +1 -1
  244. package/dist/core/tools/output-accumulator.d.ts +50 -0
  245. package/dist/core/tools/output-accumulator.d.ts.map +1 -0
  246. package/dist/core/tools/output-accumulator.js +178 -0
  247. package/dist/core/tools/output-accumulator.js.map +1 -0
  248. package/dist/core/tools/path-utils.d.ts.map +1 -1
  249. package/dist/core/tools/path-utils.js +1 -1
  250. package/dist/core/tools/path-utils.js.map +1 -1
  251. package/dist/core/tools/read.d.ts +9 -13
  252. package/dist/core/tools/read.d.ts.map +1 -1
  253. package/dist/core/tools/read.js +175 -52
  254. package/dist/core/tools/read.js.map +1 -1
  255. package/dist/core/tools/render-utils.d.ts +21 -0
  256. package/dist/core/tools/render-utils.d.ts.map +1 -0
  257. package/dist/core/tools/render-utils.js +49 -0
  258. package/dist/core/tools/render-utils.js.map +1 -0
  259. package/dist/core/tools/tool-definition-wrapper.d.ts +14 -0
  260. package/dist/core/tools/tool-definition-wrapper.d.ts.map +1 -0
  261. package/dist/core/tools/tool-definition-wrapper.js +34 -0
  262. package/dist/core/tools/tool-definition-wrapper.js.map +1 -0
  263. package/dist/core/tools/truncate.d.ts.map +1 -1
  264. package/dist/core/tools/truncate.js.map +1 -1
  265. package/dist/core/tools/write.d.ts +8 -11
  266. package/dist/core/tools/write.d.ts.map +1 -1
  267. package/dist/core/tools/write.js +167 -32
  268. package/dist/core/tools/write.js.map +1 -1
  269. package/dist/index.d.ts +12 -9
  270. package/dist/index.d.ts.map +1 -1
  271. package/dist/index.js +12 -10
  272. package/dist/index.js.map +1 -1
  273. package/dist/main.d.ts +5 -1
  274. package/dist/main.d.ts.map +1 -1
  275. package/dist/main.js +326 -404
  276. package/dist/main.js.map +1 -1
  277. package/dist/migrations.d.ts +2 -2
  278. package/dist/migrations.d.ts.map +1 -1
  279. package/dist/migrations.js +24 -4
  280. package/dist/migrations.js.map +1 -1
  281. package/dist/modes/index.d.ts.map +1 -1
  282. package/dist/modes/interactive/components/armin.d.ts.map +1 -1
  283. package/dist/modes/interactive/components/armin.js +10 -6
  284. package/dist/modes/interactive/components/armin.js.map +1 -1
  285. package/dist/modes/interactive/components/assistant-message.d.ts +5 -1
  286. package/dist/modes/interactive/components/assistant-message.d.ts.map +1 -1
  287. package/dist/modes/interactive/components/assistant-message.js +32 -3
  288. package/dist/modes/interactive/components/assistant-message.js.map +1 -1
  289. package/dist/modes/interactive/components/bash-execution.d.ts +0 -1
  290. package/dist/modes/interactive/components/bash-execution.d.ts.map +1 -1
  291. package/dist/modes/interactive/components/bash-execution.js +31 -12
  292. package/dist/modes/interactive/components/bash-execution.js.map +1 -1
  293. package/dist/modes/interactive/components/bordered-loader.d.ts.map +1 -1
  294. package/dist/modes/interactive/components/bordered-loader.js +7 -1
  295. package/dist/modes/interactive/components/bordered-loader.js.map +1 -1
  296. package/dist/modes/interactive/components/branch-summary-message.d.ts.map +1 -1
  297. package/dist/modes/interactive/components/branch-summary-message.js +5 -3
  298. package/dist/modes/interactive/components/branch-summary-message.js.map +1 -1
  299. package/dist/modes/interactive/components/compaction-summary-message.d.ts.map +1 -1
  300. package/dist/modes/interactive/components/compaction-summary-message.js +5 -3
  301. package/dist/modes/interactive/components/compaction-summary-message.js.map +1 -1
  302. package/dist/modes/interactive/components/config-selector.d.ts.map +1 -1
  303. package/dist/modes/interactive/components/config-selector.js +49 -16
  304. package/dist/modes/interactive/components/config-selector.js.map +1 -1
  305. package/dist/modes/interactive/components/countdown-timer.d.ts.map +1 -1
  306. package/dist/modes/interactive/components/countdown-timer.js +5 -0
  307. package/dist/modes/interactive/components/countdown-timer.js.map +1 -1
  308. package/dist/modes/interactive/components/custom-editor.d.ts +3 -3
  309. package/dist/modes/interactive/components/custom-editor.d.ts.map +1 -1
  310. package/dist/modes/interactive/components/custom-editor.js +14 -7
  311. package/dist/modes/interactive/components/custom-editor.js.map +1 -1
  312. package/dist/modes/interactive/components/custom-message.d.ts.map +1 -1
  313. package/dist/modes/interactive/components/custom-message.js +6 -1
  314. package/dist/modes/interactive/components/custom-message.js.map +1 -1
  315. package/dist/modes/interactive/components/daxnuts.d.ts.map +1 -1
  316. package/dist/modes/interactive/components/daxnuts.js +8 -6
  317. package/dist/modes/interactive/components/daxnuts.js.map +1 -1
  318. package/dist/modes/interactive/components/diff.d.ts.map +1 -1
  319. package/dist/modes/interactive/components/diff.js.map +1 -1
  320. package/dist/modes/interactive/components/dynamic-border.d.ts.map +1 -1
  321. package/dist/modes/interactive/components/dynamic-border.js +1 -0
  322. package/dist/modes/interactive/components/dynamic-border.js.map +1 -1
  323. package/dist/modes/interactive/components/earendil-announcement.d.ts +5 -0
  324. package/dist/modes/interactive/components/earendil-announcement.d.ts.map +1 -0
  325. package/dist/modes/interactive/components/earendil-announcement.js +40 -0
  326. package/dist/modes/interactive/components/earendil-announcement.js.map +1 -0
  327. package/dist/modes/interactive/components/extension-editor.d.ts.map +1 -1
  328. package/dist/modes/interactive/components/extension-editor.js +16 -10
  329. package/dist/modes/interactive/components/extension-editor.js.map +1 -1
  330. package/dist/modes/interactive/components/extension-input.d.ts.map +1 -1
  331. package/dist/modes/interactive/components/extension-input.js +13 -7
  332. package/dist/modes/interactive/components/extension-input.js.map +1 -1
  333. package/dist/modes/interactive/components/extension-selector.d.ts.map +1 -1
  334. package/dist/modes/interactive/components/extension-selector.js +18 -11
  335. package/dist/modes/interactive/components/extension-selector.js.map +1 -1
  336. package/dist/modes/interactive/components/footer.d.ts +1 -0
  337. package/dist/modes/interactive/components/footer.d.ts.map +1 -1
  338. package/dist/modes/interactive/components/footer.js +7 -2
  339. package/dist/modes/interactive/components/footer.js.map +1 -1
  340. package/dist/modes/interactive/components/index.d.ts +1 -1
  341. package/dist/modes/interactive/components/index.d.ts.map +1 -1
  342. package/dist/modes/interactive/components/index.js +1 -1
  343. package/dist/modes/interactive/components/index.js.map +1 -1
  344. package/dist/modes/interactive/components/keybinding-hints.d.ts +8 -36
  345. package/dist/modes/interactive/components/keybinding-hints.d.ts.map +1 -1
  346. package/dist/modes/interactive/components/keybinding-hints.js +23 -48
  347. package/dist/modes/interactive/components/keybinding-hints.js.map +1 -1
  348. package/dist/modes/interactive/components/login-dialog.d.ts +5 -1
  349. package/dist/modes/interactive/components/login-dialog.d.ts.map +1 -1
  350. package/dist/modes/interactive/components/login-dialog.js +35 -14
  351. package/dist/modes/interactive/components/login-dialog.js.map +1 -1
  352. package/dist/modes/interactive/components/model-selector.d.ts.map +1 -1
  353. package/dist/modes/interactive/components/model-selector.js +41 -22
  354. package/dist/modes/interactive/components/model-selector.js.map +1 -1
  355. package/dist/modes/interactive/components/oauth-selector.d.ts +18 -6
  356. package/dist/modes/interactive/components/oauth-selector.d.ts.map +1 -1
  357. package/dist/modes/interactive/components/oauth-selector.js +104 -31
  358. package/dist/modes/interactive/components/oauth-selector.js.map +1 -1
  359. package/dist/modes/interactive/components/scoped-models-selector.d.ts +5 -12
  360. package/dist/modes/interactive/components/scoped-models-selector.d.ts.map +1 -1
  361. package/dist/modes/interactive/components/scoped-models-selector.js +61 -42
  362. package/dist/modes/interactive/components/scoped-models-selector.js.map +1 -1
  363. package/dist/modes/interactive/components/session-selector-search.d.ts.map +1 -1
  364. package/dist/modes/interactive/components/session-selector-search.js.map +1 -1
  365. package/dist/modes/interactive/components/session-selector.d.ts +2 -1
  366. package/dist/modes/interactive/components/session-selector.d.ts.map +1 -1
  367. package/dist/modes/interactive/components/session-selector.js +109 -73
  368. package/dist/modes/interactive/components/session-selector.js.map +1 -1
  369. package/dist/modes/interactive/components/settings-selector.d.ts +9 -0
  370. package/dist/modes/interactive/components/settings-selector.d.ts.map +1 -1
  371. package/dist/modes/interactive/components/settings-selector.js +84 -4
  372. package/dist/modes/interactive/components/settings-selector.js.map +1 -1
  373. package/dist/modes/interactive/components/show-images-selector.d.ts.map +1 -1
  374. package/dist/modes/interactive/components/show-images-selector.js +6 -1
  375. package/dist/modes/interactive/components/show-images-selector.js.map +1 -1
  376. package/dist/modes/interactive/components/skill-invocation-message.d.ts.map +1 -1
  377. package/dist/modes/interactive/components/skill-invocation-message.js +5 -3
  378. package/dist/modes/interactive/components/skill-invocation-message.js.map +1 -1
  379. package/dist/modes/interactive/components/theme-selector.d.ts.map +1 -1
  380. package/dist/modes/interactive/components/theme-selector.js +7 -1
  381. package/dist/modes/interactive/components/theme-selector.js.map +1 -1
  382. package/dist/modes/interactive/components/thinking-selector.d.ts.map +1 -1
  383. package/dist/modes/interactive/components/thinking-selector.js +6 -1
  384. package/dist/modes/interactive/components/thinking-selector.js.map +1 -1
  385. package/dist/modes/interactive/components/tool-execution.d.ts +20 -34
  386. package/dist/modes/interactive/components/tool-execution.d.ts.map +1 -1
  387. package/dist/modes/interactive/components/tool-execution.js +158 -636
  388. package/dist/modes/interactive/components/tool-execution.js.map +1 -1
  389. package/dist/modes/interactive/components/tree-selector.d.ts +21 -2
  390. package/dist/modes/interactive/components/tree-selector.d.ts.map +1 -1
  391. package/dist/modes/interactive/components/tree-selector.js +224 -52
  392. package/dist/modes/interactive/components/tree-selector.js.map +1 -1
  393. package/dist/modes/interactive/components/user-message-selector.d.ts +2 -2
  394. package/dist/modes/interactive/components/user-message-selector.d.ts.map +1 -1
  395. package/dist/modes/interactive/components/user-message-selector.js +20 -16
  396. package/dist/modes/interactive/components/user-message-selector.js.map +1 -1
  397. package/dist/modes/interactive/components/user-message.d.ts +1 -0
  398. package/dist/modes/interactive/components/user-message.d.ts.map +1 -1
  399. package/dist/modes/interactive/components/user-message.js +8 -6
  400. package/dist/modes/interactive/components/user-message.js.map +1 -1
  401. package/dist/modes/interactive/components/visual-truncate.d.ts.map +1 -1
  402. package/dist/modes/interactive/components/visual-truncate.js.map +1 -1
  403. package/dist/modes/interactive/interactive-mode.d.ts +67 -39
  404. package/dist/modes/interactive/interactive-mode.d.ts.map +1 -1
  405. package/dist/modes/interactive/interactive-mode.js +1556 -680
  406. package/dist/modes/interactive/interactive-mode.js.map +1 -1
  407. package/dist/modes/interactive/theme/dark.json +1 -1
  408. package/dist/modes/interactive/theme/light.json +1 -1
  409. package/dist/modes/interactive/theme/theme.d.ts +3 -0
  410. package/dist/modes/interactive/theme/theme.d.ts.map +1 -1
  411. package/dist/modes/interactive/theme/theme.js +101 -72
  412. package/dist/modes/interactive/theme/theme.js.map +1 -1
  413. package/dist/modes/print-mode.d.ts +2 -2
  414. package/dist/modes/print-mode.d.ts.map +1 -1
  415. package/dist/modes/print-mode.js +107 -77
  416. package/dist/modes/print-mode.js.map +1 -1
  417. package/dist/modes/rpc/jsonl.d.ts +17 -0
  418. package/dist/modes/rpc/jsonl.d.ts.map +1 -0
  419. package/dist/modes/rpc/jsonl.js +49 -0
  420. package/dist/modes/rpc/jsonl.js.map +1 -0
  421. package/dist/modes/rpc/rpc-client.d.ts +8 -1
  422. package/dist/modes/rpc/rpc-client.d.ts.map +1 -1
  423. package/dist/modes/rpc/rpc-client.js +22 -16
  424. package/dist/modes/rpc/rpc-client.js.map +1 -1
  425. package/dist/modes/rpc/rpc-mode.d.ts +2 -2
  426. package/dist/modes/rpc/rpc-mode.d.ts.map +1 -1
  427. package/dist/modes/rpc/rpc-mode.js +184 -94
  428. package/dist/modes/rpc/rpc-mode.js.map +1 -1
  429. package/dist/modes/rpc/rpc-types.d.ts +14 -4
  430. package/dist/modes/rpc/rpc-types.d.ts.map +1 -1
  431. package/dist/modes/rpc/rpc-types.js.map +1 -1
  432. package/dist/package-manager-cli.d.ts +4 -0
  433. package/dist/package-manager-cli.d.ts.map +1 -0
  434. package/dist/package-manager-cli.js +460 -0
  435. package/dist/package-manager-cli.js.map +1 -0
  436. package/dist/utils/changelog.d.ts.map +1 -1
  437. package/dist/utils/changelog.js.map +1 -1
  438. package/dist/utils/child-process.d.ts +12 -0
  439. package/dist/utils/child-process.d.ts.map +1 -0
  440. package/dist/utils/child-process.js +86 -0
  441. package/dist/utils/child-process.js.map +1 -0
  442. package/dist/utils/clipboard-image.d.ts.map +1 -1
  443. package/dist/utils/clipboard-image.js +94 -11
  444. package/dist/utils/clipboard-image.js.map +1 -1
  445. package/dist/utils/clipboard-native.d.ts +1 -0
  446. package/dist/utils/clipboard-native.d.ts.map +1 -1
  447. package/dist/utils/clipboard-native.js.map +1 -1
  448. package/dist/utils/clipboard.d.ts +1 -1
  449. package/dist/utils/clipboard.d.ts.map +1 -1
  450. package/dist/utils/clipboard.js +96 -46
  451. package/dist/utils/clipboard.js.map +1 -1
  452. package/dist/utils/exif-orientation.d.ts +5 -0
  453. package/dist/utils/exif-orientation.d.ts.map +1 -0
  454. package/dist/utils/exif-orientation.js +158 -0
  455. package/dist/utils/exif-orientation.js.map +1 -0
  456. package/dist/utils/frontmatter.d.ts.map +1 -1
  457. package/dist/utils/frontmatter.js.map +1 -1
  458. package/dist/utils/fs-watch.d.ts +5 -0
  459. package/dist/utils/fs-watch.d.ts.map +1 -0
  460. package/dist/utils/fs-watch.js +25 -0
  461. package/dist/utils/fs-watch.js.map +1 -0
  462. package/dist/utils/git.d.ts.map +1 -1
  463. package/dist/utils/git.js.map +1 -1
  464. package/dist/utils/image-convert.d.ts.map +1 -1
  465. package/dist/utils/image-convert.js +5 -1
  466. package/dist/utils/image-convert.js.map +1 -1
  467. package/dist/utils/image-resize.d.ts +5 -5
  468. package/dist/utils/image-resize.d.ts.map +1 -1
  469. package/dist/utils/image-resize.js +51 -95
  470. package/dist/utils/image-resize.js.map +1 -1
  471. package/dist/utils/mime.d.ts.map +1 -1
  472. package/dist/utils/mime.js.map +1 -1
  473. package/dist/utils/paths.d.ts +16 -0
  474. package/dist/utils/paths.d.ts.map +1 -0
  475. package/dist/utils/paths.js +50 -0
  476. package/dist/utils/paths.js.map +1 -0
  477. package/dist/utils/photon.d.ts.map +1 -1
  478. package/dist/utils/photon.js.map +1 -1
  479. package/dist/utils/pi-user-agent.d.ts +2 -0
  480. package/dist/utils/pi-user-agent.d.ts.map +1 -0
  481. package/dist/utils/pi-user-agent.js +5 -0
  482. package/dist/utils/pi-user-agent.js.map +1 -0
  483. package/dist/utils/shell.d.ts +10 -6
  484. package/dist/utils/shell.d.ts.map +1 -1
  485. package/dist/utils/shell.js +29 -25
  486. package/dist/utils/shell.js.map +1 -1
  487. package/dist/utils/sleep.d.ts.map +1 -1
  488. package/dist/utils/sleep.js.map +1 -1
  489. package/dist/utils/tools-manager.d.ts.map +1 -1
  490. package/dist/utils/tools-manager.js +11 -6
  491. package/dist/utils/tools-manager.js.map +1 -1
  492. package/dist/utils/version-check.d.ts +14 -0
  493. package/dist/utils/version-check.d.ts.map +1 -0
  494. package/dist/utils/version-check.js +77 -0
  495. package/dist/utils/version-check.js.map +1 -0
  496. package/docs/compaction.md +394 -0
  497. package/docs/custom-provider.md +646 -0
  498. package/docs/development.md +71 -0
  499. package/docs/docs.json +148 -0
  500. package/docs/extensions.md +2596 -0
  501. package/docs/images/doom-extension.png +0 -0
  502. package/docs/images/exy.png +0 -0
  503. package/docs/images/interactive-mode.png +0 -0
  504. package/docs/images/tree-view.png +0 -0
  505. package/docs/index.md +70 -0
  506. package/docs/json.md +82 -0
  507. package/docs/keybindings.md +197 -0
  508. package/docs/models.md +474 -0
  509. package/docs/packages.md +223 -0
  510. package/docs/prompt-templates.md +88 -0
  511. package/docs/providers.md +243 -0
  512. package/docs/quickstart.md +142 -0
  513. package/docs/rpc.md +1407 -0
  514. package/docs/sdk.md +1149 -0
  515. package/docs/session-format.md +412 -0
  516. package/docs/sessions.md +137 -0
  517. package/docs/settings.md +279 -0
  518. package/docs/shell-aliases.md +13 -0
  519. package/docs/skills.md +232 -0
  520. package/docs/terminal-setup.md +106 -0
  521. package/docs/termux.md +127 -0
  522. package/docs/themes.md +295 -0
  523. package/docs/tmux.md +61 -0
  524. package/docs/tui.md +918 -0
  525. package/docs/usage.md +277 -0
  526. package/docs/windows.md +17 -0
  527. package/examples/README.md +25 -0
  528. package/examples/extensions/README.md +208 -0
  529. package/examples/extensions/auto-commit-on-exit.ts +49 -0
  530. package/examples/extensions/bash-spawn-hook.ts +30 -0
  531. package/examples/extensions/bookmark.ts +50 -0
  532. package/examples/extensions/border-status-editor.ts +150 -0
  533. package/examples/extensions/built-in-tool-renderer.ts +249 -0
  534. package/examples/extensions/claude-rules.ts +86 -0
  535. package/examples/extensions/commands.ts +72 -0
  536. package/examples/extensions/confirm-destructive.ts +59 -0
  537. package/examples/extensions/custom-compaction.ts +127 -0
  538. package/examples/extensions/custom-footer.ts +64 -0
  539. package/examples/extensions/custom-header.ts +73 -0
  540. package/examples/extensions/custom-provider-anthropic/index.ts +604 -0
  541. package/examples/extensions/custom-provider-anthropic/package-lock.json +24 -0
  542. package/examples/extensions/custom-provider-anthropic/package.json +19 -0
  543. package/examples/extensions/custom-provider-gitlab-duo/index.ts +349 -0
  544. package/examples/extensions/custom-provider-gitlab-duo/package.json +16 -0
  545. package/examples/extensions/custom-provider-gitlab-duo/test.ts +82 -0
  546. package/examples/extensions/dirty-repo-guard.ts +56 -0
  547. package/examples/extensions/doom-overlay/README.md +46 -0
  548. package/examples/extensions/doom-overlay/doom/build/doom.js +21 -0
  549. package/examples/extensions/doom-overlay/doom/build/doom.wasm +0 -0
  550. package/examples/extensions/doom-overlay/doom/build.sh +152 -0
  551. package/examples/extensions/doom-overlay/doom/doomgeneric_pi.c +72 -0
  552. package/examples/extensions/doom-overlay/doom-component.ts +132 -0
  553. package/examples/extensions/doom-overlay/doom-engine.ts +173 -0
  554. package/examples/extensions/doom-overlay/doom-keys.ts +104 -0
  555. package/examples/extensions/doom-overlay/index.ts +74 -0
  556. package/examples/extensions/doom-overlay/wad-finder.ts +51 -0
  557. package/examples/extensions/dynamic-resources/SKILL.md +8 -0
  558. package/examples/extensions/dynamic-resources/dynamic.json +79 -0
  559. package/examples/extensions/dynamic-resources/dynamic.md +5 -0
  560. package/examples/extensions/dynamic-resources/index.ts +15 -0
  561. package/examples/extensions/dynamic-tools.ts +74 -0
  562. package/examples/extensions/event-bus.ts +43 -0
  563. package/examples/extensions/file-trigger.ts +41 -0
  564. package/examples/extensions/git-checkpoint.ts +53 -0
  565. package/examples/extensions/github-issue-autocomplete.ts +185 -0
  566. package/examples/extensions/handoff.ts +191 -0
  567. package/examples/extensions/hello.ts +26 -0
  568. package/examples/extensions/hidden-thinking-label.ts +53 -0
  569. package/examples/extensions/inline-bash.ts +94 -0
  570. package/examples/extensions/input-transform.ts +43 -0
  571. package/examples/extensions/interactive-shell.ts +196 -0
  572. package/examples/extensions/mac-system-theme.ts +47 -0
  573. package/examples/extensions/message-renderer.ts +59 -0
  574. package/examples/extensions/minimal-mode.ts +426 -0
  575. package/examples/extensions/modal-editor.ts +85 -0
  576. package/examples/extensions/model-status.ts +31 -0
  577. package/examples/extensions/notify.ts +55 -0
  578. package/examples/extensions/overlay-qa-tests.ts +1348 -0
  579. package/examples/extensions/overlay-test.ts +150 -0
  580. package/examples/extensions/permission-gate.ts +34 -0
  581. package/examples/extensions/pirate.ts +47 -0
  582. package/examples/extensions/plan-mode/README.md +65 -0
  583. package/examples/extensions/plan-mode/index.ts +340 -0
  584. package/examples/extensions/plan-mode/utils.ts +168 -0
  585. package/examples/extensions/preset.ts +430 -0
  586. package/examples/extensions/prompt-customizer.ts +97 -0
  587. package/examples/extensions/protected-paths.ts +30 -0
  588. package/examples/extensions/provider-payload.ts +18 -0
  589. package/examples/extensions/qna.ts +122 -0
  590. package/examples/extensions/question.ts +264 -0
  591. package/examples/extensions/questionnaire.ts +427 -0
  592. package/examples/extensions/rainbow-editor.ts +88 -0
  593. package/examples/extensions/reload-runtime.ts +37 -0
  594. package/examples/extensions/rpc-demo.ts +118 -0
  595. package/examples/extensions/sandbox/index.ts +321 -0
  596. package/examples/extensions/sandbox/package-lock.json +92 -0
  597. package/examples/extensions/sandbox/package.json +19 -0
  598. package/examples/extensions/send-user-message.ts +97 -0
  599. package/examples/extensions/session-name.ts +27 -0
  600. package/examples/extensions/shutdown-command.ts +63 -0
  601. package/examples/extensions/snake.ts +343 -0
  602. package/examples/extensions/space-invaders.ts +560 -0
  603. package/examples/extensions/ssh.ts +220 -0
  604. package/examples/extensions/status-line.ts +32 -0
  605. package/examples/extensions/structured-output.ts +65 -0
  606. package/examples/extensions/subagent/README.md +172 -0
  607. package/examples/extensions/subagent/agents/planner.md +37 -0
  608. package/examples/extensions/subagent/agents/reviewer.md +35 -0
  609. package/examples/extensions/subagent/agents/scout.md +50 -0
  610. package/examples/extensions/subagent/agents/worker.md +24 -0
  611. package/examples/extensions/subagent/agents.ts +126 -0
  612. package/examples/extensions/subagent/index.ts +987 -0
  613. package/examples/extensions/subagent/prompts/implement-and-review.md +10 -0
  614. package/examples/extensions/subagent/prompts/implement.md +10 -0
  615. package/examples/extensions/subagent/prompts/scout-and-plan.md +9 -0
  616. package/examples/extensions/summarize.ts +206 -0
  617. package/examples/extensions/system-prompt-header.ts +17 -0
  618. package/examples/extensions/tic-tac-toe.ts +1008 -0
  619. package/examples/extensions/timed-confirm.ts +70 -0
  620. package/examples/extensions/titlebar-spinner.ts +58 -0
  621. package/examples/extensions/todo.ts +297 -0
  622. package/examples/extensions/tool-override.ts +144 -0
  623. package/examples/extensions/tools.ts +141 -0
  624. package/examples/extensions/trigger-compact.ts +50 -0
  625. package/examples/extensions/truncated-tool.ts +195 -0
  626. package/examples/extensions/widget-placement.ts +9 -0
  627. package/examples/extensions/with-deps/index.ts +32 -0
  628. package/examples/extensions/with-deps/package-lock.json +31 -0
  629. package/examples/extensions/with-deps/package.json +22 -0
  630. package/examples/extensions/working-indicator.ts +123 -0
  631. package/examples/extensions/working-message-test.ts +25 -0
  632. package/examples/rpc-extension-ui.ts +632 -0
  633. package/examples/sdk/01-minimal.ts +22 -0
  634. package/examples/sdk/02-custom-model.ts +49 -0
  635. package/examples/sdk/03-custom-prompt.ts +62 -0
  636. package/examples/sdk/04-skills.ts +55 -0
  637. package/examples/sdk/05-tools.ts +44 -0
  638. package/examples/sdk/06-extensions.ts +90 -0
  639. package/examples/sdk/07-context-files.ts +42 -0
  640. package/examples/sdk/08-prompt-templates.ts +51 -0
  641. package/examples/sdk/09-api-keys-and-oauth.ts +48 -0
  642. package/examples/sdk/10-settings.ts +53 -0
  643. package/examples/sdk/11-sessions.ts +48 -0
  644. package/examples/sdk/12-full-control.ts +73 -0
  645. package/examples/sdk/13-session-runtime.ts +67 -0
  646. package/examples/sdk/README.md +147 -0
  647. package/extensions/phi/init.ts +15 -1
  648. package/extensions/phi/keys.ts +186 -0
  649. package/extensions/phi/providers/alibaba.ts +126 -0
  650. package/extensions/phi/providers/opencode-go.ts +204 -0
  651. package/extensions/phi/setup.ts +692 -0
  652. package/extensions/phi/smart-router.ts +8 -0
  653. package/package.json +17 -12
  654. package/scripts/copy-assets.sh +0 -0
  655. package/scripts/migrate-sessions.sh +0 -0
@@ -0,0 +1,692 @@
1
+ /**
2
+ * Setup Wizard Extension (/setup) - Refonte UX du wizard de configuration.
3
+ *
4
+ * Per Q8 strategy B: nouvelle commande /setup qui remplace /phi-init
5
+ * (gardé en alias rétrocompat dans init.ts). UX:
6
+ * - Panneau de statut persistant via setWidget (providers + assignments)
7
+ * - Fuzzy search via ctx.ui.select (matching builtin Phi/upstream)
8
+ * - Ping API immédiat à la saisie de clé (validation 401/200)
9
+ * - Choix endpoint Alibaba (OpenAI-compat vs Anthropic-compat per Q2C)
10
+ * - OpenCode Go avec auto-fetch runtime des modèles (per Q4A)
11
+ * - Sélection séparée chat normal vs orchestration (5 phases)
12
+ * - Persistance atomique via ApiKeyStore (chmod 0600 Unix)
13
+ * - Hot-reload propagation: setKey émet "key_changed" event
14
+ *
15
+ * Note: ctx.ui.input ne supporte pas le masking actuellement (limitation TUI).
16
+ * Pour compenser:
17
+ * - Warning explicite avant la saisie ("la clé apparaitra à l'écran")
18
+ * - Toutes les notifications post-saisie utilisent ApiKeyStore.maskKey()
19
+ * - Storage chmod 0600 garantit la sécurité au repos
20
+ */
21
+
22
+ import { ApiKeyStore, type ExtensionAPI, type ExtensionUIContext, getApiKeyStore } from "phi-code";
23
+ import { writeFile, mkdir } from "node:fs/promises";
24
+ import { join } from "node:path";
25
+ import { homedir } from "node:os";
26
+ import {
27
+ ALIBABA_ENV_VAR,
28
+ ALIBABA_MODELS,
29
+ ALIBABA_PROVIDERS,
30
+ ALIBABA_RATE_LIMITS,
31
+ buildAlibabaProviderConfig,
32
+ pingAlibaba,
33
+ validateAlibabaApiKey,
34
+ } from "./providers/alibaba.js";
35
+ import {
36
+ OPENCODE_GO_AUTH_URL,
37
+ OPENCODE_GO_ENV_VAR,
38
+ buildOpenCodeGoProviderConfig,
39
+ getOpenCodeGoModels,
40
+ pingOpenCodeGo,
41
+ validateOpenCodeGoApiKey,
42
+ } from "./providers/opencode-go.js";
43
+
44
+ // ─── Types ───────────────────────────────────────────────────────────────
45
+
46
+ interface ProviderEntry {
47
+ id: string;
48
+ displayName: string;
49
+ envVar: string;
50
+ baseUrl: string;
51
+ api: string;
52
+ staticModels: string[];
53
+ supportsOAuth?: boolean;
54
+ local?: boolean;
55
+ probeUrl?: string;
56
+ docUrl?: string;
57
+ }
58
+
59
+ interface RouteAssignment {
60
+ preferred: string;
61
+ fallback: string;
62
+ }
63
+
64
+ interface RoutingConfigOut {
65
+ routes: Record<
66
+ string,
67
+ {
68
+ description: string;
69
+ keywords: string[];
70
+ preferredModel: string;
71
+ fallback: string;
72
+ agent: string;
73
+ }
74
+ >;
75
+ default: { model: string; agent: string | null };
76
+ }
77
+
78
+ const ORCHESTRATION_ROLES = [
79
+ { key: "explore", label: "Explore", desc: "Read-only analysis", agent: "explore", keywords: ["read", "analyze", "explain", "understand", "find", "search", "look", "show", "what", "how"] },
80
+ { key: "plan", label: "Plan", desc: "Architecture and design", agent: "plan", keywords: ["plan", "design", "architect", "spec", "structure", "organize", "strategy", "approach"] },
81
+ { key: "code", label: "Code", desc: "Implementation", agent: "code", keywords: ["implement", "create", "build", "refactor", "write", "add", "modify", "update", "generate"] },
82
+ { key: "test", label: "Test", desc: "Validation and tests", agent: "test", keywords: ["test", "verify", "validate", "check", "assert", "coverage"] },
83
+ { key: "review", label: "Review", desc: "Quality and security review", agent: "review", keywords: ["review", "audit", "quality", "security", "improve", "optimize"] },
84
+ ] as const;
85
+
86
+ const DEBUG_KEYWORDS = ["fix", "bug", "error", "debug", "crash", "broken", "failing", "issue", "troubleshoot"];
87
+
88
+ // ─── Provider catalog ────────────────────────────────────────────────────
89
+
90
+ function getProviderCatalog(): ProviderEntry[] {
91
+ return [
92
+ {
93
+ id: "alibaba-codingplan",
94
+ displayName: "Alibaba Coding Plan",
95
+ envVar: ALIBABA_ENV_VAR,
96
+ baseUrl: ALIBABA_PROVIDERS.openai.baseUrl,
97
+ api: "openai-completions",
98
+ staticModels: ALIBABA_MODELS.map((m) => m.id),
99
+ docUrl: "https://www.alibabacloud.com/help/en/model-studio/coding-plan",
100
+ },
101
+ {
102
+ id: "opencode-go",
103
+ displayName: "OpenCode Go (zen)",
104
+ envVar: OPENCODE_GO_ENV_VAR,
105
+ baseUrl: "https://opencode.ai/zen/go/v1",
106
+ api: "openai-completions",
107
+ staticModels: [],
108
+ docUrl: OPENCODE_GO_AUTH_URL,
109
+ },
110
+ {
111
+ id: "openai",
112
+ displayName: "OpenAI",
113
+ envVar: "OPENAI_API_KEY",
114
+ baseUrl: "https://api.openai.com/v1",
115
+ api: "openai-completions",
116
+ staticModels: ["gpt-4o", "gpt-4o-mini", "o1", "o3-mini", "gpt-5"],
117
+ supportsOAuth: true,
118
+ },
119
+ {
120
+ id: "anthropic",
121
+ displayName: "Anthropic",
122
+ envVar: "ANTHROPIC_API_KEY",
123
+ baseUrl: "https://api.anthropic.com/v1",
124
+ api: "anthropic-messages",
125
+ staticModels: ["claude-opus-4-6", "claude-sonnet-4-6", "claude-3-5-haiku-20241022"],
126
+ supportsOAuth: true,
127
+ },
128
+ {
129
+ id: "google",
130
+ displayName: "Google Gemini",
131
+ envVar: "GOOGLE_API_KEY",
132
+ baseUrl: "https://generativelanguage.googleapis.com/v1beta",
133
+ api: "google",
134
+ staticModels: ["gemini-2.5-pro", "gemini-2.5-flash"],
135
+ supportsOAuth: true,
136
+ },
137
+ {
138
+ id: "openrouter",
139
+ displayName: "OpenRouter",
140
+ envVar: "OPENROUTER_API_KEY",
141
+ baseUrl: "https://openrouter.ai/api/v1",
142
+ api: "openai-completions",
143
+ staticModels: [],
144
+ },
145
+ {
146
+ id: "groq",
147
+ displayName: "Groq",
148
+ envVar: "GROQ_API_KEY",
149
+ baseUrl: "https://api.groq.com/openai/v1",
150
+ api: "openai-completions",
151
+ staticModels: ["llama-3.3-70b-versatile", "openai/gpt-oss-120b"],
152
+ },
153
+ {
154
+ id: "ollama",
155
+ displayName: "Ollama (local)",
156
+ envVar: "OLLAMA",
157
+ baseUrl: "http://localhost:11434/v1",
158
+ api: "openai-completions",
159
+ staticModels: [],
160
+ local: true,
161
+ probeUrl: "http://localhost:11434/v1/models",
162
+ },
163
+ {
164
+ id: "lm-studio",
165
+ displayName: "LM Studio (local)",
166
+ envVar: "LM_STUDIO",
167
+ baseUrl: "http://localhost:1234/v1",
168
+ api: "openai-completions",
169
+ staticModels: [],
170
+ local: true,
171
+ probeUrl: "http://localhost:1234/v1/models",
172
+ },
173
+ ];
174
+ }
175
+
176
+ // ─── Helpers ─────────────────────────────────────────────────────────────
177
+
178
+ async function probeLocalProvider(provider: ProviderEntry): Promise<string[]> {
179
+ if (!provider.probeUrl) return [];
180
+ const controller = new AbortController();
181
+ const timeout = setTimeout(() => controller.abort(), 2_500);
182
+ try {
183
+ const res = await fetch(provider.probeUrl, {
184
+ signal: controller.signal,
185
+ headers: { Authorization: `Bearer ${provider.id === "ollama" ? "ollama" : "lm-studio"}` },
186
+ });
187
+ clearTimeout(timeout);
188
+ if (!res.ok) return [];
189
+ const data = (await res.json()) as { data?: Array<{ id?: string; name?: string }> };
190
+ return (data.data ?? []).map((m) => m.id ?? m.name ?? "").filter(Boolean);
191
+ } catch {
192
+ clearTimeout(timeout);
193
+ return [];
194
+ }
195
+ }
196
+
197
+ function buildStatusWidget(
198
+ store: ApiKeyStore,
199
+ available: Map<string, { source: "key" | "env" | "local"; modelCount: number }>,
200
+ assignments: { default?: string; orchestration: Record<string, RouteAssignment> },
201
+ ): string[] {
202
+ const lines: string[] = [];
203
+ lines.push("─── Phi Code Setup ───");
204
+ lines.push("");
205
+ lines.push("Providers:");
206
+ const catalog = getProviderCatalog();
207
+ for (const p of catalog) {
208
+ const state = available.get(p.id);
209
+ const icon = state ? "[ok]" : "[--]";
210
+ const note = state ? ` (${state.modelCount} models, ${state.source})` : "";
211
+ lines.push(` ${icon} ${p.displayName}${note}`);
212
+ }
213
+ lines.push("");
214
+ lines.push("Assignments:");
215
+ lines.push(` Default chat : ${assignments.default ?? "(not set)"}`);
216
+ for (const role of ORCHESTRATION_ROLES) {
217
+ const a = assignments.orchestration[role.key];
218
+ const preferred = a?.preferred ?? "(not set)";
219
+ const fallback = a?.fallback ?? "(none)";
220
+ lines.push(` ${role.label.padEnd(8)} : ${preferred} / ${fallback}`);
221
+ }
222
+ lines.push("");
223
+ lines.push(`Keys file : ${store.configPath} (chmod 0600 on Unix)`);
224
+ return lines;
225
+ }
226
+
227
+ function maskKeyForDisplay(key: string | undefined): string {
228
+ return ApiKeyStore.maskKey(key);
229
+ }
230
+
231
+ function buildRoutingConfig(
232
+ defaultModel: string,
233
+ orchestration: Record<string, RouteAssignment>,
234
+ ): RoutingConfigOut {
235
+ const routes: RoutingConfigOut["routes"] = {};
236
+ for (const role of ORCHESTRATION_ROLES) {
237
+ const a = orchestration[role.key] ?? { preferred: defaultModel, fallback: defaultModel };
238
+ routes[role.key] = {
239
+ description: role.desc,
240
+ keywords: [...role.keywords],
241
+ preferredModel: a.preferred,
242
+ fallback: a.fallback,
243
+ agent: role.agent,
244
+ };
245
+ }
246
+ routes.debug = {
247
+ description: "Debugging, fixing, error resolution",
248
+ keywords: [...DEBUG_KEYWORDS],
249
+ preferredModel: orchestration.code?.preferred ?? defaultModel,
250
+ fallback: orchestration.code?.fallback ?? defaultModel,
251
+ agent: "code",
252
+ };
253
+ return {
254
+ routes,
255
+ default: { model: defaultModel, agent: null },
256
+ };
257
+ }
258
+
259
+ async function writeRoutingConfig(routing: RoutingConfigOut): Promise<string> {
260
+ const dir = join(homedir(), ".phi", "agent");
261
+ await mkdir(dir, { recursive: true });
262
+ const path = join(dir, "routing.json");
263
+ await writeFile(path, `${JSON.stringify({ ...routing, $schema: "./routing.schema.json", version: 1 }, null, 2)}\n`, "utf-8");
264
+ return path;
265
+ }
266
+
267
+ // ─── Provider configuration sub-flow ─────────────────────────────────────
268
+
269
+ async function configureAlibaba(
270
+ ui: ExtensionUIContext,
271
+ store: ApiKeyStore,
272
+ ): Promise<{ providerId: string; modelCount: number } | undefined> {
273
+ ui.notify(
274
+ `**Alibaba Coding Plan** (${ALIBABA_RATE_LIMITS.subscriptionType})\n` +
275
+ `Rate limits: ${ALIBABA_RATE_LIMITS.per5Hours}/5h | ${ALIBABA_RATE_LIMITS.perWeek}/week | ${ALIBABA_RATE_LIMITS.perMonth}/month\n` +
276
+ `Both variants share the SAME API key (env var ${ALIBABA_ENV_VAR}, format sk-sp-xxxxx).`,
277
+ "info",
278
+ );
279
+
280
+ const variantChoice = await ui.select("Which Alibaba endpoint to configure?", [
281
+ "OpenAI-compat (/v1) - legacy, broad compat",
282
+ "Anthropic-compat (/apps/anthropic) - ~99.7% prompt cache hit (recommended)",
283
+ "Both endpoints (configure once, register both)",
284
+ "Cancel",
285
+ ]);
286
+ if (!variantChoice || variantChoice === "Cancel") return undefined;
287
+
288
+ ui.notify(
289
+ "WARNING: the key you type will be visible on screen during input. " +
290
+ "It will be stored chmod 0600 in ~/.phi/agent/models.json.",
291
+ "warning",
292
+ );
293
+ const apiKey = await ui.input("Paste your Alibaba Coding Plan API key", "sk-sp-...");
294
+ if (!apiKey || apiKey.trim().length === 0) {
295
+ ui.notify("No key provided. Skipped.", "warning");
296
+ return undefined;
297
+ }
298
+
299
+ const trimmed = apiKey.trim();
300
+ const validationError = validateAlibabaApiKey(trimmed);
301
+ if (validationError) {
302
+ const proceed = await ui.confirm("Invalid key format", `${validationError}. Save anyway?`);
303
+ if (!proceed) return undefined;
304
+ }
305
+
306
+ ui.setStatus("setup-ping", "Pinging Alibaba endpoint...");
307
+ const pingResult = await pingAlibaba(trimmed);
308
+ ui.setStatus("setup-ping", undefined);
309
+
310
+ if (!pingResult.ok) {
311
+ const proceed = await ui.confirm(
312
+ "Ping failed",
313
+ `Alibaba ping failed: ${pingResult.error ?? "unknown"}. Save key anyway?`,
314
+ );
315
+ if (!proceed) return undefined;
316
+ } else {
317
+ ui.notify("Alibaba ping OK (200).", "info");
318
+ }
319
+
320
+ let modelCount = 0;
321
+ let lastProviderId = "alibaba-codingplan";
322
+
323
+ const installVariant = (variant: "openai" | "anthropic"): void => {
324
+ const provider = ALIBABA_PROVIDERS[variant];
325
+ const config = buildAlibabaProviderConfig(variant, trimmed);
326
+ store.setKey(provider.id, trimmed, {
327
+ baseUrl: config.baseUrl,
328
+ api: config.api,
329
+ models: config.models,
330
+ });
331
+ modelCount += config.models.length;
332
+ lastProviderId = provider.id;
333
+ };
334
+
335
+ if (variantChoice.startsWith("OpenAI-compat")) installVariant("openai");
336
+ else if (variantChoice.startsWith("Anthropic-compat")) installVariant("anthropic");
337
+ else {
338
+ installVariant("openai");
339
+ installVariant("anthropic");
340
+ }
341
+
342
+ ui.notify(
343
+ `Alibaba configured: \`${maskKeyForDisplay(trimmed)}\` -> ${variantChoice.split(" -")[0]}\n` +
344
+ `${modelCount} model entries saved to ~/.phi/agent/models.json.`,
345
+ "info",
346
+ );
347
+ return { providerId: lastProviderId, modelCount };
348
+ }
349
+
350
+ async function configureOpenCodeGo(
351
+ ui: ExtensionUIContext,
352
+ store: ApiKeyStore,
353
+ ): Promise<{ providerId: string; modelCount: number } | undefined> {
354
+ ui.notify(
355
+ `**OpenCode Go (zen)** - subscribe at ${OPENCODE_GO_AUTH_URL} ($5 first month, $10/month).\n` +
356
+ `After subscribing, paste your API key below.`,
357
+ "info",
358
+ );
359
+
360
+ ui.notify("WARNING: the key you type will be visible on screen during input.", "warning");
361
+ const apiKey = await ui.input("Paste your OpenCode Go API key", "...");
362
+ if (!apiKey || apiKey.trim().length === 0) {
363
+ ui.notify("No key provided. Skipped.", "warning");
364
+ return undefined;
365
+ }
366
+
367
+ const trimmed = apiKey.trim();
368
+ const validationError = validateOpenCodeGoApiKey(trimmed);
369
+ if (validationError) {
370
+ const proceed = await ui.confirm("Invalid key format", `${validationError}. Save anyway?`);
371
+ if (!proceed) return undefined;
372
+ }
373
+
374
+ ui.setStatus("setup-ping", "Pinging OpenCode Go...");
375
+ const pingResult = await pingOpenCodeGo(trimmed);
376
+ ui.setStatus("setup-ping", undefined);
377
+
378
+ if (!pingResult.ok) {
379
+ const proceed = await ui.confirm(
380
+ "Ping failed",
381
+ `OpenCode Go ping failed: ${pingResult.error ?? "unknown"}. Save key anyway?`,
382
+ );
383
+ if (!proceed) return undefined;
384
+ } else {
385
+ ui.notify("OpenCode Go ping OK (200).", "info");
386
+ }
387
+
388
+ ui.setStatus("setup-fetch", "Fetching live OpenCode Go model list...");
389
+ const { models, source } = await getOpenCodeGoModels({ apiKey: trimmed, forceRefresh: true });
390
+ ui.setStatus("setup-fetch", undefined);
391
+
392
+ ui.notify(`Fetched ${models.length} OpenCode Go models (source: ${source}).`, "info");
393
+ const config = buildOpenCodeGoProviderConfig(trimmed, models);
394
+ store.setKey("opencode-go", trimmed, {
395
+ baseUrl: config.baseUrl,
396
+ api: config.api,
397
+ models: config.models,
398
+ });
399
+
400
+ ui.notify(
401
+ `OpenCode Go configured: \`${maskKeyForDisplay(trimmed)}\` (${models.length} models)`,
402
+ "info",
403
+ );
404
+ return { providerId: "opencode-go", modelCount: models.length };
405
+ }
406
+
407
+ async function configureGenericCloud(
408
+ ui: ExtensionUIContext,
409
+ store: ApiKeyStore,
410
+ provider: ProviderEntry,
411
+ ): Promise<{ providerId: string; modelCount: number } | undefined> {
412
+ if (provider.supportsOAuth) {
413
+ const authChoice = await ui.select(`Auth method for ${provider.displayName}`, [
414
+ "API Key (paste your key)",
415
+ "OAuth (run /login after setup)",
416
+ "Cancel",
417
+ ]);
418
+ if (!authChoice || authChoice === "Cancel") return undefined;
419
+ if (authChoice.startsWith("OAuth")) {
420
+ ui.notify(
421
+ `Run \`/login ${provider.id}\` after setup to authenticate via OAuth.`,
422
+ "info",
423
+ );
424
+ store.setKey(provider.id, "$OAUTH", {
425
+ baseUrl: provider.baseUrl,
426
+ api: provider.api,
427
+ });
428
+ return { providerId: provider.id, modelCount: provider.staticModels.length };
429
+ }
430
+ }
431
+
432
+ ui.notify("WARNING: the key you type will be visible on screen during input.", "warning");
433
+ const apiKey = await ui.input(`Paste your ${provider.displayName} API key`, "...");
434
+ if (!apiKey || apiKey.trim().length === 0) {
435
+ ui.notify("No key provided. Skipped.", "warning");
436
+ return undefined;
437
+ }
438
+
439
+ const trimmed = apiKey.trim();
440
+ if (trimmed.length < 8) {
441
+ const proceed = await ui.confirm("Suspiciously short key", "Save anyway?");
442
+ if (!proceed) return undefined;
443
+ }
444
+
445
+ store.setKey(provider.id, trimmed, {
446
+ baseUrl: provider.baseUrl,
447
+ api: provider.api,
448
+ models: provider.staticModels.map((id) => ({
449
+ id,
450
+ name: id,
451
+ reasoning: true,
452
+ input: ["text"] as const,
453
+ })),
454
+ });
455
+ ui.notify(
456
+ `${provider.displayName} configured: \`${maskKeyForDisplay(trimmed)}\` (${provider.staticModels.length} models)`,
457
+ "info",
458
+ );
459
+ return { providerId: provider.id, modelCount: provider.staticModels.length };
460
+ }
461
+
462
+ async function configureLocal(
463
+ ui: ExtensionUIContext,
464
+ store: ApiKeyStore,
465
+ provider: ProviderEntry,
466
+ ): Promise<{ providerId: string; modelCount: number } | undefined> {
467
+ ui.setStatus("setup-probe", `Probing ${provider.displayName}...`);
468
+ const models = await probeLocalProvider(provider);
469
+ ui.setStatus("setup-probe", undefined);
470
+
471
+ if (models.length === 0) {
472
+ ui.notify(
473
+ `${provider.displayName} not reachable at ${provider.baseUrl}. ` +
474
+ `Start the server and re-run /setup, or skip.`,
475
+ "warning",
476
+ );
477
+ return undefined;
478
+ }
479
+
480
+ store.setKey(provider.id, "local", {
481
+ baseUrl: provider.baseUrl,
482
+ api: provider.api,
483
+ models: models.map((id) => ({
484
+ id,
485
+ name: id,
486
+ reasoning: false,
487
+ input: ["text"] as const,
488
+ })),
489
+ });
490
+ ui.notify(`${provider.displayName} configured: ${models.length} models discovered.`, "info");
491
+ return { providerId: provider.id, modelCount: models.length };
492
+ }
493
+
494
+ // ─── Assignment sub-flow ─────────────────────────────────────────────────
495
+
496
+ async function pickModelFromCatalog(
497
+ ui: ExtensionUIContext,
498
+ prompt: string,
499
+ allModelIds: string[],
500
+ ): Promise<string | undefined> {
501
+ if (allModelIds.length === 0) {
502
+ ui.notify("No models available. Configure a provider first.", "warning");
503
+ return undefined;
504
+ }
505
+ const options = ["(keep default)", ...allModelIds];
506
+ const choice = await ui.select(prompt, options);
507
+ if (!choice || choice === options[0]) return undefined;
508
+ return choice;
509
+ }
510
+
511
+ async function configureAssignments(
512
+ ui: ExtensionUIContext,
513
+ allModelIds: string[],
514
+ ): Promise<{ defaultModel: string; orchestration: Record<string, RouteAssignment> }> {
515
+ if (allModelIds.length === 0) {
516
+ ui.notify("No models available for assignment. Configure a provider first.", "warning");
517
+ return { defaultModel: "default", orchestration: {} };
518
+ }
519
+
520
+ const defaultModel =
521
+ (await pickModelFromCatalog(ui, "Default chat model (used when no orchestration is active)", allModelIds)) ??
522
+ allModelIds[0];
523
+
524
+ const orchestration: Record<string, RouteAssignment> = {};
525
+ for (const role of ORCHESTRATION_ROLES) {
526
+ const preferred =
527
+ (await pickModelFromCatalog(ui, `${role.label} - preferred model (${role.desc})`, allModelIds)) ??
528
+ defaultModel;
529
+ const fallbackOptions = allModelIds.filter((m) => m !== preferred);
530
+ const fallback = fallbackOptions.length > 0
531
+ ? (await pickModelFromCatalog(ui, `${role.label} - fallback model`, fallbackOptions)) ?? preferred
532
+ : preferred;
533
+ orchestration[role.key] = { preferred, fallback };
534
+ ui.notify(` ${role.label}: ${preferred} / ${fallback}`, "info");
535
+ }
536
+
537
+ return { defaultModel, orchestration };
538
+ }
539
+
540
+ // ─── Extension ───────────────────────────────────────────────────────────
541
+
542
+ export default function setupExtension(pi: ExtensionAPI) {
543
+ pi.registerCommand("setup", {
544
+ description: "Phi Code setup wizard (refonte UX, replaces /phi-init)",
545
+ handler: async (_args, ctx) => {
546
+ const ui = ctx.ui;
547
+ const store = getApiKeyStore();
548
+ try {
549
+ store.load();
550
+ } catch {
551
+ // empty file or missing, fine
552
+ }
553
+
554
+ ui.notify(
555
+ "**φ Phi Code Setup Wizard**\n\n" +
556
+ "This wizard configures providers and assigns models to agent roles.\n" +
557
+ "Keys are stored in `~/.phi/agent/models.json` (chmod 0600 on Unix).\n" +
558
+ "Edit that file directly later to hot-reload (no restart needed).",
559
+ "info",
560
+ );
561
+
562
+ const available = new Map<string, { source: "key" | "env" | "local"; modelCount: number }>();
563
+ const assignments: { default?: string; orchestration: Record<string, RouteAssignment> } = {
564
+ orchestration: {},
565
+ };
566
+
567
+ const refreshAvailable = (): void => {
568
+ const catalog = getProviderCatalog();
569
+ available.clear();
570
+ for (const p of catalog) {
571
+ const stored = store.getProvider(p.id);
572
+ if (stored?.apiKey) {
573
+ const source = stored.apiKey === "$OAUTH" ? "key" : stored.apiKey === "local" ? "local" : "key";
574
+ const modelCount = Array.isArray(stored.models) ? stored.models.length : p.staticModels.length;
575
+ available.set(p.id, { source, modelCount });
576
+ continue;
577
+ }
578
+ if (!p.local && process.env[p.envVar]) {
579
+ available.set(p.id, { source: "env", modelCount: p.staticModels.length });
580
+ }
581
+ }
582
+ ui.setWidget("setup-status", buildStatusWidget(store, available, assignments));
583
+ };
584
+
585
+ refreshAvailable();
586
+
587
+ let done = false;
588
+ while (!done) {
589
+ const catalog = getProviderCatalog();
590
+ const choices: string[] = [];
591
+ for (const p of catalog) {
592
+ const state = available.get(p.id);
593
+ const tag = state ? "[ok]" : "[--]";
594
+ const modelTag = state ? ` (${state.modelCount} models)` : "";
595
+ choices.push(`${tag} ${p.displayName}${modelTag}`);
596
+ }
597
+ choices.push("---");
598
+ choices.push("Assign models to agent roles");
599
+ choices.push("Finish and save");
600
+ choices.push("Quit without saving");
601
+
602
+ const action = await ui.select("Phi Code Setup - choose an action", choices);
603
+ if (!action) {
604
+ done = true;
605
+ break;
606
+ }
607
+
608
+ if (action === "Quit without saving") {
609
+ const confirm = await ui.confirm("Quit", "Discard all in-memory assignments? (provider keys already saved are kept)");
610
+ if (confirm) {
611
+ ui.setWidget("setup-status", undefined);
612
+ ui.notify("Setup cancelled (saved provider keys are unchanged).", "warning");
613
+ return;
614
+ }
615
+ continue;
616
+ }
617
+
618
+ if (action === "Finish and save") {
619
+ if (!assignments.default || Object.keys(assignments.orchestration).length === 0) {
620
+ const proceed = await ui.confirm(
621
+ "Assignments incomplete",
622
+ "You have not assigned all roles. Save current state anyway?",
623
+ );
624
+ if (!proceed) continue;
625
+ }
626
+ done = true;
627
+ break;
628
+ }
629
+
630
+ if (action === "Assign models to agent roles") {
631
+ const allModelIds: string[] = [];
632
+ for (const p of catalog) {
633
+ const stored = store.getProvider(p.id);
634
+ if (!stored) continue;
635
+ const models = Array.isArray(stored.models) ? stored.models : [];
636
+ for (const m of models) {
637
+ const id = (m as { id?: string }).id;
638
+ if (typeof id === "string" && !allModelIds.includes(id)) allModelIds.push(id);
639
+ }
640
+ }
641
+ const { defaultModel, orchestration } = await configureAssignments(ui, allModelIds);
642
+ assignments.default = defaultModel;
643
+ assignments.orchestration = orchestration;
644
+ refreshAvailable();
645
+ continue;
646
+ }
647
+
648
+ if (action === "---") continue;
649
+
650
+ const providerIndex = choices.indexOf(action);
651
+ if (providerIndex < 0 || providerIndex >= catalog.length) continue;
652
+ const provider = catalog[providerIndex];
653
+
654
+ let result: { providerId: string; modelCount: number } | undefined;
655
+ if (provider.id === "alibaba-codingplan") {
656
+ result = await configureAlibaba(ui, store);
657
+ } else if (provider.id === "opencode-go") {
658
+ result = await configureOpenCodeGo(ui, store);
659
+ } else if (provider.local) {
660
+ result = await configureLocal(ui, store, provider);
661
+ } else {
662
+ result = await configureGenericCloud(ui, store, provider);
663
+ }
664
+
665
+ if (result) refreshAvailable();
666
+ }
667
+
668
+ // Save routing if assignments were made
669
+ if (assignments.default) {
670
+ try {
671
+ const routing = buildRoutingConfig(assignments.default, assignments.orchestration);
672
+ const routingPath = await writeRoutingConfig(routing);
673
+ ui.notify(`Routing config written to \`${routingPath}\`.`, "info");
674
+ } catch (err) {
675
+ ui.notify(`Failed to write routing.json: ${err}`, "error");
676
+ }
677
+ }
678
+
679
+ ui.setWidget("setup-status", undefined);
680
+ ui.notify(
681
+ "**Setup complete.**\n\n" +
682
+ "Next steps:\n" +
683
+ " - `/keys` to list/manage saved keys\n" +
684
+ " - `/routing` to inspect routing\n" +
685
+ " - `/agents` to list sub-agents\n" +
686
+ " - `/skills` to list skills\n" +
687
+ " - Edit `~/.phi/agent/models.json` or `routing.json` directly: hot-reload kicks in",
688
+ "info",
689
+ );
690
+ },
691
+ });
692
+ }
@@ -193,5 +193,13 @@ export default function smartRouterExtension(pi: ExtensionAPI) {
193
193
 
194
194
  pi.on("session_start", async (_event, _ctx) => {
195
195
  await loadConfig();
196
+ // Listen for routing.json file-watcher events (emitted by keys.ts extension).
197
+ // This implements Q9 strategy A: auto-reload SmartRouter when routing.json
198
+ // changes on disk, no /routing reload command needed.
199
+ pi.events.on("routing_json_changed", () => {
200
+ loadConfig().catch(() => {
201
+ // If reload fails, keep the in-memory config rather than wiping it
202
+ });
203
+ });
196
204
  });
197
205
  }