Skip to content

Fix/nullable schema and stream finish reason - #4859

Closed
jo-marshall wants to merge 17 commits into
QuantumNous:mainfrom
xmz-ai:fix/nullable-schema-and-stream-finish-reason
Closed

Fix/nullable schema and stream finish reason#4859
jo-marshall wants to merge 17 commits into
QuantumNous:mainfrom
xmz-ai:fix/nullable-schema-and-stream-finish-reason

Conversation

@jo-marshall

@jo-marshall jo-marshall commented May 14, 2026

Copy link
Copy Markdown

⚠️ 提交说明 / PR Notice

Important

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

📝 变更描述 / Description

(简述:做了什么?为什么这样改能生效?请基于你对代码逻辑的理解来写,避免粘贴未经整理的内容)

🚀 变更类型 / Type of change

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

🔗 关联任务 / Related Issue

  • Closes # (如有)

✅ 提交前检查项 / Checklist

  • 人工确认: 我已亲自整理并撰写此描述,没有直接粘贴未经处理的 AI 输出。
  • 非重复提交: 我已搜索现有的 IssuesPRs,确认不是重复提交。
  • Bug fix 说明: 若此 PR 标记为 Bug fix,我已提交或关联对应 Issue,且不会将设计取舍、预期不一致或理解偏差直接归类为 bug。
  • 变更理解: 我已理解这些更改的工作原理及可能影响。
  • 范围聚焦: 本 PR 未包含任何与当前任务无关的代码改动。
  • 本地验证: 已在本地运行并通过测试或手动验证,维护者可以据此复核结果。
  • 安全合规: 代码中无敏感凭据,且符合项目代码规范。

📸 运行证明 / Proof of Work

(请在此粘贴截图、关键日志或测试报告,以证明变更生效)

Summary by CodeRabbit

Release Notes

New Features

  • Added coin-based billing option for quota purchases
  • Added "Force Streaming" setting for channel configurations
  • Added model filtering by tag
  • Token creation response now includes the API key

Chores

  • Rebranded platform name from "New API" to "Agentrix API"
  • Updated service port from 3000 to 3006
  • Added automated deployment workflow
  • Simplified UI navigation and pricing display

Tests

  • Added test coverage for streaming scenarios

Review Change Stack

VeryGoodUser1 and others added 17 commits May 7, 2026 15:29
- Add BILLING_MODE=coin|internal env-var routing
- CoinFundingSource implements FundingSource using coin SDK debit/refund
- GetSubscription/GetUsage return coin balance when BILLING_MODE=coin
- Parse out_user_id from token name (agentrix-{user-id}-{key})
- Balance check uses USD units in error message

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
…late error messages to English

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Replace favicon and logo with Agentrix branding, hide home link from
navigation bar, and remove billing type column and token group filter
from the model pricing page.

Co-Authored-By: Claude Opus 4 <noreply@anthropic.com>
@coderabbitai

coderabbitai Bot commented May 14, 2026

Copy link
Copy Markdown
Contributor

Caution

Review failed

The pull request is closed.

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: fbd40e99-4475-46c5-b380-85c4cfd0c419

📥 Commits

Reviewing files that changed from the base of the PR and between 18282e6 and 306d8fb.

