Skip to content

fix: 修复Gemini渠道API端点URL显示问题#123

Merged
AmintaCCCP merged 7 commits intomainfrom
fix/gemini-api-url-display
Apr 28, 2026
Merged

fix: 修复Gemini渠道API端点URL显示问题#123
AmintaCCCP merged 7 commits intomainfrom
fix/gemini-api-url-display

Conversation

@AmintaCCCP
Copy link
Copy Markdown
Owner

@AmintaCCCP AmintaCCCP commented Apr 28, 2026

Summary

  • 选择Gemini类型时自动填充官方默认端点 https://generativelanguage.googleapis.com/v1beta
  • 修正 buildFinalApiUrl 对 gemini 类型的处理,返回正确的 v1beta/models/{model}:generateContent 路径
  • 更新UI提示文案,Gemini用户看到"只填到v1beta即可,路径会自动生成"

Test plan

  • 选择Gemini渠道时,API端点输入框应自动填充官方默认值
  • 选择Gemini渠道时,提示文案应正确引导用户
  • 最终请求URL预览应显示 .../v1beta/models/{model}:generateContent 格式

🤖 Generated with Claude Code

Summary by CodeRabbit

  • New Features

    • Automatic base URL defaults per AI provider and auto-update when switching API type.
    • Gemini endpoint input simplified—enter the v1beta model prefix; endpoint is constructed automatically.
    • API Endpoint helper text clarified with specific Gemini guidance and narrowed prohibited paths.
  • Bug Fixes

    • Reset restores provider-specific default endpoints and preserves loaded endpoint values when editing existing configs.

@AmintaCCCP AmintaCCCP linked an issue Apr 28, 2026 that may be closed by this pull request
@coderabbitai
Copy link
Copy Markdown
Contributor

coderabbitai Bot commented Apr 28, 2026

Note

Reviews paused

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

Use the following commands to manage reviews:

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

Use the checkboxes below for quick actions:

  • ▶️ Resume reviews
  • 🔍 Trigger review
📝 Walkthrough

Walkthrough

The UI now sets provider-specific default base URLs (OpenAI to /v1) and auto-fills/clears form.baseUrl when apiType changes only if the user hasn't customized it. The API URL builder adds a Gemini-specific path (v1beta/models/{model}:generateContent); API Endpoint help text was adjusted.

Changes

Cohort / File(s) Summary
AI Config UI
src/components/settings/AIConfigPanel.tsx
Add defaultApiEndpoints mapping; default form.baseUrl to OpenAI /v1; useEffect auto-populates or clears form.baseUrl on apiType changes only when not customized; update API Endpoint helper text (Gemini guidance + narrowed forbidden paths).
API URL Builder
src/utils/apiUrlBuilder.ts
buildFinalApiUrl special-cases apiType === 'gemini' to return baseUrl/v1beta/models/{model}:generateContent; preserve existing OpenAI responses vs chat completions logic for other types.

Sequence Diagram(s)

sequenceDiagram
  participant User as User
  participant UI as AIConfigPanel
  participant Builder as apiUrlBuilder
  participant API as Remote API

  User->>UI: change apiType (e.g., "gemini")
  UI->>UI: useEffect checks if baseUrl was customized
  alt baseUrl not customized
    UI->>UI: set or clear form.baseUrl per defaultApiEndpoints
  end
  User->>UI: submit request with model
  UI->>Builder: buildFinalApiUrl(apiType, baseUrl, model)
  alt apiType == "gemini"
    Builder->>Builder: return "baseUrl/v1beta/models/{model}:generateContent"
  else
    Builder->>Builder: return existing OpenAI responses/chat completions path
  end
  UI->>API: send request to built endpoint
  API-->>UI: response
  UI-->>User: display result
Loading

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~25 minutes

Possibly related PRs

Poem

🐰 I hopped through lines of code tonight,

