@cainmaila/gemini-cli-mcp 1.0.0
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/LICENSE +21 -0
- package/README.md +196 -0
- package/README.zh-TW.md +196 -0
- package/build/cli/buildArgs.d.ts +12 -0
- package/build/cli/buildArgs.js +19 -0
- package/build/cli/buildArgs.js.map +1 -0
- package/build/cli/geminiCommandRunner.d.ts +2 -0
- package/build/cli/geminiCommandRunner.js +108 -0
- package/build/cli/geminiCommandRunner.js.map +1 -0
- package/build/cli/geminiInspector.d.ts +10 -0
- package/build/cli/geminiInspector.js +336 -0
- package/build/cli/geminiInspector.js.map +1 -0
- package/build/cli/geminiRunner.d.ts +2 -0
- package/build/cli/geminiRunner.js +20 -0
- package/build/cli/geminiRunner.js.map +1 -0
- package/build/cli/taskPrompt.d.ts +7 -0
- package/build/cli/taskPrompt.js +31 -0
- package/build/cli/taskPrompt.js.map +1 -0
- package/build/index.d.ts +2 -0
- package/build/index.js +14 -0
- package/build/index.js.map +1 -0
- package/build/mcp/tools.d.ts +244 -0
- package/build/mcp/tools.js +500 -0
- package/build/mcp/tools.js.map +1 -0
- package/build/server.d.ts +3 -0
- package/build/server.js +12 -0
- package/build/server.js.map +1 -0
- package/build/types.d.ts +95 -0
- package/build/types.js +3 -0
- package/build/types.js.map +1 -0
- package/package.json +56 -0
package/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 cain.chu
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
package/README.md
ADDED
|
@@ -0,0 +1,196 @@
|
|
|
1
|
+
<div align="center">
|
|
2
|
+
<img src="./assets/banner.svg" alt="Gemini CLI MCP Banner" width="100%" />
|
|
3
|
+
|
|
4
|
+
# 🤖 Gemini CLI MCP Server
|
|
5
|
+
|
|
6
|
+
*Seamless AI-to-AI Delegation via Local Gemini CLI*
|
|
7
|
+
|
|
8
|
+
[](https://www.npmjs.org/package/@cainmaila/gemini-cli-mcp)
|
|
9
|
+
[](https://opensource.org/licenses/MIT)
|
|
10
|
+
[](#requirements)
|
|
11
|
+
|
|
12
|
+
[**English**](./README.md) · [**繁體中文**](./README.zh-TW.md)
|
|
13
|
+
</div>
|
|
14
|
+
|
|
15
|
+
---
|
|
16
|
+
|
|
17
|
+
## 🌟 Why Gemini CLI MCP?
|
|
18
|
+
|
|
19
|
+
`gemini-cli-mcp` is an advanced Model Context Protocol (MCP) server that empowers your AI assistants by delegating complex tasks to your locally installed Gemini CLI.
|
|
20
|
+
|
|
21
|
+
Rather than collapsing failures into generic errors, this server returns **structured results along with execution metadata**, making it an essential tool for robust AI-to-AI handoffs and deep debugging.
|
|
22
|
+
|
|
23
|
+
### ✨ Key Features
|
|
24
|
+
|
|
25
|
+
- **🚀 Zero-Friction Auth**: Transparently utilizes your existing local Gemini CLI setup and credentials.
|
|
26
|
+
- **🔌 Standard MCP Ready**: Runs headless over `stdio`, effortlessly integrating with standard MCP client setups.
|
|
27
|
+
- **🛠️ Task-Oriented & Flexible**: Choose `executeTask` for direct answers, or drop down to `executePrompt` for precise control.
|
|
28
|
+
- **🎨 Native Image Generation**: Harnesses your local `nanobanana` extension to generate and retrieve images seamlessly.
|
|
29
|
+
- **🔍 Environment Inspection**: Instantly discover available commands, extensions, skills, and MCP servers on the local machine.
|
|
30
|
+
|
|
31
|
+
---
|
|
32
|
+
|
|
33
|
+
## 📦 Installation
|
|
34
|
+
|
|
35
|
+
Getting started is quick and easy. Ensure you have [Node.js 18.18+](https://nodejs.org/) installed along with a configured local Gemini CLI.
|
|
36
|
+
|
|
37
|
+
```bash
|
|
38
|
+
# Install dependencies
|
|
39
|
+
npm install
|
|
40
|
+
|
|
41
|
+
# Build the project
|
|
42
|
+
npm run build
|
|
43
|
+
```
|
|
44
|
+
|
|
45
|
+
---
|
|
46
|
+
|
|
47
|
+
## 🚀 Quick Start & Usage
|
|
48
|
+
|
|
49
|
+
### Running the Server
|
|
50
|
+
|
|
51
|
+
Since this is an MCP server, it is designed to communicate over `stdio` and should be launched by your MCP client.
|
|
52
|
+
|
|
53
|
+
```bash
|
|
54
|
+
node build/index.js
|
|
55
|
+
```
|
|
56
|
+
|
|
57
|
+
### Client Configuration Example
|
|
58
|
+
|
|
59
|
+
Add the following to your AI assistant's MCP configuration:
|
|
60
|
+
|
|
61
|
+
```json
|
|
62
|
+
{
|
|
63
|
+
"mcpServers": {
|
|
64
|
+
"gemini-cli": {
|
|
65
|
+
"command": "node",
|
|
66
|
+
"args": ["/absolute/path/to/gemini-cli-mcp/build/index.js"]
|
|
67
|
+
}
|
|
68
|
+
}
|
|
69
|
+
}
|
|
70
|
+
```
|
|
71
|
+
|
|
72
|
+
If you package or install this elsewhere, point the client to the built entry file at `build/index.js`.
|
|
73
|
+
|
|
74
|
+
---
|
|
75
|
+
|
|
76
|
+
## 🛠️ Available Tools
|
|
77
|
+
|
|
78
|
+
<details>
|
|
79
|
+
<summary><b><code>executeTask</code> (Recommended)</b></summary>
|
|
80
|
+
|
|
81
|
+
Best for upstream AI systems. Hands off a task to the Gemini CLI and returns a ready-to-use answer. Auto-applies edit approvals when necessary!
|
|
82
|
+
|
|
83
|
+
**Input Example:**
|
|
84
|
+
```json
|
|
85
|
+
{
|
|
86
|
+
"task": "Query today's weather in Taipei and provide a short summary.",
|
|
87
|
+
"expectedOutput": "Direct answer, no intro.",
|
|
88
|
+
"timeoutMs": 180000
|
|
89
|
+
}
|
|
90
|
+
```
|
|
91
|
+
|
|
92
|
+
**Output Example:**
|
|
93
|
+
```json
|
|
94
|
+
{
|
|
95
|
+
"answer": "...",
|
|
96
|
+
"ok": true,
|
|
97
|
+
"stdout": "...",
|
|
98
|
+
"stderr": "...",
|
|
99
|
+
"exitCode": 0,
|
|
100
|
+
"elapsedMs": 23053
|
|
101
|
+
}
|
|
102
|
+
```
|
|
103
|
+
</details>
|
|
104
|
+
|
|
105
|
+
<details>
|
|
106
|
+
<summary><b><code>executePrompt</code></b></summary>
|
|
107
|
+
|
|
108
|
+
A lower-level interface designed for callers who demand exact prompt control.
|
|
109
|
+
|
|
110
|
+
**Input Example:**
|
|
111
|
+
```json
|
|
112
|
+
{
|
|
113
|
+
"prompt": "Summarize the current repository",
|
|
114
|
+
"model": "gemini-2.5-pro",
|
|
115
|
+
"timeoutMs": 60000
|
|
116
|
+
}
|
|
117
|
+
```
|
|
118
|
+
|
|
119
|
+
**Output Example:**
|
|
120
|
+
```json
|
|
121
|
+
{
|
|
122
|
+
"ok": true,
|
|
123
|
+
"finalText": "...",
|
|
124
|
+
"stdout": "...",
|
|
125
|
+
"stderr": "",
|
|
126
|
+
"exitCode": 0,
|
|
127
|
+
"elapsedMs": 1532
|
|
128
|
+
}
|
|
129
|
+
```
|
|
130
|
+
</details>
|
|
131
|
+
|
|
132
|
+
<details>
|
|
133
|
+
<summary><b><code>executeImageTask</code></b></summary>
|
|
134
|
+
|
|
135
|
+
Flawless image-generation backed by the local `nanobanana` extension. Bypasses interactive prompts automatically!
|
|
136
|
+
|
|
137
|
+
**Input Example:**
|
|
138
|
+
```json
|
|
139
|
+
{
|
|
140
|
+
"prompt": "a cute orange cat portrait, clean light background",
|
|
141
|
+
"count": 1,
|
|
142
|
+
"timeoutMs": 180000
|
|
143
|
+
}
|
|
144
|
+
```
|
|
145
|
+
|
|
146
|
+
**Output Example:**
|
|
147
|
+
```json
|
|
148
|
+
{
|
|
149
|
+
"ok": true,
|
|
150
|
+
"responseText": "/path/to/project/nanobanana-output/cat.png",
|
|
151
|
+
"imagePaths": ["/path/to/project/nanobanana-output/cat.png"],
|
|
152
|
+
"primaryImagePath": "/path/to/project/nanobanana-output/cat.png",
|
|
153
|
+
"exitCode": 0,
|
|
154
|
+
"elapsedMs": 12000
|
|
155
|
+
}
|
|
156
|
+
```
|
|
157
|
+
</details>
|
|
158
|
+
|
|
159
|
+
<details>
|
|
160
|
+
<summary><b><code>inspectGeminiCli</code></b></summary>
|
|
161
|
+
|
|
162
|
+
Discover your AI environment's capabilities on the fly. Returns top-level commands, installed extensions, available skills, and configured MCP servers.
|
|
163
|
+
|
|
164
|
+
**Input Example:**
|
|
165
|
+
```json
|
|
166
|
+
{
|
|
167
|
+
"includeModelReportedTools": true,
|
|
168
|
+
"timeoutMs": 60000
|
|
169
|
+
}
|
|
170
|
+
```
|
|
171
|
+
</details>
|
|
172
|
+
|
|
173
|
+
---
|
|
174
|
+
|
|
175
|
+
## ⚙️ Environment Overrides
|
|
176
|
+
|
|
177
|
+
Tailor the server to your specific environment simply by setting these variables:
|
|
178
|
+
|
|
179
|
+
| Variable | Description | Default |
|
|
180
|
+
|----------|-------------|---------|
|
|
181
|
+
| `GEMINI_CLI_PATH` | Path to the Gemini executable | `gemini` |
|
|
182
|
+
| `GEMINI_PROMPT_FLAG` | The flag used for passing prompts | `-p` |
|
|
183
|
+
| `GEMINI_MODEL_FLAG` | The flag used to specify the model | `--model` |
|
|
184
|
+
|
|
185
|
+
---
|
|
186
|
+
|
|
187
|
+
## 📚 Notes & Contributing
|
|
188
|
+
|
|
189
|
+
- **Authentication**: This server relies on your existing local Gemini CLI authentication.
|
|
190
|
+
- **Resilience**: If the local CLI is missing or broken, you will receive structured failure details—never a silent crash.
|
|
191
|
+
- **Want to build with us?** Check out our developer guide in [DEVELOPMENT.md](DEVELOPMENT.md).
|
|
192
|
+
|
|
193
|
+
<br/>
|
|
194
|
+
<div align="center">
|
|
195
|
+
<i>Built for the next generation of AI collaboration.</i>
|
|
196
|
+
</div>
|
package/README.zh-TW.md
ADDED
|
@@ -0,0 +1,196 @@
|
|
|
1
|
+
<div align="center">
|
|
2
|
+
<img src="./assets/banner.svg" alt="Gemini CLI MCP Banner" width="100%" />
|
|
3
|
+
|
|
4
|
+
# 🤖 Gemini CLI MCP Server
|
|
5
|
+
|
|
6
|
+
*輕量、無縫的 AI 本地代理協作工具*
|
|
7
|
+
|
|
8
|
+
[](https://www.npmjs.org/package/gemini-cli-mcp)
|
|
9
|
+
[](https://opensource.org/licenses/MIT)
|
|
10
|
+
[](#要求條件)
|
|
11
|
+
|
|
12
|
+
[**English**](./README.md) · [**繁體中文**](./README.zh-TW.md)
|
|
13
|
+
</div>
|
|
14
|
+
|
|
15
|
+
---
|
|
16
|
+
|
|
17
|
+
## 🌟 為什麼選擇 Gemini CLI MCP?
|
|
18
|
+
|
|
19
|
+
`gemini-cli-mcp` 是一個強大的 Model Context Protocol (MCP) 伺服器,能讓你的 AI 助理將複雜的任務直接委託給本地安裝的 Gemini CLI。
|
|
20
|
+
|
|
21
|
+
本伺服器不會在遇到錯誤時只拋出籠統的例外訊息,而是會將 **結構化的執行結果與完整的執行 Metadata** 一併回傳。這使得它成為處理「AI 委託另一位 AI」場景,並且進行深度除錯時不可或缺的利器。
|
|
22
|
+
|
|
23
|
+
### ✨ 核心亮點
|
|
24
|
+
|
|
25
|
+
- **🚀 零摩擦認證**:直接運用你本地端現有的 Gemini CLI 設定與驗證授權,隨插即穿。
|
|
26
|
+
- **🔌 完美接軌標準 MCP**:透過 `stdio` 無頭 (Headless) 運行,完美契合標準的 MCP 客戶端架構。
|
|
27
|
+
- **🛠️ 任務導向設計**:提供 `executeTask` 以獲取直接答案,也能使用降級介面 `executePrompt` 來獲得精準的 Prompt 控制權。
|
|
28
|
+
- **🎨 原生圖片生成支援**:無縫接軌本地端的 `nanobanana` 擴充套件,輕鬆生成圖像並回傳路徑。
|
|
29
|
+
- **🔍 深度環境檢測**:一鍵掃描當前本地端可用的 Gemini CLI 指令、擴充套件、Skills 以及設定檔中的 MCP Server。
|
|
30
|
+
|
|
31
|
+
---
|
|
32
|
+
|
|
33
|
+
## 📦 安裝說明
|
|
34
|
+
|
|
35
|
+
開始使用非常簡單。請確認你已安裝了 [Node.js 18.18+](https://nodejs.org/) 以及配置好並能自動運行的本地端 Gemini CLI 驗證。
|
|
36
|
+
|
|
37
|
+
```bash
|
|
38
|
+
# 安裝相依套件
|
|
39
|
+
npm install
|
|
40
|
+
|
|
41
|
+
# 編譯專案
|
|
42
|
+
npm run build
|
|
43
|
+
```
|
|
44
|
+
|
|
45
|
+
---
|
|
46
|
+
|
|
47
|
+
## 🚀 快速上手與使用方法
|
|
48
|
+
|
|
49
|
+
### 啟動伺服器
|
|
50
|
+
|
|
51
|
+
由於這是一個 MCP 伺服器,它被設計成透過 `stdio` 溝通,並且應該由你的 MCP 客戶端應用程式來啟動:
|
|
52
|
+
|
|
53
|
+
```bash
|
|
54
|
+
node build/index.js
|
|
55
|
+
```
|
|
56
|
+
|
|
57
|
+
### MCP 客戶端設定範例
|
|
58
|
+
|
|
59
|
+
將以下配置加入你所使用的 AI 助理之 MCP 設定檔中:
|
|
60
|
+
|
|
61
|
+
```json
|
|
62
|
+
{
|
|
63
|
+
"mcpServers": {
|
|
64
|
+
"gemini-cli": {
|
|
65
|
+
"command": "node",
|
|
66
|
+
"args": ["/絕對路徑/到/你的/gemini-cli-mcp/build/index.js"]
|
|
67
|
+
}
|
|
68
|
+
}
|
|
69
|
+
}
|
|
70
|
+
```
|
|
71
|
+
|
|
72
|
+
如果將此伺服器打包或安裝在其他地方,請確保用戶端指向編譯好的 `build/index.js`。
|
|
73
|
+
|
|
74
|
+
---
|
|
75
|
+
|
|
76
|
+
## 🛠️ 強大的可用工具 (Tools)
|
|
77
|
+
|
|
78
|
+
<details>
|
|
79
|
+
<summary><b><code>executeTask</code>(最推薦使用)</b></summary>
|
|
80
|
+
|
|
81
|
+
這是上游 AI 系統的最佳預設工具。當你需要 Gemini CLI 幫你完成一項任務並直接回傳解答時,選這個就對了!如果任務牽涉修改檔案,伺服器還會自動啟用 Auto-Edit 核准模式。
|
|
82
|
+
|
|
83
|
+
**輸入範例:**
|
|
84
|
+
```json
|
|
85
|
+
{
|
|
86
|
+
"task": "請查詢台北市今天的天氣,並用繁體中文簡短回答:天氣概況、溫度、降雨機率、以及一個外出建議。",
|
|
87
|
+
"expectedOutput": "直接回答,不要寫前言。",
|
|
88
|
+
"timeoutMs": 180000
|
|
89
|
+
}
|
|
90
|
+
```
|
|
91
|
+
|
|
92
|
+
**輸出範例:**
|
|
93
|
+
```json
|
|
94
|
+
{
|
|
95
|
+
"answer": "台北今天多雲到晴,約 11°C 至 19°C,降雨機率低,建議早晚加外套。",
|
|
96
|
+
"ok": true,
|
|
97
|
+
"stdout": "...",
|
|
98
|
+
"stderr": "...",
|
|
99
|
+
"exitCode": 0,
|
|
100
|
+
"elapsedMs": 23053
|
|
101
|
+
}
|
|
102
|
+
```
|
|
103
|
+
</details>
|
|
104
|
+
|
|
105
|
+
<details>
|
|
106
|
+
<summary><b><code>executePrompt</code></b></summary>
|
|
107
|
+
|
|
108
|
+
專為需要精確控制 Prompt 參數的呼叫者所準備的底層介面。
|
|
109
|
+
|
|
110
|
+
**輸入範例:**
|
|
111
|
+
```json
|
|
112
|
+
{
|
|
113
|
+
"prompt": "Summarize the current repository",
|
|
114
|
+
"model": "gemini-2.5-pro",
|
|
115
|
+
"timeoutMs": 60000
|
|
116
|
+
}
|
|
117
|
+
```
|
|
118
|
+
|
|
119
|
+
**輸出範例:**
|
|
120
|
+
```json
|
|
121
|
+
{
|
|
122
|
+
"ok": true,
|
|
123
|
+
"finalText": "...",
|
|
124
|
+
"stdout": "...",
|
|
125
|
+
"stderr": "",
|
|
126
|
+
"exitCode": 0,
|
|
127
|
+
"elapsedMs": 1532
|
|
128
|
+
}
|
|
129
|
+
```
|
|
130
|
+
</details>
|
|
131
|
+
|
|
132
|
+
<details>
|
|
133
|
+
<summary><b><code>executeImageTask</code></b></summary>
|
|
134
|
+
|
|
135
|
+
支援本地 `nanobanana` 擴充套件的穩健圖片生成介面。預設會啟用 YOLO 模式以自動繞過互動式認證提示,實現全自動生成!
|
|
136
|
+
|
|
137
|
+
**輸入範例:**
|
|
138
|
+
```json
|
|
139
|
+
{
|
|
140
|
+
"prompt": "一隻可愛的橘貓肖像,乾淨明亮的背景",
|
|
141
|
+
"count": 1,
|
|
142
|
+
"timeoutMs": 180000
|
|
143
|
+
}
|
|
144
|
+
```
|
|
145
|
+
|
|
146
|
+
**輸出範例:**
|
|
147
|
+
```json
|
|
148
|
+
{
|
|
149
|
+
"ok": true,
|
|
150
|
+
"responseText": "/path/to/project/nanobanana-output/cat.png",
|
|
151
|
+
"imagePaths": ["/path/to/project/nanobanana-output/cat.png"],
|
|
152
|
+
"primaryImagePath": "/path/to/project/nanobanana-output/cat.png",
|
|
153
|
+
"exitCode": 0,
|
|
154
|
+
"elapsedMs": 12000
|
|
155
|
+
}
|
|
156
|
+
```
|
|
157
|
+
</details>
|
|
158
|
+
|
|
159
|
+
<details>
|
|
160
|
+
<summary><b><code>inspectGeminiCli</code></b></summary>
|
|
161
|
+
|
|
162
|
+
用來動態探索本地 Gemini CLI 環境的利器。它會掃描並回報頂層指令、擴充套件、可用 Skills 以及所有的 MCP 伺服器狀態。
|
|
163
|
+
|
|
164
|
+
**輸入範例:**
|
|
165
|
+
```json
|
|
166
|
+
{
|
|
167
|
+
"includeModelReportedTools": true,
|
|
168
|
+
"timeoutMs": 60000
|
|
169
|
+
}
|
|
170
|
+
```
|
|
171
|
+
</details>
|
|
172
|
+
|
|
173
|
+
---
|
|
174
|
+
|
|
175
|
+
## ⚙️ 進階環境變數 (Overrides)
|
|
176
|
+
|
|
177
|
+
若需要客製化伺服器行為,你可以設定以下環境變數:
|
|
178
|
+
|
|
179
|
+
| 變數名稱 | 說明 | 預設值 |
|
|
180
|
+
|----------|-------------|---------|
|
|
181
|
+
| `GEMINI_CLI_PATH` | 覆蓋 Gemini CLI 執行檔路徑 | `gemini` |
|
|
182
|
+
| `GEMINI_PROMPT_FLAG` | 覆蓋傳遞 Prompt 使用的 Flag | `-p` |
|
|
183
|
+
| `GEMINI_MODEL_FLAG` | 覆蓋指定外部模型的 Flag | `--model` |
|
|
184
|
+
|
|
185
|
+
---
|
|
186
|
+
|
|
187
|
+
## 📚 注意事項與貢獻
|
|
188
|
+
|
|
189
|
+
- **身份驗證**:本伺服器底層直接依賴你本地主機已設定好的 Gemini CLI 授權。
|
|
190
|
+
- **強健的除錯機制**:如果本地的 Gemini CLI 發生問題或遺失配置,工具將回傳包含詳細狀態細節的 Json 物件,而不是無聲無息的崩潰。
|
|
191
|
+
- **想參與開發?** 請詳閱 [DEVELOPMENT.md](DEVELOPMENT.md) 開發者文件。
|
|
192
|
+
|
|
193
|
+
<br/>
|
|
194
|
+
<div align="center">
|
|
195
|
+
<i>專為下一代 AI 代理協作而生。</i>
|
|
196
|
+
</div>
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
import type { ExecutePromptInput } from "../types.js";
|
|
2
|
+
export declare const DEFAULT_TIMEOUT_MS = 60000;
|
|
3
|
+
export declare const MIN_TIMEOUT_MS = 1000;
|
|
4
|
+
export declare const MAX_TIMEOUT_MS: number;
|
|
5
|
+
export declare const DEFAULT_PROMPT_FLAG = "-p";
|
|
6
|
+
export declare const DEFAULT_MODEL_FLAG = "--model";
|
|
7
|
+
export interface GeminiFlagOptions {
|
|
8
|
+
promptFlag?: string;
|
|
9
|
+
modelFlag?: string;
|
|
10
|
+
}
|
|
11
|
+
export declare function normalizeTimeout(timeoutMs?: number): number;
|
|
12
|
+
export declare function buildGeminiArgs(input: Pick<ExecutePromptInput, "prompt" | "model">, options?: GeminiFlagOptions): string[];
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
export const DEFAULT_TIMEOUT_MS = 60_000;
|
|
2
|
+
export const MIN_TIMEOUT_MS = 1_000;
|
|
3
|
+
export const MAX_TIMEOUT_MS = 10 * 60_000;
|
|
4
|
+
export const DEFAULT_PROMPT_FLAG = "-p";
|
|
5
|
+
export const DEFAULT_MODEL_FLAG = "--model";
|
|
6
|
+
export function normalizeTimeout(timeoutMs) {
|
|
7
|
+
return timeoutMs ?? DEFAULT_TIMEOUT_MS;
|
|
8
|
+
}
|
|
9
|
+
export function buildGeminiArgs(input, options = {}) {
|
|
10
|
+
const promptFlag = options.promptFlag ?? DEFAULT_PROMPT_FLAG;
|
|
11
|
+
const modelFlag = options.modelFlag ?? DEFAULT_MODEL_FLAG;
|
|
12
|
+
const args = [];
|
|
13
|
+
if (input.model) {
|
|
14
|
+
args.push(modelFlag, input.model);
|
|
15
|
+
}
|
|
16
|
+
args.push(promptFlag, input.prompt);
|
|
17
|
+
return args;
|
|
18
|
+
}
|
|
19
|
+
//# sourceMappingURL=buildArgs.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"buildArgs.js","sourceRoot":"","sources":["../../src/cli/buildArgs.ts"],"names":[],"mappings":"AAEA,MAAM,CAAC,MAAM,kBAAkB,GAAG,MAAM,CAAC;AACzC,MAAM,CAAC,MAAM,cAAc,GAAG,KAAK,CAAC;AACpC,MAAM,CAAC,MAAM,cAAc,GAAG,EAAE,GAAG,MAAM,CAAC;AAC1C,MAAM,CAAC,MAAM,mBAAmB,GAAG,IAAI,CAAC;AACxC,MAAM,CAAC,MAAM,kBAAkB,GAAG,SAAS,CAAC;AAO5C,MAAM,UAAU,gBAAgB,CAAC,SAAkB;IACjD,OAAO,SAAS,IAAI,kBAAkB,CAAC;AACzC,CAAC;AAED,MAAM,UAAU,eAAe,CAC7B,KAAmD,EACnD,UAA6B,EAAE;IAE/B,MAAM,UAAU,GAAG,OAAO,CAAC,UAAU,IAAI,mBAAmB,CAAC;IAC7D,MAAM,SAAS,GAAG,OAAO,CAAC,SAAS,IAAI,kBAAkB,CAAC;IAC1D,MAAM,IAAI,GAAa,EAAE,CAAC;IAE1B,IAAI,KAAK,CAAC,KAAK,EAAE,CAAC;QAChB,IAAI,CAAC,IAAI,CAAC,SAAS,EAAE,KAAK,CAAC,KAAK,CAAC,CAAC;IACpC,CAAC;IAED,IAAI,CAAC,IAAI,CAAC,UAAU,EAAE,KAAK,CAAC,MAAM,CAAC,CAAC;IAEpC,OAAO,IAAI,CAAC;AACd,CAAC"}
|
|
@@ -0,0 +1,108 @@
|
|
|
1
|
+
import { spawn } from "node:child_process";
|
|
2
|
+
import { normalizeTimeout } from "./buildArgs.js";
|
|
3
|
+
const DEFAULT_COMMAND = "gemini";
|
|
4
|
+
const KILL_GRACE_MS = 5_000;
|
|
5
|
+
export async function runGeminiCommand(input, options = {}) {
|
|
6
|
+
const startedAt = Date.now();
|
|
7
|
+
const timeoutMs = normalizeTimeout(input.timeoutMs);
|
|
8
|
+
const command = options.command ?? options.env?.GEMINI_CLI_PATH ?? DEFAULT_COMMAND;
|
|
9
|
+
const env = {
|
|
10
|
+
...process.env,
|
|
11
|
+
...options.env,
|
|
12
|
+
};
|
|
13
|
+
return await new Promise((resolve) => {
|
|
14
|
+
let stdout = "";
|
|
15
|
+
let stderr = "";
|
|
16
|
+
let resolved = false;
|
|
17
|
+
let timedOut = false;
|
|
18
|
+
let aborted = options.signal?.aborted ?? false;
|
|
19
|
+
let exitCode = null;
|
|
20
|
+
let exitSignal = null;
|
|
21
|
+
let spawnError;
|
|
22
|
+
let killTimer;
|
|
23
|
+
const finish = () => {
|
|
24
|
+
if (resolved) {
|
|
25
|
+
return;
|
|
26
|
+
}
|
|
27
|
+
resolved = true;
|
|
28
|
+
if (killTimer) {
|
|
29
|
+
clearTimeout(killTimer);
|
|
30
|
+
}
|
|
31
|
+
const elapsedMs = Date.now() - startedAt;
|
|
32
|
+
const finalText = stdout.trim();
|
|
33
|
+
const ok = !spawnError && !timedOut && !aborted && exitCode === 0;
|
|
34
|
+
resolve({
|
|
35
|
+
ok,
|
|
36
|
+
finalText,
|
|
37
|
+
stdout,
|
|
38
|
+
stderr,
|
|
39
|
+
exitCode,
|
|
40
|
+
signal: exitSignal,
|
|
41
|
+
elapsedMs,
|
|
42
|
+
timedOut,
|
|
43
|
+
aborted,
|
|
44
|
+
command,
|
|
45
|
+
args: input.args,
|
|
46
|
+
...(input.cwd ? { workingDirectory: input.cwd } : {}),
|
|
47
|
+
...(spawnError?.message ? { errorMessage: spawnError.message } : {}),
|
|
48
|
+
});
|
|
49
|
+
};
|
|
50
|
+
const child = spawn(command, input.args, {
|
|
51
|
+
cwd: input.cwd,
|
|
52
|
+
env,
|
|
53
|
+
shell: false,
|
|
54
|
+
stdio: ["ignore", "pipe", "pipe"],
|
|
55
|
+
});
|
|
56
|
+
const stopChild = (reason) => {
|
|
57
|
+
if (reason === "timeout") {
|
|
58
|
+
timedOut = true;
|
|
59
|
+
}
|
|
60
|
+
else {
|
|
61
|
+
aborted = true;
|
|
62
|
+
}
|
|
63
|
+
if (child.killed) {
|
|
64
|
+
return;
|
|
65
|
+
}
|
|
66
|
+
child.kill("SIGTERM");
|
|
67
|
+
killTimer = setTimeout(() => {
|
|
68
|
+
if (!child.killed) {
|
|
69
|
+
child.kill("SIGKILL");
|
|
70
|
+
}
|
|
71
|
+
}, KILL_GRACE_MS);
|
|
72
|
+
};
|
|
73
|
+
const timeoutHandle = setTimeout(() => {
|
|
74
|
+
stopChild("timeout");
|
|
75
|
+
}, timeoutMs);
|
|
76
|
+
const abortHandler = () => {
|
|
77
|
+
stopChild("abort");
|
|
78
|
+
};
|
|
79
|
+
options.signal?.addEventListener("abort", abortHandler, { once: true });
|
|
80
|
+
child.stdout.setEncoding("utf8");
|
|
81
|
+
child.stderr.setEncoding("utf8");
|
|
82
|
+
child.stdout.on("data", (chunk) => {
|
|
83
|
+
stdout += chunk;
|
|
84
|
+
});
|
|
85
|
+
child.stderr.on("data", (chunk) => {
|
|
86
|
+
stderr += chunk;
|
|
87
|
+
});
|
|
88
|
+
child.on("error", (error) => {
|
|
89
|
+
spawnError = error;
|
|
90
|
+
});
|
|
91
|
+
child.on("close", (code, signal) => {
|
|
92
|
+
clearTimeout(timeoutHandle);
|
|
93
|
+
options.signal?.removeEventListener("abort", abortHandler);
|
|
94
|
+
exitCode = code;
|
|
95
|
+
exitSignal = signal;
|
|
96
|
+
finish();
|
|
97
|
+
});
|
|
98
|
+
child.on("spawn", () => {
|
|
99
|
+
if (options.signal?.aborted) {
|
|
100
|
+
stopChild("abort");
|
|
101
|
+
}
|
|
102
|
+
});
|
|
103
|
+
if (options.signal?.aborted) {
|
|
104
|
+
stopChild("abort");
|
|
105
|
+
}
|
|
106
|
+
});
|
|
107
|
+
}
|
|
108
|
+
//# sourceMappingURL=geminiCommandRunner.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"geminiCommandRunner.js","sourceRoot":"","sources":["../../src/cli/geminiCommandRunner.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
import type { GeminiCliCommandInfo, GeminiCliExtensionInfo, GeminiCliInspectionResult, GeminiCliMcpServerInfo, GeminiCliModelReportedSummary, GeminiCliSkillInfo, GeminiCommandInput, GeminiExecutionResult, GeminiRunnerOptions } from "../types.js";
|
|
2
|
+
export declare function parseGeminiHelpCommands(stdout: string): GeminiCliCommandInfo[];
|
|
3
|
+
export declare function parseGeminiExtensions(stdout: string): GeminiCliExtensionInfo[];
|
|
4
|
+
export declare function parseGeminiSkills(stdout: string): GeminiCliSkillInfo[];
|
|
5
|
+
export declare function parseGeminiMcpServers(stdout: string): GeminiCliMcpServerInfo[];
|
|
6
|
+
export declare function parseModelReportedSummary(text?: string): GeminiCliModelReportedSummary | undefined;
|
|
7
|
+
export declare function inspectGeminiCli(input?: {
|
|
8
|
+
includeModelReportedTools?: boolean | undefined;
|
|
9
|
+
timeoutMs?: number | undefined;
|
|
10
|
+
}, runner?: (input: GeminiCommandInput, options?: GeminiRunnerOptions) => Promise<GeminiExecutionResult>, options?: GeminiRunnerOptions): Promise<GeminiCliInspectionResult>;
|