svamp-cli 0.1.29 → 0.1.30
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 +7 -7
- package/dist/{commands-CgT3AgJ0.mjs → commands-B2xQb9u7.mjs} +1 -1
- package/dist/{commands-CKTIJoV0.mjs → commands-C5pW2VmI.mjs} +286 -60
- package/dist/{commands-DDB3y1L1.mjs → commands-TZkNivgV.mjs} +295 -44
- package/dist/index.mjs +1 -1
- package/dist/{run-DZmxHj-e.mjs → run-CtCTd6if.mjs} +234 -50
- package/dist/{run-CuN6K7pN.mjs → run-Cxdc5Zmw.mjs} +316 -164
- package/dist/{run-DMD0N00A.mjs → run-dBWhjQRf.mjs} +316 -76
- package/package.json +1 -1
- package/dist/agent-cli.mjs +0 -453
- package/dist/commands-1CYZC6Xh.mjs +0 -481
- package/dist/commands-B1DcpgLW.mjs +0 -481
- package/dist/commands-BGmdgMAC.mjs +0 -485
- package/dist/commands-BOeSil-P.mjs +0 -459
- package/dist/commands-BU4GZQuH.mjs +0 -481
- package/dist/commands-Ba66PxtQ.mjs +0 -481
- package/dist/commands-C0-xqIIc.mjs +0 -481
- package/dist/commands-C7Qy5n6d.mjs +0 -481
- package/dist/commands-CKpC8R9T.mjs +0 -481
- package/dist/commands-CNqOjR1y.mjs +0 -481
- package/dist/commands-CVKh1tWr.mjs +0 -485
- package/dist/commands-CYBblX73.mjs +0 -485
- package/dist/commands-CZBYmj16.mjs +0 -485
- package/dist/commands-CcWIvCA4.mjs +0 -481
- package/dist/commands-Cfwf-cQG.mjs +0 -481
- package/dist/commands-DCNO2m66.mjs +0 -471
- package/dist/commands-DRIFvhmC.mjs +0 -481
- package/dist/commands-DXmw2dzy.mjs +0 -481
- package/dist/commands-DkSvlKFF.mjs +0 -485
- package/dist/commands-DnDd4Sew.mjs +0 -481
- package/dist/commands-DnpnAFQW.mjs +0 -485
- package/dist/commands-Do-TVYFm.mjs +0 -481
- package/dist/commands-GEXri0yz.mjs +0 -484
- package/dist/commands-Kzm0_XNH.mjs +0 -481
- package/dist/commands-MQvNbIid.mjs +0 -481
- package/dist/commands-_uCC3U1U.mjs +0 -481
- package/dist/commands-y2WG29W9.mjs +0 -485
- package/dist/hyphaClient-DLkclazm.mjs +0 -39
- package/dist/package-ASJ9pMHk.mjs +0 -60
- package/dist/package-B2FOzHaM.mjs +0 -57
- package/dist/package-Bk_PFVA0.mjs +0 -57
- package/dist/package-Bnij-ZtR.mjs +0 -57
- package/dist/package-BtRbHfjz.mjs +0 -57
- package/dist/package-C5B0twb8.mjs +0 -57
- package/dist/package-CC5d8_0L.mjs +0 -57
- package/dist/package-CCJ045H0.mjs +0 -60
- package/dist/package-CS219SXn.mjs +0 -57
- package/dist/package-Cd-9ktpd.mjs +0 -60
- package/dist/package-CgBD49cA.mjs +0 -57
- package/dist/package-CvnNnsm7.mjs +0 -60
- package/dist/package-DPXkSwHu.mjs +0 -57
- package/dist/package-DpqWz9Cr.mjs +0 -60
- package/dist/package-JqEt5Ib4.mjs +0 -57
- package/dist/package-k18Su1iE.mjs +0 -58
- package/dist/package-nzkXV1aM.mjs +0 -57
- package/dist/package-pNo6GC3a.mjs +0 -60
- package/dist/package-pZp14zKI.mjs +0 -57
- package/dist/run-4fyJcaRE.mjs +0 -3856
- package/dist/run-B6oqR83K.mjs +0 -4631
- package/dist/run-BI32lPRK.mjs +0 -3870
- package/dist/run-BQHneHfW.mjs +0 -3834
- package/dist/run-Bb4fyIWZ.mjs +0 -3812
- package/dist/run-BglwnB-A.mjs +0 -3889
- package/dist/run-BjVWuitO.mjs +0 -3919
- package/dist/run-BzUE-JUT.mjs +0 -3708
- package/dist/run-BzqS97Sx.mjs +0 -3666
- package/dist/run-C6snRxyh.mjs +0 -3826
- package/dist/run-C8CI8Ujj.mjs +0 -3693
- package/dist/run-CL-FS4Yc.mjs +0 -3933
- package/dist/run-CS1Z4GcM.mjs +0 -3786
- package/dist/run-CT7uizQo.mjs +0 -4492
- package/dist/run-CUIj4xbE.mjs +0 -4880
- package/dist/run-CW26vPqj.mjs +0 -3919
- package/dist/run-CkTufc0D.mjs +0 -3875
- package/dist/run-Cmostc0S.mjs +0 -3902
- package/dist/run-Cp3kKdzm.mjs +0 -3865
- package/dist/run-D0bCTY72.mjs +0 -3816
- package/dist/run-D4N6FQON.mjs +0 -4673
- package/dist/run-D4dlA0jo.mjs +0 -4813
- package/dist/run-DMW8ibIw.mjs +0 -3958
- package/dist/run-DO52unxE.mjs +0 -3950
- package/dist/run-DQ5FOQ_c.mjs +0 -4788
- package/dist/run-DT7FgL8L.mjs +0 -4339
- package/dist/run-DYhBROuo.mjs +0 -3934
- package/dist/run-DjfPjgOb.mjs +0 -3904
- package/dist/run-DlL4JALM.mjs +0 -4719
- package/dist/run-Dp2JPkGI.mjs +0 -3913
- package/dist/run-Dptna3Je.mjs +0 -3867
- package/dist/run-DwK3dfHd.mjs +0 -3875
- package/dist/run-M_SMt96j.mjs +0 -3913
- package/dist/run-MlpxQUPN.mjs +0 -3869
- package/dist/run-PuTIelbv.mjs +0 -3706
- package/dist/run-h37iSCUB.mjs +0 -3934
- package/dist/run-lpV0oguG.mjs +0 -3897
- package/dist/run-oHmTMcv8.mjs +0 -4721
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-dBWhjQRf.mjs';
|
|
2
2
|
import 'os';
|
|
3
3
|
import 'fs/promises';
|
|
4
4
|
import 'fs';
|
|
@@ -104,7 +104,7 @@ async function handleAgentCommand() {
|
|
|
104
104
|
return;
|
|
105
105
|
}
|
|
106
106
|
if (agentArgs[0] === "list") {
|
|
107
|
-
const { KNOWN_ACP_AGENTS } = await import('./run-
|
|
107
|
+
const { KNOWN_ACP_AGENTS } = await import('./run-dBWhjQRf.mjs').then(function (n) { return n.f; });
|
|
108
108
|
console.log("Known ACP agents:");
|
|
109
109
|
for (const [name, config2] of Object.entries(KNOWN_ACP_AGENTS)) {
|
|
110
110
|
console.log(` ${name.padEnd(12)} ${config2.command} ${config2.args.join(" ")}`);
|
|
@@ -113,10 +113,10 @@ async function handleAgentCommand() {
|
|
|
113
113
|
console.log('Use "svamp agent -- <command> [args]" for a custom ACP agent.');
|
|
114
114
|
return;
|
|
115
115
|
}
|
|
116
|
-
const { resolveAcpAgentConfig } = await import('./run-
|
|
117
|
-
const { AcpBackend } = await import('./run-
|
|
118
|
-
const { GeminiTransport } = await import('./run-
|
|
119
|
-
const { DefaultTransport } = await import('./run-
|
|
116
|
+
const { resolveAcpAgentConfig } = await import('./run-dBWhjQRf.mjs').then(function (n) { return n.f; });
|
|
117
|
+
const { AcpBackend } = await import('./run-dBWhjQRf.mjs').then(function (n) { return n.e; });
|
|
118
|
+
const { GeminiTransport } = await import('./run-dBWhjQRf.mjs').then(function (n) { return n.G; });
|
|
119
|
+
const { DefaultTransport } = await import('./run-dBWhjQRf.mjs').then(function (n) { return n.D; });
|
|
120
120
|
let cwd = process.cwd();
|
|
121
121
|
const filteredArgs = [];
|
|
122
122
|
for (let i = 0; i < agentArgs.length; i++) {
|
|
@@ -255,7 +255,7 @@ async function handleSessionCommand() {
|
|
|
255
255
|
printSessionHelp();
|
|
256
256
|
return;
|
|
257
257
|
}
|
|
258
|
-
const { sessionList, sessionSpawn, sessionStop, sessionInfo, sessionMessages, sessionAttach, sessionMachines, sessionSend, sessionWait } = await import('./commands-
|
|
258
|
+
const { sessionList, sessionSpawn, sessionStop, sessionInfo, sessionMessages, sessionAttach, sessionMachines, sessionSend, sessionWait } = await import('./commands-C5pW2VmI.mjs');
|
|
259
259
|
const parseFlagStr = (flag, shortFlag) => {
|
|
260
260
|
for (let i = 1; i < sessionArgs.length; i++) {
|
|
261
261
|
if ((sessionArgs[i] === flag || shortFlag) && i + 1 < sessionArgs.length) {
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { existsSync, readFileSync } from 'node:fs';
|
|
2
2
|
import { join } from 'node:path';
|
|
3
3
|
import os from 'node:os';
|
|
4
|
-
import { c as connectToHypha } from './run-
|
|
4
|
+
import { c as connectToHypha } from './run-CtCTd6if.mjs';
|
|
5
5
|
import 'os';
|
|
6
6
|
import 'fs/promises';
|
|
7
7
|
import 'fs';
|
|
@@ -1,7 +1,51 @@
|
|
|
1
1
|
import { existsSync, readFileSync } from 'node:fs';
|
|
2
2
|
import { join } from 'node:path';
|
|
3
3
|
import os from 'node:os';
|
|
4
|
-
import { c as connectToHypha } from './
|
|
4
|
+
import { c as connectToHypha } from './run-dBWhjQRf.mjs';
|
|
5
|
+
import 'os';
|
|
6
|
+
import 'fs/promises';
|
|
7
|
+
import 'fs';
|
|
8
|
+
import 'path';
|
|
9
|
+
import 'url';
|
|
10
|
+
import 'child_process';
|
|
11
|
+
import 'crypto';
|
|
12
|
+
import 'node:crypto';
|
|
13
|
+
import 'node:child_process';
|
|
14
|
+
import '@agentclientprotocol/sdk';
|
|
15
|
+
import '@modelcontextprotocol/sdk/client/index.js';
|
|
16
|
+
import '@modelcontextprotocol/sdk/client/stdio.js';
|
|
17
|
+
import '@modelcontextprotocol/sdk/types.js';
|
|
18
|
+
import 'zod';
|
|
19
|
+
import 'node:fs/promises';
|
|
20
|
+
import 'node:util';
|
|
21
|
+
|
|
22
|
+
function toMarkdownInline(value) {
|
|
23
|
+
const escaped = value.replace(/`/g, "\\`");
|
|
24
|
+
return `\`${escaped}\``;
|
|
25
|
+
}
|
|
26
|
+
function formatSessionStatus(data) {
|
|
27
|
+
const lines = [
|
|
28
|
+
"## Session Status",
|
|
29
|
+
"",
|
|
30
|
+
`- Session ID: ${toMarkdownInline(data.sessionId)}`,
|
|
31
|
+
`- Agent: ${data.flavor}`
|
|
32
|
+
];
|
|
33
|
+
if (data.name) lines.push(`- Name: ${data.name}`);
|
|
34
|
+
if (data.summary) lines.push(`- Summary: ${data.summary}`);
|
|
35
|
+
if (data.path) lines.push(`- Path: ${data.path}`);
|
|
36
|
+
if (data.host) lines.push(`- Host: ${data.host}`);
|
|
37
|
+
if (data.lifecycleState) lines.push(`- Lifecycle: ${data.lifecycleState}`);
|
|
38
|
+
lines.push(`- Active: ${data.active ? "yes" : "no"}`);
|
|
39
|
+
lines.push(`- Thinking: ${data.thinking ? "yes" : "no"}`);
|
|
40
|
+
lines.push(`- Agent Status: ${data.active ? "busy" : "idle"}`);
|
|
41
|
+
if (data.startedBy) lines.push(`- Started By: ${data.startedBy}`);
|
|
42
|
+
if (data.claudeSessionId) lines.push(`- Claude Session: ${data.claudeSessionId}`);
|
|
43
|
+
if (data.sessionLink) lines.push(`- Link: ${data.sessionLink}`);
|
|
44
|
+
return lines.join("\n");
|
|
45
|
+
}
|
|
46
|
+
function formatJson(data) {
|
|
47
|
+
return JSON.stringify(data, null, 2);
|
|
48
|
+
}
|
|
5
49
|
|
|
6
50
|
const SVAMP_HOME = process.env.SVAMP_HOME || join(os.homedir(), ".svamp");
|
|
7
51
|
const DAEMON_STATE_FILE = join(SVAMP_HOME, "daemon.state.json");
|
|
@@ -354,49 +398,168 @@ function renderMessage(msg) {
|
|
|
354
398
|
}
|
|
355
399
|
}
|
|
356
400
|
}
|
|
357
|
-
|
|
401
|
+
function extractMessageText(msg) {
|
|
402
|
+
const content = msg.content;
|
|
403
|
+
if (!content) return null;
|
|
404
|
+
const role = content.role || "unknown";
|
|
405
|
+
let text = "";
|
|
406
|
+
if (role === "user") {
|
|
407
|
+
const data = content.content;
|
|
408
|
+
if (typeof data === "string") {
|
|
409
|
+
try {
|
|
410
|
+
const parsed = JSON.parse(data);
|
|
411
|
+
text = parsed?.text || parsed?.content?.text || data;
|
|
412
|
+
} catch {
|
|
413
|
+
text = data;
|
|
414
|
+
}
|
|
415
|
+
} else if (data?.text) {
|
|
416
|
+
text = data.text;
|
|
417
|
+
} else if (data?.type === "text") {
|
|
418
|
+
text = data.text || "";
|
|
419
|
+
} else {
|
|
420
|
+
text = typeof data === "object" ? JSON.stringify(data) : String(data || "");
|
|
421
|
+
}
|
|
422
|
+
} else if (role === "agent" || role === "assistant") {
|
|
423
|
+
const data = content.content?.data || content.content;
|
|
424
|
+
if (!data) return null;
|
|
425
|
+
if (data.type === "assistant" && Array.isArray(data.content)) {
|
|
426
|
+
const parts = [];
|
|
427
|
+
for (const block of data.content) {
|
|
428
|
+
if (block.type === "text" && block.text) {
|
|
429
|
+
parts.push(block.text);
|
|
430
|
+
} else if (block.type === "tool_use") {
|
|
431
|
+
parts.push(`[tool: ${block.name}]`);
|
|
432
|
+
}
|
|
433
|
+
}
|
|
434
|
+
text = parts.join("\n");
|
|
435
|
+
} else if (data.type === "result") {
|
|
436
|
+
text = data.result || "";
|
|
437
|
+
} else if (data.type === "output") {
|
|
438
|
+
const inner = data.data;
|
|
439
|
+
if (inner?.type === "assistant" && Array.isArray(inner.content)) {
|
|
440
|
+
const parts = [];
|
|
441
|
+
for (const block of inner.content) {
|
|
442
|
+
if (block.type === "text" && block.text) {
|
|
443
|
+
parts.push(block.text);
|
|
444
|
+
} else if (block.type === "tool_use") {
|
|
445
|
+
parts.push(`[tool: ${block.name}]`);
|
|
446
|
+
}
|
|
447
|
+
}
|
|
448
|
+
text = parts.join("\n");
|
|
449
|
+
} else if (inner?.type === "result") {
|
|
450
|
+
text = inner.result || "";
|
|
451
|
+
}
|
|
452
|
+
}
|
|
453
|
+
} else if (role === "session") {
|
|
454
|
+
text = "[session event]";
|
|
455
|
+
}
|
|
456
|
+
return {
|
|
457
|
+
id: msg.id || "",
|
|
458
|
+
seq: msg.seq || 0,
|
|
459
|
+
role,
|
|
460
|
+
text,
|
|
461
|
+
createdAt: msg.createdAt || 0
|
|
462
|
+
};
|
|
463
|
+
}
|
|
464
|
+
async function waitForIdle(server, sessionId, timeoutMs) {
|
|
465
|
+
const svc = await server.getService(`svamp-session-${sessionId}`);
|
|
466
|
+
const pollInterval = 2e3;
|
|
467
|
+
const deadline = Date.now() + timeoutMs;
|
|
468
|
+
while (Date.now() < deadline) {
|
|
469
|
+
const activity = await svc.getActivityState();
|
|
470
|
+
if (activity && !activity.active) {
|
|
471
|
+
return;
|
|
472
|
+
}
|
|
473
|
+
await new Promise((r) => setTimeout(r, pollInterval));
|
|
474
|
+
}
|
|
475
|
+
throw new Error("Timeout waiting for agent to become idle");
|
|
476
|
+
}
|
|
477
|
+
async function waitForBusyThenIdle(server, sessionId, timeoutMs = 3e5, busyTimeoutMs = 1e4) {
|
|
478
|
+
const svc = await server.getService(`svamp-session-${sessionId}`);
|
|
479
|
+
const pollInterval = 2e3;
|
|
480
|
+
const deadline = Date.now() + timeoutMs;
|
|
481
|
+
const busyDeadline = Date.now() + busyTimeoutMs;
|
|
482
|
+
let sawBusy = false;
|
|
483
|
+
while (Date.now() < deadline) {
|
|
484
|
+
const activity = await svc.getActivityState();
|
|
485
|
+
const isActive = activity?.active === true;
|
|
486
|
+
if (isActive) {
|
|
487
|
+
sawBusy = true;
|
|
488
|
+
}
|
|
489
|
+
if (sawBusy && !isActive) {
|
|
490
|
+
return;
|
|
491
|
+
}
|
|
492
|
+
if (!sawBusy && Date.now() > busyDeadline) {
|
|
493
|
+
return;
|
|
494
|
+
}
|
|
495
|
+
await new Promise((r) => setTimeout(r, pollInterval));
|
|
496
|
+
}
|
|
497
|
+
throw new Error("Timeout waiting for agent to become idle");
|
|
498
|
+
}
|
|
499
|
+
async function sessionList(machineId, opts) {
|
|
358
500
|
const { server, machine } = await connectAndGetMachine(machineId);
|
|
359
501
|
try {
|
|
360
502
|
const sessions = await machine.listSessions();
|
|
361
|
-
|
|
362
|
-
|
|
503
|
+
const filtered = opts?.active ? sessions.filter((s) => s.active) : sessions;
|
|
504
|
+
if (filtered.length === 0) {
|
|
505
|
+
if (opts?.json) {
|
|
506
|
+
console.log(formatJson([]));
|
|
507
|
+
} else {
|
|
508
|
+
console.log("No active sessions.");
|
|
509
|
+
}
|
|
363
510
|
return;
|
|
364
511
|
}
|
|
365
512
|
const enriched = [];
|
|
366
|
-
for (const s of
|
|
513
|
+
for (const s of filtered) {
|
|
367
514
|
let flavor = "claude";
|
|
368
515
|
let name = "";
|
|
516
|
+
let path = s.directory || "";
|
|
517
|
+
let host = "";
|
|
369
518
|
if (s.metadata) {
|
|
370
519
|
flavor = s.metadata.flavor || "claude";
|
|
371
520
|
name = s.metadata.name || "";
|
|
372
521
|
}
|
|
373
|
-
if (
|
|
522
|
+
if (s.active) {
|
|
374
523
|
try {
|
|
375
524
|
const svc = await server.getService(`svamp-session-${s.sessionId}`);
|
|
376
525
|
const { metadata } = await svc.getMetadata();
|
|
377
526
|
flavor = metadata?.flavor || flavor;
|
|
378
|
-
name = metadata?.name ||
|
|
527
|
+
name = metadata?.name || name;
|
|
528
|
+
path = metadata?.path || path;
|
|
529
|
+
host = metadata?.host || "";
|
|
379
530
|
} catch {
|
|
380
531
|
}
|
|
381
532
|
}
|
|
382
|
-
enriched.push({ ...s, flavor, name });
|
|
533
|
+
enriched.push({ ...s, flavor, name, path, host });
|
|
383
534
|
}
|
|
384
|
-
|
|
385
|
-
|
|
386
|
-
|
|
387
|
-
|
|
388
|
-
|
|
389
|
-
|
|
390
|
-
|
|
391
|
-
|
|
392
|
-
|
|
393
|
-
|
|
535
|
+
if (opts?.json) {
|
|
536
|
+
console.log(formatJson(enriched.map((s) => ({
|
|
537
|
+
sessionId: s.sessionId,
|
|
538
|
+
agent: s.flavor,
|
|
539
|
+
name: s.name,
|
|
540
|
+
path: s.path,
|
|
541
|
+
host: s.host,
|
|
542
|
+
active: s.active,
|
|
543
|
+
directory: s.directory
|
|
544
|
+
}))));
|
|
545
|
+
} else {
|
|
546
|
+
const header = `${"ID".padEnd(10)} ${"AGENT".padEnd(10)} ${"STATUS".padEnd(9)} ${"NAME".padEnd(25)} ${"DIRECTORY".padEnd(35)}`;
|
|
547
|
+
console.log(header);
|
|
548
|
+
console.log("-".repeat(header.length));
|
|
549
|
+
for (const s of enriched) {
|
|
550
|
+
const id = s.sessionId.slice(0, 8);
|
|
551
|
+
const agent = (s.flavor || "claude").padEnd(10);
|
|
552
|
+
const status = s.active ? "\x1B[32mactive\x1B[0m " : "\x1B[90minactive\x1B[0m";
|
|
553
|
+
const name = truncate(s.name || "-", 25).padEnd(25);
|
|
554
|
+
const dir = truncate(s.directory || "-", 33).padEnd(35);
|
|
555
|
+
console.log(`${id.padEnd(10)} ${agent} ${status} ${name} ${dir}`);
|
|
556
|
+
}
|
|
394
557
|
}
|
|
395
558
|
} finally {
|
|
396
559
|
await server.disconnect();
|
|
397
560
|
}
|
|
398
561
|
}
|
|
399
|
-
async function sessionSpawn(agent, directory, machineId) {
|
|
562
|
+
async function sessionSpawn(agent, directory, machineId, opts) {
|
|
400
563
|
const { server, machine } = await connectAndGetMachine(machineId);
|
|
401
564
|
try {
|
|
402
565
|
console.log(`Spawning ${agent} session in ${directory}...`);
|
|
@@ -407,6 +570,22 @@ async function sessionSpawn(agent, directory, machineId) {
|
|
|
407
570
|
if (result.type === "success") {
|
|
408
571
|
console.log(`Session started: ${result.sessionId}`);
|
|
409
572
|
if (result.message) console.log(` ${result.message}`);
|
|
573
|
+
if (opts?.message && result.sessionId) {
|
|
574
|
+
const svc = await server.getService(`svamp-session-${result.sessionId}`);
|
|
575
|
+
const sendResult = await svc.sendMessage(
|
|
576
|
+
JSON.stringify({
|
|
577
|
+
role: "user",
|
|
578
|
+
content: { type: "text", text: opts.message },
|
|
579
|
+
meta: { sentFrom: "svamp-cli" }
|
|
580
|
+
})
|
|
581
|
+
);
|
|
582
|
+
console.log(`Message sent (seq: ${sendResult.seq})`);
|
|
583
|
+
if (opts.wait) {
|
|
584
|
+
console.log("Waiting for agent to become idle...");
|
|
585
|
+
await waitForBusyThenIdle(server, result.sessionId);
|
|
586
|
+
console.log("Agent is idle.");
|
|
587
|
+
}
|
|
588
|
+
}
|
|
410
589
|
} else if (result.type === "requestToApproveDirectoryCreation") {
|
|
411
590
|
console.error(`Directory ${result.directory} does not exist. Create it first or use an existing directory.`);
|
|
412
591
|
process.exit(1);
|
|
@@ -434,7 +613,7 @@ async function sessionStop(sessionId, machineId) {
|
|
|
434
613
|
await server.disconnect();
|
|
435
614
|
}
|
|
436
615
|
}
|
|
437
|
-
async function sessionInfo(sessionId, machineId) {
|
|
616
|
+
async function sessionInfo(sessionId, machineId, opts) {
|
|
438
617
|
const { server, machine } = await connectAndGetMachine(machineId);
|
|
439
618
|
try {
|
|
440
619
|
const sessions = await machine.listSessions();
|
|
@@ -449,43 +628,62 @@ async function sessionInfo(sessionId, machineId) {
|
|
|
449
628
|
activity = await svc.getActivityState();
|
|
450
629
|
} catch {
|
|
451
630
|
}
|
|
452
|
-
|
|
453
|
-
|
|
454
|
-
|
|
455
|
-
|
|
456
|
-
|
|
457
|
-
|
|
458
|
-
|
|
459
|
-
|
|
460
|
-
|
|
461
|
-
|
|
462
|
-
|
|
463
|
-
|
|
464
|
-
|
|
465
|
-
|
|
466
|
-
|
|
467
|
-
|
|
468
|
-
|
|
631
|
+
const statusData = {
|
|
632
|
+
sessionId: fullId,
|
|
633
|
+
flavor: metadata.flavor || "claude",
|
|
634
|
+
name: metadata.name || "",
|
|
635
|
+
path: metadata.path || match.directory || "",
|
|
636
|
+
host: metadata.host || "",
|
|
637
|
+
lifecycleState: metadata.lifecycleState || "unknown",
|
|
638
|
+
active: activity.active ?? false,
|
|
639
|
+
thinking: activity.thinking ?? false,
|
|
640
|
+
startedBy: metadata.startedBy || match.startedBy || "",
|
|
641
|
+
summary: metadata.summary?.text || void 0,
|
|
642
|
+
claudeSessionId: metadata.claudeSessionId || void 0,
|
|
643
|
+
sessionLink: metadata.sessionLink?.url || void 0
|
|
644
|
+
};
|
|
645
|
+
if (opts?.json) {
|
|
646
|
+
console.log(formatJson(statusData));
|
|
647
|
+
} else {
|
|
648
|
+
console.log(formatSessionStatus(statusData));
|
|
469
649
|
}
|
|
470
650
|
} finally {
|
|
471
651
|
await server.disconnect();
|
|
472
652
|
}
|
|
473
653
|
}
|
|
474
|
-
async function sessionMessages(sessionId,
|
|
654
|
+
async function sessionMessages(sessionId, machineId, opts) {
|
|
475
655
|
const { server, machine } = await connectAndGetMachine(machineId);
|
|
476
656
|
try {
|
|
477
657
|
const sessions = await machine.listSessions();
|
|
478
658
|
const match = resolveSessionId(sessions, sessionId);
|
|
479
659
|
const fullId = match.sessionId;
|
|
480
660
|
const svc = await server.getService(`svamp-session-${fullId}`);
|
|
481
|
-
const
|
|
482
|
-
const
|
|
661
|
+
const afterSeq = opts?.after ?? 0;
|
|
662
|
+
const apiLimit = opts?.limit ?? 1e3;
|
|
663
|
+
const { messages } = await svc.getMessages(afterSeq, apiLimit);
|
|
664
|
+
const toShow = opts?.last ? messages.slice(-opts.last) : messages;
|
|
483
665
|
if (toShow.length === 0) {
|
|
484
|
-
|
|
666
|
+
if (opts?.json) {
|
|
667
|
+
console.log(formatJson([]));
|
|
668
|
+
} else {
|
|
669
|
+
console.log("No messages yet.");
|
|
670
|
+
}
|
|
485
671
|
return;
|
|
486
672
|
}
|
|
487
|
-
|
|
488
|
-
|
|
673
|
+
if (opts?.json) {
|
|
674
|
+
const formatted = [];
|
|
675
|
+
for (const msg of toShow) {
|
|
676
|
+
const extracted = extractMessageText(msg);
|
|
677
|
+
if (extracted) {
|
|
678
|
+
formatted.push(extracted);
|
|
679
|
+
}
|
|
680
|
+
}
|
|
681
|
+
formatted.sort((a, b) => a.createdAt - b.createdAt);
|
|
682
|
+
console.log(formatJson(formatted));
|
|
683
|
+
} else {
|
|
684
|
+
for (const msg of toShow) {
|
|
685
|
+
renderMessage(msg);
|
|
686
|
+
}
|
|
489
687
|
}
|
|
490
688
|
} finally {
|
|
491
689
|
await server.disconnect();
|
|
@@ -607,30 +805,58 @@ async function sessionAttach(sessionId, machineId) {
|
|
|
607
805
|
process.exit(0);
|
|
608
806
|
});
|
|
609
807
|
}
|
|
610
|
-
async function
|
|
808
|
+
async function sessionSend(sessionId, message, machineId, opts) {
|
|
611
809
|
const { server, machine } = await connectAndGetMachine(machineId);
|
|
612
810
|
try {
|
|
613
|
-
|
|
614
|
-
const
|
|
615
|
-
|
|
616
|
-
|
|
617
|
-
|
|
618
|
-
|
|
619
|
-
|
|
620
|
-
|
|
811
|
+
const sessions = await machine.listSessions();
|
|
812
|
+
const match = resolveSessionId(sessions, sessionId);
|
|
813
|
+
const fullId = match.sessionId;
|
|
814
|
+
const svc = await server.getService(`svamp-session-${fullId}`);
|
|
815
|
+
const result = await svc.sendMessage(
|
|
816
|
+
JSON.stringify({
|
|
817
|
+
role: "user",
|
|
818
|
+
content: { type: "text", text: message },
|
|
819
|
+
meta: { sentFrom: "svamp-cli" }
|
|
820
|
+
})
|
|
821
|
+
);
|
|
822
|
+
if (opts?.wait) {
|
|
823
|
+
const timeoutMs = (opts.timeout || 300) * 1e3;
|
|
824
|
+
await waitForBusyThenIdle(server, fullId, timeoutMs);
|
|
621
825
|
}
|
|
622
|
-
|
|
623
|
-
|
|
624
|
-
|
|
625
|
-
|
|
626
|
-
|
|
826
|
+
if (opts?.json) {
|
|
827
|
+
console.log(formatJson({
|
|
828
|
+
sessionId: fullId,
|
|
829
|
+
message,
|
|
830
|
+
sent: true,
|
|
831
|
+
seq: result.seq,
|
|
832
|
+
waited: !!opts.wait
|
|
833
|
+
}));
|
|
834
|
+
} else {
|
|
835
|
+
console.log(`Message sent to session ${fullId.slice(0, 8)} (seq: ${result.seq})`);
|
|
836
|
+
if (opts?.wait) {
|
|
837
|
+
console.log("Agent is idle.");
|
|
627
838
|
}
|
|
628
839
|
}
|
|
629
|
-
|
|
630
|
-
|
|
840
|
+
} finally {
|
|
841
|
+
await server.disconnect();
|
|
842
|
+
}
|
|
843
|
+
}
|
|
844
|
+
async function sessionWait(sessionId, machineId, opts) {
|
|
845
|
+
const { server, machine } = await connectAndGetMachine(machineId);
|
|
846
|
+
try {
|
|
847
|
+
const sessions = await machine.listSessions();
|
|
848
|
+
const match = resolveSessionId(sessions, sessionId);
|
|
849
|
+
const fullId = match.sessionId;
|
|
850
|
+
const timeoutMs = (opts?.timeout || 300) * 1e3;
|
|
851
|
+
await waitForIdle(server, fullId, timeoutMs);
|
|
852
|
+
console.log(`Session ${fullId.slice(0, 8)} is idle.`);
|
|
853
|
+
} catch (err) {
|
|
854
|
+
const msg = err instanceof Error ? err.message : String(err);
|
|
855
|
+
console.error(msg);
|
|
856
|
+
process.exitCode = 1;
|
|
631
857
|
} finally {
|
|
632
858
|
await server.disconnect();
|
|
633
859
|
}
|
|
634
860
|
}
|
|
635
861
|
|
|
636
|
-
export { connectAndGetMachine, renderMessage, resolveSessionId, sessionAttach, sessionInfo, sessionList, sessionMachines, sessionMessages,
|
|
862
|
+
export { connectAndGetMachine, renderMessage, resolveSessionId, sessionAttach, sessionInfo, sessionList, sessionMachines, sessionMessages, sessionSend, sessionSpawn, sessionStop, sessionWait };
|