fix relay stream handling and key query logs - #2
Merged
Conversation
There was a problem hiding this comment.
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_useliketool_useand associatinginput_json_deltaby 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": |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Important
📝 变更描述 / Description
将流式响应的语义有效性与终止帧完整性分开处理:已经产生有效内容但缺少终止事件的请求继续结算,同时在流状态中保留异常;真正空回和不完整工具参数仍按错误处理。Claude 服务端工具调用现在会按 block index 聚合
input_json_delta,避免 Web Search 和 Code Execution 在首个参数分片处被错误截断。Xuancat 密钥查询同时展示消费日志和错误日志,并显示状态及完整错误详情。
MY_CHANGES_BACKUP.md已同步记录这些保留差异。🚀 变更类型 / Type of change
🔗 关联任务 / Related Issue
✅ 提交前检查项 / Checklist
📸 运行证明 / Proof of Work