ai: openai-compatible-chat rejects reasoning delivered as an encrypted object (Iceman)

未关闭 适合新手
#61,512 2 条评论 0 个 reaction 已指派 0 人 在 GitHub 查看

维护者通常 1 天内回复

@jimmyallinai 已经在做这个了。

开始于 2026年11月3日。

评估

难度
2/5
预计耗时
1-3 小时
新手友好度
75/100
Issue 类型
缺陷
描述清晰度
描述清楚
活跃度
活跃
技术栈
typescript
领域
api, backend

调研方向

Issue 指向 packages/ai/src/protocols/openai-chat.ts,其中流式 schema 目前要求 reasoning 是字符串。首先阅读该 schema 以及对 reasoning_details 的处理;使用一个 delta.reasoning 为对象的流式 chunk 重现问题。修复完成的标准是,加密的 reasoning 结构不再中止该轮对话,且流能够完成。

由索引模型根据 Issue 内容生成。

描述

reproduced

Summary

When opencode-go/iceman-contributor-free streams encrypted reasoning, it sends choices[].delta.reasoning as a JSON object ({content, encrypted_content, summary}) instead of a string. The OpenAI-compatible Chat schema requires a string, so the whole turn fails with AI.Error.InvalidProviderOutput: Invalid opencode-go/openai-compatible-chat stream event. Plain turns succeed, which makes the failure look intermittent.

Environment

  • opencode version: 2.1.4 (npm @opencode/cli, latest channel; 2.2.5 also affected — see below)
  • OS: Windows 10.0.19045.7663 (win32 x64)
  • Terminal: TERM=xterm-256color (terminal app not reported)
  • Shell: bash (Git for Windows)
  • Install/channel: global npm install, release
  • Active plugins: none

Reproduction

  1. POST to https://opencode.ai/inference/go/openai/v1/chat/completions with model: iceman-contributor-free, stream: true, one function tool, and a prompt that triggers a tool call.

  2. The streamed chunk that carries the tool call looks like this:

    {
      "choices": [
        {
          "index": 0,
          "delta": {
            "role": "assistant",
            "content": null,
            "reasoning": {
              "content": null,
              "encrypted_content": "gAAAA...",
              "summary": null
            },
            "tool_calls": [
              { "id": "call_...", "type": "function", "function": { "name": "...", "arguments": "..." } }
            ]
          },
          "finish_reason": "tool_calls"
        }
      ],
      "object": "chat.completion.chunk"
    }
    
  3. Select the same model in the TUI and send a prompt that makes the model think before answering or calling a tool.

Expected Behavior

The parser should tolerate this shape — map encrypted_content / summary into reasoning details (as it already does for reasoning_details) or ignore unsupported fields — and the turn should complete.

Actual Behavior

The turn aborts with:

AI.Error: Invalid opencode-go/openai-compatible-chat stream event

and the session fails to drain, producing no response. Relevant log line:

timestamp=2026-11-03T22:48:55.264Z level=ERROR message="Failed to drain Session" cause="AI.Error: Invalid opencode-go/openai-compatible-chat stream event ..."

Additional Context

  • Schema in packages/ai/src/protocols/openai-chat.ts still requires a string:

    reasoning: optionalNull(Schema.String),
    

    I checked this on v2.2.5 and on dev; upgrading from 2.1.4 does not fix it.

  • Frequency: intermittent. Turns without an encrypted reasoning delta succeed; turns that stream the object fail. Same model, same session, minutes apart.

  • Workaround: switch to a different model.

  • Related (not duplicates): #40690 (tool-call stream validation), #37553 / #35283 (delta.reasoning as a string being dropped, now handled).

主要语言
TypeScript
星标
224k
派生
30k
平均合并
6 小时 12 分钟
30 天内合并 PR
445

环境准备

从这里开始

  1. 先读完整个 Issue,再读项目的贡献指南。
  2. 在 Issue 下留言说明你要接手 —— 这能避免两个人做同样的事。
  3. Fork 仓库,在一个分支上完成修改。
  4. 提交 Pull Request,并在描述里引用这个 Issue 编号。

anomalyco/opencode 的其他 Issue

查看 anomalyco/opencode 的全部 Issue

相似的 Issue

更多 TypeScript Issue

把新 issue 发到你的邮箱

精选适合新手参与的 GitHub issue 摘要。