fix: remove gemini support since google discontinued it

This commit is contained in:
Haileyesus
2026-07-06 17:01:29 +03:00
parent 6daae87443
commit 4e423f5fa2
100 changed files with 247 additions and 3799 deletions

View File

@@ -39,7 +39,6 @@ interface UseChatComposerStateArgs {
claudeModel: string;
codexModel: string;
currentProviderEffort: string;
geminiModel: string;
opencodeModel: string;
isLoading: boolean;
canAbortSession: boolean;
@@ -180,7 +179,6 @@ export function useChatComposerState({
claudeModel,
codexModel,
currentProviderEffort,
geminiModel,
opencodeModel,
isLoading,
canAbortSession,
@@ -353,9 +351,7 @@ export function useChatComposerState({
? cursorModel
: provider === 'codex'
? codexModel
: provider === 'gemini'
? geminiModel
: provider === 'opencode'
: provider === 'opencode'
? opencodeModel
: claudeModel,
tokenUsage: tokenBudget,
@@ -410,7 +406,6 @@ export function useChatComposerState({
codexModel,
currentSessionId,
cursorModel,
geminiModel,
opencodeModel,
handleBuiltInCommand,
handleCustomCommand,
@@ -741,9 +736,7 @@ export function useChatComposerState({
? 'cursor-tools-settings'
: provider === 'codex'
? 'codex-settings'
: provider === 'gemini'
? 'gemini-settings'
: provider === 'opencode'
: provider === 'opencode'
? 'opencode-settings'
: 'claude-settings';
const savedSettings = safeLocalStorage.getItem(settingsKey);
@@ -767,9 +760,7 @@ export function useChatComposerState({
? cursorModel
: provider === 'codex'
? codexModel
: provider === 'gemini'
? geminiModel
: provider === 'opencode'
: provider === 'opencode'
? opencodeModel
: claudeModel;
const effort = currentProviderEffort;
@@ -815,7 +806,6 @@ export function useChatComposerState({
currentSessionId,
cursorModel,
executeCommand,
geminiModel,
opencodeModel,
isLoading,
onSessionProcessing,

View File

@@ -20,11 +20,17 @@ const FALLBACK_DEFAULT_MODEL: Record<LLMProvider, string> = {
claude: 'default',
cursor: 'gpt-5.3-codex',
codex: 'gpt-5.4',
gemini: 'gemini-3.1-pro-preview',
opencode: 'anthropic/claude-sonnet-4-5',
};
const PROVIDERS: LLMProvider[] = ['claude', 'cursor', 'codex', 'gemini', 'opencode'];
const PROVIDERS: LLMProvider[] = ['claude', 'cursor', 'codex', 'opencode'];
const readStoredProvider = (): LLMProvider => {
const storedProvider = localStorage.getItem('selected-provider');
return PROVIDERS.includes(storedProvider as LLMProvider)
? storedProvider as LLMProvider
: 'claude';
};
/**
* Fallback permission-mode matrix used only until the backend capability
@@ -36,7 +42,6 @@ const FALLBACK_PERMISSION_MODES: Record<LLMProvider, PermissionMode[]> = {
claude: ['default', 'auto', 'acceptEdits', 'bypassPermissions', 'plan'],
cursor: ['default', 'acceptEdits', 'bypassPermissions', 'plan'],
codex: ['default', 'acceptEdits', 'bypassPermissions'],
gemini: ['default', 'acceptEdits', 'bypassPermissions', 'plan'],
opencode: ['default', 'acceptEdits', 'bypassPermissions', 'plan'],
};
@@ -85,9 +90,7 @@ type ChangeActiveModelApiResponse = {
export function useChatProviderState({ selectedSession, selectedProject: _selectedProject }: UseChatProviderStateArgs) {
const [permissionMode, setPermissionMode] = useState<PermissionMode>('default');
const [pendingPermissionRequests, setPendingPermissionRequests] = useState<PendingPermissionRequest[]>([]);
const [provider, setProvider] = useState<LLMProvider>(() => {
return (localStorage.getItem('selected-provider') as LLMProvider) || 'claude';
});
const [provider, setProvider] = useState<LLMProvider>(readStoredProvider);
const [cursorModel, setCursorModel] = useState<string>(() => {
return localStorage.getItem('cursor-model') || FALLBACK_DEFAULT_MODEL.cursor;
});
@@ -103,9 +106,6 @@ export function useChatProviderState({ selectedSession, selectedProject: _select
return acc;
}, {});
});
const [geminiModel, setGeminiModel] = useState<string>(() => {
return localStorage.getItem('gemini-model') || FALLBACK_DEFAULT_MODEL.gemini;
});
const [opencodeModel, setOpenCodeModel] = useState<string>(() => {
return localStorage.getItem('opencode-model') || FALLBACK_DEFAULT_MODEL.opencode;
});
@@ -151,12 +151,6 @@ export function useChatProviderState({ selectedSession, selectedProject: _select
return;
}
if (targetProvider === 'gemini') {
setGeminiModel(model);
localStorage.setItem('gemini-model', model);
return;
}
setOpenCodeModel(model);
localStorage.setItem('opencode-model', model);
}, []);
@@ -360,9 +354,8 @@ export function useChatProviderState({ selectedSession, selectedProject: _select
claude: claudeModel,
cursor: cursorModel,
codex: codexModel,
gemini: geminiModel,
opencode: opencodeModel,
}), [claudeModel, cursorModel, codexModel, geminiModel, opencodeModel]);
}), [claudeModel, cursorModel, codexModel, opencodeModel]);
useEffect(() => {
const claude = providerModelCatalog.claude;
@@ -403,19 +396,6 @@ export function useChatProviderState({ selectedSession, selectedProject: _select
}
}, [providerModelCatalog.codex, codexModel]);
useEffect(() => {
const gemini = providerModelCatalog.gemini;
if (gemini) {
const next = pickStoredOrCurrent('gemini-model', geminiModel, gemini);
if (next !== geminiModel) {
setGeminiModel(next);
}
if (localStorage.getItem('gemini-model') !== next) {
localStorage.setItem('gemini-model', next);
}
}
}, [providerModelCatalog.gemini, geminiModel]);
useEffect(() => {
const opencode = providerModelCatalog.opencode;
if (opencode) {
@@ -589,8 +569,6 @@ export function useChatProviderState({ selectedSession, selectedProject: _select
setCodexModel,
currentProviderEffort,
currentProviderEffortOptions,
geminiModel,
setGeminiModel,
opencodeModel,
setOpenCodeModel,
permissionMode,

View File

@@ -71,8 +71,6 @@ function ChatInterface({
setCodexModel,
currentProviderEffort,
currentProviderEffortOptions,
geminiModel,
setGeminiModel,
opencodeModel,
setOpenCodeModel,
permissionMode,
@@ -204,7 +202,6 @@ function ChatInterface({
claudeModel,
codexModel,
currentProviderEffort,
geminiModel,
opencodeModel,
isLoading: isProcessing,
canAbortSession,
@@ -300,9 +297,7 @@ function ChatInterface({
? t('messageTypes.cursor')
: provider === 'codex'
? t('messageTypes.codex')
: provider === 'gemini'
? t('messageTypes.gemini')
: provider === 'opencode'
: provider === 'opencode'
? t('messageTypes.opencode', { defaultValue: 'OpenCode' })
: t('messageTypes.claude');
@@ -342,8 +337,6 @@ function ChatInterface({
setCursorModel={setCursorModel}
codexModel={codexModel}
setCodexModel={setCodexModel}
geminiModel={geminiModel}
setGeminiModel={setGeminiModel}
opencodeModel={opencodeModel}
setOpenCodeModel={setOpenCodeModel}
providerModelCatalog={providerModelCatalog}
@@ -451,9 +444,7 @@ function ChatInterface({
? t('messageTypes.cursor')
: provider === 'codex'
? t('messageTypes.codex')
: provider === 'gemini'
? t('messageTypes.gemini')
: provider === 'opencode'
: provider === 'opencode'
? t('messageTypes.opencode', { defaultValue: 'OpenCode' })
: t('messageTypes.claude'),
})}

View File

@@ -38,8 +38,6 @@ interface ChatMessagesPaneProps {
setCursorModel: (model: string) => void;
codexModel: string;
setCodexModel: (model: string) => void;
geminiModel: string;
setGeminiModel: (model: string) => void;
opencodeModel: string;
setOpenCodeModel: (model: string) => void;
providerModelCatalog: Partial<Record<LLMProvider, ProviderModelsDefinition>>;
@@ -88,8 +86,6 @@ function ChatMessagesPane({
setCursorModel,
codexModel,
setCodexModel,
geminiModel,
setGeminiModel,
opencodeModel,
setOpenCodeModel,
providerModelCatalog,
@@ -189,8 +185,6 @@ function ChatMessagesPane({
setCursorModel={setCursorModel}
codexModel={codexModel}
setCodexModel={setCodexModel}
geminiModel={geminiModel}
setGeminiModel={setGeminiModel}
opencodeModel={opencodeModel}
setOpenCodeModel={setOpenCodeModel}
providerModelCatalog={providerModelCatalog}

View File

@@ -61,7 +61,6 @@ const PROVIDER_LABELS: Record<string, string> = {
claude: 'Claude',
cursor: 'Cursor',
codex: 'Codex',
gemini: 'Gemini',
opencode: 'OpenCode',
};

View File

@@ -149,9 +149,7 @@ const MessageComponent = memo(({ message, prevMessage, createDiff, onFileOpen, s
? t('messageTypes.cursor')
: provider === 'codex'
? t('messageTypes.codex')
: provider === 'gemini'
? t('messageTypes.gemini')
: provider === 'opencode'
: provider === 'opencode'
? t('messageTypes.opencode', { defaultValue: 'OpenCode' })
: t('messageTypes.claude'))}
</div>

View File

@@ -26,7 +26,6 @@ import {
const PROVIDER_META: { id: LLMProvider; name: string }[] = [
{ id: "claude", name: "Anthropic" },
{ id: "codex", name: "OpenAI" },
{ id: "gemini", name: "Google" },
{ id: "cursor", name: "Cursor" },
{ id: "opencode", name: "OpenCode" },
];
@@ -57,8 +56,6 @@ type ProviderSelectionEmptyStateProps = {
setCursorModel: (model: string) => void;
codexModel: string;
setCodexModel: (model: string) => void;
geminiModel: string;
setGeminiModel: (model: string) => void;
opencodeModel: string;
setOpenCodeModel: (model: string) => void;
providerModelCatalog: Partial<Record<LLMProvider, ProviderModelsDefinition>>;
@@ -88,12 +85,10 @@ function getCurrentModel(
c: string,
cu: string,
co: string,
g: string,
o: string,
) {
if (p === "claude") return c;
if (p === "codex") return co;
if (p === "gemini") return g;
if (p === "opencode") return o;
return cu;
}
@@ -103,7 +98,7 @@ function getProviderDisplayName(p: LLMProvider) {
if (p === "cursor") return "Cursor";
if (p === "codex") return "Codex";
if (p === "opencode") return "OpenCode";
return "Gemini";
return "Claude";
}
export default function ProviderSelectionEmptyState({
@@ -118,8 +113,6 @@ export default function ProviderSelectionEmptyState({
setCursorModel,
codexModel,
setCodexModel,
geminiModel,
setGeminiModel,
opencodeModel,
setOpenCodeModel,
providerModelCatalog,
@@ -149,7 +142,6 @@ export default function ProviderSelectionEmptyState({
claudeModel,
cursorModel,
codexModel,
geminiModel,
opencodeModel,
);
@@ -169,9 +161,6 @@ export default function ProviderSelectionEmptyState({
} else if (providerId === "codex") {
setCodexModel(modelValue);
localStorage.setItem("codex-model", modelValue);
} else if (providerId === "gemini") {
setGeminiModel(modelValue);
localStorage.setItem("gemini-model", modelValue);
} else if (providerId === "opencode") {
setOpenCodeModel(modelValue);
localStorage.setItem("opencode-model", modelValue);
@@ -180,7 +169,7 @@ export default function ProviderSelectionEmptyState({
localStorage.setItem("cursor-model", modelValue);
}
},
[setClaudeModel, setCursorModel, setCodexModel, setGeminiModel, setOpenCodeModel],
[setClaudeModel, setCursorModel, setCodexModel, setOpenCodeModel],
);
const handleModelSelect = useCallback(
@@ -323,9 +312,6 @@ export default function ProviderSelectionEmptyState({
codex: t("providerSelection.readyPrompt.codex", {
model: codexModel,
}),
gemini: t("providerSelection.readyPrompt.gemini", {
model: geminiModel,
}),
opencode: t("providerSelection.readyPrompt.opencode", {
model: opencodeModel,
defaultValue: "Ready with OpenCode {{model}}",

View File

@@ -1,263 +0,0 @@
import { useId } from 'react';
type GeminiLogoProps = {
className?: string;
};
const GeminiLogo = ({ className = 'w-5 h-5' }: GeminiLogoProps) => {
const id = useId().replace(/:/g, '');
const maskId = `${id}-gemini-mask`;
const gradientId = `${id}-gemini-gradient`;
const filterIds = Array.from({ length: 11 }, (_, index) => `${id}-gemini-filter-${index}`);
return (
<svg
viewBox="0 0 65 65"
role="img"
aria-label="Gemini"
className={className}
fill="none"
xmlns="http://www.w3.org/2000/svg"
>
<mask
id={maskId}
style={{ maskType: 'alpha' }}
maskUnits="userSpaceOnUse"
x="0"
y="0"
width="65"
height="65"
>
<path
d="M32.447 0c.68 0 1.273.465 1.439 1.125a38.904 38.904 0 001.999 5.905c2.152 5 5.105 9.376 8.854 13.125 3.751 3.75 8.126 6.703 13.125 8.855a38.98 38.98 0 005.906 1.999c.66.166 1.124.758 1.124 1.438 0 .68-.464 1.273-1.125 1.439a38.902 38.902 0 00-5.905 1.999c-5 2.152-9.375 5.105-13.125 8.854-3.749 3.751-6.702 8.126-8.854 13.125a38.973 38.973 0 00-2 5.906 1.485 1.485 0 01-1.438 1.124c-.68 0-1.272-.464-1.438-1.125a38.913 38.913 0 00-2-5.905c-2.151-5-5.103-9.375-8.854-13.125-3.75-3.749-8.125-6.702-13.125-8.854a38.973 38.973 0 00-5.905-2A1.485 1.485 0 010 32.448c0-.68.465-1.272 1.125-1.438a38.903 38.903 0 005.905-2c5-2.151 9.376-5.104 13.125-8.854 3.75-3.749 6.703-8.125 8.855-13.125a38.972 38.972 0 001.999-5.905A1.485 1.485 0 0132.447 0z"
fill="#000"
/>
<path
d="M32.447 0c.68 0 1.273.465 1.439 1.125a38.904 38.904 0 001.999 5.905c2.152 5 5.105 9.376 8.854 13.125 3.751 3.75 8.126 6.703 13.125 8.855a38.98 38.98 0 005.906 1.999c.66.166 1.124.758 1.124 1.438 0 .68-.464 1.273-1.125 1.439a38.902 38.902 0 00-5.905 1.999c-5 2.152-9.375 5.105-13.125 8.854-3.749 3.751-6.702 8.126-8.854 13.125a38.973 38.973 0 00-2 5.906 1.485 1.485 0 01-1.438 1.124c-.68 0-1.272-.464-1.438-1.125a38.913 38.913 0 00-2-5.905c-2.151-5-5.103-9.375-8.854-13.125-3.75-3.749-8.125-6.702-13.125-8.854a38.973 38.973 0 00-5.905-2A1.485 1.485 0 010 32.448c0-.68.465-1.272 1.125-1.438a38.903 38.903 0 005.905-2c5-2.151 9.376-5.104 13.125-8.854 3.75-3.749 6.703-8.125 8.855-13.125a38.972 38.972 0 001.999-5.905A1.485 1.485 0 0132.447 0z"
fill={`url(#${gradientId})`}
/>
</mask>
<g mask={`url(#${maskId})`}>
<g filter={`url(#${filterIds[0]})`}>
<path
d="M-5.859 50.734c7.498 2.663 16.116-2.33 19.249-11.152 3.133-8.821-.406-18.131-7.904-20.794-7.498-2.663-16.116 2.33-19.25 11.151-3.132 8.822.407 18.132 7.905 20.795z"
fill="#FFE432"
/>
</g>
<g filter={`url(#${filterIds[1]})`}>
<path
d="M27.433 21.649c10.3 0 18.651-8.535 18.651-19.062 0-10.528-8.35-19.062-18.651-19.062S8.78-7.94 8.78 2.587c0 10.527 8.35 19.062 18.652 19.062z"
fill="#FC413D"
/>
</g>
<g filter={`url(#${filterIds[2]})`}>
<path
d="M20.184 82.608c10.753-.525 18.918-12.244 18.237-26.174-.68-13.93-9.95-24.797-20.703-24.271C6.965 32.689-1.2 44.407-.519 58.337c.681 13.93 9.95 24.797 20.703 24.271z"
fill="#00B95C"
/>
</g>
<g filter={`url(#${filterIds[3]})`}>
<path
d="M20.184 82.608c10.753-.525 18.918-12.244 18.237-26.174-.68-13.93-9.95-24.797-20.703-24.271C6.965 32.689-1.2 44.407-.519 58.337c.681 13.93 9.95 24.797 20.703 24.271z"
fill="#00B95C"
/>
</g>
<g filter={`url(#${filterIds[4]})`}>
<path
d="M30.954 74.181c9.014-5.485 11.427-17.976 5.389-27.9-6.038-9.925-18.241-13.524-27.256-8.04-9.015 5.486-11.428 17.977-5.39 27.902 6.04 9.924 18.242 13.523 27.257 8.038z"
fill="#00B95C"
/>
</g>
<g filter={`url(#${filterIds[5]})`}>
<path
d="M67.391 42.993c10.132 0 18.346-7.91 18.346-17.666 0-9.757-8.214-17.667-18.346-17.667s-18.346 7.91-18.346 17.667c0 9.757 8.214 17.666 18.346 17.666z"
fill="#3186FF"
/>
</g>
<g filter={`url(#${filterIds[6]})`}>
<path
d="M-13.065 40.944c9.33 7.094 22.959 4.869 30.442-4.972 7.483-9.84 5.987-23.569-3.343-30.663C4.704-1.786-8.924.439-16.408 10.28c-7.483 9.84-5.986 23.57 3.343 30.664z"
fill="#FBBC04"
/>
</g>
<g filter={`url(#${filterIds[7]})`}>
<path
d="M34.74 51.43c11.135 7.656 25.896 5.524 32.968-4.764 7.073-10.287 3.779-24.832-7.357-32.488C49.215 6.52 34.455 8.654 27.382 18.94c-7.072 10.288-3.779 24.833 7.357 32.49z"
fill="#3186FF"
/>
</g>
<g filter={`url(#${filterIds[8]})`}>
<path
d="M54.984-2.336c2.833 3.852-.808 11.34-8.131 16.727-7.324 5.387-15.557 6.631-18.39 2.78-2.833-3.853.807-11.342 8.13-16.728 7.324-5.387 15.558-6.631 18.39-2.78z"
fill="#749BFF"
/>
</g>
<g filter={`url(#${filterIds[9]})`}>
<path
d="M31.727 16.104C43.053 5.598 46.94-8.626 40.41-15.666c-6.53-7.04-21.006-4.232-32.332 6.274s-15.214 24.73-8.683 31.77c6.53 7.04 21.006 4.232 32.332-6.274z"
fill="#FC413D"
/>
</g>
<g filter={`url(#${filterIds[10]})`}>
<path
d="M8.51 53.838c6.732 4.818 14.46 5.55 17.262 1.636 2.802-3.915-.384-10.994-7.116-15.812-6.731-4.818-14.46-5.55-17.261-1.636-2.802 3.915.383 10.994 7.115 15.812z"
fill="#FFEE48"
/>
</g>
</g>
<defs>
<filter
id={filterIds[0]}
x="-19.824"
y="13.152"
width="39.274"
height="43.217"
filterUnits="userSpaceOnUse"
colorInterpolationFilters="sRGB"
>
<feFlood floodOpacity="0" result="BackgroundImageFix" />
<feBlend in="SourceGraphic" in2="BackgroundImageFix" result="shape" />
<feGaussianBlur stdDeviation="2.46" result="effect1_foregroundBlur_2001_67" />
</filter>
<filter
id={filterIds[1]}
x="-15.001"
y="-40.257"
width="84.868"
height="85.688"
filterUnits="userSpaceOnUse"
colorInterpolationFilters="sRGB"
>
<feFlood floodOpacity="0" result="BackgroundImageFix" />
<feBlend in="SourceGraphic" in2="BackgroundImageFix" result="shape" />
<feGaussianBlur stdDeviation="11.891" result="effect1_foregroundBlur_2001_67" />
</filter>
<filter
id={filterIds[2]}
x="-20.776"
y="11.927"
width="79.454"
height="90.916"
filterUnits="userSpaceOnUse"
colorInterpolationFilters="sRGB"
>
<feFlood floodOpacity="0" result="BackgroundImageFix" />
<feBlend in="SourceGraphic" in2="BackgroundImageFix" result="shape" />
<feGaussianBlur stdDeviation="10.109" result="effect1_foregroundBlur_2001_67" />
</filter>
<filter
id={filterIds[3]}
x="-20.776"
y="11.927"
width="79.454"
height="90.916"
filterUnits="userSpaceOnUse"
colorInterpolationFilters="sRGB"
>
<feFlood floodOpacity="0" result="BackgroundImageFix" />
<feBlend in="SourceGraphic" in2="BackgroundImageFix" result="shape" />
<feGaussianBlur stdDeviation="10.109" result="effect1_foregroundBlur_2001_67" />
</filter>
<filter
id={filterIds[4]}
x="-19.845"
y="15.459"
width="79.731"
height="81.505"
filterUnits="userSpaceOnUse"
colorInterpolationFilters="sRGB"
>
<feFlood floodOpacity="0" result="BackgroundImageFix" />
<feBlend in="SourceGraphic" in2="BackgroundImageFix" result="shape" />
<feGaussianBlur stdDeviation="10.109" result="effect1_foregroundBlur_2001_67" />
</filter>
<filter
id={filterIds[5]}
x="29.832"
y="-11.552"
width="75.117"
height="73.758"
filterUnits="userSpaceOnUse"
colorInterpolationFilters="sRGB"
>
<feFlood floodOpacity="0" result="BackgroundImageFix" />
<feBlend in="SourceGraphic" in2="BackgroundImageFix" result="shape" />
<feGaussianBlur stdDeviation="9.606" result="effect1_foregroundBlur_2001_67" />
</filter>
<filter
id={filterIds[6]}
x="-38.583"
y="-16.253"
width="78.135"
height="78.758"
filterUnits="userSpaceOnUse"
colorInterpolationFilters="sRGB"
>
<feFlood floodOpacity="0" result="BackgroundImageFix" />
<feBlend in="SourceGraphic" in2="BackgroundImageFix" result="shape" />
<feGaussianBlur stdDeviation="8.706" result="effect1_foregroundBlur_2001_67" />
</filter>
<filter
id={filterIds[7]}
x="8.107"
y="-5.966"
width="78.877"
height="77.539"
filterUnits="userSpaceOnUse"
colorInterpolationFilters="sRGB"
>
<feFlood floodOpacity="0" result="BackgroundImageFix" />
<feBlend in="SourceGraphic" in2="BackgroundImageFix" result="shape" />
<feGaussianBlur stdDeviation="7.775" result="effect1_foregroundBlur_2001_67" />
</filter>
<filter
id={filterIds[8]}
x="13.587"
y="-18.488"
width="56.272"
height="51.81"
filterUnits="userSpaceOnUse"
colorInterpolationFilters="sRGB"
>
<feFlood floodOpacity="0" result="BackgroundImageFix" />
<feBlend in="SourceGraphic" in2="BackgroundImageFix" result="shape" />
<feGaussianBlur stdDeviation="6.957" result="effect1_foregroundBlur_2001_67" />
</filter>
<filter
id={filterIds[9]}
x="-15.526"
y="-31.297"
width="70.856"
height="69.306"
filterUnits="userSpaceOnUse"
colorInterpolationFilters="sRGB"
>
<feFlood floodOpacity="0" result="BackgroundImageFix" />
<feBlend in="SourceGraphic" in2="BackgroundImageFix" result="shape" />
<feGaussianBlur stdDeviation="5.876" result="effect1_foregroundBlur_2001_67" />
</filter>
<filter
id={filterIds[10]}
x="-14.168"
y="20.964"
width="55.501"
height="51.571"
filterUnits="userSpaceOnUse"
colorInterpolationFilters="sRGB"
>
<feFlood floodOpacity="0" result="BackgroundImageFix" />
<feBlend in="SourceGraphic" in2="BackgroundImageFix" result="shape" />
<feGaussianBlur stdDeviation="7.273" result="effect1_foregroundBlur_2001_67" />
</filter>
<linearGradient id={gradientId} x1="18.447" x2="52.153" y1="43.42" y2="15.004" gradientUnits="userSpaceOnUse">
<stop stopColor="#4893FC" />
<stop offset=".27" stopColor="#4893FC" />
<stop offset=".777" stopColor="#969DFF" />
<stop offset="1" stopColor="#BD99FE" />
</linearGradient>
</defs>
</svg>
);
};
export default GeminiLogo;

View File

@@ -2,7 +2,6 @@ import type { LLMProvider } from '../../types/app';
import ClaudeLogo from './ClaudeLogo';
import CodexLogo from './CodexLogo';
import CursorLogo from './CursorLogo';
import GeminiLogo from './GeminiLogo';
import OpenCodeLogo from './OpenCodeLogo';
type SessionProviderLogoProps = {
@@ -22,10 +21,6 @@ export default function SessionProviderLogo({
return <CodexLogo className={className} />;
}
if (provider === 'gemini') {
return <GeminiLogo className={className} />;
}
if (provider === 'opencode') {
return <OpenCodeLogo className={className} />;
}

View File

@@ -4,7 +4,6 @@ export const MCP_PROVIDER_NAMES: Record<McpProvider, string> = {
claude: 'Claude',
cursor: 'Cursor',
codex: 'Codex',
gemini: 'Gemini',
opencode: 'OpenCode',
};
@@ -12,7 +11,6 @@ export const MCP_SUPPORTED_SCOPES: Record<McpProvider, McpScope[]> = {
claude: ['user', 'project', 'local'],
cursor: ['user', 'project'],
codex: ['user', 'project'],
gemini: ['user', 'project'],
opencode: ['user', 'project'],
};
@@ -20,7 +18,6 @@ export const MCP_SUPPORTED_TRANSPORTS: Record<McpProvider, McpTransport[]> = {
claude: ['stdio', 'http', 'sse'],
cursor: ['stdio', 'http'],
codex: ['stdio', 'http'],
gemini: ['stdio', 'http', 'sse'],
opencode: ['stdio', 'http'],
};
@@ -32,7 +29,6 @@ export const MCP_PROVIDER_BUTTON_CLASSES: Record<McpProvider, string> = {
claude: 'bg-primary text-primary-foreground hover:bg-primary/90',
cursor: 'bg-primary text-primary-foreground hover:bg-primary/90',
codex: 'bg-primary text-primary-foreground hover:bg-primary/90',
gemini: 'bg-primary text-primary-foreground hover:bg-primary/90',
opencode: 'bg-primary text-primary-foreground hover:bg-primary/90',
};
@@ -40,7 +36,6 @@ export const MCP_SUPPORTS_WORKING_DIRECTORY: Record<McpProvider, boolean> = {
claude: false,
cursor: false,
codex: true,
gemini: true,
opencode: false,
};

View File

@@ -127,9 +127,9 @@ export default function McpServers({ selectedProvider, currentProjects }: McpSer
});
const globalButtonLabel = 'Add Global MCP Server';
const providerButtonLabel = `Add ${providerName} MCP Server`;
const globalAddDescription = 'Add Global MCP Server writes one common stdio or HTTP server to Claude, Cursor, Codex, and Gemini.';
const globalAddDescription = 'Add Global MCP Server writes one common stdio or HTTP server to Claude, Cursor, Codex, and OpenCode.';
const providerAddDescription = `${providerButtonLabel} only changes ${providerName}.`;
const globalModalDescription = 'Adds this MCP server to every provider: Claude, Cursor, Codex, and Gemini. '
const globalModalDescription = 'Adds this MCP server to every provider: Claude, Cursor, Codex, and OpenCode. '
+ 'Only stdio and HTTP transports are supported because the same config must work across all providers.';
return (

View File

@@ -30,13 +30,6 @@ const providerCards = [
iconContainerClassName: 'bg-gray-100 dark:bg-gray-800',
loginButtonClassName: 'bg-gray-800 hover:bg-gray-900 dark:bg-gray-700 dark:hover:bg-gray-600',
},
{
provider: 'gemini' as const,
title: 'Gemini',
connectedClassName: 'bg-teal-50 dark:bg-teal-900/20 border-teal-200 dark:border-teal-800',
iconContainerClassName: 'bg-teal-100 dark:bg-teal-900/30',
loginButtonClassName: 'bg-teal-600 hover:bg-teal-700',
},
{
provider: 'opencode' as const,
title: 'OpenCode',

View File

@@ -10,13 +10,12 @@ export type ProviderAuthStatus = {
export type ProviderAuthStatusMap = Record<LLMProvider, ProviderAuthStatus>;
export const CLI_PROVIDERS: LLMProvider[] = ['claude', 'cursor', 'codex', 'gemini', 'opencode'];
export const CLI_PROVIDERS: LLMProvider[] = ['claude', 'cursor', 'codex', 'opencode'];
export const PROVIDER_AUTH_STATUS_ENDPOINTS: Record<LLMProvider, string> = {
claude: '/api/providers/claude/auth/status',
cursor: '/api/providers/cursor/auth/status',
codex: '/api/providers/codex/auth/status',
gemini: '/api/providers/gemini/auth/status',
opencode: '/api/providers/opencode/auth/status',
};
@@ -24,6 +23,5 @@ export const createInitialProviderAuthStatusMap = (loading = true): ProviderAuth
claude: { authenticated: false, email: null, method: null, error: null, loading },
cursor: { authenticated: false, email: null, method: null, error: null, loading },
codex: { authenticated: false, email: null, method: null, error: null, loading },
gemini: { authenticated: false, email: null, method: null, error: null, loading },
opencode: { authenticated: false, email: null, method: null, error: null, loading },
});

View File

@@ -1,4 +1,4 @@
import { ExternalLink, KeyRound, X } from 'lucide-react';
import { X } from 'lucide-react';
import StandaloneShell from '../../standalone-shell/view/StandaloneShell';
import { DEFAULT_PROJECT_FOR_EMPTY_SHELL, IS_PLATFORM } from '../../../constants/config';
import type { LLMProvider } from '../../../types/app';
@@ -41,7 +41,7 @@ const getProviderCommand = ({
return 'opencode auth login';
}
return 'gemini status';
return 'claude --dangerously-skip-permissions /login';
};
const getProviderTitle = (provider: LLMProvider) => {
@@ -49,7 +49,7 @@ const getProviderTitle = (provider: LLMProvider) => {
if (provider === 'cursor') return 'Cursor CLI Login';
if (provider === 'codex') return 'Codex CLI Login';
if (provider === 'opencode') return 'OpenCode CLI Login';
return 'Gemini CLI Configuration';
return 'Claude CLI Login';
};
export default function ProviderLoginModal({
@@ -87,61 +87,7 @@ export default function ProviderLoginModal({
</div>
<div className="flex-1 overflow-hidden">
{provider === 'gemini' ? (
<div className="flex h-full flex-col items-center justify-center bg-gray-50 p-8 text-center dark:bg-gray-900/50">
<div className="mb-6 flex h-16 w-16 items-center justify-center rounded-full bg-blue-100 dark:bg-blue-900/30">
<KeyRound className="h-8 w-8 text-blue-600 dark:text-blue-400" />
</div>
<h4 className="mb-3 text-xl font-medium text-gray-900 dark:text-white">Setup Gemini API Access</h4>
<p className="mb-8 max-w-md text-gray-600 dark:text-gray-400">
The Gemini CLI requires an API key to function. Configure it in your terminal first.
</p>
<div className="w-full max-w-lg rounded-xl border border-gray-200 bg-white p-6 text-left shadow-sm dark:border-gray-700 dark:bg-gray-800">
<ol className="space-y-4">
<li className="flex gap-4">
<div className="flex h-6 w-6 flex-shrink-0 items-center justify-center rounded-full bg-blue-100 text-sm font-medium text-blue-600 dark:bg-blue-900/50 dark:text-blue-400">
1
</div>
<div>
<p className="mb-1 text-sm font-medium text-gray-900 dark:text-white">Get your API key</p>
<a
href="https://aistudio.google.com/app/apikey"
target="_blank"
rel="noreferrer"
className="flex inline-flex items-center gap-1 text-sm text-blue-600 hover:underline dark:text-blue-400"
>
Google AI Studio <ExternalLink className="h-3 w-3" />
</a>
</div>
</li>
<li className="flex gap-4">
<div className="flex h-6 w-6 flex-shrink-0 items-center justify-center rounded-full bg-blue-100 text-sm font-medium text-blue-600 dark:bg-blue-900/50 dark:text-blue-400">
2
</div>
<div>
<p className="mb-1 text-sm font-medium text-gray-900 dark:text-white">Run configuration</p>
<p className="mb-2 text-sm text-gray-600 dark:text-gray-400">Open your terminal and run:</p>
<code className="block rounded bg-gray-100 px-3 py-2 font-mono text-sm text-pink-600 dark:bg-gray-900 dark:text-pink-400">
gemini config set api_key YOUR_KEY
</code>
</div>
</li>
</ol>
</div>
<button
onClick={onClose}
className="mt-8 rounded-lg bg-blue-600 px-6 py-2.5 font-medium text-white transition-colors hover:bg-blue-700"
>
Done
</button>
</div>
) : (
<StandaloneShell project={DEFAULT_PROJECT_FOR_EMPTY_SHELL} command={command} onComplete={handleComplete} minimal={true} />
)}
<StandaloneShell project={DEFAULT_PROJECT_FOR_EMPTY_SHELL} command={command} onComplete={handleComplete} minimal={true} />
</div>
</div>
</div>

View File

@@ -39,7 +39,7 @@ export const SETTINGS_MAIN_TABS: SettingsMainTabMeta[] = [
{ id: 'about', label: 'About', keywords: 'about version info', icon: Info },
];
export const AGENT_PROVIDERS: AgentProvider[] = ['claude', 'cursor', 'codex', 'gemini', 'opencode'];
export const AGENT_PROVIDERS: AgentProvider[] = ['claude', 'cursor', 'codex', 'opencode'];
export const AGENT_CATEGORIES: AgentCategory[] = ['account', 'permissions', 'mcp'];
export const DEFAULT_PROJECT_SORT_ORDER: ProjectSortOrder = 'name';

View File

@@ -14,7 +14,6 @@ import type {
CodeEditorSettingsState,
CodexPermissionMode,
CursorPermissionsState,
GeminiPermissionMode,
NotificationPreferencesState,
ProjectSortOrder,
SettingsMainTab,
@@ -159,7 +158,6 @@ export function useSettingsController({ isOpen, initialTab }: UseSettingsControl
createDefaultNotificationPreferences()
));
const [codexPermissionMode, setCodexPermissionMode] = useState<CodexPermissionMode>('default');
const [geminiPermissionMode, setGeminiPermissionMode] = useState<GeminiPermissionMode>('default');
const [showLoginModal, setShowLoginModal] = useState(false);
const [loginProvider, setLoginProvider] = useState<ActiveLoginProvider>('');
@@ -198,12 +196,6 @@ export function useSettingsController({ isOpen, initialTab }: UseSettingsControl
);
setCodexPermissionMode(toCodexPermissionMode(savedCodexSettings.permissionMode));
const savedGeminiSettings = parseJson<{ permissionMode?: GeminiPermissionMode }>(
localStorage.getItem('gemini-settings'),
{},
);
setGeminiPermissionMode(savedGeminiSettings.permissionMode || 'default');
try {
const notificationResponse = await authenticatedFetch('/api/settings/notification-preferences');
if (notificationResponse.ok) {
@@ -276,11 +268,6 @@ export function useSettingsController({ isOpen, initialTab }: UseSettingsControl
lastUpdated: now,
}));
localStorage.setItem('gemini-settings', JSON.stringify({
permissionMode: geminiPermissionMode,
lastUpdated: now,
}));
const notificationResponse = await authenticatedFetch('/api/settings/notification-preferences', {
method: 'PUT',
body: JSON.stringify(notificationPreferences),
@@ -303,7 +290,6 @@ export function useSettingsController({ isOpen, initialTab }: UseSettingsControl
cursorPermissions.disallowedCommands,
cursorPermissions.skipPermissions,
notificationPreferences,
geminiPermissionMode,
projectSortOrder,
]);
@@ -409,8 +395,6 @@ export function useSettingsController({ isOpen, initialTab }: UseSettingsControl
codexPermissionMode,
setCodexPermissionMode,
providerAuthStatus,
geminiPermissionMode,
setGeminiPermissionMode,
openLoginForProvider,
showLoginModal,
setShowLoginModal,

View File

@@ -9,7 +9,6 @@ export type AgentCategory = 'account' | 'permissions' | 'mcp' | 'skills';
export type ProjectSortOrder = 'name' | 'date';
export type SaveStatus = 'success' | 'error' | null;
export type CodexPermissionMode = 'default' | 'acceptEdits' | 'bypassPermissions';
export type GeminiPermissionMode = 'default' | 'auto_edit' | 'yolo';
export type SettingsProject = {
name: string;

View File

@@ -52,8 +52,6 @@ function Settings({ isOpen, onClose, projects = [], initialTab = 'agents' }: Set
codexPermissionMode,
setCodexPermissionMode,
providerAuthStatus,
geminiPermissionMode,
setGeminiPermissionMode,
openLoginForProvider,
showLoginModal,
setShowLoginModal,
@@ -187,8 +185,6 @@ function Settings({ isOpen, onClose, projects = [], initialTab = 'agents' }: Set
onCursorPermissionsChange={setCursorPermissions}
codexPermissionMode={codexPermissionMode}
onCodexPermissionModeChange={setCodexPermissionMode}
geminiPermissionMode={geminiPermissionMode}
onGeminiPermissionModeChange={setGeminiPermissionMode}
projects={projects}
/>
)}

View File

@@ -12,7 +12,7 @@ type AgentListItemProps = {
type AgentConfig = {
name: string;
color: 'blue' | 'purple' | 'gray' | 'indigo' | 'zinc';
color: 'blue' | 'purple' | 'gray' | 'zinc';
};
const agentConfig: Record<AgentProvider, AgentConfig> = {
@@ -28,10 +28,6 @@ const agentConfig: Record<AgentProvider, AgentConfig> = {
name: 'Codex',
color: 'gray',
},
gemini: {
name: 'Gemini',
color: 'indigo',
},
opencode: {
name: 'OpenCode',
color: 'zinc',
@@ -48,9 +44,6 @@ const colorClasses = {
gray: {
dot: 'bg-foreground/60',
},
indigo: {
dot: 'bg-indigo-500',
},
zinc: {
dot: 'bg-zinc-500',
},

View File

@@ -16,8 +16,6 @@ export default function AgentsSettingsTab({
onCursorPermissionsChange,
codexPermissionMode,
onCodexPermissionModeChange,
geminiPermissionMode,
onGeminiPermissionModeChange,
projects,
}: AgentsSettingsTabProps) {
const [selectedAgent, setSelectedAgent] = useState<AgentProvider>('claude');
@@ -29,7 +27,7 @@ export default function AgentsSettingsTab({
), [selectedAgent]);
const visibleAgents = useMemo<AgentProvider[]>(() => {
return ['claude', 'cursor', 'codex', 'gemini', 'opencode'];
return ['claude', 'cursor', 'codex', 'opencode'];
}, []);
const agentContextById = useMemo<Record<AgentProvider, AgentContext>>(() => ({
@@ -45,10 +43,6 @@ export default function AgentsSettingsTab({
authStatus: providerAuthStatus.codex,
onLogin: () => onProviderLogin('codex'),
},
gemini: {
authStatus: providerAuthStatus.gemini,
onLogin: () => onProviderLogin('gemini'),
},
opencode: {
authStatus: providerAuthStatus.opencode,
onLogin: () => onProviderLogin('opencode'),
@@ -58,7 +52,6 @@ export default function AgentsSettingsTab({
providerAuthStatus.claude,
providerAuthStatus.codex,
providerAuthStatus.cursor,
providerAuthStatus.gemini,
providerAuthStatus.opencode,
]);
@@ -95,8 +88,6 @@ export default function AgentsSettingsTab({
onCursorPermissionsChange={onCursorPermissionsChange}
codexPermissionMode={codexPermissionMode}
onCodexPermissionModeChange={onCodexPermissionModeChange}
geminiPermissionMode={geminiPermissionMode}
onGeminiPermissionModeChange={onGeminiPermissionModeChange}
projects={projects}
/>
</div>

View File

@@ -7,7 +7,6 @@ const AGENT_NAMES: Record<AgentProvider, string> = {
claude: 'Claude',
cursor: 'Cursor',
codex: 'Codex',
gemini: 'Gemini',
opencode: 'OpenCode',
};
@@ -24,7 +23,6 @@ export default function AgentSelectorSection({
const dotColor =
agent === 'claude' ? 'bg-blue-500' :
agent === 'cursor' ? 'bg-purple-500' :
agent === 'gemini' ? 'bg-indigo-500' :
agent === 'opencode' ? 'bg-zinc-500' : 'bg-foreground/60';
return (

View File

@@ -45,15 +45,6 @@ const agentConfig: Record<AgentProvider, AgentVisualConfig> = {
subtextClass: 'text-gray-700 dark:text-gray-300',
buttonClass: 'bg-gray-800 hover:bg-gray-900 active:bg-gray-950 dark:bg-gray-700 dark:hover:bg-gray-600 dark:active:bg-gray-500',
},
gemini: {
name: 'Gemini',
description: 'Google Gemini AI assistant',
bgClass: 'bg-indigo-50 dark:bg-indigo-900/20',
borderClass: 'border-indigo-200 dark:border-indigo-800',
textClass: 'text-indigo-900 dark:text-indigo-100',
subtextClass: 'text-indigo-700 dark:text-indigo-300',
buttonClass: 'bg-indigo-600 hover:bg-indigo-700 active:bg-indigo-800',
},
opencode: {
name: 'OpenCode',
description: 'OpenCode CLI assistant',

View File

@@ -2,7 +2,7 @@ import { useState } from 'react';
import { AlertTriangle, Plus, Shield, X } from 'lucide-react';
import { useTranslation } from 'react-i18next';
import { Button, Input } from '../../../../../../../shared/view/ui';
import type { CodexPermissionMode, GeminiPermissionMode } from '../../../../../types/types';
import type { CodexPermissionMode } from '../../../../../types/types';
const COMMON_CLAUDE_TOOLS = [
'Bash(git log:*)',
@@ -579,111 +579,7 @@ function CodexPermissions({ permissionMode, onPermissionModeChange }: Omit<Codex
);
}
type GeminiPermissionsProps = {
agent: 'gemini';
permissionMode: GeminiPermissionMode;
onPermissionModeChange: (value: GeminiPermissionMode) => void;
};
// Gemini Permissions
function GeminiPermissions({ permissionMode, onPermissionModeChange }: Omit<GeminiPermissionsProps, 'agent'>) {
const { t } = useTranslation(['settings', 'chat']);
return (
<div className="space-y-6">
<div className="space-y-4">
<div className="flex items-center gap-3">
<Shield className="h-5 w-5 text-green-500" />
<h3 className="text-lg font-medium text-foreground">
{t('gemini.permissionMode')}
</h3>
</div>
<p className="text-sm text-muted-foreground">
{t('gemini.description')}
</p>
{/* Default Mode */}
<div
className={`cursor-pointer rounded-lg border p-4 transition-all ${permissionMode === 'default'
? 'border-border bg-accent'
: 'border-border bg-card/50 active:border-border active:bg-accent/50'
}`}
onClick={() => onPermissionModeChange('default')}
>
<label className="flex cursor-pointer items-start gap-3">
<input
type="radio"
name="geminiPermissionMode"
checked={permissionMode === 'default'}
onChange={() => onPermissionModeChange('default')}
className="mt-1 h-4 w-4 text-green-600"
/>
<div>
<div className="font-medium text-foreground">{t('gemini.modes.default.title')}</div>
<div className="text-sm text-muted-foreground">
{t('gemini.modes.default.description')}
</div>
</div>
</label>
</div>
{/* Auto Edit Mode */}
<div
className={`cursor-pointer rounded-lg border p-4 transition-all ${permissionMode === 'auto_edit'
? 'border-green-400 bg-green-50 dark:border-green-600 dark:bg-green-900/20'
: 'border-border bg-card/50 active:border-border active:bg-accent/50'
}`}
onClick={() => onPermissionModeChange('auto_edit')}
>
<label className="flex cursor-pointer items-start gap-3">
<input
type="radio"
name="geminiPermissionMode"
checked={permissionMode === 'auto_edit'}
onChange={() => onPermissionModeChange('auto_edit')}
className="mt-1 h-4 w-4 text-green-600"
/>
<div>
<div className="font-medium text-green-900 dark:text-green-100">{t('gemini.modes.autoEdit.title')}</div>
<div className="text-sm text-green-700 dark:text-green-300">
{t('gemini.modes.autoEdit.description')}
</div>
</div>
</label>
</div>
{/* YOLO Mode */}
<div
className={`cursor-pointer rounded-lg border p-4 transition-all ${permissionMode === 'yolo'
? 'border-orange-400 bg-orange-50 dark:border-orange-600 dark:bg-orange-900/20'
: 'border-border bg-card/50 active:border-border active:bg-accent/50'
}`}
onClick={() => onPermissionModeChange('yolo')}
>
<label className="flex cursor-pointer items-start gap-3">
<input
type="radio"
name="geminiPermissionMode"
checked={permissionMode === 'yolo'}
onChange={() => onPermissionModeChange('yolo')}
className="mt-1 h-4 w-4 text-orange-600"
/>
<div>
<div className="flex items-center gap-2 font-medium text-orange-900 dark:text-orange-100">
{t('gemini.modes.yolo.title')}
<AlertTriangle className="h-4 w-4" />
</div>
<div className="text-sm text-orange-700 dark:text-orange-300">
{t('gemini.modes.yolo.description')}
</div>
</div>
</label>
</div>
</div>
</div>
);
}
type PermissionsContentProps = ClaudePermissionsProps | CursorPermissionsProps | CodexPermissionsProps | GeminiPermissionsProps;
type PermissionsContentProps = ClaudePermissionsProps | CursorPermissionsProps | CodexPermissionsProps;
export default function PermissionsContent(props: PermissionsContentProps) {
if (props.agent === 'claude') {
@@ -694,9 +590,5 @@ export default function PermissionsContent(props: PermissionsContentProps) {
return <CursorPermissions {...props} />;
}
if (props.agent === 'gemini') {
return <GeminiPermissions {...props} />;
}
return <CodexPermissions {...props} />;
}

View File

@@ -5,7 +5,6 @@ import type {
ClaudePermissionsState,
CursorPermissionsState,
CodexPermissionMode,
GeminiPermissionMode,
SettingsProject,
} from '../../../types/types';
@@ -26,8 +25,6 @@ export type AgentsSettingsTabProps = {
onCursorPermissionsChange: (value: CursorPermissionsState) => void;
codexPermissionMode: CodexPermissionMode;
onCodexPermissionModeChange: (value: CodexPermissionMode) => void;
geminiPermissionMode: GeminiPermissionMode;
onGeminiPermissionModeChange: (value: GeminiPermissionMode) => void;
projects: SettingsProject[];
};
@@ -55,7 +52,5 @@ export type AgentCategoryContentSectionProps = {
onCursorPermissionsChange: (value: CursorPermissionsState) => void;
codexPermissionMode: CodexPermissionMode;
onCodexPermissionModeChange: (value: CodexPermissionMode) => void;
geminiPermissionMode: GeminiPermissionMode;
onGeminiPermissionModeChange: (value: GeminiPermissionMode) => void;
projects: SettingsProject[];
};

View File

@@ -59,7 +59,6 @@ const PROVIDER_NAMES: Record<SkillsProvider, string> = {
claude: 'Claude',
codex: 'Codex',
cursor: 'Cursor',
gemini: 'Gemini',
opencode: 'OpenCode',
};
@@ -67,7 +66,6 @@ const PROVIDER_SKILL_PATHS: Record<Exclude<SkillsProvider, 'opencode'>, string>
claude: '~/.claude/skills/<skill-name>/SKILL.md',
codex: '~/.agents/skills/<skill-name>/SKILL.md',
cursor: '~/.cursor/skills/<skill-name>/SKILL.md',
gemini: '~/.gemini/skills/<skill-name>/SKILL.md',
};
const SCOPE_LABELS: Record<SkillsScope, string> = {

View File

@@ -17,8 +17,7 @@
"tool": "Werkzeug",
"claude": "Claude",
"cursor": "Cursor",
"codex": "Codex",
"gemini": "Gemini"
"codex": "Codex"
},
"tools": {
"settings": "Werkzeugeinstellungen",
@@ -103,24 +102,6 @@
},
"technicalDetails": "Technische Details"
},
"gemini": {
"permissionMode": "Gemini-Berechtigungsmodus",
"description": "Steuert, wie Gemini CLI Vorgangsgenehmigungen handhabt.",
"modes": {
"default": {
"title": "Standard (Genehmigung erforderlich)",
"description": "Gemini fordert vor der Ausführung von Befehlen, dem Schreiben von Dateien und dem Abrufen von Web-Ressourcen eine Genehmigung an."
},
"autoEdit": {
"title": "Auto-Bearbeitung (Dateigenehmigungen überspringen)",
"description": "Gemini genehmigt automatisch Dateibearbeitungen und Web-Abrufe, fragt aber weiterhin bei Shell-Befehlen nach."
},
"yolo": {
"title": "YOLO (Alle Berechtigungen umgehen)",
"description": "Gemini führt alle Vorgänge ohne Rückfrage aus. Vorsicht ist geboten."
}
}
},
"input": {
"placeholder": "/ für Befehle, @ für Dateien eingeben oder {{provider}} etwas fragen...",
"placeholderDefault": "Nachricht eingeben...",
@@ -152,7 +133,6 @@
"claude": "Bereit, Claude mit {{model}} zu verwenden. Gib unten deine Nachricht ein.",
"cursor": "Bereit, Cursor mit {{model}} zu verwenden. Gib unten deine Nachricht ein.",
"codex": "Bereit, Codex mit {{model}} zu verwenden. Gib unten deine Nachricht ein.",
"gemini": "Bereit, Gemini mit {{model}} zu verwenden. Gib unten deine Nachricht ein.",
"default": "Wähl oben einen Anbieter, um zu beginnen"
},
"pressToSearch": "Drücke <kbd>{{shortcut}}</kbd>, um Sitzungen, Dateien und Commits zu durchsuchen"

View File

@@ -322,9 +322,6 @@
},
"codex": {
"description": "OpenAI Codex KI-Assistent"
},
"gemini": {
"description": "Google Gemini KI-Assistent"
}
},
"connectionStatus": "Verbindungsstatus",

View File

@@ -18,7 +18,6 @@
"claude": "Claude",
"cursor": "Cursor",
"codex": "Codex",
"gemini": "Gemini",
"opencode": "OpenCode"
},
"tools": {
@@ -104,24 +103,6 @@
},
"technicalDetails": "Technical details"
},
"gemini": {
"permissionMode": "Gemini Permission Mode",
"description": "Control how Gemini CLI handles operation approvals.",
"modes": {
"default": {
"title": "Standard (Ask for Approval)",
"description": "Gemini will prompt for approval before executing commands, writing files, and fetching web resources."
},
"autoEdit": {
"title": "Auto Edit (Skip File Approvals)",
"description": "Gemini will automatically approve file edits and web fetches, but will still prompt for shell commands."
},
"yolo": {
"title": "YOLO (Bypass All Permissions)",
"description": "Gemini will execute all operations without asking for approval. Exercise caution."
}
}
},
"voice": {
"input": "Voice input",
"stopRecording": "Stop recording",
@@ -171,7 +152,6 @@
"claude": "Ready to use Claude with {{model}}. Start typing your message below.",
"cursor": "Ready to use Cursor with {{model}}. Start typing your message below.",
"codex": "Ready to use Codex with {{model}}. Start typing your message below.",
"gemini": "Ready to use Gemini with {{model}}. Start typing your message below.",
"opencode": "Ready to use OpenCode with {{model}}. Start typing your message below.",
"default": "Select a provider above to begin"
},

View File

@@ -349,9 +349,6 @@
"codex": {
"description": "OpenAI Codex AI assistant"
},
"gemini": {
"description": "Google Gemini AI assistant"
},
"opencode": {
"description": "OpenCode CLI assistant"
}

View File

@@ -18,7 +18,6 @@
"claude": "Claude",
"cursor": "Cursor",
"codex": "Codex",
"gemini": "Gemini",
"opencode": "OpenCode"
},
"tools": {
@@ -104,24 +103,6 @@
},
"technicalDetails": "Détails techniques"
},
"gemini": {
"permissionMode": "Mode de permission Gemini",
"description": "Contrôlez comment Gemini CLI gère les approbations d'opérations.",
"modes": {
"default": {
"title": "Standard (demander l'approbation)",
"description": "Gemini demandera une approbation avant d'exécuter des commandes, d'écrire des fichiers et de récupérer des ressources web."
},
"autoEdit": {
"title": "Modification automatique (ignorer les approbations de fichiers)",
"description": "Gemini approuvera automatiquement les modifications de fichiers et les récupérations web, mais demandera toujours pour les commandes shell."
},
"yolo": {
"title": "YOLO (contourner toutes les permissions)",
"description": "Gemini exécutera toutes les opérations sans demander d'approbation. Utilisez avec prudence."
}
}
},
"input": {
"placeholder": "Tapez / pour les commandes, @ pour les fichiers, ou posez une question à {{provider}}...",
"placeholderDefault": "Tapez votre message...",
@@ -153,7 +134,6 @@
"claude": "Prêt à utiliser Claude avec {{model}}. Commencez à taper votre message ci-dessous.",
"cursor": "Prêt à utiliser Cursor avec {{model}}. Commencez à taper votre message ci-dessous.",
"codex": "Prêt à utiliser Codex avec {{model}}. Commencez à taper votre message ci-dessous.",
"gemini": "Prêt à utiliser Gemini avec {{model}}. Commencez à taper votre message ci-dessous.",
"opencode": "Prêt à utiliser OpenCode avec {{model}}. Commencez à taper votre message ci-dessous.",
"default": "Sélectionnez un fournisseur ci-dessus pour commencer"
},

View File

@@ -323,9 +323,6 @@
"codex": {
"description": "Assistant IA Codex d'OpenAI"
},
"gemini": {
"description": "Assistant IA Gemini de Google"
},
"opencode": {
"description": "Assistant CLI OpenCode"
}

View File

@@ -17,8 +17,7 @@
"tool": "Strumento",
"claude": "Claude",
"cursor": "Cursor",
"codex": "Codex",
"gemini": "Gemini"
"codex": "Codex"
},
"tools": {
"settings": "Impostazioni strumento",
@@ -103,24 +102,6 @@
},
"technicalDetails": "Dettagli tecnici"
},
"gemini": {
"permissionMode": "Modalità permessi Gemini",
"description": "Controlla come Gemini CLI gestisce le approvazioni delle operazioni.",
"modes": {
"default": {
"title": "Standard (chiedi approvazione)",
"description": "Gemini chiederà l'approvazione prima di eseguire comandi, scrivere file e recuperare risorse web."
},
"autoEdit": {
"title": "Modifica automatica (salta approvazioni file)",
"description": "Gemini approverà automaticamente modifiche ai file e recupero web, ma chiederà conferma per i comandi shell."
},
"yolo": {
"title": "YOLO (ignora tutti i permessi)",
"description": "Gemini eseguirà tutte le operazioni senza chiedere approvazione. Usa con cautela."
}
}
},
"input": {
"placeholder": "Digita / per i comandi, @ per i file, o chiedi qualcosa a {{provider}}...",
"placeholderDefault": "Scrivi il tuo messaggio...",
@@ -152,7 +133,6 @@
"claude": "Pronto a usare Claude con {{model}}. Inizia a digitare il tuo messaggio qui sotto.",
"cursor": "Pronto a usare Cursor con {{model}}. Inizia a digitare il tuo messaggio qui sotto.",
"codex": "Pronto a usare Codex con {{model}}. Inizia a digitare il tuo messaggio qui sotto.",
"gemini": "Pronto a usare Gemini con {{model}}. Inizia a digitare il tuo messaggio qui sotto.",
"default": "Seleziona un provider sopra per iniziare"
},
"pressToSearch": "Premi <kbd>{{shortcut}}</kbd> per cercare sessioni, file e commit"

View File

@@ -322,9 +322,6 @@
},
"codex": {
"description": "Assistente AI OpenAI Codex"
},
"gemini": {
"description": "Assistente AI Google Gemini"
}
},
"connectionStatus": "Stato connessione",

