svamp-cli 0.2.21 → 0.2.22
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/{agentCommands-DRxsYzlw.mjs → agentCommands-C32VYCxV.mjs} +2 -2
- package/dist/cli.mjs +30 -30
- package/dist/{commands-DkmPKHhv.mjs → commands-6ottz7I-.mjs} +2 -2
- package/dist/{commands-DVCdUK0p.mjs → commands-CNDLej2C.mjs} +1 -1
- package/dist/commands-DGsQyrpg.mjs +154 -0
- package/dist/{frpc-Ckiiq9Lw.mjs → frpc-Dz3UhcgJ.mjs} +20 -7
- package/dist/index.mjs +1 -1
- package/dist/{package-DkmeUIJ-.mjs → package-6Bo1dVcf.mjs} +4 -3
- package/dist/{run-B_yFI97i.mjs → run-B64CzU72.mjs} +1 -1
- package/dist/{run-CdjKXuaY.mjs → run-CQfp9fM9.mjs} +17 -20
- package/dist/{serveCommands-PxeZcd-5.mjs → serveCommands-C515r-sl.mjs} +4 -4
- package/dist/{serveManager-Be7Dgpoe.mjs → serveManager-6vRqOXK_.mjs} +17 -38
- package/package.json +4 -3
- package/dist/api-BRbsyqJ4.mjs +0 -147
- package/dist/commands-DdwOBsOi.mjs +0 -477
|
@@ -148,7 +148,7 @@ async function sessionBroadcast(action, args) {
|
|
|
148
148
|
console.log(`Broadcast sent: ${action}`);
|
|
149
149
|
}
|
|
150
150
|
async function connectToMachineService() {
|
|
151
|
-
const { connectAndGetMachine } = await import('./commands-
|
|
151
|
+
const { connectAndGetMachine } = await import('./commands-CNDLej2C.mjs');
|
|
152
152
|
return connectAndGetMachine();
|
|
153
153
|
}
|
|
154
154
|
async function inboxSend(targetSessionId, opts) {
|
|
@@ -165,7 +165,7 @@ async function inboxSend(targetSessionId, opts) {
|
|
|
165
165
|
}
|
|
166
166
|
const { server, machine } = await connectToMachineService();
|
|
167
167
|
try {
|
|
168
|
-
const { resolveSessionId } = await import('./commands-
|
|
168
|
+
const { resolveSessionId } = await import('./commands-CNDLej2C.mjs');
|
|
169
169
|
const sessions = await machine.listSessions();
|
|
170
170
|
const match = resolveSessionId(sessions, targetSessionId);
|
|
171
171
|
const fullTargetId = match.sessionId;
|
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-CQfp9fM9.mjs';
|
|
2
2
|
import 'os';
|
|
3
3
|
import 'fs/promises';
|
|
4
4
|
import 'fs';
|
|
@@ -36,7 +36,7 @@ async function main() {
|
|
|
36
36
|
await logoutFromHypha();
|
|
37
37
|
} else if (subcommand === "daemon") {
|
|
38
38
|
if (daemonSubcommand === "restart") {
|
|
39
|
-
const { restartDaemon } = await import('./run-
|
|
39
|
+
const { restartDaemon } = await import('./run-CQfp9fM9.mjs').then(function (n) { return n.k; });
|
|
40
40
|
await restartDaemon();
|
|
41
41
|
process.exit(0);
|
|
42
42
|
}
|
|
@@ -238,7 +238,7 @@ async function main() {
|
|
|
238
238
|
console.error("svamp service: Service commands are not available in sandboxed sessions.");
|
|
239
239
|
process.exit(1);
|
|
240
240
|
}
|
|
241
|
-
const { handleServiceCommand } = await import('./commands-
|
|
241
|
+
const { handleServiceCommand } = await import('./commands-DGsQyrpg.mjs');
|
|
242
242
|
await handleServiceCommand();
|
|
243
243
|
} else if (subcommand === "serve") {
|
|
244
244
|
const { isSandboxed: isSandboxedServe } = await import('./sandboxDetect-DNTcbgWD.mjs');
|
|
@@ -246,7 +246,7 @@ async function main() {
|
|
|
246
246
|
console.error("svamp serve: Serve commands are not available in sandboxed sessions.");
|
|
247
247
|
process.exit(1);
|
|
248
248
|
}
|
|
249
|
-
const { handleServeCommand } = await import('./serveCommands-
|
|
249
|
+
const { handleServeCommand } = await import('./serveCommands-C515r-sl.mjs');
|
|
250
250
|
await handleServeCommand();
|
|
251
251
|
process.exit(0);
|
|
252
252
|
} else if (subcommand === "process" || subcommand === "proc") {
|
|
@@ -255,7 +255,7 @@ async function main() {
|
|
|
255
255
|
console.error("svamp process: Process commands are not available in sandboxed sessions.");
|
|
256
256
|
process.exit(1);
|
|
257
257
|
}
|
|
258
|
-
const { processCommand } = await import('./commands-
|
|
258
|
+
const { processCommand } = await import('./commands-6ottz7I-.mjs');
|
|
259
259
|
let machineId;
|
|
260
260
|
const processArgs = args.slice(1);
|
|
261
261
|
const mIdx = processArgs.findIndex((a) => a === "--machine" || a === "-m");
|
|
@@ -273,7 +273,7 @@ async function main() {
|
|
|
273
273
|
} else if (!subcommand || subcommand === "start") {
|
|
274
274
|
await handleInteractiveCommand();
|
|
275
275
|
} else if (subcommand === "--version" || subcommand === "-v") {
|
|
276
|
-
const pkg = await import('./package-
|
|
276
|
+
const pkg = await import('./package-6Bo1dVcf.mjs').catch(() => ({ default: { version: "unknown" } }));
|
|
277
277
|
console.log(`svamp version: ${pkg.default.version}`);
|
|
278
278
|
} else {
|
|
279
279
|
console.error(`Unknown command: ${subcommand}`);
|
|
@@ -282,7 +282,7 @@ async function main() {
|
|
|
282
282
|
}
|
|
283
283
|
}
|
|
284
284
|
async function handleInteractiveCommand() {
|
|
285
|
-
const { runInteractive } = await import('./run-
|
|
285
|
+
const { runInteractive } = await import('./run-B64CzU72.mjs');
|
|
286
286
|
const interactiveArgs = subcommand === "start" ? args.slice(1) : args;
|
|
287
287
|
let directory = process.cwd();
|
|
288
288
|
let resumeSessionId;
|
|
@@ -327,7 +327,7 @@ async function handleAgentCommand() {
|
|
|
327
327
|
return;
|
|
328
328
|
}
|
|
329
329
|
if (agentArgs[0] === "list") {
|
|
330
|
-
const { KNOWN_ACP_AGENTS, KNOWN_MCP_AGENTS: KNOWN_MCP_AGENTS2 } = await import('./run-
|
|
330
|
+
const { KNOWN_ACP_AGENTS, KNOWN_MCP_AGENTS: KNOWN_MCP_AGENTS2 } = await import('./run-CQfp9fM9.mjs').then(function (n) { return n.i; });
|
|
331
331
|
console.log("Known agents:");
|
|
332
332
|
for (const [name, config2] of Object.entries(KNOWN_ACP_AGENTS)) {
|
|
333
333
|
console.log(` ${name.padEnd(12)} ${config2.command} ${config2.args.join(" ")} (ACP)`);
|
|
@@ -339,7 +339,7 @@ async function handleAgentCommand() {
|
|
|
339
339
|
console.log('Use "svamp agent -- <command> [args]" for a custom ACP agent.');
|
|
340
340
|
return;
|
|
341
341
|
}
|
|
342
|
-
const { resolveAcpAgentConfig, KNOWN_MCP_AGENTS } = await import('./run-
|
|
342
|
+
const { resolveAcpAgentConfig, KNOWN_MCP_AGENTS } = await import('./run-CQfp9fM9.mjs').then(function (n) { return n.i; });
|
|
343
343
|
let cwd = process.cwd();
|
|
344
344
|
const filteredArgs = [];
|
|
345
345
|
for (let i = 0; i < agentArgs.length; i++) {
|
|
@@ -363,12 +363,12 @@ async function handleAgentCommand() {
|
|
|
363
363
|
console.log(`Starting ${config.agentName} agent in ${cwd}...`);
|
|
364
364
|
let backend;
|
|
365
365
|
if (KNOWN_MCP_AGENTS[config.agentName]) {
|
|
366
|
-
const { CodexMcpBackend } = await import('./run-
|
|
366
|
+
const { CodexMcpBackend } = await import('./run-CQfp9fM9.mjs').then(function (n) { return n.j; });
|
|
367
367
|
backend = new CodexMcpBackend({ cwd, log: logFn });
|
|
368
368
|
} else {
|
|
369
|
-
const { AcpBackend } = await import('./run-
|
|
370
|
-
const { GeminiTransport } = await import('./run-
|
|
371
|
-
const { DefaultTransport } = await import('./run-
|
|
369
|
+
const { AcpBackend } = await import('./run-CQfp9fM9.mjs').then(function (n) { return n.h; });
|
|
370
|
+
const { GeminiTransport } = await import('./run-CQfp9fM9.mjs').then(function (n) { return n.G; });
|
|
371
|
+
const { DefaultTransport } = await import('./run-CQfp9fM9.mjs').then(function (n) { return n.D; });
|
|
372
372
|
const transportHandler = config.agentName === "gemini" ? new GeminiTransport() : new DefaultTransport(config.agentName);
|
|
373
373
|
backend = new AcpBackend({
|
|
374
374
|
agentName: config.agentName,
|
|
@@ -495,7 +495,7 @@ async function handleSessionCommand() {
|
|
|
495
495
|
process.exit(1);
|
|
496
496
|
}
|
|
497
497
|
}
|
|
498
|
-
const { sessionList, sessionSpawn, sessionStop, sessionInfo, sessionMessages, sessionAttach, sessionMachines, sessionSend, sessionWait, sessionShare, sessionRalphStart, sessionRalphCancel, sessionRalphStatus, sessionInboxSend, sessionInboxList, sessionInboxRead, sessionInboxReply, sessionInboxClear } = await import('./commands-
|
|
498
|
+
const { sessionList, sessionSpawn, sessionStop, sessionInfo, sessionMessages, sessionAttach, sessionMachines, sessionSend, sessionWait, sessionShare, sessionRalphStart, sessionRalphCancel, sessionRalphStatus, sessionInboxSend, sessionInboxList, sessionInboxRead, sessionInboxReply, sessionInboxClear } = await import('./commands-CNDLej2C.mjs');
|
|
499
499
|
const parseFlagStr = (flag, shortFlag) => {
|
|
500
500
|
for (let i = 1; i < sessionArgs.length; i++) {
|
|
501
501
|
if ((sessionArgs[i] === flag || shortFlag) && i + 1 < sessionArgs.length) {
|
|
@@ -555,7 +555,7 @@ async function handleSessionCommand() {
|
|
|
555
555
|
allowDomain.push(sessionArgs[++i]);
|
|
556
556
|
}
|
|
557
557
|
}
|
|
558
|
-
const { parseShareArg } = await import('./commands-
|
|
558
|
+
const { parseShareArg } = await import('./commands-CNDLej2C.mjs');
|
|
559
559
|
const shareEntries = share.map((s) => parseShareArg(s));
|
|
560
560
|
await sessionSpawn(agent, dir, targetMachineId, {
|
|
561
561
|
message,
|
|
@@ -641,7 +641,7 @@ async function handleSessionCommand() {
|
|
|
641
641
|
console.error("Usage: svamp session approve <session-id> [request-id] [--json]");
|
|
642
642
|
process.exit(1);
|
|
643
643
|
}
|
|
644
|
-
const { sessionApprove } = await import('./commands-
|
|
644
|
+
const { sessionApprove } = await import('./commands-CNDLej2C.mjs');
|
|
645
645
|
const approveReqId = sessionArgs[2] && !sessionArgs[2].startsWith("--") ? sessionArgs[2] : void 0;
|
|
646
646
|
await sessionApprove(sessionArgs[1], approveReqId, targetMachineId, {
|
|
647
647
|
json: hasFlag("--json")
|
|
@@ -651,7 +651,7 @@ async function handleSessionCommand() {
|
|
|
651
651
|
console.error("Usage: svamp session deny <session-id> [request-id] [--json]");
|
|
652
652
|
process.exit(1);
|
|
653
653
|
}
|
|
654
|
-
const { sessionDeny } = await import('./commands-
|
|
654
|
+
const { sessionDeny } = await import('./commands-CNDLej2C.mjs');
|
|
655
655
|
const denyReqId = sessionArgs[2] && !sessionArgs[2].startsWith("--") ? sessionArgs[2] : void 0;
|
|
656
656
|
await sessionDeny(sessionArgs[1], denyReqId, targetMachineId, {
|
|
657
657
|
json: hasFlag("--json")
|
|
@@ -687,7 +687,7 @@ async function handleSessionCommand() {
|
|
|
687
687
|
console.error("Usage: svamp session set-title <title>");
|
|
688
688
|
process.exit(1);
|
|
689
689
|
}
|
|
690
|
-
const { sessionSetTitle } = await import('./agentCommands-
|
|
690
|
+
const { sessionSetTitle } = await import('./agentCommands-C32VYCxV.mjs');
|
|
691
691
|
await sessionSetTitle(title);
|
|
692
692
|
} else if (sessionSubcommand === "set-link") {
|
|
693
693
|
const url = sessionArgs[1];
|
|
@@ -696,7 +696,7 @@ async function handleSessionCommand() {
|
|
|
696
696
|
process.exit(1);
|
|
697
697
|
}
|
|
698
698
|
const label = sessionArgs[2] && !sessionArgs[2].startsWith("--") ? sessionArgs[2] : void 0;
|
|
699
|
-
const { sessionSetLink } = await import('./agentCommands-
|
|
699
|
+
const { sessionSetLink } = await import('./agentCommands-C32VYCxV.mjs');
|
|
700
700
|
await sessionSetLink(url, label);
|
|
701
701
|
} else if (sessionSubcommand === "notify") {
|
|
702
702
|
const message = sessionArgs[1];
|
|
@@ -705,7 +705,7 @@ async function handleSessionCommand() {
|
|
|
705
705
|
process.exit(1);
|
|
706
706
|
}
|
|
707
707
|
const level = parseFlagStr("--level") || "info";
|
|
708
|
-
const { sessionNotify } = await import('./agentCommands-
|
|
708
|
+
const { sessionNotify } = await import('./agentCommands-C32VYCxV.mjs');
|
|
709
709
|
await sessionNotify(message, level);
|
|
710
710
|
} else if (sessionSubcommand === "broadcast") {
|
|
711
711
|
const action = sessionArgs[1];
|
|
@@ -713,7 +713,7 @@ async function handleSessionCommand() {
|
|
|
713
713
|
console.error("Usage: svamp session broadcast <action> [args...]\nActions: open-canvas <url> [label], close-canvas, toast <message>");
|
|
714
714
|
process.exit(1);
|
|
715
715
|
}
|
|
716
|
-
const { sessionBroadcast } = await import('./agentCommands-
|
|
716
|
+
const { sessionBroadcast } = await import('./agentCommands-C32VYCxV.mjs');
|
|
717
717
|
await sessionBroadcast(action, sessionArgs.slice(2).filter((a) => !a.startsWith("--")));
|
|
718
718
|
} else if (sessionSubcommand === "inbox") {
|
|
719
719
|
const inboxSubcmd = sessionArgs[1];
|
|
@@ -724,7 +724,7 @@ async function handleSessionCommand() {
|
|
|
724
724
|
process.exit(1);
|
|
725
725
|
}
|
|
726
726
|
if (agentSessionId) {
|
|
727
|
-
const { inboxSend } = await import('./agentCommands-
|
|
727
|
+
const { inboxSend } = await import('./agentCommands-C32VYCxV.mjs');
|
|
728
728
|
await inboxSend(sessionArgs[2], {
|
|
729
729
|
body: sessionArgs[3],
|
|
730
730
|
subject: parseFlagStr("--subject"),
|
|
@@ -739,7 +739,7 @@ async function handleSessionCommand() {
|
|
|
739
739
|
}
|
|
740
740
|
} else if (inboxSubcmd === "list" || inboxSubcmd === "ls") {
|
|
741
741
|
if (agentSessionId && !sessionArgs[2]) {
|
|
742
|
-
const { inboxList } = await import('./agentCommands-
|
|
742
|
+
const { inboxList } = await import('./agentCommands-C32VYCxV.mjs');
|
|
743
743
|
await inboxList({
|
|
744
744
|
unread: hasFlag("--unread"),
|
|
745
745
|
limit: parseFlagInt("--limit"),
|
|
@@ -761,7 +761,7 @@ async function handleSessionCommand() {
|
|
|
761
761
|
process.exit(1);
|
|
762
762
|
}
|
|
763
763
|
if (agentSessionId && !sessionArgs[3]) {
|
|
764
|
-
const { inboxList } = await import('./agentCommands-
|
|
764
|
+
const { inboxList } = await import('./agentCommands-C32VYCxV.mjs');
|
|
765
765
|
await sessionInboxRead(agentSessionId, sessionArgs[2], targetMachineId);
|
|
766
766
|
} else if (sessionArgs[3]) {
|
|
767
767
|
await sessionInboxRead(sessionArgs[2], sessionArgs[3], targetMachineId);
|
|
@@ -771,7 +771,7 @@ async function handleSessionCommand() {
|
|
|
771
771
|
}
|
|
772
772
|
} else if (inboxSubcmd === "reply") {
|
|
773
773
|
if (agentSessionId && sessionArgs[2] && sessionArgs[3] && !sessionArgs[4]) {
|
|
774
|
-
const { inboxReply } = await import('./agentCommands-
|
|
774
|
+
const { inboxReply } = await import('./agentCommands-C32VYCxV.mjs');
|
|
775
775
|
await inboxReply(sessionArgs[2], sessionArgs[3]);
|
|
776
776
|
} else if (sessionArgs[2] && sessionArgs[3] && sessionArgs[4]) {
|
|
777
777
|
await sessionInboxReply(sessionArgs[2], sessionArgs[3], sessionArgs[4], targetMachineId);
|
|
@@ -807,7 +807,7 @@ async function handleMachineCommand() {
|
|
|
807
807
|
return;
|
|
808
808
|
}
|
|
809
809
|
if (machineSubcommand === "share") {
|
|
810
|
-
const { machineShare } = await import('./commands-
|
|
810
|
+
const { machineShare } = await import('./commands-CNDLej2C.mjs');
|
|
811
811
|
let machineId;
|
|
812
812
|
const shareArgs = [];
|
|
813
813
|
for (let i = 1; i < machineArgs.length; i++) {
|
|
@@ -837,7 +837,7 @@ async function handleMachineCommand() {
|
|
|
837
837
|
}
|
|
838
838
|
await machineShare(machineId, { add, remove, list, configPath, showConfig });
|
|
839
839
|
} else if (machineSubcommand === "exec") {
|
|
840
|
-
const { machineExec } = await import('./commands-
|
|
840
|
+
const { machineExec } = await import('./commands-CNDLej2C.mjs');
|
|
841
841
|
let machineId;
|
|
842
842
|
let cwd;
|
|
843
843
|
const cmdParts = [];
|
|
@@ -857,7 +857,7 @@ async function handleMachineCommand() {
|
|
|
857
857
|
}
|
|
858
858
|
await machineExec(machineId, command, cwd);
|
|
859
859
|
} else if (machineSubcommand === "info") {
|
|
860
|
-
const { machineInfo } = await import('./commands-
|
|
860
|
+
const { machineInfo } = await import('./commands-CNDLej2C.mjs');
|
|
861
861
|
let machineId;
|
|
862
862
|
for (let i = 1; i < machineArgs.length; i++) {
|
|
863
863
|
if ((machineArgs[i] === "--machine" || machineArgs[i] === "-m") && i + 1 < machineArgs.length) {
|
|
@@ -877,10 +877,10 @@ async function handleMachineCommand() {
|
|
|
877
877
|
level = machineArgs[++i];
|
|
878
878
|
}
|
|
879
879
|
}
|
|
880
|
-
const { machineNotify } = await import('./agentCommands-
|
|
880
|
+
const { machineNotify } = await import('./agentCommands-C32VYCxV.mjs');
|
|
881
881
|
await machineNotify(message, level);
|
|
882
882
|
} else if (machineSubcommand === "ls") {
|
|
883
|
-
const { machineLs } = await import('./commands-
|
|
883
|
+
const { machineLs } = await import('./commands-CNDLej2C.mjs');
|
|
884
884
|
let machineId;
|
|
885
885
|
let showHidden = false;
|
|
886
886
|
let path;
|
|
@@ -1,11 +1,11 @@
|
|
|
1
1
|
import { writeFileSync, readFileSync } from 'fs';
|
|
2
2
|
import { resolve } from 'path';
|
|
3
|
-
import { connectAndGetMachine } from './commands-
|
|
3
|
+
import { connectAndGetMachine } from './commands-CNDLej2C.mjs';
|
|
4
4
|
import 'node:fs';
|
|
5
5
|
import 'node:child_process';
|
|
6
6
|
import 'node:path';
|
|
7
7
|
import 'node:os';
|
|
8
|
-
import './run-
|
|
8
|
+
import './run-CQfp9fM9.mjs';
|
|
9
9
|
import 'os';
|
|
10
10
|
import 'fs/promises';
|
|
11
11
|
import 'url';
|
|
@@ -2,7 +2,7 @@ import { existsSync, readFileSync } from 'node:fs';
|
|
|
2
2
|
import { execSync } from 'node:child_process';
|
|
3
3
|
import { resolve, join } from 'node:path';
|
|
4
4
|
import os from 'node:os';
|
|
5
|
-
import { l as loadSecurityContextConfig, e as resolveSecurityContext, f as buildSecurityContextFromFlags, m as mergeSecurityContexts, c as connectToHypha } from './run-
|
|
5
|
+
import { l as loadSecurityContextConfig, e as resolveSecurityContext, f as buildSecurityContextFromFlags, m as mergeSecurityContexts, c as connectToHypha } from './run-CQfp9fM9.mjs';
|
|
6
6
|
import 'os';
|
|
7
7
|
import 'fs/promises';
|
|
8
8
|
import 'fs';
|
|
@@ -0,0 +1,154 @@
|
|
|
1
|
+
import * as path from 'path';
|
|
2
|
+
|
|
3
|
+
function getAllFlags(args, flag) {
|
|
4
|
+
const values = [];
|
|
5
|
+
for (let i = 0; i < args.length; i++) {
|
|
6
|
+
if (args[i] === flag && i + 1 < args.length) {
|
|
7
|
+
values.push(args[i + 1]);
|
|
8
|
+
i++;
|
|
9
|
+
}
|
|
10
|
+
}
|
|
11
|
+
return values;
|
|
12
|
+
}
|
|
13
|
+
function hasFlag(args, ...flags) {
|
|
14
|
+
return flags.some((f) => args.includes(f));
|
|
15
|
+
}
|
|
16
|
+
function positionalArgs(args) {
|
|
17
|
+
const result = [];
|
|
18
|
+
for (let i = 0; i < args.length; i++) {
|
|
19
|
+
if (args[i].startsWith("--")) {
|
|
20
|
+
if (i + 1 < args.length && !args[i + 1].startsWith("--")) {
|
|
21
|
+
i++;
|
|
22
|
+
}
|
|
23
|
+
continue;
|
|
24
|
+
}
|
|
25
|
+
result.push(args[i]);
|
|
26
|
+
}
|
|
27
|
+
return result;
|
|
28
|
+
}
|
|
29
|
+
function parsePorts(args) {
|
|
30
|
+
const portStrs = getAllFlags(args, "--port");
|
|
31
|
+
if (portStrs.length === 0) return [];
|
|
32
|
+
const ports = [];
|
|
33
|
+
for (const s of portStrs) {
|
|
34
|
+
const p = parseInt(s, 10);
|
|
35
|
+
if (isNaN(p) || p < 1 || p > 65535) {
|
|
36
|
+
console.error(`Error: invalid port '${s}' \u2014 must be 1-65535`);
|
|
37
|
+
process.exit(1);
|
|
38
|
+
}
|
|
39
|
+
ports.push(p);
|
|
40
|
+
}
|
|
41
|
+
return ports;
|
|
42
|
+
}
|
|
43
|
+
async function serviceExpose(args) {
|
|
44
|
+
const positional = positionalArgs(args);
|
|
45
|
+
const name = positional[0];
|
|
46
|
+
const ports = parsePorts(args);
|
|
47
|
+
if (!name || ports.length === 0) {
|
|
48
|
+
console.error("Usage: svamp service expose <name> --port <port> [--port <port2>]");
|
|
49
|
+
process.exit(1);
|
|
50
|
+
}
|
|
51
|
+
const { runFrpcTunnel } = await import('./frpc-Dz3UhcgJ.mjs');
|
|
52
|
+
await runFrpcTunnel(name, ports);
|
|
53
|
+
}
|
|
54
|
+
async function serviceServe(args) {
|
|
55
|
+
const positional = positionalArgs(args);
|
|
56
|
+
const name = positional[0];
|
|
57
|
+
const directory = positional[1] || ".";
|
|
58
|
+
const noListing = hasFlag(args, "--no-listing");
|
|
59
|
+
if (!name) {
|
|
60
|
+
console.error("Usage: svamp service serve <name> [directory] [--no-listing]");
|
|
61
|
+
console.error(" directory defaults to current directory");
|
|
62
|
+
process.exit(1);
|
|
63
|
+
}
|
|
64
|
+
try {
|
|
65
|
+
const resolvedDir = path.resolve(directory);
|
|
66
|
+
console.log(`Serving ${resolvedDir}`);
|
|
67
|
+
const caddyPort = 18080;
|
|
68
|
+
const { CaddyManager } = await import('./caddy-fJWXn1kE.mjs');
|
|
69
|
+
const caddy = new CaddyManager({ listenPort: caddyPort });
|
|
70
|
+
await caddy.addMount(name, resolvedDir, !noListing);
|
|
71
|
+
await caddy.start();
|
|
72
|
+
const cleanup = () => {
|
|
73
|
+
caddy.stop();
|
|
74
|
+
process.exit(0);
|
|
75
|
+
};
|
|
76
|
+
process.on("SIGINT", cleanup);
|
|
77
|
+
process.on("SIGTERM", cleanup);
|
|
78
|
+
const { runFrpcTunnel } = await import('./frpc-Dz3UhcgJ.mjs');
|
|
79
|
+
await runFrpcTunnel(name, [caddyPort]);
|
|
80
|
+
} catch (err) {
|
|
81
|
+
console.error(`Error serving directory: ${err.message}`);
|
|
82
|
+
process.exit(1);
|
|
83
|
+
}
|
|
84
|
+
}
|
|
85
|
+
async function serviceTunnel(args) {
|
|
86
|
+
await serviceExpose(args);
|
|
87
|
+
}
|
|
88
|
+
async function serviceList(args) {
|
|
89
|
+
console.log("Active tunnels are managed by the svamp daemon.");
|
|
90
|
+
console.log('Use "svamp service expose" to start a tunnel in the foreground.');
|
|
91
|
+
}
|
|
92
|
+
async function serviceDelete(args) {
|
|
93
|
+
const positional = positionalArgs(args);
|
|
94
|
+
const name = positional[0];
|
|
95
|
+
if (!name) {
|
|
96
|
+
console.error("Usage: svamp service delete <name>");
|
|
97
|
+
process.exit(1);
|
|
98
|
+
}
|
|
99
|
+
console.log(`Tunnel '${name}' can only be stopped via the daemon (tunnelStop RPC).`);
|
|
100
|
+
}
|
|
101
|
+
async function handleServiceCommand() {
|
|
102
|
+
const args = process.argv.slice(2);
|
|
103
|
+
const serviceArgs = args.slice(1);
|
|
104
|
+
const sub = serviceArgs[0];
|
|
105
|
+
if (!sub || sub === "--help" || sub === "-h") {
|
|
106
|
+
printServiceHelp();
|
|
107
|
+
return;
|
|
108
|
+
}
|
|
109
|
+
const commandArgs = serviceArgs.slice(1);
|
|
110
|
+
if (sub === "expose") {
|
|
111
|
+
await serviceExpose(commandArgs);
|
|
112
|
+
} else if (sub === "serve") {
|
|
113
|
+
await serviceServe(commandArgs);
|
|
114
|
+
} else if (sub === "tunnel") {
|
|
115
|
+
await serviceTunnel(commandArgs);
|
|
116
|
+
} else if (sub === "list" || sub === "ls") {
|
|
117
|
+
await serviceList();
|
|
118
|
+
} else if (sub === "delete" || sub === "rm") {
|
|
119
|
+
await serviceDelete(commandArgs);
|
|
120
|
+
} else {
|
|
121
|
+
console.error(`Unknown service command: ${sub}`);
|
|
122
|
+
printServiceHelp();
|
|
123
|
+
process.exit(1);
|
|
124
|
+
}
|
|
125
|
+
}
|
|
126
|
+
function printServiceHelp() {
|
|
127
|
+
console.log(`
|
|
128
|
+
svamp service \u2014 Expose local services via frpc tunnels
|
|
129
|
+
|
|
130
|
+
Usage:
|
|
131
|
+
svamp service expose <name> --port <port> [--port <port2>] Expose local ports via tunnel
|
|
132
|
+
svamp service serve <name> [directory] [--no-listing] Serve static files via tunnel
|
|
133
|
+
svamp service tunnel <name> --port <port> [--port <port2>] Alias for expose
|
|
134
|
+
svamp service list List active tunnels (daemon)
|
|
135
|
+
svamp service delete <name> Stop a tunnel (daemon)
|
|
136
|
+
|
|
137
|
+
All services are exposed via frpc tunnels to frps running in the cluster.
|
|
138
|
+
Each port gets a unique public URL at *.svc.hypha.aicell.io.
|
|
139
|
+
|
|
140
|
+
Environment variables (optional):
|
|
141
|
+
FRPS_SERVER_ADDR frps server address (default: frps-ctrl.svc.hypha.aicell.io)
|
|
142
|
+
FRPS_SERVER_PORT frps server port (default: 443, uses WSS transport)
|
|
143
|
+
FRPS_AUTH_TOKEN frps authentication token
|
|
144
|
+
FRPS_SUBDOMAIN_HOST Base domain for subdomains (default: svc.hypha.aicell.io)
|
|
145
|
+
|
|
146
|
+
Examples:
|
|
147
|
+
svamp service expose my-api --port 8000
|
|
148
|
+
svamp service expose my-api --port 8000 --port 3000
|
|
149
|
+
svamp service serve my-site ./dist
|
|
150
|
+
svamp service serve my-site
|
|
151
|
+
`.trim());
|
|
152
|
+
}
|
|
153
|
+
|
|
154
|
+
export { handleServiceCommand, serviceDelete, serviceExpose, serviceList, serviceServe, serviceTunnel };
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { spawn, execSync } from 'child_process';
|
|
2
|
-
import { mkdirSync, writeFileSync, unlinkSync, existsSync, chmodSync } from 'fs';
|
|
2
|
+
import { mkdirSync, writeFileSync, unlinkSync, existsSync, chmodSync, readFileSync } from 'fs';
|
|
3
3
|
import { join } from 'path';
|
|
4
4
|
import { homedir, platform, arch } from 'os';
|
|
5
5
|
import { randomUUID } from 'crypto';
|
|
@@ -7,8 +7,8 @@ import { randomUUID } from 'crypto';
|
|
|
7
7
|
const FRP_VERSION = "0.61.1";
|
|
8
8
|
const BIN_DIR = join(homedir(), ".svamp", "bin");
|
|
9
9
|
const FRPC_BIN = join(BIN_DIR, platform() === "win32" ? "frpc.exe" : "frpc");
|
|
10
|
-
const DEFAULT_FRPS_ADDR = "
|
|
11
|
-
const DEFAULT_FRPS_PORT =
|
|
10
|
+
const DEFAULT_FRPS_ADDR = "frps-ctrl.svc.hypha.aicell.io";
|
|
11
|
+
const DEFAULT_FRPS_PORT = 443;
|
|
12
12
|
function getFrpcDownloadUrl() {
|
|
13
13
|
const os = platform();
|
|
14
14
|
const a = arch();
|
|
@@ -80,6 +80,15 @@ async function ensureFrpc(log) {
|
|
|
80
80
|
{ stdio: "pipe" }
|
|
81
81
|
);
|
|
82
82
|
chmodSync(FRPC_BIN, 493);
|
|
83
|
+
const bin = readFileSync(FRPC_BIN);
|
|
84
|
+
const old = Buffer.from("/~!frp");
|
|
85
|
+
const patched = Buffer.from("/frpws");
|
|
86
|
+
const idx = bin.indexOf(old);
|
|
87
|
+
if (idx !== -1) {
|
|
88
|
+
patched.copy(bin, idx);
|
|
89
|
+
writeFileSync(FRPC_BIN, bin);
|
|
90
|
+
logger("Patched frpc WebSocket path: /~!frp \u2192 /frpws");
|
|
91
|
+
}
|
|
83
92
|
logger(`frpc installed at ${FRPC_BIN}`);
|
|
84
93
|
} finally {
|
|
85
94
|
try {
|
|
@@ -90,6 +99,7 @@ async function ensureFrpc(log) {
|
|
|
90
99
|
return FRPC_BIN;
|
|
91
100
|
}
|
|
92
101
|
function generateFrpcConfig(config, proxies) {
|
|
102
|
+
const useWSS = config.serverPort === 443;
|
|
93
103
|
const lines = [
|
|
94
104
|
"# Auto-generated by svamp \u2014 do not edit",
|
|
95
105
|
`serverAddr = "${config.serverAddr}"`,
|
|
@@ -99,6 +109,7 @@ function generateFrpcConfig(config, proxies) {
|
|
|
99
109
|
`auth.token = "${config.authToken}"`,
|
|
100
110
|
"",
|
|
101
111
|
"# Transport",
|
|
112
|
+
...useWSS ? ['transport.protocol = "wss"'] : [],
|
|
102
113
|
"transport.heartbeatInterval = 30",
|
|
103
114
|
"transport.heartbeatTimeout = 90",
|
|
104
115
|
"transport.poolCount = 5",
|
|
@@ -137,6 +148,7 @@ class FrpcTunnel {
|
|
|
137
148
|
log;
|
|
138
149
|
logBuffer = [];
|
|
139
150
|
maxLogLines = 200;
|
|
151
|
+
proxies = [];
|
|
140
152
|
constructor(options) {
|
|
141
153
|
this.options = options;
|
|
142
154
|
this.log = options.log || ((msg) => console.log(`[FRPC] ${msg}`));
|
|
@@ -144,7 +156,7 @@ class FrpcTunnel {
|
|
|
144
156
|
serverAddr: options.serverConfig?.serverAddr || process.env.FRPS_SERVER_ADDR || DEFAULT_FRPS_ADDR,
|
|
145
157
|
serverPort: options.serverConfig?.serverPort || parseInt(process.env.FRPS_SERVER_PORT || "", 10) || DEFAULT_FRPS_PORT,
|
|
146
158
|
authToken: options.serverConfig?.authToken || process.env.FRPS_AUTH_TOKEN || "",
|
|
147
|
-
subDomainHost: options.serverConfig?.subDomainHost || process.env.FRPS_SUBDOMAIN_HOST || "svc.hypha.
|
|
159
|
+
subDomainHost: options.serverConfig?.subDomainHost || process.env.FRPS_SUBDOMAIN_HOST || "svc.hypha.aicell.io"
|
|
148
160
|
};
|
|
149
161
|
if (!this.serverConfig.authToken) {
|
|
150
162
|
throw new Error(
|
|
@@ -170,6 +182,7 @@ class FrpcTunnel {
|
|
|
170
182
|
subdomain
|
|
171
183
|
};
|
|
172
184
|
});
|
|
185
|
+
this.proxies = proxies;
|
|
173
186
|
const configContent = generateFrpcConfig(this.serverConfig, proxies);
|
|
174
187
|
writeFileSync(this.configPath, configContent);
|
|
175
188
|
this.log(`Config written to ${this.configPath}`);
|
|
@@ -279,9 +292,9 @@ class FrpcTunnel {
|
|
|
279
292
|
getUrls() {
|
|
280
293
|
const urls = /* @__PURE__ */ new Map();
|
|
281
294
|
const base = this.serverConfig.subDomainHost || "svc.hypha.amun.ai";
|
|
282
|
-
for (const
|
|
283
|
-
const subdomain =
|
|
284
|
-
urls.set(
|
|
295
|
+
for (const proxy of this.proxies) {
|
|
296
|
+
const subdomain = proxy.subdomain || proxy.name;
|
|
297
|
+
urls.set(proxy.localPort, `https://${subdomain}.${base}`);
|
|
285
298
|
}
|
|
286
299
|
return urls;
|
|
287
300
|
}
|
package/dist/index.mjs
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
export { c as connectToHypha, d as daemonStatus, g as getHyphaServerUrl, r as registerMachineService, a as registerSessionService, s as startDaemon, b as stopDaemon } from './run-
|
|
1
|
+
export { c as connectToHypha, d as daemonStatus, g as getHyphaServerUrl, r as registerMachineService, a as registerSessionService, s as startDaemon, b as stopDaemon } from './run-CQfp9fM9.mjs';
|
|
2
2
|
import 'os';
|
|
3
3
|
import 'fs/promises';
|
|
4
4
|
import 'fs';
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
var name = "svamp-cli";
|
|
2
|
-
var version = "0.2.
|
|
2
|
+
var version = "0.2.22";
|
|
3
3
|
var description = "Svamp CLI — AI workspace daemon on Hypha Cloud";
|
|
4
4
|
var author = "Amun AI AB";
|
|
5
5
|
var license = "SEE LICENSE IN LICENSE";
|
|
@@ -19,11 +19,12 @@ var exports$1 = {
|
|
|
19
19
|
var scripts = {
|
|
20
20
|
build: "rm -rf dist && tsc --noEmit && pkgroll",
|
|
21
21
|
typecheck: "tsc --noEmit",
|
|
22
|
-
test: "npx tsx test/test-authorize.mjs && npx tsx test/test-session-helpers.mjs && npx tsx test/test-cli-routing.mjs && npx tsx test/test-security-context.mjs && npx tsx test/test-ralph-loop.mjs && npx tsx test/test-message-helpers.mjs && npx tsx test/test-agent-config.mjs && npx tsx test/test-wrap-command.mjs && npx tsx test/test-credential-staging.mjs && npx tsx test/test-output-formatters.mjs && npx tsx test/test-agent-types.mjs && npx tsx test/test-transport.mjs && npx tsx test/test-session-update-handlers.mjs && npx tsx test/test-session-scanner.mjs && npx tsx test/test-hypha-client.mjs && npx tsx test/test-hook-settings.mjs && npx tsx test/test-session-service-logic.mjs && npx tsx test/test-daemon-persistence.mjs && npx tsx test/test-detect-isolation.mjs && npx tsx test/test-machine-service-logic.mjs && npx tsx test/test-interactive-helpers.mjs && npx tsx test/test-codex-backend.mjs && npx tsx test/test-acp-backend.mjs && npx tsx test/test-acp-bridge.mjs && npx tsx test/test-hook-server.mjs && npx tsx test/test-session-commands.mjs && npx tsx test/test-interactive-console.mjs && npx tsx test/test-session-messages.mjs && npx tsx test/test-skills.mjs && npx tsx test/test-agent-grouping.mjs && npx tsx test/test-ralph-loop-integration.mjs && npx tsx test/test-ralph-loop-modes.mjs && npx tsx test/test-machine-list-directory.mjs && npx tsx test/test-service-commands.mjs && npx tsx test/test-supervisor.mjs && npx tsx test/test-clear-detection.mjs && npx tsx test/test-session-consolidation.mjs && npx tsx test/test-inbox.mjs && npx tsx test/test-session-rpc-dispatch.mjs && npx tsx test/test-sandbox-cli.mjs && npx tsx test/test-serve-manager.mjs && npx tsx test/test-
|
|
22
|
+
test: "npx tsx test/test-authorize.mjs && npx tsx test/test-session-helpers.mjs && npx tsx test/test-cli-routing.mjs && npx tsx test/test-security-context.mjs && npx tsx test/test-ralph-loop.mjs && npx tsx test/test-message-helpers.mjs && npx tsx test/test-agent-config.mjs && npx tsx test/test-wrap-command.mjs && npx tsx test/test-credential-staging.mjs && npx tsx test/test-output-formatters.mjs && npx tsx test/test-agent-types.mjs && npx tsx test/test-transport.mjs && npx tsx test/test-session-update-handlers.mjs && npx tsx test/test-session-scanner.mjs && npx tsx test/test-hypha-client.mjs && npx tsx test/test-hook-settings.mjs && npx tsx test/test-session-service-logic.mjs && npx tsx test/test-daemon-persistence.mjs && npx tsx test/test-detect-isolation.mjs && npx tsx test/test-machine-service-logic.mjs && npx tsx test/test-interactive-helpers.mjs && npx tsx test/test-codex-backend.mjs && npx tsx test/test-acp-backend.mjs && npx tsx test/test-acp-bridge.mjs && npx tsx test/test-hook-server.mjs && npx tsx test/test-session-commands.mjs && npx tsx test/test-interactive-console.mjs && npx tsx test/test-session-messages.mjs && npx tsx test/test-skills.mjs && npx tsx test/test-agent-grouping.mjs && npx tsx test/test-ralph-loop-integration.mjs && npx tsx test/test-ralph-loop-modes.mjs && npx tsx test/test-machine-list-directory.mjs && npx tsx test/test-service-commands.mjs && npx tsx test/test-supervisor.mjs && npx tsx test/test-clear-detection.mjs && npx tsx test/test-session-consolidation.mjs && npx tsx test/test-inbox.mjs && npx tsx test/test-session-rpc-dispatch.mjs && npx tsx test/test-sandbox-cli.mjs && npx tsx test/test-serve-manager.mjs && npx tsx test/test-serve-stability.mjs && npx tsx test/test-frpc-e2e.mjs --unit-only",
|
|
23
23
|
"test:hypha": "node --no-warnings test/test-hypha-service.mjs",
|
|
24
24
|
dev: "tsx src/cli.ts",
|
|
25
25
|
"dev:daemon": "tsx src/cli.ts daemon start-sync",
|
|
26
|
-
"test:e2e": "node --no-warnings test/e2e-session-tests.mjs"
|
|
26
|
+
"test:e2e": "node --no-warnings test/e2e-session-tests.mjs",
|
|
27
|
+
"test:frpc": "npx tsx test/test-frpc-e2e.mjs"
|
|
27
28
|
};
|
|
28
29
|
var dependencies = {
|
|
29
30
|
"@agentclientprotocol/sdk": "^0.14.1",
|
|
@@ -2,7 +2,7 @@ import{createRequire as _pkgrollCR}from"node:module";const require=_pkgrollCR(im
|
|
|
2
2
|
import os from 'node:os';
|
|
3
3
|
import { join, resolve } from 'node:path';
|
|
4
4
|
import { mkdirSync, writeFileSync, existsSync, unlinkSync, readFileSync, watch } from 'node:fs';
|
|
5
|
-
import { c as connectToHypha, a as registerSessionService } from './run-
|
|
5
|
+
import { c as connectToHypha, a as registerSessionService } from './run-CQfp9fM9.mjs';
|
|
6
6
|
import { createServer } from 'node:http';
|
|
7
7
|
import { spawn } from 'node:child_process';
|
|
8
8
|
import { createInterface } from 'node:readline';
|
|
@@ -1065,37 +1065,34 @@ async function registerMachineService(server, machineId, metadata, daemonState,
|
|
|
1065
1065
|
if (!handlers.supervisor) return [];
|
|
1066
1066
|
return handlers.supervisor.getLogs(params.idOrName, params.last ?? 50);
|
|
1067
1067
|
},
|
|
1068
|
-
// ── Service
|
|
1069
|
-
/** List
|
|
1068
|
+
// ── Service / Tunnel management ──────────────────────────────────
|
|
1069
|
+
/** List active tunnels (replaces the old agent-sandbox serviceList). */
|
|
1070
1070
|
serviceList: async (context) => {
|
|
1071
1071
|
authorizeRequest(context, currentMetadata.sharing, "view");
|
|
1072
|
-
|
|
1073
|
-
|
|
1074
|
-
|
|
1075
|
-
|
|
1076
|
-
|
|
1077
|
-
}
|
|
1078
|
-
},
|
|
1079
|
-
/** Get full details of a single service group (includes backends + health). */
|
|
1080
|
-
serviceGet: async (params, context) => {
|
|
1081
|
-
authorizeRequest(context, currentMetadata.sharing, "view");
|
|
1082
|
-
const { getServiceGroup } = await import('./api-BRbsyqJ4.mjs');
|
|
1083
|
-
return getServiceGroup(params.name);
|
|
1072
|
+
const tunnels = handlers.tunnels;
|
|
1073
|
+
if (!tunnels) return [];
|
|
1074
|
+
return Array.from(tunnels.entries()).map(([, tunnel]) => ({
|
|
1075
|
+
...tunnel.status
|
|
1076
|
+
}));
|
|
1084
1077
|
},
|
|
1085
|
-
/** Delete a
|
|
1078
|
+
/** Delete/stop a tunnel (replaces the old agent-sandbox serviceDelete). */
|
|
1086
1079
|
serviceDelete: async (params, context) => {
|
|
1087
1080
|
authorizeRequest(context, currentMetadata.sharing, "admin");
|
|
1088
|
-
const
|
|
1089
|
-
|
|
1081
|
+
const tunnels = handlers.tunnels;
|
|
1082
|
+
if (!tunnels) throw new Error("Tunnel management not available");
|
|
1083
|
+
const client = tunnels.get(params.name);
|
|
1084
|
+
if (!client) throw new Error(`Tunnel '${params.name}' not found`);
|
|
1085
|
+
client.destroy();
|
|
1086
|
+
tunnels.delete(params.name);
|
|
1087
|
+
return { name: params.name, stopped: true };
|
|
1090
1088
|
},
|
|
1091
|
-
// ── Tunnel management ────────────────────────────────────────────
|
|
1092
1089
|
/** Start a reverse tunnel for a service group (local/cloud machine). */
|
|
1093
1090
|
tunnelStart: async (params, context) => {
|
|
1094
1091
|
authorizeRequest(context, currentMetadata.sharing, "admin");
|
|
1095
1092
|
const tunnels = handlers.tunnels;
|
|
1096
1093
|
if (!tunnels) throw new Error("Tunnel management not available");
|
|
1097
1094
|
if (tunnels.has(params.name)) throw new Error(`Tunnel '${params.name}' already running`);
|
|
1098
|
-
const { FrpcTunnel } = await import('./frpc-
|
|
1095
|
+
const { FrpcTunnel } = await import('./frpc-Dz3UhcgJ.mjs');
|
|
1099
1096
|
const tunnel = new FrpcTunnel({
|
|
1100
1097
|
name: params.name,
|
|
1101
1098
|
ports: params.ports,
|
|
@@ -6238,7 +6235,7 @@ async function startDaemon(options) {
|
|
|
6238
6235
|
const supervisor = new ProcessSupervisor(join(SVAMP_HOME, "processes"));
|
|
6239
6236
|
await supervisor.init();
|
|
6240
6237
|
const tunnels = /* @__PURE__ */ new Map();
|
|
6241
|
-
const { ServeManager } = await import('./serveManager-
|
|
6238
|
+
const { ServeManager } = await import('./serveManager-6vRqOXK_.mjs');
|
|
6242
6239
|
const serveManager = new ServeManager(SVAMP_HOME, (msg) => logger.log(`[SERVE] ${msg}`), hyphaServerUrl);
|
|
6243
6240
|
ensureAutoInstalledSkills(logger).catch(() => {
|
|
6244
6241
|
});
|