ARTICLE DETAIL

资讯详情

深耕郑州网站建设与运营推广的一线实战洞察。

Operit 的 OpenCode Provider 隔离改造:公共 Provider 恢复基线、协议专用路由与静态验证指南

Operit 的 OpenCode Provider 隔离改造:公共 Provider 恢复基线、协议专用路由与静态验证指南 AI Agent人工智能大模型AI 应用工具调用本地部署MCP ClientsAgent 记忆【免费下载链接】OperitThe most powerful AI agent and AI chat software on Android/Operit是一款Android上能力最为强大、发展最久的AI Agent项目地址https://gitcode.com/gh_mirrors/op/Operit点击查看免费下载本文以docs/TODO/opencode_provider_isolation_20260820/三部曲文档基线恢复、路由隔离、验证记录为核心骨架结合 Operit 仓库中OpenCodeProvider.kt的实际实现完整讲解 OpenCode provider 隔离改造的来龙去脉公共 provider 如何摆脱 OpenCode 特例、协议路由如何收敛到专用实现、以及如何在不运行构建与测试的前提下完成静态验证。读者读完后可以掌握一套公共 provider 保持通用行为 专用 provider 承载协议差异的扩展点设计思路并能在自己的 provider 接入工作中复用它。一、改造背景marker 注入带来的公共路径污染Operit 首版接入 OpenCode 时把路由、认证和思考参数通过OpenCodeReasoningParametersmarker 注入 Claude、Gemini、OpenAI 和 Responses 等普通 provider 的请求构建路径。带来的问题是普通 provider 需要识别 OpenCode 特例公共请求路径因此承担了不属于自身的协议差异index.md。从源码结构看这个设计的核心缺陷有两个单一 marker 进入所有请求构建路径OpenCodeReasoningParameters只为一个 provider 服务却影响了所有普通请求的 reasoning 自动注入、参数过滤和 Gemini 请求端点01-public-provider-baseline.md。认证与端点逻辑被揉进公共实现OpenCode 网关对认证头如 Gemini 的x-goog-api-key和 SSE URL 有自己约定若这些逻辑散落在公共 provider 中公共 provider 的端点与认证行为会被悄悄改变。修正意图让 OpenCode 的协议适配留在 OpenCode 专用实现中。普通 provider 只保留自己的通用行为必要的继承点只表达稳定的请求构建扩展不引用 OpenCode 类型也不做分支判断index.md。改造的作用域被明确限定为四件事index.md恢复公共 provider 的原有 reasoning、认证和端点行为为 OpenCode 的 Chat Completions、Responses、Anthropic 和 Gemini 路由提供隔离实现修正 OpenCode Gemini 的认证头和 SSE URL保留现有设置、模型目录和路由测试并补充隔离边界说明。二、公共 provider 恢复边界不引用 OpenCode 类型2.1 完成标准01-public-provider-baseline.md给出了三条可验证的完成标准01-public-provider-baseline.mdClaudeProvider.kt、GeminiProvider.kt、OpenAIProvider.kt、OpenAIResponsesProvider.kt不包含 OpenCode 特例判断OpenCode 专用代码承担显式 reasoning 参数OpenCode 专用代码承担 Geminix-goog-api-key与 SSE URL。2.2 仓库中的实现证据在仓库中搜索llmprovider目录公共 provider 文件均独立存在ClaudeProvider.ktGeminiProvider.ktOpenAIProvider.ktOpenAIResponsesProvider.kt而对OpenCode关键词的目录级搜索显示它只出现在 OpenCodeProvider.kt、AIServiceFactory.kt、CodexProvider.kt 和 ModelListFetcher.kt 中——公共 provider 文件中没有 OpenCode 引用与文档声明的恢复边界一致。此外公共 provider 的通用行为仍然保留例如 OpenAIResponsesProvider.kt 中仍保留对reasoning_effort的通用处理逻辑空值/缺失时移除说明 reasoning 参数的管理继续留在各公共 provider 的既有语义内而不是被 OpenCode 的显式参数注入所替代。三、OpenCode 路由隔离专用实现的四协议边界3.1 路由职责OpenCodeProvider负责根据模型选择协议并把请求交给专用 provider 实现。专用实现可以复用通用 provider 的消息、工具和流处理但通过受控扩展点覆盖请求体和请求 URL不把 OpenCode 条件写回公共 provider02-opencode-routing.md。请求边界被明确约定为四条02-opencode-routing.md协议路由专用行为OpenAI Chat Completions显式传入reasoning_effortOpenAI Responses显式传入reasoning不触发公共自动注入Anthropic Messages显式传入thinking/output_configGemini使用模型 URL、x-goog-api-key和流式?altsse3.2 路由工厂与模型→协议映射在 OpenCodeProvider.kt 中create方法负责路由装配先剔除模型名中的opencode/、opencode-go/前缀通过OpenCodeRouting.endpointFor计算端点、protocolFor计算协议注入 OpenCode 网关需要的请求头统一User-Agent: Operit/VERSION_NAMEGo 端点额外加x-opencode-session: operit-config.id用于网关识别客户端并稳定 prompt-cache 路由按协议构造专用 provider 并包装为OpenCodeProvider委托。模型到协议的映射规则OpenCodeRouting.protocolFor可以从源码中完整还原gemini-*→GEMINI_GENERICclaude-*、qwen3.*、Go 端点下的minimax-*、非 Go 端点下以-free结尾的minimax-*→ANTHROPIC_GENERICgpt-*、grok-*、muse-spark-*→OPENAI_RESPONSES_GENERIC非 Go 端点下的minimax-*→OPENAI_GENERICbig-pickle-*、deepseek-*、glm-*、hy3*、hy4-*、kimi-*、ling-*、longcat-*、mimo-*、nemotron-*、omen-*、qwen3-coder*、ring-*、north-*、laguna-*、trinity-*、x-preview-*→OPENAI_GENERIC其余模型抛出IllegalArgumentException(Unsupported OpenCode model protocol: ...)。端点推导OpenCodeRouting.endpointFor遵循统一补/v1约定normalizedBase会去掉末尾/若不以/v1结尾则补上/v1再拼接协议路径Responses →$base/responsesAnthropic →$base/messagesGemini →$base/models/$modelName其余 →$base/chat/completionsisGo判断依据端点是否以/zen/go或/zen/go/v1结尾catalogProviderId据此返回opencode-go或opencode用于模型目录的 provider 标识。在 AIServiceFactory.kt第 608 行附近中OpenCodeProvider.create被接入服务工厂的 provider 装配流程路由对上层调用方保持透明。3.3 Thinking 参数注入路径OpenCodeProvider.sendMessage通过ThinkingConfigurationApplier.modelParameters生成 thinking 映射与 OpenCode 参数再叠加到模型参数上最后委托给底层 provider。这里有个值得注意的细节enableThinking只在协议为OPENAI_RESPONSES_GENERIC时才透传给委托方enableThinking thinkingEnabled protocol ApiProviderType.OPENAI_RESPONSES_GENERIC避免公共自动注入逻辑被 OpenCode 的显式参数干扰——这正是显式传入、不触发公共自动注入边界的实现体现。四、四个专用 provider 的实现细节4.1 OpenCodeChatProviderreasoning_content 的提取与回传这是隔离改造中最关键的一处。OpenCode 的 OpenAI Chat 路由会向后端透传 DeepSeek 风格 thinking 输出——即使 Operit 未显式开启 thinkingOpenCode 也可能按模型能力自行开启。该协议要求历史 assistant 消息必须原样回传reasoning_content否则模型完成工具调用后的下一轮请求会返回 400The reasoning_content in the thinking mode must be passed back to the API.OpenCodeChatProvider把 reasoning_content 的提取与回传完全收敛在自身内部不动通用 OpenAIProvider.kt重写createRequestBody强制preserveThinkInHistory true让父类的buildMessagesAndCountTokens保留历史 assistant 消息中的think内容覆盖customizeFinalRequestObject在 messagesArray 后处理阶段遍历 assistant 消息用ChatUtils.extractThinkingContent把think.../think拆分为reasoning_content字段与清理后的content字段总是写入reasoning_content即使为空也写因为上游在历史不含该字段时会拒绝请求空字符串与未写含义不同。多模态 JSONArray 形态的 content 会被跳过避免改动既有多模态构造逻辑。4.2 OpenCodeResponsesProviderreasoning 元信息清理OpenCodeResponsesProvider继承 OpenAIProvider.kt设置useResponsesApi true走 Responses API。在 thinking 关闭时它通过ChatUtils.stripOpenAiResponsesReasoningMetaTurns从请求历史中剥离 Responses 风格的 reasoning 元信息轮次避免把不应透传的思考元数据送入请求体。4.3 OpenCodeClaudeProviderthinking / budget_tokens / output_configOpenCodeClaudeProvider继承 ClaudeProvider.kt并在addParameters扩展点中只放行三个显式参数thinking、budget_tokens、output_config。参数按ParameterValueType分类型写入请求体OBJECT 类型会先JSONObject(raw)解析失败时仅记日志而不中断请求。其余 Claude 通用参数仍走父类逻辑。公共 ClaudeProvider.kt 中对output_config的处理仍然保留约第 1183 行说明 Anthropic 协议的通用支持并未被 OpenCode 特例污染。4.4 OpenCodeGeminiProvider认证头与 SSE URL 的修正OpenCodeGeminiProvider继承 GeminiProvider.kt重写createRequest完成两处关键修正认证头使用x-goog-api-key携带 OpenCode 的 API Key而非公共 Gemini 的认证方式SSE URL流式请求拼?altsse端点按streamGenerateContent/generateContent区分方法URL 结构为$base/models/$modelName:method?altsse。apiBase会先从端点中剥离/models/之后的部分再补/v1确保 Gemini 方法后缀拼接正确。请求 URL 会被写入调试日志OpenCodeGeminiProvidertag便于排查路由问题。五、静态验证记录不构建、不测试、只查边界本次改造按仓库执行准则不运行构建、Gradle 或测试命令采用纯静态验证03-verification.md执行静态 diff 检查git diff --check确认改动无空白错误、无残留冲突标记核对公共 provider 不再引用 OpenCode 专用类型——即第一节中列出的完成标准逐条成立。仓库证据与这一验证结论吻合在app/src/main/java/com/ai/assistance/operit/api/chat/llmprovider/目录内搜索OpenCode命中文件只有OpenCodeProvider.kt、AIServiceFactory.kt、CodexProvider.kt、ModelListFetcher.kt四个公共 provider 文件ClaudeProvider.kt、GeminiProvider.kt、OpenAIProvider.kt、OpenAIResponsesProvider.kt均无命中。也就是说静态搜索可以直接作为公共 provider 已隔离的可重复验证手段。六、完成记录与可复用的边界清单根据 index.md 的完成记录公共 Provider 已移除 OpenCode marker、端点判断和认证分支OpenCode Chat、Responses、Anthropic、Gemini 专用实现已合并到 OpenCodeProvider.kt已执行git diff --check未运行构建、Gradle 或测试命令。整个改造沉淀出的边界清单可以直接作为后续 provider 接入的检查表公共 provider 零引用任何新 provider 的特例都不得出现在ClaudeProvider.kt/GeminiProvider.kt/OpenAIProvider.kt/OpenAIResponsesProvider.kt中协议差异收敛于专用子类通过继承 受控扩展点createRequestBody、addParameters、createRequest、customizeFinalRequestObject覆盖请求体和 URL思考参数显式化OpenCode 场景下reasoning_effort、reasoning、thinking/output_config由专用实现显式注入公共自动注入路径保持原样认证与端点各归其位x-goog-api-key、?altsse、/zen/go端点识别等 OpenCode 网关约定只存在于专用代码中静态验证闭环git diff --check 目录级关键词搜索确认公共 provider 无 OpenCode 引用即可完成隔离边界核验无需依赖构建与测试命令。这套做法的价值在于公共 provider 的 reasoning、认证和端点行为完全恢复为通用语义OpenCode 的协议适配在专用实现中自包含后续任何一方演进都不会互相破坏——这正是让协议差异留在该在的地方的工程实践。赞分享AI Agent人工智能大模型AI 应用工具调用本地部署MCP ClientsAgent 记忆【免费下载链接】OperitThe most powerful AI agent and AI chat software on Android/Operit是一款Android上能力最为强大、发展最久的AI Agent项目地址https://gitcode.com/gh_mirrors/op/Operit点击查看免费下载相关推荐Kick-Off价格页面模板设计吸引客户的产品定价页面Kick Off价格页面模板设计吸引客户的产品定价页面 Kick Off是一款基于UIkit 3的快速启动模板提供了丰富的布局和组件帮助开发者快速构建现代AI Agent人工智能大模型AI 应用工具调用本地部署MCP ClientsAgent 记忆GUI 自动化Operit OpenCode Provider 路由隔离多协议请求边界与专用适配实现解析Operit OpenCode Provider 路由隔离多协议请求边界与专用适配实现解析 导读 本文基于 Operit 仓库的 docs/TODO/openAI Agent人工智能大模型AI 应用工具调用本地部署MCP ClientsAgent 记忆GUI 自动化Carbon 语言与工具链版本控制方案Versioning完全解析从 SemVer 规范到 Bazel 构建落地Carbon 语言与工具链版本控制方案Versioning完全解析从 SemVer 规范到 Bazel 构建落地 导读 本文以 Carbon LanguAI Agent人工智能大模型AI 应用工具调用本地部署MCP ClientsAgent 记忆GUI 自动化上一篇distrobox create 完全指南在终端中创建深度集成宿主机的 Linux 容器下一篇ACE-Step UI终极指南5分钟掌握免费AI音乐创作的完整解决方案创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考
返回列表