svamp-cli 0.2.47 → 0.2.49

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.
@@ -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-JWrmpGcs.mjs');
151
+ const { connectAndGetMachine } = await import('./commands-CTQAVadm.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-JWrmpGcs.mjs');
168
+ const { resolveSessionId } = await import('./commands-CTQAVadm.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-6umeTX-K.mjs';
1
+ import { s as startDaemon, b as stopDaemon, d as daemonStatus } from './run-V2qpcN7f.mjs';
2
2
  import 'os';
3
3
  import 'fs/promises';
4
4
  import 'fs';
@@ -38,17 +38,19 @@ async function main() {
38
38
  if (daemonSubcommand === "restart") {
39
39
  try {
40
40
  await applyClaudeAuthFlags(args);
41
+ await applyDaemonShareFlag(args);
41
42
  } catch (err) {
42
43
  console.error(`svamp daemon restart: ${err.message || err}`);
43
44
  process.exit(1);
44
45
  }
45
- const { restartDaemon } = await import('./run-6umeTX-K.mjs').then(function (n) { return n.o; });
46
+ const { restartDaemon } = await import('./run-V2qpcN7f.mjs').then(function (n) { return n.u; });
46
47
  await restartDaemon();
47
48
  process.exit(0);
48
49
  }
49
50
  if (daemonSubcommand === "start") {
50
51
  try {
51
52
  await applyClaudeAuthFlags(args);
53
+ await applyDaemonShareFlag(args);
52
54
  } catch (err) {
53
55
  console.error(`svamp daemon start: ${err.message || err}`);
54
56
  process.exit(1);
@@ -277,7 +279,7 @@ async function main() {
277
279
  console.error("svamp service: Service commands are not available in sandboxed sessions.");
278
280
  process.exit(1);
279
281
  }
280
- const { handleServiceCommand } = await import('./commands-TyAIFJx-.mjs');
282
+ const { handleServiceCommand } = await import('./commands-BswZUToD.mjs');
281
283
  await handleServiceCommand();
282
284
  } else if (subcommand === "serve") {
283
285
  const { isSandboxed: isSandboxedServe } = await import('./sandboxDetect-DNTcbgWD.mjs');
@@ -285,7 +287,7 @@ async function main() {
285
287
  console.error("svamp serve: Serve commands are not available in sandboxed sessions.");
286
288
  process.exit(1);
287
289
  }
288
- const { handleServeCommand } = await import('./serveCommands-FUE8m232.mjs');
290
+ const { handleServeCommand } = await import('./serveCommands-Cj-P-FeY.mjs');
289
291
  await handleServeCommand();
290
292
  process.exit(0);
291
293
  } else if (subcommand === "process" || subcommand === "proc") {
@@ -294,7 +296,7 @@ async function main() {
294
296
  console.error("svamp process: Process commands are not available in sandboxed sessions.");
295
297
  process.exit(1);
296
298
  }
297
- const { processCommand } = await import('./commands-BJR_98XX.mjs');
299
+ const { processCommand } = await import('./commands-DmxhoO5X.mjs');
298
300
  let machineId;
299
301
  const processArgs = args.slice(1);
300
302
  const mIdx = processArgs.findIndex((a) => a === "--machine" || a === "-m");
@@ -312,7 +314,7 @@ async function main() {
312
314
  } else if (!subcommand || subcommand === "start") {
313
315
  await handleInteractiveCommand();
314
316
  } else if (subcommand === "--version" || subcommand === "-v") {
315
- const pkg = await import('./package-CNFS7wvh.mjs').catch(() => ({ default: { version: "unknown" } }));
317
+ const pkg = await import('./package-DnTJGm-n.mjs').catch(() => ({ default: { version: "unknown" } }));
316
318
  console.log(`svamp version: ${pkg.default.version}`);
317
319
  } else {
318
320
  console.error(`Unknown command: ${subcommand}`);
@@ -321,7 +323,7 @@ async function main() {
321
323
  }
322
324
  }
323
325
  async function handleInteractiveCommand() {
324
- const { runInteractive } = await import('./run-DR7E3IZL.mjs');
326
+ const { runInteractive } = await import('./run-mXTPYgtc.mjs');
325
327
  const interactiveArgs = subcommand === "start" ? args.slice(1) : args;
326
328
  let directory = process.cwd();
327
329
  let resumeSessionId;
@@ -366,7 +368,7 @@ async function handleAgentCommand() {
366
368
  return;
367
369
  }
368
370
  if (agentArgs[0] === "list") {
369
- const { KNOWN_ACP_AGENTS, KNOWN_MCP_AGENTS: KNOWN_MCP_AGENTS2 } = await import('./run-6umeTX-K.mjs').then(function (n) { return n.j; });
371
+ const { KNOWN_ACP_AGENTS, KNOWN_MCP_AGENTS: KNOWN_MCP_AGENTS2 } = await import('./run-V2qpcN7f.mjs').then(function (n) { return n.p; });
370
372
  console.log("Known agents:");
371
373
  for (const [name, config2] of Object.entries(KNOWN_ACP_AGENTS)) {
372
374
  console.log(` ${name.padEnd(12)} ${config2.command} ${config2.args.join(" ")} (ACP)`);
@@ -378,7 +380,7 @@ async function handleAgentCommand() {
378
380
  console.log('Use "svamp agent -- <command> [args]" for a custom ACP agent.');
379
381
  return;
380
382
  }
381
- const { resolveAcpAgentConfig, KNOWN_MCP_AGENTS } = await import('./run-6umeTX-K.mjs').then(function (n) { return n.j; });
383
+ const { resolveAcpAgentConfig, KNOWN_MCP_AGENTS } = await import('./run-V2qpcN7f.mjs').then(function (n) { return n.p; });
382
384
  let cwd = process.cwd();
383
385
  const filteredArgs = [];
384
386
  for (let i = 0; i < agentArgs.length; i++) {
@@ -402,12 +404,12 @@ async function handleAgentCommand() {
402
404
  console.log(`Starting ${config.agentName} agent in ${cwd}...`);
403
405
  let backend;
404
406
  if (KNOWN_MCP_AGENTS[config.agentName]) {
405
- const { CodexMcpBackend } = await import('./run-6umeTX-K.mjs').then(function (n) { return n.k; });
407
+ const { CodexMcpBackend } = await import('./run-V2qpcN7f.mjs').then(function (n) { return n.q; });
406
408
  backend = new CodexMcpBackend({ cwd, log: logFn });
407
409
  } else {
408
- const { AcpBackend } = await import('./run-6umeTX-K.mjs').then(function (n) { return n.i; });
409
- const { GeminiTransport } = await import('./run-6umeTX-K.mjs').then(function (n) { return n.G; });
410
- const { DefaultTransport } = await import('./run-6umeTX-K.mjs').then(function (n) { return n.D; });
410
+ const { AcpBackend } = await import('./run-V2qpcN7f.mjs').then(function (n) { return n.o; });
411
+ const { GeminiTransport } = await import('./run-V2qpcN7f.mjs').then(function (n) { return n.G; });
412
+ const { DefaultTransport } = await import('./run-V2qpcN7f.mjs').then(function (n) { return n.D; });
411
413
  const transportHandler = config.agentName === "gemini" ? new GeminiTransport() : new DefaultTransport(config.agentName);
412
414
  backend = new AcpBackend({
413
415
  agentName: config.agentName,
@@ -534,7 +536,7 @@ async function handleSessionCommand() {
534
536
  process.exit(1);
535
537
  }
536
538
  }
537
- const { sessionList, sessionSpawn, sessionStop, sessionInfo, sessionMessages, sessionAttach, sessionMachines, sessionSend, sessionWait, sessionShare, sessionRalphStart, sessionRalphCancel, sessionRalphStatus, sessionInboxSend, sessionInboxList, sessionInboxRead, sessionInboxReply, sessionInboxClear } = await import('./commands-JWrmpGcs.mjs');
539
+ const { sessionList, sessionSpawn, sessionStop, sessionInfo, sessionMessages, sessionAttach, sessionMachines, sessionSend, sessionWait, sessionShare, sessionRalphStart, sessionRalphCancel, sessionRalphStatus, sessionInboxSend, sessionInboxList, sessionInboxRead, sessionInboxReply, sessionInboxClear } = await import('./commands-CTQAVadm.mjs');
538
540
  const parseFlagStr = (flag, shortFlag) => {
539
541
  for (let i = 1; i < sessionArgs.length; i++) {
540
542
  if ((sessionArgs[i] === flag || shortFlag) && i + 1 < sessionArgs.length) {
@@ -594,7 +596,7 @@ async function handleSessionCommand() {
594
596
  allowDomain.push(sessionArgs[++i]);
595
597
  }
596
598
  }
597
- const { parseShareArg } = await import('./commands-JWrmpGcs.mjs');
599
+ const { parseShareArg } = await import('./commands-CTQAVadm.mjs');
598
600
  const shareEntries = share.map((s) => parseShareArg(s));
599
601
  await sessionSpawn(agent, dir, targetMachineId, {
600
602
  message,
@@ -680,7 +682,7 @@ async function handleSessionCommand() {
680
682
  console.error("Usage: svamp session approve <session-id> [request-id] [--json]");
681
683
  process.exit(1);
682
684
  }
683
- const { sessionApprove } = await import('./commands-JWrmpGcs.mjs');
685
+ const { sessionApprove } = await import('./commands-CTQAVadm.mjs');
684
686
  const approveReqId = sessionArgs[2] && !sessionArgs[2].startsWith("--") ? sessionArgs[2] : void 0;
685
687
  await sessionApprove(sessionArgs[1], approveReqId, targetMachineId, {
686
688
  json: hasFlag("--json")
@@ -690,7 +692,7 @@ async function handleSessionCommand() {
690
692
  console.error("Usage: svamp session deny <session-id> [request-id] [--json]");
691
693
  process.exit(1);
692
694
  }
693
- const { sessionDeny } = await import('./commands-JWrmpGcs.mjs');
695
+ const { sessionDeny } = await import('./commands-CTQAVadm.mjs');
694
696
  const denyReqId = sessionArgs[2] && !sessionArgs[2].startsWith("--") ? sessionArgs[2] : void 0;
695
697
  await sessionDeny(sessionArgs[1], denyReqId, targetMachineId, {
696
698
  json: hasFlag("--json")
@@ -726,7 +728,7 @@ async function handleSessionCommand() {
726
728
  console.error("Usage: svamp session set-title <title>");
727
729
  process.exit(1);
728
730
  }
729
- const { sessionSetTitle } = await import('./agentCommands-BuGwfYhd.mjs');
731
+ const { sessionSetTitle } = await import('./agentCommands-CpR_jpWk.mjs');
730
732
  await sessionSetTitle(title);
731
733
  } else if (sessionSubcommand === "set-link") {
732
734
  const url = sessionArgs[1];
@@ -735,7 +737,7 @@ async function handleSessionCommand() {
735
737
  process.exit(1);
736
738
  }
737
739
  const label = sessionArgs[2] && !sessionArgs[2].startsWith("--") ? sessionArgs[2] : void 0;
738
- const { sessionSetLink } = await import('./agentCommands-BuGwfYhd.mjs');
740
+ const { sessionSetLink } = await import('./agentCommands-CpR_jpWk.mjs');
739
741
  await sessionSetLink(url, label);
740
742
  } else if (sessionSubcommand === "notify") {
741
743
  const message = sessionArgs[1];
@@ -744,7 +746,7 @@ async function handleSessionCommand() {
744
746
  process.exit(1);
745
747
  }
746
748
  const level = parseFlagStr("--level") || "info";
747
- const { sessionNotify } = await import('./agentCommands-BuGwfYhd.mjs');
749
+ const { sessionNotify } = await import('./agentCommands-CpR_jpWk.mjs');
748
750
  await sessionNotify(message, level);
749
751
  } else if (sessionSubcommand === "broadcast") {
750
752
  const action = sessionArgs[1];
@@ -752,7 +754,7 @@ async function handleSessionCommand() {
752
754
  console.error("Usage: svamp session broadcast <action> [args...]\nActions: open-canvas <url> [label], close-canvas, toast <message>");
753
755
  process.exit(1);
754
756
  }
755
- const { sessionBroadcast } = await import('./agentCommands-BuGwfYhd.mjs');
757
+ const { sessionBroadcast } = await import('./agentCommands-CpR_jpWk.mjs');
756
758
  await sessionBroadcast(action, sessionArgs.slice(2).filter((a) => !a.startsWith("--")));
757
759
  } else if (sessionSubcommand === "inbox") {
758
760
  const inboxSubcmd = sessionArgs[1];
@@ -763,7 +765,7 @@ async function handleSessionCommand() {
763
765
  process.exit(1);
764
766
  }
765
767
  if (agentSessionId) {
766
- const { inboxSend } = await import('./agentCommands-BuGwfYhd.mjs');
768
+ const { inboxSend } = await import('./agentCommands-CpR_jpWk.mjs');
767
769
  await inboxSend(sessionArgs[2], {
768
770
  body: sessionArgs[3],
769
771
  subject: parseFlagStr("--subject"),
@@ -778,7 +780,7 @@ async function handleSessionCommand() {
778
780
  }
779
781
  } else if (inboxSubcmd === "list" || inboxSubcmd === "ls") {
780
782
  if (agentSessionId && !sessionArgs[2]) {
781
- const { inboxList } = await import('./agentCommands-BuGwfYhd.mjs');
783
+ const { inboxList } = await import('./agentCommands-CpR_jpWk.mjs');
782
784
  await inboxList({
783
785
  unread: hasFlag("--unread"),
784
786
  limit: parseFlagInt("--limit"),
@@ -800,7 +802,7 @@ async function handleSessionCommand() {
800
802
  process.exit(1);
801
803
  }
802
804
  if (agentSessionId && !sessionArgs[3]) {
803
- const { inboxList } = await import('./agentCommands-BuGwfYhd.mjs');
805
+ const { inboxList } = await import('./agentCommands-CpR_jpWk.mjs');
804
806
  await sessionInboxRead(agentSessionId, sessionArgs[2], targetMachineId);
805
807
  } else if (sessionArgs[3]) {
806
808
  await sessionInboxRead(sessionArgs[2], sessionArgs[3], targetMachineId);
@@ -810,7 +812,7 @@ async function handleSessionCommand() {
810
812
  }
811
813
  } else if (inboxSubcmd === "reply") {
812
814
  if (agentSessionId && sessionArgs[2] && sessionArgs[3] && !sessionArgs[4]) {
813
- const { inboxReply } = await import('./agentCommands-BuGwfYhd.mjs');
815
+ const { inboxReply } = await import('./agentCommands-CpR_jpWk.mjs');
814
816
  await inboxReply(sessionArgs[2], sessionArgs[3]);
815
817
  } else if (sessionArgs[2] && sessionArgs[3] && sessionArgs[4]) {
816
818
  await sessionInboxReply(sessionArgs[2], sessionArgs[3], sessionArgs[4], targetMachineId);
@@ -846,7 +848,7 @@ async function handleMachineCommand() {
846
848
  return;
847
849
  }
848
850
  if (machineSubcommand === "share") {
849
- const { machineShare } = await import('./commands-JWrmpGcs.mjs');
851
+ const { machineShare } = await import('./commands-CTQAVadm.mjs');
850
852
  let machineId;
851
853
  const shareArgs = [];
852
854
  for (let i = 1; i < machineArgs.length; i++) {
@@ -876,7 +878,7 @@ async function handleMachineCommand() {
876
878
  }
877
879
  await machineShare(machineId, { add, remove, list, configPath, showConfig });
878
880
  } else if (machineSubcommand === "exec") {
879
- const { machineExec } = await import('./commands-JWrmpGcs.mjs');
881
+ const { machineExec } = await import('./commands-CTQAVadm.mjs');
880
882
  let machineId;
881
883
  let cwd;
882
884
  const cmdParts = [];
@@ -896,7 +898,7 @@ async function handleMachineCommand() {
896
898
  }
897
899
  await machineExec(machineId, command, cwd);
898
900
  } else if (machineSubcommand === "info") {
899
- const { machineInfo } = await import('./commands-JWrmpGcs.mjs');
901
+ const { machineInfo } = await import('./commands-CTQAVadm.mjs');
900
902
  let machineId;
901
903
  for (let i = 1; i < machineArgs.length; i++) {
902
904
  if ((machineArgs[i] === "--machine" || machineArgs[i] === "-m") && i + 1 < machineArgs.length) {
@@ -916,10 +918,10 @@ async function handleMachineCommand() {
916
918
  level = machineArgs[++i];
917
919
  }
918
920
  }
919
- const { machineNotify } = await import('./agentCommands-BuGwfYhd.mjs');
921
+ const { machineNotify } = await import('./agentCommands-CpR_jpWk.mjs');
920
922
  await machineNotify(message, level);
921
923
  } else if (machineSubcommand === "ls") {
922
- const { machineLs } = await import('./commands-JWrmpGcs.mjs');
924
+ const { machineLs } = await import('./commands-CTQAVadm.mjs');
923
925
  let machineId;
924
926
  let showHidden = false;
925
927
  let path;
@@ -1366,6 +1368,11 @@ Claude auth flags (take effect on next start/restart):
1366
1368
  svamp daemon start --use-hypha-proxy
1367
1369
  svamp daemon start --use-claude-login
1368
1370
  svamp daemon start --anthropic-base-url URL --anthropic-api-key KEY
1371
+
1372
+ Machine sharing (seed at boot \u2014 equivalent to running 'svamp machine share --add'
1373
+ for each email; idempotent, never removes):
1374
+ svamp daemon start --share alice@example.com,bob@example.com
1375
+ svamp daemon start --share alice@example.com --share bob@example.com
1369
1376
  `);
1370
1377
  }
1371
1378
  async function applyClaudeAuthFlags(argv) {
@@ -1381,7 +1388,7 @@ async function applyClaudeAuthFlags(argv) {
1381
1388
  "--use-hypha-proxy, --use-claude-login, and --anthropic-base-url/--anthropic-api-key are mutually exclusive"
1382
1389
  );
1383
1390
  }
1384
- const mod = await import('./run-6umeTX-K.mjs').then(function (n) { return n.n; });
1391
+ const mod = await import('./run-V2qpcN7f.mjs').then(function (n) { return n.t; });
1385
1392
  if (hasHypha) {
1386
1393
  mod.setClaudeAuthHyphaProxy();
1387
1394
  console.log("Claude auth configured: hypha-proxy (uses HYPHA_TOKEN live at each spawn).");
@@ -1402,9 +1409,37 @@ async function applyClaudeAuthFlags(argv) {
1402
1409
  mod.setClaudeAuthCustom(baseUrl, apiKey);
1403
1410
  console.log(`Claude auth configured: custom (base URL ${baseUrl}).`);
1404
1411
  }
1412
+ const DAEMON_SHARE_ENV_KEY = "SVAMP_SHARE_EMAILS";
1413
+ async function applyDaemonShareFlag(argv) {
1414
+ const collected = [];
1415
+ for (let i = 0; i < argv.length; i++) {
1416
+ if (argv[i] === "--share" && i + 1 < argv.length) {
1417
+ const value = argv[++i];
1418
+ for (const part of value.split(",")) {
1419
+ const email = part.trim();
1420
+ if (!email) continue;
1421
+ if (!email.includes("@")) {
1422
+ throw new Error(`--share value "${email}" is not a valid email address`);
1423
+ }
1424
+ collected.push(email);
1425
+ }
1426
+ }
1427
+ }
1428
+ if (collected.length === 0) return;
1429
+ const { updateEnvFile } = await import('./run-V2qpcN7f.mjs').then(function (n) { return n.t; });
1430
+ const seen = /* @__PURE__ */ new Set();
1431
+ const deduped = collected.filter((e) => {
1432
+ const k = e.toLowerCase();
1433
+ if (seen.has(k)) return false;
1434
+ seen.add(k);
1435
+ return true;
1436
+ });
1437
+ updateEnvFile({ [DAEMON_SHARE_ENV_KEY]: deduped.join(",") });
1438
+ console.log(`Machine sharing seed updated: ${deduped.join(", ")} (will be added at next daemon start).`);
1439
+ }
1405
1440
  async function handleDaemonAuthCommand(argv) {
1406
1441
  const sub = (argv[0] || "status").toLowerCase();
1407
- const mod = await import('./run-6umeTX-K.mjs').then(function (n) { return n.n; });
1442
+ const mod = await import('./run-V2qpcN7f.mjs').then(function (n) { return n.t; });
1408
1443
  if (sub === "--help" || sub === "-h" || sub === "help") {
1409
1444
  console.log(`
1410
1445
  svamp daemon auth \u2014 Configure how Claude subprocesses authenticate
@@ -1559,7 +1594,7 @@ PERMISSION WORKFLOW (only relevant for "default" and "acceptEdits" modes):
1559
1594
  ISOLATION & SHARING OPTIONS (for spawn):
1560
1595
  --isolate Force OS-level sandbox (even without sharing)
1561
1596
  --security-context <path> Apply security context config (JSON file)
1562
- --share <email>[:<role>] Share session (repeatable). Role: view|interact|admin
1597
+ --share <email> Share session with user (repeatable). Added users have full access; the legacy :role suffix is accepted but ignored.
1563
1598
  --deny-network Block all network access
1564
1599
  --deny-read <path> Deny reading path (repeatable)
1565
1600
  --allow-write <path> Allow writing path (repeatable)
@@ -97,7 +97,7 @@ async function serviceServe(args) {
97
97
  }
98
98
  async function serviceList(_args) {
99
99
  try {
100
- const { connectAndGetMachine } = await import('./commands-JWrmpGcs.mjs');
100
+ const { connectAndGetMachine } = await import('./commands-CTQAVadm.mjs');
101
101
  const { server, machine } = await connectAndGetMachine();
102
102
  try {
103
103
  const tunnels = await machine.tunnelList({});
@@ -126,7 +126,7 @@ async function serviceDelete(args) {
126
126
  process.exit(1);
127
127
  }
128
128
  try {
129
- const { connectAndGetMachine } = await import('./commands-JWrmpGcs.mjs');
129
+ const { connectAndGetMachine } = await import('./commands-CTQAVadm.mjs');
130
130
  const { server, machine } = await connectAndGetMachine();
131
131
  try {
132
132
  await machine.tunnelStop({ name });
@@ -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-6umeTX-K.mjs';
5
+ import { n as normalizeAllowedUser, l as loadSecurityContextConfig, e as resolveSecurityContext, f as buildSecurityContextFromFlags, m as mergeSecurityContexts, c as connectToHypha, i as buildSessionShareUrl, j as buildMachineShareUrl } from './run-V2qpcN7f.mjs';
6
6
  import 'os';
7
7
  import 'fs/promises';
8
8
  import 'fs';
@@ -894,11 +894,16 @@ function createWorktree(baseDir) {
894
894
  function parseShareArg(arg) {
895
895
  const parts = arg.split(":");
896
896
  const email = parts[0];
897
- const role = parts[1] || "interact";
898
- if (!["view", "interact", "admin"].includes(role)) {
899
- throw new Error(`Invalid role "${role}" in --share ${arg}. Must be view, interact, or admin.`);
897
+ const suppliedRole = parts[1];
898
+ if (suppliedRole) {
899
+ if (!["view", "interact", "admin"].includes(suppliedRole)) {
900
+ throw new Error(`Invalid role "${suppliedRole}" in --share ${arg}. Per-user roles are deprecated; omit the :role suffix.`);
901
+ }
902
+ if (suppliedRole !== "admin") {
903
+ console.warn(`Note: per-user role "${suppliedRole}" is deprecated. Added users have full (owner-equivalent) access.`);
904
+ }
900
905
  }
901
- return { email, role };
906
+ return { email, role: "admin" };
902
907
  }
903
908
  async function sessionSpawn(agent, directory, machineId, opts) {
904
909
  const { server, machine } = await connectAndGetMachine(machineId);
@@ -909,12 +914,9 @@ async function sessionSpawn(agent, directory, machineId, opts) {
909
914
  enabled: true,
910
915
  owner: "",
911
916
  // will be auto-set by machine service from Hypha context
912
- allowedUsers: opts.share.map((s) => ({
913
- email: s.email,
914
- role: s.role || "interact",
915
- addedAt: Date.now(),
916
- addedBy: "cli"
917
- }))
917
+ allowedUsers: opts.share.map(
918
+ (s) => normalizeAllowedUser({ email: s.email, addedBy: "cli" }, "cli")
919
+ )
918
920
  };
919
921
  }
920
922
  let securityContext;
@@ -983,7 +985,7 @@ async function sessionSpawn(agent, directory, machineId, opts) {
983
985
  console.log(`Security context: ${JSON.stringify(securityContext, null, 2)}`);
984
986
  }
985
987
  if (sharing) {
986
- console.log(`Sharing with: ${sharing.allowedUsers.map((u) => `${u.email} (${u.role})`).join(", ")}`);
988
+ console.log(`Sharing with: ${sharing.allowedUsers.map((u) => u.email).join(", ")} (full access)`);
987
989
  }
988
990
  const result = await machine.spawnSession({
989
991
  directory,
@@ -1441,9 +1443,9 @@ async function sessionShare(sessionIdPartial, machineId, opts) {
1441
1443
  if (sharing.allowedUsers.length === 0) {
1442
1444
  console.log("No shared users.");
1443
1445
  } else {
1444
- console.log("Shared users:");
1446
+ console.log("Shared users (each has full access):");
1445
1447
  for (const u of sharing.allowedUsers) {
1446
- console.log(` ${u.email.padEnd(30)} ${u.role.padEnd(10)} (added ${new Date(u.addedAt).toISOString().slice(0, 10)})`);
1448
+ console.log(` ${u.email.padEnd(30)} (added ${new Date(u.addedAt).toISOString().slice(0, 10)})`);
1447
1449
  }
1448
1450
  }
1449
1451
  const secCtx = metaResult.metadata?.securityContext;
@@ -1452,10 +1454,16 @@ async function sessionShare(sessionIdPartial, machineId, opts) {
1452
1454
  Security context:`);
1453
1455
  console.log(JSON.stringify(secCtx, null, 2));
1454
1456
  }
1457
+ console.log(`
1458
+ Share link: ${buildSessionShareUrl({
1459
+ sessionId: fullId,
1460
+ workspace: server.config?.workspace,
1461
+ machineServiceId: machine.id || `${server.config?.workspace}/${server.config?.client_id}:default`
1462
+ })}`);
1455
1463
  return;
1456
1464
  }
1457
1465
  if (opts.add) {
1458
- const { email, role } = parseShareArg(opts.add);
1466
+ const { email } = parseShareArg(opts.add);
1459
1467
  const metaResult = await svc.getMetadata();
1460
1468
  let sharing = metaResult.metadata?.sharing || {
1461
1469
  enabled: true,
@@ -1466,14 +1474,15 @@ Security context:`);
1466
1474
  sharing.allowedUsers = sharing.allowedUsers.filter(
1467
1475
  (u) => u.email.toLowerCase() !== email.toLowerCase()
1468
1476
  );
1469
- sharing.allowedUsers.push({
1470
- email,
1471
- role,
1472
- addedAt: Date.now(),
1473
- addedBy: "cli"
1474
- });
1477
+ sharing.allowedUsers.push(normalizeAllowedUser({ email, addedBy: "cli" }, "cli"));
1475
1478
  await svc.updateSharing(sharing);
1476
- console.log(`Shared session ${fullId.slice(0, 8)} with ${email} (${role}).`);
1479
+ const shareUrl = buildSessionShareUrl({
1480
+ sessionId: fullId,
1481
+ workspace: server.config?.workspace,
1482
+ machineServiceId: machine.id || `${server.config?.workspace}/${server.config?.client_id}:default`
1483
+ });
1484
+ console.log(`Shared session ${fullId.slice(0, 8)} with ${email} (full access).`);
1485
+ console.log(`Share link: ${shareUrl}`);
1477
1486
  return;
1478
1487
  }
1479
1488
  if (opts.remove) {
@@ -1544,11 +1553,16 @@ async function machineShare(machineId, opts) {
1544
1553
  if (sharing.allowedUsers.length === 0) {
1545
1554
  console.log("No shared users.");
1546
1555
  } else {
1547
- console.log("Shared users:");
1556
+ console.log("Shared users (each has full machine access):");
1548
1557
  for (const u of sharing.allowedUsers) {
1549
- console.log(` ${u.email.padEnd(30)} ${u.role.padEnd(10)} (added ${new Date(u.addedAt).toISOString().slice(0, 10)})`);
1558
+ console.log(` ${u.email.padEnd(30)} (added ${new Date(u.addedAt).toISOString().slice(0, 10)})`);
1550
1559
  }
1551
1560
  }
1561
+ console.log(`
1562
+ Share link: ${buildMachineShareUrl({
1563
+ machineId: info.machineId,
1564
+ workspace: server.config?.workspace
1565
+ })}`);
1552
1566
  }
1553
1567
  const iso = info.metadata?.isolationCapabilities;
1554
1568
  if (iso) {
@@ -1584,7 +1598,7 @@ Isolation: ${iso.available.length > 0 ? iso.available.join(", ") : "none availab
1584
1598
  return;
1585
1599
  }
1586
1600
  if (opts.add) {
1587
- const { email, role } = parseShareArg(opts.add);
1601
+ const { email } = parseShareArg(opts.add);
1588
1602
  const info = await machine.getMachineInfo();
1589
1603
  let sharing = info.metadata?.sharing || {
1590
1604
  enabled: true,
@@ -1595,14 +1609,14 @@ Isolation: ${iso.available.length > 0 ? iso.available.join(", ") : "none availab
1595
1609
  sharing.allowedUsers = sharing.allowedUsers.filter(
1596
1610
  (u) => u.email.toLowerCase() !== email.toLowerCase()
1597
1611
  );
1598
- sharing.allowedUsers.push({
1599
- email,
1600
- role,
1601
- addedAt: Date.now(),
1602
- addedBy: "cli"
1603
- });
1612
+ sharing.allowedUsers.push(normalizeAllowedUser({ email, addedBy: "cli" }, "cli"));
1604
1613
  await machine.updateSharing(sharing);
1605
- console.log(`Shared machine with ${email} (${role}).`);
1614
+ const shareUrl = buildMachineShareUrl({
1615
+ machineId: info.machineId,
1616
+ workspace: server.config?.workspace
1617
+ });
1618
+ console.log(`Shared machine with ${email} (full access).`);
1619
+ console.log(`Share link: ${shareUrl}`);
1606
1620
  return;
1607
1621
  }
1608
1622
  if (opts.remove) {
@@ -1,11 +1,11 @@
1
1
  import { writeFileSync, readFileSync } from 'fs';
2
2
  import { resolve } from 'path';
3
- import { connectAndGetMachine } from './commands-JWrmpGcs.mjs';
3
+ import { connectAndGetMachine } from './commands-CTQAVadm.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-6umeTX-K.mjs';
8
+ import './run-V2qpcN7f.mjs';
9
9
  import 'os';
10
10
  import 'fs/promises';
11
11
  import 'url';
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-6umeTX-K.mjs';
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-V2qpcN7f.mjs';
2
2
  import 'os';
3
3
  import 'fs/promises';
4
4
  import 'fs';
@@ -0,0 +1,63 @@
1
+ var name = "svamp-cli";
2
+ var version = "0.2.49";
3
+ var description = "Svamp CLI — AI workspace daemon on Hypha Cloud";
4
+ var author = "Amun AI AB";
5
+ var license = "SEE LICENSE IN LICENSE";
6
+ var type = "module";
7
+ var bin = {
8
+ svamp: "./bin/svamp.mjs"
9
+ };
10
+ var files = [
11
+ "dist",
12
+ "bin"
13
+ ];
14
+ var main = "./dist/index.mjs";
15
+ var exports$1 = {
16
+ ".": "./dist/index.mjs",
17
+ "./cli": "./dist/cli.mjs"
18
+ };
19
+ var scripts = {
20
+ build: "rm -rf dist && tsc --noEmit && pkgroll",
21
+ typecheck: "tsc --noEmit",
22
+ test: "npx tsx test/test-authorize.mjs && npx tsx test/test-normalize-allowed-user.mjs && npx tsx test/test-share-url.mjs && npx tsx test/test-update-sharing-normalization.mjs && npx tsx test/test-staged-homes-sweep.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-isolation-decision.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-claude-auth.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-supervisor-lock.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
+ "test:hypha": "node --no-warnings test/test-hypha-service.mjs",
24
+ dev: "tsx src/cli.ts",
25
+ "dev:daemon": "tsx src/cli.ts daemon start-sync",
26
+ "test:e2e": "node --no-warnings test/e2e-session-tests.mjs",
27
+ "test:frpc": "npx tsx test/test-frpc-e2e.mjs"
28
+ };
29
+ var dependencies = {
30
+ "@agentclientprotocol/sdk": "^0.14.1",
31
+ "@modelcontextprotocol/sdk": "^1.25.3",
32
+ "hypha-rpc": "0.21.40",
33
+ "node-pty": "1.2.0-beta.11",
34
+ ws: "^8.18.0",
35
+ yaml: "^2.8.2",
36
+ zod: "^3.24.4"
37
+ };
38
+ var devDependencies = {
39
+ "@types/node": ">=20",
40
+ "@types/ws": "^8.5.14",
41
+ pkgroll: "^2.14.2",
42
+ tsx: "^4.20.6",
43
+ typescript: "5.9.3"
44
+ };
45
+ var packageManager = "yarn@1.22.22";
46
+ var _package = {
47
+ name: name,
48
+ version: version,
49
+ description: description,
50
+ author: author,
51
+ license: license,
52
+ type: type,
53
+ bin: bin,
54
+ files: files,
55
+ main: main,
56
+ exports: exports$1,
57
+ scripts: scripts,
58
+ dependencies: dependencies,
59
+ devDependencies: devDependencies,
60
+ packageManager: packageManager
61
+ };
62
+
63
+ export { author, bin, _package as default, dependencies, description, devDependencies, exports$1 as exports, files, license, main, name, packageManager, scripts, type, version };