@bivy/bivy 0.2.0-staging.29 → 0.2.0-staging.31

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/bin/bivy.mjs CHANGED
@@ -1527,7 +1527,7 @@ async function cmdExec(args = []) {
1527
1527
  function cmdCompletions(args = []) {
1528
1528
  const shell = (args[0] || "").toLowerCase();
1529
1529
  const commands = [
1530
- "run", "sessions", "ls", "resume", "promote", "nodes", "agents", "agents:install", "shim", "takeover", "token", "exec",
1530
+ "run", "sessions", "ls", "resume", "promote", "rename", "nodes", "agents", "agents:install", "shim", "takeover", "token", "exec",
1531
1531
  "send", "kill", "setup", "start", "stop", "restart", "status", "doctor", "logs", "login",
1532
1532
  "update", "update:log", "open", "service", "secrets", "voice", "link", "relay:setup",
1533
1533
  "github:connect", "github:app-create", "github:app-connect", "github:app-sync", "prune", "uninstall", "help", "version",
@@ -1908,6 +1908,49 @@ async function cmdPromote(args = []) {
1908
1908
  }
1909
1909
  }
1910
1910
 
1911
+ // `bivy rename <name>` — rename THIS node. Runs against the local daemon, which
1912
+ // persists the name to .bivy/node.json and live-updates relay/work-queue routing
1913
+ // (no restart needed). If the name collides on your account the control plane
1914
+ // auto-adjusts it for uniqueness, so we re-read the node info afterward to show
1915
+ // the name that actually stuck. Alias: node:rename.
1916
+ async function cmdRename(args = []) {
1917
+ if (args.includes("-h") || args.includes("--help")) {
1918
+ console.log('Usage: bivy rename <name>\n\nRename this node. Takes effect immediately (no restart). If the name is already used by another node on your account, it is auto-adjusted to stay unique.');
1919
+ return;
1920
+ }
1921
+ if (!(await ensureDeps())) process.exit(1);
1922
+ // Node names may contain spaces, so join all positional (non-flag) args rather
1923
+ // than taking only the first. The daemon trims/collapses whitespace and caps
1924
+ // the length; we just forward the raw text.
1925
+ const name = args.filter((a) => !a.startsWith("-")).join(" ").trim();
1926
+ if (!name) { console.error(c.red("Usage: bivy rename <name>")); process.exit(1); return; }
1927
+
1928
+ const config = loadConfig();
1929
+ if (!(await ensureNodeRunning(config))) { console.error(c.red(`Could not start the Bivy node at ${url(config)}.`)); process.exit(1); return; }
1930
+ let token;
1931
+ try { token = await localDeviceToken(config); }
1932
+ catch (error) { console.error(c.red(error?.message || String(error))); process.exit(1); return; }
1933
+
1934
+ const base = url(config);
1935
+ const prev = await fetchJson(base, "/api/node/info", token).then((d) => d?.name).catch(() => undefined);
1936
+ const res = await fetch(`${base}/api/node/name`, {
1937
+ method: "POST",
1938
+ headers: { authorization: `Bearer ${token}`, "content-type": "application/json" },
1939
+ body: JSON.stringify({ name }),
1940
+ });
1941
+ if (!res.ok) {
1942
+ const data = await res.json().catch(() => ({}));
1943
+ console.error(c.red(`Rename failed (${res.status}): ${data.error || "unknown error"}`));
1944
+ process.exit(1);
1945
+ return;
1946
+ }
1947
+ const data = await res.json().catch(() => ({}));
1948
+ const applied = data.name || name;
1949
+ if (prev && prev !== applied) console.log(c.green(`Renamed node: ${c.dim(prev)} → ${applied}`));
1950
+ else console.log(c.green(`Node name set to "${applied}".`));
1951
+ if (applied !== name) console.log(c.dim(`(Adjusted from "${name}" to stay unique on your account.)`));
1952
+ }
1953
+
1911
1954
  // `bivy send <id> "<message>"` — send a prompt to an existing session and stream
1912
1955
  // the reply. Thin wrapper over the headless exec client with --session.
1913
1956
  // Deliberately does NOT intercept -h/--help (see cmdExec above) — the message
@@ -3968,6 +4011,7 @@ ${c.bold("bivy")} — Bivy node CLI
3968
4011
  ${c.cyan("bivy run <agent> --node <name>")} Start the session on another registered node
3969
4012
  ${c.cyan("bivy run <agent> --clone [remote]")} Start in a fresh clone (current repo, or a given remote)
3970
4013
  ${c.cyan("bivy run <agent> --workspace <dir>")} Start in an existing directory (default: current repo, else the configured workspace)
4014
+ ${c.cyan("bivy rename <name>")} Rename this node (takes effect immediately, no restart)
3971
4015
  ${c.cyan("bivy nodes")} List/add/remove other nodes (add <name> <url> --token <t>)
3972
4016
  ${c.cyan("bivy agents")} List the supported agents and which are installed (--json)
3973
4017
  ${c.cyan("bivy shim install <agent>")} Make interactive '<agent>' launch its native TUI in a Bivy PTY (remote-visible)
@@ -4051,6 +4095,10 @@ An agent's own --help passes through, e.g. 'bivy run claude --help'.`);
4051
4095
  case "promote":
4052
4096
  await cmdPromote(args);
4053
4097
  break;
4098
+ case "rename":
4099
+ case "node:rename":
4100
+ await cmdRename(args);
4101
+ break;
4054
4102
  case "nodes":
4055
4103
  await cmdNodes(args);
4056
4104
  break;
package/dist/server.js CHANGED
@@ -2589,6 +2589,7 @@ const RELAY_COMMANDS = {
2589
2589
  agent: meta?.runtimeId ?? s.agent,
2590
2590
  agentName: meta?.agentName ?? s.agentName,
2591
2591
  source: rec?.source ?? meta?.source,
2592
+ forkedFrom: rec?.forkedFrom ?? meta?.forkedFrom,
2592
2593
  branch: rec?.worktree?.branch ?? meta?.branch,
2593
2594
  sandbox: rec?.sandbox ?? normalizeSandboxTier(meta?.sandbox),
2594
2595
  prUrl: rec?.prUrl ?? meta?.prUrl,
@@ -5358,6 +5359,11 @@ async function standUpFork(opts) {
5358
5359
  const record = plan.kind === "resume"
5359
5360
  ? await createSession(cwd, plan.sessionFile, { runtimeId: targetRuntimeId, source: bundle.record.source, makeActive: false })
5360
5361
  : await createSession(cwd, undefined, { runtimeId: targetRuntimeId, source: bundle.record.source, makeActive: false });
5362
+ // Mark the new session as a fork of its source, so the run card can show
5363
+ // "Forked from …" and the lineage survives a reload (persisted below). Just
5364
+ // the parent's session id — an identifier, not content, so it's safe to
5365
+ // carry into metadata the same way branch/prUrl already are.
5366
+ record.forkedFrom = bundle.record.sourceSessionId;
5361
5367
  // Attach the reconstructed worktree to the record. createSession only
5362
5368
  // populates record.worktree when it provisions one itself (fresh repo session)
5363
5369
  // or restores it from stored metadata (resume) — neither happens for a fork,
@@ -5711,6 +5717,7 @@ function persistSessionMetadata(record, status = sessionStatus(record)) {
5711
5717
  name: record.session.getName(),
5712
5718
  workspace: record.workspace,
5713
5719
  source: record.source ?? "manual",
5720
+ forkedFrom: record.forkedFrom,
5714
5721
  runtimeId: record.runtimeId,
5715
5722
  sandbox: record.sandbox,
5716
5723
  agentName: getRuntime(record.runtimeId).displayName,
@@ -8429,6 +8436,7 @@ app.get("/api/sessions", async (_req, res, next) => {
8429
8436
  agent: meta?.runtimeId ?? s.agent,
8430
8437
  agentName: meta?.agentName ?? s.agentName,
8431
8438
  source: rec?.source ?? meta?.source,
8439
+ forkedFrom: rec?.forkedFrom ?? meta?.forkedFrom,
8432
8440
  branch: rec?.worktree?.branch ?? meta?.branch,
8433
8441
  prUrl: rec?.prUrl ?? meta?.prUrl,
8434
8442
  prs: rec?.prs ?? meta?.prs,
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@bivy/bivy",
3
- "version": "0.2.0-staging.29",
3
+ "version": "0.2.0-staging.31",
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.",