Skip to content

feat(claude): support AWS Bedrock Claude count_tokens forwarding#4926

Open
B1F030 wants to merge 1 commit into
QuantumNous:mainfrom
B1F030:codex/bedrock-count-tokens
Open

feat(claude): support AWS Bedrock Claude count_tokens forwarding#4926
B1F030 wants to merge 1 commit into
QuantumNous:mainfrom
B1F030:codex/bedrock-count-tokens

Conversation

@B1F030

@B1F030 B1F030 commented May 17, 2026

Copy link
Copy Markdown

⚠️ 提交说明 / PR Notice

Important

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

📝 变更描述 / Description

新增 Anthropic 兼容的 POST /v1/messages/count_tokens 接口,当前仅面向 AWS Bedrock Claude 渠道。

Claude SDK / CLI 会在发送部分请求前调用 messages/count_tokens 获取输入 token 数。对于 AWS Bedrock Claude,Bedrock Runtime 已提供官方 CountTokens 能力,因此本 PR 不在本地估算 token,而是在现有鉴权、限速和渠道分发流程之后,将请求转发到 AWS Bedrock CountTokens

实现上新增了 Claude count tokens relay mode,并为该路由增加 AWS-only 渠道过滤,避免同一模型同时存在非 AWS 渠道时被错误分发。controller 中为该模式单独分支处理,请求成功时直接返回 Anthropic 兼容结果 {"input_tokens": <number>},不进入本地 token 估算、模型价格计算、预扣费或消费结算流程。

AWS channel 内部使用 Bedrock SDK 的 CountTokens,输入采用 InvokeModelTokensRequest,并复用现有 AWS Claude 请求转换、模型映射、cross-region model id、header override 与 param override 逻辑。非 Claude AWS 模型(例如 Nova)会被拒绝,不提供本地 fallback。

🚀 变更类型 / Type of change

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

🔗 关联任务 / Related Issue

✅ 提交前检查项 / Checklist

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

📸 运行证明 / Proof of Work

已运行以下本地检查:

$ go test ./relay/channel/aws -run 'Test.*CountTokens|TestDoAwsClientRequest' -v
=== RUN   TestDoAwsClientRequest_AppliesRuntimeHeaderOverrideToAnthropicBeta
=== PAUSE TestDoAwsClientRequest_AppliesRuntimeHeaderOverrideToAnthropicBeta
=== RUN   TestBuildAwsCountTokensInputUsesInvokeModelBody
=== PAUSE TestBuildAwsCountTokensInputUsesInvokeModelBody
=== RUN   TestBuildAwsCountTokensInputRejectsNonClaudeModel
=== PAUSE TestBuildAwsCountTokensInputRejectsNonClaudeModel
=== CONT  TestDoAwsClientRequest_AppliesRuntimeHeaderOverrideToAnthropicBeta
=== CONT  TestBuildAwsCountTokensInputRejectsNonClaudeModel
=== CONT  TestBuildAwsCountTokensInputUsesInvokeModelBody
--- PASS: TestBuildAwsCountTokensInputRejectsNonClaudeModel (0.00s)
--- PASS: TestBuildAwsCountTokensInputUsesInvokeModelBody (0.00s)
--- PASS: TestDoAwsClientRequest_AppliesRuntimeHeaderOverrideToAnthropicBeta (0.00s)
PASS
ok  	github.com/QuantumNous/new-api/relay/channel/aws	0.857s

$ go test ./middleware ./service ./model -run 'Test.*ChannelType|Test.*SatisfiedChannel' -v
=== RUN   TestLimitChannelTypesStoresAllowedTypes
--- PASS: TestLimitChannelTypesStoresAllowedTypes (0.00s)
PASS
ok  	github.com/QuantumNous/new-api/middleware	0.789s
testing: warning: no tests to run
PASS
ok  	github.com/QuantumNous/new-api/service	1.500s [no tests to run]
=== RUN   TestGetRandomSatisfiedChannelWithTypesFiltersCandidates
--- PASS: TestGetRandomSatisfiedChannelWithTypesFiltersCandidates (0.00s)
=== RUN   TestGetRandomSatisfiedChannelWithTypesReturnsNilWhenNoCandidateMatches
--- PASS: TestGetRandomSatisfiedChannelWithTypesReturnsNilWhenNoCandidateMatches (0.00s)
PASS
ok  	github.com/QuantumNous/new-api/model	1.004s

