@sma1lboy/rove 0.9.211 → 0.9.213

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.
Files changed (69) hide show
  1. package/dist/cli/{chunk-jr3403fm.js → chunk-03c94xqf.js} +1 -1
  2. package/dist/cli/{chunk-jkddy77a.js → chunk-1yct1p0n.js} +2 -2
  3. package/dist/cli/{chunk-pwp22zq3.js → chunk-317g68qr.js} +1 -1
  4. package/dist/cli/{chunk-mzyr470r.js → chunk-3f1ca1kr.js} +1 -1
  5. package/dist/cli/{chunk-gbmz90yt.js → chunk-3gsmy0mr.js} +1 -1
  6. package/dist/cli/chunk-3nd9fjt3.js +3 -0
  7. package/dist/cli/{chunk-9wg9snjs.js → chunk-47j1228v.js} +9 -8
  8. package/dist/cli/{chunk-mv0c5tqb.js → chunk-4a91xxgw.js} +1 -1
  9. package/dist/cli/{chunk-qtwbzz0t.js → chunk-54zebn5b.js} +1 -1
  10. package/dist/cli/{chunk-ygadamzf.js → chunk-57cqzftt.js} +2 -2
  11. package/dist/cli/{chunk-sa7yam4k.js → chunk-6f5j69rh.js} +1 -1
  12. package/dist/cli/{chunk-m2t0etdn.js → chunk-7fg0wtxp.js} +1 -1
  13. package/dist/cli/{chunk-8m6f3myf.js → chunk-7gj6kyyw.js} +1 -1
  14. package/dist/cli/{chunk-zqzjbd5x.js → chunk-7t3p38df.js} +2 -2
  15. package/dist/cli/{chunk-94k3x9s4.js → chunk-8007xx97.js} +1 -1
  16. package/dist/cli/{chunk-38n756dh.js → chunk-8709ehx1.js} +1 -1
  17. package/dist/cli/{chunk-kghvc2x8.js → chunk-8mc69wa6.js} +1 -1
  18. package/dist/cli/{chunk-x67ebsrg.js → chunk-9cctabn2.js} +1 -1
  19. package/dist/cli/{chunk-dp37sv5k.js → chunk-anjt9swx.js} +1 -1
  20. package/dist/cli/{chunk-j4kr3mn5.js → chunk-as1ghrb2.js} +1 -1
  21. package/dist/cli/{chunk-26m6m9v1.js → chunk-aw5hp1z2.js} +1 -1
  22. package/dist/cli/{chunk-kx5gzpmt.js → chunk-azpm8w85.js} +4 -4
  23. package/dist/cli/{chunk-rrt4z9at.js → chunk-b4nsqbed.js} +1 -1
  24. package/dist/cli/{chunk-gqq2yq9r.js → chunk-bd0kfaeh.js} +1 -1
  25. package/dist/cli/{chunk-bapcjjpn.js → chunk-cfmh4gze.js} +1 -1
  26. package/dist/cli/chunk-dzr295ne.js +3 -0
  27. package/dist/cli/chunk-e3tvtycw.js +2 -0
  28. package/dist/cli/{chunk-gnncrk3w.js → chunk-e7wnkqp4.js} +1 -1
  29. package/dist/cli/{chunk-r83qrttp.js → chunk-eg51a56n.js} +1 -1
  30. package/dist/cli/{chunk-1seen4k4.js → chunk-gtz69203.js} +1 -1
  31. package/dist/cli/{chunk-arj1d3vp.js → chunk-jhw0xy4z.js} +1 -1
  32. package/dist/cli/{chunk-f7n1stv7.js → chunk-jkbveh5e.js} +1 -1
  33. package/dist/cli/{chunk-r0kczw2t.js → chunk-jkhgdeg8.js} +1 -1
  34. package/dist/cli/{chunk-t8sv7x3q.js → chunk-jttp6t6w.js} +1 -1
  35. package/dist/cli/{chunk-60fmp80z.js → chunk-k5cav6bb.js} +1 -1
  36. package/dist/cli/{chunk-ktkmr7y1.js → chunk-m5x5d9ht.js} +1 -1
  37. package/dist/cli/{chunk-bzha4s5k.js → chunk-mg5rzt5n.js} +1 -1
  38. package/dist/cli/{chunk-11z0gvxp.js → chunk-mkw4xj5y.js} +2 -2
  39. package/dist/cli/{chunk-qwc3mmhj.js → chunk-nbanjs8t.js} +1 -1
  40. package/dist/cli/{chunk-z2f0y7jw.js → chunk-nm1mcpre.js} +1 -1
  41. package/dist/cli/{chunk-6cc1e9pz.js → chunk-pqf8tzav.js} +1 -1
  42. package/dist/cli/chunk-px6q0vgx.js +4 -0
  43. package/dist/cli/{chunk-fs44z8vj.js → chunk-pzv510fc.js} +3 -3
  44. package/dist/cli/{chunk-7pwzz75n.js → chunk-q61g5ywc.js} +1 -1
  45. package/dist/cli/{chunk-zq98c5ra.js → chunk-qbvt3vbq.js} +1 -1
  46. package/dist/cli/{chunk-bw6qkdac.js → chunk-rhbkwd0b.js} +1 -1
  47. package/dist/cli/{chunk-3j7j0egr.js → chunk-rpjsckx1.js} +2 -2
  48. package/dist/cli/{chunk-nxfqz3ez.js → chunk-rtdkkpn9.js} +1 -1
  49. package/dist/cli/{chunk-2d8bq2a2.js → chunk-s8kvg9d5.js} +22 -22
  50. package/dist/cli/{chunk-bhmerr46.js → chunk-sc2t1sjk.js} +1 -1
  51. package/dist/cli/{chunk-x190hqtb.js → chunk-shee1k2q.js} +1 -1
  52. package/dist/cli/{chunk-nvb8qsms.js → chunk-vymf5j1q.js} +1 -1
  53. package/dist/cli/{chunk-6xesn42r.js → chunk-w0efa7ed.js} +1 -1
  54. package/dist/cli/{chunk-t6311mnm.js → chunk-wbtyp7c3.js} +1 -1
  55. package/dist/cli/{chunk-k437p7qv.js → chunk-wh3q1m5r.js} +1 -1
  56. package/dist/cli/{chunk-en33n4tg.js → chunk-xke62d3w.js} +1 -1
  57. package/dist/cli/{chunk-c5jvfep2.js → chunk-xntcryqj.js} +1 -1
  58. package/dist/cli/{chunk-fbg2zn64.js → chunk-xw1vrarx.js} +1 -1
  59. package/dist/cli/{chunk-6knm7sgz.js → chunk-yazhchnz.js} +2 -2
  60. package/dist/cli/{chunk-2cnzaw88.js → chunk-zpfmkw6a.js} +1 -1
  61. package/dist/cli/{chunk-vcsxd84r.js → chunk-zpfxmcvq.js} +1 -1
  62. package/dist/cli/index.js +3 -3
  63. package/dist/cli/kobe.js +1 -1
  64. package/dist/cli/pty-host-node.mjs +142 -90
  65. package/dist/cli/rove.js +1 -1
  66. package/package.json +1 -1
  67. package/dist/cli/chunk-gqqnp8fp.js +0 -3
  68. package/dist/cli/chunk-kc13hzqs.js +0 -3
  69. package/dist/cli/chunk-zd46ghvd.js +0 -4
