@sma1lboy/rove 0.9.244 → 0.9.246
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/dist/cli/{chunk-smqze3sm.js → chunk-0xrdy726.js} +1 -1
- package/dist/cli/{chunk-kdee8kgm.js → chunk-1wt1esef.js} +1 -1
- package/dist/cli/{chunk-2zmcwmn8.js → chunk-1zxheb0c.js} +1 -1
- package/dist/cli/{chunk-hh66tk5v.js → chunk-2whnrjrr.js} +1 -1
- package/dist/cli/{chunk-9b6pdnxp.js → chunk-33dt8jkh.js} +2 -2
- package/dist/cli/{chunk-t7e76hpj.js → chunk-4ayqnz4j.js} +1 -1
- package/dist/cli/{chunk-tje9nhmd.js → chunk-66cew8sb.js} +1 -1
- package/dist/cli/{chunk-fwbk82nn.js → chunk-6nk7h22s.js} +1 -1
- package/dist/cli/{chunk-ysqaq4bk.js → chunk-74v6dm9n.js} +1 -1
- package/dist/cli/{chunk-195nhfna.js → chunk-7za7dj9z.js} +1 -1
- package/dist/cli/{chunk-dk03kqd4.js → chunk-84h387qb.js} +1 -1
- package/dist/cli/{chunk-y76adyep.js → chunk-8manew0x.js} +7 -7
- package/dist/cli/{chunk-r12sxzvg.js → chunk-8ztzk7tg.js} +1 -1
- package/dist/cli/{chunk-j5mvw8cb.js → chunk-9m5g6t5k.js} +1 -1
- package/dist/cli/{chunk-s633vsc6.js → chunk-9nm43nw4.js} +1 -1
- package/dist/cli/{chunk-8tcqt5p4.js → chunk-9xq1r084.js} +1 -1
- package/dist/cli/{chunk-5a0582t8.js → chunk-aq04rqv7.js} +1 -1
- package/dist/cli/{chunk-qy2exha8.js → chunk-c5rb17k9.js} +1 -1
- package/dist/cli/{chunk-8vtdcnre.js → chunk-ca3bfxd9.js} +1 -1
- package/dist/cli/{chunk-e6x95bc9.js → chunk-cgt8wmd7.js} +1 -1
- package/dist/cli/{chunk-g203qezy.js → chunk-efq3j5v8.js} +1 -1
- package/dist/cli/{chunk-0v82hp1z.js → chunk-fcfh9xsq.js} +1 -1
- package/dist/cli/{chunk-8fhx8ys9.js → chunk-g2kb61q5.js} +2 -2
- package/dist/cli/{chunk-qgfgjhgb.js → chunk-g8eh5jd4.js} +1 -1
- package/dist/cli/{chunk-bx5myh57.js → chunk-gxdfyn42.js} +1 -1
- package/dist/cli/{chunk-th5caet8.js → chunk-jj460xsw.js} +1 -1
- package/dist/cli/chunk-k67vbszb.js +3 -0
- package/dist/cli/{chunk-2pvck9jx.js → chunk-kxpfm6mb.js} +3 -3
- package/dist/cli/{chunk-jva9qfcn.js → chunk-ncxfyfb5.js} +1 -1
- package/dist/cli/{chunk-20r85tnf.js → chunk-pb4cc1vy.js} +2 -2
- package/dist/cli/chunk-q0av0rvg.js +9 -0
- package/dist/cli/{chunk-1erp3qxx.js → chunk-q4qxhh4d.js} +1 -1
- package/dist/cli/{chunk-p1htk7za.js → chunk-qdmzsx2z.js} +1 -1
- package/dist/cli/{chunk-w26thyva.js → chunk-qgck9n3y.js} +1 -1
- package/dist/cli/{chunk-p7wsz1kf.js → chunk-t6zw81pp.js} +1 -1
- package/dist/cli/{chunk-kr9bvxaz.js → chunk-taf0014q.js} +2 -2
- package/dist/cli/chunk-tkbdgh2k.js +3 -0
- package/dist/cli/{chunk-xyzar5xd.js → chunk-wpvxfzb9.js} +1 -1
- package/dist/cli/chunk-xvdk2b8e.js +18 -0
- package/dist/cli/index.js +3 -3
- package/dist/cli/pty-host-node.mjs +215 -4
- package/dist/cli/rove.js +1 -1
- package/dist/skills/rove/SKILL.md +1 -1
- package/dist/skills/rove/references/api-flags.md +9 -8
- package/package.json +2 -2
- package/dist/cli/chunk-0mj358p5.js +0 -3
- package/dist/cli/chunk-9vy0csmk.js +0 -9
- package/dist/cli/chunk-cv9rjs9p.js +0 -3
- package/dist/cli/chunk-rfgwj1m7.js +0 -18
package/dist/cli/index.js
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
#!/usr/bin/env bun
|
|
2
2
|
// @bun
|
|
3
|
-
import{matchPathGlob}from"./chunk-kg11c1py.js";import{switchFlag}from"./chunk-zsfyj36g.js";import{connectIfRunning}from"./chunk-96cjpssp.js";import"./chunk-9w5g7frx.js";import"./chunk-gvrtrvnz.js";import{expandTilde}from"./chunk-ag3txfg2.js";import{errorMessage}from"./chunk-2brn8e1y.js";import{BUILTIN_VENDORS,coerceVendorId,isBuiltinVendor}from"./chunk-h2m7em1e.js";import{CURRENT_VERSION}from"./chunk-
|
|
4
|
-
`),process.exit(1);let projectRoot=await projectRootFor(dir);await withDaemonOrLocal({daemon:async(client)=>{let taskId;if(projectRoot)taskId=(await client.request("task.ensureMain",{repo:projectRoot})).task.id;else taskId=(await client.request("task.openDir",{dir})).taskId;await client.request("task.setActive",{taskId})},local:async(orch)=>{let task=projectRoot?await orch.ensureMainTask(projectRoot):await orch.openDirectoryTask({dir}),{writeLastActiveTaskId}=await import("./chunk-ktzbg4jg.js");writeLastActiveTaskId(String(task.id))}});let{publishRoveTerminalTitle}=await import("./chunk-t8v9rpdx.js");publishRoveTerminalTitle();let{launchTui}=await import("./chunk-
|
|
3
|
+
import{matchPathGlob}from"./chunk-kg11c1py.js";import{switchFlag}from"./chunk-zsfyj36g.js";import{connectIfRunning}from"./chunk-96cjpssp.js";import"./chunk-9w5g7frx.js";import"./chunk-gvrtrvnz.js";import{expandTilde}from"./chunk-ag3txfg2.js";import{errorMessage}from"./chunk-2brn8e1y.js";import{BUILTIN_VENDORS,coerceVendorId,isBuiltinVendor}from"./chunk-h2m7em1e.js";import{CURRENT_VERSION}from"./chunk-6nk7h22s.js";import{rejectionReason}from"./chunk-3342qzve.js";import"./chunk-a7kq09ke.js";import"./chunk-prqeddy7.js";import{ROVE_PRODUCT_NAME}from"./chunk-zt7wfnva.js";import"./chunk-yt15y085.js";import"./chunk-adkva3ep.js";import"./chunk-0422g8ac.js";import"./chunk-hq9tbzqa.js";import{pathSyntax}from"./chunk-pn5ygqn6.js";import"./chunk-npwzmmv9.js";import"./chunk-b39sdtt0.js";import"./chunk-nc46gddg.js";import{__require}from"./chunk-wqfp8d9w.js";import{resolve as resolve2}from"path";function debugEnabled(env){return env.ROVE_DEBUG==="1"||env.ROVE_DEBUG==="1"}function failureSubject(cliName,argv){let verb=argv[2];return verb&&!verb.startsWith("-")&&!verb.includes("/")?`${cliName} ${verb}`:cliName}function summarizeCliGitError(message,cwd){if(!/not a git repository/i.test(message))return null;return`${cwd} is not a git repository \u2014 run this inside one, or pass a repo path.`}function formatCliFailure(err,opts){let subject=failureSubject(opts.cliName,opts.argv);if(debugEnabled(opts.env))return`${subject}: ${String(err instanceof Error?err.stack??err:err)}`;let raw=errorMessage(err);return`${subject}: ${summarizeCliGitError(raw,opts.cwd)??raw}`}var DYNAMIC_COMMANDS=new Map([["completions",async(args)=>{let{runCompletionsSubcommand}=await import("./chunk-g2kb61q5.js");await runCompletionsSubcommand(args)}],["export",async(args)=>{let{runExportSubcommand}=await import("./chunk-vej49hnt.js");await runExportSubcommand(args)}],["repo",async(args)=>{let{runRepoSubcommand}=await import("./chunk-easxds8p.js");await runRepoSubcommand(args)}],["api",async(args)=>{let{runApiSubcommand}=await import("./chunk-1zxheb0c.js");await runApiSubcommand(args)}],["update",async(args)=>{let{runUpdateSubcommand}=await import("./chunk-pb4cc1vy.js");await runUpdateSubcommand(args)}],["theme",async(args)=>{let{runThemeSubcommand}=await import("./chunk-skf7y627.js");await runThemeSubcommand(args)}],["feedback",async(args)=>{let{runFeedbackSubcommand}=await import("./chunk-wpvxfzb9.js");await runFeedbackSubcommand(args)}],["daemon",async(args)=>{let{runDaemonSubcommand}=await import("./chunk-ca3bfxd9.js");await runDaemonSubcommand(args)}],["machine",async(args)=>{let{runMachineSubcommand}=await import("./chunk-p83wf4zw.js");await runMachineSubcommand(args)}],["weixin",async(args)=>{let{runChannelCli}=await import("./chunk-1wt1esef.js");await runChannelCli("weixin",args)}],["doctor",async(args)=>{let{runDoctorSubcommand}=await import("./chunk-c5rb17k9.js");await runDoctorSubcommand(args)}],["config",async(args)=>{let{runConfigSubcommand}=await import("./chunk-p18ehv9y.js");await runConfigSubcommand(args)}],["reset",async(args)=>{let{runResetSubcommand}=await import("./chunk-fcfh9xsq.js");await runResetSubcommand(args)}],["pty-host",async(args)=>{let{runPtyHostSubcommand}=await import("./chunk-tkbdgh2k.js");await runPtyHostSubcommand(args)}],["skill",async(args)=>{let{runSkillSubcommand}=await import("./chunk-kxpfm6mb.js");await runSkillSubcommand(args)}],["plugin",async(args)=>{let{runPluginSubcommand}=await import("./chunk-taf0014q.js");await runPluginSubcommand(args)}],["hook",async(args)=>{let{runHookSubcommand}=await import("./chunk-8ztzk7tg.js");await runHookSubcommand(args)}]]);import{statSync}from"fs";import{resolve}from"path";async function openLocalOrchestrator(){let{TaskIndexStore}=await import("./chunk-pe6wnsww.js"),{GitWorktreeManager}=await import("./chunk-9q1m5qz0.js"),{Orchestrator}=await import("./chunk-8pna13mr.js"),store=new TaskIndexStore;return await store.load(),new Orchestrator({store,worktrees:new GitWorktreeManager})}async function withDaemonOrLocal(bridge){let client=await connectIfRunning();if(client)try{return await bridge.daemon(client)}finally{client.close()}let orch=await openLocalOrchestrator();return bridge.local(orch)}function isPathLikeArg(arg){return arg==="."||arg===".."||arg.startsWith("./")||arg.startsWith("../")||arg.startsWith(".\\")||arg.startsWith("..\\")||pathSyntax(arg).isAbsolute(arg)||arg.startsWith("/")||arg==="~"||arg.startsWith("~/")||arg.startsWith("~\\")}async function projectRootFor(dir){let{isGitRepo,resolveRepoRoot}=await import("./chunk-ng12dprz.js"),{projectRejection}=await import("./chunk-2vgc5cyj.js"),top=resolveRepoRoot(dir);if(top!==dir)return null;return projectRejection(top,isGitRepo,"explicit")?null:top}async function runOpenDirectory(arg){let dir=resolve(process.cwd(),expandTilde(arg)),isDir=!1;try{isDir=statSync(dir).isDirectory()}catch{isDir=!1}if(!isDir)process.stderr.write(`${ROVE_PRODUCT_NAME}: "${arg}" is not a directory (resolved to ${dir}).
|
|
4
|
+
`),process.exit(1);let projectRoot=await projectRootFor(dir);await withDaemonOrLocal({daemon:async(client)=>{let taskId;if(projectRoot)taskId=(await client.request("task.ensureMain",{repo:projectRoot})).task.id;else taskId=(await client.request("task.openDir",{dir})).taskId;await client.request("task.setActive",{taskId})},local:async(orch)=>{let task=projectRoot?await orch.ensureMainTask(projectRoot):await orch.openDirectoryTask({dir}),{writeLastActiveTaskId}=await import("./chunk-ktzbg4jg.js");writeLastActiveTaskId(String(task.id))}});let{publishRoveTerminalTitle}=await import("./chunk-t8v9rpdx.js");publishRoveTerminalTitle();let{launchTui}=await import("./chunk-84h387qb.js");await launchTui()}function topLevelUsage(cliName=ROVE_PRODUCT_NAME){return[`${cliName} ${CURRENT_VERSION}`,"",`Usage: ${cliName} [command] [options]`,"","Run with no command to launch PureTUI.",`Run \`${cliName} .\` (or \`${cliName} <path>\`) to open a directory as a standalone task.`,"","Commands:"," completions <shell> Generate shell completion script (bash/zsh/fish)"," add [path] Save a repo path for the new-task picker"," remove [path] Forget a saved project (inverse of add; non-destructive)"," adopt [glob] Import existing git worktrees as tasks"," export [--csv|--json] Print the task list (json/csv/table; daemon-free)"," repo <verb> Per-repo init script + first prompt (show|set|unset)",` api <verb> Scriptable RPC surface for agents (see \`${cliName} api --help\`)`," daemon <verb> Manage the daemon (start|stop|status|restart)"," machine <verb> Other computers running Rove (add|remove|list)"," weixin <verb> Talk to Rove from WeChat (login|logout|status|allow|deny)"," doctor [--report|--fix] Diagnose daemon/PTY/engines/git; --fix walks the remedies",` config [--path] Open ${cliName}'s config file (state.json) in your editor`," reset [--hard] Stop runtimes; optionally wipe task/UI state"," theme <verb> Manage user themes (list|add|remove)",` skill <verb> Install the ${cliName} agent skill (install|status|command|print)`," plugin <verb> Install and run plugins (install|link|list|action|\u2026)"," feedback Send feedback to GitHub Discussions",` update [version|channel|list] Self-update ${cliName}, switch channel, or list versions`,"","Options:"," -v, --version Print version"," -h, --help Print this help"," --skill Print the agent skill file and exit"].join(`
|
|
5
5
|
`)}var CLI_NAME=ROVE_PRODUCT_NAME,ADD_USAGE=[`Usage: ${CLI_NAME} add [path]`,` ${CLI_NAME} add --remote --host <host> --user <user> --path <basePath> [--port N] [--key [path] | --password]`,"","Save a repo for the new-task picker. With --remote, register an SSH-backed","project whose worktrees live on <host>; engine launch over SSH is pending.",""].join(`
|
|
6
6
|
`);async function runAddSubcommand(rest){let arg=rest[0];if(arg==="--help"||arg==="-h"||arg==="help"){process.stdout.write(ADD_USAGE);return}if(arg==="--remote"){let{runAddRemote}=await import("./chunk-53cyns0f.js");await runAddRemote(rest.slice(1));return}if(arg?.startsWith("-"))process.stderr.write(`${CLI_NAME} add: unknown flag "${arg}"
|
|
7
7
|
|
|
@@ -24,4 +24,4 @@ ${ADOPT_USAGE}
|
|
|
24
24
|
pass a path glob to adopt, e.g. ${CLI_NAME} adopt '${repo}/*' --yes`);return}let matched=worktrees.filter(isMatch);if(matched.length===0){console.log(`
|
|
25
25
|
no worktrees match glob ${JSON.stringify(glob)}`);return}if(!yes){console.log(`
|
|
26
26
|
${matched.length} worktree(s) match \u2014 re-run with --yes to adopt them`);return}await adoptWorktreesInto(orch,repo,matched,vendor),console.log(`done \u2014 adopted ${matched.length} worktree(s)`)}function printTopLevelUsage(out){out.write(`${topLevelUsage()}
|
|
27
|
-
`)}var COMMANDS=new Map([["add",runAddSubcommand],["remove",runRemoveSubcommand],["adopt",runAdoptSubcommand],...DYNAMIC_COMMANDS]);async function main(){let[,,...rawArgs]=process.argv,[subcommand,...rest]=rawArgs;if(subcommand==="--version"||subcommand==="-v"||subcommand==="version"){let{CURRENT_VERSION:CURRENT_VERSION2}=await import("./chunk-
|
|
27
|
+
`)}var COMMANDS=new Map([["add",runAddSubcommand],["remove",runRemoveSubcommand],["adopt",runAdoptSubcommand],...DYNAMIC_COMMANDS]);async function main(){let[,,...rawArgs]=process.argv,[subcommand,...rest]=rawArgs;if(subcommand==="--version"||subcommand==="-v"||subcommand==="version"){let{CURRENT_VERSION:CURRENT_VERSION2}=await import("./chunk-gxdfyn42.js");console.log(`${CLI_NAME} ${CURRENT_VERSION2}`);return}if(subcommand==="--help"||subcommand==="-h"||subcommand==="help"){printTopLevelUsage(process.stdout);return}if(subcommand==="--skill"){let{runSkillSubcommand}=await import("./chunk-kxpfm6mb.js");await runSkillSubcommand(["print"]);return}let handler=subcommand!==void 0?COMMANDS.get(subcommand):void 0;if(handler){await handler(rest);return}if(subcommand!==void 0&&isPathLikeArg(subcommand)){await runOpenDirectory(subcommand);return}if(subcommand!==void 0)console.error(`${CLI_NAME}: unknown command '${subcommand}'`),printTopLevelUsage(process.stderr),process.exit(2);let{publishRoveTerminalTitle}=await import("./chunk-t8v9rpdx.js");publishRoveTerminalTitle();let{launchTui}=await import("./chunk-84h387qb.js");await launchTui()}main().catch((err)=>{console.error(formatCliFailure(err,{cliName:CLI_NAME,argv:process.argv,cwd:process.cwd(),env:process.env})),process.exit(1)});
|
|
@@ -1395,6 +1395,170 @@ function clearFrozenSessions(dir = defaultPtyFreezeDir()) {
|
|
|
1395
1395
|
} catch {}
|
|
1396
1396
|
}
|
|
1397
1397
|
|
|
1398
|
+
// ../rove-daemon/src/daemon/osc-signals.ts
|
|
1399
|
+
import { StringDecoder as StringDecoder2 } from "node:string_decoder";
|
|
1400
|
+
function createOscSignals() {
|
|
1401
|
+
return { carry: "", decoder: new StringDecoder2("utf8"), records: new Map, contexts: [] };
|
|
1402
|
+
}
|
|
1403
|
+
function freeText(raw, encodedLimit, decodedLimit) {
|
|
1404
|
+
if (raw === undefined)
|
|
1405
|
+
return;
|
|
1406
|
+
if (raw.length > encodedLimit || !/^[A-Za-z0-9+/]*={0,2}$/.test(raw) || raw.replace(/=+$/, "").length % 4 === 1)
|
|
1407
|
+
throw new Error("Invalid base64");
|
|
1408
|
+
const bytes = Buffer.from(raw, "base64");
|
|
1409
|
+
if (bytes.length > decodedLimit)
|
|
1410
|
+
throw new Error("Text exceeds limit");
|
|
1411
|
+
const text = new TextDecoder("utf-8", { fatal: true }).decode(bytes);
|
|
1412
|
+
if (/[\x00-\x1f\x7f-\x9f]/u.test(text))
|
|
1413
|
+
throw new Error("Control character");
|
|
1414
|
+
return text;
|
|
1415
|
+
}
|
|
1416
|
+
function applyProgramStatus(signals, body, now) {
|
|
1417
|
+
if (Buffer.byteLength(body) + 10 > 4096)
|
|
1418
|
+
return;
|
|
1419
|
+
const pairs = Object.create(null);
|
|
1420
|
+
for (const pair of body.split(":")) {
|
|
1421
|
+
const split = pair.indexOf("=");
|
|
1422
|
+
if (split < 1)
|
|
1423
|
+
continue;
|
|
1424
|
+
const key = pair.slice(0, split).trim();
|
|
1425
|
+
const value = pair.slice(split + 1).trim();
|
|
1426
|
+
if (key.length > 16)
|
|
1427
|
+
return;
|
|
1428
|
+
if (/^[a-z]+$/.test(key) && /^[A-Za-z0-9_.,+/=-]*$/.test(value))
|
|
1429
|
+
pairs[key] = value;
|
|
1430
|
+
}
|
|
1431
|
+
const id = pairs.id ?? "";
|
|
1432
|
+
if (pairs.id !== undefined && (id.length > 128 || id.split("/").length > 8 || !/^[A-Za-z0-9_.+-]{1,32}(\/[A-Za-z0-9_.+-]{1,32})*$/.test(id)))
|
|
1433
|
+
return;
|
|
1434
|
+
const state = pairs.state;
|
|
1435
|
+
if (!["idle", "working", "done", "blocked", "error", "clear"].includes(state ?? ""))
|
|
1436
|
+
return;
|
|
1437
|
+
let msg;
|
|
1438
|
+
let title;
|
|
1439
|
+
try {
|
|
1440
|
+
msg = freeText(pairs.msg, 2732, 2048);
|
|
1441
|
+
title = freeText(pairs.title, 256, 192);
|
|
1442
|
+
} catch {
|
|
1443
|
+
return;
|
|
1444
|
+
}
|
|
1445
|
+
if (pairs.app !== undefined && pairs.app.length > 32)
|
|
1446
|
+
return;
|
|
1447
|
+
if (state === "clear") {
|
|
1448
|
+
for (const key of signals.records.keys())
|
|
1449
|
+
if (!id || key === id || key.startsWith(`${id}/`))
|
|
1450
|
+
signals.records.delete(key);
|
|
1451
|
+
return;
|
|
1452
|
+
}
|
|
1453
|
+
if (state !== "idle" && state !== "working" && state !== "done" && state !== "blocked" && state !== "error")
|
|
1454
|
+
return;
|
|
1455
|
+
const kind = pairs.kind === "permission" || pairs.kind === "question" || pairs.kind === "auth" ? pairs.kind : undefined;
|
|
1456
|
+
const progress = pairs.progress !== undefined && /^\d{1,3}$/.test(pairs.progress) && Number(pairs.progress) <= 100 ? Number(pairs.progress) : undefined;
|
|
1457
|
+
signals.records.delete(id);
|
|
1458
|
+
signals.records.set(id, {
|
|
1459
|
+
id,
|
|
1460
|
+
state,
|
|
1461
|
+
at: now,
|
|
1462
|
+
...msg !== undefined ? { msg } : {},
|
|
1463
|
+
...title !== undefined ? { title } : {},
|
|
1464
|
+
...pairs.app && /^[A-Za-z0-9_.+-]{1,32}$/.test(pairs.app) ? { app: pairs.app } : {},
|
|
1465
|
+
...state === "blocked" && kind ? { kind } : {},
|
|
1466
|
+
...(state === "working" || state === "blocked") && progress !== undefined ? { progress } : {}
|
|
1467
|
+
});
|
|
1468
|
+
if (signals.records.size > 64) {
|
|
1469
|
+
const first = signals.records.keys().next().value;
|
|
1470
|
+
if (first !== undefined)
|
|
1471
|
+
signals.records.delete(first);
|
|
1472
|
+
}
|
|
1473
|
+
}
|
|
1474
|
+
function applyContext(signals, body) {
|
|
1475
|
+
if (Buffer.byteLength(body) > 4096 || /[\x00-\x1f\x7f]/.test(body))
|
|
1476
|
+
return;
|
|
1477
|
+
const [head = "", ...fields] = body.split(";");
|
|
1478
|
+
const split = head.indexOf("=");
|
|
1479
|
+
const operation = head.slice(0, split);
|
|
1480
|
+
const decodeContextField = (text) => text.replace(/\\x(3b|5c)/g, (_, hex) => hex === "3b" ? ";" : "\\");
|
|
1481
|
+
const id = decodeContextField(head.slice(split + 1));
|
|
1482
|
+
if (operation !== "start" && operation !== "end" || !/^[ -~]{1,64}$/.test(id))
|
|
1483
|
+
return;
|
|
1484
|
+
const index = signals.contexts.findIndex((c) => c.id === id);
|
|
1485
|
+
if (operation === "end") {
|
|
1486
|
+
if (index !== -1)
|
|
1487
|
+
signals.contexts.splice(index);
|
|
1488
|
+
return;
|
|
1489
|
+
}
|
|
1490
|
+
if (index !== -1)
|
|
1491
|
+
signals.contexts.splice(index);
|
|
1492
|
+
if (signals.contexts.length >= 32)
|
|
1493
|
+
return;
|
|
1494
|
+
const metadata = Object.create(null);
|
|
1495
|
+
for (const field of fields) {
|
|
1496
|
+
const i = field.indexOf("=");
|
|
1497
|
+
if (i > 0)
|
|
1498
|
+
metadata[field.slice(0, i)] = decodeContextField(field.slice(i + 1));
|
|
1499
|
+
}
|
|
1500
|
+
signals.contexts.push({ id, metadata });
|
|
1501
|
+
}
|
|
1502
|
+
function clearTransientStatuses(signals) {
|
|
1503
|
+
for (const [id, record] of signals.records) {
|
|
1504
|
+
if (record.state === "working" || record.state === "blocked" || record.state === "idle")
|
|
1505
|
+
signals.records.delete(id);
|
|
1506
|
+
}
|
|
1507
|
+
}
|
|
1508
|
+
function scanOscSignals(signals, bytes, now = Date.now(), onRootChange) {
|
|
1509
|
+
const text = signals.carry + signals.decoder.write(bytes);
|
|
1510
|
+
signals.carry = "";
|
|
1511
|
+
let queries = 0;
|
|
1512
|
+
for (let i = 0;i < text.length; i++) {
|
|
1513
|
+
if (text[i] !== "\x1B")
|
|
1514
|
+
continue;
|
|
1515
|
+
if (i === text.length - 1) {
|
|
1516
|
+
signals.carry = "\x1B";
|
|
1517
|
+
break;
|
|
1518
|
+
}
|
|
1519
|
+
if (text[i + 1] === "c") {
|
|
1520
|
+
const hadRoot = signals.records.has("");
|
|
1521
|
+
signals.records.clear();
|
|
1522
|
+
if (hadRoot)
|
|
1523
|
+
onRootChange?.(null);
|
|
1524
|
+
signals.contexts = [];
|
|
1525
|
+
i++;
|
|
1526
|
+
continue;
|
|
1527
|
+
}
|
|
1528
|
+
if (text[i + 1] !== "]")
|
|
1529
|
+
continue;
|
|
1530
|
+
const begin = i;
|
|
1531
|
+
i += 2;
|
|
1532
|
+
let end = i;
|
|
1533
|
+
while (end < text.length && text[end] !== "\x07" && text[end] !== "\x1B")
|
|
1534
|
+
end++;
|
|
1535
|
+
if (end === text.length || text[end] === "\x1B" && end + 1 === text.length) {
|
|
1536
|
+
if (text.length - begin <= 8192)
|
|
1537
|
+
signals.carry = text.slice(begin);
|
|
1538
|
+
break;
|
|
1539
|
+
}
|
|
1540
|
+
if (text[end] === "\x1B" && text[end + 1] !== "\\") {
|
|
1541
|
+
i = end - 1;
|
|
1542
|
+
continue;
|
|
1543
|
+
}
|
|
1544
|
+
const before = signals.records.get("");
|
|
1545
|
+
const body = text.slice(i, end);
|
|
1546
|
+
if (body === "7501;?")
|
|
1547
|
+
queries++;
|
|
1548
|
+
else if (body.startsWith("7501;"))
|
|
1549
|
+
applyProgramStatus(signals, body.slice(5), now);
|
|
1550
|
+
else if (body.startsWith("3008;"))
|
|
1551
|
+
applyContext(signals, body.slice(5));
|
|
1552
|
+
else if (body === "133;A" || body.startsWith("133;A;"))
|
|
1553
|
+
clearTransientStatuses(signals);
|
|
1554
|
+
const after = signals.records.get("");
|
|
1555
|
+
if (before !== after)
|
|
1556
|
+
onRootChange?.(after ?? null);
|
|
1557
|
+
i = end + (text[end] === "\x1B" ? 1 : 0);
|
|
1558
|
+
}
|
|
1559
|
+
return queries;
|
|
1560
|
+
}
|
|
1561
|
+
|
|
1398
1562
|
// ../rove-daemon/src/daemon/pty-child-controller.ts
|
|
1399
1563
|
import { randomUUID as randomUUID6 } from "node:crypto";
|
|
1400
1564
|
|
|
@@ -1476,7 +1640,7 @@ function embeddedTerminalEnv(base, overrides = {}) {
|
|
|
1476
1640
|
|
|
1477
1641
|
// ../rove-daemon/src/daemon/pty-host-types.ts
|
|
1478
1642
|
import { randomUUID as randomUUID5 } from "node:crypto";
|
|
1479
|
-
import { StringDecoder as
|
|
1643
|
+
import { StringDecoder as StringDecoder3 } from "node:string_decoder";
|
|
1480
1644
|
function freshSessionState(key, spec, argv) {
|
|
1481
1645
|
return {
|
|
1482
1646
|
key,
|
|
@@ -1492,7 +1656,7 @@ function freshSessionState(key, spec, argv) {
|
|
|
1492
1656
|
command: argv,
|
|
1493
1657
|
title: "",
|
|
1494
1658
|
titleCarry: "",
|
|
1495
|
-
titleDecoder: new
|
|
1659
|
+
titleDecoder: new StringDecoder3("utf8"),
|
|
1496
1660
|
colorQueryCarry: "",
|
|
1497
1661
|
defaultColors: parseTerminalDefaultColors(spec.defaultColors) ?? DEFAULT_TERMINAL_COLORS,
|
|
1498
1662
|
modes: freshModeTrack(),
|
|
@@ -1517,6 +1681,9 @@ function sessionInfo(s) {
|
|
|
1517
1681
|
pid: s.proc?.pid ?? null,
|
|
1518
1682
|
command: s.command,
|
|
1519
1683
|
title: s.title,
|
|
1684
|
+
programStatusEvent: s.programStatusEvent,
|
|
1685
|
+
programStatus: s.oscSignals?.records.get(""),
|
|
1686
|
+
contexts: s.oscSignals?.contexts,
|
|
1520
1687
|
totalBytes: s.totalBytes,
|
|
1521
1688
|
parked: s.parked,
|
|
1522
1689
|
parkedScreenBytes: s.parkedScreenBytes,
|
|
@@ -1672,6 +1839,9 @@ class PtyChildController {
|
|
|
1672
1839
|
}
|
|
1673
1840
|
startChild(session) {
|
|
1674
1841
|
session.generation = randomUUID6();
|
|
1842
|
+
session.oscSignals = undefined;
|
|
1843
|
+
session.programStatusEvent = undefined;
|
|
1844
|
+
this.reportStatus(session, null);
|
|
1675
1845
|
try {
|
|
1676
1846
|
session.proc = (this.deps.driver ?? bunTerminalDriver())({
|
|
1677
1847
|
argv: [...session.command],
|
|
@@ -1708,6 +1878,12 @@ class PtyChildController {
|
|
|
1708
1878
|
if (!session.alive)
|
|
1709
1879
|
return;
|
|
1710
1880
|
session.alive = false;
|
|
1881
|
+
if (session.oscSignals) {
|
|
1882
|
+
const before = session.oscSignals.records.get("");
|
|
1883
|
+
clearTransientStatuses(session.oscSignals);
|
|
1884
|
+
if (before !== session.oscSignals.records.get(""))
|
|
1885
|
+
this.reportStatus(session, null);
|
|
1886
|
+
}
|
|
1711
1887
|
const sessionExit = {
|
|
1712
1888
|
code: exit?.code ?? null,
|
|
1713
1889
|
signal: exit?.signal ?? null,
|
|
@@ -1719,12 +1895,27 @@ class PtyChildController {
|
|
|
1719
1895
|
} catch {}
|
|
1720
1896
|
this.deps.onExit?.(session, sessionExit);
|
|
1721
1897
|
}
|
|
1898
|
+
reportStatus(session, status) {
|
|
1899
|
+
const event = {
|
|
1900
|
+
key: session.key,
|
|
1901
|
+
generation: session.generation,
|
|
1902
|
+
revision: (session.programStatusEvent?.revision ?? 0) + 1,
|
|
1903
|
+
at: Date.now(),
|
|
1904
|
+
status
|
|
1905
|
+
};
|
|
1906
|
+
session.programStatusEvent = event;
|
|
1907
|
+
this.deps.onProgramStatus?.(event);
|
|
1908
|
+
}
|
|
1722
1909
|
onData(session, data) {
|
|
1723
1910
|
const buf = typeof data === "string" ? Buffer.from(data, "utf8") : Buffer.from(data);
|
|
1724
1911
|
const text = buf.toString("latin1");
|
|
1912
|
+
session.oscSignals ??= createOscSignals();
|
|
1913
|
+
const queries = scanOscSignals(session.oscSignals, buf, Date.now(), (status) => this.reportStatus(session, status));
|
|
1725
1914
|
const colorQueries = foldDefaultColorQueries(session.colorQueryCarry, text);
|
|
1726
1915
|
session.colorQueryCarry = colorQueries.carry;
|
|
1727
1916
|
const replies = colorQueries.slots.map((slot) => formatDefaultColorReply(slot, session.defaultColors));
|
|
1917
|
+
for (let i = 0;i < Math.min(queries, 16); i++)
|
|
1918
|
+
replies.push("\x1B]7501;?\x1B\\");
|
|
1728
1919
|
const modeReplies = scanTerminalModes(session.modes, text);
|
|
1729
1920
|
if (session.emulatorSinks.size === 0)
|
|
1730
1921
|
replies.push(...modeReplies);
|
|
@@ -1833,6 +2024,7 @@ class PtyHost {
|
|
|
1833
2024
|
this.scrollbackCap = opts.scrollbackCap ?? DEFAULT_SCROLLBACK_CAP;
|
|
1834
2025
|
this.childController = new PtyChildController({
|
|
1835
2026
|
driver: opts.driver,
|
|
2027
|
+
onProgramStatus: (event) => this.opts.onProgramStatus?.(event),
|
|
1836
2028
|
scrollbackCap: this.scrollbackCap,
|
|
1837
2029
|
onSessionStart: (spare) => {
|
|
1838
2030
|
if (!spare)
|
|
@@ -1983,6 +2175,12 @@ class PtyHost {
|
|
|
1983
2175
|
return false;
|
|
1984
2176
|
this.sessions.delete(from);
|
|
1985
2177
|
session.key = to;
|
|
2178
|
+
if (session.programStatusEvent) {
|
|
2179
|
+
const previous = session.programStatusEvent;
|
|
2180
|
+
this.opts.onProgramStatus?.({ ...previous, revision: previous.revision + 1, at: Date.now(), status: null });
|
|
2181
|
+
session.programStatusEvent = { ...previous, key: to, revision: previous.revision + 1, at: Date.now() };
|
|
2182
|
+
this.opts.onProgramStatus?.(session.programStatusEvent);
|
|
2183
|
+
}
|
|
1986
2184
|
this.sessions.set(to, session);
|
|
1987
2185
|
this.opts.freeze?.drop(from);
|
|
1988
2186
|
this.maybeFreeze(session, true);
|
|
@@ -2093,7 +2291,7 @@ import { dirname as dirname6 } from "node:path";
|
|
|
2093
2291
|
|
|
2094
2292
|
// ../rove-daemon/src/client/index.ts
|
|
2095
2293
|
import { connect } from "node:net";
|
|
2096
|
-
import { StringDecoder as
|
|
2294
|
+
import { StringDecoder as StringDecoder4 } from "node:string_decoder";
|
|
2097
2295
|
|
|
2098
2296
|
// ../rove-daemon/src/client/client-log.ts
|
|
2099
2297
|
import { appendFile, mkdir as mkdir3, rename as rename2, stat } from "node:fs/promises";
|
|
@@ -2362,7 +2560,7 @@ class RoveDaemonClient {
|
|
|
2362
2560
|
};
|
|
2363
2561
|
socket.once("connect", onConnect);
|
|
2364
2562
|
socket.once("error", onError);
|
|
2365
|
-
const decoder = new
|
|
2563
|
+
const decoder = new StringDecoder4("utf8");
|
|
2366
2564
|
this.buffer = "";
|
|
2367
2565
|
socket.on("data", (chunk) => this.onData(decoder.write(chunk)));
|
|
2368
2566
|
socket.on("close", () => this.onSocketClose(socket));
|
|
@@ -2684,6 +2882,13 @@ function dispatchPtyRequest(req, client, deps) {
|
|
|
2684
2882
|
ptys.detach(requireString(payload, "key"), client, payload.parked === true, typeof payload.parkedScreenBytes === "number" ? payload.parkedScreenBytes : 0);
|
|
2685
2883
|
}
|
|
2686
2884
|
return {};
|
|
2885
|
+
case "pty.watchStatus":
|
|
2886
|
+
client.watchProgramStatus = true;
|
|
2887
|
+
for (const session of ptys.list()) {
|
|
2888
|
+
if (session.programStatusEvent)
|
|
2889
|
+
deps.writeFrame(client, { type: "event", name: "pty.programStatus", payload: session.programStatusEvent });
|
|
2890
|
+
}
|
|
2891
|
+
return { supported: true };
|
|
2687
2892
|
case "pty.list":
|
|
2688
2893
|
return {
|
|
2689
2894
|
pid: process.pid,
|
|
@@ -2804,6 +3009,12 @@ async function startPtyHostServer(options = {}) {
|
|
|
2804
3009
|
}, orphanCheckMs);
|
|
2805
3010
|
orphanTimer.unref?.();
|
|
2806
3011
|
const ptys = new PtyHost({
|
|
3012
|
+
onProgramStatus: (event) => {
|
|
3013
|
+
for (const client of clients) {
|
|
3014
|
+
if (client.watchProgramStatus)
|
|
3015
|
+
writeFrame(client, { type: "event", name: "pty.programStatus", payload: event });
|
|
3016
|
+
}
|
|
3017
|
+
},
|
|
2807
3018
|
onSessionStart: cancelIdle,
|
|
2808
3019
|
onSessionEnd: () => {
|
|
2809
3020
|
if (ptys.liveCount() === 0)
|
package/dist/cli/rove.js
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
|
-
import{join as n}from"node:path";import{createInterface as a}from"node:readline/promises";import{pathToFileURL as ss}from"node:url";import{spawnSync as Q}from"node:child_process";import{constants as d,accessSync as R}from"node:fs";import{homedir as I}from"node:os";import{basename as U,delimiter as o,dirname as _,join as k}from"node:path";import{fileURLToPath as T}from"node:url";var H={$schema:"https://json.schemastore.org/package.json",name:"@sma1lboy/rove",version:"0.9.
|
|
2
|
+
import{join as n}from"node:path";import{createInterface as a}from"node:readline/promises";import{pathToFileURL as ss}from"node:url";import{spawnSync as Q}from"node:child_process";import{constants as d,accessSync as R}from"node:fs";import{homedir as I}from"node:os";import{basename as U,delimiter as o,dirname as _,join as k}from"node:path";import{fileURLToPath as T}from"node:url";var H={$schema:"https://json.schemastore.org/package.json",name:"@sma1lboy/rove",version:"0.9.246",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:{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:mock":"ROVE_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","build:rubric":"bun run scripts/build-tier-rubric.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":"ROVE_INCLUDE_SOCKET=1 vitest run test/daemon --pool forks --minWorkers=1 --maxWorkers=4 --passWithNoTests","test:socket:coverage":"ROVE_INCLUDE_SOCKET=1 ROVE_COVERAGE_DAEMON=1 vitest run test/daemon --coverage --pool forks --minWorkers=1 --maxWorkers=4 --passWithNoTests","test:behavior":"ROVE_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.21.3"},devDependencies:{"@biomejs/biome":"1.9.4","@sma1lboy/rove-daemon":"0.7.20","@tsconfig/bun":"1.0.11","@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","rove-weixin":"0.0.7",typescript:"5.8.2",vitest:"2.1.9"},trustedDependencies:[]};var q="rove";var i=q;var z="ROVE_BUN",e="ROVE_NO_BUN_BOOTSTRAP",F="ROVE_SKIP_BUN_CHECK",$=H.engines.bun.match(/\d+\.\d+\.\d+/)?.[0]??"0.0.0",L=(s)=>{try{return R(s,d.X_OK),!0}catch{return!1}},B=(s)=>s==="win32"?"bun.exe":"bun",f=(s)=>{let t=Q(s,["--version"],{encoding:"utf8",timeout:5000});if(t.error||t.status!==0)return null;return t.stdout?.split(`
|
|
3
3
|
`)[0]?.trim()??""};function J(s){return s.trim().match(/^v?(\d+\.\d+\.\d+)/)?.[1]??null}function X(s,t=$){let c=J(s),b=J(t);if(!c||!b)return!0;let W=c.split(".").map(Number),g=b.split(".").map(Number);for(let x=0;x<3;x++){let y=W[x]??0,r=g[x]??0;if(y!==r)return y>r}return!0}function Y(s=process.env){return s[F]==="1"}function A(s={}){let t=s.env??process.env,c=s.platform??process.platform,b=s.home??t.HOME??t.USERPROFILE??I(),W=B(c),g=[],x=t[z]?.trim();if(x)g.push(x);for(let G of(t.PATH??t.Path??"").split(o))if(G)g.push(k(G,W));let y=t.BUN_INSTALL?.trim();if(y)g.push(k(y,"bin",W));if(b)g.push(k(b,".bun","bin",W));let r=s.launcherDir;if(r)g.push(k(r,"..","..","node_modules","bun","bin",W)),g.push(k(r,"..","..","..","bun","bin",W));return g}function N(s={}){let t=s.isExecutable??L;return A(s).find((c)=>t(c))??null}function Z(s={}){let t=s.isExecutable??L,c=s.bunVersionOf??f;if(Y(s.env??process.env))return{bun:N(s),stale:null,unusable:null};let b=null,W=null;for(let g of A(s)){if(!t(g))continue;let x=c(g);if(x===null){W??=g;continue}if(X(x))return{bun:g,stale:b,unusable:W};b??={path:g,version:J(x)??x}}return{bun:null,stale:b,unusable:W}}function h(s){return _(T(s))}function C(s){return U(T(s)).replace(/\.[cm]?[jt]s$/,"")}function u(s=process.platform){return s==="win32"?["powershell","-NoProfile","-Command","irm bun.sh/install.ps1 | iex"]:["bash","-c","curl -fsSL https://bun.sh/install | bash"]}function D(s=i,t=process.platform){let c=t==="win32"?'powershell -c "irm bun.sh/install.ps1 | iex"':"curl -fsSL https://bun.sh/install | bash";return[`${s}: Rove runs on the Bun runtime, and no Bun was found on this machine.`,"","Install Bun, then run this command again:",` ${c}`," 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: ${z}=/path/to/bun`,""].join(`
|
|
4
4
|
`)}function j(s,t,c=i){return[`${c}: this machine's Bun is too old for Rove — found ${t} at ${s}, need ${$} 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: ${z}=/path/to/bun`,`Run on this one anyway (unsupported, terminals will be blank): ${F}=1`,""].join(`
|
|
5
5
|
`)}function v(s,t=i){return[`${t}: the Bun at ${s} could not be run — \`${s} --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: ${z}=/path/to/bun`,""].join(`
|
|
@@ -3,7 +3,7 @@ name: rove
|
|
|
3
3
|
description: Use when controlling Rove tasks, parallel coding attempts, hosted agent sessions, task lifecycle, or the daemon-owned issue tracker from a shell. Also the ONLY channel for messaging another agent session on this machine — `rove api send`, never a peer/MCP side channel.
|
|
4
4
|
---
|
|
5
5
|
|
|
6
|
-
<!-- rove-skill-version:
|
|
6
|
+
<!-- rove-skill-version: 57 — bump in lockstep with ROVE_SKILL_VERSION (src/lib/skill-install.ts). -->
|
|
7
7
|
|
|
8
8
|
# Rove shell control
|
|
9
9
|
|
|
@@ -71,7 +71,7 @@ see both.
|
|
|
71
71
|
|
|
72
72
|
<!-- generated:begin read -->
|
|
73
73
|
```text
|
|
74
|
-
list
|
|
74
|
+
list --repo --status <S1,S2> --activity <A1,A2>
|
|
75
75
|
get-task --task-id(REQ)
|
|
76
76
|
pty-list (none)
|
|
77
77
|
collect --task-ids <a,b,c> --group --repo
|
|
@@ -266,12 +266,12 @@ it fires with no TUI attached.
|
|
|
266
266
|
```text
|
|
267
267
|
routine-list (none)
|
|
268
268
|
routine-create --repo(REQ) --name(REQ) --prompt|--prompt-file(REQ) --schedule(REQ)
|
|
269
|
-
--vendor{claude|codex|copilot|kimi|pi|omp|bob} --
|
|
270
|
-
--precheck-timeout(120) --grace(60)
|
|
271
|
-
--target-tab --disabled
|
|
272
|
-
routine-update --id(REQ) --name --prompt|--prompt-file --schedule --vendor --
|
|
273
|
-
--precheck --precheck-timeout(120) --grace(60)
|
|
274
|
-
--target-task --target-tab --enabled
|
|
269
|
+
--vendor{claude|codex|copilot|kimi|pi|omp|bob} --model --effort
|
|
270
|
+
--base-branch --precheck --precheck-timeout(120) --grace(60)
|
|
271
|
+
--persistent-session --target-task --target-tab --disabled
|
|
272
|
+
routine-update --id(REQ) --name --prompt|--prompt-file --schedule --vendor --model
|
|
273
|
+
--effort --base-branch --precheck --precheck-timeout(120) --grace(60)
|
|
274
|
+
--persistent-session --target-task --target-tab --enabled
|
|
275
275
|
routine-delete --id(REQ)
|
|
276
276
|
routine-run-now --id(REQ)
|
|
277
277
|
routine-respond --run(REQ) --text --prompt-file
|
|
@@ -302,7 +302,8 @@ A bare `--enabled` means true, so pausing a routine is
|
|
|
302
302
|
`routine-update --id <id> --enabled=false` (the same `=false` spelling
|
|
303
303
|
`update --pinned=false` uses).
|
|
304
304
|
|
|
305
|
-
`routine-update --schedule` re-anchors the next run. `--precheck ''` clears it
|
|
305
|
+
`routine-update --schedule` re-anchors the next run. `--precheck ''` clears it, as
|
|
306
|
+
`--model ''` and `--effort ''` clear the routine's model and effort pins.
|
|
306
307
|
`routine-run-now` skips the precheck deliberately (asking for it IS the answer)
|
|
307
308
|
and does not shift the schedule. `routine-delete` leaves already-created tasks
|
|
308
309
|
alone.
|
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.
|
|
4
|
+
"version": "0.9.246",
|
|
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",
|
|
@@ -88,7 +88,7 @@
|
|
|
88
88
|
"@vitest/coverage-v8": "2.1.9",
|
|
89
89
|
"knip": "^6.14.2",
|
|
90
90
|
"react-devtools-core": "^7.0.1",
|
|
91
|
-
"rove-weixin": "0.0.
|
|
91
|
+
"rove-weixin": "0.0.7",
|
|
92
92
|
"typescript": "5.8.2",
|
|
93
93
|
"vitest": "2.1.9"
|
|
94
94
|
},
|
|
@@ -1,3 +0,0 @@
|
|
|
1
|
-
// @bun
|
|
2
|
-
class ClientWriter{socket;highWaterMark;onOverflow;queue=new Map;snapshots=new Map;sequence=0;queuedBytes=0;paused=!1;droppedFrames=0;overflowed=!1;constructor(socket,options={}){this.socket=socket;this.highWaterMark=options.highWaterMark??8388608,this.onOverflow=options.onOverflow??(()=>socket.destroy())}get isPaused(){return this.paused}get pendingBytes(){return this.queuedBytes}get pendingCount(){return this.queue.size}get dropped(){return this.droppedFrames}write(line,replaceKey=null){if(this.overflowed)return;if(!this.paused){if(!this.safeWrite(line))this.pause();return}if(replaceKey!==null){let previous=this.snapshots.get(replaceKey);if(previous!==void 0)this.dequeue(previous),this.droppedFrames++}let id=this.sequence++,frame={line,bytes:Buffer.byteLength(line),replaceKey};if(this.queue.set(id,frame),replaceKey!==null)this.snapshots.set(replaceKey,id);if(this.queuedBytes+=frame.bytes,this.queuedBytes<=this.highWaterMark)return;this.overflowed=!0,this.queue.clear(),this.snapshots.clear(),this.queuedBytes=0,this.onOverflow()}dequeue(id){let frame=this.queue.get(id);if(!frame)return;if(this.queue.delete(id),this.queuedBytes-=frame.bytes,frame.replaceKey!==null)this.snapshots.delete(frame.replaceKey)}pause(){this.paused=!0,this.socket.once("drain",()=>{if(this.paused=!1,this.overflowed)return;for(let[id,frame]of this.queue)if(this.dequeue(id),!this.safeWrite(frame.line)){this.pause();return}})}safeWrite(line){try{return this.socket.write(line)}catch{return!0}}}function objectPayload(payload){if(!payload||typeof payload!=="object"||Array.isArray(payload))return{};return payload}function requireString(payload,key){let value=payload[key];if(typeof value!=="string"||value.length===0)throw Error(`${key} is required`);return value}function optionalString(payload,key){let value=payload[key];if(value===void 0||value===null||value==="")return;if(typeof value!=="string")throw Error(`${key} must be a string`);return value}function optionalBoolean(payload,key){let value=payload[key];if(value===void 0||value===null)return;if(typeof value!=="boolean")throw Error(`${key} must be a boolean`);return value}function requireNumber(payload,key){let value=payload[key];if(typeof value!=="number"||!Number.isFinite(value))throw Error(`${key} must be a finite number`);return value}function optionalNumber(payload,key){let value=payload[key];if(value===void 0||value===null)return;if(typeof value!=="number"||!Number.isFinite(value))throw Error(`${key} must be a finite number`);return value}function optionalVendor(payload,key){let value=optionalString(payload,key);return value&&value.trim().length>0?value:void 0}function optionalActivityDetail(payload){let raw=payload.detail;if(!raw||typeof raw!=="object"||Array.isArray(raw))return;let d=raw,out={};if(d.failure==="rate_limit"||d.failure==="billing"||d.failure==="other")out.failure=d.failure;if(d.waiting==="permission"||d.waiting==="input")out.waiting=d.waiting;if(typeof d.note==="string")out.note=d.note;let tool=d.tool;if(tool&&typeof tool==="object"&&!Array.isArray(tool))out.tool={...typeof tool.name==="string"?{name:tool.name}:{},...typeof tool.id==="string"?{id:tool.id}:{}};let compact=d.compact;if(compact&&typeof compact==="object"&&!Array.isArray(compact))out.compact=compact.trigger==="manual"||compact.trigger==="auto"?{trigger:compact.trigger}:{};let subagent=d.subagent;if(subagent&&typeof subagent==="object"&&!Array.isArray(subagent))out.subagent={...typeof subagent.type==="string"?{type:subagent.type}:{},...typeof subagent.id==="string"?{id:subagent.id}:{}};return Object.keys(out).length>0?out:void 0}class LineReceiver{maxBytes;storage=Buffer.alloc(0);length=0;failed=!1;constructor(maxBytes=8388608){this.maxBytes=maxBytes}get pendingBytes(){return this.length}push(chunk,onLine){if(this.failed)return!1;let start=0;while(start<chunk.length){let newline=chunk.indexOf(10,start),end=newline===-1?chunk.length:newline,size=this.length+end-start;if(size>this.maxBytes)return this.failed=!0,this.storage=Buffer.alloc(0),this.length=0,!1;if(size>this.storage.length){let capacity=Math.min(this.maxBytes,Math.max(size,this.storage.length*2,1024)),grown=Buffer.allocUnsafe(capacity);this.storage.copy(grown,0,0,this.length),this.storage=grown}if(chunk.copy(this.storage,this.length,start,end),this.length=size,newline===-1)return!0;let line=this.storage.toString("utf8",0,this.length);this.length=0,onLine(line),start=newline+1}return!0}}
|
|
3
|
-
export{ClientWriter,objectPayload,requireString,optionalString,optionalBoolean,requireNumber,optionalNumber,optionalVendor,optionalActivityDetail,LineReceiver};
|