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 CHANGED
@@ -1,4 +1,4 @@
1
- import { s as startDaemon, b as stopDaemon, d as daemonStatus } from './run-xiJdI9RG.mjs';
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
- console.log("svamp version: 0.1.0");
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] Login to Hypha (opens browser, stores token)
173
- svamp daemon start Start the daemon (detached)
174
- svamp daemon stop Stop the daemon
175
- svamp daemon status Show daemon status
176
- svamp --version Show version
177
- svamp --help Show this help
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 Config directory (default: ~/.svamp)
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);