View File

@@ -322,9 +322,6 @@
},
"codex": {
"description": "OpenAI Codex AIアシスタント"
},
"gemini": {
"description": "Google Gemini AIアシスタント"
}
},
"connectionStatus": "接続状態",

View File

@@ -17,8 +17,7 @@
"tool": "도구",
"claude": "Claude",
"cursor": "Cursor",
"codex": "Codex",
"gemini": "Gemini"
"codex": "Codex"
},
"tools": {
"settings": "도구 설정",
@@ -134,7 +133,6 @@
"claude": "{{model}} 모델로 Claude를 사용할 준비가 되었습니다. 아래에 메시지를 입력하세요.",
"cursor": "{{model}} 모델로 Cursor를 사용할 준비가 되었습니다. 아래에 메시지를 입력하세요.",
"codex": "{{model}} 모델로 Codex를 사용할 준비가 되었습니다. 아래에 메시지를 입력하세요.",
"gemini": "{{model}} 모델로 Gemini를 사용할 준비가 되었습니다. 아래에 메시지를 입력하세요.",
"default": "시작하려면 위에서 제공자를 선택하세요"
},
"pressToSearch": "<kbd>{{shortcut}}</kbd>를 눌러 세션, 파일 및 커밋을 검색하세요"

View File

@@ -322,9 +322,6 @@
},
"codex": {
"description": "OpenAI Codex AI 어시스턴트"
},
"gemini": {
"description": "Google Gemini AI 어시스턴트"
}
},
"connectionStatus": "연결 상태",

