{ "$schema": "http://json-schema.org/draft-07/schema#", "$id": "https://desirecore.net/schemas/config-center/provider.schema.json", "title": "Provider", "description": "frozen baseline schema 镜像 desirecore d185299(fix #471 之前)的 computeProviderSchema/providerModelSchema,作为已发布客户端兼容契约。任何写入 compute/providers/*.json 或 compute/coding-plans/*.json 的数据都必须通过此校验,否则会破坏老客户端(已发布版本的 schema 无法理解超出此契约的字段或类型)。\n\n关键约束:\n- defaultTemperature / defaultTopP 必须是 number(不接受 null)—— 历史教训:曾因 null 写入导致老客户端校验失败死锁\n- 顶层与 model 内 additionalProperties 均为 false —— 新增字段必须先升级老客户端 schema 再推送数据", "type": "object", "required": [ "id", "provider", "label", "baseUrl", "apiKeyRef", "apiKeyVerified", "enabled", "status", "services", "models" ], "properties": { "id": { "type": "string", "description": "提供商唯一标识符(如 provider-openai-001)", "minLength": 1 }, "provider": { "type": "string", "description": "提供商标识:openai、anthropic、deepseek、dashscope(阿里云)等", "minLength": 1 }, "label": { "type": "string", "description": "提供商显示名称(如 OpenAI、Anthropic、阿里云 DashScope)", "minLength": 1 }, "baseUrl": { "type": "string", "description": "API 基础 URL(如 https://api.openai.com/v1)", "minLength": 1 }, "apiFormat": { "type": "string", "description": "API 协议格式:openai-completions、anthropic-messages、openai-responses、google-generative-ai 等" }, "mediaBaseUrl": { "type": "string", "description": "媒体 API 基础 URL。当 provider 使用 Anthropic 格式(baseUrl 指向 /anthropic 端点)但其媒体 API(图片/语音/视频/音乐)仍走 OpenAI /v1 端点时使用" }, "apiKeyRef": { "type": "string", "description": "密钥引用名,对应 secrets.json 中的 key;空字符串表示未配置密钥" }, "apiKeyVerified": { "type": "boolean", "description": "API Key 是否已通过验证" }, "enabled": { "type": "boolean", "description": "是否启用此提供商" }, "status": { "type": "string", "enum": ["configured", "unconfigured", "error"], "description": "提供商状态" }, "services": { "type": "array", "description": "支持的服务类型列表(如 chat、reasoning、vision、embedding)", "items": { "type": "string" } }, "priceCurrency": { "type": "string", "enum": ["USD", "CNY"], "description": "价格货币单位。models 中的 inputPrice/outputPrice 均以此货币计价" }, "accessMode": { "type": "string", "enum": ["api", "coding-plan", "token-plan"], "description": "接入模式:api(按量付费)、coding-plan(编程订阅套餐)或 token-plan(Token 团队版订阅)" }, "brandGroup": { "type": "string", "description": "品牌分组标识,UI 按此字段排序" }, "credentialSource": { "type": "string", "enum": ["codex-cli", "claude-oauth", "github-copilot"], "description": "凭证托管来源。codex-cli:密钥由客户端本地 Codex CLI 凭证检测器托管(读取 ~/.codex/auth.json 自动刷新写回,fresh token 同步 secrets.json)。claude-oauth:Claude 订阅接入,由客户端 claude-auth 检测器托管——首选复用本机 Claude Code 登录(Agent SDK 自读,不写不刷新),或应用内 OAuth / setup-token 兜底;模型调用经 compat-proxy 内 claude-agent-sdk 后端履约,不直连。github-copilot:GitHub Copilot 订阅接入,由客户端 copilot-auth 检测器托管——GitHub Device Flow 登录,长期 GitHub OAuth token 存 config/copilot-oauth.json,定期交换约 30 分钟有效的 Copilot session token 写入 secrets.json;模型调用携带 Copilot 协议 headers 直连交换响应 endpoints.api 指定域名,模型列表由客户端在登录后经 /models 动态发现(可用集合随订阅档位与组织策略变化,故预设 models 为空)。需 requiredClientVersion ≥ 引入此字段的客户端版本——老客户端不识别本字段,必须先发版铺开 compute.json 韧性(容忍未知字段)再推送本数据" }, "codingPlan": { "type": "object", "description": "Coding Plan / Token Plan 专属配置(仅当 accessMode = coding-plan 或 token-plan 时有效)", "properties": { "planTier": { "type": "string" }, "planLabel": { "type": "string" }, "quotas": { "type": "object", "properties": { "per5h": { "type": "number", "minimum": 0 }, "perWeek": { "type": "number", "minimum": 0 }, "perMonth": { "type": "number", "minimum": 0 }, "per7d": { "type": "number", "minimum": 0 } }, "additionalProperties": false }, "usageTracking": { "type": "object", "properties": { "method": { "type": "string", "enum": ["rest-api", "response-header", "manual", "credits", "none"] }, "endpoint": { "type": "string" }, "headerKeys": { "type": "object", "properties": { "remaining": { "type": "string" }, "limit": { "type": "string" }, "reset": { "type": "string" } }, "additionalProperties": false }, "consoleUrl": { "type": "string" } }, "additionalProperties": false }, "modelIdOverride": { "type": "string" }, "maxConcurrent": { "type": "number", "minimum": 1 }, "expiresAt": { "type": "string", "format": "date-time" } }, "additionalProperties": false }, "tokenPlan": { "type": "object", "description": "Token Plan 团队版专属配置(仅当 accessMode = token-plan 时有效)", "properties": { "planTier": { "type": "string" }, "planLabel": { "type": "string" }, "quotas": { "type": "object", "properties": { "per5h": { "type": "number", "minimum": 0 }, "perWeek": { "type": "number", "minimum": 0 }, "perMonth": { "type": "number", "minimum": 0 }, "per7d": { "type": "number", "minimum": 0 } }, "additionalProperties": false }, "usageTracking": { "type": "object", "properties": { "method": { "type": "string", "enum": ["rest-api", "response-header", "manual", "credits", "none"] }, "endpoint": { "type": "string" }, "headerKeys": { "type": "object", "properties": { "remaining": { "type": "string" }, "limit": { "type": "string" }, "reset": { "type": "string" } }, "additionalProperties": false }, "consoleUrl": { "type": "string" } }, "additionalProperties": false }, "modelIdOverride": { "type": "string" }, "maxConcurrent": { "type": "number", "minimum": 1 }, "expiresAt": { "type": "string", "format": "date-time" } }, "additionalProperties": false }, "models": { "type": "array", "description": "此接入面当前可调用的模型列表。可用性、凭据、价格与 API 映射属于 Provider;模型能力、上下文、Smart tier 与产品 reasoning 合同以 compute/model-specs 为准。", "items": { "$ref": "#/definitions/model" } }, "tombstones": { "type": "array", "description": "预置显式删除的模型 modelName 白名单", "items": { "type": "string" } }, "requiredClientVersion": { "type": "string", "pattern": "^\\d+\\.\\d+\\.\\d+$", "description": "使用此 provider 所需的最低客户端版本(semver x.y.z)。对已铺开韧性(#848/#1021)的客户端是可安全推送的未知字段(非毒丸——毒丸只源自已知字段的 enum 值扩展);≥ 支持版本(含 desirecore #1038)的客户端据此把 provider 优雅门控为「需更新客户端」并从模型选择器排除。规约:新凭据源/新能力 provider 必须声明本字段;降低/解除要求请改为更小版本号而非删除字段(预设合并不回传字段删除)" } }, "additionalProperties": false, "definitions": { "model": { "type": "object", "required": ["modelName", "displayName", "serviceType", "capabilities"], "properties": { "modelName": { "type": "string", "description": "此 Provider 接入面实际接受的模型 ID,用于 API 调用并与 ModelSpec 的精确/受控别名匹配(如 gpt-5-mini、claude-sonnet-4)。", "minLength": 1 }, "displayName": { "type": "string", "description": "旧客户端展示兼容副本。新 Smart 路径以 ModelSpec.displayName 为模型事实,此字段仅随接入面保留。", "minLength": 1 }, "serviceType": { "type": ["string", "array"], "items": { "type": "string" }, "description": "旧客户端兼容的接入面服务声明;新 Smart 路径以 ModelSpec.spec 为能力事实。支持单个字符串或数组:chat、reasoning、fast、responses、translation、tts、asr、voice_clone、realtime_voice、simultaneous_interpret、vision、ocr、image_gen、video_gen、embedding、rerank、omni、computer_use 等" }, "description": { "type": "string", "description": "模型简要描述" }, "contextWindow": { "type": "number", "description": "旧客户端兼容副本;Smart 以 ModelSpec.spec.contextWindow 为模型事实,本地接入面覆盖只能收紧。", "minimum": 0 }, "maxOutputTokens": { "type": "number", "description": "旧客户端兼容副本;新模型规格以 ModelSpec.spec.maxOutputTokens 为准。", "minimum": 0 }, "capabilities": { "type": "array", "description": "旧客户端兼容副本;Smart 的能力标签以 ModelSpec.spec.capabilities 为准,接入面或用户覆盖只能收紧,不能扩张。", "items": { "type": "string" } }, "inputPrice": { "type": "number", "description": "输入价格(每百万 token),货币由 Provider.priceCurrency 决定", "minimum": 0 }, "outputPrice": { "type": "number", "description": "输出价格(每百万 token),货币由 Provider.priceCurrency 决定", "minimum": 0 }, "defaultTemperature": { "type": "number", "description": "默认温度参数(0-2)。【重要】必须是 number,禁止写为 null 或字符串。reasoning 等不支持温度的模型应完全省略此字段。null 会破坏 fix #471 之前发布的客户端(schema 严格 number),导致 readComputeConfig 死锁。", "minimum": 0, "maximum": 2 }, "defaultTopP": { "type": "number", "description": "默认 Top-P 参数(0-1)。【重要】必须是 number,禁止写为 null 或字符串。reasoning 等不支持 Top-P 的模型应完全省略此字段。null 会破坏 fix #471 之前发布的客户端,导致死锁。", "minimum": 0, "maximum": 1 }, "extra": { "type": "object", "description": "接入面特定配置:如 TTS 模型音色列表、ASR 支持格式、reasoning effort 与 native thinking 回放能力。这里是兼容扩展面:旧客户端会安全保留并忽略未知子字段。", "properties": { "thinkingRoundTrip": { "type": "object", "description": "当前 Provider/model 接入面是否允许回放 Provider 原样返回的 Anthropic thinking。只授权当前未闭合工具轨迹;UI 展示 thinking、已完成旧轮次、跨模型/凭据数据永远没有回放资格。", "required": ["enabled", "protocol", "allowEmptySignature", "scope"], "properties": { "enabled": { "type": "boolean", "description": "显式能力开关;客户端只接受 true,false 或缺失均 fail closed。" }, "protocol": { "type": "string", "enum": ["anthropic-messages"], "description": "能力对应的线上协议;不得由 Provider 名称或 URL 猜测。" }, "allowEmptySignature": { "type": "boolean", "description": "是否允许回放该接入面原样返回的空 signature;只有真机证明网关确实要求时才能设为 true,不得制造空签名。" }, "scope": { "type": "string", "enum": ["active-tool-turn"], "description": "固定只作用于当前未闭合工具轨迹,禁止扩张到完成历史。" } }, "additionalProperties": false }, "reasoning": { "type": "object", "description": "当前 Provider 接入面接受哪些 reasoning effort 值——精确档位矩阵。只能写在 provider model 的 extra 里:同一模型经不同网关支持的集合可能不同,因此 model-spec 的 spec.extra 里写本键会被客户端 applySpec 主动丢弃。想表达「这个模型根本关不掉思考」的用 model-spec 的 spec.extra.thinkingOnly,那只回答 off 能否使用、不声明任何深度档位。", "required": ["supportedEfforts"], "properties": { "supportedEfforts": { "type": "array", "minItems": 1, "uniqueItems": true, "items": { "type": "string", "enum": ["none", "minimal", "low", "medium", "high", "xhigh", "max"] }, "description": "当前接入面实际接受的 OpenAI reasoning effort;它只能收紧精确 ModelSpec.routing.reasoning 合同,不能扩张。none 在产品层映射为 off;Ultra 是多 Agent 编排模式,禁止写入。" }, "defaultEffort": { "type": "string", "enum": ["minimal", "low", "medium", "high", "xhigh", "max"], "description": "当前接入面推荐的显式默认档位;仅当它仍属于 ModelSpec 合同时生效,且必须同时存在于 supportedEfforts。" } }, "allOf": [ { "if": { "required": ["defaultEffort"], "properties": { "defaultEffort": { "const": "minimal" } } }, "then": { "properties": { "supportedEfforts": { "contains": { "const": "minimal" } } } } }, { "if": { "required": ["defaultEffort"], "properties": { "defaultEffort": { "const": "low" } } }, "then": { "properties": { "supportedEfforts": { "contains": { "const": "low" } } } } }, { "if": { "required": ["defaultEffort"], "properties": { "defaultEffort": { "const": "medium" } } }, "then": { "properties": { "supportedEfforts": { "contains": { "const": "medium" } } } } }, { "if": { "required": ["defaultEffort"], "properties": { "defaultEffort": { "const": "high" } } }, "then": { "properties": { "supportedEfforts": { "contains": { "const": "high" } } } } }, { "if": { "required": ["defaultEffort"], "properties": { "defaultEffort": { "const": "xhigh" } } }, "then": { "properties": { "supportedEfforts": { "contains": { "const": "xhigh" } } } } }, { "if": { "required": ["defaultEffort"], "properties": { "defaultEffort": { "const": "max" } } }, "then": { "properties": { "supportedEfforts": { "contains": { "const": "max" } } } } } ], "additionalProperties": false } }, "additionalProperties": true }, "apiModelId": { "type": "string", "description": "实际传给上游 API 的 model 参数。当 modelName 与 API 期望名称不同时使用" }, "source": { "type": "string", "enum": ["preset", "synced", "user-added", "ollama-discovery"], "description": "模型来源。config-center 数据应统一为 preset" } }, "additionalProperties": false } } }