@phi-code-admin/phi-code 0.74.2 → 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 (656) 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/extensions/phi/web-search.ts +432 -186
  654. package/package.json +111 -106
  655. package/scripts/copy-assets.sh +0 -0
  656. package/scripts/migrate-sessions.sh +0 -0
@@ -0,0 +1,147 @@
1
+ # SDK Examples
2
+
3
+ Programmatic usage of pi-coding-agent via `createAgentSession()` and `createAgentSessionRuntime()`.
4
+
5
+ The runtime example shows how to build a recreate function that closes over process-global fixed inputs and recreates cwd-bound services and sessions as the active session cwd changes.
6
+
7
+ ## Examples
8
+
9
+ | File | Description |
10
+ |------|-------------|
11
+ | `01-minimal.ts` | Simplest usage with all defaults |
12
+ | `02-custom-model.ts` | Select model and thinking level |
13
+ | `03-custom-prompt.ts` | Replace or modify system prompt |
14
+ | `04-skills.ts` | Discover, filter, or replace skills |
15
+ | `05-tools.ts` | Built-in tools, custom tools |
16
+ | `06-extensions.ts` | Logging, blocking, result modification |
17
+ | `07-context-files.ts` | AGENTS.md context files |
18
+ | `08-slash-commands.ts` | File-based slash commands |
19
+ | `09-api-keys-and-oauth.ts` | API key resolution, OAuth config |
20
+ | `10-settings.ts` | Override compaction, retry, terminal settings |
21
+ | `11-sessions.ts` | In-memory, persistent, continue, list sessions |
22
+ | `12-full-control.ts` | Replace everything, no discovery |
23
+ | `13-session-runtime.ts` | Manage runtime-backed session replacement |
24
+
25
+ ## Running
26
+
27
+ ```bash
28
+ cd packages/coding-agent
29
+ npx tsx examples/sdk/01-minimal.ts
30
+ ```
31
+
32
+ ## Quick Reference
33
+
34
+ ```typescript
35
+ import { getModel } from "@earendil-works/pi-ai";
36
+ import {
37
+ AuthStorage,
38
+ createAgentSession,
39
+ DefaultResourceLoader,
40
+ ModelRegistry,
41
+ SessionManager,
42
+ SettingsManager,
43
+ codingTools,
44
+ readOnlyTools,
45
+ readTool, bashTool, editTool, writeTool,
46
+ } from "@earendil-works/pi-coding-agent";
47
+
48
+ // Auth and models setup
49
+ const authStorage = AuthStorage.create();
50
+ const modelRegistry = ModelRegistry.create(authStorage);
51
+
52
+ // Minimal
53
+ const { session } = await createAgentSession({ authStorage, modelRegistry });
54
+
55
+ // Custom model
56
+ const model = getModel("anthropic", "claude-opus-4-5");
57
+ const { session } = await createAgentSession({ model, thinkingLevel: "high", authStorage, modelRegistry });
58
+
59
+ // Modify prompt
60
+ const loader = new DefaultResourceLoader({
61
+ systemPromptOverride: (base) => `${base}\n\nBe concise.`,
62
+ });
63
+ await loader.reload();
64
+ const { session } = await createAgentSession({ resourceLoader: loader, authStorage, modelRegistry });
65
+
66
+ // Read-only
67
+ const { session } = await createAgentSession({ tools: readOnlyTools, authStorage, modelRegistry });
68
+
69
+ // In-memory
70
+ const { session } = await createAgentSession({
71
+ sessionManager: SessionManager.inMemory(),
72
+ authStorage,
73
+ modelRegistry,
74
+ });
75
+
76
+ // Full control
77
+ const customAuth = AuthStorage.create("/my/app/auth.json");
78
+ customAuth.setRuntimeApiKey("anthropic", process.env.MY_KEY!);
79
+ const customRegistry = ModelRegistry.create(customAuth);
80
+
81
+ const resourceLoader = new DefaultResourceLoader({
82
+ systemPromptOverride: () => "You are helpful.",
83
+ extensionFactories: [myExtension],
84
+ skillsOverride: () => ({ skills: [], diagnostics: [] }),
85
+ agentsFilesOverride: () => ({ agentsFiles: [] }),
86
+ promptsOverride: () => ({ prompts: [], diagnostics: [] }),
87
+ });
88
+ await resourceLoader.reload();
89
+
90
+ const { session } = await createAgentSession({
91
+ model,
92
+ authStorage: customAuth,
93
+ modelRegistry: customRegistry,
94
+ resourceLoader,
95
+ tools: [readTool, bashTool],
96
+ customTools: [{ tool: myTool }],
97
+ sessionManager: SessionManager.inMemory(),
98
+ settingsManager: SettingsManager.inMemory(),
99
+ });
100
+
101
+ // Run prompts
102
+ session.subscribe((event) => {
103
+ if (event.type === "message_update" && event.assistantMessageEvent.type === "text_delta") {
104
+ process.stdout.write(event.assistantMessageEvent.delta);
105
+ }
106
+ });
107
+ await session.prompt("Hello");
108
+ ```
109
+
110
+ ## Options
111
+
112
+ | Option | Default | Description |
113
+ |--------|---------|-------------|
114
+ | `authStorage` | `AuthStorage.create()` | Credential storage |
115
+ | `modelRegistry` | `ModelRegistry.create(authStorage)` | Model registry |
116
+ | `cwd` | `process.cwd()` | Working directory |
117
+ | `agentDir` | `~/.pi/agent` | Config directory |
118
+ | `model` | From settings/first available | Model to use |
119
+ | `thinkingLevel` | From settings/"off" | off, low, medium, high |
120
+ | `tools` | `codingTools` | Built-in tools |
121
+ | `customTools` | `[]` | Additional tool definitions |
122
+ | `resourceLoader` | DefaultResourceLoader | Resource loader for extensions, skills, prompts, themes |
123
+ | `sessionManager` | `SessionManager.create(cwd)` | Persistence |
124
+ | `settingsManager` | `SettingsManager.create(cwd, agentDir)` | Settings overrides |
125
+
126
+ ## Events
127
+
128
+ ```typescript
129
+ session.subscribe((event) => {
130
+ switch (event.type) {
131
+ case "message_update":
132
+ if (event.assistantMessageEvent.type === "text_delta") {
133
+ process.stdout.write(event.assistantMessageEvent.delta);
134
+ }
135
+ break;
136
+ case "tool_execution_start":
137
+ console.log(`Tool: ${event.toolName}`);
138
+ break;
139
+ case "tool_execution_end":
140
+ console.log(`Result: ${event.result}`);
141
+ break;
142
+ case "agent_end":
143
+ console.log("Done");
144
+ break;
145
+ }
146
+ });
147
+ ```
@@ -152,6 +152,13 @@ function detectProviders(): DetectedProvider[] {
152
152
  models: ["qwen3.5-plus", "qwen3-max-2026-01-23", "qwen3-coder-plus", "qwen3-coder-next", "kimi-k2.5", "glm-5", "glm-4.7", "MiniMax-M2.5"],
153
153
  available: false,
154
154
  },
