@alessai/hive-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 +217 -0
- package/conf/cli_clients/claude.json +9 -0
- package/conf/cli_clients/codex.json +9 -0
- package/conf/cli_clients/gemini.json +9 -0
- package/conf/cli_clients/glm.json +12 -0
- package/dist/agents/base.d.ts +12 -0
- package/dist/agents/base.d.ts.map +1 -0
- package/dist/agents/base.js +138 -0
- package/dist/agents/base.js.map +1 -0
- package/dist/agents/claude.d.ts +10 -0
- package/dist/agents/claude.d.ts.map +1 -0
- package/dist/agents/claude.js +19 -0
- package/dist/agents/claude.js.map +1 -0
- package/dist/agents/codex.d.ts +10 -0
- package/dist/agents/codex.d.ts.map +1 -0
- package/dist/agents/codex.js +21 -0
- package/dist/agents/codex.js.map +1 -0
- package/dist/agents/factory.d.ts +4 -0
- package/dist/agents/factory.d.ts.map +1 -0
- package/dist/agents/factory.js +17 -0
- package/dist/agents/factory.js.map +1 -0
- package/dist/agents/gemini.d.ts +23 -0
- package/dist/agents/gemini.d.ts.map +1 -0
- package/dist/agents/gemini.js +62 -0
- package/dist/agents/gemini.js.map +1 -0
- package/dist/config/constants.d.ts +10 -0
- package/dist/config/constants.d.ts.map +1 -0
- package/dist/config/constants.js +15 -0
- package/dist/config/constants.js.map +1 -0
- package/dist/config/internal-defaults.d.ts +3 -0
- package/dist/config/internal-defaults.d.ts.map +1 -0
- package/dist/config/internal-defaults.js +23 -0
- package/dist/config/internal-defaults.js.map +1 -0
- package/dist/config/registry.d.ts +5 -0
- package/dist/config/registry.d.ts.map +1 -0
- package/dist/config/registry.js +59 -0
- package/dist/config/registry.js.map +1 -0
- package/dist/continuation/store.d.ts +6 -0
- package/dist/continuation/store.d.ts.map +1 -0
- package/dist/continuation/store.js +123 -0
- package/dist/continuation/store.js.map +1 -0
- package/dist/index.d.ts +3 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +98 -0
- package/dist/index.js.map +1 -0
- package/dist/log.d.ts +3 -0
- package/dist/log.d.ts.map +1 -0
- package/dist/log.js +5 -0
- package/dist/log.js.map +1 -0
- package/dist/parsers/base.d.ts +9 -0
- package/dist/parsers/base.d.ts.map +1 -0
- package/dist/parsers/base.js +11 -0
- package/dist/parsers/base.js.map +1 -0
- package/dist/parsers/claude.d.ts +13 -0
- package/dist/parsers/claude.d.ts.map +1 -0
- package/dist/parsers/claude.js +110 -0
- package/dist/parsers/claude.js.map +1 -0
- package/dist/parsers/codex.d.ts +16 -0
- package/dist/parsers/codex.d.ts.map +1 -0
- package/dist/parsers/codex.js +39 -0
- package/dist/parsers/codex.js.map +1 -0
- package/dist/parsers/gemini.d.ts +13 -0
- package/dist/parsers/gemini.d.ts.map +1 -0
- package/dist/parsers/gemini.js +37 -0
- package/dist/parsers/gemini.js.map +1 -0
- package/dist/parsers/index.d.ts +8 -0
- package/dist/parsers/index.d.ts.map +1 -0
- package/dist/parsers/index.js +22 -0
- package/dist/parsers/index.js.map +1 -0
- package/dist/parsers/raw.d.ts +5 -0
- package/dist/parsers/raw.d.ts.map +1 -0
- package/dist/parsers/raw.js +6 -0
- package/dist/parsers/raw.js.map +1 -0
- package/dist/progress.d.ts +4 -0
- package/dist/progress.d.ts.map +1 -0
- package/dist/progress.js +12 -0
- package/dist/progress.js.map +1 -0
- package/dist/prompts/loader.d.ts +12 -0
- package/dist/prompts/loader.d.ts.map +1 -0
- package/dist/prompts/loader.js +48 -0
- package/dist/prompts/loader.js.map +1 -0
- package/dist/tools/hive-consensus.d.ts +3 -0
- package/dist/tools/hive-consensus.d.ts.map +1 -0
- package/dist/tools/hive-consensus.js +54 -0
- package/dist/tools/hive-consensus.js.map +1 -0
- package/dist/tools/hive.d.ts +3 -0
- package/dist/tools/hive.d.ts.map +1 -0
- package/dist/tools/hive.js +114 -0
- package/dist/tools/hive.js.map +1 -0
- package/dist/types.d.ts +81 -0
- package/dist/types.d.ts.map +1 -0
- package/dist/types.js +2 -0
- package/dist/types.js.map +1 -0
- package/package.json +52 -0
- package/prompts/analyst.txt +6 -0
- package/prompts/apilookup.txt +6 -0
- package/prompts/challenger.txt +6 -0
- package/prompts/debugger.txt +6 -0
- package/prompts/default.txt +4 -0
- package/prompts/docgen.txt +6 -0
- package/prompts/planner.txt +6 -0
- package/prompts/precommit.txt +6 -0
- package/prompts/refactor.txt +6 -0
- package/prompts/reviewer.txt +6 -0
- package/prompts/secaudit.txt +6 -0
- package/prompts/testgen.txt +6 -0
- package/prompts/thinker.txt +6 -0
- package/prompts/tracer.txt +6 -0
package/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2025 alessai
|
|
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,217 @@
|
|
|
1
|
+
# Hive MCP
|
|
2
|
+
|
|
3
|
+
An MCP server that spawns external AI CLIs as subagents. Give any MCP-compatible host (Claude Code, Cursor, Windsurf, etc.) the ability to delegate tasks to Gemini, Claude, Codex, or any custom CLI tool.
|
|
4
|
+
|
|
5
|
+
## What it does
|
|
6
|
+
|
|
7
|
+
Hive exposes two MCP tools:
|
|
8
|
+
|
|
9
|
+
- **`hivesingle`** — Spawn a single CLI agent with a role-specific system prompt
|
|
10
|
+
- **`hive`** — Spawn 2+ CLI agents in parallel with the same prompt, collect all responses
|
|
11
|
+
|
|
12
|
+
Each agent runs as a child process with full tool access (filesystem, shell, web search) — whatever the underlying CLI supports.
|
|
13
|
+
|
|
14
|
+
## Install
|
|
15
|
+
|
|
16
|
+
### Claude Code
|
|
17
|
+
|
|
18
|
+
```bash
|
|
19
|
+
claude mcp add hive -- npx @alessai/hive-mcp
|
|
20
|
+
```
|
|
21
|
+
|
|
22
|
+
### Cursor / Windsurf / other MCP hosts
|
|
23
|
+
|
|
24
|
+
Add to your MCP config:
|
|
25
|
+
|
|
26
|
+
```json
|
|
27
|
+
{
|
|
28
|
+
"hive": {
|
|
29
|
+
"type": "stdio",
|
|
30
|
+
"command": "npx",
|
|
31
|
+
"args": ["hive-mcp"]
|
|
32
|
+
}
|
|
33
|
+
}
|
|
34
|
+
```
|
|
35
|
+
|
|
36
|
+
### From source
|
|
37
|
+
|
|
38
|
+
```bash
|
|
39
|
+
git clone https://github.com/alessai/Hive-MCP.git
|
|
40
|
+
cd Hive-MCP
|
|
41
|
+
npm install && npm run build
|
|
42
|
+
claude mcp add hive node ./dist/index.js
|
|
43
|
+
```
|
|
44
|
+
|
|
45
|
+
## Prerequisites
|
|
46
|
+
|
|
47
|
+
You need the CLI tools installed for whichever agents you want to use:
|
|
48
|
+
|
|
49
|
+
| Agent | CLI | Install |
|
|
50
|
+
|-------|-----|---------|
|
|
51
|
+
| Gemini | `gemini` | `npm install -g @anthropic-ai/gemini-cli` or see [Gemini CLI docs](https://github.com/google-gemini/gemini-cli) |
|
|
52
|
+
| Claude | `claude` | `npm install -g @anthropic-ai/claude-code` or see [Claude Code docs](https://docs.anthropic.com/en/docs/claude-code) |
|
|
53
|
+
| Codex | `codex` | See [Codex CLI docs](https://github.com/openai/codex) |
|
|
54
|
+
|
|
55
|
+
Only install the CLIs you plan to use. Hive will report a clear error if a CLI isn't found.
|
|
56
|
+
|
|
57
|
+
## Tools
|
|
58
|
+
|
|
59
|
+
### `hivesingle`
|
|
60
|
+
|
|
61
|
+
Spawn a single CLI agent.
|
|
62
|
+
|
|
63
|
+
| Parameter | Type | Required | Description |
|
|
64
|
+
|-----------|------|----------|-------------|
|
|
65
|
+
| `client` | string | yes | CLI client to use (`gemini`, `claude`, `codex`, `glm`, or custom) |
|
|
66
|
+
| `prompt` | string | yes | The task or question |
|
|
67
|
+
| `role` | string | no | Role-based system prompt (see [Roles](#roles)) |
|
|
68
|
+
| `continuation_id` | string | no | Thread ID for multi-turn conversations |
|
|
69
|
+
| `cwd` | string | no | Working directory for the CLI process |
|
|
70
|
+
|
|
71
|
+
### `hive`
|
|
72
|
+
|
|
73
|
+
Spawn multiple CLI agents in parallel with the same prompt. Defaults to `gemini` + `glm`.
|
|
74
|
+
|
|
75
|
+
| Parameter | Type | Required | Description |
|
|
76
|
+
|-----------|------|----------|-------------|
|
|
77
|
+
| `clients` | string[] | no | CLI clients to query (default: `["gemini", "glm"]`) |
|
|
78
|
+
| `prompt` | string | yes | The task or question |
|
|
79
|
+
| `role` | string | no | Role-based system prompt (see [Roles](#roles)) |
|
|
80
|
+
| `cwd` | string | no | Working directory for all CLI processes |
|
|
81
|
+
|
|
82
|
+
## Roles
|
|
83
|
+
|
|
84
|
+
Role prompts shape agent behavior. Each role injects a system prompt tailored for the task:
|
|
85
|
+
|
|
86
|
+
| Role | Purpose |
|
|
87
|
+
|------|---------|
|
|
88
|
+
| `default` | General-purpose assistant |
|
|
89
|
+
| `reviewer` | Code review — bugs, style, security |
|
|
90
|
+
| `debugger` | Systematic debugging and root cause analysis |
|
|
91
|
+
| `planner` | Break down tasks into implementation steps |
|
|
92
|
+
| `thinker` | Deep exploration before answering |
|
|
93
|
+
| `analyst` | Architecture and dependency analysis |
|
|
94
|
+
| `refactor` | Improve code structure without changing behavior |
|
|
95
|
+
| `testgen` | Generate comprehensive test cases |
|
|
96
|
+
| `secaudit` | Security audit (OWASP top 10, etc.) |
|
|
97
|
+
| `docgen` | Generate documentation |
|
|
98
|
+
| `precommit` | Pre-commit review checklist |
|
|
99
|
+
| `challenger` | Devil's advocate — find flaws and risks |
|
|
100
|
+
| `apilookup` | Find correct API usage and signatures |
|
|
101
|
+
| `tracer` | Trace execution flow through code |
|
|
102
|
+
|
|
103
|
+
All agents also receive a capabilities preamble reminding them they have full tool access (filesystem, shell, web).
|
|
104
|
+
|
|
105
|
+
## CLI client configuration
|
|
106
|
+
|
|
107
|
+
### Built-in clients
|
|
108
|
+
|
|
109
|
+
Hive ships with configs for 4 clients in `conf/cli_clients/`:
|
|
110
|
+
|
|
111
|
+
| Client | CLI | Model | Timeout |
|
|
112
|
+
|--------|-----|-------|---------|
|
|
113
|
+
| `gemini` | `gemini` | gemini-2.5-pro | 5 min |
|
|
114
|
+
| `claude` | `claude` | default | 30 min |
|
|
115
|
+
| `glm` | `claude` | opus | 30 min |
|
|
116
|
+
| `codex` | `codex` | default | 10 min |
|
|
117
|
+
|
|
118
|
+
### Custom clients
|
|
119
|
+
|
|
120
|
+
Add JSON files to `~/.hive/cli_clients/` to register custom clients or override built-ins.
|
|
121
|
+
|
|
122
|
+
```json
|
|
123
|
+
{
|
|
124
|
+
"name": "my-agent",
|
|
125
|
+
"command": "my-cli-tool",
|
|
126
|
+
"runner": "gemini",
|
|
127
|
+
"additional_args": ["--flag", "value"],
|
|
128
|
+
"env": {},
|
|
129
|
+
"timeout_seconds": 300,
|
|
130
|
+
"roles": {}
|
|
131
|
+
}
|
|
132
|
+
```
|
|
133
|
+
|
|
134
|
+
**Fields:**
|
|
135
|
+
|
|
136
|
+
| Field | Type | Description |
|
|
137
|
+
|-------|------|-------------|
|
|
138
|
+
| `name` | string | Client name (used in tool calls) |
|
|
139
|
+
| `command` | string | CLI executable name or path |
|
|
140
|
+
| `runner` | string | Agent behavior: `"gemini"`, `"claude"`, `"codex"`, or omit for base |
|
|
141
|
+
| `additional_args` | string[] | Extra CLI arguments |
|
|
142
|
+
| `env` | object | Environment variables for the process |
|
|
143
|
+
| `timeout_seconds` | number | Process timeout (default: 300) |
|
|
144
|
+
| `roles` | object | Per-role overrides (optional) |
|
|
145
|
+
|
|
146
|
+
The `runner` field determines how Hive interacts with the CLI:
|
|
147
|
+
|
|
148
|
+
| Runner | System prompt | Output format | Parser |
|
|
149
|
+
|--------|--------------|---------------|--------|
|
|
150
|
+
| `gemini` | via `-p` flag | JSON (`-o json`) | Extracts from Gemini JSON response |
|
|
151
|
+
| `claude` | via `--append-system-prompt` flag | JSON (`--output-format json`) | Extracts from Claude JSONL events |
|
|
152
|
+
| `codex` | via stdin | JSONL (`exec --json`) | Extracts from Codex JSONL stream |
|
|
153
|
+
| base (default) | via stdin | raw text | Returns stdout as-is |
|
|
154
|
+
|
|
155
|
+
User configs in `~/.hive/cli_clients/` override built-in configs with the same name.
|
|
156
|
+
|
|
157
|
+
## Multi-turn conversations
|
|
158
|
+
|
|
159
|
+
Pass a `continuation_id` to `hivesingle` to maintain context across calls. Hive stores conversation turns on disk (`~/.hive/threads/`) with a 30-minute TTL and 100-thread LRU cap.
|
|
160
|
+
|
|
161
|
+
```
|
|
162
|
+
# First call
|
|
163
|
+
hivesingle(client: "gemini", prompt: "Explain this codebase", continuation_id: "session-1")
|
|
164
|
+
|
|
165
|
+
# Follow-up (context is preserved)
|
|
166
|
+
hivesingle(client: "gemini", prompt: "Now focus on the auth module", continuation_id: "session-1")
|
|
167
|
+
```
|
|
168
|
+
|
|
169
|
+
## How it works
|
|
170
|
+
|
|
171
|
+
```
|
|
172
|
+
MCP Host (Claude Code, Cursor, etc.)
|
|
173
|
+
↓ MCP tool call
|
|
174
|
+
Hive MCP Server
|
|
175
|
+
↓ child_process.spawn()
|
|
176
|
+
CLI Agent (gemini, claude, codex)
|
|
177
|
+
↓ stdout/stderr
|
|
178
|
+
Parse output → return to host
|
|
179
|
+
```
|
|
180
|
+
|
|
181
|
+
1. The MCP host calls `hivesingle` or `hive`
|
|
182
|
+
2. Hive resolves the client config, loads the role prompt, and builds CLI arguments
|
|
183
|
+
3. The CLI is spawned as a child process with the prompt piped via stdin or flags
|
|
184
|
+
4. Hive streams progress notifications back to the host while waiting
|
|
185
|
+
5. On completion, the output is parsed (JSON/JSONL/raw) and returned
|
|
186
|
+
|
|
187
|
+
Each agent runs in its own process with full access to whatever tools the CLI provides. Hive is just the bridge.
|
|
188
|
+
|
|
189
|
+
## Project structure
|
|
190
|
+
|
|
191
|
+
```
|
|
192
|
+
├── conf/cli_clients/ # Built-in CLI client configs (JSON)
|
|
193
|
+
├── prompts/ # 14 role-based system prompt templates
|
|
194
|
+
├── src/
|
|
195
|
+
│ ├── index.ts # MCP server entry point, tool registration
|
|
196
|
+
│ ├── types.ts # TypeScript interfaces
|
|
197
|
+
│ ├── agents/ # CLI agent implementations (base, gemini, claude, codex)
|
|
198
|
+
│ ├── config/ # Config loading, internal defaults, constants
|
|
199
|
+
│ ├── parsers/ # Output parsers (gemini JSON, claude JSONL, codex JSONL, raw)
|
|
200
|
+
│ ├── prompts/ # Prompt template loader
|
|
201
|
+
│ ├── continuation/ # Multi-turn conversation store
|
|
202
|
+
│ └── tools/ # Tool handlers (hivesingle, hive consensus)
|
|
203
|
+
├── dist/ # Compiled output (gitignored)
|
|
204
|
+
└── package.json
|
|
205
|
+
```
|
|
206
|
+
|
|
207
|
+
## Development
|
|
208
|
+
|
|
209
|
+
```bash
|
|
210
|
+
npm run dev # Watch mode (recompiles on changes)
|
|
211
|
+
npm run build # One-time build
|
|
212
|
+
npm start # Run the server directly
|
|
213
|
+
```
|
|
214
|
+
|
|
215
|
+
## License
|
|
216
|
+
|
|
217
|
+
[MIT](LICENSE)
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
import type { ResolvedClient, SpawnResult, ProgressCallback } from "../types.js";
|
|
2
|
+
export declare class BaseCLIAgent {
|
|
3
|
+
protected client: ResolvedClient;
|
|
4
|
+
constructor(client: ResolvedClient);
|
|
5
|
+
/** Build the full args array for the CLI command */
|
|
6
|
+
protected buildArgs(systemPrompt: string | undefined, userPrompt: string): string[];
|
|
7
|
+
/** Build the stdin content to pipe to the process */
|
|
8
|
+
protected buildStdin(systemPrompt: string | undefined, userPrompt: string): string;
|
|
9
|
+
/** Run the CLI process */
|
|
10
|
+
run(systemPrompt: string | undefined, userPrompt: string, cwd?: string, onProgress?: ProgressCallback): Promise<SpawnResult>;
|
|
11
|
+
}
|
|
12
|
+
//# sourceMappingURL=base.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"base.d.ts","sourceRoot":"","sources":["../../src/agents/base.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,cAAc,EAAE,WAAW,EAAE,gBAAgB,EAAE,MAAM,aAAa,CAAC;AAoBjF,qBAAa,YAAY;IACvB,SAAS,CAAC,MAAM,EAAE,cAAc,CAAC;gBAErB,MAAM,EAAE,cAAc;IAIlC,oDAAoD;IACpD,SAAS,CAAC,SAAS,CAAC,YAAY,EAAE,MAAM,GAAG,SAAS,EAAE,UAAU,EAAE,MAAM,GAAG,MAAM,EAAE;IAUnF,qDAAqD;IACrD,SAAS,CAAC,UAAU,CAAC,YAAY,EAAE,MAAM,GAAG,SAAS,EAAE,UAAU,EAAE,MAAM,GAAG,MAAM;IAOlF,0BAA0B;IACpB,GAAG,CAAC,YAAY,EAAE,MAAM,GAAG,SAAS,EAAE,UAAU,EAAE,MAAM,EAAE,GAAG,CAAC,EAAE,MAAM,EAAE,UAAU,CAAC,EAAE,gBAAgB,GAAG,OAAO,CAAC,WAAW,CAAC;CA6GnI"}
|
|
@@ -0,0 +1,138 @@
|
|
|
1
|
+
import { spawn } from "node:child_process";
|
|
2
|
+
import { MAX_OUTPUT_CHARS } from "../config/constants.js";
|
|
3
|
+
import { log } from "../log.js";
|
|
4
|
+
// Track active child processes for cleanup on server exit
|
|
5
|
+
const activeChildren = new Set();
|
|
6
|
+
function cleanupChildren() {
|
|
7
|
+
for (const child of activeChildren) {
|
|
8
|
+
try {
|
|
9
|
+
if (child.pid)
|
|
10
|
+
process.kill(-child.pid, "SIGKILL");
|
|
11
|
+
}
|
|
12
|
+
catch { /* already dead */ }
|
|
13
|
+
}
|
|
14
|
+
activeChildren.clear();
|
|
15
|
+
}
|
|
16
|
+
// Clean up children on exit. Use "exit" event only — signal handlers
|
|
17
|
+
// that call process.exit() prevent stdout from flushing (breaks MCP stdio transport).
|
|
18
|
+
process.on("exit", cleanupChildren);
|
|
19
|
+
export class BaseCLIAgent {
|
|
20
|
+
client;
|
|
21
|
+
constructor(client) {
|
|
22
|
+
this.client = client;
|
|
23
|
+
}
|
|
24
|
+
/** Build the full args array for the CLI command */
|
|
25
|
+
buildArgs(systemPrompt, userPrompt) {
|
|
26
|
+
const args = [...this.client.output_args, ...this.client.additional_args];
|
|
27
|
+
if (systemPrompt && this.client.prompt_injection === "flag" && this.client.prompt_flag) {
|
|
28
|
+
args.push(this.client.prompt_flag, systemPrompt);
|
|
29
|
+
}
|
|
30
|
+
return args;
|
|
31
|
+
}
|
|
32
|
+
/** Build the stdin content to pipe to the process */
|
|
33
|
+
buildStdin(systemPrompt, userPrompt) {
|
|
34
|
+
if (systemPrompt && this.client.prompt_injection === "stdin") {
|
|
35
|
+
return `${systemPrompt}\n\n${userPrompt}`;
|
|
36
|
+
}
|
|
37
|
+
return userPrompt;
|
|
38
|
+
}
|
|
39
|
+
/** Run the CLI process */
|
|
40
|
+
async run(systemPrompt, userPrompt, cwd, onProgress) {
|
|
41
|
+
const args = this.buildArgs(systemPrompt, userPrompt);
|
|
42
|
+
const stdinContent = this.buildStdin(systemPrompt, userPrompt);
|
|
43
|
+
// Strip env vars that block nested sessions or corrupt JSON output
|
|
44
|
+
const { CLAUDECODE: _1, // Prevents Claude-in-Claude nesting check
|
|
45
|
+
FORCE_COLOR: _2, // Prevents ANSI escape codes in JSON output
|
|
46
|
+
NO_COLOR: _3, // Let CLIs decide color based on TTY detection
|
|
47
|
+
...cleanEnv } = process.env;
|
|
48
|
+
const env = { ...cleanEnv, ...this.client.env };
|
|
49
|
+
const timeoutMs = this.client.timeout_seconds * 1000;
|
|
50
|
+
log(`[${this.client.name}] Spawning: ${this.client.command} ${args.map(a => a.length > 80 ? a.slice(0, 80) + "..." : a).join(" ")}`);
|
|
51
|
+
return new Promise((resolve) => {
|
|
52
|
+
let stdout = "";
|
|
53
|
+
let stderr = "";
|
|
54
|
+
let timedOut = false;
|
|
55
|
+
let settled = false;
|
|
56
|
+
const spawnStart = Date.now();
|
|
57
|
+
const child = spawn(this.client.command, args, {
|
|
58
|
+
cwd: cwd ?? process.cwd(),
|
|
59
|
+
env,
|
|
60
|
+
stdio: ["pipe", "pipe", "pipe"],
|
|
61
|
+
detached: true, // Create process group so we can kill the entire tree
|
|
62
|
+
});
|
|
63
|
+
activeChildren.add(child);
|
|
64
|
+
// Periodic progress updates every 10s while waiting
|
|
65
|
+
const progressInterval = onProgress ? setInterval(() => {
|
|
66
|
+
const elapsed = Math.round((Date.now() - spawnStart) / 1000);
|
|
67
|
+
const bytesReceived = stdout.length + stderr.length;
|
|
68
|
+
const progressPct = Math.min(80, Math.round((elapsed / this.client.timeout_seconds) * 80));
|
|
69
|
+
onProgress(`Waiting for ${this.client.name} response... (${elapsed}s elapsed, ${bytesReceived.toLocaleString()} bytes received)`, progressPct, 100).catch(() => { }); // fire-and-forget, don't crash on notification failure
|
|
70
|
+
}, 10_000) : undefined;
|
|
71
|
+
const timer = setTimeout(() => {
|
|
72
|
+
timedOut = true;
|
|
73
|
+
log(`[${this.client.name}] Timeout after ${this.client.timeout_seconds}s — sending SIGTERM`);
|
|
74
|
+
// Kill the entire process group (child + its subprocesses)
|
|
75
|
+
try {
|
|
76
|
+
if (child.pid)
|
|
77
|
+
process.kill(-child.pid, "SIGTERM");
|
|
78
|
+
}
|
|
79
|
+
catch { /* already dead */ }
|
|
80
|
+
// Force kill after 3s grace period
|
|
81
|
+
setTimeout(() => {
|
|
82
|
+
try {
|
|
83
|
+
if (child.pid)
|
|
84
|
+
process.kill(-child.pid, "SIGKILL");
|
|
85
|
+
}
|
|
86
|
+
catch { /* already dead */ }
|
|
87
|
+
}, 3000);
|
|
88
|
+
}, timeoutMs);
|
|
89
|
+
child.stdout.on("data", (chunk) => {
|
|
90
|
+
// Raw buffer needs to be large enough to capture verbose JSON event streams
|
|
91
|
+
// (Claude's --output-format json includes init events with all tool names).
|
|
92
|
+
// Final response is still capped at MAX_OUTPUT_CHARS in hive.ts.
|
|
93
|
+
if (stdout.length < MAX_OUTPUT_CHARS * 20) {
|
|
94
|
+
stdout += chunk.toString();
|
|
95
|
+
}
|
|
96
|
+
});
|
|
97
|
+
child.stderr.on("data", (chunk) => {
|
|
98
|
+
if (stderr.length < MAX_OUTPUT_CHARS) {
|
|
99
|
+
stderr += chunk.toString();
|
|
100
|
+
}
|
|
101
|
+
});
|
|
102
|
+
// Prevent stdin errors from crashing the server (child may die before write completes)
|
|
103
|
+
child.stdin.on("error", () => { });
|
|
104
|
+
const finish = (exitCode) => {
|
|
105
|
+
if (settled)
|
|
106
|
+
return;
|
|
107
|
+
settled = true;
|
|
108
|
+
clearTimeout(timer);
|
|
109
|
+
if (progressInterval)
|
|
110
|
+
clearInterval(progressInterval);
|
|
111
|
+
activeChildren.delete(child);
|
|
112
|
+
log(`[${this.client.name}] Exited: code=${exitCode} timedOut=${timedOut} stdout=${stdout.length}bytes stderr=${stderr.length}bytes`);
|
|
113
|
+
resolve({ stdout, stderr, exitCode, timedOut });
|
|
114
|
+
};
|
|
115
|
+
child.on("close", (code) => finish(code));
|
|
116
|
+
child.on("error", (err) => {
|
|
117
|
+
const msg = err.code === "ENOENT"
|
|
118
|
+
? `CLI "${this.client.command}" not found. Is it installed and in PATH?`
|
|
119
|
+
: `Spawn error: ${err.message}`;
|
|
120
|
+
log(`[${this.client.name}] Error: ${msg}`);
|
|
121
|
+
stderr += `\n${msg}`;
|
|
122
|
+
finish(1);
|
|
123
|
+
});
|
|
124
|
+
// Detached processes won't keep the parent alive — unref so MCP server can exit cleanly
|
|
125
|
+
child.unref();
|
|
126
|
+
// Write to stdin and close
|
|
127
|
+
if (stdinContent) {
|
|
128
|
+
child.stdin.write(stdinContent, () => {
|
|
129
|
+
child.stdin.end();
|
|
130
|
+
});
|
|
131
|
+
}
|
|
132
|
+
else {
|
|
133
|
+
child.stdin.end();
|
|
134
|
+
}
|
|
135
|
+
});
|
|
136
|
+
}
|
|
137
|
+
}
|
|
138
|
+
//# sourceMappingURL=base.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"base.js","sourceRoot":"","sources":["../../src/agents/base.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
import { BaseCLIAgent } from "./base.js";
|
|
2
|
+
import type { ResolvedClient } from "../types.js";
|
|
3
|
+
export declare class ClaudeAgent extends BaseCLIAgent {
|
|
4
|
+
constructor(client: ResolvedClient);
|
|
5
|
+
/** Claude uses --append-system-prompt flag for system prompt injection, user prompt via stdin */
|
|
6
|
+
protected buildArgs(systemPrompt: string | undefined, userPrompt: string): string[];
|
|
7
|
+
/** Claude gets user prompt via stdin only (system prompt goes via flag) */
|
|
8
|
+
protected buildStdin(systemPrompt: string | undefined, userPrompt: string): string;
|
|
9
|
+
}
|
|
10
|
+
//# sourceMappingURL=claude.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"claude.d.ts","sourceRoot":"","sources":["../../src/agents/claude.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,YAAY,EAAE,MAAM,WAAW,CAAC;AACzC,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,aAAa,CAAC;AAElD,qBAAa,WAAY,SAAQ,YAAY;gBAC/B,MAAM,EAAE,cAAc;IAIlC,iGAAiG;cAC9E,SAAS,CAAC,YAAY,EAAE,MAAM,GAAG,SAAS,EAAE,UAAU,EAAE,MAAM,GAAG,MAAM,EAAE;IAU5F,2EAA2E;cACxD,UAAU,CAAC,YAAY,EAAE,MAAM,GAAG,SAAS,EAAE,UAAU,EAAE,MAAM,GAAG,MAAM;CAG5F"}
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
import { BaseCLIAgent } from "./base.js";
|
|
2
|
+
export class ClaudeAgent extends BaseCLIAgent {
|
|
3
|
+
constructor(client) {
|
|
4
|
+
super(client);
|
|
5
|
+
}
|
|
6
|
+
/** Claude uses --append-system-prompt flag for system prompt injection, user prompt via stdin */
|
|
7
|
+
buildArgs(systemPrompt, userPrompt) {
|
|
8
|
+
const args = [...this.client.output_args, ...this.client.additional_args];
|
|
9
|
+
if (systemPrompt && this.client.prompt_flag) {
|
|
10
|
+
args.push(this.client.prompt_flag, systemPrompt);
|
|
11
|
+
}
|
|
12
|
+
return args;
|
|
13
|
+
}
|
|
14
|
+
/** Claude gets user prompt via stdin only (system prompt goes via flag) */
|
|
15
|
+
buildStdin(systemPrompt, userPrompt) {
|
|
16
|
+
return userPrompt;
|
|
17
|
+
}
|
|
18
|
+
}
|
|
19
|
+
//# sourceMappingURL=claude.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"claude.js","sourceRoot":"","sources":["../../src/agents/claude.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,YAAY,EAAE,MAAM,WAAW,CAAC;AAGzC,MAAM,OAAO,WAAY,SAAQ,YAAY;IAC3C,YAAY,MAAsB;QAChC,KAAK,CAAC,MAAM,CAAC,CAAC;IAChB,CAAC;IAED,iGAAiG;IAC9E,SAAS,CAAC,YAAgC,EAAE,UAAkB;QAC/E,MAAM,IAAI,GAAa,CAAC,GAAG,IAAI,CAAC,MAAM,CAAC,WAAW,EAAE,GAAG,IAAI,CAAC,MAAM,CAAC,eAAe,CAAC,CAAC;QAEpF,IAAI,YAAY,IAAI,IAAI,CAAC,MAAM,CAAC,WAAW,EAAE,CAAC;YAC5C,IAAI,CAAC,IAAI,CAAC,IAAI,CAAC,MAAM,CAAC,WAAW,EAAE,YAAY,CAAC,CAAC;QACnD,CAAC;QAED,OAAO,IAAI,CAAC;IACd,CAAC;IAED,2EAA2E;IACxD,UAAU,CAAC,YAAgC,EAAE,UAAkB;QAChF,OAAO,UAAU,CAAC;IACpB,CAAC;CACF"}
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
import { BaseCLIAgent } from "./base.js";
|
|
2
|
+
import type { ResolvedClient, SpawnResult, ProgressCallback } from "../types.js";
|
|
3
|
+
export declare class CodexAgent extends BaseCLIAgent {
|
|
4
|
+
constructor(client: ResolvedClient);
|
|
5
|
+
/** Codex uses `exec` subcommand — inject it before other args if not already present */
|
|
6
|
+
protected buildArgs(systemPrompt: string | undefined, userPrompt: string): string[];
|
|
7
|
+
/** Codex JSONL output can have broken lines — stderr is useful for diagnostics */
|
|
8
|
+
run(systemPrompt: string | undefined, userPrompt: string, cwd?: string, onProgress?: ProgressCallback): Promise<SpawnResult>;
|
|
9
|
+
}
|
|
10
|
+
//# sourceMappingURL=codex.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"codex.d.ts","sourceRoot":"","sources":["../../src/agents/codex.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,YAAY,EAAE,MAAM,WAAW,CAAC;AACzC,OAAO,KAAK,EAAE,cAAc,EAAE,WAAW,EAAE,gBAAgB,EAAE,MAAM,aAAa,CAAC;AAEjF,qBAAa,UAAW,SAAQ,YAAY;gBAC9B,MAAM,EAAE,cAAc;IAIlC,wFAAwF;cACrE,SAAS,CAAC,YAAY,EAAE,MAAM,GAAG,SAAS,EAAE,UAAU,EAAE,MAAM,GAAG,MAAM,EAAE;IAW5F,kFAAkF;IACnE,GAAG,CAAC,YAAY,EAAE,MAAM,GAAG,SAAS,EAAE,UAAU,EAAE,MAAM,EAAE,GAAG,CAAC,EAAE,MAAM,EAAE,UAAU,CAAC,EAAE,gBAAgB,GAAG,OAAO,CAAC,WAAW,CAAC;CAI5I"}
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
import { BaseCLIAgent } from "./base.js";
|
|
2
|
+
export class CodexAgent extends BaseCLIAgent {
|
|
3
|
+
constructor(client) {
|
|
4
|
+
super(client);
|
|
5
|
+
}
|
|
6
|
+
/** Codex uses `exec` subcommand — inject it before other args if not already present */
|
|
7
|
+
buildArgs(systemPrompt, userPrompt) {
|
|
8
|
+
const args = super.buildArgs(systemPrompt, userPrompt);
|
|
9
|
+
// Ensure 'exec' is first if output_args doesn't already start with it
|
|
10
|
+
if (args[0] !== "exec") {
|
|
11
|
+
// output_args for codex should be ["exec", "--json"] so this is a safety check
|
|
12
|
+
}
|
|
13
|
+
return args;
|
|
14
|
+
}
|
|
15
|
+
/** Codex JSONL output can have broken lines — stderr is useful for diagnostics */
|
|
16
|
+
async run(systemPrompt, userPrompt, cwd, onProgress) {
|
|
17
|
+
const result = await super.run(systemPrompt, userPrompt, cwd, onProgress);
|
|
18
|
+
return result;
|
|
19
|
+
}
|
|
20
|
+
}
|
|
21
|
+
//# sourceMappingURL=codex.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"codex.js","sourceRoot":"","sources":["../../src/agents/codex.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,YAAY,EAAE,MAAM,WAAW,CAAC;AAGzC,MAAM,OAAO,UAAW,SAAQ,YAAY;IAC1C,YAAY,MAAsB;QAChC,KAAK,CAAC,MAAM,CAAC,CAAC;IAChB,CAAC;IAED,wFAAwF;IACrE,SAAS,CAAC,YAAgC,EAAE,UAAkB;QAC/E,MAAM,IAAI,GAAG,KAAK,CAAC,SAAS,CAAC,YAAY,EAAE,UAAU,CAAC,CAAC;QAEvD,sEAAsE;QACtE,IAAI,IAAI,CAAC,CAAC,CAAC,KAAK,MAAM,EAAE,CAAC;YACvB,+EAA+E;QACjF,CAAC;QAED,OAAO,IAAI,CAAC;IACd,CAAC;IAED,kFAAkF;IACzE,KAAK,CAAC,GAAG,CAAC,YAAgC,EAAE,UAAkB,EAAE,GAAY,EAAE,UAA6B;QAClH,MAAM,MAAM,GAAG,MAAM,KAAK,CAAC,GAAG,CAAC,YAAY,EAAE,UAAU,EAAE,GAAG,EAAE,UAAU,CAAC,CAAC;QAC1E,OAAO,MAAM,CAAC;IAChB,CAAC;CACF"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"factory.d.ts","sourceRoot":"","sources":["../../src/agents/factory.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,aAAa,CAAC;AAClD,OAAO,EAAE,YAAY,EAAE,MAAM,WAAW,CAAC;AAKzC,wBAAgB,WAAW,CAAC,MAAM,EAAE,cAAc,GAAG,YAAY,CAWhE"}
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
import { BaseCLIAgent } from "./base.js";
|
|
2
|
+
import { GeminiAgent } from "./gemini.js";
|
|
3
|
+
import { ClaudeAgent } from "./claude.js";
|
|
4
|
+
import { CodexAgent } from "./codex.js";
|
|
5
|
+
export function createAgent(client) {
|
|
6
|
+
switch (client.runner) {
|
|
7
|
+
case "gemini":
|
|
8
|
+
return new GeminiAgent(client);
|
|
9
|
+
case "claude":
|
|
10
|
+
return new ClaudeAgent(client);
|
|
11
|
+
case "codex":
|
|
12
|
+
return new CodexAgent(client);
|
|
13
|
+
default:
|
|
14
|
+
return new BaseCLIAgent(client);
|
|
15
|
+
}
|
|
16
|
+
}
|
|
17
|
+
//# sourceMappingURL=factory.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"factory.js","sourceRoot":"","sources":["../../src/agents/factory.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,YAAY,EAAE,MAAM,WAAW,CAAC;AACzC,OAAO,EAAE,WAAW,EAAE,MAAM,aAAa,CAAC;AAC1C,OAAO,EAAE,WAAW,EAAE,MAAM,aAAa,CAAC;AAC1C,OAAO,EAAE,UAAU,EAAE,MAAM,YAAY,CAAC;AAExC,MAAM,UAAU,WAAW,CAAC,MAAsB;IAChD,QAAQ,MAAM,CAAC,MAAM,EAAE,CAAC;QACtB,KAAK,QAAQ;YACX,OAAO,IAAI,WAAW,CAAC,MAAM,CAAC,CAAC;QACjC,KAAK,QAAQ;YACX,OAAO,IAAI,WAAW,CAAC,MAAM,CAAC,CAAC;QACjC,KAAK,OAAO;YACV,OAAO,IAAI,UAAU,CAAC,MAAM,CAAC,CAAC;QAChC;YACE,OAAO,IAAI,YAAY,CAAC,MAAM,CAAC,CAAC;IACpC,CAAC;AACH,CAAC"}
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
import { BaseCLIAgent } from "./base.js";
|
|
2
|
+
import type { ResolvedClient, SpawnResult, ProgressCallback } from "../types.js";
|
|
3
|
+
export declare class GeminiAgent extends BaseCLIAgent {
|
|
4
|
+
constructor(client: ResolvedClient);
|
|
5
|
+
/**
|
|
6
|
+
* Gemini uses -p for headless mode. When both -p and stdin are provided,
|
|
7
|
+
* -p gives the instruction and stdin provides content.
|
|
8
|
+
*
|
|
9
|
+
* Strategy:
|
|
10
|
+
* - System prompt → -p flag (instructions)
|
|
11
|
+
* - User prompt → stdin (content, no arg length limit)
|
|
12
|
+
* - No system prompt → -p with user prompt directly
|
|
13
|
+
*/
|
|
14
|
+
protected buildArgs(systemPrompt: string | undefined, userPrompt: string): string[];
|
|
15
|
+
/**
|
|
16
|
+
* Stdin carries the user prompt when system prompt is in -p,
|
|
17
|
+
* or empty when user prompt is short enough for -p.
|
|
18
|
+
*/
|
|
19
|
+
protected buildStdin(systemPrompt: string | undefined, userPrompt: string): string;
|
|
20
|
+
/** Filter known Gemini stderr noise */
|
|
21
|
+
run(systemPrompt: string | undefined, userPrompt: string, cwd?: string, onProgress?: ProgressCallback): Promise<SpawnResult>;
|
|
22
|
+
}
|
|
23
|
+
//# sourceMappingURL=gemini.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"gemini.d.ts","sourceRoot":"","sources":["../../src/agents/gemini.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,YAAY,EAAE,MAAM,WAAW,CAAC;AACzC,OAAO,KAAK,EAAE,cAAc,EAAE,WAAW,EAAE,gBAAgB,EAAE,MAAM,aAAa,CAAC;AAEjF,qBAAa,WAAY,SAAQ,YAAY;gBAC/B,MAAM,EAAE,cAAc;IAIlC;;;;;;;;OAQG;cACgB,SAAS,CAAC,YAAY,EAAE,MAAM,GAAG,SAAS,EAAE,UAAU,EAAE,MAAM,GAAG,MAAM,EAAE;IAoB5F;;;OAGG;cACgB,UAAU,CAAC,YAAY,EAAE,MAAM,GAAG,SAAS,EAAE,UAAU,EAAE,MAAM,GAAG,MAAM;IAY3F,uCAAuC;IACxB,GAAG,CAAC,YAAY,EAAE,MAAM,GAAG,SAAS,EAAE,UAAU,EAAE,MAAM,EAAE,GAAG,CAAC,EAAE,MAAM,EAAE,UAAU,CAAC,EAAE,gBAAgB,GAAG,OAAO,CAAC,WAAW,CAAC;CAa5I"}
|
|
@@ -0,0 +1,62 @@
|
|
|
1
|
+
import { BaseCLIAgent } from "./base.js";
|
|
2
|
+
export class GeminiAgent extends BaseCLIAgent {
|
|
3
|
+
constructor(client) {
|
|
4
|
+
super(client);
|
|
5
|
+
}
|
|
6
|
+
/**
|
|
7
|
+
* Gemini uses -p for headless mode. When both -p and stdin are provided,
|
|
8
|
+
* -p gives the instruction and stdin provides content.
|
|
9
|
+
*
|
|
10
|
+
* Strategy:
|
|
11
|
+
* - System prompt → -p flag (instructions)
|
|
12
|
+
* - User prompt → stdin (content, no arg length limit)
|
|
13
|
+
* - No system prompt → -p with user prompt directly
|
|
14
|
+
*/
|
|
15
|
+
buildArgs(systemPrompt, userPrompt) {
|
|
16
|
+
const args = [...this.client.output_args, ...this.client.additional_args];
|
|
17
|
+
if (systemPrompt) {
|
|
18
|
+
// System prompt as -p instruction, user prompt goes via stdin
|
|
19
|
+
args.push("-p", systemPrompt);
|
|
20
|
+
}
|
|
21
|
+
else {
|
|
22
|
+
// No system prompt — use -p for headless mode with short prompt,
|
|
23
|
+
// or stdin for long prompts to avoid arg length limits
|
|
24
|
+
if (userPrompt.length < 50_000) {
|
|
25
|
+
args.push("-p", userPrompt);
|
|
26
|
+
}
|
|
27
|
+
else {
|
|
28
|
+
// Long prompt — -p with minimal instruction, full prompt via stdin
|
|
29
|
+
args.push("-p", "Process the following input:");
|
|
30
|
+
}
|
|
31
|
+
}
|
|
32
|
+
return args;
|
|
33
|
+
}
|
|
34
|
+
/**
|
|
35
|
+
* Stdin carries the user prompt when system prompt is in -p,
|
|
36
|
+
* or empty when user prompt is short enough for -p.
|
|
37
|
+
*/
|
|
38
|
+
buildStdin(systemPrompt, userPrompt) {
|
|
39
|
+
if (systemPrompt) {
|
|
40
|
+
// System prompt is in -p, user prompt goes here
|
|
41
|
+
return userPrompt;
|
|
42
|
+
}
|
|
43
|
+
// No system prompt — if short, it went in -p; if long, it goes here
|
|
44
|
+
if (userPrompt.length < 50_000) {
|
|
45
|
+
return "";
|
|
46
|
+
}
|
|
47
|
+
return userPrompt;
|
|
48
|
+
}
|
|
49
|
+
/** Filter known Gemini stderr noise */
|
|
50
|
+
async run(systemPrompt, userPrompt, cwd, onProgress) {
|
|
51
|
+
const result = await super.run(systemPrompt, userPrompt, cwd, onProgress);
|
|
52
|
+
if (result.stderr) {
|
|
53
|
+
result.stderr = result.stderr
|
|
54
|
+
.split("\n")
|
|
55
|
+
.filter(line => !line.includes("WARNING") && !line.includes("I/O"))
|
|
56
|
+
.join("\n")
|
|
57
|
+
.trim();
|
|
58
|
+
}
|
|
59
|
+
return result;
|
|
60
|
+
}
|
|
61
|
+
}
|
|
62
|
+
//# sourceMappingURL=gemini.js.map
|