@code-yeongyu/senpi 2026.7.14-3 → 2026.7.16-2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +105 -0
- package/README.md +6 -6
- package/dist/bun/cli.js +2 -0
- package/dist/bun/cli.js.map +1 -1
- package/dist/cli/args.js +1 -1
- package/dist/cli/args.js.map +1 -1
- package/dist/cli/list-models.d.ts +2 -2
- package/dist/cli/list-models.d.ts.map +1 -1
- package/dist/cli/list-models.js +3 -3
- package/dist/cli/list-models.js.map +1 -1
- package/dist/core/agent-session-runtime.d.ts.map +1 -1
- package/dist/core/agent-session-runtime.js +3 -0
- package/dist/core/agent-session-runtime.js.map +1 -1
- package/dist/core/agent-session-services.d.ts +4 -3
- package/dist/core/agent-session-services.d.ts.map +1 -1
- package/dist/core/agent-session-services.js +14 -5
- package/dist/core/agent-session-services.js.map +1 -1
- package/dist/core/agent-session.d.ts +8 -4
- package/dist/core/agent-session.d.ts.map +1 -1
- package/dist/core/agent-session.js +80 -29
- package/dist/core/agent-session.js.map +1 -1
- package/dist/core/auth-providers.js +1 -1
- package/dist/core/auth-providers.js.map +1 -1
- package/dist/core/auth-storage.d.ts +32 -87
- package/dist/core/auth-storage.d.ts.map +1 -1
- package/dist/core/auth-storage.js +158 -221
- package/dist/core/auth-storage.js.map +1 -1
- package/dist/core/cache-stats.d.ts +2 -2
- package/dist/core/cache-stats.d.ts.map +1 -1
- package/dist/core/cache-stats.js +1 -1
- package/dist/core/cache-stats.js.map +1 -1
- package/dist/core/dynamic-prompt/build.d.ts.map +1 -1
- package/dist/core/dynamic-prompt/build.js +6 -1
- package/dist/core/dynamic-prompt/build.js.map +1 -1
- package/dist/core/extensions/builtin/bash-timeout/timeout.js +2 -2
- package/dist/core/extensions/builtin/bash-timeout/timeout.js.map +1 -1
- package/dist/core/extensions/builtin/prompt-preset/gpt-5.6.js +8 -8
- package/dist/core/extensions/builtin/prompt-preset/gpt-5.6.js.map +1 -1
- package/dist/core/extensions/loader.d.ts.map +1 -1
- package/dist/core/extensions/loader.js +8 -2
- package/dist/core/extensions/loader.js.map +1 -1
- package/dist/core/extensions/runner.d.ts +1 -0
- package/dist/core/extensions/runner.d.ts.map +1 -1
- package/dist/core/extensions/runner.js +3 -0
- package/dist/core/extensions/runner.js.map +1 -1
- package/dist/core/extensions/types.d.ts +15 -2
- package/dist/core/extensions/types.d.ts.map +1 -1
- package/dist/core/extensions/types.js.map +1 -1
- package/dist/core/model-config.d.ts +589 -0
- package/dist/core/model-config.d.ts.map +1 -0
- package/dist/core/model-config.js +288 -0
- package/dist/core/model-config.js.map +1 -0
- package/dist/core/model-registry.d.ts +17 -146
- package/dist/core/model-registry.d.ts.map +1 -1
- package/dist/core/model-registry.js +69 -958
- package/dist/core/model-registry.js.map +1 -1
- package/dist/core/model-resolver.d.ts +8 -5
- package/dist/core/model-resolver.d.ts.map +1 -1
- package/dist/core/model-resolver.js +18 -18
- package/dist/core/model-resolver.js.map +1 -1
- package/dist/core/model-runtime.d.ts +81 -0
- package/dist/core/model-runtime.d.ts.map +1 -0
- package/dist/core/model-runtime.js +442 -0
- package/dist/core/model-runtime.js.map +1 -0
- package/dist/core/models-store.d.ts +17 -0
- package/dist/core/models-store.d.ts.map +1 -0
- package/dist/core/models-store.js +46 -0
- package/dist/core/models-store.js.map +1 -0
- package/dist/core/provider-composer.d.ts +64 -0
- package/dist/core/provider-composer.d.ts.map +1 -0
- package/dist/core/provider-composer.js +406 -0
- package/dist/core/provider-composer.js.map +1 -0
- package/dist/core/provider-display-names.js +1 -1
- package/dist/core/provider-display-names.js.map +1 -1
- package/dist/core/radius.d.ts +0 -19
- package/dist/core/radius.d.ts.map +1 -1
- package/dist/core/radius.js +0 -28
- package/dist/core/radius.js.map +1 -1
- package/dist/core/remote-catalog-provider.d.ts +5 -0
- package/dist/core/remote-catalog-provider.d.ts.map +1 -0
- package/dist/core/remote-catalog-provider.js +83 -0
- package/dist/core/remote-catalog-provider.js.map +1 -0
- package/dist/core/runtime-credentials.d.ts +15 -0
- package/dist/core/runtime-credentials.d.ts.map +1 -0
- package/dist/core/runtime-credentials.js +35 -0
- package/dist/core/runtime-credentials.js.map +1 -0
- package/dist/core/sdk.d.ts +11 -20
- package/dist/core/sdk.d.ts.map +1 -1
- package/dist/core/sdk.js +61 -89
- package/dist/core/sdk.js.map +1 -1
- package/dist/core/skills.js +1 -1
- package/dist/core/skills.js.map +1 -1
- package/dist/index.d.ts +2 -1
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +2 -2
- package/dist/index.js.map +1 -1
- package/dist/main.d.ts.map +1 -1
- package/dist/main.js +10 -13
- package/dist/main.js.map +1 -1
- package/dist/modes/interactive/components/assistant-message.d.ts.map +1 -1
- package/dist/modes/interactive/components/assistant-message.js +22 -10
- package/dist/modes/interactive/components/assistant-message.js.map +1 -1
- package/dist/modes/interactive/components/footer.js +1 -1
- package/dist/modes/interactive/components/footer.js.map +1 -1
- package/dist/modes/interactive/components/login-dialog.d.ts +4 -8
- package/dist/modes/interactive/components/login-dialog.d.ts.map +1 -1
- package/dist/modes/interactive/components/login-dialog.js +14 -12
- package/dist/modes/interactive/components/login-dialog.js.map +1 -1
- package/dist/modes/interactive/components/model-selector.d.ts +13 -4
- package/dist/modes/interactive/components/model-selector.d.ts.map +1 -1
- package/dist/modes/interactive/components/model-selector.js +84 -41
- package/dist/modes/interactive/components/model-selector.js.map +1 -1
- package/dist/modes/interactive/components/oauth-selector.d.ts +4 -4
- package/dist/modes/interactive/components/oauth-selector.d.ts.map +1 -1
- package/dist/modes/interactive/components/oauth-selector.js +14 -25
- package/dist/modes/interactive/components/oauth-selector.js.map +1 -1
- package/dist/modes/interactive/interactive-mode.d.ts +5 -1
- package/dist/modes/interactive/interactive-mode.d.ts.map +1 -1
- package/dist/modes/interactive/interactive-mode.js +154 -128
- package/dist/modes/interactive/interactive-mode.js.map +1 -1
- package/dist/package-manager-cli.d.ts.map +1 -1
- package/dist/package-manager-cli.js +70 -8
- package/dist/package-manager-cli.js.map +1 -1
- package/docs/custom-provider.md +6 -11
- package/docs/extensions.md +78 -555
- package/docs/models.md +2 -0
- package/docs/packages.md +1 -0
- package/docs/providers.md +23 -11
- package/docs/sdk.md +79 -105
- package/docs/usage.md +1 -0
- package/examples/extensions/README.md +1 -0
- package/examples/extensions/custom-provider-anthropic/index.ts +1 -1
- package/examples/extensions/custom-provider-anthropic/package-lock.json +2 -2
- package/examples/extensions/custom-provider-anthropic/package.json +1 -1
- package/examples/extensions/custom-provider-gitlab-duo/package.json +1 -1
- package/examples/extensions/gondolin/package-lock.json +2 -2
- package/examples/extensions/gondolin/package.json +1 -1
- package/examples/extensions/kimi-deferred-tools.ts +61 -0
- package/examples/extensions/sandbox/package-lock.json +2 -2
- package/examples/extensions/sandbox/package.json +1 -1
- package/examples/extensions/with-deps/package-lock.json +2 -2
- package/examples/extensions/with-deps/package.json +1 -1
- package/examples/sdk/02-custom-model.ts +5 -8
- package/examples/sdk/09-api-keys-and-oauth.ts +13 -31
- package/examples/sdk/12-full-control.ts +8 -13
- package/examples/sdk/README.md +14 -18
- package/node_modules/@code-yeongyu/senpi-codemode/CHANGELOG.md +16 -0
- package/node_modules/@code-yeongyu/senpi-codemode/package.json +3 -3
- package/node_modules/@code-yeongyu/senpi-codemode/src/kernels/js/local-module-loader.ts +2 -2
- package/node_modules/@code-yeongyu/senpi-codemode/src/kernels/js/rewrite-imports.ts +4 -4
- package/node_modules/@code-yeongyu/senpi-codemode/src/tool/render.ts +32 -32
- package/node_modules/@earendil-works/pi-agent-core/package.json +4 -4
- package/node_modules/@earendil-works/pi-ai/README.md +77 -23
- package/node_modules/@earendil-works/pi-ai/dist/api/lazy.d.ts.map +1 -1
- package/node_modules/@earendil-works/pi-ai/dist/api/lazy.js +9 -10
- package/node_modules/@earendil-works/pi-ai/dist/api/lazy.js.map +1 -1
- package/node_modules/@earendil-works/pi-ai/dist/api/openai-codex-responses.d.ts.map +1 -1
- package/node_modules/@earendil-works/pi-ai/dist/api/openai-codex-responses.js +3 -2
- package/node_modules/@earendil-works/pi-ai/dist/api/openai-codex-responses.js.map +1 -1
- package/node_modules/@earendil-works/pi-ai/dist/api/openai-completions.d.ts +2 -1
- package/node_modules/@earendil-works/pi-ai/dist/api/openai-completions.d.ts.map +1 -1
- package/node_modules/@earendil-works/pi-ai/dist/api/openai-completions.js +42 -2
- package/node_modules/@earendil-works/pi-ai/dist/api/openai-completions.js.map +1 -1
- package/node_modules/@earendil-works/pi-ai/dist/api/openai-responses.js +2 -0
- package/node_modules/@earendil-works/pi-ai/dist/api/openai-responses.js.map +1 -1
- package/node_modules/@earendil-works/pi-ai/dist/auth/credential-store.d.ts +2 -1
- package/node_modules/@earendil-works/pi-ai/dist/auth/credential-store.d.ts.map +1 -1
- package/node_modules/@earendil-works/pi-ai/dist/auth/credential-store.js +3 -0
- package/node_modules/@earendil-works/pi-ai/dist/auth/credential-store.js.map +1 -1
- package/node_modules/@earendil-works/pi-ai/dist/auth/helpers.d.ts +1 -0
- package/node_modules/@earendil-works/pi-ai/dist/auth/helpers.d.ts.map +1 -1
- package/node_modules/@earendil-works/pi-ai/dist/auth/helpers.js +4 -3
- package/node_modules/@earendil-works/pi-ai/dist/auth/helpers.js.map +1 -1
- package/node_modules/@earendil-works/pi-ai/dist/auth/oauth/anthropic.d.ts +9 -0
- package/node_modules/@earendil-works/pi-ai/dist/auth/oauth/anthropic.d.ts.map +1 -0
- package/node_modules/@earendil-works/pi-ai/dist/{utils → auth}/oauth/anthropic.js +51 -116
- package/node_modules/@earendil-works/pi-ai/dist/auth/oauth/anthropic.js.map +1 -0
- package/node_modules/@earendil-works/pi-ai/dist/auth/oauth/device-code.d.ts.map +1 -0
- package/node_modules/@earendil-works/pi-ai/dist/auth/oauth/device-code.js.map +1 -0
- package/node_modules/@earendil-works/pi-ai/dist/auth/oauth/github-copilot.d.ts +6 -0
- package/node_modules/@earendil-works/pi-ai/dist/auth/oauth/github-copilot.d.ts.map +1 -0
- package/node_modules/@earendil-works/pi-ai/dist/{utils → auth}/oauth/github-copilot.js +18 -77
- package/node_modules/@earendil-works/pi-ai/dist/auth/oauth/github-copilot.js.map +1 -0
- package/node_modules/@earendil-works/pi-ai/dist/auth/oauth/load.d.ts +23 -0
- package/node_modules/@earendil-works/pi-ai/dist/auth/oauth/load.d.ts.map +1 -0
- package/node_modules/@earendil-works/pi-ai/dist/auth/oauth/load.js +49 -0
- package/node_modules/@earendil-works/pi-ai/dist/auth/oauth/load.js.map +1 -0
- package/node_modules/@earendil-works/pi-ai/dist/auth/oauth/oauth-page.d.ts.map +1 -0
- package/node_modules/@earendil-works/pi-ai/dist/auth/oauth/oauth-page.js.map +1 -0
- package/node_modules/@earendil-works/pi-ai/dist/auth/oauth/openai-codex.d.ts +9 -0
- package/node_modules/@earendil-works/pi-ai/dist/auth/oauth/openai-codex.d.ts.map +1 -0
- package/node_modules/@earendil-works/pi-ai/dist/{utils → auth}/oauth/openai-codex.js +61 -155
- package/node_modules/@earendil-works/pi-ai/dist/auth/oauth/openai-codex.js.map +1 -0
- package/node_modules/@earendil-works/pi-ai/dist/auth/oauth/pkce.d.ts.map +1 -0
- package/node_modules/@earendil-works/pi-ai/dist/auth/oauth/pkce.js.map +1 -0
- package/node_modules/@earendil-works/pi-ai/dist/auth/oauth/radius.d.ts +16 -0
- package/node_modules/@earendil-works/pi-ai/dist/auth/oauth/radius.d.ts.map +1 -0
- package/node_modules/@earendil-works/pi-ai/dist/{utils → auth}/oauth/radius.js +31 -128
- package/node_modules/@earendil-works/pi-ai/dist/auth/oauth/radius.js.map +1 -0
- package/node_modules/@earendil-works/pi-ai/dist/auth/oauth/xai.d.ts +6 -0
- package/node_modules/@earendil-works/pi-ai/dist/auth/oauth/xai.d.ts.map +1 -0
- package/node_modules/@earendil-works/pi-ai/dist/auth/oauth/xai.js +189 -0
- package/node_modules/@earendil-works/pi-ai/dist/auth/oauth/xai.js.map +1 -0
- package/node_modules/@earendil-works/pi-ai/dist/auth/resolve.d.ts +2 -4
- package/node_modules/@earendil-works/pi-ai/dist/auth/resolve.d.ts.map +1 -1
- package/node_modules/@earendil-works/pi-ai/dist/auth/resolve.js +9 -7
- package/node_modules/@earendil-works/pi-ai/dist/auth/resolve.js.map +1 -1
- package/node_modules/@earendil-works/pi-ai/dist/auth/types.d.ts +49 -10
- package/node_modules/@earendil-works/pi-ai/dist/auth/types.d.ts.map +1 -1
- package/node_modules/@earendil-works/pi-ai/dist/auth/types.js.map +1 -1
- package/node_modules/@earendil-works/pi-ai/dist/bun-oauth.d.ts +3 -0
- package/node_modules/@earendil-works/pi-ai/dist/bun-oauth.d.ts.map +1 -0
- package/node_modules/@earendil-works/pi-ai/dist/bun-oauth.js +17 -0
- package/node_modules/@earendil-works/pi-ai/dist/bun-oauth.js.map +1 -0
- package/node_modules/@earendil-works/pi-ai/dist/cli.js +58 -76
- package/node_modules/@earendil-works/pi-ai/dist/cli.js.map +1 -1
- package/node_modules/@earendil-works/pi-ai/dist/compat/extension-oauth-types.d.ts +42 -0
- package/node_modules/@earendil-works/pi-ai/dist/compat/extension-oauth-types.d.ts.map +1 -0
- package/node_modules/@earendil-works/pi-ai/dist/compat/extension-oauth-types.js +2 -0
- package/node_modules/@earendil-works/pi-ai/dist/compat/extension-oauth-types.js.map +1 -0
- package/node_modules/@earendil-works/pi-ai/dist/compat.d.ts.map +1 -1
- package/node_modules/@earendil-works/pi-ai/dist/compat.js +46 -22
- package/node_modules/@earendil-works/pi-ai/dist/compat.js.map +1 -1
- package/node_modules/@earendil-works/pi-ai/dist/env-api-keys.js +1 -1
- package/node_modules/@earendil-works/pi-ai/dist/env-api-keys.js.map +1 -1
- package/node_modules/@earendil-works/pi-ai/dist/images-models.d.ts +4 -2
- package/node_modules/@earendil-works/pi-ai/dist/images-models.d.ts.map +1 -1
- package/node_modules/@earendil-works/pi-ai/dist/images-models.js +5 -4
- package/node_modules/@earendil-works/pi-ai/dist/images-models.js.map +1 -1
- package/node_modules/@earendil-works/pi-ai/dist/index.d.ts +2 -1
- package/node_modules/@earendil-works/pi-ai/dist/index.d.ts.map +1 -1
- package/node_modules/@earendil-works/pi-ai/dist/index.js +1 -0
- package/node_modules/@earendil-works/pi-ai/dist/index.js.map +1 -1
- package/node_modules/@earendil-works/pi-ai/dist/models-store.d.ts +25 -0
- package/node_modules/@earendil-works/pi-ai/dist/models-store.d.ts.map +1 -0
- package/node_modules/@earendil-works/pi-ai/dist/models-store.js +16 -0
- package/node_modules/@earendil-works/pi-ai/dist/models-store.js.map +1 -0
- package/node_modules/@earendil-works/pi-ai/dist/models.d.ts +69 -30
- package/node_modules/@earendil-works/pi-ai/dist/models.d.ts.map +1 -1
- package/node_modules/@earendil-works/pi-ai/dist/models.generated.d.ts +270 -114
- package/node_modules/@earendil-works/pi-ai/dist/models.generated.d.ts.map +1 -1
- package/node_modules/@earendil-works/pi-ai/dist/models.js +217 -31
- package/node_modules/@earendil-works/pi-ai/dist/models.js.map +1 -1
- package/node_modules/@earendil-works/pi-ai/dist/oauth.d.ts +2 -1
- package/node_modules/@earendil-works/pi-ai/dist/oauth.d.ts.map +1 -1
- package/node_modules/@earendil-works/pi-ai/dist/oauth.js +1 -1
- package/node_modules/@earendil-works/pi-ai/dist/oauth.js.map +1 -1
- package/node_modules/@earendil-works/pi-ai/dist/providers/all.d.ts +2 -1
- package/node_modules/@earendil-works/pi-ai/dist/providers/all.d.ts.map +1 -1
- package/node_modules/@earendil-works/pi-ai/dist/providers/all.js +3 -0
- package/node_modules/@earendil-works/pi-ai/dist/providers/all.js.map +1 -1
- package/node_modules/@earendil-works/pi-ai/dist/providers/amazon-bedrock.d.ts.map +1 -1
- package/node_modules/@earendil-works/pi-ai/dist/providers/amazon-bedrock.js +51 -10
- package/node_modules/@earendil-works/pi-ai/dist/providers/amazon-bedrock.js.map +1 -1
- package/node_modules/@earendil-works/pi-ai/dist/providers/anthropic.d.ts.map +1 -1
- package/node_modules/@earendil-works/pi-ai/dist/providers/anthropic.js +1 -1
- package/node_modules/@earendil-works/pi-ai/dist/providers/anthropic.js.map +1 -1
- package/node_modules/@earendil-works/pi-ai/dist/providers/cloudflare-ai-gateway.d.ts.map +1 -1
- package/node_modules/@earendil-works/pi-ai/dist/providers/cloudflare-ai-gateway.js +4 -3
- package/node_modules/@earendil-works/pi-ai/dist/providers/cloudflare-ai-gateway.js.map +1 -1
- package/node_modules/@earendil-works/pi-ai/dist/providers/cloudflare-auth.d.ts.map +1 -1
- package/node_modules/@earendil-works/pi-ai/dist/providers/cloudflare-auth.js +13 -20
- package/node_modules/@earendil-works/pi-ai/dist/providers/cloudflare-auth.js.map +1 -1
- package/node_modules/@earendil-works/pi-ai/dist/providers/cloudflare-stream.d.ts +8 -0
- package/node_modules/@earendil-works/pi-ai/dist/providers/cloudflare-stream.d.ts.map +1 -0
- package/node_modules/@earendil-works/pi-ai/dist/providers/cloudflare-stream.js +21 -0
- package/node_modules/@earendil-works/pi-ai/dist/providers/cloudflare-stream.js.map +1 -0
- package/node_modules/@earendil-works/pi-ai/dist/providers/cloudflare-workers-ai.d.ts.map +1 -1
- package/node_modules/@earendil-works/pi-ai/dist/providers/cloudflare-workers-ai.js +2 -1
- package/node_modules/@earendil-works/pi-ai/dist/providers/cloudflare-workers-ai.js.map +1 -1
- package/node_modules/@earendil-works/pi-ai/dist/providers/github-copilot.d.ts.map +1 -1
- package/node_modules/@earendil-works/pi-ai/dist/providers/github-copilot.js +11 -1
- package/node_modules/@earendil-works/pi-ai/dist/providers/github-copilot.js.map +1 -1
- package/node_modules/@earendil-works/pi-ai/dist/providers/google-vertex.d.ts.map +1 -1
- package/node_modules/@earendil-works/pi-ai/dist/providers/google-vertex.js +56 -5
- package/node_modules/@earendil-works/pi-ai/dist/providers/google-vertex.js.map +1 -1
- package/node_modules/@earendil-works/pi-ai/dist/providers/kimi-coding.models.d.ts +66 -0
- package/node_modules/@earendil-works/pi-ai/dist/providers/kimi-coding.models.d.ts.map +1 -1
- package/node_modules/@earendil-works/pi-ai/dist/providers/kimi-coding.models.js +42 -0
- package/node_modules/@earendil-works/pi-ai/dist/providers/kimi-coding.models.js.map +1 -1
- package/node_modules/@earendil-works/pi-ai/dist/providers/moonshotai-cn.models.d.ts +36 -0
- package/node_modules/@earendil-works/pi-ai/dist/providers/moonshotai-cn.models.d.ts.map +1 -1
- package/node_modules/@earendil-works/pi-ai/dist/providers/moonshotai-cn.models.js +19 -0
- package/node_modules/@earendil-works/pi-ai/dist/providers/moonshotai-cn.models.js.map +1 -1
- package/node_modules/@earendil-works/pi-ai/dist/providers/moonshotai.models.d.ts +36 -0
- package/node_modules/@earendil-works/pi-ai/dist/providers/moonshotai.models.d.ts.map +1 -1
- package/node_modules/@earendil-works/pi-ai/dist/providers/moonshotai.models.js +19 -0
- package/node_modules/@earendil-works/pi-ai/dist/providers/moonshotai.models.js.map +1 -1
- package/node_modules/@earendil-works/pi-ai/dist/providers/openai-codex.d.ts.map +1 -1
- package/node_modules/@earendil-works/pi-ai/dist/providers/openai-codex.js +1 -1
- package/node_modules/@earendil-works/pi-ai/dist/providers/openai-codex.js.map +1 -1
- package/node_modules/@earendil-works/pi-ai/dist/providers/openrouter.models.d.ts +42 -0
- package/node_modules/@earendil-works/pi-ai/dist/providers/openrouter.models.d.ts.map +1 -1
- package/node_modules/@earendil-works/pi-ai/dist/providers/openrouter.models.js +178 -142
- package/node_modules/@earendil-works/pi-ai/dist/providers/openrouter.models.js.map +1 -1
- package/node_modules/@earendil-works/pi-ai/dist/providers/radius-config.d.ts +26 -0
- package/node_modules/@earendil-works/pi-ai/dist/providers/radius-config.d.ts.map +1 -0
- package/node_modules/@earendil-works/pi-ai/dist/providers/radius-config.js +59 -0
- package/node_modules/@earendil-works/pi-ai/dist/providers/radius-config.js.map +1 -0
- package/node_modules/@earendil-works/pi-ai/dist/providers/radius.d.ts +9 -0
- package/node_modules/@earendil-works/pi-ai/dist/providers/radius.d.ts.map +1 -0
- package/node_modules/@earendil-works/pi-ai/dist/providers/radius.js +54 -0
- package/node_modules/@earendil-works/pi-ai/dist/providers/radius.js.map +1 -0
- package/node_modules/@earendil-works/pi-ai/dist/providers/vercel-ai-gateway.models.d.ts +84 -0
- package/node_modules/@earendil-works/pi-ai/dist/providers/vercel-ai-gateway.models.d.ts.map +1 -1
- package/node_modules/@earendil-works/pi-ai/dist/providers/vercel-ai-gateway.models.js +72 -0
- package/node_modules/@earendil-works/pi-ai/dist/providers/vercel-ai-gateway.models.js.map +1 -1
- package/node_modules/@earendil-works/pi-ai/dist/providers/xai.d.ts +1 -1
- package/node_modules/@earendil-works/pi-ai/dist/providers/xai.d.ts.map +1 -1
- package/node_modules/@earendil-works/pi-ai/dist/providers/xai.js +15 -3
- package/node_modules/@earendil-works/pi-ai/dist/providers/xai.js.map +1 -1
- package/node_modules/@earendil-works/pi-ai/dist/providers/xai.models.d.ts +6 -114
- package/node_modules/@earendil-works/pi-ai/dist/providers/xai.models.d.ts.map +1 -1
- package/node_modules/@earendil-works/pi-ai/dist/providers/xai.models.js +3 -92
- package/node_modules/@earendil-works/pi-ai/dist/providers/xai.models.js.map +1 -1
- package/node_modules/@earendil-works/pi-ai/dist/types.d.ts +2 -0
- package/node_modules/@earendil-works/pi-ai/dist/types.d.ts.map +1 -1
- package/node_modules/@earendil-works/pi-ai/dist/types.js.map +1 -1
- package/node_modules/@earendil-works/pi-ai/package.json +6 -1
- package/node_modules/@earendil-works/pi-pty/package.json +1 -1
- package/node_modules/@earendil-works/pi-tui/dist/utils.d.ts.map +1 -1
- package/node_modules/@earendil-works/pi-tui/dist/utils.js +22 -4
- package/node_modules/@earendil-works/pi-tui/dist/utils.js.map +1 -1
- package/node_modules/@earendil-works/pi-tui/package.json +1 -1
- package/package.json +6 -6
- package/node_modules/@earendil-works/pi-ai/dist/utils/oauth/anthropic.d.ts +0 -27
- package/node_modules/@earendil-works/pi-ai/dist/utils/oauth/anthropic.d.ts.map +0 -1
- package/node_modules/@earendil-works/pi-ai/dist/utils/oauth/anthropic.js.map +0 -1
- package/node_modules/@earendil-works/pi-ai/dist/utils/oauth/device-code.d.ts.map +0 -1
- package/node_modules/@earendil-works/pi-ai/dist/utils/oauth/device-code.js.map +0 -1
- package/node_modules/@earendil-works/pi-ai/dist/utils/oauth/github-copilot.d.ts +0 -32
- package/node_modules/@earendil-works/pi-ai/dist/utils/oauth/github-copilot.d.ts.map +0 -1
- package/node_modules/@earendil-works/pi-ai/dist/utils/oauth/github-copilot.js.map +0 -1
- package/node_modules/@earendil-works/pi-ai/dist/utils/oauth/index.d.ts +0 -59
- package/node_modules/@earendil-works/pi-ai/dist/utils/oauth/index.d.ts.map +0 -1
- package/node_modules/@earendil-works/pi-ai/dist/utils/oauth/index.js +0 -131
- package/node_modules/@earendil-works/pi-ai/dist/utils/oauth/index.js.map +0 -1
- package/node_modules/@earendil-works/pi-ai/dist/utils/oauth/load.d.ts +0 -5
- package/node_modules/@earendil-works/pi-ai/dist/utils/oauth/load.d.ts.map +0 -1
- package/node_modules/@earendil-works/pi-ai/dist/utils/oauth/load.js +0 -22
- package/node_modules/@earendil-works/pi-ai/dist/utils/oauth/load.js.map +0 -1
- package/node_modules/@earendil-works/pi-ai/dist/utils/oauth/oauth-page.d.ts.map +0 -1
- package/node_modules/@earendil-works/pi-ai/dist/utils/oauth/oauth-page.js.map +0 -1
- package/node_modules/@earendil-works/pi-ai/dist/utils/oauth/openai-codex.d.ts +0 -45
- package/node_modules/@earendil-works/pi-ai/dist/utils/oauth/openai-codex.d.ts.map +0 -1
- package/node_modules/@earendil-works/pi-ai/dist/utils/oauth/openai-codex.js.map +0 -1
- package/node_modules/@earendil-works/pi-ai/dist/utils/oauth/pkce.d.ts.map +0 -1
- package/node_modules/@earendil-works/pi-ai/dist/utils/oauth/pkce.js.map +0 -1
- package/node_modules/@earendil-works/pi-ai/dist/utils/oauth/radius.d.ts +0 -39
- package/node_modules/@earendil-works/pi-ai/dist/utils/oauth/radius.d.ts.map +0 -1
- package/node_modules/@earendil-works/pi-ai/dist/utils/oauth/radius.js.map +0 -1
- package/node_modules/@earendil-works/pi-ai/dist/utils/oauth/types.d.ts +0 -64
- package/node_modules/@earendil-works/pi-ai/dist/utils/oauth/types.d.ts.map +0 -1
- package/node_modules/@earendil-works/pi-ai/dist/utils/oauth/types.js +0 -2
- package/node_modules/@earendil-works/pi-ai/dist/utils/oauth/types.js.map +0 -1
- /package/node_modules/@earendil-works/pi-ai/dist/{utils → auth}/oauth/device-code.d.ts +0 -0
- /package/node_modules/@earendil-works/pi-ai/dist/{utils → auth}/oauth/device-code.js +0 -0
- /package/node_modules/@earendil-works/pi-ai/dist/{utils → auth}/oauth/oauth-page.d.ts +0 -0
- /package/node_modules/@earendil-works/pi-ai/dist/{utils → auth}/oauth/oauth-page.js +0 -0
- /package/node_modules/@earendil-works/pi-ai/dist/{utils → auth}/oauth/pkce.d.ts +0 -0
- /package/node_modules/@earendil-works/pi-ai/dist/{utils → auth}/oauth/pkce.js +0 -0
|
@@ -1,1012 +1,123 @@
|
|
|
1
|
-
|
|
2
|
-
* Model registry - manages built-in and custom models, provides API key resolution.
|
|
3
|
-
*/
|
|
4
|
-
import { getModels, getProviders, registerApiProvider, resetApiProviders, } from "@earendil-works/pi-ai/compat";
|
|
5
|
-
import { registerOAuthProvider, resetOAuthProviders } from "@earendil-works/pi-ai/oauth";
|
|
6
|
-
import { existsSync, readFileSync } from "fs";
|
|
7
|
-
import { join } from "path";
|
|
8
|
-
import { Type } from "typebox";
|
|
9
|
-
import { Compile } from "typebox/compile";
|
|
1
|
+
import { join } from "node:path";
|
|
10
2
|
import { getAgentDir } from "../config.js";
|
|
11
|
-
import {
|
|
12
|
-
import {
|
|
3
|
+
import { AuthStorage } from "./auth-storage.js";
|
|
4
|
+
import { ModelRuntime as DefaultModelRuntime } from "./model-runtime.js";
|
|
13
5
|
import { BUILT_IN_PROVIDER_DISPLAY_NAMES } from "./provider-display-names.js";
|
|
14
|
-
|
|
15
|
-
import { getConfigValueEnvVarNames, isCommandConfigValue, isConfigValueConfigured, resolveConfigValueOrThrow, resolveConfigValueUncached, resolveHeadersOrThrow, } from "./resolve-config-value.js";
|
|
16
|
-
// Schema for OpenRouter routing preferences
|
|
17
|
-
const PercentileCutoffsSchema = Type.Object({
|
|
18
|
-
p50: Type.Optional(Type.Number()),
|
|
19
|
-
p75: Type.Optional(Type.Number()),
|
|
20
|
-
p90: Type.Optional(Type.Number()),
|
|
21
|
-
p99: Type.Optional(Type.Number()),
|
|
22
|
-
});
|
|
23
|
-
const OpenRouterRoutingSchema = Type.Object({
|
|
24
|
-
allow_fallbacks: Type.Optional(Type.Boolean()),
|
|
25
|
-
require_parameters: Type.Optional(Type.Boolean()),
|
|
26
|
-
data_collection: Type.Optional(Type.Union([Type.Literal("deny"), Type.Literal("allow")])),
|
|
27
|
-
zdr: Type.Optional(Type.Boolean()),
|
|
28
|
-
enforce_distillable_text: Type.Optional(Type.Boolean()),
|
|
29
|
-
order: Type.Optional(Type.Array(Type.String())),
|
|
30
|
-
only: Type.Optional(Type.Array(Type.String())),
|
|
31
|
-
ignore: Type.Optional(Type.Array(Type.String())),
|
|
32
|
-
quantizations: Type.Optional(Type.Array(Type.String())),
|
|
33
|
-
sort: Type.Optional(Type.Union([
|
|
34
|
-
Type.String(),
|
|
35
|
-
Type.Object({
|
|
36
|
-
by: Type.Optional(Type.String()),
|
|
37
|
-
partition: Type.Optional(Type.Union([Type.String(), Type.Null()])),
|
|
38
|
-
}),
|
|
39
|
-
])),
|
|
40
|
-
max_price: Type.Optional(Type.Object({
|
|
41
|
-
prompt: Type.Optional(Type.Union([Type.Number(), Type.String()])),
|
|
42
|
-
completion: Type.Optional(Type.Union([Type.Number(), Type.String()])),
|
|
43
|
-
image: Type.Optional(Type.Union([Type.Number(), Type.String()])),
|
|
44
|
-
audio: Type.Optional(Type.Union([Type.Number(), Type.String()])),
|
|
45
|
-
request: Type.Optional(Type.Union([Type.Number(), Type.String()])),
|
|
46
|
-
})),
|
|
47
|
-
preferred_min_throughput: Type.Optional(Type.Union([Type.Number(), PercentileCutoffsSchema])),
|
|
48
|
-
preferred_max_latency: Type.Optional(Type.Union([Type.Number(), PercentileCutoffsSchema])),
|
|
49
|
-
});
|
|
50
|
-
// Schema for Vercel AI Gateway routing preferences
|
|
51
|
-
const VercelGatewayRoutingSchema = Type.Object({
|
|
52
|
-
only: Type.Optional(Type.Array(Type.String())),
|
|
53
|
-
order: Type.Optional(Type.Array(Type.String())),
|
|
54
|
-
});
|
|
55
|
-
// Schema for thinking level support and provider-specific values
|
|
56
|
-
const ThinkingLevelMapValueSchema = Type.Union([Type.String(), Type.Null()]);
|
|
57
|
-
const ThinkingLevelMapSchema = Type.Object({
|
|
58
|
-
off: Type.Optional(ThinkingLevelMapValueSchema),
|
|
59
|
-
minimal: Type.Optional(ThinkingLevelMapValueSchema),
|
|
60
|
-
low: Type.Optional(ThinkingLevelMapValueSchema),
|
|
61
|
-
medium: Type.Optional(ThinkingLevelMapValueSchema),
|
|
62
|
-
high: Type.Optional(ThinkingLevelMapValueSchema),
|
|
63
|
-
xhigh: Type.Optional(ThinkingLevelMapValueSchema),
|
|
64
|
-
max: Type.Optional(ThinkingLevelMapValueSchema),
|
|
65
|
-
});
|
|
66
|
-
const ChatTemplateKwargScalarSchema = Type.Union([Type.String(), Type.Number(), Type.Boolean(), Type.Null()]);
|
|
67
|
-
const ChatTemplateKwargVariableSchema = Type.Object({
|
|
68
|
-
$var: Type.Union([Type.Literal("thinking.enabled"), Type.Literal("thinking.effort")]),
|
|
69
|
-
omitWhenOff: Type.Optional(Type.Boolean()),
|
|
70
|
-
});
|
|
71
|
-
const ChatTemplateKwargSchema = Type.Union([ChatTemplateKwargScalarSchema, ChatTemplateKwargVariableSchema]);
|
|
72
|
-
const OpenAICompletionsCompatSchema = Type.Object({
|
|
73
|
-
supportsStore: Type.Optional(Type.Boolean()),
|
|
74
|
-
supportsDeveloperRole: Type.Optional(Type.Boolean()),
|
|
75
|
-
supportsReasoningEffort: Type.Optional(Type.Boolean()),
|
|
76
|
-
supportsUsageInStreaming: Type.Optional(Type.Boolean()),
|
|
77
|
-
maxTokensField: Type.Optional(Type.Union([Type.Literal("max_completion_tokens"), Type.Literal("max_tokens")])),
|
|
78
|
-
requiresToolResultName: Type.Optional(Type.Boolean()),
|
|
79
|
-
requiresAssistantAfterToolResult: Type.Optional(Type.Boolean()),
|
|
80
|
-
requiresThinkingAsText: Type.Optional(Type.Boolean()),
|
|
81
|
-
requiresReasoningContentOnAssistantMessages: Type.Optional(Type.Boolean()),
|
|
82
|
-
thinkingFormat: Type.Optional(Type.Union([
|
|
83
|
-
Type.Literal("openai"),
|
|
84
|
-
Type.Literal("openrouter"),
|
|
85
|
-
Type.Literal("together"),
|
|
86
|
-
Type.Literal("deepseek"),
|
|
87
|
-
Type.Literal("zai"),
|
|
88
|
-
Type.Literal("qwen"),
|
|
89
|
-
Type.Literal("chat-template"),
|
|
90
|
-
Type.Literal("qwen-chat-template"),
|
|
91
|
-
Type.Literal("string-thinking"),
|
|
92
|
-
Type.Literal("ant-ling"),
|
|
93
|
-
])),
|
|
94
|
-
chatTemplateKwargs: Type.Optional(Type.Record(Type.String(), ChatTemplateKwargSchema)),
|
|
95
|
-
cacheControlFormat: Type.Optional(Type.Literal("anthropic")),
|
|
96
|
-
openRouterRouting: Type.Optional(OpenRouterRoutingSchema),
|
|
97
|
-
vercelGatewayRouting: Type.Optional(VercelGatewayRoutingSchema),
|
|
98
|
-
supportsStrictMode: Type.Optional(Type.Boolean()),
|
|
99
|
-
toolCallFormat: Type.Optional(Type.Union([
|
|
100
|
-
Type.Literal("anthropic-xml"),
|
|
101
|
-
Type.Literal("hermes"),
|
|
102
|
-
Type.Literal("gemma4"),
|
|
103
|
-
Type.Literal("gemma4-delimiter"),
|
|
104
|
-
Type.Literal("xml"),
|
|
105
|
-
Type.Literal("yaml-xml"),
|
|
106
|
-
])),
|
|
107
|
-
sendSessionAffinityHeaders: Type.Optional(Type.Boolean()),
|
|
108
|
-
sessionAffinityFormat: Type.Optional(Type.Union([Type.Literal("openai"), Type.Literal("openai-nosession"), Type.Literal("openrouter")])),
|
|
109
|
-
supportsLongCacheRetention: Type.Optional(Type.Boolean()),
|
|
110
|
-
});
|
|
111
|
-
const OpenAIResponsesCompatSchema = Type.Object({
|
|
112
|
-
supportsDeveloperRole: Type.Optional(Type.Boolean()),
|
|
113
|
-
sessionAffinityFormat: Type.Optional(Type.Union([Type.Literal("openai"), Type.Literal("openai-nosession"), Type.Literal("openrouter")])),
|
|
114
|
-
supportsLongCacheRetention: Type.Optional(Type.Boolean()),
|
|
115
|
-
supportsWebSocket: Type.Optional(Type.Boolean()),
|
|
116
|
-
supportsWebSearchPreview: Type.Optional(Type.Boolean()),
|
|
117
|
-
supportsToolSearch: Type.Optional(Type.Boolean()),
|
|
118
|
-
});
|
|
119
|
-
const AnthropicMessagesCompatSchema = Type.Object({
|
|
120
|
-
supportsEagerToolInputStreaming: Type.Optional(Type.Boolean()),
|
|
121
|
-
supportsLongCacheRetention: Type.Optional(Type.Boolean()),
|
|
122
|
-
supportsDisabledThinking: Type.Optional(Type.Boolean()),
|
|
123
|
-
sendSessionAffinityHeaders: Type.Optional(Type.Boolean()),
|
|
124
|
-
supportsCacheControlOnTools: Type.Optional(Type.Boolean()),
|
|
125
|
-
supportsToolChoice: Type.Optional(Type.Boolean()),
|
|
126
|
-
supportsForcedToolChoice: Type.Optional(Type.Boolean()),
|
|
127
|
-
forceAdaptiveThinking: Type.Optional(Type.Boolean()),
|
|
128
|
-
supportsToolReferences: Type.Optional(Type.Boolean()),
|
|
129
|
-
});
|
|
130
|
-
const ProviderCompatSchema = Type.Union([
|
|
131
|
-
OpenAICompletionsCompatSchema,
|
|
132
|
-
OpenAIResponsesCompatSchema,
|
|
133
|
-
AnthropicMessagesCompatSchema,
|
|
134
|
-
]);
|
|
135
|
-
const ModelCostRatesSchema = {
|
|
136
|
-
input: Type.Number(),
|
|
137
|
-
output: Type.Number(),
|
|
138
|
-
cacheRead: Type.Number(),
|
|
139
|
-
cacheWrite: Type.Number(),
|
|
140
|
-
};
|
|
141
|
-
const ModelCostTierSchema = Type.Object({
|
|
142
|
-
inputTokensAbove: Type.Number(),
|
|
143
|
-
...ModelCostRatesSchema,
|
|
144
|
-
});
|
|
145
|
-
const ModelCostSchema = Type.Object({
|
|
146
|
-
...ModelCostRatesSchema,
|
|
147
|
-
tiers: Type.Optional(Type.Array(ModelCostTierSchema)),
|
|
148
|
-
});
|
|
149
|
-
// Schema for custom model definition
|
|
150
|
-
// Most fields are optional with sensible defaults for local models (Ollama, LM Studio, etc.)
|
|
151
|
-
const ExtraBodySchema = Type.Record(Type.String(), Type.Unknown());
|
|
152
|
-
const ServiceTierSchema = Type.Union([Type.Literal("auto"), Type.Literal("flex"), Type.Literal("priority")]);
|
|
153
|
-
const CacheRetentionSchema = Type.Union([Type.Literal("none"), Type.Literal("short"), Type.Literal("long")]);
|
|
154
|
-
const ModelDefinitionSchema = Type.Object({
|
|
155
|
-
id: Type.String({ minLength: 1 }),
|
|
156
|
-
name: Type.Optional(Type.String({ minLength: 1 })),
|
|
157
|
-
upstreamModelId: Type.Optional(Type.String({ minLength: 1 })),
|
|
158
|
-
serviceTier: Type.Optional(ServiceTierSchema),
|
|
159
|
-
promptPreset: Type.Optional(Type.String({ minLength: 1 })),
|
|
160
|
-
api: Type.Optional(Type.String({ minLength: 1 })),
|
|
161
|
-
baseUrl: Type.Optional(Type.String({ minLength: 1 })),
|
|
162
|
-
reasoning: Type.Optional(Type.Boolean()),
|
|
163
|
-
thinkingLevelMap: Type.Optional(ThinkingLevelMapSchema),
|
|
164
|
-
input: Type.Optional(Type.Array(Type.Union([Type.Literal("text"), Type.Literal("image"), Type.Literal("video")]))),
|
|
165
|
-
cost: Type.Optional(ModelCostSchema),
|
|
166
|
-
contextWindow: Type.Optional(Type.Number()),
|
|
167
|
-
maxTokens: Type.Optional(Type.Number()),
|
|
168
|
-
headers: Type.Optional(Type.Record(Type.String(), Type.String())),
|
|
169
|
-
extraBody: Type.Optional(ExtraBodySchema),
|
|
170
|
-
cacheRetention: Type.Optional(CacheRetentionSchema),
|
|
171
|
-
compat: Type.Optional(ProviderCompatSchema),
|
|
172
|
-
});
|
|
173
|
-
// Schema for per-model overrides (all fields optional, merged with built-in model)
|
|
174
|
-
const ModelOverrideSchema = Type.Object({
|
|
175
|
-
name: Type.Optional(Type.String({ minLength: 1 })),
|
|
176
|
-
promptPreset: Type.Optional(Type.String({ minLength: 1 })),
|
|
177
|
-
reasoning: Type.Optional(Type.Boolean()),
|
|
178
|
-
thinkingLevelMap: Type.Optional(ThinkingLevelMapSchema),
|
|
179
|
-
thinkingLevelMapMode: Type.Optional(Type.Union([Type.Literal("merge"), Type.Literal("replace")])),
|
|
180
|
-
input: Type.Optional(Type.Array(Type.Union([Type.Literal("text"), Type.Literal("image"), Type.Literal("video")]))),
|
|
181
|
-
cost: Type.Optional(Type.Object({
|
|
182
|
-
input: Type.Optional(Type.Number()),
|
|
183
|
-
output: Type.Optional(Type.Number()),
|
|
184
|
-
cacheRead: Type.Optional(Type.Number()),
|
|
185
|
-
cacheWrite: Type.Optional(Type.Number()),
|
|
186
|
-
tiers: Type.Optional(Type.Array(ModelCostTierSchema)),
|
|
187
|
-
})),
|
|
188
|
-
contextWindow: Type.Optional(Type.Number()),
|
|
189
|
-
maxTokens: Type.Optional(Type.Number()),
|
|
190
|
-
headers: Type.Optional(Type.Record(Type.String(), Type.String())),
|
|
191
|
-
extraBody: Type.Optional(ExtraBodySchema),
|
|
192
|
-
cacheRetention: Type.Optional(CacheRetentionSchema),
|
|
193
|
-
compat: Type.Optional(ProviderCompatSchema),
|
|
194
|
-
});
|
|
195
|
-
const ProviderConfigSchema = Type.Object({
|
|
196
|
-
name: Type.Optional(Type.String({ minLength: 1 })),
|
|
197
|
-
disabled: Type.Optional(Type.Boolean()),
|
|
198
|
-
baseUrl: Type.Optional(Type.String({ minLength: 1 })),
|
|
199
|
-
apiKey: Type.Optional(Type.String({ minLength: 1 })),
|
|
200
|
-
api: Type.Optional(Type.String({ minLength: 1 })),
|
|
201
|
-
/** OAuth flavor spoken by this provider's endpoint. Registers a sign-in
|
|
202
|
-
* provider with a dynamic model catalog (e.g. a custom Radius gateway). */
|
|
203
|
-
oauth: Type.Optional(Type.Literal("radius")),
|
|
204
|
-
headers: Type.Optional(Type.Record(Type.String(), Type.String())),
|
|
205
|
-
extraBody: Type.Optional(ExtraBodySchema),
|
|
206
|
-
cacheRetention: Type.Optional(CacheRetentionSchema),
|
|
207
|
-
compat: Type.Optional(ProviderCompatSchema),
|
|
208
|
-
authHeader: Type.Optional(Type.Boolean()),
|
|
209
|
-
whitelist: Type.Optional(Type.Array(Type.String({ minLength: 1 }))),
|
|
210
|
-
blacklist: Type.Optional(Type.Array(Type.String({ minLength: 1 }))),
|
|
211
|
-
models: Type.Optional(Type.Array(ModelDefinitionSchema)),
|
|
212
|
-
modelOverrides: Type.Optional(Type.Record(Type.String(), ModelOverrideSchema)),
|
|
213
|
-
});
|
|
214
|
-
const ModelsConfigSchema = Type.Object({
|
|
215
|
-
disabledProviders: Type.Optional(Type.Array(Type.String({ minLength: 1 }))),
|
|
216
|
-
providers: Type.Record(Type.String(), ProviderConfigSchema),
|
|
217
|
-
});
|
|
218
|
-
const validateModelsConfig = Compile(ModelsConfigSchema);
|
|
219
|
-
function formatValidationPath(error) {
|
|
220
|
-
if (error.keyword === "required") {
|
|
221
|
-
const requiredProperties = error.params.requiredProperties;
|
|
222
|
-
const requiredProperty = requiredProperties?.[0];
|
|
223
|
-
if (requiredProperty) {
|
|
224
|
-
const basePath = error.instancePath.replace(/^\//, "").replace(/\//g, ".");
|
|
225
|
-
return basePath ? `${basePath}.${requiredProperty}` : requiredProperty;
|
|
226
|
-
}
|
|
227
|
-
}
|
|
228
|
-
const path = error.instancePath.replace(/^\//, "").replace(/\//g, ".");
|
|
229
|
-
return path || "root";
|
|
230
|
-
}
|
|
231
|
-
function emptyCustomModelsResult(error) {
|
|
232
|
-
return {
|
|
233
|
-
models: [],
|
|
234
|
-
overrides: new Map(),
|
|
235
|
-
modelOverrides: new Map(),
|
|
236
|
-
disabledProviders: new Set(),
|
|
237
|
-
modelWhitelists: new Map(),
|
|
238
|
-
modelBlacklists: new Map(),
|
|
239
|
-
error,
|
|
240
|
-
};
|
|
241
|
-
}
|
|
242
|
-
function mergeCompat(baseCompat, overrideCompat) {
|
|
243
|
-
if (!overrideCompat)
|
|
244
|
-
return baseCompat;
|
|
245
|
-
const base = baseCompat;
|
|
246
|
-
const override = overrideCompat;
|
|
247
|
-
const merged = { ...base, ...override };
|
|
248
|
-
const baseCompletions = base;
|
|
249
|
-
const overrideCompletions = override;
|
|
250
|
-
const mergedCompletions = merged;
|
|
251
|
-
if (baseCompletions?.openRouterRouting || overrideCompletions.openRouterRouting) {
|
|
252
|
-
mergedCompletions.openRouterRouting = {
|
|
253
|
-
...baseCompletions?.openRouterRouting,
|
|
254
|
-
...overrideCompletions.openRouterRouting,
|
|
255
|
-
};
|
|
256
|
-
}
|
|
257
|
-
if (baseCompletions?.vercelGatewayRouting || overrideCompletions.vercelGatewayRouting) {
|
|
258
|
-
mergedCompletions.vercelGatewayRouting = {
|
|
259
|
-
...baseCompletions?.vercelGatewayRouting,
|
|
260
|
-
...overrideCompletions.vercelGatewayRouting,
|
|
261
|
-
};
|
|
262
|
-
}
|
|
263
|
-
if (baseCompletions?.chatTemplateKwargs || overrideCompletions.chatTemplateKwargs) {
|
|
264
|
-
mergedCompletions.chatTemplateKwargs = {
|
|
265
|
-
...baseCompletions?.chatTemplateKwargs,
|
|
266
|
-
...overrideCompletions.chatTemplateKwargs,
|
|
267
|
-
};
|
|
268
|
-
}
|
|
269
|
-
return merged;
|
|
270
|
-
}
|
|
271
|
-
/**
|
|
272
|
-
* Deep merge a model override into a model.
|
|
273
|
-
* Handles nested objects (cost, compat) by merging rather than replacing.
|
|
274
|
-
*/
|
|
275
|
-
function applyModelOverride(model, override) {
|
|
276
|
-
const modelWithConfigMetadata = model;
|
|
277
|
-
const result = { ...modelWithConfigMetadata };
|
|
278
|
-
// Simple field overrides
|
|
279
|
-
if (override.name !== undefined)
|
|
280
|
-
result.name = override.name;
|
|
281
|
-
if (override.promptPreset !== undefined)
|
|
282
|
-
result.promptPreset = override.promptPreset;
|
|
283
|
-
if (override.reasoning !== undefined)
|
|
284
|
-
result.reasoning = override.reasoning;
|
|
285
|
-
if (override.thinkingLevelMap !== undefined) {
|
|
286
|
-
result.thinkingLevelMap =
|
|
287
|
-
override.thinkingLevelMapMode === "replace"
|
|
288
|
-
? { ...override.thinkingLevelMap }
|
|
289
|
-
: { ...modelWithConfigMetadata.thinkingLevelMap, ...override.thinkingLevelMap };
|
|
290
|
-
}
|
|
291
|
-
if (override.input !== undefined)
|
|
292
|
-
result.input = override.input;
|
|
293
|
-
if (override.contextWindow !== undefined)
|
|
294
|
-
result.contextWindow = override.contextWindow;
|
|
295
|
-
if (override.maxTokens !== undefined)
|
|
296
|
-
result.maxTokens = override.maxTokens;
|
|
297
|
-
if (override.cacheRetention !== undefined)
|
|
298
|
-
result.cacheRetention = override.cacheRetention;
|
|
299
|
-
// Merge cost (partial override)
|
|
300
|
-
if (override.cost) {
|
|
301
|
-
result.cost = {
|
|
302
|
-
input: override.cost.input ?? model.cost.input,
|
|
303
|
-
output: override.cost.output ?? model.cost.output,
|
|
304
|
-
cacheRead: override.cost.cacheRead ?? model.cost.cacheRead,
|
|
305
|
-
cacheWrite: override.cost.cacheWrite ?? model.cost.cacheWrite,
|
|
306
|
-
tiers: override.cost.tiers ?? model.cost.tiers,
|
|
307
|
-
};
|
|
308
|
-
}
|
|
309
|
-
// Deep merge compat
|
|
310
|
-
result.compat = mergeCompat(model.compat, override.compat);
|
|
311
|
-
return result;
|
|
312
|
-
}
|
|
6
|
+
export { clearApiKeyCache } from "./provider-composer.js";
|
|
313
7
|
/**
|
|
314
|
-
*
|
|
8
|
+
* Synchronous compatibility facade exposed to extensions.
|
|
9
|
+
* Coding-agent internals use ModelRuntime directly.
|
|
315
10
|
*/
|
|
316
11
|
export class ModelRegistry {
|
|
317
|
-
constructor(
|
|
318
|
-
this.
|
|
319
|
-
this.providerRequestConfigs = new Map();
|
|
320
|
-
this.modelRequestHeaders = new Map();
|
|
321
|
-
this.modelRequestExtraBody = new Map();
|
|
322
|
-
this.modelRequestUpstreamIds = new Map();
|
|
323
|
-
this.modelRequestServiceTiers = new Map();
|
|
324
|
-
this.configModelOverrides = new Map();
|
|
325
|
-
this.registeredProviders = new Map();
|
|
326
|
-
this.loadError = undefined;
|
|
12
|
+
constructor(runtime, authStorage = AuthStorage.inMemory()) {
|
|
13
|
+
this.runtime = runtime;
|
|
327
14
|
this.authStorage = authStorage;
|
|
328
|
-
this.modelsJsonPath = modelsJsonPath ? normalizePath(modelsJsonPath) : undefined;
|
|
329
|
-
this.loadModels();
|
|
330
15
|
}
|
|
331
16
|
static create(authStorage, modelsJsonPath = join(getAgentDir(), "models.json")) {
|
|
332
|
-
return new ModelRegistry(authStorage, modelsJsonPath);
|
|
17
|
+
return new ModelRegistry(DefaultModelRuntime.createSync({ credentials: authStorage, modelsPath: modelsJsonPath }), authStorage);
|
|
333
18
|
}
|
|
334
19
|
static inMemory(authStorage) {
|
|
335
|
-
return new ModelRegistry(authStorage,
|
|
20
|
+
return new ModelRegistry(DefaultModelRuntime.createSync({ credentials: authStorage, modelsPath: null }), authStorage);
|
|
336
21
|
}
|
|
337
|
-
|
|
338
|
-
|
|
339
|
-
|
|
22
|
+
get modelRuntime() {
|
|
23
|
+
return this.runtime;
|
|
24
|
+
}
|
|
25
|
+
/** Reload models.json asynchronously. Await before making synchronous registry reads. */
|
|
340
26
|
refresh() {
|
|
341
|
-
this.
|
|
342
|
-
this.modelRequestHeaders.clear();
|
|
343
|
-
this.modelRequestExtraBody.clear();
|
|
344
|
-
this.modelRequestUpstreamIds.clear();
|
|
345
|
-
this.modelRequestServiceTiers.clear();
|
|
346
|
-
this.loadError = undefined;
|
|
347
|
-
// Ensure dynamic API/OAuth registrations are rebuilt from current provider state.
|
|
348
|
-
resetApiProviders();
|
|
349
|
-
resetOAuthProviders();
|
|
350
|
-
this.loadModels();
|
|
351
|
-
for (const [providerName, config] of this.registeredProviders.entries()) {
|
|
352
|
-
this.applyProviderConfig(providerName, config);
|
|
353
|
-
}
|
|
27
|
+
return this.runtime.reloadConfig();
|
|
354
28
|
}
|
|
355
|
-
/**
|
|
356
|
-
* Get any error from loading models.json (undefined if no error).
|
|
357
|
-
*/
|
|
358
29
|
getError() {
|
|
359
|
-
return this.
|
|
30
|
+
return this.runtime.getError();
|
|
360
31
|
}
|
|
361
|
-
|
|
362
|
-
|
|
363
|
-
const { models: customModels, overrides, modelOverrides, disabledProviders, modelWhitelists, modelBlacklists, error, } = this.modelsJsonPath ? this.loadCustomModels(this.modelsJsonPath) : emptyCustomModelsResult();
|
|
364
|
-
this.configModelOverrides = modelOverrides;
|
|
365
|
-
if (error) {
|
|
366
|
-
this.loadError = error;
|
|
367
|
-
// Keep built-in models even if custom models failed to load
|
|
368
|
-
}
|
|
369
|
-
const builtInModels = this.loadBuiltInModels(overrides, modelOverrides, disabledProviders, modelWhitelists, modelBlacklists);
|
|
370
|
-
let combined = this.mergeCustomModels(builtInModels, customModels);
|
|
371
|
-
// Let OAuth providers modify their models (e.g., update baseUrl)
|
|
372
|
-
for (const oauthProvider of this.authStorage.getOAuthProviders()) {
|
|
373
|
-
const cred = this.authStorage.get(oauthProvider.id);
|
|
374
|
-
if (cred?.type === "oauth" && oauthProvider.modifyModels) {
|
|
375
|
-
combined = oauthProvider.modifyModels(combined, cred);
|
|
376
|
-
}
|
|
377
|
-
}
|
|
378
|
-
this.models = combined;
|
|
32
|
+
getAll() {
|
|
33
|
+
return [...this.runtime.getModels()];
|
|
379
34
|
}
|
|
380
|
-
|
|
381
|
-
|
|
382
|
-
|
|
383
|
-
|
|
35
|
+
getAvailable() {
|
|
36
|
+
if (this.runtime.hasAvailabilitySnapshot()) {
|
|
37
|
+
return [...this.runtime.getAvailableSnapshot()];
|
|
38
|
+
}
|
|
39
|
+
return this.runtime.getProviders().flatMap((provider) => {
|
|
40
|
+
if (!this.authStorage.hasAuth(provider.id) && !this.runtime.getProviderAuthStatus(provider.id).configured) {
|
|
384
41
|
return [];
|
|
385
42
|
}
|
|
386
|
-
const models = getModels(provider);
|
|
387
|
-
|
|
388
|
-
const perModelOverrides = modelOverrides.get(provider);
|
|
389
|
-
const whitelist = modelWhitelists.get(provider);
|
|
390
|
-
const blacklist = modelBlacklists.get(provider);
|
|
391
|
-
return models.flatMap((m) => {
|
|
392
|
-
if (whitelist && !whitelist.has(m.id))
|
|
393
|
-
return [];
|
|
394
|
-
if (blacklist?.has(m.id))
|
|
395
|
-
return [];
|
|
396
|
-
let model = m;
|
|
397
|
-
// Apply provider-level baseUrl/headers/compat override
|
|
398
|
-
if (providerOverride) {
|
|
399
|
-
model = {
|
|
400
|
-
...model,
|
|
401
|
-
baseUrl: providerOverride.baseUrl ?? model.baseUrl,
|
|
402
|
-
compat: mergeCompat(model.compat, providerOverride.compat),
|
|
403
|
-
cacheRetention: model.cacheRetention ?? providerOverride.cacheRetention,
|
|
404
|
-
};
|
|
405
|
-
}
|
|
406
|
-
// Apply per-model override
|
|
407
|
-
const modelOverride = perModelOverrides?.get(m.id);
|
|
408
|
-
if (modelOverride) {
|
|
409
|
-
model = applyModelOverride(model, modelOverride);
|
|
410
|
-
}
|
|
411
|
-
return [model];
|
|
412
|
-
});
|
|
43
|
+
const models = this.runtime.getModels(provider.id);
|
|
44
|
+
return [...(provider.filterModels?.(models, this.authStorage.get(provider.id)) ?? models)];
|
|
413
45
|
});
|
|
414
46
|
}
|
|
415
|
-
getConfiguredModelOverride(providerName, modelId) {
|
|
416
|
-
return this.configModelOverrides.get(providerName)?.get(modelId);
|
|
417
|
-
}
|
|
418
|
-
applyConfiguredModelOverride(providerName, model) {
|
|
419
|
-
const modelOverride = this.getConfiguredModelOverride(providerName, model.id);
|
|
420
|
-
return modelOverride ? applyModelOverride(model, modelOverride) : model;
|
|
421
|
-
}
|
|
422
|
-
/** Merge custom models into built-in list by provider+id (custom wins on conflicts). */
|
|
423
|
-
mergeCustomModels(builtInModels, customModels) {
|
|
424
|
-
const merged = [...builtInModels];
|
|
425
|
-
for (const customModel of customModels) {
|
|
426
|
-
const existingIndex = merged.findIndex((m) => m.provider === customModel.provider && m.id === customModel.id);
|
|
427
|
-
if (existingIndex >= 0) {
|
|
428
|
-
merged[existingIndex] = customModel;
|
|
429
|
-
}
|
|
430
|
-
else {
|
|
431
|
-
merged.push(customModel);
|
|
432
|
-
}
|
|
433
|
-
}
|
|
434
|
-
return merged;
|
|
435
|
-
}
|
|
436
|
-
loadCustomModels(modelsJsonPath) {
|
|
437
|
-
if (!existsSync(modelsJsonPath)) {
|
|
438
|
-
return emptyCustomModelsResult();
|
|
439
|
-
}
|
|
440
|
-
try {
|
|
441
|
-
const content = readFileSync(modelsJsonPath, "utf-8");
|
|
442
|
-
const parsed = JSON.parse(stripJsonComments(content));
|
|
443
|
-
if (!validateModelsConfig.Check(parsed)) {
|
|
444
|
-
const errors = validateModelsConfig
|
|
445
|
-
.Errors(parsed)
|
|
446
|
-
.map((error) => ` - ${formatValidationPath(error)}: ${error.message}`)
|
|
447
|
-
.join("\n") || "Unknown schema error";
|
|
448
|
-
return emptyCustomModelsResult(`Invalid models.json schema:\n${errors}\n\nFile: ${modelsJsonPath}`);
|
|
449
|
-
}
|
|
450
|
-
const config = parsed;
|
|
451
|
-
// Additional validation
|
|
452
|
-
this.validateConfig(config);
|
|
453
|
-
const overrides = new Map();
|
|
454
|
-
const modelOverrides = new Map();
|
|
455
|
-
const disabledProviders = new Set(config.disabledProviders ?? []);
|
|
456
|
-
const modelWhitelists = new Map();
|
|
457
|
-
const modelBlacklists = new Map();
|
|
458
|
-
for (const [providerName, providerConfig] of Object.entries(config.providers)) {
|
|
459
|
-
if (providerConfig.disabled) {
|
|
460
|
-
disabledProviders.add(providerName);
|
|
461
|
-
}
|
|
462
|
-
if (providerConfig.whitelist) {
|
|
463
|
-
modelWhitelists.set(providerName, new Set(providerConfig.whitelist));
|
|
464
|
-
}
|
|
465
|
-
if (providerConfig.blacklist) {
|
|
466
|
-
modelBlacklists.set(providerName, new Set(providerConfig.blacklist));
|
|
467
|
-
}
|
|
468
|
-
if (providerConfig.baseUrl || providerConfig.compat || providerConfig.cacheRetention) {
|
|
469
|
-
overrides.set(providerName, {
|
|
470
|
-
baseUrl: providerConfig.baseUrl,
|
|
471
|
-
compat: providerConfig.compat,
|
|
472
|
-
cacheRetention: providerConfig.cacheRetention,
|
|
473
|
-
});
|
|
474
|
-
}
|
|
475
|
-
if (providerConfig.oauth === "radius") {
|
|
476
|
-
// Must run before the modifyModels loop in loadModels() so the
|
|
477
|
-
// credential-cached catalog is injected on this load.
|
|
478
|
-
registerCustomRadiusOAuthProvider(providerName, providerConfig.name, providerConfig.baseUrl);
|
|
479
|
-
}
|
|
480
|
-
this.storeProviderRequestConfig(providerName, providerConfig);
|
|
481
|
-
if (providerConfig.modelOverrides) {
|
|
482
|
-
modelOverrides.set(providerName, new Map(Object.entries(providerConfig.modelOverrides)));
|
|
483
|
-
for (const [modelId, modelOverride] of Object.entries(providerConfig.modelOverrides)) {
|
|
484
|
-
this.storeModelHeaders(providerName, modelId, modelOverride.headers);
|
|
485
|
-
this.storeModelExtraBody(providerName, modelId, modelOverride.extraBody);
|
|
486
|
-
}
|
|
487
|
-
}
|
|
488
|
-
}
|
|
489
|
-
return {
|
|
490
|
-
models: this.parseModels(config, disabledProviders, modelWhitelists, modelBlacklists),
|
|
491
|
-
overrides,
|
|
492
|
-
modelOverrides,
|
|
493
|
-
disabledProviders,
|
|
494
|
-
modelWhitelists,
|
|
495
|
-
modelBlacklists,
|
|
496
|
-
error: undefined,
|
|
497
|
-
};
|
|
498
|
-
}
|
|
499
|
-
catch (error) {
|
|
500
|
-
if (error instanceof SyntaxError) {
|
|
501
|
-
return emptyCustomModelsResult(`Failed to parse models.json: ${error.message}\n\nFile: ${modelsJsonPath}`);
|
|
502
|
-
}
|
|
503
|
-
return emptyCustomModelsResult(`Failed to load models.json: ${error instanceof Error ? error.message : error}\n\nFile: ${modelsJsonPath}`);
|
|
504
|
-
}
|
|
505
|
-
}
|
|
506
|
-
validateConfig(config) {
|
|
507
|
-
const builtInProviders = new Set(getProviders());
|
|
508
|
-
for (const [providerName, providerConfig] of Object.entries(config.providers)) {
|
|
509
|
-
if (providerConfig.disabled)
|
|
510
|
-
continue;
|
|
511
|
-
const isBuiltIn = builtInProviders.has(providerName);
|
|
512
|
-
const hasProviderApi = !!providerConfig.api;
|
|
513
|
-
const models = providerConfig.models ?? [];
|
|
514
|
-
const hasModelOverrides = providerConfig.modelOverrides && Object.keys(providerConfig.modelOverrides).length > 0;
|
|
515
|
-
if (providerConfig.oauth && !providerConfig.baseUrl) {
|
|
516
|
-
throw new Error(`Provider ${providerName}: "baseUrl" is required when "oauth" is set.`);
|
|
517
|
-
}
|
|
518
|
-
if (models.length === 0 && !providerConfig.oauth) {
|
|
519
|
-
// Override-only config: needs baseUrl, headers, compat, modelOverrides, extraBody, or some combination.
|
|
520
|
-
if (!providerConfig.baseUrl &&
|
|
521
|
-
!providerConfig.headers &&
|
|
522
|
-
!providerConfig.compat &&
|
|
523
|
-
!providerConfig.cacheRetention &&
|
|
524
|
-
!hasModelOverrides &&
|
|
525
|
-
!providerConfig.extraBody &&
|
|
526
|
-
!providerConfig.whitelist &&
|
|
527
|
-
!providerConfig.blacklist) {
|
|
528
|
-
throw new Error(`Provider ${providerName}: must specify "baseUrl", "headers", "compat", "cacheRetention", "modelOverrides", "extraBody", "whitelist", "blacklist", or "models".`);
|
|
529
|
-
}
|
|
530
|
-
}
|
|
531
|
-
else if (!isBuiltIn) {
|
|
532
|
-
// Non-built-in providers with custom models require an endpoint.
|
|
533
|
-
// Auth can come from auth.json, --api-key, or provider request config.
|
|
534
|
-
if (!providerConfig.baseUrl) {
|
|
535
|
-
throw new Error(`Provider ${providerName}: "baseUrl" is required when defining custom models.`);
|
|
536
|
-
}
|
|
537
|
-
}
|
|
538
|
-
// Built-in providers with custom models: baseUrl/apiKey/api are optional,
|
|
539
|
-
// inherited from built-in models. Auth comes from env vars / auth storage.
|
|
540
|
-
for (const modelDef of models) {
|
|
541
|
-
const hasModelApi = !!modelDef.api;
|
|
542
|
-
if (!hasProviderApi && !hasModelApi && !isBuiltIn) {
|
|
543
|
-
throw new Error(`Provider ${providerName}, model ${modelDef.id}: no "api" specified. Set at provider or model level.`);
|
|
544
|
-
}
|
|
545
|
-
// For built-in providers, api is optional — inherited from built-in models.
|
|
546
|
-
if (!modelDef.id)
|
|
547
|
-
throw new Error(`Provider ${providerName}: model missing "id"`);
|
|
548
|
-
// Validate contextWindow/maxTokens only if provided (they have defaults)
|
|
549
|
-
if (modelDef.contextWindow !== undefined && modelDef.contextWindow <= 0)
|
|
550
|
-
throw new Error(`Provider ${providerName}, model ${modelDef.id}: invalid contextWindow`);
|
|
551
|
-
if (modelDef.maxTokens !== undefined && modelDef.maxTokens <= 0)
|
|
552
|
-
throw new Error(`Provider ${providerName}, model ${modelDef.id}: invalid maxTokens`);
|
|
553
|
-
}
|
|
554
|
-
}
|
|
555
|
-
}
|
|
556
|
-
parseModels(config, disabledProviders, modelWhitelists, modelBlacklists) {
|
|
557
|
-
const models = [];
|
|
558
|
-
const builtInProviders = new Set(getProviders());
|
|
559
|
-
// Cache built-in defaults (api, baseUrl) per provider, extracted from first model.
|
|
560
|
-
const builtInDefaultsCache = new Map();
|
|
561
|
-
const getBuiltInDefaults = (providerName) => {
|
|
562
|
-
if (!builtInProviders.has(providerName))
|
|
563
|
-
return undefined;
|
|
564
|
-
if (builtInDefaultsCache.has(providerName))
|
|
565
|
-
return builtInDefaultsCache.get(providerName);
|
|
566
|
-
const builtIn = getModels(providerName);
|
|
567
|
-
if (builtIn.length === 0)
|
|
568
|
-
return undefined;
|
|
569
|
-
const defaults = { api: builtIn[0].api, baseUrl: builtIn[0].baseUrl };
|
|
570
|
-
builtInDefaultsCache.set(providerName, defaults);
|
|
571
|
-
return defaults;
|
|
572
|
-
};
|
|
573
|
-
for (const [providerName, providerConfig] of Object.entries(config.providers)) {
|
|
574
|
-
if (disabledProviders.has(providerName))
|
|
575
|
-
continue;
|
|
576
|
-
const modelDefs = providerConfig.models ?? [];
|
|
577
|
-
if (modelDefs.length === 0)
|
|
578
|
-
continue; // Override-only, no custom models
|
|
579
|
-
const builtInDefaults = getBuiltInDefaults(providerName);
|
|
580
|
-
const whitelist = modelWhitelists.get(providerName);
|
|
581
|
-
const blacklist = modelBlacklists.get(providerName);
|
|
582
|
-
for (const modelDef of modelDefs) {
|
|
583
|
-
if (whitelist && !whitelist.has(modelDef.id))
|
|
584
|
-
continue;
|
|
585
|
-
if (blacklist?.has(modelDef.id))
|
|
586
|
-
continue;
|
|
587
|
-
const api = modelDef.api ?? providerConfig.api ?? builtInDefaults?.api;
|
|
588
|
-
if (!api)
|
|
589
|
-
continue;
|
|
590
|
-
const baseUrl = modelDef.baseUrl ?? providerConfig.baseUrl ?? builtInDefaults?.baseUrl;
|
|
591
|
-
if (!baseUrl)
|
|
592
|
-
continue;
|
|
593
|
-
const compat = mergeCompat(providerConfig.compat, modelDef.compat);
|
|
594
|
-
this.storeModelHeaders(providerName, modelDef.id, modelDef.headers);
|
|
595
|
-
this.storeModelExtraBody(providerName, modelDef.id, modelDef.extraBody);
|
|
596
|
-
this.storeModelUpstreamId(providerName, modelDef.id, modelDef.upstreamModelId);
|
|
597
|
-
this.storeModelServiceTier(providerName, modelDef.id, modelDef.serviceTier);
|
|
598
|
-
const defaultCost = { input: 0, output: 0, cacheRead: 0, cacheWrite: 0 };
|
|
599
|
-
models.push({
|
|
600
|
-
id: modelDef.id,
|
|
601
|
-
name: modelDef.name ?? modelDef.id,
|
|
602
|
-
promptPreset: modelDef.promptPreset,
|
|
603
|
-
api: api,
|
|
604
|
-
provider: providerName,
|
|
605
|
-
baseUrl,
|
|
606
|
-
reasoning: modelDef.reasoning ?? false,
|
|
607
|
-
cacheRetention: modelDef.cacheRetention ?? providerConfig.cacheRetention,
|
|
608
|
-
thinkingLevelMap: modelDef.thinkingLevelMap,
|
|
609
|
-
input: (modelDef.input ?? ["text"]),
|
|
610
|
-
cost: modelDef.cost ?? defaultCost,
|
|
611
|
-
contextWindow: modelDef.contextWindow ?? 128000,
|
|
612
|
-
maxTokens: modelDef.maxTokens ?? 16384,
|
|
613
|
-
headers: undefined,
|
|
614
|
-
compat,
|
|
615
|
-
});
|
|
616
|
-
}
|
|
617
|
-
}
|
|
618
|
-
return models;
|
|
619
|
-
}
|
|
620
|
-
/**
|
|
621
|
-
* Get all models (built-in + custom).
|
|
622
|
-
* If models.json had errors, returns only built-in models.
|
|
623
|
-
*/
|
|
624
|
-
getAll() {
|
|
625
|
-
return this.models;
|
|
626
|
-
}
|
|
627
|
-
/**
|
|
628
|
-
* Get only models that have auth configured.
|
|
629
|
-
* This is a fast check that doesn't refresh OAuth tokens.
|
|
630
|
-
*/
|
|
631
|
-
getAvailable() {
|
|
632
|
-
return this.models.filter((m) => this.hasConfiguredAuth(m));
|
|
633
|
-
}
|
|
634
|
-
/**
|
|
635
|
-
* Find a model by provider and ID.
|
|
636
|
-
*/
|
|
637
47
|
find(provider, modelId) {
|
|
638
|
-
return this.
|
|
639
|
-
}
|
|
640
|
-
getUpstreamModelId(model) {
|
|
641
|
-
return this.modelRequestUpstreamIds.get(this.getModelRequestKey(model.provider, model.id));
|
|
48
|
+
return this.runtime.getModel(provider, modelId);
|
|
642
49
|
}
|
|
643
|
-
/**
|
|
644
|
-
* Get API key for a model.
|
|
645
|
-
*/
|
|
646
50
|
hasConfiguredAuth(model) {
|
|
647
|
-
|
|
648
|
-
return (this.authStorage.hasAuth(model.provider) ||
|
|
649
|
-
(providerApiKey !== undefined && isConfigValueConfigured(providerApiKey)));
|
|
650
|
-
}
|
|
651
|
-
getModelRequestKey(provider, modelId) {
|
|
652
|
-
return `${provider}:${modelId}`;
|
|
653
|
-
}
|
|
654
|
-
storeProviderRequestConfig(providerName, config, preservedApiKey) {
|
|
655
|
-
const apiKey = config.apiKey ?? preservedApiKey;
|
|
656
|
-
if (!apiKey && !config.headers && !config.extraBody && config.authHeader !== true) {
|
|
657
|
-
this.providerRequestConfigs.delete(providerName);
|
|
658
|
-
return;
|
|
659
|
-
}
|
|
660
|
-
this.providerRequestConfigs.set(providerName, {
|
|
661
|
-
apiKey,
|
|
662
|
-
headers: config.headers,
|
|
663
|
-
extraBody: config.extraBody,
|
|
664
|
-
authHeader: config.authHeader,
|
|
665
|
-
});
|
|
666
|
-
}
|
|
667
|
-
storeModelHeaders(providerName, modelId, headers) {
|
|
668
|
-
const key = this.getModelRequestKey(providerName, modelId);
|
|
669
|
-
if (!headers || Object.keys(headers).length === 0) {
|
|
670
|
-
this.modelRequestHeaders.delete(key);
|
|
671
|
-
return;
|
|
672
|
-
}
|
|
673
|
-
this.modelRequestHeaders.set(key, headers);
|
|
674
|
-
}
|
|
675
|
-
storeModelExtraBody(providerName, modelId, extraBody) {
|
|
676
|
-
const key = this.getModelRequestKey(providerName, modelId);
|
|
677
|
-
if (!extraBody || Object.keys(extraBody).length === 0) {
|
|
678
|
-
this.modelRequestExtraBody.delete(key);
|
|
679
|
-
return;
|
|
680
|
-
}
|
|
681
|
-
this.modelRequestExtraBody.set(key, extraBody);
|
|
51
|
+
return this.authStorage.hasAuth(model.provider) || this.runtime.getProviderAuthStatus(model.provider).configured;
|
|
682
52
|
}
|
|
683
|
-
|
|
684
|
-
|
|
685
|
-
if (!upstreamModelId) {
|
|
686
|
-
this.modelRequestUpstreamIds.delete(key);
|
|
687
|
-
return;
|
|
688
|
-
}
|
|
689
|
-
this.modelRequestUpstreamIds.set(key, upstreamModelId);
|
|
690
|
-
}
|
|
691
|
-
storeModelServiceTier(providerName, modelId, serviceTier) {
|
|
692
|
-
const key = this.getModelRequestKey(providerName, modelId);
|
|
693
|
-
if (!serviceTier) {
|
|
694
|
-
this.modelRequestServiceTiers.delete(key);
|
|
695
|
-
return;
|
|
696
|
-
}
|
|
697
|
-
this.modelRequestServiceTiers.set(key, serviceTier);
|
|
698
|
-
}
|
|
699
|
-
clearModelRequestConfigForProvider(providerName) {
|
|
700
|
-
const prefix = `${providerName}:`;
|
|
701
|
-
for (const key of this.modelRequestHeaders.keys()) {
|
|
702
|
-
if (key.startsWith(prefix)) {
|
|
703
|
-
this.modelRequestHeaders.delete(key);
|
|
704
|
-
}
|
|
705
|
-
}
|
|
706
|
-
for (const key of this.modelRequestExtraBody.keys()) {
|
|
707
|
-
if (key.startsWith(prefix)) {
|
|
708
|
-
this.modelRequestExtraBody.delete(key);
|
|
709
|
-
}
|
|
710
|
-
}
|
|
711
|
-
for (const key of this.modelRequestUpstreamIds.keys()) {
|
|
712
|
-
if (key.startsWith(prefix)) {
|
|
713
|
-
this.modelRequestUpstreamIds.delete(key);
|
|
714
|
-
}
|
|
715
|
-
}
|
|
716
|
-
for (const key of this.modelRequestServiceTiers.keys()) {
|
|
717
|
-
if (key.startsWith(prefix)) {
|
|
718
|
-
this.modelRequestServiceTiers.delete(key);
|
|
719
|
-
}
|
|
720
|
-
}
|
|
53
|
+
getUpstreamModelId(model) {
|
|
54
|
+
return this.runtime.getCompatibilityRequestConfig(model).upstreamModelId;
|
|
721
55
|
}
|
|
722
|
-
/**
|
|
723
|
-
* Get API key and request headers for a model.
|
|
724
|
-
*/
|
|
725
56
|
async getApiKeyAndHeaders(model) {
|
|
726
57
|
try {
|
|
727
|
-
const
|
|
728
|
-
const
|
|
729
|
-
|
|
730
|
-
|
|
731
|
-
(providerConfig?.apiKey
|
|
732
|
-
? resolveConfigValueOrThrow(providerConfig.apiKey, `API key for provider "${model.provider}"`, providerEnv)
|
|
733
|
-
: undefined);
|
|
734
|
-
const modelRequestKey = this.getModelRequestKey(model.provider, model.id);
|
|
735
|
-
const providerHeaders = resolveHeadersOrThrow(providerConfig?.headers, `provider "${model.provider}"`, providerEnv);
|
|
736
|
-
const modelHeaders = resolveHeadersOrThrow(this.modelRequestHeaders.get(modelRequestKey), `model "${model.provider}/${model.id}"`, providerEnv);
|
|
737
|
-
let headers = model.headers || providerHeaders || modelHeaders
|
|
738
|
-
? { ...model.headers, ...providerHeaders, ...modelHeaders }
|
|
739
|
-
: undefined;
|
|
740
|
-
if (providerConfig?.authHeader) {
|
|
741
|
-
if (!apiKey) {
|
|
58
|
+
const resolution = await this.runtime.getAuth(model);
|
|
59
|
+
const compatibility = this.runtime.getCompatibilityRequestConfig(model, resolution?.env);
|
|
60
|
+
if (!resolution) {
|
|
61
|
+
if (compatibility.authHeader) {
|
|
742
62
|
return { ok: false, error: `No API key found for "${model.provider}"` };
|
|
743
63
|
}
|
|
744
|
-
headers =
|
|
745
|
-
|
|
746
|
-
|
|
747
|
-
|
|
748
|
-
const extraBody = providerExtraBody || modelExtraBody ? { ...providerExtraBody, ...modelExtraBody } : undefined;
|
|
749
|
-
const upstreamModelId = this.modelRequestUpstreamIds.get(modelRequestKey);
|
|
750
|
-
const serviceTier = this.modelRequestServiceTiers.get(modelRequestKey);
|
|
751
|
-
const resolved = { ok: true };
|
|
752
|
-
if (apiKey !== undefined) {
|
|
753
|
-
resolved.apiKey = apiKey;
|
|
754
|
-
}
|
|
755
|
-
if (headers && Object.keys(headers).length > 0) {
|
|
756
|
-
resolved.headers = headers;
|
|
757
|
-
}
|
|
758
|
-
if (extraBody && Object.keys(extraBody).length > 0) {
|
|
759
|
-
resolved.extraBody = extraBody;
|
|
760
|
-
}
|
|
761
|
-
if (upstreamModelId !== undefined) {
|
|
762
|
-
resolved.upstreamModelId = upstreamModelId;
|
|
763
|
-
}
|
|
764
|
-
if (serviceTier !== undefined) {
|
|
765
|
-
resolved.serviceTier = serviceTier;
|
|
766
|
-
}
|
|
767
|
-
if (providerEnv && Object.keys(providerEnv).length > 0) {
|
|
768
|
-
resolved.env = providerEnv;
|
|
64
|
+
const headers = compatibility.headers
|
|
65
|
+
? Object.fromEntries(Object.entries(compatibility.headers).filter((entry) => entry[1] !== null))
|
|
66
|
+
: undefined;
|
|
67
|
+
return { ok: true, headers, extraBody: compatibility.extraBody };
|
|
769
68
|
}
|
|
770
|
-
|
|
69
|
+
const headers = resolution.auth.headers
|
|
70
|
+
? Object.fromEntries(Object.entries(resolution.auth.headers).filter((entry) => entry[1] !== null))
|
|
71
|
+
: undefined;
|
|
72
|
+
return {
|
|
73
|
+
ok: true,
|
|
74
|
+
apiKey: resolution.auth.apiKey,
|
|
75
|
+
headers,
|
|
76
|
+
extraBody: compatibility.extraBody,
|
|
77
|
+
upstreamModelId: compatibility.upstreamModelId,
|
|
78
|
+
serviceTier: compatibility.serviceTier,
|
|
79
|
+
env: resolution.env,
|
|
80
|
+
};
|
|
771
81
|
}
|
|
772
82
|
catch (error) {
|
|
83
|
+
const cause = error instanceof Error ? error.cause : undefined;
|
|
84
|
+
const message = cause instanceof Error ? cause.message : error instanceof Error ? error.message : String(error);
|
|
773
85
|
return {
|
|
774
86
|
ok: false,
|
|
775
|
-
error:
|
|
87
|
+
error: message === "authHeader requires a resolved API key"
|
|
88
|
+
? `No API key found for "${model.provider}"`
|
|
89
|
+
: message,
|
|
776
90
|
};
|
|
777
91
|
}
|
|
778
92
|
}
|
|
779
|
-
/**
|
|
780
|
-
* Return auth status for a provider, including request auth configured in models.json.
|
|
781
|
-
* This intentionally does not execute command-backed config values.
|
|
782
|
-
*/
|
|
783
93
|
getProviderAuthStatus(provider) {
|
|
784
|
-
|
|
785
|
-
if (authStatus.source) {
|
|
786
|
-
return authStatus;
|
|
787
|
-
}
|
|
788
|
-
const providerApiKey = this.providerRequestConfigs.get(provider)?.apiKey;
|
|
789
|
-
if (!providerApiKey) {
|
|
790
|
-
return authStatus;
|
|
791
|
-
}
|
|
792
|
-
if (isCommandConfigValue(providerApiKey)) {
|
|
793
|
-
return { configured: true, source: "models_json_command" };
|
|
794
|
-
}
|
|
795
|
-
const envVarNames = getConfigValueEnvVarNames(providerApiKey);
|
|
796
|
-
if (envVarNames.length > 0) {
|
|
797
|
-
return isConfigValueConfigured(providerApiKey)
|
|
798
|
-
? { configured: true, source: "environment", label: envVarNames.join(", ") }
|
|
799
|
-
: { configured: false };
|
|
800
|
-
}
|
|
801
|
-
return { configured: true, source: "models_json_key" };
|
|
94
|
+
return this.runtime.getProviderAuthStatus(provider);
|
|
802
95
|
}
|
|
803
|
-
/**
|
|
804
|
-
* Get display name for a provider.
|
|
805
|
-
*/
|
|
806
96
|
getProviderDisplayName(provider) {
|
|
807
|
-
|
|
808
|
-
const oauthProvider = this.authStorage.getOAuthProviders().find((p) => p.id === provider);
|
|
809
|
-
return (registeredProvider?.name ??
|
|
810
|
-
registeredProvider?.oauth?.name ??
|
|
811
|
-
oauthProvider?.name ??
|
|
812
|
-
BUILT_IN_PROVIDER_DISPLAY_NAMES[provider] ??
|
|
813
|
-
provider);
|
|
97
|
+
return this.runtime.getProvider(provider)?.name ?? BUILT_IN_PROVIDER_DISPLAY_NAMES[provider] ?? provider;
|
|
814
98
|
}
|
|
815
|
-
/**
|
|
816
|
-
* Get API key for a provider.
|
|
817
|
-
*/
|
|
818
99
|
async getApiKeyForProvider(provider) {
|
|
819
|
-
|
|
820
|
-
|
|
821
|
-
|
|
100
|
+
try {
|
|
101
|
+
return (await this.runtime.getAuth(provider))?.auth.apiKey;
|
|
102
|
+
}
|
|
103
|
+
catch {
|
|
104
|
+
return undefined;
|
|
822
105
|
}
|
|
823
|
-
const providerApiKey = this.providerRequestConfigs.get(provider)?.apiKey;
|
|
824
|
-
return providerApiKey
|
|
825
|
-
? resolveConfigValueUncached(providerApiKey, this.authStorage.getProviderEnv(provider))
|
|
826
|
-
: undefined;
|
|
827
106
|
}
|
|
828
|
-
/**
|
|
829
|
-
* Check if a model is using OAuth credentials (subscription).
|
|
830
|
-
*/
|
|
831
107
|
isUsingOAuth(model) {
|
|
832
|
-
|
|
833
|
-
return cred?.type === "oauth";
|
|
108
|
+
return this.authStorage.get(model.provider)?.type === "oauth" || this.runtime.isUsingOAuth(model.provider);
|
|
834
109
|
}
|
|
835
|
-
/**
|
|
836
|
-
* Register a provider dynamically (from extensions).
|
|
837
|
-
*
|
|
838
|
-
* If provider has models: replaces all existing models for this provider.
|
|
839
|
-
* If provider has only baseUrl/headers: overrides existing models' URLs.
|
|
840
|
-
* If provider has oauth: registers OAuth provider for /login support.
|
|
841
|
-
*/
|
|
842
110
|
registerProvider(providerName, config) {
|
|
843
|
-
this.
|
|
844
|
-
this.applyProviderConfig(providerName, config);
|
|
845
|
-
this.upsertRegisteredProvider(providerName, config);
|
|
111
|
+
this.runtime.registerProvider(providerName, config);
|
|
846
112
|
}
|
|
847
|
-
/**
|
|
848
|
-
* Unregister a previously registered provider.
|
|
849
|
-
*
|
|
850
|
-
* Removes the provider from the registry and reloads models from disk so that
|
|
851
|
-
* built-in models overridden by this provider are restored to their original state.
|
|
852
|
-
* Also resets dynamic OAuth and API stream registrations before reapplying
|
|
853
|
-
* remaining dynamic providers.
|
|
854
|
-
* Has no effect if the provider was never registered.
|
|
855
|
-
*/
|
|
856
113
|
unregisterProvider(providerName) {
|
|
857
|
-
|
|
858
|
-
return;
|
|
859
|
-
this.registeredProviders.delete(providerName);
|
|
860
|
-
this.refresh();
|
|
861
|
-
}
|
|
862
|
-
/**
|
|
863
|
-
* Upsert a provider config into registeredProviders.
|
|
864
|
-
* If the provider is already registered, defined values in the incoming config
|
|
865
|
-
* override existing ones; undefined values are preserved from the stored config.
|
|
866
|
-
* If the provider is not registered, the incoming config is stored as-is.
|
|
867
|
-
*/
|
|
868
|
-
upsertRegisteredProvider(providerName, config) {
|
|
869
|
-
const existing = this.registeredProviders.get(providerName);
|
|
870
|
-
if (!existing) {
|
|
871
|
-
this.registeredProviders.set(providerName, config);
|
|
872
|
-
return;
|
|
873
|
-
}
|
|
874
|
-
const next = { ...existing };
|
|
875
|
-
if (config.name !== undefined)
|
|
876
|
-
next.name = config.name;
|
|
877
|
-
if (config.baseUrl !== undefined)
|
|
878
|
-
next.baseUrl = config.baseUrl;
|
|
879
|
-
if (config.apiKey !== undefined)
|
|
880
|
-
next.apiKey = config.apiKey;
|
|
881
|
-
if (config.api !== undefined)
|
|
882
|
-
next.api = config.api;
|
|
883
|
-
if (config.streamSimple !== undefined)
|
|
884
|
-
next.streamSimple = config.streamSimple;
|
|
885
|
-
if (config.oauth !== undefined)
|
|
886
|
-
next.oauth = config.oauth;
|
|
887
|
-
if (config.models !== undefined)
|
|
888
|
-
next.models = config.models;
|
|
889
|
-
if (config.headers !== undefined) {
|
|
890
|
-
next.headers = config.headers;
|
|
891
|
-
}
|
|
892
|
-
else {
|
|
893
|
-
delete next.headers;
|
|
894
|
-
}
|
|
895
|
-
if (config.extraBody !== undefined) {
|
|
896
|
-
next.extraBody = config.extraBody;
|
|
897
|
-
}
|
|
898
|
-
else {
|
|
899
|
-
delete next.extraBody;
|
|
900
|
-
}
|
|
901
|
-
if (config.cacheRetention !== undefined) {
|
|
902
|
-
next.cacheRetention = config.cacheRetention;
|
|
903
|
-
}
|
|
904
|
-
else {
|
|
905
|
-
delete next.cacheRetention;
|
|
906
|
-
}
|
|
907
|
-
if (config.authHeader !== undefined) {
|
|
908
|
-
next.authHeader = config.authHeader;
|
|
909
|
-
}
|
|
910
|
-
else {
|
|
911
|
-
delete next.authHeader;
|
|
912
|
-
}
|
|
913
|
-
this.registeredProviders.set(providerName, next);
|
|
114
|
+
this.runtime.unregisterProvider(providerName);
|
|
914
115
|
}
|
|
915
|
-
|
|
916
|
-
|
|
917
|
-
throw new Error(`Provider ${providerName}: "api" is required when registering streamSimple.`);
|
|
918
|
-
}
|
|
919
|
-
if (!config.models || config.models.length === 0) {
|
|
920
|
-
return;
|
|
921
|
-
}
|
|
922
|
-
if (!config.baseUrl) {
|
|
923
|
-
throw new Error(`Provider ${providerName}: "baseUrl" is required when defining models.`);
|
|
924
|
-
}
|
|
925
|
-
if (!config.apiKey && !config.oauth) {
|
|
926
|
-
throw new Error(`Provider ${providerName}: "apiKey" or "oauth" is required when defining models.`);
|
|
927
|
-
}
|
|
928
|
-
for (const modelDef of config.models) {
|
|
929
|
-
const api = modelDef.api || config.api;
|
|
930
|
-
if (!api) {
|
|
931
|
-
throw new Error(`Provider ${providerName}, model ${modelDef.id}: no "api" specified.`);
|
|
932
|
-
}
|
|
933
|
-
}
|
|
116
|
+
getRegisteredProviderConfig(providerName) {
|
|
117
|
+
return this.runtime.getRegisteredProviderConfig(providerName);
|
|
934
118
|
}
|
|
935
|
-
|
|
936
|
-
|
|
937
|
-
if (config.oauth) {
|
|
938
|
-
// Ensure the OAuth provider ID matches the provider name
|
|
939
|
-
const oauthProvider = {
|
|
940
|
-
...config.oauth,
|
|
941
|
-
id: providerName,
|
|
942
|
-
};
|
|
943
|
-
registerOAuthProvider(oauthProvider);
|
|
944
|
-
}
|
|
945
|
-
if (config.streamSimple) {
|
|
946
|
-
const streamSimple = config.streamSimple;
|
|
947
|
-
registerApiProvider({
|
|
948
|
-
api: config.api,
|
|
949
|
-
stream: (model, context, options) => streamSimple(model, context, options),
|
|
950
|
-
streamSimple,
|
|
951
|
-
}, `provider:${providerName}`);
|
|
952
|
-
}
|
|
953
|
-
this.storeProviderRequestConfig(providerName, config, this.registeredProviders.get(providerName)?.apiKey);
|
|
954
|
-
if (config.models && config.models.length > 0) {
|
|
955
|
-
// Full replacement: remove existing models for this provider
|
|
956
|
-
this.models = this.models.filter((m) => m.provider !== providerName);
|
|
957
|
-
this.clearModelRequestConfigForProvider(providerName);
|
|
958
|
-
// Parse and add new models
|
|
959
|
-
for (const modelDef of config.models) {
|
|
960
|
-
const api = modelDef.api || config.api;
|
|
961
|
-
const modelOverride = this.getConfiguredModelOverride(providerName, modelDef.id);
|
|
962
|
-
const headers = modelDef.headers || modelOverride?.headers
|
|
963
|
-
? { ...modelDef.headers, ...modelOverride?.headers }
|
|
964
|
-
: undefined;
|
|
965
|
-
const extraBody = modelDef.extraBody || modelOverride?.extraBody
|
|
966
|
-
? { ...modelDef.extraBody, ...modelOverride?.extraBody }
|
|
967
|
-
: undefined;
|
|
968
|
-
this.storeModelHeaders(providerName, modelDef.id, headers);
|
|
969
|
-
this.storeModelExtraBody(providerName, modelDef.id, extraBody);
|
|
970
|
-
this.storeModelUpstreamId(providerName, modelDef.id, modelDef.upstreamModelId);
|
|
971
|
-
this.storeModelServiceTier(providerName, modelDef.id, modelDef.serviceTier);
|
|
972
|
-
const model = this.applyConfiguredModelOverride(providerName, {
|
|
973
|
-
id: modelDef.id,
|
|
974
|
-
name: modelDef.name,
|
|
975
|
-
api: api,
|
|
976
|
-
provider: providerName,
|
|
977
|
-
baseUrl: modelDef.baseUrl ?? config.baseUrl,
|
|
978
|
-
reasoning: modelDef.reasoning,
|
|
979
|
-
cacheRetention: modelDef.cacheRetention ?? config.cacheRetention,
|
|
980
|
-
thinkingLevelMap: modelDef.thinkingLevelMap,
|
|
981
|
-
input: modelDef.input,
|
|
982
|
-
cost: modelDef.cost,
|
|
983
|
-
contextWindow: modelDef.contextWindow,
|
|
984
|
-
maxTokens: modelDef.maxTokens,
|
|
985
|
-
headers: undefined,
|
|
986
|
-
compat: modelDef.compat,
|
|
987
|
-
});
|
|
988
|
-
this.models.push(model);
|
|
989
|
-
}
|
|
990
|
-
// Apply OAuth modifyModels if credentials exist (e.g., to update baseUrl)
|
|
991
|
-
if (config.oauth?.modifyModels) {
|
|
992
|
-
const cred = this.authStorage.get(providerName);
|
|
993
|
-
if (cred?.type === "oauth") {
|
|
994
|
-
this.models = config.oauth.modifyModels(this.models, cred);
|
|
995
|
-
}
|
|
996
|
-
}
|
|
997
|
-
}
|
|
998
|
-
else if (config.baseUrl || config.headers || config.extraBody || config.cacheRetention) {
|
|
999
|
-
// Override-only: update baseUrl for existing models. Request headers and extraBody are resolved per request.
|
|
1000
|
-
this.models = this.models.map((m) => {
|
|
1001
|
-
if (m.provider !== providerName)
|
|
1002
|
-
return m;
|
|
1003
|
-
return {
|
|
1004
|
-
...m,
|
|
1005
|
-
baseUrl: config.baseUrl ?? m.baseUrl,
|
|
1006
|
-
cacheRetention: m.cacheRetention ?? config.cacheRetention,
|
|
1007
|
-
};
|
|
1008
|
-
});
|
|
1009
|
-
}
|
|
119
|
+
getRegisteredProviderIds() {
|
|
120
|
+
return this.runtime.getRegisteredProviderIds();
|
|
1010
121
|
}
|
|
1011
122
|
}
|
|
1012
123
|
//# sourceMappingURL=model-registry.js.map
|