Skip to content

fix(parser): 修复 Gemini init 事件 session_id 未提取的问题#111

Merged
cexll merged 1 commit into
stellarlinkco:masterfrom
makoMakoGo:fix/gemini-session-id-extraction
Jan 8, 2026
Merged

fix(parser): 修复 Gemini init 事件 session_id 未提取的问题#111
cexll merged 1 commit into
stellarlinkco:masterfrom
makoMakoGo:fix/gemini-session-id-extraction

Conversation

@makoMakoGo
Copy link
Copy Markdown
Contributor

@makoMakoGo makoMakoGo commented Jan 8, 2026

问题描述

使用 codeagent-wrapper --backend gemini 调用 Gemini CLI 后,未输出 SESSION_ID,导致无法使用 resume 功能延续会话。

说明(环境有限):

仅本人Windows11使用遇到此问题,且修复完成后只在本机Windows环境测试通过

根因分析

Gemini CLI 的 session_id 出现在 init 事件中:

{"type":"init","timestamp":"...","session_id":"0e05a575-4e72-4315-b3a2-15a57457226d","model":"auto-gemini-3"}

parser.go:174isGemini 判定条件只检查 role/delta/status 字段:

isGemini := event.Role != "" || event.Delta != nil || event.Status != ""

导致 init 事件被当作 "Unknown event" 忽略(parser.go:282),session_id 无法提取。

Claude 后端正常是因为其 session_id 出现在 type=="result" 事件中,有专门的处理逻辑。

修复方案

isGemini 条件中增加对 init 事件的识别:

isGemini := (event.Type == "init" && event.SessionID != "") || event.Role != "" || event.Delta != nil || event.Status != ""

改动文件

  • codeagent-wrapper/parser.go:174 - 修复 isGemini 判定条件
  • codeagent-wrapper/main_test.go - 新增 TestBackendParseJSONStream_GeminiInitEventSessionID 单测

手动测试记录

Gemini 后端(修复目标)

# 第一次调用
$ ./codeagent-wrapper.exe --backend gemini - <<< "定义 count = 2.5,输出当前值"
count = 2.5
---
SESSION_ID: 7eb9dfa9-7bf2-45dd-9929-8d53c54d347a  ✅ 修复后正常输出

# Resume 调用
$ ./codeagent-wrapper.exe --backend gemini resume 7eb9dfa9-7bf2-45dd-9929-8d53c54d347a - <<< "把 count 加 1.1,输出新值"
3.6
---
SESSION_ID: 7eb9dfa9-7bf2-45dd-9929-8d53c54d347a  ✅ 会话延续正常 (2.5 + 1.1 = 3.6)

Codex 后端(回归测试)

# 第一次调用
$ ./codeagent-wrapper.exe --backend codex - <<< "定义 count = 0,输出当前值"
count = 0
---
SESSION_ID: 019b9c1e-a3b0-75c2-9d1a-1c5c59e8d564  ✅

# Resume 调用
$ ./codeagent-wrapper.exe --backend codex resume 019b9c1e-a3b0-75c2-9d1a-1c5c59e8d564 - <<< "把 count 加 1,输出新值"
count = 1
---
SESSION_ID: 019b9c1e-a3b0-75c2-9d1a-1c5c59e8d564  ✅ 会话延续正常

Claude 后端(回归测试)

# 第一次调用
$ ./codeagent-wrapper.exe --backend claude - <<< "定义 count = 0,输出当前值"
count=0
0
---
SESSION_ID: 1f868900-4028-492a-a409-e54ae9d4a822  ✅

# Resume 调用
$ ./codeagent-wrapper.exe --backend claude resume 1f868900-4028-492a-a409-e54ae9d4a822 - <<< "把 count 加 1,输出新值"
count=1
1
---
SESSION_ID: 1f868900-4028-492a-a409-e54ae9d4a822  ✅ 会话延续正常

单元测试

$ go test -v ./codeagent-wrapper/... -run TestBackendParseJSONStream_Gemini
=== RUN   TestBackendParseJSONStream_GeminiEvents
--- PASS: TestBackendParseJSONStream_GeminiEvents (0.00s)
=== RUN   TestBackendParseJSONStream_GeminiInitEventSessionID
--- PASS: TestBackendParseJSONStream_GeminiInitEventSessionID (0.00s)
=== RUN   TestBackendParseJSONStream_GeminiEvents_DeltaFalseStillDetected
--- PASS: TestBackendParseJSONStream_GeminiEvents_DeltaFalseStillDetected (0.00s)
=== RUN   TestBackendParseJSONStream_GeminiEvents_OnMessageTriggeredOnStatus
--- PASS: TestBackendParseJSONStream_GeminiEvents_OnMessageTriggeredOnStatus (0.00s)
PASS