Tucked defaults in where they fit just right,
Gemini routes stitched in a thread,
Base URLs hum as configs are read,
A tiny hop — deployment delight.

🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 0.00% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (4 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The PR title is in Chinese and translates to 'fix: Fix Gemini channel API endpoint URL display issue'. The changes address Gemini API endpoint configuration, auto-fill defaults, and URL path construction, which aligns with the title's reference to fixing Gemini API endpoint display.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.

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

✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch fix/gemini-api-url-display

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.

Copy link
Copy Markdown
Contributor

@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

🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@src/components/settings/AIConfigPanel.tsx`:
- Around line 56-61: The useEffect references form before its declaration and
only autofills when baseUrl is empty; move the useEffect so it appears after the
form state declaration (the useState that defines form) and change its logic to
handle API-type switches by tracking the previous apiType with a useRef
(prevApiType) — on apiType change, if defaultApiEndpoints[form.apiType] exists
and (form.baseUrl is empty OR form.baseUrl equals
defaultApiEndpoints[prevApiType]) then call setForm(prev => ({ ...prev, baseUrl:
defaultApiEndpoints[form.apiType] })); ensure the effect depends on form.apiType
and form.baseUrl (or use prevApiType ref) and reference the symbols useEffect,
defaultApiEndpoints, form, setForm, baseUrl, apiType, and prevApiType.
🪄 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: defaults

Review profile: CHILL

Plan: Pro

Run ID: 791385aa-137e-4e47-9c99-30dd0cda6de1

📥 Commits

Reviewing files that changed from the base of the PR and between 0d33851 and ec0cc2e.

📒 Files selected for processing (2)
  • src/components/settings/AIConfigPanel.tsx
  • src/utils/apiUrlBuilder.ts

Comment thread src/components/settings/AIConfigPanel.tsx Outdated
- 选择Gemini类型时自动填充官方默认端点 https://generativelanguage.googleapis.com/v1beta
- 修正buildFinalApiUrl对gemini类型的处理,返回正确的v1beta/models/{model}:generateContent路径
- 更新UI提示文案,Gemini用户看到"只填到v1beta即可,路径会自动生成"

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
@AmintaCCCP AmintaCCCP force-pushed the fix/gemini-api-url-display branch from ec0cc2e to 5e8a2a9 Compare April 28, 2026 10:42
Copy link
Copy Markdown
Contributor

@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

♻️ Duplicate comments (1)
src/components/settings/AIConfigPanel.tsx (1)

76-82: ⚠️ Potential issue | 🟠 Major

Endpoint defaults are declared but not applied on API-type switch.

Line 76 defines provider defaults, but switching form.apiType (Line 366) still does not auto-update form.baseUrl, so selecting Gemini can keep the previous provider URL. This misses the PR objective.

💡 Suggested fix
+  const prevApiTypeRef = useRef<AIApiType>(form.apiType);
+
+  useEffect(() => {
+    const nextDefault = defaultApiEndpoints[form.apiType];
+    const prevDefault = defaultApiEndpoints[prevApiTypeRef.current];
+    const shouldAutofill =
+      !!nextDefault &&
+      (form.baseUrl === '' || form.baseUrl === prevDefault) &&
+      form.baseUrl !== nextDefault;
+
+    if (shouldAutofill) {
+      setForm(prev => ({ ...prev, baseUrl: nextDefault }));
+    }
+    prevApiTypeRef.current = form.apiType;
+  }, [form.apiType, form.baseUrl]);
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@src/components/settings/AIConfigPanel.tsx` around lines 76 - 82, The
defaultApiEndpoints map (defaultApiEndpoints) is defined but not applied when
form.apiType changes; update the API-type switch handler (where form.apiType is
set) to also set form.baseUrl to defaultApiEndpoints[form.apiType] (or the
selected value) when the user selects a new provider, using the form state
setter used in this component (e.g., setForm or the form change handler) so that
selecting "gemini", "claude", "openai", etc. automatically updates the baseUrl
field; ensure you only overwrite baseUrl when the endpoint default is non-empty
to avoid clobbering user-entered custom URLs.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@src/components/settings/AIConfigPanel.tsx`:
- Around line 85-90: The reset logic uses the current form.apiType to compute
defaultUrl then sets apiType to 'openai', causing mismatched baseUrl; update the
resetForm logic so defaultUrl is derived from the new apiType (the value being
set, e.g., 'openai') or compute baseUrl after you set apiType so that setForm({
apiType, baseUrl }) uses matching values; locate the reset handler where
defaultUrl is computed from form.apiType and change it to use the target apiType
string (or compute baseUrl from defaultApiEndpoints[targetApiType]) so
name/apiType/baseUrl stay consistent.

---

Duplicate comments:
In `@src/components/settings/AIConfigPanel.tsx`:
- Around line 76-82: The defaultApiEndpoints map (defaultApiEndpoints) is
defined but not applied when form.apiType changes; update the API-type switch
handler (where form.apiType is set) to also set form.baseUrl to
defaultApiEndpoints[form.apiType] (or the selected value) when the user selects
a new provider, using the form state setter used in this component (e.g.,
setForm or the form change handler) so that selecting "gemini", "claude",
"openai", etc. automatically updates the baseUrl field; ensure you only
overwrite baseUrl when the endpoint default is non-empty to avoid clobbering
user-entered custom URLs.
🪄 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: defaults

Review profile: CHILL

Plan: Pro

Run ID: 6abd2206-5f11-489e-b685-9d8910755145

📥 Commits

Reviewing files that changed from the base of the PR and between ec0cc2e and 5e8a2a9.

📒 Files selected for processing (2)
  • src/components/settings/AIConfigPanel.tsx
  • src/utils/apiUrlBuilder.ts

Comment thread src/components/settings/AIConfigPanel.tsx Outdated
- 添加useEffect监听form.apiType变化,自动填充对应默认端点
- 使用prevApiTypeRef避免重复设置
- 修复resetForm中apiType与baseUrl不匹配的问题
- 仅在baseUrl为空或等于上一个默认端点时才填充

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

@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)
src/components/settings/AIConfigPanel.tsx (1)

64-95: ⚠️ Potential issue | 🟠 Major

Don't let the custom-endpoint mode inherit OpenAI's default URL.

openai-compatible has no default endpoint, so switching from a provider with a default leaves https://api.openai.com/v1 in the field. That makes the custom-endpoint mode start from the wrong base and can be saved unchanged. Clear the field when the target type has no default, or only preserve user-entered custom values.

Suggested fix
   useEffect(() => {
     if (form.apiType !== prevApiTypeRef.current) {
       const nextDefault = defaultApiEndpoints[form.apiType];
       const prevDefault = defaultApiEndpoints[prevApiTypeRef.current];
-      if (nextDefault && (form.baseUrl === '' || form.baseUrl === prevDefault)) {
-        setForm(prev => ({ ...prev, baseUrl: nextDefault }));
-      }
+      if (nextDefault) {
+        if (form.baseUrl === '' || form.baseUrl === prevDefault) {
+          setForm(prev => ({ ...prev, baseUrl: nextDefault }));
+        }
+      } else if (form.baseUrl === prevDefault) {
+        setForm(prev => ({ ...prev, baseUrl: '' }));
+      }
       prevApiTypeRef.current = form.apiType;
     }
   }, [form.apiType, form.baseUrl]);
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@src/components/settings/AIConfigPanel.tsx` around lines 64 - 95, The effect
that auto-fills baseUrl (useEffect referencing prevApiTypeRef,
defaultApiEndpoints, form.apiType, form.baseUrl, and setForm) currently only
updates when the new API type has a default endpoint, so switching to
'openai-compatible' can leave the OpenAI URL in place; change the logic so when
nextDefault is falsy (no default, e.g., 'openai-compatible') and the current
form.baseUrl equals the previous provider's default (prevDefault) you set
baseUrl to '' (clear it), while if the user had already entered a custom baseUrl
you preserve it; otherwise when nextDefault exists keep the existing behavior
(set baseUrl to nextDefault if baseUrl is empty or equals prevDefault).
🤖 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 `@src/components/settings/AIConfigPanel.tsx`:
- Around line 64-95: The effect that auto-fills baseUrl (useEffect referencing
prevApiTypeRef, defaultApiEndpoints, form.apiType, form.baseUrl, and setForm)
currently only updates when the new API type has a default endpoint, so
switching to 'openai-compatible' can leave the OpenAI URL in place; change the
logic so when nextDefault is falsy (no default, e.g., 'openai-compatible') and
the current form.baseUrl equals the previous provider's default (prevDefault)
you set baseUrl to '' (clear it), while if the user had already entered a custom
baseUrl you preserve it; otherwise when nextDefault exists keep the existing
behavior (set baseUrl to nextDefault if baseUrl is empty or equals prevDefault).

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: 9a36a99d-8eef-4f3f-8256-cb6677186e43

📥 Commits

Reviewing files that changed from the base of the PR and between 5e8a2a9 and 095f17f.

📒 Files selected for processing (1)
  • src/components/settings/AIConfigPanel.tsx

当切换到无默认端点的API类型时,如果当前baseUrl等于前一个默认端点则清空
避免用户误以为仍在使用OpenAI的URL

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

@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 (1)
src/components/settings/AIConfigPanel.tsx (1)

64-82: Avoid duplicating the OpenAI default endpoint.

baseUrl is hardcoded in the initial state and again in defaultApiEndpoints, so the initial form can drift from the reset/switch behavior later. Hoist the map above useState and initialize from defaultApiEndpoints.openai.

♻️ Suggested cleanup
+  const defaultApiEndpoints: Record<AIApiType, string> = {
+    openai: 'https://api.openai.com/v1',
+    'openai-responses': 'https://api.openai.com/v1',
+    claude: 'https://api.anthropic.com/v1',
+    gemini: 'https://generativelanguage.googleapis.com/v1beta',
+    'openai-compatible': '',
+  };
+
   const [form, setForm] = useState<AIFormState>({
     name: '',
     apiType: 'openai',
-    baseUrl: 'https://api.openai.com/v1',
+    baseUrl: defaultApiEndpoints.openai,
     apiKey: '',
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@src/components/settings/AIConfigPanel.tsx` around lines 64 - 82, Move the
defaultApiEndpoints map out of the component state block and define it above the
useState call, then initialize the form's baseUrl using
defaultApiEndpoints.openai instead of the hardcoded 'https://api.openai.com/v1';
update the AIFormState initial object (used in useState) to reference
defaultApiEndpoints.openai and remove the duplicate hardcoded URL so
switching/reset logic that uses defaultApiEndpoints stays consistent with the
initial form state.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@src/components/settings/AIConfigPanel.tsx`:
- Around line 84-100: The auto-fill effect (the useEffect that compares
form.apiType to prevApiTypeRef.current and updates baseUrl) is unintentionally
running when handleEdit hydrates an existing config; to fix, ensure the effect
only reacts to user-driven API-type changes or mark hydration as such. Two
acceptable fixes: (A) update prevApiTypeRef.current to the incoming
config.apiType inside handleEdit before calling setForm so the effect sees no
change, or (B) add a short-lived "isHydrating" ref/state that handleEdit sets
true while it writes form and the useEffect early-returns if isHydrating is
true; reference prevApiTypeRef, useEffect, setForm, and handleEdit when applying
the change.

---

Nitpick comments:
In `@src/components/settings/AIConfigPanel.tsx`:
- Around line 64-82: Move the defaultApiEndpoints map out of the component state
block and define it above the useState call, then initialize the form's baseUrl
using defaultApiEndpoints.openai instead of the hardcoded
'https://api.openai.com/v1'; update the AIFormState initial object (used in
useState) to reference defaultApiEndpoints.openai and remove the duplicate
hardcoded URL so switching/reset logic that uses defaultApiEndpoints stays
consistent with the initial form state.
🪄 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: defaults

Review profile: CHILL

Plan: Pro

Run ID: b87417b4-61f7-47d0-9267-ba863d933063

📥 Commits

Reviewing files that changed from the base of the PR and between 095f17f and 4997583.

📒 Files selected for processing (1)
  • src/components/settings/AIConfigPanel.tsx

Comment thread src/components/settings/AIConfigPanel.tsx
在handleEdit中先同步prevApiTypeRef.current为配置的apiType
避免effect误判为apiType变化而清空或覆盖用户已保存的自定义URL

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

@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 (1)
src/components/settings/AIConfigPanel.tsx (1)

76-82: Consider hoisting defaultApiEndpoints outside the component.

This constant object is recreated on every render. Since the values are static, moving it outside the component (or wrapping in useMemo) avoids unnecessary object allocations and ensures referential stability.

♻️ Suggested refactor
+const DEFAULT_API_ENDPOINTS: Record<AIApiType, string> = {
+  openai: 'https://api.openai.com/v1',
+  'openai-responses': 'https://api.openai.com/v1',
+  claude: 'https://api.anthropic.com/v1',
+  gemini: 'https://generativelanguage.googleapis.com/v1beta',
+  'openai-compatible': '',
+};
+
 export const AIConfigPanel: React.FC<AIConfigPanelProps> = ({ t }) => {
   // ...
-  const defaultApiEndpoints: Record<AIApiType, string> = {
-    openai: 'https://api.openai.com/v1',
-    'openai-responses': 'https://api.openai.com/v1',
-    claude: 'https://api.anthropic.com/v1',
-    gemini: 'https://generativelanguage.googleapis.com/v1beta',
-    'openai-compatible': '',
-  };

Then update all references from defaultApiEndpoints to DEFAULT_API_ENDPOINTS.

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

In `@src/components/settings/AIConfigPanel.tsx` around lines 76 - 82, Hoist the
defaultApiEndpoints object out of the AIConfigPanel component to avoid
recreating it on every render: create a top-level constant named
DEFAULT_API_ENDPOINTS with the same entries and replace all in-component
references to defaultApiEndpoints with DEFAULT_API_ENDPOINTS (alternatively,
wrap it in useMemo inside AIConfigPanel if you prefer a hook-based approach);
ensure the symbol DEFAULT_API_ENDPOINTS is exported/visible where needed and
update usages in this file accordingly.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Nitpick comments:
In `@src/components/settings/AIConfigPanel.tsx`:
- Around line 76-82: Hoist the defaultApiEndpoints object out of the
AIConfigPanel component to avoid recreating it on every render: create a
top-level constant named DEFAULT_API_ENDPOINTS with the same entries and replace
all in-component references to defaultApiEndpoints with DEFAULT_API_ENDPOINTS
(alternatively, wrap it in useMemo inside AIConfigPanel if you prefer a
hook-based approach); ensure the symbol DEFAULT_API_ENDPOINTS is
exported/visible where needed and update usages in this file accordingly.

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: ebe25747-87d0-44b5-924c-f570ce0f819a

📥 Commits

Reviewing files that changed from the base of the PR and between 4997583 and f4619a8.

📒 Files selected for processing (1)
  • src/components/settings/AIConfigPanel.tsx

避免每次渲染时重复创建对象,减少不必要的内存分配

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
@AmintaCCCP AmintaCCCP merged commit f53535a into main Apr 28, 2026
5 checks passed
@AmintaCCCP AmintaCCCP deleted the fix/gemini-api-url-display branch April 28, 2026 11:25
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.

Gemini配置显示的完整路径是openai

1 participant