View File

@@ -17,8 +17,7 @@
"tool": "Инструмент",
"claude": "Claude",
"cursor": "Cursor",
"codex": "Codex",
"gemini": "Gemini"
"codex": "Codex"
},
"tools": {
"settings": "Настройки инструмента",
@@ -103,24 +102,6 @@
},
"technicalDetails": "Технические детали"
},
"gemini": {
"permissionMode": "Режим разрешений Gemini",
"description": "Управление тем, как Gemini CLI обрабатывает подтверждения операций.",
"modes": {
"default": {
"title": "Стандартный (запрашивать подтверждение)",
"description": "Gemini будет запрашивать подтверждение перед выполнением команд, записью файлов и получением веб-ресурсов."
},
"autoEdit": {
"title": "Автоматическое редактирование (пропускать подтверждения файлов)",
"description": "Gemini будет автоматически подтверждать редактирование файлов и веб-запросы, но все еще будет запрашивать подтверждение для команд оболочки."
},
"yolo": {
"title": "YOLO (обход всех разрешений)",
"description": "Gemini будет выполнять все операции без запроса подтверждения. Будьте осторожны."
}
}
},
"input": {
"placeholder": "Введите / для команд, @ для файлов, или спросите {{provider}} что угодно...",
"placeholderDefault": "Введите ваше сообщение...",
@@ -152,7 +133,6 @@
"claude": "Готов использовать Claude с {{model}}. Начните вводить сообщение ниже.",
"cursor": "Готов использовать Cursor с {{model}}. Начните вводить сообщение ниже.",
"codex": "Готов использовать Codex с {{model}}. Начните вводить сообщение ниже.",
"gemini": "Готов использовать Gemini с {{model}}. Начните вводить сообщение ниже.",
"default": "Выберите провайдера выше для начала"
},
"pressToSearch": "Нажмите <kbd>{{shortcut}}</kbd>, чтобы искать сессии, файлы и коммиты"