$ go test ./controller ./router -run 'Test.*CountTokens|^$'
ok  	github.com/QuantumNous/new-api/controller	0.673s [no tests to run]
?   	github.com/QuantumNous/new-api/router	[no test files]

Summary by CodeRabbit

  • New Features

    • Added a Claude token-counting HTTP endpoint for AWS Bedrock models (POST /v1/messages/count_tokens).
    • Enforced per-route channel-type restrictions during channel selection, rejecting disallowed channel types.
  • Tests

    • Added unit tests for channel-type middleware, channel selection with type filters, and AWS count-tokens behavior.
  • Localization

    • Added disallowed-channel-type error message in English, Simplified Chinese, and Traditional Chinese.

@coderabbitai

coderabbitai Bot commented May 17, 2026

Copy link
Copy Markdown
Contributor

Review Change Stack

Note

Reviews paused

It looks like this branch is under active development. To avoid overwhelming you with review comments due to an influx of new commits, CodeRabbit has automatically paused this review. You can configure this behavior by changing the reviews.auto_review.auto_pause_after_reviewed_commits setting.

Use the following commands to manage reviews:

  • @coderabbitai resume to resume automatic reviews.
  • @coderabbitai review to trigger a single review.

Use the checkboxes below for quick actions:

  • ▶️ Resume reviews
  • 🔍 Trigger review

Walkthrough

Adds a /v1/messages/count_tokens endpoint with middleware to limit allowed channel types, propagates allowed-type filtering through service/model/cache selection, implements AWS Bedrock Claude token-counting, and integrates a dedicated relay handler and route short-circuit.

Changes

Claude Token Counting with Channel Type Filtering

