Skip to content

feat: add reasoning and service_tier params to Codex provider#365

Merged
ymkiux merged 5 commits intomainfrom
feat/codex-reasoning-service-tier
Mar 11, 2026
Merged

feat: add reasoning and service_tier params to Codex provider#365
ymkiux merged 5 commits intomainfrom
feat/codex-reasoning-service-tier

Conversation

@Bowl42
Copy link
Collaborator

@Bowl42 Bowl42 commented Mar 9, 2026

Summary

  • 为 Codex 请求增加 reasoning(推理强度)和 service_tier(服务等级)参数支持
  • Provider 配置中可强制覆盖这两个参数,对所有经过该 Provider 的请求生效
  • 支持 baseURL 自定义上游地址(方便测试及私有部署)

后端

  • CodexRequest / OpenAIRequest 增加 ServiceTier 字段
  • codex↔openai 转换层透传 service_tier
  • codex→claude 转换层透传 reasoning.effortoutput_config.effort
  • ProviderConfigCodex 增加 BaseURLReasoningServiceTier 配置项
  • codex adapter 和 cliproxyapi_codex adapter 在发送上游请求前应用 Provider 级覆盖

前端

  • Provider 编辑页增加推理强度和服务等级下拉选择器
  • 选项:跟随请求(默认)/ Low / Medium / High(reasoning);Auto / Default / Flex / Priority(service_tier)
  • 中英文 i18n 翻译

service_tier 可选值

说明
auto / default 标准处理
flex 低优先级,更便宜(约半价),延迟不保证
priority 高优先级,更低延迟,价格约 2x 标准价

Test plan

  • Go 单元测试通过(go test ./internal/converter/... ./internal/adapter/...
  • E2E 测试 5 个场景全部通过:
    1. Provider 配置覆盖(high/priority)→ 客户端传 low/flex → 上游收到 high/priority
    2. Provider 配置覆盖(low/flex)→ 客户端传 high/priority → 上游收到 low/flex
    3. Provider 无覆盖 → 客户端传 medium/auto → 上游收到 medium/auto(透传)
    4. 运行时动态更新 Provider 配置 → 立即生效
    5. 客户端完全不传 reasoning/service_tier → Provider 覆盖仍然注入

🤖 Generated with Claude Code

Summary by CodeRabbit

发布说明

  • 新功能

    • Codex 提供者支持在配置中覆盖推理努力级别与服务层级,并可指定自定义 Codex API 基础 URL;请求会相应反映流式/非流式与覆盖设置。
    • API 请求/响应结构扩展以传递 service_tier 字段,相关转换链路已同步。
  • Bug 修复

    • 简化并修复管理路由的鉴权判定,避免未定义用户导致的跳转错误。
  • 测试

    • 添加端到端 Playwright 测试,验证提供者覆盖行为与动态更新。
  • 本地化

    • 增加中/英文界面文案用于推理与服务层级选项。

Add support for `reasoning` (effort) and `service_tier` parameters in
Codex requests, with provider-level overrides that force these values
for all requests routed through a given provider.

- Add `ServiceTier` field to CodexRequest and OpenAIRequest types
- Forward `service_tier` through codex↔openai converters
- Forward `reasoning.effort` to Claude `output_config` in codex→claude
- Add `BaseURL`, `Reasoning`, `ServiceTier` to ProviderConfigCodex
- Apply provider overrides in both codex and cliproxyapi_codex adapters
- Add dropdown selects in provider UI (reasoning / service_tier)
- Add E2E test with mock Codex server (5 scenarios)

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
@coderabbitai
Copy link

coderabbitai bot commented Mar 9, 2026

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: d518ddb8-cae1-48ab-8ba3-d38f7f7470b5

📥 Commits

Reviewing files that changed from the base of the PR and between ef6e5f5 and 094ffb8.

📒 Files selected for processing (1)
  • web/src/components/auth/admin-route.tsx
🚧 Files skipped from review as they are similar to previous changes (1)
  • web/src/components/auth/admin-route.tsx
📜 Recent review details
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (1)
  • GitHub Check: playwright

📝 Walkthrough

Walkthrough

为 Codex 提供商新增 BaseURL、Reasoning、ServiceTier 配置并在后端适配器中应用这些覆盖;转换器传播新字段;前端新增配置界面与本地化;添加 Playwright E2E 测试覆盖覆盖生效、透传与动态更新场景。

Changes

Cohort / File(s) Summary
域模型与类型定义
internal/domain/model.go, internal/converter/types_codex.go, internal/converter/types_openai.go, web/src/lib/transport/types.ts
为 ProviderConfigCodex 与请求类型新增字段 BaseURL/Reasoning/ServiceTier(含 JSON/TS 类型)。
Codex 适配器与 CLI 代理适配器
internal/adapter/provider/codex/adapter.go, internal/adapter/provider/cliproxyapi_codex/adapter.go
在构建并转发上游请求前应用 provider 配置覆盖(自定义 BaseURL、覆盖 reasoning.effort 与 service_tier),注入 stream 标志并调整上游 URL 构造与 header 使用。
转换器
internal/converter/codex_to_claude.go, internal/converter/codex_to_openai.go, internal/converter/openai_to_codex.go
在协议间转换时传播 Reasoning/ServiceTier(将 reasoning.effort 映射到目标请求,并携带 service_tier;回显 include service_tier)。
前端 UI 与国际化
web/src/pages/providers/components/codex-provider-view.tsx, web/src/locales/en.json, web/src/locales/zh.json, web/src/components/auth/admin-route.tsx
在 Codex 提供商配置页新增 Reasoning 与 ServiceTier 控件与持久化逻辑;添加对应翻译键;简化 admin-route 的鉴权重定向判断。
E2E 测试
tests/e2e/playwright/test-codex-reasoning-servicetier.mjs, tests/e2e/playwright/package.json
新增 Playwright 测试脚本与 npm 脚本,包含 mock Codex 服务和 5 个场景,验证覆盖、透传与动态 provider 更新。

Sequence Diagram(s)

sequenceDiagram
    participant Client
    participant Proxy as "API 代理"
    participant Adapter as "Codex 适配器"
    participant Converter as "转换器"
    participant CodexAPI as "Codex 上游"

    Client->>Proxy: 发送 /v1/responses 请求
    Proxy->>Adapter: 路由到 Codex 适配器
    Adapter->>Adapter: 读取 ProviderConfigCodex (BaseURL, Reasoning, ServiceTier)
    Adapter->>Converter: 传入请求与 provider 覆盖
    Converter->>Converter: 注入 reasoning.effort / service_tier / stream
    Converter->>Adapter: 返回转换后的上游请求体
    Adapter->>CodexAPI: 使用自定义或默认 BaseURL 转发请求
    CodexAPI-->>Adapter: 返回响应
    Adapter-->>Proxy: 返回代理处理后的响应
    Proxy-->>Client: 返回最终响应
Loading

Estimated code review effort

🎯 4 (Complex) | ⏱️ ~60 minutes

Possibly related PRs

Suggested reviewers

  • SurviveM
  • awsl233777

Poem

🐰 洞里跳出新配置,BaseURL 与分级齐。
理性高低随提供,服务优先按需移。
前后端携手跑测试,五关验证码农醉。

🚥 Pre-merge checks | ✅ 2 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 42.86% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (2 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed 标题准确地总结了PR的主要变更:为Codex提供商添加reasoning和service_tier参数支持。

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

✨ Finishing Touches
  • 📝 Generate docstrings (stacked PR)
  • 📝 Generate docstrings (commit on current branch)
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Post copyable unit tests in a comment
  • Commit unit tests in branch feat/codex-reasoning-service-tier

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.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 1

🧹 Nitpick comments (3)
tests/e2e/playwright/package.json (1)

6-7: 建议添加 headed 模式脚本以保持一致性。

其他测试(passkey、project-filter、stats-chart)都有对应的 :headed 脚本,建议为新增的测试也添加一个,方便调试时可视化运行。

♻️ 建议的修改
     "test:codex-overrides": "node test-codex-reasoning-servicetier.mjs",
+    "test:codex-overrides:headed": "HEADED=1 node test-codex-reasoning-servicetier.mjs",
     "test:passkey": "node test-passkey-discoverable.mjs",
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@tests/e2e/playwright/package.json` around lines 6 - 7, Add a headed-mode
script for the new codex test to match the other tests: create a new npm script
(e.g., named similar to "test:codex-overrides:headed") that runs the same test
file test-codex-reasoning-servicetier.mjs but in headed mode (non-headless) so
it can be visualized during debugging; ensure the new script mirrors the
behavior of the existing headed variants for the other tests and is adjacent to
the "test:codex-overrides" script in package.json.
web/src/pages/providers/components/codex-provider-view.tsx (1)

664-669: 建议:选项文本应使用 i18n。

下拉选项的显示文本(如 "Low"、"Medium"、"High"、"Auto"、"Default"、"Flex"、"Priority")目前是硬编码的英文,建议使用 i18n 以保持与应用其他部分的一致性。

♻️ 建议的修改示例

en.json 中添加:

"reasoningLow": "Low",
"reasoningMedium": "Medium",
"reasoningHigh": "High",
"serviceTierAuto": "Auto",
"serviceTierDefault": "Default",
"serviceTierFlex": "Flex",
"serviceTierPriority": "Priority"

然后在组件中使用:

-<option value="low">Low</option>
+<option value="low">{t('providers.codex.reasoningLow')}</option>

Also applies to: 687-692

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@web/src/pages/providers/components/codex-provider-view.tsx` around lines 664
- 669, Replace hard-coded English option labels in the Codex provider select
elements with i18n lookups: use the component's translation function t(...)
instead of "Low", "Medium", "High", "Auto", "Default", "Flex", "Priority".
Update the option elements in codex-provider-view.tsx (the select that currently
renders <option value="">{t('providers.codex.followRequest')}</option> and the
other option literals) to call t with keys like 'reasoningLow',
'reasoningMedium', 'reasoningHigh', 'serviceTierAuto', 'serviceTierDefault',
'serviceTierFlex', and 'serviceTierPriority'; add those keys to the locale files
(e.g., en.json) as suggested. Ensure you change the other similar select block
referenced around the second location (lines ~687-692) as well so all option
texts use t(...) consistently.
tests/e2e/playwright/test-codex-reasoning-servicetier.mjs (1)

502-507: 建议:测试结束后清理创建的 provider 和 route。

当前测试只禁用了 route 但未删除创建的 provider 和 route。多次运行测试会累积测试数据。建议在测试结束前清理资源。

♻️ 建议的清理逻辑
// 在 process.exit 前添加清理逻辑
console.log('\n--- Cleanup: Deleting test providers and routes ---');
const providerIds = [provider1.id, provider2.id, provider3.id, provider5.id];
const routeIds = [route1.id, route2.id, route3.id, route5.id];

for (const id of routeIds) {
  try {
    await adminAPI('DELETE', `/routes/${id}`, null, jwt);
  } catch {}
}
for (const id of providerIds) {
  try {
    await adminAPI('DELETE', `/providers/${id}`, null, jwt);
  } catch {}
}
console.log('✅ Cleanup completed');
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@tests/e2e/playwright/test-codex-reasoning-servicetier.mjs` around lines 502 -
507, Tests disable route5 but do not remove created providers/routes, causing
test data to accumulate; before calling mockServer.close() and
process.exit(exitCode) add cleanup that calls adminAPI('DELETE',
`/routes/${id}`, ...) for each of route1, route2, route3, route5 and
adminAPI('DELETE', `/providers/${id}`, ...) for each of provider1, provider2,
provider3, provider5, wrapping each call in try/catch to ignore failures, log
start/completion of cleanup, and await all deletions prior to mockServer.close()
and process.exit to ensure resources are removed after the test.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@internal/converter/openai_to_codex.go`:
- Around line 39-41: The code currently uses gjson.GetBytes(rawJSON,
"service_tier") and only checks v.Exists() before calling sjson.Set(out,
"service_tier", v.Value()), which will write an empty string; change the guard
to also skip setting when v.Value() is the empty string (or v.Str == "") so that
no "service_tier" key is emitted for empty values, matching the reverse
converter's semantics; update the conditional around gjson.GetBytes(...,
"service_tier")/sjson.Set(...) to require existence and non-empty value before
calling sjson.Set.

---

Nitpick comments:
In `@tests/e2e/playwright/package.json`:
- Around line 6-7: Add a headed-mode script for the new codex test to match the
other tests: create a new npm script (e.g., named similar to
"test:codex-overrides:headed") that runs the same test file
test-codex-reasoning-servicetier.mjs but in headed mode (non-headless) so it can
be visualized during debugging; ensure the new script mirrors the behavior of
the existing headed variants for the other tests and is adjacent to the
"test:codex-overrides" script in package.json.

In `@tests/e2e/playwright/test-codex-reasoning-servicetier.mjs`:
- Around line 502-507: Tests disable route5 but do not remove created
providers/routes, causing test data to accumulate; before calling
mockServer.close() and process.exit(exitCode) add cleanup that calls
adminAPI('DELETE', `/routes/${id}`, ...) for each of route1, route2, route3,
route5 and adminAPI('DELETE', `/providers/${id}`, ...) for each of provider1,
provider2, provider3, provider5, wrapping each call in try/catch to ignore
failures, log start/completion of cleanup, and await all deletions prior to
mockServer.close() and process.exit to ensure resources are removed after the
test.

In `@web/src/pages/providers/components/codex-provider-view.tsx`:
- Around line 664-669: Replace hard-coded English option labels in the Codex
provider select elements with i18n lookups: use the component's translation
function t(...) instead of "Low", "Medium", "High", "Auto", "Default", "Flex",
"Priority". Update the option elements in codex-provider-view.tsx (the select
that currently renders <option
value="">{t('providers.codex.followRequest')}</option> and the other option
literals) to call t with keys like 'reasoningLow', 'reasoningMedium',
'reasoningHigh', 'serviceTierAuto', 'serviceTierDefault', 'serviceTierFlex', and
'serviceTierPriority'; add those keys to the locale files (e.g., en.json) as
suggested. Ensure you change the other similar select block referenced around
the second location (lines ~687-692) as well so all option texts use t(...)
consistently.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: f8f5ad3a-a7b6-44bf-b6d1-e09391628314

📥 Commits

Reviewing files that changed from the base of the PR and between 6cd6fd6 and f406192.

📒 Files selected for processing (15)
  • internal/adapter/provider/cliproxyapi_codex/adapter.go
  • internal/adapter/provider/codex/adapter.go
  • internal/converter/codex_to_claude.go
  • internal/converter/codex_to_openai.go
  • internal/converter/openai_to_codex.go
  • internal/converter/types_codex.go
  • internal/converter/types_openai.go
  • internal/domain/model.go
  • tests/e2e/playwright/package.json
  • tests/e2e/playwright/test-codex-reasoning-servicetier.mjs
  • web/src/components/auth/admin-route.tsx
  • web/src/lib/transport/types.ts
  • web/src/locales/en.json
  • web/src/locales/zh.json
  • web/src/pages/providers/components/codex-provider-view.tsx
📜 Review details
🔇 Additional comments (16)
web/src/components/auth/admin-route.tsx (1)

22-22: 这处空值保护改得对。

Line 22 和前面的加载守卫配合后,既消除了 user 为空时的访问风险,也不会放宽管理员路由的限制。

internal/adapter/provider/cliproxyapi_codex/adapter.go (1)

216-227: 覆盖时机放得合适。

Line 216 起直接改写 requestBody,后面的 PayloadOriginalRequest 和事件日志都会看到同一份上游请求体,行为是一致的。

internal/converter/codex_to_claude.go (1)

39-44: 这段映射是合理的。

只在请求显式带了 reasoning.effort 时创建 output_config,避免了无意义字段写入。

internal/converter/codex_to_openai.go (1)

54-56: service_tier 的透传实现很干净。

这里只在非空时写入,和其它可选字段的处理方式保持了一致。

internal/converter/types_openai.go (1)

12-12: 字段定义没问题。

json:"service_tier,omitempty" 和现有请求模型风格一致,不会影响未设置场景的序列化结果。

internal/converter/types_codex.go (1)

16-16: 这里的请求类型扩展是正确的。

新字段直接落在 CodexRequest 上,后续各转换层透传会更自然。

internal/converter/openai_to_codex.go (1)

907-907: service_tier 纳入请求回显是有帮助的。

这能让 OpenAI→Codex 转换后的响应在调试时保留更多上下文字段。

web/src/locales/zh.json (1)

277-282: 这组中文文案补得完整。

标签、说明和“跟随请求”选项都齐了,能覆盖新增下拉框的主要展示场景。

internal/domain/model.go (1)

151-161: LGTM!

新增的三个字段(BaseURLReasoningServiceTier)定义清晰,JSON 标签与现有字段风格一致,注释也完整说明了可选值。

web/src/lib/transport/types.ts (1)

70-72: LGTM!

TypeScript 类型定义与 Go 后端 ProviderConfigCodex 结构体保持同步,字段命名和注释都符合规范。

web/src/locales/en.json (1)

277-282: LGTM!

新增的翻译键命名规范,描述清晰地解释了覆盖行为,与 UI 组件中的使用方式匹配。

internal/adapter/provider/codex/adapter.go (2)

124-135: LGTM!

Provider 级别覆盖的实现正确:

  • 使用传入的 provider 参数而非 a.provider,支持动态更新后的配置立即生效
  • 空字符串时不覆盖,保留客户端原始值
  • reasoning.effort 使用嵌套路径设置,与 Codex API 规范一致

138-146: LGTM!

BaseURL 处理逻辑正确:使用 strings.TrimRight 去除尾部斜杠,确保拼接路径时不会产生双斜杠问题。

web/src/pages/providers/components/codex-provider-view.tsx (2)

360-374: LGTM!

状态初始化和同步逻辑遵循现有模式,与 useCLIProxyAPIdisableErrorCooldown 的实现保持一致。


423-467: LGTM!

变更处理函数使用乐观更新模式,失败时正确回滚状态。空值转换为 undefined 确保配置字段被正确移除。

tests/e2e/playwright/test-codex-reasoning-servicetier.mjs (1)

1-19: 测试覆盖全面!

测试脚本覆盖了 5 个关键场景:

  1. 覆盖为 high/priority
  2. 覆盖为 low/flex
  3. 无覆盖(透传)
  4. 动态更新 provider 配置
  5. 客户端省略字段时 provider 注入

使用 mock 服务器捕获请求 body 的方式很好地验证了覆盖行为。

- Guard against empty service_tier in openai_to_codex converter
- Add headed mode script for codex test
- Use i18n for dropdown option labels
- Add cleanup of test providers/routes after E2E tests

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
@ymkiux
Copy link
Contributor

ymkiux commented Mar 9, 2026

@coderabbitai review

@coderabbitai
Copy link

coderabbitai bot commented Mar 9, 2026

✅ Actions performed

Review triggered.

Note: CodeRabbit is an incremental review system and does not re-review already reviewed commits. This command is applicable only when automatic reviews are paused.

Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

🧹 Nitpick comments (3)
web/src/pages/providers/components/codex-provider-view.tsx (1)

423-467: 处理函数实现正确,但存在代码重复。

handleChangeReasoninghandleChangeServiceTier 逻辑几乎相同,仅字段名不同。当前实现可以正常工作,但如果后续需要添加更多类似的配置项,可以考虑抽取一个通用的更新函数。

♻️ 可选:抽取通用处理函数
const handleChangeCodexConfig = async <K extends keyof ProviderConfigCodex>(
  key: K,
  value: string,
  setState: React.Dispatch<React.SetStateAction<string>>,
) => {
  if (!config) return;
  const prev = config[key] ?? '';
  setState(value);
  try {
    await updateProvider.mutateAsync({
      id: provider.id,
      data: {
        ...provider,
        config: {
          ...provider.config,
          codex: {
            ...config,
            [key]: value || undefined,
          },
        },
      },
    });
  } catch {
    setState(prev);
  }
};
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@web/src/pages/providers/components/codex-provider-view.tsx` around lines 423
- 467, The two handlers handleChangeReasoning and handleChangeServiceTier
duplicate the same optimistic-update + rollback pattern; extract a generic
updater (e.g., handleChangeCodexConfig) that accepts the codex key (like
"reasoning" | "serviceTier"), the new value, and the state setter, then perform
the same early-return on missing config, capture prev value, setState(value),
call updateProvider.mutateAsync with provider.id and data merging
provider.config.codex with {[key]: value || undefined}, and on catch restore the
prev via the provided setter; replace both specific handlers to call this
generic function to remove duplication.
tests/e2e/playwright/test-codex-reasoning-servicetier.mjs (1)

504-514: 清理步骤遗漏了 API Token 的删除。

测试在 Line 208-215 创建了 token1Result,但清理阶段只删除了 routes 和 providers,未删除创建的 API token。这可能导致测试数据残留。

♻️ 建议补充 token 清理
   // ===== Cleanup =====
   console.log('\n--- Cleanup: Deleting test providers and routes ---');
   const routeIds = [route1.id, route2.id, route3.id, route5.id];
   const providerIds = [provider1.id, provider2.id, provider3.id, provider5.id];
   for (const id of routeIds) {
     try { await adminAPI('DELETE', `/routes/${id}`, null, jwt); } catch {}
   }
   for (const id of providerIds) {
     try { await adminAPI('DELETE', `/providers/${id}`, null, jwt); } catch {}
   }
+  // Clean up API token
+  if (token1Result?.id) {
+    try { await adminAPI('DELETE', `/api-tokens/${token1Result.id}`, null, jwt); } catch {}
+  }
   console.log('✅ Cleanup completed');
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@tests/e2e/playwright/test-codex-reasoning-servicetier.mjs` around lines 504 -
514, Cleanup misses removing the API token created earlier; after deleting
routes and providers also call adminAPI('DELETE', ...) to remove the token
created as token1Result (use its id from token1Result.id) — add a loop or single
DELETE call similar to the route/provider cleanup using the same adminAPI
function (and jwt) to delete the created API token(s) to avoid leftover test
data.
tests/e2e/playwright/package.json (1)

7-8: HEADED=1 环境变量在此测试中未被使用。

test-codex-reasoning-servicetier.mjs 是纯 Node.js HTTP 测试,不使用 Playwright 浏览器自动化。HEADED=1 环境变量不会产生任何效果。虽然不影响功能,但可能会让其他开发者产生困惑。

可以考虑移除 :headed 变体,或在测试文件中添加注释说明这是一个纯 API 测试。

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@tests/e2e/playwright/package.json` around lines 7 - 8, The package.json
includes a redundant "test:codex-overrides:headed" script that sets HEADED=1 but
the target test file test-codex-reasoning-servicetier.mjs is a pure Node HTTP
test and does not use Playwright HEADed mode; either remove the
"test:codex-overrides:headed" script from package.json to avoid confusion, or
keep it but add a clear comment at the top of
test-codex-reasoning-servicetier.mjs stating that this is a pure API/Node.js
test and the HEADED env var is ignored (reference scripts "test:codex-overrides"
and "test:codex-overrides:headed" and the file
test-codex-reasoning-servicetier.mjs to locate the change).
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Nitpick comments:
In `@tests/e2e/playwright/package.json`:
- Around line 7-8: The package.json includes a redundant
"test:codex-overrides:headed" script that sets HEADED=1 but the target test file
test-codex-reasoning-servicetier.mjs is a pure Node HTTP test and does not use
Playwright HEADed mode; either remove the "test:codex-overrides:headed" script
from package.json to avoid confusion, or keep it but add a clear comment at the
top of test-codex-reasoning-servicetier.mjs stating that this is a pure
API/Node.js test and the HEADED env var is ignored (reference scripts
"test:codex-overrides" and "test:codex-overrides:headed" and the file
test-codex-reasoning-servicetier.mjs to locate the change).

In `@tests/e2e/playwright/test-codex-reasoning-servicetier.mjs`:
- Around line 504-514: Cleanup misses removing the API token created earlier;
after deleting routes and providers also call adminAPI('DELETE', ...) to remove
the token created as token1Result (use its id from token1Result.id) — add a loop
or single DELETE call similar to the route/provider cleanup using the same
adminAPI function (and jwt) to delete the created API token(s) to avoid leftover
test data.

In `@web/src/pages/providers/components/codex-provider-view.tsx`:
- Around line 423-467: The two handlers handleChangeReasoning and
handleChangeServiceTier duplicate the same optimistic-update + rollback pattern;
extract a generic updater (e.g., handleChangeCodexConfig) that accepts the codex
key (like "reasoning" | "serviceTier"), the new value, and the state setter,
then perform the same early-return on missing config, capture prev value,
setState(value), call updateProvider.mutateAsync with provider.id and data
merging provider.config.codex with {[key]: value || undefined}, and on catch
restore the prev via the provided setter; replace both specific handlers to call
this generic function to remove duplication.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: 0c764485-34d9-45e4-b647-523428383637

📥 Commits

Reviewing files that changed from the base of the PR and between f406192 and 850d162.

📒 Files selected for processing (6)
  • internal/converter/openai_to_codex.go
  • tests/e2e/playwright/package.json
  • tests/e2e/playwright/test-codex-reasoning-servicetier.mjs
  • web/src/locales/en.json
  • web/src/locales/zh.json
  • web/src/pages/providers/components/codex-provider-view.tsx
🚧 Files skipped from review as they are similar to previous changes (1)
  • internal/converter/openai_to_codex.go
📜 Review details
🧰 Additional context used
🧠 Learnings (1)
📓 Common learnings
Learnt from: Bowl42
Repo: awsl-project/maxx PR: 187
File: internal/adapter/provider/codex/adapter.go:305-331
Timestamp: 2026-02-06T09:39:16.667Z
Learning: 在 Codex provider 的 `internal/adapter/provider/codex/adapter.go` 中,从 ID Token 提取的 PII 字段(Email, Name, Picture, AccountID, UserID 等)持久化到 provider config 是产品需求,用于前端展示账户信息。这是经过确认的设计决策,并计划在隐私文档中补充数据保留策略。
🔇 Additional comments (6)
web/src/locales/en.json (1)

277-289: LGTM!

新增的 i18n 键值结构正确,与 codex-provider-view.tsx 中使用的 t('providers.codex.reasoning') 等调用路径完全匹配。翻译文本清晰易懂。

tests/e2e/playwright/test-codex-reasoning-servicetier.mjs (1)

1-93: 测试结构设计良好。

Mock 服务器实现清晰,能够正确捕获请求并返回有效的 Codex Responses API 格式响应。测试覆盖了 5 个关键场景:高优先级覆盖、低优先级覆盖、透传、动态更新和字段注入。

tests/e2e/playwright/package.json (1)

6-6: LGTM!

测试脚本链式调用结构正确,新测试已正确集成到主测试流程中。

web/src/pages/providers/components/codex-provider-view.tsx (2)

360-374: LGTM!

状态初始化和同步逻辑遵循了文件中现有的 useCLIProxyAPIdisableErrorCooldown 模式,保持了一致性。


650-693: UI 实现清晰,与现有样式保持一致。

新增的 Reasoning 和 Service Tier 下拉选择器与现有的配置项布局风格一致,翻译键使用正确。

web/src/locales/zh.json (1)

277-289: LGTM!

中文翻译准确且自然,与 en.json 结构完全对应。术语使用与文件中现有翻译风格保持一致(如"跟随请求"、"弹性"等)。

Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (1)
web/src/components/auth/admin-route.tsx (1)

12-12: ⚠️ Potential issue | 🔴 Critical

移除未使用的 isAuthenticated 变量。

isAuthenticated 被解构但从未使用,导致 TypeScript 和 ESLint 构建失败。根据 pipeline 错误日志,这是一个阻塞性问题。

🐛 建议修复
-  const { authEnabled, user, isLoading, isAuthenticated } = useAuth();
+  const { authEnabled, user, isLoading } = useAuth();
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@web/src/components/auth/admin-route.tsx` at line 12, 在 admin-route.tsx 中的
const { authEnabled, user, isLoading, isAuthenticated } = useAuth(); 解構包含未使用的
isAuthenticated,請刪除該屬性以修復 TypeScript/ESLint 錯誤:將解構改為 const { authEnabled, user,
isLoading } = useAuth();(確認沒有其他地方引用 isAuthenticated,若需要其語義請改為使用
useAuth().isAuthenticated 明確引用),修改後執行一次 lint/build 驗證變更。
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Outside diff comments:
In `@web/src/components/auth/admin-route.tsx`:
- Line 12: 在 admin-route.tsx 中的 const { authEnabled, user, isLoading,
isAuthenticated } = useAuth(); 解構包含未使用的 isAuthenticated,請刪除該屬性以修復
TypeScript/ESLint 錯誤:將解構改為 const { authEnabled, user, isLoading } =
useAuth();(確認沒有其他地方引用 isAuthenticated,若需要其語義請改為使用 useAuth().isAuthenticated
明確引用),修改後執行一次 lint/build 驗證變更。

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: f61f89b4-7efb-443b-b341-794d10cebb11

📥 Commits

Reviewing files that changed from the base of the PR and between 850d162 and ef6e5f5.

📒 Files selected for processing (4)
  • web/src/components/auth/admin-route.tsx
  • web/src/lib/transport/types.ts
  • web/src/locales/en.json
  • web/src/locales/zh.json
🚧 Files skipped from review as they are similar to previous changes (2)
  • web/src/lib/transport/types.ts
  • web/src/locales/en.json
📜 Review details
🧰 Additional context used
🪛 GitHub Actions: E2E Playwright Tests
web/src/components/auth/admin-route.tsx

[error] 12-12: TS6133: 'isAuthenticated' is declared but its value is never read. (During build: tsc -b && vite build)

🪛 GitHub Actions: Lint
web/src/components/auth/admin-route.tsx

[error] 12-12: ESLint: 'isAuthenticated' is assigned a value but never used. (no-unused-vars)

🔇 Additional comments (2)
web/src/components/auth/admin-route.tsx (1)

22-24: 逻辑简化看起来合理。

简化后的守卫条件 authEnabled && user?.role !== 'admin' 是正确的:

  • authEnabled=false 时,根据 auth-context.tsx 的逻辑,用户会被自动设置为 role: 'admin',因此条件不会触发重定向。
  • authEnabled=true 时,只有 admin 角色才能访问受保护的路由。

修复上方的未使用变量问题后即可正常工作。

web/src/locales/zh.json (1)

278-290: 翻译新增内容正确。

新增的 Codex 相关翻译 key 与 PR 目标一致,翻译质量良好:

  • reasoning → "推理强度" ✓
  • serviceTier → "服务等级" ✓
  • followRequest → "跟随请求" ✓
  • serviceTierFlex → "弹性" 准确传达了 flex 层级的"灵活/低优先级"语义

JSON 结构和逗号处理正确。

Removed isAuthenticated from AdminRoute component.
@ymkiux ymkiux merged commit 5460bf2 into main Mar 11, 2026
4 checks passed
@ymkiux ymkiux deleted the feat/codex-reasoning-service-tier branch March 11, 2026 00:48
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