@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.
- package/CHANGELOG.md +1186 -4
- package/README.md +478 -379
- package/dist/bun/cli.d.ts +3 -0
- package/dist/bun/cli.d.ts.map +1 -0
- package/dist/bun/cli.js +9 -0
- package/dist/bun/cli.js.map +1 -0
- package/dist/bun/register-bedrock.d.ts +2 -0
- package/dist/bun/register-bedrock.d.ts.map +1 -0
- package/dist/bun/register-bedrock.js +4 -0
- package/dist/bun/register-bedrock.js.map +1 -0
- package/dist/bun/restore-sandbox-env.d.ts +13 -0
- package/dist/bun/restore-sandbox-env.d.ts.map +1 -0
- package/dist/bun/restore-sandbox-env.js +32 -0
- package/dist/bun/restore-sandbox-env.js.map +1 -0
- package/dist/cli/args.d.ts +12 -7
- package/dist/cli/args.d.ts.map +1 -1
- package/dist/cli/args.js +87 -45
- package/dist/cli/args.js.map +1 -1
- package/dist/cli/config-selector.d.ts.map +1 -1
- package/dist/cli/config-selector.js.map +1 -1
- package/dist/cli/file-processor.d.ts.map +1 -1
- package/dist/cli/file-processor.js +4 -0
- package/dist/cli/file-processor.js.map +1 -1
- package/dist/cli/initial-message.d.ts +18 -0
- package/dist/cli/initial-message.d.ts.map +1 -0
- package/dist/cli/initial-message.js +22 -0
- package/dist/cli/initial-message.js.map +1 -0
- package/dist/cli/list-models.d.ts.map +1 -1
- package/dist/cli/list-models.js +7 -1
- package/dist/cli/list-models.js.map +1 -1
- package/dist/cli/session-picker.d.ts.map +1 -1
- package/dist/cli/session-picker.js +2 -1
- package/dist/cli/session-picker.js.map +1 -1
- package/dist/cli.d.ts.map +1 -1
- package/dist/cli.js +9 -5
- package/dist/cli.js.map +1 -1
- package/dist/config.d.ts +24 -0
- package/dist/config.d.ts.map +1 -1
- package/dist/config.js +226 -30
- package/dist/config.js.map +1 -1
- package/dist/core/agent-session-runtime.d.ts +117 -0
- package/dist/core/agent-session-runtime.d.ts.map +1 -0
- package/dist/core/agent-session-runtime.js +300 -0
- package/dist/core/agent-session-runtime.js.map +1 -0
- package/dist/core/agent-session-services.d.ts +86 -0
- package/dist/core/agent-session-services.d.ts.map +1 -0
- package/dist/core/agent-session-services.js +117 -0
- package/dist/core/agent-session-services.js.map +1 -0
- package/dist/core/agent-session.d.ts +63 -82
- package/dist/core/agent-session.d.ts.map +1 -1
- package/dist/core/agent-session.js +674 -628
- package/dist/core/agent-session.js.map +1 -1
- package/dist/core/api-key-store.d.ts +87 -0
- package/dist/core/api-key-store.d.ts.map +1 -0
- package/dist/core/api-key-store.js +168 -0
- package/dist/core/api-key-store.js.map +1 -0
- package/dist/core/auth-guidance.d.ts +5 -0
- package/dist/core/auth-guidance.d.ts.map +1 -0
- package/dist/core/auth-guidance.js +21 -0
- package/dist/core/auth-guidance.js.map +1 -0
- package/dist/core/auth-storage.d.ts +12 -5
- package/dist/core/auth-storage.d.ts.map +1 -1
- package/dist/core/auth-storage.js +34 -8
- package/dist/core/auth-storage.js.map +1 -1
- package/dist/core/bash-executor.d.ts +0 -15
- package/dist/core/bash-executor.d.ts.map +1 -1
- package/dist/core/bash-executor.js +28 -129
- package/dist/core/bash-executor.js.map +1 -1
- package/dist/core/compaction/branch-summarization.d.ts +2 -0
- package/dist/core/compaction/branch-summarization.d.ts.map +1 -1
- package/dist/core/compaction/branch-summarization.js +3 -2
- package/dist/core/compaction/branch-summarization.js.map +1 -1
- package/dist/core/compaction/compaction.d.ts +4 -4
- package/dist/core/compaction/compaction.d.ts.map +1 -1
- package/dist/core/compaction/compaction.js +32 -27
- package/dist/core/compaction/compaction.js.map +1 -1
- package/dist/core/compaction/index.d.ts.map +1 -1
- package/dist/core/compaction/utils.d.ts.map +1 -1
- package/dist/core/compaction/utils.js.map +1 -1
- package/dist/core/config-watcher.d.ts +47 -0
- package/dist/core/config-watcher.d.ts.map +1 -0
- package/dist/core/config-watcher.js +135 -0
- package/dist/core/config-watcher.js.map +1 -0
- package/dist/core/default-models.json +80 -0
- package/dist/core/defaults.d.ts.map +1 -1
- package/dist/core/diagnostics.d.ts.map +1 -1
- package/dist/core/event-bus.d.ts.map +1 -1
- package/dist/core/event-bus.js.map +1 -1
- package/dist/core/exec.d.ts.map +1 -1
- package/dist/core/exec.js +7 -3
- package/dist/core/exec.js.map +1 -1
- package/dist/core/export-html/ansi-to-html.d.ts.map +1 -1
- package/dist/core/export-html/ansi-to-html.js +1 -1
- package/dist/core/export-html/ansi-to-html.js.map +1 -1
- package/dist/core/export-html/index.d.ts +7 -4
- package/dist/core/export-html/index.d.ts.map +1 -1
- package/dist/core/export-html/index.js +15 -13
- package/dist/core/export-html/index.js.map +1 -1
- package/dist/core/export-html/template.css +112 -17
- package/dist/core/export-html/template.html +1 -0
- package/dist/core/export-html/template.js +312 -64
- package/dist/core/export-html/tool-renderer.d.ts +9 -10
- package/dist/core/export-html/tool-renderer.d.ts.map +1 -1
- package/dist/core/export-html/tool-renderer.js +61 -16
- package/dist/core/export-html/tool-renderer.js.map +1 -1
- package/dist/core/extensions/index.d.ts +5 -4
- package/dist/core/extensions/index.d.ts.map +1 -1
- package/dist/core/extensions/index.js +2 -2
- package/dist/core/extensions/index.js.map +1 -1
- package/dist/core/extensions/loader.d.ts +0 -1
- package/dist/core/extensions/loader.d.ts.map +1 -1
- package/dist/core/extensions/loader.js +98 -18
- package/dist/core/extensions/loader.js.map +1 -1
- package/dist/core/extensions/runner.d.ts +27 -14
- package/dist/core/extensions/runner.d.ts.map +1 -1
- package/dist/core/extensions/runner.js +299 -115
- package/dist/core/extensions/runner.js.map +1 -1
- package/dist/core/extensions/types.d.ts +200 -44
- package/dist/core/extensions/types.d.ts.map +1 -1
- package/dist/core/extensions/types.js +10 -0
- package/dist/core/extensions/types.js.map +1 -1
- package/dist/core/extensions/wrapper.d.ts +4 -11
- package/dist/core/extensions/wrapper.d.ts.map +1 -1
- package/dist/core/extensions/wrapper.js +7 -87
- package/dist/core/extensions/wrapper.js.map +1 -1
- package/dist/core/footer-data-provider.d.ts +22 -2
- package/dist/core/footer-data-provider.d.ts.map +1 -1
- package/dist/core/footer-data-provider.js +225 -49
- package/dist/core/footer-data-provider.js.map +1 -1
- package/dist/core/index.d.ts +5 -2
- package/dist/core/index.d.ts.map +1 -1
- package/dist/core/index.js +5 -2
- package/dist/core/index.js.map +1 -1
- package/dist/core/keybindings.d.ts +348 -50
- package/dist/core/keybindings.d.ts.map +1 -1
- package/dist/core/keybindings.js +276 -132
- package/dist/core/keybindings.js.map +1 -1
- package/dist/core/messages.d.ts.map +1 -1
- package/dist/core/messages.js.map +1 -1
- package/dist/core/model-registry.d.ts +41 -5
- package/dist/core/model-registry.d.ts.map +1 -1
- package/dist/core/model-registry.js +316 -136
- package/dist/core/model-registry.js.map +1 -1
- package/dist/core/model-resolver.d.ts +6 -0
- package/dist/core/model-resolver.d.ts.map +1 -1
- package/dist/core/model-resolver.js +70 -37
- package/dist/core/model-resolver.js.map +1 -1
- package/dist/core/output-guard.d.ts +6 -0
- package/dist/core/output-guard.d.ts.map +1 -0
- package/dist/core/output-guard.js +59 -0
- package/dist/core/output-guard.js.map +1 -0
- package/dist/core/package-manager.d.ts +49 -7
- package/dist/core/package-manager.d.ts.map +1 -1
- package/dist/core/package-manager.js +655 -122
- package/dist/core/package-manager.js.map +1 -1
- package/dist/core/prompt-templates.d.ts +12 -10
- package/dist/core/prompt-templates.d.ts.map +1 -1
- package/dist/core/prompt-templates.js +37 -38
- package/dist/core/prompt-templates.js.map +1 -1
- package/dist/core/provider-display-names.d.ts +2 -0
- package/dist/core/provider-display-names.d.ts.map +1 -0
- package/dist/core/provider-display-names.js +33 -0
- package/dist/core/provider-display-names.js.map +1 -0
- package/dist/core/resolve-config-value.d.ts +6 -0
- package/dist/core/resolve-config-value.d.ts.map +1 -1
- package/dist/core/resolve-config-value.js +75 -8
- package/dist/core/resolve-config-value.js.map +1 -1
- package/dist/core/resource-loader.d.ts +18 -8
- package/dist/core/resource-loader.d.ts.map +1 -1
- package/dist/core/resource-loader.js +217 -123
- package/dist/core/resource-loader.js.map +1 -1
- package/dist/core/sdk.d.ts +25 -8
- package/dist/core/sdk.d.ts.map +1 -1
- package/dist/core/sdk.js +84 -37
- package/dist/core/sdk.js.map +1 -1
- package/dist/core/session-cwd.d.ts +19 -0
- package/dist/core/session-cwd.d.ts.map +1 -0
- package/dist/core/session-cwd.js +38 -0
- package/dist/core/session-cwd.js.map +1 -0
- package/dist/core/session-manager.d.ts +11 -1
- package/dist/core/session-manager.d.ts.map +1 -1
- package/dist/core/session-manager.js +42 -27
- package/dist/core/session-manager.js.map +1 -1
- package/dist/core/settings-manager.d.ts +34 -5
- package/dist/core/settings-manager.d.ts.map +1 -1
- package/dist/core/settings-manager.js +113 -13
- package/dist/core/settings-manager.js.map +1 -1
- package/dist/core/skills.d.ts +13 -11
- package/dist/core/skills.d.ts.map +1 -1
- package/dist/core/skills.js +59 -19
- package/dist/core/skills.js.map +1 -1
- package/dist/core/slash-commands.d.ts +2 -3
- package/dist/core/slash-commands.d.ts.map +1 -1
- package/dist/core/slash-commands.js +9 -6
- package/dist/core/slash-commands.js.map +1 -1
- package/dist/core/source-info.d.ts +18 -0
- package/dist/core/source-info.d.ts.map +1 -0
- package/dist/core/source-info.js +19 -0
- package/dist/core/source-info.js.map +1 -0
- package/dist/core/system-prompt.d.ts +3 -3
- package/dist/core/system-prompt.d.ts.map +1 -1
- package/dist/core/system-prompt.js +16 -55
- package/dist/core/system-prompt.js.map +1 -1
- package/dist/core/telemetry.d.ts +3 -0
- package/dist/core/telemetry.d.ts.map +1 -0
- package/dist/core/telemetry.js +9 -0
- package/dist/core/telemetry.js.map +1 -0
- package/dist/core/timings.d.ts +1 -0
- package/dist/core/timings.d.ts.map +1 -1
- package/dist/core/timings.js +6 -0
- package/dist/core/timings.js.map +1 -1
- package/dist/core/tools/bash.d.ts +27 -14
- package/dist/core/tools/bash.d.ts.map +1 -1
- package/dist/core/tools/bash.js +301 -208
- package/dist/core/tools/bash.js.map +1 -1
- package/dist/core/tools/edit-diff.d.ts +23 -1
- package/dist/core/tools/edit-diff.d.ts.map +1 -1
- package/dist/core/tools/edit-diff.js +154 -59
- package/dist/core/tools/edit-diff.js.map +1 -1
- package/dist/core/tools/edit.d.ts +22 -12
- package/dist/core/tools/edit.d.ts.map +1 -1
- package/dist/core/tools/edit.js +243 -65
- package/dist/core/tools/edit.js.map +1 -1
- package/dist/core/tools/file-mutation-queue.d.ts +6 -0
- package/dist/core/tools/file-mutation-queue.d.ts.map +1 -0
- package/dist/core/tools/file-mutation-queue.js +37 -0
- package/dist/core/tools/file-mutation-queue.js.map +1 -0
- package/dist/core/tools/find.d.ts +10 -14
- package/dist/core/tools/find.d.ts.map +1 -1
- package/dist/core/tools/find.js +202 -110
- package/dist/core/tools/find.js.map +1 -1
- package/dist/core/tools/grep.d.ts +14 -22
- package/dist/core/tools/grep.d.ts.map +1 -1
- package/dist/core/tools/grep.js +100 -35
- package/dist/core/tools/grep.js.map +1 -1
- package/dist/core/tools/index.d.ts +27 -60
- package/dist/core/tools/index.d.ts.map +1 -1
- package/dist/core/tools/index.js +96 -45
- package/dist/core/tools/index.js.map +1 -1
- package/dist/core/tools/ls.d.ts +8 -11
- package/dist/core/tools/ls.d.ts.map +1 -1
- package/dist/core/tools/ls.js +66 -15
- package/dist/core/tools/ls.js.map +1 -1
- package/dist/core/tools/output-accumulator.d.ts +50 -0
- package/dist/core/tools/output-accumulator.d.ts.map +1 -0
- package/dist/core/tools/output-accumulator.js +178 -0
- package/dist/core/tools/output-accumulator.js.map +1 -0
- package/dist/core/tools/path-utils.d.ts.map +1 -1
- package/dist/core/tools/path-utils.js +1 -1
- package/dist/core/tools/path-utils.js.map +1 -1
- package/dist/core/tools/read.d.ts +9 -13
- package/dist/core/tools/read.d.ts.map +1 -1
- package/dist/core/tools/read.js +175 -52
- package/dist/core/tools/read.js.map +1 -1
- package/dist/core/tools/render-utils.d.ts +21 -0
- package/dist/core/tools/render-utils.d.ts.map +1 -0
- package/dist/core/tools/render-utils.js +49 -0
- package/dist/core/tools/render-utils.js.map +1 -0
- package/dist/core/tools/tool-definition-wrapper.d.ts +14 -0
- package/dist/core/tools/tool-definition-wrapper.d.ts.map +1 -0
- package/dist/core/tools/tool-definition-wrapper.js +34 -0
- package/dist/core/tools/tool-definition-wrapper.js.map +1 -0
- package/dist/core/tools/truncate.d.ts.map +1 -1
- package/dist/core/tools/truncate.js.map +1 -1
- package/dist/core/tools/write.d.ts +8 -11
- package/dist/core/tools/write.d.ts.map +1 -1
- package/dist/core/tools/write.js +167 -32
- package/dist/core/tools/write.js.map +1 -1
- package/dist/index.d.ts +12 -9
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +12 -10
- package/dist/index.js.map +1 -1
- package/dist/main.d.ts +5 -1
- package/dist/main.d.ts.map +1 -1
- package/dist/main.js +326 -404
- package/dist/main.js.map +1 -1
- package/dist/migrations.d.ts +2 -2
- package/dist/migrations.d.ts.map +1 -1
- package/dist/migrations.js +24 -4
- package/dist/migrations.js.map +1 -1
- package/dist/modes/index.d.ts.map +1 -1
- package/dist/modes/interactive/components/armin.d.ts.map +1 -1
- package/dist/modes/interactive/components/armin.js +10 -6
- package/dist/modes/interactive/components/armin.js.map +1 -1
- package/dist/modes/interactive/components/assistant-message.d.ts +5 -1
- package/dist/modes/interactive/components/assistant-message.d.ts.map +1 -1
- package/dist/modes/interactive/components/assistant-message.js +32 -3
- package/dist/modes/interactive/components/assistant-message.js.map +1 -1
- package/dist/modes/interactive/components/bash-execution.d.ts +0 -1
- package/dist/modes/interactive/components/bash-execution.d.ts.map +1 -1
- package/dist/modes/interactive/components/bash-execution.js +31 -12
- package/dist/modes/interactive/components/bash-execution.js.map +1 -1
- package/dist/modes/interactive/components/bordered-loader.d.ts.map +1 -1
- package/dist/modes/interactive/components/bordered-loader.js +7 -1
- package/dist/modes/interactive/components/bordered-loader.js.map +1 -1
- package/dist/modes/interactive/components/branch-summary-message.d.ts.map +1 -1
- package/dist/modes/interactive/components/branch-summary-message.js +5 -3
- package/dist/modes/interactive/components/branch-summary-message.js.map +1 -1
- package/dist/modes/interactive/components/compaction-summary-message.d.ts.map +1 -1
- package/dist/modes/interactive/components/compaction-summary-message.js +5 -3
- package/dist/modes/interactive/components/compaction-summary-message.js.map +1 -1
- package/dist/modes/interactive/components/config-selector.d.ts.map +1 -1
- package/dist/modes/interactive/components/config-selector.js +49 -16
- package/dist/modes/interactive/components/config-selector.js.map +1 -1
- package/dist/modes/interactive/components/countdown-timer.d.ts.map +1 -1
- package/dist/modes/interactive/components/countdown-timer.js +5 -0
- package/dist/modes/interactive/components/countdown-timer.js.map +1 -1
- package/dist/modes/interactive/components/custom-editor.d.ts +3 -3
- package/dist/modes/interactive/components/custom-editor.d.ts.map +1 -1
- package/dist/modes/interactive/components/custom-editor.js +14 -7
- package/dist/modes/interactive/components/custom-editor.js.map +1 -1
- package/dist/modes/interactive/components/custom-message.d.ts.map +1 -1
- package/dist/modes/interactive/components/custom-message.js +6 -1
- package/dist/modes/interactive/components/custom-message.js.map +1 -1
- package/dist/modes/interactive/components/daxnuts.d.ts.map +1 -1
- package/dist/modes/interactive/components/daxnuts.js +8 -6
- package/dist/modes/interactive/components/daxnuts.js.map +1 -1
- package/dist/modes/interactive/components/diff.d.ts.map +1 -1
- package/dist/modes/interactive/components/diff.js.map +1 -1
- package/dist/modes/interactive/components/dynamic-border.d.ts.map +1 -1
- package/dist/modes/interactive/components/dynamic-border.js +1 -0
- package/dist/modes/interactive/components/dynamic-border.js.map +1 -1
- package/dist/modes/interactive/components/earendil-announcement.d.ts +5 -0
- package/dist/modes/interactive/components/earendil-announcement.d.ts.map +1 -0
- package/dist/modes/interactive/components/earendil-announcement.js +40 -0
- package/dist/modes/interactive/components/earendil-announcement.js.map +1 -0
- package/dist/modes/interactive/components/extension-editor.d.ts.map +1 -1
- package/dist/modes/interactive/components/extension-editor.js +16 -10
- package/dist/modes/interactive/components/extension-editor.js.map +1 -1
- package/dist/modes/interactive/components/extension-input.d.ts.map +1 -1
- package/dist/modes/interactive/components/extension-input.js +13 -7
- package/dist/modes/interactive/components/extension-input.js.map +1 -1
- package/dist/modes/interactive/components/extension-selector.d.ts.map +1 -1
- package/dist/modes/interactive/components/extension-selector.js +18 -11
- package/dist/modes/interactive/components/extension-selector.js.map +1 -1
- package/dist/modes/interactive/components/footer.d.ts +1 -0
- package/dist/modes/interactive/components/footer.d.ts.map +1 -1
- package/dist/modes/interactive/components/footer.js +7 -2
- package/dist/modes/interactive/components/footer.js.map +1 -1
- package/dist/modes/interactive/components/index.d.ts +1 -1
- package/dist/modes/interactive/components/index.d.ts.map +1 -1
- package/dist/modes/interactive/components/index.js +1 -1
- package/dist/modes/interactive/components/index.js.map +1 -1
- package/dist/modes/interactive/components/keybinding-hints.d.ts +8 -36
- package/dist/modes/interactive/components/keybinding-hints.d.ts.map +1 -1
- package/dist/modes/interactive/components/keybinding-hints.js +23 -48
- package/dist/modes/interactive/components/keybinding-hints.js.map +1 -1
- package/dist/modes/interactive/components/login-dialog.d.ts +5 -1
- package/dist/modes/interactive/components/login-dialog.d.ts.map +1 -1
- package/dist/modes/interactive/components/login-dialog.js +35 -14
- package/dist/modes/interactive/components/login-dialog.js.map +1 -1
- package/dist/modes/interactive/components/model-selector.d.ts.map +1 -1
- package/dist/modes/interactive/components/model-selector.js +41 -22
- package/dist/modes/interactive/components/model-selector.js.map +1 -1
- package/dist/modes/interactive/components/oauth-selector.d.ts +18 -6
- package/dist/modes/interactive/components/oauth-selector.d.ts.map +1 -1
- package/dist/modes/interactive/components/oauth-selector.js +104 -31
- package/dist/modes/interactive/components/oauth-selector.js.map +1 -1
- package/dist/modes/interactive/components/scoped-models-selector.d.ts +5 -12
- package/dist/modes/interactive/components/scoped-models-selector.d.ts.map +1 -1
- package/dist/modes/interactive/components/scoped-models-selector.js +61 -42
- package/dist/modes/interactive/components/scoped-models-selector.js.map +1 -1
- package/dist/modes/interactive/components/session-selector-search.d.ts.map +1 -1
- package/dist/modes/interactive/components/session-selector-search.js.map +1 -1
- package/dist/modes/interactive/components/session-selector.d.ts +2 -1
- package/dist/modes/interactive/components/session-selector.d.ts.map +1 -1
- package/dist/modes/interactive/components/session-selector.js +109 -73
- package/dist/modes/interactive/components/session-selector.js.map +1 -1
- package/dist/modes/interactive/components/settings-selector.d.ts +9 -0
- package/dist/modes/interactive/components/settings-selector.d.ts.map +1 -1
- package/dist/modes/interactive/components/settings-selector.js +84 -4
- package/dist/modes/interactive/components/settings-selector.js.map +1 -1
- package/dist/modes/interactive/components/show-images-selector.d.ts.map +1 -1
- package/dist/modes/interactive/components/show-images-selector.js +6 -1
- package/dist/modes/interactive/components/show-images-selector.js.map +1 -1
- package/dist/modes/interactive/components/skill-invocation-message.d.ts.map +1 -1
- package/dist/modes/interactive/components/skill-invocation-message.js +5 -3
- package/dist/modes/interactive/components/skill-invocation-message.js.map +1 -1
- package/dist/modes/interactive/components/theme-selector.d.ts.map +1 -1
- package/dist/modes/interactive/components/theme-selector.js +7 -1
- package/dist/modes/interactive/components/theme-selector.js.map +1 -1
- package/dist/modes/interactive/components/thinking-selector.d.ts.map +1 -1
- package/dist/modes/interactive/components/thinking-selector.js +6 -1
- package/dist/modes/interactive/components/thinking-selector.js.map +1 -1
- package/dist/modes/interactive/components/tool-execution.d.ts +20 -34
- package/dist/modes/interactive/components/tool-execution.d.ts.map +1 -1
- package/dist/modes/interactive/components/tool-execution.js +158 -636
- package/dist/modes/interactive/components/tool-execution.js.map +1 -1
- package/dist/modes/interactive/components/tree-selector.d.ts +21 -2
- package/dist/modes/interactive/components/tree-selector.d.ts.map +1 -1
- package/dist/modes/interactive/components/tree-selector.js +224 -52
- package/dist/modes/interactive/components/tree-selector.js.map +1 -1
- package/dist/modes/interactive/components/user-message-selector.d.ts +2 -2
- package/dist/modes/interactive/components/user-message-selector.d.ts.map +1 -1
- package/dist/modes/interactive/components/user-message-selector.js +20 -16
- package/dist/modes/interactive/components/user-message-selector.js.map +1 -1
- package/dist/modes/interactive/components/user-message.d.ts +1 -0
- package/dist/modes/interactive/components/user-message.d.ts.map +1 -1
- package/dist/modes/interactive/components/user-message.js +8 -6
- package/dist/modes/interactive/components/user-message.js.map +1 -1
- package/dist/modes/interactive/components/visual-truncate.d.ts.map +1 -1
- package/dist/modes/interactive/components/visual-truncate.js.map +1 -1
- package/dist/modes/interactive/interactive-mode.d.ts +67 -39
- package/dist/modes/interactive/interactive-mode.d.ts.map +1 -1
- package/dist/modes/interactive/interactive-mode.js +1556 -680
- package/dist/modes/interactive/interactive-mode.js.map +1 -1
- package/dist/modes/interactive/theme/dark.json +1 -1
- package/dist/modes/interactive/theme/light.json +1 -1
- package/dist/modes/interactive/theme/theme.d.ts +3 -0
- package/dist/modes/interactive/theme/theme.d.ts.map +1 -1
- package/dist/modes/interactive/theme/theme.js +101 -72
- package/dist/modes/interactive/theme/theme.js.map +1 -1
- package/dist/modes/print-mode.d.ts +2 -2
- package/dist/modes/print-mode.d.ts.map +1 -1
- package/dist/modes/print-mode.js +107 -77
- package/dist/modes/print-mode.js.map +1 -1
- package/dist/modes/rpc/jsonl.d.ts +17 -0
- package/dist/modes/rpc/jsonl.d.ts.map +1 -0
- package/dist/modes/rpc/jsonl.js +49 -0
- package/dist/modes/rpc/jsonl.js.map +1 -0
- package/dist/modes/rpc/rpc-client.d.ts +8 -1
- package/dist/modes/rpc/rpc-client.d.ts.map +1 -1
- package/dist/modes/rpc/rpc-client.js +22 -16
- package/dist/modes/rpc/rpc-client.js.map +1 -1
- package/dist/modes/rpc/rpc-mode.d.ts +2 -2
- package/dist/modes/rpc/rpc-mode.d.ts.map +1 -1
- package/dist/modes/rpc/rpc-mode.js +184 -94
- package/dist/modes/rpc/rpc-mode.js.map +1 -1
- package/dist/modes/rpc/rpc-types.d.ts +14 -4
- package/dist/modes/rpc/rpc-types.d.ts.map +1 -1
- package/dist/modes/rpc/rpc-types.js.map +1 -1
- package/dist/package-manager-cli.d.ts +4 -0
- package/dist/package-manager-cli.d.ts.map +1 -0
- package/dist/package-manager-cli.js +460 -0
- package/dist/package-manager-cli.js.map +1 -0
- package/dist/utils/changelog.d.ts.map +1 -1
- package/dist/utils/changelog.js.map +1 -1
- package/dist/utils/child-process.d.ts +12 -0
- package/dist/utils/child-process.d.ts.map +1 -0
- package/dist/utils/child-process.js +86 -0
- package/dist/utils/child-process.js.map +1 -0
- package/dist/utils/clipboard-image.d.ts.map +1 -1
- package/dist/utils/clipboard-image.js +94 -11
- package/dist/utils/clipboard-image.js.map +1 -1
- package/dist/utils/clipboard-native.d.ts +1 -0
- package/dist/utils/clipboard-native.d.ts.map +1 -1
- package/dist/utils/clipboard-native.js.map +1 -1
- package/dist/utils/clipboard.d.ts +1 -1
- package/dist/utils/clipboard.d.ts.map +1 -1
- package/dist/utils/clipboard.js +96 -46
- package/dist/utils/clipboard.js.map +1 -1
- package/dist/utils/exif-orientation.d.ts +5 -0
- package/dist/utils/exif-orientation.d.ts.map +1 -0
- package/dist/utils/exif-orientation.js +158 -0
- package/dist/utils/exif-orientation.js.map +1 -0
- package/dist/utils/frontmatter.d.ts.map +1 -1
- package/dist/utils/frontmatter.js.map +1 -1
- package/dist/utils/fs-watch.d.ts +5 -0
- package/dist/utils/fs-watch.d.ts.map +1 -0
- package/dist/utils/fs-watch.js +25 -0
- package/dist/utils/fs-watch.js.map +1 -0
- package/dist/utils/git.d.ts.map +1 -1
- package/dist/utils/git.js.map +1 -1
- package/dist/utils/image-convert.d.ts.map +1 -1
- package/dist/utils/image-convert.js +5 -1
- package/dist/utils/image-convert.js.map +1 -1
- package/dist/utils/image-resize.d.ts +5 -5
- package/dist/utils/image-resize.d.ts.map +1 -1
- package/dist/utils/image-resize.js +51 -95
- package/dist/utils/image-resize.js.map +1 -1
- package/dist/utils/mime.d.ts.map +1 -1
- package/dist/utils/mime.js.map +1 -1
- package/dist/utils/paths.d.ts +16 -0
- package/dist/utils/paths.d.ts.map +1 -0
- package/dist/utils/paths.js +50 -0
- package/dist/utils/paths.js.map +1 -0
- package/dist/utils/photon.d.ts.map +1 -1
- package/dist/utils/photon.js.map +1 -1
- package/dist/utils/pi-user-agent.d.ts +2 -0
- package/dist/utils/pi-user-agent.d.ts.map +1 -0
- package/dist/utils/pi-user-agent.js +5 -0
- package/dist/utils/pi-user-agent.js.map +1 -0
- package/dist/utils/shell.d.ts +10 -6
- package/dist/utils/shell.d.ts.map +1 -1
- package/dist/utils/shell.js +29 -25
- package/dist/utils/shell.js.map +1 -1
- package/dist/utils/sleep.d.ts.map +1 -1
- package/dist/utils/sleep.js.map +1 -1
- package/dist/utils/tools-manager.d.ts.map +1 -1
- package/dist/utils/tools-manager.js +11 -6
- package/dist/utils/tools-manager.js.map +1 -1
- package/dist/utils/version-check.d.ts +14 -0
- package/dist/utils/version-check.d.ts.map +1 -0
- package/dist/utils/version-check.js +77 -0
- package/dist/utils/version-check.js.map +1 -0
- package/docs/compaction.md +394 -0
- package/docs/custom-provider.md +646 -0
- package/docs/development.md +71 -0
- package/docs/docs.json +148 -0
- package/docs/extensions.md +2596 -0
- package/docs/images/doom-extension.png +0 -0
- package/docs/images/exy.png +0 -0
- package/docs/images/interactive-mode.png +0 -0
- package/docs/images/tree-view.png +0 -0
- package/docs/index.md +70 -0
- package/docs/json.md +82 -0
- package/docs/keybindings.md +197 -0
- package/docs/models.md +474 -0
- package/docs/packages.md +223 -0
- package/docs/prompt-templates.md +88 -0
- package/docs/providers.md +243 -0
- package/docs/quickstart.md +142 -0
- package/docs/rpc.md +1407 -0
- package/docs/sdk.md +1149 -0
- package/docs/session-format.md +412 -0
- package/docs/sessions.md +137 -0
- package/docs/settings.md +279 -0
- package/docs/shell-aliases.md +13 -0
- package/docs/skills.md +232 -0
- package/docs/terminal-setup.md +106 -0
- package/docs/termux.md +127 -0
- package/docs/themes.md +295 -0
- package/docs/tmux.md +61 -0
- package/docs/tui.md +918 -0
- package/docs/usage.md +277 -0
- package/docs/windows.md +17 -0
- package/examples/README.md +25 -0
- package/examples/extensions/README.md +208 -0
- package/examples/extensions/auto-commit-on-exit.ts +49 -0
- package/examples/extensions/bash-spawn-hook.ts +30 -0
- package/examples/extensions/bookmark.ts +50 -0
- package/examples/extensions/border-status-editor.ts +150 -0
- package/examples/extensions/built-in-tool-renderer.ts +249 -0
- package/examples/extensions/claude-rules.ts +86 -0
- package/examples/extensions/commands.ts +72 -0
- package/examples/extensions/confirm-destructive.ts +59 -0
- package/examples/extensions/custom-compaction.ts +127 -0
- package/examples/extensions/custom-footer.ts +64 -0
- package/examples/extensions/custom-header.ts +73 -0
- package/examples/extensions/custom-provider-anthropic/index.ts +604 -0
- package/examples/extensions/custom-provider-anthropic/package-lock.json +24 -0
- package/examples/extensions/custom-provider-anthropic/package.json +19 -0
- package/examples/extensions/custom-provider-gitlab-duo/index.ts +349 -0
- package/examples/extensions/custom-provider-gitlab-duo/package.json +16 -0
- package/examples/extensions/custom-provider-gitlab-duo/test.ts +82 -0
- package/examples/extensions/dirty-repo-guard.ts +56 -0
- package/examples/extensions/doom-overlay/README.md +46 -0
- package/examples/extensions/doom-overlay/doom/build/doom.js +21 -0
- package/examples/extensions/doom-overlay/doom/build/doom.wasm +0 -0
- package/examples/extensions/doom-overlay/doom/build.sh +152 -0
- package/examples/extensions/doom-overlay/doom/doomgeneric_pi.c +72 -0
- package/examples/extensions/doom-overlay/doom-component.ts +132 -0
- package/examples/extensions/doom-overlay/doom-engine.ts +173 -0
- package/examples/extensions/doom-overlay/doom-keys.ts +104 -0
- package/examples/extensions/doom-overlay/index.ts +74 -0
- package/examples/extensions/doom-overlay/wad-finder.ts +51 -0
- package/examples/extensions/dynamic-resources/SKILL.md +8 -0
- package/examples/extensions/dynamic-resources/dynamic.json +79 -0
- package/examples/extensions/dynamic-resources/dynamic.md +5 -0
- package/examples/extensions/dynamic-resources/index.ts +15 -0
- package/examples/extensions/dynamic-tools.ts +74 -0
- package/examples/extensions/event-bus.ts +43 -0
- package/examples/extensions/file-trigger.ts +41 -0
- package/examples/extensions/git-checkpoint.ts +53 -0
- package/examples/extensions/github-issue-autocomplete.ts +185 -0
- package/examples/extensions/handoff.ts +191 -0
- package/examples/extensions/hello.ts +26 -0
- package/examples/extensions/hidden-thinking-label.ts +53 -0
- package/examples/extensions/inline-bash.ts +94 -0
- package/examples/extensions/input-transform.ts +43 -0
- package/examples/extensions/interactive-shell.ts +196 -0
- package/examples/extensions/mac-system-theme.ts +47 -0
- package/examples/extensions/message-renderer.ts +59 -0
- package/examples/extensions/minimal-mode.ts +426 -0
- package/examples/extensions/modal-editor.ts +85 -0
- package/examples/extensions/model-status.ts +31 -0
- package/examples/extensions/notify.ts +55 -0
- package/examples/extensions/overlay-qa-tests.ts +1348 -0
- package/examples/extensions/overlay-test.ts +150 -0
- package/examples/extensions/permission-gate.ts +34 -0
- package/examples/extensions/pirate.ts +47 -0
- package/examples/extensions/plan-mode/README.md +65 -0
- package/examples/extensions/plan-mode/index.ts +340 -0
- package/examples/extensions/plan-mode/utils.ts +168 -0
- package/examples/extensions/preset.ts +430 -0
- package/examples/extensions/prompt-customizer.ts +97 -0
- package/examples/extensions/protected-paths.ts +30 -0
- package/examples/extensions/provider-payload.ts +18 -0
- package/examples/extensions/qna.ts +122 -0
- package/examples/extensions/question.ts +264 -0
- package/examples/extensions/questionnaire.ts +427 -0
- package/examples/extensions/rainbow-editor.ts +88 -0
- package/examples/extensions/reload-runtime.ts +37 -0
- package/examples/extensions/rpc-demo.ts +118 -0
- package/examples/extensions/sandbox/index.ts +321 -0
- package/examples/extensions/sandbox/package-lock.json +92 -0
- package/examples/extensions/sandbox/package.json +19 -0
- package/examples/extensions/send-user-message.ts +97 -0
- package/examples/extensions/session-name.ts +27 -0
- package/examples/extensions/shutdown-command.ts +63 -0
- package/examples/extensions/snake.ts +343 -0
- package/examples/extensions/space-invaders.ts +560 -0
- package/examples/extensions/ssh.ts +220 -0
- package/examples/extensions/status-line.ts +32 -0
- package/examples/extensions/structured-output.ts +65 -0
- package/examples/extensions/subagent/README.md +172 -0
- package/examples/extensions/subagent/agents/planner.md +37 -0
- package/examples/extensions/subagent/agents/reviewer.md +35 -0
- package/examples/extensions/subagent/agents/scout.md +50 -0
- package/examples/extensions/subagent/agents/worker.md +24 -0
- package/examples/extensions/subagent/agents.ts +126 -0
- package/examples/extensions/subagent/index.ts +987 -0
- package/examples/extensions/subagent/prompts/implement-and-review.md +10 -0
- package/examples/extensions/subagent/prompts/implement.md +10 -0
- package/examples/extensions/subagent/prompts/scout-and-plan.md +9 -0
- package/examples/extensions/summarize.ts +206 -0
- package/examples/extensions/system-prompt-header.ts +17 -0
- package/examples/extensions/tic-tac-toe.ts +1008 -0
- package/examples/extensions/timed-confirm.ts +70 -0
- package/examples/extensions/titlebar-spinner.ts +58 -0
- package/examples/extensions/todo.ts +297 -0
- package/examples/extensions/tool-override.ts +144 -0
- package/examples/extensions/tools.ts +141 -0
- package/examples/extensions/trigger-compact.ts +50 -0
- package/examples/extensions/truncated-tool.ts +195 -0
- package/examples/extensions/widget-placement.ts +9 -0
- package/examples/extensions/with-deps/index.ts +32 -0
- package/examples/extensions/with-deps/package-lock.json +31 -0
- package/examples/extensions/with-deps/package.json +22 -0
- package/examples/extensions/working-indicator.ts +123 -0
- package/examples/extensions/working-message-test.ts +25 -0
- package/examples/rpc-extension-ui.ts +632 -0
- package/examples/sdk/01-minimal.ts +22 -0
- package/examples/sdk/02-custom-model.ts +49 -0
- package/examples/sdk/03-custom-prompt.ts +62 -0
- package/examples/sdk/04-skills.ts +55 -0
- package/examples/sdk/05-tools.ts +44 -0
- package/examples/sdk/06-extensions.ts +90 -0
- package/examples/sdk/07-context-files.ts +42 -0
- package/examples/sdk/08-prompt-templates.ts +51 -0
- package/examples/sdk/09-api-keys-and-oauth.ts +48 -0
- package/examples/sdk/10-settings.ts +53 -0
- package/examples/sdk/11-sessions.ts +48 -0
- package/examples/sdk/12-full-control.ts +73 -0
- package/examples/sdk/13-session-runtime.ts +67 -0
- package/examples/sdk/README.md +147 -0
- package/extensions/phi/init.ts +15 -1
- package/extensions/phi/keys.ts +186 -0
- package/extensions/phi/providers/alibaba.ts +126 -0
- package/extensions/phi/providers/opencode-go.ts +204 -0
- package/extensions/phi/setup.ts +692 -0
- package/extensions/phi/smart-router.ts +8 -0
- package/extensions/phi/web-search.ts +432 -186
- package/package.json +111 -106
- package/scripts/copy-assets.sh +0 -0
- 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
|
+
```
|
package/extensions/phi/init.ts
CHANGED
|
@@ -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 —
|
|
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
|
+
}
|