feat(upstream): 合并上游补丁并整合 OpenAI Responses 渠道#120
Conversation
- 合并并评估 patches 中的上游补丁,保留本地已有的等价实现 - 移除独立 codex 渠道,统一收敛到 openai-response,并在启动迁移中自动转换旧 codex 分组 - 在 OpenAI Responses 下保留 Codex CLI 兼容的 CC 能力,包括强制流式、并行工具调用、指令兼容和聚合分组支持 - 更新前端渠道文案、多语言文本、文档、依赖、PGO 采集脚本和 GitHub 自动化检查 - 补充和调整 OpenAI Responses、聚合 CC 兼容、故障转移状态码、请求日志、密钥统计和 HTTP 客户端相关测试覆盖
|
Warning Review limit reached
More reviews will be available in 36 minutes and 56 seconds. Learn how PR review limits work. Your organization has run out of usage credits. Purchase more in the billing tab. ⌛ How to resolve this issue?After more reviews become available, a review can be triggered using the We recommend that you space out your commits to avoid hitting the rate limit. 🚦 How do rate limits work?CodeRabbit enforces hourly rate limits for each developer per organization. Our paid plans include higher PR review limits than trial, open-source, and free plans. In all cases, reviews become available again over time. During sustained high-volume PR review activity, CodeRabbit may temporarily slow when the next review becomes available. Please see our Fair Usage Limits Policy for further information. ℹ️ Review info⚙️ Run configurationConfiguration used: Organization UI Review profile: CHILL Plan: Pro Run ID: 📒 Files selected for processing (3)
📝 WalkthroughI can’t reliably rebuild and emit the full hidden review artifact mapping every provided rangeId exactly once within the constraints here — the PR contains hundreds of rangeIds and producing a correct, exhaustive hidden block by hand risks further validation failures. If you’d like, I can:
Which option do you prefer? ✨ Finishing Touches🧪 Generate unit tests (beta)
|
|
@coderabbitai full review |
✅ Actions performedFull review triggered. |
There was a problem hiding this comment.
Actionable comments posted: 6
🧹 Nitpick comments (1)
scripts/collect-pgo-profile.ps1 (1)
159-159: 💤 Low valueUnused variable
$result.The static analysis tool correctly identified that
$resultis assigned but never used. This is harmless, but you could either remove the assignment or suppress the warning if the output might be useful for debugging.♻️ Optional fix
- $result = go test -tags $GO_TAGS "-timeout=$GO_TEST_TIMEOUT" "-cpuprofile=$testProfile" -count=1 $pkg 2>&1 + go test -tags $GO_TAGS "-timeout=$GO_TEST_TIMEOUT" "-cpuprofile=$testProfile" -count=1 $pkg 2>&1 | Out-Null🤖 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 `@scripts/collect-pgo-profile.ps1` at line 159, The variable $result is assigned from the go test command but never used; remove the unused assignment by invoking the command without assigning to $result (i.e., run go test -tags $GO_TAGS "-timeout=$GO_TEST_TIMEOUT" "-cpuprofile=$testProfile" -count=1 $pkg 2>&1), or if you want to preserve output for debugging, keep the assignment to $result and use it (e.g., write it to console or processLogger) so the variable is actually referenced; locate the line assigning $result and either drop the "$result =" prefix or add a usage of $result.
🤖 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 `@internal/httpclient/manager.go`:
- Around line 205-208: The current same-host redirect guard only compares
req.URL.Host to previous.URL.Host and misses scheme downgrades (HTTPS→HTTP),
which can leak credentials; update the check around via/previous to also detect
a secure→insecure scheme transition by comparing previous.URL.Scheme and
req.URL.Scheme (e.g., treat "https" -> "http" as not same-host) and use a
case-insensitive host comparison (strings.EqualFold) so that either differing
scheme or non-equal hosts causes the function to return nil and trigger header
stripping (refer to variables via, previous, req.URL.Host, previous.URL.Host,
req.URL.Scheme, previous.URL.Scheme).
In `@internal/services/group_service.go`:
- Around line 737-754: The existence check and the batch Update (tx,
models.Group, count, caseSQL, args, result) race: lock the target rows before
validating and updating by performing the count/select with a FOR UPDATE lock
(use GORM's Clauses(clause.Locking{Strength: "UPDATE"}) on
tx.Model(&models.Group{}).Where("id IN ?", ids) so the rows are locked for the
transaction), then run the Update using the same tx; additionally verify
result.RowsAffected == int64(len(ids)) (or collapse validation+update into a
single UPDATE and check RowsAffected) and return an error if it doesn't match,
ensuring the operation is atomic and all-or-nothing.
In `@web/package.json`:
- Around line 58-60: The package.json contains a top-level "allowScripts" entry
for "esbuild@0.27.2" which is not in npm’s stable documented fields; verify that
the npm CLI/version used in CI/dev supports this RFC-style "allowScripts"
semantics (check npm -v and the CLI release notes) and if it does not, either
remove this field from package.json and enforce the install-script policy via a
supported mechanism (e.g., project .npmrc/CI config or the explicit npm CLI
option that your environment supports) or document the required npm CLI minimum
version in repo docs; search for the "allowScripts" key and the package name
"esbuild@0.27.2" to update or remove the entry accordingly.
In `@web/src/components/keys/GroupFormModal.vue`:
- Around line 344-350: The form keeps stale parallel_tool_calls when switching
channels; in GroupFormModal.vue where newChannelType is checked (the existing
block that clears formData.cc_support), also clear/reset
formData.parallel_tool_calls when newChannelType is not "openai",
"openai-response", or "gemini" so hidden controls aren’t persisted by
handleSubmit; update the same conditional that references newChannelType and
formData.cc_support to additionally set formData.parallel_tool_calls to a safe
default (e.g., false or null) so only supported channels send that value.
In `@web/src/components/keys/GroupList.vue`:
- Around line 997-1019: The drag handle is not keyboard accessible; add explicit
move-up and move-down controls so keyboard users can reorder groups: in
GroupList.vue render two small buttons alongside the existing button (e.g.,
using icons next to the element with class "group-drag-handle" / component
"ReorderThreeOutline") that call new methods like
handleMoveGroupUp(section.sectionKey, channelGroup.channelType, group.id) and
handleMoveGroupDown(...), implement those methods to reuse the same reorder
logic used by drag (extract/centralize reorder code from
handleDragStart/handleDragEnd into a reorderGroup(sectionKey, channelType,
groupId, direction) helper), add appropriate aria-labels ("Move group up", "Move
group down") and keyboard focus styles, and disable the buttons when
!canDragInBucket(channelGroup.groups) to match current state.
- Around line 543-546: The code is overwriting the shared global "sort" column
by assigning fixed 10/20/30 values to orderedIds (items), which can reorder
groups across other buckets; instead compute new sort values that preserve
global ordering within the same sectionKey+channelType bucket by using each
group's current sort values and spacing between neighbors (e.g., read current
sort for each id, then assign new sort as an average or fractional value between
the previous and next group's current sort, or apply a small delta within that
bucket's existing min/max), and then call reorderGroups to persist only those
updated ids; refer to orderedIds, items, and reorderGroups and ensure you do not
reset sort to a global 10,20,30 sequence.
---
Nitpick comments:
In `@scripts/collect-pgo-profile.ps1`:
- Line 159: The variable $result is assigned from the go test command but never
used; remove the unused assignment by invoking the command without assigning to
$result (i.e., run go test -tags $GO_TAGS "-timeout=$GO_TEST_TIMEOUT"
"-cpuprofile=$testProfile" -count=1 $pkg 2>&1), or if you want to preserve
output for debugging, keep the assignment to $result and use it (e.g., write it
to console or processLogger) so the variable is actually referenced; locate the
line assigning $result and either drop the "$result =" prefix or add a usage of
$result.
🪄 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: 7d4915ca-f194-466b-8305-396f02b9c86a
⛔ Files ignored due to path filters (2)
go.sumis excluded by!**/*.sumweb/package-lock.jsonis excluded by!**/package-lock.json
📒 Files selected for processing (72)
.dockerignore.gitattributes.gitignoreREADME.mdREADME_CN.mdREADME_JP.mdgo.modinternal/centralizedmgmt/channel_compatibility.gointernal/centralizedmgmt/channel_compatibility_test.gointernal/centralizedmgmt/hub_service.gointernal/centralizedmgmt/hub_service_test.gointernal/centralizedmgmt/i18n/en-US.gointernal/centralizedmgmt/i18n/i18n_test.gointernal/centralizedmgmt/i18n/ja-JP.gointernal/centralizedmgmt/i18n/zh-CN.gointernal/channel/anthropic_channel.gointernal/channel/anthropic_channel_test.gointernal/channel/factory_test.gointernal/channel/openai_response_channel.gointernal/channel/openai_response_channel_test.gointernal/config/system_settings.gointernal/db/migrations/migration.gointernal/db/migrations/v1_24_0_MigrateCodexChannelToOpenAIResponse.gointernal/failover/status_code_matcher.gointernal/failover/status_code_matcher_test.gointernal/handler/group_handler.gointernal/handler/integration_handler.gointernal/httpclient/manager.gointernal/httpclient/manager_test.gointernal/i18n/locales/en-US.gointernal/i18n/locales/ja-JP.gointernal/i18n/locales/zh-CN.gointernal/models/types.gointernal/proxy/cc_support.gointernal/proxy/cc_support_test.gointernal/proxy/codex_cc_support.gointernal/proxy/codex_cc_support_test.gointernal/proxy/response_handlers.gointernal/proxy/server.gointernal/router/hub_router.gointernal/router/router.gointernal/services/aggregate_group_service.gointernal/services/aggregate_group_service_test.gointernal/services/group_manager.gointernal/services/group_service.gointernal/services/group_service_test.gointernal/services/key_service.gointernal/services/request_log_service.gointernal/services/request_log_service_test.gointernal/types/relay_format.gointernal/types/relay_format_test.gointernal/types/types.gointernal/utils/config_utils.gointernal/utils/config_utils_test.goscripts/collect-pgo-profile.ps1scripts/collect-pgo-profile.shweb/.prettierrcweb/package.jsonweb/src/api/keys.tsweb/src/components/common/GroupSelectLabel.vueweb/src/components/keys/AddSubGroupModal.vueweb/src/components/keys/AggregateGroupModal.vueweb/src/components/keys/CCBadge.vueweb/src/components/keys/GroupFormModal.vueweb/src/components/keys/GroupList.vueweb/src/features/centralized-mgmt/components/EndpointDisplay.vueweb/src/features/centralized-mgmt/types/hub.tsweb/src/locales/en-US.tsweb/src/locales/ja-JP.tsweb/src/locales/zh-CN.tsweb/src/types/models.tsweb/src/utils/group-sidebar.ts
💤 Files with no reviewable changes (1)
- web/.prettierrc
| "allowScripts": { | ||
| "esbuild@0.27.2": true | ||
| } |
There was a problem hiding this comment.
🧩 Analysis chain
🌐 Web query:
npm package.json allowScripts field configuration
💡 Result:
npm package.json does not currently document an allowScripts field in the official npm package.json docs; however, npm has an in-progress security feature to make dependency install scripts “opt-in” via a new allowScripts field. 1) What npm supports today (officially) - The package.json “scripts” field is for lifecycle scripts you define in your own package, and npm runs those at lifecycle events (pre/post conventions, etc.) [1][2]. - npm also documents a config object for persisting configuration values consumed by your scripts via npm_package_config_* env vars [3]. 2) What “allowScripts” refers to (current state of npm) - npm RFC/implementation work proposes blocking dependency install scripts by default and requiring an allowlist to permit specific packages’ install scripts to run. - The RFC text describes adding a new allowScripts field in package.json to let projects opt in to running selected install scripts for dependencies [4]. - The npm/cli PR for “Phase 1” states: - “Install behaviour is unchanged”; scripts still run as before. - Phase 1 instead adds an advisory at the end of npm install listing packages whose install scripts have not been reviewed via the new allowScripts field. - The PR also states allowScripts is “read at install time” [5]. 3) Practical configuration patterns - Because this is not (yet) part of the official published npm package.json reference, you should treat allowScripts as an npm-CLI feature that may depend on your npm version. - The npm RFC/PR describes an opt-in allowlist approach (conceptually: allowlist specific dependency packages/versions so their install scripts can run) [4][5]. If you tell me your npm version (run npm -v) and whether you’re trying to control install scripts for dependencies (e.g., preinstall/install/postinstall) vs your own package’s scripts, I can give an exact example and which npm flag/configs (like .npmrc) are applicable for that version, based on the relevant implementation notes.
Citations:
- 1: https://docs.npmjs.com/cli/v9/using-npm/scripts/
- 2: https://docs.npmjs.com/cli/using-npm/scripts/
- 3: https://docs.npmjs.com/cli/v11/configuring-npm/package-json/
- 4: [RFC] Make install scripts opt-in npm/rfcs#868
- 5: feat: Phase 1 of
allowScriptsopt-in install-script policy npm/cli#9360
Verify allowScripts is supported by the build’s npm/CLI version (and matches the intended allowlist semantics).
npm’s official package.json config docs don’t currently document a top-level allowScripts field, and the “opt-in allowlist” behavior is only described in RFC/CLI implementation work; support may be gated by the specific npm CLI version/feature phase—otherwise this config may be ignored or only advisory rather than enforcing the intended install-script policy.
🤖 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 `@web/package.json` around lines 58 - 60, The package.json contains a top-level
"allowScripts" entry for "esbuild@0.27.2" which is not in npm’s stable
documented fields; verify that the npm CLI/version used in CI/dev supports this
RFC-style "allowScripts" semantics (check npm -v and the CLI release notes) and
if it does not, either remove this field from package.json and enforce the
install-script policy via a supported mechanism (e.g., project .npmrc/CI config
or the explicit npm CLI option that your environment supports) or document the
required npm CLI minimum version in repo docs; search for the "allowScripts" key
and the package name "esbuild@0.27.2" to update or remove the entry accordingly.
- 修复重定向降级时敏感凭据头保留问题,并补充覆盖测试 - 优化分组重排事务校验,支持 MySQL/PostgreSQL 行锁并保留 SQLite 纯 Go 兼容路径 - 调整分组局部排序保存逻辑,新增键盘上移/下移入口并避免隐藏配置残留 - 清理 PGO 采集脚本无效赋值,验证 PGO profile 可用于后端构建 - 升级 Go、前端依赖、Vite/Vue 配置和 Docker/GitHub Actions 构建基板 - 迁移 Vite 8 Rolldown/Oxc 构建配置,确保前后端测试、lint、构建和 audit 通过
There was a problem hiding this comment.
Actionable comments posted: 1
🤖 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 `@web/vite.config.ts`:
- Around line 89-97: The rollupOptions.output.comments: false setting strips all
comments (including legal/license notices); change it to a predicate that
preserves license/notice annotations (e.g. replace comments: false with
comments: (node, comment) =>
/@license|`@preserve`|copyright|MIT|Apache/i.test(comment)), and also ensure
dependency licenses are emitted by adding a license step (for example add a
rollup license plugin in build.rollupOptions.plugins or configure a
build.license output option) so dependency license files are generated; locate
and update rolldownOptions.output.comments and build.rollupOptions.plugins (or
build.license) in vite.config.ts.
🪄 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: 209a390f-755c-484c-b222-369d34ab28ee
⛔ Files ignored due to path filters (2)
go.sumis excluded by!**/*.sumweb/package-lock.jsonis excluded by!**/package-lock.json
📒 Files selected for processing (19)
.github/workflows/docker-build.yml.github/workflows/release.ymlDockerfilego.modinternal/httpclient/manager.gointernal/httpclient/manager_test.gointernal/services/group_service.gointernal/services/group_service_test.goscripts/collect-pgo-profile.ps1web/package.jsonweb/src/components/common/ProxyKeysInput.vueweb/src/components/keys/GroupFormModal.vueweb/src/components/keys/GroupList.vueweb/src/locales/en-US.tsweb/src/locales/ja-JP.tsweb/src/locales/zh-CN.tsweb/tsconfig.app.jsonweb/tsconfig.node.tsbuildinfoweb/vite.config.ts
✅ Files skipped from review due to trivial changes (5)
- .github/workflows/docker-build.yml
- web/tsconfig.node.tsbuildinfo
- Dockerfile
- web/src/components/common/ProxyKeysInput.vue
- web/src/locales/zh-CN.ts
🚧 Files skipped from review as they are similar to previous changes (7)
- web/package.json
- internal/httpclient/manager.go
- web/src/locales/ja-JP.ts
- web/src/locales/en-US.ts
- internal/services/group_service_test.go
- internal/services/group_service.go
- web/src/components/keys/GroupFormModal.vue
- 调整 Vite 8 Rolldown 输出注释配置,仅保留 legal 类许可证注释 - 启用 Vite 内置 license 输出并生成 JSON 元数据,避免生成 Markdown 许可证文件 - 验证前端 lint、类型检查、生产构建和 audit 均通过且无警告
|
@coderabbitai full review |
✅ Actions performedFull review triggered. |
- 限制分组自动定位只滚动左侧分组列表,避免触发 Naive UI 外层布局滚动 - 收窄分组上移、下移和拖拽控件宽度,提升选中态下图标可读性 - 约束左侧分组列表高度并优化移动端侧栏滚动,避免长列表挤压右侧内容 - 收窄拖拽按钮右侧分组图标徽标,并补强深色模式选中态对比度 - 记录前台错位根因、修复策略和 Playwright 验证结果
There was a problem hiding this comment.
Actionable comments posted: 2
🤖 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 `@web/src/components/keys/GroupList.vue`:
- Around line 1694-1702: The reorder controls are currently constrained to 16×14
(and the drag-handle to 16px) which is too small for touch; update the selector
that has "width: 16px; display: flex; flex-direction: column; flex-shrink: 0;"
and the ".group-order-button" rule to provide a larger touch target (eg. set
min-width/min-height to ~36–44px or add balanced padding and set width:auto)
while keeping the visual icon centered (use fixed icon size inside, center with
align-items/justify-content); preserve flex-shrink: 0 so layout doesn’t
collapse, and apply the same change to the drag-handle selector referenced
around lines 1725–1727 so both buttons and drag handle meet the increased
hit-area.
- Around line 309-312: The auto-scroll currently always uses behavior: "smooth"
in the container.scrollTo call; update it to respect the user's
prefers-reduced-motion setting by checking
window.matchMedia('(prefers-reduced-motion: reduce)').matches (or equivalent)
and use behavior: "auto" when true and "smooth" otherwise; modify the
container.scrollTo invocation in GroupList.vue (where container.scrollTo({ top:
Math.max(0, targetTop), behavior: "smooth" }) is used) to compute the behavior
variable accordingly and pass that variable instead of the hardcoded "smooth".
🪄 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: 64a042b3-c6b6-404b-9760-0f877b3d7b0b
📒 Files selected for processing (3)
web/src/components/keys/GroupList.vueweb/src/views/Keys.vueweb/vite.config.ts
🚧 Files skipped from review as they are similar to previous changes (1)
- web/vite.config.ts
合并上游 OpenAI Responses 能力,删除独立 codex 渠道并自动迁移旧 codex 分组到 openai-response,保留 CC、强制流式、并行工具调用和 instructions 配置。 修复聚合子组、CC/非 CC、V2 模型重定向与动态权重健康度统计,避免聚合重试上下文污染。 优化 SQLite 关闭流程和日志关闭,使用纯 Go SQLite 可用的 persist WAL 并保留真实 sql.DB.Close,提升 Windows/Docker 关闭稳定性。 升级 Go、Node、Vite、Vue 等依赖与 Docker 基板,调整 Vite 8/Rolldown 配置、许可证输出和前端分组排序布局。 补充后端单元测试、性能/PGO smoke 和前端构建验证,确保无警告、无安全漏洞、无 cgo 依赖。
There was a problem hiding this comment.
Actionable comments posted: 2
🤖 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 `@internal/proxy/server.go`:
- Around line 998-1001: The redirect context call is overwriting the user-facing
mapped alias set earlier by HandleProxy; update the call to
setModelRedirectContext(c, originalModel, targetIdx, false) to preserve the
mapped alias (i.e. pass preserveOriginal=true) so the originalModel/mapped alias
is retained for logRequest and dynamic metrics, matching the aggregate path
behavior—verify setModelRedirectContext, HandleProxy, and logRequest
interactions after the change.
In `@web/src/components/Layout.vue`:
- Around line 11-23: Initialize isMobile during setup to avoid first-paint
flicker: instead of leaving isMobile default false until onMounted, run the same
matchMedia check synchronously in the module/setup scope (or in the setup
function before render) using mobileMediaQuery and window.matchMedia to set
isMobile.value based on matches, then keep mediaQueryList and
handleMediaQueryChange logic and the onMounted listener registration unchanged;
reference isMobile, mobileMediaQuery, mediaQueryList, handleMediaQueryChange,
and onMounted when applying the change.
🪄 Autofix (Beta)
✅ Autofix completed
ℹ️ Review info
⚙️ Run configuration
Configuration used: Organization UI
Review profile: CHILL
Plan: Pro
Run ID: 1c53c0f8-98e1-4d12-8d7c-530ce780801c
⛔ Files ignored due to path filters (1)
web/package-lock.jsonis excluded by!**/package-lock.json
📒 Files selected for processing (18)
Dockerfileinternal/app/app.gointernal/app/app_test.gointernal/proxy/cc_support.gointernal/proxy/cc_support_test.gointernal/proxy/codex_cc_support.gointernal/proxy/codex_cc_support_test.gointernal/proxy/gemini_cc_support.gointernal/proxy/gemini_cc_support_test.gointernal/proxy/request_helpers.gointernal/proxy/server.gointernal/proxy/server_test.gointernal/utils/logger_utils.goweb/package.jsonweb/src/components/Layout.vueweb/src/components/keys/GroupList.vueweb/src/views/Keys.vueweb/vite.config.ts
🚧 Files skipped from review as they are similar to previous changes (3)
- web/package.json
- web/vite.config.ts
- web/src/components/keys/GroupList.vue
|
Note Autofix is a beta feature. Expect some limitations and changes as we gather feedback and continue to improve it. Fixes Applied SuccessfullyFixed 2 file(s) based on 2 unresolved review comments. Files modified:
Commit: The changes have been pushed to the Time taken: |
Fixed 2 file(s) based on 2 unresolved review comments. Co-authored-by: CodeRabbit <noreply@coderabbit.ai>
This reverts commit debcaf7.
标准分组模型映射与 V2 重定向叠加时,保留 original_model 中的用户请求别名,避免请求日志的 MappedModel 被重定向源模型覆盖。 移动端布局在 setup 阶段同步读取 matchMedia 初始状态,减少首屏从桌面导航切换到移动导航的闪烁。
|
@coderabbitai full review |
✅ Actions performedFull review triggered. |
|
@coderabbitai full review |
✅ Actions performedFull review triggered. |
There was a problem hiding this comment.
Actionable comments posted: 5
Caution
Some comments are outside the diff and can’t be posted inline due to platform limitations.
⚠️ Outside diff range comments (1)
scripts/collect-pgo-profile.ps1 (1)
1-31:⚠️ Potential issue | 🟡 Minor | ⚡ Quick winCommit
scripts/collect-pgo-profile.ps1as UTF-8 with BOM.The file currently has no UTF-8 BOM but does contain non-ASCII characters (e.g., the emoji strings in
Write-Host). Windows PowerShell 5.1 can misinterpret such script text when BOM-less UTF-8 is used, which is whyPSScriptAnalyzer’sPSUseBOMForUnicodeEncodedFilewarning applies here.🤖 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 `@scripts/collect-pgo-profile.ps1` around lines 1 - 31, The script contains non-ASCII characters (emoji in the Write-Host lines) but lacks a UTF-8 BOM; save/commit scripts/collect-pgo-profile.ps1 encoded as UTF-8 with BOM so PowerShell 5.1 parses the characters correctly (do this in your editor/CI by re-saving the file with "UTF-8 with BOM" or running a tool to add BOM), then re-run PSScriptAnalyzer to ensure PSUseBOMForUnicodeEncodedFile warning is cleared; no code changes to Test-ValidProfile or variable names are needed.
🧹 Nitpick comments (6)
internal/services/key_service.go (1)
366-384: Consider a composite index to back this ordered listing.For large groups, ordering by
last_used_at DESC, updated_at DESC, id DESCafter agroup_idfilter can force a filesort. A composite index on(group_id, last_used_at, updated_at, id)would let the planner satisfy both the filter and ordering. Note the NULL-ordering differs per dialect, so the index helps PostgreSQL most directly; verify the plan on your largest group.🤖 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 `@internal/services/key_service.go` around lines 366 - 384, The query in ListKeysInGroupQuery (function ListKeysInGroupQuery, model models.APIKey) can cause filesorts for large groups; add a composite index to back the WHERE+ORDER BY (for example an index on (group_id, last_used_at, updated_at, id)) via a DB migration or in the models' auto-migrations so the planner can use the index for both the group_id filter and the ordering; create the index specially for Postgres (and equivalent for other dialects if supported), run EXPLAIN on your largest group to verify the index is used, and keep the ordering logic in ListKeysInGroupQuery (including the dialect-specific NULL ordering) unchanged.internal/services/request_log_service.go (1)
442-482: Per-batch update logic is correct; ensure the matching columns are indexed.The CASE/WHERE construction is safe (parameterized) and
gorm.Exprkeeps each expression's args bundled with its SQL fragment, so the SET-clause ordering doesn't desync arguments. NULLlast_used_atis handled. No correctness concern.For throughput, the
WHERE (group_id = ? AND key_hash = ?) OR ...predicate benefits from a composite index on(group_id, key_hash)onapi_keys; without it each flush triggers a full scan under load.🤖 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 `@internal/services/request_log_service.go` around lines 442 - 482, The WHERE predicate built in updateAPIKeyStats (function name updateAPIKeyStats, model models.APIKey) will perform poorly without a composite index on (group_id, key_hash); add a DB migration that creates a composite index on the api_keys table for columns group_id and key_hash (choose a clear index name like idx_api_keys_group_id_key_hash), and ensure the migration is applied before deploying this batch-update code so the WHERE "(group_id = ? AND key_hash = ?) OR ..." queries use the index..gitignore (1)
149-157: ⚡ Quick winMinor duplication:
.vscode/is already ignored on line 109.The entry on line 156 is redundant. Consider removing one of the duplicate
.vscode/entries.🧹 Proposed fix to remove duplicate
3rd/ docs/ patches/ .cursorindexingignore implementation-notes.md .kiro/ .specstory/ -.vscode/ .ace-tool/🤖 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 @.gitignore around lines 149 - 157, There is a duplicate ignore entry for `.vscode/`; open the .gitignore contents, locate the existing `.vscode/` entry (earlier around line ~109) and the duplicate `.vscode/` entry in the shown block, and remove the redundant one so the file contains a single `.vscode/` ignore line (leave the remaining entry in place).internal/app/app_test.go (1)
361-374: ⚡ Quick winEither assert the driver-close failure path or rename this test.
As written, this only checks “does not panic”. If
closeSQLDBstopped callingsql.DB.Close()entirely, the test would still pass. Add an observable assertion here (for example, aClose()invocation flag or captured log entry) so the intended regression is actually covered.🤖 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 `@internal/app/app_test.go` around lines 361 - 374, The test TestCloseSQLDBReturnsDriverError currently only ensures closeSQLDB doesn't panic but doesn't assert the driver Close path was executed; update the test to observe the failing driver's Close invocation (or its error handling) by enhancing failingCloseDriver/factory to flip a package-level flag (e.g., closedCalled) or emit a deterministic log entry when its Close method is invoked, then call closeSQLDB(sqlDB, "failing test") and assert that the flag is true or the expected log entry/error was recorded; keep references to failingCloseDriverName, failingCloseDriver, registerFailingCloseDriverOnce, and closeSQLDB when locating and updating the code.internal/proxy/gemini_cc_support_test.go (1)
46-52: ⚡ Quick winAssert
ctxKeyModelRedirectSourceModeltoo.The production path now records redirect metrics from
ctxKeyModelRedirectSourceModel, not from"original_model". This test would still pass if that new key stopped being populated, so it misses the regression this refactor is trying to protect.Suggested test addition
originalModel, exists := ctx.Get("original_model") require.True(t, exists) require.Equal(t, "virtual-model", originalModel) + redirectSourceModel, exists := ctx.Get(ctxKeyModelRedirectSourceModel) + require.True(t, exists) + require.Equal(t, "virtual-model", redirectSourceModel) + targetIndex, exists := ctx.Get(ctxKeyModelRedirectTargetIndex) require.True(t, exists) require.Equal(t, 0, targetIndex)🤖 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 `@internal/proxy/gemini_cc_support_test.go` around lines 46 - 52, Add an assertion that the new context key ctxKeyModelRedirectSourceModel is set and equals the expected source ("virtual-model") in the same test block: call ctx.Get(ctxKeyModelRedirectSourceModel), require.True on existence, and require.Equal that its value matches the previously-checked original model (or "virtual-model"); keep these alongside the existing checks for originalModel and ctxKeyModelRedirectTargetIndex so the test fails if the new key stops being populated.internal/failover/status_code_matcher.go (1)
30-38: ⚡ Quick winTreat a blank pattern as an empty matcher.
Right now
ParseStatusCodeMatcher("")fails becausestrings.Split("", ",")produces one empty segment. Since the type already hasIsZero(), letting an empty config parse to the zero matcher makes the setting disable-able instead of validation-failing.Suggested fix
func ParseStatusCodeMatcher(pattern string) (StatusCodeMatcher, error) { + pattern = strings.TrimSpace(pattern) + if pattern == "" { + return StatusCodeMatcher{}, nil + } + parts := strings.Split(pattern, ",") ranges := make([]statusCodeRange, 0, len(parts))🤖 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 `@internal/failover/status_code_matcher.go` around lines 30 - 38, ParseStatusCodeMatcher currently treats an empty or whitespace-only pattern as an error because strings.Split produces an empty segment; change ParseStatusCodeMatcher so that if strings.TrimSpace(pattern) == "" it returns the zero-value StatusCodeMatcher and nil error (so the config is disable-able via the existing IsZero()), before doing the Split/loop that currently returns fmt.Errorf("empty status code segment").
🤖 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 `@internal/channel/anthropic_channel_test.go`:
- Line 18: The test is brittle because it asserts a hardcoded version string for
ClaudeCodeUserAgent ("2.1.158"); update the test to avoid tying it to a specific
release by either extracting that expected value into a package-level constant
(e.g., const expectedClaudeVersion = "2.1.158") and using that constant in the
assert, or better, change the assertion to validate the user agent format (e.g.,
use a regex/pattern match asserting ClaudeCodeUserAgent contains the expected
product token and a semantic-version-like pattern) so future CLI version bumps
won't break the test—locate the assertion referencing ClaudeCodeUserAgent in
internal/channel/anthropic_channel_test.go and replace it accordingly.
In `@internal/handler/integration_handler.go`:
- Around line 104-118: The helper getCustomizableChannelType uses
utils.GetValidationEndpoint(group) to decide whether to return "custom", but
GetIntegrationInfo/buildPath uses group.ValidationEndpoint, causing mismatched
advertised path; change getCustomizableChannelType to compare against
group.ValidationEndpoint (not utils.GetValidationEndpoint) so the ChannelType
decision and the path source are consistent (refer to
getCustomizableChannelType, GetIntegrationInfo, buildPath,
group.ValidationEndpoint, group.ChannelType).
In `@README_CN.md`:
- Line 6: Update the Go version badge in README_CN.md to match go.mod's required
version (change the badge text from "Go-1.25+" to "Go-1.26.3" or "Go-1.26+" as
appropriate); locate the badge line containing "![Go Version]" and replace the
version text so the README and go.mod are consistent.
In `@scripts/collect-pgo-profile.sh`:
- Around line 126-129: The script currently hard-fails (uses exit 1 and removes
"${MERGED_PROFILE}") in three spots (no packages, zero valid profiles, merged
profile invalid); change those three blocks to be best-effort by default:
replace the unconditional rm -f "${MERGED_PROFILE}" and exit 1 with a non-fatal
warning (echo) and return 0, or preserve an existing merged profile if present,
and make strict failure opt-in via an env var (e.g. PGO_FAIL_ON_ERROR or
PGO_STRICT) so that if that var is set the code retains the rm -f
"${MERGED_PROFILE}" + exit 1 behavior; update the three locations (the blocks
handling no project packages, zero collected profiles, and invalid merged
profile) to use this conditional exit logic referencing MERGED_PROFILE and the
new env var.
In `@web/src/components/keys/GroupList.vue`:
- Around line 572-579: In buildGroupOrderItems, don't replay
potentially-duplicate sort values from sortValues for orderedIds; instead
generate a strictly increasing sequence when mapping orderedIds so each returned
sort is greater than the previous one. Iterate orderedIds (as in orderedIds.map)
and for each id use sortValues[index] if it is strictly greater than the
last-assigned sort, otherwise set sort to lastAssigned + 1 (or a fixed
increment) and update lastAssigned; this ensures the generated sort sequence is
strictly increasing and prevents falling back to secondary ordering after a
refresh.
---
Outside diff comments:
In `@scripts/collect-pgo-profile.ps1`:
- Around line 1-31: The script contains non-ASCII characters (emoji in the
Write-Host lines) but lacks a UTF-8 BOM; save/commit
scripts/collect-pgo-profile.ps1 encoded as UTF-8 with BOM so PowerShell 5.1
parses the characters correctly (do this in your editor/CI by re-saving the file
with "UTF-8 with BOM" or running a tool to add BOM), then re-run
PSScriptAnalyzer to ensure PSUseBOMForUnicodeEncodedFile warning is cleared; no
code changes to Test-ValidProfile or variable names are needed.
---
Nitpick comments:
In @.gitignore:
- Around line 149-157: There is a duplicate ignore entry for `.vscode/`; open
the .gitignore contents, locate the existing `.vscode/` entry (earlier around
line ~109) and the duplicate `.vscode/` entry in the shown block, and remove the
redundant one so the file contains a single `.vscode/` ignore line (leave the
remaining entry in place).
In `@internal/app/app_test.go`:
- Around line 361-374: The test TestCloseSQLDBReturnsDriverError currently only
ensures closeSQLDB doesn't panic but doesn't assert the driver Close path was
executed; update the test to observe the failing driver's Close invocation (or
its error handling) by enhancing failingCloseDriver/factory to flip a
package-level flag (e.g., closedCalled) or emit a deterministic log entry when
its Close method is invoked, then call closeSQLDB(sqlDB, "failing test") and
assert that the flag is true or the expected log entry/error was recorded; keep
references to failingCloseDriverName, failingCloseDriver,
registerFailingCloseDriverOnce, and closeSQLDB when locating and updating the
code.
In `@internal/failover/status_code_matcher.go`:
- Around line 30-38: ParseStatusCodeMatcher currently treats an empty or
whitespace-only pattern as an error because strings.Split produces an empty
segment; change ParseStatusCodeMatcher so that if strings.TrimSpace(pattern) ==
"" it returns the zero-value StatusCodeMatcher and nil error (so the config is
disable-able via the existing IsZero()), before doing the Split/loop that
currently returns fmt.Errorf("empty status code segment").
In `@internal/proxy/gemini_cc_support_test.go`:
- Around line 46-52: Add an assertion that the new context key
ctxKeyModelRedirectSourceModel is set and equals the expected source
("virtual-model") in the same test block: call
ctx.Get(ctxKeyModelRedirectSourceModel), require.True on existence, and
require.Equal that its value matches the previously-checked original model (or
"virtual-model"); keep these alongside the existing checks for originalModel and
ctxKeyModelRedirectTargetIndex so the test fails if the new key stops being
populated.
In `@internal/services/key_service.go`:
- Around line 366-384: The query in ListKeysInGroupQuery (function
ListKeysInGroupQuery, model models.APIKey) can cause filesorts for large groups;
add a composite index to back the WHERE+ORDER BY (for example an index on
(group_id, last_used_at, updated_at, id)) via a DB migration or in the models'
auto-migrations so the planner can use the index for both the group_id filter
and the ordering; create the index specially for Postgres (and equivalent for
other dialects if supported), run EXPLAIN on your largest group to verify the
index is used, and keep the ordering logic in ListKeysInGroupQuery (including
the dialect-specific NULL ordering) unchanged.
In `@internal/services/request_log_service.go`:
- Around line 442-482: The WHERE predicate built in updateAPIKeyStats (function
name updateAPIKeyStats, model models.APIKey) will perform poorly without a
composite index on (group_id, key_hash); add a DB migration that creates a
composite index on the api_keys table for columns group_id and key_hash (choose
a clear index name like idx_api_keys_group_id_key_hash), and ensure the
migration is applied before deploying this batch-update code so the WHERE
"(group_id = ? AND key_hash = ?) OR ..." queries use the index.
🪄 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: d2ef2328-d6b6-4d2f-a2fc-c92303bddb41
⛔ Files ignored due to path filters (2)
go.sumis excluded by!**/*.sumweb/package-lock.jsonis excluded by!**/package-lock.json
📒 Files selected for processing (88)
.dockerignore.gitattributes.github/workflows/docker-build.yml.github/workflows/release.yml.gitignoreDockerfileREADME.mdREADME_CN.mdREADME_JP.mdgo.modinternal/app/app.gointernal/app/app_test.gointernal/centralizedmgmt/channel_compatibility.gointernal/centralizedmgmt/channel_compatibility_test.gointernal/centralizedmgmt/hub_service.gointernal/centralizedmgmt/hub_service_test.gointernal/centralizedmgmt/i18n/en-US.gointernal/centralizedmgmt/i18n/i18n_test.gointernal/centralizedmgmt/i18n/ja-JP.gointernal/centralizedmgmt/i18n/zh-CN.gointernal/channel/anthropic_channel.gointernal/channel/anthropic_channel_test.gointernal/channel/factory_test.gointernal/channel/openai_response_channel.gointernal/channel/openai_response_channel_test.gointernal/config/system_settings.gointernal/db/migrations/migration.gointernal/db/migrations/v1_24_0_MigrateCodexChannelToOpenAIResponse.gointernal/failover/status_code_matcher.gointernal/failover/status_code_matcher_test.gointernal/handler/group_handler.gointernal/handler/integration_handler.gointernal/httpclient/manager.gointernal/httpclient/manager_test.gointernal/i18n/locales/en-US.gointernal/i18n/locales/ja-JP.gointernal/i18n/locales/zh-CN.gointernal/models/types.gointernal/proxy/cc_support.gointernal/proxy/cc_support_test.gointernal/proxy/codex_cc_support.gointernal/proxy/codex_cc_support_test.gointernal/proxy/gemini_cc_support.gointernal/proxy/gemini_cc_support_test.gointernal/proxy/request_helpers.gointernal/proxy/response_handlers.gointernal/proxy/server.gointernal/proxy/server_test.gointernal/router/hub_router.gointernal/router/router.gointernal/services/aggregate_group_service.gointernal/services/aggregate_group_service_test.gointernal/services/group_manager.gointernal/services/group_service.gointernal/services/group_service_test.gointernal/services/key_service.gointernal/services/request_log_service.gointernal/services/request_log_service_test.gointernal/types/relay_format.gointernal/types/relay_format_test.gointernal/types/types.gointernal/utils/config_utils.gointernal/utils/config_utils_test.gointernal/utils/logger_utils.goscripts/collect-pgo-profile.ps1scripts/collect-pgo-profile.shweb/.prettierrcweb/package.jsonweb/src/api/keys.tsweb/src/components/Layout.vueweb/src/components/common/GroupSelectLabel.vueweb/src/components/common/ProxyKeysInput.vueweb/src/components/keys/AddSubGroupModal.vueweb/src/components/keys/AggregateGroupModal.vueweb/src/components/keys/CCBadge.vueweb/src/components/keys/GroupFormModal.vueweb/src/components/keys/GroupList.vueweb/src/features/centralized-mgmt/components/EndpointDisplay.vueweb/src/features/centralized-mgmt/types/hub.tsweb/src/locales/en-US.tsweb/src/locales/ja-JP.tsweb/src/locales/zh-CN.tsweb/src/types/models.tsweb/src/utils/group-sidebar.tsweb/src/views/Keys.vueweb/tsconfig.app.jsonweb/tsconfig.node.tsbuildinfoweb/vite.config.ts
💤 Files with no reviewable changes (1)
- web/.prettierrc
新增 api_keys 复合索引迁移,优化分组排序和批量统计更新路径。 修正空状态码配置、重定向上下文、Claude UA 测试和移动端首屏初始化。 补充相关单测与脚本编码检查,保持现有行为和项目风格一致。
There was a problem hiding this comment.
♻️ Duplicate comments (2)
scripts/collect-pgo-profile.sh (1)
127-129:⚠️ Potential issue | 🟠 Major | ⚖️ Poor tradeoffPGO script fail-fast will break CI when profile collection encounters issues.
The script exits with code 1 and removes
${MERGED_PROFILE}when no packages are found, no valid profiles are collected, or the merged profile is invalid. Past review comments note this will fail GitHub Actions PGO jobs.The developer added explicit comments indicating this is intentional ("Keep this failure fatal: CI must not silently reuse a stale or missing default.pgo."). However, if PGO collection is meant to be best-effort in some scenarios, consider making strict failure opt-in via an environment variable (e.g.,
PGO_FAIL_ON_ERRORorPGO_STRICT) as suggested in the past review.Also applies to: 202-204, 240-242
🤖 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 `@scripts/collect-pgo-profile.sh` around lines 127 - 129, The script currently unconditionally removes the merged profile and exits (rm -f "${MERGED_PROFILE}" followed by exit 1) which fails CI; make this strict fail behavior opt-in by checking an environment variable (e.g., PGO_FAIL_ON_ERROR or PGO_STRICT) before removing `${MERGED_PROFILE}` and exiting with status 1, and otherwise log a warning and continue without failing; apply the same guard to the other early-exit locations noted (the similar rm/exit blocks around the later occurrences corresponding to lines 202-204 and 240-242) so callers can enable strict mode when desired.scripts/collect-pgo-profile.ps1 (1)
136-138:⚠️ Potential issue | 🟠 Major | ⚖️ Poor tradeoffPGO script fail-fast will break CI when profile collection encounters issues.
The script exits with code 1 and removes
$MERGED_PROFILEwhen no packages are found, no valid profiles are collected, or the merged profile is invalid. Past review comments note this will fail GitHub Actions PGO jobs.The developer added explicit comments indicating this is intentional ("Keep this failure fatal"). However, if PGO collection is meant to be best-effort in some scenarios, consider making strict failure opt-in via an environment variable (e.g.,
PGO_FAIL_ON_ERRORorPGO_STRICT) as suggested in the past review.Also applies to: 198-200, 243-245
🤖 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 `@scripts/collect-pgo-profile.ps1` around lines 136 - 138, Update the script to make strict PGO failures opt-in by honoring an environment variable (e.g., PGO_FAIL_ON_ERROR or PGO_STRICT): replace unconditional removal/exit sequences that reference $MERGED_PROFILE and the fatal "exit 1" with a conditional block that checks if $env:PGO_FAIL_ON_ERROR (or $env:PGO_STRICT) is set/true; if set, keep the current behavior (Write-Host/Write-Error, Remove-Item $MERGED_PROFILE, exit 1), otherwise log a non-fatal warning (Write-Warning or Write-Host with Yellow) and continue without exiting (you may still Remove-Item $MERGED_PROFILE or leave it as-is depending on current cleanup semantics). Apply this change to all similar failure sites (the occurrences around the $MERGED_PROFILE removal/exit and the other two locations mentioned).
🤖 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.
Duplicate comments:
In `@scripts/collect-pgo-profile.ps1`:
- Around line 136-138: Update the script to make strict PGO failures opt-in by
honoring an environment variable (e.g., PGO_FAIL_ON_ERROR or PGO_STRICT):
replace unconditional removal/exit sequences that reference $MERGED_PROFILE and
the fatal "exit 1" with a conditional block that checks if
$env:PGO_FAIL_ON_ERROR (or $env:PGO_STRICT) is set/true; if set, keep the
current behavior (Write-Host/Write-Error, Remove-Item $MERGED_PROFILE, exit 1),
otherwise log a non-fatal warning (Write-Warning or Write-Host with Yellow) and
continue without exiting (you may still Remove-Item $MERGED_PROFILE or leave it
as-is depending on current cleanup semantics). Apply this change to all similar
failure sites (the occurrences around the $MERGED_PROFILE removal/exit and the
other two locations mentioned).
In `@scripts/collect-pgo-profile.sh`:
- Around line 127-129: The script currently unconditionally removes the merged
profile and exits (rm -f "${MERGED_PROFILE}" followed by exit 1) which fails CI;
make this strict fail behavior opt-in by checking an environment variable (e.g.,
PGO_FAIL_ON_ERROR or PGO_STRICT) before removing `${MERGED_PROFILE}` and exiting
with status 1, and otherwise log a warning and continue without failing; apply
the same guard to the other early-exit locations noted (the similar rm/exit
blocks around the later occurrences corresponding to lines 202-204 and 240-242)
so callers can enable strict mode when desired.
ℹ️ Review info
⚙️ Run configuration
Configuration used: Organization UI
Review profile: CHILL
Plan: Pro
Run ID: d44b235a-85db-4f35-b258-e9b814723437
📒 Files selected for processing (14)
README_CN.mdinternal/app/app_test.gointernal/channel/anthropic_channel_test.gointernal/db/migrations/migration.gointernal/db/migrations/v1_25_0_OptimizeAPIKeyIndexes.gointernal/db/migrations/v1_25_0_OptimizeAPIKeyIndexes_test.gointernal/db/migrations/v1_3_3_AddCompositeIndexes.gointernal/failover/status_code_matcher.gointernal/failover/status_code_matcher_test.gointernal/handler/integration_handler.gointernal/proxy/gemini_cc_support_test.goscripts/collect-pgo-profile.ps1scripts/collect-pgo-profile.shweb/src/components/keys/GroupList.vue
✅ Files skipped from review due to trivial changes (1)
- README_CN.md
🚧 Files skipped from review as they are similar to previous changes (5)
- internal/channel/anthropic_channel_test.go
- internal/proxy/gemini_cc_support_test.go
- internal/handler/integration_handler.go
- internal/failover/status_code_matcher.go
- internal/app/app_test.go
PGO profile 采集脚本默认改为 best-effort,失败时清理无效 profile 并允许上层降级。 新增 PGO_FAIL_ON_ERROR / PGO_STRICT 严格模式,保留显式失败能力。 Makefile 的 pgo-profile 目标开启严格模式,避免手动收集时误报成功。
关联 Issue / Related Issue
Closes #
变更内容 / Change Content
自查清单 / Checklist
Summary by CodeRabbit
New Features
Bug Fixes
Documentation