🤖 Generated with Claude Code

Gemini CLI 的 session_id 出现在 init 事件中,但 parser 的 isGemini
判定条件只检查 role/delta/status 字段,导致 init 事件被当作
"Unknown event" 忽略,session_id 无法提取。

修复方案:在 isGemini 条件中增加对 init 事件的识别。

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
@makoMakoGo
Copy link
Copy Markdown
Contributor Author

makoMakoGo commented Jan 8, 2026

这个问题,是昨天遇到windows 下 codex后端无法识别 完成 并退出 时 一块发现的,用 cc +dev +codeagent(cc+codex)修的,然后单独让codex review 了 一遍,不懂具体代码,尽力了只能说

@makoMakoGo
Copy link
Copy Markdown
Contributor Author

makoMakoGo commented Jan 8, 2026

Auto generated by Codex

总体:LGTM。这个修复是必要且合理的:Gemini stream-json 的 session_id 出现在 init 事件里,而旧的 isGemini 只看 role/delta/status,导致 init 被当 Unknown 丢掉。

实现点评:

  • codeagent-wrapper/parser.go:把 (type=init && session_id!= "") 纳入 isGemini,能稳定拿到 threadID。
  • codeagent-wrapper/main_test.go:增加仅 init 的回归用例,覆盖真实失败场景。

建议/潜在改进:

  • threadID 的提取不该绑在 backend 分支里(Claude/Gemini 各写一份)。更稳妥是:统一在解析后先做一次 if threadID=="" && event.SessionID!="" { threadID=event.SessionID },减少未来又被“识别条件”坑到的概率。
  • 现在 isGemini 仍不看 content 字段;如果 gemini CLI 将来输出 message 不带 role/delta/status,只带 content,仍可能被漏掉。可视需要补一条测试/判定(注意不要误判其它 backends)。

安全/泄露检查(粗检):

  • 本 PR 没有引入对 content 或完整原始 JSON 的日志输出;Gemini 分支只记录 content_len 等元信息,所以不会把用户提示/模型回复泄到日志里(除非上层自己打印 stdout,那是另一回事)。
  • 代码路径没有新增外部命令/文件写入点;只是更早识别 init 事件,风险面很小。

格式/断行:

  • gofmt -l 对改动文件无输出;没有明显的行尾空白/换行问题。

测试说明(环境有限):

  • 本地仅在 Windows 上跑了针对性测试:go test ./codeagent-wrapper -run TestBackendParseJSONStream_Geminigo test ./codeagent-wrapper -run TestBackendParseJSONStream_OnComplete_GeminiTerminalResultStatus 通过。
  • 未在 Linux/macOS 上验证;同时该仓库 Windows 下全量 go test ./codeagent-wrapper/... 目前有多处既有失败(PATH/symlink/logger 等),因此这次只做了最小相关覆盖。

Copy link
Copy Markdown
Collaborator

@cexll cexll left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

代码审查通过 ✅

审查结论

修复方案准确,直接命中根因,代码正确性、安全性、性能均无问题。批准合并

关键发现

  • ✅ 修复逻辑正确:将 init 事件纳入 isGemini 判定,使 session_id 能在 parser.go:257 正确提取
  • ✅ 影响面窄:仅改变之前被忽略的特定事件归类
  • ✅ 对其他后端无影响:Codex/Claude 分支在前且条件互斥
  • ✅ 性能影响几乎为零
  • ✅ CI 测试通过

改进建议(非阻塞)

建议后续补充测试用例,覆盖"session_id 只在 init 出现、后续事件不含 session_id"的场景:

func TestBackendParseJSONStream_GeminiInitOnlySessionID(t *testing.T) {
    input := `{"type":"init","session_id":"gemini-xyz"}
{"type":"message","content":"Hello","role":"assistant"}
{"type":"result","status":"completed"}`
    
    _, threadID := parseJSONStream(strings.NewReader(input))
    if threadID != "gemini-xyz" {
        t.Fatalf("threadID=%q, want %q", threadID, "gemini-xyz")
    }
}

技术债务提醒

isGemini 条件持续变长,未来可考虑将 threadID 提取逻辑从后端判定中解耦。


审查工具:codeagent (codex backend)

@cexll cexll merged commit 81f298c into stellarlinkco:master Jan 8, 2026
1 check passed
@makoMakoGo makoMakoGo deleted the fix/gemini-session-id-extraction branch January 14, 2026 07:30
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants