svamp-cli 0.1.29 → 0.1.31

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.
Files changed (98) hide show
  1. package/dist/cli.mjs +8 -8
  2. package/dist/{commands-CgT3AgJ0.mjs → commands-78RHC879.mjs} +162 -55
  3. package/dist/index.mjs +1 -1
  4. package/dist/{package-DPXkSwHu.mjs → package-BtoCHVOd.mjs} +1 -1
  5. package/dist/{run-BCSNMhiz.mjs → run-dBWhjQRf.mjs} +66 -61
  6. package/package.json +1 -1
  7. package/dist/agent-cli.mjs +0 -453
  8. package/dist/commands-1CYZC6Xh.mjs +0 -481
  9. package/dist/commands-B1DcpgLW.mjs +0 -481
  10. package/dist/commands-BGmdgMAC.mjs +0 -485
  11. package/dist/commands-BOeSil-P.mjs +0 -459
  12. package/dist/commands-BU4GZQuH.mjs +0 -481
  13. package/dist/commands-Ba66PxtQ.mjs +0 -481
  14. package/dist/commands-C0-xqIIc.mjs +0 -481
  15. package/dist/commands-C7Qy5n6d.mjs +0 -481
  16. package/dist/commands-CKTIJoV0.mjs +0 -636
  17. package/dist/commands-CKpC8R9T.mjs +0 -481
  18. package/dist/commands-CNqOjR1y.mjs +0 -481
  19. package/dist/commands-CVKh1tWr.mjs +0 -485
  20. package/dist/commands-CYBblX73.mjs +0 -485
  21. package/dist/commands-CZBYmj16.mjs +0 -485
  22. package/dist/commands-CcWIvCA4.mjs +0 -481
  23. package/dist/commands-Cfwf-cQG.mjs +0 -481
  24. package/dist/commands-CtO1WRt4.mjs +0 -862
  25. package/dist/commands-DCNO2m66.mjs +0 -471
  26. package/dist/commands-DDB3y1L1.mjs +0 -611
  27. package/dist/commands-DRIFvhmC.mjs +0 -481
  28. package/dist/commands-DXmw2dzy.mjs +0 -481
  29. package/dist/commands-DkSvlKFF.mjs +0 -485
  30. package/dist/commands-DnDd4Sew.mjs +0 -481
  31. package/dist/commands-DnpnAFQW.mjs +0 -485
  32. package/dist/commands-Do-TVYFm.mjs +0 -481
  33. package/dist/commands-GEXri0yz.mjs +0 -484
  34. package/dist/commands-Kzm0_XNH.mjs +0 -481
  35. package/dist/commands-MQvNbIid.mjs +0 -481
  36. package/dist/commands-_uCC3U1U.mjs +0 -481
  37. package/dist/commands-y2WG29W9.mjs +0 -485
  38. package/dist/hyphaClient-DLkclazm.mjs +0 -39
  39. package/dist/package-ASJ9pMHk.mjs +0 -60
  40. package/dist/package-B2FOzHaM.mjs +0 -57
  41. package/dist/package-Bk_PFVA0.mjs +0 -57
  42. package/dist/package-Bnij-ZtR.mjs +0 -57
  43. package/dist/package-BtRbHfjz.mjs +0 -57
  44. package/dist/package-C5B0twb8.mjs +0 -57
  45. package/dist/package-CC5d8_0L.mjs +0 -57
  46. package/dist/package-CCJ045H0.mjs +0 -60
  47. package/dist/package-CKOQ5lA7.mjs +0 -57
  48. package/dist/package-CS219SXn.mjs +0 -57
  49. package/dist/package-Cd-9ktpd.mjs +0 -60
  50. package/dist/package-CgBD49cA.mjs +0 -57
  51. package/dist/package-CvnNnsm7.mjs +0 -60
  52. package/dist/package-DpqWz9Cr.mjs +0 -60
  53. package/dist/package-JqEt5Ib4.mjs +0 -57
  54. package/dist/package-k18Su1iE.mjs +0 -58
  55. package/dist/package-nzkXV1aM.mjs +0 -57
  56. package/dist/package-pNo6GC3a.mjs +0 -60
  57. package/dist/package-pZp14zKI.mjs +0 -57
  58. package/dist/run-4fyJcaRE.mjs +0 -3856
  59. package/dist/run-B6oqR83K.mjs +0 -4631
  60. package/dist/run-BI32lPRK.mjs +0 -3870
  61. package/dist/run-BQHneHfW.mjs +0 -3834
  62. package/dist/run-Bb4fyIWZ.mjs +0 -3812
  63. package/dist/run-BglwnB-A.mjs +0 -3889
  64. package/dist/run-BjVWuitO.mjs +0 -3919
  65. package/dist/run-BzUE-JUT.mjs +0 -3708
  66. package/dist/run-BzqS97Sx.mjs +0 -3666
  67. package/dist/run-C6snRxyh.mjs +0 -3826
  68. package/dist/run-C8CI8Ujj.mjs +0 -3693
  69. package/dist/run-CL-FS4Yc.mjs +0 -3933
  70. package/dist/run-CS1Z4GcM.mjs +0 -3786
  71. package/dist/run-CT7uizQo.mjs +0 -4492
  72. package/dist/run-CUIj4xbE.mjs +0 -4880
  73. package/dist/run-CW26vPqj.mjs +0 -3919
  74. package/dist/run-CkTufc0D.mjs +0 -3875
  75. package/dist/run-Cmostc0S.mjs +0 -3902
  76. package/dist/run-Cp3kKdzm.mjs +0 -3865
  77. package/dist/run-CuN6K7pN.mjs +0 -4824
  78. package/dist/run-D0bCTY72.mjs +0 -3816
  79. package/dist/run-D4N6FQON.mjs +0 -4673
  80. package/dist/run-D4dlA0jo.mjs +0 -4813
  81. package/dist/run-DMD0N00A.mjs +0 -4737
  82. package/dist/run-DMW8ibIw.mjs +0 -3958
  83. package/dist/run-DO52unxE.mjs +0 -3950
  84. package/dist/run-DQ5FOQ_c.mjs +0 -4788
  85. package/dist/run-DT7FgL8L.mjs +0 -4339
  86. package/dist/run-DYhBROuo.mjs +0 -3934
  87. package/dist/run-DZmxHj-e.mjs +0 -4774
  88. package/dist/run-DjfPjgOb.mjs +0 -3904
  89. package/dist/run-DlL4JALM.mjs +0 -4719
  90. package/dist/run-Dp2JPkGI.mjs +0 -3913
  91. package/dist/run-Dptna3Je.mjs +0 -3867
  92. package/dist/run-DwK3dfHd.mjs +0 -3875
  93. package/dist/run-M_SMt96j.mjs +0 -3913
  94. package/dist/run-MlpxQUPN.mjs +0 -3869
  95. package/dist/run-PuTIelbv.mjs +0 -3706
  96. package/dist/run-h37iSCUB.mjs +0 -3934
  97. package/dist/run-lpV0oguG.mjs +0 -3897
  98. package/dist/run-oHmTMcv8.mjs +0 -4721