155
+ {
156
+ name: "OpenCode Go",
157
+ envVar: "OPENCODE_GO_API_KEY",
158
+ baseUrl: "https://opencode.ai/zen/go/v1",
159
+ models: ["kimi-k2.6", "kimi-k2.5", "qwen3-coder", "qwen3-coder-plus", "glm-4.6", "glm-5", "deepseek-v3", "minimax-m2", "MiniMax-M2.5", "moonshotai-kimi-thinking", "z-ai-glm-4.7", "gpt-oss-120b"],
160
+ available: false,
161
+ },
155
162
  {
156
163
  name: "OpenAI",
157
164
  envVar: "OPENAI_API_KEY",
@@ -408,8 +415,15 @@ _Edit this file to customize Phi Code's behavior for your project._
408
415
  // ─── Command ─────────────────────────────────────────────────────
409
416
 
410
417
  pi.registerCommand("phi-init", {
411
- description: "Initialize Phi Code — interactive setup wizard",
418
+ description: "Initialize Phi Code (legacy alias prefer /setup for the refined wizard)",
412
419
  handler: async (args, ctx) => {
420
+ ctx.ui.notify(
421
+ "NOTE: `/phi-init` is the legacy wizard. The refined replacement is `/setup` " +
422
+ "(richer flow: Alibaba dual-endpoint, OpenCode Go auto-fetch, ping validation, " +
423
+ "separate chat/orchestration assignments, hot-reload integration). " +
424
+ "This legacy command still works for backwards compatibility.",
425
+ "info",
426
+ );
413
427
  try {
414
428
  ctx.ui.notify("╔══════════════════════════════════════╗", "info");
415
429
  ctx.ui.notify("║ φ Phi Code Setup Wizard ║", "info");
@@ -0,0 +1,186 @@
1
+ /**
2
+ * Keys Extension - /keys command for managing API keys + file watcher hot-reload.
3
+ *
4
+ * Per Q5 strategy C: explicit /keys command AND file watcher on
5
+ * ~/.phi/agent/models.json + routing.json.
6
+ *
7
+ * Subcommands:
8
+ * /keys : list configured providers with masked keys
9
+ * /keys set <id> <key> : set or update a provider key
10
+ * /keys remove <id> : remove a provider key (preserves the rest of config)
11
+ * /keys test <id> : ping the provider API to validate the key
12
+ * /keys reload : force reload from disk (triggers store_reloaded event)
13
+ *
14
+ * File watcher (started at session_start) reloads automatically when the
15
+ * user edits ~/.phi/agent/models.json or routing.json with their text editor.
16
+ * The smart-router and orchestrator listen for these events to invalidate
17
+ * their internal caches.
18
+ *
19
+ * Security (Q6): keys are stored in plain text in ~/.phi/agent/models.json
20
+ * with chmod 0600 on Unix. The user is warned in /setup and on `set`.
21
+ */
22
+
23
+ import { ApiKeyStore, type ExtensionAPI, getApiKeyStore, getConfigWatcher } from "phi-code";
24
+
25
+ interface ProviderPingFn {
26
+ (key: string, timeoutMs?: number): Promise<{ ok: boolean; error?: string }>;
27
+ }
28
+
29
+ const PROVIDER_PING_REGISTRY: Record<string, ProviderPingFn> = {};
30
+
31
+ /**
32
+ * Public helper for other extensions to register a ping function for a provider.
33
+ * Used by alibaba.ts / opencode-go.ts to expose validation.
34
+ */
35
+ export function registerProviderPing(providerId: string, ping: ProviderPingFn): void {
36
+ PROVIDER_PING_REGISTRY[providerId] = ping;
37
+ }
38
+
39
+ export default function keysExtension(pi: ExtensionAPI) {
40
+ const store = getApiKeyStore();
41
+ const watcher = getConfigWatcher();
42
+
43
+ pi.registerCommand("keys", {
44
+ description: "Manage API keys (list / set / remove / test / reload)",
45
+ handler: async (args, ctx) => {
46
+ const tokens = args.trim().split(/\s+/).filter(Boolean);
47
+ const sub = tokens[0]?.toLowerCase() ?? "";
48
+
49
+ try {
50
+ if (sub === "" || sub === "list") {
51
+ const providers = store.listProviders();
52
+ if (providers.length === 0) {
53
+ ctx.ui.notify(
54
+ "No providers configured. Use `/keys set <provider-id> <key>` or `/setup` to add one.",
55
+ "info",
56
+ );
57
+ return;
58
+ }
59
+ let out = `**API Keys (${providers.length} providers)**\n\n`;
60
+ out += `Storage: \`${store.configPath}\` (chmod 0600 on Unix)\n\n`;
61
+ for (const id of providers) {
62
+ const cfg = store.getProvider(id);
63
+ const masked = ApiKeyStore.maskKey(cfg?.apiKey);
64
+ const url = cfg?.baseUrl ?? "(no baseUrl)";
65
+ out += ` **${id}** : \`${masked}\` -> ${url}\n`;
66
+ }
67
+ out += `\nCommands: \`/keys set <id> <key>\`, \`/keys remove <id>\`, \`/keys test <id>\`, \`/keys reload\``;
68
+ ctx.ui.notify(out, "info");
69
+ return;
70
+ }
71
+
72
+ if (sub === "set") {
73
+ const id = tokens[1];
74
+ const key = tokens.slice(2).join(" ");
75
+ if (!id || !key) {
76
+ ctx.ui.notify("Usage: `/keys set <provider-id> <api-key>`", "warning");
77
+ return;
78
+ }
79
+ watcher.muteForWrite("models_json_changed");
80
+ store.setKey(id, key);
81
+ ctx.ui.notify(
82
+ `Key set for \`${id}\` (\`${ApiKeyStore.maskKey(key)}\`). Stored in ${store.configPath}.\n` +
83
+ `Hot-reload will propagate to providers using this key.\n` +
84
+ `Use \`/keys test ${id}\` to validate.`,
85
+ "info",
86
+ );
87
+ return;
88
+ }
89
+
90
+ if (sub === "remove" || sub === "rm" || sub === "delete") {
91
+ const id = tokens[1];
92
+ if (!id) {
93
+ ctx.ui.notify("Usage: `/keys remove <provider-id>`", "warning");
94
+ return;
95
+ }
96
+ const before = store.getKey(id);
97
+ if (!before) {
98
+ ctx.ui.notify(`No key configured for \`${id}\`. Nothing to remove.`, "info");
99
+ return;
100
+ }
101
+ watcher.muteForWrite("models_json_changed");
102
+ store.removeKey(id);
103
+ ctx.ui.notify(`Key removed for \`${id}\` (provider config retained).`, "info");
104
+ return;
105
+ }
106
+
107
+ if (sub === "test") {
108
+ const id = tokens[1];
109
+ if (!id) {
110
+ ctx.ui.notify("Usage: `/keys test <provider-id>`", "warning");
111
+ return;
112
+ }
113
+ const key = store.getKey(id);
114
+ if (!key) {
115
+ ctx.ui.notify(`No key configured for \`${id}\`.`, "warning");
116
+ return;
117
+ }
118
+ const ping = PROVIDER_PING_REGISTRY[id];
119
+ if (!ping) {
120
+ ctx.ui.notify(
121
+ `No ping handler registered for \`${id}\`. Built-in pings exist for: ${Object.keys(PROVIDER_PING_REGISTRY).join(", ") || "(none)"}.`,
122
+ "warning",
123
+ );
124
+ return;
125
+ }
126
+ ctx.ui.notify(`Pinging \`${id}\`...`, "info");
127
+ const result = await ping(key);
128
+ if (result.ok) {
129
+ ctx.ui.notify(`\`${id}\`: API key valid (200 OK).`, "info");
130
+ } else {
131
+ ctx.ui.notify(`\`${id}\`: ${result.error ?? "ping failed"}`, "error");
132
+ }
133
+ return;
134
+ }
135
+
136
+ if (sub === "reload") {
137
+ store.reloadFromDisk();
138
+ ctx.ui.notify("Reloaded keys from disk. Listeners notified.", "info");
139
+ return;
140
+ }
141
+
142
+ ctx.ui.notify(
143
+ "Unknown subcommand. Use: `/keys [list|set|remove|test|reload]`",
144
+ "warning",
145
+ );
146
+ } catch (err) {
147
+ ctx.ui.notify(`/keys error: ${err instanceof Error ? err.message : String(err)}`, "error");
148
+ }
149
+ },
150
+ });
151
+
152
+ pi.on("session_start", async (_event, ctx) => {
153
+ try {
154
+ store.load();
155
+ } catch {
156
+ // Empty/missing models.json on first run is normal
157
+ }
158
+
159
+ watcher.start();
160
+ watcher.on("models_json_changed", () => {
161
+ try {
162
+ store.reloadFromDisk();
163
+ ctx.ui.notify("Detected change in `models.json`. Keys reloaded.", "info");
164
+ } catch (err) {
165
+ ctx.ui.notify(`Failed to reload models.json: ${err}`, "warning");
166
+ }
167
+ });
168
+ watcher.on("routing_json_changed", () => {
169
+ ctx.ui.notify("Detected change in `routing.json`. Smart-router will reload on next input.", "info");
170
+ pi.events.emit("routing_json_changed", { source: "watcher" });
171
+ });
172
+ watcher.on("watcher_error", (data: unknown) => {
173
+ const d = data as { path: string; error: unknown };
174
+ ctx.ui.notify(`Config watcher error on ${d.path}: ${d.error}`, "warning");
175
+ });
176
+
177
+ const providers = store.listProviders();
178
+ if (providers.length > 0) {
179
+ ctx.ui.notify(
180
+ `Loaded ${providers.length} provider key(s) from \`~/.phi/agent/models.json\` (chmod 0600). ` +
181
+ `Use \`/keys\` to list/manage. Editing this file in your editor will hot-reload.`,
182
+ "info",
183
+ );
184
+ }
185
+ });
186
+ }
@@ -0,0 +1,126 @@
1
+ /**
2
+ * Alibaba Coding Plan Provider - Source of truth for Alibaba config.
3
+ *
4
+ * Provides 2 variants:
5
+ * - alibaba-codingplan : OpenAI-compat (/v1) — legacy, works everywhere
6
+ * - alibaba-codingplan-anthropic: Anthropic-compat (/apps/anthropic) — ~99.7% prompt cache hit
7
+ *
8
+ * Both share ALIBABA_CODING_PLAN_KEY env var (format: sk-sp-xxxxx).
9
+ *
10
+ * Models are STATIC versioned (no public listing endpoint).
11
+ * To refresh: run `npx tsx scripts/refresh-alibaba-models.ts` (Q3 strategy C).
12
+ *
13
+ * Rate limits (Pro Plan, $50/month):
14
+ * - 6,000 requests / 5-hour sliding window
15
+ * - 45,000 requests / week (resets Mon 00:00 UTC+8)
16
+ * - 90,000 requests / month (resets on subscription anniversary)
17
+ */
18
+
19
+ export const ALIBABA_ENV_VAR = "ALIBABA_CODING_PLAN_KEY";
20
+ export const ALIBABA_API_KEY_PREFIX = "sk-sp-";
21
+
22
+ export const ALIBABA_PROVIDERS = {
23
+ openai: {
24
+ id: "alibaba-codingplan",
25
+ displayName: "Alibaba Coding Plan (OpenAI-compat)",
26
+ baseUrl: "https://coding-intl.dashscope.aliyuncs.com/v1",
27
+ api: "openai-completions" as const,
28
+ },
29
+ anthropic: {
30
+ id: "alibaba-codingplan-anthropic",
31
+ displayName: "Alibaba Coding Plan (Anthropic-compat, native prompt cache)",
32
+ baseUrl: "https://coding-intl.dashscope.aliyuncs.com/apps/anthropic",
33
+ api: "anthropic-messages" as const,
34
+ },
35
+ } as const;
36
+
37
+ export interface AlibabaModelSpec {
38
+ id: string;
39
+ name: string;
40
+ contextWindow: number;
41
+ maxTokens: number;
42
+ reasoning: boolean;
43
+ }
44
+
45
+ /**
46
+ * Bundled Alibaba models. Refresh via `scripts/refresh-alibaba-models.ts`.
47
+ * Last verified: 2026-05-10.
48
+ */
49
+ export const ALIBABA_MODELS: readonly AlibabaModelSpec[] = [
50
+ { id: "qwen3.5-plus", name: "Qwen 3.5 Plus", contextWindow: 1_000_000, maxTokens: 16_384, reasoning: true },
51
+ { id: "qwen3-max-2026-01-23", name: "Qwen 3 Max", contextWindow: 262_144, maxTokens: 16_384, reasoning: true },
52
+ { id: "qwen3-coder-plus", name: "Qwen 3 Coder Plus", contextWindow: 1_000_000, maxTokens: 16_384, reasoning: true },
53
+ { id: "qwen3-coder-next", name: "Qwen 3 Coder Next", contextWindow: 1_000_000, maxTokens: 16_384, reasoning: true },
54
+ { id: "kimi-k2.5", name: "Kimi K2.5", contextWindow: 262_144, maxTokens: 16_384, reasoning: true },
55
+ { id: "glm-5", name: "GLM 5", contextWindow: 200_000, maxTokens: 128_000, reasoning: true },
56
+ { id: "glm-4.7", name: "GLM 4.7", contextWindow: 200_000, maxTokens: 128_000, reasoning: true },
57
+ { id: "MiniMax-M2.5", name: "MiniMax M2.5", contextWindow: 1_000_000, maxTokens: 16_384, reasoning: true },
58
+ ] as const;
59
+
60
+ export const ALIBABA_RATE_LIMITS = {
61
+ per5Hours: 6_000,
62
+ perWeek: 45_000,
63
+ perMonth: 90_000,
64
+ weekResetUTC: "Mon 00:00 UTC+8",
65
+ subscriptionType: "Pro Plan ($50/month)",
66
+ } as const;
67
+
68
+ /**
69
+ * Validate Alibaba Coding Plan API key format.
70
+ * Returns null if valid, error message otherwise.
71
+ */
72
+ export function validateAlibabaApiKey(key: string): string | null {
73
+ const trimmed = key.trim();
74
+ if (trimmed.length === 0) return "API key is empty";
75
+ if (trimmed.length < 10) return "API key too short";
76
+ if (!trimmed.startsWith(ALIBABA_API_KEY_PREFIX)) {
77
+ return `API key should start with "${ALIBABA_API_KEY_PREFIX}" (Coding Plan prefix)`;
78
+ }
79
+ return null;
80
+ }
81
+
82
+ /**
83
+ * Build a models.json provider entry for one variant.
84
+ * Used by init.ts/setup.ts when user picks Alibaba.
85
+ */
86
+ export function buildAlibabaProviderConfig(variant: "openai" | "anthropic", apiKey: string) {
87
+ const provider = ALIBABA_PROVIDERS[variant];
88
+ const isAnthropic = variant === "anthropic";
89
+ return {
90
+ baseUrl: provider.baseUrl,
91
+ api: provider.api,
92
+ apiKey,
93
+ models: ALIBABA_MODELS.map((m) => ({
94
+ id: m.id,
95
+ name: isAnthropic ? `${m.name} (Anthropic-compat)` : m.name,
96
+ reasoning: m.reasoning,
97
+ input: ["text"] as const,
98
+ contextWindow: m.contextWindow,
99
+ maxTokens: m.maxTokens,
100
+ ...(isAnthropic ? { compat: { supportsLongCacheRetention: true } } : {}),
101
+ })),
102
+ };
103
+ }
104
+
105
+ /**
106
+ * Test an Alibaba API key by hitting /v1/models (lightweight).
107
+ * Returns true if 200, false otherwise.
108
+ */
109
+ export async function pingAlibaba(apiKey: string, timeoutMs = 5_000): Promise<{ ok: boolean; error?: string }> {
110
+ const controller = new AbortController();
111
+ const timeout = setTimeout(() => controller.abort(), timeoutMs);
112
+ try {
113
+ const res = await fetch(`${ALIBABA_PROVIDERS.openai.baseUrl}/models`, {
114
+ signal: controller.signal,
115
+ headers: { Authorization: `Bearer ${apiKey}` },
116
+ });
117
+ clearTimeout(timeout);
118
+ if (res.ok) return { ok: true };
119
+ if (res.status === 401) return { ok: false, error: "Invalid API key (401)" };
120
+ return { ok: false, error: `HTTP ${res.status}` };
121
+ } catch (err) {
122
+ clearTimeout(timeout);
123
+ const msg = err instanceof Error ? err.message : String(err);
124
+ return { ok: false, error: msg };
125
+ }
126
+ }
@@ -0,0 +1,204 @@
1
+ /**
2
+ * OpenCode Go (zen) Provider - Runtime auto-fetch of available models.
3
+ *
4
+ * Per Q4 strategy A:
5
+ * - Fetch live list from https://opencode.ai/zen/go/v1/models at runtime
6
+ * - Cache TTL 1 hour in memory + refresh background
7
+ * - Fallback to bundled static list versioned (last sync date) on network failure
8
+ *
9
+ * Authentication is API-key only (no OAuth device code per opencode.ai docs).
10
+ * Users get key from https://opencode.ai/auth after subscribing to Go ($5 first month).
11
+ *
12
+ * Provider id: opencode-go (already a KnownProvider in phi-code-ai).
13
+ * Endpoints:
14
+ * - Models list: https://opencode.ai/zen/go/v1/models
15
+ * - OpenAI-compat: https://opencode.ai/zen/go/v1/chat/completions
16
+ * - Anthropic-compat: https://opencode.ai/zen/go/v1/messages
17
+ *
18
+ * Model IDs follow format: opencode-go/<model-id> (e.g., opencode-go/kimi-k2.6).
19
+ */
20
+
21
+ export const OPENCODE_GO_ENV_VAR = "OPENCODE_GO_API_KEY";
22
+ export const OPENCODE_GO_AUTH_URL = "https://opencode.ai/auth";
23
+ export const OPENCODE_GO_MODELS_URL = "https://opencode.ai/zen/go/v1/models";
24
+ export const OPENCODE_GO_OPENAI_URL = "https://opencode.ai/zen/go/v1/chat/completions";
25
+ export const OPENCODE_GO_ANTHROPIC_URL = "https://opencode.ai/zen/go/v1/messages";
26
+
27
+ export interface OpenCodeGoModel {
28
+ id: string;
29
+ name?: string;
30
+ contextWindow?: number;
31
+ maxTokens?: number;
32
+ }
33
+
34
+ interface OpenCodeGoModelsResponse {
35
+ data?: Array<{
36
+ id: string;
37
+ name?: string;
38
+ context_length?: number;
39
+ max_tokens?: number;
40
+ context_window?: number;
41
+ }>;
42
+ }
43
+
44
+ /**
45
+ * Fallback static list of OpenCode Go models.
46
+ * Last verified: 2026-05-10 (12 models).
47
+ * Used when network unreachable or auth fails before configuration.
48
+ */
49
+ export const OPENCODE_GO_FALLBACK_MODELS: readonly OpenCodeGoModel[] = [
50
+ { id: "kimi-k2.6", name: "Kimi K2.6", contextWindow: 256_000, maxTokens: 16_384 },
51
+ { id: "kimi-k2.5", name: "Kimi K2.5", contextWindow: 256_000, maxTokens: 16_384 },
52
+ { id: "qwen3-coder", name: "Qwen 3 Coder", contextWindow: 1_000_000, maxTokens: 16_384 },
53
+ { id: "qwen3-coder-plus", name: "Qwen 3 Coder Plus", contextWindow: 1_000_000, maxTokens: 16_384 },
54
+ { id: "glm-4.6", name: "GLM 4.6", contextWindow: 200_000, maxTokens: 128_000 },
55
+ { id: "glm-5", name: "GLM 5", contextWindow: 200_000, maxTokens: 128_000 },
56
+ { id: "deepseek-v3", name: "DeepSeek V3", contextWindow: 128_000, maxTokens: 8_192 },
57
+ { id: "minimax-m2", name: "MiniMax M2", contextWindow: 1_000_000, maxTokens: 16_384 },
58
+ { id: "MiniMax-M2.5", name: "MiniMax M2.5", contextWindow: 1_000_000, maxTokens: 16_384 },
59
+ { id: "moonshotai-kimi-thinking", name: "Kimi Thinking", contextWindow: 256_000, maxTokens: 16_384 },
60
+ { id: "z-ai-glm-4.7", name: "Z-AI GLM 4.7", contextWindow: 200_000, maxTokens: 128_000 },
61
+ { id: "gpt-oss-120b", name: "GPT-OSS 120B", contextWindow: 128_000, maxTokens: 8_192 },
62
+ ] as const;
63
+
64
+ interface CacheEntry {
65
+ models: OpenCodeGoModel[];
66
+ fetchedAt: number;
67
+ }
68
+
69
+ const CACHE_TTL_MS = 60 * 60 * 1000; // 1 hour
70
+ let cache: CacheEntry | null = null;
71
+ let inflightFetch: Promise<OpenCodeGoModel[]> | null = null;
72
+
73
+ function isCacheValid(now: number): boolean {
74
+ return cache !== null && now - cache.fetchedAt < CACHE_TTL_MS;
75
+ }
76
+
77
+ async function fetchModelsRaw(apiKey: string | undefined, timeoutMs: number): Promise<OpenCodeGoModel[]> {
78
+ const controller = new AbortController();
79
+ const timeout = setTimeout(() => controller.abort(), timeoutMs);
80
+ try {
81
+ const headers: Record<string, string> = { Accept: "application/json" };
82
+ if (apiKey) headers.Authorization = `Bearer ${apiKey}`;
83
+ const res = await fetch(OPENCODE_GO_MODELS_URL, { signal: controller.signal, headers });
84
+ clearTimeout(timeout);
85
+ if (!res.ok) {
86
+ throw new Error(`HTTP ${res.status}`);
87
+ }
88
+ const json = (await res.json()) as OpenCodeGoModelsResponse;
89
+ const data = json.data ?? [];
90
+ return data.map((m) => ({
91
+ id: m.id,
92
+ name: m.name ?? m.id,
93
+ contextWindow: m.context_length ?? m.context_window,
94
+ maxTokens: m.max_tokens,
95
+ }));
96
+ } catch (err) {
97
+ clearTimeout(timeout);
98
+ throw err;
99
+ }
100
+ }
101
+
102
+ /**
103
+ * Get OpenCode Go models. Uses cache (TTL 1h) when fresh,
104
+ * else fetches live with fallback to static list on failure.
105
+ */
106
+ export async function getOpenCodeGoModels(options?: {
107
+ apiKey?: string;
108
+ forceRefresh?: boolean;
109
+ timeoutMs?: number;
110
+ }): Promise<{ models: OpenCodeGoModel[]; source: "cache" | "live" | "fallback" }> {
111
+ const now = Date.now();
112
+ const force = options?.forceRefresh === true;
113
+ const timeoutMs = options?.timeoutMs ?? 5_000;
114
+
115
+ if (!force && isCacheValid(now)) {
116
+ return { models: cache!.models, source: "cache" };
117
+ }
118
+
119
+ if (inflightFetch) {
120
+ try {
121
+ const models = await inflightFetch;
122
+ return { models, source: "live" };
123
+ } catch {
124
+ // fall through to fresh attempt
125
+ }
126
+ }
127
+
128
+ inflightFetch = fetchModelsRaw(options?.apiKey, timeoutMs);
129
+ try {
130
+ const models = await inflightFetch;
131
+ cache = { models, fetchedAt: now };
132
+ return { models, source: "live" };
133
+ } catch {
134
+ if (cache) {
135
+ return { models: cache.models, source: "cache" };
136
+ }
137
+ return { models: [...OPENCODE_GO_FALLBACK_MODELS], source: "fallback" };
138
+ } finally {
139
+ inflightFetch = null;
140
+ }
141
+ }
142
+
143
+ /**
144
+ * Validate OpenCode Go API key by hitting /models with auth.
145
+ * No standardized key prefix is documented, so we only check non-empty.
146
+ */
147
+ export function validateOpenCodeGoApiKey(key: string): string | null {
148
+ const trimmed = key.trim();
149
+ if (trimmed.length === 0) return "API key is empty";
150
+ if (trimmed.length < 10) return "API key too short";
151
+ return null;
152
+ }
153
+
154
+ /**
155
+ * Ping the OpenCode Go API with a given key.
156
+ */
157
+ export async function pingOpenCodeGo(apiKey: string, timeoutMs = 5_000): Promise<{ ok: boolean; error?: string }> {
158
+ const controller = new AbortController();
159
+ const timeout = setTimeout(() => controller.abort(), timeoutMs);
160
+ try {
161
+ const res = await fetch(OPENCODE_GO_MODELS_URL, {
162
+ signal: controller.signal,
163
+ headers: { Authorization: `Bearer ${apiKey}`, Accept: "application/json" },
164
+ });
165
+ clearTimeout(timeout);
166
+ if (res.ok) return { ok: true };
167
+ if (res.status === 401) return { ok: false, error: "Invalid API key (401)" };
168
+ return { ok: false, error: `HTTP ${res.status}` };
169
+ } catch (err) {
170
+ clearTimeout(timeout);
171
+ const msg = err instanceof Error ? err.message : String(err);
172
+ return { ok: false, error: msg };
173
+ }
174
+ }
175
+
176
+ /**
177
+ * Build a models.json provider entry from a fetched/fallback model list.
178
+ * OpenCode Go is a KnownProvider in phi-code-ai, so this is only used
179
+ * when the user wants to override defaults (e.g., add a new model
180
+ * not yet in models.generated.ts).
181
+ */
182
+ export function buildOpenCodeGoProviderConfig(apiKey: string, models: OpenCodeGoModel[]) {
183
+ return {
184
+ baseUrl: "https://opencode.ai/zen/go/v1",
185
+ api: "openai-completions" as const,
186
+ apiKey,
187
+ models: models.map((m) => ({
188
+ id: m.id,
189
+ name: m.name ?? m.id,
190
+ reasoning: true,
191
+ input: ["text"] as const,
192
+ contextWindow: m.contextWindow ?? 128_000,
193
+ maxTokens: m.maxTokens ?? 16_384,
194
+ })),
195
+ };
196
+ }
197
+
198
+ /**
199
+ * Reset the in-memory cache. Useful for tests.
200
+ */
201
+ export function _resetOpenCodeGoCache(): void {
202
+ cache = null;
203
+ inflightFetch = null;
204
+ }