View File

@@ -322,9 +322,6 @@
},
"codex": {
"description": "AI-ассистент OpenAI Codex"
},
"gemini": {
"description": "AI-ассистент Google Gemini"
}
},
"connectionStatus": "Статус подключения",

View File

@@ -17,8 +17,7 @@
"tool": "Araç",
"claude": "Claude",
"cursor": "Cursor",
"codex": "Codex",
"gemini": "Gemini"
"codex": "Codex"
},
"tools": {
"settings": "Araç Ayarları",
@@ -103,24 +102,6 @@
},
"technicalDetails": "Teknik ayrıntılar"
},
"gemini": {
"permissionMode": "Gemini İzin Modu",
"description": "Gemini CLI'ın işlem onaylarını nasıl yönettiğini kontrol et.",
"modes": {
"default": {
"title": "Standart (Onay İste)",
"description": "Gemini, komut çalıştırmadan, dosya yazmadan ve web kaynağı getirmeden önce onay ister."
},
"autoEdit": {
"title": "Otomatik Düzenleme (Dosya Onaylarını Atla)",
"description": "Gemini dosya düzenlemelerini ve web getirmelerini otomatik onaylar, ama shell komutları için yine de onay ister."
},
"yolo": {
"title": "YOLO (Tüm İzinleri Atla)",
"description": "Gemini tüm işlemleri onay almadan çalıştırır. Dikkatli kullan."
}
}
},
"input": {
"placeholder": "Komutlar için /, dosyalar için @ yaz ya da {{provider}}'a her şeyi sor...",
"placeholderDefault": "Mesajını yaz...",
@@ -152,7 +133,6 @@
"claude": "Claude'u {{model}} ile kullanmaya hazır. Mesajını aşağıya yazmaya başla.",
"cursor": "Cursor'ı {{model}} ile kullanmaya hazır. Mesajını aşağıya yazmaya başla.",
"codex": "Codex'i {{model}} ile kullanmaya hazır. Mesajını aşağıya yazmaya başla.",
"gemini": "Gemini'yi {{model}} ile kullanmaya hazır. Mesajını aşağıya yazmaya başla.",
"default": "Başlamak için yukarıdan bir sağlayıcı seç"
},
"pressToSearch": "Oturumlarda, dosyalarda ve commit'lerde arama yapmak için <kbd>{{shortcut}}</kbd> tuşlarına bas"