@@ -1,453 +0,0 @@
1
- import { Command } from 'commander';
2
- import { connectAndGetMachine, resolveSessionId } from './commands-DDB3y1L1.mjs';
3
- import 'node:fs';
4
- import 'node:path';
5
- import 'node:os';
6
- import './hyphaClient-DLkclazm.mjs';
7
-
8
- function formatIsoTime(ts) {
9
- if (!ts) return "-";
10
- const date = new Date(ts);
11
- if (Number.isNaN(date.getTime())) return "-";
12
- return date.toISOString();
13
- }
14
- function toMarkdownInline(value) {
15
- const escaped = value.replace(/`/g, "\\`");
16
- return `\`${escaped}\``;
17
- }
18
- function normalizeCodeBlockText(value) {
19
- const text = value.trim().length > 0 ? value : "(empty)";
20
- return text.replace(/```/g, "``\\`");
21
- }
22
- function formatSessionTable(sessions) {
23
- if (sessions.length === 0) {
24
- return "## Sessions\n\n- Total: 0\n- Items: none";
25
- }
26
- const sections = sessions.map((s, index) => {
27
- const name = s.name || "-";
28
- const path = s.path || s.directory || "-";
29
- const status = s.active ? "active" : "inactive";
30
- return [
31
- `### Session ${index + 1}`,
32
- `- ID: ${toMarkdownInline(s.sessionId)}`,
33
- `- Agent: ${s.flavor || "claude"}`,
34
- `- Name: ${name}`,
35
- `- Path: ${path}`,
36
- `- Status: ${status}`
37
- ].join("\n");
38
- });
39
- return `## Sessions
40
-
41
- - Total: ${sessions.length}
42
-
43
- ${sections.join("\n\n")}`;
44
- }
45
- function formatSessionStatus(data) {
46
- const lines = [
47
- "## Session Status",
48
- "",
49
- `- Session ID: ${toMarkdownInline(data.sessionId)}`,
50
- `- Agent: ${data.flavor}`
51
- ];
52
- if (data.name) lines.push(`- Name: ${data.name}`);
53
- if (data.summary) lines.push(`- Summary: ${data.summary}`);
54
- if (data.path) lines.push(`- Path: ${data.path}`);
55
- if (data.host) lines.push(`- Host: ${data.host}`);
56
- if (data.lifecycleState) lines.push(`- Lifecycle: ${data.lifecycleState}`);
57
- lines.push(`- Active: ${data.active ? "yes" : "no"}`);
58
- lines.push(`- Thinking: ${data.thinking ? "yes" : "no"}`);
59
- lines.push(`- Agent Status: ${data.active ? "busy" : "idle"}`);
60
- if (data.startedBy) lines.push(`- Started By: ${data.startedBy}`);
61
- if (data.claudeSessionId) lines.push(`- Claude Session: ${data.claudeSessionId}`);
62
- if (data.sessionLink) lines.push(`- Link: ${data.sessionLink}`);
63
- return lines.join("\n");
64
- }
65
- function formatMessageHistory(messages) {
66
- if (messages.length === 0) {
67
- return "## Message History\n\n- Count: 0\n- Items: none";
68
- }
69
- const sections = messages.map((msg, index) => {
70
- return [
71
- `### Message ${index + 1}`,
72
- `- ID: ${toMarkdownInline(msg.id)}`,
73
- `- Time: ${formatIsoTime(msg.createdAt)}`,
74
- `- Role: ${msg.role}`,
75
- "- Text:",
76
- "```text",
77
- normalizeCodeBlockText(msg.text),
78
- "```"
79
- ].join("\n");
80
- });
81
- return `## Message History
82
-
83
- - Count: ${messages.length}
84
-
85
- ${sections.join("\n\n")}`;
86
- }
87
- function formatJson(data) {
88
- return JSON.stringify(data, null, 2);
89
- }
90
-
91
- async function resolveSessionByPath(machine, server, path) {
92
- const sessions = await machine.listSessions();
93
- const active = sessions.filter((s) => s.active);
94
- let matches = active.filter((s) => s.directory === path);
95
- if (matches.length === 0) {
96
- for (const s of active) {
97
- try {
98
- const svc = await server.getService(`svamp-session-${s.sessionId}`);
99
- const { metadata } = await svc.getMetadata();
100
- if (metadata?.path === path) {
101
- matches.push(s);
102
- }
103
- } catch {
104
- }
105
- }
106
- }
107
- if (matches.length === 0) {
108
- throw new Error(`No active session found for path "${path}"`);
109
- }
110
- return matches[0];
111
- }
112
- function extractMessageText(msg) {
113
- const content = msg.content;
114
- if (!content) return null;
115
- const role = content.role || "unknown";
116
- let text = "";
117
- if (role === "user") {
118
- const data = content.content;
119
- if (typeof data === "string") {
120
- try {
121
- const parsed = JSON.parse(data);
122
- text = parsed?.text || parsed?.content?.text || data;
123
- } catch {
124
- text = data;
125
- }
126
- } else if (data?.text) {
127
- text = data.text;
128
- } else if (data?.type === "text") {
129
- text = data.text || "";
130
- } else {
131
- text = typeof data === "object" ? JSON.stringify(data) : String(data || "");
132
- }
133
- } else if (role === "agent" || role === "assistant") {
134
- const data = content.content?.data || content.content;
135
- if (!data) return null;
136
- if (data.type === "assistant" && Array.isArray(data.content)) {
137
- const parts = [];
138
- for (const block of data.content) {
139
- if (block.type === "text" && block.text) {
140
- parts.push(block.text);
141
- } else if (block.type === "tool_use") {
142
- parts.push(`[tool: ${block.name}]`);
143
- }
144
- }
145
- text = parts.join("\n");
146
- } else if (data.type === "result") {
147
- text = data.result || "";
148
- } else if (data.type === "output") {
149
- const inner = data.data;
150
- if (inner?.type === "assistant" && Array.isArray(inner.content)) {
151
- const parts = [];
152
- for (const block of inner.content) {
153
- if (block.type === "text" && block.text) {
154
- parts.push(block.text);
155
- } else if (block.type === "tool_use") {
156
- parts.push(`[tool: ${block.name}]`);
157
- }
158
- }
159
- text = parts.join("\n");
160
- } else if (inner?.type === "result") {
161
- text = inner.result || "";
162
- }
163
- }
164
- } else if (role === "session") {
165
- text = "[session event]";
166
- }
167
- return {
168
- id: msg.id || "",
169
- seq: msg.seq || 0,
170
- role,
171
- text,
172
- createdAt: msg.createdAt || 0
173
- };
174
- }
175
- async function waitForIdle(server, sessionId, timeoutMs) {
176
- const svc = await server.getService(`svamp-session-${sessionId}`);
177
- const pollInterval = 2e3;
178
- const deadline = Date.now() + timeoutMs;
179
- while (Date.now() < deadline) {
180
- const activity = await svc.getActivityState();
181
- if (activity && !activity.active) {
182
- return;
183
- }
184
- await new Promise((r) => setTimeout(r, pollInterval));
185
- }
186
- throw new Error("Timeout waiting for agent to become idle");
187
- }
188
- async function waitForBusyThenIdle(server, sessionId, timeoutMs = 3e5, busyTimeoutMs = 1e4) {
189
- const svc = await server.getService(`svamp-session-${sessionId}`);
190
- const pollInterval = 2e3;
191
- const deadline = Date.now() + timeoutMs;
192
- const busyDeadline = Date.now() + busyTimeoutMs;
193
- let sawBusy = false;
194
- while (Date.now() < deadline) {
195
- const activity = await svc.getActivityState();
196
- const isActive = activity?.active === true;
197
- if (isActive) {
198
- sawBusy = true;
199
- }
200
- if (sawBusy && !isActive) {
201
- return;
202
- }
203
- if (!sawBusy && Date.now() > busyDeadline) {
204
- return;
205
- }
206
- await new Promise((r) => setTimeout(r, pollInterval));
207
- }
208
- throw new Error("Timeout waiting for agent to become idle");
209
- }
210
- const program = new Command();
211
- program.name("svamp-agent").description("CLI client for controlling Svamp sessions remotely").version("0.1.0");
212
- program.command("list").description("List all sessions").option("--active", "Show only active sessions").option("--json", "Output as JSON").action(async (opts) => {
213
- const { server, machine } = await connectAndGetMachine();
214
- try {
215
- const sessions = await machine.listSessions();
216
- const filtered = opts.active ? sessions.filter((s) => s.active) : sessions;
217
- const enriched = [];
218
- for (const s of filtered) {
219
- let flavor = "claude";
220
- let name = "";
221
- let path = s.directory || "";
222
- let host = "";
223
- if (s.metadata) {
224
- flavor = s.metadata.flavor || "claude";
225
- name = s.metadata.name || "";
226
- }
227
- if (s.active) {
228
- try {
229
- const svc = await server.getService(`svamp-session-${s.sessionId}`);
230
- const { metadata } = await svc.getMetadata();
231
- flavor = metadata?.flavor || flavor;
232
- name = metadata?.name || name;
233
- path = metadata?.path || path;
234
- host = metadata?.host || "";
235
- } catch {
236
- }
237
- }
238
- enriched.push({ ...s, flavor, name, path, host });
239
- }
240
- if (opts.json) {
241
- console.log(formatJson(enriched.map((s) => ({
242
- sessionId: s.sessionId,
243
- agent: s.flavor,
244
- name: s.name,
245
- path: s.path,
246
- host: s.host,
247
- active: s.active,
248
- directory: s.directory
249
- }))));
250
- } else {
251
- console.log(formatSessionTable(enriched));
252
- }
253
- } finally {
254
- await server.disconnect();
255
- }
256
- });
257
- program.command("status").description("Get live session state").argument("<session-id>", "Session ID or prefix").option("--json", "Output as JSON").action(async (sessionId, opts) => {
258
- const { server, machine } = await connectAndGetMachine();
259
- try {
260
- const sessions = await machine.listSessions();
261
- const match = resolveSessionId(sessions, sessionId);
262
- const fullId = match.sessionId;
263
- let metadata = {};
264
- let activity = {};
265
- try {
266
- const svc = await server.getService(`svamp-session-${fullId}`);
267
- const metaResult = await svc.getMetadata();
268
- metadata = metaResult.metadata || {};
269
- activity = await svc.getActivityState();
270
- } catch {
271
- }
272
- const statusData = {
273
- sessionId: fullId,
274
- flavor: metadata.flavor || "claude",
275
- name: metadata.name || "",
276
- path: metadata.path || match.directory || "",
277
- host: metadata.host || "",
278
- lifecycleState: metadata.lifecycleState || "unknown",
279
- active: activity.active ?? false,
280
- thinking: activity.thinking ?? false,
281
- startedBy: metadata.startedBy || match.startedBy || "",
282
- summary: metadata.summary?.text || void 0,
283
- claudeSessionId: metadata.claudeSessionId || void 0,
284
- sessionLink: metadata.sessionLink?.url || void 0
285
- };
286
- if (opts.json) {
287
- console.log(formatJson(statusData));
288
- } else {
289
- console.log(formatSessionStatus(statusData));
290
- }
291
- } finally {
292
- await server.disconnect();
293
- }
294
- });
295
- program.command("create").description("Create a new session").option("--agent <agent>", "Agent type (claude, gemini, opencode)", "claude").option("--directory <path>", "Working directory path").option("--json", "Output as JSON").action(async (opts) => {
296
- const { server, machine } = await connectAndGetMachine();
297
- try {
298
- const directory = opts.directory ?? process.cwd();
299
- const result = await machine.spawnSession({
300
- directory,
301
- agent: opts.agent
302
- });
303
- if (result.type === "success") {
304
- if (opts.json) {
305
- console.log(formatJson({
306
- sessionId: result.sessionId,
307
- agent: opts.agent,
308
- directory
309
- }));
310
- } else {
311
- console.log([
312
- "## Session Created",
313
- "",
314
- `- Session ID: \`${result.sessionId}\``,
315
- `- Agent: ${opts.agent}`,
316
- `- Directory: ${directory}`,
317
- ...result.message ? [`- Note: ${result.message}`] : []
318
- ].join("\n"));
319
- }
320
- } else if (result.type === "requestToApproveDirectoryCreation") {
321
- throw new Error(`Directory ${result.directory} does not exist. Create it first or use an existing directory.`);
322
- } else {
323
- throw new Error(result.errorMessage || "Unknown error creating session");
324
- }
325
- } finally {
326
- await server.disconnect();
327
- }
328
- });
329
- program.command("send").description("Send a message to a session").argument("<session-id>", "Session ID or prefix (ignored when --by-path is used)").argument("<message>", "Message text").option("--wait", "Wait for agent to become idle").option("--by-path <path>", "Resolve session by working directory path (active sessions only)").option("--json", "Output as JSON").action(async (sessionId, message, opts) => {
330
- const { server, machine } = await connectAndGetMachine();
331
- try {
332
- let match;
333
- if (opts.byPath) {
334
- match = await resolveSessionByPath(machine, server, opts.byPath);
335
- } else {
336
- const sessions = await machine.listSessions();
337
- match = resolveSessionId(sessions, sessionId);
338
- }
339
- const fullId = match.sessionId;
340
- const svc = await server.getService(`svamp-session-${fullId}`);
341
- const result = await svc.sendMessage(
342
- JSON.stringify({
343
- role: "user",
344
- content: { type: "text", text: message },
345
- meta: { sentFrom: "svamp-agent" }
346
- })
347
- );
348
- if (opts.wait) {
349
- await waitForBusyThenIdle(server, fullId);
350
- }
351
- if (opts.json) {
352
- console.log(formatJson({
353
- sessionId: fullId,
354
- message,
355
- sent: true,
356
- seq: result.seq,
357
- waited: !!opts.wait
358
- }));
359
- } else {
360
- console.log([
361
- "## Message Sent",
362
- "",
363
- `- Session ID: \`${fullId}\``,
364
- `- Sequence: ${result.seq}`,
365
- ...opts.wait ? [`- Waited For Idle: yes`] : []
366
- ].join("\n"));
367
- }
368
- } finally {
369
- await server.disconnect();
370
- }
371
- });
372
- program.command("history").description("Read message history").argument("<session-id>", "Session ID or prefix").option("--limit <n>", "Limit number of messages", (v) => {
373
- const n = parseInt(v, 10);
374
- if (isNaN(n) || n <= 0) throw new Error("--limit must be a positive integer");
375
- return n;
376
- }).option("--after <seq>", "Only show messages after this sequence number", (v) => {
377
- const n = parseInt(v, 10);
378
- if (isNaN(n) || n < 0) throw new Error("--after must be a non-negative integer");
379
- return n;
380
- }).option("--json", "Output as JSON").action(async (sessionId, opts) => {
381
- const { server, machine } = await connectAndGetMachine();
382
- try {
383
- const sessions = await machine.listSessions();
384
- const match = resolveSessionId(sessions, sessionId);
385
- const fullId = match.sessionId;
386
- const svc = await server.getService(`svamp-session-${fullId}`);
387
- const afterSeq = opts.after ?? 0;
388
- const apiLimit = opts.limit ?? 500;
389
- const { messages } = await svc.getMessages(afterSeq, apiLimit);
390
- let formatted = [];
391
- for (const msg of messages) {
392
- const extracted = extractMessageText(msg);
393
- if (extracted) {
394
- formatted.push(extracted);
395
- }
396
- }
397
- formatted.sort((a, b) => a.createdAt - b.createdAt);
398
- if (opts.json) {
399
- console.log(formatJson(formatted));
400
- } else {
401
- console.log(formatMessageHistory(formatted));
402
- }
403
- } finally {
404
- await server.disconnect();
405
- }
406
- });
407
- program.command("stop").description("Stop a session").argument("<session-id>", "Session ID or prefix").action(async (sessionId) => {
408
- const { server, machine } = await connectAndGetMachine();
409
- try {
410
- const sessions = await machine.listSessions();
411
- const match = resolveSessionId(sessions, sessionId);
412
- const success = await machine.stopSession(match.sessionId);
413
- if (success) {
414
- console.log([
415
- "## Session Stopped",
416
- "",
417
- `- Session ID: \`${match.sessionId}\``
418
- ].join("\n"));
419
- } else {
420
- throw new Error("Failed to stop session (not found on daemon)");
421
- }
422
- } finally {
423
- await server.disconnect();
424
- }
425
- });
426
- program.command("wait").description("Wait for agent to become idle").argument("<session-id>", "Session ID or prefix").option("--timeout <seconds>", "Timeout in seconds", (v) => {
427
- const n = parseInt(v, 10);
428
- if (isNaN(n) || n <= 0) throw new Error("--timeout must be a positive integer");
429
- return n;
430
- }, 300).action(async (sessionId, opts) => {
431
- const { server, machine } = await connectAndGetMachine();
432
- try {
433
- const sessions = await machine.listSessions();
434
- const match = resolveSessionId(sessions, sessionId);
435
- const fullId = match.sessionId;
436
- await waitForIdle(server, fullId, opts.timeout * 1e3);
437
- console.log([
438
- "## Session Idle",
439
- "",
440
- `- Session ID: \`${fullId}\``
441
- ].join("\n"));
442
- } catch (err) {
443
- const msg = err instanceof Error ? err.message : String(err);
444
- console.error(msg);
445
- process.exitCode = 1;
446
- } finally {
447
- await server.disconnect();
448
- }
449
- });
450
- program.parseAsync(process.argv).catch((err) => {
451
- console.error(err instanceof Error ? err.message : String(err));
452
- process.exitCode = 1;
453
- });