⛔ Files ignored due to path filters (7)
  • go.sum is excluded by !**/*.sum
  • web/classic/bun.lock is excluded by !**/*.lock
  • web/classic/public/favicon.ico is excluded by !**/*.ico
  • web/classic/public/logo.png is excluded by !**/*.png
  • web/default/bun.lock is excluded by !**/*.lock
  • web/default/public/favicon.ico is excluded by !**/*.ico
  • web/default/public/logo.png is excluded by !**/*.png
📒 Files selected for processing (46)
  • .github/workflows/deploy.yml
  • .gitignore
  • CLAUDE.md
  • Dockerfile
  • common/billing_mode.go
  • common/coin_client.go
  • common/constants.go
  • controller/billing.go
  • controller/model.go
  • controller/token.go
  • dto/channel_settings.go
  • electron/main.js
  • go.mod
  • model/ability.go
  • relay/channel/cloudflare/adaptor.go
  • relay/channel/codex/adaptor.go
  • relay/channel/openai/adaptor.go
  • relay/channel/openai/chat_via_responses.go
  • relay/channel/openai/chat_via_responses_test.go
  • relay/channel/openai/relay_responses.go
  • relay/channel/xai/adaptor.go
  • relay/chat_completions_via_responses.go
  • relay/common/relay_info.go
  • relay/responses_handler.go
  • service/billing_session.go
  • service/coin_balance.go
  • service/coin_billing.go
  • service/convert.go
  • service/openaicompat/chat_to_responses.go
  • service/openaicompat/chat_to_responses_test.go
  • start.sh
  • web/classic/index.html
  • web/classic/package.json
  • web/classic/src/components/layout/Footer.jsx
  • web/classic/src/components/layout/headerbar/HeaderLogo.jsx
  • web/classic/src/components/layout/headerbar/UserArea.jsx
  • web/classic/src/components/table/channels/modals/EditChannelModal.jsx
  • web/classic/src/components/table/model-pricing/layout/PricingSidebar.jsx
  • web/classic/src/components/table/model-pricing/view/table/PricingTableColumns.jsx
  • web/classic/src/helpers/utils.jsx
  • web/classic/src/hooks/common/useNavigation.js
  • web/classic/src/i18n/locales/en.json
  • web/classic/src/i18n/locales/zh-CN.json
  • web/classic/src/index.jsx
  • web/classic/src/pages/Home/index.jsx
  • web/classic/vite.config.js

Walkthrough

Multi-phase platform upgrade rebranding the system to Agentrix API, introducing coin-based billing mode with quota conversion, adding channel-level force-streaming control, implementing tool parameter schema normalization for chat-to-responses conversion, simplifying frontend UI, and deploying infrastructure automation.

Changes

Agentrix Rebranding

Layer / File(s) Summary
Core system name and constants
common/constants.go, Dockerfile
SystemName constant and Docker EXPOSE port updated from "New API"→"Agentrix API" and 3000→3006.
Web frontend branding
web/classic/index.html, web/classic/src/components/layout/headerbar/HeaderLogo.jsx, web/classic/src/helpers/utils.jsx, web/classic/src/components/layout/Footer.jsx
HTML title, component text, helper function fallback, and footer/header text updated to "Agentrix API".
Electron app title
electron/main.js
Electron BrowserWindow title changed to "Agentrix API".
Port configuration updates
web/classic/package.json, web/classic/vite.config.js
Dev server proxy and Vite config updated from localhost:3000 to localhost:3006; Vite dev port set to 5171.

Coin-Based Billing System

Layer / File(s) Summary
Billing mode constants and SDK
common/billing_mode.go, go.mod
New BillingModeCoin and BillingModeInternal constants with GetBillingMode() helper; added github.com/xmz-ai/coin/sdk/go/coin v0.2.2 dependency.
Coin SDK client singleton
common/coin_client.go
Thread-safe lazy-initialized GetCoinClient() reading environment variables for service configuration.
Coin balance and quota conversion
service/coin_balance.go
GetCoinBalance() fetches user balance from coin service and converts to quota units; maps 404 (user not found) to zero balance.
Coin funding source lifecycle
service/coin_billing.go
CoinFundingSource struct managing pre-consume debit, settle/refund operations with trade reference tracking and refundable limits; ParseOutUserIDFromTokenName() helper extracts user ID from token name.
Billing session coin integration
service/billing_session.go
NewBillingSession() routes to coin-based path when BILLING_MODE=coin: parses user ID, validates balance, initializes CoinFundingSource, and pre-consumes quota.
Billing API coin-mode endpoints
controller/billing.go
GetSubscription() and GetUsage() detect coin billing mode, returning fixed OpenAI-compatible responses and short-circuiting existing quota logic.

Force Upstream Streaming Feature

Layer / File(s) Summary
Channel settings DTO extension
dto/channel_settings.go
Added ForceStream boolean field to enable force-streaming control via JSON configuration.
RelayInfo field and propagation
relay/common/relay_info.go
Added ForceUpstreamStream field to RelayInfo; set during InitChannelMeta() when channel ForceStream is enabled and request is not already streaming.
Adaptor routing logic
relay/channel/openai/adaptor.go, relay/channel/cloudflare/adaptor.go, relay/channel/codex/adaptor.go, relay/channel/xai/adaptor.go
Updated DoResponse() across all adaptors to check ForceUpstreamStream and route to stream-aggregate handler; Codex also updated SetupRequestHeader() to compute streaming via IsStream || ForceUpstreamStream.
Responses request streaming override
relay/responses_handler.go
Conditionally set request.Stream = true when ForceUpstreamStream enabled to propagate forced streaming to upstream.

Chat-to-Responses Stream Aggregation and Tool Schema

Layer / File(s) Summary
Responses SSE aggregation handler
relay/channel/openai/relay_responses.go
Implemented OaiResponsesStreamAggregateHandler and helper aggregateResponsesFromSSE() to buffer SSE events, extract outputs, compute usage, and return single JSON response with tool call counting.
Chat-to-responses aggregation
relay/channel/openai/chat_via_responses.go
New OaiResponsesToChatStreamAggregateHandler aggregates Responses SSE into chat-completion format, computes missing usage, marshals in relay format, returns single JSON.
Chat streaming tool-call improvements
relay/channel/openai/chat_via_responses.go
Adjusted OaiResponsesToChatStreamHandler to emit tool-call deltas regardless of output text state; changed finish-reason tool_calls selection to depend on sawToolCall alone.
Chat-completions-via-Responses flow
relay/chat_completions_via_responses.go
Captures client stream intent separately, forces upstream streaming when needed, checks HTTP status before headers, routes to aggregate handler when forced-streaming without client streaming, computes final IsStream from both signals.
Tool parameter schema normalization
service/openaicompat/chat_to_responses.go
Added comprehensive helpers to convert chat tool parameters to Responses format: recursive schema normalization (null removal, type inference, required filtering, metadata merging, enum type inference) and tool-call argument rewriting to prune invalid/empty fields.
Tool schema and aggregation tests
relay/channel/openai/chat_via_responses_test.go, service/openaicompat/chat_to_responses_test.go
Test coverage for SSE-to-chat streaming (text-only and reasoning-summary flows) and tool parameter schema conversions (nullable drops, required filtering, argument value handling).
OpenAI-to-Claude response conversion
service/convert.go
Updated StreamResponseOpenAI2Claude() to defer final message-stop when usage missing from both current and cached state; updated ResponseOpenAI2Claude() to always convert tool calls and separately convert text content, removing finish-reason gating.

Frontend UI and Navigation

Layer / File(s) Summary
Footer component restructuring
web/classic/src/components/layout/Footer.jsx
Simplified footer: removed demo-mode conditional multi-column layout, replaced with compact copyright/link; updated localStorage HTML rendering with custom-footer container.
Home page Agentrix redesign
web/classic/src/pages/Home/index.jsx
New hero section with fixed AGENTRIX_BASE_URL and AGENTRIX_KEYS_URL constants; localized CTAs linking to API keys page and pricing; removed demo-mode/docs/console actions.
Navigation defaults
web/classic/src/hooks/common/useNavigation.js
Default navigation now enables only pricing while disabling home, console, docs, about.
Channel force-stream UI
web/classic/src/components/table/channels/modals/EditChannelModal.jsx
Extended channel modal with force_stream form field, state initialization, parsing from saved settings, UI switch toggle, and submission wiring.
Model pricing UI refinements
web/classic/src/components/table/model-pricing/layout/PricingSidebar.jsx, web/classic/src/components/table/model-pricing/view/table/PricingTableColumns.jsx
Removed PricingGroups and PricingQuotaTypes sidebar filters; removed quotaColumn from pricing table for cleaner model browsing.
Internationalization and console cleanup
web/classic/src/i18n/locales/en.json, web/classic/src/i18n/locales/zh-CN.json, web/classic/src/index.jsx
Added English and Chinese i18n keys for "Force Streaming" feature; removed browser console welcome message.

Infrastructure, Build, and Deployment

Layer / File(s) Summary
Docker lifecycle management
start.sh
Comprehensive shell script with strict Bash mode, Docker/env validation helpers, and CLI dispatch for container start/stop/restart/logs/status/build with volume mounting and env-file support.
GitHub Actions deployment workflow
.github/workflows/deploy.yml
Automated deployment on develop-branch pushes with commit-message skip guard, SSH remote execution of git-reset and start.sh build/restart using configured secrets and ports.
Web artifact ignore patterns
.gitignore
Updated patterns to ignore web/node_modules, web/**/node_modules, web/**/dist.
Documentation rule update
CLAUDE.md
Removed "Protected Project Information" rule; renumbered "Upstream Relay Request DTOs" guidance to Rule 5.