View File

@@ -323,9 +323,6 @@
},
"codex": {
"description": "OpenAI Codex AI asistanı"
},
"gemini": {
"description": "Google Gemini AI asistanı"
}
},
"connectionStatus": "Bağlantı Durumu",

View File

@@ -17,8 +17,7 @@
"tool": "工具",
"claude": "Claude",
"cursor": "Cursor",
"codex": "Codex",
"gemini": "Gemini"
"codex": "Codex"
},
"tools": {
"settings": "工具设置",
@@ -134,7 +133,6 @@
"claude": "准备好使用带有 {{model}} 的 Claude。请在下方开始输入您的消息。",
"cursor": "准备好使用带有 {{model}} 的 Cursor。请在下方开始输入您的消息。",
"codex": "准备好使用带有 {{model}} 的 Codex。请在下方开始输入您的消息。",
"gemini": "准备好使用带有 {{model}} 的 Gemini。请在下方开始输入您的消息。",
"default": "请在上方选择一个提供者以开始"
},
"pressToSearch": "按 <kbd>{{shortcut}}</kbd> 搜索会话、文件和提交"

View File

@@ -323,9 +323,6 @@
},
"codex": {
"description": "OpenAI Codex AI 助手"
},
"gemini": {
"description": "Google Gemini AI 助手"
}
},
"connectionStatus": "连接状态",

