ai-sdk-provider-gemini-cli-agentic 0.1.0 → 0.1.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +296 -0
- package/dist/index.cjs +29 -11
- package/dist/index.d.cts +4 -0
- package/dist/index.d.ts +4 -0
- package/dist/index.js +29 -11
- package/package.json +1 -1
package/README.md
ADDED
|
@@ -0,0 +1,296 @@
|
|
|
1
|
+
# ai-sdk-provider-gemini-cli-agentic
|
|
2
|
+
|
|
3
|
+
[](https://www.npmjs.com/package/ai-sdk-provider-gemini-cli-agentic)
|
|
4
|
+
[](./LICENSE)
|
|
5
|
+
|
|
6
|
+
[AI SDK](https://sdk.vercel.ai/docs) v6 provider for [Google Gemini CLI](https://github.com/google-gemini/gemini-cli) agentic mode.
|
|
7
|
+
|
|
8
|
+
This provider spawns `gemini` as a subprocess with `--output-format stream-json`, enabling full agentic capabilities like file system access, code editing, and tool execution through the AI SDK interface.
|
|
9
|
+
|
|
10
|
+
## Features
|
|
11
|
+
|
|
12
|
+
- **Full Agentic Support**: Access all Gemini CLI tools (file system, code editing, shell commands, etc.)
|
|
13
|
+
- **Streaming**: Real-time streaming of text and tool calls
|
|
14
|
+
- **Tool Streaming**: Watch tool calls and results as they happen
|
|
15
|
+
- **Approval Modes**: Control tool approval behavior (`default`, `auto_edit`, `yolo`)
|
|
16
|
+
- **Sandbox Mode**: Run in a sandboxed environment for safety
|
|
17
|
+
- **Session Resume**: Resume previous sessions
|
|
18
|
+
- **MCP Server Support**: Integrate with MCP servers
|
|
19
|
+
- **Custom Logging**: Built-in logging with customization support
|
|
20
|
+
- **AI SDK v6 Compatible**: Works with `generateText`, `streamText`, and `streamObject`
|
|
21
|
+
|
|
22
|
+
## Requirements
|
|
23
|
+
|
|
24
|
+
- [Gemini CLI](https://github.com/google-gemini/gemini-cli) installed and authenticated (or use `allowNpx: true`)
|
|
25
|
+
- Node.js 18+
|
|
26
|
+
- AI SDK v6+
|
|
27
|
+
|
|
28
|
+
## Installation
|
|
29
|
+
|
|
30
|
+
```bash
|
|
31
|
+
npm install ai-sdk-provider-gemini-cli-agentic ai
|
|
32
|
+
```
|
|
33
|
+
|
|
34
|
+
### Install Gemini CLI (Optional)
|
|
35
|
+
|
|
36
|
+
**Option 1**: Install globally (recommended for frequent use):
|
|
37
|
+
|
|
38
|
+
```bash
|
|
39
|
+
npm install -g @google/gemini-cli
|
|
40
|
+
```
|
|
41
|
+
|
|
42
|
+
**Option 2**: Use `allowNpx: true` to run via npx (no global install needed):
|
|
43
|
+
|
|
44
|
+
```javascript
|
|
45
|
+
geminiCli('auto', { allowNpx: true })
|
|
46
|
+
```
|
|
47
|
+
|
|
48
|
+
Then authenticate:
|
|
49
|
+
|
|
50
|
+
```bash
|
|
51
|
+
gemini auth login
|
|
52
|
+
```
|
|
53
|
+
|
|
54
|
+
## Quick Start
|
|
55
|
+
|
|
56
|
+
```javascript
|
|
57
|
+
import { geminiCli } from 'ai-sdk-provider-gemini-cli-agentic';
|
|
58
|
+
import { generateText, streamText } from 'ai';
|
|
59
|
+
|
|
60
|
+
// Basic usage
|
|
61
|
+
const { text } = await generateText({
|
|
62
|
+
model: geminiCli('gemini-2.5-flash'),
|
|
63
|
+
prompt: 'List files in the current directory',
|
|
64
|
+
});
|
|
65
|
+
|
|
66
|
+
// Streaming
|
|
67
|
+
const result = streamText({
|
|
68
|
+
model: geminiCli('auto', { cwd: process.cwd() }),
|
|
69
|
+
prompt: 'Explain the structure of this project',
|
|
70
|
+
});
|
|
71
|
+
|
|
72
|
+
for await (const chunk of result.textStream) {
|
|
73
|
+
process.stdout.write(chunk);
|
|
74
|
+
}
|
|
75
|
+
```
|
|
76
|
+
|
|
77
|
+
## Configuration
|
|
78
|
+
|
|
79
|
+
### Provider Settings
|
|
80
|
+
|
|
81
|
+
```javascript
|
|
82
|
+
import { createGeminiCli } from 'ai-sdk-provider-gemini-cli-agentic';
|
|
83
|
+
|
|
84
|
+
const provider = createGeminiCli({
|
|
85
|
+
defaultSettings: {
|
|
86
|
+
geminiPath: '/usr/local/bin/gemini', // Custom CLI path
|
|
87
|
+
cwd: '/path/to/project', // Working directory
|
|
88
|
+
approvalMode: 'auto_edit', // Approval mode
|
|
89
|
+
sandbox: true, // Enable sandbox
|
|
90
|
+
verbose: true, // Verbose output
|
|
91
|
+
},
|
|
92
|
+
});
|
|
93
|
+
|
|
94
|
+
const model = provider('gemini-2.5-flash');
|
|
95
|
+
```
|
|
96
|
+
|
|
97
|
+
### Per-Model Settings
|
|
98
|
+
|
|
99
|
+
```javascript
|
|
100
|
+
const model = geminiCli('gemini-2.5-flash', {
|
|
101
|
+
cwd: process.cwd(),
|
|
102
|
+
approvalMode: 'yolo',
|
|
103
|
+
sandbox: false,
|
|
104
|
+
includeDirectories: ['../shared-lib'],
|
|
105
|
+
allowedTools: ['read_file', 'write_file', 'list_directory'],
|
|
106
|
+
allowedMcpServerNames: ['filesystem'],
|
|
107
|
+
resume: 'latest', // or session index number
|
|
108
|
+
env: {
|
|
109
|
+
MY_VAR: 'value',
|
|
110
|
+
},
|
|
111
|
+
});
|
|
112
|
+
```
|
|
113
|
+
|
|
114
|
+
### Settings Reference
|
|
115
|
+
|
|
116
|
+
| Setting | Type | Description |
|
|
117
|
+
|---------|------|-------------|
|
|
118
|
+
| `geminiPath` | `string` | Path to Gemini CLI executable (default: `'gemini'`) |
|
|
119
|
+
| `allowNpx` | `boolean` | Allow falling back to `npx @google/gemini-cli` if CLI not found |
|
|
120
|
+
| `cwd` | `string` | Working directory for CLI operations |
|
|
121
|
+
| `approvalMode` | `'default' \| 'auto_edit' \| 'yolo'` | Tool approval behavior |
|
|
122
|
+
| `yolo` | `boolean` | Auto-approve all operations (alias for `approvalMode: 'yolo'`) |
|
|
123
|
+
| `sandbox` | `boolean` | Enable sandbox mode |
|
|
124
|
+
| `includeDirectories` | `string[]` | Additional directories to include |
|
|
125
|
+
| `allowedTools` | `string[]` | Tools allowed without confirmation |
|
|
126
|
+
| `allowedMcpServerNames` | `string[]` | Allowed MCP server names |
|
|
127
|
+
| `resume` | `string \| boolean` | Resume session (`'latest'`, index, or `true`) |
|
|
128
|
+
| `model` | `string` | Override model name |
|
|
129
|
+
| `env` | `Record<string, string>` | Environment variables |
|
|
130
|
+
| `verbose` | `boolean` | Enable verbose logging |
|
|
131
|
+
| `logger` | `Logger \| false` | Custom logger or `false` to disable |
|
|
132
|
+
|
|
133
|
+
## Approval Modes
|
|
134
|
+
|
|
135
|
+
| Mode | Description |
|
|
136
|
+
|------|-------------|
|
|
137
|
+
| `default` | Prompt for approval on each tool operation |
|
|
138
|
+
| `auto_edit` | Auto-approve file editing tools |
|
|
139
|
+
| `yolo` | Auto-approve all tools (use with caution) |
|
|
140
|
+
|
|
141
|
+
```javascript
|
|
142
|
+
// Conservative (default)
|
|
143
|
+
geminiCli('auto', { approvalMode: 'default' })
|
|
144
|
+
|
|
145
|
+
// Auto-approve edits only
|
|
146
|
+
geminiCli('auto', { approvalMode: 'auto_edit' })
|
|
147
|
+
|
|
148
|
+
// Full automation (dangerous!)
|
|
149
|
+
geminiCli('auto', { approvalMode: 'yolo' })
|
|
150
|
+
// or
|
|
151
|
+
geminiCli('auto', { yolo: true })
|
|
152
|
+
```
|
|
153
|
+
|
|
154
|
+
## Streaming with Tool Calls
|
|
155
|
+
|
|
156
|
+
```javascript
|
|
157
|
+
import { geminiCli } from 'ai-sdk-provider-gemini-cli-agentic';
|
|
158
|
+
import { streamText } from 'ai';
|
|
159
|
+
|
|
160
|
+
const result = streamText({
|
|
161
|
+
model: geminiCli('auto', { cwd: process.cwd() }),
|
|
162
|
+
prompt: 'Read package.json and explain the dependencies',
|
|
163
|
+
});
|
|
164
|
+
|
|
165
|
+
for await (const part of result.fullStream) {
|
|
166
|
+
switch (part.type) {
|
|
167
|
+
case 'text-delta':
|
|
168
|
+
process.stdout.write(part.textDelta);
|
|
169
|
+
break;
|
|
170
|
+
case 'tool-call':
|
|
171
|
+
console.log(`\n🔧 Tool: ${part.toolName}`);
|
|
172
|
+
console.log(` Args: ${JSON.stringify(part.args)}`);
|
|
173
|
+
break;
|
|
174
|
+
case 'tool-result':
|
|
175
|
+
console.log(` Result: ${part.result?.slice(0, 100)}...`);
|
|
176
|
+
break;
|
|
177
|
+
}
|
|
178
|
+
}
|
|
179
|
+
```
|
|
180
|
+
|
|
181
|
+
## Logging
|
|
182
|
+
|
|
183
|
+
### Default Logger
|
|
184
|
+
|
|
185
|
+
```javascript
|
|
186
|
+
const model = geminiCli('auto', {
|
|
187
|
+
verbose: true, // Enable info-level logging
|
|
188
|
+
});
|
|
189
|
+
```
|
|
190
|
+
|
|
191
|
+
### Custom Logger
|
|
192
|
+
|
|
193
|
+
```javascript
|
|
194
|
+
const model = geminiCli('auto', {
|
|
195
|
+
logger: {
|
|
196
|
+
debug: (msg) => console.debug('[DEBUG]', msg),
|
|
197
|
+
info: (msg) => console.info('[INFO]', msg),
|
|
198
|
+
warn: (msg) => console.warn('[WARN]', msg),
|
|
199
|
+
error: (msg) => console.error('[ERROR]', msg),
|
|
200
|
+
},
|
|
201
|
+
});
|
|
202
|
+
```
|
|
203
|
+
|
|
204
|
+
### Disable Logging
|
|
205
|
+
|
|
206
|
+
```javascript
|
|
207
|
+
const model = geminiCli('auto', {
|
|
208
|
+
logger: false,
|
|
209
|
+
});
|
|
210
|
+
```
|
|
211
|
+
|
|
212
|
+
## Error Handling
|
|
213
|
+
|
|
214
|
+
```javascript
|
|
215
|
+
import { geminiCli, isAuthenticationError } from 'ai-sdk-provider-gemini-cli-agentic';
|
|
216
|
+
import { generateText } from 'ai';
|
|
217
|
+
|
|
218
|
+
try {
|
|
219
|
+
const { text } = await generateText({
|
|
220
|
+
model: geminiCli('auto'),
|
|
221
|
+
prompt: 'Hello',
|
|
222
|
+
});
|
|
223
|
+
} catch (error) {
|
|
224
|
+
if (isAuthenticationError(error)) {
|
|
225
|
+
console.error('Please run: gemini auth login');
|
|
226
|
+
} else {
|
|
227
|
+
console.error('Error:', error.message);
|
|
228
|
+
}
|
|
229
|
+
}
|
|
230
|
+
```
|
|
231
|
+
|
|
232
|
+
## Models
|
|
233
|
+
|
|
234
|
+
The model ID is passed directly to Gemini CLI's `-m` flag:
|
|
235
|
+
|
|
236
|
+
```javascript
|
|
237
|
+
// Use auto model selection
|
|
238
|
+
geminiCli('auto')
|
|
239
|
+
|
|
240
|
+
// Specific models
|
|
241
|
+
geminiCli('gemini-2.5-flash')
|
|
242
|
+
geminiCli('gemini-2.5-pro')
|
|
243
|
+
geminiCli('gemini-3')
|
|
244
|
+
```
|
|
245
|
+
|
|
246
|
+
## Examples
|
|
247
|
+
|
|
248
|
+
See the [`examples/`](./examples/) directory for more usage examples:
|
|
249
|
+
|
|
250
|
+
- `basic-usage.mjs` - Simple text generation
|
|
251
|
+
- `streaming.mjs` - Streaming responses
|
|
252
|
+
- `streaming-tool-calls.mjs` - Watching tool execution
|
|
253
|
+
- `conversation-history.mjs` - Multi-turn conversations
|
|
254
|
+
- `custom-config.mjs` - Advanced configuration
|
|
255
|
+
- `permissions-and-sandbox.mjs` - Approval modes and sandbox
|
|
256
|
+
- `error-handling.mjs` - Error handling patterns
|
|
257
|
+
- `logging-*.mjs` - Various logging configurations
|
|
258
|
+
|
|
259
|
+
Run examples:
|
|
260
|
+
|
|
261
|
+
```bash
|
|
262
|
+
cd examples
|
|
263
|
+
node basic-usage.mjs
|
|
264
|
+
```
|
|
265
|
+
|
|
266
|
+
## Limitations
|
|
267
|
+
|
|
268
|
+
- **Interactive Prompts**: The provider cannot handle Gemini CLI's interactive approval prompts. Use `approvalMode: 'yolo'` or `approvalMode: 'auto_edit'` for automation.
|
|
269
|
+
- **No Image Input**: Image/multimodal input is not supported (text only).
|
|
270
|
+
- **No Embedding/Image Models**: Only language model is supported (`embeddingModel` and `imageModel` throw errors).
|
|
271
|
+
- **Subprocess Overhead**: Each call spawns a new subprocess; not suitable for high-frequency requests.
|
|
272
|
+
|
|
273
|
+
## CLI Flags Mapping
|
|
274
|
+
|
|
275
|
+
| Provider Setting | CLI Flag |
|
|
276
|
+
|-----------------|----------|
|
|
277
|
+
| `cwd` | Process working directory |
|
|
278
|
+
| `approvalMode` | `--approval-mode` |
|
|
279
|
+
| `yolo` | `-y` / `--yolo` |
|
|
280
|
+
| `sandbox` | `-s` / `--sandbox` |
|
|
281
|
+
| `includeDirectories` | `--include-directories` |
|
|
282
|
+
| `allowedTools` | `--allowed-tools` |
|
|
283
|
+
| `allowedMcpServerNames` | `--allowed-mcp-server-names` |
|
|
284
|
+
| `resume` | `-r` / `--resume` |
|
|
285
|
+
| `model` | `-m` / `--model` |
|
|
286
|
+
| *(always set)* | `--output-format stream-json` |
|
|
287
|
+
|
|
288
|
+
## License
|
|
289
|
+
|
|
290
|
+
MIT
|
|
291
|
+
|
|
292
|
+
## Related
|
|
293
|
+
|
|
294
|
+
- [AI SDK](https://sdk.vercel.ai/docs) - The AI SDK by Vercel
|
|
295
|
+
- [Gemini CLI](https://github.com/google-gemini/gemini-cli) - Google's Gemini CLI
|
|
296
|
+
- [ai-sdk-provider-codex-cli](https://github.com/J3n5en/ai-sdk-provider-codex-cli) - Similar provider for OpenAI Codex CLI
|
package/dist/index.cjs
CHANGED
|
@@ -216,6 +216,17 @@ function mapGeminiFinishReason(status) {
|
|
|
216
216
|
return { unified: "stop", raw: status };
|
|
217
217
|
}
|
|
218
218
|
}
|
|
219
|
+
function resolveGeminiPath(explicitPath, allowNpx) {
|
|
220
|
+
if (explicitPath) {
|
|
221
|
+
const lower = explicitPath.toLowerCase();
|
|
222
|
+
if (lower.endsWith(".js") || lower.endsWith(".mjs") || lower.endsWith(".cjs")) {
|
|
223
|
+
return { cmd: "node", args: [explicitPath] };
|
|
224
|
+
}
|
|
225
|
+
return { cmd: explicitPath, args: [] };
|
|
226
|
+
}
|
|
227
|
+
if (allowNpx) return { cmd: "npx", args: ["-y", "@google/gemini-cli"] };
|
|
228
|
+
return { cmd: "gemini", args: [] };
|
|
229
|
+
}
|
|
219
230
|
var GeminiCliLanguageModel = class {
|
|
220
231
|
specificationVersion = "v3";
|
|
221
232
|
provider = "gemini-cli";
|
|
@@ -248,9 +259,11 @@ var GeminiCliLanguageModel = class {
|
|
|
248
259
|
allowedMcpServerNames: providerOptions.allowedMcpServerNames ?? this.settings.allowedMcpServerNames
|
|
249
260
|
};
|
|
250
261
|
}
|
|
251
|
-
buildArgs(
|
|
252
|
-
const
|
|
253
|
-
const
|
|
262
|
+
buildArgs(settings = this.settings) {
|
|
263
|
+
const base = resolveGeminiPath(settings.geminiPath, settings.allowNpx);
|
|
264
|
+
const cmd = base.cmd;
|
|
265
|
+
const args = [...base.args];
|
|
266
|
+
const shell = process.platform === "win32" && (base.cmd === "npx" || base.cmd === "gemini");
|
|
254
267
|
args.push("--output-format", "stream-json");
|
|
255
268
|
if (this.modelId && this.modelId !== "auto") {
|
|
256
269
|
args.push("-m", this.modelId);
|
|
@@ -281,12 +294,12 @@ var GeminiCliLanguageModel = class {
|
|
|
281
294
|
args.push("--resume", "latest");
|
|
282
295
|
}
|
|
283
296
|
}
|
|
284
|
-
args.push(
|
|
297
|
+
args.push("-");
|
|
285
298
|
const env = {
|
|
286
299
|
...process.env,
|
|
287
300
|
...settings.env || {}
|
|
288
301
|
};
|
|
289
|
-
return { cmd, args, env, cwd: settings.cwd };
|
|
302
|
+
return { cmd, args, env, cwd: settings.cwd, shell };
|
|
290
303
|
}
|
|
291
304
|
mapWarnings(options) {
|
|
292
305
|
const unsupported = [];
|
|
@@ -333,14 +346,16 @@ var GeminiCliLanguageModel = class {
|
|
|
333
346
|
schema: geminiCliProviderOptionsSchema
|
|
334
347
|
});
|
|
335
348
|
const effectiveSettings = this.mergeSettings(providerOptions);
|
|
336
|
-
const { cmd, args, env, cwd } = this.buildArgs(
|
|
337
|
-
this.logger.debug(`[gemini-cli] Executing: ${cmd} ${args.
|
|
349
|
+
const { cmd, args, env, cwd, shell } = this.buildArgs(effectiveSettings);
|
|
350
|
+
this.logger.debug(`[gemini-cli] Executing: ${cmd} ${args.join(" ")}`);
|
|
338
351
|
let text = "";
|
|
339
352
|
let usage = createEmptyUsage();
|
|
340
353
|
let finishReason = { unified: "stop", raw: void 0 };
|
|
341
354
|
const content = [];
|
|
342
355
|
const toolResults = /* @__PURE__ */ new Map();
|
|
343
|
-
const child = child_process.spawn(cmd, args, { env, cwd, stdio: ["
|
|
356
|
+
const child = child_process.spawn(cmd, args, { env, cwd, shell, stdio: ["pipe", "pipe", "pipe"] });
|
|
357
|
+
child.stdin.write(promptText);
|
|
358
|
+
child.stdin.end();
|
|
344
359
|
let onAbort;
|
|
345
360
|
if (options.abortSignal) {
|
|
346
361
|
if (options.abortSignal.aborted) {
|
|
@@ -465,14 +480,16 @@ var GeminiCliLanguageModel = class {
|
|
|
465
480
|
schema: geminiCliProviderOptionsSchema
|
|
466
481
|
});
|
|
467
482
|
const effectiveSettings = this.mergeSettings(providerOptions);
|
|
468
|
-
const { cmd, args, env, cwd } = this.buildArgs(
|
|
469
|
-
this.logger.debug(`[gemini-cli] Streaming: ${cmd} ${args.
|
|
483
|
+
const { cmd, args, env, cwd, shell } = this.buildArgs(effectiveSettings);
|
|
484
|
+
this.logger.debug(`[gemini-cli] Streaming: ${cmd} ${args.join(" ")}`);
|
|
470
485
|
const model = this;
|
|
471
486
|
const abortSignal = options.abortSignal;
|
|
472
487
|
const stream = new ReadableStream({
|
|
473
488
|
start(controller) {
|
|
474
489
|
const startTime = Date.now();
|
|
475
|
-
const child = child_process.spawn(cmd, args, { env, cwd, stdio: ["
|
|
490
|
+
const child = child_process.spawn(cmd, args, { env, cwd, shell, stdio: ["pipe", "pipe", "pipe"] });
|
|
491
|
+
child.stdin.write(promptText);
|
|
492
|
+
child.stdin.end();
|
|
476
493
|
controller.enqueue({ type: "stream-start", warnings });
|
|
477
494
|
let stderr = "";
|
|
478
495
|
let lastUsage;
|
|
@@ -609,6 +626,7 @@ var loggerFunctionSchema = zod.z.object({
|
|
|
609
626
|
});
|
|
610
627
|
var settingsSchema = zod.z.object({
|
|
611
628
|
geminiPath: zod.z.string().optional(),
|
|
629
|
+
allowNpx: zod.z.boolean().optional(),
|
|
612
630
|
cwd: zod.z.string().optional(),
|
|
613
631
|
includeDirectories: zod.z.array(zod.z.string().min(1)).optional(),
|
|
614
632
|
approvalMode: zod.z.enum(["default", "auto_edit", "yolo"]).optional(),
|
package/dist/index.d.cts
CHANGED
|
@@ -25,6 +25,10 @@ interface GeminiCliSettings {
|
|
|
25
25
|
* @default 'gemini' (uses system PATH)
|
|
26
26
|
*/
|
|
27
27
|
geminiPath?: string;
|
|
28
|
+
/**
|
|
29
|
+
* Allow falling back to `npx @google/gemini-cli` if the binary cannot be resolved.
|
|
30
|
+
*/
|
|
31
|
+
allowNpx?: boolean;
|
|
28
32
|
/**
|
|
29
33
|
* Working directory for CLI operations.
|
|
30
34
|
*/
|
package/dist/index.d.ts
CHANGED
|
@@ -25,6 +25,10 @@ interface GeminiCliSettings {
|
|
|
25
25
|
* @default 'gemini' (uses system PATH)
|
|
26
26
|
*/
|
|
27
27
|
geminiPath?: string;
|
|
28
|
+
/**
|
|
29
|
+
* Allow falling back to `npx @google/gemini-cli` if the binary cannot be resolved.
|
|
30
|
+
*/
|
|
31
|
+
allowNpx?: boolean;
|
|
28
32
|
/**
|
|
29
33
|
* Working directory for CLI operations.
|
|
30
34
|
*/
|
package/dist/index.js
CHANGED
|
@@ -214,6 +214,17 @@ function mapGeminiFinishReason(status) {
|
|
|
214
214
|
return { unified: "stop", raw: status };
|
|
215
215
|
}
|
|
216
216
|
}
|
|
217
|
+
function resolveGeminiPath(explicitPath, allowNpx) {
|
|
218
|
+
if (explicitPath) {
|
|
219
|
+
const lower = explicitPath.toLowerCase();
|
|
220
|
+
if (lower.endsWith(".js") || lower.endsWith(".mjs") || lower.endsWith(".cjs")) {
|
|
221
|
+
return { cmd: "node", args: [explicitPath] };
|
|
222
|
+
}
|
|
223
|
+
return { cmd: explicitPath, args: [] };
|
|
224
|
+
}
|
|
225
|
+
if (allowNpx) return { cmd: "npx", args: ["-y", "@google/gemini-cli"] };
|
|
226
|
+
return { cmd: "gemini", args: [] };
|
|
227
|
+
}
|
|
217
228
|
var GeminiCliLanguageModel = class {
|
|
218
229
|
specificationVersion = "v3";
|
|
219
230
|
provider = "gemini-cli";
|
|
@@ -246,9 +257,11 @@ var GeminiCliLanguageModel = class {
|
|
|
246
257
|
allowedMcpServerNames: providerOptions.allowedMcpServerNames ?? this.settings.allowedMcpServerNames
|
|
247
258
|
};
|
|
248
259
|
}
|
|
249
|
-
buildArgs(
|
|
250
|
-
const
|
|
251
|
-
const
|
|
260
|
+
buildArgs(settings = this.settings) {
|
|
261
|
+
const base = resolveGeminiPath(settings.geminiPath, settings.allowNpx);
|
|
262
|
+
const cmd = base.cmd;
|
|
263
|
+
const args = [...base.args];
|
|
264
|
+
const shell = process.platform === "win32" && (base.cmd === "npx" || base.cmd === "gemini");
|
|
252
265
|
args.push("--output-format", "stream-json");
|
|
253
266
|
if (this.modelId && this.modelId !== "auto") {
|
|
254
267
|
args.push("-m", this.modelId);
|
|
@@ -279,12 +292,12 @@ var GeminiCliLanguageModel = class {
|
|
|
279
292
|
args.push("--resume", "latest");
|
|
280
293
|
}
|
|
281
294
|
}
|
|
282
|
-
args.push(
|
|
295
|
+
args.push("-");
|
|
283
296
|
const env = {
|
|
284
297
|
...process.env,
|
|
285
298
|
...settings.env || {}
|
|
286
299
|
};
|
|
287
|
-
return { cmd, args, env, cwd: settings.cwd };
|
|
300
|
+
return { cmd, args, env, cwd: settings.cwd, shell };
|
|
288
301
|
}
|
|
289
302
|
mapWarnings(options) {
|
|
290
303
|
const unsupported = [];
|
|
@@ -331,14 +344,16 @@ var GeminiCliLanguageModel = class {
|
|
|
331
344
|
schema: geminiCliProviderOptionsSchema
|
|
332
345
|
});
|
|
333
346
|
const effectiveSettings = this.mergeSettings(providerOptions);
|
|
334
|
-
const { cmd, args, env, cwd } = this.buildArgs(
|
|
335
|
-
this.logger.debug(`[gemini-cli] Executing: ${cmd} ${args.
|
|
347
|
+
const { cmd, args, env, cwd, shell } = this.buildArgs(effectiveSettings);
|
|
348
|
+
this.logger.debug(`[gemini-cli] Executing: ${cmd} ${args.join(" ")}`);
|
|
336
349
|
let text = "";
|
|
337
350
|
let usage = createEmptyUsage();
|
|
338
351
|
let finishReason = { unified: "stop", raw: void 0 };
|
|
339
352
|
const content = [];
|
|
340
353
|
const toolResults = /* @__PURE__ */ new Map();
|
|
341
|
-
const child = spawn(cmd, args, { env, cwd, stdio: ["
|
|
354
|
+
const child = spawn(cmd, args, { env, cwd, shell, stdio: ["pipe", "pipe", "pipe"] });
|
|
355
|
+
child.stdin.write(promptText);
|
|
356
|
+
child.stdin.end();
|
|
342
357
|
let onAbort;
|
|
343
358
|
if (options.abortSignal) {
|
|
344
359
|
if (options.abortSignal.aborted) {
|
|
@@ -463,14 +478,16 @@ var GeminiCliLanguageModel = class {
|
|
|
463
478
|
schema: geminiCliProviderOptionsSchema
|
|
464
479
|
});
|
|
465
480
|
const effectiveSettings = this.mergeSettings(providerOptions);
|
|
466
|
-
const { cmd, args, env, cwd } = this.buildArgs(
|
|
467
|
-
this.logger.debug(`[gemini-cli] Streaming: ${cmd} ${args.
|
|
481
|
+
const { cmd, args, env, cwd, shell } = this.buildArgs(effectiveSettings);
|
|
482
|
+
this.logger.debug(`[gemini-cli] Streaming: ${cmd} ${args.join(" ")}`);
|
|
468
483
|
const model = this;
|
|
469
484
|
const abortSignal = options.abortSignal;
|
|
470
485
|
const stream = new ReadableStream({
|
|
471
486
|
start(controller) {
|
|
472
487
|
const startTime = Date.now();
|
|
473
|
-
const child = spawn(cmd, args, { env, cwd, stdio: ["
|
|
488
|
+
const child = spawn(cmd, args, { env, cwd, shell, stdio: ["pipe", "pipe", "pipe"] });
|
|
489
|
+
child.stdin.write(promptText);
|
|
490
|
+
child.stdin.end();
|
|
474
491
|
controller.enqueue({ type: "stream-start", warnings });
|
|
475
492
|
let stderr = "";
|
|
476
493
|
let lastUsage;
|
|
@@ -607,6 +624,7 @@ var loggerFunctionSchema = z.object({
|
|
|
607
624
|
});
|
|
608
625
|
var settingsSchema = z.object({
|
|
609
626
|
geminiPath: z.string().optional(),
|
|
627
|
+
allowNpx: z.boolean().optional(),
|
|
610
628
|
cwd: z.string().optional(),
|
|
611
629
|
includeDirectories: z.array(z.string().min(1)).optional(),
|
|
612
630
|
approvalMode: z.enum(["default", "auto_edit", "yolo"]).optional(),
|