API Enhancements and Data Model

Layer / File(s) Summary
Token response with full key
controller/token.go
AddToken() success response now includes the newly created token's full key alongside existing success/message fields.
Model filtering by optional tag
controller/model.go, model/ability.go
ListModels() accepts optional tag query parameter; routes through tag-filtered GetGroupEnabledModelsByTag() or tag-agnostic helper based on tag presence; helper function queries abilities table for tag-based model filtering.

Estimated code review effort

🎯 4 (Complex) | ⏱️ ~60 minutes


Possibly related PRs


Suggested reviewers

  • seefs001
  • Calcium-Ion

🐰 In gardens of code, the coins do flow,
Streaming forced upstream, responses aglow!
From "New API" to Agentrix we go,
With schemas rewritten and features to show—
A hop and a skip, this PR's quite the show! 🚀

✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
⚔️ Resolve merge conflicts
  • Resolve merge conflict in branch fix/nullable-schema-and-stream-finish-reason

Warning

There were issues while running some tools. Please review the errors and either fix the tool's configuration or disable the tool if it's a critical failure.

🔧 ast-grep (0.42.2)
web/classic/src/components/table/channels/modals/EditChannelModal.jsx

Tip

💬 Introducing Slack Agent: The best way for teams to turn conversations into code.

Slack Agent is built on CodeRabbit's deep understanding of your code, so your team can collaborate across the entire SDLC without losing context.

  • Generate code and open pull requests
  • Plan features and break down work
  • Investigate incidents and troubleshoot customer tickets together
  • Automate recurring tasks and respond to alerts with triggers
  • Summarize progress and report instantly

Built for teams:

  • Shared memory across your entire org—no repeating context
  • Per-thread sandboxes to safely plan and execute work
  • Governance built-in—scoped access, auditability, and budget controls

One agent for your entire SDLC. Right inside Slack.

👉 Get started


Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

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.

3 participants