Skip to content

Commit 2df8103

Browse files
committed
feat: add Gemini CLI integration using @google/gemini-cli-core
- Add GeminiCliHandler provider for OAuth-based Gemini access - Add gemini-cli type definitions and model configurations - Update provider registry to include gemini-cli - Add comprehensive tests for GeminiCliHandler - Add @google/gemini-cli-core as dependency (pending npm package) This integration allows users to authenticate with Gemini using the official Gemini CLI OAuth flow instead of API keys, providing a more secure and sustainable authentication method. Addresses #7353
1 parent b433d1f commit 2df8103

File tree

8 files changed

+999
-2
lines changed

8 files changed

+999
-2
lines changed

packages/types/src/provider-settings.ts

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@ import {
1212
doubaoModels,
1313
featherlessModels,
1414
fireworksModels,
15+
geminiCliModels,
1516
geminiModels,
1617
groqModels,
1718
ioIntelligenceModels,
@@ -440,7 +441,7 @@ export const getApiProtocol = (provider: ProviderName | undefined, modelId?: str
440441
}
441442

442443
export const MODELS_BY_PROVIDER: Record<
443-
Exclude<ProviderName, "fake-ai" | "human-relay" | "gemini-cli" | "lmstudio" | "openai" | "ollama">,
444+
Exclude<ProviderName, "fake-ai" | "human-relay" | "lmstudio" | "openai" | "ollama">,
444445
{ id: ProviderName; label: string; models: string[] }
445446
> = {
446447
anthropic: {
@@ -485,6 +486,11 @@ export const MODELS_BY_PROVIDER: Record<
485486
label: "Google Gemini",
486487
models: Object.keys(geminiModels),
487488
},
489+
"gemini-cli": {
490+
id: "gemini-cli",
491+
label: "Gemini CLI",
492+
models: Object.keys(geminiCliModels),
493+
},
488494
groq: { id: "groq", label: "Groq", models: Object.keys(groqModels) },
489495
"io-intelligence": {
490496
id: "io-intelligence",
Lines changed: 207 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,207 @@
1+
import type { ModelInfo } from "../model.js"
2+
3+
// Gemini CLI models - using the same models as regular Gemini
4+
// but accessed through the @google/gemini-cli-core library
5+
export type GeminiCliModelId = keyof typeof geminiCliModels
6+
7+
export const geminiCliDefaultModelId: GeminiCliModelId = "gemini-2.0-flash-001"
8+
9+
// Re-use the same model definitions as regular Gemini since they're the same models
10+
// just accessed through a different authentication mechanism (OAuth via CLI)
11+
export const geminiCliModels = {
12+
"gemini-2.5-flash-preview-04-17:thinking": {
13+
maxTokens: 65_535,
14+
contextWindow: 1_048_576,
15+
supportsImages: true,
16+
supportsPromptCache: false,
17+
inputPrice: 0.15,
18+
outputPrice: 3.5,
19+
maxThinkingTokens: 24_576,
20+
supportsReasoningBudget: true,
21+
requiredReasoningBudget: true,
22+
},
23+
"gemini-2.5-flash-preview-04-17": {
24+
maxTokens: 65_535,
25+
contextWindow: 1_048_576,
26+
supportsImages: true,
27+
supportsPromptCache: false,
28+
inputPrice: 0.15,
29+
outputPrice: 0.6,
30+
},
31+
"gemini-2.5-flash-preview-05-20:thinking": {
32+
maxTokens: 65_535,
33+
contextWindow: 1_048_576,
34+
supportsImages: true,
35+
supportsPromptCache: true,
36+
inputPrice: 0.15,
37+
outputPrice: 3.5,
38+
cacheReadsPrice: 0.0375,
39+
cacheWritesPrice: 1.0,
40+
maxThinkingTokens: 24_576,
41+
supportsReasoningBudget: true,
42+
requiredReasoningBudget: true,
43+
},
44+
"gemini-2.5-flash-preview-05-20": {
45+
maxTokens: 65_535,
46+
contextWindow: 1_048_576,
47+
supportsImages: true,
48+
supportsPromptCache: true,
49+
inputPrice: 0.15,
50+
outputPrice: 0.6,
51+
cacheReadsPrice: 0.0375,
52+
cacheWritesPrice: 1.0,
53+
},
54+
"gemini-2.5-flash": {
55+
maxTokens: 64_000,
56+
contextWindow: 1_048_576,
57+
supportsImages: true,
58+
supportsPromptCache: true,
59+
inputPrice: 0.3,
60+
outputPrice: 2.5,
61+
cacheReadsPrice: 0.075,
62+
cacheWritesPrice: 1.0,
63+
maxThinkingTokens: 24_576,
64+
supportsReasoningBudget: true,
65+
},
66+
"gemini-2.5-pro-exp-03-25": {
67+
maxTokens: 65_535,
68+
contextWindow: 1_048_576,
69+
supportsImages: true,
70+
supportsPromptCache: false,
71+
inputPrice: 0,
72+
outputPrice: 0,
73+
},
74+
"gemini-2.5-pro-preview-03-25": {
75+
maxTokens: 65_535,
76+
contextWindow: 1_048_576,
77+
supportsImages: true,
78+
supportsPromptCache: true,
79+
inputPrice: 2.5,
80+
outputPrice: 15,
81+
cacheReadsPrice: 0.625,
82+
cacheWritesPrice: 4.5,
83+
tiers: [
84+
{
85+
contextWindow: 200_000,
86+
inputPrice: 1.25,
87+
outputPrice: 10,
88+
cacheReadsPrice: 0.31,
89+
},
90+
{
91+
contextWindow: Infinity,
92+
inputPrice: 2.5,
93+
outputPrice: 15,
94+
cacheReadsPrice: 0.625,
95+
},
96+
],
97+
},
98+
"gemini-2.5-pro": {
99+
maxTokens: 64_000,
100+
contextWindow: 1_048_576,
101+
supportsImages: true,
102+
supportsPromptCache: true,
103+
inputPrice: 2.5,
104+
outputPrice: 15,
105+
cacheReadsPrice: 0.625,
106+
cacheWritesPrice: 4.5,
107+
maxThinkingTokens: 32_768,
108+
supportsReasoningBudget: true,
109+
requiredReasoningBudget: true,
110+
tiers: [
111+
{
112+
contextWindow: 200_000,
113+
inputPrice: 1.25,
114+
outputPrice: 10,
115+
cacheReadsPrice: 0.31,
116+
},
117+
{
118+
contextWindow: Infinity,
119+
inputPrice: 2.5,
120+
outputPrice: 15,
121+
cacheReadsPrice: 0.625,
122+
},
123+
],
124+
},
125+
"gemini-2.0-flash-001": {
126+
maxTokens: 8192,
127+
contextWindow: 1_048_576,
128+
supportsImages: true,
129+
supportsPromptCache: true,
130+
inputPrice: 0.1,
131+
outputPrice: 0.4,
132+
cacheReadsPrice: 0.025,
133+
cacheWritesPrice: 1.0,
134+
},
135+
"gemini-2.0-flash-lite-preview-02-05": {
136+
maxTokens: 8192,
137+
contextWindow: 1_048_576,
138+
supportsImages: true,
139+
supportsPromptCache: false,
140+
inputPrice: 0,
141+
outputPrice: 0,
142+
},
143+
"gemini-2.0-pro-exp-02-05": {
144+
maxTokens: 8192,
145+
contextWindow: 2_097_152,
146+
supportsImages: true,
147+
supportsPromptCache: false,
148+
inputPrice: 0,
149+
outputPrice: 0,
150+
},
151+
"gemini-2.0-flash-thinking-exp-01-21": {
152+
maxTokens: 65_536,
153+
contextWindow: 1_048_576,
154+
supportsImages: true,
155+
supportsPromptCache: false,
156+
inputPrice: 0,
157+
outputPrice: 0,
158+
},
159+
"gemini-2.0-flash-thinking-exp-1219": {
160+
maxTokens: 8192,
161+
contextWindow: 32_767,
162+
supportsImages: true,
163+
supportsPromptCache: false,
164+
inputPrice: 0,
165+
outputPrice: 0,
166+
},
167+
"gemini-2.0-flash-exp": {
168+
maxTokens: 8192,
169+
contextWindow: 1_048_576,
170+
supportsImages: true,
171+
supportsPromptCache: false,
172+
inputPrice: 0,
173+
outputPrice: 0,
174+
},
175+
"gemini-1.5-flash-002": {
176+
maxTokens: 8192,
177+
contextWindow: 1_048_576,
178+
supportsImages: true,
179+
supportsPromptCache: true,
180+
inputPrice: 0.15,
181+
outputPrice: 0.6,
182+
cacheReadsPrice: 0.0375,
183+
cacheWritesPrice: 1.0,
184+
tiers: [
185+
{
186+
contextWindow: 128_000,
187+
inputPrice: 0.075,
188+
outputPrice: 0.3,
189+
cacheReadsPrice: 0.01875,
190+
},
191+
{
192+
contextWindow: Infinity,
193+
inputPrice: 0.15,
194+
outputPrice: 0.6,
195+
cacheReadsPrice: 0.0375,
196+
},
197+
],
198+
},
199+
"gemini-1.5-pro-002": {
200+
maxTokens: 8192,
201+
contextWindow: 2_097_152,
202+
supportsImages: true,
203+
supportsPromptCache: false,
204+
inputPrice: 0,
205+
outputPrice: 0,
206+
},
207+
} as const satisfies Record<string, ModelInfo>

packages/types/src/providers/index.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@ export * from "./deepseek.js"
77
export * from "./doubao.js"
88
export * from "./featherless.js"
99
export * from "./fireworks.js"
10+
export * from "./gemini-cli.js"
1011
export * from "./gemini.js"
1112
export * from "./glama.js"
1213
export * from "./groq.js"

src/api/index.ts

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@ import {
1414
AnthropicVertexHandler,
1515
OpenAiHandler,
1616
LmStudioHandler,
17+
GeminiCliHandler,
1718
GeminiHandler,
1819
OpenAiNativeHandler,
1920
DeepSeekHandler,
@@ -102,6 +103,8 @@ export function buildApiHandler(configuration: ProviderSettings): ApiHandler {
102103
return new LmStudioHandler(options)
103104
case "gemini":
104105
return new GeminiHandler(options)
106+
case "gemini-cli":
107+
return new GeminiCliHandler(options)
105108
case "openai-native":
106109
return new OpenAiNativeHandler(options)
107110
case "deepseek":
@@ -149,7 +152,7 @@ export function buildApiHandler(configuration: ProviderSettings): ApiHandler {
149152
case "featherless":
150153
return new FeatherlessHandler(options)
151154
default:
152-
apiProvider satisfies "gemini-cli" | undefined
155+
apiProvider satisfies undefined
153156
return new AnthropicHandler(options)
154157
}
155158
}

0 commit comments

Comments
 (0)