@elvatis_com/elvatis-mcp 1.1.2 → 1.2.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/README.md +16 -3
- package/dist/session-registry.d.ts +34 -0
- package/dist/session-registry.d.ts.map +1 -0
- package/dist/session-registry.js +139 -0
- package/dist/session-registry.js.map +1 -0
- package/dist/spawn.d.ts +1 -1
- package/dist/spawn.d.ts.map +1 -1
- package/dist/spawn.js +9 -3
- package/dist/spawn.js.map +1 -1
- package/dist/tools/claude.d.ts +15 -2
- package/dist/tools/claude.d.ts.map +1 -1
- package/dist/tools/claude.js +36 -10
- package/dist/tools/claude.js.map +1 -1
- package/dist/tools/codex.d.ts +11 -2
- package/dist/tools/codex.d.ts.map +1 -1
- package/dist/tools/codex.js +27 -9
- package/dist/tools/codex.js.map +1 -1
- package/dist/tools/gemini.d.ts +14 -5
- package/dist/tools/gemini.d.ts.map +1 -1
- package/dist/tools/gemini.js +30 -11
- package/dist/tools/gemini.js.map +1 -1
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -4,7 +4,7 @@
|
|
|
4
4
|
|
|
5
5
|
[](https://www.npmjs.com/package/@elvatis_com/elvatis-mcp)
|
|
6
6
|
[](LICENSE)
|
|
7
|
-
[](#test-results)
|
|
8
8
|
|
|
9
9
|
## What is this?
|
|
10
10
|
|
|
@@ -54,6 +54,18 @@ The key idea: Claude is the orchestrator, but it can delegate specialized work t
|
|
|
54
54
|
| `codex_run` | OpenAI Codex | Local CLI | OpenAI login | Coding, debugging, file editing, shell scripts | API usage |
|
|
55
55
|
| `local_llm_run` | LM Studio / Ollama / llama.cpp | HTTP | None | Classification, formatting, extraction, rewriting | **Free** |
|
|
56
56
|
|
|
57
|
+
### Session Resume
|
|
58
|
+
|
|
59
|
+
`claude_run`, `gemini_run`, and `codex_run` use **CLI session resume** to eliminate cold-start overhead. On the first call a new session is created; subsequent calls resume it so the model receives only the new message instead of re-processing the full conversation history.
|
|
60
|
+
|
|
61
|
+
| Metric | Without session resume | With session resume |
|
|
62
|
+
|--------|----------------------|---------------------|
|
|
63
|
+
| Prompt size per request | 18-25 KB | <1 KB (new message only) |
|
|
64
|
+
| Claude Sonnet response time | 80-120s (50% hang rate) | 5-10s |
|
|
65
|
+
| Silent hang rate | ~50% | Near 0% |
|
|
66
|
+
|
|
67
|
+
Sessions are persisted to `~/.openclaw/cli-bridge/cli-sessions.json` and expire after 2 hours of inactivity or 50 requests. The `session_id` is returned in every response so you can inspect which session was used.
|
|
68
|
+
|
|
57
69
|
### Smart Prompt Splitting
|
|
58
70
|
|
|
59
71
|
The `prompt_split` tool analyzes complex prompts and breaks them into sub-tasks:
|
|
@@ -252,7 +264,7 @@ Median of 3 runs, `max_tokens=512`. Tasks: classify (1-word sentiment), extract
|
|
|
252
264
|
|-------|---------|-------------|------|-------|
|
|
253
265
|
| **local_llm_run** | GPT-OSS 20B (Vulkan GPU) | **1.0s** | Free | 4x faster than Codex, 6x faster than Claude |
|
|
254
266
|
| codex_run | OpenAI Codex CLI | 4.1s | Pay-per-use | Best for coding tasks |
|
|
255
|
-
| claude_run | Claude Sonnet 4.6 | 6.3s | Pay-per-use | Best for complex reasoning |
|
|
267
|
+
| claude_run | Claude Sonnet 4.6 | 6.3s (5-10s with session resume) | Pay-per-use | Best for complex reasoning |
|
|
256
268
|
| gemini_run | Gemini 2.5 Flash | 34.0s | Free tier | CLI startup overhead, best for long context |
|
|
257
269
|
|
|
258
270
|
### Service Latency (system_status)
|
|
@@ -560,7 +572,8 @@ src/
|
|
|
560
572
|
config.ts Environment variable configuration
|
|
561
573
|
dashboard.ts Status dashboard HTML renderer
|
|
562
574
|
ssh.ts SSH exec helper (Windows/macOS/Linux)
|
|
563
|
-
spawn.ts Local process spawner for CLI sub-agents
|
|
575
|
+
spawn.ts Local process spawner for CLI sub-agents (supports stdin piping)
|
|
576
|
+
session-registry.ts CLI session registry: persist/resume Claude, Gemini, Codex sessions
|
|
564
577
|
tools/
|
|
565
578
|
home.ts Home Assistant: light, climate, scene, vacuum, sensors
|
|
566
579
|
home-automation.ts HA automations: list, trigger, enable, disable
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* CLI Session Registry
|
|
3
|
+
*
|
|
4
|
+
* Maintains persistent sessions for Claude, Gemini, and Codex CLI sub-agents.
|
|
5
|
+
* Session resume avoids re-processing full conversation history on every call,
|
|
6
|
+
* eliminating the silent hang (~50%) and slow response (80-120s) issues caused
|
|
7
|
+
* by large prompt re-tokenization.
|
|
8
|
+
*
|
|
9
|
+
* Sessions are persisted to ~/.openclaw/cli-bridge/cli-sessions.json.
|
|
10
|
+
* TTL: 2 hours of inactivity, or 50 requests (whichever comes first).
|
|
11
|
+
*/
|
|
12
|
+
export interface CliSessionEntry {
|
|
13
|
+
sessionId: string;
|
|
14
|
+
provider: string;
|
|
15
|
+
model: string;
|
|
16
|
+
createdAt: number;
|
|
17
|
+
lastUsedAt: number;
|
|
18
|
+
requestCount: number;
|
|
19
|
+
}
|
|
20
|
+
/**
|
|
21
|
+
* Returns an existing valid session or creates a new one.
|
|
22
|
+
* A session is valid if it was used within the TTL and has not exceeded MAX_REQUESTS.
|
|
23
|
+
*/
|
|
24
|
+
export declare function getOrCreateSession(provider: string, model: string): CliSessionEntry;
|
|
25
|
+
/** Call after a successful response to update the session metadata. */
|
|
26
|
+
export declare function recordSuccess(provider: string, model: string): void;
|
|
27
|
+
/**
|
|
28
|
+
* Remove a session so the next call creates a fresh one.
|
|
29
|
+
* Use when the CLI reports "session not found" or auth errors.
|
|
30
|
+
*/
|
|
31
|
+
export declare function invalidateSession(provider: string, model: string): void;
|
|
32
|
+
/** Returns true if this session entry is a first-ever request (requestCount === 0). */
|
|
33
|
+
export declare function isNewSession(entry: CliSessionEntry): boolean;
|
|
34
|
+
//# sourceMappingURL=session-registry.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"session-registry.d.ts","sourceRoot":"","sources":["../src/session-registry.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;GAUG;AAOH,MAAM,WAAW,eAAe;IAC9B,SAAS,EAAE,MAAM,CAAC;IAClB,QAAQ,EAAE,MAAM,CAAC;IACjB,KAAK,EAAE,MAAM,CAAC;IACd,SAAS,EAAE,MAAM,CAAC;IAClB,UAAU,EAAE,MAAM,CAAC;IACnB,YAAY,EAAE,MAAM,CAAC;CACtB;AAwCD;;;GAGG;AACH,wBAAgB,kBAAkB,CAAC,QAAQ,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,GAAG,eAAe,CAwBnF;AAED,uEAAuE;AACvE,wBAAgB,aAAa,CAAC,QAAQ,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,GAAG,IAAI,CAQnE;AAED;;;GAGG;AACH,wBAAgB,iBAAiB,CAAC,QAAQ,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,GAAG,IAAI,CAIvE;AAED,uFAAuF;AACvF,wBAAgB,YAAY,CAAC,KAAK,EAAE,eAAe,GAAG,OAAO,CAE5D"}
|
|
@@ -0,0 +1,139 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* CLI Session Registry
|
|
4
|
+
*
|
|
5
|
+
* Maintains persistent sessions for Claude, Gemini, and Codex CLI sub-agents.
|
|
6
|
+
* Session resume avoids re-processing full conversation history on every call,
|
|
7
|
+
* eliminating the silent hang (~50%) and slow response (80-120s) issues caused
|
|
8
|
+
* by large prompt re-tokenization.
|
|
9
|
+
*
|
|
10
|
+
* Sessions are persisted to ~/.openclaw/cli-bridge/cli-sessions.json.
|
|
11
|
+
* TTL: 2 hours of inactivity, or 50 requests (whichever comes first).
|
|
12
|
+
*/
|
|
13
|
+
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
14
|
+
if (k2 === undefined) k2 = k;
|
|
15
|
+
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
16
|
+
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
17
|
+
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
18
|
+
}
|
|
19
|
+
Object.defineProperty(o, k2, desc);
|
|
20
|
+
}) : (function(o, m, k, k2) {
|
|
21
|
+
if (k2 === undefined) k2 = k;
|
|
22
|
+
o[k2] = m[k];
|
|
23
|
+
}));
|
|
24
|
+
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
|
|
25
|
+
Object.defineProperty(o, "default", { enumerable: true, value: v });
|
|
26
|
+
}) : function(o, v) {
|
|
27
|
+
o["default"] = v;
|
|
28
|
+
});
|
|
29
|
+
var __importStar = (this && this.__importStar) || (function () {
|
|
30
|
+
var ownKeys = function(o) {
|
|
31
|
+
ownKeys = Object.getOwnPropertyNames || function (o) {
|
|
32
|
+
var ar = [];
|
|
33
|
+
for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
|
|
34
|
+
return ar;
|
|
35
|
+
};
|
|
36
|
+
return ownKeys(o);
|
|
37
|
+
};
|
|
38
|
+
return function (mod) {
|
|
39
|
+
if (mod && mod.__esModule) return mod;
|
|
40
|
+
var result = {};
|
|
41
|
+
if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
|
|
42
|
+
__setModuleDefault(result, mod);
|
|
43
|
+
return result;
|
|
44
|
+
};
|
|
45
|
+
})();
|
|
46
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
47
|
+
exports.getOrCreateSession = getOrCreateSession;
|
|
48
|
+
exports.recordSuccess = recordSuccess;
|
|
49
|
+
exports.invalidateSession = invalidateSession;
|
|
50
|
+
exports.isNewSession = isNewSession;
|
|
51
|
+
const crypto_1 = require("crypto");
|
|
52
|
+
const fs = __importStar(require("fs"));
|
|
53
|
+
const path = __importStar(require("path"));
|
|
54
|
+
const os = __importStar(require("os"));
|
|
55
|
+
const SESSIONS_FILE = path.join(os.homedir(), '.openclaw', 'cli-bridge', 'cli-sessions.json');
|
|
56
|
+
const TTL_MS = 2 * 60 * 60 * 1000; // 2 hours
|
|
57
|
+
const MAX_REQUESTS = 50;
|
|
58
|
+
const sessions = new Map();
|
|
59
|
+
let loaded = false;
|
|
60
|
+
function sessionKey(provider, model) {
|
|
61
|
+
return `${provider}:${model}`;
|
|
62
|
+
}
|
|
63
|
+
function load() {
|
|
64
|
+
if (loaded)
|
|
65
|
+
return;
|
|
66
|
+
loaded = true;
|
|
67
|
+
try {
|
|
68
|
+
if (fs.existsSync(SESSIONS_FILE)) {
|
|
69
|
+
const raw = fs.readFileSync(SESSIONS_FILE, 'utf8');
|
|
70
|
+
const arr = JSON.parse(raw);
|
|
71
|
+
for (const entry of arr) {
|
|
72
|
+
sessions.set(sessionKey(entry.provider, entry.model), entry);
|
|
73
|
+
}
|
|
74
|
+
}
|
|
75
|
+
}
|
|
76
|
+
catch {
|
|
77
|
+
// Ignore parse errors: start fresh
|
|
78
|
+
}
|
|
79
|
+
}
|
|
80
|
+
function save() {
|
|
81
|
+
try {
|
|
82
|
+
const dir = path.dirname(SESSIONS_FILE);
|
|
83
|
+
if (!fs.existsSync(dir))
|
|
84
|
+
fs.mkdirSync(dir, { recursive: true });
|
|
85
|
+
fs.writeFileSync(SESSIONS_FILE, JSON.stringify([...sessions.values()], null, 2));
|
|
86
|
+
}
|
|
87
|
+
catch {
|
|
88
|
+
// Best-effort: session loss is recoverable (next call creates a fresh session)
|
|
89
|
+
}
|
|
90
|
+
}
|
|
91
|
+
/**
|
|
92
|
+
* Returns an existing valid session or creates a new one.
|
|
93
|
+
* A session is valid if it was used within the TTL and has not exceeded MAX_REQUESTS.
|
|
94
|
+
*/
|
|
95
|
+
function getOrCreateSession(provider, model) {
|
|
96
|
+
load();
|
|
97
|
+
const key = sessionKey(provider, model);
|
|
98
|
+
const existing = sessions.get(key);
|
|
99
|
+
if (existing &&
|
|
100
|
+
(Date.now() - existing.lastUsedAt) < TTL_MS &&
|
|
101
|
+
existing.requestCount < MAX_REQUESTS) {
|
|
102
|
+
return existing;
|
|
103
|
+
}
|
|
104
|
+
const entry = {
|
|
105
|
+
sessionId: (0, crypto_1.randomUUID)(),
|
|
106
|
+
provider,
|
|
107
|
+
model,
|
|
108
|
+
createdAt: Date.now(),
|
|
109
|
+
lastUsedAt: Date.now(),
|
|
110
|
+
requestCount: 0,
|
|
111
|
+
};
|
|
112
|
+
sessions.set(key, entry);
|
|
113
|
+
save();
|
|
114
|
+
return entry;
|
|
115
|
+
}
|
|
116
|
+
/** Call after a successful response to update the session metadata. */
|
|
117
|
+
function recordSuccess(provider, model) {
|
|
118
|
+
load();
|
|
119
|
+
const entry = sessions.get(sessionKey(provider, model));
|
|
120
|
+
if (entry) {
|
|
121
|
+
entry.requestCount++;
|
|
122
|
+
entry.lastUsedAt = Date.now();
|
|
123
|
+
save();
|
|
124
|
+
}
|
|
125
|
+
}
|
|
126
|
+
/**
|
|
127
|
+
* Remove a session so the next call creates a fresh one.
|
|
128
|
+
* Use when the CLI reports "session not found" or auth errors.
|
|
129
|
+
*/
|
|
130
|
+
function invalidateSession(provider, model) {
|
|
131
|
+
load();
|
|
132
|
+
sessions.delete(sessionKey(provider, model));
|
|
133
|
+
save();
|
|
134
|
+
}
|
|
135
|
+
/** Returns true if this session entry is a first-ever request (requestCount === 0). */
|
|
136
|
+
function isNewSession(entry) {
|
|
137
|
+
return entry.requestCount === 0;
|
|
138
|
+
}
|
|
139
|
+
//# sourceMappingURL=session-registry.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"session-registry.js","sourceRoot":"","sources":["../src/session-registry.ts"],"names":[],"mappings":"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"}
|
package/dist/spawn.d.ts
CHANGED
|
@@ -11,5 +11,5 @@
|
|
|
11
11
|
* On Windows, builds a single command string for cmd.exe to avoid
|
|
12
12
|
* DEP0190 (passing args to child_process with shell:true).
|
|
13
13
|
*/
|
|
14
|
-
export declare function spawnLocal(cmd: string, args: string[], timeoutMs: number): Promise<string>;
|
|
14
|
+
export declare function spawnLocal(cmd: string, args: string[], timeoutMs: number, cwd?: string, stdinData?: string): Promise<string>;
|
|
15
15
|
//# sourceMappingURL=spawn.d.ts.map
|
package/dist/spawn.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"spawn.d.ts","sourceRoot":"","sources":["../src/spawn.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAgDH;;;;;;;GAOG;AACH,wBAAgB,UAAU,CACxB,GAAG,EAAE,MAAM,EACX,IAAI,EAAE,MAAM,EAAE,EACd,SAAS,EAAE,MAAM,
|
|
1
|
+
{"version":3,"file":"spawn.d.ts","sourceRoot":"","sources":["../src/spawn.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAgDH;;;;;;;GAOG;AACH,wBAAgB,UAAU,CACxB,GAAG,EAAE,MAAM,EACX,IAAI,EAAE,MAAM,EAAE,EACd,SAAS,EAAE,MAAM,EACjB,GAAG,CAAC,EAAE,MAAM,EACZ,SAAS,CAAC,EAAE,MAAM,GACjB,OAAO,CAAC,MAAM,CAAC,CAiEjB"}
|
package/dist/spawn.js
CHANGED
|
@@ -90,7 +90,7 @@ function escapeWinArg(arg) {
|
|
|
90
90
|
* On Windows, builds a single command string for cmd.exe to avoid
|
|
91
91
|
* DEP0190 (passing args to child_process with shell:true).
|
|
92
92
|
*/
|
|
93
|
-
function spawnLocal(cmd, args, timeoutMs) {
|
|
93
|
+
function spawnLocal(cmd, args, timeoutMs, cwd, stdinData) {
|
|
94
94
|
const isWin = process.platform === 'win32';
|
|
95
95
|
// On Windows we need shell:true so cmd.exe resolves .cmd/.ps1 wrappers
|
|
96
96
|
// (e.g. gemini.cmd, codex.cmd). To avoid DEP0190 we build a single
|
|
@@ -99,14 +99,20 @@ function spawnLocal(cmd, args, timeoutMs) {
|
|
|
99
99
|
? `${cmd} ${args.map(escapeWinArg).join(' ')}`
|
|
100
100
|
: cmd;
|
|
101
101
|
const spawnArgs = isWin ? [] : args;
|
|
102
|
+
// Default cwd to home directory so sub-agents never inherit System32
|
|
103
|
+
// (Electron sets process.cwd() = C:\Windows\System32 for MCP server processes).
|
|
104
|
+
const effectiveCwd = cwd ?? os.homedir();
|
|
102
105
|
return new Promise((resolve, reject) => {
|
|
103
106
|
const proc = (0, child_process_1.spawn)(spawnCmd, spawnArgs, {
|
|
104
107
|
shell: isWin,
|
|
105
108
|
windowsHide: true,
|
|
106
109
|
env: spawnEnv(),
|
|
110
|
+
cwd: effectiveCwd,
|
|
107
111
|
});
|
|
108
|
-
//
|
|
109
|
-
|
|
112
|
+
// Write prompt via stdin if provided, then close
|
|
113
|
+
if (stdinData !== undefined) {
|
|
114
|
+
proc.stdin?.write(stdinData);
|
|
115
|
+
}
|
|
110
116
|
proc.stdin?.end();
|
|
111
117
|
let stdout = '';
|
|
112
118
|
let stderr = '';
|
package/dist/spawn.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"spawn.js","sourceRoot":"","sources":["../src/spawn.ts"],"names":[],"mappings":";AAAA;;;;GAIG;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAwDH,
|
|
1
|
+
{"version":3,"file":"spawn.js","sourceRoot":"","sources":["../src/spawn.ts"],"names":[],"mappings":"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"}
|
package/dist/tools/claude.d.ts
CHANGED
|
@@ -1,8 +1,13 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* Claude sub-agent tool.
|
|
3
3
|
*
|
|
4
|
-
* Uses the Claude Code CLI in non-interactive mode:
|
|
5
|
-
* claude -p
|
|
4
|
+
* Uses the Claude Code CLI in non-interactive mode with session resume:
|
|
5
|
+
* echo "<prompt>" | claude -p --session-id <uuid> --output-format json ... (first request)
|
|
6
|
+
* echo "<prompt>" | claude -p --resume <uuid> --output-format json ... (subsequent)
|
|
7
|
+
*
|
|
8
|
+
* Session resume keeps conversation context on the CLI side so subsequent
|
|
9
|
+
* requests only send the new message (not the full history), eliminating
|
|
10
|
+
* the ~50% silent hang rate and 80-120s response times on large prompts.
|
|
6
11
|
*
|
|
7
12
|
* Authentication: uses locally cached Anthropic credentials
|
|
8
13
|
* (from Claude Code login or ANTHROPIC_API_KEY env var).
|
|
@@ -17,19 +22,23 @@ export declare const claudeRunSchema: z.ZodObject<{
|
|
|
17
22
|
prompt: z.ZodString;
|
|
18
23
|
model: z.ZodOptional<z.ZodString>;
|
|
19
24
|
timeout_seconds: z.ZodDefault<z.ZodNumber>;
|
|
25
|
+
working_directory: z.ZodOptional<z.ZodString>;
|
|
20
26
|
}, "strip", z.ZodTypeAny, {
|
|
21
27
|
prompt: string;
|
|
22
28
|
timeout_seconds: number;
|
|
23
29
|
model?: string | undefined;
|
|
30
|
+
working_directory?: string | undefined;
|
|
24
31
|
}, {
|
|
25
32
|
prompt: string;
|
|
26
33
|
model?: string | undefined;
|
|
27
34
|
timeout_seconds?: number | undefined;
|
|
35
|
+
working_directory?: string | undefined;
|
|
28
36
|
}>;
|
|
29
37
|
export declare function handleClaudeRun(args: {
|
|
30
38
|
prompt: string;
|
|
31
39
|
model?: string;
|
|
32
40
|
timeout_seconds: number;
|
|
41
|
+
working_directory?: string;
|
|
33
42
|
}): Promise<{
|
|
34
43
|
success: boolean;
|
|
35
44
|
error: string;
|
|
@@ -39,6 +48,7 @@ export declare function handleClaudeRun(args: {
|
|
|
39
48
|
duration_ms?: undefined;
|
|
40
49
|
cost_usd?: undefined;
|
|
41
50
|
stop_reason?: undefined;
|
|
51
|
+
session_id?: undefined;
|
|
42
52
|
note?: undefined;
|
|
43
53
|
} | {
|
|
44
54
|
success: boolean;
|
|
@@ -49,6 +59,7 @@ export declare function handleClaudeRun(args: {
|
|
|
49
59
|
duration_ms?: undefined;
|
|
50
60
|
cost_usd?: undefined;
|
|
51
61
|
stop_reason?: undefined;
|
|
62
|
+
session_id?: undefined;
|
|
52
63
|
note?: undefined;
|
|
53
64
|
} | {
|
|
54
65
|
success: boolean;
|
|
@@ -57,6 +68,7 @@ export declare function handleClaudeRun(args: {
|
|
|
57
68
|
duration_ms: number | undefined;
|
|
58
69
|
cost_usd: number | undefined;
|
|
59
70
|
stop_reason: string | undefined;
|
|
71
|
+
session_id: string;
|
|
60
72
|
error?: undefined;
|
|
61
73
|
hint?: undefined;
|
|
62
74
|
note?: undefined;
|
|
@@ -65,6 +77,7 @@ export declare function handleClaudeRun(args: {
|
|
|
65
77
|
response: string;
|
|
66
78
|
model: string;
|
|
67
79
|
note: string;
|
|
80
|
+
session_id: string;
|
|
68
81
|
error?: undefined;
|
|
69
82
|
hint?: undefined;
|
|
70
83
|
duration_ms?: undefined;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"claude.d.ts","sourceRoot":"","sources":["../../src/tools/claude.ts"],"names":[],"mappings":"AAAA
|
|
1
|
+
{"version":3,"file":"claude.d.ts","sourceRoot":"","sources":["../../src/tools/claude.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;GAkBG;AAEH,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AAMxB,eAAO,MAAM,eAAe;;;;;;;;;;;;;;;EAc1B,CAAC;AAIH,wBAAsB,eAAe,CACnC,IAAI,EAAE;IAAE,MAAM,EAAE,MAAM,CAAC;IAAC,KAAK,CAAC,EAAE,MAAM,CAAC;IAAC,eAAe,EAAE,MAAM,CAAC;IAAC,iBAAiB,CAAC,EAAE,MAAM,CAAA;CAAE;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA+E9F"}
|
package/dist/tools/claude.js
CHANGED
|
@@ -2,8 +2,13 @@
|
|
|
2
2
|
/**
|
|
3
3
|
* Claude sub-agent tool.
|
|
4
4
|
*
|
|
5
|
-
* Uses the Claude Code CLI in non-interactive mode:
|
|
6
|
-
* claude -p
|
|
5
|
+
* Uses the Claude Code CLI in non-interactive mode with session resume:
|
|
6
|
+
* echo "<prompt>" | claude -p --session-id <uuid> --output-format json ... (first request)
|
|
7
|
+
* echo "<prompt>" | claude -p --resume <uuid> --output-format json ... (subsequent)
|
|
8
|
+
*
|
|
9
|
+
* Session resume keeps conversation context on the CLI side so subsequent
|
|
10
|
+
* requests only send the new message (not the full history), eliminating
|
|
11
|
+
* the ~50% silent hang rate and 80-120s response times on large prompts.
|
|
7
12
|
*
|
|
8
13
|
* Authentication: uses locally cached Anthropic credentials
|
|
9
14
|
* (from Claude Code login or ANTHROPIC_API_KEY env var).
|
|
@@ -18,30 +23,48 @@ exports.claudeRunSchema = void 0;
|
|
|
18
23
|
exports.handleClaudeRun = handleClaudeRun;
|
|
19
24
|
const zod_1 = require("zod");
|
|
20
25
|
const spawn_js_1 = require("../spawn.js");
|
|
26
|
+
const session_registry_js_1 = require("../session-registry.js");
|
|
21
27
|
// --- Schema ---
|
|
22
28
|
exports.claudeRunSchema = zod_1.z.object({
|
|
23
29
|
prompt: zod_1.z.string().describe('Prompt or question to send to Claude.'),
|
|
24
30
|
model: zod_1.z.string().optional().describe('Claude model to use, e.g. "claude-sonnet-4-6", "claude-opus-4-6", "claude-haiku-4-5". '
|
|
25
31
|
+ 'Omit to use the default model.'),
|
|
26
32
|
timeout_seconds: zod_1.z.number().min(5).max(300).default(60).describe('Max seconds to wait for a response.'),
|
|
33
|
+
working_directory: zod_1.z.string().optional().describe('Working directory for the Claude process. Set this to the project root so Claude can read local files. Defaults to the user home directory.'),
|
|
27
34
|
});
|
|
28
35
|
// --- Handler ---
|
|
29
36
|
async function handleClaudeRun(args) {
|
|
37
|
+
const model = args.model ?? 'claude-sonnet-4-6';
|
|
38
|
+
const session = (0, session_registry_js_1.getOrCreateSession)('claude', model);
|
|
30
39
|
const cliArgs = [
|
|
31
|
-
'-p',
|
|
40
|
+
'-p',
|
|
32
41
|
'--output-format', 'json',
|
|
33
|
-
'--max-turns', '1',
|
|
42
|
+
'--max-turns', '1',
|
|
43
|
+
'--permission-mode', 'bypassPermissions',
|
|
44
|
+
'--dangerously-skip-permissions',
|
|
34
45
|
];
|
|
35
46
|
if (args.model)
|
|
36
47
|
cliArgs.push('--model', args.model);
|
|
48
|
+
// Use --session-id on first request, --resume on subsequent
|
|
49
|
+
if ((0, session_registry_js_1.isNewSession)(session)) {
|
|
50
|
+
cliArgs.push('--session-id', session.sessionId);
|
|
51
|
+
}
|
|
52
|
+
else {
|
|
53
|
+
cliArgs.push('--resume', session.sessionId);
|
|
54
|
+
}
|
|
37
55
|
let raw;
|
|
38
56
|
try {
|
|
39
|
-
raw = await (0, spawn_js_1.spawnLocal)('claude', cliArgs, args.timeout_seconds * 1000);
|
|
57
|
+
raw = await (0, spawn_js_1.spawnLocal)('claude', cliArgs, args.timeout_seconds * 1000, args.working_directory, args.prompt);
|
|
40
58
|
}
|
|
41
59
|
catch (err) {
|
|
60
|
+
const errMsg = String(err);
|
|
61
|
+
// Session may have been cleaned up externally: invalidate and let the caller retry
|
|
62
|
+
if (errMsg.includes('session not found') || errMsg.includes('ENOENT')) {
|
|
63
|
+
(0, session_registry_js_1.invalidateSession)('claude', model);
|
|
64
|
+
}
|
|
42
65
|
return {
|
|
43
66
|
success: false,
|
|
44
|
-
error:
|
|
67
|
+
error: errMsg,
|
|
45
68
|
hint: 'Install Claude Code: npm install -g @anthropic-ai/claude-code, then run `claude` once to authenticate.',
|
|
46
69
|
};
|
|
47
70
|
}
|
|
@@ -51,10 +74,10 @@ async function handleClaudeRun(args) {
|
|
|
51
74
|
if (parsed.is_error) {
|
|
52
75
|
return { success: false, error: parsed.result ?? 'Unknown error from Claude CLI' };
|
|
53
76
|
}
|
|
54
|
-
|
|
77
|
+
(0, session_registry_js_1.recordSuccess)('claude', model);
|
|
55
78
|
const modelUsed = parsed.modelUsage
|
|
56
|
-
? Object.keys(parsed.modelUsage)[0] ??
|
|
57
|
-
:
|
|
79
|
+
? Object.keys(parsed.modelUsage)[0] ?? model
|
|
80
|
+
: model;
|
|
58
81
|
return {
|
|
59
82
|
success: true,
|
|
60
83
|
response: parsed.result ?? '(empty response)',
|
|
@@ -62,15 +85,18 @@ async function handleClaudeRun(args) {
|
|
|
62
85
|
duration_ms: parsed.duration_ms,
|
|
63
86
|
cost_usd: parsed.total_cost_usd,
|
|
64
87
|
stop_reason: parsed.stop_reason,
|
|
88
|
+
session_id: session.sessionId,
|
|
65
89
|
};
|
|
66
90
|
}
|
|
67
91
|
catch {
|
|
68
92
|
// CLI returned plain text instead of JSON
|
|
93
|
+
(0, session_registry_js_1.recordSuccess)('claude', model);
|
|
69
94
|
return {
|
|
70
95
|
success: true,
|
|
71
96
|
response: raw.trim(),
|
|
72
|
-
model
|
|
97
|
+
model,
|
|
73
98
|
note: 'Response was plain text, not JSON.',
|
|
99
|
+
session_id: session.sessionId,
|
|
74
100
|
};
|
|
75
101
|
}
|
|
76
102
|
}
|
package/dist/tools/claude.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"claude.js","sourceRoot":"","sources":["../../src/tools/claude.ts"],"names":[],"mappings":";AAAA
|
|
1
|
+
{"version":3,"file":"claude.js","sourceRoot":"","sources":["../../src/tools/claude.ts"],"names":[],"mappings":"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"}
|
package/dist/tools/codex.d.ts
CHANGED
|
@@ -1,8 +1,11 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* Codex sub-agent tool.
|
|
3
3
|
*
|
|
4
|
-
* Uses the @openai/codex CLI in non-interactive mode:
|
|
5
|
-
*
|
|
4
|
+
* Uses the @openai/codex CLI in non-interactive mode with session resume:
|
|
5
|
+
* echo "<prompt>" | codex exec --json --full-auto [--model <m>] (first request)
|
|
6
|
+
* echo "<prompt>" | codex exec resume <session-id> --json --full-auto (subsequent)
|
|
7
|
+
*
|
|
8
|
+
* Note: --ephemeral is NOT used here (that flag skips session persistence).
|
|
6
9
|
*
|
|
7
10
|
* Authentication: the CLI uses locally cached OpenAI credentials.
|
|
8
11
|
* Run `codex` once interactively to authenticate.
|
|
@@ -29,15 +32,18 @@ export declare const codexRunSchema: z.ZodObject<{
|
|
|
29
32
|
model: z.ZodOptional<z.ZodString>;
|
|
30
33
|
sandbox: z.ZodDefault<z.ZodEnum<["full-auto", "dangerous"]>>;
|
|
31
34
|
timeout_seconds: z.ZodDefault<z.ZodNumber>;
|
|
35
|
+
working_directory: z.ZodOptional<z.ZodString>;
|
|
32
36
|
}, "strip", z.ZodTypeAny, {
|
|
33
37
|
prompt: string;
|
|
34
38
|
timeout_seconds: number;
|
|
35
39
|
sandbox: "full-auto" | "dangerous";
|
|
36
40
|
model?: string | undefined;
|
|
41
|
+
working_directory?: string | undefined;
|
|
37
42
|
}, {
|
|
38
43
|
prompt: string;
|
|
39
44
|
model?: string | undefined;
|
|
40
45
|
timeout_seconds?: number | undefined;
|
|
46
|
+
working_directory?: string | undefined;
|
|
41
47
|
sandbox?: "full-auto" | "dangerous" | undefined;
|
|
42
48
|
}>;
|
|
43
49
|
export declare function handleCodexRun(args: {
|
|
@@ -45,6 +51,7 @@ export declare function handleCodexRun(args: {
|
|
|
45
51
|
model?: string;
|
|
46
52
|
sandbox: 'full-auto' | 'dangerous';
|
|
47
53
|
timeout_seconds: number;
|
|
54
|
+
working_directory?: string;
|
|
48
55
|
}, config: Config): Promise<{
|
|
49
56
|
success: boolean;
|
|
50
57
|
error: string;
|
|
@@ -52,11 +59,13 @@ export declare function handleCodexRun(args: {
|
|
|
52
59
|
response?: undefined;
|
|
53
60
|
model?: undefined;
|
|
54
61
|
sandbox?: undefined;
|
|
62
|
+
session_id?: undefined;
|
|
55
63
|
} | {
|
|
56
64
|
success: boolean;
|
|
57
65
|
response: string;
|
|
58
66
|
model: string;
|
|
59
67
|
sandbox: "full-auto" | "dangerous";
|
|
68
|
+
session_id: string;
|
|
60
69
|
error?: undefined;
|
|
61
70
|
hint?: undefined;
|
|
62
71
|
}>;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"codex.d.ts","sourceRoot":"","sources":["../../src/tools/codex.ts"],"names":[],"mappings":"AAAA
|
|
1
|
+
{"version":3,"file":"codex.d.ts","sourceRoot":"","sources":["../../src/tools/codex.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;GA0BG;AAEH,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AACxB,OAAO,EAAE,MAAM,EAAE,MAAM,cAAc,CAAC;AAMtC,eAAO,MAAM,cAAc;;;;;;;;;;;;;;;;;;EAmBzB,CAAC;AAuDH,wBAAsB,cAAc,CAClC,IAAI,EAAE;IACJ,MAAM,EAAE,MAAM,CAAC;IACf,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,OAAO,EAAE,WAAW,GAAG,WAAW,CAAC;IACnC,eAAe,EAAE,MAAM,CAAC;IACxB,iBAAiB,CAAC,EAAE,MAAM,CAAC;CAC5B,EACD,MAAM,EAAE,MAAM;;;;;;;;;;;;;;;;GA8Cf"}
|
package/dist/tools/codex.js
CHANGED
|
@@ -2,8 +2,11 @@
|
|
|
2
2
|
/**
|
|
3
3
|
* Codex sub-agent tool.
|
|
4
4
|
*
|
|
5
|
-
* Uses the @openai/codex CLI in non-interactive mode:
|
|
6
|
-
*
|
|
5
|
+
* Uses the @openai/codex CLI in non-interactive mode with session resume:
|
|
6
|
+
* echo "<prompt>" | codex exec --json --full-auto [--model <m>] (first request)
|
|
7
|
+
* echo "<prompt>" | codex exec resume <session-id> --json --full-auto (subsequent)
|
|
8
|
+
*
|
|
9
|
+
* Note: --ephemeral is NOT used here (that flag skips session persistence).
|
|
7
10
|
*
|
|
8
11
|
* Authentication: the CLI uses locally cached OpenAI credentials.
|
|
9
12
|
* Run `codex` once interactively to authenticate.
|
|
@@ -28,6 +31,7 @@ exports.codexRunSchema = void 0;
|
|
|
28
31
|
exports.handleCodexRun = handleCodexRun;
|
|
29
32
|
const zod_1 = require("zod");
|
|
30
33
|
const spawn_js_1 = require("../spawn.js");
|
|
34
|
+
const session_registry_js_1 = require("../session-registry.js");
|
|
31
35
|
// --- Schemas ---
|
|
32
36
|
exports.codexRunSchema = zod_1.z.object({
|
|
33
37
|
prompt: zod_1.z.string().describe('Task or question to send to the Codex AI agent. ' +
|
|
@@ -37,6 +41,7 @@ exports.codexRunSchema = zod_1.z.object({
|
|
|
37
41
|
sandbox: zod_1.z.enum(['full-auto', 'dangerous']).default('full-auto').describe('"full-auto": workspace-write sandbox, no approval prompts (default, recommended). ' +
|
|
38
42
|
'"dangerous": bypass all approvals and sandbox — only use in isolated environments.'),
|
|
39
43
|
timeout_seconds: zod_1.z.number().min(10).max(600).default(120).describe('Max seconds to wait. Codex tasks can take longer than Gemini — 120s default.'),
|
|
44
|
+
working_directory: zod_1.z.string().optional().describe('Working directory for the Codex process. Set this to the project root so Codex can read and write local files. Defaults to the user home directory.'),
|
|
40
45
|
});
|
|
41
46
|
function extractResponseFromJsonl(raw) {
|
|
42
47
|
// Parse JSONL events and extract the assistant message text
|
|
@@ -81,33 +86,46 @@ function extractResponseFromJsonl(raw) {
|
|
|
81
86
|
}
|
|
82
87
|
// --- Handler ---
|
|
83
88
|
async function handleCodexRun(args, config) {
|
|
84
|
-
const model = args.model ?? config.codexModel;
|
|
85
|
-
const
|
|
89
|
+
const model = args.model ?? config.codexModel ?? 'default';
|
|
90
|
+
const session = (0, session_registry_js_1.getOrCreateSession)('codex', model);
|
|
91
|
+
// Codex resume uses a subcommand: `codex exec resume <session-id>`
|
|
92
|
+
// First request uses plain `codex exec`; subsequent requests use the resume subcommand.
|
|
93
|
+
const cliArgs = ['exec'];
|
|
94
|
+
if (!(0, session_registry_js_1.isNewSession)(session)) {
|
|
95
|
+
cliArgs.push('resume', session.sessionId);
|
|
96
|
+
}
|
|
97
|
+
cliArgs.push('--json');
|
|
86
98
|
if (args.sandbox === 'dangerous') {
|
|
87
99
|
cliArgs.push('--dangerously-bypass-approvals-and-sandbox');
|
|
88
100
|
}
|
|
89
101
|
else {
|
|
90
102
|
cliArgs.push('--full-auto');
|
|
91
103
|
}
|
|
92
|
-
if (model)
|
|
93
|
-
cliArgs.push('--model', model);
|
|
104
|
+
if (args.model)
|
|
105
|
+
cliArgs.push('--model', args.model);
|
|
94
106
|
let raw;
|
|
95
107
|
try {
|
|
96
|
-
raw = await (0, spawn_js_1.spawnLocal)('codex', cliArgs, args.timeout_seconds * 1000);
|
|
108
|
+
raw = await (0, spawn_js_1.spawnLocal)('codex', cliArgs, args.timeout_seconds * 1000, args.working_directory, args.prompt);
|
|
97
109
|
}
|
|
98
110
|
catch (err) {
|
|
111
|
+
const errMsg = String(err);
|
|
112
|
+
if (errMsg.includes('session not found') || errMsg.includes('not found')) {
|
|
113
|
+
(0, session_registry_js_1.invalidateSession)('codex', model);
|
|
114
|
+
}
|
|
99
115
|
return {
|
|
100
116
|
success: false,
|
|
101
|
-
error:
|
|
117
|
+
error: errMsg,
|
|
102
118
|
hint: 'Run `codex` once to authenticate, or check `codex --version` to confirm the CLI is installed.',
|
|
103
119
|
};
|
|
104
120
|
}
|
|
121
|
+
(0, session_registry_js_1.recordSuccess)('codex', model);
|
|
105
122
|
const response = extractResponseFromJsonl(raw);
|
|
106
123
|
return {
|
|
107
124
|
success: true,
|
|
108
125
|
response,
|
|
109
|
-
model
|
|
126
|
+
model,
|
|
110
127
|
sandbox: args.sandbox,
|
|
128
|
+
session_id: session.sessionId,
|
|
111
129
|
};
|
|
112
130
|
}
|
|
113
131
|
//# sourceMappingURL=codex.js.map
|
package/dist/tools/codex.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"codex.js","sourceRoot":"","sources":["../../src/tools/codex.ts"],"names":[],"mappings":";AAAA
|
|
1
|
+
{"version":3,"file":"codex.js","sourceRoot":"","sources":["../../src/tools/codex.ts"],"names":[],"mappings":"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"}
|
package/dist/tools/gemini.d.ts
CHANGED
|
@@ -1,15 +1,16 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* Gemini sub-agent tool.
|
|
3
3
|
*
|
|
4
|
-
* Uses the @google/gemini-cli package in headless mode:
|
|
5
|
-
* gemini -p "
|
|
4
|
+
* Uses the @google/gemini-cli package in headless mode with session resume:
|
|
5
|
+
* echo "<prompt>" | gemini -p "" --model <model> --resume <uuid> --approval-mode yolo
|
|
6
|
+
*
|
|
7
|
+
* Gemini creates a new session when --resume is passed with an unknown UUID,
|
|
8
|
+
* so we always pass --resume (using our generated UUID) -- no separate
|
|
9
|
+
* "first request" path needed.
|
|
6
10
|
*
|
|
7
11
|
* Authentication: the CLI uses locally cached Google credentials
|
|
8
12
|
* (from `gemini auth login`). No API key env var required.
|
|
9
13
|
*
|
|
10
|
-
* Output format (--output-format json):
|
|
11
|
-
* { "response": "...", "stats": { ... }, "error": null }
|
|
12
|
-
*
|
|
13
14
|
* Use cases vs openclaw_run:
|
|
14
15
|
* - Direct, fast Gemini call with no OpenClaw overhead
|
|
15
16
|
* - Works even when the OpenClaw server is unreachable
|
|
@@ -22,19 +23,23 @@ export declare const geminiRunSchema: z.ZodObject<{
|
|
|
22
23
|
prompt: z.ZodString;
|
|
23
24
|
model: z.ZodOptional<z.ZodString>;
|
|
24
25
|
timeout_seconds: z.ZodDefault<z.ZodNumber>;
|
|
26
|
+
working_directory: z.ZodOptional<z.ZodString>;
|
|
25
27
|
}, "strip", z.ZodTypeAny, {
|
|
26
28
|
prompt: string;
|
|
27
29
|
timeout_seconds: number;
|
|
28
30
|
model?: string | undefined;
|
|
31
|
+
working_directory?: string | undefined;
|
|
29
32
|
}, {
|
|
30
33
|
prompt: string;
|
|
31
34
|
model?: string | undefined;
|
|
32
35
|
timeout_seconds?: number | undefined;
|
|
36
|
+
working_directory?: string | undefined;
|
|
33
37
|
}>;
|
|
34
38
|
export declare function handleGeminiRun(args: {
|
|
35
39
|
prompt: string;
|
|
36
40
|
model?: string;
|
|
37
41
|
timeout_seconds: number;
|
|
42
|
+
working_directory?: string;
|
|
38
43
|
}, config: Config): Promise<{
|
|
39
44
|
success: boolean;
|
|
40
45
|
error: string;
|
|
@@ -43,6 +48,7 @@ export declare function handleGeminiRun(args: {
|
|
|
43
48
|
response?: undefined;
|
|
44
49
|
model?: undefined;
|
|
45
50
|
stats?: undefined;
|
|
51
|
+
session_id?: undefined;
|
|
46
52
|
note?: undefined;
|
|
47
53
|
} | {
|
|
48
54
|
success: boolean;
|
|
@@ -52,12 +58,14 @@ export declare function handleGeminiRun(args: {
|
|
|
52
58
|
response?: undefined;
|
|
53
59
|
model?: undefined;
|
|
54
60
|
stats?: undefined;
|
|
61
|
+
session_id?: undefined;
|
|
55
62
|
note?: undefined;
|
|
56
63
|
} | {
|
|
57
64
|
success: boolean;
|
|
58
65
|
response: string;
|
|
59
66
|
model: string;
|
|
60
67
|
stats: Record<string, unknown> | undefined;
|
|
68
|
+
session_id: string;
|
|
61
69
|
error?: undefined;
|
|
62
70
|
hint?: undefined;
|
|
63
71
|
raw?: undefined;
|
|
@@ -67,6 +75,7 @@ export declare function handleGeminiRun(args: {
|
|
|
67
75
|
response: string;
|
|
68
76
|
model: string;
|
|
69
77
|
note: string;
|
|
78
|
+
session_id: string;
|
|
70
79
|
error?: undefined;
|
|
71
80
|
hint?: undefined;
|
|
72
81
|
raw?: undefined;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"gemini.d.ts","sourceRoot":"","sources":["../../src/tools/gemini.ts"],"names":[],"mappings":"AAAA
|
|
1
|
+
{"version":3,"file":"gemini.d.ts","sourceRoot":"","sources":["../../src/tools/gemini.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;GAkBG;AAEH,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AACxB,OAAO,EAAE,MAAM,EAAE,MAAM,cAAc,CAAC;AAMtC,eAAO,MAAM,eAAe;;;;;;;;;;;;;;;EAc1B,CAAC;AAIH,wBAAsB,eAAe,CACnC,IAAI,EAAE;IAAE,MAAM,EAAE,MAAM,CAAC;IAAC,KAAK,CAAC,EAAE,MAAM,CAAC;IAAC,eAAe,EAAE,MAAM,CAAC;IAAC,iBAAiB,CAAC,EAAE,MAAM,CAAA;CAAE,EAC7F,MAAM,EAAE,MAAM;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA6Df"}
|
package/dist/tools/gemini.js
CHANGED
|
@@ -2,15 +2,16 @@
|
|
|
2
2
|
/**
|
|
3
3
|
* Gemini sub-agent tool.
|
|
4
4
|
*
|
|
5
|
-
* Uses the @google/gemini-cli package in headless mode:
|
|
6
|
-
* gemini -p "
|
|
5
|
+
* Uses the @google/gemini-cli package in headless mode with session resume:
|
|
6
|
+
* echo "<prompt>" | gemini -p "" --model <model> --resume <uuid> --approval-mode yolo
|
|
7
|
+
*
|
|
8
|
+
* Gemini creates a new session when --resume is passed with an unknown UUID,
|
|
9
|
+
* so we always pass --resume (using our generated UUID) -- no separate
|
|
10
|
+
* "first request" path needed.
|
|
7
11
|
*
|
|
8
12
|
* Authentication: the CLI uses locally cached Google credentials
|
|
9
13
|
* (from `gemini auth login`). No API key env var required.
|
|
10
14
|
*
|
|
11
|
-
* Output format (--output-format json):
|
|
12
|
-
* { "response": "...", "stats": { ... }, "error": null }
|
|
13
|
-
*
|
|
14
15
|
* Use cases vs openclaw_run:
|
|
15
16
|
* - Direct, fast Gemini call with no OpenClaw overhead
|
|
16
17
|
* - Works even when the OpenClaw server is unreachable
|
|
@@ -22,27 +23,41 @@ exports.geminiRunSchema = void 0;
|
|
|
22
23
|
exports.handleGeminiRun = handleGeminiRun;
|
|
23
24
|
const zod_1 = require("zod");
|
|
24
25
|
const spawn_js_1 = require("../spawn.js");
|
|
26
|
+
const session_registry_js_1 = require("../session-registry.js");
|
|
25
27
|
// --- Schemas ---
|
|
26
28
|
exports.geminiRunSchema = zod_1.z.object({
|
|
27
29
|
prompt: zod_1.z.string().describe('Prompt or question to send to the Gemini AI model.'),
|
|
28
30
|
model: zod_1.z.string().optional().describe('Gemini model to use, e.g. "gemini-2.5-pro" or "gemini-2.5-flash". ' +
|
|
29
31
|
'Omit to use the configured default (GEMINI_MODEL env var).'),
|
|
30
32
|
timeout_seconds: zod_1.z.number().min(5).max(300).default(60).describe('Max seconds to wait for a response.'),
|
|
33
|
+
working_directory: zod_1.z.string().optional().describe('Working directory for the Gemini process. Set this to the project root so Gemini can read local files. Defaults to the user home directory.'),
|
|
31
34
|
});
|
|
32
35
|
// --- Handler ---
|
|
33
36
|
async function handleGeminiRun(args, config) {
|
|
34
|
-
const model = args.model ?? config.geminiModel;
|
|
35
|
-
const
|
|
37
|
+
const model = args.model ?? config.geminiModel ?? 'gemini-2.5-flash';
|
|
38
|
+
const session = (0, session_registry_js_1.getOrCreateSession)('gemini', model);
|
|
39
|
+
// Gemini creates a new session when --resume is given an unknown UUID,
|
|
40
|
+
// so --resume is always used (no --session-id equivalent needed).
|
|
41
|
+
const cliArgs = [
|
|
42
|
+
'-p', '',
|
|
43
|
+
'--output-format', 'json',
|
|
44
|
+
'--resume', session.sessionId,
|
|
45
|
+
'--approval-mode', 'yolo',
|
|
46
|
+
];
|
|
36
47
|
if (model)
|
|
37
48
|
cliArgs.push('--model', model);
|
|
38
49
|
let raw;
|
|
39
50
|
try {
|
|
40
|
-
raw = await (0, spawn_js_1.spawnLocal)('gemini', cliArgs, args.timeout_seconds * 1000);
|
|
51
|
+
raw = await (0, spawn_js_1.spawnLocal)('gemini', cliArgs, args.timeout_seconds * 1000, args.working_directory, args.prompt);
|
|
41
52
|
}
|
|
42
53
|
catch (err) {
|
|
54
|
+
const errMsg = String(err);
|
|
55
|
+
if (errMsg.includes('session not found') || errMsg.includes('not found')) {
|
|
56
|
+
(0, session_registry_js_1.invalidateSession)('gemini', model);
|
|
57
|
+
}
|
|
43
58
|
return {
|
|
44
59
|
success: false,
|
|
45
|
-
error:
|
|
60
|
+
error: errMsg,
|
|
46
61
|
hint: 'Run `gemini auth login` to authenticate, or check `gemini --version` to confirm the CLI is installed.',
|
|
47
62
|
};
|
|
48
63
|
}
|
|
@@ -52,20 +67,24 @@ async function handleGeminiRun(args, config) {
|
|
|
52
67
|
if (parsed.error) {
|
|
53
68
|
return { success: false, error: parsed.error.message, raw };
|
|
54
69
|
}
|
|
70
|
+
(0, session_registry_js_1.recordSuccess)('gemini', model);
|
|
55
71
|
return {
|
|
56
72
|
success: true,
|
|
57
73
|
response: parsed.response ?? '(empty response)',
|
|
58
|
-
model
|
|
74
|
+
model,
|
|
59
75
|
stats: parsed.stats,
|
|
76
|
+
session_id: session.sessionId,
|
|
60
77
|
};
|
|
61
78
|
}
|
|
62
79
|
catch {
|
|
63
80
|
// CLI returned plain text instead of JSON (can happen with some versions)
|
|
81
|
+
(0, session_registry_js_1.recordSuccess)('gemini', model);
|
|
64
82
|
return {
|
|
65
83
|
success: true,
|
|
66
84
|
response: raw.trim(),
|
|
67
|
-
model
|
|
85
|
+
model,
|
|
68
86
|
note: 'Response was plain text, not JSON — consider upgrading @google/gemini-cli',
|
|
87
|
+
session_id: session.sessionId,
|
|
69
88
|
};
|
|
70
89
|
}
|
|
71
90
|
}
|
package/dist/tools/gemini.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"gemini.js","sourceRoot":"","sources":["../../src/tools/gemini.ts"],"names":[],"mappings":";AAAA
|
|
1
|
+
{"version":3,"file":"gemini.js","sourceRoot":"","sources":["../../src/tools/gemini.ts"],"names":[],"mappings":";AAAA;;;;;;;;;;;;;;;;;;GAkBG;;;AA2BH,0CA+DC;AAxFD,6BAAwB;AAExB,0CAAyC;AACzC,gEAA8F;AAE9F,kBAAkB;AAEL,QAAA,eAAe,GAAG,OAAC,CAAC,MAAM,CAAC;IACtC,MAAM,EAAE,OAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,CACzB,oDAAoD,CACrD;IACD,KAAK,EAAE,OAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,EAAE,CAAC,QAAQ,CACnC,oEAAoE;QACpE,4DAA4D,CAC7D;IACD,eAAe,EAAE,OAAC,CAAC,MAAM,EAAE,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC,OAAO,CAAC,EAAE,CAAC,CAAC,QAAQ,CAC9D,qCAAqC,CACtC;IACD,iBAAiB,EAAE,OAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,EAAE,CAAC,QAAQ,CAC/C,6IAA6I,CAC9I;CACF,CAAC,CAAC;AAEH,kBAAkB;AAEX,KAAK,UAAU,eAAe,CACnC,IAA6F,EAC7F,MAAc;IAEd,MAAM,KAAK,GAAG,IAAI,CAAC,KAAK,IAAI,MAAM,CAAC,WAAW,IAAI,kBAAkB,CAAC;IACrE,MAAM,OAAO,GAAG,IAAA,wCAAkB,EAAC,QAAQ,EAAE,KAAK,CAAC,CAAC;IAEpD,uEAAuE;IACvE,kEAAkE;IAClE,MAAM,OAAO,GAAG;QACd,IAAI,EAAE,EAAE;QACR,iBAAiB,EAAE,MAAM;QACzB,UAAU,EAAE,OAAO,CAAC,SAAS;QAC7B,iBAAiB,EAAE,MAAM;KAC1B,CAAC;IACF,IAAI,KAAK;QAAE,OAAO,CAAC,IAAI,CAAC,SAAS,EAAE,KAAK,CAAC,CAAC;IAE1C,IAAI,GAAW,CAAC;IAChB,IAAI,CAAC;QACH,GAAG,GAAG,MAAM,IAAA,qBAAU,EAAC,QAAQ,EAAE,OAAO,EAAE,IAAI,CAAC,eAAe,GAAG,IAAI,EAAE,IAAI,CAAC,iBAAiB,EAAE,IAAI,CAAC,MAAM,CAAC,CAAC;IAC9G,CAAC;IAAC,OAAO,GAAG,EAAE,CAAC;QACb,MAAM,MAAM,GAAG,MAAM,CAAC,GAAG,CAAC,CAAC;QAC3B,IAAI,MAAM,CAAC,QAAQ,CAAC,mBAAmB,CAAC,IAAI,MAAM,CAAC,QAAQ,CAAC,WAAW,CAAC,EAAE,CAAC;YACzE,IAAA,uCAAiB,EAAC,QAAQ,EAAE,KAAK,CAAC,CAAC;QACrC,CAAC;QACD,OAAO;YACL,OAAO,EAAE,KAAK;YACd,KAAK,EAAE,MAAM;YACb,IAAI,EAAE,uGAAuG;SAC9G,CAAC;IACJ,CAAC;IAED,wDAAwD;IACxD,IAAI,CAAC;QACH,MAAM,MAAM,GAAG,IAAI,CAAC,KAAK,CAAC,GAAG,CAAC,IAAI,EAAE,CAInC,CAAC;QAEF,IAAI,MAAM,CAAC,KAAK,EAAE,CAAC;YACjB,OAAO,EAAE,OAAO,EAAE,KAAK,EAAE,KAAK,EAAE,MAAM,CAAC,KAAK,CAAC,OAAO,EAAE,GAAG,EAAE,CAAC;QAC9D,CAAC;QAED,IAAA,mCAAa,EAAC,QAAQ,EAAE,KAAK,CAAC,CAAC;QAC/B,OAAO;YACL,OAAO,EAAE,IAAI;YACb,QAAQ,EAAE,MAAM,CAAC,QAAQ,IAAI,kBAAkB;YAC/C,KAAK;YACL,KAAK,EAAE,MAAM,CAAC,KAAK;YACnB,UAAU,EAAE,OAAO,CAAC,SAAS;SAC9B,CAAC;IACJ,CAAC;IAAC,MAAM,CAAC;QACP,0EAA0E;QAC1E,IAAA,mCAAa,EAAC,QAAQ,EAAE,KAAK,CAAC,CAAC;QAC/B,OAAO;YACL,OAAO,EAAE,IAAI;YACb,QAAQ,EAAE,GAAG,CAAC,IAAI,EAAE;YACpB,KAAK;YACL,IAAI,EAAE,2EAA2E;YACjF,UAAU,EAAE,OAAO,CAAC,SAAS;SAC9B,CAAC;IACJ,CAAC;AACH,CAAC"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@elvatis_com/elvatis-mcp",
|
|
3
|
-
"version": "1.
|
|
3
|
+
"version": "1.2.0",
|
|
4
4
|
"description": "MCP server for OpenClaw — expose smart home, memory, cron, and more to Claude Desktop, Cursor, Windsurf, and any MCP client",
|
|
5
5
|
"main": "dist/index.js",
|
|
6
6
|
"types": "dist/index.d.ts",
|