@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
|
@@ -1,31 +1,64 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* Model registry - manages built-in and custom models, provides API key resolution.
|
|
3
3
|
*/
|
|
4
|
+
import { existsSync, readFileSync } from "fs";
|
|
5
|
+
import { join } from "path";
|
|
4
6
|
import { getModels, getProviders, registerApiProvider, resetApiProviders, } from "phi-code-ai";
|
|
5
7
|
import { registerOAuthProvider, resetOAuthProviders } from "phi-code-ai/oauth";
|
|
6
|
-
import { Type } from "
|
|
7
|
-
import
|
|
8
|
-
import { existsSync, readFileSync } from "fs";
|
|
9
|
-
import { join, dirname } from "path";
|
|
10
|
-
import { fileURLToPath } from "url";
|
|
8
|
+
import { Type } from "typebox";
|
|
9
|
+
import { Compile } from "typebox/compile";
|
|
11
10
|
import { getAgentDir } from "../config.js";
|
|
12
|
-
import {
|
|
13
|
-
|
|
14
|
-
const ajv = new Ajv();
|
|
15
|
-
const __filename = fileURLToPath(import.meta.url);
|
|
16
|
-
const __dirname = dirname(__filename);
|
|
17
|
-
const DEFAULT_MODELS_PATH = join(__dirname, "default-models.json");
|
|
11
|
+
import { BUILT_IN_PROVIDER_DISPLAY_NAMES } from "./provider-display-names.js";
|
|
12
|
+
import { clearConfigValueCache, resolveConfigValueOrThrow, resolveConfigValueUncached, resolveHeadersOrThrow, } from "./resolve-config-value.js";
|
|
18
13
|
// Schema for OpenRouter routing preferences
|
|
14
|
+
const PercentileCutoffsSchema = Type.Object({
|
|
15
|
+
p50: Type.Optional(Type.Number()),
|
|
16
|
+
p75: Type.Optional(Type.Number()),
|
|
17
|
+
p90: Type.Optional(Type.Number()),
|
|
18
|
+
p99: Type.Optional(Type.Number()),
|
|
19
|
+
});
|
|
19
20
|
const OpenRouterRoutingSchema = Type.Object({
|
|
20
|
-
|
|
21
|
+
allow_fallbacks: Type.Optional(Type.Boolean()),
|
|
22
|
+
require_parameters: Type.Optional(Type.Boolean()),
|
|
23
|
+
data_collection: Type.Optional(Type.Union([Type.Literal("deny"), Type.Literal("allow")])),
|
|
24
|
+
zdr: Type.Optional(Type.Boolean()),
|
|
25
|
+
enforce_distillable_text: Type.Optional(Type.Boolean()),
|
|
21
26
|
order: Type.Optional(Type.Array(Type.String())),
|
|
27
|
+
only: Type.Optional(Type.Array(Type.String())),
|
|
28
|
+
ignore: Type.Optional(Type.Array(Type.String())),
|
|
29
|
+
quantizations: Type.Optional(Type.Array(Type.String())),
|
|
30
|
+
sort: Type.Optional(Type.Union([
|
|
31
|
+
Type.String(),
|
|
32
|
+
Type.Object({
|
|
33
|
+
by: Type.Optional(Type.String()),
|
|
34
|
+
partition: Type.Optional(Type.Union([Type.String(), Type.Null()])),
|
|
35
|
+
}),
|
|
36
|
+
])),
|
|
37
|
+
max_price: Type.Optional(Type.Object({
|
|
38
|
+
prompt: Type.Optional(Type.Union([Type.Number(), Type.String()])),
|
|
39
|
+
completion: Type.Optional(Type.Union([Type.Number(), Type.String()])),
|
|
40
|
+
image: Type.Optional(Type.Union([Type.Number(), Type.String()])),
|
|
41
|
+
audio: Type.Optional(Type.Union([Type.Number(), Type.String()])),
|
|
42
|
+
request: Type.Optional(Type.Union([Type.Number(), Type.String()])),
|
|
43
|
+
})),
|
|
44
|
+
preferred_min_throughput: Type.Optional(Type.Union([Type.Number(), PercentileCutoffsSchema])),
|
|
45
|
+
preferred_max_latency: Type.Optional(Type.Union([Type.Number(), PercentileCutoffsSchema])),
|
|
22
46
|
});
|
|
23
47
|
// Schema for Vercel AI Gateway routing preferences
|
|
24
48
|
const VercelGatewayRoutingSchema = Type.Object({
|
|
25
49
|
only: Type.Optional(Type.Array(Type.String())),
|
|
26
50
|
order: Type.Optional(Type.Array(Type.String())),
|
|
27
51
|
});
|
|
28
|
-
// Schema for
|
|
52
|
+
// Schema for thinking level support and provider-specific values
|
|
53
|
+
const ThinkingLevelMapValueSchema = Type.Union([Type.String(), Type.Null()]);
|
|
54
|
+
const ThinkingLevelMapSchema = Type.Object({
|
|
55
|
+
off: Type.Optional(ThinkingLevelMapValueSchema),
|
|
56
|
+
minimal: Type.Optional(ThinkingLevelMapValueSchema),
|
|
57
|
+
low: Type.Optional(ThinkingLevelMapValueSchema),
|
|
58
|
+
medium: Type.Optional(ThinkingLevelMapValueSchema),
|
|
59
|
+
high: Type.Optional(ThinkingLevelMapValueSchema),
|
|
60
|
+
xhigh: Type.Optional(ThinkingLevelMapValueSchema),
|
|
61
|
+
});
|
|
29
62
|
const OpenAICompletionsCompatSchema = Type.Object({
|
|
30
63
|
supportsStore: Type.Optional(Type.Boolean()),
|
|
31
64
|
supportsDeveloperRole: Type.Optional(Type.Boolean()),
|
|
@@ -35,15 +68,35 @@ const OpenAICompletionsCompatSchema = Type.Object({
|
|
|
35
68
|
requiresToolResultName: Type.Optional(Type.Boolean()),
|
|
36
69
|
requiresAssistantAfterToolResult: Type.Optional(Type.Boolean()),
|
|
37
70
|
requiresThinkingAsText: Type.Optional(Type.Boolean()),
|
|
38
|
-
|
|
39
|
-
thinkingFormat: Type.Optional(Type.Union([
|
|
71
|
+
requiresReasoningContentOnAssistantMessages: Type.Optional(Type.Boolean()),
|
|
72
|
+
thinkingFormat: Type.Optional(Type.Union([
|
|
73
|
+
Type.Literal("openai"),
|
|
74
|
+
Type.Literal("openrouter"),
|
|
75
|
+
Type.Literal("together"),
|
|
76
|
+
Type.Literal("deepseek"),
|
|
77
|
+
Type.Literal("zai"),
|
|
78
|
+
Type.Literal("qwen"),
|
|
79
|
+
Type.Literal("qwen-chat-template"),
|
|
80
|
+
])),
|
|
81
|
+
cacheControlFormat: Type.Optional(Type.Literal("anthropic")),
|
|
40
82
|
openRouterRouting: Type.Optional(OpenRouterRoutingSchema),
|
|
41
83
|
vercelGatewayRouting: Type.Optional(VercelGatewayRoutingSchema),
|
|
84
|
+
supportsStrictMode: Type.Optional(Type.Boolean()),
|
|
85
|
+
supportsLongCacheRetention: Type.Optional(Type.Boolean()),
|
|
42
86
|
});
|
|
43
87
|
const OpenAIResponsesCompatSchema = Type.Object({
|
|
44
|
-
|
|
88
|
+
sendSessionIdHeader: Type.Optional(Type.Boolean()),
|
|
89
|
+
supportsLongCacheRetention: Type.Optional(Type.Boolean()),
|
|
90
|
+
});
|
|
91
|
+
const AnthropicMessagesCompatSchema = Type.Object({
|
|
92
|
+
supportsEagerToolInputStreaming: Type.Optional(Type.Boolean()),
|
|
93
|
+
supportsLongCacheRetention: Type.Optional(Type.Boolean()),
|
|
45
94
|
});
|
|
46
|
-
const
|
|
95
|
+
const ProviderCompatSchema = Type.Union([
|
|
96
|
+
OpenAICompletionsCompatSchema,
|
|
97
|
+
OpenAIResponsesCompatSchema,
|
|
98
|
+
AnthropicMessagesCompatSchema,
|
|
99
|
+
]);
|
|
47
100
|
// Schema for custom model definition
|
|
48
101
|
// Most fields are optional with sensible defaults for local models (Ollama, LM Studio, etc.)
|
|
49
102
|
const ModelDefinitionSchema = Type.Object({
|
|
@@ -52,6 +105,7 @@ const ModelDefinitionSchema = Type.Object({
|
|
|
52
105
|
api: Type.Optional(Type.String({ minLength: 1 })),
|
|
53
106
|
baseUrl: Type.Optional(Type.String({ minLength: 1 })),
|
|
54
107
|
reasoning: Type.Optional(Type.Boolean()),
|
|
108
|
+
thinkingLevelMap: Type.Optional(ThinkingLevelMapSchema),
|
|
55
109
|
input: Type.Optional(Type.Array(Type.Union([Type.Literal("text"), Type.Literal("image")]))),
|
|
56
110
|
cost: Type.Optional(Type.Object({
|
|
57
111
|
input: Type.Number(),
|
|
@@ -62,12 +116,13 @@ const ModelDefinitionSchema = Type.Object({
|
|
|
62
116
|
contextWindow: Type.Optional(Type.Number()),
|
|
63
117
|
maxTokens: Type.Optional(Type.Number()),
|
|
64
118
|
headers: Type.Optional(Type.Record(Type.String(), Type.String())),
|
|
65
|
-
compat: Type.Optional(
|
|
119
|
+
compat: Type.Optional(ProviderCompatSchema),
|
|
66
120
|
});
|
|
67
121
|
// Schema for per-model overrides (all fields optional, merged with built-in model)
|
|
68
122
|
const ModelOverrideSchema = Type.Object({
|
|
69
123
|
name: Type.Optional(Type.String({ minLength: 1 })),
|
|
70
124
|
reasoning: Type.Optional(Type.Boolean()),
|
|
125
|
+
thinkingLevelMap: Type.Optional(ThinkingLevelMapSchema),
|
|
71
126
|
input: Type.Optional(Type.Array(Type.Union([Type.Literal("text"), Type.Literal("image")]))),
|
|
72
127
|
cost: Type.Optional(Type.Object({
|
|
73
128
|
input: Type.Optional(Type.Number()),
|
|
@@ -78,13 +133,15 @@ const ModelOverrideSchema = Type.Object({
|
|
|
78
133
|
contextWindow: Type.Optional(Type.Number()),
|
|
79
134
|
maxTokens: Type.Optional(Type.Number()),
|
|
80
135
|
headers: Type.Optional(Type.Record(Type.String(), Type.String())),
|
|
81
|
-
compat: Type.Optional(
|
|
136
|
+
compat: Type.Optional(ProviderCompatSchema),
|
|
82
137
|
});
|
|
83
138
|
const ProviderConfigSchema = Type.Object({
|
|
139
|
+
name: Type.Optional(Type.String({ minLength: 1 })),
|
|
84
140
|
baseUrl: Type.Optional(Type.String({ minLength: 1 })),
|
|
85
141
|
apiKey: Type.Optional(Type.String({ minLength: 1 })),
|
|
86
142
|
api: Type.Optional(Type.String({ minLength: 1 })),
|
|
87
143
|
headers: Type.Optional(Type.Record(Type.String(), Type.String())),
|
|
144
|
+
compat: Type.Optional(ProviderCompatSchema),
|
|
88
145
|
authHeader: Type.Optional(Type.Boolean()),
|
|
89
146
|
models: Type.Optional(Type.Array(ModelDefinitionSchema)),
|
|
90
147
|
modelOverrides: Type.Optional(Type.Record(Type.String(), ModelOverrideSchema)),
|
|
@@ -92,7 +149,25 @@ const ProviderConfigSchema = Type.Object({
|
|
|
92
149
|
const ModelsConfigSchema = Type.Object({
|
|
93
150
|
providers: Type.Record(Type.String(), ProviderConfigSchema),
|
|
94
151
|
});
|
|
95
|
-
|
|
152
|
+
const validateModelsConfig = Compile(ModelsConfigSchema);
|
|
153
|
+
function formatValidationPath(error) {
|
|
154
|
+
if (error.keyword === "required") {
|
|
155
|
+
const requiredProperties = error.params.requiredProperties;
|
|
156
|
+
const requiredProperty = requiredProperties?.[0];
|
|
157
|
+
if (requiredProperty) {
|
|
158
|
+
const basePath = error.instancePath.replace(/^\//, "").replace(/\//g, ".");
|
|
159
|
+
return basePath ? `${basePath}.${requiredProperty}` : requiredProperty;
|
|
160
|
+
}
|
|
161
|
+
}
|
|
162
|
+
const path = error.instancePath.replace(/^\//, "").replace(/\//g, ".");
|
|
163
|
+
return path || "root";
|
|
164
|
+
}
|
|
165
|
+
/** Strip `//` line comments and trailing commas from JSON, leaving string literals untouched. */
|
|
166
|
+
function stripJsonComments(input) {
|
|
167
|
+
return input
|
|
168
|
+
.replace(/"(?:\\.|[^"\\])*"|\/\/[^\n]*/g, (m) => (m[0] === '"' ? m : ""))
|
|
169
|
+
.replace(/"(?:\\.|[^"\\])*"|,(\s*[}\]])/g, (m, tail) => tail ?? (m[0] === '"' ? m : ""));
|
|
170
|
+
}
|
|
96
171
|
function emptyCustomModelsResult(error) {
|
|
97
172
|
return { models: [], overrides: new Map(), modelOverrides: new Map(), error };
|
|
98
173
|
}
|
|
@@ -130,6 +205,9 @@ function applyModelOverride(model, override) {
|
|
|
130
205
|
result.name = override.name;
|
|
131
206
|
if (override.reasoning !== undefined)
|
|
132
207
|
result.reasoning = override.reasoning;
|
|
208
|
+
if (override.thinkingLevelMap !== undefined) {
|
|
209
|
+
result.thinkingLevelMap = { ...model.thinkingLevelMap, ...override.thinkingLevelMap };
|
|
210
|
+
}
|
|
133
211
|
if (override.input !== undefined)
|
|
134
212
|
result.input = override.input;
|
|
135
213
|
if (override.contextWindow !== undefined)
|
|
@@ -145,11 +223,6 @@ function applyModelOverride(model, override) {
|
|
|
145
223
|
cacheWrite: override.cost.cacheWrite ?? model.cost.cacheWrite,
|
|
146
224
|
};
|
|
147
225
|
}
|
|
148
|
-
// Merge headers
|
|
149
|
-
if (override.headers) {
|
|
150
|
-
const resolvedHeaders = resolveHeaders(override.headers);
|
|
151
|
-
result.headers = resolvedHeaders ? { ...model.headers, ...resolvedHeaders } : model.headers;
|
|
152
|
-
}
|
|
153
226
|
// Deep merge compat
|
|
154
227
|
result.compat = mergeCompat(model.compat, override.compat);
|
|
155
228
|
return result;
|
|
@@ -160,29 +233,30 @@ export const clearApiKeyCache = clearConfigValueCache;
|
|
|
160
233
|
* Model registry - loads and manages models, resolves API keys via AuthStorage.
|
|
161
234
|
*/
|
|
162
235
|
export class ModelRegistry {
|
|
163
|
-
|
|
236
|
+
authStorage;
|
|
237
|
+
modelsJsonPath;
|
|
238
|
+
models = [];
|
|
239
|
+
providerRequestConfigs = new Map();
|
|
240
|
+
modelRequestHeaders = new Map();
|
|
241
|
+
registeredProviders = new Map();
|
|
242
|
+
loadError = undefined;
|
|
243
|
+
constructor(authStorage, modelsJsonPath) {
|
|
164
244
|
this.authStorage = authStorage;
|
|
165
245
|
this.modelsJsonPath = modelsJsonPath;
|
|
166
|
-
this.models = [];
|
|
167
|
-
this.customProviderApiKeys = new Map();
|
|
168
|
-
this.registeredProviders = new Map();
|
|
169
|
-
this.loadError = undefined;
|
|
170
|
-
// Set up fallback resolver for custom provider API keys
|
|
171
|
-
this.authStorage.setFallbackResolver((provider) => {
|
|
172
|
-
const keyConfig = this.customProviderApiKeys.get(provider);
|
|
173
|
-
if (keyConfig) {
|
|
174
|
-
return resolveConfigValue(keyConfig);
|
|
175
|
-
}
|
|
176
|
-
return undefined;
|
|
177
|
-
});
|
|
178
|
-
// Load models
|
|
179
246
|
this.loadModels();
|
|
180
247
|
}
|
|
248
|
+
static create(authStorage, modelsJsonPath = join(getAgentDir(), "models.json")) {
|
|
249
|
+
return new ModelRegistry(authStorage, modelsJsonPath);
|
|
250
|
+
}
|
|
251
|
+
static inMemory(authStorage) {
|
|
252
|
+
return new ModelRegistry(authStorage, undefined);
|
|
253
|
+
}
|
|
181
254
|
/**
|
|
182
255
|
* Reload models from disk (built-in + custom from models.json).
|
|
183
256
|
*/
|
|
184
257
|
refresh() {
|
|
185
|
-
this.
|
|
258
|
+
this.providerRequestConfigs.clear();
|
|
259
|
+
this.modelRequestHeaders.clear();
|
|
186
260
|
this.loadError = undefined;
|
|
187
261
|
// Ensure dynamic API/OAuth registrations are rebuilt from current provider state.
|
|
188
262
|
resetApiProviders();
|
|
@@ -224,13 +298,12 @@ export class ModelRegistry {
|
|
|
224
298
|
const perModelOverrides = modelOverrides.get(provider);
|
|
225
299
|
return models.map((m) => {
|
|
226
300
|
let model = m;
|
|
227
|
-
// Apply provider-level baseUrl/headers override
|
|
301
|
+
// Apply provider-level baseUrl/headers/compat override
|
|
228
302
|
if (providerOverride) {
|
|
229
|
-
const resolvedHeaders = resolveHeaders(providerOverride.headers);
|
|
230
303
|
model = {
|
|
231
304
|
...model,
|
|
232
305
|
baseUrl: providerOverride.baseUrl ?? model.baseUrl,
|
|
233
|
-
|
|
306
|
+
compat: mergeCompat(model.compat, providerOverride.compat),
|
|
234
307
|
};
|
|
235
308
|
}
|
|
236
309
|
// Apply per-model override
|
|
@@ -258,68 +331,62 @@ export class ModelRegistry {
|
|
|
258
331
|
}
|
|
259
332
|
loadCustomModels(modelsJsonPath) {
|
|
260
333
|
if (!existsSync(modelsJsonPath)) {
|
|
261
|
-
// If user's models.json doesn't exist, try to load default models
|
|
262
|
-
if (existsSync(DEFAULT_MODELS_PATH)) {
|
|
263
|
-
return this.loadModelsFromFile(DEFAULT_MODELS_PATH);
|
|
264
|
-
}
|
|
265
334
|
return emptyCustomModelsResult();
|
|
266
335
|
}
|
|
267
|
-
return this.loadModelsFromFile(modelsJsonPath);
|
|
268
|
-
}
|
|
269
|
-
loadModelsFromFile(filePath) {
|
|
270
336
|
try {
|
|
271
|
-
const content = readFileSync(
|
|
272
|
-
const
|
|
273
|
-
|
|
274
|
-
|
|
275
|
-
|
|
276
|
-
|
|
277
|
-
"Unknown schema error";
|
|
278
|
-
return emptyCustomModelsResult(`Invalid models.json schema:\n${errors}\n\nFile: ${
|
|
337
|
+
const content = readFileSync(modelsJsonPath, "utf-8");
|
|
338
|
+
const parsed = JSON.parse(stripJsonComments(content));
|
|
339
|
+
if (!validateModelsConfig.Check(parsed)) {
|
|
340
|
+
const errors = validateModelsConfig
|
|
341
|
+
.Errors(parsed)
|
|
342
|
+
.map((error) => ` - ${formatValidationPath(error)}: ${error.message}`)
|
|
343
|
+
.join("\n") || "Unknown schema error";
|
|
344
|
+
return emptyCustomModelsResult(`Invalid models.json schema:\n${errors}\n\nFile: ${modelsJsonPath}`);
|
|
279
345
|
}
|
|
346
|
+
const config = parsed;
|
|
280
347
|
// Additional validation
|
|
281
348
|
this.validateConfig(config);
|
|
282
349
|
const overrides = new Map();
|
|
283
350
|
const modelOverrides = new Map();
|
|
284
351
|
for (const [providerName, providerConfig] of Object.entries(config.providers)) {
|
|
285
|
-
|
|
286
|
-
if (providerConfig.baseUrl || providerConfig.headers || providerConfig.apiKey) {
|
|
352
|
+
if (providerConfig.baseUrl || providerConfig.compat) {
|
|
287
353
|
overrides.set(providerName, {
|
|
288
354
|
baseUrl: providerConfig.baseUrl,
|
|
289
|
-
|
|
290
|
-
apiKey: providerConfig.apiKey,
|
|
355
|
+
compat: providerConfig.compat,
|
|
291
356
|
});
|
|
292
357
|
}
|
|
293
|
-
|
|
294
|
-
if (providerConfig.apiKey) {
|
|
295
|
-
this.customProviderApiKeys.set(providerName, providerConfig.apiKey);
|
|
296
|
-
}
|
|
358
|
+
this.storeProviderRequestConfig(providerName, providerConfig);
|
|
297
359
|
if (providerConfig.modelOverrides) {
|
|
298
360
|
modelOverrides.set(providerName, new Map(Object.entries(providerConfig.modelOverrides)));
|
|
361
|
+
for (const [modelId, modelOverride] of Object.entries(providerConfig.modelOverrides)) {
|
|
362
|
+
this.storeModelHeaders(providerName, modelId, modelOverride.headers);
|
|
363
|
+
}
|
|
299
364
|
}
|
|
300
365
|
}
|
|
301
366
|
return { models: this.parseModels(config), overrides, modelOverrides, error: undefined };
|
|
302
367
|
}
|
|
303
368
|
catch (error) {
|
|
304
369
|
if (error instanceof SyntaxError) {
|
|
305
|
-
return emptyCustomModelsResult(`Failed to parse models.json: ${error.message}\n\nFile: ${
|
|
370
|
+
return emptyCustomModelsResult(`Failed to parse models.json: ${error.message}\n\nFile: ${modelsJsonPath}`);
|
|
306
371
|
}
|
|
307
|
-
return emptyCustomModelsResult(`Failed to load models.json: ${error instanceof Error ? error.message : error}\n\nFile: ${
|
|
372
|
+
return emptyCustomModelsResult(`Failed to load models.json: ${error instanceof Error ? error.message : error}\n\nFile: ${modelsJsonPath}`);
|
|
308
373
|
}
|
|
309
374
|
}
|
|
310
375
|
validateConfig(config) {
|
|
376
|
+
const builtInProviders = new Set(getProviders());
|
|
311
377
|
for (const [providerName, providerConfig] of Object.entries(config.providers)) {
|
|
378
|
+
const isBuiltIn = builtInProviders.has(providerName);
|
|
312
379
|
const hasProviderApi = !!providerConfig.api;
|
|
313
380
|
const models = providerConfig.models ?? [];
|
|
314
381
|
const hasModelOverrides = providerConfig.modelOverrides && Object.keys(providerConfig.modelOverrides).length > 0;
|
|
315
382
|
if (models.length === 0) {
|
|
316
|
-
// Override-only config: needs baseUrl
|
|
317
|
-
if (!providerConfig.baseUrl && !hasModelOverrides) {
|
|
318
|
-
throw new Error(`Provider ${providerName}: must specify "baseUrl", "modelOverrides", or "models".`);
|
|
383
|
+
// Override-only config: needs baseUrl, headers, compat, modelOverrides, or some combination.
|
|
384
|
+
if (!providerConfig.baseUrl && !providerConfig.headers && !providerConfig.compat && !hasModelOverrides) {
|
|
385
|
+
throw new Error(`Provider ${providerName}: must specify "baseUrl", "headers", "compat", "modelOverrides", or "models".`);
|
|
319
386
|
}
|
|
320
387
|
}
|
|
321
|
-
else {
|
|
322
|
-
//
|
|
388
|
+
else if (!isBuiltIn) {
|
|
389
|
+
// Non-built-in providers with custom models require endpoint + auth.
|
|
323
390
|
if (!providerConfig.baseUrl) {
|
|
324
391
|
throw new Error(`Provider ${providerName}: "baseUrl" is required when defining custom models.`);
|
|
325
392
|
}
|
|
@@ -327,11 +394,14 @@ export class ModelRegistry {
|
|
|
327
394
|
throw new Error(`Provider ${providerName}: "apiKey" is required when defining custom models.`);
|
|
328
395
|
}
|
|
329
396
|
}
|
|
397
|
+
// Built-in providers with custom models: baseUrl/apiKey/api are optional,
|
|
398
|
+
// inherited from built-in models. Auth comes from env vars / auth storage.
|
|
330
399
|
for (const modelDef of models) {
|
|
331
400
|
const hasModelApi = !!modelDef.api;
|
|
332
|
-
if (!hasProviderApi && !hasModelApi) {
|
|
401
|
+
if (!hasProviderApi && !hasModelApi && !isBuiltIn) {
|
|
333
402
|
throw new Error(`Provider ${providerName}, model ${modelDef.id}: no "api" specified. Set at provider or model level.`);
|
|
334
403
|
}
|
|
404
|
+
// For built-in providers, api is optional — inherited from built-in models.
|
|
335
405
|
if (!modelDef.id)
|
|
336
406
|
throw new Error(`Provider ${providerName}: model missing "id"`);
|
|
337
407
|
// Validate contextWindow/maxTokens only if provided (they have defaults)
|
|
@@ -344,46 +414,50 @@ export class ModelRegistry {
|
|
|
344
414
|
}
|
|
345
415
|
parseModels(config) {
|
|
346
416
|
const models = [];
|
|
417
|
+
const builtInProviders = new Set(getProviders());
|
|
418
|
+
// Cache built-in defaults (api, baseUrl) per provider, extracted from first model.
|
|
419
|
+
const builtInDefaultsCache = new Map();
|
|
420
|
+
const getBuiltInDefaults = (providerName) => {
|
|
421
|
+
if (!builtInProviders.has(providerName))
|
|
422
|
+
return undefined;
|
|
423
|
+
if (builtInDefaultsCache.has(providerName))
|
|
424
|
+
return builtInDefaultsCache.get(providerName);
|
|
425
|
+
const builtIn = getModels(providerName);
|
|
426
|
+
if (builtIn.length === 0)
|
|
427
|
+
return undefined;
|
|
428
|
+
const defaults = { api: builtIn[0].api, baseUrl: builtIn[0].baseUrl };
|
|
429
|
+
builtInDefaultsCache.set(providerName, defaults);
|
|
430
|
+
return defaults;
|
|
431
|
+
};
|
|
347
432
|
for (const [providerName, providerConfig] of Object.entries(config.providers)) {
|
|
348
433
|
const modelDefs = providerConfig.models ?? [];
|
|
349
434
|
if (modelDefs.length === 0)
|
|
350
435
|
continue; // Override-only, no custom models
|
|
351
|
-
|
|
352
|
-
if (providerConfig.apiKey) {
|
|
353
|
-
this.customProviderApiKeys.set(providerName, providerConfig.apiKey);
|
|
354
|
-
}
|
|
436
|
+
const builtInDefaults = getBuiltInDefaults(providerName);
|
|
355
437
|
for (const modelDef of modelDefs) {
|
|
356
|
-
const api = modelDef.api
|
|
438
|
+
const api = modelDef.api ?? providerConfig.api ?? builtInDefaults?.api;
|
|
357
439
|
if (!api)
|
|
358
440
|
continue;
|
|
359
|
-
|
|
360
|
-
|
|
361
|
-
|
|
362
|
-
const
|
|
363
|
-
|
|
364
|
-
// If authHeader is true, add Authorization header with resolved API key
|
|
365
|
-
if (providerConfig.authHeader && providerConfig.apiKey) {
|
|
366
|
-
const resolvedKey = resolveConfigValue(providerConfig.apiKey);
|
|
367
|
-
if (resolvedKey) {
|
|
368
|
-
headers = { ...headers, Authorization: `Bearer ${resolvedKey}` };
|
|
369
|
-
}
|
|
370
|
-
}
|
|
371
|
-
// Provider baseUrl is required when custom models are defined.
|
|
372
|
-
// Individual models can override it with modelDef.baseUrl.
|
|
441
|
+
const baseUrl = modelDef.baseUrl ?? providerConfig.baseUrl ?? builtInDefaults?.baseUrl;
|
|
442
|
+
if (!baseUrl)
|
|
443
|
+
continue;
|
|
444
|
+
const compat = mergeCompat(providerConfig.compat, modelDef.compat);
|
|
445
|
+
this.storeModelHeaders(providerName, modelDef.id, modelDef.headers);
|
|
373
446
|
const defaultCost = { input: 0, output: 0, cacheRead: 0, cacheWrite: 0 };
|
|
374
447
|
models.push({
|
|
375
448
|
id: modelDef.id,
|
|
376
449
|
name: modelDef.name ?? modelDef.id,
|
|
377
450
|
api: api,
|
|
378
451
|
provider: providerName,
|
|
379
|
-
baseUrl
|
|
452
|
+
baseUrl,
|
|
380
453
|
reasoning: modelDef.reasoning ?? false,
|
|
454
|
+
thinkingLevelMap: modelDef.thinkingLevelMap,
|
|
381
455
|
input: (modelDef.input ?? ["text"]),
|
|
382
456
|
cost: modelDef.cost ?? defaultCost,
|
|
383
457
|
contextWindow: modelDef.contextWindow ?? 128000,
|
|
384
458
|
maxTokens: modelDef.maxTokens ?? 16384,
|
|
385
|
-
headers,
|
|
386
|
-
compat
|
|
459
|
+
headers: undefined,
|
|
460
|
+
compat,
|
|
387
461
|
});
|
|
388
462
|
}
|
|
389
463
|
}
|
|
@@ -401,7 +475,7 @@ export class ModelRegistry {
|
|
|
401
475
|
* This is a fast check that doesn't refresh OAuth tokens.
|
|
402
476
|
*/
|
|
403
477
|
getAvailable() {
|
|
404
|
-
return this.models.filter((m) => this.
|
|
478
|
+
return this.models.filter((m) => this.hasConfiguredAuth(m));
|
|
405
479
|
}
|
|
406
480
|
/**
|
|
407
481
|
* Find a model by provider and ID.
|
|
@@ -412,14 +486,109 @@ export class ModelRegistry {
|
|
|
412
486
|
/**
|
|
413
487
|
* Get API key for a model.
|
|
414
488
|
*/
|
|
415
|
-
|
|
416
|
-
return this.authStorage.
|
|
489
|
+
hasConfiguredAuth(model) {
|
|
490
|
+
return (this.authStorage.hasAuth(model.provider) ||
|
|
491
|
+
this.providerRequestConfigs.get(model.provider)?.apiKey !== undefined);
|
|
492
|
+
}
|
|
493
|
+
getModelRequestKey(provider, modelId) {
|
|
494
|
+
return `${provider}:${modelId}`;
|
|
495
|
+
}
|
|
496
|
+
storeProviderRequestConfig(providerName, config) {
|
|
497
|
+
if (!config.apiKey && !config.headers && !config.authHeader) {
|
|
498
|
+
return;
|
|
499
|
+
}
|
|
500
|
+
this.providerRequestConfigs.set(providerName, {
|
|
501
|
+
apiKey: config.apiKey,
|
|
502
|
+
headers: config.headers,
|
|
503
|
+
authHeader: config.authHeader,
|
|
504
|
+
});
|
|
505
|
+
}
|
|
506
|
+
storeModelHeaders(providerName, modelId, headers) {
|
|
507
|
+
const key = this.getModelRequestKey(providerName, modelId);
|
|
508
|
+
if (!headers || Object.keys(headers).length === 0) {
|
|
509
|
+
this.modelRequestHeaders.delete(key);
|
|
510
|
+
return;
|
|
511
|
+
}
|
|
512
|
+
this.modelRequestHeaders.set(key, headers);
|
|
513
|
+
}
|
|
514
|
+
/**
|
|
515
|
+
* Get API key and request headers for a model.
|
|
516
|
+
*/
|
|
517
|
+
async getApiKeyAndHeaders(model) {
|
|
518
|
+
try {
|
|
519
|
+
const providerConfig = this.providerRequestConfigs.get(model.provider);
|
|
520
|
+
const apiKeyFromAuthStorage = await this.authStorage.getApiKey(model.provider, { includeFallback: false });
|
|
521
|
+
const apiKey = apiKeyFromAuthStorage ??
|
|
522
|
+
(providerConfig?.apiKey
|
|
523
|
+
? resolveConfigValueOrThrow(providerConfig.apiKey, `API key for provider "${model.provider}"`)
|
|
524
|
+
: undefined);
|
|
525
|
+
const providerHeaders = resolveHeadersOrThrow(providerConfig?.headers, `provider "${model.provider}"`);
|
|
526
|
+
const modelHeaders = resolveHeadersOrThrow(this.modelRequestHeaders.get(this.getModelRequestKey(model.provider, model.id)), `model "${model.provider}/${model.id}"`);
|
|
527
|
+
let headers = model.headers || providerHeaders || modelHeaders
|
|
528
|
+
? { ...model.headers, ...providerHeaders, ...modelHeaders }
|
|
529
|
+
: undefined;
|
|
530
|
+
if (providerConfig?.authHeader) {
|
|
531
|
+
if (!apiKey) {
|
|
532
|
+
return { ok: false, error: `No API key found for "${model.provider}"` };
|
|
533
|
+
}
|
|
534
|
+
headers = { ...headers, Authorization: `Bearer ${apiKey}` };
|
|
535
|
+
}
|
|
536
|
+
return {
|
|
537
|
+
ok: true,
|
|
538
|
+
apiKey,
|
|
539
|
+
headers: headers && Object.keys(headers).length > 0 ? headers : undefined,
|
|
540
|
+
};
|
|
541
|
+
}
|
|
542
|
+
catch (error) {
|
|
543
|
+
return {
|
|
544
|
+
ok: false,
|
|
545
|
+
error: error instanceof Error ? error.message : String(error),
|
|
546
|
+
};
|
|
547
|
+
}
|
|
548
|
+
}
|
|
549
|
+
/**
|
|
550
|
+
* Return auth status for a provider, including request auth configured in models.json.
|
|
551
|
+
* This intentionally does not execute command-backed config values.
|
|
552
|
+
*/
|
|
553
|
+
getProviderAuthStatus(provider) {
|
|
554
|
+
const authStatus = this.authStorage.getAuthStatus(provider);
|
|
555
|
+
if (authStatus.source) {
|
|
556
|
+
return authStatus;
|
|
557
|
+
}
|
|
558
|
+
const providerApiKey = this.providerRequestConfigs.get(provider)?.apiKey;
|
|
559
|
+
if (!providerApiKey) {
|
|
560
|
+
return authStatus;
|
|
561
|
+
}
|
|
562
|
+
if (providerApiKey.startsWith("!")) {
|
|
563
|
+
return { configured: true, source: "models_json_command" };
|
|
564
|
+
}
|
|
565
|
+
if (process.env[providerApiKey]) {
|
|
566
|
+
return { configured: true, source: "environment", label: providerApiKey };
|
|
567
|
+
}
|
|
568
|
+
return { configured: true, source: "models_json_key" };
|
|
569
|
+
}
|
|
570
|
+
/**
|
|
571
|
+
* Get display name for a provider.
|
|
572
|
+
*/
|
|
573
|
+
getProviderDisplayName(provider) {
|
|
574
|
+
const registeredProvider = this.registeredProviders.get(provider);
|
|
575
|
+
const oauthProvider = this.authStorage.getOAuthProviders().find((p) => p.id === provider);
|
|
576
|
+
return (registeredProvider?.name ??
|
|
577
|
+
registeredProvider?.oauth?.name ??
|
|
578
|
+
oauthProvider?.name ??
|
|
579
|
+
BUILT_IN_PROVIDER_DISPLAY_NAMES[provider] ??
|
|
580
|
+
provider);
|
|
417
581
|
}
|
|
418
582
|
/**
|
|
419
583
|
* Get API key for a provider.
|
|
420
584
|
*/
|
|
421
585
|
async getApiKeyForProvider(provider) {
|
|
422
|
-
|
|
586
|
+
const apiKey = await this.authStorage.getApiKey(provider, { includeFallback: false });
|
|
587
|
+
if (apiKey !== undefined) {
|
|
588
|
+
return apiKey;
|
|
589
|
+
}
|
|
590
|
+
const providerApiKey = this.providerRequestConfigs.get(provider)?.apiKey;
|
|
591
|
+
return providerApiKey ? resolveConfigValueUncached(providerApiKey) : undefined;
|
|
423
592
|
}
|
|
424
593
|
/**
|
|
425
594
|
* Check if a model is using OAuth credentials (subscription).
|
|
@@ -436,8 +605,9 @@ export class ModelRegistry {
|
|
|
436
605
|
* If provider has oauth: registers OAuth provider for /login support.
|
|
437
606
|
*/
|
|
438
607
|
registerProvider(providerName, config) {
|
|
439
|
-
this.
|
|
608
|
+
this.validateProviderConfig(providerName, config);
|
|
440
609
|
this.applyProviderConfig(providerName, config);
|
|
610
|
+
this.upsertRegisteredProvider(providerName, config);
|
|
441
611
|
}
|
|
442
612
|
/**
|
|
443
613
|
* Unregister a previously registered provider.
|
|
@@ -452,9 +622,46 @@ export class ModelRegistry {
|
|
|
452
622
|
if (!this.registeredProviders.has(providerName))
|
|
453
623
|
return;
|
|
454
624
|
this.registeredProviders.delete(providerName);
|
|
455
|
-
this.customProviderApiKeys.delete(providerName);
|
|
456
625
|
this.refresh();
|
|
457
626
|
}
|
|
627
|
+
/**
|
|
628
|
+
* Upsert a provider config into registeredProviders.
|
|
629
|
+
* If the provider is already registered, defined values in the incoming config
|
|
630
|
+
* override existing ones; undefined values are preserved from the stored config.
|
|
631
|
+
* If the provider is not registered, the incoming config is stored as-is.
|
|
632
|
+
*/
|
|
633
|
+
upsertRegisteredProvider(providerName, config) {
|
|
634
|
+
const existing = this.registeredProviders.get(providerName);
|
|
635
|
+
if (!existing) {
|
|
636
|
+
this.registeredProviders.set(providerName, config);
|
|
637
|
+
return;
|
|
638
|
+
}
|
|
639
|
+
for (const k of Object.keys(config)) {
|
|
640
|
+
if (config[k] !== undefined) {
|
|
641
|
+
existing[k] = config[k];
|
|
642
|
+
}
|
|
643
|
+
}
|
|
644
|
+
}
|
|
645
|
+
validateProviderConfig(providerName, config) {
|
|
646
|
+
if (config.streamSimple && !config.api) {
|
|
647
|
+
throw new Error(`Provider ${providerName}: "api" is required when registering streamSimple.`);
|
|
648
|
+
}
|
|
649
|
+
if (!config.models || config.models.length === 0) {
|
|
650
|
+
return;
|
|
651
|
+
}
|
|
652
|
+
if (!config.baseUrl) {
|
|
653
|
+
throw new Error(`Provider ${providerName}: "baseUrl" is required when defining models.`);
|
|
654
|
+
}
|
|
655
|
+
if (!config.apiKey && !config.oauth) {
|
|
656
|
+
throw new Error(`Provider ${providerName}: "apiKey" or "oauth" is required when defining models.`);
|
|
657
|
+
}
|
|
658
|
+
for (const modelDef of config.models) {
|
|
659
|
+
const api = modelDef.api || config.api;
|
|
660
|
+
if (!api) {
|
|
661
|
+
throw new Error(`Provider ${providerName}, model ${modelDef.id}: no "api" specified.`);
|
|
662
|
+
}
|
|
663
|
+
}
|
|
664
|
+
}
|
|
458
665
|
applyProviderConfig(providerName, config) {
|
|
459
666
|
// Register OAuth provider if provided
|
|
460
667
|
if (config.oauth) {
|
|
@@ -466,9 +673,6 @@ export class ModelRegistry {
|
|
|
466
673
|
registerOAuthProvider(oauthProvider);
|
|
467
674
|
}
|
|
468
675
|
if (config.streamSimple) {
|
|
469
|
-
if (!config.api) {
|
|
470
|
-
throw new Error(`Provider ${providerName}: "api" is required when registering streamSimple.`);
|
|
471
|
-
}
|
|
472
676
|
const streamSimple = config.streamSimple;
|
|
473
677
|
registerApiProvider({
|
|
474
678
|
api: config.api,
|
|
@@ -476,49 +680,27 @@ export class ModelRegistry {
|
|
|
476
680
|
streamSimple,
|
|
477
681
|
}, `provider:${providerName}`);
|
|
478
682
|
}
|
|
479
|
-
|
|
480
|
-
if (config.apiKey) {
|
|
481
|
-
this.customProviderApiKeys.set(providerName, config.apiKey);
|
|
482
|
-
}
|
|
683
|
+
this.storeProviderRequestConfig(providerName, config);
|
|
483
684
|
if (config.models && config.models.length > 0) {
|
|
484
685
|
// Full replacement: remove existing models for this provider
|
|
485
686
|
this.models = this.models.filter((m) => m.provider !== providerName);
|
|
486
|
-
// Validate required fields
|
|
487
|
-
if (!config.baseUrl) {
|
|
488
|
-
throw new Error(`Provider ${providerName}: "baseUrl" is required when defining models.`);
|
|
489
|
-
}
|
|
490
|
-
if (!config.apiKey && !config.oauth) {
|
|
491
|
-
throw new Error(`Provider ${providerName}: "apiKey" or "oauth" is required when defining models.`);
|
|
492
|
-
}
|
|
493
687
|
// Parse and add new models
|
|
494
688
|
for (const modelDef of config.models) {
|
|
495
689
|
const api = modelDef.api || config.api;
|
|
496
|
-
|
|
497
|
-
throw new Error(`Provider ${providerName}, model ${modelDef.id}: no "api" specified.`);
|
|
498
|
-
}
|
|
499
|
-
// Merge headers
|
|
500
|
-
const providerHeaders = resolveHeaders(config.headers);
|
|
501
|
-
const modelHeaders = resolveHeaders(modelDef.headers);
|
|
502
|
-
let headers = providerHeaders || modelHeaders ? { ...providerHeaders, ...modelHeaders } : undefined;
|
|
503
|
-
// If authHeader is true, add Authorization header
|
|
504
|
-
if (config.authHeader && config.apiKey) {
|
|
505
|
-
const resolvedKey = resolveConfigValue(config.apiKey);
|
|
506
|
-
if (resolvedKey) {
|
|
507
|
-
headers = { ...headers, Authorization: `Bearer ${resolvedKey}` };
|
|
508
|
-
}
|
|
509
|
-
}
|
|
690
|
+
this.storeModelHeaders(providerName, modelDef.id, modelDef.headers);
|
|
510
691
|
this.models.push({
|
|
511
692
|
id: modelDef.id,
|
|
512
693
|
name: modelDef.name,
|
|
513
694
|
api: api,
|
|
514
695
|
provider: providerName,
|
|
515
|
-
baseUrl: config.baseUrl,
|
|
696
|
+
baseUrl: modelDef.baseUrl ?? config.baseUrl,
|
|
516
697
|
reasoning: modelDef.reasoning,
|
|
698
|
+
thinkingLevelMap: modelDef.thinkingLevelMap,
|
|
517
699
|
input: modelDef.input,
|
|
518
700
|
cost: modelDef.cost,
|
|
519
701
|
contextWindow: modelDef.contextWindow,
|
|
520
702
|
maxTokens: modelDef.maxTokens,
|
|
521
|
-
headers,
|
|
703
|
+
headers: undefined,
|
|
522
704
|
compat: modelDef.compat,
|
|
523
705
|
});
|
|
524
706
|
}
|
|
@@ -530,16 +712,14 @@ export class ModelRegistry {
|
|
|
530
712
|
}
|
|
531
713
|
}
|
|
532
714
|
}
|
|
533
|
-
else if (config.baseUrl) {
|
|
534
|
-
// Override-only: update baseUrl
|
|
535
|
-
const resolvedHeaders = resolveHeaders(config.headers);
|
|
715
|
+
else if (config.baseUrl || config.headers) {
|
|
716
|
+
// Override-only: update baseUrl for existing models. Request headers are resolved per request.
|
|
536
717
|
this.models = this.models.map((m) => {
|
|
537
718
|
if (m.provider !== providerName)
|
|
538
719
|
return m;
|
|
539
720
|
return {
|
|
540
721
|
...m,
|
|
541
722
|
baseUrl: config.baseUrl ?? m.baseUrl,
|
|
542
|
-
headers: resolvedHeaders ? { ...m.headers, ...resolvedHeaders } : m.headers,
|
|
543
723
|
};
|
|
544
724
|
});
|
|
545
725
|
}
|