feat(gemini): add Gemini provider integration (#202)

* feat(gemini): add Gemini provider integration

- Add gemini_config.rs module for .env file parsing
- Extend AppType enum to support Gemini
- Implement GeminiConfigEditor and GeminiFormFields components
- Add GeminiIcon with standardized 1024x1024 viewBox
- Add Gemini provider presets configuration
- Update i18n translations for Gemini support
- Extend ProviderService and McpService for Gemini

* fix(gemini): resolve TypeScript errors, add i18n support, and fix MCP logic

**Critical Fixes:**
- Fix TS2741 errors in tests/msw/state.ts by adding missing Gemini type definitions
- Fix ProviderCard.extractApiUrl to support GOOGLE_GEMINI_BASE_URL display
- Add missing apps.gemini i18n keys (zh/en) for proper app name display
- Fix MCP service Gemini cross-app duplication logic to prevent self-copy

**Technical Details:**
- tests/msw/state.ts: Add gemini default providers, current ID, and MCP config
- ProviderCard.tsx: Check both ANTHROPIC_BASE_URL and GOOGLE_GEMINI_BASE_URL
- services/mcp.rs: Skip Gemini in sync_other_side logic with unreachable!() guards
- Run pnpm format to auto-fix code style issues

**Verification:**
-  pnpm typecheck passes
-  pnpm format completed

* feat(gemini): enhance authentication and config parsing

- Add strict and lenient .env parsing modes
- Implement PackyCode partner authentication detection
- Support Google OAuth official authentication
- Auto-configure security.auth.selectedType for PackyCode
- Add comprehensive test coverage for all auth types
- Update i18n for OAuth hints and Gemini config

---------

Co-authored-by: Jason <farion1231@gmail.com>
This commit is contained in:
YoVinchen
2025-11-12 10:47:34 +08:00
committed by GitHub
parent 32a2ba5ef6
commit 8a05e7bd3d
46 changed files with 2522 additions and 276 deletions

View File

@@ -39,7 +39,8 @@ export function useSpeedTestEndpoints({
initialData,
}: UseSpeedTestEndpointsProps) {
const claudeEndpoints = useMemo<EndpointCandidate[]>(() => {
if (appId !== "claude") return [];
// Reuse this branch for Claude and Gemini (non-Codex)
if (appId !== "claude" && appId !== "gemini") return [];
const map = new Map<string, EndpointCandidate>();
// 所有端点都标记为 isCustom: true给用户完全的管理自由
@@ -66,26 +67,37 @@ export function useSpeedTestEndpoints({
// 3. 编辑模式:初始数据中的 URL
if (initialData && typeof initialData.settingsConfig === "object") {
const configEnv = initialData.settingsConfig as {
env?: { ANTHROPIC_BASE_URL?: string };
env?: { ANTHROPIC_BASE_URL?: string; GOOGLE_GEMINI_BASE_URL?: string };
};
const envUrl = configEnv.env?.ANTHROPIC_BASE_URL;
if (typeof envUrl === "string") {
add(envUrl);
}
const envUrls = [
configEnv.env?.ANTHROPIC_BASE_URL,
configEnv.env?.GOOGLE_GEMINI_BASE_URL,
];
envUrls.forEach((u) => {
if (typeof u === "string") add(u);
});
}
// 4. 预设中的 endpointCandidates也允许用户删除
if (selectedPresetId && selectedPresetId !== "custom") {
const entry = presetEntries.find((item) => item.id === selectedPresetId);
if (entry) {
const preset = entry.preset as ProviderPreset;
// 添加预设自己的 baseUrl
const presetEnv = preset.settingsConfig as {
env?: { ANTHROPIC_BASE_URL?: string };
const preset = entry.preset as ProviderPreset & {
settingsConfig?: { env?: { GOOGLE_GEMINI_BASE_URL?: string } };
endpointCandidates?: string[];
};
if (presetEnv.env?.ANTHROPIC_BASE_URL) {
add(presetEnv.env.ANTHROPIC_BASE_URL);
}
// 添加预设自己的 baseUrl兼容 Claude/Gemini
const presetEnv = preset.settingsConfig as {
env?: {
ANTHROPIC_BASE_URL?: string;
GOOGLE_GEMINI_BASE_URL?: string;
};
};
const presetUrls = [
presetEnv?.env?.ANTHROPIC_BASE_URL,
presetEnv?.env?.GOOGLE_GEMINI_BASE_URL,
];
presetUrls.forEach((u) => add(u));
// 添加预设的候选端点
if (preset.endpointCandidates) {
preset.endpointCandidates.forEach((url) => add(url));