svamp-cli 0.1.5 → 0.1.7
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/dist/cli.mjs +269 -9
- package/dist/commands-C8QbpD3d.mjs +476 -0
- package/dist/commands-D8bwJSm-.mjs +487 -0
- package/dist/commands-DNF79jRn.mjs +440 -0
- package/dist/commands-p36abIvL.mjs +485 -0
- package/dist/commands-zTpXV_OI.mjs +452 -0
- package/dist/index.mjs +3 -1
- package/dist/package-DD4JHOe_.mjs +57 -0
- package/dist/package-DsYI3JjY.mjs +57 -0
- package/dist/run-C2z4Zl9E.mjs +3617 -0
- package/dist/run-C9o6o85x.mjs +3617 -0
- package/dist/run-CZTsU12c.mjs +3629 -0
- package/dist/run-DLreYPnX.mjs +3628 -0
- package/dist/run-aevHxpEl.mjs +3630 -0
- package/package.json +2 -1
package/dist/cli.mjs
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { s as startDaemon, b as stopDaemon, d as daemonStatus } from './run-
|
|
1
|
+
import { s as startDaemon, b as stopDaemon, d as daemonStatus } from './run-aevHxpEl.mjs';
|
|
2
2
|
import 'os';
|
|
3
3
|
import 'fs/promises';
|
|
4
4
|
import 'fs';
|
|
@@ -13,6 +13,8 @@ import '@modelcontextprotocol/sdk/server/mcp.js';
|
|
|
13
13
|
import 'node:http';
|
|
14
14
|
import '@modelcontextprotocol/sdk/server/streamableHttp.js';
|
|
15
15
|
import 'zod';
|
|
16
|
+
import 'node:child_process';
|
|
17
|
+
import '@agentclientprotocol/sdk';
|
|
16
18
|
|
|
17
19
|
const args = process.argv.slice(2);
|
|
18
20
|
const subcommand = args[0];
|
|
@@ -70,16 +72,218 @@ async function main() {
|
|
|
70
72
|
} else {
|
|
71
73
|
printDaemonHelp();
|
|
72
74
|
}
|
|
75
|
+
} else if (subcommand === "agent") {
|
|
76
|
+
await handleAgentCommand();
|
|
77
|
+
} else if (subcommand === "session") {
|
|
78
|
+
await handleSessionCommand();
|
|
73
79
|
} else if (subcommand === "--help" || subcommand === "-h" || !subcommand) {
|
|
74
80
|
printHelp();
|
|
75
81
|
} else if (subcommand === "--version" || subcommand === "-v") {
|
|
76
|
-
|
|
82
|
+
const pkg = await import('./package-DD4JHOe_.mjs').catch(() => ({ default: { version: "unknown" } }));
|
|
83
|
+
console.log(`svamp version: ${pkg.default.version}`);
|
|
77
84
|
} else {
|
|
78
85
|
console.error(`Unknown command: ${subcommand}`);
|
|
79
86
|
printHelp();
|
|
80
87
|
process.exit(1);
|
|
81
88
|
}
|
|
82
89
|
}
|
|
90
|
+
async function handleAgentCommand() {
|
|
91
|
+
const agentArgs = args.slice(1);
|
|
92
|
+
if (agentArgs.length === 0 || agentArgs[0] === "--help" || agentArgs[0] === "-h") {
|
|
93
|
+
printAgentHelp();
|
|
94
|
+
return;
|
|
95
|
+
}
|
|
96
|
+
if (agentArgs[0] === "list") {
|
|
97
|
+
const { KNOWN_ACP_AGENTS } = await import('./run-aevHxpEl.mjs').then(function (n) { return n.f; });
|
|
98
|
+
console.log("Known ACP agents:");
|
|
99
|
+
for (const [name, config2] of Object.entries(KNOWN_ACP_AGENTS)) {
|
|
100
|
+
console.log(` ${name.padEnd(12)} ${config2.command} ${config2.args.join(" ")}`);
|
|
101
|
+
}
|
|
102
|
+
console.log('\nUse "svamp agent <name>" to start an interactive session.');
|
|
103
|
+
console.log('Use "svamp agent -- <command> [args]" for a custom ACP agent.');
|
|
104
|
+
return;
|
|
105
|
+
}
|
|
106
|
+
const { resolveAcpAgentConfig } = await import('./run-aevHxpEl.mjs').then(function (n) { return n.f; });
|
|
107
|
+
const { AcpBackend } = await import('./run-aevHxpEl.mjs').then(function (n) { return n.e; });
|
|
108
|
+
const { GeminiTransport } = await import('./run-aevHxpEl.mjs').then(function (n) { return n.G; });
|
|
109
|
+
const { DefaultTransport } = await import('./run-aevHxpEl.mjs').then(function (n) { return n.D; });
|
|
110
|
+
let cwd = process.cwd();
|
|
111
|
+
const filteredArgs = [];
|
|
112
|
+
for (let i = 0; i < agentArgs.length; i++) {
|
|
113
|
+
if ((agentArgs[i] === "-d" || agentArgs[i] === "--directory") && i + 1 < agentArgs.length) {
|
|
114
|
+
cwd = agentArgs[i + 1];
|
|
115
|
+
i++;
|
|
116
|
+
} else {
|
|
117
|
+
filteredArgs.push(agentArgs[i]);
|
|
118
|
+
}
|
|
119
|
+
}
|
|
120
|
+
let config;
|
|
121
|
+
try {
|
|
122
|
+
config = resolveAcpAgentConfig(filteredArgs);
|
|
123
|
+
} catch (err) {
|
|
124
|
+
console.error(err.message);
|
|
125
|
+
process.exit(1);
|
|
126
|
+
}
|
|
127
|
+
console.log(`Starting ${config.agentName} agent in ${cwd}...`);
|
|
128
|
+
const transportHandler = config.agentName === "gemini" ? new GeminiTransport() : new DefaultTransport(config.agentName);
|
|
129
|
+
const backend = new AcpBackend({
|
|
130
|
+
agentName: config.agentName,
|
|
131
|
+
cwd,
|
|
132
|
+
command: config.command,
|
|
133
|
+
args: config.args,
|
|
134
|
+
transportHandler,
|
|
135
|
+
log: (...logArgs) => {
|
|
136
|
+
if (process.env.DEBUG) {
|
|
137
|
+
console.error("[debug]", ...logArgs);
|
|
138
|
+
}
|
|
139
|
+
}
|
|
140
|
+
});
|
|
141
|
+
let currentText = "";
|
|
142
|
+
backend.onMessage((msg) => {
|
|
143
|
+
switch (msg.type) {
|
|
144
|
+
case "model-output":
|
|
145
|
+
if (msg.textDelta) {
|
|
146
|
+
process.stdout.write(msg.textDelta);
|
|
147
|
+
currentText += msg.textDelta;
|
|
148
|
+
} else if (msg.fullText) {
|
|
149
|
+
process.stdout.write(msg.fullText);
|
|
150
|
+
}
|
|
151
|
+
break;
|
|
152
|
+
case "status":
|
|
153
|
+
if (msg.status === "idle") {
|
|
154
|
+
if (currentText && !currentText.endsWith("\n")) {
|
|
155
|
+
process.stdout.write("\n");
|
|
156
|
+
}
|
|
157
|
+
currentText = "";
|
|
158
|
+
process.stdout.write("\n> ");
|
|
159
|
+
} else if (msg.status === "error") {
|
|
160
|
+
console.error(`
|
|
161
|
+
Error: ${msg.detail}`);
|
|
162
|
+
} else if (msg.status === "stopped") {
|
|
163
|
+
console.log(`
|
|
164
|
+
Agent stopped: ${msg.detail || ""}`);
|
|
165
|
+
}
|
|
166
|
+
break;
|
|
167
|
+
case "tool-call":
|
|
168
|
+
console.log(`
|
|
169
|
+
[tool] ${msg.toolName}(${JSON.stringify(msg.args).substring(0, 100)})`);
|
|
170
|
+
break;
|
|
171
|
+
case "tool-result": {
|
|
172
|
+
const resultStr = typeof msg.result === "string" ? msg.result : JSON.stringify(msg.result);
|
|
173
|
+
if (resultStr.length > 200) {
|
|
174
|
+
console.log(`[tool result] ${resultStr.substring(0, 200)}...`);
|
|
175
|
+
}
|
|
176
|
+
break;
|
|
177
|
+
}
|
|
178
|
+
case "event":
|
|
179
|
+
if (msg.name === "thinking") {
|
|
180
|
+
const payload = msg.payload;
|
|
181
|
+
if (payload?.text) {
|
|
182
|
+
process.stdout.write(`\x1B[90m${payload.text}\x1B[0m`);
|
|
183
|
+
}
|
|
184
|
+
}
|
|
185
|
+
break;
|
|
186
|
+
}
|
|
187
|
+
});
|
|
188
|
+
try {
|
|
189
|
+
const result = await backend.startSession();
|
|
190
|
+
console.log(`Session started: ${result.sessionId}`);
|
|
191
|
+
process.stdout.write("> ");
|
|
192
|
+
} catch (err) {
|
|
193
|
+
const errMsg = err?.message || (typeof err === "object" ? JSON.stringify(err) : String(err));
|
|
194
|
+
console.error(`Failed to start ${config.agentName}: ${errMsg}`);
|
|
195
|
+
process.exit(1);
|
|
196
|
+
}
|
|
197
|
+
const readline = await import('readline');
|
|
198
|
+
const rl = readline.createInterface({
|
|
199
|
+
input: process.stdin,
|
|
200
|
+
output: process.stdout,
|
|
201
|
+
terminal: false
|
|
202
|
+
});
|
|
203
|
+
rl.on("line", async (line) => {
|
|
204
|
+
const trimmed = line.trim();
|
|
205
|
+
if (!trimmed) return;
|
|
206
|
+
if (trimmed === "/quit" || trimmed === "/exit") {
|
|
207
|
+
console.log("Shutting down...");
|
|
208
|
+
await backend.dispose();
|
|
209
|
+
process.exit(0);
|
|
210
|
+
}
|
|
211
|
+
if (trimmed === "/cancel") {
|
|
212
|
+
await backend.cancel("");
|
|
213
|
+
return;
|
|
214
|
+
}
|
|
215
|
+
try {
|
|
216
|
+
await backend.sendPrompt("", trimmed);
|
|
217
|
+
} catch (err) {
|
|
218
|
+
console.error(`Error: ${err.message}`);
|
|
219
|
+
}
|
|
220
|
+
});
|
|
221
|
+
rl.on("close", async () => {
|
|
222
|
+
await backend.dispose();
|
|
223
|
+
process.exit(0);
|
|
224
|
+
});
|
|
225
|
+
process.on("SIGINT", async () => {
|
|
226
|
+
console.log("\nShutting down...");
|
|
227
|
+
await backend.dispose();
|
|
228
|
+
process.exit(0);
|
|
229
|
+
});
|
|
230
|
+
}
|
|
231
|
+
async function handleSessionCommand() {
|
|
232
|
+
const sessionArgs = args.slice(1);
|
|
233
|
+
const sessionSubcommand = sessionArgs[0];
|
|
234
|
+
if (!sessionSubcommand || sessionSubcommand === "--help" || sessionSubcommand === "-h") {
|
|
235
|
+
printSessionHelp();
|
|
236
|
+
return;
|
|
237
|
+
}
|
|
238
|
+
const { sessionList, sessionSpawn, sessionStop, sessionInfo, sessionMessages, sessionAttach } = await import('./commands-p36abIvL.mjs');
|
|
239
|
+
if (sessionSubcommand === "list" || sessionSubcommand === "ls") {
|
|
240
|
+
await sessionList();
|
|
241
|
+
} else if (sessionSubcommand === "spawn") {
|
|
242
|
+
const agent = sessionArgs[1] || "claude";
|
|
243
|
+
let dir = process.cwd();
|
|
244
|
+
for (let i = 1; i < sessionArgs.length; i++) {
|
|
245
|
+
if ((sessionArgs[i] === "-d" || sessionArgs[i] === "--directory") && i + 1 < sessionArgs.length) {
|
|
246
|
+
dir = sessionArgs[i + 1];
|
|
247
|
+
i++;
|
|
248
|
+
}
|
|
249
|
+
}
|
|
250
|
+
await sessionSpawn(agent, dir);
|
|
251
|
+
} else if (sessionSubcommand === "stop") {
|
|
252
|
+
if (!sessionArgs[1]) {
|
|
253
|
+
console.error("Usage: svamp session stop <session-id>");
|
|
254
|
+
process.exit(1);
|
|
255
|
+
}
|
|
256
|
+
await sessionStop(sessionArgs[1]);
|
|
257
|
+
} else if (sessionSubcommand === "info") {
|
|
258
|
+
if (!sessionArgs[1]) {
|
|
259
|
+
console.error("Usage: svamp session info <session-id>");
|
|
260
|
+
process.exit(1);
|
|
261
|
+
}
|
|
262
|
+
await sessionInfo(sessionArgs[1]);
|
|
263
|
+
} else if (sessionSubcommand === "messages" || sessionSubcommand === "msgs") {
|
|
264
|
+
if (!sessionArgs[1]) {
|
|
265
|
+
console.error("Usage: svamp session messages <session-id> [--last N]");
|
|
266
|
+
process.exit(1);
|
|
267
|
+
}
|
|
268
|
+
let last;
|
|
269
|
+
const lastIdx = sessionArgs.indexOf("--last");
|
|
270
|
+
if (lastIdx >= 0 && sessionArgs[lastIdx + 1]) {
|
|
271
|
+
last = parseInt(sessionArgs[lastIdx + 1], 10);
|
|
272
|
+
}
|
|
273
|
+
await sessionMessages(sessionArgs[1], last);
|
|
274
|
+
} else if (sessionSubcommand === "attach") {
|
|
275
|
+
if (!sessionArgs[1]) {
|
|
276
|
+
console.error("Usage: svamp session attach <session-id>");
|
|
277
|
+
process.exit(1);
|
|
278
|
+
}
|
|
279
|
+
await sessionAttach(sessionArgs[1]);
|
|
280
|
+
} else {
|
|
281
|
+
console.error(`Unknown session command: ${sessionSubcommand}`);
|
|
282
|
+
printSessionHelp();
|
|
283
|
+
process.exit(1);
|
|
284
|
+
}
|
|
285
|
+
process.exit(0);
|
|
286
|
+
}
|
|
83
287
|
async function loginToHypha() {
|
|
84
288
|
const serverUrl = args[1] || process.env.HYPHA_SERVER_URL;
|
|
85
289
|
if (!serverUrl) {
|
|
@@ -169,19 +373,26 @@ function printHelp() {
|
|
|
169
373
|
svamp \u2014 Svamp CLI with Hypha transport
|
|
170
374
|
|
|
171
375
|
Usage:
|
|
172
|
-
svamp login [url]
|
|
173
|
-
svamp daemon start
|
|
174
|
-
svamp daemon stop
|
|
175
|
-
svamp daemon status
|
|
176
|
-
svamp
|
|
177
|
-
svamp
|
|
376
|
+
svamp login [url] Login to Hypha (opens browser, stores token)
|
|
377
|
+
svamp daemon start Start the daemon (detached)
|
|
378
|
+
svamp daemon stop Stop the daemon
|
|
379
|
+
svamp daemon status Show daemon status
|
|
380
|
+
svamp session list List active daemon sessions
|
|
381
|
+
svamp session spawn Spawn a new session on the daemon
|
|
382
|
+
svamp session attach <id> Attach to a session (interactive)
|
|
383
|
+
svamp session --help Show all session commands
|
|
384
|
+
svamp agent list List known ACP agents
|
|
385
|
+
svamp agent <name> Start local ACP agent session
|
|
386
|
+
svamp agent -- <cmd> Start custom ACP agent
|
|
387
|
+
svamp --version Show version
|
|
388
|
+
svamp --help Show this help
|
|
178
389
|
|
|
179
390
|
Environment variables:
|
|
180
391
|
HYPHA_SERVER_URL Hypha server URL (required for daemon)
|
|
181
392
|
HYPHA_TOKEN Hypha auth token (stored by login command)
|
|
182
393
|
HYPHA_WORKSPACE Hypha workspace / user ID (stored by login command)
|
|
183
394
|
SVAMP_MACHINE_ID Machine identifier (optional, auto-generated)
|
|
184
|
-
SVAMP_HOME
|
|
395
|
+
SVAMP_HOME Config directory (default: ~/.svamp)
|
|
185
396
|
`);
|
|
186
397
|
}
|
|
187
398
|
function printDaemonHelp() {
|
|
@@ -194,6 +405,55 @@ Usage:
|
|
|
194
405
|
svamp daemon status Show daemon status
|
|
195
406
|
`);
|
|
196
407
|
}
|
|
408
|
+
function printSessionHelp() {
|
|
409
|
+
console.log(`
|
|
410
|
+
svamp session \u2014 Manage daemon sessions (Claude, Gemini, OpenCode)
|
|
411
|
+
|
|
412
|
+
Usage:
|
|
413
|
+
svamp session list List active sessions
|
|
414
|
+
svamp session spawn <agent> [-d <path>] Spawn a new session
|
|
415
|
+
svamp session stop <id> Stop a session
|
|
416
|
+
svamp session info <id> Show session metadata
|
|
417
|
+
svamp session messages <id> [--last N] Dump recent messages
|
|
418
|
+
svamp session attach <id> Attach to session (interactive)
|
|
419
|
+
|
|
420
|
+
Agents: claude (default), gemini, opencode
|
|
421
|
+
|
|
422
|
+
Session IDs can be abbreviated (prefix match, like Docker).
|
|
423
|
+
|
|
424
|
+
Attach commands:
|
|
425
|
+
/quit, /detach Detach (session keeps running)
|
|
426
|
+
/abort, /cancel Cancel current agent turn
|
|
427
|
+
/kill Stop the session
|
|
428
|
+
/info Show session status
|
|
429
|
+
|
|
430
|
+
Examples:
|
|
431
|
+
svamp session list
|
|
432
|
+
svamp session spawn claude -d ~/projects/myapp
|
|
433
|
+
svamp session spawn gemini
|
|
434
|
+
svamp session info abc12345
|
|
435
|
+
svamp session messages abc12345 --last 10
|
|
436
|
+
svamp session attach abc12345
|
|
437
|
+
`);
|
|
438
|
+
}
|
|
439
|
+
function printAgentHelp() {
|
|
440
|
+
console.log(`
|
|
441
|
+
svamp agent \u2014 Interactive ACP agent sessions
|
|
442
|
+
|
|
443
|
+
Usage:
|
|
444
|
+
svamp agent list List known ACP agents
|
|
445
|
+
svamp agent <name> [-d <path>] Start interactive agent session
|
|
446
|
+
svamp agent -- <cmd> [args] Start custom ACP agent
|
|
447
|
+
|
|
448
|
+
Examples:
|
|
449
|
+
svamp agent gemini Start Gemini agent in current directory
|
|
450
|
+
svamp agent gemini -d /tmp/proj Start Gemini agent in /tmp/proj
|
|
451
|
+
svamp agent opencode Start OpenCode agent
|
|
452
|
+
svamp agent -- mycli --acp Start custom ACP-compatible agent
|
|
453
|
+
|
|
454
|
+
Known agents: gemini, opencode
|
|
455
|
+
`);
|
|
456
|
+
}
|
|
197
457
|
main().catch((err) => {
|
|
198
458
|
console.error("Fatal error:", err);
|
|
199
459
|
process.exit(1);
|