View File

@@ -17,8 +17,7 @@
"tool": "工具",
"claude": "Claude",
"cursor": "Cursor",
"codex": "Codex",
"gemini": "Gemini"
"codex": "Codex"
},
"tools": {
"settings": "工具設定",
@@ -170,7 +169,6 @@
"claude": "準備好使用 {{model}} 的 Claude。請在下方開始輸入您的訊息。",
"cursor": "準備好使用 {{model}} 的 Cursor。請在下方開始輸入您的訊息。",
"codex": "準備好使用 {{model}} 的 Codex。請在下方開始輸入您的訊息。",
"gemini": "準備好使用 {{model}} 的 Gemini。請在下方開始輸入您的訊息。",
"default": "請在上方選擇一個提供者以開始"
},
"pressToSearch": "按 <kbd>{{shortcut}}</kbd> 搜尋工作階段、檔案和提交"

View File

@@ -323,9 +323,6 @@
},
"codex": {
"description": "OpenAI Codex AI 助手"
},
"gemini": {
"description": "Google Gemini AI 助手"
}
},
"connectionStatus": "連線狀態",

View File

@@ -1,4 +1,4 @@
export type LLMProvider = 'claude' | 'cursor' | 'codex' | 'gemini' | 'opencode';
export type LLMProvider = 'claude' | 'cursor' | 'codex' | 'opencode';
export type ProviderModelOption = {
value: string;