agent-yes 1.139.0 → 1.140.0
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/{SUPPORTED_CLIS-BFecLJMA.js → SUPPORTED_CLIS-DnhSdiHO.js} +2 -2
- package/dist/SUPPORTED_CLIS-vnAMkGCv.js +8 -0
- package/dist/cli.js +3 -3
- package/dist/index.js +2 -2
- package/dist/{schedule-4GF8Vbln.js → schedule-BBJndWWa.js} +4 -4
- package/dist/{serve-I9lIuvEu.js → serve-DKAxT4TT.js} +15 -11
- package/dist/{setup-CIVspdWF.js → setup-pO43opst.js} +2 -2
- package/dist/{subcommands-DOjOgwxr.js → subcommands-Clu93rSP.js} +25 -13
- package/dist/subcommands-jcuTXpcx.js +7 -0
- package/dist/{ts-Cjaqub-v.js → ts-Bal_DlNX.js} +2 -2
- package/dist/{versionChecker-FREexFyS.js → versionChecker-BRJsYunz.js} +2 -2
- package/lab/ui/console-logic.js +18 -0
- package/lab/ui/index.html +306 -0
- package/package.json +1 -1
- package/ts/serve.ts +17 -8
- package/ts/subcommands.spec.ts +58 -1
- package/ts/subcommands.ts +0 -0
- package/dist/SUPPORTED_CLIS-vtxMZB6R.js +0 -8
- package/dist/subcommands-BcjTv_7c.js +0 -7
|
@@ -1,8 +1,8 @@
|
|
|
1
|
-
import { t as CLIS_CONFIG } from "./ts-
|
|
1
|
+
import { t as CLIS_CONFIG } from "./ts-Bal_DlNX.js";
|
|
2
2
|
|
|
3
3
|
//#region ts/SUPPORTED_CLIS.ts
|
|
4
4
|
const SUPPORTED_CLIS = Object.keys(CLIS_CONFIG);
|
|
5
5
|
|
|
6
6
|
//#endregion
|
|
7
7
|
export { SUPPORTED_CLIS as t };
|
|
8
|
-
//# sourceMappingURL=SUPPORTED_CLIS-
|
|
8
|
+
//# sourceMappingURL=SUPPORTED_CLIS-DnhSdiHO.js.map
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
import "./ts-Bal_DlNX.js";
|
|
2
|
+
import "./logger-CDIsZ-Pp.js";
|
|
3
|
+
import "./versionChecker-BRJsYunz.js";
|
|
4
|
+
import "./pidStore-fqXqTKkh.js";
|
|
5
|
+
import "./globalPidIndex-DlmmJlO8.js";
|
|
6
|
+
import { t as SUPPORTED_CLIS } from "./SUPPORTED_CLIS-DnhSdiHO.js";
|
|
7
|
+
|
|
8
|
+
export { SUPPORTED_CLIS };
|
package/dist/cli.js
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
#!/usr/bin/env bun
|
|
2
2
|
import { t as invokedCliName } from "./invokedCli-zdFbz1ST.js";
|
|
3
3
|
import { n as logger } from "./logger-CDIsZ-Pp.js";
|
|
4
|
-
import { i as versionString, n as displayVersion, r as getInstalledPackage, t as checkAndAutoUpdate } from "./versionChecker-
|
|
4
|
+
import { i as versionString, n as displayVersion, r as getInstalledPackage, t as checkAndAutoUpdate } from "./versionChecker-BRJsYunz.js";
|
|
5
5
|
import { argv } from "process";
|
|
6
6
|
import { execFileSync, spawn } from "child_process";
|
|
7
7
|
import ms from "ms";
|
|
@@ -480,7 +480,7 @@ function buildRustArgs(argv, cliFromScript, supportedClis) {
|
|
|
480
480
|
const rawArg = process.argv[2];
|
|
481
481
|
const managerCommands = !invokedCliName(process.argv);
|
|
482
482
|
const isHelpFlag = rawArg === "-h" || rawArg === "--help";
|
|
483
|
-
const { isSubcommand, runSubcommand, cmdHelp } = await import("./subcommands-
|
|
483
|
+
const { isSubcommand, runSubcommand, cmdHelp } = await import("./subcommands-jcuTXpcx.js");
|
|
484
484
|
if (isHelpFlag && process.argv.length === 3) {
|
|
485
485
|
cmdHelp(managerCommands);
|
|
486
486
|
process.exit(0);
|
|
@@ -513,7 +513,7 @@ if (config.useRust) {
|
|
|
513
513
|
}
|
|
514
514
|
}
|
|
515
515
|
if (rustBinary) {
|
|
516
|
-
const { SUPPORTED_CLIS } = await import("./SUPPORTED_CLIS-
|
|
516
|
+
const { SUPPORTED_CLIS } = await import("./SUPPORTED_CLIS-vnAMkGCv.js");
|
|
517
517
|
const rustArgs = buildRustArgs(process.argv, config.cli, SUPPORTED_CLIS);
|
|
518
518
|
if (config.verbose) {
|
|
519
519
|
console.log(`[rust] Using binary: ${rustBinary}`);
|
package/dist/index.js
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
import { a as removeControlCharacters, i as AgentContext, n as agentYes, r as config, t as CLIS_CONFIG } from "./ts-
|
|
1
|
+
import { a as removeControlCharacters, i as AgentContext, n as agentYes, r as config, t as CLIS_CONFIG } from "./ts-Bal_DlNX.js";
|
|
2
2
|
import "./logger-CDIsZ-Pp.js";
|
|
3
|
-
import "./versionChecker-
|
|
3
|
+
import "./versionChecker-BRJsYunz.js";
|
|
4
4
|
import "./pidStore-fqXqTKkh.js";
|
|
5
5
|
import "./globalPidIndex-DlmmJlO8.js";
|
|
6
6
|
|
|
@@ -1,9 +1,9 @@
|
|
|
1
|
-
import "./ts-
|
|
1
|
+
import "./ts-Bal_DlNX.js";
|
|
2
2
|
import "./logger-CDIsZ-Pp.js";
|
|
3
|
-
import "./versionChecker-
|
|
3
|
+
import "./versionChecker-BRJsYunz.js";
|
|
4
4
|
import "./pidStore-fqXqTKkh.js";
|
|
5
5
|
import "./globalPidIndex-DlmmJlO8.js";
|
|
6
|
-
import { t as SUPPORTED_CLIS } from "./SUPPORTED_CLIS-
|
|
6
|
+
import { t as SUPPORTED_CLIS } from "./SUPPORTED_CLIS-DnhSdiHO.js";
|
|
7
7
|
import { n as resolveSpawnCwd } from "./workspaceConfig-BCOqRBEW.js";
|
|
8
8
|
import { createHash } from "node:crypto";
|
|
9
9
|
|
|
@@ -141,4 +141,4 @@ async function cmdSchedule(rest) {
|
|
|
141
141
|
|
|
142
142
|
//#endregion
|
|
143
143
|
export { cmdSchedule };
|
|
144
|
-
//# sourceMappingURL=schedule-
|
|
144
|
+
//# sourceMappingURL=schedule-BBJndWWa.js.map
|
|
@@ -1,13 +1,13 @@
|
|
|
1
|
-
import "./ts-
|
|
1
|
+
import "./ts-Bal_DlNX.js";
|
|
2
2
|
import "./logger-CDIsZ-Pp.js";
|
|
3
|
-
import { r as getInstalledPackage } from "./versionChecker-
|
|
3
|
+
import { r as getInstalledPackage } from "./versionChecker-BRJsYunz.js";
|
|
4
4
|
import "./pidStore-fqXqTKkh.js";
|
|
5
5
|
import { a as updateGlobalPidStatus } from "./globalPidIndex-DlmmJlO8.js";
|
|
6
6
|
import { t as pgidForWrapper } from "./reaper-C-eWAxIj.js";
|
|
7
7
|
import "./configShared-C1C04bbq.js";
|
|
8
|
-
import { t as SUPPORTED_CLIS } from "./SUPPORTED_CLIS-
|
|
8
|
+
import { t as SUPPORTED_CLIS } from "./SUPPORTED_CLIS-DnhSdiHO.js";
|
|
9
9
|
import "./remotes-PKKjfTI1.js";
|
|
10
|
-
import {
|
|
10
|
+
import { S as writeToIpc, _ as resolveOne, b as snapshotStatus, c as extractTaskCounts, f as listRecords, h as renderRawLog, i as controlCodeFromName, m as readNotes, o as deriveLiveStatus } from "./subcommands-Clu93rSP.js";
|
|
11
11
|
import yargs from "yargs";
|
|
12
12
|
import { mkdir, open, readFile, stat, writeFile } from "fs/promises";
|
|
13
13
|
import { homedir, hostname, userInfo } from "os";
|
|
@@ -651,12 +651,16 @@ Options:
|
|
|
651
651
|
if (!root) return null;
|
|
652
652
|
return ensureRepoWatch(root).val;
|
|
653
653
|
};
|
|
654
|
-
const withMeta = async (r) =>
|
|
655
|
-
|
|
656
|
-
|
|
657
|
-
|
|
658
|
-
|
|
659
|
-
|
|
654
|
+
const withMeta = async (r) => {
|
|
655
|
+
const status = await deriveLiveStatus(r);
|
|
656
|
+
return {
|
|
657
|
+
...r,
|
|
658
|
+
status,
|
|
659
|
+
title: await logTitle(r.log_file),
|
|
660
|
+
git: status === "exited" ? null : await gitStatus(r.cwd),
|
|
661
|
+
tasks: status === "exited" ? null : await logTasks(r.log_file)
|
|
662
|
+
};
|
|
663
|
+
};
|
|
660
664
|
const presence = /* @__PURE__ */ new Map();
|
|
661
665
|
const PRESENCE_TTL_MS = 12e3;
|
|
662
666
|
const apiFetch = async (req) => {
|
|
@@ -1171,4 +1175,4 @@ Options:
|
|
|
1171
1175
|
|
|
1172
1176
|
//#endregion
|
|
1173
1177
|
export { cmdServe };
|
|
1174
|
-
//# sourceMappingURL=serve-
|
|
1178
|
+
//# sourceMappingURL=serve-DKAxT4TT.js.map
|
|
@@ -32,7 +32,7 @@ async function cmdSetup(rest) {
|
|
|
32
32
|
if (!existsSync(abs)) process.stderr.write(` note: that directory doesn't exist yet — create it, or agents spawned there will fail\n`);
|
|
33
33
|
if (noShare) return 0;
|
|
34
34
|
process.stdout.write(`\nsharing this machine to agent-yes.com…\n`);
|
|
35
|
-
const { cmdServe } = await import("./serve-
|
|
35
|
+
const { cmdServe } = await import("./serve-DKAxT4TT.js");
|
|
36
36
|
return cmdServe([
|
|
37
37
|
"install",
|
|
38
38
|
"--share",
|
|
@@ -42,4 +42,4 @@ async function cmdSetup(rest) {
|
|
|
42
42
|
|
|
43
43
|
//#endregion
|
|
44
44
|
export { cmdSetup };
|
|
45
|
-
//# sourceMappingURL=setup-
|
|
45
|
+
//# sourceMappingURL=setup-pO43opst.js.map
|
|
@@ -533,15 +533,15 @@ async function runSubcommand(argv) {
|
|
|
533
533
|
case "restart": return await cmdRestart(rest);
|
|
534
534
|
case "note": return await cmdNote(rest);
|
|
535
535
|
case "serve": {
|
|
536
|
-
const { cmdServe } = await import("./serve-
|
|
536
|
+
const { cmdServe } = await import("./serve-DKAxT4TT.js");
|
|
537
537
|
return cmdServe(rest);
|
|
538
538
|
}
|
|
539
539
|
case "setup": {
|
|
540
|
-
const { cmdSetup } = await import("./setup-
|
|
540
|
+
const { cmdSetup } = await import("./setup-pO43opst.js");
|
|
541
541
|
return cmdSetup(rest);
|
|
542
542
|
}
|
|
543
543
|
case "schedule": {
|
|
544
|
-
const { cmdSchedule } = await import("./schedule-
|
|
544
|
+
const { cmdSchedule } = await import("./schedule-BBJndWWa.js");
|
|
545
545
|
return cmdSchedule(rest);
|
|
546
546
|
}
|
|
547
547
|
case "remote": {
|
|
@@ -942,22 +942,34 @@ async function runAllRemotesLs(opts) {
|
|
|
942
942
|
return 0;
|
|
943
943
|
}
|
|
944
944
|
/**
|
|
945
|
+
* Cheap live status from liveness + log quiescence only (no log-content read):
|
|
946
|
+
* `exited` when the pid is gone or the record is exited, else `idle` when the log
|
|
947
|
+
* has been quiet longer than IDLE_THRESHOLD_MS, else `active`. The stored `status`
|
|
948
|
+
* field can go stale (the wrapper's idle mirror lags), so anything surfacing live
|
|
949
|
+
* status should derive it here. Safe to call per-agent on a hot path — one stat(),
|
|
950
|
+
* no 32KB tail read — which is why the serve's 1s console tick uses THIS rather
|
|
951
|
+
* than the richer deriveLiveState below.
|
|
952
|
+
*/
|
|
953
|
+
async function deriveLiveStatus(r) {
|
|
954
|
+
if (r.status === "exited" || !isPidAlive(r.pid)) return "exited";
|
|
955
|
+
if (!r.log_file) return "active";
|
|
956
|
+
const mtime = await stat(r.log_file).then((s) => s.mtimeMs).catch(() => null);
|
|
957
|
+
return mtime !== null && Date.now() - mtime > IDLE_THRESHOLD_MS ? "idle" : "active";
|
|
958
|
+
}
|
|
959
|
+
/**
|
|
945
960
|
* The live display state of one agent: stopped (exited) / idle (alive+quiet) /
|
|
946
961
|
* active (alive+recent output) / needs_input (alive but parked on an unanswered
|
|
947
962
|
* menu). Shared by the `ay ls` human table AND its `--json` output so both report
|
|
948
963
|
* needs_input identically — an orchestrator parsing `ay ls --json` is the primary
|
|
949
|
-
* consumer.
|
|
964
|
+
* consumer. Builds on the cheap deriveLiveStatus, then adds the menu (needs_input)
|
|
965
|
+
* override, which DOES read the log tail.
|
|
950
966
|
*/
|
|
951
967
|
async function deriveLiveState(r) {
|
|
952
|
-
|
|
968
|
+
const base = await deriveLiveStatus(r);
|
|
969
|
+
if (base === "exited") return {
|
|
953
970
|
state: "stopped",
|
|
954
971
|
question: null
|
|
955
972
|
};
|
|
956
|
-
let state = "active";
|
|
957
|
-
if (r.log_file) {
|
|
958
|
-
const mtime = await stat(r.log_file).then((s) => s.mtimeMs).catch(() => null);
|
|
959
|
-
state = mtime !== null && Date.now() - mtime > IDLE_THRESHOLD_MS ? "idle" : "active";
|
|
960
|
-
}
|
|
961
973
|
if (r.log_file) {
|
|
962
974
|
const ni = await extractNeedsInput(r.log_file, r.cli);
|
|
963
975
|
if (ni) return {
|
|
@@ -966,7 +978,7 @@ async function deriveLiveState(r) {
|
|
|
966
978
|
};
|
|
967
979
|
}
|
|
968
980
|
return {
|
|
969
|
-
state,
|
|
981
|
+
state: base,
|
|
970
982
|
question: null
|
|
971
983
|
};
|
|
972
984
|
}
|
|
@@ -2427,5 +2439,5 @@ async function cmdResultSet(rest) {
|
|
|
2427
2439
|
}
|
|
2428
2440
|
|
|
2429
2441
|
//#endregion
|
|
2430
|
-
export {
|
|
2431
|
-
//# sourceMappingURL=subcommands-
|
|
2442
|
+
export { writeToIpc as S, resolveOne as _, cursorAbs as a, snapshotStatus as b, extractTaskCounts as c, isSubcommand as d, listRecords as f, renderRawLogLines as g, renderRawLog as h, controlCodeFromName as i, finalizedLines as l, readNotes as m, READ_PAGE_DEFAULT as n, deriveLiveStatus as o, matchKeyword as p, cmdHelp as r, extractNeedsInput as s, GRACEFUL_EXIT_COMMANDS as t, isPidAlive as u, resolveReadWindow as v, stopTipForCli as x, runSubcommand as y };
|
|
2443
|
+
//# sourceMappingURL=subcommands-Clu93rSP.js.map
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
import "./logger-CDIsZ-Pp.js";
|
|
2
|
+
import "./globalPidIndex-DlmmJlO8.js";
|
|
3
|
+
import "./configShared-C1C04bbq.js";
|
|
4
|
+
import "./remotes-PKKjfTI1.js";
|
|
5
|
+
import { S as writeToIpc, _ as resolveOne, a as cursorAbs, b as snapshotStatus, c as extractTaskCounts, d as isSubcommand, f as listRecords, g as renderRawLogLines, h as renderRawLog, i as controlCodeFromName, l as finalizedLines, m as readNotes, n as READ_PAGE_DEFAULT, o as deriveLiveStatus, p as matchKeyword, r as cmdHelp, s as extractNeedsInput, t as GRACEFUL_EXIT_COMMANDS, u as isPidAlive, v as resolveReadWindow, x as stopTipForCli, y as runSubcommand } from "./subcommands-Clu93rSP.js";
|
|
6
|
+
|
|
7
|
+
export { cmdHelp, isSubcommand, runSubcommand };
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { n as logger, t as addTransport } from "./logger-CDIsZ-Pp.js";
|
|
2
|
-
import { r as getInstalledPackage } from "./versionChecker-
|
|
2
|
+
import { r as getInstalledPackage } from "./versionChecker-BRJsYunz.js";
|
|
3
3
|
import { t as agentYesHome } from "./agentYesHome-_eJa3DaX.js";
|
|
4
4
|
import { i as shouldUseLock, r as releaseLock, t as acquireLock } from "./runningLock-V4qvXgAw.js";
|
|
5
5
|
import { t as PidStore } from "./pidStore-fqXqTKkh.js";
|
|
@@ -1788,4 +1788,4 @@ function sleep(ms) {
|
|
|
1788
1788
|
|
|
1789
1789
|
//#endregion
|
|
1790
1790
|
export { removeControlCharacters as a, AgentContext as i, agentYes as n, config as r, CLIS_CONFIG as t };
|
|
1791
|
-
//# sourceMappingURL=ts-
|
|
1791
|
+
//# sourceMappingURL=ts-Bal_DlNX.js.map
|
|
@@ -7,7 +7,7 @@ import { fileURLToPath } from "url";
|
|
|
7
7
|
|
|
8
8
|
//#region package.json
|
|
9
9
|
var name = "agent-yes";
|
|
10
|
-
var version = "1.
|
|
10
|
+
var version = "1.140.0";
|
|
11
11
|
|
|
12
12
|
//#endregion
|
|
13
13
|
//#region ts/versionChecker.ts
|
|
@@ -215,4 +215,4 @@ async function displayVersion() {
|
|
|
215
215
|
|
|
216
216
|
//#endregion
|
|
217
217
|
export { versionString as i, displayVersion as n, getInstalledPackage as r, checkAndAutoUpdate as t };
|
|
218
|
-
//# sourceMappingURL=versionChecker-
|
|
218
|
+
//# sourceMappingURL=versionChecker-BRJsYunz.js.map
|
package/lab/ui/console-logic.js
CHANGED
|
@@ -475,3 +475,21 @@ export function docTitle(name, status) {
|
|
|
475
475
|
const g = statusGlyph(status);
|
|
476
476
|
return (g ? g + " " : "") + n + " - agent-yes";
|
|
477
477
|
}
|
|
478
|
+
|
|
479
|
+
// Relevance score for the Cmd+K omnibox — higher ranks first. Title hits beat
|
|
480
|
+
// cwd/prompt hits so the "quick title match" surfaces at the top; 0 means no
|
|
481
|
+
// title/cwd/prompt hit (such an agent only appears via a tail-content match,
|
|
482
|
+
// which the caller scores separately and ranks below these).
|
|
483
|
+
export function omniScore(e, query) {
|
|
484
|
+
const q = String(query || "")
|
|
485
|
+
.trim()
|
|
486
|
+
.toLowerCase();
|
|
487
|
+
if (!q) return 0;
|
|
488
|
+
const title = (e.title || "").toLowerCase();
|
|
489
|
+
if (title === q) return 100;
|
|
490
|
+
if (title.startsWith(q)) return 80;
|
|
491
|
+
if (title.includes(q)) return 60;
|
|
492
|
+
if ((e.cwd || "").toLowerCase().includes(q)) return 40;
|
|
493
|
+
if ((e.prompt || "").toLowerCase().includes(q)) return 20;
|
|
494
|
+
return 0;
|
|
495
|
+
}
|
package/lab/ui/index.html
CHANGED
|
@@ -545,6 +545,102 @@
|
|
|
545
545
|
align-items: center;
|
|
546
546
|
justify-content: center;
|
|
547
547
|
}
|
|
548
|
+
/* Cmd/Ctrl+K omnibox */
|
|
549
|
+
.omni {
|
|
550
|
+
position: fixed;
|
|
551
|
+
inset: 0;
|
|
552
|
+
z-index: 30;
|
|
553
|
+
background: rgba(2, 6, 12, 0.6);
|
|
554
|
+
display: flex;
|
|
555
|
+
align-items: flex-start;
|
|
556
|
+
justify-content: center;
|
|
557
|
+
padding-top: 12vh;
|
|
558
|
+
}
|
|
559
|
+
.omnibox {
|
|
560
|
+
width: min(680px, 92vw);
|
|
561
|
+
background: var(--panel);
|
|
562
|
+
border: 1px solid var(--line);
|
|
563
|
+
border-radius: 10px;
|
|
564
|
+
box-shadow: 0 16px 48px rgba(0, 0, 0, 0.5);
|
|
565
|
+
overflow: hidden;
|
|
566
|
+
font-family: var(--mono);
|
|
567
|
+
}
|
|
568
|
+
#omni-input {
|
|
569
|
+
width: 100%;
|
|
570
|
+
box-sizing: border-box;
|
|
571
|
+
padding: 14px 16px;
|
|
572
|
+
border: 0;
|
|
573
|
+
border-bottom: 1px solid var(--line);
|
|
574
|
+
background: transparent;
|
|
575
|
+
color: var(--fg);
|
|
576
|
+
font: 15px var(--mono);
|
|
577
|
+
outline: none;
|
|
578
|
+
}
|
|
579
|
+
.omni-results {
|
|
580
|
+
max-height: 52vh;
|
|
581
|
+
overflow-y: auto;
|
|
582
|
+
}
|
|
583
|
+
.omni-row {
|
|
584
|
+
display: flex;
|
|
585
|
+
align-items: center;
|
|
586
|
+
gap: 8px;
|
|
587
|
+
padding: 8px 14px;
|
|
588
|
+
cursor: pointer;
|
|
589
|
+
border-left: 2px solid transparent;
|
|
590
|
+
}
|
|
591
|
+
.omni-row.sel {
|
|
592
|
+
background: color-mix(in srgb, var(--accent) 16%, transparent);
|
|
593
|
+
border-left-color: var(--accent);
|
|
594
|
+
}
|
|
595
|
+
.omni-main {
|
|
596
|
+
flex: 1;
|
|
597
|
+
min-width: 0;
|
|
598
|
+
}
|
|
599
|
+
.omni-title {
|
|
600
|
+
color: var(--fg);
|
|
601
|
+
white-space: nowrap;
|
|
602
|
+
overflow: hidden;
|
|
603
|
+
text-overflow: ellipsis;
|
|
604
|
+
}
|
|
605
|
+
.omni-sub {
|
|
606
|
+
color: var(--muted);
|
|
607
|
+
font-size: 11px;
|
|
608
|
+
white-space: nowrap;
|
|
609
|
+
overflow: hidden;
|
|
610
|
+
text-overflow: ellipsis;
|
|
611
|
+
}
|
|
612
|
+
.omni-snip {
|
|
613
|
+
color: var(--muted);
|
|
614
|
+
font-size: 11px;
|
|
615
|
+
opacity: 0.85;
|
|
616
|
+
white-space: nowrap;
|
|
617
|
+
overflow: hidden;
|
|
618
|
+
text-overflow: ellipsis;
|
|
619
|
+
}
|
|
620
|
+
.omni-snip b {
|
|
621
|
+
color: var(--amber);
|
|
622
|
+
font-weight: 600;
|
|
623
|
+
}
|
|
624
|
+
.omni-spawn {
|
|
625
|
+
border-top: 1px solid var(--line);
|
|
626
|
+
}
|
|
627
|
+
.omni-spawn .omni-title {
|
|
628
|
+
color: var(--green);
|
|
629
|
+
}
|
|
630
|
+
.omni-empty {
|
|
631
|
+
padding: 14px;
|
|
632
|
+
color: var(--muted);
|
|
633
|
+
}
|
|
634
|
+
.omni-foot {
|
|
635
|
+
padding: 8px 14px;
|
|
636
|
+
border-top: 1px solid var(--line);
|
|
637
|
+
color: var(--muted);
|
|
638
|
+
font-size: 11px;
|
|
639
|
+
}
|
|
640
|
+
.omni-foot b {
|
|
641
|
+
color: var(--fg);
|
|
642
|
+
font-weight: 600;
|
|
643
|
+
}
|
|
548
644
|
.lcard {
|
|
549
645
|
background: var(--panel);
|
|
550
646
|
border: 1px solid var(--line);
|
|
@@ -1380,6 +1476,24 @@
|
|
|
1380
1476
|
<div class="launchoverlay" id="launch" style="display: none"></div>
|
|
1381
1477
|
<div class="launchoverlay" id="newform" style="display: none"></div>
|
|
1382
1478
|
|
|
1479
|
+
<!-- Cmd/Ctrl+K omnibox: search agents by title (instant) then output (tail),
|
|
1480
|
+
or spawn a new agent in the highlighted agent's cwd with the typed prompt. -->
|
|
1481
|
+
<div class="omni" id="omni" style="display: none">
|
|
1482
|
+
<div class="omnibox">
|
|
1483
|
+
<input
|
|
1484
|
+
id="omni-input"
|
|
1485
|
+
placeholder="Search agents by title, then output…"
|
|
1486
|
+
spellcheck="false"
|
|
1487
|
+
autocapitalize="off"
|
|
1488
|
+
autocomplete="off"
|
|
1489
|
+
/>
|
|
1490
|
+
<div class="omni-results" id="omni-results"></div>
|
|
1491
|
+
<div class="omni-foot">
|
|
1492
|
+
<span><b>↑↓</b> move <b>⏎</b> open <b>⌘⏎</b> spawn here <b>esc</b> close</span>
|
|
1493
|
+
</div>
|
|
1494
|
+
</div>
|
|
1495
|
+
</div>
|
|
1496
|
+
|
|
1383
1497
|
<script type="module">
|
|
1384
1498
|
// Pure list/identity/filter helpers live in a sibling module so they can be
|
|
1385
1499
|
// unit-tested (tests/ui-logic/console-logic.spec.ts) without a DOM. This
|
|
@@ -1407,6 +1521,7 @@
|
|
|
1407
1521
|
selSegments,
|
|
1408
1522
|
fitTransform,
|
|
1409
1523
|
docTitle,
|
|
1524
|
+
omniScore,
|
|
1410
1525
|
} from "./console-logic.js";
|
|
1411
1526
|
import {
|
|
1412
1527
|
MARKER as E2E_MARKER,
|
|
@@ -1953,6 +2068,9 @@
|
|
|
1953
2068
|
async fetchJSON(path) {
|
|
1954
2069
|
return (await fetch(withTok(path))).json();
|
|
1955
2070
|
},
|
|
2071
|
+
async fetchText(path) {
|
|
2072
|
+
return (await fetch(withTok(path))).text();
|
|
2073
|
+
},
|
|
1956
2074
|
async post(path, bodyObj) {
|
|
1957
2075
|
const r = await fetch(withTok(path), {
|
|
1958
2076
|
method: "POST",
|
|
@@ -1974,6 +2092,9 @@
|
|
|
1974
2092
|
async fetchJSON(path) {
|
|
1975
2093
|
return JSON.parse((await rtc.req("GET", path)).text);
|
|
1976
2094
|
},
|
|
2095
|
+
async fetchText(path) {
|
|
2096
|
+
return (await rtc.req("GET", path)).text;
|
|
2097
|
+
},
|
|
1977
2098
|
async post(path, bodyObj) {
|
|
1978
2099
|
const r = await rtc.req("POST", path, JSON.stringify(bodyObj));
|
|
1979
2100
|
return { ok: r.status >= 200 && r.status < 300, text: r.text };
|
|
@@ -3523,6 +3644,7 @@
|
|
|
3523
3644
|
window.addEventListener(
|
|
3524
3645
|
"keydown",
|
|
3525
3646
|
(e) => {
|
|
3647
|
+
if (omniOpen()) return; // omnibox owns the keyboard while open
|
|
3526
3648
|
const mod = IS_MAC ? e.metaKey : e.altKey;
|
|
3527
3649
|
if (!mod || (e.key !== "ArrowDown" && e.key !== "ArrowUp")) return;
|
|
3528
3650
|
e.preventDefault();
|
|
@@ -3532,6 +3654,190 @@
|
|
|
3532
3654
|
true,
|
|
3533
3655
|
);
|
|
3534
3656
|
|
|
3657
|
+
// ---- Cmd/Ctrl+K omnibox: search agents (title → output) or spawn here ----
|
|
3658
|
+
let omniRows = []; // [{kind:'agent', entry, snippet?} | {kind:'spawn'}]
|
|
3659
|
+
let omniIdx = 0;
|
|
3660
|
+
let omniTailTimer = null;
|
|
3661
|
+
let omniTailSeq = 0;
|
|
3662
|
+
const omniOpen = () => $("omni").style.display !== "none";
|
|
3663
|
+
|
|
3664
|
+
function openOmni() {
|
|
3665
|
+
$("omni").style.display = "flex";
|
|
3666
|
+
const inp = $("omni-input");
|
|
3667
|
+
inp.value = "";
|
|
3668
|
+
inp.focus();
|
|
3669
|
+
runOmni();
|
|
3670
|
+
}
|
|
3671
|
+
function closeOmni() {
|
|
3672
|
+
if (omniTailTimer) clearTimeout(omniTailTimer);
|
|
3673
|
+
omniTailSeq++; // cancel any in-flight tail search
|
|
3674
|
+
$("omni").style.display = "none";
|
|
3675
|
+
}
|
|
3676
|
+
|
|
3677
|
+
// The agent the spawn action is anchored to: the highlighted agent row, else
|
|
3678
|
+
// the first agent result, else whatever's open in the console.
|
|
3679
|
+
function omniAnchor() {
|
|
3680
|
+
const hi = omniRows[omniIdx];
|
|
3681
|
+
if (hi && hi.kind === "agent") return hi.entry;
|
|
3682
|
+
const first = omniRows.find((r) => r.kind === "agent");
|
|
3683
|
+
return first ? first.entry : entries.find((x) => x._key === sel) || null;
|
|
3684
|
+
}
|
|
3685
|
+
|
|
3686
|
+
function renderOmni() {
|
|
3687
|
+
const q = $("omni-input").value.trim();
|
|
3688
|
+
if (omniIdx >= omniRows.length) omniIdx = Math.max(0, omniRows.length - 1);
|
|
3689
|
+
const anchor = omniAnchor();
|
|
3690
|
+
const html = omniRows
|
|
3691
|
+
.map((r, i) => {
|
|
3692
|
+
const sc = i === omniIdx ? " sel" : "";
|
|
3693
|
+
if (r.kind === "spawn") {
|
|
3694
|
+
return `<div class="omni-row omni-spawn${sc}" data-i="${i}">
|
|
3695
|
+
<span class="dot active"></span>
|
|
3696
|
+
<div class="omni-main">
|
|
3697
|
+
<div class="omni-title">✦ Spawn new ${esc(anchor?.cli || "claude")} agent here</div>
|
|
3698
|
+
<div class="omni-sub">${esc(anchor?.cwd || "(host default)")} · prompt: ${esc(q || "(empty)")}</div>
|
|
3699
|
+
</div></div>`;
|
|
3700
|
+
}
|
|
3701
|
+
const e = r.entry;
|
|
3702
|
+
const snip = r.snippet ? `<div class="omni-snip">…${r.snippet}…</div>` : "";
|
|
3703
|
+
return `<div class="omni-row${sc}" data-i="${i}">
|
|
3704
|
+
<span class="dot ${esc(e.status)}"></span>
|
|
3705
|
+
<div class="omni-main">
|
|
3706
|
+
<div class="omni-title">${esc(e.title || cliLabel(e) || ident(e) || "agent")}</div>
|
|
3707
|
+
<div class="omni-sub">${esc((e.cli || "") + " · " + (e.cwd || ""))}</div>
|
|
3708
|
+
${snip}
|
|
3709
|
+
</div></div>`;
|
|
3710
|
+
})
|
|
3711
|
+
.join("");
|
|
3712
|
+
$("omni-results").innerHTML = html || `<div class="omni-empty">no matches</div>`;
|
|
3713
|
+
const selrow = $("omni-results").querySelector(".omni-row.sel");
|
|
3714
|
+
if (selrow) selrow.scrollIntoView({ block: "nearest" });
|
|
3715
|
+
}
|
|
3716
|
+
|
|
3717
|
+
function runOmni() {
|
|
3718
|
+
const q = $("omni-input").value.trim();
|
|
3719
|
+
const toks = q.split(/\s+/).filter(Boolean);
|
|
3720
|
+
// Tier 1 — instant title/identity match, ranked title-first then by recency.
|
|
3721
|
+
const hits = entries
|
|
3722
|
+
.filter((e) => (toks.length ? matches(e, toks) : true))
|
|
3723
|
+
.sort(
|
|
3724
|
+
(a, b) =>
|
|
3725
|
+
omniScore(b, q) - omniScore(a, q) || (b.started_at || 0) - (a.started_at || 0),
|
|
3726
|
+
)
|
|
3727
|
+
.slice(0, 30);
|
|
3728
|
+
omniRows = hits.map((entry) => ({ kind: "agent", entry }));
|
|
3729
|
+
if (q) omniRows.push({ kind: "spawn" });
|
|
3730
|
+
omniIdx = 0;
|
|
3731
|
+
renderOmni();
|
|
3732
|
+
// Tier 2 — debounced output (tail) search for alive agents not already shown.
|
|
3733
|
+
if (omniTailTimer) clearTimeout(omniTailTimer);
|
|
3734
|
+
if (q.length >= 2) omniTailTimer = setTimeout(() => omniTailSearch(q), 320);
|
|
3735
|
+
}
|
|
3736
|
+
|
|
3737
|
+
async function omniTailSearch(q) {
|
|
3738
|
+
const seq = ++omniTailSeq;
|
|
3739
|
+
const have = new Set(omniRows.filter((r) => r.kind === "agent").map((r) => r.entry._key));
|
|
3740
|
+
const ql = q.toLowerCase();
|
|
3741
|
+
const cands = entries.filter((e) => !have.has(e._key) && e.status !== "exited").slice(0, 20);
|
|
3742
|
+
await Promise.all(
|
|
3743
|
+
cands.map(async (e) => {
|
|
3744
|
+
const src = srcFor(e);
|
|
3745
|
+
if (!src?.tx?.fetchText) return;
|
|
3746
|
+
let text = "";
|
|
3747
|
+
try {
|
|
3748
|
+
text = await src.tx.fetchText(
|
|
3749
|
+
"/api/read/" + encodeURIComponent(e.pid) + "?mode=tail&n=120",
|
|
3750
|
+
);
|
|
3751
|
+
} catch {
|
|
3752
|
+
return;
|
|
3753
|
+
}
|
|
3754
|
+
if (seq !== omniTailSeq) return; // superseded or closed
|
|
3755
|
+
const idx = text.toLowerCase().indexOf(ql);
|
|
3756
|
+
if (idx < 0) return;
|
|
3757
|
+
const raw = text
|
|
3758
|
+
.slice(Math.max(0, idx - 24), idx + q.length + 24)
|
|
3759
|
+
.replace(/\s+/g, " ")
|
|
3760
|
+
.trim();
|
|
3761
|
+
const li = raw.toLowerCase().indexOf(ql);
|
|
3762
|
+
const snippet =
|
|
3763
|
+
li >= 0
|
|
3764
|
+
? esc(raw.slice(0, li)) +
|
|
3765
|
+
"<b>" +
|
|
3766
|
+
esc(raw.slice(li, li + q.length)) +
|
|
3767
|
+
"</b>" +
|
|
3768
|
+
esc(raw.slice(li + q.length))
|
|
3769
|
+
: esc(raw);
|
|
3770
|
+
const at = omniRows.findIndex((r) => r.kind === "spawn");
|
|
3771
|
+
const row = { kind: "agent", entry: e, snippet };
|
|
3772
|
+
if (at >= 0) omniRows.splice(at, 0, row);
|
|
3773
|
+
else omniRows.push(row);
|
|
3774
|
+
}),
|
|
3775
|
+
);
|
|
3776
|
+
if (seq === omniTailSeq) renderOmni();
|
|
3777
|
+
}
|
|
3778
|
+
|
|
3779
|
+
function omniMove(d) {
|
|
3780
|
+
if (!omniRows.length) return;
|
|
3781
|
+
omniIdx = (omniIdx + d + omniRows.length) % omniRows.length;
|
|
3782
|
+
renderOmni();
|
|
3783
|
+
}
|
|
3784
|
+
async function omniActivate(forceSpawn) {
|
|
3785
|
+
const q = $("omni-input").value.trim();
|
|
3786
|
+
const row = omniRows[omniIdx];
|
|
3787
|
+
if (forceSpawn || (row && row.kind === "spawn")) {
|
|
3788
|
+
const anchor = omniAnchor();
|
|
3789
|
+
closeOmni();
|
|
3790
|
+
await spawnAndSelect(
|
|
3791
|
+
{ cli: anchor?.cli || "claude", cwd: anchor?.cwd || undefined, prompt: q || undefined },
|
|
3792
|
+
anchor?._room,
|
|
3793
|
+
);
|
|
3794
|
+
return;
|
|
3795
|
+
}
|
|
3796
|
+
if (row && row.kind === "agent") {
|
|
3797
|
+
closeOmni();
|
|
3798
|
+
select(row.entry._key);
|
|
3799
|
+
}
|
|
3800
|
+
}
|
|
3801
|
+
|
|
3802
|
+
$("omni-input").addEventListener("input", runOmni);
|
|
3803
|
+
$("omni-results").addEventListener("click", (ev) => {
|
|
3804
|
+
const r = ev.target.closest(".omni-row");
|
|
3805
|
+
if (!r) return;
|
|
3806
|
+
omniIdx = +r.dataset.i;
|
|
3807
|
+
omniActivate(false);
|
|
3808
|
+
});
|
|
3809
|
+
$("omni").addEventListener("mousedown", (ev) => {
|
|
3810
|
+
if (ev.target === $("omni")) closeOmni(); // backdrop click closes
|
|
3811
|
+
});
|
|
3812
|
+
$("omni-input").addEventListener("keydown", (ev) => {
|
|
3813
|
+
if (ev.key === "Escape") {
|
|
3814
|
+
ev.preventDefault();
|
|
3815
|
+
closeOmni();
|
|
3816
|
+
} else if (ev.key === "ArrowDown") {
|
|
3817
|
+
ev.preventDefault();
|
|
3818
|
+
omniMove(1);
|
|
3819
|
+
} else if (ev.key === "ArrowUp") {
|
|
3820
|
+
ev.preventDefault();
|
|
3821
|
+
omniMove(-1);
|
|
3822
|
+
} else if (ev.key === "Enter") {
|
|
3823
|
+
ev.preventDefault();
|
|
3824
|
+
omniActivate(ev.metaKey || ev.ctrlKey);
|
|
3825
|
+
}
|
|
3826
|
+
});
|
|
3827
|
+
// Cmd+K (Mac) / Ctrl+K (others) toggles the omnibox. Capture phase so it beats
|
|
3828
|
+
// xterm's textarea handler and isn't forwarded to the agent as a keystroke.
|
|
3829
|
+
window.addEventListener(
|
|
3830
|
+
"keydown",
|
|
3831
|
+
(e) => {
|
|
3832
|
+
if ((e.metaKey || e.ctrlKey) && (e.key === "k" || e.key === "K")) {
|
|
3833
|
+
e.preventDefault();
|
|
3834
|
+
e.stopPropagation();
|
|
3835
|
+
omniOpen() ? closeOmni() : openOmni();
|
|
3836
|
+
}
|
|
3837
|
+
},
|
|
3838
|
+
true,
|
|
3839
|
+
);
|
|
3840
|
+
|
|
3535
3841
|
// ---- rooms: localStorage cache + a manager you open by clicking the badge ----
|
|
3536
3842
|
const ROOMS_KEY = "ay.rooms";
|
|
3537
3843
|
const ROOM_TTL_MS = 90 * 24 * 60 * 60 * 1000; // evict stale rooms to bound how long a secret lingers in localStorage
|
package/package.json
CHANGED
package/ts/serve.ts
CHANGED
|
@@ -7,6 +7,7 @@ import path from "path";
|
|
|
7
7
|
import yargs from "yargs";
|
|
8
8
|
import {
|
|
9
9
|
controlCodeFromName,
|
|
10
|
+
deriveLiveStatus,
|
|
10
11
|
extractTaskCounts,
|
|
11
12
|
listRecords,
|
|
12
13
|
readNotes,
|
|
@@ -933,14 +934,22 @@ export async function cmdServe(rest: string[]): Promise<number> {
|
|
|
933
934
|
|
|
934
935
|
// One agent record decorated for the console: the latest OSC title + a git
|
|
935
936
|
// snapshot (skipped for exited agents — their repo state is no longer live).
|
|
936
|
-
const withMeta = async (r: Awaited<ReturnType<typeof listRecords>>[number]) =>
|
|
937
|
-
|
|
938
|
-
|
|
939
|
-
|
|
940
|
-
//
|
|
941
|
-
|
|
942
|
-
|
|
943
|
-
|
|
937
|
+
const withMeta = async (r: Awaited<ReturnType<typeof listRecords>>[number]) => {
|
|
938
|
+
// The stored `status` field lags (the wrapper's idle mirror is fire-and-forget),
|
|
939
|
+
// so the console showed agents as "active" long after they went quiet. Derive
|
|
940
|
+
// the LIVE status here — same liveness+log-mtime basis as `ay ls` — so the
|
|
941
|
+
// console's dot (and the browser tab glyph) flips to idle in step with `ay ls`.
|
|
942
|
+
const status = await deriveLiveStatus(r);
|
|
943
|
+
return {
|
|
944
|
+
...r,
|
|
945
|
+
status,
|
|
946
|
+
title: await logTitle(r.log_file),
|
|
947
|
+
git: status === "exited" ? null : await gitStatus(r.cwd),
|
|
948
|
+
// Task progress from the rendered todo block (null when none detected → no
|
|
949
|
+
// badge). Skipped for exited agents — their screen is no longer live.
|
|
950
|
+
tasks: status === "exited" ? null : await logTasks(r.log_file),
|
|
951
|
+
};
|
|
952
|
+
};
|
|
944
953
|
|
|
945
954
|
// Multi-peer presence blackboard: viewerId -> what that viewer is watching +
|
|
946
955
|
// its viewport/selection. Purely cosmetic ("who else is looking at this agent"),
|
package/ts/subcommands.spec.ts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { afterEach, beforeEach, describe, expect, it, vi } from "vitest";
|
|
2
|
-
import { mkdir, mkdtemp, rm, writeFile } from "fs/promises";
|
|
2
|
+
import { mkdir, mkdtemp, rm, utimes, writeFile } from "fs/promises";
|
|
3
3
|
import { tmpdir } from "os";
|
|
4
4
|
import path from "path";
|
|
5
5
|
|
|
@@ -1466,3 +1466,60 @@ describe("subcommands.resolveReadWindow", () => {
|
|
|
1466
1466
|
});
|
|
1467
1467
|
});
|
|
1468
1468
|
});
|
|
1469
|
+
|
|
1470
|
+
describe("subcommands.deriveLiveStatus", () => {
|
|
1471
|
+
const rec = (over: any) => ({
|
|
1472
|
+
pid: process.pid,
|
|
1473
|
+
cli: "claude",
|
|
1474
|
+
prompt: null,
|
|
1475
|
+
cwd: "/tmp",
|
|
1476
|
+
log_file: null,
|
|
1477
|
+
fifo_file: null,
|
|
1478
|
+
status: "active",
|
|
1479
|
+
exit_code: null,
|
|
1480
|
+
exit_reason: null,
|
|
1481
|
+
started_at: 0,
|
|
1482
|
+
...over,
|
|
1483
|
+
});
|
|
1484
|
+
|
|
1485
|
+
it("returns 'exited' for a dead pid", async () => {
|
|
1486
|
+
const mod = await loadModule();
|
|
1487
|
+
expect(await mod.deriveLiveStatus(rec({ pid: 2147483646 }))).toBe("exited");
|
|
1488
|
+
});
|
|
1489
|
+
|
|
1490
|
+
it("returns 'exited' when the record is already exited", async () => {
|
|
1491
|
+
const mod = await loadModule();
|
|
1492
|
+
expect(await mod.deriveLiveStatus(rec({ status: "exited" }))).toBe("exited");
|
|
1493
|
+
});
|
|
1494
|
+
|
|
1495
|
+
it("returns 'active' for an alive pid with no log file", async () => {
|
|
1496
|
+
const mod = await loadModule();
|
|
1497
|
+
expect(await mod.deriveLiveStatus(rec({ log_file: null }))).toBe("active");
|
|
1498
|
+
});
|
|
1499
|
+
|
|
1500
|
+
it("returns 'active' for an alive pid with a freshly-written log", async () => {
|
|
1501
|
+
const dir = await mkdtemp(path.join(tmpdir(), "ay-dls-"));
|
|
1502
|
+
try {
|
|
1503
|
+
const log = path.join(dir, "a.log");
|
|
1504
|
+
await writeFile(log, "hi");
|
|
1505
|
+
const mod = await loadModule();
|
|
1506
|
+
expect(await mod.deriveLiveStatus(rec({ log_file: log }))).toBe("active");
|
|
1507
|
+
} finally {
|
|
1508
|
+
await rm(dir, { recursive: true, force: true }).catch(() => null);
|
|
1509
|
+
}
|
|
1510
|
+
});
|
|
1511
|
+
|
|
1512
|
+
it("returns 'idle' when the log has been quiet past the threshold", async () => {
|
|
1513
|
+
const dir = await mkdtemp(path.join(tmpdir(), "ay-dls-"));
|
|
1514
|
+
try {
|
|
1515
|
+
const log = path.join(dir, "a.log");
|
|
1516
|
+
await writeFile(log, "hi");
|
|
1517
|
+
const old = new Date(Date.now() - 5 * 60 * 1000); // 5 min ago > 60s threshold
|
|
1518
|
+
await utimes(log, old, old);
|
|
1519
|
+
const mod = await loadModule();
|
|
1520
|
+
expect(await mod.deriveLiveStatus(rec({ log_file: log }))).toBe("idle");
|
|
1521
|
+
} finally {
|
|
1522
|
+
await rm(dir, { recursive: true, force: true }).catch(() => null);
|
|
1523
|
+
}
|
|
1524
|
+
});
|
|
1525
|
+
});
|
package/ts/subcommands.ts
CHANGED
|
Binary file
|
|
@@ -1,8 +0,0 @@
|
|
|
1
|
-
import "./ts-Cjaqub-v.js";
|
|
2
|
-
import "./logger-CDIsZ-Pp.js";
|
|
3
|
-
import "./versionChecker-FREexFyS.js";
|
|
4
|
-
import "./pidStore-fqXqTKkh.js";
|
|
5
|
-
import "./globalPidIndex-DlmmJlO8.js";
|
|
6
|
-
import { t as SUPPORTED_CLIS } from "./SUPPORTED_CLIS-BFecLJMA.js";
|
|
7
|
-
|
|
8
|
-
export { SUPPORTED_CLIS };
|
|
@@ -1,7 +0,0 @@
|
|
|
1
|
-
import "./logger-CDIsZ-Pp.js";
|
|
2
|
-
import "./globalPidIndex-DlmmJlO8.js";
|
|
3
|
-
import "./configShared-C1C04bbq.js";
|
|
4
|
-
import "./remotes-PKKjfTI1.js";
|
|
5
|
-
import { _ as resolveReadWindow, a as cursorAbs, b as stopTipForCli, c as finalizedLines, d as listRecords, f as matchKeyword, g as resolveOne, h as renderRawLogLines, i as controlCodeFromName, l as isPidAlive, m as renderRawLog, n as READ_PAGE_DEFAULT, o as extractNeedsInput, p as readNotes, r as cmdHelp, s as extractTaskCounts, t as GRACEFUL_EXIT_COMMANDS, u as isSubcommand, v as runSubcommand, x as writeToIpc, y as snapshotStatus } from "./subcommands-DOjOgwxr.js";
|
|
6
|
-
|
|
7
|
-
export { cmdHelp, isSubcommand, runSubcommand };
|