@armadra/agent 0.0.0-stage → 0.3.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 +37 -0
- package/LICENSE +21 -0
- package/README.md +470 -2
- package/dist/agent/agent.d.ts +56 -0
- package/dist/agent/agent.js +129 -0
- package/dist/agent/loop.d.ts +51 -0
- package/dist/agent/loop.js +158 -0
- package/dist/agent/queue.d.ts +25 -0
- package/dist/agent/queue.js +55 -0
- package/dist/agent/retry.d.ts +22 -0
- package/dist/agent/retry.js +92 -0
- package/dist/agent/schema.d.ts +27 -0
- package/dist/agent/schema.js +186 -0
- package/dist/agent/session-cache.d.ts +100 -0
- package/dist/agent/session-cache.js +514 -0
- package/dist/agent/session-compaction.d.ts +49 -0
- package/dist/agent/session-compaction.js +251 -0
- package/dist/agent/session-core.d.ts +103 -0
- package/dist/agent/session-core.js +7 -0
- package/dist/agent/session-run.d.ts +55 -0
- package/dist/agent/session-run.js +246 -0
- package/dist/agent/session-state.d.ts +39 -0
- package/dist/agent/session-state.js +119 -0
- package/dist/agent/session-subagent.d.ts +54 -0
- package/dist/agent/session-subagent.js +157 -0
- package/dist/agent/session-sync.d.ts +20 -0
- package/dist/agent/session-sync.js +111 -0
- package/dist/agent/session-tools.d.ts +24 -0
- package/dist/agent/session-tools.js +277 -0
- package/dist/agent/session.d.ts +117 -0
- package/dist/agent/session.js +485 -0
- package/dist/agent/system-prompt.d.ts +49 -0
- package/dist/agent/system-prompt.js +121 -0
- package/dist/agent/tool-runner.d.ts +64 -0
- package/dist/agent/tool-runner.js +309 -0
- package/dist/agent/transform.d.ts +26 -0
- package/dist/agent/transform.js +171 -0
- package/dist/agent/types.d.ts +378 -0
- package/dist/agent/types.js +21 -0
- package/dist/ai/apis/anthropic-messages.d.ts +26 -0
- package/dist/ai/apis/anthropic-messages.js +214 -0
- package/dist/ai/apis/anthropic-request.d.ts +42 -0
- package/dist/ai/apis/anthropic-request.js +282 -0
- package/dist/ai/apis/api.d.ts +28 -0
- package/dist/ai/apis/api.js +102 -0
- package/dist/ai/apis/cache-params.d.ts +48 -0
- package/dist/ai/apis/cache-params.js +163 -0
- package/dist/ai/apis/google-generative-ai.d.ts +32 -0
- package/dist/ai/apis/google-generative-ai.js +249 -0
- package/dist/ai/apis/google-request.d.ts +40 -0
- package/dist/ai/apis/google-request.js +255 -0
- package/dist/ai/apis/openai-compat.d.ts +35 -0
- package/dist/ai/apis/openai-compat.js +142 -0
- package/dist/ai/apis/openai-completions.d.ts +28 -0
- package/dist/ai/apis/openai-completions.js +246 -0
- package/dist/ai/apis/openai-request.d.ts +35 -0
- package/dist/ai/apis/openai-request.js +303 -0
- package/dist/ai/apis/openai-responses-request.d.ts +52 -0
- package/dist/ai/apis/openai-responses-request.js +266 -0
- package/dist/ai/apis/openai-responses.d.ts +28 -0
- package/dist/ai/apis/openai-responses.js +304 -0
- package/dist/ai/apis/shared.d.ts +56 -0
- package/dist/ai/apis/shared.js +179 -0
- package/dist/ai/cache/economics.d.ts +24 -0
- package/dist/ai/cache/economics.js +69 -0
- package/dist/ai/cache/fingerprint.d.ts +17 -0
- package/dist/ai/cache/fingerprint.js +39 -0
- package/dist/ai/cache/miss.d.ts +49 -0
- package/dist/ai/cache/miss.js +96 -0
- package/dist/ai/cache/reporting.d.ts +39 -0
- package/dist/ai/cache/reporting.js +103 -0
- package/dist/ai/cache/types.d.ts +94 -0
- package/dist/ai/cache/types.js +19 -0
- package/dist/ai/cache/warmer.d.ts +94 -0
- package/dist/ai/cache/warmer.js +224 -0
- package/dist/ai/context.d.ts +35 -0
- package/dist/ai/context.js +114 -0
- package/dist/ai/cost.d.ts +21 -0
- package/dist/ai/cost.js +60 -0
- package/dist/ai/event-stream.d.ts +33 -0
- package/dist/ai/event-stream.js +101 -0
- package/dist/ai/fake/fake-provider.d.ts +68 -0
- package/dist/ai/fake/fake-provider.js +278 -0
- package/dist/ai/fake/fake-script.d.ts +69 -0
- package/dist/ai/fake/fake-script.js +142 -0
- package/dist/ai/http.d.ts +54 -0
- package/dist/ai/http.js +212 -0
- package/dist/ai/json-partial.d.ts +17 -0
- package/dist/ai/json-partial.js +243 -0
- package/dist/ai/overflow.d.ts +22 -0
- package/dist/ai/overflow.js +61 -0
- package/dist/ai/providers/auth.d.ts +71 -0
- package/dist/ai/providers/auth.js +202 -0
- package/dist/ai/providers/builtin.d.ts +23 -0
- package/dist/ai/providers/builtin.js +148 -0
- package/dist/ai/providers/catalog-data.d.ts +5 -0
- package/dist/ai/providers/catalog-data.js +19 -0
- package/dist/ai/providers/catalog.d.ts +28 -0
- package/dist/ai/providers/catalog.js +166 -0
- package/dist/ai/providers/channels.d.ts +51 -0
- package/dist/ai/providers/channels.js +96 -0
- package/dist/ai/providers/enrich.d.ts +34 -0
- package/dist/ai/providers/enrich.js +86 -0
- package/dist/ai/providers/models-dev-cache.d.ts +53 -0
- package/dist/ai/providers/models-dev-cache.js +147 -0
- package/dist/ai/providers/models-dev.d.ts +99 -0
- package/dist/ai/providers/models-dev.js +315 -0
- package/dist/ai/providers/registry.d.ts +114 -0
- package/dist/ai/providers/registry.js +458 -0
- package/dist/ai/sse.d.ts +32 -0
- package/dist/ai/sse.js +140 -0
- package/dist/ai/thinking.d.ts +42 -0
- package/dist/ai/thinking.js +101 -0
- package/dist/ai/types.d.ts +448 -0
- package/dist/ai/types.js +19 -0
- package/dist/bundle/ama-sandbox.cjs +324 -0
- package/dist/bundle/ama.cjs +27837 -0
- package/dist/bundle.d.ts +9 -0
- package/dist/bundle.js +15 -0
- package/dist/cli/args.d.ts +85 -0
- package/dist/cli/args.js +408 -0
- package/dist/cli/bootstrap.d.ts +18 -0
- package/dist/cli/bootstrap.js +399 -0
- package/dist/cli/compose-providers.d.ts +37 -0
- package/dist/cli/compose-providers.js +107 -0
- package/dist/cli/compose-session.d.ts +72 -0
- package/dist/cli/compose-session.js +370 -0
- package/dist/cli/compose-store.d.ts +24 -0
- package/dist/cli/compose-store.js +125 -0
- package/dist/cli/compose.d.ts +108 -0
- package/dist/cli/compose.js +221 -0
- package/dist/cli/default-model.d.ts +16 -0
- package/dist/cli/default-model.js +24 -0
- package/dist/cli/deps.d.ts +207 -0
- package/dist/cli/deps.js +12 -0
- package/dist/cli/exit-codes.d.ts +29 -0
- package/dist/cli/exit-codes.js +40 -0
- package/dist/cli/main.d.ts +27 -0
- package/dist/cli/main.js +177 -0
- package/dist/cli/runtime.d.ts +90 -0
- package/dist/cli/runtime.js +8 -0
- package/dist/cli/startup-screen.d.ts +15 -0
- package/dist/cli/startup-screen.js +56 -0
- package/dist/cli/startup-steps.d.ts +35 -0
- package/dist/cli/startup-steps.js +202 -0
- package/dist/cli/subcommands/auth.d.ts +12 -0
- package/dist/cli/subcommands/auth.js +91 -0
- package/dist/cli/subcommands/config.d.ts +53 -0
- package/dist/cli/subcommands/config.js +277 -0
- package/dist/cli/subcommands/context.d.ts +21 -0
- package/dist/cli/subcommands/context.js +42 -0
- package/dist/cli/subcommands/doctor.d.ts +11 -0
- package/dist/cli/subcommands/doctor.js +246 -0
- package/dist/cli/subcommands/init.d.ts +6 -0
- package/dist/cli/subcommands/init.js +22 -0
- package/dist/cli/subcommands/model-meta.d.ts +16 -0
- package/dist/cli/subcommands/model-meta.js +54 -0
- package/dist/cli/subcommands/models-cache-probe.d.ts +34 -0
- package/dist/cli/subcommands/models-cache-probe.js +190 -0
- package/dist/cli/subcommands/models-discover.d.ts +46 -0
- package/dist/cli/subcommands/models-discover.js +232 -0
- package/dist/cli/subcommands/models.d.ts +40 -0
- package/dist/cli/subcommands/models.js +152 -0
- package/dist/cli/subcommands/providers-list.d.ts +8 -0
- package/dist/cli/subcommands/providers-list.js +97 -0
- package/dist/cli/subcommands/providers-plan.d.ts +79 -0
- package/dist/cli/subcommands/providers-plan.js +215 -0
- package/dist/cli/subcommands/providers.d.ts +27 -0
- package/dist/cli/subcommands/providers.js +433 -0
- package/dist/cli/subcommands/sessions.d.ts +11 -0
- package/dist/cli/subcommands/sessions.js +100 -0
- package/dist/codemode/capability.d.ts +37 -0
- package/dist/codemode/capability.js +55 -0
- package/dist/codemode/declarations.d.ts +44 -0
- package/dist/codemode/declarations.js +111 -0
- package/dist/codemode/host-side.d.ts +59 -0
- package/dist/codemode/host-side.js +253 -0
- package/dist/codemode/modes.d.ts +23 -0
- package/dist/codemode/modes.js +40 -0
- package/dist/codemode/protocol.d.ts +91 -0
- package/dist/codemode/protocol.js +114 -0
- package/dist/codemode/sandbox-entry.d.ts +25 -0
- package/dist/codemode/sandbox-entry.js +323 -0
- package/dist/codemode/store.d.ts +26 -0
- package/dist/codemode/store.js +53 -0
- package/dist/codemode/tool.d.ts +105 -0
- package/dist/codemode/tool.js +283 -0
- package/dist/compaction/branch-summary.d.ts +30 -0
- package/dist/compaction/branch-summary.js +79 -0
- package/dist/compaction/breaker.d.ts +32 -0
- package/dist/compaction/breaker.js +65 -0
- package/dist/compaction/cut-point.d.ts +23 -0
- package/dist/compaction/cut-point.js +70 -0
- package/dist/compaction/estimate.d.ts +30 -0
- package/dist/compaction/estimate.js +114 -0
- package/dist/compaction/prune-tier.d.ts +31 -0
- package/dist/compaction/prune-tier.js +83 -0
- package/dist/compaction/serialize.d.ts +20 -0
- package/dist/compaction/serialize.js +115 -0
- package/dist/compaction/summarize-tier.d.ts +111 -0
- package/dist/compaction/summarize-tier.js +305 -0
- package/dist/config/auth-file.d.ts +39 -0
- package/dist/config/auth-file.js +92 -0
- package/dist/config/context-files.d.ts +30 -0
- package/dist/config/context-files.js +77 -0
- package/dist/config/init.d.ts +30 -0
- package/dist/config/init.js +92 -0
- package/dist/config/json-schema.d.ts +14 -0
- package/dist/config/json-schema.js +182 -0
- package/dist/config/load.d.ts +45 -0
- package/dist/config/load.js +97 -0
- package/dist/config/merge.d.ts +73 -0
- package/dist/config/merge.js +248 -0
- package/dist/config/paths.d.ts +38 -0
- package/dist/config/paths.js +108 -0
- package/dist/config/profile.d.ts +27 -0
- package/dist/config/profile.js +65 -0
- package/dist/config/schema.d.ts +34 -0
- package/dist/config/schema.js +476 -0
- package/dist/config/trust.d.ts +42 -0
- package/dist/config/trust.js +122 -0
- package/dist/config/types.d.ts +190 -0
- package/dist/config/types.js +29 -0
- package/dist/config/write.d.ts +10 -0
- package/dist/config/write.js +25 -0
- package/dist/errors.d.ts +28 -0
- package/dist/errors.js +30 -0
- package/dist/hooks/config.d.ts +49 -0
- package/dist/hooks/config.js +102 -0
- package/dist/hooks/dispatcher.d.ts +41 -0
- package/dist/hooks/dispatcher.js +104 -0
- package/dist/hooks/matcher.d.ts +22 -0
- package/dist/hooks/matcher.js +108 -0
- package/dist/hooks/protocol.d.ts +33 -0
- package/dist/hooks/protocol.js +240 -0
- package/dist/hooks/runner.d.ts +30 -0
- package/dist/hooks/runner.js +143 -0
- package/dist/hooks/types.d.ts +147 -0
- package/dist/hooks/types.js +20 -0
- package/dist/host/api-impl.d.ts +75 -0
- package/dist/host/api-impl.js +173 -0
- package/dist/host/loader.d.ts +31 -0
- package/dist/host/loader.js +147 -0
- package/dist/host/types.d.ts +169 -0
- package/dist/host/types.js +14 -0
- package/dist/host.d.ts +5 -0
- package/dist/host.js +4 -0
- package/dist/index.d.ts +41 -0
- package/dist/index.js +28 -0
- package/dist/modes/commands-core.d.ts +44 -0
- package/dist/modes/commands-core.js +171 -0
- package/dist/modes/image-input.d.ts +27 -0
- package/dist/modes/image-input.js +78 -0
- package/dist/modes/interactive/approval-dialog.d.ts +48 -0
- package/dist/modes/interactive/approval-dialog.js +202 -0
- package/dist/modes/interactive/commands.d.ts +41 -0
- package/dist/modes/interactive/commands.js +201 -0
- package/dist/modes/interactive/completion.d.ts +53 -0
- package/dist/modes/interactive/completion.js +157 -0
- package/dist/modes/interactive/interactive-mode.d.ts +46 -0
- package/dist/modes/interactive/interactive-mode.js +491 -0
- package/dist/modes/interactive/key-dispatch.d.ts +29 -0
- package/dist/modes/interactive/key-dispatch.js +107 -0
- package/dist/modes/interactive/line/line-editor.d.ts +50 -0
- package/dist/modes/interactive/line/line-editor.js +232 -0
- package/dist/modes/interactive/line/line-mode.d.ts +20 -0
- package/dist/modes/interactive/line/line-mode.js +218 -0
- package/dist/modes/interactive/line/line-render.d.ts +35 -0
- package/dist/modes/interactive/line/line-render.js +171 -0
- package/dist/modes/interactive/line/paste-state.d.ts +26 -0
- package/dist/modes/interactive/line/paste-state.js +72 -0
- package/dist/modes/interactive/message-view.d.ts +77 -0
- package/dist/modes/interactive/message-view.js +269 -0
- package/dist/modes/interactive/pickers.d.ts +42 -0
- package/dist/modes/interactive/pickers.js +115 -0
- package/dist/modes/interactive/startup-ui.d.ts +33 -0
- package/dist/modes/interactive/startup-ui.js +268 -0
- package/dist/modes/interactive/status-bar.d.ts +48 -0
- package/dist/modes/interactive/status-bar.js +139 -0
- package/dist/modes/interactive/tool-view.d.ts +95 -0
- package/dist/modes/interactive/tool-view.js +344 -0
- package/dist/modes/print/json-event.d.ts +15 -0
- package/dist/modes/print/json-event.js +39 -0
- package/dist/modes/print/print-mode.d.ts +17 -0
- package/dist/modes/print/print-mode.js +107 -0
- package/dist/modes/rpc/commands.d.ts +40 -0
- package/dist/modes/rpc/commands.js +263 -0
- package/dist/modes/rpc/jsonl.d.ts +16 -0
- package/dist/modes/rpc/jsonl.js +55 -0
- package/dist/modes/rpc/rpc-mode.d.ts +22 -0
- package/dist/modes/rpc/rpc-mode.js +153 -0
- package/dist/modes/session-report.d.ts +55 -0
- package/dist/modes/session-report.js +278 -0
- package/dist/modes/shared.d.ts +13 -0
- package/dist/modes/shared.js +52 -0
- package/dist/modes/startup-ui-text.d.ts +16 -0
- package/dist/modes/startup-ui-text.js +103 -0
- package/dist/permissions/broker.d.ts +47 -0
- package/dist/permissions/broker.js +107 -0
- package/dist/permissions/dangerous.d.ts +47 -0
- package/dist/permissions/dangerous.js +370 -0
- package/dist/permissions/pipeline.d.ts +51 -0
- package/dist/permissions/pipeline.js +181 -0
- package/dist/permissions/preview.d.ts +43 -0
- package/dist/permissions/preview.js +463 -0
- package/dist/permissions/rules.d.ts +58 -0
- package/dist/permissions/rules.js +249 -0
- package/dist/permissions/types.d.ts +100 -0
- package/dist/permissions/types.js +18 -0
- package/dist/rpc.d.ts +173 -0
- package/dist/rpc.js +13 -0
- package/dist/sdk.d.ts +98 -0
- package/dist/sdk.js +195 -0
- package/dist/session/manager.d.ts +70 -0
- package/dist/session/manager.js +278 -0
- package/dist/session/migrate.d.ts +19 -0
- package/dist/session/migrate.js +53 -0
- package/dist/session/projection.d.ts +50 -0
- package/dist/session/projection.js +184 -0
- package/dist/session/store.d.ts +47 -0
- package/dist/session/store.js +210 -0
- package/dist/session/tree.d.ts +21 -0
- package/dist/session/tree.js +88 -0
- package/dist/session/types.d.ts +201 -0
- package/dist/session/types.js +18 -0
- package/dist/skills/discover.d.ts +60 -0
- package/dist/skills/discover.js +160 -0
- package/dist/skills/expand.d.ts +35 -0
- package/dist/skills/expand.js +46 -0
- package/dist/skills/frontmatter.d.ts +27 -0
- package/dist/skills/frontmatter.js +157 -0
- package/dist/skills/index-prompt.d.ts +13 -0
- package/dist/skills/index-prompt.js +42 -0
- package/dist/skills/templates.d.ts +52 -0
- package/dist/skills/templates.js +177 -0
- package/dist/tools/bash.d.ts +49 -0
- package/dist/tools/bash.js +222 -0
- package/dist/tools/edit-fuzzy.d.ts +36 -0
- package/dist/tools/edit-fuzzy.js +129 -0
- package/dist/tools/edit.d.ts +38 -0
- package/dist/tools/edit.js +241 -0
- package/dist/tools/file-mutex.d.ts +8 -0
- package/dist/tools/file-mutex.js +29 -0
- package/dist/tools/glob.d.ts +44 -0
- package/dist/tools/glob.js +217 -0
- package/dist/tools/grep.d.ts +39 -0
- package/dist/tools/grep.js +179 -0
- package/dist/tools/ignore.d.ts +40 -0
- package/dist/tools/ignore.js +174 -0
- package/dist/tools/image-file.d.ts +31 -0
- package/dist/tools/image-file.js +114 -0
- package/dist/tools/ls.d.ts +21 -0
- package/dist/tools/ls.js +96 -0
- package/dist/tools/output-accumulator.d.ts +48 -0
- package/dist/tools/output-accumulator.js +106 -0
- package/dist/tools/paths.d.ts +20 -0
- package/dist/tools/paths.js +58 -0
- package/dist/tools/presets.d.ts +71 -0
- package/dist/tools/presets.js +128 -0
- package/dist/tools/process-tree.d.ts +35 -0
- package/dist/tools/process-tree.js +125 -0
- package/dist/tools/read.d.ts +24 -0
- package/dist/tools/read.js +132 -0
- package/dist/tools/registry.d.ts +43 -0
- package/dist/tools/registry.js +106 -0
- package/dist/tools/shell.d.ts +38 -0
- package/dist/tools/shell.js +91 -0
- package/dist/tools/task.d.ts +29 -0
- package/dist/tools/task.js +107 -0
- package/dist/tools/todo.d.ts +28 -0
- package/dist/tools/todo.js +107 -0
- package/dist/tools/truncate.d.ts +44 -0
- package/dist/tools/truncate.js +175 -0
- package/dist/tools/types.d.ts +135 -0
- package/dist/tools/types.js +19 -0
- package/dist/tools/write.d.ts +20 -0
- package/dist/tools/write.js +84 -0
- package/dist/tui/ansi.d.ts +29 -0
- package/dist/tui/ansi.js +420 -0
- package/dist/tui/component.d.ts +38 -0
- package/dist/tui/component.js +13 -0
- package/dist/tui/components/box.d.ts +26 -0
- package/dist/tui/components/box.js +65 -0
- package/dist/tui/components/container.d.ts +14 -0
- package/dist/tui/components/container.js +39 -0
- package/dist/tui/components/editor-buffer.d.ts +67 -0
- package/dist/tui/components/editor-buffer.js +300 -0
- package/dist/tui/components/editor-paste.d.ts +29 -0
- package/dist/tui/components/editor-paste.js +64 -0
- package/dist/tui/components/editor.d.ts +114 -0
- package/dist/tui/components/editor.js +530 -0
- package/dist/tui/components/key-value.d.ts +29 -0
- package/dist/tui/components/key-value.js +48 -0
- package/dist/tui/components/loader.d.ts +35 -0
- package/dist/tui/components/loader.js +71 -0
- package/dist/tui/components/markdown.d.ts +90 -0
- package/dist/tui/components/markdown.js +462 -0
- package/dist/tui/components/meter.d.ts +29 -0
- package/dist/tui/components/meter.js +47 -0
- package/dist/tui/components/overlay.d.ts +24 -0
- package/dist/tui/components/overlay.js +52 -0
- package/dist/tui/components/select-list.d.ts +57 -0
- package/dist/tui/components/select-list.js +179 -0
- package/dist/tui/components/spacer.d.ts +11 -0
- package/dist/tui/components/spacer.js +16 -0
- package/dist/tui/components/text.d.ts +30 -0
- package/dist/tui/components/text.js +65 -0
- package/dist/tui/keybindings.d.ts +66 -0
- package/dist/tui/keybindings.js +120 -0
- package/dist/tui/keys.d.ts +38 -0
- package/dist/tui/keys.js +275 -0
- package/dist/tui/stdin-buffer.d.ts +41 -0
- package/dist/tui/stdin-buffer.js +206 -0
- package/dist/tui/terminal.d.ts +79 -0
- package/dist/tui/terminal.js +153 -0
- package/dist/tui/theme.d.ts +31 -0
- package/dist/tui/theme.js +199 -0
- package/dist/tui/tui.d.ts +103 -0
- package/dist/tui/tui.js +363 -0
- package/dist/tui/vt-screen.d.ts +46 -0
- package/dist/tui/vt-screen.js +251 -0
- package/dist/tui.d.ts +30 -0
- package/dist/tui.js +31 -0
- package/dist/version.d.ts +8 -0
- package/dist/version.js +24 -0
- package/docs/codemode.md +102 -0
- package/docs/hooks.md +196 -0
- package/docs/host-api.md +161 -0
- package/docs/providers.md +531 -0
- package/docs/rpc.md +253 -0
- package/docs/session-format.md +119 -0
- package/docs/tui.md +170 -0
- package/package.json +101 -4
|
@@ -0,0 +1,202 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* API Key 发现(设计 §3.5)。顺序:
|
|
3
|
+
* ① `--api-key`(只对 `--model` 指定的那家供应商)
|
|
4
|
+
* ② `--auth-file` / profile.authFile 指向的 auth.json
|
|
5
|
+
* ③ 用户级 `<configDir>/auth.json`(不是 0600 → warning 并照用)
|
|
6
|
+
* ④ config.json 的 `providers.<id>.apiKey`(`$ENV_NAME`、`${ENV_NAME}`、`!command`;`$$` 转义)
|
|
7
|
+
* ⑤ 环境变量:`provider.envKeys` 顺序(profile.authEnv=false 时跳过)
|
|
8
|
+
* ⑥ `requiresApiKey: false` 的供应商:无 key 也放行(source "none")
|
|
9
|
+
*
|
|
10
|
+
* auth.json 的 `apiKey` 以 `!` 开头 = 执行命令取值(stdout 去首尾空白;超时 10 s;空输出或
|
|
11
|
+
* 非零退出视为未配置,继续找下一来源);同一命令进程内只执行一次。
|
|
12
|
+
* 密钥只出现在 `resolve()` 的返回值里:warning 文案不含密钥与命令输出。
|
|
13
|
+
*/
|
|
14
|
+
import { exec } from "node:child_process";
|
|
15
|
+
import { readFileSync, statSync } from "node:fs";
|
|
16
|
+
import { homedir } from "node:os";
|
|
17
|
+
import { join } from "node:path";
|
|
18
|
+
/** 用户级配置目录:AMA_CONFIG_DIR > %APPDATA%\ama > $XDG_CONFIG_HOME/ama > ~/.config/ama。 */
|
|
19
|
+
export function defaultConfigDir(env = process.env) {
|
|
20
|
+
if (env["AMA_CONFIG_DIR"])
|
|
21
|
+
return env["AMA_CONFIG_DIR"];
|
|
22
|
+
if (process.platform === "win32" && env["APPDATA"])
|
|
23
|
+
return join(env["APPDATA"], "ama");
|
|
24
|
+
if (env["XDG_CONFIG_HOME"])
|
|
25
|
+
return join(env["XDG_CONFIG_HOME"], "ama");
|
|
26
|
+
return join(env["HOME"] ?? homedir(), ".config", "ama");
|
|
27
|
+
}
|
|
28
|
+
/** 读 auth.json;不存在返回 undefined;格式错误 / 权限过宽记 warning。 */
|
|
29
|
+
export function readAuthFile(path, onWarning) {
|
|
30
|
+
let raw;
|
|
31
|
+
try {
|
|
32
|
+
raw = readFileSync(path, "utf8");
|
|
33
|
+
}
|
|
34
|
+
catch (error) {
|
|
35
|
+
const code = error.code;
|
|
36
|
+
if (code !== "ENOENT")
|
|
37
|
+
onWarning?.(`cannot read auth file ${path}`);
|
|
38
|
+
return undefined;
|
|
39
|
+
}
|
|
40
|
+
if (process.platform !== "win32") {
|
|
41
|
+
try {
|
|
42
|
+
const mode = statSync(path).mode & 0o777;
|
|
43
|
+
if ((mode & 0o077) !== 0) {
|
|
44
|
+
onWarning?.(`auth file ${path} has permissions ${mode.toString(8).padStart(4, "0")}; expected 0600`);
|
|
45
|
+
}
|
|
46
|
+
}
|
|
47
|
+
catch {
|
|
48
|
+
// 读得到就不必再纠结 stat
|
|
49
|
+
}
|
|
50
|
+
}
|
|
51
|
+
try {
|
|
52
|
+
const value = JSON.parse(raw);
|
|
53
|
+
if (typeof value !== "object" || value === null)
|
|
54
|
+
throw new Error("not an object");
|
|
55
|
+
const providers = value.providers;
|
|
56
|
+
if (typeof providers !== "object" || providers === null)
|
|
57
|
+
throw new Error("no providers");
|
|
58
|
+
return value;
|
|
59
|
+
}
|
|
60
|
+
catch {
|
|
61
|
+
onWarning?.(`auth file ${path} is not a valid auth.json; ignored`);
|
|
62
|
+
return undefined;
|
|
63
|
+
}
|
|
64
|
+
}
|
|
65
|
+
/**
|
|
66
|
+
* 展开 config.json 的 `$NAME` / `${NAME}`(`$$` → `$`)。引用的变量未设置或为空 →
|
|
67
|
+
* undefined(视为未配置)。
|
|
68
|
+
*/
|
|
69
|
+
export function expandEnvRefs(value, env) {
|
|
70
|
+
let missing = false;
|
|
71
|
+
const out = value.replace(/\$\$|\$\{([A-Za-z_][A-Za-z0-9_]*)\}|\$([A-Za-z_][A-Za-z0-9_]*)/g, (match, braced, bare) => {
|
|
72
|
+
if (match === "$$")
|
|
73
|
+
return "$";
|
|
74
|
+
const name = braced ?? bare ?? "";
|
|
75
|
+
const resolved = env[name];
|
|
76
|
+
if (resolved === undefined || resolved === "")
|
|
77
|
+
missing = true;
|
|
78
|
+
return resolved ?? "";
|
|
79
|
+
});
|
|
80
|
+
return missing || out.length === 0 ? undefined : out;
|
|
81
|
+
}
|
|
82
|
+
export class ApiKeyResolver {
|
|
83
|
+
options;
|
|
84
|
+
env;
|
|
85
|
+
commandCache = new Map();
|
|
86
|
+
fileCache = new Map();
|
|
87
|
+
constructor(options = {}) {
|
|
88
|
+
this.options = options;
|
|
89
|
+
this.env = options.env ?? process.env;
|
|
90
|
+
}
|
|
91
|
+
warn(message) {
|
|
92
|
+
this.options.onWarning?.(message);
|
|
93
|
+
}
|
|
94
|
+
authFiles() {
|
|
95
|
+
const files = [];
|
|
96
|
+
if (this.options.authFile)
|
|
97
|
+
files.push(this.options.authFile);
|
|
98
|
+
const user = this.options.userAuthFile === undefined
|
|
99
|
+
? join(defaultConfigDir(this.env), "auth.json")
|
|
100
|
+
: this.options.userAuthFile;
|
|
101
|
+
if (user && !files.includes(user))
|
|
102
|
+
files.push(user);
|
|
103
|
+
return files;
|
|
104
|
+
}
|
|
105
|
+
loadFile(path) {
|
|
106
|
+
if (!this.fileCache.has(path))
|
|
107
|
+
this.fileCache.set(path, readAuthFile(path, (m) => this.warn(m)));
|
|
108
|
+
return this.fileCache.get(path);
|
|
109
|
+
}
|
|
110
|
+
/** auth.json 里该供应商的条目(按 ② ③ 顺序第一个)。 */
|
|
111
|
+
authEntry(providerId) {
|
|
112
|
+
for (const path of this.authFiles()) {
|
|
113
|
+
const entry = this.loadFile(path)?.providers[providerId];
|
|
114
|
+
if (entry && typeof entry.apiKey === "string")
|
|
115
|
+
return { entry, path };
|
|
116
|
+
}
|
|
117
|
+
return undefined;
|
|
118
|
+
}
|
|
119
|
+
runCommand(command, extraEnv) {
|
|
120
|
+
const key = `${command}\0${JSON.stringify(extraEnv ?? {})}`;
|
|
121
|
+
let pending = this.commandCache.get(key);
|
|
122
|
+
if (!pending) {
|
|
123
|
+
const timeout = this.options.commandTimeoutMs ?? 10_000;
|
|
124
|
+
pending = new Promise((resolve) => {
|
|
125
|
+
exec(command, { timeout, windowsHide: true, env: { ...this.env, ...extraEnv }, maxBuffer: 1 << 20 }, (error, stdout) => {
|
|
126
|
+
const value = String(stdout).trim();
|
|
127
|
+
if (error || value.length === 0) {
|
|
128
|
+
this.warn(`api key command failed or printed nothing: ${command.split(/\s+/)[0]}`);
|
|
129
|
+
resolve(undefined);
|
|
130
|
+
}
|
|
131
|
+
else
|
|
132
|
+
resolve(value);
|
|
133
|
+
});
|
|
134
|
+
});
|
|
135
|
+
this.commandCache.set(key, pending);
|
|
136
|
+
}
|
|
137
|
+
return pending;
|
|
138
|
+
}
|
|
139
|
+
async fromAuthFiles(providerId) {
|
|
140
|
+
for (const path of this.authFiles()) {
|
|
141
|
+
const entry = this.loadFile(path)?.providers[providerId];
|
|
142
|
+
if (!entry || typeof entry.apiKey !== "string" || entry.apiKey.length === 0)
|
|
143
|
+
continue;
|
|
144
|
+
const value = entry.apiKey.startsWith("!")
|
|
145
|
+
? await this.runCommand(entry.apiKey.slice(1), entry.env)
|
|
146
|
+
: entry.apiKey;
|
|
147
|
+
if (value)
|
|
148
|
+
return { apiKey: value, source: "auth-file", origin: path };
|
|
149
|
+
}
|
|
150
|
+
return undefined;
|
|
151
|
+
}
|
|
152
|
+
async fromConfig(providerId) {
|
|
153
|
+
const raw = this.options.configKeys?.[providerId];
|
|
154
|
+
if (!raw)
|
|
155
|
+
return undefined;
|
|
156
|
+
if (raw.startsWith("!"))
|
|
157
|
+
return this.runCommand(raw.slice(1));
|
|
158
|
+
return expandEnvRefs(raw, this.env);
|
|
159
|
+
}
|
|
160
|
+
fromEnv(provider) {
|
|
161
|
+
if (this.options.useEnv === false)
|
|
162
|
+
return undefined;
|
|
163
|
+
for (const name of provider.envKeys) {
|
|
164
|
+
const value = this.env[name];
|
|
165
|
+
if (value && value.trim().length > 0) {
|
|
166
|
+
return { apiKey: value.trim(), source: "env", origin: name };
|
|
167
|
+
}
|
|
168
|
+
}
|
|
169
|
+
return undefined;
|
|
170
|
+
}
|
|
171
|
+
async resolve(provider) {
|
|
172
|
+
const cli = this.options.cliApiKey;
|
|
173
|
+
if (cli && cli.provider === provider.id && cli.apiKey) {
|
|
174
|
+
return { apiKey: cli.apiKey, source: "cli" };
|
|
175
|
+
}
|
|
176
|
+
const fromFile = await this.fromAuthFiles(provider.id);
|
|
177
|
+
if (fromFile)
|
|
178
|
+
return fromFile;
|
|
179
|
+
const fromConfig = await this.fromConfig(provider.id);
|
|
180
|
+
if (fromConfig)
|
|
181
|
+
return { apiKey: fromConfig, source: "config" };
|
|
182
|
+
const fromEnv = this.fromEnv(provider);
|
|
183
|
+
if (fromEnv)
|
|
184
|
+
return fromEnv;
|
|
185
|
+
return { apiKey: undefined, source: "none" };
|
|
186
|
+
}
|
|
187
|
+
/**
|
|
188
|
+
* 同步判断「看起来配置了 key」(不执行 `!command`,只看配置是否存在;env 引用需已设置)。
|
|
189
|
+
* 供 `findModel()` 在无斜杠引用时过滤候选。
|
|
190
|
+
*/
|
|
191
|
+
hasConfiguredKey(provider) {
|
|
192
|
+
const cli = this.options.cliApiKey;
|
|
193
|
+
if (cli && cli.provider === provider.id && cli.apiKey)
|
|
194
|
+
return true;
|
|
195
|
+
if (this.authEntry(provider.id)?.entry.apiKey)
|
|
196
|
+
return true;
|
|
197
|
+
const raw = this.options.configKeys?.[provider.id];
|
|
198
|
+
if (raw && (raw.startsWith("!") || expandEnvRefs(raw, this.env) !== undefined))
|
|
199
|
+
return true;
|
|
200
|
+
return this.fromEnv(provider) !== undefined;
|
|
201
|
+
}
|
|
202
|
+
}
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* 13 家内置供应商(设计 §3.3)。这里只放供应商级数据;模型来自 catalog/*.json,compat 由
|
|
3
|
+
* 各协议的 detectCompat 推断(openai-compat.ts 的推断表),这里只写推断不出来的东西。
|
|
4
|
+
*
|
|
5
|
+
* 这里的 `api` 是供应商级缺省;目录条目可用 `api` 覆盖(openai 推理模型与 xai 目录模型走
|
|
6
|
+
* openai-responses,见 catalog/*.json)。
|
|
7
|
+
*
|
|
8
|
+
* `baseUrlEnv`(第三波 §2.3):通行约定的 baseUrl 环境变量(OpenAI SDK 的 `OPENAI_BASE_URL`、
|
|
9
|
+
* Claude Code 的 `ANTHROPIC_BASE_URL`),设了就把内置供应商指向中转站,零配置可用;优先级低于
|
|
10
|
+
* config.json 与 auth.json 的 baseUrl。
|
|
11
|
+
*/
|
|
12
|
+
import type { ProviderData } from "../types.js";
|
|
13
|
+
export type BuiltinProvider = Omit<ProviderData, "models" | "builtin"> & {
|
|
14
|
+
baseUrlEnv?: string;
|
|
15
|
+
};
|
|
16
|
+
export declare const BUILTIN_PROVIDERS: readonly BuiltinProvider[];
|
|
17
|
+
/**
|
|
18
|
+
* 内置供应商的 baseUrl 是否被改到了非官方主机(中转站):此时目录外的 model id 也接受,
|
|
19
|
+
* compat 走保守缺省。非内置供应商返回 false。
|
|
20
|
+
*/
|
|
21
|
+
export declare function isRelayedBaseUrl(providerId: string, baseUrl: string): boolean;
|
|
22
|
+
/** 自定义供应商的兜底环境变量名:`AMA_API_KEY_<ID>`(非字母数字转下划线、大写)。 */
|
|
23
|
+
export declare function fallbackEnvKey(providerId: string): string;
|
|
@@ -0,0 +1,148 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* 13 家内置供应商(设计 §3.3)。这里只放供应商级数据;模型来自 catalog/*.json,compat 由
|
|
3
|
+
* 各协议的 detectCompat 推断(openai-compat.ts 的推断表),这里只写推断不出来的东西。
|
|
4
|
+
*
|
|
5
|
+
* 这里的 `api` 是供应商级缺省;目录条目可用 `api` 覆盖(openai 推理模型与 xai 目录模型走
|
|
6
|
+
* openai-responses,见 catalog/*.json)。
|
|
7
|
+
*
|
|
8
|
+
* `baseUrlEnv`(第三波 §2.3):通行约定的 baseUrl 环境变量(OpenAI SDK 的 `OPENAI_BASE_URL`、
|
|
9
|
+
* Claude Code 的 `ANTHROPIC_BASE_URL`),设了就把内置供应商指向中转站,零配置可用;优先级低于
|
|
10
|
+
* config.json 与 auth.json 的 baseUrl。
|
|
11
|
+
*/
|
|
12
|
+
export const BUILTIN_PROVIDERS = [
|
|
13
|
+
{
|
|
14
|
+
id: "anthropic",
|
|
15
|
+
name: "Anthropic",
|
|
16
|
+
api: "anthropic-messages",
|
|
17
|
+
baseUrl: "https://api.anthropic.com",
|
|
18
|
+
baseUrlEnv: "ANTHROPIC_BASE_URL",
|
|
19
|
+
envKeys: ["ANTHROPIC_API_KEY", "AMA_API_KEY_ANTHROPIC"],
|
|
20
|
+
authHeader: "x-api-key",
|
|
21
|
+
requiresApiKey: true,
|
|
22
|
+
},
|
|
23
|
+
{
|
|
24
|
+
id: "openai",
|
|
25
|
+
name: "OpenAI",
|
|
26
|
+
api: "openai-completions",
|
|
27
|
+
baseUrl: "https://api.openai.com/v1",
|
|
28
|
+
baseUrlEnv: "OPENAI_BASE_URL",
|
|
29
|
+
envKeys: ["OPENAI_API_KEY", "AMA_API_KEY_OPENAI"],
|
|
30
|
+
requiresApiKey: true,
|
|
31
|
+
},
|
|
32
|
+
{
|
|
33
|
+
id: "google",
|
|
34
|
+
name: "Google Gemini",
|
|
35
|
+
api: "google-generative-ai",
|
|
36
|
+
baseUrl: "https://generativelanguage.googleapis.com/v1beta",
|
|
37
|
+
envKeys: ["GEMINI_API_KEY", "GOOGLE_API_KEY", "AMA_API_KEY_GOOGLE"],
|
|
38
|
+
authHeader: "x-goog-api-key",
|
|
39
|
+
requiresApiKey: true,
|
|
40
|
+
},
|
|
41
|
+
{
|
|
42
|
+
id: "deepseek",
|
|
43
|
+
name: "DeepSeek",
|
|
44
|
+
api: "openai-completions",
|
|
45
|
+
baseUrl: "https://api.deepseek.com",
|
|
46
|
+
envKeys: ["DEEPSEEK_API_KEY", "AMA_API_KEY_DEEPSEEK"],
|
|
47
|
+
requiresApiKey: true,
|
|
48
|
+
},
|
|
49
|
+
{
|
|
50
|
+
id: "moonshot",
|
|
51
|
+
name: "Moonshot (Kimi)",
|
|
52
|
+
api: "openai-completions",
|
|
53
|
+
baseUrl: "https://api.moonshot.cn/v1",
|
|
54
|
+
envKeys: ["MOONSHOT_API_KEY", "KIMI_API_KEY", "AMA_API_KEY_MOONSHOT"],
|
|
55
|
+
requiresApiKey: true,
|
|
56
|
+
},
|
|
57
|
+
{
|
|
58
|
+
id: "zhipu",
|
|
59
|
+
name: "Zhipu GLM",
|
|
60
|
+
api: "openai-completions",
|
|
61
|
+
baseUrl: "https://open.bigmodel.cn/api/paas/v4",
|
|
62
|
+
envKeys: ["ZHIPU_API_KEY", "ZAI_API_KEY", "AMA_API_KEY_ZHIPU"],
|
|
63
|
+
requiresApiKey: true,
|
|
64
|
+
},
|
|
65
|
+
{
|
|
66
|
+
id: "dashscope",
|
|
67
|
+
name: "Alibaba DashScope (Qwen)",
|
|
68
|
+
api: "openai-completions",
|
|
69
|
+
baseUrl: "https://dashscope.aliyuncs.com/compatible-mode/v1",
|
|
70
|
+
envKeys: ["DASHSCOPE_API_KEY", "QWEN_API_KEY", "AMA_API_KEY_DASHSCOPE"],
|
|
71
|
+
requiresApiKey: true,
|
|
72
|
+
},
|
|
73
|
+
{
|
|
74
|
+
id: "openrouter",
|
|
75
|
+
name: "OpenRouter",
|
|
76
|
+
api: "openai-completions",
|
|
77
|
+
baseUrl: "https://openrouter.ai/api/v1",
|
|
78
|
+
envKeys: ["OPENROUTER_API_KEY", "AMA_API_KEY_OPENROUTER"],
|
|
79
|
+
headers: {
|
|
80
|
+
"HTTP-Referer": "https://github.com/Owlbay/armadra-agent",
|
|
81
|
+
"X-Title": "ama",
|
|
82
|
+
},
|
|
83
|
+
requiresApiKey: true,
|
|
84
|
+
},
|
|
85
|
+
{
|
|
86
|
+
id: "groq",
|
|
87
|
+
name: "Groq",
|
|
88
|
+
api: "openai-completions",
|
|
89
|
+
baseUrl: "https://api.groq.com/openai/v1",
|
|
90
|
+
envKeys: ["GROQ_API_KEY", "AMA_API_KEY_GROQ"],
|
|
91
|
+
requiresApiKey: true,
|
|
92
|
+
},
|
|
93
|
+
{
|
|
94
|
+
id: "xai",
|
|
95
|
+
name: "xAI",
|
|
96
|
+
api: "openai-completions",
|
|
97
|
+
baseUrl: "https://api.x.ai/v1",
|
|
98
|
+
envKeys: ["XAI_API_KEY", "AMA_API_KEY_XAI"],
|
|
99
|
+
requiresApiKey: true,
|
|
100
|
+
},
|
|
101
|
+
{
|
|
102
|
+
id: "mistral",
|
|
103
|
+
name: "Mistral",
|
|
104
|
+
api: "openai-completions",
|
|
105
|
+
baseUrl: "https://api.mistral.ai/v1",
|
|
106
|
+
envKeys: ["MISTRAL_API_KEY", "AMA_API_KEY_MISTRAL"],
|
|
107
|
+
requiresApiKey: true,
|
|
108
|
+
},
|
|
109
|
+
{
|
|
110
|
+
id: "ollama",
|
|
111
|
+
name: "Ollama (local)",
|
|
112
|
+
api: "openai-completions",
|
|
113
|
+
baseUrl: "http://127.0.0.1:11434/v1",
|
|
114
|
+
envKeys: ["OLLAMA_API_KEY", "AMA_API_KEY_OLLAMA"],
|
|
115
|
+
requiresApiKey: false,
|
|
116
|
+
},
|
|
117
|
+
{
|
|
118
|
+
id: "lmstudio",
|
|
119
|
+
name: "LM Studio (local)",
|
|
120
|
+
api: "openai-completions",
|
|
121
|
+
baseUrl: "http://127.0.0.1:1234/v1",
|
|
122
|
+
envKeys: ["AMA_API_KEY_LMSTUDIO"],
|
|
123
|
+
requiresApiKey: false,
|
|
124
|
+
},
|
|
125
|
+
];
|
|
126
|
+
/** 主机名(不含端口);无法解析时返回 undefined。 */
|
|
127
|
+
function hostOf(url) {
|
|
128
|
+
try {
|
|
129
|
+
return new URL(url).hostname.toLowerCase();
|
|
130
|
+
}
|
|
131
|
+
catch {
|
|
132
|
+
return undefined;
|
|
133
|
+
}
|
|
134
|
+
}
|
|
135
|
+
/**
|
|
136
|
+
* 内置供应商的 baseUrl 是否被改到了非官方主机(中转站):此时目录外的 model id 也接受,
|
|
137
|
+
* compat 走保守缺省。非内置供应商返回 false。
|
|
138
|
+
*/
|
|
139
|
+
export function isRelayedBaseUrl(providerId, baseUrl) {
|
|
140
|
+
const builtin = BUILTIN_PROVIDERS.find((p) => p.id === providerId);
|
|
141
|
+
if (builtin === undefined || builtin.requiresApiKey === false)
|
|
142
|
+
return false;
|
|
143
|
+
return hostOf(baseUrl) !== hostOf(builtin.baseUrl);
|
|
144
|
+
}
|
|
145
|
+
/** 自定义供应商的兜底环境变量名:`AMA_API_KEY_<ID>`(非字母数字转下划线、大写)。 */
|
|
146
|
+
export function fallbackEnvKey(providerId) {
|
|
147
|
+
return `AMA_API_KEY_${providerId.replace(/[^a-zA-Z0-9]/g, "_").toUpperCase()}`;
|
|
148
|
+
}
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* 由 catalog/*.json 生成,勿手改。重新生成:
|
|
3
|
+
* UPDATE_CATALOG=1 pnpm vitest run src/ai/providers/catalog.test.ts
|
|
4
|
+
*/
|
|
5
|
+
export const CATALOG_SOURCES = {
|
|
6
|
+
anthropic: '{"version":1,"provider":"anthropic","models":[{"id":"claude-fable-5-1","name":"Claude Fable 5.1","contextWindow":1000000,"maxTokens":128000,"reasoning":true,"input":["text","image"],"cost":{"input":10,"output":50,"cacheRead":0.25,"cacheWrite":12.5},"thinkingLevelMap":{"off":null,"xhigh":"xhigh"},"promptCache":{"short":300,"long":3600,"minTokens":512},"compat":{"adaptiveThinking":true}},{"id":"claude-fable-5","name":"Claude Fable 5","contextWindow":1000000,"maxTokens":128000,"reasoning":true,"input":["text","image"],"cost":{"input":10,"output":50,"cacheRead":1,"cacheWrite":12.5},"thinkingLevelMap":{"off":null,"xhigh":"xhigh"},"promptCache":{"short":300,"long":3600,"minTokens":512},"compat":{"adaptiveThinking":true}},{"id":"claude-opus-5-5","name":"Claude Opus 5.5","contextWindow":1000000,"maxTokens":128000,"reasoning":true,"input":["text","image"],"cost":{"input":4,"output":20,"cacheRead":0.2,"cacheWrite":5},"thinkingLevelMap":{"off":null,"minimal":null,"low":"low","medium":"medium","high":"high","xhigh":"xhigh"},"promptCache":{"short":300,"long":3600,"minTokens":512},"compat":{"adaptiveThinking":true}},{"id":"claude-opus-5","name":"Claude Opus 5","contextWindow":1000000,"maxTokens":128000,"reasoning":true,"input":["text","image"],"cost":{"input":5,"output":25,"cacheRead":0.5,"cacheWrite":6.25},"thinkingLevelMap":{"off":null,"xhigh":"xhigh"},"promptCache":{"short":300,"long":3600,"minTokens":512},"compat":{"adaptiveThinking":true}},{"id":"claude-opus-4-8","name":"Claude Opus 4.8","contextWindow":1000000,"maxTokens":128000,"reasoning":true,"input":["text","image"],"cost":{"input":5,"output":25,"cacheRead":0.5,"cacheWrite":6.25},"thinkingLevelMap":{"xhigh":"xhigh"},"promptCache":{"short":300,"long":3600,"minTokens":1024},"compat":{"adaptiveThinking":true}},{"id":"claude-opus-4-7","name":"Claude Opus 4.7","contextWindow":1000000,"maxTokens":128000,"reasoning":true,"input":["text","image"],"cost":{"input":5,"output":25,"cacheRead":0.5,"cacheWrite":6.25},"thinkingLevelMap":{"xhigh":"xhigh"},"promptCache":{"short":300,"long":3600,"minTokens":2048},"compat":{"adaptiveThinking":true}},{"id":"claude-opus-4-6","name":"Claude Opus 4.6","contextWindow":1000000,"maxTokens":128000,"reasoning":true,"input":["text","image"],"cost":{"input":5,"output":25,"cacheRead":0.5,"cacheWrite":6.25},"promptCache":{"short":300,"long":3600,"minTokens":4096},"compat":{"adaptiveThinking":true}},{"id":"claude-sonnet-5-5","name":"Claude Sonnet 5.5","contextWindow":1000000,"maxTokens":128000,"reasoning":true,"input":["text","image"],"cost":{"input":2,"output":10,"cacheRead":0.2,"cacheWrite":2.5},"thinkingLevelMap":{"off":null,"minimal":null,"low":"low","medium":"medium","high":"high","xhigh":"xhigh"},"promptCache":{"short":300,"long":3600,"minTokens":512},"compat":{"adaptiveThinking":true}},{"id":"claude-sonnet-5","name":"Claude Sonnet 5","contextWindow":1000000,"maxTokens":128000,"reasoning":true,"input":["text","image"],"cost":{"input":2,"output":10,"cacheRead":0.2,"cacheWrite":2.5},"thinkingLevelMap":{"xhigh":"xhigh"},"promptCache":{"short":300,"long":3600,"minTokens":1024},"compat":{"adaptiveThinking":true}},{"id":"claude-sonnet-4-6","name":"Claude Sonnet 4.6","contextWindow":1000000,"maxTokens":128000,"reasoning":true,"input":["text","image"],"cost":{"input":3,"output":15,"cacheRead":0.3,"cacheWrite":3.75},"promptCache":{"short":300,"long":3600,"minTokens":1024},"compat":{"adaptiveThinking":true}},{"id":"claude-sonnet-4-5","name":"Claude Sonnet 4.5 (latest)","contextWindow":1000000,"maxTokens":64000,"reasoning":true,"input":["text","image"],"cost":{"input":3,"output":15,"cacheRead":0.3,"cacheWrite":3.75},"promptCache":{"short":300,"long":3600,"minTokens":1024}},{"id":"claude-haiku-4-5","name":"Claude Haiku 4.5 (latest)","contextWindow":200000,"maxTokens":64000,"reasoning":true,"input":["text","image"],"cost":{"input":1,"output":5,"cacheRead":0.1,"cacheWrite":1.25},"promptCache":{"short":300,"long":3600,"minTokens":4096}},{"id":"claude-opus-4-5","name":"Claude Opus 4.5 (latest)","contextWindow":200000,"maxTokens":64000,"reasoning":true,"input":["text","image"],"cost":{"input":5,"output":25,"cacheRead":0.5,"cacheWrite":6.25},"promptCache":{"short":300,"long":3600,"minTokens":4096}}]}',
|
|
7
|
+
dashscope: '{"version":1,"provider":"dashscope","models":[{"id":"qwen3.8-max","name":"Qwen3.8 Max","contextWindow":1000000,"maxTokens":131072,"reasoning":true,"input":["text","image"],"thinkingLevelMap":{"off":null,"minimal":null,"low":"low","medium":"medium","high":null,"xhigh":"xhigh"},"compat":{"supportsReasoningEffort":true}},{"id":"qwen3.8-flash","name":"Qwen3.8 Flash","contextWindow":1000000,"maxTokens":131072,"reasoning":true,"input":["text","image"],"thinkingLevelMap":{"off":null,"minimal":null,"low":"low","medium":"medium","high":null,"xhigh":"xhigh"},"compat":{"supportsReasoningEffort":true}},{"id":"qwen3.7-max","name":"Qwen3.7 Max","contextWindow":1000000,"maxTokens":131072,"reasoning":true,"input":["text"],"compat":{"supportsReasoningEffort":false}},{"id":"qwen3.7-plus","name":"Qwen3.7 Plus","contextWindow":1000000,"maxTokens":65536,"reasoning":true,"input":["text","image"],"compat":{"supportsReasoningEffort":false}},{"id":"qwen3.6-plus","name":"Qwen3.6 Plus","contextWindow":1000000,"maxTokens":65536,"reasoning":true,"input":["text","image"],"compat":{"supportsReasoningEffort":false}},{"id":"qwen3.6-flash","name":"Qwen3.6 Flash","contextWindow":1000000,"maxTokens":65536,"reasoning":true,"input":["text","image"],"compat":{"supportsReasoningEffort":false}}]}',
|
|
8
|
+
deepseek: '{"version":1,"provider":"deepseek","models":[{"id":"deepseek-v4-pro","name":"DeepSeek V4 Pro","contextWindow":1000000,"maxTokens":384000,"reasoning":true,"input":["text"],"cost":{"input":1.32,"output":3.96,"cacheRead":0.044,"cacheWrite":0},"thinkingLevelMap":{"minimal":null,"low":null,"medium":null,"high":"high"}},{"id":"deepseek-flash","name":"DeepSeek V4.1 Flash","contextWindow":1000000,"maxTokens":384000,"reasoning":true,"input":["text","image"],"cost":{"input":0.3,"output":1.2,"cacheRead":0.006,"cacheWrite":0},"thinkingLevelMap":{"minimal":null,"low":"low","medium":null,"high":"high"}}]}',
|
|
9
|
+
google: '{"version":1,"provider":"google","models":[{"id":"gemini-3.8-flash","name":"Gemini 3.8 Flash","contextWindow":1048576,"maxTokens":65536,"reasoning":true,"input":["text","image"],"cost":{"input":0.75,"output":3.75,"cacheRead":0.075,"cacheWrite":0},"thinkingLevelMap":{"off":null,"minimal":null,"low":"low","medium":"medium","high":"high","xhigh":null}},{"id":"gemini-3.7-flash","name":"Gemini 3.7 Flash","contextWindow":1048576,"maxTokens":65536,"reasoning":true,"input":["text","image"],"cost":{"input":0.75,"output":3.75,"cacheRead":0.075,"cacheWrite":0},"thinkingLevelMap":{"off":null,"minimal":null,"low":"low","medium":"medium","high":"high","xhigh":null}},{"id":"gemini-3.5-flash","name":"Gemini 3.5 Flash","contextWindow":1048576,"maxTokens":65536,"reasoning":true,"input":["text","image"],"cost":{"input":1.5,"output":9,"cacheRead":0.15,"cacheWrite":0},"thinkingLevelMap":{"off":null,"minimal":"minimal","low":"low","medium":"medium","high":"high","xhigh":null}},{"id":"gemini-3.5-flash-lite","name":"Gemini 3.5 Flash Lite","contextWindow":1048576,"maxTokens":65536,"reasoning":true,"input":["text","image"],"cost":{"input":0.3,"output":2.5,"cacheRead":0.03,"cacheWrite":0},"thinkingLevelMap":{"off":null,"minimal":"minimal","low":"low","medium":"medium","high":"high","xhigh":null}},{"id":"gemini-3.1-pro-preview","name":"Gemini 3.1 Pro Preview","contextWindow":1048576,"maxTokens":65536,"reasoning":true,"input":["text","image"],"cost":{"input":2,"output":12,"cacheRead":0.2,"cacheWrite":0},"thinkingLevelMap":{"off":null,"minimal":null,"low":"low","medium":"medium","high":"high","xhigh":null}},{"id":"gemini-3-flash-preview","name":"Gemini 3 Flash Preview","contextWindow":1048576,"maxTokens":65536,"reasoning":true,"input":["text","image"],"cost":{"input":0.5,"output":3,"cacheRead":0.05,"cacheWrite":0},"thinkingLevelMap":{"off":null,"minimal":"minimal","low":"low","medium":"medium","high":"high","xhigh":null}},{"id":"gemini-2.5-pro","name":"Gemini 2.5 Pro","contextWindow":1048576,"maxTokens":65536,"reasoning":true,"input":["text","image"],"cost":{"input":1.25,"output":10,"cacheRead":0.125,"cacheWrite":0},"thinkingLevelMap":{"off":null,"minimal":128,"low":2048,"medium":8192,"high":32768}},{"id":"gemini-2.5-flash","name":"Gemini 2.5 Flash","contextWindow":1048576,"maxTokens":65536,"reasoning":true,"input":["text","image"],"cost":{"input":0.3,"output":2.5,"cacheRead":0.03,"cacheWrite":0},"thinkingLevelMap":{"minimal":128,"low":2048,"medium":8192,"high":24576}},{"id":"gemini-2.5-flash-lite","name":"Gemini 2.5 Flash-Lite","contextWindow":1048576,"maxTokens":65536,"reasoning":true,"input":["text","image"],"cost":{"input":0.1,"output":0.4,"cacheRead":0.01,"cacheWrite":0},"thinkingLevelMap":{"minimal":512,"low":2048,"medium":8192,"high":24576}}]}',
|
|
10
|
+
groq: '{"version":1,"provider":"groq","models":[{"id":"openai/gpt-oss-120b","name":"GPT OSS 120B","contextWindow":131072,"maxTokens":65536,"reasoning":true,"input":["text"],"cost":{"input":0.15,"output":0.6,"cacheRead":0.075,"cacheWrite":0},"thinkingLevelMap":{"off":null,"minimal":null,"low":"low","medium":"medium","high":"high","xhigh":null}},{"id":"openai/gpt-oss-20b","name":"GPT OSS 20B","contextWindow":131072,"maxTokens":65536,"reasoning":true,"input":["text"],"cost":{"input":0.075,"output":0.3,"cacheRead":0.0375,"cacheWrite":0},"thinkingLevelMap":{"off":null,"minimal":null,"low":"low","medium":"medium","high":"high","xhigh":null}},{"id":"openai/gpt-oss-safeguard-20b","name":"Safety GPT OSS 20B","contextWindow":131072,"maxTokens":65536,"reasoning":true,"input":["text"],"cost":{"input":0.075,"output":0.3,"cacheRead":0,"cacheWrite":0},"thinkingLevelMap":{"off":null,"minimal":null,"low":"low","medium":"medium","high":"high","xhigh":null}},{"id":"qwen/qwen3.8-27b","name":"Qwen3.8 27B","contextWindow":131042,"maxTokens":16384,"reasoning":true,"input":["text","image"],"cost":{"input":0.8,"output":4,"cacheRead":0,"cacheWrite":0},"thinkingLevelMap":{"off":"none","minimal":null,"low":"low","medium":"medium","high":"high","xhigh":null}},{"id":"qwen/qwen3.6-27b","name":"Qwen3.6 27B","contextWindow":131072,"maxTokens":16384,"reasoning":true,"input":["text","image"],"cost":{"input":0.6,"output":3,"cacheRead":0.3,"cacheWrite":0},"thinkingLevelMap":{"off":"none","minimal":null,"low":null,"medium":null,"high":"default","xhigh":null}},{"id":"llama-3.3-70b-versatile","name":"Llama 3.3 70B","contextWindow":131072,"maxTokens":32768,"reasoning":false,"input":["text"],"cost":{"input":0.59,"output":0.79,"cacheRead":0,"cacheWrite":0}},{"id":"llama-3.1-8b-instant","name":"Llama 3.1 8B","contextWindow":131072,"maxTokens":131072,"reasoning":false,"input":["text"],"cost":{"input":0.05,"output":0.08,"cacheRead":0,"cacheWrite":0}}]}',
|
|
11
|
+
lmstudio: '{"version":1,"provider":"lmstudio","models":[]}',
|
|
12
|
+
mistral: '{"version":1,"provider":"mistral","models":[{"id":"mistral-large-latest","name":"Mistral Large (latest)","contextWindow":262144,"maxTokens":262144,"reasoning":false,"input":["text","image"],"cost":{"input":0.5,"output":1.5,"cacheRead":0.05,"cacheWrite":0}},{"id":"mistral-medium-latest","name":"Mistral Medium (latest)","contextWindow":262144,"maxTokens":262144,"reasoning":true,"input":["text","image"],"cost":{"input":1.5,"output":7.5,"cacheRead":0.15,"cacheWrite":0},"thinkingLevelMap":{"off":"none","minimal":null,"low":null,"medium":null,"high":"high","xhigh":null}},{"id":"mistral-small-latest","name":"Mistral Small (latest)","contextWindow":256000,"maxTokens":256000,"reasoning":true,"input":["text","image"],"cost":{"input":0.15,"output":0.6,"cacheRead":0.015,"cacheWrite":0},"thinkingLevelMap":{"off":"none","minimal":null,"low":null,"medium":null,"high":"high","xhigh":null}},{"id":"magistral-medium-latest","name":"Magistral Medium (latest)","contextWindow":128000,"maxTokens":16384,"reasoning":true,"input":["text"],"cost":{"input":2,"output":5,"cacheRead":0.2,"cacheWrite":0}},{"id":"codestral-latest","name":"Codestral (latest)","contextWindow":256000,"maxTokens":4096,"reasoning":false,"input":["text"],"cost":{"input":0.3,"output":0.9,"cacheRead":0.03,"cacheWrite":0}},{"id":"devstral-latest","name":"Devstral 2","contextWindow":262144,"maxTokens":262144,"reasoning":false,"input":["text"],"cost":{"input":0.4,"output":2,"cacheRead":0.04,"cacheWrite":0}},{"id":"devstral-medium-latest","name":"Devstral 2 (latest)","contextWindow":262144,"maxTokens":262144,"reasoning":false,"input":["text"],"cost":{"input":0.4,"output":2,"cacheRead":0.04,"cacheWrite":0}},{"id":"ministral-8b-latest","name":"Ministral 8B (latest)","contextWindow":128000,"maxTokens":128000,"reasoning":false,"input":["text"],"cost":{"input":0.1,"output":0.1,"cacheRead":0.01,"cacheWrite":0}},{"id":"pixtral-large-latest","name":"Pixtral Large (latest)","contextWindow":128000,"maxTokens":128000,"reasoning":false,"input":["text","image"],"cost":{"input":2,"output":6,"cacheRead":0.2,"cacheWrite":0}}]}',
|
|
13
|
+
moonshot: '{"version":1,"provider":"moonshot","models":[{"id":"kimi-k3","name":"Kimi K3","contextWindow":1048576,"maxTokens":1048576,"reasoning":true,"input":["text","image"],"cost":{"input":3,"output":15,"cacheRead":0.3,"cacheWrite":0},"thinkingLevelMap":{"off":null,"minimal":null,"low":"low","medium":null,"high":"high","xhigh":null},"promptCache":{"short":300},"compat":{"supportsReasoningEffort":true}},{"id":"kimi-k2.7-code","name":"Kimi K2.7 Code","contextWindow":262144,"maxTokens":262144,"reasoning":true,"input":["text","image"],"cost":{"input":0.95,"output":4,"cacheRead":0.19,"cacheWrite":0},"thinkingLevelMap":{"off":null},"promptCache":{"short":300},"compat":{"supportsReasoningEffort":false}},{"id":"kimi-k2.7-code-highspeed","name":"Kimi K2.7 Code HighSpeed","contextWindow":262144,"maxTokens":262144,"reasoning":true,"input":["text","image"],"cost":{"input":1.9,"output":8,"cacheRead":0.38,"cacheWrite":0},"thinkingLevelMap":{"off":null},"promptCache":{"short":300},"compat":{"supportsReasoningEffort":false}},{"id":"kimi-k2.6","name":"Kimi K2.6","contextWindow":262144,"maxTokens":262144,"reasoning":true,"input":["text","image"],"cost":{"input":0.95,"output":4,"cacheRead":0.16,"cacheWrite":0},"promptCache":{"short":300},"compat":{"supportsReasoningEffort":false}}]}',
|
|
14
|
+
ollama: '{"version":1,"provider":"ollama","models":[]}',
|
|
15
|
+
openai: '{"version":1,"provider":"openai","models":[{"id":"gpt-6.1-sol","name":"GPT-6.1 Sol","api":"openai-responses","contextWindow":272000,"maxTokens":128000,"reasoning":true,"input":["text","image"],"cost":{"input":2,"output":10,"cacheRead":0.1,"cacheWrite":2.5,"tiers":[{"inputTokensAbove":272000,"input":4,"output":15,"cacheRead":0.2,"cacheWrite":5}]},"thinkingLevelMap":{"off":null,"minimal":null,"low":"low","medium":"medium","high":"high","xhigh":"xhigh"},"promptCache":{"short":300,"long":86400,"minTokens":1024}},{"id":"gpt-6-sol","name":"GPT-6 Sol","api":"openai-responses","contextWindow":272000,"maxTokens":128000,"reasoning":true,"input":["text","image"],"cost":{"input":2,"output":10,"cacheRead":0.2,"cacheWrite":2.5,"tiers":[{"inputTokensAbove":272000,"input":4,"output":15,"cacheRead":0.4,"cacheWrite":5}]},"thinkingLevelMap":{"off":"none","minimal":null,"low":"low","medium":"medium","high":"high","xhigh":"xhigh"},"promptCache":{"short":300,"long":86400,"minTokens":1024}},{"id":"gpt-6-luna","name":"GPT-6 Luna","api":"openai-responses","contextWindow":272000,"maxTokens":128000,"reasoning":true,"input":["text","image"],"cost":{"input":0.1,"output":0.5,"cacheRead":0.01,"cacheWrite":0.125,"tiers":[{"inputTokensAbove":272000,"input":0.2,"output":0.75,"cacheRead":0.02,"cacheWrite":0.25}]},"thinkingLevelMap":{"off":"none","minimal":null,"low":"low","medium":"medium","high":"high","xhigh":"xhigh"},"promptCache":{"short":300,"long":86400,"minTokens":1024}},{"id":"gpt-6-astra","name":"GPT-6 Astra","api":"openai-responses","contextWindow":272000,"maxTokens":128000,"reasoning":true,"input":["text","image"],"cost":{"input":10,"output":50,"cacheRead":1,"cacheWrite":12.5,"tiers":[{"inputTokensAbove":272000,"input":20,"output":75,"cacheRead":2,"cacheWrite":25}]},"thinkingLevelMap":{"off":null,"minimal":null,"low":"low","medium":"medium","high":"high","xhigh":"xhigh"},"promptCache":{"short":300,"long":86400,"minTokens":1024}},{"id":"gpt-5.5","name":"GPT-5.5","api":"openai-responses","contextWindow":272000,"maxTokens":128000,"reasoning":true,"input":["text","image"],"cost":{"input":5,"output":30,"cacheRead":0.5,"cacheWrite":0,"tiers":[{"inputTokensAbove":272000,"input":10,"output":45,"cacheRead":1,"cacheWrite":0}]},"thinkingLevelMap":{"off":"none","minimal":null,"low":"low","medium":"medium","high":"high","xhigh":"xhigh"},"promptCache":{"short":300,"long":86400,"minTokens":1024}},{"id":"gpt-5.4","name":"GPT-5.4","api":"openai-responses","contextWindow":272000,"maxTokens":128000,"reasoning":true,"input":["text","image"],"cost":{"input":2.5,"output":15,"cacheRead":0.25,"cacheWrite":0,"tiers":[{"inputTokensAbove":272000,"input":5,"output":22.5,"cacheRead":0.5,"cacheWrite":0}]},"thinkingLevelMap":{"off":"none","minimal":null,"low":"low","medium":"medium","high":"high","xhigh":"xhigh"},"promptCache":{"short":300,"long":86400,"minTokens":1024}},{"id":"gpt-5.4-mini","name":"GPT-5.4 mini","api":"openai-responses","contextWindow":400000,"maxTokens":128000,"reasoning":true,"input":["text","image"],"cost":{"input":0.75,"output":4.5,"cacheRead":0.075,"cacheWrite":0},"thinkingLevelMap":{"off":"none","minimal":null,"low":"low","medium":"medium","high":"high","xhigh":"xhigh"},"promptCache":{"short":300,"long":86400,"minTokens":1024}},{"id":"gpt-5.4-nano","name":"GPT-5.4 nano","api":"openai-responses","contextWindow":400000,"maxTokens":128000,"reasoning":true,"input":["text","image"],"cost":{"input":0.2,"output":1.25,"cacheRead":0.02,"cacheWrite":0},"thinkingLevelMap":{"off":"none","minimal":null,"low":"low","medium":"medium","high":"high","xhigh":"xhigh"},"promptCache":{"short":300,"long":86400,"minTokens":1024}},{"id":"gpt-5","name":"GPT-5","api":"openai-responses","contextWindow":400000,"maxTokens":128000,"reasoning":true,"input":["text","image"],"cost":{"input":1.25,"output":10,"cacheRead":0.125,"cacheWrite":0},"thinkingLevelMap":{"off":null,"minimal":"minimal","low":"low","medium":"medium","high":"high","xhigh":null},"promptCache":{"short":300,"long":86400,"minTokens":1024}},{"id":"gpt-5-mini","name":"GPT-5 Mini","api":"openai-responses","contextWindow":400000,"maxTokens":128000,"reasoning":true,"input":["text","image"],"cost":{"input":0.25,"output":2,"cacheRead":0.025,"cacheWrite":0},"thinkingLevelMap":{"off":null,"minimal":"minimal","low":"low","medium":"medium","high":"high","xhigh":null},"promptCache":{"short":300,"long":86400,"minTokens":1024}},{"id":"gpt-4.1","name":"GPT-4.1","contextWindow":1047576,"maxTokens":32768,"reasoning":false,"input":["text","image"],"cost":{"input":2,"output":8,"cacheRead":0.5,"cacheWrite":0},"promptCache":{"short":300,"long":86400,"minTokens":1024}},{"id":"gpt-4o","name":"GPT-4o","contextWindow":128000,"maxTokens":16384,"reasoning":false,"input":["text","image"],"cost":{"input":2.5,"output":10,"cacheRead":1.25,"cacheWrite":0},"promptCache":{"short":300,"long":86400,"minTokens":1024}},{"id":"gpt-4o-mini","name":"GPT-4o mini","contextWindow":128000,"maxTokens":16384,"reasoning":false,"input":["text","image"],"cost":{"input":0.15,"output":0.6,"cacheRead":0.075,"cacheWrite":0},"promptCache":{"short":300,"long":86400,"minTokens":1024}},{"id":"o4-mini","name":"o4-mini","api":"openai-responses","contextWindow":200000,"maxTokens":100000,"reasoning":true,"input":["text","image"],"cost":{"input":1.1,"output":4.4,"cacheRead":0.275,"cacheWrite":0},"thinkingLevelMap":{"off":null,"minimal":null,"low":"low","medium":"medium","high":"high","xhigh":null},"promptCache":{"short":300,"long":86400,"minTokens":1024}},{"id":"o3","name":"o3","api":"openai-responses","contextWindow":200000,"maxTokens":100000,"reasoning":true,"input":["text","image"],"cost":{"input":2,"output":8,"cacheRead":0.5,"cacheWrite":0},"thinkingLevelMap":{"off":null,"minimal":null,"low":"low","medium":"medium","high":"high","xhigh":null},"promptCache":{"short":300,"long":86400,"minTokens":1024}}]}',
|
|
16
|
+
openrouter: '{"version":1,"provider":"openrouter","models":[{"id":"anthropic/claude-opus-5.5","name":"Anthropic: Claude Opus 5.5","contextWindow":1000000,"maxTokens":128000,"reasoning":true,"input":["text","image"],"cost":{"input":4,"output":20,"cacheRead":0.2,"cacheWrite":5},"thinkingLevelMap":{"off":null,"minimal":null,"low":"low","medium":"medium","high":"high","xhigh":"xhigh"}},{"id":"anthropic/claude-sonnet-5.5","name":"Anthropic: Claude Sonnet 5.5","contextWindow":1000000,"maxTokens":128000,"reasoning":true,"input":["text","image"],"cost":{"input":2,"output":10,"cacheRead":0.2,"cacheWrite":2.5},"thinkingLevelMap":{"off":null,"minimal":null,"low":"low","medium":"medium","high":"high","xhigh":"xhigh"}},{"id":"anthropic/claude-haiku-4.5","name":"Anthropic: Claude Haiku 4.5","contextWindow":200000,"maxTokens":64000,"reasoning":true,"input":["text","image"],"cost":{"input":1,"output":5,"cacheRead":0.1,"cacheWrite":1.25}},{"id":"openai/gpt-6-sol","name":"OpenAI: GPT-6 Sol","contextWindow":1050000,"maxTokens":128000,"reasoning":true,"input":["text","image"],"cost":{"input":2,"output":10,"cacheRead":0.2,"cacheWrite":2.5},"thinkingLevelMap":{"off":"none","minimal":null,"low":"low","medium":"medium","high":"high","xhigh":"xhigh"},"compat":{"supportsMidConvoSystemMessages":true}},{"id":"openai/gpt-5.5","name":"OpenAI: GPT-5.5","contextWindow":1050000,"maxTokens":128000,"reasoning":true,"input":["text","image"],"cost":{"input":5,"output":30,"cacheRead":0.5,"cacheWrite":0},"thinkingLevelMap":{"off":"none","minimal":null,"low":"low","medium":"medium","high":"high","xhigh":"xhigh"},"compat":{"supportsMidConvoSystemMessages":true}},{"id":"openai/gpt-5.4-mini","name":"OpenAI: GPT-5.4 Mini","contextWindow":400000,"maxTokens":128000,"reasoning":true,"input":["text","image"],"cost":{"input":0.75,"output":4.5,"cacheRead":0.075,"cacheWrite":0},"thinkingLevelMap":{"off":"none","minimal":null,"low":"low","medium":"medium","high":"high","xhigh":"xhigh"},"compat":{"supportsMidConvoSystemMessages":true}},{"id":"google/gemini-3.8-flash","name":"Google: Gemini 3.8 Flash","contextWindow":1048576,"maxTokens":65536,"reasoning":true,"input":["text","image"],"cost":{"input":0.75,"output":3.75,"cacheRead":0.075,"cacheWrite":0.041667},"thinkingLevelMap":{"off":null,"minimal":null,"low":"low","medium":"medium","high":"high","xhigh":null}},{"id":"google/gemini-3.1-pro-preview","name":"Google: Gemini 3.1 Pro Preview","contextWindow":1048576,"maxTokens":65536,"reasoning":true,"input":["text","image"],"cost":{"input":2,"output":12,"cacheRead":0.2,"cacheWrite":0.375},"thinkingLevelMap":{"off":null,"minimal":null,"low":"low","medium":"medium","high":"high","xhigh":null}},{"id":"deepseek/deepseek-v4-pro","name":"DeepSeek: DeepSeek V4 Pro 0423","contextWindow":1024000,"maxTokens":384000,"reasoning":true,"input":["text"],"cost":{"input":0.2088,"output":0.4176,"cacheRead":0.0174,"cacheWrite":0},"thinkingLevelMap":{"off":"none","minimal":null,"low":null,"medium":null,"high":"high","xhigh":"xhigh"},"compat":{"requiresReasoningContentOnAssistantMessages":true}},{"id":"moonshotai/kimi-k3","name":"MoonshotAI: Kimi K3","contextWindow":1048576,"maxTokens":131072,"reasoning":true,"input":["text","image"],"cost":{"input":0.6635,"output":10,"cacheRead":0.6635,"cacheWrite":0},"thinkingLevelMap":{"off":"none","minimal":null,"low":"low","medium":null,"high":"high","xhigh":null}},{"id":"qwen/qwen3.7-max","name":"Qwen: Qwen3.7 Max","contextWindow":1000000,"maxTokens":131072,"reasoning":true,"input":["text"],"cost":{"input":1.475,"output":4.425,"cacheRead":0.295,"cacheWrite":1.84375}},{"id":"z-ai/glm-5.3","name":"Z.ai: GLM 5.3","contextWindow":1048576,"maxTokens":943718,"reasoning":true,"input":["text"],"cost":{"input":0.2219,"output":3.39,"cacheRead":0.1775,"cacheWrite":0},"thinkingLevelMap":{"off":null,"minimal":null,"low":"low","medium":null,"high":"high","xhigh":null}},{"id":"x-ai/grok-4.7","name":"SpaceXAI: Grok 4.7","contextWindow":500000,"maxTokens":450000,"reasoning":true,"input":["text","image"],"cost":{"input":2,"output":6,"cacheRead":0.5,"cacheWrite":0},"thinkingLevelMap":{"off":null,"minimal":null,"low":"low","medium":"medium","high":"high","xhigh":"xhigh"}}]}',
|
|
17
|
+
xai: '{"version":1,"provider":"xai","models":[{"id":"grok-4.7","name":"Grok 4.7","api":"openai-responses","contextWindow":500000,"maxTokens":500000,"reasoning":true,"input":["text","image"],"cost":{"input":2,"output":6,"cacheRead":0.5,"cacheWrite":0,"tiers":[{"inputTokensAbove":200000,"input":4,"output":12,"cacheRead":1,"cacheWrite":0}]},"thinkingLevelMap":{"off":null,"minimal":null,"low":"low","medium":"medium","high":"high","xhigh":"xhigh"}},{"id":"grok-4.6","name":"Grok 4.6","api":"openai-responses","contextWindow":500000,"maxTokens":500000,"reasoning":true,"input":["text","image"],"cost":{"input":2,"output":6,"cacheRead":0.5,"cacheWrite":0,"tiers":[{"inputTokensAbove":200000,"input":4,"output":12,"cacheRead":1,"cacheWrite":0}]},"thinkingLevelMap":{"off":null,"minimal":null,"low":"low","medium":"medium","high":"high","xhigh":"xhigh"}},{"id":"grok-4.5","name":"Grok 4.5","api":"openai-responses","contextWindow":500000,"maxTokens":500000,"reasoning":true,"input":["text","image"],"cost":{"input":2,"output":6,"cacheRead":0.3,"cacheWrite":0,"tiers":[{"inputTokensAbove":200000,"input":4,"output":12,"cacheRead":0.6,"cacheWrite":0}]},"thinkingLevelMap":{"off":null,"minimal":null,"low":"low","medium":"medium","high":"high","xhigh":null}},{"id":"grok-4.3","name":"Grok 4.3","api":"openai-responses","contextWindow":1000000,"maxTokens":30000,"reasoning":true,"input":["text","image"],"cost":{"input":1.25,"output":2.5,"cacheRead":0.2,"cacheWrite":0,"tiers":[{"inputTokensAbove":200000,"input":2.5,"output":5,"cacheRead":0.4,"cacheWrite":0}]},"thinkingLevelMap":{"off":"none","minimal":null,"low":"low","medium":"medium","high":"high","xhigh":null}}]}',
|
|
18
|
+
zhipu: '{"version":1,"provider":"zhipu","models":[{"id":"glm-5.3","name":"GLM-5.3","contextWindow":1000000,"maxTokens":131072,"reasoning":true,"input":["text"],"cost":{"input":1.4,"output":4.4,"cacheRead":0.26,"cacheWrite":0},"thinkingLevelMap":{"off":null,"minimal":null,"low":"low","medium":null,"high":"high","xhigh":null},"compat":{"supportsReasoningEffort":true}},{"id":"glm-5.3-flash","name":"GLM-5.3-Flash","contextWindow":1000000,"maxTokens":131072,"reasoning":true,"input":["text","image"],"cost":{"input":0.15,"output":0.5,"cacheRead":0.03,"cacheWrite":0},"thinkingLevelMap":{"off":null,"minimal":null,"low":"low","medium":null,"high":"high","xhigh":null},"compat":{"supportsReasoningEffort":true}},{"id":"glm-5.2","name":"GLM-5.2","contextWindow":1000000,"maxTokens":131072,"reasoning":true,"input":["text"],"cost":{"input":1.4,"output":4.4,"cacheRead":0.26,"cacheWrite":0},"thinkingLevelMap":{"off":"none","minimal":null,"low":null,"medium":null,"high":"high","xhigh":null},"compat":{"supportsReasoningEffort":true}},{"id":"glm-5-turbo","name":"GLM-5-Turbo","contextWindow":200000,"maxTokens":131072,"reasoning":true,"input":["text"],"cost":{"input":1.2,"output":4,"cacheRead":0.24,"cacheWrite":0},"compat":{"supportsReasoningEffort":false}},{"id":"glm-4.7","name":"GLM-4.7","contextWindow":204800,"maxTokens":131072,"reasoning":true,"input":["text"],"cost":{"input":0.6,"output":2.2,"cacheRead":0.11,"cacheWrite":0},"compat":{"supportsReasoningEffort":false}}]}',
|
|
19
|
+
};
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* 模型目录(设计 §3.4):`catalog/*.json` 是数据源(人工校对、PR 更新),随包携带。
|
|
3
|
+
*
|
|
4
|
+
* 运行时零依赖、bundle 为单文件,不能在运行时读 JSON 文件;`catalog-data.ts` 是由 JSON 生成
|
|
5
|
+
* 的字符串表(`UPDATE_CATALOG=1 pnpm vitest run src/ai/providers/catalog.test.ts` 重新生成,
|
|
6
|
+
* 测试守住两者一致)。本模块解析并校验它,另提供覆盖合并。
|
|
7
|
+
*
|
|
8
|
+
* 必填字段:id、name、maxTokens、reasoning;contextWindow 与 cost「宁缺不猜」——数据源里
|
|
9
|
+
* 不确定的就不写(缺 contextWindow → 关自动压缩并警告;缺 cost → 显示 `$?`)。`promptCache`
|
|
10
|
+
* (TTL 秒数与最小可缓存长度)同样只写有公开依据的值(第三波 §1.4),留空 = 不承诺。
|
|
11
|
+
*/
|
|
12
|
+
import type { Model, ModelCatalogFile } from "../types.js";
|
|
13
|
+
export type CatalogModel = ModelCatalogFile["models"][number];
|
|
14
|
+
/** 校验一个模型条目,返回问题列表(空 = 合法)。 */
|
|
15
|
+
export declare function checkCatalogModel(value: unknown, path: string): string[];
|
|
16
|
+
export declare function parseCatalogFile(value: unknown, source: string): ModelCatalogFile;
|
|
17
|
+
/** 内置目录:供应商 id → 模型条目(深拷贝,调用方可随意修改)。 */
|
|
18
|
+
export declare function loadBuiltinCatalog(): Map<string, CatalogModel[]>;
|
|
19
|
+
/** 目录条目 → Model(补 provider / api 与缺省 input)。 */
|
|
20
|
+
export declare function toModel(entry: CatalogModel, provider: string, api: Model["api"]): Model;
|
|
21
|
+
/** 自定义模型缺省:maxTokens 8192、reasoning false、input ["text"]、name = id;不猜 contextWindow。 */
|
|
22
|
+
export declare function withCustomDefaults(entry: Partial<Omit<Model, "provider" | "api">> & {
|
|
23
|
+
id: string;
|
|
24
|
+
}, provider: string, api: Model["api"]): Model;
|
|
25
|
+
/** 只改元数据:浅合并,`compat` / `cost` / `thinkingLevelMap` / `headers` 再合并一层。 */
|
|
26
|
+
export declare function applyModelOverride(model: Model, override: Partial<Omit<Model, "provider" | "api">> & {
|
|
27
|
+
id: string;
|
|
28
|
+
}): Model;
|