@@ -135,6 +135,18 @@ function defaultPtyFreezeDir(homeDir = readRoveHomeDirEnv() ?? homedir()) {
135
135
  return runtimeDataPath(homeDir, "pty-sessions");
136
136
  }
137
137
 
138
+ // ../kobe-daemon/src/daemon/process-tree.ts
139
+ import { execFile } from "node:child_process";
140
+ var TASKKILL_TIMEOUT_MS = 5000;
141
+ function taskkillProcessTree(pid) {
142
+ return new Promise((resolve) => {
143
+ execFile("taskkill", ["/T", "/F", "/PID", String(pid)], { windowsHide: true, timeout: TASKKILL_TIMEOUT_MS }, (err, stdout, stderr) => {
144
+ const detail = (stderr || stdout || err?.message || "").trim().replace(/\s+/g, " ");
145
+ resolve(err ? `taskkill /T /F /PID ${pid} did not complete: ${detail}` : `taskkill /T /F /PID ${pid}: ${detail}`);
146
+ });
147
+ });
148
+ }
149
+
138
150
  // ../kobe-daemon/src/daemon/pty-driver.ts
139
151
  var TERMINAL_NAME = "xterm-256color";
140
152
  function bunTerminalDriver(spawn) {
@@ -160,7 +172,7 @@ function bunTerminalDriver(spawn) {
160
172
  };
161
173
  };
162
174
  }
