@bivy/bivy 0.7.0-staging.103 → 0.7.0-staging.105

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.
@@ -116,14 +116,27 @@ function claudeCodeInfo() {
116
116
  },
117
117
  };
118
118
  }
119
+ // Memoized CLI probes. `commandAvailable`/`resolveCommandPath`/`probeHelpText`
120
+ // each shell out with a BLOCKING spawnSync, and the runtime catalog that calls
121
+ // them (cliAgentInfo → prefersAcp/acpSupportedByBinary) is rebuilt often — on
122
+ // every advertise and every runtimes.list send. Re-probing per build stalled the
123
+ // event loop for seconds at a time (a synchronous spawn storm). A CLI's presence
124
+ // is effectively constant for the daemon's run, so cache per command for the
125
+ // process lifetime and clear on install (invalidateCliProbeCache).
126
+ const COMMAND_AVAILABLE_CACHE = new Map();
119
127
  function commandAvailable(command) {
120
128
  if (!command.trim())
121
129
  return false;
130
+ const cached = COMMAND_AVAILABLE_CACHE.get(command);
131
+ if (cached !== undefined)
132
+ return cached;
122
133
  const result = spawnSync(process.platform === "win32" ? "where" : "command", process.platform === "win32" ? [command] : ["-v", command], {
123
134
  shell: process.platform !== "win32",
124
135
  stdio: "ignore",
125
136
  });
126
- return result.status === 0;
137
+ const available = result.status === 0;
138
+ COMMAND_AVAILABLE_CACHE.set(command, available);
139
+ return available;
127
140
  }
128
141
  function genericCliInfo() {
129
142
  const options = processRuntimeFromEnv();
@@ -869,17 +882,23 @@ function cliThinkingConfig(id) {
869
882
  * Used to key the help-probe cache: caching by the bare NAME would keep serving a
870
883
  * stale answer after the binary behind that name changed (a CLI upgraded or
871
884
  * installed while the daemon is running, or a different PATH entry winning).
885
+ * Memoized per command (see COMMAND_AVAILABLE_CACHE) — it spawnSyncs, and is hit
886
+ * on every catalog build.
872
887
  */
888
+ const COMMAND_PATH_CACHE = new Map();
873
889
  function resolveCommandPath(command) {
874
890
  if (!command.trim())
875
891
  return null;
892
+ const cached = COMMAND_PATH_CACHE.get(command);
893
+ if (cached !== undefined)
894
+ return cached;
876
895
  const res = spawnSync(process.platform === "win32" ? "where" : "command", process.platform === "win32" ? [command] : ["-v", command], {
877
896
  shell: process.platform !== "win32",
878
897
  encoding: "utf8",
879
898
  });
880
- if (res.status !== 0)
881
- return null;
882
- return (res.stdout ?? "").split(/\r?\n/)[0]?.trim() || null;
899
+ const resolved = res.status !== 0 ? null : ((res.stdout ?? "").split(/\r?\n/)[0]?.trim() || null);
900
+ COMMAND_PATH_CACHE.set(command, resolved);
901
+ return resolved;
883
902
  }
884
903
  const HELP_PROBE_CACHE = new Map();
885
904
  function probeHelpText(command) {
@@ -898,6 +917,19 @@ function probeHelpText(command) {
898
917
  HELP_PROBE_CACHE.set(key, text);
899
918
  return text;
900
919
  }
920
+ /**
921
+ * Drop every memoized CLI probe (availability, resolved path, --help text). These
922
+ * probes shell out with a blocking spawnSync and are cached for the process
923
+ * lifetime to keep the frequently-rebuilt runtime catalog off the event loop, so a
924
+ * CLI installed/updated mid-run wouldn't otherwise be noticed until a restart.
925
+ * Call this right after Bivy installs a runtime so the next catalog build re-probes
926
+ * and reflects the new binary immediately.
927
+ */
928
+ export function invalidateCliProbeCache() {
929
+ COMMAND_AVAILABLE_CACHE.clear();
930
+ COMMAND_PATH_CACHE.clear();
931
+ HELP_PROBE_CACHE.clear();
932
+ }
901
933
  // A resume template mixes launch flags (`-p`, `--force`) with the resume-specific
902
934
  // token(s) (`--resume`, `threads continue`, `-s`, `--restore`, …). Only the latter
903
935
  // evidence resume support, so we match on those — otherwise a shared launch flag
package/dist/server.js CHANGED
@@ -8,7 +8,7 @@ import { randomUUID, randomBytes, timingSafeEqual, createHash } from "node:crypt
8
8
  import { fileURLToPath } from "node:url";
9
9
  import express from "express";
10
10
  import { WebSocketServer, WebSocket } from "ws";
11
- import { listRuntimes, catalogRuntimes, cliInstallSpec, isCliAgentId } from "./runtime/index.js";
11
+ import { listRuntimes, catalogRuntimes, cliInstallSpec, invalidateCliProbeCache, isCliAgentId } from "./runtime/index.js";
12
12
  import { createRunPolicy } from "./policy/run-policy.js";
13
13
  import { DEFAULT_BACKOFF } from "./policy/ruleset.js";
14
14
  import { SessionRerouteController } from "./policy/session-reroute.js";
@@ -3217,6 +3217,9 @@ const RELAY_COMMANDS = {
3217
3217
  const before = runtimeList().find((runtime) => runtime.id === spec.id);
3218
3218
  if (before?.status !== "available")
3219
3219
  await runInstallCommand(spec);
3220
+ // The just-installed binary changes what the CLI probes would report, so drop
3221
+ // their (process-lifetime) cache and let the catalog below re-probe it.
3222
+ invalidateCliProbeCache();
3220
3223
  const activeAgent = active?.runtimeId ?? defaultRuntimeId;
3221
3224
  const runtimes = runtimeList(activeAgent);
3222
3225
  relay?.sendEvent({ type: "runtime.install.done", id: spec.id, runtimes });
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@bivy/bivy",
3
- "version": "0.7.0-staging.103",
3
+ "version": "0.7.0-staging.105",
4
4
  "type": "module",
5
5
  "license": "FSL-1.1-ALv2",
6
6
  "description": "Run coding agents on machines you own. Source-available, self-hostable agent workspace.",