diff --git a/README.md b/README.md index a9916de..c629167 100644 --- a/README.md +++ b/README.md @@ -26,6 +26,7 @@ PR #1 曾把 reasoning 模型的 `defaultTemperature` / `defaultTopP` 写为 `nu | `provider.schema.json` | `compute/providers/*.json`、`compute/coding-plans/*.json` | `defaultTemperature`/`defaultTopP` 必须是 number,禁止 null/string;`additionalProperties: false` | | `manifest.schema.json` | `manifest.json` | `presetDataVersion` 必须是递增整数 | | `service-map.schema.json` | `compute/service-map.json` | 每条映射须含 `modelName` + `providerId` | +| `smart-model-catalog.schema.json` | `compute/smart-routing/model-catalog.json` | 智能路由三档量级、接入面、exact model 能力和稳定优先级 | | `providers-index.schema.json` | 两个 `_index.json` | `order` 数组无重复 | | `pricing.schema.json` | `compute/pricing.json` | `markupRatio` / `usdToCny` 为正数 | @@ -62,6 +63,17 @@ PR #1 曾把 reasoning 模型的 `defaultTemperature` / `defaultTopP` 写为 `nu 否则老客户端会因未知字段校验失败死锁。 +### 智能路由目录的边界 + +`compute/smart-routing/model-catalog.json` 是路由器直接消费的、按接入面核对过的策略快照: + +- `tier`、`routingPriority`、`eligibleForAgent` 和 `defaultReference` 属于路由策略; +- `capabilities`、上下文和 reasoning 是该 `providerId + model` 接入面的可用能力快照; +- 它不声明 API key、baseUrl、登录状态、用户额度或实时计价;`desirecore-cloud` 的连接与计费状态仍由登录后的 Provider 接口动态下发; +- Codex、Claude 条目必须能在对应 `compute/providers/*.json` 中按 exact model 找到,测试会阻止已下线模型继续参与路由。 + +客户端把本文件作为可热更新主数据源,并保留同 Schema 的内置离线兜底。调整 Provider 或 model-spec 的能力事实时,应同步审阅本目录,避免路由快照漂移。 + --- ## 本地校验 @@ -78,7 +90,7 @@ CI(GitHub Actions)会在每个 PR 自动运行 `validate` 和 `test`,不 ## 数据修改流程 -1. 编辑 `compute/providers/.json`、`compute/coding-plans/.json` 或 `compute/service-map.json` +1. 编辑 `compute/providers/.json`、`compute/coding-plans/.json`、`compute/service-map.json` 或 `compute/smart-routing/model-catalog.json` 2. 编辑 `compute/providers/_index.json` 或 `coding-plans/_index.json`(新增/删除 provider 时) 3. **必须**递增 `manifest.json#presetDataVersion`,并更新 `updatedAt` 4. `npm run validate` 本地确认通过 @@ -95,3 +107,4 @@ CI(GitHub Actions)会在每个 PR 自动运行 `validate` 和 `test`,不 - **构建期同步**:`npm run sync-config-center` 把数据复制到 desirecore 主仓 `lib/agent-service/defaults/` - **运行时同步**:客户端启动后后台 git fetch 本仓库,每 30 分钟检查一次远程更新 - **版本比对**:`presetDataVersion`(递增整数)+ digest(SHA-256)双重校验 +- **智能路由目录**:新客户端按文件 mtime 热加载 `compute/smart-routing/model-catalog.json`;缺失或校验失败时使用随客户端发布的内置 JSON diff --git a/__tests__/validate.test.mjs b/__tests__/validate.test.mjs index a6aec77..cb3f871 100644 --- a/__tests__/validate.test.mjs +++ b/__tests__/validate.test.mjs @@ -85,6 +85,49 @@ describe('真实数据全量校验', () => { assert.equal(result.ok, true, JSON.stringify(result.errors, null, 2)) }) + it('智能路由模型目录应通过 smart-model-catalog schema', () => { + const result = validateFile( + join(ROOT, 'compute', 'smart-routing', 'model-catalog.json'), + validators, + ) + assert.equal(result.ok, true, JSON.stringify(result.errors, null, 2)) + + const catalog = JSON.parse(readFileSync( + join(ROOT, 'compute', 'smart-routing', 'model-catalog.json'), + 'utf8', + )) + assert.deepEqual(catalog.tiers.map((tier) => tier.id), [ + 'flagship', + 'balanced', + 'lightweight', + ]) + assert.deepEqual(catalog.providers.map((provider) => provider.provider), [ + 'openai-codex', + 'anthropic-claude', + 'desirecore-cloud', + ]) + assert.equal( + catalog.providers.flatMap((provider) => provider.models).length, + 37, + ) + + for (const provider of catalog.providers.filter((item) => item.provider !== 'desirecore-cloud')) { + const providerFile = JSON.parse(readFileSync( + join(ROOT, 'compute', 'providers', `${provider.provider}.json`), + 'utf8', + )) + assert.equal(providerFile.id, provider.providerId) + const publishedModels = new Set(providerFile.models.map((model) => model.modelName)) + for (const model of provider.models) { + assert.equal( + publishedModels.has(model.model), + true, + `${provider.providerId}/${model.model} 必须存在于对应接入面 Provider 清单`, + ) + } + } + }) + it('两个 _index.json 应通过 providers-index schema', () => { const r1 = validateFile(join(ROOT, 'compute', 'providers', '_index.json'), validators) const r2 = validateFile(join(ROOT, 'compute', 'coding-plans', '_index.json'), validators) @@ -304,6 +347,28 @@ describe('真实数据全量校验', () => { }) }) +describe('智能路由模型目录 schema 反例', () => { + const validate = compile('smart-model-catalog') + + it('拒绝未声明的策略字段,避免新旧客户端静默分叉', () => { + const data = JSON.parse(readFileSync( + join(ROOT, 'compute', 'smart-routing', 'model-catalog.json'), + 'utf8', + )) + data.providers[0].models[0].unknownRoutingPolicy = true + assert.equal(validate(data), false) + }) + + it('拒绝当前客户端未声明支持的目录版本', () => { + const data = JSON.parse(readFileSync( + join(ROOT, 'compute', 'smart-routing', 'model-catalog.json'), + 'utf8', + )) + data.version = 2 + assert.equal(validate(data), false) + }) +}) + // ==================== Runtime 清单反例 ==================== describe('runtime-recommended schema 反例', () => { diff --git a/compute/smart-routing/model-catalog.json b/compute/smart-routing/model-catalog.json new file mode 100644 index 0000000..c8e230b --- /dev/null +++ b/compute/smart-routing/model-catalog.json @@ -0,0 +1,1099 @@ +{ + "$schema": "https://desirecore.net/schemas/smart-model-catalog.json", + "version": 1, + "updatedAt": "2026-08-09T13:45:49.000Z", + "source": "config-center", + "tiers": [ + { + "id": "flagship", + "label": "旗舰", + "labelEn": "Flagship", + "description": "最高能力,优先用于复杂推理、关键交付和长程智能体任务。", + "defaultReasoning": "high" + }, + { + "id": "balanced", + "label": "均衡", + "labelEn": "Balanced", + "description": "质量、速度与成本平衡,适合大多数日常任务。", + "defaultReasoning": "medium" + }, + { + "id": "lightweight", + "label": "轻量", + "labelEn": "Lightweight", + "description": "优先低延迟与低成本,适合明确、短链路和批量任务。", + "defaultReasoning": "low" + } + ], + "providers": [ + { + "providerId": "provider-openai-codex-plan-001", + "provider": "openai-codex", + "displayName": "ChatGPT 订阅 (Codex)", + "models": [ + { + "model": "gpt-5.6-sol", + "displayName": "GPT-5.6 Sol", + "tier": "flagship", + "routingPriority": 10, + "serviceTypes": [ + "chat" + ], + "capabilities": [ + "chat", + "reasoning", + "code", + "vision", + "long_context", + "tool_use", + "agent" + ], + "contextWindow": 1050000, + "maxOutputTokens": 128000, + "supportedReasoning": [ + "auto", + "off", + "low", + "medium", + "high", + "xhigh", + "max" + ], + "defaultReasoning": "low", + "eligibleForAgent": true, + "defaultReference": false + }, + { + "model": "gpt-5.6-terra", + "displayName": "GPT-5.6 Terra", + "tier": "balanced", + "routingPriority": 10, + "serviceTypes": [ + "chat" + ], + "capabilities": [ + "chat", + "reasoning", + "code", + "vision", + "long_context", + "tool_use", + "agent" + ], + "contextWindow": 1050000, + "maxOutputTokens": 128000, + "supportedReasoning": [ + "auto", + "off", + "low", + "medium", + "high", + "xhigh", + "max" + ], + "defaultReasoning": "medium", + "eligibleForAgent": true, + "defaultReference": false + }, + { + "model": "gpt-5.6-luna", + "displayName": "GPT-5.6 Luna", + "tier": "lightweight", + "routingPriority": 10, + "serviceTypes": [ + "chat" + ], + "capabilities": [ + "chat", + "reasoning", + "code", + "vision", + "long_context", + "tool_use", + "fast" + ], + "contextWindow": 1050000, + "maxOutputTokens": 128000, + "supportedReasoning": [ + "auto", + "off", + "low", + "medium", + "high", + "xhigh", + "max" + ], + "defaultReasoning": "medium", + "eligibleForAgent": true, + "defaultReference": false + }, + { + "model": "gpt-5.5", + "displayName": "GPT-5.5", + "tier": "flagship", + "routingPriority": 60, + "serviceTypes": [ + "chat" + ], + "capabilities": [ + "chat", + "reasoning", + "code", + "vision", + "long_context", + "tool_use", + "agent" + ], + "contextWindow": 1050000, + "maxOutputTokens": 128000, + "supportedReasoning": [ + "auto", + "off", + "low", + "medium", + "high", + "xhigh" + ], + "defaultReasoning": "medium", + "eligibleForAgent": true, + "defaultReference": false + }, + { + "model": "gpt-5.4", + "displayName": "GPT-5.4", + "tier": "balanced", + "routingPriority": 60, + "serviceTypes": [ + "chat" + ], + "capabilities": [ + "chat", + "reasoning", + "code", + "vision", + "long_context", + "tool_use", + "agent" + ], + "contextWindow": 1050000, + "maxOutputTokens": 128000, + "supportedReasoning": [ + "auto", + "off", + "low", + "medium", + "high", + "xhigh" + ], + "defaultReasoning": "medium", + "eligibleForAgent": true, + "defaultReference": false + }, + { + "model": "gpt-5.4-mini", + "displayName": "GPT-5.4 Mini", + "tier": "lightweight", + "routingPriority": 25, + "serviceTypes": [ + "chat" + ], + "capabilities": [ + "chat", + "reasoning", + "code", + "vision", + "long_context", + "tool_use", + "fast" + ], + "contextWindow": 400000, + "maxOutputTokens": 128000, + "supportedReasoning": [ + "auto", + "off", + "low", + "medium", + "high", + "xhigh" + ], + "defaultReasoning": "low", + "eligibleForAgent": true, + "defaultReference": false + }, + { + "model": "gpt-5.3-codex-spark", + "displayName": "GPT-5.3 Codex Spark(Pro 专属)", + "tier": "lightweight", + "routingPriority": 30, + "serviceTypes": [ + "chat" + ], + "capabilities": [ + "chat", + "code", + "tool_use", + "fast" + ], + "contextWindow": 128000, + "maxOutputTokens": null, + "supportedReasoning": [ + "auto" + ], + "defaultReasoning": "auto", + "eligibleForAgent": true, + "defaultReference": false + } + ] + }, + { + "providerId": "provider-anthropic-claude-plan-001", + "provider": "anthropic-claude", + "displayName": "Claude 订阅 (Claude Code)", + "models": [ + { + "model": "claude-fable-5", + "displayName": "Claude Fable 5", + "tier": "flagship", + "routingPriority": 20, + "serviceTypes": [ + "chat" + ], + "capabilities": [ + "chat", + "reasoning", + "code", + "vision", + "tool_use", + "agent", + "long_context" + ], + "contextWindow": 1000000, + "maxOutputTokens": 128000, + "supportedReasoning": [ + "auto", + "low", + "medium", + "high", + "xhigh", + "max" + ], + "defaultReasoning": "xhigh", + "eligibleForAgent": true, + "defaultReference": false + }, + { + "model": "claude-opus-5", + "displayName": "Claude Opus 5", + "tier": "flagship", + "routingPriority": 25, + "serviceTypes": [ + "chat" + ], + "capabilities": [ + "chat", + "reasoning", + "code", + "vision", + "tool_use", + "agent", + "long_context" + ], + "contextWindow": 1000000, + "maxOutputTokens": 128000, + "supportedReasoning": [ + "auto", + "low", + "medium", + "high", + "xhigh", + "max" + ], + "defaultReasoning": "xhigh", + "eligibleForAgent": true, + "defaultReference": false + }, + { + "model": "claude-sonnet-5", + "displayName": "Claude Sonnet 5", + "tier": "balanced", + "routingPriority": 20, + "serviceTypes": [ + "chat" + ], + "capabilities": [ + "chat", + "reasoning", + "code", + "vision", + "tool_use", + "agent", + "long_context" + ], + "contextWindow": 1000000, + "maxOutputTokens": 128000, + "supportedReasoning": [ + "auto", + "low", + "medium", + "high", + "xhigh", + "max" + ], + "defaultReasoning": "xhigh", + "eligibleForAgent": true, + "defaultReference": false + }, + { + "model": "claude-haiku-4-5", + "displayName": "Claude Haiku 4.5", + "tier": "lightweight", + "routingPriority": 20, + "serviceTypes": [ + "chat" + ], + "capabilities": [ + "chat", + "code", + "vision", + "tool_use" + ], + "contextWindow": 200000, + "maxOutputTokens": 64000, + "supportedReasoning": [ + "auto" + ], + "defaultReasoning": "auto", + "eligibleForAgent": true, + "defaultReference": false + } + ] + }, + { + "providerId": "desirecore-cloud", + "provider": "desirecore-cloud", + "displayName": "官方算力", + "models": [ + { + "model": "wan2.7-image-pro", + "displayName": "通义万相 2.7 Pro", + "tier": "flagship", + "routingPriority": 100, + "serviceTypes": [ + "image_gen" + ], + "capabilities": [ + "chat", + "image_generation", + "chinese_optimized", + "high_quality" + ], + "contextWindow": null, + "maxOutputTokens": null, + "supportedReasoning": [ + "auto" + ], + "defaultReasoning": "auto", + "eligibleForAgent": false, + "defaultReference": false + }, + { + "model": "MiniMax-Hailuo-2.3-fast", + "displayName": "海螺视频 2.3 快速版", + "tier": "lightweight", + "routingPriority": 101, + "serviceTypes": [ + "video_gen" + ], + "capabilities": [ + "chat", + "video_generation", + "image_to_video", + "camera_control", + "fast", + "chinese_optimized" + ], + "contextWindow": null, + "maxOutputTokens": null, + "supportedReasoning": [ + "auto" + ], + "defaultReasoning": "auto", + "eligibleForAgent": false, + "defaultReference": false + }, + { + "model": "MiniMax-Hailuo-2.3", + "displayName": "海螺视频 2.3", + "tier": "balanced", + "routingPriority": 102, + "serviceTypes": [ + "video_gen" + ], + "capabilities": [ + "chat", + "video_generation", + "text_to_video", + "image_to_video", + "camera_control", + "chinese_optimized", + "high_quality" + ], + "contextWindow": null, + "maxOutputTokens": null, + "supportedReasoning": [ + "auto" + ], + "defaultReasoning": "auto", + "eligibleForAgent": false, + "defaultReference": false + }, + { + "model": "mimo-v2.5-pro", + "displayName": "MiMo V2.5 Pro", + "tier": "flagship", + "routingPriority": 50, + "serviceTypes": [ + "chat", + "reasoning" + ], + "capabilities": [ + "chat", + "reasoning", + "tool_use", + "code" + ], + "contextWindow": 1000000, + "maxOutputTokens": 131072, + "supportedReasoning": [ + "auto", + "off", + "minimal", + "low", + "medium", + "high", + "xhigh" + ], + "defaultReasoning": "high", + "eligibleForAgent": true, + "defaultReference": false + }, + { + "model": "qwen3.7-plus", + "displayName": "Qwen3.7 Plus", + "tier": "balanced", + "routingPriority": 35, + "serviceTypes": [ + "chat" + ], + "capabilities": [ + "chat", + "reasoning", + "code", + "vision", + "multilingual", + "tool_use", + "long_context" + ], + "contextWindow": 1000000, + "maxOutputTokens": 65536, + "supportedReasoning": [ + "auto", + "off", + "minimal", + "low", + "medium", + "high", + "xhigh" + ], + "defaultReasoning": "medium", + "eligibleForAgent": true, + "defaultReference": false + }, + { + "model": "mimo-v2.5", + "displayName": "MiMo V2.5", + "tier": "lightweight", + "routingPriority": 40, + "serviceTypes": [ + "chat", + "vision" + ], + "capabilities": [ + "chat", + "reasoning", + "vision", + "tool_use", + "code" + ], + "contextWindow": 1000000, + "maxOutputTokens": 131072, + "supportedReasoning": [ + "auto", + "off", + "minimal", + "low", + "medium", + "high", + "xhigh" + ], + "defaultReasoning": "low", + "eligibleForAgent": true, + "defaultReference": false + }, + { + "model": "MiniMax-M3", + "displayName": "MiniMax M3", + "tier": "balanced", + "routingPriority": 30, + "serviceTypes": [ + "chat" + ], + "capabilities": [ + "chat", + "reasoning", + "code", + "vision", + "video_understanding", + "tool_use", + "long_context" + ], + "contextWindow": 1048576, + "maxOutputTokens": 512000, + "supportedReasoning": [ + "auto", + "off", + "minimal", + "low", + "medium", + "high", + "xhigh" + ], + "defaultReasoning": "medium", + "eligibleForAgent": true, + "defaultReference": false + }, + { + "model": "wan2.7-image", + "displayName": "通义万相 2.7", + "tier": "balanced", + "routingPriority": 107, + "serviceTypes": [ + "image_gen" + ], + "capabilities": [ + "chat", + "image_generation", + "chinese_optimized" + ], + "contextWindow": null, + "maxOutputTokens": null, + "supportedReasoning": [ + "auto" + ], + "defaultReasoning": "auto", + "eligibleForAgent": false, + "defaultReference": false + }, + { + "model": "glm-5.1", + "displayName": "GLM-5.1", + "tier": "balanced", + "routingPriority": 65, + "serviceTypes": [ + "chat" + ], + "capabilities": [ + "chat", + "reasoning", + "code", + "multilingual", + "deep_thinking", + "long_context", + "math", + "tool_use", + "agent" + ], + "contextWindow": 200000, + "maxOutputTokens": 128000, + "supportedReasoning": [ + "auto", + "off", + "minimal", + "low", + "medium", + "high", + "xhigh" + ], + "defaultReasoning": "medium", + "eligibleForAgent": true, + "defaultReference": false + }, + { + "model": "deepseek-v4-flash", + "displayName": "DeepSeek V4 Flash", + "tier": "lightweight", + "routingPriority": 35, + "serviceTypes": [ + "chat", + "reasoning" + ], + "capabilities": [ + "chat", + "code", + "reasoning", + "deep_thinking", + "multilingual", + "tool_use" + ], + "contextWindow": 1000000, + "maxOutputTokens": 384000, + "supportedReasoning": [ + "auto", + "high", + "max" + ], + "defaultReasoning": "high", + "eligibleForAgent": true, + "defaultReference": false + }, + { + "model": "deepseek-v4-pro", + "displayName": "DeepSeek V4 Pro", + "tier": "flagship", + "routingPriority": 30, + "serviceTypes": [ + "chat", + "reasoning" + ], + "capabilities": [ + "chat", + "reasoning", + "deep_thinking", + "code", + "math", + "science", + "multilingual", + "tool_use" + ], + "contextWindow": 1000000, + "maxOutputTokens": 384000, + "supportedReasoning": [ + "auto", + "high", + "max" + ], + "defaultReasoning": "high", + "eligibleForAgent": true, + "defaultReference": true + }, + { + "model": "kimi-k2.6", + "displayName": "Kimi K2.6", + "tier": "balanced", + "routingPriority": 45, + "serviceTypes": [ + "chat" + ], + "capabilities": [ + "chat", + "reasoning", + "code", + "tool_use", + "agent", + "long_context", + "vision" + ], + "contextWindow": 262144, + "maxOutputTokens": 16384, + "supportedReasoning": [ + "auto", + "off", + "minimal", + "low", + "medium", + "high", + "xhigh" + ], + "defaultReasoning": "medium", + "eligibleForAgent": true, + "defaultReference": false + }, + { + "model": "kimi-k2.7-code", + "displayName": "Kimi K2.7 Code", + "tier": "balanced", + "routingPriority": 50, + "serviceTypes": [ + "chat" + ], + "capabilities": [ + "chat", + "code", + "vision", + "tool_use" + ], + "contextWindow": 262144, + "maxOutputTokens": 16384, + "supportedReasoning": [ + "auto" + ], + "defaultReasoning": "auto", + "eligibleForAgent": true, + "defaultReference": false + }, + { + "model": "image-01", + "displayName": "MiniMax Image 01", + "tier": "balanced", + "routingPriority": 113, + "serviceTypes": [ + "image_gen" + ], + "capabilities": [ + "chat", + "image_generation", + "subject_reference", + "chinese_optimized" + ], + "contextWindow": null, + "maxOutputTokens": null, + "supportedReasoning": [ + "auto" + ], + "defaultReasoning": "auto", + "eligibleForAgent": false, + "defaultReference": false + }, + { + "model": "mimo-v2.5-tts", + "displayName": "MiMo V2.5 TTS", + "tier": "lightweight", + "routingPriority": 114, + "serviceTypes": [ + "tts" + ], + "capabilities": [ + "chat", + "tts", + "multilingual", + "style_control" + ], + "contextWindow": 8192, + "maxOutputTokens": null, + "supportedReasoning": [ + "auto" + ], + "defaultReasoning": "auto", + "eligibleForAgent": false, + "defaultReference": false + }, + { + "model": "happyhorse-1.1-i2v", + "displayName": "HappyHorse 1.1 I2V", + "tier": "flagship", + "routingPriority": 115, + "serviceTypes": [ + "video_gen" + ], + "capabilities": [ + "chat", + "video_generation", + "image_to_video", + "high_quality" + ], + "contextWindow": null, + "maxOutputTokens": null, + "supportedReasoning": [ + "auto" + ], + "defaultReasoning": "auto", + "eligibleForAgent": false, + "defaultReference": false + }, + { + "model": "happyhorse-1.1-t2v", + "displayName": "HappyHorse 1.1 T2V", + "tier": "flagship", + "routingPriority": 116, + "serviceTypes": [ + "video_gen" + ], + "capabilities": [ + "chat", + "video_generation", + "text_to_video", + "high_quality" + ], + "contextWindow": null, + "maxOutputTokens": null, + "supportedReasoning": [ + "auto" + ], + "defaultReasoning": "auto", + "eligibleForAgent": false, + "defaultReference": false + }, + { + "model": "happyhorse-1.1-r2v", + "displayName": "HappyHorse 1.1 R2V", + "tier": "flagship", + "routingPriority": 117, + "serviceTypes": [ + "video_gen" + ], + "capabilities": [ + "chat", + "video_generation", + "reference_to_video", + "multi_image", + "high_quality" + ], + "contextWindow": null, + "maxOutputTokens": null, + "supportedReasoning": [ + "auto" + ], + "defaultReasoning": "auto", + "eligibleForAgent": false, + "defaultReference": false + }, + { + "model": "doubao-seedance-2.0-mini", + "displayName": "Seedance 2.0 Mini", + "tier": "lightweight", + "routingPriority": 118, + "serviceTypes": [ + "video_gen" + ], + "capabilities": [ + "chat", + "video_generation", + "image_to_video", + "text_to_video", + "video_editing", + "video_extension", + "audio_generation", + "first_last_frame", + "fast", + "cost_effective" + ], + "contextWindow": null, + "maxOutputTokens": null, + "supportedReasoning": [ + "auto" + ], + "defaultReasoning": "auto", + "eligibleForAgent": false, + "defaultReference": false + }, + { + "model": "doubao-seedance-2.0-fast", + "displayName": "Seedance 2.0 Fast", + "tier": "balanced", + "routingPriority": 119, + "serviceTypes": [ + "video_gen" + ], + "capabilities": [ + "chat", + "video_generation", + "image_to_video", + "text_to_video", + "video_editing", + "video_extension", + "audio_generation", + "first_last_frame", + "fast" + ], + "contextWindow": null, + "maxOutputTokens": null, + "supportedReasoning": [ + "auto" + ], + "defaultReasoning": "auto", + "eligibleForAgent": false, + "defaultReference": false + }, + { + "model": "doubao-seedance-2.0", + "displayName": "Seedance 2.0", + "tier": "flagship", + "routingPriority": 120, + "serviceTypes": [ + "video_gen" + ], + "capabilities": [ + "chat", + "video_generation", + "image_to_video", + "text_to_video", + "video_editing", + "video_extension", + "audio_generation", + "first_last_frame" + ], + "contextWindow": null, + "maxOutputTokens": null, + "supportedReasoning": [ + "auto" + ], + "defaultReasoning": "auto", + "eligibleForAgent": false, + "defaultReference": false + }, + { + "model": "glm-5.2", + "displayName": "GLM-5.2", + "tier": "flagship", + "routingPriority": 45, + "serviceTypes": [ + "chat" + ], + "capabilities": [ + "chat", + "reasoning", + "deep_thinking", + "code", + "multilingual", + "tool_use", + "long_context" + ], + "contextWindow": 1048576, + "maxOutputTokens": 32768, + "supportedReasoning": [ + "auto", + "off", + "minimal", + "low", + "medium", + "high", + "xhigh" + ], + "defaultReasoning": "high", + "eligibleForAgent": true, + "defaultReference": false + }, + { + "model": "kimi-k3", + "displayName": "Kimi K3", + "tier": "flagship", + "routingPriority": 35, + "serviceTypes": [ + "reasoning" + ], + "capabilities": [ + "chat", + "reasoning", + "code", + "tool_use", + "agent", + "long_context", + "vision" + ], + "contextWindow": 1048576, + "maxOutputTokens": 131072, + "supportedReasoning": [ + "auto", + "off", + "minimal", + "low", + "medium", + "high", + "xhigh" + ], + "defaultReasoning": "high", + "eligibleForAgent": true, + "defaultReference": false + }, + { + "model": "mimo-v2.5-asr", + "displayName": "MiMo V2.5 ASR", + "tier": "lightweight", + "routingPriority": 123, + "serviceTypes": [ + "asr" + ], + "capabilities": [ + "chat", + "asr", + "multilingual" + ], + "contextWindow": null, + "maxOutputTokens": null, + "supportedReasoning": [ + "auto" + ], + "defaultReasoning": "auto", + "eligibleForAgent": false, + "defaultReference": false + }, + { + "model": "qwen3.8-max-preview", + "displayName": "Qwen3.8 Max Preview", + "tier": "flagship", + "routingPriority": 40, + "serviceTypes": [ + "chat" + ], + "capabilities": [ + "chat", + "reasoning", + "code", + "multilingual", + "tool_use", + "long_context", + "agent", + "vision" + ], + "contextWindow": 1000000, + "maxOutputTokens": 65536, + "supportedReasoning": [ + "auto", + "off", + "minimal", + "low", + "medium", + "high", + "xhigh" + ], + "defaultReasoning": "high", + "eligibleForAgent": true, + "defaultReference": false + }, + { + "model": "doubao-seed-2.1-turbo", + "displayName": "Doubao Seed 2.1 Turbo", + "tier": "balanced", + "routingPriority": 40, + "serviceTypes": [ + "chat" + ], + "capabilities": [ + "chat", + "reasoning", + "code", + "multilingual", + "long_context", + "tool_use", + "vision" + ], + "contextWindow": 256000, + "maxOutputTokens": 128000, + "supportedReasoning": [ + "auto", + "off", + "minimal", + "low", + "medium", + "high", + "xhigh" + ], + "defaultReasoning": "medium", + "eligibleForAgent": true, + "defaultReference": false + } + ] + } + ] +} diff --git a/manifest.json b/manifest.json index e9e9fc7..6caed51 100644 --- a/manifest.json +++ b/manifest.json @@ -1,6 +1,6 @@ { "version": "1.0.0", - "presetDataVersion": 87, - "updatedAt": "2026-08-08", + "presetDataVersion": 88, + "updatedAt": "2026-08-10", "description": "DesireCore 官方配置中心" } diff --git a/schemas/smart-model-catalog.schema.json b/schemas/smart-model-catalog.schema.json new file mode 100644 index 0000000..b7ee989 --- /dev/null +++ b/schemas/smart-model-catalog.schema.json @@ -0,0 +1,273 @@ +{ + "$schema": "http://json-schema.org/draft-07/schema#", + "$id": "https://desirecore.net/schemas/smart-model-catalog.json", + "title": "SmartModelCatalog", + "description": "智能路由量级、Provider 和模型能力目录;Config Center、内置兜底与未来接口共用此契约。", + "type": "object", + "required": [ + "version", + "updatedAt", + "source", + "tiers", + "providers" + ], + "properties": { + "$schema": { + "type": "string", + "description": "本数据对应的 JSON Schema 标识。" + }, + "version": { + "type": "integer", + "minimum": 1, + "maximum": 1, + "description": "目录结构版本;当前客户端只接受 v1,不兼容的新语义必须递增版本并由新客户端接入。" + }, + "updatedAt": { + "type": "string", + "format": "date-time", + "description": "本目录最近一次人工/自动核对时间。" + }, + "source": { + "type": "string", + "enum": [ + "builtin", + "config-center", + "provider-api" + ], + "description": "目录来源:config-center=配置中心下发,builtin=客户端离线兜底,provider-api=未来接口实时数据。" + }, + "tiers": { + "type": "array", + "minItems": 3, + "maxItems": 3, + "items": { + "type": "object", + "required": [ + "id", + "label", + "labelEn", + "description", + "defaultReasoning" + ], + "properties": { + "id": { + "type": "string", + "enum": [ + "flagship", + "balanced", + "lightweight" + ], + "description": "智能路由量级:flagship=最高能力,balanced=质量与成本平衡,lightweight=最快最省。" + }, + "label": { + "type": "string", + "minLength": 1, + "description": "中文量级标签。" + }, + "labelEn": { + "type": "string", + "minLength": 1, + "description": "英文量级标签。" + }, + "description": { + "type": "string", + "minLength": 1, + "description": "该量级的任务选择目标。" + }, + "defaultReasoning": { + "type": "string", + "enum": [ + "auto", + "off", + "minimal", + "low", + "medium", + "high", + "xhigh", + "max" + ], + "description": "该量级在模型支持时优先采用的默认思考深度。" + } + }, + "additionalProperties": false + }, + "description": "三档量级的自描述定义。" + }, + "providers": { + "type": "array", + "minItems": 1, + "items": { + "type": "object", + "required": [ + "providerId", + "provider", + "displayName", + "models" + ], + "properties": { + "providerId": { + "type": "string", + "minLength": 1, + "maxLength": 200, + "description": "compute.json 中的 Provider 唯一 ID。" + }, + "provider": { + "type": "string", + "minLength": 1, + "maxLength": 120, + "description": "Provider 协议标识。" + }, + "displayName": { + "type": "string", + "minLength": 1, + "maxLength": 200, + "description": "Provider 展示名称。" + }, + "models": { + "type": "array", + "minItems": 1, + "items": { + "type": "object", + "required": [ + "model", + "displayName", + "tier", + "routingPriority", + "serviceTypes", + "capabilities", + "contextWindow", + "maxOutputTokens", + "supportedReasoning", + "defaultReasoning", + "eligibleForAgent", + "defaultReference" + ], + "properties": { + "model": { + "type": "string", + "minLength": 1, + "maxLength": 300, + "description": "传给对应 Provider 的真实 modelName;禁止使用 smart 等虚拟名称。" + }, + "displayName": { + "type": "string", + "minLength": 1, + "maxLength": 200, + "description": "客户端展示名称。" + }, + "tier": { + "type": "string", + "enum": [ + "flagship", + "balanced", + "lightweight" + ], + "description": "此模型在智能路由中的能力量级。" + }, + "routingPriority": { + "type": "integer", + "minimum": 0, + "maximum": 10000, + "description": "同一量级内的稳定选择顺序,数值越小越优先;凭据与硬能力校验仍先于此排序。" + }, + "serviceTypes": { + "type": "array", + "minItems": 1, + "maxItems": 16, + "uniqueItems": true, + "items": { + "type": "string", + "minLength": 1, + "maxLength": 64, + "pattern": "^[a-z0-9_]+$", + "description": "可用于任务硬约束匹配的规范能力标签,例如 vision、code、tool_use、long_context。" + }, + "description": "模型服务类型快照,例如 chat、reasoning、image_gen、video_gen。" + }, + "capabilities": { + "type": "array", + "maxItems": 64, + "uniqueItems": true, + "items": { + "type": "string", + "minLength": 1, + "maxLength": 64, + "pattern": "^[a-z0-9_]+$", + "description": "可用于任务硬约束匹配的规范能力标签,例如 vision、code、tool_use、long_context。" + }, + "description": "模型能力快照;任务 requiredCapabilities 必须全部命中。" + }, + "contextWindow": { + "type": [ + "integer", + "null" + ], + "minimum": 1, + "maximum": 10000000, + "description": "上下文窗口 token 数;非文本模型或未知时为 null。" + }, + "maxOutputTokens": { + "type": [ + "integer", + "null" + ], + "minimum": 1, + "maximum": 1000000, + "description": "最大输出 token 数;未知或不适用时为 null。" + }, + "supportedReasoning": { + "type": "array", + "minItems": 1, + "maxItems": 8, + "uniqueItems": true, + "items": { + "type": "string", + "enum": [ + "auto", + "off", + "minimal", + "low", + "medium", + "high", + "xhigh", + "max" + ], + "description": "本次 Run 或当前 assignment 的思考深度;最终值仍受目标 Provider × Model 能力矩阵约束。" + }, + "description": "该 Provider × Model 接入面声明的可用 reasoning 档位。" + }, + "defaultReasoning": { + "type": "string", + "enum": [ + "auto", + "off", + "minimal", + "low", + "medium", + "high", + "xhigh", + "max" + ], + "description": "未显式指定时的模型参考 reasoning;路由还会结合量级默认值并做能力协商。" + }, + "eligibleForAgent": { + "type": "boolean", + "description": "是否可作为 Agent 主模型。图像/视频生成、ASR/TTS 等专用模型为 false。" + }, + "defaultReference": { + "type": "boolean", + "description": "是否为 Provider/defaultServiceMap 给出的默认参考。它只影响同级排序,不是强制答案。" + } + }, + "additionalProperties": false + }, + "description": "该接入面当前已核对的模型目录。" + } + }, + "additionalProperties": false + }, + "description": "参与智能路由和能力匹配的 Provider 目录。" + } + }, + "additionalProperties": false +} diff --git a/scripts/validate.mjs b/scripts/validate.mjs index d872fa3..5ffb1c2 100644 --- a/scripts/validate.mjs +++ b/scripts/validate.mjs @@ -46,6 +46,7 @@ function pickSchemaKey(absPath) { if (rel === 'manifest.json') return 'manifest' if (rel === 'compute/pricing.json') return 'pricing' if (rel === 'compute/service-map.json') return 'service-map' + if (rel === 'compute/smart-routing/model-catalog.json') return 'smart-model-catalog' if (rel === 'compute/providers/_index.json') return 'providers-index' if (rel === 'runtimes/recommended.json') return 'runtime-recommended' if (rel === 'runtimes/versions-fallback.json') return 'runtime-versions-fallback'