svamp-cli 0.2.102 → 0.2.104

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.
@@ -2,7 +2,7 @@ import { existsSync, readFileSync } from 'node:fs';
2
2
  import { execSync } from 'node:child_process';
3
3
  import { basename, resolve, join } from 'node:path';
4
4
  import os from 'node:os';
5
- import { F as normalizeAllowedUser, G as loadSecurityContextConfig, H as resolveSecurityContext, I as buildSecurityContextFromFlags, J as mergeSecurityContexts, c as connectToHypha, K as buildSessionShareUrl, L as computeOutboundHop, M as buildMachineShareUrl } from './run-B_FyvS11.mjs';
5
+ import { F as normalizeAllowedUser, G as loadSecurityContextConfig, H as resolveSecurityContext, I as buildSecurityContextFromFlags, J as mergeSecurityContexts, c as connectToHypha, K as buildSessionShareUrl, L as computeOutboundHop, M as buildMachineShareUrl } from './run-CoaYIdw1.mjs';
6
6
  import 'os';
7
7
  import 'fs/promises';
8
8
  import 'fs';
@@ -786,7 +786,6 @@ function formatPeerLine(s) {
786
786
  }
787
787
  async function sessionWhoami(opts) {
788
788
  const currentSessionId = process.env.SVAMP_SESSION_ID;
789
- const PEER_CAP = 18;
790
789
  const { server, machines } = await connectAndGetAllMachines();
791
790
  try {
792
791
  const perMachine = await Promise.allSettled(
@@ -814,9 +813,14 @@ async function sessionWhoami(opts) {
814
813
  }
815
814
  if (opts?.json) {
816
815
  console.log(formatJson({
816
+ operator: server.config?.user?.email || gathered.find((g) => g.info?.metadata?.sharing?.owner)?.info?.metadata?.sharing?.owner || null,
817
+ workspace: server.config?.workspace || null,
817
818
  currentSessionId: currentSession?.sessionId || currentSessionId || null,
818
819
  currentMachine: current ? machineLabel(current.info) : null,
820
+ totalSessions: gathered.reduce((n, g) => n + g.sessions.length, 0),
819
821
  machines: gathered.map((g) => ({
822
+ sessionCount: g.sessions.length,
823
+ activeCount: g.sessions.filter((s) => s.active).length,
820
824
  machine: machineLabel(g.info),
821
825
  isCurrent: g === current,
822
826
  sessions: g.sessions.map((s) => ({
@@ -831,7 +835,14 @@ async function sessionWhoami(opts) {
831
835
  }));
832
836
  return;
833
837
  }
838
+ const operatorUser = server.config?.user;
839
+ const operatorEmail = operatorUser?.email || gathered.find((g) => g.info?.metadata?.sharing?.owner)?.info?.metadata?.sharing?.owner;
840
+ const workspace = server.config?.workspace;
834
841
  const lines = ["# Your environment", ""];
842
+ if (operatorEmail || workspace) {
843
+ lines.push(`Operator: ${operatorEmail || "unknown"}${workspace ? ` \xB7 workspace ${workspace}` : ""}`);
844
+ lines.push("");
845
+ }
835
846
  if (currentSession && current) {
836
847
  const m = currentSession.metadata || {};
837
848
  lines.push("## This session");
@@ -848,30 +859,30 @@ async function sessionWhoami(opts) {
848
859
  }
849
860
  lines.push("");
850
861
  const byActive = (a, b) => (b.active ? 1 : 0) - (a.active ? 1 : 0);
851
- if (current) {
852
- const peers = current.sessions.filter((s) => s.sessionId !== currentSession?.sessionId).sort(byActive);
853
- lines.push(`## Same machine \u2014 ${machineLabel(current.info)} (${peers.length} peer${peers.length === 1 ? "" : "s"})`);
854
- if (peers.length === 0) lines.push(" (no other sessions here)");
855
- const shown = opts?.all ? peers : peers.slice(0, PEER_CAP);
856
- for (const s of shown) lines.push(formatPeerLine(s));
857
- if (peers.length > shown.length) lines.push(` \u2026 +${peers.length - shown.length} more \u2014 run \`svamp session whoami --all\` to see all`);
858
- lines.push("");
859
- }
860
- const others = gathered.filter((g) => g !== current);
861
- const otherTotal = others.reduce((n, g) => n + g.sessions.length, 0);
862
- if (others.length > 0) {
863
- lines.push(`## Other machines \u2014 same user (${otherTotal} session${otherTotal === 1 ? "" : "s"})`);
864
- for (const g of others) {
865
- const ms = [...g.sessions].sort(byActive);
866
- lines.push(` \u2022 ${machineLabel(g.info)} (${ms.length}):`);
867
- if (ms.length === 0) lines.push(" (none)");
868
- const shown = opts?.all ? ms : ms.slice(0, PEER_CAP);
869
- for (const s of shown) lines.push(formatPeerLine(s));
870
- if (ms.length > shown.length) lines.push(` \u2026 +${ms.length - shown.length} more (--all)`);
862
+ const activeOf = (arr) => arr.filter((s) => s.active).length;
863
+ const grandTotal = gathered.reduce((n, g) => n + g.sessions.length, 0);
864
+ const orderedMachines = [...gathered].sort((a, b) => {
865
+ if (a === current) return -1;
866
+ if (b === current) return 1;
867
+ return b.sessions.length - a.sessions.length;
868
+ });
869
+ lines.push(`## Machines (same user) \u2014 ${grandTotal} session${grandTotal === 1 ? "" : "s"} across ${gathered.length} machine${gathered.length === 1 ? "" : "s"}`);
870
+ for (const g of orderedMachines) {
871
+ const ms = [...g.sessions].sort(byActive);
872
+ const here = g === current ? " (this machine)" : "";
873
+ lines.push(`- ${machineLabel(g.info)}${here}: ${ms.length} session${ms.length === 1 ? "" : "s"} (${activeOf(ms)} active)`);
874
+ if (opts?.all) {
875
+ const peers = g === current ? ms.filter((s) => s.sessionId !== currentSession?.sessionId) : ms;
876
+ for (const s of peers) lines.push(formatPeerLine(s));
871
877
  }
872
- lines.push("");
873
878
  }
879
+ lines.push("- List sessions: `svamp session list` (add `--active`, or `-m <machine>` for one).");
880
+ if (!opts?.all && grandTotal > 1) {
881
+ lines.push("- Or `svamp session whoami --all` to list every session inline.");
882
+ }
883
+ lines.push("");
874
884
  lines.push("## Reach a peer");
885
+ lines.push("- `svamp session list` \u2014 find a peer's id/title, then:");
875
886
  lines.push("- `svamp session info <id>` / `svamp session messages <id>` \u2014 inspect before reaching out");
876
887
  lines.push('- `svamp session send <id> "<msg>"` \u2014 drop a message into a peer\'s inbox');
877
888
  lines.push('- Reply to an inbox message: `svamp session inbox reply <message-id> "<body>"`');
@@ -2420,8 +2431,17 @@ async function sessionInboxReply(sessionIdPartial, messageId, body, machineId) {
2420
2431
  console.error(`Message ${messageId} not found in inbox.`);
2421
2432
  process.exit(1);
2422
2433
  }
2434
+ if (original.channelId && original.correlationId) {
2435
+ const rr = await machine.sessionRPC(fullId, "channelReply", { params: { channel: original.channelId, correlationId: original.correlationId, to: original.from, body } });
2436
+ if (rr?.error) {
2437
+ console.error(`Channel reply failed: ${rr.error}`);
2438
+ process.exit(1);
2439
+ }
2440
+ console.log(`Reply queued to "${original.from}" on channel ${original.channelId} (correlation ${original.correlationId}).`);
2441
+ return;
2442
+ }
2423
2443
  if (!original.fromSession) {
2424
- console.error("Cannot reply: original message has no fromSession.");
2444
+ console.error("Cannot reply: original message has no fromSession (and not a channel message).");
2425
2445
  process.exit(1);
2426
2446
  }
2427
2447
  const { randomUUID } = await import('node:crypto');
@@ -1,11 +1,11 @@
1
1
  import { writeFileSync, readFileSync } from 'fs';
2
2
  import { resolve } from 'path';
3
- import { connectAndGetMachine } from './commands-DpRXzSr9.mjs';
3
+ import { connectAndGetMachine } from './commands-o0MBJocy.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-B_FyvS11.mjs';
8
+ import './run-CoaYIdw1.mjs';
9
9
  import 'os';
10
10
  import 'fs/promises';
11
11
  import 'url';
@@ -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-B_FyvS11.mjs';
4
+ import { c as connectToHypha } from './run-CoaYIdw1.mjs';
5
5
  import { PINNED_CLAUDE_CODE_VERSION } from './pinnedClaudeCode-HydRNEt7.mjs';
6
6
  import 'os';
7
7
  import 'fs/promises';
@@ -3,14 +3,14 @@ import { mkdirSync, writeFileSync, unlinkSync, existsSync, chmodSync, readFileSy
3
3
  import { join } from 'path';
4
4
  import { homedir, platform, arch } from 'os';
5
5
  import { createHash, randomUUID } from 'crypto';
6
- import { h as getFrpsSubdomainHost, i as getFrpsServerPort, j as getFrpsServerAddr } from './run-B_FyvS11.mjs';
6
+ import { h as getFrpsSubdomainHost, i as getFrpsServerPort, j as getFrpsServerAddr } from './run-CoaYIdw1.mjs';
7
7
  import 'fs/promises';
8
8
  import 'url';
9
9
  import 'node:fs';
10
10
  import 'node:child_process';
11
11
  import 'util';
12
- import 'node:crypto';
13
12
  import 'node:path';
13
+ import 'node:crypto';
14
14
  import 'node:os';
15
15
  import 'node:events';
16
16
  import '@agentclientprotocol/sdk';
@@ -1,5 +1,5 @@
1
- import { E as resolveModel, N as describeMisconfiguration, O as buildMachineDeps } from './run-B_FyvS11.mjs';
2
- import { handleRealtimeEvent, initMachineVoiceSession } from './sideband-DYhbiCEA.mjs';
1
+ import { E as resolveModel, N as describeMisconfiguration, O as buildMachineDeps } from './run-CoaYIdw1.mjs';
2
+ import { handleRealtimeEvent, initMachineVoiceSession } from './sideband-CO0bdYO_.mjs';
3
3
  import { WebSocket } from 'ws';
4
4
  import { execSync, spawn } from 'child_process';
5
5
  import 'os';
@@ -11,8 +11,8 @@ import 'crypto';
11
11
  import 'node:fs';
12
12
  import 'node:child_process';
13
13
  import 'util';
14
- import 'node:crypto';
15
14
  import 'node:path';
15
+ import 'node:crypto';
16
16
  import 'node:os';
17
17
  import 'node:events';
18
18
  import '@agentclientprotocol/sdk';
@@ -138,8 +138,9 @@ data: ${JSON.stringify({ error: out.error })}
138
138
  const key = (req.headers.authorization || "").replace(/^Bearer\s+/i, "") || u.searchParams.get("key") || void 0;
139
139
  const message = body.message ?? u.searchParams.get("message") ?? "";
140
140
  const from = body.from ?? u.searchParams.get("from") ?? void 0;
141
+ const session = body.session ?? u.searchParams.get("session") ?? void 0;
141
142
  try {
142
- const out = await rpc.channelSend({ channel: channelId, message, from, key });
143
+ const out = await rpc.channelSend({ channel: channelId, message, from, key, session });
143
144
  json(out?.error ? 400 : 200, out);
144
145
  } catch (e) {
145
146
  json(500, { error: e?.message || String(e) });
package/dist/index.mjs CHANGED
@@ -1,4 +1,4 @@
1
- export { c as connectToHypha, a as createSessionStore, d as daemonStatus, g as getHyphaServerUrl, r as registerMachineService, s as startDaemon, b as stopDaemon } from './run-B_FyvS11.mjs';
1
+ export { c as connectToHypha, a as createSessionStore, d as daemonStatus, g as getHyphaServerUrl, r as registerMachineService, s as startDaemon, b as stopDaemon } from './run-CoaYIdw1.mjs';
2
2
  import 'os';
3
3
  import 'fs/promises';
4
4
  import 'fs';
@@ -9,8 +9,8 @@ import 'crypto';
9
9
  import 'node:fs';
10
10
  import 'node:child_process';
11
11
  import 'util';
12
- import 'node:crypto';
13
12
  import 'node:path';
13
+ import 'node:crypto';
14
14
  import 'node:os';
15
15
  import 'node:events';
16
16
  import '@agentclientprotocol/sdk';
@@ -1,5 +1,5 @@
1
1
  var name = "svamp-cli";
2
- var version = "0.2.102";
2
+ var version = "0.2.104";
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,7 +19,7 @@ var exports$1 = {
19
19
  var scripts = {
20
20
  build: "rm -rf dist bin/skills && mkdir -p bin/skills && cp -r ../../skills/artifact bin/skills/artifact && cp -r ../../skills/loop bin/skills/loop && tsc --noEmit && pkgroll",
21
21
  typecheck: "tsc --noEmit",
22
- test: "npx tsx test/test-context-window.mjs && npx tsx test/test-instance-config.mjs && 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-loop-activation.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-inbox-guard.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-session-send-query.mjs && npx tsx test/test-skills.mjs && npx tsx test/test-agent-grouping.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 && node test/test-supervisor-restart.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 && node test/pinnedClaudeCode.test.mjs && node test/fleet.test.mjs && npx tsx test/test-routine.mjs && npx tsx test/test-routine-rpc.mjs && npx tsx test/test-session-file.mjs && npx tsx test/test-channel-rpc.mjs && npx tsx test/test-wise-agent.mjs && npx tsx test/test-channel-agent.mjs && npx tsx test/test-channels-service.mjs && npx tsx test/test-channel-async-reply.mjs && npx tsx test/test-wise-agent-auth.mjs && npx tsx test/test-channel-http.mjs && npx tsx test/test-wise-voice.mjs && npx tsx test/test-wise-headless.mjs && npx tsx test/test-wise-machine.mjs",
22
+ test: "npx tsx test/test-context-window.mjs && npx tsx test/test-instance-config.mjs && 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-loop-activation.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-inbox-guard.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-session-send-query.mjs && npx tsx test/test-skills.mjs && npx tsx test/test-agent-grouping.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 && node test/test-supervisor-restart.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 && node test/pinnedClaudeCode.test.mjs && node test/fleet.test.mjs && npx tsx test/test-routine.mjs && npx tsx test/test-routine-rpc.mjs && npx tsx test/test-session-file.mjs && npx tsx test/test-channel-rpc.mjs && npx tsx test/test-wise-agent.mjs && npx tsx test/test-channel-agent.mjs && npx tsx test/test-channels-service.mjs && npx tsx test/test-channel-async-reply.mjs && npx tsx test/test-channel-binding.mjs && npx tsx test/test-wise-agent-auth.mjs && npx tsx test/test-channel-http.mjs && npx tsx test/test-wise-voice.mjs && npx tsx test/test-wise-headless.mjs && npx tsx test/test-wise-machine.mjs",
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",