Repository navigation
fix(vertex): pass project_id in API Key mode to avoid 404 on official endpoints - #6330
Conversation
|
Note Reviews pausedIt 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 Use the following commands to manage reviews:
Use the checkboxes below for quick actions:
WalkthroughVertex API Key configuration now accepts an optional project ID, which is trimmed and passed into Gemini and Claude Vertex URL construction. New tests cover project-scoped URLs, streaming query suffixes, Claude routing, and legacy behavior without a project ID. ChangesVertex API Key Project ID
Estimated code review effort: 2 (Simple) | ~10 minutes 🚥 Pre-merge checks | ✅ 5
✨ Finishing Touches
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. > A bunny hops through Vertex skies, Comment |
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/classic/src/components/table/channels/modals/EditChannelModal.jsx`:
- Around line 2750-2767: Update the Form.Input for vertex_project_id in the
inputs.type === 41 and inputs.vertex_key_type === 'api_key' branch to include
form validation rules requiring a non-empty project ID. Reuse the surrounding
form’s established required-field rule format and keep the existing change
handler and display text unchanged.
🪄 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: 2ea4518a-4399-4fc7-aac9-3080fd5644e6
📒 Files selected for processing (14)
dto/channel_settings.gorelay/channel/vertex/adaptor.gorelay/channel/vertex/adaptor_api_key_url_test.goweb/classic/src/components/table/channels/modals/EditChannelModal.jsxweb/default/src/features/channels/components/drawers/channel-mutate-drawer.tsxweb/default/src/features/channels/lib/channel-form.tsweb/default/src/features/channels/types.tsweb/default/src/i18n/locales/en.jsonweb/default/src/i18n/locales/fr.jsonweb/default/src/i18n/locales/ja.jsonweb/default/src/i18n/locales/ru.jsonweb/default/src/i18n/locales/vi.jsonweb/default/src/i18n/locales/zh-TW.jsonweb/default/src/i18n/locales/zh.json
| {inputs.type === 41 && | ||
| inputs.vertex_key_type === 'api_key' && ( | ||
| <Form.Input | ||
| field='vertex_project_id' | ||
| label={t('Vertex AI 项目 ID')} | ||
| placeholder={t('例如 my-project-123')} | ||
| extraText={t( | ||
| 'API Key 模式下必填:拥有该 Vertex AI 资源的 Google Cloud 项目 ID。官方端点要求路径中包含 /projects/{project_id}/locations/{region}/...。', | ||
| )} | ||
| onChange={(value) => | ||
| handleChannelOtherSettingsChange( | ||
| 'vertex_project_id', | ||
| value, | ||
| ) | ||
| } | ||
| style={{ width: '100%' }} | ||
| /> | ||
| )} |
There was a problem hiding this comment.
🎯 Functional Correctness | 🟡 Minor | ⚡ Quick win
Add form validation rules to enforce the required project ID.
The extraText explicitly states that this field is required in API Key mode ("API Key 模式下必填"), but the Form.Input lacks a rules property to enforce this at the form level. If left empty, the submission will succeed without the ID, resulting in upstream requests failing with a 404 error.
Consider adding the rules property to ensure users provide a valid project ID before submitting.
💻 Proposed fix
<Form.Input
field='vertex_project_id'
label={t('Vertex AI 项目 ID')}
placeholder={t('例如 my-project-123')}
+ rules={[{ required: true, message: t('请输入 Vertex AI 项目 ID') }]}
extraText={t(
'API Key 模式下必填:拥有该 Vertex AI 资源的 Google Cloud 项目 ID。官方端点要求路径中包含 /projects/{project_id}/locations/{region}/...。',
)}
onChange={(value) =>📝 Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.
| {inputs.type === 41 && | |
| inputs.vertex_key_type === 'api_key' && ( | |
| <Form.Input | |
| field='vertex_project_id' | |
| label={t('Vertex AI 项目 ID')} | |
| placeholder={t('例如 my-project-123')} | |
| extraText={t( | |
| 'API Key 模式下必填:拥有该 Vertex AI 资源的 Google Cloud 项目 ID。官方端点要求路径中包含 /projects/{project_id}/locations/{region}/...。', | |
| )} | |
| onChange={(value) => | |
| handleChannelOtherSettingsChange( | |
| 'vertex_project_id', | |
| value, | |
| ) | |
| } | |
| style={{ width: '100%' }} | |
| /> | |
| )} | |
| {inputs.type === 41 && | |
| inputs.vertex_key_type === 'api_key' && ( | |
| <Form.Input | |
| field='vertex_project_id' | |
| label={t('Vertex AI 项目 ID')} | |
| placeholder={t('例如 my-project-123')} | |
| rules={[{ required: true, message: t('请输入 Vertex AI 项目 ID') }]} | |
| extraText={t( | |
| 'API Key 模式下必填:拥有该 Vertex AI 资源的 Google Cloud 项目 ID。官方端点要求路径中包含 /projects/{project_id}/locations/{region}/...', | |
| )} | |
| onChange={(value) => | |
| handleChannelOtherSettingsChange( | |
| 'vertex_project_id', | |
| value, | |
| ) | |
| } | |
| style={{ width: '100%' }} | |
| /> | |
| )} |
🤖 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/classic/src/components/table/channels/modals/EditChannelModal.jsx` around
lines 2750 - 2767, Update the Form.Input for vertex_project_id in the
inputs.type === 41 and inputs.vertex_key_type === 'api_key' branch to include
form validation rules requiring a non-empty project ID. Reuse the surrounding
form’s established required-field rule format and keep the existing change
handler and display text unchanged.
|
Self-review pass before this gets reviewed — found and fixed one issue:
One doc-level nit (not pushing a commit for it): the checklist mentions |
4b63dea to
7361790
Compare
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 `@relay/channel/vertex/adaptor_api_key_url_test.go`:
- Around line 39-41: Replace the non-fatal URL checks in
relay/channel/vertex/adaptor_api_key_url_test.go at lines 39-41, 55-56, 69-71,
and 85-87 with assert calls, while retaining require for setup and fatal
assertions; add the testify/assert import alongside the existing testify
imports.
🪄 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: d1a9c996-157d-41c4-abc5-26213c4fba7a
📒 Files selected for processing (14)
dto/channel_settings.gorelay/channel/vertex/adaptor.gorelay/channel/vertex/adaptor_api_key_url_test.goweb/classic/src/components/table/channels/modals/EditChannelModal.jsxweb/default/src/features/channels/components/drawers/channel-mutate-drawer.tsxweb/default/src/features/channels/lib/channel-form.tsweb/default/src/features/channels/types.tsweb/default/src/i18n/locales/en.jsonweb/default/src/i18n/locales/fr.jsonweb/default/src/i18n/locales/ja.jsonweb/default/src/i18n/locales/ru.jsonweb/default/src/i18n/locales/vi.jsonweb/default/src/i18n/locales/zh-TW.jsonweb/default/src/i18n/locales/zh.json
🚧 Files skipped from review as they are similar to previous changes (12)
- web/default/src/i18n/locales/zh-TW.json
- web/default/src/features/channels/types.ts
- web/default/src/i18n/locales/zh.json
- web/default/src/i18n/locales/fr.json
- web/default/src/features/channels/components/drawers/channel-mutate-drawer.tsx
- web/default/src/i18n/locales/vi.json
- web/default/src/i18n/locales/en.json
- dto/channel_settings.go
- web/default/src/i18n/locales/ru.json
- web/default/src/features/channels/lib/channel-form.ts
- relay/channel/vertex/adaptor.go
- web/classic/src/components/table/channels/modals/EditChannelModal.jsx
| require.Contains(t, url, "/projects/"+projectID+"/locations/", "URL should embed the configured project_id") | ||
| require.Contains(t, url, "/publishers/google/models/gemini-3.1-flash-image:generateContent") | ||
| require.True(t, strings.HasSuffix(url, "key="+apiKey), "URL should end with the API key query, got: %s", url) |
There was a problem hiding this comment.
📐 Maintainability & Code Quality | 🟡 Minor | ⚡ Quick win
Use assert for non-fatal checks across all tests.
As per coding guidelines, backend tests must use testify/require for setup and fatal assertions (like require.NoError) and testify/assert for non-fatal checks. Using assert allows the test to continue executing and report multiple failures, improving debuggability. Please make this replacement across the file and add the "github.com/stretchr/testify/assert" import block.
relay/channel/vertex/adaptor_api_key_url_test.go#L39-L41: replacerequirewithassertfor URL content checks.relay/channel/vertex/adaptor_api_key_url_test.go#L55-L56: replacerequirewithassertfor URL content checks.relay/channel/vertex/adaptor_api_key_url_test.go#L69-L71: replacerequirewithassertfor URL content checks.relay/channel/vertex/adaptor_api_key_url_test.go#L85-L87: replacerequirewithassertfor URL content checks.
💡 Proposed change for the anchor site
- require.Contains(t, url, "/projects/"+projectID+"/locations/", "URL should embed the configured project_id")
- require.Contains(t, url, "/publishers/google/models/gemini-3.1-flash-image:generateContent")
- require.True(t, strings.HasSuffix(url, "key="+apiKey), "URL should end with the API key query, got: %s", url)
+ assert.Contains(t, url, "/projects/"+projectID+"/locations/", "URL should embed the configured project_id")
+ assert.Contains(t, url, "/publishers/google/models/gemini-3.1-flash-image:generateContent")
+ assert.True(t, strings.HasSuffix(url, "key="+apiKey), "URL should end with the API key query, got: %s", url)📝 Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.
| require.Contains(t, url, "/projects/"+projectID+"/locations/", "URL should embed the configured project_id") | |
| require.Contains(t, url, "/publishers/google/models/gemini-3.1-flash-image:generateContent") | |
| require.True(t, strings.HasSuffix(url, "key="+apiKey), "URL should end with the API key query, got: %s", url) | |
| assert.Contains(t, url, "/projects/"+projectID+"/locations/", "URL should embed the configured project_id") | |
| assert.Contains(t, url, "/publishers/google/models/gemini-3.1-flash-image:generateContent") | |
| assert.True(t, strings.HasSuffix(url, "key="+apiKey), "URL should end with the API key query, got: %s", url) |
📍 Affects 1 file
relay/channel/vertex/adaptor_api_key_url_test.go#L39-L41(this comment)relay/channel/vertex/adaptor_api_key_url_test.go#L55-L56relay/channel/vertex/adaptor_api_key_url_test.go#L69-L71relay/channel/vertex/adaptor_api_key_url_test.go#L85-L87
🤖 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 `@relay/channel/vertex/adaptor_api_key_url_test.go` around lines 39 - 41,
Replace the non-fatal URL checks in
relay/channel/vertex/adaptor_api_key_url_test.go at lines 39-41, 55-56, 69-71,
and 85-87 with assert calls, while retaining require for setup and fatal
assertions; add the testify/assert import alongside the existing testify
imports.
Source: Coding guidelines
7361790 to
de347e2
Compare
|
Rebased onto latest main and addressed the form-validation gap:
Local verification:
|
… endpoints Closes QuantumNous#6250. Vertex AI channel in vertex_key_type=api_key mode: getRequestUrl passed an empty string as project_id to BuildGoogleModelURL / BuildAnthropicModelURL, leaving the URL without the /projects/{PROJECT_ID}/locations/{REGION}/ segment, so the official Vertex endpoints returned 404. In JSON mode project_id is parsed from the service account, so the bug is specific to api_key mode. Fix: - Add VertexProjectID to ChannelOtherSettings (used only in api_key mode; JSON mode keeps parsing from the service account, unchanged). - In adaptor.go's api_key branch, use ChannelOtherSettings.VertexProjectID instead of the hardcoded empty string. When unset, fall back to the legacy behavior so existing api_key channels are not broken. - Frontend (web/default): show a Project ID input when VertexKeyType=api_key, persist settings.vertex_project_id, and require it via superRefine so users cannot save an api_key channel that would still 404. Clear the residual field in non-api_key mode or non-Vertex channels. - Add translations across 7 locales (en/zh/zh-TW/ja/fr/ru/vi). Regression tests (relay/channel/vertex/adaptor_api_key_url_test.go) cover 4 scenarios: - api_key mode + configured project_id -> URL contains /projects/.../locations/ - api_key mode + stream suffix -> key joined with &, path contains project_id - api_key mode + Claude mode -> anthropic publisher path - api_key mode + empty project_id -> falls back to legacy behavior
de347e2 to
e900241
Compare
There was a problem hiding this comment.
Caution
Some comments are outside the diff and can’t be posted inline due to platform limitations.
⚠️ Outside diff range comments (1)
relaykit/dto/channel_settings.go (1)
23-25: 🎯 Functional Correctness | 🟡 Minor | ⚡ Quick winAlign the HTTP/1 shard documentation with validation.
The field comment says
HTTP2ConnectionShardsis ignored whenHTTPProtocolis"http1", but validation rejects any value greater than1. Either document values above one as invalid for HTTP/1, or actually ignore/normalize them; the current contract makes a documented configuration fail validation.Also applies to: 45-50
🤖 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 `@relaykit/dto/channel_settings.go` around lines 23 - 25, Align the HTTP2ConnectionShards comment with the validation behavior: document values greater than 1 as invalid when HTTPProtocol is "http1" instead of saying they are ignored. Update the field documentation near HTTP2ConnectionShards and any corresponding validation-related comment without changing validation logic.
🤖 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.
Outside diff comments:
In `@relaykit/dto/channel_settings.go`:
- Around line 23-25: Align the HTTP2ConnectionShards comment with the validation
behavior: document values greater than 1 as invalid when HTTPProtocol is "http1"
instead of saying they are ignored. Update the field documentation near
HTTP2ConnectionShards and any corresponding validation-related comment without
changing validation logic.
ℹ️ Review info
⚙️ Run configuration
Configuration used: Organization UI
Review profile: CHILL
Plan: Pro Plus
Run ID: edda6a93-4c38-4efb-bfc1-4a10e9545a53
📒 Files selected for processing (3)
relay/channel/vertex/adaptor.gorelay/channel/vertex/adaptor_api_key_url_test.gorelaykit/dto/channel_settings.go
🚧 Files skipped from review as they are similar to previous changes (1)
- relay/channel/vertex/adaptor.go
51fdfc5 to
2b6f1df
Compare
Express-mode API keys are documented without a project, so a required project ID would block saving those channels. Without one the URL keeps the express-mode form as before; with one, the URL carries the project and the deployment region, so a global region is honored. - Drop the required check and describe the field in plain words. - Treat vertex_project_id as a sensitive field, like the key format. - Assert exact request URLs in a table test, including the global case. - Cover saving, clearing and loading the project ID in the channel form.
Sync 54 upstream commit(s) via merge (fork history preserved). Behavior changes from upstream: - 4013729 fix: disable sensitive word filtering by default and clear the default word list (QuantumNous#7814) Upstream commits: - 5e95951 feat(channels): add drag mode for channel priority ordering - 5a59d69 fix(pricing): hide task prices left at zero when another price is set - 3e2ce2c fix: align model card summary with status bar hours (QuantumNous#7847) - b0a98ac fix(web): apply theme class before first paint so Dark Reader detects dark mode (QuantumNous#7571) - f92c576 fix(web): cover Cloudflare clef and NVIDIA model families in provider rules (QuantumNous#7840) - ff36846 fix(relayconvert): 保留 Chat/Claude → Responses 转换中 input_image 的 detail 字段 (QuantumNous#7855) - 09109ec fix(middleware): 过载哨兵改用容器口径并加入连续性与新鲜度判定 (QuantumNous#7317) - d032204 feat(aws): add Mantle Messages API support - ca2cae6 fix(relaykit): emit summary on reasoning items announced without one (QuantumNous#7833) - 45fbb14 fix(rate-limit): count each group with its own limit separately - 6549a17 fix(dashboard): draw flow chart labels in the theme text color (QuantumNous#7821) - c9179d3 fix(playground): support the reasoning field in chat responses (QuantumNous#7831) - 908f94d fix(web): hide pages the user cannot open from console search - 19d435e fix(relay): mask only the custom upstream address in error messages (QuantumNous#7822) - 718a4e7 fix(vertex): use the multi-region hostnames for us and eu - f196934 feat(plugins): bind Hailuo, Vidu and Veo plugins to New API channels - bfdad29 fix(vidu): bill the model, duration and resolution Vidu generates - 150ab3c chore(licenses): refresh the third-party dependency inventory - 76cd511 build: upgrade moejs to v0.1.0-alpha.7 - 1b63c28 fix(claude): preserve explicit zero usage and cache-only billing (QuantumNous#7816) - c9f7b62 fix(web): sort pricing models by input, output and per-request price (QuantumNous#7813) - a0bf6a8 fix(vertex): pass project_id in API Key mode to avoid 404 on official endpoints (QuantumNous#6330) - 4013729 fix: disable sensitive word filtering by default and clear the default word list (QuantumNous#7814) - 7de10f2 feat(token): let an API key read its owner's quota - ef60ef2 fix(relay): keep the cause of a failed body read for every later reader - d10eafb fix(relay): report the real cause when a request body cannot be read - 63cecab feat(channel): support Sub2API balance queries (QuantumNous#7749) - b4be2a7 feat(ui): show newly added pricing groups at the top (QuantumNous#7782) - 633b4c5 feat(logs): export usage logs from the common log page (QuantumNous#7774) - dd59854 chore(deps-dev): bump undici from 6.28.0 to 6.29.0 in /electron (QuantumNous#7624) - 93cf4ba chore(deps-dev): bump js-yaml from 4.3.1 to 4.3.2 in /electron (QuantumNous#7327) - 3c9fb2a chore(deps-dev): bump brace-expansion from 1.1.16 to 1.1.21 in /electron (QuantumNous#7623) - 9f04810 chore(deps): bump ai from 7.0.31 to 7.0.136 in /web (QuantumNous#7767) - 3fe394c chore(deps): bump github.com/gorilla/websocket from 1.5.0 to 1.5.3 (QuantumNous#7001) - 1c58f3d chore(deps-dev): bump fast-uri from 3.1.5 to 3.1.7 in /electron (QuantumNous#7169) - 7f51a97 chore(deps-dev): bump js-yaml from 4.3.1 to 4.3.2 in /electron (QuantumNous#7327) - 7e25797 chore(deps-dev): bump electron from 39.8.10 to 41.10.6 in /electron (QuantumNous#7625) - bf4e1eb build(deps-dev): bump oxfmt from 0.57.0 to 0.72.0 in /web (QuantumNous#7766) - 82306b3 build(deps-dev): bump @tanstack/router-plugin in /web (QuantumNous#7768) - c730add build(deps): bump stream-markdown-parser from 1.1.3 to 1.2.18 in /web (QuantumNous#7769) - b8c2dc1 build(deps): bump yace from 1.1.0 to 1.1.1 in /web (QuantumNous#7770) - ba29f06 chore(deps-dev): bump @xmldom/xmldom from 0.8.13 to 0.8.15 in /electron (QuantumNous#7187) - 767a82b fix(claude): forward thinking.block_binding and every anthropic-beta value (QuantumNous#7732) - 2b85a8f fix(auth): show legal consent warning on password login (QuantumNous#7771) - 2ed0587 fix(ci): stabilize checks and configure Bun dependency updates (QuantumNous#7765) - 9948b1e fix(pricing): accept declared endpoint arrays in pricing conversion (QuantumNous#7724) - 4bfcf28 chore(web): bump @lobehub/icons to 5.22.0 (QuantumNous#7764) - fc08b76 fix(web): preserve recorded billing tiers in usage log previews (QuantumNous#7763) - ba0e478 fix(relaykit): preserve assistant text with tool calls (QuantumNous#6871) - 34b1942 fix(pricing): allow root access when the model square is disabled (QuantumNous#7761) - b22a43b fix: mark task settlement logs with is_task for tiered billing display (QuantumNous#7446) - bbf60b4 fix(logs): vertically align billing source icons on mobile (QuantumNous#7760) - 3f926c3 fix(metrics): count completed streams after context cancellation (QuantumNous#7638) - 3827fd8 fix(web): show cache read price on expression model cards (QuantumNous#7757) Local tests not run (CI-only).
Important
📝 变更描述 / Description
Vertex AI 渠道在 `vertex_key_type=api_key` 模式下,`getRequestUrl` 把空字符串作为 `project_id` 传给 `BuildGoogleModelURL` / `BuildAnthropicModelURL`。这导致 URL 缺少 `/projects/{PROJECT_ID}/locations/{REGION}/` 段,Google 官方 Vertex 端点会返回 404:
```
https://aiplatform.googleapis.com/v1/publishers/google/models/{model}:generateContent?key=...
↑ 缺少 /projects/{PROJECT_ID}/locations/{REGION}
```
JSON 模式下 `project_id` 从 service account JSON 解析,工作正常;问题只出现在 api_key 模式。
修复:
🚀 变更类型 / Type of change
🔗 关联任务 / Related Issue
✅ 提交前检查项 / Checklist
📸 运行证明 / Proof of Work
Go 后端单元测试(新增 4 个,覆盖 api_key 模式 URL 构建)
```
=== RUN TestGetRequestUrl_APIKey_UsesProjectIDFromSettings
--- PASS
=== RUN TestGetRequestUrl_APIKey_StreamSuffixUsesAmpersand
--- PASS
=== RUN TestGetRequestUrl_APIKey_ClaudeModeUsesProjectID
--- PASS
=== RUN TestGetRequestUrl_APIKey_EmptyProjectIDFallsBackToLegacyBehavior
--- PASS
ok github.com/QuantumNous/new-api/relay/channel/vertex
```
关键断言:URL 含 `/projects/zmdy6v-mffg/locations/` 且以 `key=<API_KEY>` 结尾;空 project_id 时 URL 不含 `/projects/` 段(保持旧行为)。
前端类型检查
```
前端 lint(仅改动文件)
```
pnpm oxlint src/features/channels/lib/channel-form.ts
src/features/channels/components/drawers/channel-mutate-drawer.tsx
src/features/channels/types.ts
Found 0 warnings and 0 errors.
```
Summary by CodeRabbit
New Features
Bug Fixes