Skip to content

fix relay stream handling and key query logs - #2

Merged
mumingluan merged 1 commit into
mainfrom
codex/relay-stream-and-key-log-fixes
Aug 11, 2026
Merged

fix relay stream handling and key query logs#2
mumingluan merged 1 commit into
mainfrom
codex/relay-stream-and-key-log-fixes

Conversation

@mumingluan

Copy link
Copy Markdown
Owner

⚠️ 提交说明 / PR Notice

Important

  • 请提供人工撰写的简洁摘要,避免直接粘贴未经整理的 AI 输出。

📝 变更描述 / Description

将流式响应的语义有效性与终止帧完整性分开处理:已经产生有效内容但缺少终止事件的请求继续结算,同时在流状态中保留异常;真正空回和不完整工具参数仍按错误处理。Claude 服务端工具调用现在会按 block index 聚合 input_json_delta,避免 Web Search 和 Code Execution 在首个参数分片处被错误截断。

Xuancat 密钥查询同时展示消费日志和错误日志,并显示状态及完整错误详情。MY_CHANGES_BACKUP.md 已同步记录这些保留差异。

🚀 变更类型 / Type of change

  • 🐛 Bug 修复 (Bug fix) - 请关联对应 Issue,避免将设计取舍、理解偏差或预期不一致直接归类为 bug
  • ✨ 新功能 (New feature) - 重大特性建议先通过 Issue 沟通
  • ⚡ 性能优化 / 重构 (Refactor)
  • 📝 文档更新 (Documentation)

🔗 关联任务 / Related Issue

  • 无公开 Issue;问题由本地代理链路抓包复现。

✅ 提交前检查项 / Checklist

  • 人工确认: 我已亲自整理并撰写此描述,没有直接粘贴未经处理的 AI 输出。
  • 非重复提交: 我已搜索现有的 Issues 与 PRs,确认不是重复提交。
  • Bug fix 说明: 该修复基于可复现的 Claude SSE 服务端工具流截断问题。
  • 变更理解: 我已理解这些更改的工作原理及可能影响。
  • 范围聚焦: 本 PR 未包含部署二进制、构建产物或前端备份目录。
  • 本地验证: 已在本地运行并通过测试或手动验证,维护者可以据此复核结果。
  • 安全合规: 代码中无敏感凭据,且符合项目代码规范。

📸 运行证明 / Proof of Work

go test ./relay/...
PASS

bun test src/features/xuancat-pages/__tests__/key-query-logs.test.ts
1 pass, 0 fail

bun run typecheck
PASS

@mumingluan
mumingluan marked this pull request as ready for review August 11, 2026 03:29
Copilot AI lite review requested due to automatic review settings August 11, 2026 03:29
@mumingluan
mumingluan merged commit 0e741e6 into main Aug 11, 2026
1 check passed

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Pull request overview

This PR adjusts relay stream validation to decouple “semantic output exists” from “terminal frame received”, allowing billing/usage settlement to proceed for non-empty streams that end abnormally while still recording stream anomalies. It also updates the Xuancat key-query UI to include error logs with status + full details.

Changes:

  • Split stream validation into ValidateOutput() vs terminal checks, and update OpenAI/Responses/Claude/Gemini stream handlers to record missing-terminal as a soft stream error instead of failing the request when semantic output exists.
  • Fix Claude streamed server tool calls by treating server_tool_use like tool_use and associating input_json_delta by block index.
  • Enhance Xuancat key query logs display (include error logs, show status badge and error details), with a small shared isKeyQueryLog() helper + tests.

Reviewed changes

Copilot reviewed 14 out of 14 changed files in this pull request and generated 1 comment.

Show a summary per file
File Description
web/src/features/xuancat-pages/utils.ts Adds isKeyQueryLog() helper to centralize which log types appear in key query.
web/src/features/xuancat-pages/types.ts Extends UsageLog to include content for displaying log details.
web/src/features/xuancat-pages/components/key-query-dialog.tsx Shows success/error status and full content details; includes error logs in the list.
web/src/features/xuancat-pages/tests/key-query-logs.test.ts Regression test for key-query log type filtering (consume + error, excludes unrelated).
web/src/features/system-settings/request-limits/token-rate-limit-section.tsx Import reordering/formatting cleanup.
web/src/features/system-settings/request-limits/token-daily-rate-limit-section.tsx Import reordering/formatting cleanup.
relay/responsevalidator/validator.go Introduces ValidateOutput() and updates OpenAI/Claude/Responses stream semantics; includes server_tool_use tool tracking.
relay/responsevalidator/validator_test.go Adds tests for output-vs-terminal separation and server tool streamed arguments.
relay/channel/openai/relay-openai.go Accepts non-empty unterminated streams, records StreamStatus soft error instead of failing.
relay/channel/openai/relay_responses.go Same as above for Responses streaming.
relay/channel/openai/chat_stream_test.go End-to-end regression tests for billing semantic output without terminal and still rejecting empty streams.
relay/channel/gemini/relay-gemini.go Records missing terminal finish reason as StreamStatus error rather than failing when output exists.
relay/channel/claude/relay-claude.go Uses ValidateOutput() for semantic validation and records missing message_stop as StreamStatus error.
MY_CHANGES_BACKUP.md Updates internal change log to reflect the preserved behavioral differences.

💡 Add a code-review agent skill or configure MCP servers for context-aware, tailored reviews. Learn more in the docs.

Comment on lines 281 to 289
switch block.Type {
case "tool_use":
case "tool_use", "server_tool_use":
if strings.TrimSpace(block.Name) == "" {
return fmt.Errorf("tool_use block has no name")
return fmt.Errorf("%s block has no name", block.Type)
}
index := response.GetIndex()
s.tools[index] = &streamedToolCall{name: block.Name}
s.Output = true
case "text":
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