svamp-cli 0.1.34 → 0.1.35

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.
@@ -233,7 +233,7 @@ async function runLocalMode(opts) {
233
233
  log(`[local] Spawning: claude ${args.join(" ")}`);
234
234
  const claudeBin = findClaudeBinary();
235
235
  if (!claudeBin) {
236
- console.error("Claude Code CLI not found. Install with: npm install -g @anthropic-ai/claude-code");
236
+ process.stderr.write("Claude Code CLI not found. Install with: npm install -g @anthropic-ai/claude-code\n");
237
237
  return { type: "exit", code: 1 };
238
238
  }
239
239
  process.stdin.pause();
@@ -293,14 +293,15 @@ async function runRemoteMode(opts) {
293
293
  } catch {
294
294
  }
295
295
  if (!claudeBin || !existsSync(claudeBin)) {
296
- console.error("Claude Code CLI not found.");
296
+ process.stderr.write("Claude Code CLI not found.\n");
297
297
  return "exit";
298
298
  }
299
- console.log("\n\x1B[90m" + "\u2550".repeat(50) + "\x1B[0m");
300
- console.log("\x1B[36m Remote mode\x1B[0m \u2014 processing message from web app");
301
- console.log("\x1B[90m Press Space Space to switch to local mode\x1B[0m");
302
- console.log("\x1B[90m Press Ctrl-C Ctrl-C to exit\x1B[0m");
303
- console.log("\x1B[90m" + "\u2550".repeat(50) + "\x1B[0m\n");
299
+ const print = (s) => process.stderr.write(s + "\n");
300
+ print("\n\x1B[90m" + "\u2550".repeat(50) + "\x1B[0m");
301
+ print("\x1B[36m Remote mode\x1B[0m \u2014 processing message from web app");
302
+ print("\x1B[90m Press Space Space to switch to local mode\x1B[0m");
303
+ print("\x1B[90m Press Ctrl-C Ctrl-C to exit\x1B[0m");
304
+ print("\x1B[90m" + "\u2550".repeat(50) + "\x1B[0m\n");
304
305
  let exitReason = null;
305
306
  let lastSpace = 0;
306
307
  let lastCtrlC = 0;
@@ -385,7 +386,7 @@ async function runRemoteMode(opts) {
385
386
  continue;
386
387
  }
387
388
  if (!exitReason && !abortController.signal.aborted) {
388
- console.log("\n\x1B[90m Agent idle. Waiting for next message...\x1B[0m");
389
+ process.stderr.write("\n\x1B[90m Agent idle. Waiting for next message...\x1B[0m\n");
389
390
  }
390
391
  }
391
392
  } finally {
@@ -667,17 +668,11 @@ async function runInteractive(options) {
667
668
  const token = process.env.HYPHA_TOKEN;
668
669
  if (serverUrl && token) {
669
670
  try {
670
- const origLog = console.log;
671
- const origWarn = console.warn;
672
- console.log = () => {
673
- };
674
- console.warn = () => {
675
- };
671
+ suppressHyphaLogs();
676
672
  server = await connectToHypha({ serverUrl, token, name: "svamp-interactive" });
677
- console.log = origLog;
678
- console.warn = origWarn;
679
673
  log("Connected to Hypha");
680
674
  } catch (err) {
675
+ restoreConsoleLogs();
681
676
  console.error(`\x1B[33mNote:\x1B[0m Could not connect to Hypha (${err.message}). Running in offline mode.`);
682
677
  }
683
678
  } else {
@@ -720,6 +715,7 @@ async function runInteractive(options) {
720
715
  lifecycleState: "running",
721
716
  flavor: "claude"
722
717
  };
718
+ let currentMode = "local";
723
719
  if (server) {
724
720
  const callbacks = {
725
721
  onUserMessage: (content, _meta) => {
@@ -756,6 +752,7 @@ async function runInteractive(options) {
756
752
  );
757
753
  log(`Session service registered: svamp-session-${sessionId}`);
758
754
  } catch (err) {
755
+ restoreConsoleLogs();
759
756
  console.error(`\x1B[33mNote:\x1B[0m Could not register session on Hypha (${err.message}).`);
760
757
  }
761
758
  }
@@ -783,6 +780,7 @@ async function runInteractive(options) {
783
780
  }
784
781
  const cleanup = async () => {
785
782
  log("Cleaning up...");
783
+ restoreConsoleLogs();
786
784
  if (keepAliveInterval) clearInterval(keepAliveInterval);
787
785
  if (sessionService) {
788
786
  sessionService.sendSessionEnd();
@@ -813,12 +811,14 @@ async function runInteractive(options) {
813
811
  if (options.resumeSessionId) ; else if (options.continueSession) {
814
812
  claudeArgs.push("--continue");
815
813
  }
814
+ restoreConsoleLogs();
816
815
  console.log(`\x1B[36mSvamp interactive mode\x1B[0m`);
817
816
  if (server && sessionService) {
818
817
  console.log(`\x1B[90mSession synced to Hypha \u2014 visible in the web app\x1B[0m`);
819
818
  console.log(`\x1B[90mSession ID: ${sessionId.slice(0, 8)}\x1B[0m`);
820
819
  }
821
820
  console.log("");
821
+ if (server) suppressHyphaLogs();
822
822
  try {
823
823
  const exitCode = await loop({
824
824
  cwd,
@@ -829,7 +829,11 @@ async function runInteractive(options) {
829
829
  log,
830
830
  onModeChange: (mode) => {
831
831
  log(`Mode changed: ${mode}`);
832
+ currentMode = mode;
832
833
  if (sessionService) {
834
+ sessionService.updateAgentState({
835
+ controlledByUser: mode === "local"
836
+ });
833
837
  sessionService.updateMetadata({ ...metadata, lifecycleState: "running" });
834
838
  sessionService.sendKeepAlive(false, mode);
835
839
  }
@@ -893,5 +897,32 @@ function readMachineId() {
893
897
  return null;
894
898
  }
895
899
  }
900
+ let _origLog = null;
901
+ let _origWarn = null;
902
+ let _origInfo = null;
903
+ function suppressHyphaLogs() {
904
+ if (_origLog) return;
905
+ _origLog = console.log;
906
+ _origWarn = console.warn;
907
+ _origInfo = console.info;
908
+ console.log = (...args) => {
909
+ if (DEBUG) _origLog.call(console, "[hypha-log]", ...args);
910
+ };
911
+ console.warn = (...args) => {
912
+ if (DEBUG) _origWarn.call(console, "[hypha-warn]", ...args);
913
+ };
914
+ console.info = (...args) => {
915
+ if (DEBUG) _origInfo.call(console, "[hypha-info]", ...args);
916
+ };
917
+ }
918
+ function restoreConsoleLogs() {
919
+ if (!_origLog) return;
920
+ console.log = _origLog;
921
+ console.warn = _origWarn;
922
+ console.info = _origInfo;
923
+ _origLog = null;
924
+ _origWarn = null;
925
+ _origInfo = null;
926
+ }
896
927
 
897
928
  export { runInteractive };