返回 DeepSeek-Reasonix
OPENCODE_RECOVERY_COMPARISON.md
根目录 / docs / OPENCODE_RECOVERY_COMPARISON.md
1 # OpenCode comparison after live tests / 真实测试后的 OpenCode 对照
2
3 Date / 日期: 2026-09-05. Source baseline / 源码基线:
4 [`bbd72fb8b0bb6de580d2041a0150016227c63ac0`](https://github.com/anomalyco/opencode/tree/bbd72fb8b0bb6de580d2041a0150016227c63ac0).
5 This is a source comparison with Reasonix live experiments, not a same-account
6 end-to-end benchmark of the OpenCode executable. / 本文结合 OpenCode 固定源码与
7 Reasonix 实测;没有宣称运行 OpenCode 完整客户端作同账户对照。
8
9 ## 1. Normal text completion without the requested tool / 正常结束却没有执行工具
10
11 Kimi K3 returned HTTP 200 and `stop` with no tool-call fields on the original
12 wire. It sometimes invented an echo result. Reasonix did not drop a received
13 call: the call was absent before parsing. Both low and max effort reproduced
14 this behavior with the minimal no-argument echo fixture.
15
16 Kimi 的问题发生在模型输出层:原始响应没有工具调用,却输出了声称的结果;
17 low、max 两个档位均出现过。不能把调高思考档位当成已证实的修复。
18
19 OpenCode's [session loop](https://github.com/anomalyco/opencode/blob/bbd72fb8b0bb6de580d2041a0150016227c63ac0/packages/opencode/src/session/prompt.ts#L1096)
20 exits on a normal finish without tool parts. It explicitly continues when real
21 tool parts exist even if the provider says `stop`. It does not generally infer
22 an unperformed task from prose and automatically ask again.
23 Its [Kimi prompt selection](https://github.com/anomalyco/opencode/blob/bbd72fb8b0bb6de580d2041a0150016227c63ac0/packages/opencode/src/session/system.ts#L45)
24 and [action instructions](https://github.com/anomalyco/opencode/blob/bbd72fb8b0bb6de580d2041a0150016227c63ac0/packages/opencode/src/session/prompt/kimi.txt#L3)
25 make execution requirements explicit. Ordinary runs do not force tools:
26 [`required` is selected for JSON-schema structured output](https://github.com/anomalyco/opencode/blob/bbd72fb8b0bb6de580d2041a0150016227c63ac0/packages/opencode/src/session/prompt.ts#L1285).
27
28 OpenCode 也不会因为用户的自然语言要求而普遍强制工具调用。应吸收它的明确
29 行动提示与真实工具状态判断,而不是把 `stop` 改为重试,或给所有轮次设置
30 `tool_choice=required`,从而破坏问答、最终总结和权限边界。
31
32 Prompt-only experiment: adding a short execution-and-evidence instruction at
33 max effort completed 6/6 baseline/cut samples, versus 5/6 with the original
34 minimal prompt. Production prompts are unchanged. The samples were sequential,
35 small, and not statistically conclusive. A separate three-sample Kimi parameter
36 fixture passed twice; one run used a label that did not preserve the requested
37 Unicode/newline value. All three runs called each tool once. This semantic value
38 mismatch is not malformed JSON and is not solved by SDK tool-name repair.
39
40 短提示实验六例全完成,可作为优先验证的候选;不能直接宣称问题已经修复。
41 参数值不符应由工具返回具体校验错误,允许模型在授权范围内纠正;适配器不应
42 擅自替换业务参数。首个错误样本没有记录原始参数字节,故没有进一步断言其
43 精确错误值;三例工具各调用一次,也不能证明参数纠错循环已经验证。
44
45 Recommended change / 建议:
46
47 - First validate a small, static instruction that action requests require real
48 tool execution and that completion claims require actual results. Evaluate
49 realistic read/edit/test tasks as well as the echo fixture. / 先验证短小、
50 稳定的行动提示,覆盖真实读取、编辑、测试任务;不能只优化一个 echo 用例。
51 - If a host-owned workflow already has a verifiable unfinished required action,
52 allow at most one bounded reminder, sharing the existing turn budget. A
53 completed write, permission rejection, cancellation or unknown side effect
54 must prevent action replay. Ordinary conversation should retain normal stops.
55 / 仅在宿主已有确定的未完成动作状态时考虑一次提醒,共享预算;不得凭文字
56 猜任务,也不得重放已完成写入、拒绝权限或结果未知的操作。
57 - This reminder would be a Reasonix extension, not behavior proven in OpenCode.
58 Any system-prompt change changes the cache prefix once; do not inject changing
59 reminders into healthy turns. / 自动提醒属于 Reasonix 的额外设计。固定提示
60 修改会使对应缓存前缀变化一次,不应向正常轮次持续注入动态提示。
61
62 ## 2. Opaque HTTP 400 on custom DeepSeek Messages / 自定义 Messages 的不透明 400
63
64 Six Go Flash/Pro replay-rejection probes deliberately damaged the second
65 outbound request while retaining the completed local tool result. Chat and
66 Responses returned an identifiable error and recovered: four probes each made
67 three requests and executed the tool once. Messages returned only
68 `{"model":"deepseek-v4-flash"}` or the Pro counterpart with HTTP 400. Both
69 Messages probes stopped after two requests, retaining the single completed tool.
70
71 Go 的 Chat、Responses 四例能识别并修复;Messages 两例缺少具体错误原因。
72 我们知道测试故意破坏了回放,但真实客户端没有代理的内部知识,因此不能由
73 HTTP 400 加模型名称推断 reasoning 缺失。
74
75 OpenCode's [retry classifier](https://github.com/anomalyco/opencode/blob/bbd72fb8b0bb6de580d2041a0150016227c63ac0/packages/opencode/src/session/retry.ts#L85)
76 also requires retryable status/metadata or recognized error text; this bare 400
77 body does not satisfy those conditions. Its current gateway
78 [requires matching wire formats](https://github.com/anomalyco/opencode/blob/bbd72fb8b0bb6de580d2041a0150016227c63ac0/packages/console/app/src/routes/zen/util/handler.ts#L214),
79 and the [same-format converter is an identity](https://github.com/anomalyco/opencode/blob/bbd72fb8b0bb6de580d2041a0150016227c63ac0/packages/console/app/src/routes/zen/util/provider/provider.ts#L215).
80 This source snapshot does not establish which deployed upstream or intermediary
81 removed the details. / 当前公开源码不能证明是哪一层部署丢失了错误详情,不能
82 直接把现场现象归因于某个转换函数。
83
84 Recommended change / 建议:
85
86 - Continue automatic repair for an explicit replay error or locally provable
87 invalid history, using the existing one-time repair budget. / 明确回放错误、
88 本地可证明无效的历史继续走现有一次修复路径。
89 - Preserve safe status, error code and available request identifiers; surface
90 an explicit “upstream did not provide the cause” diagnostic for opaque errors.
91 Do not retry all 400s or fabricate missing thinking/signatures. / 不透明错误
92 清楚说明上游未提供原因;不把全部 400 改成自动重生成,不伪造证明。
93 - The service owner should preserve structured errors and retry headers on
94 failure paths. The audited gateway keeps only content-type/cache-control from
95 upstream headers on this path; locally generated quota errors have a separate
96 path. No upstream issue/comment was posted. / 应由服务端保留错误和重试提示;
97 本次没有代用户向上游提交 issue 或评论。
98 - Keep the recommended DeepSeek Chat route, while respecting explicit custom
99 Messages/Responses selections. Provide a deliberate recovery-from-valid-history
100 action if automatic classification is impossible, preserving completed results.
101 / 保留推荐的 Chat 默认路由,自定义协议不静默切换;无法自动判断时,可提供
102 明确的有效历史恢复入口,保留已完成结果,不重放未知写入。
103
104 ## 3. Search succeeded but structured sources were absent / 搜索成功但来源缺失
105
106 Two Go Responses samples completed native search and the following echo call.
107 The raw search action contained queries but no sources; the final response's
108 message annotations were empty. This is a source-availability gap, not a failed
109 search request or demonstrated parser loss. Go's DeepSeek Messages search
110 sample supplied ten structured sources.
111
112 OpenCode's [independent websearch tool](https://github.com/anomalyco/opencode/blob/bbd72fb8b0bb6de580d2041a0150016227c63ac0/packages/opencode/src/tool/websearch.ts#L65)
113 uses Exa or Parallel through a separate MCP-style call, independent of the main
114 model's inference protocol. It returns actual tool output and asks for the
115 search permission. It does not establish that native Responses must supply
116 `action.sources`. / OpenCode 通过独立搜索服务提供工具结果,主模型用哪种协议
117 与搜索后端解耦;不能据此声称原生 Responses 一定能返回来源。
118
119 Recommended change / 建议:
120
121 - Reuse Reasonix's existing independent `web_search` owner. Keep the main model,
122 protocol and thinking settings unchanged. / 复用已实现的独立搜索,不再建平行系统。
123 - Distinguish search execution, raw item replay, and structured source availability
124 in tests and presentation. Missing sources are not a transport retry signal.
125 / 分开验证搜索执行、原始 item 回放与来源可用性;缺来源不触发网络重试。
126 - Use the configured source-capable search route. Any fallback requires an
127 already configured/authorized route and a finite auxiliary budget; do not send
128 a vendor credential to another service. Never infer verified sources from
129 generated prose. / 使用已配置且能提供来源的后端;后备搜索共享辅助预算,
130 不跨供应商发送密钥,也不把模型生成的 URL 当作已验证来源。
131
132 ## 4. Protocol-specific compatibility and retry ownership / 分协议兼容与重试归属
133
134 OpenCode [normalizes interleaved Chat reasoning, including empty values](https://github.com/anomalyco/opencode/blob/bbd72fb8b0bb6de580d2041a0150016227c63ac0/packages/opencode/src/provider/transform.ts#L322).
135 Its [Anthropic normalization preserves signed empty blocks](https://github.com/anomalyco/opencode/blob/bbd72fb8b0bb6de580d2041a0150016227c63ac0/packages/opencode/src/provider/transform.ts#L168).
136 These transformations should not be copied as a universal empty-reasoning rule.
137 Reasonix should retain its protocol contracts: Chat empty-field compatibility;
138 actual unsigned thinking for DeepSeek Messages; original proofs for native
139 Claude; complete raw items for Responses. / 不应跨协议照搬补空值。此前实现的
140 能力判定与原始回放资料仍应保留。
141
142 OpenCode [disables SDK retries by default and repairs malformed tool calls at the tool boundary](https://github.com/anomalyco/opencode/blob/bbd72fb8b0bb6de580d2041a0150016227c63ac0/packages/opencode/src/session/llm.ts#L296).
143 The pinned [session retry policy](https://github.com/anomalyco/opencode/blob/bbd72fb8b0bb6de580d2041a0150016227c63ac0/packages/opencode/src/session/retry.ts#L26)
144 uses five retries, exponential delay and jitter. Reasonix already has centralized
145 request ownership; retain its agreed Pi-style three fast retries and explicitly
146 selected main-session waiting semantics. Do not silently replace them with this
147 OpenCode version's constants. / 借鉴重试归属与错误分类,不照抄次数,也不声称
148 Reasonix 的主会话持续等待是 OpenCode 的默认行为。
149
150 ## Delivery and next priority / 交付与下一步优先级
151
152 Already implemented during testing: correct Go client/session headers across
153 all three adapters and quota-aware errors that distinguish allowance exhaustion
154 from invalid credentials. Root/desktop suites, lint and focused race tests passed.
155 This analysis introduces no silent model/protocol switch or new global retry.
156
157 本轮已经落地三协议请求头与额度分类修复。剩余优先级:验证行动提示的真实任务
158 收益;补齐不透明上游错误的诊断/明确恢复入口;完善搜索来源可用性状态。
159 所有动作继续复用当前恢复预算、工具持久化和独立搜索实现。
160
161 See [live results and limitations](MULTIPROVIDER_VALIDATION.md). / 具体样本、
162 未通过场景及验证边界见实测报告,不能宣布 #9808 的任意端点场景已完全解决。
163
163 lines MARKDOWN