gsd-pi 2.74.0-dev.b741afb → 2.74.0-dev.ffbcc03
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/dist/resources/extensions/gsd/activity-log.js +16 -0
- package/dist/resources/extensions/gsd/auto/loop.js +147 -10
- package/dist/resources/extensions/gsd/auto/phases.js +113 -3
- package/dist/resources/extensions/gsd/auto/session.js +10 -0
- package/dist/resources/extensions/gsd/auto-dispatch.js +11 -1
- package/dist/resources/extensions/gsd/auto-model-selection.js +51 -5
- package/dist/resources/extensions/gsd/auto-post-unit.js +215 -8
- package/dist/resources/extensions/gsd/auto-recovery.js +24 -10
- package/dist/resources/extensions/gsd/auto-unit-closeout.js +18 -0
- package/dist/resources/extensions/gsd/auto-verification.js +100 -2
- package/dist/resources/extensions/gsd/auto.js +28 -2
- package/dist/resources/extensions/gsd/bootstrap/register-extension.js +10 -1
- package/dist/resources/extensions/gsd/bootstrap/register-hooks.js +61 -9
- package/dist/resources/extensions/gsd/cache.js +16 -5
- package/dist/resources/extensions/gsd/commands/handlers/ops.js +5 -0
- package/dist/resources/extensions/gsd/commands-extract-learnings.js +225 -0
- package/dist/resources/extensions/gsd/commands-prefs-wizard.js +1 -1
- package/dist/resources/extensions/gsd/docs/preferences-reference.md +14 -1
- package/dist/resources/extensions/gsd/ecosystem/gsd-extension-api.js +144 -0
- package/dist/resources/extensions/gsd/ecosystem/loader.js +145 -0
- package/dist/resources/extensions/gsd/git-service.js +49 -1
- package/dist/resources/extensions/gsd/graph-context.js +98 -7
- package/dist/resources/extensions/gsd/gsd-db.js +260 -2
- package/dist/resources/extensions/gsd/guided-flow.js +24 -1
- package/dist/resources/extensions/gsd/init-wizard.js +1 -0
- package/dist/resources/extensions/gsd/journal.js +27 -0
- package/dist/resources/extensions/gsd/metrics.js +19 -0
- package/dist/resources/extensions/gsd/parallel-orchestrator.js +33 -1
- package/dist/resources/extensions/gsd/preferences-models.js +20 -3
- package/dist/resources/extensions/gsd/preferences-types.js +1 -0
- package/dist/resources/extensions/gsd/preferences-validation.js +108 -2
- package/dist/resources/extensions/gsd/preferences.js +26 -0
- package/dist/resources/extensions/gsd/safety/evidence-collector.js +15 -30
- package/dist/resources/extensions/gsd/slice-parallel-orchestrator.js +12 -2
- package/dist/resources/extensions/gsd/templates/PREFERENCES.md +18 -0
- package/dist/resources/extensions/gsd/tools/complete-slice.js +5 -0
- package/dist/resources/extensions/gsd/tools/validate-milestone.js +39 -4
- package/dist/resources/extensions/gsd/unit-ownership.js +1 -1
- package/dist/resources/extensions/gsd/uok/audit-toggle.js +7 -0
- package/dist/resources/extensions/gsd/uok/audit.js +40 -0
- package/dist/resources/extensions/gsd/uok/contracts.js +1 -0
- package/dist/resources/extensions/gsd/uok/execution-graph.js +179 -0
- package/dist/resources/extensions/gsd/uok/flags.js +29 -0
- package/dist/resources/extensions/gsd/uok/gate-runner.js +109 -0
- package/dist/resources/extensions/gsd/uok/gitops.js +53 -0
- package/dist/resources/extensions/gsd/uok/kernel.js +80 -0
- package/dist/resources/extensions/gsd/uok/loop-adapter.js +133 -0
- package/dist/resources/extensions/gsd/uok/model-policy.js +66 -0
- package/dist/resources/extensions/gsd/uok/plan-v2.js +132 -0
- package/dist/resources/extensions/gsd/workflow-logger.js +22 -0
- package/dist/resources/extensions/ttsr/ttsr-manager.js +3 -1
- package/dist/tsconfig.extensions.tsbuildinfo +1 -1
- package/dist/web/standalone/.next/BUILD_ID +1 -1
- package/dist/web/standalone/.next/app-path-routes-manifest.json +9 -9
- package/dist/web/standalone/.next/build-manifest.json +2 -2
- package/dist/web/standalone/.next/prerender-manifest.json +3 -3
- package/dist/web/standalone/.next/server/app/_global-error.html +1 -1
- package/dist/web/standalone/.next/server/app/_global-error.rsc +1 -1
- package/dist/web/standalone/.next/server/app/_global-error.segments/_full.segment.rsc +1 -1
- package/dist/web/standalone/.next/server/app/_global-error.segments/_global-error/__PAGE__.segment.rsc +1 -1
- package/dist/web/standalone/.next/server/app/_global-error.segments/_global-error.segment.rsc +1 -1
- package/dist/web/standalone/.next/server/app/_global-error.segments/_head.segment.rsc +1 -1
- package/dist/web/standalone/.next/server/app/_global-error.segments/_index.segment.rsc +1 -1
- package/dist/web/standalone/.next/server/app/_global-error.segments/_tree.segment.rsc +1 -1
- package/dist/web/standalone/.next/server/app/_not-found.html +1 -1
- package/dist/web/standalone/.next/server/app/_not-found.rsc +1 -1
- package/dist/web/standalone/.next/server/app/_not-found.segments/_full.segment.rsc +1 -1
- package/dist/web/standalone/.next/server/app/_not-found.segments/_head.segment.rsc +1 -1
- package/dist/web/standalone/.next/server/app/_not-found.segments/_index.segment.rsc +1 -1
- package/dist/web/standalone/.next/server/app/_not-found.segments/_not-found/__PAGE__.segment.rsc +1 -1
- package/dist/web/standalone/.next/server/app/_not-found.segments/_not-found.segment.rsc +1 -1
- package/dist/web/standalone/.next/server/app/_not-found.segments/_tree.segment.rsc +1 -1
- package/dist/web/standalone/.next/server/app/api/onboarding/route.js +1 -1
- package/dist/web/standalone/.next/server/app/api/terminal/input/route.js +1 -1
- package/dist/web/standalone/.next/server/app/api/terminal/resize/route.js +1 -1
- package/dist/web/standalone/.next/server/app/api/terminal/sessions/route.js +1 -1
- package/dist/web/standalone/.next/server/app/api/terminal/stream/route.js +1 -1
- package/dist/web/standalone/.next/server/app/index.html +1 -1
- package/dist/web/standalone/.next/server/app/index.rsc +1 -1
- package/dist/web/standalone/.next/server/app/index.segments/__PAGE__.segment.rsc +1 -1
- package/dist/web/standalone/.next/server/app/index.segments/_full.segment.rsc +1 -1
- package/dist/web/standalone/.next/server/app/index.segments/_head.segment.rsc +1 -1
- package/dist/web/standalone/.next/server/app/index.segments/_index.segment.rsc +1 -1
- package/dist/web/standalone/.next/server/app/index.segments/_tree.segment.rsc +1 -1
- package/dist/web/standalone/.next/server/app-paths-manifest.json +9 -9
- package/dist/web/standalone/.next/server/chunks/6897.js +3 -3
- package/dist/web/standalone/.next/server/middleware-build-manifest.js +1 -1
- package/dist/web/standalone/.next/server/middleware-manifest.json +5 -5
- package/dist/web/standalone/.next/server/pages/404.html +1 -1
- package/dist/web/standalone/.next/server/pages/500.html +1 -1
- package/dist/web/standalone/.next/server/server-reference-manifest.json +1 -1
- package/package.json +1 -1
- package/packages/mcp-server/dist/readers/graph.d.ts +1 -1
- package/packages/mcp-server/dist/readers/graph.d.ts.map +1 -1
- package/packages/mcp-server/dist/readers/graph.js +107 -0
- package/packages/mcp-server/dist/readers/graph.js.map +1 -1
- package/packages/mcp-server/dist/workflow-tools.d.ts.map +1 -1
- package/packages/mcp-server/dist/workflow-tools.js +88 -6
- package/packages/mcp-server/dist/workflow-tools.js.map +1 -1
- package/packages/mcp-server/src/readers/graph.test.ts +178 -0
- package/packages/mcp-server/src/readers/graph.ts +148 -1
- package/packages/mcp-server/src/workflow-tools.ts +95 -10
- package/packages/mcp-server/tsconfig.tsbuildinfo +1 -1
- package/packages/pi-agent-core/tsconfig.tsbuildinfo +1 -1
- package/packages/pi-ai/dist/index.d.ts +1 -9
- package/packages/pi-ai/dist/index.d.ts.map +1 -1
- package/packages/pi-ai/dist/index.js +1 -9
- package/packages/pi-ai/dist/index.js.map +1 -1
- package/packages/pi-ai/dist/models/capability-patches.d.ts +19 -0
- package/packages/pi-ai/dist/models/capability-patches.d.ts.map +1 -0
- package/packages/pi-ai/dist/models/capability-patches.js +36 -0
- package/packages/pi-ai/dist/models/capability-patches.js.map +1 -0
- package/packages/pi-ai/dist/{models.custom.d.ts → models/custom.d.ts} +1 -1
- package/packages/pi-ai/dist/models/custom.d.ts.map +1 -0
- package/packages/pi-ai/dist/{models.custom.js → models/custom.js} +4 -4
- package/packages/pi-ai/dist/models/custom.js.map +1 -0
- package/packages/pi-ai/dist/models/generated/amazon-bedrock.d.ts +1482 -0
- package/packages/pi-ai/dist/models/generated/amazon-bedrock.d.ts.map +1 -0
- package/packages/pi-ai/dist/models/generated/amazon-bedrock.js +1484 -0
- package/packages/pi-ai/dist/models/generated/amazon-bedrock.js.map +1 -0
- package/packages/pi-ai/dist/models/generated/anthropic.d.ts +377 -0
- package/packages/pi-ai/dist/models/generated/anthropic.d.ts.map +1 -0
- package/packages/pi-ai/dist/models/generated/anthropic.js +379 -0
- package/packages/pi-ai/dist/models/generated/anthropic.js.map +1 -0
- package/packages/pi-ai/dist/models/generated/azure-openai-responses.d.ts +700 -0
- package/packages/pi-ai/dist/models/generated/azure-openai-responses.d.ts.map +1 -0
- package/packages/pi-ai/dist/models/generated/azure-openai-responses.js +702 -0
- package/packages/pi-ai/dist/models/generated/azure-openai-responses.js.map +1 -0
- package/packages/pi-ai/dist/models/generated/cerebras.d.ts +71 -0
- package/packages/pi-ai/dist/models/generated/cerebras.d.ts.map +1 -0
- package/packages/pi-ai/dist/models/generated/cerebras.js +73 -0
- package/packages/pi-ai/dist/models/generated/cerebras.js.map +1 -0
- package/packages/pi-ai/dist/models/generated/github-copilot.d.ts +590 -0
- package/packages/pi-ai/dist/models/generated/github-copilot.d.ts.map +1 -0
- package/packages/pi-ai/dist/models/generated/github-copilot.js +444 -0
- package/packages/pi-ai/dist/models/generated/github-copilot.js.map +1 -0
- package/packages/pi-ai/dist/models/generated/google-antigravity.d.ts +156 -0
- package/packages/pi-ai/dist/models/generated/google-antigravity.d.ts.map +1 -0
- package/packages/pi-ai/dist/models/generated/google-antigravity.js +158 -0
- package/packages/pi-ai/dist/models/generated/google-antigravity.js.map +1 -0
- package/packages/pi-ai/dist/models/generated/google-gemini-cli.d.ts +105 -0
- package/packages/pi-ai/dist/models/generated/google-gemini-cli.d.ts.map +1 -0
- package/packages/pi-ai/dist/models/generated/google-gemini-cli.js +107 -0
- package/packages/pi-ai/dist/models/generated/google-gemini-cli.js.map +1 -0
- package/packages/pi-ai/dist/models/generated/google-vertex.d.ts +207 -0
- package/packages/pi-ai/dist/models/generated/google-vertex.d.ts.map +1 -0
- package/packages/pi-ai/dist/models/generated/google-vertex.js +209 -0
- package/packages/pi-ai/dist/models/generated/google-vertex.js.map +1 -0
- package/packages/pi-ai/dist/models/generated/google.d.ts +462 -0
- package/packages/pi-ai/dist/models/generated/google.d.ts.map +1 -0
- package/packages/pi-ai/dist/models/generated/google.js +464 -0
- package/packages/pi-ai/dist/models/generated/google.js.map +1 -0
- package/packages/pi-ai/dist/models/generated/groq.d.ts +309 -0
- package/packages/pi-ai/dist/models/generated/groq.d.ts.map +1 -0
- package/packages/pi-ai/dist/models/generated/groq.js +311 -0
- package/packages/pi-ai/dist/models/generated/groq.js.map +1 -0
- package/packages/pi-ai/dist/models/generated/huggingface.d.ts +383 -0
- package/packages/pi-ai/dist/models/generated/huggingface.d.ts.map +1 -0
- package/packages/pi-ai/dist/models/generated/huggingface.js +347 -0
- package/packages/pi-ai/dist/models/generated/huggingface.js.map +1 -0
- package/packages/pi-ai/dist/{models.generated.d.ts → models/generated/index.d.ts} +1 -1
- package/packages/pi-ai/dist/{models.generated.d.ts.map → models/generated/index.d.ts.map} +1 -1
- package/packages/pi-ai/dist/models/generated/index.js +51 -0
- package/packages/pi-ai/dist/models/generated/index.js.map +1 -0
- package/packages/pi-ai/dist/models/generated/kimi-coding.d.ts +37 -0
- package/packages/pi-ai/dist/models/generated/kimi-coding.d.ts.map +1 -0
- package/packages/pi-ai/dist/models/generated/kimi-coding.js +39 -0
- package/packages/pi-ai/dist/models/generated/kimi-coding.js.map +1 -0
- package/packages/pi-ai/dist/models/generated/minimax-cn.d.ts +105 -0
- package/packages/pi-ai/dist/models/generated/minimax-cn.d.ts.map +1 -0
- package/packages/pi-ai/dist/models/generated/minimax-cn.js +107 -0
- package/packages/pi-ai/dist/models/generated/minimax-cn.js.map +1 -0
- package/packages/pi-ai/dist/models/generated/minimax.d.ts +105 -0
- package/packages/pi-ai/dist/models/generated/minimax.d.ts.map +1 -0
- package/packages/pi-ai/dist/models/generated/minimax.js +107 -0
- package/packages/pi-ai/dist/models/generated/minimax.js.map +1 -0
- package/packages/pi-ai/dist/models/generated/mistral.d.ts +445 -0
- package/packages/pi-ai/dist/models/generated/mistral.d.ts.map +1 -0
- package/packages/pi-ai/dist/models/generated/mistral.js +447 -0
- package/packages/pi-ai/dist/models/generated/mistral.js.map +1 -0
- package/packages/pi-ai/dist/models/generated/openai-codex.d.ts +139 -0
- package/packages/pi-ai/dist/models/generated/openai-codex.d.ts.map +1 -0
- package/packages/pi-ai/dist/models/generated/openai-codex.js +141 -0
- package/packages/pi-ai/dist/models/generated/openai-codex.js.map +1 -0
- package/packages/pi-ai/dist/models/generated/openai.d.ts +700 -0
- package/packages/pi-ai/dist/models/generated/openai.d.ts.map +1 -0
- package/packages/pi-ai/dist/models/generated/openai.js +702 -0
- package/packages/pi-ai/dist/models/generated/openai.js.map +1 -0
- package/packages/pi-ai/dist/models/generated/opencode-go.d.ts +122 -0
- package/packages/pi-ai/dist/models/generated/opencode-go.d.ts.map +1 -0
- package/packages/pi-ai/dist/models/generated/opencode-go.js +124 -0
- package/packages/pi-ai/dist/models/generated/opencode-go.js.map +1 -0
- package/packages/pi-ai/dist/models/generated/opencode.d.ts +530 -0
- package/packages/pi-ai/dist/models/generated/opencode.d.ts.map +1 -0
- package/packages/pi-ai/dist/models/generated/opencode.js +532 -0
- package/packages/pi-ai/dist/models/generated/opencode.js.map +1 -0
- package/packages/pi-ai/dist/models/generated/openrouter.d.ts +4270 -0
- package/packages/pi-ai/dist/models/generated/openrouter.d.ts.map +1 -0
- package/packages/pi-ai/dist/models/generated/openrouter.js +4272 -0
- package/packages/pi-ai/dist/models/generated/openrouter.js.map +1 -0
- package/packages/pi-ai/dist/models/generated/vercel-ai-gateway.d.ts +2604 -0
- package/packages/pi-ai/dist/models/generated/vercel-ai-gateway.d.ts.map +1 -0
- package/packages/pi-ai/dist/models/generated/vercel-ai-gateway.js +2606 -0
- package/packages/pi-ai/dist/models/generated/vercel-ai-gateway.js.map +1 -0
- package/packages/pi-ai/dist/models/generated/xai.d.ts +411 -0
- package/packages/pi-ai/dist/models/generated/xai.d.ts.map +1 -0
- package/packages/pi-ai/dist/models/generated/xai.js +413 -0
- package/packages/pi-ai/dist/models/generated/xai.js.map +1 -0
- package/packages/pi-ai/dist/models/generated/zai.d.ts +276 -0
- package/packages/pi-ai/dist/models/generated/zai.d.ts.map +1 -0
- package/packages/pi-ai/dist/models/generated/zai.js +239 -0
- package/packages/pi-ai/dist/models/generated/zai.js.map +1 -0
- package/packages/pi-ai/dist/models/index.d.ts +27 -0
- package/packages/pi-ai/dist/models/index.d.ts.map +1 -0
- package/packages/pi-ai/dist/models/index.js +80 -0
- package/packages/pi-ai/dist/models/index.js.map +1 -0
- package/packages/pi-ai/dist/models.d.ts +1 -36
- package/packages/pi-ai/dist/models.d.ts.map +1 -1
- package/packages/pi-ai/dist/models.generated.test.js +1 -2
- package/packages/pi-ai/dist/models.generated.test.js.map +1 -1
- package/packages/pi-ai/dist/models.js +3 -112
- package/packages/pi-ai/dist/models.js.map +1 -1
- package/packages/pi-ai/dist/models.test.js +6 -5
- package/packages/pi-ai/dist/models.test.js.map +1 -1
- package/packages/pi-ai/scripts/generate-models.ts +74 -40
- package/packages/pi-ai/src/index.ts +1 -9
- package/packages/pi-ai/src/models/capability-patches.ts +40 -0
- package/packages/pi-ai/src/{models.custom.ts → models/custom.ts} +4 -4
- package/packages/pi-ai/src/models/generated/amazon-bedrock.ts +1486 -0
- package/packages/pi-ai/src/models/generated/anthropic.ts +381 -0
- package/packages/pi-ai/src/models/generated/azure-openai-responses.ts +704 -0
- package/packages/pi-ai/src/models/generated/cerebras.ts +75 -0
- package/packages/pi-ai/src/models/generated/github-copilot.ts +446 -0
- package/packages/pi-ai/src/models/generated/google-antigravity.ts +160 -0
- package/packages/pi-ai/src/models/generated/google-gemini-cli.ts +109 -0
- package/packages/pi-ai/src/models/generated/google-vertex.ts +211 -0
- package/packages/pi-ai/src/models/generated/google.ts +466 -0
- package/packages/pi-ai/src/models/generated/groq.ts +313 -0
- package/packages/pi-ai/src/models/generated/huggingface.ts +349 -0
- package/packages/pi-ai/src/models/generated/index.ts +52 -0
- package/packages/pi-ai/src/models/generated/kimi-coding.ts +41 -0
- package/packages/pi-ai/src/models/generated/minimax-cn.ts +109 -0
- package/packages/pi-ai/src/models/generated/minimax.ts +109 -0
- package/packages/pi-ai/src/models/generated/mistral.ts +449 -0
- package/packages/pi-ai/src/models/generated/openai-codex.ts +143 -0
- package/packages/pi-ai/src/models/generated/openai.ts +704 -0
- package/packages/pi-ai/src/models/generated/opencode-go.ts +126 -0
- package/packages/pi-ai/src/models/generated/opencode.ts +534 -0
- package/packages/pi-ai/src/models/generated/openrouter.ts +4274 -0
- package/packages/pi-ai/src/models/generated/vercel-ai-gateway.ts +2608 -0
- package/packages/pi-ai/src/models/generated/xai.ts +415 -0
- package/packages/pi-ai/src/models/generated/zai.ts +241 -0
- package/packages/pi-ai/src/models/index.ts +106 -0
- package/packages/pi-ai/src/models.generated.test.ts +1 -2
- package/packages/pi-ai/src/models.test.ts +6 -5
- package/packages/pi-ai/src/models.ts +3 -153
- package/packages/pi-ai/tsconfig.tsbuildinfo +1 -1
- package/packages/pi-coding-agent/dist/core/agent-session.d.ts.map +1 -1
- package/packages/pi-coding-agent/dist/core/agent-session.js +8 -2
- package/packages/pi-coding-agent/dist/core/agent-session.js.map +1 -1
- package/packages/pi-coding-agent/dist/core/chat-controller-ordering.test.js +472 -0
- package/packages/pi-coding-agent/dist/core/chat-controller-ordering.test.js.map +1 -1
- package/packages/pi-coding-agent/dist/core/model-registry-env-fallback.test.d.ts +2 -0
- package/packages/pi-coding-agent/dist/core/model-registry-env-fallback.test.d.ts.map +1 -0
- package/packages/pi-coding-agent/dist/core/model-registry-env-fallback.test.js +52 -0
- package/packages/pi-coding-agent/dist/core/model-registry-env-fallback.test.js.map +1 -0
- package/packages/pi-coding-agent/dist/core/model-registry.d.ts.map +1 -1
- package/packages/pi-coding-agent/dist/core/model-registry.js +2 -2
- package/packages/pi-coding-agent/dist/core/model-registry.js.map +1 -1
- package/packages/pi-coding-agent/dist/modes/interactive/components/__tests__/tool-execution.test.js +11 -0
- package/packages/pi-coding-agent/dist/modes/interactive/components/__tests__/tool-execution.test.js.map +1 -1
- package/packages/pi-coding-agent/dist/modes/interactive/components/assistant-message.d.ts +1 -0
- package/packages/pi-coding-agent/dist/modes/interactive/components/assistant-message.d.ts.map +1 -1
- package/packages/pi-coding-agent/dist/modes/interactive/components/assistant-message.js +23 -9
- package/packages/pi-coding-agent/dist/modes/interactive/components/assistant-message.js.map +1 -1
- package/packages/pi-coding-agent/dist/modes/interactive/components/chat-frame.d.ts +11 -0
- package/packages/pi-coding-agent/dist/modes/interactive/components/chat-frame.d.ts.map +1 -0
- package/packages/pi-coding-agent/dist/modes/interactive/components/chat-frame.js +47 -0
- package/packages/pi-coding-agent/dist/modes/interactive/components/chat-frame.js.map +1 -0
- package/packages/pi-coding-agent/dist/modes/interactive/components/tool-execution.d.ts +8 -0
- package/packages/pi-coding-agent/dist/modes/interactive/components/tool-execution.d.ts.map +1 -1
- package/packages/pi-coding-agent/dist/modes/interactive/components/tool-execution.js +68 -8
- package/packages/pi-coding-agent/dist/modes/interactive/components/tool-execution.js.map +1 -1
- package/packages/pi-coding-agent/dist/modes/interactive/components/user-message.d.ts.map +1 -1
- package/packages/pi-coding-agent/dist/modes/interactive/components/user-message.js +22 -22
- package/packages/pi-coding-agent/dist/modes/interactive/components/user-message.js.map +1 -1
- package/packages/pi-coding-agent/dist/modes/interactive/controllers/chat-controller.d.ts.map +1 -1
- package/packages/pi-coding-agent/dist/modes/interactive/controllers/chat-controller.js +232 -18
- package/packages/pi-coding-agent/dist/modes/interactive/controllers/chat-controller.js.map +1 -1
- package/packages/pi-coding-agent/dist/modes/interactive/interactive-mode-ordering.test.d.ts +2 -0
- package/packages/pi-coding-agent/dist/modes/interactive/interactive-mode-ordering.test.d.ts.map +1 -0
- package/packages/pi-coding-agent/dist/modes/interactive/interactive-mode-ordering.test.js +38 -0
- package/packages/pi-coding-agent/dist/modes/interactive/interactive-mode-ordering.test.js.map +1 -0
- package/packages/pi-coding-agent/dist/modes/interactive/interactive-mode.d.ts +14 -0
- package/packages/pi-coding-agent/dist/modes/interactive/interactive-mode.d.ts.map +1 -1
- package/packages/pi-coding-agent/dist/modes/interactive/interactive-mode.js +70 -6
- package/packages/pi-coding-agent/dist/modes/interactive/interactive-mode.js.map +1 -1
- package/packages/pi-coding-agent/src/core/agent-session.ts +12 -6
- package/packages/pi-coding-agent/src/core/chat-controller-ordering.test.ts +612 -0
- package/packages/pi-coding-agent/src/core/model-registry-env-fallback.test.ts +59 -0
- package/packages/pi-coding-agent/src/core/model-registry.ts +2 -1
- package/packages/pi-coding-agent/src/modes/interactive/components/__tests__/tool-execution.test.ts +19 -0
- package/packages/pi-coding-agent/src/modes/interactive/components/assistant-message.ts +25 -10
- package/packages/pi-coding-agent/src/modes/interactive/components/chat-frame.ts +67 -0
- package/packages/pi-coding-agent/src/modes/interactive/components/tool-execution.ts +83 -7
- package/packages/pi-coding-agent/src/modes/interactive/components/user-message.ts +23 -26
- package/packages/pi-coding-agent/src/modes/interactive/controllers/chat-controller.ts +298 -41
- package/packages/pi-coding-agent/src/modes/interactive/interactive-mode-ordering.test.ts +44 -0
- package/packages/pi-coding-agent/src/modes/interactive/interactive-mode.ts +92 -6
- package/packages/pi-coding-agent/src/types/ambient-modules.d.ts +69 -0
- package/packages/pi-coding-agent/tsconfig.json +2 -2
- package/packages/pi-coding-agent/tsconfig.tsbuildinfo +1 -1
- package/src/resources/extensions/gsd/activity-log.ts +21 -0
- package/src/resources/extensions/gsd/auto/loop-deps.ts +4 -0
- package/src/resources/extensions/gsd/auto/loop.ts +159 -10
- package/src/resources/extensions/gsd/auto/phases.ts +123 -3
- package/src/resources/extensions/gsd/auto/session.ts +10 -0
- package/src/resources/extensions/gsd/auto-dispatch.ts +16 -6
- package/src/resources/extensions/gsd/auto-model-selection.ts +66 -5
- package/src/resources/extensions/gsd/auto-post-unit.ts +226 -9
- package/src/resources/extensions/gsd/auto-recovery.ts +29 -9
- package/src/resources/extensions/gsd/auto-unit-closeout.ts +25 -1
- package/src/resources/extensions/gsd/auto-verification.ts +129 -2
- package/src/resources/extensions/gsd/auto.ts +34 -2
- package/src/resources/extensions/gsd/bootstrap/register-extension.ts +15 -1
- package/src/resources/extensions/gsd/bootstrap/register-hooks.ts +72 -8
- package/src/resources/extensions/gsd/cache.ts +16 -5
- package/src/resources/extensions/gsd/commands/handlers/ops.ts +5 -0
- package/src/resources/extensions/gsd/commands-extract-learnings.ts +304 -0
- package/src/resources/extensions/gsd/commands-prefs-wizard.ts +1 -1
- package/src/resources/extensions/gsd/docs/preferences-reference.md +14 -1
- package/src/resources/extensions/gsd/ecosystem/gsd-extension-api.ts +228 -0
- package/src/resources/extensions/gsd/ecosystem/loader.ts +201 -0
- package/src/resources/extensions/gsd/git-service.ts +68 -0
- package/src/resources/extensions/gsd/graph-context.ts +139 -12
- package/src/resources/extensions/gsd/gsd-db.ts +321 -3
- package/src/resources/extensions/gsd/guided-flow.ts +33 -1
- package/src/resources/extensions/gsd/init-wizard.ts +3 -2
- package/src/resources/extensions/gsd/journal.ts +30 -0
- package/src/resources/extensions/gsd/metrics.ts +26 -0
- package/src/resources/extensions/gsd/parallel-orchestrator.ts +40 -1
- package/src/resources/extensions/gsd/preferences-models.ts +20 -3
- package/src/resources/extensions/gsd/preferences-types.ts +32 -0
- package/src/resources/extensions/gsd/preferences-validation.ts +107 -2
- package/src/resources/extensions/gsd/preferences.ts +28 -0
- package/src/resources/extensions/gsd/safety/evidence-collector.ts +15 -31
- package/src/resources/extensions/gsd/session-lock.ts +14 -2
- package/src/resources/extensions/gsd/slice-parallel-orchestrator.ts +20 -1
- package/src/resources/extensions/gsd/templates/PREFERENCES.md +18 -0
- package/src/resources/extensions/gsd/tests/artifacts-table-preserved-on-cache-invalidate.test.ts +177 -0
- package/src/resources/extensions/gsd/tests/auto-loop.test.ts +7 -3
- package/src/resources/extensions/gsd/tests/auto-model-selection.test.ts +20 -0
- package/src/resources/extensions/gsd/tests/auto-project-root-env.test.ts +7 -3
- package/src/resources/extensions/gsd/tests/auto-retry-mcp-churn-fixes.test.ts +272 -0
- package/src/resources/extensions/gsd/tests/cold-resume-db-reopen.test.ts +6 -2
- package/src/resources/extensions/gsd/tests/commands-extract-learnings.test.ts +340 -0
- package/src/resources/extensions/gsd/tests/complete-slice.test.ts +2 -2
- package/src/resources/extensions/gsd/tests/complete-task.test.ts +2 -2
- package/src/resources/extensions/gsd/tests/finalize-timeout-guard.test.ts +10 -7
- package/src/resources/extensions/gsd/tests/gsd-db.test.ts +1 -1
- package/src/resources/extensions/gsd/tests/health-widget.test.ts +1 -1
- package/src/resources/extensions/gsd/tests/md-importer.test.ts +1 -2
- package/src/resources/extensions/gsd/tests/memory-store.test.ts +2 -3
- package/src/resources/extensions/gsd/tests/post-exec-retry-bypass.test.ts +79 -1
- package/src/resources/extensions/gsd/tests/post-unit-state-rebuild.test.ts +2 -1
- package/src/resources/extensions/gsd/tests/pre-execution-pause-wiring.test.ts +40 -1
- package/src/resources/extensions/gsd/tests/register-hooks-depth-verification.test.ts +1 -1
- package/src/resources/extensions/gsd/tests/token-profile.test.ts +8 -5
- package/src/resources/extensions/gsd/tests/uok-audit-unified.test.ts +101 -0
- package/src/resources/extensions/gsd/tests/uok-contracts.test.ts +85 -0
- package/src/resources/extensions/gsd/tests/uok-execution-graph.test.ts +69 -0
- package/src/resources/extensions/gsd/tests/uok-flags.test.ts +39 -0
- package/src/resources/extensions/gsd/tests/uok-gate-runner.test.ts +70 -0
- package/src/resources/extensions/gsd/tests/uok-gitops-turn-action.test.ts +85 -0
- package/src/resources/extensions/gsd/tests/uok-gitops-wiring.test.ts +35 -0
- package/src/resources/extensions/gsd/tests/uok-model-policy.test.ts +89 -0
- package/src/resources/extensions/gsd/tests/uok-plan-v2-wiring.test.ts +167 -0
- package/src/resources/extensions/gsd/tests/uok-preferences.test.ts +42 -0
- package/src/resources/extensions/gsd/tests/validate-milestone-write-order.test.ts +39 -0
- package/src/resources/extensions/gsd/tools/complete-slice.ts +9 -2
- package/src/resources/extensions/gsd/tools/validate-milestone.ts +48 -3
- package/src/resources/extensions/gsd/types.ts +14 -1
- package/src/resources/extensions/gsd/unit-ownership.ts +2 -2
- package/src/resources/extensions/gsd/uok/audit-toggle.ts +9 -0
- package/src/resources/extensions/gsd/uok/audit.ts +51 -0
- package/src/resources/extensions/gsd/uok/contracts.ts +135 -0
- package/src/resources/extensions/gsd/uok/execution-graph.ts +241 -0
- package/src/resources/extensions/gsd/uok/flags.ts +45 -0
- package/src/resources/extensions/gsd/uok/gate-runner.ts +146 -0
- package/src/resources/extensions/gsd/uok/gitops.ts +75 -0
- package/src/resources/extensions/gsd/uok/kernel.ts +105 -0
- package/src/resources/extensions/gsd/uok/loop-adapter.ts +162 -0
- package/src/resources/extensions/gsd/uok/model-policy.ts +112 -0
- package/src/resources/extensions/gsd/uok/plan-v2.ts +156 -0
- package/src/resources/extensions/gsd/workflow-logger.ts +27 -1
- package/src/resources/extensions/ttsr/ttsr-manager.ts +10 -5
- package/packages/pi-ai/dist/models.custom.d.ts.map +0 -1
- package/packages/pi-ai/dist/models.custom.js.map +0 -1
- package/packages/pi-ai/dist/models.generated.js +0 -14343
- package/packages/pi-ai/dist/models.generated.js.map +0 -1
- package/packages/pi-ai/src/models.generated.ts +0 -14345
- /package/dist/web/standalone/.next/static/{XnHY5eXUsTCFmNodWHetD → kn6xzWKYnogsxp2b6RpDD}/_buildManifest.js +0 -0
- /package/dist/web/standalone/.next/static/{XnHY5eXUsTCFmNodWHetD → kn6xzWKYnogsxp2b6RpDD}/_ssgManifest.js +0 -0
|
@@ -1,37 +1,2 @@
|
|
|
1
|
-
|
|
2
|
-
import type { Api, KnownProvider, Model, Usage } from "./types.js";
|
|
3
|
-
/**
|
|
4
|
-
* Apply capability patches to a list of models.
|
|
5
|
-
*
|
|
6
|
-
* Models constructed outside the static pi-ai registry (custom models from
|
|
7
|
-
* models.json, extension-registered models, discovered models) do not pass
|
|
8
|
-
* through the module-init patch loop. Call this function after assembling
|
|
9
|
-
* any model list to ensure capabilities are set correctly.
|
|
10
|
-
*
|
|
11
|
-
* Explicit `capabilities` already set on a model take precedence over patches.
|
|
12
|
-
*/
|
|
13
|
-
export declare function applyCapabilityPatches(models: Model<Api>[]): Model<Api>[];
|
|
14
|
-
/** Providers that have entries in the generated MODELS constant */
|
|
15
|
-
type GeneratedProvider = keyof typeof MODELS & KnownProvider;
|
|
16
|
-
type ModelApi<TProvider extends GeneratedProvider, TModelId extends keyof (typeof MODELS)[TProvider]> = (typeof MODELS)[TProvider][TModelId] extends {
|
|
17
|
-
api: infer TApi;
|
|
18
|
-
} ? (TApi extends Api ? TApi : never) : never;
|
|
19
|
-
export declare function getModel<TProvider extends GeneratedProvider, TModelId extends keyof (typeof MODELS)[TProvider]>(provider: TProvider, modelId: TModelId): Model<ModelApi<TProvider, TModelId>>;
|
|
20
|
-
export declare function getProviders(): KnownProvider[];
|
|
21
|
-
export declare function getModels<TProvider extends KnownProvider>(provider: TProvider): Model<Api>[];
|
|
22
|
-
export declare function calculateCost<TApi extends Api>(model: Model<TApi>, usage: Usage): Usage["cost"];
|
|
23
|
-
/**
|
|
24
|
-
* Check if a model supports xhigh thinking level.
|
|
25
|
-
*
|
|
26
|
-
* Reads from `model.capabilities.supportsXhigh` — set via CAPABILITY_PATCHES
|
|
27
|
-
* for generated models or declared directly in custom model definitions.
|
|
28
|
-
* Do not add model-ID or provider-name checks here; update CAPABILITY_PATCHES instead.
|
|
29
|
-
*/
|
|
30
|
-
export declare function supportsXhigh<TApi extends Api>(model: Model<TApi>): boolean;
|
|
31
|
-
/**
|
|
32
|
-
* Check if two models are equal by comparing both their id and provider.
|
|
33
|
-
* Returns false if either model is null or undefined.
|
|
34
|
-
*/
|
|
35
|
-
export declare function modelsAreEqual<TApi extends Api>(a: Model<TApi> | null | undefined, b: Model<TApi> | null | undefined): boolean;
|
|
36
|
-
export {};
|
|
1
|
+
export * from "./models/index.js";
|
|
37
2
|
//# sourceMappingURL=models.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"models.d.ts","sourceRoot":"","sources":["../src/models.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"models.d.ts","sourceRoot":"","sources":["../src/models.ts"],"names":[],"mappings":"AAEA,cAAc,mBAAmB,CAAC"}
|
|
@@ -1,7 +1,6 @@
|
|
|
1
1
|
import { describe, it } from "node:test";
|
|
2
2
|
import assert from "node:assert/strict";
|
|
3
|
-
import { MODELS } from "./models.
|
|
4
|
-
import { getModel, getModels, getProviders } from "./models.js";
|
|
3
|
+
import { MODELS, getModel, getModels, getProviders } from "./models/index.js";
|
|
5
4
|
// ═══════════════════════════════════════════════════════════════════════════
|
|
6
5
|
// Regression: qwen/qwen3.6-plus missing from OpenRouter (issue #3582)
|
|
7
6
|
// ═══════════════════════════════════════════════════════════════════════════
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"models.generated.test.js","sourceRoot":"","sources":["../src/models.generated.test.ts"],"names":[],"mappings":"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","sourcesContent":["import { describe, it } from \"node:test\";\nimport assert from \"node:assert/strict\";\nimport { MODELS } from \"./models.generated.js\";\nimport { getModel, getModels, getProviders } from \"./models.js\";\n\n// ═══════════════════════════════════════════════════════════════════════════\n// Regression: qwen/qwen3.6-plus missing from OpenRouter (issue #3582)\n// ═══════════════════════════════════════════════════════════════════════════\n\ndescribe(\"regression #3582 — qwen/qwen3.6-plus available via openrouter\", () => {\n\tit(\"qwen/qwen3.6-plus exists in MODELS['openrouter']\", () => {\n\t\tconst model = MODELS[\"openrouter\"][\"qwen/qwen3.6-plus\" as keyof (typeof MODELS)[\"openrouter\"]];\n\t\tassert.ok(model, \"qwen/qwen3.6-plus must be present in MODELS.openrouter\");\n\t});\n\n\tit(\"qwen/qwen3.6-plus is accessible via getModel()\", () => {\n\t\tconst model = getModel(\"openrouter\", \"qwen/qwen3.6-plus\" as any);\n\t\tassert.ok(model, \"getModel('openrouter', 'qwen/qwen3.6-plus') must return a model\");\n\t});\n\n\tit(\"qwen/qwen3.6-plus has id matching its registry key\", () => {\n\t\tconst model = getModel(\"openrouter\", \"qwen/qwen3.6-plus\" as any);\n\t\tassert.equal(model.id, \"qwen/qwen3.6-plus\");\n\t});\n\n\tit(\"qwen/qwen3.6-plus has provider set to openrouter\", () => {\n\t\tconst model = getModel(\"openrouter\", \"qwen/qwen3.6-plus\" as any);\n\t\tassert.equal(model.provider, \"openrouter\");\n\t});\n\n\tit(\"qwen/qwen3.6-plus has reasoning enabled\", () => {\n\t\tconst model = getModel(\"openrouter\", \"qwen/qwen3.6-plus\" as any);\n\t\tassert.equal(model.reasoning, true, \"Qwen3.6 Plus is a reasoning model\");\n\t});\n\n\tit(\"qwen/qwen3.6-plus has 1M context window\", () => {\n\t\tconst model = getModel(\"openrouter\", \"qwen/qwen3.6-plus\" as any);\n\t\tassert.equal(model.contextWindow, 1_000_000);\n\t});\n});\n\n// ═══════════════════════════════════════════════════════════════════════════\n// Regression: z-ai/glm-5.1 missing from OpenRouter (issue #4069)\n// ═══════════════════════════════════════════════════════════════════════════\n\ndescribe(\"regression #4069 — z-ai/glm-5.1 available via openrouter\", () => {\n\tit(\"z-ai/glm-5.1 exists in MODELS['openrouter']\", () => {\n\t\tconst model = MODELS[\"openrouter\"][\"z-ai/glm-5.1\" as keyof (typeof MODELS)[\"openrouter\"]];\n\t\tassert.ok(model, \"z-ai/glm-5.1 must be present in MODELS.openrouter\");\n\t});\n\n\tit(\"z-ai/glm-5.1 is accessible via getModel()\", () => {\n\t\tconst model = getModel(\"openrouter\", \"z-ai/glm-5.1\" as any);\n\t\tassert.ok(model, \"getModel('openrouter', 'z-ai/glm-5.1') must return a model\");\n\t});\n\n\tit(\"z-ai/glm-5.1 has id matching its registry key\", () => {\n\t\tconst model = getModel(\"openrouter\", \"z-ai/glm-5.1\" as any);\n\t\tassert.equal(model.id, \"z-ai/glm-5.1\");\n\t});\n\n\tit(\"z-ai/glm-5.1 has provider set to openrouter\", () => {\n\t\tconst model = getModel(\"openrouter\", \"z-ai/glm-5.1\" as any);\n\t\tassert.equal(model.provider, \"openrouter\");\n\t});\n\n\tit(\"z-ai/glm-5.1 has a positive context window\", () => {\n\t\tconst model = getModel(\"openrouter\", \"z-ai/glm-5.1\" as any);\n\t\tassert.ok(model.contextWindow > 0);\n\t});\n\n\tit(\"z-ai/glm-5.1 uses the OpenRouter base URL\", () => {\n\t\tconst model = getModel(\"openrouter\", \"z-ai/glm-5.1\" as any);\n\t\tassert.equal(model.baseUrl, \"https://openrouter.ai/api/v1\");\n\t});\n});\n\n// ═══════════════════════════════════════════════════════════════════════════\n// Structural invariants — every model in MODELS must be well-formed\n// ═══════════════════════════════════════════════════════════════════════════\n\ndescribe(\"MODELS structural invariants\", () => {\n\ttype ModelEntry = { providerKey: string; modelKey: string; model: Record<string, unknown> };\n\n\tfunction allModels(): ModelEntry[] {\n\t\tconst entries: ModelEntry[] = [];\n\t\tfor (const [providerKey, providerModels] of Object.entries(MODELS)) {\n\t\t\tfor (const [modelKey, model] of Object.entries(providerModels)) {\n\t\t\t\tentries.push({ providerKey, modelKey, model: model as Record<string, unknown> });\n\t\t\t}\n\t\t}\n\t\treturn entries;\n\t}\n\n\tit(\"every model's id field matches its key in MODELS\", () => {\n\t\tconst mismatches: string[] = [];\n\t\tfor (const { providerKey, modelKey, model } of allModels()) {\n\t\t\tif (model[\"id\"] !== modelKey) {\n\t\t\t\tmismatches.push(`${providerKey}/${modelKey}: id=\"${model[\"id\"]}\"`);\n\t\t\t}\n\t\t}\n\t\tassert.deepEqual(mismatches, [], `Models where 'id' doesn't match registry key:\\n ${mismatches.join(\"\\n \")}`);\n\t});\n\n\tit(\"every model's provider field matches its parent provider key\", () => {\n\t\tconst mismatches: string[] = [];\n\t\tfor (const { providerKey, modelKey, model } of allModels()) {\n\t\t\tif (model[\"provider\"] !== providerKey) {\n\t\t\t\tmismatches.push(`${providerKey}/${modelKey}: provider=\"${model[\"provider\"]}\"`);\n\t\t\t}\n\t\t}\n\t\tassert.deepEqual(mismatches, [], `Models where 'provider' doesn't match parent key:\\n ${mismatches.join(\"\\n \")}`);\n\t});\n\n\tit(\"every model has a non-empty string name\", () => {\n\t\tconst invalid: string[] = [];\n\t\tfor (const { providerKey, modelKey, model } of allModels()) {\n\t\t\tif (typeof model[\"name\"] !== \"string\" || model[\"name\"].trim() === \"\") {\n\t\t\t\tinvalid.push(`${providerKey}/${modelKey}`);\n\t\t\t}\n\t\t}\n\t\tassert.deepEqual(invalid, [], `Models with missing or empty name:\\n ${invalid.join(\"\\n \")}`);\n\t});\n\n\tit(\"every model has a non-empty string api\", () => {\n\t\tconst invalid: string[] = [];\n\t\tfor (const { providerKey, modelKey, model } of allModels()) {\n\t\t\tif (typeof model[\"api\"] !== \"string\" || model[\"api\"].trim() === \"\") {\n\t\t\t\tinvalid.push(`${providerKey}/${modelKey}`);\n\t\t\t}\n\t\t}\n\t\tassert.deepEqual(invalid, [], `Models with missing or empty api:\\n ${invalid.join(\"\\n \")}`);\n\t});\n\n\tit(\"every model's baseUrl starts with https:// (or is empty for azure-openai-responses)\", () => {\n\t\tconst invalid: string[] = [];\n\t\tfor (const { providerKey, modelKey, model } of allModels()) {\n\t\t\tif (providerKey === \"azure-openai-responses\") continue;\n\t\t\tconst url = model[\"baseUrl\"];\n\t\t\tif (typeof url !== \"string\" || !url.startsWith(\"https://\")) {\n\t\t\t\tinvalid.push(`${providerKey}/${modelKey}: baseUrl=\"${url}\"`);\n\t\t\t}\n\t\t}\n\t\tassert.deepEqual(invalid, [], `Models with missing or non-HTTPS baseUrl:\\n ${invalid.join(\"\\n \")}`);\n\t});\n\n\tit(\"azure-openai-responses models have an empty baseUrl (runtime-configured)\", () => {\n\t\tconst models = getModels(\"azure-openai-responses\");\n\t\tassert.ok(models.length > 0, \"azure-openai-responses must have at least one model\");\n\t\tfor (const model of models) {\n\t\t\tassert.equal(model.baseUrl, \"\", `azure-openai-responses/${model.id} should have empty baseUrl`);\n\t\t}\n\t});\n\n\tit(\"every model has a boolean reasoning field\", () => {\n\t\tconst invalid: string[] = [];\n\t\tfor (const { providerKey, modelKey, model } of allModels()) {\n\t\t\tif (typeof model[\"reasoning\"] !== \"boolean\") {\n\t\t\t\tinvalid.push(`${providerKey}/${modelKey}: reasoning=${model[\"reasoning\"]}`);\n\t\t\t}\n\t\t}\n\t\tassert.deepEqual(invalid, [], `Models with non-boolean reasoning:\\n ${invalid.join(\"\\n \")}`);\n\t});\n\n\tit(\"every model has a non-empty input array\", () => {\n\t\tconst invalid: string[] = [];\n\t\tfor (const { providerKey, modelKey, model } of allModels()) {\n\t\t\tconst input = model[\"input\"];\n\t\t\tif (!Array.isArray(input) || input.length === 0) {\n\t\t\t\tinvalid.push(`${providerKey}/${modelKey}`);\n\t\t\t}\n\t\t}\n\t\tassert.deepEqual(invalid, [], `Models with missing or empty input array:\\n ${invalid.join(\"\\n \")}`);\n\t});\n\n\tit(\"every model has a positive contextWindow\", () => {\n\t\tconst invalid: string[] = [];\n\t\tfor (const { providerKey, modelKey, model } of allModels()) {\n\t\t\tconst cw = model[\"contextWindow\"];\n\t\t\tif (typeof cw !== \"number\" || cw <= 0 || !Number.isFinite(cw)) {\n\t\t\t\tinvalid.push(`${providerKey}/${modelKey}: contextWindow=${cw}`);\n\t\t\t}\n\t\t}\n\t\tassert.deepEqual(invalid, [], `Models with invalid contextWindow:\\n ${invalid.join(\"\\n \")}`);\n\t});\n\n\tit(\"every model has a positive maxTokens\", () => {\n\t\tconst invalid: string[] = [];\n\t\tfor (const { providerKey, modelKey, model } of allModels()) {\n\t\t\tconst mt = model[\"maxTokens\"];\n\t\t\tif (typeof mt !== \"number\" || mt <= 0 || !Number.isFinite(mt)) {\n\t\t\t\tinvalid.push(`${providerKey}/${modelKey}: maxTokens=${mt}`);\n\t\t\t}\n\t\t}\n\t\tassert.deepEqual(invalid, [], `Models with invalid maxTokens:\\n ${invalid.join(\"\\n \")}`);\n\t});\n\n\tit(\"every model's maxTokens does not exceed contextWindow\", () => {\n\t\tconst knownExceptions = new Set([\n\t\t\t\"openrouter/meta-llama/llama-3-8b-instruct\",\n\t\t\t\"openrouter/nex-agi/deepseek-v3.1-nex-n1\",\n\t\t\t\"openrouter/openai/gpt-3.5-turbo-0613\",\n\t\t\t\"openrouter/z-ai/glm-5\",\n\t\t]);\n\n\t\tconst invalid: string[] = [];\n\t\tfor (const { providerKey, modelKey, model } of allModels()) {\n\t\t\tif (knownExceptions.has(`${providerKey}/${modelKey}`)) continue;\n\t\t\tconst cw = model[\"contextWindow\"] as number;\n\t\t\tconst mt = model[\"maxTokens\"] as number;\n\t\t\tif (typeof cw === \"number\" && typeof mt === \"number\" && mt > cw) {\n\t\t\t\tinvalid.push(`${providerKey}/${modelKey}: maxTokens(${mt}) > contextWindow(${cw})`);\n\t\t\t}\n\t\t}\n\t\tassert.deepEqual(invalid, [], `Models where maxTokens exceeds contextWindow:\\n ${invalid.join(\"\\n \")}`);\n\t});\n\n\tit(\"every model has a cost object with non-negative numeric fields\", () => {\n\t\tconst knownNegativeCostModels = new Set([\n\t\t\t\"openrouter/openrouter/auto\",\n\t\t]);\n\n\t\tconst invalid: string[] = [];\n\t\tfor (const { providerKey, modelKey, model } of allModels()) {\n\t\t\tif (knownNegativeCostModels.has(`${providerKey}/${modelKey}`)) continue;\n\t\t\tconst cost = model[\"cost\"] as Record<string, unknown> | undefined;\n\t\t\tif (!cost || typeof cost !== \"object\") {\n\t\t\t\tinvalid.push(`${providerKey}/${modelKey}: missing cost object`);\n\t\t\t\tcontinue;\n\t\t\t}\n\t\t\tfor (const field of [\"input\", \"output\", \"cacheRead\", \"cacheWrite\"] as const) {\n\t\t\t\tconst val = cost[field];\n\t\t\t\tif (typeof val !== \"number\" || val < 0 || !Number.isFinite(val)) {\n\t\t\t\t\tinvalid.push(`${providerKey}/${modelKey}: cost.${field}=${val}`);\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t\tassert.deepEqual(invalid, [], `Models with invalid cost fields:\\n ${invalid.join(\"\\n \")}`);\n\t});\n\n\tit(\"no provider has duplicate model IDs\", () => {\n\t\tconst duplicates: string[] = [];\n\t\tfor (const [providerKey, providerModels] of Object.entries(MODELS)) {\n\t\t\tconst ids = Object.values(providerModels).map((m) => (m as Record<string, unknown>)[\"id\"] as string);\n\t\t\tconst seen = new Set<string>();\n\t\t\tfor (const id of ids) {\n\t\t\t\tif (seen.has(id)) duplicates.push(`${providerKey}/${id}`);\n\t\t\t\tseen.add(id);\n\t\t\t}\n\t\t}\n\t\tassert.deepEqual(duplicates, [], `Duplicate model IDs within a provider:\\n ${duplicates.join(\"\\n \")}`);\n\t});\n});\n\n// ═══════════════════════════════════════════════════════════════════════════\n// Registry shape\n// ═══════════════════════════════════════════════════════════════════════════\n\ndescribe(\"MODELS registry shape\", () => {\n\tit(\"has exactly 23 providers\", () => {\n\t\tconst count = Object.keys(MODELS).length;\n\t\tassert.equal(count, 23, `Expected 23 providers, got ${count}: ${Object.keys(MODELS).join(\", \")}`);\n\t});\n\n\tit(\"has at least 200 models in total (sanity check)\", () => {\n\t\tlet total = 0;\n\t\tfor (const providerModels of Object.values(MODELS)) {\n\t\t\ttotal += Object.keys(providerModels).length;\n\t\t}\n\t\tassert.ok(total >= 200, `Registry has only ${total} models — unexpectedly small`);\n\t});\n\n\tit(\"all 23 expected providers are present\", () => {\n\t\tconst expected = [\n\t\t\t\"amazon-bedrock\",\n\t\t\t\"anthropic\",\n\t\t\t\"azure-openai-responses\",\n\t\t\t\"cerebras\",\n\t\t\t\"github-copilot\",\n\t\t\t\"google\",\n\t\t\t\"google-antigravity\",\n\t\t\t\"google-gemini-cli\",\n\t\t\t\"google-vertex\",\n\t\t\t\"groq\",\n\t\t\t\"huggingface\",\n\t\t\t\"kimi-coding\",\n\t\t\t\"minimax\",\n\t\t\t\"minimax-cn\",\n\t\t\t\"mistral\",\n\t\t\t\"openai\",\n\t\t\t\"openai-codex\",\n\t\t\t\"opencode\",\n\t\t\t\"opencode-go\",\n\t\t\t\"openrouter\",\n\t\t\t\"vercel-ai-gateway\",\n\t\t\t\"xai\",\n\t\t\t\"zai\",\n\t\t];\n\t\tconst actual = Object.keys(MODELS).sort();\n\t\tassert.deepEqual(actual, expected.sort());\n\t});\n\n\tit(\"getProviders() returns all generated providers\", () => {\n\t\tconst providers = getProviders();\n\t\tfor (const p of Object.keys(MODELS)) {\n\t\t\tassert.ok(providers.includes(p as any), `getProviders() missing generated provider: ${p}`);\n\t\t}\n\t});\n});\n\n// ═══════════════════════════════════════════════════════════════════════════\n// Removed models must not exist\n// ═══════════════════════════════════════════════════════════════════════════\n\ndescribe(\"removed models are absent from the registry\", () => {\n\tconst removedModels: Array<{ provider: string; id: string }> = [\n\t\t{ provider: \"openrouter\", id: \"anthropic/claude-3.5-sonnet\" },\n\t\t{ provider: \"openrouter\", id: \"anthropic/claude-3.5-sonnet-20240620\" },\n\t\t{ provider: \"openrouter\", id: \"mistralai/mistral-small-24b-instruct-2501\" },\n\t\t{ provider: \"openrouter\", id: \"mistralai/mistral-small-3.1-24b-instruct:free\" },\n\t\t{ provider: \"openrouter\", id: \"qwen/qwen3-4b:free\" },\n\t\t{ provider: \"openrouter\", id: \"stepfun/step-3.5-flash:free\" },\n\t\t{ provider: \"openrouter\", id: \"x-ai/grok-4.20-beta\" },\n\t\t{ provider: \"openrouter\", id: \"arcee-ai/trinity-mini:free\" },\n\t\t{ provider: \"openrouter\", id: \"google/gemini-3-pro-preview\" },\n\t\t{ provider: \"openrouter\", id: \"kwaipilot/kat-coder-pro\" },\n\t\t{ provider: \"openrouter\", id: \"meituan/longcat-flash-thinking\" },\n\t\t{ provider: \"vercel-ai-gateway\", id: \"xai/grok-2-vision\" },\n\t\t{ provider: \"anthropic\", id: \"claude-3-7-sonnet-latest\" },\n\t];\n\n\tfor (const { provider, id } of removedModels) {\n\t\tit(`${provider}/${id} has been removed`, () => {\n\t\t\tconst model = getModel(provider as any, id as any);\n\t\t\tassert.equal(model, undefined, `${provider}/${id} should be removed but is still present`);\n\t\t});\n\t}\n});\n\n// ═══════════════════════════════════════════════════════════════════════════\n// Spot-checks for notable models added in this regeneration\n// ═══════════════════════════════════════════════════════════════════════════\n\ndescribe(\"spot-checks for models added in this regeneration\", () => {\n\tconst newModels: Array<{ provider: string; id: string; reasoning?: boolean }> = [\n\t\t{ provider: \"openrouter\", id: \"z-ai/glm-5.1\" },\n\t\t{ provider: \"openrouter\", id: \"z-ai/glm-5v-turbo\" },\n\t\t{ provider: \"openrouter\", id: \"google/gemma-4-31b-it\" },\n\t\t{ provider: \"openrouter\", id: \"google/gemma-4-26b-a4b-it\" },\n\t\t{ provider: \"openrouter\", id: \"arcee-ai/trinity-large-thinking\", reasoning: true },\n\t\t{ provider: \"openrouter\", id: \"openai/gpt-audio\" },\n\t\t{ provider: \"openrouter\", id: \"anthropic/claude-opus-4.6-fast\" },\n\t\t{ provider: \"openrouter\", id: \"qwen/qwen3.6-plus\" },\n\t\t{ provider: \"groq\", id: \"groq/compound\" },\n\t\t{ provider: \"groq\", id: \"groq/compound-mini\" },\n\t\t{ provider: \"huggingface\", id: \"zai-org/GLM-5.1\" },\n\t\t{ provider: \"openai\", id: \"gpt-5.3-chat-latest\" },\n\t\t{ provider: \"mistral\", id: \"mistral-small-2603\" },\n\t\t{ provider: \"zai\", id: \"glm-5.1\" },\n\t];\n\n\tfor (const { provider, id, reasoning } of newModels) {\n\t\tit(`${provider}/${id} is present in the registry`, () => {\n\t\t\tconst model = getModel(provider as any, id as any);\n\t\t\tassert.ok(model, `Expected ${provider}/${id} to be present after regeneration`);\n\t\t\tassert.equal(model.id, id);\n\t\t\tassert.equal(model.provider, provider);\n\t\t\tif (reasoning !== undefined) {\n\t\t\t\tassert.equal(model.reasoning, reasoning, `${id} reasoning should be ${reasoning}`);\n\t\t\t}\n\t\t});\n\t}\n});\n"]}
|
|
1
|
+
{"version":3,"file":"models.generated.test.js","sourceRoot":"","sources":["../src/models.generated.test.ts"],"names":[],"mappings":"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","sourcesContent":["import { describe, it } from \"node:test\";\nimport assert from \"node:assert/strict\";\nimport { MODELS, getModel, getModels, getProviders } from \"./models/index.js\";\n\n// ═══════════════════════════════════════════════════════════════════════════\n// Regression: qwen/qwen3.6-plus missing from OpenRouter (issue #3582)\n// ═══════════════════════════════════════════════════════════════════════════\n\ndescribe(\"regression #3582 — qwen/qwen3.6-plus available via openrouter\", () => {\n\tit(\"qwen/qwen3.6-plus exists in MODELS['openrouter']\", () => {\n\t\tconst model = MODELS[\"openrouter\"][\"qwen/qwen3.6-plus\" as keyof (typeof MODELS)[\"openrouter\"]];\n\t\tassert.ok(model, \"qwen/qwen3.6-plus must be present in MODELS.openrouter\");\n\t});\n\n\tit(\"qwen/qwen3.6-plus is accessible via getModel()\", () => {\n\t\tconst model = getModel(\"openrouter\", \"qwen/qwen3.6-plus\" as any);\n\t\tassert.ok(model, \"getModel('openrouter', 'qwen/qwen3.6-plus') must return a model\");\n\t});\n\n\tit(\"qwen/qwen3.6-plus has id matching its registry key\", () => {\n\t\tconst model = getModel(\"openrouter\", \"qwen/qwen3.6-plus\" as any);\n\t\tassert.equal(model.id, \"qwen/qwen3.6-plus\");\n\t});\n\n\tit(\"qwen/qwen3.6-plus has provider set to openrouter\", () => {\n\t\tconst model = getModel(\"openrouter\", \"qwen/qwen3.6-plus\" as any);\n\t\tassert.equal(model.provider, \"openrouter\");\n\t});\n\n\tit(\"qwen/qwen3.6-plus has reasoning enabled\", () => {\n\t\tconst model = getModel(\"openrouter\", \"qwen/qwen3.6-plus\" as any);\n\t\tassert.equal(model.reasoning, true, \"Qwen3.6 Plus is a reasoning model\");\n\t});\n\n\tit(\"qwen/qwen3.6-plus has 1M context window\", () => {\n\t\tconst model = getModel(\"openrouter\", \"qwen/qwen3.6-plus\" as any);\n\t\tassert.equal(model.contextWindow, 1_000_000);\n\t});\n});\n\n// ═══════════════════════════════════════════════════════════════════════════\n// Regression: z-ai/glm-5.1 missing from OpenRouter (issue #4069)\n// ═══════════════════════════════════════════════════════════════════════════\n\ndescribe(\"regression #4069 — z-ai/glm-5.1 available via openrouter\", () => {\n\tit(\"z-ai/glm-5.1 exists in MODELS['openrouter']\", () => {\n\t\tconst model = MODELS[\"openrouter\"][\"z-ai/glm-5.1\" as keyof (typeof MODELS)[\"openrouter\"]];\n\t\tassert.ok(model, \"z-ai/glm-5.1 must be present in MODELS.openrouter\");\n\t});\n\n\tit(\"z-ai/glm-5.1 is accessible via getModel()\", () => {\n\t\tconst model = getModel(\"openrouter\", \"z-ai/glm-5.1\" as any);\n\t\tassert.ok(model, \"getModel('openrouter', 'z-ai/glm-5.1') must return a model\");\n\t});\n\n\tit(\"z-ai/glm-5.1 has id matching its registry key\", () => {\n\t\tconst model = getModel(\"openrouter\", \"z-ai/glm-5.1\" as any);\n\t\tassert.equal(model.id, \"z-ai/glm-5.1\");\n\t});\n\n\tit(\"z-ai/glm-5.1 has provider set to openrouter\", () => {\n\t\tconst model = getModel(\"openrouter\", \"z-ai/glm-5.1\" as any);\n\t\tassert.equal(model.provider, \"openrouter\");\n\t});\n\n\tit(\"z-ai/glm-5.1 has a positive context window\", () => {\n\t\tconst model = getModel(\"openrouter\", \"z-ai/glm-5.1\" as any);\n\t\tassert.ok(model.contextWindow > 0);\n\t});\n\n\tit(\"z-ai/glm-5.1 uses the OpenRouter base URL\", () => {\n\t\tconst model = getModel(\"openrouter\", \"z-ai/glm-5.1\" as any);\n\t\tassert.equal(model.baseUrl, \"https://openrouter.ai/api/v1\");\n\t});\n});\n\n// ═══════════════════════════════════════════════════════════════════════════\n// Structural invariants — every model in MODELS must be well-formed\n// ═══════════════════════════════════════════════════════════════════════════\n\ndescribe(\"MODELS structural invariants\", () => {\n\ttype ModelEntry = { providerKey: string; modelKey: string; model: Record<string, unknown> };\n\n\tfunction allModels(): ModelEntry[] {\n\t\tconst entries: ModelEntry[] = [];\n\t\tfor (const [providerKey, providerModels] of Object.entries(MODELS)) {\n\t\t\tfor (const [modelKey, model] of Object.entries(providerModels)) {\n\t\t\t\tentries.push({ providerKey, modelKey, model: model as Record<string, unknown> });\n\t\t\t}\n\t\t}\n\t\treturn entries;\n\t}\n\n\tit(\"every model's id field matches its key in MODELS\", () => {\n\t\tconst mismatches: string[] = [];\n\t\tfor (const { providerKey, modelKey, model } of allModels()) {\n\t\t\tif (model[\"id\"] !== modelKey) {\n\t\t\t\tmismatches.push(`${providerKey}/${modelKey}: id=\"${model[\"id\"]}\"`);\n\t\t\t}\n\t\t}\n\t\tassert.deepEqual(mismatches, [], `Models where 'id' doesn't match registry key:\\n ${mismatches.join(\"\\n \")}`);\n\t});\n\n\tit(\"every model's provider field matches its parent provider key\", () => {\n\t\tconst mismatches: string[] = [];\n\t\tfor (const { providerKey, modelKey, model } of allModels()) {\n\t\t\tif (model[\"provider\"] !== providerKey) {\n\t\t\t\tmismatches.push(`${providerKey}/${modelKey}: provider=\"${model[\"provider\"]}\"`);\n\t\t\t}\n\t\t}\n\t\tassert.deepEqual(mismatches, [], `Models where 'provider' doesn't match parent key:\\n ${mismatches.join(\"\\n \")}`);\n\t});\n\n\tit(\"every model has a non-empty string name\", () => {\n\t\tconst invalid: string[] = [];\n\t\tfor (const { providerKey, modelKey, model } of allModels()) {\n\t\t\tif (typeof model[\"name\"] !== \"string\" || model[\"name\"].trim() === \"\") {\n\t\t\t\tinvalid.push(`${providerKey}/${modelKey}`);\n\t\t\t}\n\t\t}\n\t\tassert.deepEqual(invalid, [], `Models with missing or empty name:\\n ${invalid.join(\"\\n \")}`);\n\t});\n\n\tit(\"every model has a non-empty string api\", () => {\n\t\tconst invalid: string[] = [];\n\t\tfor (const { providerKey, modelKey, model } of allModels()) {\n\t\t\tif (typeof model[\"api\"] !== \"string\" || model[\"api\"].trim() === \"\") {\n\t\t\t\tinvalid.push(`${providerKey}/${modelKey}`);\n\t\t\t}\n\t\t}\n\t\tassert.deepEqual(invalid, [], `Models with missing or empty api:\\n ${invalid.join(\"\\n \")}`);\n\t});\n\n\tit(\"every model's baseUrl starts with https:// (or is empty for azure-openai-responses)\", () => {\n\t\tconst invalid: string[] = [];\n\t\tfor (const { providerKey, modelKey, model } of allModels()) {\n\t\t\tif (providerKey === \"azure-openai-responses\") continue;\n\t\t\tconst url = model[\"baseUrl\"];\n\t\t\tif (typeof url !== \"string\" || !url.startsWith(\"https://\")) {\n\t\t\t\tinvalid.push(`${providerKey}/${modelKey}: baseUrl=\"${url}\"`);\n\t\t\t}\n\t\t}\n\t\tassert.deepEqual(invalid, [], `Models with missing or non-HTTPS baseUrl:\\n ${invalid.join(\"\\n \")}`);\n\t});\n\n\tit(\"azure-openai-responses models have an empty baseUrl (runtime-configured)\", () => {\n\t\tconst models = getModels(\"azure-openai-responses\");\n\t\tassert.ok(models.length > 0, \"azure-openai-responses must have at least one model\");\n\t\tfor (const model of models) {\n\t\t\tassert.equal(model.baseUrl, \"\", `azure-openai-responses/${model.id} should have empty baseUrl`);\n\t\t}\n\t});\n\n\tit(\"every model has a boolean reasoning field\", () => {\n\t\tconst invalid: string[] = [];\n\t\tfor (const { providerKey, modelKey, model } of allModels()) {\n\t\t\tif (typeof model[\"reasoning\"] !== \"boolean\") {\n\t\t\t\tinvalid.push(`${providerKey}/${modelKey}: reasoning=${model[\"reasoning\"]}`);\n\t\t\t}\n\t\t}\n\t\tassert.deepEqual(invalid, [], `Models with non-boolean reasoning:\\n ${invalid.join(\"\\n \")}`);\n\t});\n\n\tit(\"every model has a non-empty input array\", () => {\n\t\tconst invalid: string[] = [];\n\t\tfor (const { providerKey, modelKey, model } of allModels()) {\n\t\t\tconst input = model[\"input\"];\n\t\t\tif (!Array.isArray(input) || input.length === 0) {\n\t\t\t\tinvalid.push(`${providerKey}/${modelKey}`);\n\t\t\t}\n\t\t}\n\t\tassert.deepEqual(invalid, [], `Models with missing or empty input array:\\n ${invalid.join(\"\\n \")}`);\n\t});\n\n\tit(\"every model has a positive contextWindow\", () => {\n\t\tconst invalid: string[] = [];\n\t\tfor (const { providerKey, modelKey, model } of allModels()) {\n\t\t\tconst cw = model[\"contextWindow\"];\n\t\t\tif (typeof cw !== \"number\" || cw <= 0 || !Number.isFinite(cw)) {\n\t\t\t\tinvalid.push(`${providerKey}/${modelKey}: contextWindow=${cw}`);\n\t\t\t}\n\t\t}\n\t\tassert.deepEqual(invalid, [], `Models with invalid contextWindow:\\n ${invalid.join(\"\\n \")}`);\n\t});\n\n\tit(\"every model has a positive maxTokens\", () => {\n\t\tconst invalid: string[] = [];\n\t\tfor (const { providerKey, modelKey, model } of allModels()) {\n\t\t\tconst mt = model[\"maxTokens\"];\n\t\t\tif (typeof mt !== \"number\" || mt <= 0 || !Number.isFinite(mt)) {\n\t\t\t\tinvalid.push(`${providerKey}/${modelKey}: maxTokens=${mt}`);\n\t\t\t}\n\t\t}\n\t\tassert.deepEqual(invalid, [], `Models with invalid maxTokens:\\n ${invalid.join(\"\\n \")}`);\n\t});\n\n\tit(\"every model's maxTokens does not exceed contextWindow\", () => {\n\t\tconst knownExceptions = new Set([\n\t\t\t\"openrouter/meta-llama/llama-3-8b-instruct\",\n\t\t\t\"openrouter/nex-agi/deepseek-v3.1-nex-n1\",\n\t\t\t\"openrouter/openai/gpt-3.5-turbo-0613\",\n\t\t\t\"openrouter/z-ai/glm-5\",\n\t\t]);\n\n\t\tconst invalid: string[] = [];\n\t\tfor (const { providerKey, modelKey, model } of allModels()) {\n\t\t\tif (knownExceptions.has(`${providerKey}/${modelKey}`)) continue;\n\t\t\tconst cw = model[\"contextWindow\"] as number;\n\t\t\tconst mt = model[\"maxTokens\"] as number;\n\t\t\tif (typeof cw === \"number\" && typeof mt === \"number\" && mt > cw) {\n\t\t\t\tinvalid.push(`${providerKey}/${modelKey}: maxTokens(${mt}) > contextWindow(${cw})`);\n\t\t\t}\n\t\t}\n\t\tassert.deepEqual(invalid, [], `Models where maxTokens exceeds contextWindow:\\n ${invalid.join(\"\\n \")}`);\n\t});\n\n\tit(\"every model has a cost object with non-negative numeric fields\", () => {\n\t\tconst knownNegativeCostModels = new Set([\n\t\t\t\"openrouter/openrouter/auto\",\n\t\t]);\n\n\t\tconst invalid: string[] = [];\n\t\tfor (const { providerKey, modelKey, model } of allModels()) {\n\t\t\tif (knownNegativeCostModels.has(`${providerKey}/${modelKey}`)) continue;\n\t\t\tconst cost = model[\"cost\"] as Record<string, unknown> | undefined;\n\t\t\tif (!cost || typeof cost !== \"object\") {\n\t\t\t\tinvalid.push(`${providerKey}/${modelKey}: missing cost object`);\n\t\t\t\tcontinue;\n\t\t\t}\n\t\t\tfor (const field of [\"input\", \"output\", \"cacheRead\", \"cacheWrite\"] as const) {\n\t\t\t\tconst val = cost[field];\n\t\t\t\tif (typeof val !== \"number\" || val < 0 || !Number.isFinite(val)) {\n\t\t\t\t\tinvalid.push(`${providerKey}/${modelKey}: cost.${field}=${val}`);\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t\tassert.deepEqual(invalid, [], `Models with invalid cost fields:\\n ${invalid.join(\"\\n \")}`);\n\t});\n\n\tit(\"no provider has duplicate model IDs\", () => {\n\t\tconst duplicates: string[] = [];\n\t\tfor (const [providerKey, providerModels] of Object.entries(MODELS)) {\n\t\t\tconst ids = Object.values(providerModels).map((m) => (m as Record<string, unknown>)[\"id\"] as string);\n\t\t\tconst seen = new Set<string>();\n\t\t\tfor (const id of ids) {\n\t\t\t\tif (seen.has(id)) duplicates.push(`${providerKey}/${id}`);\n\t\t\t\tseen.add(id);\n\t\t\t}\n\t\t}\n\t\tassert.deepEqual(duplicates, [], `Duplicate model IDs within a provider:\\n ${duplicates.join(\"\\n \")}`);\n\t});\n});\n\n// ═══════════════════════════════════════════════════════════════════════════\n// Registry shape\n// ═══════════════════════════════════════════════════════════════════════════\n\ndescribe(\"MODELS registry shape\", () => {\n\tit(\"has exactly 23 providers\", () => {\n\t\tconst count = Object.keys(MODELS).length;\n\t\tassert.equal(count, 23, `Expected 23 providers, got ${count}: ${Object.keys(MODELS).join(\", \")}`);\n\t});\n\n\tit(\"has at least 200 models in total (sanity check)\", () => {\n\t\tlet total = 0;\n\t\tfor (const providerModels of Object.values(MODELS)) {\n\t\t\ttotal += Object.keys(providerModels).length;\n\t\t}\n\t\tassert.ok(total >= 200, `Registry has only ${total} models — unexpectedly small`);\n\t});\n\n\tit(\"all 23 expected providers are present\", () => {\n\t\tconst expected = [\n\t\t\t\"amazon-bedrock\",\n\t\t\t\"anthropic\",\n\t\t\t\"azure-openai-responses\",\n\t\t\t\"cerebras\",\n\t\t\t\"github-copilot\",\n\t\t\t\"google\",\n\t\t\t\"google-antigravity\",\n\t\t\t\"google-gemini-cli\",\n\t\t\t\"google-vertex\",\n\t\t\t\"groq\",\n\t\t\t\"huggingface\",\n\t\t\t\"kimi-coding\",\n\t\t\t\"minimax\",\n\t\t\t\"minimax-cn\",\n\t\t\t\"mistral\",\n\t\t\t\"openai\",\n\t\t\t\"openai-codex\",\n\t\t\t\"opencode\",\n\t\t\t\"opencode-go\",\n\t\t\t\"openrouter\",\n\t\t\t\"vercel-ai-gateway\",\n\t\t\t\"xai\",\n\t\t\t\"zai\",\n\t\t];\n\t\tconst actual = Object.keys(MODELS).sort();\n\t\tassert.deepEqual(actual, expected.sort());\n\t});\n\n\tit(\"getProviders() returns all generated providers\", () => {\n\t\tconst providers = getProviders();\n\t\tfor (const p of Object.keys(MODELS)) {\n\t\t\tassert.ok(providers.includes(p as any), `getProviders() missing generated provider: ${p}`);\n\t\t}\n\t});\n});\n\n// ═══════════════════════════════════════════════════════════════════════════\n// Removed models must not exist\n// ═══════════════════════════════════════════════════════════════════════════\n\ndescribe(\"removed models are absent from the registry\", () => {\n\tconst removedModels: Array<{ provider: string; id: string }> = [\n\t\t{ provider: \"openrouter\", id: \"anthropic/claude-3.5-sonnet\" },\n\t\t{ provider: \"openrouter\", id: \"anthropic/claude-3.5-sonnet-20240620\" },\n\t\t{ provider: \"openrouter\", id: \"mistralai/mistral-small-24b-instruct-2501\" },\n\t\t{ provider: \"openrouter\", id: \"mistralai/mistral-small-3.1-24b-instruct:free\" },\n\t\t{ provider: \"openrouter\", id: \"qwen/qwen3-4b:free\" },\n\t\t{ provider: \"openrouter\", id: \"stepfun/step-3.5-flash:free\" },\n\t\t{ provider: \"openrouter\", id: \"x-ai/grok-4.20-beta\" },\n\t\t{ provider: \"openrouter\", id: \"arcee-ai/trinity-mini:free\" },\n\t\t{ provider: \"openrouter\", id: \"google/gemini-3-pro-preview\" },\n\t\t{ provider: \"openrouter\", id: \"kwaipilot/kat-coder-pro\" },\n\t\t{ provider: \"openrouter\", id: \"meituan/longcat-flash-thinking\" },\n\t\t{ provider: \"vercel-ai-gateway\", id: \"xai/grok-2-vision\" },\n\t\t{ provider: \"anthropic\", id: \"claude-3-7-sonnet-latest\" },\n\t];\n\n\tfor (const { provider, id } of removedModels) {\n\t\tit(`${provider}/${id} has been removed`, () => {\n\t\t\tconst model = getModel(provider as any, id as any);\n\t\t\tassert.equal(model, undefined, `${provider}/${id} should be removed but is still present`);\n\t\t});\n\t}\n});\n\n// ═══════════════════════════════════════════════════════════════════════════\n// Spot-checks for notable models added in this regeneration\n// ═══════════════════════════════════════════════════════════════════════════\n\ndescribe(\"spot-checks for models added in this regeneration\", () => {\n\tconst newModels: Array<{ provider: string; id: string; reasoning?: boolean }> = [\n\t\t{ provider: \"openrouter\", id: \"z-ai/glm-5.1\" },\n\t\t{ provider: \"openrouter\", id: \"z-ai/glm-5v-turbo\" },\n\t\t{ provider: \"openrouter\", id: \"google/gemma-4-31b-it\" },\n\t\t{ provider: \"openrouter\", id: \"google/gemma-4-26b-a4b-it\" },\n\t\t{ provider: \"openrouter\", id: \"arcee-ai/trinity-large-thinking\", reasoning: true },\n\t\t{ provider: \"openrouter\", id: \"openai/gpt-audio\" },\n\t\t{ provider: \"openrouter\", id: \"anthropic/claude-opus-4.6-fast\" },\n\t\t{ provider: \"openrouter\", id: \"qwen/qwen3.6-plus\" },\n\t\t{ provider: \"groq\", id: \"groq/compound\" },\n\t\t{ provider: \"groq\", id: \"groq/compound-mini\" },\n\t\t{ provider: \"huggingface\", id: \"zai-org/GLM-5.1\" },\n\t\t{ provider: \"openai\", id: \"gpt-5.3-chat-latest\" },\n\t\t{ provider: \"mistral\", id: \"mistral-small-2603\" },\n\t\t{ provider: \"zai\", id: \"glm-5.1\" },\n\t];\n\n\tfor (const { provider, id, reasoning } of newModels) {\n\t\tit(`${provider}/${id} is present in the registry`, () => {\n\t\t\tconst model = getModel(provider as any, id as any);\n\t\t\tassert.ok(model, `Expected ${provider}/${id} to be present after regeneration`);\n\t\t\tassert.equal(model.id, id);\n\t\t\tassert.equal(model.provider, provider);\n\t\t\tif (reasoning !== undefined) {\n\t\t\t\tassert.equal(model.reasoning, reasoning, `${id} reasoning should be ${reasoning}`);\n\t\t\t}\n\t\t});\n\t}\n});\n"]}
|
|
@@ -1,113 +1,4 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
// Initialize registry from auto-generated MODELS (models.dev catalog)
|
|
5
|
-
for (const [provider, models] of Object.entries(MODELS)) {
|
|
6
|
-
const providerModels = new Map();
|
|
7
|
-
for (const [id, model] of Object.entries(models)) {
|
|
8
|
-
providerModels.set(id, model);
|
|
9
|
-
}
|
|
10
|
-
modelRegistry.set(provider, providerModels);
|
|
11
|
-
}
|
|
12
|
-
// Merge manually-maintained custom providers that are NOT in models.dev.
|
|
13
|
-
// Custom models are additive — they never overwrite generated entries.
|
|
14
|
-
// See: https://github.com/gsd-build/gsd-2/issues/2339
|
|
15
|
-
for (const [provider, models] of Object.entries(CUSTOM_MODELS)) {
|
|
16
|
-
if (!modelRegistry.has(provider)) {
|
|
17
|
-
modelRegistry.set(provider, new Map());
|
|
18
|
-
}
|
|
19
|
-
const providerModels = modelRegistry.get(provider);
|
|
20
|
-
for (const [id, model] of Object.entries(models)) {
|
|
21
|
-
if (!providerModels.has(id)) {
|
|
22
|
-
providerModels.set(id, model);
|
|
23
|
-
}
|
|
24
|
-
}
|
|
25
|
-
}
|
|
26
|
-
const CAPABILITY_PATCHES = [
|
|
27
|
-
// GPT-5.x supports xhigh thinking and OpenAI service tiers
|
|
28
|
-
{
|
|
29
|
-
match: (m) => m.id.includes("gpt-5.2") || m.id.includes("gpt-5.3") || m.id.includes("gpt-5.4"),
|
|
30
|
-
caps: { supportsXhigh: true, supportsServiceTier: true },
|
|
31
|
-
},
|
|
32
|
-
// Anthropic Opus 4.6 supports xhigh thinking
|
|
33
|
-
{
|
|
34
|
-
match: (m) => m.api === "anthropic-messages" && (m.id.includes("opus-4-6") || m.id.includes("opus-4.6")),
|
|
35
|
-
caps: { supportsXhigh: true },
|
|
36
|
-
},
|
|
37
|
-
];
|
|
38
|
-
/**
|
|
39
|
-
* Apply capability patches to a list of models.
|
|
40
|
-
*
|
|
41
|
-
* Models constructed outside the static pi-ai registry (custom models from
|
|
42
|
-
* models.json, extension-registered models, discovered models) do not pass
|
|
43
|
-
* through the module-init patch loop. Call this function after assembling
|
|
44
|
-
* any model list to ensure capabilities are set correctly.
|
|
45
|
-
*
|
|
46
|
-
* Explicit `capabilities` already set on a model take precedence over patches.
|
|
47
|
-
*/
|
|
48
|
-
export function applyCapabilityPatches(models) {
|
|
49
|
-
return models.map((model) => {
|
|
50
|
-
for (const patch of CAPABILITY_PATCHES) {
|
|
51
|
-
if (patch.match(model)) {
|
|
52
|
-
return {
|
|
53
|
-
...model,
|
|
54
|
-
capabilities: { ...patch.caps, ...model.capabilities },
|
|
55
|
-
};
|
|
56
|
-
}
|
|
57
|
-
}
|
|
58
|
-
return model;
|
|
59
|
-
});
|
|
60
|
-
}
|
|
61
|
-
// Apply patches to the static registry at module load
|
|
62
|
-
for (const [, providerModels] of modelRegistry) {
|
|
63
|
-
for (const [id, model] of providerModels) {
|
|
64
|
-
for (const patch of CAPABILITY_PATCHES) {
|
|
65
|
-
if (patch.match(model)) {
|
|
66
|
-
providerModels.set(id, {
|
|
67
|
-
...model,
|
|
68
|
-
capabilities: { ...patch.caps, ...model.capabilities },
|
|
69
|
-
});
|
|
70
|
-
break;
|
|
71
|
-
}
|
|
72
|
-
}
|
|
73
|
-
}
|
|
74
|
-
}
|
|
75
|
-
export function getModel(provider, modelId) {
|
|
76
|
-
const providerModels = modelRegistry.get(provider);
|
|
77
|
-
return providerModels?.get(modelId);
|
|
78
|
-
}
|
|
79
|
-
export function getProviders() {
|
|
80
|
-
return Array.from(modelRegistry.keys());
|
|
81
|
-
}
|
|
82
|
-
export function getModels(provider) {
|
|
83
|
-
const models = modelRegistry.get(provider);
|
|
84
|
-
return models ? Array.from(models.values()) : [];
|
|
85
|
-
}
|
|
86
|
-
export function calculateCost(model, usage) {
|
|
87
|
-
usage.cost.input = (model.cost.input / 1000000) * usage.input;
|
|
88
|
-
usage.cost.output = (model.cost.output / 1000000) * usage.output;
|
|
89
|
-
usage.cost.cacheRead = (model.cost.cacheRead / 1000000) * usage.cacheRead;
|
|
90
|
-
usage.cost.cacheWrite = (model.cost.cacheWrite / 1000000) * usage.cacheWrite;
|
|
91
|
-
usage.cost.total = usage.cost.input + usage.cost.output + usage.cost.cacheRead + usage.cost.cacheWrite;
|
|
92
|
-
return usage.cost;
|
|
93
|
-
}
|
|
94
|
-
/**
|
|
95
|
-
* Check if a model supports xhigh thinking level.
|
|
96
|
-
*
|
|
97
|
-
* Reads from `model.capabilities.supportsXhigh` — set via CAPABILITY_PATCHES
|
|
98
|
-
* for generated models or declared directly in custom model definitions.
|
|
99
|
-
* Do not add model-ID or provider-name checks here; update CAPABILITY_PATCHES instead.
|
|
100
|
-
*/
|
|
101
|
-
export function supportsXhigh(model) {
|
|
102
|
-
return model.capabilities?.supportsXhigh ?? false;
|
|
103
|
-
}
|
|
104
|
-
/**
|
|
105
|
-
* Check if two models are equal by comparing both their id and provider.
|
|
106
|
-
* Returns false if either model is null or undefined.
|
|
107
|
-
*/
|
|
108
|
-
export function modelsAreEqual(a, b) {
|
|
109
|
-
if (!a || !b)
|
|
110
|
-
return false;
|
|
111
|
-
return a.id === b.id && a.provider === b.provider;
|
|
112
|
-
}
|
|
1
|
+
// Backward-compatible entrypoint.
|
|
2
|
+
// ADR-007 moved model registry internals to src/models/*.
|
|
3
|
+
export * from "./models/index.js";
|
|
113
4
|
//# sourceMappingURL=models.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"models.js","sourceRoot":"","sources":["../src/models.ts"],"names":[],"mappings":"AAAA,
|
|
1
|
+
{"version":3,"file":"models.js","sourceRoot":"","sources":["../src/models.ts"],"names":[],"mappings":"AAAA,kCAAkC;AAClC,0DAA0D;AAC1D,cAAc,mBAAmB,CAAC","sourcesContent":["// Backward-compatible entrypoint.\n// ADR-007 moved model registry internals to src/models/*.\nexport * from \"./models/index.js\";\n"]}
|
|
@@ -5,8 +5,8 @@ import { getProviders, getModels, getModel, supportsXhigh, applyCapabilityPatche
|
|
|
5
5
|
// Custom provider preservation (regression: #2339)
|
|
6
6
|
//
|
|
7
7
|
// Custom providers (like alibaba-coding-plan) are manually maintained and
|
|
8
|
-
// NOT sourced from models.dev. They must survive
|
|
9
|
-
// regeneration by living in models
|
|
8
|
+
// NOT sourced from models.dev. They must survive generated catalog
|
|
9
|
+
// regeneration by living in models/custom.ts.
|
|
10
10
|
// ═══════════════════════════════════════════════════════════════════════════
|
|
11
11
|
describe("model registry — custom providers", () => {
|
|
12
12
|
it("alibaba-coding-plan is a registered provider", () => {
|
|
@@ -49,7 +49,7 @@ describe("model registry — custom providers", () => {
|
|
|
49
49
|
it("getModel retrieves alibaba-coding-plan models by provider+id", () => {
|
|
50
50
|
// Use type assertion to test runtime behavior — alibaba-coding-plan may come
|
|
51
51
|
// from custom models rather than the generated file, so the narrow
|
|
52
|
-
// GeneratedProvider type doesn't include it until models
|
|
52
|
+
// GeneratedProvider type doesn't include it until models/custom.ts is merged.
|
|
53
53
|
const model = getModel("alibaba-coding-plan", "qwen3.5-plus");
|
|
54
54
|
assert.ok(model, "Expected getModel to return a model for alibaba-coding-plan/qwen3.5-plus");
|
|
55
55
|
assert.equal(model.id, "qwen3.5-plus");
|
|
@@ -70,11 +70,12 @@ describe("model registry — custom zai provider (GLM-5.1)", () => {
|
|
|
70
70
|
assert.equal(model.baseUrl, "https://api.z.ai/api/coding/paas/v4");
|
|
71
71
|
assert.equal(model.api, "openai-completions");
|
|
72
72
|
});
|
|
73
|
-
it("glm-5.1 has reasoning enabled and
|
|
73
|
+
it("glm-5.1 has reasoning enabled and uses generated catalog precedence", () => {
|
|
74
74
|
const model = getModel("zai", "glm-5.1");
|
|
75
75
|
assert.ok(model);
|
|
76
76
|
assert.equal(model.reasoning, true);
|
|
77
|
-
|
|
77
|
+
// Generated catalog entries are loaded first; custom models are additive-only.
|
|
78
|
+
assert.equal(model.contextWindow, 200000);
|
|
78
79
|
assert.equal(model.maxTokens, 131072);
|
|
79
80
|
});
|
|
80
81
|
it("custom glm-5.1 does not overwrite generated zai models", () => {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"models.test.js","sourceRoot":"","sources":["../src/models.test.ts"],"names":[],"mappings":"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","sourcesContent":["import { describe, it } from \"node:test\";\nimport assert from \"node:assert/strict\";\nimport { getProviders, getModels, getModel, supportsXhigh, applyCapabilityPatches } from \"./models.js\";\nimport type { Api, Model } from \"./types.js\";\n\n// ═══════════════════════════════════════════════════════════════════════════\n// Custom provider preservation (regression: #2339)\n//\n// Custom providers (like alibaba-coding-plan) are manually maintained and\n// NOT sourced from models.dev. They must survive models.generated.ts\n// regeneration by living in models.custom.ts.\n// ═══════════════════════════════════════════════════════════════════════════\n\ndescribe(\"model registry — custom providers\", () => {\n\tit(\"alibaba-coding-plan is a registered provider\", () => {\n\t\tconst providers = getProviders();\n\t\tassert.ok(\n\t\t\tproviders.includes(\"alibaba-coding-plan\"),\n\t\t\t`Expected \"alibaba-coding-plan\" in providers, got: ${providers.join(\", \")}`,\n\t\t);\n\t});\n\n\tit(\"alibaba-coding-plan has all expected models\", () => {\n\t\tconst models = getModels(\"alibaba-coding-plan\");\n\t\tconst ids = models.map((m) => m.id).sort();\n\t\tconst expected = [\n\t\t\t\"MiniMax-M2.5\",\n\t\t\t\"glm-4.7\",\n\t\t\t\"glm-5\",\n\t\t\t\"kimi-k2.5\",\n\t\t\t\"qwen3-coder-next\",\n\t\t\t\"qwen3-coder-plus\",\n\t\t\t\"qwen3-max-2026-01-23\",\n\t\t\t\"qwen3.5-plus\",\n\t\t];\n\t\tassert.deepEqual(ids, expected);\n\t});\n\n\tit(\"alibaba-coding-plan models use the correct base URL\", () => {\n\t\tconst models = getModels(\"alibaba-coding-plan\");\n\t\tfor (const model of models) {\n\t\t\tassert.equal(\n\t\t\t\tmodel.baseUrl,\n\t\t\t\t\"https://coding-intl.dashscope.aliyuncs.com/v1\",\n\t\t\t\t`Model ${model.id} has wrong baseUrl: ${model.baseUrl}`,\n\t\t\t);\n\t\t}\n\t});\n\n\tit(\"alibaba-coding-plan models use openai-completions API\", () => {\n\t\tconst models = getModels(\"alibaba-coding-plan\");\n\t\tfor (const model of models) {\n\t\t\tassert.equal(model.api, \"openai-completions\", `Model ${model.id} has wrong api: ${model.api}`);\n\t\t}\n\t});\n\n\tit(\"alibaba-coding-plan models have provider set correctly\", () => {\n\t\tconst models = getModels(\"alibaba-coding-plan\");\n\t\tfor (const model of models) {\n\t\t\tassert.equal(\n\t\t\t\tmodel.provider,\n\t\t\t\t\"alibaba-coding-plan\",\n\t\t\t\t`Model ${model.id} has wrong provider: ${model.provider}`,\n\t\t\t);\n\t\t}\n\t});\n\n\tit(\"getModel retrieves alibaba-coding-plan models by provider+id\", () => {\n\t\t// Use type assertion to test runtime behavior — alibaba-coding-plan may come\n\t\t// from custom models rather than the generated file, so the narrow\n\t\t// GeneratedProvider type doesn't include it until models.custom.ts is merged.\n\t\tconst model = getModel(\"alibaba-coding-plan\" as any, \"qwen3.5-plus\" as any);\n\t\tassert.ok(model, \"Expected getModel to return a model for alibaba-coding-plan/qwen3.5-plus\");\n\t\tassert.equal(model.id, \"qwen3.5-plus\");\n\t\tassert.equal(model.provider, \"alibaba-coding-plan\");\n\t});\n});\n\ndescribe(\"model registry — custom zai provider (GLM-5.1)\", () => {\n\tit(\"zai provider includes glm-5.1 from custom models\", () => {\n\t\tconst models = getModels(\"zai\" as any);\n\t\tconst ids = models.map((m) => m.id);\n\t\tassert.ok(ids.includes(\"glm-5.1\"), `Expected \"glm-5.1\" in zai models, got: ${ids.join(\", \")}`);\n\t});\n\n\tit(\"glm-5.1 has correct provider and base URL\", () => {\n\t\tconst model = getModel(\"zai\" as any, \"glm-5.1\" as any);\n\t\tassert.ok(model, \"Expected getModel to return a model for zai/glm-5.1\");\n\t\tassert.equal(model.id, \"glm-5.1\");\n\t\tassert.equal(model.provider, \"zai\");\n\t\tassert.equal(model.baseUrl, \"https://api.z.ai/api/coding/paas/v4\");\n\t\tassert.equal(model.api, \"openai-completions\");\n\t});\n\n\tit(\"glm-5.1 has reasoning enabled and correct context window\", () => {\n\t\tconst model = getModel(\"zai\" as any, \"glm-5.1\" as any);\n\t\tassert.ok(model);\n\t\tassert.equal(model.reasoning, true);\n\t\tassert.equal(model.contextWindow, 204800);\n\t\tassert.equal(model.maxTokens, 131072);\n\t});\n\n\tit(\"custom glm-5.1 does not overwrite generated zai models\", () => {\n\t\tconst models = getModels(\"zai\" as any);\n\t\tconst ids = models.map((m) => m.id);\n\t\t// Generated models must still exist alongside custom glm-5.1\n\t\tassert.ok(ids.includes(\"glm-5\"), \"Generated glm-5 should still exist\");\n\t\tassert.ok(ids.includes(\"glm-5-turbo\"), \"Generated glm-5-turbo should still exist\");\n\t});\n});\n\n// ═══════════════════════════════════════════════════════════════════════════\n// New provider: alibaba-dashscope (feat: #3891)\n//\n// Regular DashScope API for users without the Coding Plan.\n// Separate from alibaba-coding-plan — different endpoint, auth, and pricing.\n// ═══════════════════════════════════════════════════════════════════════════\n\ndescribe(\"model registry — alibaba-dashscope provider\", () => {\n\tit(\"alibaba-dashscope is a registered provider\", () => {\n\t\tconst providers = getProviders();\n\t\tassert.ok(\n\t\t\tproviders.includes(\"alibaba-dashscope\"),\n\t\t\t`Expected \"alibaba-dashscope\" in providers, got: ${providers.join(\", \")}`,\n\t\t);\n\t});\n\n\tit(\"alibaba-dashscope has all expected models\", () => {\n\t\tconst models = getModels(\"alibaba-dashscope\");\n\t\tconst ids = models.map((m) => m.id).sort();\n\t\tconst expected = [\n\t\t\t\"qwen3-coder-plus\",\n\t\t\t\"qwen3-max\",\n\t\t\t\"qwen3.5-flash\",\n\t\t\t\"qwen3.5-plus\",\n\t\t\t\"qwen3.6-plus\",\n\t\t];\n\t\tassert.deepEqual(ids, expected);\n\t});\n\n\tit(\"alibaba-dashscope models use the international DashScope base URL\", () => {\n\t\tconst models = getModels(\"alibaba-dashscope\");\n\t\tfor (const model of models) {\n\t\t\tassert.equal(\n\t\t\t\tmodel.baseUrl,\n\t\t\t\t\"https://dashscope-intl.aliyuncs.com/compatible-mode/v1\",\n\t\t\t\t`Model ${model.id} has wrong baseUrl: ${model.baseUrl}`,\n\t\t\t);\n\t\t}\n\t});\n\n\tit(\"alibaba-dashscope models use openai-completions API\", () => {\n\t\tconst models = getModels(\"alibaba-dashscope\");\n\t\tfor (const model of models) {\n\t\t\tassert.equal(model.api, \"openai-completions\", `Model ${model.id} has wrong api: ${model.api}`);\n\t\t}\n\t});\n\n\tit(\"alibaba-dashscope models have provider set correctly\", () => {\n\t\tconst models = getModels(\"alibaba-dashscope\");\n\t\tfor (const model of models) {\n\t\t\tassert.equal(\n\t\t\t\tmodel.provider,\n\t\t\t\t\"alibaba-dashscope\",\n\t\t\t\t`Model ${model.id} has wrong provider: ${model.provider}`,\n\t\t\t);\n\t\t}\n\t});\n\n\tit(\"alibaba-dashscope models all have 1M context window\", () => {\n\t\tconst models = getModels(\"alibaba-dashscope\");\n\t\tfor (const model of models) {\n\t\t\tassert.equal(model.contextWindow, 1_000_000, `Model ${model.id} has wrong contextWindow: ${model.contextWindow}`);\n\t\t}\n\t});\n\n\tit(\"alibaba-dashscope models have positive paid costs (not free-tier)\", () => {\n\t\tconst models = getModels(\"alibaba-dashscope\");\n\t\tfor (const model of models) {\n\t\t\tassert.ok(model.cost.input > 0, `${model.id}: input cost should be > 0 (paid tier)`);\n\t\t\tassert.ok(model.cost.output > 0, `${model.id}: output cost should be > 0 (paid tier)`);\n\t\t}\n\t});\n\n\tit(\"qwen3-max is a reasoning model with correct pricing\", () => {\n\t\tconst model = getModel(\"alibaba-dashscope\" as any, \"qwen3-max\" as any);\n\t\tassert.ok(model, \"Expected getModel to return qwen3-max for alibaba-dashscope\");\n\t\tassert.equal(model.reasoning, true);\n\t\tassert.equal(model.cost.input, 1.2);\n\t\tassert.equal(model.cost.output, 6);\n\t\tassert.equal(model.maxTokens, 32768);\n\t});\n\n\tit(\"qwen3.5-plus is a reasoning model with correct pricing\", () => {\n\t\tconst model = getModel(\"alibaba-dashscope\" as any, \"qwen3.5-plus\" as any);\n\t\tassert.ok(model, \"Expected getModel to return qwen3.5-plus for alibaba-dashscope\");\n\t\tassert.equal(model.reasoning, true);\n\t\tassert.equal(model.cost.input, 0.4);\n\t\tassert.equal(model.cost.output, 1.2);\n\t\tassert.equal(model.maxTokens, 65536);\n\t});\n\n\tit(\"qwen3.5-flash is not a reasoning model\", () => {\n\t\tconst model = getModel(\"alibaba-dashscope\" as any, \"qwen3.5-flash\" as any);\n\t\tassert.ok(model, \"Expected getModel to return qwen3.5-flash for alibaba-dashscope\");\n\t\tassert.equal(model.reasoning, false);\n\t\tassert.equal(model.cost.input, 0.1);\n\t\tassert.equal(model.cost.output, 0.4);\n\t});\n\n\tit(\"qwen3-coder-plus is not a reasoning model\", () => {\n\t\tconst model = getModel(\"alibaba-dashscope\" as any, \"qwen3-coder-plus\" as any);\n\t\tassert.ok(model, \"Expected getModel to return qwen3-coder-plus for alibaba-dashscope\");\n\t\tassert.equal(model.reasoning, false);\n\t\tassert.equal(model.cost.input, 1.0);\n\t\tassert.equal(model.cost.output, 5.0);\n\t});\n\n\tit(\"qwen3.6-plus is a reasoning model\", () => {\n\t\tconst model = getModel(\"alibaba-dashscope\" as any, \"qwen3.6-plus\" as any);\n\t\tassert.ok(model, \"Expected getModel to return qwen3.6-plus for alibaba-dashscope\");\n\t\tassert.equal(model.reasoning, true);\n\t\tassert.equal(model.cost.input, 0.5);\n\t\tassert.equal(model.cost.output, 3.0);\n\t});\n\n\tit(\"alibaba-dashscope is independent of alibaba-coding-plan (different endpoint)\", () => {\n\t\tconst dashscope = getModels(\"alibaba-dashscope\");\n\t\tconst codingPlan = getModels(\"alibaba-coding-plan\");\n\t\tfor (const m of dashscope) {\n\t\t\tassert.notEqual(\n\t\t\t\tm.baseUrl,\n\t\t\t\t\"https://coding-intl.dashscope.aliyuncs.com/v1\",\n\t\t\t\t`${m.id} must not use the Coding Plan endpoint`,\n\t\t\t);\n\t\t}\n\t\t// Both providers must coexist — coding-plan must not have been overwritten\n\t\tassert.ok(codingPlan.length > 0, \"alibaba-coding-plan must still have models\");\n\t});\n\n\tit(\"getModel returns undefined for unknown model in alibaba-dashscope (failure path)\", () => {\n\t\tconst model = getModel(\"alibaba-dashscope\" as any, \"does-not-exist\" as any);\n\t\tassert.equal(model, undefined);\n\t});\n});\n\ndescribe(\"model registry — custom models do not collide with generated models\", () => {\n\tit(\"generated providers still exist alongside custom providers\", () => {\n\t\tconst providers = getProviders();\n\t\t// Spot-check a few generated providers\n\t\tassert.ok(providers.includes(\"openai\"), \"openai should be in providers\");\n\t\tassert.ok(providers.includes(\"anthropic\"), \"anthropic should be in providers\");\n\t});\n});\n\n// ═══════════════════════════════════════════════════════════════════════════\n// Capability patches (regression: #2546)\n//\n// CAPABILITY_PATCHES must apply capabilities to models in the static\n// registry AND to models constructed outside of it (custom, extension,\n// discovered). supportsXhigh() reads model.capabilities — not model IDs.\n// ═══════════════════════════════════════════════════════════════════════════\n\n/** Helper: build a minimal synthetic model for testing */\nfunction syntheticModel(overrides: Partial<Model<Api>>): Model<Api> {\n\treturn {\n\t\tid: \"test-model\",\n\t\tname: \"Test Model\",\n\t\tapi: \"openai-completions\" as Api,\n\t\tprovider: \"test-provider\",\n\t\tbaseUrl: \"https://example.com\",\n\t\treasoning: false,\n\t\tinput: [\"text\"],\n\t\tcost: { input: 0, output: 0, cacheRead: 0, cacheWrite: 0 },\n\t\tcontextWindow: 128000,\n\t\tmaxTokens: 16384,\n\t\t...overrides,\n\t} as Model<Api>;\n}\n\ndescribe(\"supportsXhigh — registry models\", () => {\n\tit(\"returns true for GPT-5.4 from the registry\", () => {\n\t\tconst model = getModel(\"openai\", \"gpt-5.4\" as any);\n\t\tif (!model) return; // skip if model not in generated catalog\n\t\tassert.equal(supportsXhigh(model), true);\n\t});\n\n\tit(\"returns false for a non-reasoning model\", () => {\n\t\tconst models = getModels(\"openai\");\n\t\tconst nonXhigh = models.find((m) => !m.id.includes(\"gpt-5.\"));\n\t\tif (!nonXhigh) return;\n\t\tassert.equal(supportsXhigh(nonXhigh), false);\n\t});\n});\n\ndescribe(\"supportsXhigh — synthetic models (regression: custom/extension models)\", () => {\n\tit(\"returns false for a model without capabilities\", () => {\n\t\tconst model = syntheticModel({ id: \"my-custom-model\" });\n\t\tassert.equal(supportsXhigh(model), false);\n\t});\n\n\tit(\"returns true when capabilities.supportsXhigh is explicitly set\", () => {\n\t\tconst model = syntheticModel({\n\t\t\tid: \"my-custom-model\",\n\t\t\tcapabilities: { supportsXhigh: true },\n\t\t});\n\t\tassert.equal(supportsXhigh(model), true);\n\t});\n});\n\ndescribe(\"applyCapabilityPatches\", () => {\n\tit(\"patches a GPT-5.4 model that has no capabilities\", () => {\n\t\tconst model = syntheticModel({ id: \"gpt-5.4-custom\" });\n\t\tassert.equal(model.capabilities, undefined);\n\n\t\tconst [patched] = applyCapabilityPatches([model]);\n\t\tassert.equal(patched.capabilities?.supportsXhigh, true);\n\t\tassert.equal(patched.capabilities?.supportsServiceTier, true);\n\t});\n\n\tit(\"patches a GPT-5.2 model\", () => {\n\t\tconst model = syntheticModel({ id: \"gpt-5.2\" });\n\t\tconst [patched] = applyCapabilityPatches([model]);\n\t\tassert.equal(patched.capabilities?.supportsXhigh, true);\n\t});\n\n\tit(\"patches an Anthropic Opus 4.6 model\", () => {\n\t\tconst model = syntheticModel({\n\t\t\tid: \"claude-opus-4-6-20260301\",\n\t\t\tapi: \"anthropic-messages\" as Api,\n\t\t});\n\t\tconst [patched] = applyCapabilityPatches([model]);\n\t\tassert.equal(patched.capabilities?.supportsXhigh, true);\n\t\t// Opus should not get supportsServiceTier\n\t\tassert.equal(patched.capabilities?.supportsServiceTier, undefined);\n\t});\n\n\tit(\"preserves explicit capabilities over patches\", () => {\n\t\tconst model = syntheticModel({\n\t\t\tid: \"gpt-5.4-custom\",\n\t\t\tcapabilities: { supportsXhigh: false, charsPerToken: 3 },\n\t\t});\n\t\tconst [patched] = applyCapabilityPatches([model]);\n\t\t// Explicit supportsXhigh: false wins over patch's true\n\t\tassert.equal(patched.capabilities?.supportsXhigh, false);\n\t\t// Patch fills in supportsServiceTier since it wasn't explicitly set\n\t\tassert.equal(patched.capabilities?.supportsServiceTier, true);\n\t\t// Explicit charsPerToken is preserved\n\t\tassert.equal(patched.capabilities?.charsPerToken, 3);\n\t});\n\n\tit(\"does not modify models that match no patches\", () => {\n\t\tconst model = syntheticModel({ id: \"gemini-2.5-pro\" });\n\t\tconst [patched] = applyCapabilityPatches([model]);\n\t\tassert.equal(patched.capabilities, undefined);\n\t\t// Should return the same reference when unpatched\n\t\tassert.equal(patched, model);\n\t});\n\n\tit(\"is idempotent — re-applying patches produces the same result\", () => {\n\t\tconst model = syntheticModel({ id: \"gpt-5.3\" });\n\t\tconst first = applyCapabilityPatches([model]);\n\t\tconst second = applyCapabilityPatches(first);\n\t\tassert.deepEqual(first[0].capabilities, second[0].capabilities);\n\t});\n});\n"]}
|
|
1
|
+
{"version":3,"file":"models.test.js","sourceRoot":"","sources":["../src/models.test.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,QAAQ,EAAE,EAAE,EAAE,MAAM,WAAW,CAAC;AACzC,OAAO,MAAM,MAAM,oBAAoB,CAAC;AACxC,OAAO,EAAE,YAAY,EAAE,SAAS,EAAE,QAAQ,EAAE,aAAa,EAAE,sBAAsB,EAAE,MAAM,aAAa,CAAC;AAGvG,8EAA8E;AAC9E,mDAAmD;AACnD,EAAE;AACF,0EAA0E;AAC1E,mEAAmE;AACnE,8CAA8C;AAC9C,8EAA8E;AAE9E,QAAQ,CAAC,mCAAmC,EAAE,GAAG,EAAE;IAClD,EAAE,CAAC,8CAA8C,EAAE,GAAG,EAAE;QACvD,MAAM,SAAS,GAAG,YAAY,EAAE,CAAC;QACjC,MAAM,CAAC,EAAE,CACR,SAAS,CAAC,QAAQ,CAAC,qBAAqB,CAAC,EACzC,qDAAqD,SAAS,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE,CAC3E,CAAC;IACH,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,6CAA6C,EAAE,GAAG,EAAE;QACtD,MAAM,MAAM,GAAG,SAAS,CAAC,qBAAqB,CAAC,CAAC;QAChD,MAAM,GAAG,GAAG,MAAM,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,IAAI,EAAE,CAAC;QAC3C,MAAM,QAAQ,GAAG;YAChB,cAAc;YACd,SAAS;YACT,OAAO;YACP,WAAW;YACX,kBAAkB;YAClB,kBAAkB;YAClB,sBAAsB;YACtB,cAAc;SACd,CAAC;QACF,MAAM,CAAC,SAAS,CAAC,GAAG,EAAE,QAAQ,CAAC,CAAC;IACjC,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,qDAAqD,EAAE,GAAG,EAAE;QAC9D,MAAM,MAAM,GAAG,SAAS,CAAC,qBAAqB,CAAC,CAAC;QAChD,KAAK,MAAM,KAAK,IAAI,MAAM,EAAE,CAAC;YAC5B,MAAM,CAAC,KAAK,CACX,KAAK,CAAC,OAAO,EACb,+CAA+C,EAC/C,SAAS,KAAK,CAAC,EAAE,uBAAuB,KAAK,CAAC,OAAO,EAAE,CACvD,CAAC;QACH,CAAC;IACF,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,uDAAuD,EAAE,GAAG,EAAE;QAChE,MAAM,MAAM,GAAG,SAAS,CAAC,qBAAqB,CAAC,CAAC;QAChD,KAAK,MAAM,KAAK,IAAI,MAAM,EAAE,CAAC;YAC5B,MAAM,CAAC,KAAK,CAAC,KAAK,CAAC,GAAG,EAAE,oBAAoB,EAAE,SAAS,KAAK,CAAC,EAAE,mBAAmB,KAAK,CAAC,GAAG,EAAE,CAAC,CAAC;QAChG,CAAC;IACF,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,wDAAwD,EAAE,GAAG,EAAE;QACjE,MAAM,MAAM,GAAG,SAAS,CAAC,qBAAqB,CAAC,CAAC;QAChD,KAAK,MAAM,KAAK,IAAI,MAAM,EAAE,CAAC;YAC5B,MAAM,CAAC,KAAK,CACX,KAAK,CAAC,QAAQ,EACd,qBAAqB,EACrB,SAAS,KAAK,CAAC,EAAE,wBAAwB,KAAK,CAAC,QAAQ,EAAE,CACzD,CAAC;QACH,CAAC;IACF,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,8DAA8D,EAAE,GAAG,EAAE;QACvE,6EAA6E;QAC7E,mEAAmE;QACnE,8EAA8E;QAC9E,MAAM,KAAK,GAAG,QAAQ,CAAC,qBAA4B,EAAE,cAAqB,CAAC,CAAC;QAC5E,MAAM,CAAC,EAAE,CAAC,KAAK,EAAE,0EAA0E,CAAC,CAAC;QAC7F,MAAM,CAAC,KAAK,CAAC,KAAK,CAAC,EAAE,EAAE,cAAc,CAAC,CAAC;QACvC,MAAM,CAAC,KAAK,CAAC,KAAK,CAAC,QAAQ,EAAE,qBAAqB,CAAC,CAAC;IACrD,CAAC,CAAC,CAAC;AACJ,CAAC,CAAC,CAAC;AAEH,QAAQ,CAAC,gDAAgD,EAAE,GAAG,EAAE;IAC/D,EAAE,CAAC,kDAAkD,EAAE,GAAG,EAAE;QAC3D,MAAM,MAAM,GAAG,SAAS,CAAC,KAAY,CAAC,CAAC;QACvC,MAAM,GAAG,GAAG,MAAM,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC;QACpC,MAAM,CAAC,EAAE,CAAC,GAAG,CAAC,QAAQ,CAAC,SAAS,CAAC,EAAE,0CAA0C,GAAG,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC;IAChG,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,2CAA2C,EAAE,GAAG,EAAE;QACpD,MAAM,KAAK,GAAG,QAAQ,CAAC,KAAY,EAAE,SAAgB,CAAC,CAAC;QACvD,MAAM,CAAC,EAAE,CAAC,KAAK,EAAE,qDAAqD,CAAC,CAAC;QACxE,MAAM,CAAC,KAAK,CAAC,KAAK,CAAC,EAAE,EAAE,SAAS,CAAC,CAAC;QAClC,MAAM,CAAC,KAAK,CAAC,KAAK,CAAC,QAAQ,EAAE,KAAK,CAAC,CAAC;QACpC,MAAM,CAAC,KAAK,CAAC,KAAK,CAAC,OAAO,EAAE,qCAAqC,CAAC,CAAC;QACnE,MAAM,CAAC,KAAK,CAAC,KAAK,CAAC,GAAG,EAAE,oBAAoB,CAAC,CAAC;IAC/C,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,qEAAqE,EAAE,GAAG,EAAE;QAC9E,MAAM,KAAK,GAAG,QAAQ,CAAC,KAAY,EAAE,SAAgB,CAAC,CAAC;QACvD,MAAM,CAAC,EAAE,CAAC,KAAK,CAAC,CAAC;QACjB,MAAM,CAAC,KAAK,CAAC,KAAK,CAAC,SAAS,EAAE,IAAI,CAAC,CAAC;QACpC,+EAA+E;QAC/E,MAAM,CAAC,KAAK,CAAC,KAAK,CAAC,aAAa,EAAE,MAAM,CAAC,CAAC;QAC1C,MAAM,CAAC,KAAK,CAAC,KAAK,CAAC,SAAS,EAAE,MAAM,CAAC,CAAC;IACvC,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,wDAAwD,EAAE,GAAG,EAAE;QACjE,MAAM,MAAM,GAAG,SAAS,CAAC,KAAY,CAAC,CAAC;QACvC,MAAM,GAAG,GAAG,MAAM,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC;QACpC,6DAA6D;QAC7D,MAAM,CAAC,EAAE,CAAC,GAAG,CAAC,QAAQ,CAAC,OAAO,CAAC,EAAE,oCAAoC,CAAC,CAAC;QACvE,MAAM,CAAC,EAAE,CAAC,GAAG,CAAC,QAAQ,CAAC,aAAa,CAAC,EAAE,0CAA0C,CAAC,CAAC;IACpF,CAAC,CAAC,CAAC;AACJ,CAAC,CAAC,CAAC;AAEH,8EAA8E;AAC9E,gDAAgD;AAChD,EAAE;AACF,2DAA2D;AAC3D,6EAA6E;AAC7E,8EAA8E;AAE9E,QAAQ,CAAC,6CAA6C,EAAE,GAAG,EAAE;IAC5D,EAAE,CAAC,4CAA4C,EAAE,GAAG,EAAE;QACrD,MAAM,SAAS,GAAG,YAAY,EAAE,CAAC;QACjC,MAAM,CAAC,EAAE,CACR,SAAS,CAAC,QAAQ,CAAC,mBAAmB,CAAC,EACvC,mDAAmD,SAAS,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE,CACzE,CAAC;IACH,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,2CAA2C,EAAE,GAAG,EAAE;QACpD,MAAM,MAAM,GAAG,SAAS,CAAC,mBAAmB,CAAC,CAAC;QAC9C,MAAM,GAAG,GAAG,MAAM,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,IAAI,EAAE,CAAC;QAC3C,MAAM,QAAQ,GAAG;YAChB,kBAAkB;YAClB,WAAW;YACX,eAAe;YACf,cAAc;YACd,cAAc;SACd,CAAC;QACF,MAAM,CAAC,SAAS,CAAC,GAAG,EAAE,QAAQ,CAAC,CAAC;IACjC,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,mEAAmE,EAAE,GAAG,EAAE;QAC5E,MAAM,MAAM,GAAG,SAAS,CAAC,mBAAmB,CAAC,CAAC;QAC9C,KAAK,MAAM,KAAK,IAAI,MAAM,EAAE,CAAC;YAC5B,MAAM,CAAC,KAAK,CACX,KAAK,CAAC,OAAO,EACb,wDAAwD,EACxD,SAAS,KAAK,CAAC,EAAE,uBAAuB,KAAK,CAAC,OAAO,EAAE,CACvD,CAAC;QACH,CAAC;IACF,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,qDAAqD,EAAE,GAAG,EAAE;QAC9D,MAAM,MAAM,GAAG,SAAS,CAAC,mBAAmB,CAAC,CAAC;QAC9C,KAAK,MAAM,KAAK,IAAI,MAAM,EAAE,CAAC;YAC5B,MAAM,CAAC,KAAK,CAAC,KAAK,CAAC,GAAG,EAAE,oBAAoB,EAAE,SAAS,KAAK,CAAC,EAAE,mBAAmB,KAAK,CAAC,GAAG,EAAE,CAAC,CAAC;QAChG,CAAC;IACF,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,sDAAsD,EAAE,GAAG,EAAE;QAC/D,MAAM,MAAM,GAAG,SAAS,CAAC,mBAAmB,CAAC,CAAC;QAC9C,KAAK,MAAM,KAAK,IAAI,MAAM,EAAE,CAAC;YAC5B,MAAM,CAAC,KAAK,CACX,KAAK,CAAC,QAAQ,EACd,mBAAmB,EACnB,SAAS,KAAK,CAAC,EAAE,wBAAwB,KAAK,CAAC,QAAQ,EAAE,CACzD,CAAC;QACH,CAAC;IACF,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,qDAAqD,EAAE,GAAG,EAAE;QAC9D,MAAM,MAAM,GAAG,SAAS,CAAC,mBAAmB,CAAC,CAAC;QAC9C,KAAK,MAAM,KAAK,IAAI,MAAM,EAAE,CAAC;YAC5B,MAAM,CAAC,KAAK,CAAC,KAAK,CAAC,aAAa,EAAE,SAAS,EAAE,SAAS,KAAK,CAAC,EAAE,6BAA6B,KAAK,CAAC,aAAa,EAAE,CAAC,CAAC;QACnH,CAAC;IACF,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,mEAAmE,EAAE,GAAG,EAAE;QAC5E,MAAM,MAAM,GAAG,SAAS,CAAC,mBAAmB,CAAC,CAAC;QAC9C,KAAK,MAAM,KAAK,IAAI,MAAM,EAAE,CAAC;YAC5B,MAAM,CAAC,EAAE,CAAC,KAAK,CAAC,IAAI,CAAC,KAAK,GAAG,CAAC,EAAE,GAAG,KAAK,CAAC,EAAE,wCAAwC,CAAC,CAAC;YACrF,MAAM,CAAC,EAAE,CAAC,KAAK,CAAC,IAAI,CAAC,MAAM,GAAG,CAAC,EAAE,GAAG,KAAK,CAAC,EAAE,yCAAyC,CAAC,CAAC;QACxF,CAAC;IACF,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,qDAAqD,EAAE,GAAG,EAAE;QAC9D,MAAM,KAAK,GAAG,QAAQ,CAAC,mBAA0B,EAAE,WAAkB,CAAC,CAAC;QACvE,MAAM,CAAC,EAAE,CAAC,KAAK,EAAE,6DAA6D,CAAC,CAAC;QAChF,MAAM,CAAC,KAAK,CAAC,KAAK,CAAC,SAAS,EAAE,IAAI,CAAC,CAAC;QACpC,MAAM,CAAC,KAAK,CAAC,KAAK,CAAC,IAAI,CAAC,KAAK,EAAE,GAAG,CAAC,CAAC;QACpC,MAAM,CAAC,KAAK,CAAC,KAAK,CAAC,IAAI,CAAC,MAAM,EAAE,CAAC,CAAC,CAAC;QACnC,MAAM,CAAC,KAAK,CAAC,KAAK,CAAC,SAAS,EAAE,KAAK,CAAC,CAAC;IACtC,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,wDAAwD,EAAE,GAAG,EAAE;QACjE,MAAM,KAAK,GAAG,QAAQ,CAAC,mBAA0B,EAAE,cAAqB,CAAC,CAAC;QAC1E,MAAM,CAAC,EAAE,CAAC,KAAK,EAAE,gEAAgE,CAAC,CAAC;QACnF,MAAM,CAAC,KAAK,CAAC,KAAK,CAAC,SAAS,EAAE,IAAI,CAAC,CAAC;QACpC,MAAM,CAAC,KAAK,CAAC,KAAK,CAAC,IAAI,CAAC,KAAK,EAAE,GAAG,CAAC,CAAC;QACpC,MAAM,CAAC,KAAK,CAAC,KAAK,CAAC,IAAI,CAAC,MAAM,EAAE,GAAG,CAAC,CAAC;QACrC,MAAM,CAAC,KAAK,CAAC,KAAK,CAAC,SAAS,EAAE,KAAK,CAAC,CAAC;IACtC,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,wCAAwC,EAAE,GAAG,EAAE;QACjD,MAAM,KAAK,GAAG,QAAQ,CAAC,mBAA0B,EAAE,eAAsB,CAAC,CAAC;QAC3E,MAAM,CAAC,EAAE,CAAC,KAAK,EAAE,iEAAiE,CAAC,CAAC;QACpF,MAAM,CAAC,KAAK,CAAC,KAAK,CAAC,SAAS,EAAE,KAAK,CAAC,CAAC;QACrC,MAAM,CAAC,KAAK,CAAC,KAAK,CAAC,IAAI,CAAC,KAAK,EAAE,GAAG,CAAC,CAAC;QACpC,MAAM,CAAC,KAAK,CAAC,KAAK,CAAC,IAAI,CAAC,MAAM,EAAE,GAAG,CAAC,CAAC;IACtC,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,2CAA2C,EAAE,GAAG,EAAE;QACpD,MAAM,KAAK,GAAG,QAAQ,CAAC,mBAA0B,EAAE,kBAAyB,CAAC,CAAC;QAC9E,MAAM,CAAC,EAAE,CAAC,KAAK,EAAE,oEAAoE,CAAC,CAAC;QACvF,MAAM,CAAC,KAAK,CAAC,KAAK,CAAC,SAAS,EAAE,KAAK,CAAC,CAAC;QACrC,MAAM,CAAC,KAAK,CAAC,KAAK,CAAC,IAAI,CAAC,KAAK,EAAE,GAAG,CAAC,CAAC;QACpC,MAAM,CAAC,KAAK,CAAC,KAAK,CAAC,IAAI,CAAC,MAAM,EAAE,GAAG,CAAC,CAAC;IACtC,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,mCAAmC,EAAE,GAAG,EAAE;QAC5C,MAAM,KAAK,GAAG,QAAQ,CAAC,mBAA0B,EAAE,cAAqB,CAAC,CAAC;QAC1E,MAAM,CAAC,EAAE,CAAC,KAAK,EAAE,gEAAgE,CAAC,CAAC;QACnF,MAAM,CAAC,KAAK,CAAC,KAAK,CAAC,SAAS,EAAE,IAAI,CAAC,CAAC;QACpC,MAAM,CAAC,KAAK,CAAC,KAAK,CAAC,IAAI,CAAC,KAAK,EAAE,GAAG,CAAC,CAAC;QACpC,MAAM,CAAC,KAAK,CAAC,KAAK,CAAC,IAAI,CAAC,MAAM,EAAE,GAAG,CAAC,CAAC;IACtC,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,8EAA8E,EAAE,GAAG,EAAE;QACvF,MAAM,SAAS,GAAG,SAAS,CAAC,mBAAmB,CAAC,CAAC;QACjD,MAAM,UAAU,GAAG,SAAS,CAAC,qBAAqB,CAAC,CAAC;QACpD,KAAK,MAAM,CAAC,IAAI,SAAS,EAAE,CAAC;YAC3B,MAAM,CAAC,QAAQ,CACd,CAAC,CAAC,OAAO,EACT,+CAA+C,EAC/C,GAAG,CAAC,CAAC,EAAE,wCAAwC,CAC/C,CAAC;QACH,CAAC;QACD,2EAA2E;QAC3E,MAAM,CAAC,EAAE,CAAC,UAAU,CAAC,MAAM,GAAG,CAAC,EAAE,4CAA4C,CAAC,CAAC;IAChF,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,kFAAkF,EAAE,GAAG,EAAE;QAC3F,MAAM,KAAK,GAAG,QAAQ,CAAC,mBAA0B,EAAE,gBAAuB,CAAC,CAAC;QAC5E,MAAM,CAAC,KAAK,CAAC,KAAK,EAAE,SAAS,CAAC,CAAC;IAChC,CAAC,CAAC,CAAC;AACJ,CAAC,CAAC,CAAC;AAEH,QAAQ,CAAC,qEAAqE,EAAE,GAAG,EAAE;IACpF,EAAE,CAAC,4DAA4D,EAAE,GAAG,EAAE;QACrE,MAAM,SAAS,GAAG,YAAY,EAAE,CAAC;QACjC,uCAAuC;QACvC,MAAM,CAAC,EAAE,CAAC,SAAS,CAAC,QAAQ,CAAC,QAAQ,CAAC,EAAE,+BAA+B,CAAC,CAAC;QACzE,MAAM,CAAC,EAAE,CAAC,SAAS,CAAC,QAAQ,CAAC,WAAW,CAAC,EAAE,kCAAkC,CAAC,CAAC;IAChF,CAAC,CAAC,CAAC;AACJ,CAAC,CAAC,CAAC;AAEH,8EAA8E;AAC9E,yCAAyC;AACzC,EAAE;AACF,qEAAqE;AACrE,uEAAuE;AACvE,yEAAyE;AACzE,8EAA8E;AAE9E,0DAA0D;AAC1D,SAAS,cAAc,CAAC,SAA8B;IACrD,OAAO;QACN,EAAE,EAAE,YAAY;QAChB,IAAI,EAAE,YAAY;QAClB,GAAG,EAAE,oBAA2B;QAChC,QAAQ,EAAE,eAAe;QACzB,OAAO,EAAE,qBAAqB;QAC9B,SAAS,EAAE,KAAK;QAChB,KAAK,EAAE,CAAC,MAAM,CAAC;QACf,IAAI,EAAE,EAAE,KAAK,EAAE,CAAC,EAAE,MAAM,EAAE,CAAC,EAAE,SAAS,EAAE,CAAC,EAAE,UAAU,EAAE,CAAC,EAAE;QAC1D,aAAa,EAAE,MAAM;QACrB,SAAS,EAAE,KAAK;QAChB,GAAG,SAAS;KACE,CAAC;AACjB,CAAC;AAED,QAAQ,CAAC,iCAAiC,EAAE,GAAG,EAAE;IAChD,EAAE,CAAC,4CAA4C,EAAE,GAAG,EAAE;QACrD,MAAM,KAAK,GAAG,QAAQ,CAAC,QAAQ,EAAE,SAAgB,CAAC,CAAC;QACnD,IAAI,CAAC,KAAK;YAAE,OAAO,CAAC,yCAAyC;QAC7D,MAAM,CAAC,KAAK,CAAC,aAAa,CAAC,KAAK,CAAC,EAAE,IAAI,CAAC,CAAC;IAC1C,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,yCAAyC,EAAE,GAAG,EAAE;QAClD,MAAM,MAAM,GAAG,SAAS,CAAC,QAAQ,CAAC,CAAC;QACnC,MAAM,QAAQ,GAAG,MAAM,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC,QAAQ,CAAC,QAAQ,CAAC,CAAC,CAAC;QAC9D,IAAI,CAAC,QAAQ;YAAE,OAAO;QACtB,MAAM,CAAC,KAAK,CAAC,aAAa,CAAC,QAAQ,CAAC,EAAE,KAAK,CAAC,CAAC;IAC9C,CAAC,CAAC,CAAC;AACJ,CAAC,CAAC,CAAC;AAEH,QAAQ,CAAC,wEAAwE,EAAE,GAAG,EAAE;IACvF,EAAE,CAAC,gDAAgD,EAAE,GAAG,EAAE;QACzD,MAAM,KAAK,GAAG,cAAc,CAAC,EAAE,EAAE,EAAE,iBAAiB,EAAE,CAAC,CAAC;QACxD,MAAM,CAAC,KAAK,CAAC,aAAa,CAAC,KAAK,CAAC,EAAE,KAAK,CAAC,CAAC;IAC3C,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,gEAAgE,EAAE,GAAG,EAAE;QACzE,MAAM,KAAK,GAAG,cAAc,CAAC;YAC5B,EAAE,EAAE,iBAAiB;YACrB,YAAY,EAAE,EAAE,aAAa,EAAE,IAAI,EAAE;SACrC,CAAC,CAAC;QACH,MAAM,CAAC,KAAK,CAAC,aAAa,CAAC,KAAK,CAAC,EAAE,IAAI,CAAC,CAAC;IAC1C,CAAC,CAAC,CAAC;AACJ,CAAC,CAAC,CAAC;AAEH,QAAQ,CAAC,wBAAwB,EAAE,GAAG,EAAE;IACvC,EAAE,CAAC,kDAAkD,EAAE,GAAG,EAAE;QAC3D,MAAM,KAAK,GAAG,cAAc,CAAC,EAAE,EAAE,EAAE,gBAAgB,EAAE,CAAC,CAAC;QACvD,MAAM,CAAC,KAAK,CAAC,KAAK,CAAC,YAAY,EAAE,SAAS,CAAC,CAAC;QAE5C,MAAM,CAAC,OAAO,CAAC,GAAG,sBAAsB,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC;QAClD,MAAM,CAAC,KAAK,CAAC,OAAO,CAAC,YAAY,EAAE,aAAa,EAAE,IAAI,CAAC,CAAC;QACxD,MAAM,CAAC,KAAK,CAAC,OAAO,CAAC,YAAY,EAAE,mBAAmB,EAAE,IAAI,CAAC,CAAC;IAC/D,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,yBAAyB,EAAE,GAAG,EAAE;QAClC,MAAM,KAAK,GAAG,cAAc,CAAC,EAAE,EAAE,EAAE,SAAS,EAAE,CAAC,CAAC;QAChD,MAAM,CAAC,OAAO,CAAC,GAAG,sBAAsB,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC;QAClD,MAAM,CAAC,KAAK,CAAC,OAAO,CAAC,YAAY,EAAE,aAAa,EAAE,IAAI,CAAC,CAAC;IACzD,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,qCAAqC,EAAE,GAAG,EAAE;QAC9C,MAAM,KAAK,GAAG,cAAc,CAAC;YAC5B,EAAE,EAAE,0BAA0B;YAC9B,GAAG,EAAE,oBAA2B;SAChC,CAAC,CAAC;QACH,MAAM,CAAC,OAAO,CAAC,GAAG,sBAAsB,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC;QAClD,MAAM,CAAC,KAAK,CAAC,OAAO,CAAC,YAAY,EAAE,aAAa,EAAE,IAAI,CAAC,CAAC;QACxD,0CAA0C;QAC1C,MAAM,CAAC,KAAK,CAAC,OAAO,CAAC,YAAY,EAAE,mBAAmB,EAAE,SAAS,CAAC,CAAC;IACpE,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,8CAA8C,EAAE,GAAG,EAAE;QACvD,MAAM,KAAK,GAAG,cAAc,CAAC;YAC5B,EAAE,EAAE,gBAAgB;YACpB,YAAY,EAAE,EAAE,aAAa,EAAE,KAAK,EAAE,aAAa,EAAE,CAAC,EAAE;SACxD,CAAC,CAAC;QACH,MAAM,CAAC,OAAO,CAAC,GAAG,sBAAsB,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC;QAClD,uDAAuD;QACvD,MAAM,CAAC,KAAK,CAAC,OAAO,CAAC,YAAY,EAAE,aAAa,EAAE,KAAK,CAAC,CAAC;QACzD,oEAAoE;QACpE,MAAM,CAAC,KAAK,CAAC,OAAO,CAAC,YAAY,EAAE,mBAAmB,EAAE,IAAI,CAAC,CAAC;QAC9D,sCAAsC;QACtC,MAAM,CAAC,KAAK,CAAC,OAAO,CAAC,YAAY,EAAE,aAAa,EAAE,CAAC,CAAC,CAAC;IACtD,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,8CAA8C,EAAE,GAAG,EAAE;QACvD,MAAM,KAAK,GAAG,cAAc,CAAC,EAAE,EAAE,EAAE,gBAAgB,EAAE,CAAC,CAAC;QACvD,MAAM,CAAC,OAAO,CAAC,GAAG,sBAAsB,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC;QAClD,MAAM,CAAC,KAAK,CAAC,OAAO,CAAC,YAAY,EAAE,SAAS,CAAC,CAAC;QAC9C,kDAAkD;QAClD,MAAM,CAAC,KAAK,CAAC,OAAO,EAAE,KAAK,CAAC,CAAC;IAC9B,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,8DAA8D,EAAE,GAAG,EAAE;QACvE,MAAM,KAAK,GAAG,cAAc,CAAC,EAAE,EAAE,EAAE,SAAS,EAAE,CAAC,CAAC;QAChD,MAAM,KAAK,GAAG,sBAAsB,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC;QAC9C,MAAM,MAAM,GAAG,sBAAsB,CAAC,KAAK,CAAC,CAAC;QAC7C,MAAM,CAAC,SAAS,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,YAAY,EAAE,MAAM,CAAC,CAAC,CAAC,CAAC,YAAY,CAAC,CAAC;IACjE,CAAC,CAAC,CAAC;AACJ,CAAC,CAAC,CAAC","sourcesContent":["import { describe, it } from \"node:test\";\nimport assert from \"node:assert/strict\";\nimport { getProviders, getModels, getModel, supportsXhigh, applyCapabilityPatches } from \"./models.js\";\nimport type { Api, Model } from \"./types.js\";\n\n// ═══════════════════════════════════════════════════════════════════════════\n// Custom provider preservation (regression: #2339)\n//\n// Custom providers (like alibaba-coding-plan) are manually maintained and\n// NOT sourced from models.dev. They must survive generated catalog\n// regeneration by living in models/custom.ts.\n// ═══════════════════════════════════════════════════════════════════════════\n\ndescribe(\"model registry — custom providers\", () => {\n\tit(\"alibaba-coding-plan is a registered provider\", () => {\n\t\tconst providers = getProviders();\n\t\tassert.ok(\n\t\t\tproviders.includes(\"alibaba-coding-plan\"),\n\t\t\t`Expected \"alibaba-coding-plan\" in providers, got: ${providers.join(\", \")}`,\n\t\t);\n\t});\n\n\tit(\"alibaba-coding-plan has all expected models\", () => {\n\t\tconst models = getModels(\"alibaba-coding-plan\");\n\t\tconst ids = models.map((m) => m.id).sort();\n\t\tconst expected = [\n\t\t\t\"MiniMax-M2.5\",\n\t\t\t\"glm-4.7\",\n\t\t\t\"glm-5\",\n\t\t\t\"kimi-k2.5\",\n\t\t\t\"qwen3-coder-next\",\n\t\t\t\"qwen3-coder-plus\",\n\t\t\t\"qwen3-max-2026-01-23\",\n\t\t\t\"qwen3.5-plus\",\n\t\t];\n\t\tassert.deepEqual(ids, expected);\n\t});\n\n\tit(\"alibaba-coding-plan models use the correct base URL\", () => {\n\t\tconst models = getModels(\"alibaba-coding-plan\");\n\t\tfor (const model of models) {\n\t\t\tassert.equal(\n\t\t\t\tmodel.baseUrl,\n\t\t\t\t\"https://coding-intl.dashscope.aliyuncs.com/v1\",\n\t\t\t\t`Model ${model.id} has wrong baseUrl: ${model.baseUrl}`,\n\t\t\t);\n\t\t}\n\t});\n\n\tit(\"alibaba-coding-plan models use openai-completions API\", () => {\n\t\tconst models = getModels(\"alibaba-coding-plan\");\n\t\tfor (const model of models) {\n\t\t\tassert.equal(model.api, \"openai-completions\", `Model ${model.id} has wrong api: ${model.api}`);\n\t\t}\n\t});\n\n\tit(\"alibaba-coding-plan models have provider set correctly\", () => {\n\t\tconst models = getModels(\"alibaba-coding-plan\");\n\t\tfor (const model of models) {\n\t\t\tassert.equal(\n\t\t\t\tmodel.provider,\n\t\t\t\t\"alibaba-coding-plan\",\n\t\t\t\t`Model ${model.id} has wrong provider: ${model.provider}`,\n\t\t\t);\n\t\t}\n\t});\n\n\tit(\"getModel retrieves alibaba-coding-plan models by provider+id\", () => {\n\t\t// Use type assertion to test runtime behavior — alibaba-coding-plan may come\n\t\t// from custom models rather than the generated file, so the narrow\n\t\t// GeneratedProvider type doesn't include it until models/custom.ts is merged.\n\t\tconst model = getModel(\"alibaba-coding-plan\" as any, \"qwen3.5-plus\" as any);\n\t\tassert.ok(model, \"Expected getModel to return a model for alibaba-coding-plan/qwen3.5-plus\");\n\t\tassert.equal(model.id, \"qwen3.5-plus\");\n\t\tassert.equal(model.provider, \"alibaba-coding-plan\");\n\t});\n});\n\ndescribe(\"model registry — custom zai provider (GLM-5.1)\", () => {\n\tit(\"zai provider includes glm-5.1 from custom models\", () => {\n\t\tconst models = getModels(\"zai\" as any);\n\t\tconst ids = models.map((m) => m.id);\n\t\tassert.ok(ids.includes(\"glm-5.1\"), `Expected \"glm-5.1\" in zai models, got: ${ids.join(\", \")}`);\n\t});\n\n\tit(\"glm-5.1 has correct provider and base URL\", () => {\n\t\tconst model = getModel(\"zai\" as any, \"glm-5.1\" as any);\n\t\tassert.ok(model, \"Expected getModel to return a model for zai/glm-5.1\");\n\t\tassert.equal(model.id, \"glm-5.1\");\n\t\tassert.equal(model.provider, \"zai\");\n\t\tassert.equal(model.baseUrl, \"https://api.z.ai/api/coding/paas/v4\");\n\t\tassert.equal(model.api, \"openai-completions\");\n\t});\n\n\tit(\"glm-5.1 has reasoning enabled and uses generated catalog precedence\", () => {\n\t\tconst model = getModel(\"zai\" as any, \"glm-5.1\" as any);\n\t\tassert.ok(model);\n\t\tassert.equal(model.reasoning, true);\n\t\t// Generated catalog entries are loaded first; custom models are additive-only.\n\t\tassert.equal(model.contextWindow, 200000);\n\t\tassert.equal(model.maxTokens, 131072);\n\t});\n\n\tit(\"custom glm-5.1 does not overwrite generated zai models\", () => {\n\t\tconst models = getModels(\"zai\" as any);\n\t\tconst ids = models.map((m) => m.id);\n\t\t// Generated models must still exist alongside custom glm-5.1\n\t\tassert.ok(ids.includes(\"glm-5\"), \"Generated glm-5 should still exist\");\n\t\tassert.ok(ids.includes(\"glm-5-turbo\"), \"Generated glm-5-turbo should still exist\");\n\t});\n});\n\n// ═══════════════════════════════════════════════════════════════════════════\n// New provider: alibaba-dashscope (feat: #3891)\n//\n// Regular DashScope API for users without the Coding Plan.\n// Separate from alibaba-coding-plan — different endpoint, auth, and pricing.\n// ═══════════════════════════════════════════════════════════════════════════\n\ndescribe(\"model registry — alibaba-dashscope provider\", () => {\n\tit(\"alibaba-dashscope is a registered provider\", () => {\n\t\tconst providers = getProviders();\n\t\tassert.ok(\n\t\t\tproviders.includes(\"alibaba-dashscope\"),\n\t\t\t`Expected \"alibaba-dashscope\" in providers, got: ${providers.join(\", \")}`,\n\t\t);\n\t});\n\n\tit(\"alibaba-dashscope has all expected models\", () => {\n\t\tconst models = getModels(\"alibaba-dashscope\");\n\t\tconst ids = models.map((m) => m.id).sort();\n\t\tconst expected = [\n\t\t\t\"qwen3-coder-plus\",\n\t\t\t\"qwen3-max\",\n\t\t\t\"qwen3.5-flash\",\n\t\t\t\"qwen3.5-plus\",\n\t\t\t\"qwen3.6-plus\",\n\t\t];\n\t\tassert.deepEqual(ids, expected);\n\t});\n\n\tit(\"alibaba-dashscope models use the international DashScope base URL\", () => {\n\t\tconst models = getModels(\"alibaba-dashscope\");\n\t\tfor (const model of models) {\n\t\t\tassert.equal(\n\t\t\t\tmodel.baseUrl,\n\t\t\t\t\"https://dashscope-intl.aliyuncs.com/compatible-mode/v1\",\n\t\t\t\t`Model ${model.id} has wrong baseUrl: ${model.baseUrl}`,\n\t\t\t);\n\t\t}\n\t});\n\n\tit(\"alibaba-dashscope models use openai-completions API\", () => {\n\t\tconst models = getModels(\"alibaba-dashscope\");\n\t\tfor (const model of models) {\n\t\t\tassert.equal(model.api, \"openai-completions\", `Model ${model.id} has wrong api: ${model.api}`);\n\t\t}\n\t});\n\n\tit(\"alibaba-dashscope models have provider set correctly\", () => {\n\t\tconst models = getModels(\"alibaba-dashscope\");\n\t\tfor (const model of models) {\n\t\t\tassert.equal(\n\t\t\t\tmodel.provider,\n\t\t\t\t\"alibaba-dashscope\",\n\t\t\t\t`Model ${model.id} has wrong provider: ${model.provider}`,\n\t\t\t);\n\t\t}\n\t});\n\n\tit(\"alibaba-dashscope models all have 1M context window\", () => {\n\t\tconst models = getModels(\"alibaba-dashscope\");\n\t\tfor (const model of models) {\n\t\t\tassert.equal(model.contextWindow, 1_000_000, `Model ${model.id} has wrong contextWindow: ${model.contextWindow}`);\n\t\t}\n\t});\n\n\tit(\"alibaba-dashscope models have positive paid costs (not free-tier)\", () => {\n\t\tconst models = getModels(\"alibaba-dashscope\");\n\t\tfor (const model of models) {\n\t\t\tassert.ok(model.cost.input > 0, `${model.id}: input cost should be > 0 (paid tier)`);\n\t\t\tassert.ok(model.cost.output > 0, `${model.id}: output cost should be > 0 (paid tier)`);\n\t\t}\n\t});\n\n\tit(\"qwen3-max is a reasoning model with correct pricing\", () => {\n\t\tconst model = getModel(\"alibaba-dashscope\" as any, \"qwen3-max\" as any);\n\t\tassert.ok(model, \"Expected getModel to return qwen3-max for alibaba-dashscope\");\n\t\tassert.equal(model.reasoning, true);\n\t\tassert.equal(model.cost.input, 1.2);\n\t\tassert.equal(model.cost.output, 6);\n\t\tassert.equal(model.maxTokens, 32768);\n\t});\n\n\tit(\"qwen3.5-plus is a reasoning model with correct pricing\", () => {\n\t\tconst model = getModel(\"alibaba-dashscope\" as any, \"qwen3.5-plus\" as any);\n\t\tassert.ok(model, \"Expected getModel to return qwen3.5-plus for alibaba-dashscope\");\n\t\tassert.equal(model.reasoning, true);\n\t\tassert.equal(model.cost.input, 0.4);\n\t\tassert.equal(model.cost.output, 1.2);\n\t\tassert.equal(model.maxTokens, 65536);\n\t});\n\n\tit(\"qwen3.5-flash is not a reasoning model\", () => {\n\t\tconst model = getModel(\"alibaba-dashscope\" as any, \"qwen3.5-flash\" as any);\n\t\tassert.ok(model, \"Expected getModel to return qwen3.5-flash for alibaba-dashscope\");\n\t\tassert.equal(model.reasoning, false);\n\t\tassert.equal(model.cost.input, 0.1);\n\t\tassert.equal(model.cost.output, 0.4);\n\t});\n\n\tit(\"qwen3-coder-plus is not a reasoning model\", () => {\n\t\tconst model = getModel(\"alibaba-dashscope\" as any, \"qwen3-coder-plus\" as any);\n\t\tassert.ok(model, \"Expected getModel to return qwen3-coder-plus for alibaba-dashscope\");\n\t\tassert.equal(model.reasoning, false);\n\t\tassert.equal(model.cost.input, 1.0);\n\t\tassert.equal(model.cost.output, 5.0);\n\t});\n\n\tit(\"qwen3.6-plus is a reasoning model\", () => {\n\t\tconst model = getModel(\"alibaba-dashscope\" as any, \"qwen3.6-plus\" as any);\n\t\tassert.ok(model, \"Expected getModel to return qwen3.6-plus for alibaba-dashscope\");\n\t\tassert.equal(model.reasoning, true);\n\t\tassert.equal(model.cost.input, 0.5);\n\t\tassert.equal(model.cost.output, 3.0);\n\t});\n\n\tit(\"alibaba-dashscope is independent of alibaba-coding-plan (different endpoint)\", () => {\n\t\tconst dashscope = getModels(\"alibaba-dashscope\");\n\t\tconst codingPlan = getModels(\"alibaba-coding-plan\");\n\t\tfor (const m of dashscope) {\n\t\t\tassert.notEqual(\n\t\t\t\tm.baseUrl,\n\t\t\t\t\"https://coding-intl.dashscope.aliyuncs.com/v1\",\n\t\t\t\t`${m.id} must not use the Coding Plan endpoint`,\n\t\t\t);\n\t\t}\n\t\t// Both providers must coexist — coding-plan must not have been overwritten\n\t\tassert.ok(codingPlan.length > 0, \"alibaba-coding-plan must still have models\");\n\t});\n\n\tit(\"getModel returns undefined for unknown model in alibaba-dashscope (failure path)\", () => {\n\t\tconst model = getModel(\"alibaba-dashscope\" as any, \"does-not-exist\" as any);\n\t\tassert.equal(model, undefined);\n\t});\n});\n\ndescribe(\"model registry — custom models do not collide with generated models\", () => {\n\tit(\"generated providers still exist alongside custom providers\", () => {\n\t\tconst providers = getProviders();\n\t\t// Spot-check a few generated providers\n\t\tassert.ok(providers.includes(\"openai\"), \"openai should be in providers\");\n\t\tassert.ok(providers.includes(\"anthropic\"), \"anthropic should be in providers\");\n\t});\n});\n\n// ═══════════════════════════════════════════════════════════════════════════\n// Capability patches (regression: #2546)\n//\n// CAPABILITY_PATCHES must apply capabilities to models in the static\n// registry AND to models constructed outside of it (custom, extension,\n// discovered). supportsXhigh() reads model.capabilities — not model IDs.\n// ═══════════════════════════════════════════════════════════════════════════\n\n/** Helper: build a minimal synthetic model for testing */\nfunction syntheticModel(overrides: Partial<Model<Api>>): Model<Api> {\n\treturn {\n\t\tid: \"test-model\",\n\t\tname: \"Test Model\",\n\t\tapi: \"openai-completions\" as Api,\n\t\tprovider: \"test-provider\",\n\t\tbaseUrl: \"https://example.com\",\n\t\treasoning: false,\n\t\tinput: [\"text\"],\n\t\tcost: { input: 0, output: 0, cacheRead: 0, cacheWrite: 0 },\n\t\tcontextWindow: 128000,\n\t\tmaxTokens: 16384,\n\t\t...overrides,\n\t} as Model<Api>;\n}\n\ndescribe(\"supportsXhigh — registry models\", () => {\n\tit(\"returns true for GPT-5.4 from the registry\", () => {\n\t\tconst model = getModel(\"openai\", \"gpt-5.4\" as any);\n\t\tif (!model) return; // skip if model not in generated catalog\n\t\tassert.equal(supportsXhigh(model), true);\n\t});\n\n\tit(\"returns false for a non-reasoning model\", () => {\n\t\tconst models = getModels(\"openai\");\n\t\tconst nonXhigh = models.find((m) => !m.id.includes(\"gpt-5.\"));\n\t\tif (!nonXhigh) return;\n\t\tassert.equal(supportsXhigh(nonXhigh), false);\n\t});\n});\n\ndescribe(\"supportsXhigh — synthetic models (regression: custom/extension models)\", () => {\n\tit(\"returns false for a model without capabilities\", () => {\n\t\tconst model = syntheticModel({ id: \"my-custom-model\" });\n\t\tassert.equal(supportsXhigh(model), false);\n\t});\n\n\tit(\"returns true when capabilities.supportsXhigh is explicitly set\", () => {\n\t\tconst model = syntheticModel({\n\t\t\tid: \"my-custom-model\",\n\t\t\tcapabilities: { supportsXhigh: true },\n\t\t});\n\t\tassert.equal(supportsXhigh(model), true);\n\t});\n});\n\ndescribe(\"applyCapabilityPatches\", () => {\n\tit(\"patches a GPT-5.4 model that has no capabilities\", () => {\n\t\tconst model = syntheticModel({ id: \"gpt-5.4-custom\" });\n\t\tassert.equal(model.capabilities, undefined);\n\n\t\tconst [patched] = applyCapabilityPatches([model]);\n\t\tassert.equal(patched.capabilities?.supportsXhigh, true);\n\t\tassert.equal(patched.capabilities?.supportsServiceTier, true);\n\t});\n\n\tit(\"patches a GPT-5.2 model\", () => {\n\t\tconst model = syntheticModel({ id: \"gpt-5.2\" });\n\t\tconst [patched] = applyCapabilityPatches([model]);\n\t\tassert.equal(patched.capabilities?.supportsXhigh, true);\n\t});\n\n\tit(\"patches an Anthropic Opus 4.6 model\", () => {\n\t\tconst model = syntheticModel({\n\t\t\tid: \"claude-opus-4-6-20260301\",\n\t\t\tapi: \"anthropic-messages\" as Api,\n\t\t});\n\t\tconst [patched] = applyCapabilityPatches([model]);\n\t\tassert.equal(patched.capabilities?.supportsXhigh, true);\n\t\t// Opus should not get supportsServiceTier\n\t\tassert.equal(patched.capabilities?.supportsServiceTier, undefined);\n\t});\n\n\tit(\"preserves explicit capabilities over patches\", () => {\n\t\tconst model = syntheticModel({\n\t\t\tid: \"gpt-5.4-custom\",\n\t\t\tcapabilities: { supportsXhigh: false, charsPerToken: 3 },\n\t\t});\n\t\tconst [patched] = applyCapabilityPatches([model]);\n\t\t// Explicit supportsXhigh: false wins over patch's true\n\t\tassert.equal(patched.capabilities?.supportsXhigh, false);\n\t\t// Patch fills in supportsServiceTier since it wasn't explicitly set\n\t\tassert.equal(patched.capabilities?.supportsServiceTier, true);\n\t\t// Explicit charsPerToken is preserved\n\t\tassert.equal(patched.capabilities?.charsPerToken, 3);\n\t});\n\n\tit(\"does not modify models that match no patches\", () => {\n\t\tconst model = syntheticModel({ id: \"gemini-2.5-pro\" });\n\t\tconst [patched] = applyCapabilityPatches([model]);\n\t\tassert.equal(patched.capabilities, undefined);\n\t\t// Should return the same reference when unpatched\n\t\tassert.equal(patched, model);\n\t});\n\n\tit(\"is idempotent — re-applying patches produces the same result\", () => {\n\t\tconst model = syntheticModel({ id: \"gpt-5.3\" });\n\t\tconst first = applyCapabilityPatches([model]);\n\t\tconst second = applyCapabilityPatches(first);\n\t\tassert.deepEqual(first[0].capabilities, second[0].capabilities);\n\t});\n});\n"]}
|