Layer / File(s) Summary
Relay Mode Constants and Foundation
constant/context_key.go, relay/constant/relay_mode.go, relay/constant/relay_mode_test.go
Adds ContextKeyAllowedChannelTypes, RelayModeClaudeCountTokens, and path-to-mode test for /v1/messages/count_tokens.
Channel Type Middleware and Request Context
middleware/distributor.go, middleware/channel_type_limit_test.go
Adds LimitChannelTypes middleware and test verifying the allowed types are stored in the request context; enforces allowlist during token-specific and affinity-preferred selection.
Routing, controller short-circuit, and distributor enforcement
router/relay-router.go, controller/relay.go, middleware/distributor.go
Registers POST /v1/messages/count_tokens with channel-type limiting, short-circuits Relay to relayClaudeCountTokens, and enforces allowed types in channel resolution and retry logic.
Service-layer wiring for allowed types
service/channel_select.go
Adds AllowedChannelTypes to RetryParam, implements GetAllowedChannelTypes and IsChannelTypeAllowed, and passes allowed types into channel selection calls.
Type-Aware Channel Selection at Model
model/ability.go
Implements GetChannelWithChannelTypes and internal type-constrained selection while preserving prior behavior when no types provided.
Cache-aware channel filtering and helpers
model/channel_cache.go
Adds GetRandomSatisfiedChannelWithTypes, cache filtering helpers (getCachedChannelsByTypes, isChannelTypeAllowed), and updates selection to use filtered candidates.
Channel cache tests
model/channel_cache_test.go
Adds tests validating type-filtered candidate selection and nil result when no candidate matches the allowed types.
AWS Bedrock Token Counting API
relay/channel/aws/relay-aws.go, relay/channel/aws/relay_aws_test.go
Adds CountClaudeTokens, buildAwsCountTokensInput, model-id normalization helpers, isAwsClaudeModel, and tests verifying InvokeModel body construction, non-Claude rejection, and AWS client error preservation.
Claude Count Tokens Relay Handler
relay/claude_count_tokens.go, relay/claude_handler.go
Adds ClaudeCountTokensHelper, buildClaudeCountTokensRequestBody, and refactors upstream Claude request preparation into prepareClaudeRequestForUpstream.
Localization keys
i18n/keys.go, i18n/locales/*
Adds distributor.channel_type_not_allowed i18n key and translations for en, zh-CN, zh-TW.

Sequence Diagram(s)

sequenceDiagram
  participant Client
  participant Router
  participant LimitChannelTypes
  participant Distribute
  participant Relay
  participant Service
  participant Model
  participant Cache
  participant AWSBedrock
  Client->>Router: POST /v1/messages/count_tokens
  Router->>LimitChannelTypes: apply allowed types (AWS)
  LimitChannelTypes->>Distribute: store allowed types in context
  Distribute->>Relay: call Relay (Claude format)
  Relay->>Relay: detect RelayModeClaudeCountTokens -> relayClaudeCountTokens
  Relay->>Service: CacheGetRandomSatisfiedChannel (AllowedChannelTypes)
  Service->>Cache: GetRandomSatisfiedChannelWithTypes
  Cache->>Model: GetChannelWithChannelTypes (if uncached)
  Relay->>AWSBedrock: CountClaudeTokens request (InvokeModel)
Loading

Estimated code review effort

🎯 4 (Complex) | ⏱️ ~60 minutes

Possibly related PRs

Suggested reviewers

  • Calcium-Ion
  • seefs001

Poem

🐰 I hopped through routes and filtered types,
Bedrock counted Claude's little gripes,
Middleware tucked allowed channels neat,
Tokens tallied, retries kept sweet,
Hop, relay, repeat! ✨

🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 4.88% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (4 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title 'feat(claude): support AWS Bedrock Claude count_tokens forwarding' accurately and concisely describes the main feature added—implementing count_tokens request forwarding to AWS Bedrock for Claude models.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests

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.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Actionable comments posted: 2

🧹 Nitpick comments (1)
controller/relay.go (1)

126-129: ⚡ Quick win

Count-tokens early return bypasses failure sampling.

At Line 128, this returns before the common perfmetrics.RecordRelaySample(..., false, 0) path, so /messages/count_tokens failures won’t be sampled like other relay failures.

Proposed patch
 if relayFormat == types.RelayFormatClaude && relayInfo.RelayMode == relayconstant.RelayModeClaudeCountTokens {
 	newAPIError = relayClaudeCountTokens(c, relayInfo, request)
+	if newAPIError != nil {
+		gopool.Go(func() {
+			perfmetrics.RecordRelaySample(relayInfo, false, 0)
+		})
+	}
 	return
 }
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@controller/relay.go` around lines 126 - 129, The early return for
count-tokens bypasses the common failure sampling path; after calling
relayClaudeCountTokens(...) but before returning, check if newAPIError != nil
and call perfmetrics.RecordRelaySample with the same parameters used elsewhere
(using relayInfo, relayFormat, false, 0) so failures for /messages/count_tokens
are sampled; alternatively, change relayClaudeCountTokens to return an error
state and let the existing common return path call
perfmetrics.RecordRelaySample. Ensure you reference relayClaudeCountTokens,
newAPIError, and perfmetrics.RecordRelaySample in the fix.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@middleware/distributor.go`:
- Around line 62-64: The forbidden message is hardcoded; replace the raw string
in the branch that calls abortWithOpenAiMessage after
service.IsChannelTypeAllowed(...) with a localized message via i18n.T(...). Use
a clear i18n key (e.g. "errors.channel_type_not_allowed") and pass
i18n.T("errors.channel_type_not_allowed") to abortWithOpenAiMessage so the
middleware uses the same localization system as other messages; update any
callers or tests expecting the raw string accordingly.

In `@relay/channel/aws/relay-aws.go`:
- Around line 173-177: CountClaudeTokens currently treats every error from
buildAwsCountTokensInput as a BadRequestBody/HTTP 400 with skip-retry; change
buildAwsCountTokensInput to return a typed *types.NewAPIError (rather than a
generic error) so callers can distinguish parsing/body errors (map to
ErrorCodeBadRequest + 400) from channel/server setup errors (map to
channel/internal error codes and appropriate HTTP 5xx or channel error status
without skip-retry). Update CountClaudeTokens to inspect the returned
*types.NewAPIError from buildAwsCountTokensInput and return it unchanged (or
remap its status/code) instead of always wrapping into BadRequestBody; reference
buildAwsCountTokensInput and CountClaudeTokens to locate the changes and ensure
retry flags (ErrOptionWithSkipRetry) are only applied for true client input
errors.

---

Nitpick comments:
In `@controller/relay.go`:
- Around line 126-129: The early return for count-tokens bypasses the common
failure sampling path; after calling relayClaudeCountTokens(...) but before
returning, check if newAPIError != nil and call perfmetrics.RecordRelaySample
with the same parameters used elsewhere (using relayInfo, relayFormat, false, 0)
so failures for /messages/count_tokens are sampled; alternatively, change
relayClaudeCountTokens to return an error state and let the existing common
return path call perfmetrics.RecordRelaySample. Ensure you reference
relayClaudeCountTokens, newAPIError, and perfmetrics.RecordRelaySample in the
fix.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: 31233d9a-6691-4224-ab16-7844c9097c70

📥 Commits

Reviewing files that changed from the base of the PR and between f69ceb6 and 828b9d7.

📒 Files selected for processing (15)
  • constant/context_key.go
  • controller/relay.go
  • middleware/channel_type_limit_test.go
  • middleware/distributor.go
  • model/ability.go
  • model/channel_cache.go
  • model/channel_cache_test.go
  • relay/channel/aws/relay-aws.go
  • relay/channel/aws/relay_aws_test.go
  • relay/claude_count_tokens.go
  • relay/claude_handler.go
  • relay/constant/relay_mode.go
  • relay/constant/relay_mode_test.go
  • router/relay-router.go
  • service/channel_select.go

Comment thread middleware/distributor.go
Comment thread relay/channel/aws/relay-aws.go
@B1F030 B1F030 force-pushed the codex/bedrock-count-tokens branch from 81f2c6c to 15a9519 Compare May 17, 2026 10:11

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

🧹 Nitpick comments (1)
controller/relay.go (1)

126-129: ⚡ Quick win

Preserve failure perf sampling on count_tokens short-circuit path.

This early return skips the existing failure sampling at Line 250, so Claude /count_tokens failures won’t be recorded via perfmetrics.RecordRelaySample.

📊 Suggested patch
 	if relayFormat == types.RelayFormatClaude && relayInfo.RelayMode == relayconstant.RelayModeClaudeCountTokens {
 		newAPIError = relayClaudeCountTokens(c, relayInfo, request)
+		if newAPIError != nil {
+			gopool.Go(func() {
+				perfmetrics.RecordRelaySample(relayInfo, false, 0)
+			})
+		}
 		return
 	}
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@controller/relay.go` around lines 126 - 129, The short-circuit handling for
Claude count_tokens in the relay (the if checking relayFormat ==
types.RelayFormatClaude && relayInfo.RelayMode ==
relayconstant.RelayModeClaudeCountTokens that calls relayClaudeCountTokens and
returns) bypasses the failure perf sampling at perfmetrics.RecordRelaySample;
modify the flow so that after calling relayClaudeCountTokens you still invoke
perfmetrics.RecordRelaySample on error (or propagate newAPIError without an
early return so the existing sampling path runs), ensuring newAPIError is
checked and recorded before returning.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Nitpick comments:
In `@controller/relay.go`:
- Around line 126-129: The short-circuit handling for Claude count_tokens in the
relay (the if checking relayFormat == types.RelayFormatClaude &&
relayInfo.RelayMode == relayconstant.RelayModeClaudeCountTokens that calls
relayClaudeCountTokens and returns) bypasses the failure perf sampling at
perfmetrics.RecordRelaySample; modify the flow so that after calling
relayClaudeCountTokens you still invoke perfmetrics.RecordRelaySample on error
(or propagate newAPIError without an early return so the existing sampling path
runs), ensuring newAPIError is checked and recorded before returning.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: 54c46eaf-fc26-4700-8067-2b5cabcaeb0f

📥 Commits

Reviewing files that changed from the base of the PR and between 828b9d7 and 15a9519.

📒 Files selected for processing (15)
  • constant/context_key.go
  • controller/relay.go
  • middleware/channel_type_limit_test.go
  • middleware/distributor.go
  • model/ability.go
  • model/channel_cache.go
  • model/channel_cache_test.go
  • relay/channel/aws/relay-aws.go
  • relay/channel/aws/relay_aws_test.go
  • relay/claude_count_tokens.go
  • relay/claude_handler.go
  • relay/constant/relay_mode.go
  • relay/constant/relay_mode_test.go
  • router/relay-router.go
  • service/channel_select.go
🚧 Files skipped from review as they are similar to previous changes (14)
  • constant/context_key.go
  • relay/constant/relay_mode_test.go
  • router/relay-router.go
  • middleware/channel_type_limit_test.go
  • relay/channel/aws/relay_aws_test.go
  • relay/constant/relay_mode.go
  • relay/claude_count_tokens.go
  • middleware/distributor.go
  • model/channel_cache_test.go
  • service/channel_select.go
  • model/channel_cache.go
  • relay/channel/aws/relay-aws.go
  • relay/claude_handler.go
  • model/ability.go

@B1F030 B1F030 changed the title feat: support AWS Bedrock Claude count_tokens forwarding feat(claude): support AWS Bedrock Claude count_tokens forwarding May 17, 2026
@B1F030

B1F030 commented May 17, 2026

Copy link
Copy Markdown
Author

/cc @Calcium-Ion Would you please take a look? Thanks!

@B1F030 B1F030 force-pushed the codex/bedrock-count-tokens branch from 5c55900 to 1d37ac6 Compare May 19, 2026 03:06
@B1F030

B1F030 commented May 26, 2026

Copy link
Copy Markdown
Author

/cc @seefs001 Would you please take a look? Thanks!

@B1F030 B1F030 force-pushed the codex/bedrock-count-tokens branch from 51dd734 to d11c57b Compare June 11, 2026 11:17

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

🧹 Nitpick comments (2)
middleware/distributor.go (2)

213-245: ⚡ Quick win

Localize the hardcoded error message.

Line 223 returns the raw English string "invalid JSON request body", while the rest of this middleware uses i18n.T(...) for localization (e.g., lines 46, 52, 200, 208). Please route this error through i18n for consistent client localization.

🌐 Proposed fix

Add an i18n key and use it:

 	if !gjson.ValidBytes(requestBody) {
-		return nil, errors.New("invalid JSON request body")
+		return nil, errors.New(i18n.T(c, i18n.MsgDistributorInvalidJSON))
 	}

Then define MsgDistributorInvalidJSON in your i18n keys/locales.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@middleware/distributor.go` around lines 213 - 245, getModelFromJSONBody
currently returns a hardcoded error "invalid JSON request body"; replace that
literal with a localized message by calling i18n.T with a new key (e.g.,
MsgDistributorInvalidJSON) so the function uses
i18n.T("MsgDistributorInvalidJSON") instead of the raw string; add the
MsgDistributorInvalidJSON entry to your i18n/locales and update any callers
expecting the error string if necessary.

247-255: ⚡ Quick win

Localize the error message.

Line 252 uses fmt.Errorf with a raw English string, while the rest of this middleware uses i18n.T(...) for consistency. To localize this error, you would need to pass the *gin.Context into getJSONStringValue so it can call i18n.T(c, ...).

🌐 Proposed fix

Refactor to accept context:

-func getJSONStringValue(result gjson.Result, field string) (string, error) {
+func getJSONStringValue(c *gin.Context, result gjson.Result, field string) (string, error) {
 	if !result.Exists() || result.Type == gjson.Null {
 		return "", nil
 	}
 	if result.Type != gjson.String {
-		return "", fmt.Errorf("field %s must be a string", field)
+		return "", errors.New(i18n.T(c, i18n.MsgDistributorFieldMustBeString, map[string]any{"Field": field}))
 	}
 	return result.String(), nil
 }

Update callers on lines 227 and 231 to pass c.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@middleware/distributor.go` around lines 247 - 255, Change getJSONStringValue
to accept a *gin.Context (e.g., func getJSONStringValue(c *gin.Context, result
gjson.Result, field string) (string, error)), replace the fmt.Errorf(...) call
with a localized error using i18n.T(c, "...") and update every caller of
getJSONStringValue to pass the current *gin.Context instance so the middleware
continues to compile and returns localized errors.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Nitpick comments:
In `@middleware/distributor.go`:
- Around line 213-245: getModelFromJSONBody currently returns a hardcoded error
"invalid JSON request body"; replace that literal with a localized message by
calling i18n.T with a new key (e.g., MsgDistributorInvalidJSON) so the function
uses i18n.T("MsgDistributorInvalidJSON") instead of the raw string; add the
MsgDistributorInvalidJSON entry to your i18n/locales and update any callers
expecting the error string if necessary.
- Around line 247-255: Change getJSONStringValue to accept a *gin.Context (e.g.,
func getJSONStringValue(c *gin.Context, result gjson.Result, field string)
(string, error)), replace the fmt.Errorf(...) call with a localized error using
i18n.T(c, "...") and update every caller of getJSONStringValue to pass the
current *gin.Context instance so the middleware continues to compile and returns
localized errors.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: 030fd4b3-6d29-4d96-b1a1-1ab1015b95eb

📥 Commits

Reviewing files that changed from the base of the PR and between 1d37ac6 and 51dd734.

📒 Files selected for processing (4)
  • controller/relay.go
  • middleware/distributor.go
  • model/channel_cache.go
  • relay/claude_handler.go
🚧 Files skipped from review as they are similar to previous changes (3)
  • model/channel_cache.go
  • controller/relay.go
  • relay/claude_handler.go

Signed-off-by: B1F030 <b1fzhang@gmail.com>
@B1F030 B1F030 force-pushed the codex/bedrock-count-tokens branch from a5b3e75 to 71c35a2 Compare June 15, 2026 11:33
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.

1 participant