@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,99 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* models.dev 模型元数据(docs/providers.md「模型元数据:models.dev」):裁剪、索引、匹配、映射。
|
|
3
|
+
*
|
|
4
|
+
* 数据源 `https://models.dev/api.json` 是「供应商 → 模型」两层表,同一个模型 id 会在几十家转售商下
|
|
5
|
+
* 重复出现且取值不一。`ModelsDevIndex.match()` 按文档里的顺序挑一条:显式 `provider/model` →
|
|
6
|
+
* `vendor/model` 形状的 id → 同名条目的 `canonical_model_id` 指向的原厂条目 → 原厂供应商 →
|
|
7
|
+
* 多数一致 → 归一化 id(去前缀 / `:后缀` / `-latest` / 日期)后重试 → 未匹配。
|
|
8
|
+
*
|
|
9
|
+
* 本模块只做纯计算(不读文件、不联网);缓存与拉取在 models-dev-cache.ts。
|
|
10
|
+
*/
|
|
11
|
+
import type { ModelCost } from "../types.js";
|
|
12
|
+
/** 用到的模型字段(name、推理、工具调用、输入模态、上下限、价格、canonical);其余写缓存时丢掉。 */
|
|
13
|
+
export interface ModelsDevModel {
|
|
14
|
+
id: string;
|
|
15
|
+
name?: string;
|
|
16
|
+
reasoning?: boolean;
|
|
17
|
+
tool_call?: boolean;
|
|
18
|
+
modalities?: {
|
|
19
|
+
input?: string[];
|
|
20
|
+
};
|
|
21
|
+
limit?: {
|
|
22
|
+
context?: number;
|
|
23
|
+
output?: number;
|
|
24
|
+
};
|
|
25
|
+
cost?: {
|
|
26
|
+
input?: number;
|
|
27
|
+
output?: number;
|
|
28
|
+
cache_read?: number;
|
|
29
|
+
cache_write?: number;
|
|
30
|
+
};
|
|
31
|
+
canonical_model_id?: string;
|
|
32
|
+
}
|
|
33
|
+
export interface ModelsDevProvider {
|
|
34
|
+
id: string;
|
|
35
|
+
name?: string;
|
|
36
|
+
models: Record<string, ModelsDevModel>;
|
|
37
|
+
}
|
|
38
|
+
export type ModelsDevData = Record<string, ModelsDevProvider>;
|
|
39
|
+
/**
|
|
40
|
+
* 原厂供应商(models.dev 的供应商 id,顺序即优先级)。通义在 `alibaba`、Llama 在 `llama`、
|
|
41
|
+
* 智谱国际站在 `zai`;models.dev 没有 `qwen` / `meta` 这样的供应商 id。
|
|
42
|
+
*/
|
|
43
|
+
export declare const FIRST_PARTY_PROVIDERS: readonly string[];
|
|
44
|
+
/** maxTokens 的上限:models.dev 给原厂上限(常与上下文相同),每次请求都会作为 max_tokens 发出。 */
|
|
45
|
+
export declare const MODELS_DEV_MAX_OUTPUT = 65536;
|
|
46
|
+
export type MatchKind = "explicit" | "prefix" | "canonical" | "vendor" | "consensus" | "single";
|
|
47
|
+
export interface ModelsDevMatch {
|
|
48
|
+
/** 选中条目 `provider/model`。 */
|
|
49
|
+
ref: string;
|
|
50
|
+
model: ModelsDevModel;
|
|
51
|
+
kind: MatchKind;
|
|
52
|
+
/** 经归一化才匹配到时的 id(如去掉日期后缀)。 */
|
|
53
|
+
normalized?: string;
|
|
54
|
+
/** 同名条目数。 */
|
|
55
|
+
candidates: number;
|
|
56
|
+
/** 多条取值不一致时的说明。 */
|
|
57
|
+
warning?: string;
|
|
58
|
+
}
|
|
59
|
+
/** 映射到 ama Model 的字段(缺的不给)。 */
|
|
60
|
+
export interface ModelsDevFields {
|
|
61
|
+
name?: string;
|
|
62
|
+
contextWindow?: number;
|
|
63
|
+
maxTokens?: number;
|
|
64
|
+
input?: ("text" | "image")[];
|
|
65
|
+
reasoning?: boolean;
|
|
66
|
+
cost?: ModelCost;
|
|
67
|
+
/** models.dev 的 tool_call;Model 上没有对应字段,只用于展示与写入过滤。 */
|
|
68
|
+
toolCall?: boolean;
|
|
69
|
+
}
|
|
70
|
+
/** 校验并裁剪 api.json:只留用到的字段;形状不对的供应商 / 模型跳过。整体不是对象抛错。 */
|
|
71
|
+
export declare function trimModelsDev(raw: unknown): ModelsDevData;
|
|
72
|
+
/**
|
|
73
|
+
* 依次尝试的 id(小写、去重):原样 → 去 `vendor/` 前缀 → 去 `:free` 一类后缀 → 去 `-latest` →
|
|
74
|
+
* 去日期后缀(`-0902`、`-20250514`、`-2025-05-14`)。
|
|
75
|
+
*/
|
|
76
|
+
export declare function idCandidates(id: string): string[];
|
|
77
|
+
export declare class ModelsDevIndex {
|
|
78
|
+
private readonly byId;
|
|
79
|
+
private readonly byRef;
|
|
80
|
+
readonly data: ModelsDevData;
|
|
81
|
+
constructor(data: ModelsDevData);
|
|
82
|
+
get providerCount(): number;
|
|
83
|
+
get modelCount(): number;
|
|
84
|
+
/** `provider/model`(不分大小写)。 */
|
|
85
|
+
get(ref: string): ModelsDevModel | undefined;
|
|
86
|
+
/**
|
|
87
|
+
* 匹配一个模型 id。`explicit` 是配置里的 `modelsDev: "provider/model"`:找得到就用,找不到返回
|
|
88
|
+
* undefined(调用方 warning),不再回落到按 id 猜。
|
|
89
|
+
*/
|
|
90
|
+
match(id: string, explicit?: string): ModelsDevMatch | undefined;
|
|
91
|
+
private choose;
|
|
92
|
+
}
|
|
93
|
+
/** models.dev 条目 → ama Model 字段(规则见 docs/providers.md)。 */
|
|
94
|
+
export declare function modelsDevFields(model: ModelsDevModel): ModelsDevFields;
|
|
95
|
+
/** 可由 models.dev 补的 Model 字段(展示来源用)。 */
|
|
96
|
+
export declare const ENRICHABLE_FIELDS: readonly ["contextWindow", "maxTokens", "input", "reasoning", "cost"];
|
|
97
|
+
export type EnrichableField = (typeof ENRICHABLE_FIELDS)[number];
|
|
98
|
+
/** 匹配方式的中文说明(表格与 `models list`)。 */
|
|
99
|
+
export declare function matchLabel(match: ModelsDevMatch | undefined): string;
|
|
@@ -0,0 +1,315 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* models.dev 模型元数据(docs/providers.md「模型元数据:models.dev」):裁剪、索引、匹配、映射。
|
|
3
|
+
*
|
|
4
|
+
* 数据源 `https://models.dev/api.json` 是「供应商 → 模型」两层表,同一个模型 id 会在几十家转售商下
|
|
5
|
+
* 重复出现且取值不一。`ModelsDevIndex.match()` 按文档里的顺序挑一条:显式 `provider/model` →
|
|
6
|
+
* `vendor/model` 形状的 id → 同名条目的 `canonical_model_id` 指向的原厂条目 → 原厂供应商 →
|
|
7
|
+
* 多数一致 → 归一化 id(去前缀 / `:后缀` / `-latest` / 日期)后重试 → 未匹配。
|
|
8
|
+
*
|
|
9
|
+
* 本模块只做纯计算(不读文件、不联网);缓存与拉取在 models-dev-cache.ts。
|
|
10
|
+
*/
|
|
11
|
+
/**
|
|
12
|
+
* 原厂供应商(models.dev 的供应商 id,顺序即优先级)。通义在 `alibaba`、Llama 在 `llama`、
|
|
13
|
+
* 智谱国际站在 `zai`;models.dev 没有 `qwen` / `meta` 这样的供应商 id。
|
|
14
|
+
*/
|
|
15
|
+
export const FIRST_PARTY_PROVIDERS = [
|
|
16
|
+
"anthropic",
|
|
17
|
+
"openai",
|
|
18
|
+
"google",
|
|
19
|
+
"deepseek",
|
|
20
|
+
"moonshotai",
|
|
21
|
+
"moonshotai-cn",
|
|
22
|
+
"zhipuai",
|
|
23
|
+
"zai",
|
|
24
|
+
"alibaba",
|
|
25
|
+
"alibaba-cn",
|
|
26
|
+
"xai",
|
|
27
|
+
"mistral",
|
|
28
|
+
"minimax",
|
|
29
|
+
"minimax-cn",
|
|
30
|
+
"llama",
|
|
31
|
+
"cohere",
|
|
32
|
+
"xiaomi",
|
|
33
|
+
"stepfun",
|
|
34
|
+
"perplexity",
|
|
35
|
+
"ai21",
|
|
36
|
+
"upstage",
|
|
37
|
+
"inception",
|
|
38
|
+
];
|
|
39
|
+
/** maxTokens 的上限:models.dev 给原厂上限(常与上下文相同),每次请求都会作为 max_tokens 发出。 */
|
|
40
|
+
export const MODELS_DEV_MAX_OUTPUT = 65_536;
|
|
41
|
+
function isRecord(value) {
|
|
42
|
+
return typeof value === "object" && value !== null && !Array.isArray(value);
|
|
43
|
+
}
|
|
44
|
+
function positive(value) {
|
|
45
|
+
return typeof value === "number" && Number.isFinite(value) && value > 0 ? value : undefined;
|
|
46
|
+
}
|
|
47
|
+
function nonNegative(value) {
|
|
48
|
+
return typeof value === "number" && Number.isFinite(value) && value >= 0 ? value : undefined;
|
|
49
|
+
}
|
|
50
|
+
function strings(value) {
|
|
51
|
+
return Array.isArray(value) ? value.filter((v) => typeof v === "string") : undefined;
|
|
52
|
+
}
|
|
53
|
+
function trimModel(id, raw) {
|
|
54
|
+
const out = { id };
|
|
55
|
+
if (typeof raw["name"] === "string")
|
|
56
|
+
out.name = raw["name"];
|
|
57
|
+
for (const key of ["reasoning", "tool_call"]) {
|
|
58
|
+
if (typeof raw[key] === "boolean")
|
|
59
|
+
out[key] = raw[key];
|
|
60
|
+
}
|
|
61
|
+
if (typeof raw["canonical_model_id"] === "string")
|
|
62
|
+
out.canonical_model_id = raw["canonical_model_id"];
|
|
63
|
+
const modalities = raw["modalities"];
|
|
64
|
+
if (isRecord(modalities)) {
|
|
65
|
+
const input = strings(modalities["input"]);
|
|
66
|
+
if (input)
|
|
67
|
+
out.modalities = { input };
|
|
68
|
+
}
|
|
69
|
+
const limit = raw["limit"];
|
|
70
|
+
if (isRecord(limit)) {
|
|
71
|
+
const context = positive(limit["context"]);
|
|
72
|
+
const output = positive(limit["output"]);
|
|
73
|
+
out.limit = {
|
|
74
|
+
...(context !== undefined ? { context } : {}),
|
|
75
|
+
...(output !== undefined ? { output } : {}),
|
|
76
|
+
};
|
|
77
|
+
}
|
|
78
|
+
const cost = raw["cost"];
|
|
79
|
+
if (isRecord(cost)) {
|
|
80
|
+
const c = {};
|
|
81
|
+
for (const key of ["input", "output", "cache_read", "cache_write"]) {
|
|
82
|
+
const v = nonNegative(cost[key]);
|
|
83
|
+
if (v !== undefined)
|
|
84
|
+
c[key] = v;
|
|
85
|
+
}
|
|
86
|
+
out.cost = c;
|
|
87
|
+
}
|
|
88
|
+
return out;
|
|
89
|
+
}
|
|
90
|
+
/** 校验并裁剪 api.json:只留用到的字段;形状不对的供应商 / 模型跳过。整体不是对象抛错。 */
|
|
91
|
+
export function trimModelsDev(raw) {
|
|
92
|
+
if (!isRecord(raw))
|
|
93
|
+
throw new Error("models.dev 数据不是对象");
|
|
94
|
+
const out = {};
|
|
95
|
+
for (const [providerId, provider] of Object.entries(raw)) {
|
|
96
|
+
if (!isRecord(provider) || !isRecord(provider["models"]))
|
|
97
|
+
continue;
|
|
98
|
+
const models = {};
|
|
99
|
+
for (const [modelId, model] of Object.entries(provider["models"])) {
|
|
100
|
+
if (isRecord(model))
|
|
101
|
+
models[modelId] = trimModel(modelId, model);
|
|
102
|
+
}
|
|
103
|
+
out[providerId] = {
|
|
104
|
+
id: providerId,
|
|
105
|
+
...(typeof provider["name"] === "string" ? { name: provider["name"] } : {}),
|
|
106
|
+
models,
|
|
107
|
+
};
|
|
108
|
+
}
|
|
109
|
+
return out;
|
|
110
|
+
}
|
|
111
|
+
/**
|
|
112
|
+
* 依次尝试的 id(小写、去重):原样 → 去 `vendor/` 前缀 → 去 `:free` 一类后缀 → 去 `-latest` →
|
|
113
|
+
* 去日期后缀(`-0902`、`-20250514`、`-2025-05-14`)。
|
|
114
|
+
*/
|
|
115
|
+
export function idCandidates(id) {
|
|
116
|
+
const out = [];
|
|
117
|
+
const add = (value) => {
|
|
118
|
+
const v = value.trim();
|
|
119
|
+
if (v !== "" && !out.includes(v))
|
|
120
|
+
out.push(v);
|
|
121
|
+
};
|
|
122
|
+
let s = id.trim().toLowerCase();
|
|
123
|
+
add(s);
|
|
124
|
+
s = s.slice(s.lastIndexOf("/") + 1);
|
|
125
|
+
add(s);
|
|
126
|
+
s = s.replace(/:[a-z0-9._-]+$/, "");
|
|
127
|
+
add(s);
|
|
128
|
+
s = s.replace(/-latest$/, "");
|
|
129
|
+
add(s);
|
|
130
|
+
s = s.replace(/-(?:\d{4}-\d{2}-\d{2}|\d{8}|\d{6}|\d{4})$/, "");
|
|
131
|
+
add(s);
|
|
132
|
+
return out;
|
|
133
|
+
}
|
|
134
|
+
function refOf(entry) {
|
|
135
|
+
return `${entry.provider}/${entry.id}`;
|
|
136
|
+
}
|
|
137
|
+
function vendorRank(provider) {
|
|
138
|
+
const i = FIRST_PARTY_PROVIDERS.indexOf(provider);
|
|
139
|
+
return i < 0 ? Number.POSITIVE_INFINITY : i;
|
|
140
|
+
}
|
|
141
|
+
function hasImage(model) {
|
|
142
|
+
return model.modalities?.input?.includes("image") === true;
|
|
143
|
+
}
|
|
144
|
+
function signature(model) {
|
|
145
|
+
return `${model.limit?.context ?? "?"}/${model.limit?.output ?? "?"}/${hasImage(model) ? "img" : "text"}`;
|
|
146
|
+
}
|
|
147
|
+
export class ModelsDevIndex {
|
|
148
|
+
byId = new Map();
|
|
149
|
+
byRef = new Map();
|
|
150
|
+
data;
|
|
151
|
+
constructor(data) {
|
|
152
|
+
this.data = data;
|
|
153
|
+
for (const [providerId, provider] of Object.entries(data)) {
|
|
154
|
+
for (const [modelId, model] of Object.entries(provider.models)) {
|
|
155
|
+
const entry = { provider: providerId, id: modelId, model };
|
|
156
|
+
const key = modelId.toLowerCase();
|
|
157
|
+
const list = this.byId.get(key);
|
|
158
|
+
if (list)
|
|
159
|
+
list.push(entry);
|
|
160
|
+
else
|
|
161
|
+
this.byId.set(key, [entry]);
|
|
162
|
+
this.byRef.set(`${providerId}/${modelId}`.toLowerCase(), entry);
|
|
163
|
+
}
|
|
164
|
+
}
|
|
165
|
+
}
|
|
166
|
+
get providerCount() {
|
|
167
|
+
return Object.keys(this.data).length;
|
|
168
|
+
}
|
|
169
|
+
get modelCount() {
|
|
170
|
+
return this.byRef.size;
|
|
171
|
+
}
|
|
172
|
+
/** `provider/model`(不分大小写)。 */
|
|
173
|
+
get(ref) {
|
|
174
|
+
return this.byRef.get(ref.toLowerCase())?.model;
|
|
175
|
+
}
|
|
176
|
+
/**
|
|
177
|
+
* 匹配一个模型 id。`explicit` 是配置里的 `modelsDev: "provider/model"`:找得到就用,找不到返回
|
|
178
|
+
* undefined(调用方 warning),不再回落到按 id 猜。
|
|
179
|
+
*/
|
|
180
|
+
match(id, explicit) {
|
|
181
|
+
if (explicit !== undefined) {
|
|
182
|
+
const entry = this.byRef.get(explicit.toLowerCase());
|
|
183
|
+
return entry
|
|
184
|
+
? { ref: refOf(entry), model: entry.model, kind: "explicit", candidates: 1 }
|
|
185
|
+
: undefined;
|
|
186
|
+
}
|
|
187
|
+
if (id.includes("/")) {
|
|
188
|
+
const entry = this.byRef.get(id.toLowerCase());
|
|
189
|
+
if (entry)
|
|
190
|
+
return { ref: refOf(entry), model: entry.model, kind: "prefix", candidates: 1 };
|
|
191
|
+
}
|
|
192
|
+
const candidates = idCandidates(id);
|
|
193
|
+
for (const [i, key] of candidates.entries()) {
|
|
194
|
+
const entries = this.byId.get(key);
|
|
195
|
+
if (!entries || entries.length === 0)
|
|
196
|
+
continue;
|
|
197
|
+
const picked = this.choose(key, entries);
|
|
198
|
+
if (i > 0 && key !== id.toLowerCase())
|
|
199
|
+
picked.normalized = key;
|
|
200
|
+
return picked;
|
|
201
|
+
}
|
|
202
|
+
return undefined;
|
|
203
|
+
}
|
|
204
|
+
choose(key, entries) {
|
|
205
|
+
const candidates = entries.length;
|
|
206
|
+
let pool = entries;
|
|
207
|
+
let owner;
|
|
208
|
+
const votes = new Map();
|
|
209
|
+
for (const e of entries) {
|
|
210
|
+
const c = e.model.canonical_model_id?.toLowerCase();
|
|
211
|
+
if (c)
|
|
212
|
+
votes.set(c, (votes.get(c) ?? 0) + 1);
|
|
213
|
+
}
|
|
214
|
+
if (votes.size > 0) {
|
|
215
|
+
const tail = (ref) => ref.slice(ref.indexOf("/") + 1);
|
|
216
|
+
const ranked = [...votes].sort((a, b) => Number(tail(b[0]) === key) - Number(tail(a[0]) === key) || b[1] - a[1]);
|
|
217
|
+
const canonical = ranked[0]?.[0] ?? "";
|
|
218
|
+
const direct = this.byRef.get(canonical);
|
|
219
|
+
if (direct)
|
|
220
|
+
return { ref: refOf(direct), model: direct.model, kind: "canonical", candidates };
|
|
221
|
+
// 原厂条目不在 models.dev 里:只在指向同一 canonical 的条目里挑,原厂只认 canonical 的厂商
|
|
222
|
+
// (否则 alibaba 转售的 kimi 会被当成「原厂」)。
|
|
223
|
+
owner = canonical.slice(0, canonical.indexOf("/"));
|
|
224
|
+
const same = entries.filter((e) => e.model.canonical_model_id?.toLowerCase() === canonical);
|
|
225
|
+
if (same.length > 0)
|
|
226
|
+
pool = same;
|
|
227
|
+
}
|
|
228
|
+
const vendor = pool
|
|
229
|
+
.filter((e) => owner !== undefined
|
|
230
|
+
? e.provider === owner || e.provider === `${owner}-cn`
|
|
231
|
+
: vendorRank(e.provider) < Number.POSITIVE_INFINITY)
|
|
232
|
+
.sort((a, b) => vendorRank(a.provider) - vendorRank(b.provider))[0];
|
|
233
|
+
if (vendor)
|
|
234
|
+
return { ref: refOf(vendor), model: vendor.model, kind: "vendor", candidates };
|
|
235
|
+
if (pool.length === 1 && pool[0]) {
|
|
236
|
+
return { ref: refOf(pool[0]), model: pool[0].model, kind: "single", candidates };
|
|
237
|
+
}
|
|
238
|
+
const groups = new Map();
|
|
239
|
+
for (const e of pool) {
|
|
240
|
+
const sig = signature(e.model);
|
|
241
|
+
const list = groups.get(sig);
|
|
242
|
+
if (list)
|
|
243
|
+
list.push(e);
|
|
244
|
+
else
|
|
245
|
+
groups.set(sig, [e]);
|
|
246
|
+
}
|
|
247
|
+
const best = [...groups.values()].sort((a, b) => b.length - a.length)[0] ?? pool;
|
|
248
|
+
const chosen = best[0];
|
|
249
|
+
const match = {
|
|
250
|
+
ref: refOf(chosen),
|
|
251
|
+
model: chosen.model,
|
|
252
|
+
kind: "consensus",
|
|
253
|
+
candidates,
|
|
254
|
+
};
|
|
255
|
+
if (groups.size > 1) {
|
|
256
|
+
match.warning =
|
|
257
|
+
`${key}:models.dev 有 ${pool.length} 个条目、${groups.size} 种取值,` +
|
|
258
|
+
`取多数(${best.length} 条:${signature(chosen.model)})`;
|
|
259
|
+
}
|
|
260
|
+
return match;
|
|
261
|
+
}
|
|
262
|
+
}
|
|
263
|
+
/** models.dev 条目 → ama Model 字段(规则见 docs/providers.md)。 */
|
|
264
|
+
export function modelsDevFields(model) {
|
|
265
|
+
const out = {};
|
|
266
|
+
if (model.name !== undefined)
|
|
267
|
+
out.name = model.name;
|
|
268
|
+
const context = positive(model.limit?.context);
|
|
269
|
+
if (context !== undefined)
|
|
270
|
+
out.contextWindow = Math.floor(context);
|
|
271
|
+
const output = positive(model.limit?.output);
|
|
272
|
+
if (output !== undefined) {
|
|
273
|
+
out.maxTokens = Math.floor(Math.min(output, MODELS_DEV_MAX_OUTPUT, context ?? output));
|
|
274
|
+
}
|
|
275
|
+
const input = model.modalities?.input;
|
|
276
|
+
if (input !== undefined)
|
|
277
|
+
out.input = input.includes("image") ? ["text", "image"] : ["text"];
|
|
278
|
+
if (model.reasoning !== undefined)
|
|
279
|
+
out.reasoning = model.reasoning;
|
|
280
|
+
if (model.tool_call !== undefined)
|
|
281
|
+
out.toolCall = model.tool_call;
|
|
282
|
+
const cost = model.cost;
|
|
283
|
+
if (cost?.input !== undefined && cost.output !== undefined) {
|
|
284
|
+
out.cost = {
|
|
285
|
+
input: cost.input,
|
|
286
|
+
output: cost.output,
|
|
287
|
+
cacheRead: cost.cache_read ?? cost.input,
|
|
288
|
+
cacheWrite: cost.cache_write ?? cost.input,
|
|
289
|
+
};
|
|
290
|
+
}
|
|
291
|
+
return out;
|
|
292
|
+
}
|
|
293
|
+
/** 可由 models.dev 补的 Model 字段(展示来源用)。 */
|
|
294
|
+
export const ENRICHABLE_FIELDS = [
|
|
295
|
+
"contextWindow",
|
|
296
|
+
"maxTokens",
|
|
297
|
+
"input",
|
|
298
|
+
"reasoning",
|
|
299
|
+
"cost",
|
|
300
|
+
];
|
|
301
|
+
/** 匹配方式的中文说明(表格与 `models list`)。 */
|
|
302
|
+
export function matchLabel(match) {
|
|
303
|
+
if (match === undefined)
|
|
304
|
+
return "未匹配";
|
|
305
|
+
const kind = {
|
|
306
|
+
explicit: "显式",
|
|
307
|
+
prefix: "前缀",
|
|
308
|
+
canonical: "原厂",
|
|
309
|
+
vendor: "原厂",
|
|
310
|
+
consensus: "多数",
|
|
311
|
+
single: "唯一",
|
|
312
|
+
};
|
|
313
|
+
const via = match.normalized !== undefined ? `,按 ${match.normalized}` : "";
|
|
314
|
+
return `${kind[match.kind]} ${match.ref}${via}`;
|
|
315
|
+
}
|
|
@@ -0,0 +1,114 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* ProviderRegistry(设计 §3.2–§3.5):内置供应商 + 目录 + config.json 合并、模型查找、
|
|
3
|
+
* `provider/model` 解析、key 解析、协议实现查找。实现 B0 契约 `ProviderRegistryApi`。
|
|
4
|
+
*
|
|
5
|
+
* 合并顺序:内置(builtin.ts + catalog)← config.json `providers.<id>`(字段覆盖;`headers` /
|
|
6
|
+
* `compat` 合并;`models[]` 同 id 整条替换、新 id 追加;`modelOverrides[]` 只改元数据;两者都可带
|
|
7
|
+
* 模型级 `api`,缺省沿用供应商的协议)←
|
|
8
|
+
* auth.json 条目的 `baseUrl`。内置 openai / anthropic 的 baseUrl 还可来自 `OPENAI_BASE_URL` /
|
|
9
|
+
* `ANTHROPIC_BASE_URL`(第三波 §2.3,优先级最低,`baseUrlEnv(id)` 报告是否生效)。之后「物化」每个模型:补 baseUrl / headers / compat /
|
|
10
|
+
* authHeader / requiresApiKey,让协议实现只看 Model 就能发请求。
|
|
11
|
+
*
|
|
12
|
+
* 模型引用:`provider/model-id`(model id 自身可含斜杠,如 `openrouter/anthropic/claude-…`);
|
|
13
|
+
* 前缀不是供应商 id 时整串当 model id。无供应商前缀时全局唯一匹配;多家同名时只留已配置 key
|
|
14
|
+
* 的;仍不唯一 → ambiguous 并列出候选。模型表为空的供应商(ollama、lmstudio、未列模型的
|
|
15
|
+
* 自定义供应商)与 baseUrl 被改到非官方主机的内置供应商(中转站)接受任意 model id,按自定义
|
|
16
|
+
* 缺省合成;后者 compat 未显式配置 `sendPromptCacheKey` 时置 false。
|
|
17
|
+
*
|
|
18
|
+
* 渠道(channels.ts):有 `channels` 的供应商,模型按首选渠道物化;`provider/model@channel` 换渠道
|
|
19
|
+
* 重新物化(协议、地址、headers、compat 取渠道的,模型级 api / baseUrl 仍覆盖);渠道 key 经
|
|
20
|
+
* `resolveApiKey(provider, channel)`。没有 `channels` 的供应商行为不变。
|
|
21
|
+
*
|
|
22
|
+
* models.dev(enrich.ts):config 里缺元数据的自定义模型与合成模型,用传入的索引(只读缓存)补
|
|
23
|
+
* contextWindow / maxTokens / input / reasoning / cost,来源记在 `modelMetadata()`;内置目录不补。
|
|
24
|
+
*/
|
|
25
|
+
import type { AmaConfig } from "../../config/types.js";
|
|
26
|
+
import { ApiRegistry } from "../apis/api.js";
|
|
27
|
+
import type { Api, ApiImplementation, ApiKeyResolution, Model, ModelLookup, ProviderChannel, ProviderData, ProviderRegistryApi } from "../types.js";
|
|
28
|
+
import { type KeyResolverOptions } from "./auth.js";
|
|
29
|
+
import { type ModelMetadata, type ModelsDevSource } from "./enrich.js";
|
|
30
|
+
export type ModelSource = "builtin" | "config" | "discovered";
|
|
31
|
+
export interface ProviderRegistryOptions {
|
|
32
|
+
config?: AmaConfig | undefined;
|
|
33
|
+
/** 缺省 createDefaultApiRegistry()。 */
|
|
34
|
+
apis?: ApiRegistry | undefined;
|
|
35
|
+
/** key 发现选项;`configKeys` 缺省取自 config.providers.*.apiKey。 */
|
|
36
|
+
keys?: KeyResolverOptions | undefined;
|
|
37
|
+
/** 注册 `fake` 供应商(缺省 true)。 */
|
|
38
|
+
includeFake?: boolean | undefined;
|
|
39
|
+
onWarning?: ((message: string) => void) | undefined;
|
|
40
|
+
/**
|
|
41
|
+
* models.dev 索引(或惰性加载函数,只读缓存不联网):给 config 里缺元数据的自定义模型补
|
|
42
|
+
* contextWindow / maxTokens / input / reasoning / cost。
|
|
43
|
+
*/
|
|
44
|
+
modelsDev?: ModelsDevSource;
|
|
45
|
+
}
|
|
46
|
+
export interface ModelEntry {
|
|
47
|
+
model: Model;
|
|
48
|
+
provider: ProviderData;
|
|
49
|
+
source: ModelSource;
|
|
50
|
+
}
|
|
51
|
+
/**
|
|
52
|
+
* 物化:模型补齐供应商级字段(不可变:返回新对象)。给了 `channel` 时协议与地址取渠道的(模型级
|
|
53
|
+
* `explicit` 覆盖优先),headers / compat 按 供应商 ← 渠道 ← 模型 合并,并记下渠道名。
|
|
54
|
+
*/
|
|
55
|
+
export declare function materializeModel(model: Model, provider: ProviderData, channel?: ProviderChannel, explicit?: {
|
|
56
|
+
api?: Api | undefined;
|
|
57
|
+
baseUrl?: string | undefined;
|
|
58
|
+
}): Model;
|
|
59
|
+
export declare class ProviderRegistry implements ProviderRegistryApi {
|
|
60
|
+
readonly warnings: string[];
|
|
61
|
+
private readonly providers;
|
|
62
|
+
private readonly sources;
|
|
63
|
+
/** baseUrl 来自环境变量的供应商 → 变量名(被 config / auth.json 覆盖后删除)。 */
|
|
64
|
+
private readonly envBaseUrls;
|
|
65
|
+
/** baseUrl 指向非官方主机的内置供应商:接受目录外的 model id。 */
|
|
66
|
+
private readonly relayed;
|
|
67
|
+
/** `provider/model` → 物化前的模型(多渠道供应商切换渠道时重新物化)。 */
|
|
68
|
+
private readonly raw;
|
|
69
|
+
/** `provider/model` → 元数据来源与 models.dev 匹配。 */
|
|
70
|
+
private readonly metadata;
|
|
71
|
+
private readonly modelsDev;
|
|
72
|
+
private readonly apis;
|
|
73
|
+
private readonly keys;
|
|
74
|
+
private readonly onWarning;
|
|
75
|
+
constructor(options?: ProviderRegistryOptions);
|
|
76
|
+
private warn;
|
|
77
|
+
/** 物化并记下原始模型;多渠道供应商用模型的首选渠道。 */
|
|
78
|
+
private materialize;
|
|
79
|
+
private applyConfig;
|
|
80
|
+
/** baseUrl 来自哪个环境变量(未生效返回 undefined)。 */
|
|
81
|
+
baseUrlEnv(providerId: string): string | undefined;
|
|
82
|
+
/** 内置供应商的 baseUrl 指向非官方主机(中转站)。 */
|
|
83
|
+
isRelayed(providerId: string): boolean;
|
|
84
|
+
/** 模型元数据的来源与 models.dev 匹配(`ama models list` / `config show` / providers 表格)。 */
|
|
85
|
+
modelMetadata(providerId: string, modelId: string): ModelMetadata | undefined;
|
|
86
|
+
list(): readonly ProviderData[];
|
|
87
|
+
get(providerId: string): ProviderData | undefined;
|
|
88
|
+
listModels(): ModelEntry[];
|
|
89
|
+
modelSource(providerId: string, modelId: string): ModelSource;
|
|
90
|
+
/** 追加 / 替换模型(例如本地枚举得到的 ollama 模型)。 */
|
|
91
|
+
addModels(providerId: string, models: readonly Model[], source?: ModelSource): void;
|
|
92
|
+
private synthesize;
|
|
93
|
+
/** 按渠道取模型:渠道不在模型的 channels 里 → 列出可用渠道。 */
|
|
94
|
+
private withChannel;
|
|
95
|
+
findModel(ref: string): ModelLookup;
|
|
96
|
+
private findPlain;
|
|
97
|
+
private similar;
|
|
98
|
+
hasConfiguredKey(providerId: string): boolean;
|
|
99
|
+
resolveApiKey(providerId: string, channel?: string): Promise<ApiKeyResolution>;
|
|
100
|
+
getApi(api: Api): ApiImplementation | undefined;
|
|
101
|
+
}
|
|
102
|
+
/** 注册表若是 ProviderRegistry(或同形状),报告 baseUrl 来自的环境变量;否则 undefined。 */
|
|
103
|
+
export declare function baseUrlEnvOf(registry: ProviderRegistryApi, providerId: string): string | undefined;
|
|
104
|
+
/**
|
|
105
|
+
* 模型枚举:本地服务(`ama models list --provider ollama|lmstudio`)与 `ama models discover`
|
|
106
|
+
* (第三波 §2.3)共用。ollama 走 `/api/tags`,其它走 OpenAI 兼容的 `GET {baseUrl}/models`;
|
|
107
|
+
* `url` / `headers` 由调用方给出时原样使用(远端中转要带鉴权头)。失败抛错由调用方展示。
|
|
108
|
+
*/
|
|
109
|
+
export declare function discoverLocalModels(provider: ProviderData, options?: {
|
|
110
|
+
signal?: AbortSignal;
|
|
111
|
+
timeoutMs?: number;
|
|
112
|
+
url?: string;
|
|
113
|
+
headers?: Record<string, string>;
|
|
114
|
+
}): Promise<Model[]>;
|