163
- async function nodePtyDriver(spawn) {
175
+ async function nodePtyDriver(spawn, endTree = taskkillProcessTree) {
164
176
  const spawnPty = spawn ?? (await import("node-pty")).spawn;
165
177
  return (request) => {
166
178
  const [file, ...args] = request.argv;
@@ -183,7 +195,8 @@ async function nodePtyDriver(spawn) {
183
195
  write: (data) => child.write(data),
184
196
  resize: (cols, rows) => child.resize(cols, rows),
185
197
  close: () => {},
186
- kill: () => child.kill()
198
+ kill: () => child.kill(),
199
+ endTree: () => endTree(child.pid)
187
200
  };
188
201
  };
189
202
  }
@@ -334,19 +347,6 @@ function logDaemonError(subsystem, err) {
334
347
  process.stderr.write(formatDaemonError(subsystem, err));
335
348
  }
336
349
 
337
- // ../kobe-daemon/src/daemon/handler-validators.ts
338
- function objectPayload(payload) {
339
- if (!payload || typeof payload !== "object" || Array.isArray(payload))
340
- return {};
341
- return payload;
342
- }
343
- function requireString(payload, key) {
344
- const value = payload[key];
345
- if (typeof value !== "string" || value.length === 0)
346
- throw new Error(`${key} is required`);
347
- return value;
348
- }
349
-
350
350
  // ../kobe-daemon/src/daemon/json-file.ts
351
351
  import { randomUUID } from "node:crypto";
352
352
  import { mkdir, rename, writeFile } from "node:fs/promises";
@@ -1103,6 +1103,13 @@ function signalProcessGroup(pid, signal, fallback, platform = process.platform,
1103
1103
  }
1104
1104
  var TERMINATION_GRACE_MS = 500;
1105
1105
  async function terminatePtyChild(proc, onSettled, onSignal) {
1106
+ if (proc.endTree) {
1107
+ onSignal?.(await proc.endTree());
1108
+ signalProcessGroup(proc.pid, "SIGKILL", () => proc.kill("SIGKILL"), process.platform, onSignal);
1109
+ await settledWithin(proc.exited, TERMINATION_GRACE_MS);
1110
+ onSettled();
1111
+ return;
1112
+ }
1106
1113
  signalProcessGroup(proc.pid, "SIGTERM", () => proc.kill("SIGTERM"), process.platform, onSignal);
1107
1114
  if (!await settledWithin(proc.exited, TERMINATION_GRACE_MS)) {
1108
1115
  signalProcessGroup(proc.pid, "SIGKILL", () => proc.kill("SIGKILL"), process.platform, onSignal);
@@ -1528,6 +1535,103 @@ class PtyHost {
1528
1535
  }
1529
1536
  }
1530
1537
 
1538
+ // ../kobe-daemon/src/daemon/handler-validators.ts
1539
+ function objectPayload(payload) {
1540
+ if (!payload || typeof payload !== "object" || Array.isArray(payload))
1541
+ return {};
1542
+ return payload;
1543
+ }
1544
+ function requireString(payload, key) {
1545
+ const value = payload[key];
1546
+ if (typeof value !== "string" || value.length === 0)
1547
+ throw new Error(`${key} is required`);
1548
+ return value;
1549
+ }
1550
+ function optionalBoolean(payload, key) {
1551
+ const value = payload[key];
1552
+ if (value === undefined || value === null)
1553
+ return;
1554
+ if (typeof value !== "boolean")
1555
+ throw new Error(`${key} must be a boolean`);
1556
+ return value;
1557
+ }
1558
+
1559
+ // ../kobe-daemon/src/daemon/pty-server-verbs.ts
1560
+ function dispatchPtyRequest(req, client, deps) {
1561
+ const { ptys } = deps;
1562
+ switch (req.name) {
1563
+ case "hello":
1564
+ return { protocolVersion: DAEMON_PROTOCOL_VERSION, ptyHost: true, pid: process.pid };
1565
+ case "pty.open": {
1566
+ const payload = objectPayload(req.payload);
1567
+ return ptys.open(requireString(payload, "key"), {
1568
+ cwd: requireString(payload, "cwd"),
1569
+ command: Array.isArray(payload.command) ? payload.command.filter((c) => typeof c === "string") : undefined,
1570
+ shell: typeof payload.shell === "string" ? payload.shell : undefined,
1571
+ cols: typeof payload.cols === "number" ? payload.cols : undefined,
1572
+ rows: typeof payload.rows === "number" ? payload.rows : undefined,
1573
+ defaultColors: parseTerminalDefaultColors(payload.defaultColors) ?? undefined
1574
+ }, client, (frame) => deps.writeFrame(client, frame), typeof payload.sinceOffset === "number" ? payload.sinceOffset : undefined, typeof payload.sincePid === "number" ? payload.sincePid : undefined);
1575
+ }
1576
+ case "pty.write": {
1577
+ const payload = objectPayload(req.payload);
1578
+ ptys.write(requireString(payload, "key"), typeof payload.data === "string" ? payload.data : "");
1579
+ return {};
1580
+ }
1581
+ case "pty.resize": {
1582
+ const payload = objectPayload(req.payload);
1583
+ ptys.resize(requireString(payload, "key"), typeof payload.cols === "number" ? payload.cols : 80, typeof payload.rows === "number" ? payload.rows : 24);
1584
+ return {};
1585
+ }
1586
+ case "pty.kill": {
1587
+ const payload = objectPayload(req.payload);
1588
+ const key = requireString(payload, "key");
1589
+ if ("expectedGeneration" in payload)
1590
+ return ptys.killIfGeneration(key, requireString(payload, "expectedGeneration"));
1591
+ if (optionalBoolean(payload, "wait") === true) {
1592
+ return ptys.kill(key).then(() => ({ accepted: true, ended: true }), (err) => {
1593
+ logDaemonError("pty-kill", err);
1594
+ return { accepted: true, ended: false };
1595
+ });
1596
+ }
1597
+ ptys.kill(key).catch((err) => logDaemonError("pty-kill", err));
1598
+ return { accepted: true };
1599
+ }
1600
+ case "pty.rename": {
1601
+ const payload = objectPayload(req.payload);
1602
+ return { renamed: ptys.rename(requireString(payload, "from"), requireString(payload, "to")) };
1603
+ }
1604
+ case "pty.detach":
1605
+ {
1606
+ const payload = objectPayload(req.payload);
1607
+ ptys.detach(requireString(payload, "key"), client, payload.parked === true, typeof payload.parkedScreenBytes === "number" ? payload.parkedScreenBytes : 0);
1608
+ }
1609
+ return {};
1610
+ case "pty.list":
1611
+ return {
1612
+ pid: process.pid,
1613
+ rssBytes: process.memoryUsage().rss,
1614
+ sessions: ptys.list(),
1615
+ stats: ptys.stats(),
1616
+ ...deps.version ? { version: deps.version } : {}
1617
+ };
1618
+ case "pty.peek": {
1619
+ const payload = objectPayload(req.payload);
1620
+ return ptys.peek(requireString(payload, "key"), typeof payload.sinceOffset === "number" ? payload.sinceOffset : undefined);
1621
+ }
1622
+ case "pty.warm": {
1623
+ const payload = objectPayload(req.payload);
1624
+ ptys.warm(requireString(payload, "cwd"), typeof payload.shell === "string" ? payload.shell : undefined, typeof payload.cols === "number" ? payload.cols : undefined, typeof payload.rows === "number" ? payload.rows : undefined);
1625
+ return {};
1626
+ }
1627
+ case "daemon.stop":
1628
+ deps.requestStop();
1629
+ return {};
1630
+ default:
1631
+ throw new Error(`unknown pty-host request: ${req.name}`);
1632
+ }
1633
+ }
1634
+
1531
1635
  // ../kobe-daemon/src/daemon/socket-guard.ts
1532
1636
  async function listenOnUnixSocket(server, socketPath) {
1533
1637
  await new Promise((resolve, reject) => {
@@ -1695,74 +1799,15 @@ async function startPtyHostServer(options = {}) {
1695
1799
  await api.close().catch((err) => logDaemonError("pty-host-shutdown", err));
1696
1800
  options.onStop?.();
1697
1801
  }
1698
- function dispatch(req, client) {
1699
- switch (req.name) {
1700
- case "hello":
1701
- return { protocolVersion: DAEMON_PROTOCOL_VERSION, ptyHost: true, pid: process.pid };
1702
- case "pty.open": {
1703
- const payload = objectPayload(req.payload);
1704
- return ptys.open(requireString(payload, "key"), {
1705
- cwd: requireString(payload, "cwd"),
1706
- command: Array.isArray(payload.command) ? payload.command.filter((c) => typeof c === "string") : undefined,
1707
- shell: typeof payload.shell === "string" ? payload.shell : undefined,
1708
- cols: typeof payload.cols === "number" ? payload.cols : undefined,
1709
- rows: typeof payload.rows === "number" ? payload.rows : undefined,
1710
- defaultColors: parseTerminalDefaultColors(payload.defaultColors) ?? undefined
1711
- }, client, (frame) => writeFrame(client, frame), typeof payload.sinceOffset === "number" ? payload.sinceOffset : undefined, typeof payload.sincePid === "number" ? payload.sincePid : undefined);
1712
- }
1713
- case "pty.write": {
1714
- const payload = objectPayload(req.payload);
1715
- ptys.write(requireString(payload, "key"), typeof payload.data === "string" ? payload.data : "");
1716
- return {};
1717
- }
1718
- case "pty.resize": {
1719
- const payload = objectPayload(req.payload);
1720
- ptys.resize(requireString(payload, "key"), typeof payload.cols === "number" ? payload.cols : 80, typeof payload.rows === "number" ? payload.rows : 24);
1721
- return {};
1722
- }
1723
- case "pty.kill": {
1724
- const payload = objectPayload(req.payload);
1725
- const key = requireString(payload, "key");
1726
- if ("expectedGeneration" in payload)
1727
- return ptys.killIfGeneration(key, requireString(payload, "expectedGeneration"));
1728
- ptys.kill(key).catch((err) => logDaemonError("pty-kill", err));
1729
- return { accepted: true };
1730
- }
1731
- case "pty.rename": {
1732
- const payload = objectPayload(req.payload);
1733
- return { renamed: ptys.rename(requireString(payload, "from"), requireString(payload, "to")) };
1734
- }
1735
- case "pty.detach":
1736
- {
1737
- const payload = objectPayload(req.payload);
1738
- ptys.detach(requireString(payload, "key"), client, payload.parked === true, typeof payload.parkedScreenBytes === "number" ? payload.parkedScreenBytes : 0);
1739
- }
1740
- return {};
1741
- case "pty.list":
1742
- return {
1743
- pid: process.pid,
1744
- rssBytes: process.memoryUsage().rss,
1745
- sessions: ptys.list(),
1746
- stats: ptys.stats(),
1747
- ...options.version ? { version: options.version } : {}
1748
- };
1749
- case "pty.peek": {
1750
- const payload = objectPayload(req.payload);
1751
- return ptys.peek(requireString(payload, "key"), typeof payload.sinceOffset === "number" ? payload.sinceOffset : undefined);
1752
- }
1753
- case "pty.warm": {
1754
- const payload = objectPayload(req.payload);
1755
- ptys.warm(requireString(payload, "cwd"), typeof payload.shell === "string" ? payload.shell : undefined, typeof payload.cols === "number" ? payload.cols : undefined, typeof payload.rows === "number" ? payload.rows : undefined);
1756
- return {};
1757
- }
1758
- case "daemon.stop":
1759
- wipeFreezeOnStop = true;
1760
- setTimeout(() => void stop(), 0).unref();
1761
- return {};
1762
- default:
1763
- throw new Error(`unknown pty-host request: ${req.name}`);
1764
- }
1765
- }
1802
+ const verbDeps = {
1803
+ ptys,
1804
+ writeFrame,
1805
+ requestStop: () => {
1806
+ wipeFreezeOnStop = true;
1807
+ setTimeout(() => void stop(), 0).unref();
1808
+ },
1809
+ ...options.version ? { version: options.version } : {}
1810
+ };
1766
1811
  function handleLine(client, line) {
1767
1812
  if (line.trim().length > 0) {
1768
1813
  let frame = null;
@@ -1775,15 +1820,22 @@ async function startPtyHostServer(options = {}) {
1775
1820
  if (frame.type !== "request") {
1776
1821
  writeFrame(client, { type: "response", id: "parse-error", error: { message: "requests only" } });
1777
1822
  } else {
1823
+ const req = frame;
1824
+ const reply = (payload) => writeFrame(client, { type: "response", id: req.id, name: req.name, payload });
1825
+ const fail = (err) => writeFrame(client, {
1826
+ type: "response",
1827
+ id: req.id,
1828
+ name: req.name,
1829
+ error: { message: err instanceof Error ? err.message : String(err) }
1830
+ });
1778
1831
  try {
1779
- writeFrame(client, { type: "response", id: frame.id, name: frame.name, payload: dispatch(frame, client) });
1832
+ const payload = dispatchPtyRequest(req, client, verbDeps);
1833
+ if (payload instanceof Promise)
1834
+ payload.then(reply, fail);
1835
+ else
1836
+ reply(payload);
1780
1837
  } catch (err) {
1781
- writeFrame(client, {
1782
- type: "response",
1783
- id: frame.id,
1784
- name: frame.name,
1785
- error: { message: err instanceof Error ? err.message : String(err) }
1786
- });
1838
+ fail(err);
1787
1839
  }
1788
1840
  }
1789
1841
  }
package/dist/cli/rove.js CHANGED
@@ -1,5 +1,5 @@
1
1
  #!/usr/bin/env node
2
- import{join as z1}from"node:path";import{createInterface as $1}from"node:readline/promises";import{pathToFileURL as J1}from"node:url";import{spawnSync as j}from"node:child_process";import{constants as m,accessSync as u}from"node:fs";import{homedir as l}from"node:os";import{basename as t,delimiter as o,dirname as r,join as Y}from"node:path";import{fileURLToPath as O}from"node:url";var g={$schema:"https://json.schemastore.org/package.json",name:"@sma1lboy/rove",version:"0.9.211",description:"Rove — the agent multiplexer for your terminal. Run coding agents on parallel tasks with isolated worktrees and persistent sessions.",keywords:["terminal","tui","cli","multiplexer","ai-agents","coding-agent","ai-coding-assistant","agentic-ai","parallel-agents","git-worktree","claude-code","codex","llm","developer-tools"],type:"module",packageManager:"bun@1.3.13",bin:{kobe:"dist/cli/kobe.js",rove:"dist/cli/rove.js"},files:["dist/cli","dist/completions","dist/web-ui","dist/skills","dist/*.wav","README.md","LICENSE"],publishConfig:{access:"public"},repository:{type:"git",url:"git+https://github.com/Sma1lboy/rove.git"},homepage:"https://rove.run",bugs:{url:"https://github.com/Sma1lboy/rove/issues"},engines:{bun:">=1.3.11"},scripts:{dev:"ROVE_DEV=1 bun --conditions=browser ./src/cli/rove.ts","dev:kobe":"KOBE_DEV=1 bun --conditions=browser ./src/cli/kobe.ts","dev:mock":"KOBE_DEV=1 bun ./src/tui-react/mock/host.tsx","dev:sandbox":"bun run scripts/dev-sandbox.ts run","dev:sandbox:reset":"bun run scripts/dev-sandbox.ts reset",build:"bun run scripts/build.ts",compile:"bun run scripts/compile.ts",typecheck:"tsc --noEmit","check-i18n":"bun run scripts/check-i18n.ts",test:"bun run test:fast && bun run test:socket","perf:golden":"bun scripts/perf-golden.ts","pty:soak":"bun scripts/pty-soak.ts","test:fast":"vitest run --passWithNoTests --minWorkers=1 --maxWorkers=8","test:socket":"KOBE_INCLUDE_SOCKET=1 vitest run test/daemon --pool forks --minWorkers=1 --maxWorkers=4 --passWithNoTests","test:socket:coverage":"KOBE_INCLUDE_SOCKET=1 KOBE_COVERAGE_DAEMON=1 vitest run test/daemon --coverage --pool forks --minWorkers=1 --maxWorkers=4 --passWithNoTests","test:behavior":"KOBE_INCLUDE_BEHAVIOR=1 vitest run test/behavior --pool forks --minWorkers=1 --maxWorkers=1 --retry=2 --passWithNoTests","test:render":"bun scripts/render-track.mjs",coverage:"vitest run --coverage --passWithNoTests",bench:"vitest bench --run",lint:"biome check .",knip:"knip-bun",postinstall:"bun run scripts/check-preview-deps.ts || true",prepublishOnly:"bun run typecheck && bun run build","plugin-sandbox":"bun run scripts/plugin-sandbox.ts"},"//":"biome.json + bunfig.toml live at the monorepo root since they apply repo-wide; bun.lock also lives at root (workspace-shared).",dependencies:{"@ansi-tools/parser":"^1.0.15","@opentui/core":"0.4.3","@opentui/react":"0.4.3","@xterm/addon-serialize":"^0.14.0","@xterm/addon-unicode11":"^0.9.0","@xterm/headless":"^6.0.0","node-pty":"^1.1.0",react:"^19.2.8","smol-toml":"^1.7.1",ws:"^8.18.0"},devDependencies:{"@biomejs/biome":"1.9.4","@sma1lboy/kobe-daemon":"0.7.19","@tsconfig/bun":"1.0.10","@types/bun":"1.3.14","@types/node":"25.6.2","@types/react":"^19.2.0","@vitest/coverage-v8":"2.1.9",knip:"^6.14.2","react-devtools-core":"^7.0.1",typescript:"5.8.2",vitest:"2.1.9"},trustedDependencies:[]};var C="rove",V="kobe";var T=V;var k=C;var d="ROVE_INVOKED_AS";function F(W=process.env){return W[d]===k?k:T}var x="ROVE_BUN",i="ROVE_NO_BUN_BOOTSTRAP",B="ROVE_SKIP_BUN_CHECK",G=g.engines.bun.match(/\d+\.\d+\.\d+/)?.[0]??"0.0.0",A=(W)=>{try{return u(W,m.X_OK),!0}catch{return!1}},a=(W)=>W==="win32"?"bun.exe":"bun",n=(W)=>{let b=j(W,["--version"],{encoding:"utf8",timeout:5000});if(b.error||b.status!==0)return null;return b.stdout?.split(`
2
+ import{join as z1}from"node:path";import{createInterface as $1}from"node:readline/promises";import{pathToFileURL as J1}from"node:url";import{spawnSync as j}from"node:child_process";import{constants as m,accessSync as u}from"node:fs";import{homedir as l}from"node:os";import{basename as t,delimiter as o,dirname as r,join as Y}from"node:path";import{fileURLToPath as O}from"node:url";var g={$schema:"https://json.schemastore.org/package.json",name:"@sma1lboy/rove",version:"0.9.213",description:"Rove — the agent multiplexer for your terminal. Run coding agents on parallel tasks with isolated worktrees and persistent sessions.",keywords:["terminal","tui","cli","multiplexer","ai-agents","coding-agent","ai-coding-assistant","agentic-ai","parallel-agents","git-worktree","claude-code","codex","llm","developer-tools"],type:"module",packageManager:"bun@1.3.13",bin:{kobe:"dist/cli/kobe.js",rove:"dist/cli/rove.js"},files:["dist/cli","dist/completions","dist/web-ui","dist/skills","dist/*.wav","README.md","LICENSE"],publishConfig:{access:"public"},repository:{type:"git",url:"git+https://github.com/Sma1lboy/rove.git"},homepage:"https://rove.run",bugs:{url:"https://github.com/Sma1lboy/rove/issues"},engines:{bun:">=1.3.11"},scripts:{dev:"ROVE_DEV=1 bun --conditions=browser ./src/cli/rove.ts","dev:kobe":"KOBE_DEV=1 bun --conditions=browser ./src/cli/kobe.ts","dev:mock":"KOBE_DEV=1 bun ./src/tui-react/mock/host.tsx","dev:sandbox":"bun run scripts/dev-sandbox.ts run","dev:sandbox:reset":"bun run scripts/dev-sandbox.ts reset",build:"bun run scripts/build.ts",compile:"bun run scripts/compile.ts",typecheck:"tsc --noEmit","check-i18n":"bun run scripts/check-i18n.ts",test:"bun run test:fast && bun run test:socket","perf:golden":"bun scripts/perf-golden.ts","pty:soak":"bun scripts/pty-soak.ts","test:fast":"vitest run --passWithNoTests --minWorkers=1 --maxWorkers=8","test:socket":"KOBE_INCLUDE_SOCKET=1 vitest run test/daemon --pool forks --minWorkers=1 --maxWorkers=4 --passWithNoTests","test:socket:coverage":"KOBE_INCLUDE_SOCKET=1 KOBE_COVERAGE_DAEMON=1 vitest run test/daemon --coverage --pool forks --minWorkers=1 --maxWorkers=4 --passWithNoTests","test:behavior":"KOBE_INCLUDE_BEHAVIOR=1 vitest run test/behavior --pool forks --minWorkers=1 --maxWorkers=1 --retry=2 --passWithNoTests","test:render":"bun scripts/render-track.mjs",coverage:"vitest run --coverage --passWithNoTests",bench:"vitest bench --run",lint:"biome check .",knip:"knip-bun",postinstall:"bun run scripts/check-preview-deps.ts || true",prepublishOnly:"bun run typecheck && bun run build","plugin-sandbox":"bun run scripts/plugin-sandbox.ts"},"//":"biome.json + bunfig.toml live at the monorepo root since they apply repo-wide; bun.lock also lives at root (workspace-shared).",dependencies:{"@ansi-tools/parser":"^1.0.15","@opentui/core":"0.4.3","@opentui/react":"0.4.3","@xterm/addon-serialize":"^0.14.0","@xterm/addon-unicode11":"^0.9.0","@xterm/headless":"^6.0.0","node-pty":"^1.1.0",react:"^19.2.8","smol-toml":"^1.7.1",ws:"^8.18.0"},devDependencies:{"@biomejs/biome":"1.9.4","@sma1lboy/kobe-daemon":"0.7.19","@tsconfig/bun":"1.0.10","@types/bun":"1.3.14","@types/node":"25.6.2","@types/react":"^19.2.0","@vitest/coverage-v8":"2.1.9",knip:"^6.14.2","react-devtools-core":"^7.0.1",typescript:"5.8.2",vitest:"2.1.9"},trustedDependencies:[]};var C="rove",V="kobe";var T=V;var k=C;var d="ROVE_INVOKED_AS";function F(W=process.env){return W[d]===k?k:T}var x="ROVE_BUN",i="ROVE_NO_BUN_BOOTSTRAP",B="ROVE_SKIP_BUN_CHECK",G=g.engines.bun.match(/\d+\.\d+\.\d+/)?.[0]??"0.0.0",A=(W)=>{try{return u(W,m.X_OK),!0}catch{return!1}},a=(W)=>W==="win32"?"bun.exe":"bun",n=(W)=>{let b=j(W,["--version"],{encoding:"utf8",timeout:5000});if(b.error||b.status!==0)return null;return b.stdout?.split(`
3
3
  `)[0]?.trim()??""};function L(W){return W.trim().match(/^v?(\d+\.\d+\.\d+)/)?.[1]??null}function K(W,b=G){let z=L(W),Q=L(b);if(!z||!Q)return!0;let J=z.split(".").map(Number),$=Q.split(".").map(Number);for(let X=0;X<3;X++){let H=J[X]??0,q=$[X]??0;if(H!==q)return H>q}return!0}function P(W=process.env){return W[B]==="1"}function h(W={}){let b=W.env??process.env,z=W.platform??process.platform,Q=W.home??b.HOME??b.USERPROFILE??l(),J=a(z),$=[],X=b[x]?.trim();if(X)$.push(X);for(let U of(b.PATH??b.Path??"").split(o))if(U)$.push(Y(U,J));let H=b.BUN_INSTALL?.trim();if(H)$.push(Y(H,"bin",J));if(Q)$.push(Y(Q,".bun","bin",J));let q=W.launcherDir;if(q)$.push(Y(q,"..","..","node_modules","bun","bin",J)),$.push(Y(q,"..","..","..","bun","bin",J));return $}function e(W={}){let b=W.isExecutable??A;return h(W).find((z)=>b(z))??null}function D(W={}){let b=W.isExecutable??A,z=W.bunVersionOf??n;if(P(W.env??process.env))return{bun:e(W),stale:null,unusable:null};let Q=null,J=null;for(let $ of h(W)){if(!b($))continue;let X=z($);if(X===null){J??=$;continue}if(K(X))return{bun:$,stale:Q,unusable:J};Q??={path:$,version:L(X)??X}}return{bun:null,stale:Q,unusable:J}}function p(W){return r(O(W))}function I(W){return t(O(W)).replace(/\.[cm]?[jt]s$/,"")}function W1(W=process.platform){return W==="win32"?["powershell","-NoProfile","-Command","irm bun.sh/install.ps1 | iex"]:["bash","-c","curl -fsSL https://bun.sh/install | bash"]}function R(W=F(),b=process.platform){let z=b==="win32"?'powershell -c "irm bun.sh/install.ps1 | iex"':"curl -fsSL https://bun.sh/install | bash";return[`${W}: Rove runs on the Bun runtime, and no Bun was found on this machine.`,"","Install Bun, then run this command again:",` ${z}`," npm install -g bun # any platform, if you already have npm","","Or install Bun and Rove together in one step:"," curl -fsSL https://rove.run/install.sh | sh","",`Already have Bun somewhere unusual? Point Rove at it: ${x}=/path/to/bun`,""].join(`
4
4
  `)}function w(W,b,z=F()){return[`${z}: this machine's Bun is too old for Rove — found ${b} at ${W}, need ${G} or newer.`,"","Rove's terminals are built on Bun's PTY API. An older Bun ignores it silently,","so every terminal and engine tab would open empty and stay empty.","","Upgrade Bun, then run this command again:"," bun upgrade # Bun installed itself (~/.bun)"," brew upgrade bun # Homebrew"," npm install -g bun@latest # npm-managed Bun","",`Have a newer Bun elsewhere? Point Rove at it: ${x}=/path/to/bun`,`Run on this one anyway (unsupported, terminals will be blank): ${B}=1`,""].join(`
5
5
  `)}function y(W,b=F()){return[`${b}: the Bun at ${W} could not be run — \`${W} --version\` failed or never returned.`,"","Rove skipped it rather than starting through it, which would hang or fail","with a message from that binary instead of this one.","","Reinstall Bun, then run this command again:"," curl -fsSL https://bun.sh/install | bash","",`Have a working Bun elsewhere? Point Rove at it: ${x}=/path/to/bun`,""].join(`
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "$schema": "https://json.schemastore.org/package.json",
3
3
  "name": "@sma1lboy/rove",
4
- "version": "0.9.211",
4
+ "version": "0.9.213",
5
5
  "description": "Rove — the agent multiplexer for your terminal. Run coding agents on parallel tasks with isolated worktrees and persistent sessions.",
6
6
  "keywords": [
7
7
  "terminal",