agent-yes 1.100.0 → 1.102.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-C6FspQLb.js +8 -0
- package/dist/{SUPPORTED_CLIS-DIHMEdRx.js → SUPPORTED_CLIS-DZBdcl3r.js} +2 -2
- package/dist/cli.js +3 -3
- package/dist/index.js +2 -2
- package/dist/{serve-C4fZSjh9.js → serve-D_NsFccM.js} +6 -5
- package/dist/{subcommands-BKY3nQV4.js → subcommands-2xkgzhhI.js} +2 -2
- package/dist/{subcommands-dnjUZ9nY.js → subcommands-Clfntx3R.js} +1 -1
- package/dist/{ts-CUn393DD.js → ts-cYD43w4Z.js} +2 -2
- package/dist/{versionChecker-BWdncsn6.js → versionChecker-DdMHudEv.js} +2 -2
- package/lab/ui/console-logic.js +79 -0
- package/lab/ui/index.html +41 -61
- package/package.json +4 -2
- package/ts/serve.ts +2 -0
- package/ts/workspaceConfig.spec.ts +71 -0
- package/ts/workspaceConfig.ts +70 -0
- package/dist/SUPPORTED_CLIS-C-cenkTG.js +0 -8
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
import "./ts-cYD43w4Z.js";
|
|
2
|
+
import "./logger-B9h0djqx.js";
|
|
3
|
+
import "./versionChecker-DdMHudEv.js";
|
|
4
|
+
import "./pidStore-DBjlqzo8.js";
|
|
5
|
+
import "./globalPidIndex-yVd3mbsV.js";
|
|
6
|
+
import { t as SUPPORTED_CLIS } from "./SUPPORTED_CLIS-DZBdcl3r.js";
|
|
7
|
+
|
|
8
|
+
export { SUPPORTED_CLIS };
|
|
@@ -1,8 +1,8 @@
|
|
|
1
|
-
import { t as CLIS_CONFIG } from "./ts-
|
|
1
|
+
import { t as CLIS_CONFIG } from "./ts-cYD43w4Z.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-DZBdcl3r.js.map
|
package/dist/cli.js
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
#!/usr/bin/env bun
|
|
2
2
|
import { n as logger } from "./logger-B9h0djqx.js";
|
|
3
|
-
import { i as versionString, n as displayVersion, r as getInstalledPackage, t as checkAndAutoUpdate } from "./versionChecker-
|
|
3
|
+
import { i as versionString, n as displayVersion, r as getInstalledPackage, t as checkAndAutoUpdate } from "./versionChecker-DdMHudEv.js";
|
|
4
4
|
import { argv } from "process";
|
|
5
5
|
import { execFileSync, spawn } from "child_process";
|
|
6
6
|
import ms from "ms";
|
|
@@ -482,7 +482,7 @@ function buildRustArgs(argv, cliFromScript, supportedClis) {
|
|
|
482
482
|
{
|
|
483
483
|
const rawArg = process.argv[2];
|
|
484
484
|
const isHelpFlag = rawArg === "-h" || rawArg === "--help";
|
|
485
|
-
const { isSubcommand, runSubcommand, cmdHelp } = await import("./subcommands-
|
|
485
|
+
const { isSubcommand, runSubcommand, cmdHelp } = await import("./subcommands-Clfntx3R.js");
|
|
486
486
|
if (isHelpFlag && process.argv.length === 3) {
|
|
487
487
|
cmdHelp();
|
|
488
488
|
process.exit(0);
|
|
@@ -515,7 +515,7 @@ if (config.useRust) {
|
|
|
515
515
|
}
|
|
516
516
|
}
|
|
517
517
|
if (rustBinary) {
|
|
518
|
-
const { SUPPORTED_CLIS } = await import("./SUPPORTED_CLIS-
|
|
518
|
+
const { SUPPORTED_CLIS } = await import("./SUPPORTED_CLIS-C6FspQLb.js");
|
|
519
519
|
const rustArgs = buildRustArgs(process.argv, config.cli, SUPPORTED_CLIS);
|
|
520
520
|
if (config.verbose) {
|
|
521
521
|
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-cYD43w4Z.js";
|
|
2
2
|
import "./logger-B9h0djqx.js";
|
|
3
|
-
import "./versionChecker-
|
|
3
|
+
import "./versionChecker-DdMHudEv.js";
|
|
4
4
|
import "./pidStore-DBjlqzo8.js";
|
|
5
5
|
import "./globalPidIndex-yVd3mbsV.js";
|
|
6
6
|
|
|
@@ -1,11 +1,11 @@
|
|
|
1
|
-
import "./ts-
|
|
1
|
+
import "./ts-cYD43w4Z.js";
|
|
2
2
|
import "./logger-B9h0djqx.js";
|
|
3
|
-
import "./versionChecker-
|
|
3
|
+
import "./versionChecker-DdMHudEv.js";
|
|
4
4
|
import "./pidStore-DBjlqzo8.js";
|
|
5
5
|
import "./globalPidIndex-yVd3mbsV.js";
|
|
6
|
-
import { t as SUPPORTED_CLIS } from "./SUPPORTED_CLIS-
|
|
6
|
+
import { t as SUPPORTED_CLIS } from "./SUPPORTED_CLIS-DZBdcl3r.js";
|
|
7
7
|
import "./remotes-C3xPRtfg.js";
|
|
8
|
-
import { c as readNotes, f as snapshotStatus, l as renderRawLog, m as writeToIpc, o as listRecords, r as controlCodeFromName, u as resolveOne } from "./subcommands-
|
|
8
|
+
import { c as readNotes, f as snapshotStatus, l as renderRawLog, m as writeToIpc, o as listRecords, r as controlCodeFromName, u as resolveOne } from "./subcommands-2xkgzhhI.js";
|
|
9
9
|
import yargs from "yargs";
|
|
10
10
|
import { mkdir, open, readFile, writeFile } from "fs/promises";
|
|
11
11
|
import { homedir } from "os";
|
|
@@ -482,6 +482,7 @@ Options:
|
|
|
482
482
|
const p = new URL(req.url).pathname;
|
|
483
483
|
if (req.method === "GET" && (p === "/" || p === "/index.html")) return serveUiFile("index.html", "text/html; charset=utf-8");
|
|
484
484
|
if (req.method === "GET" && p === "/room-client.js") return serveUiFile("room-client.js", "text/javascript; charset=utf-8");
|
|
485
|
+
if (req.method === "GET" && p === "/console-logic.js") return serveUiFile("console-logic.js", "text/javascript; charset=utf-8");
|
|
485
486
|
if (req.method === "GET" && p === "/favicon.ico") return new Response(null, { status: 204 });
|
|
486
487
|
return apiFetch(req);
|
|
487
488
|
};
|
|
@@ -551,4 +552,4 @@ Options:
|
|
|
551
552
|
|
|
552
553
|
//#endregion
|
|
553
554
|
export { cmdServe };
|
|
554
|
-
//# sourceMappingURL=serve-
|
|
555
|
+
//# sourceMappingURL=serve-D_NsFccM.js.map
|
|
@@ -163,7 +163,7 @@ async function runSubcommand(argv) {
|
|
|
163
163
|
case "restart": return await cmdRestart(rest);
|
|
164
164
|
case "note": return await cmdNote(rest);
|
|
165
165
|
case "serve": {
|
|
166
|
-
const { cmdServe } = await import("./serve-
|
|
166
|
+
const { cmdServe } = await import("./serve-D_NsFccM.js");
|
|
167
167
|
return cmdServe(rest);
|
|
168
168
|
}
|
|
169
169
|
case "setup": {
|
|
@@ -1452,4 +1452,4 @@ async function cmdStatus(rest) {
|
|
|
1452
1452
|
|
|
1453
1453
|
//#endregion
|
|
1454
1454
|
export { isSubcommand as a, readNotes as c, runSubcommand as d, snapshotStatus as f, isPidAlive as i, renderRawLog as l, writeToIpc as m, cmdHelp as n, listRecords as o, stopTipForCli as p, controlCodeFromName as r, matchKeyword as s, GRACEFUL_EXIT_COMMANDS as t, resolveOne as u };
|
|
1455
|
-
//# sourceMappingURL=subcommands-
|
|
1455
|
+
//# sourceMappingURL=subcommands-2xkgzhhI.js.map
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import "./logger-B9h0djqx.js";
|
|
2
2
|
import "./globalPidIndex-yVd3mbsV.js";
|
|
3
3
|
import "./remotes-C3xPRtfg.js";
|
|
4
|
-
import { a as isSubcommand, c as readNotes, d as runSubcommand, f as snapshotStatus, i as isPidAlive, l as renderRawLog, m as writeToIpc, n as cmdHelp, o as listRecords, p as stopTipForCli, r as controlCodeFromName, s as matchKeyword, t as GRACEFUL_EXIT_COMMANDS, u as resolveOne } from "./subcommands-
|
|
4
|
+
import { a as isSubcommand, c as readNotes, d as runSubcommand, f as snapshotStatus, i as isPidAlive, l as renderRawLog, m as writeToIpc, n as cmdHelp, o as listRecords, p as stopTipForCli, r as controlCodeFromName, s as matchKeyword, t as GRACEFUL_EXIT_COMMANDS, u as resolveOne } from "./subcommands-2xkgzhhI.js";
|
|
5
5
|
|
|
6
6
|
export { cmdHelp, isSubcommand, runSubcommand };
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { n as logger, t as addTransport } from "./logger-B9h0djqx.js";
|
|
2
|
-
import { r as getInstalledPackage } from "./versionChecker-
|
|
2
|
+
import { r as getInstalledPackage } from "./versionChecker-DdMHudEv.js";
|
|
3
3
|
import { n as agentYesHome, t as PidStore } from "./pidStore-DBjlqzo8.js";
|
|
4
4
|
import { i as shouldUseLock, r as releaseLock, t as acquireLock } from "./runningLock-CJxsoGdb.js";
|
|
5
5
|
import { i as readGlobalPids } from "./globalPidIndex-yVd3mbsV.js";
|
|
@@ -1714,4 +1714,4 @@ function sleep(ms) {
|
|
|
1714
1714
|
|
|
1715
1715
|
//#endregion
|
|
1716
1716
|
export { removeControlCharacters as a, AgentContext as i, agentYes as n, config as r, CLIS_CONFIG as t };
|
|
1717
|
-
//# sourceMappingURL=ts-
|
|
1717
|
+
//# sourceMappingURL=ts-cYD43w4Z.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.102.0";
|
|
11
11
|
|
|
12
12
|
//#endregion
|
|
13
13
|
//#region ts/versionChecker.ts
|
|
@@ -221,4 +221,4 @@ async function displayVersion() {
|
|
|
221
221
|
|
|
222
222
|
//#endregion
|
|
223
223
|
export { versionString as i, displayVersion as n, getInstalledPackage as r, checkAndAutoUpdate as t };
|
|
224
|
-
//# sourceMappingURL=versionChecker-
|
|
224
|
+
//# sourceMappingURL=versionChecker-DdMHudEv.js.map
|
|
@@ -0,0 +1,79 @@
|
|
|
1
|
+
// Pure, DOM-free logic for the agent-yes console (lab/ui/index.html).
|
|
2
|
+
//
|
|
3
|
+
// Extracted into its own ES module so it can be unit-tested in vitest
|
|
4
|
+
// (tests/ui-logic/console-logic.spec.ts) while the browser imports it directly
|
|
5
|
+
// — no build step. Everything here is a pure function of its arguments: no
|
|
6
|
+
// document/window/localStorage access, no Date.now() except via an injected
|
|
7
|
+
// `now` so age() is deterministic under test.
|
|
8
|
+
|
|
9
|
+
// An agent entry as surfaced by /api/ls (the fields this module reads):
|
|
10
|
+
// { cli, cwd, title, prompt, status, started_at, pid, _host }
|
|
11
|
+
|
|
12
|
+
// claude is the default CLI — show the cli name only when it differs, so the
|
|
13
|
+
// common case stays uncluttered and the identity (repo/branch) leads instead.
|
|
14
|
+
export const cliLabel = (e) => (e.cli && e.cli !== "claude" ? e.cli : "");
|
|
15
|
+
|
|
16
|
+
// Parse owner/repo/branch from a cwd like .../ws/<owner>/<repo>/tree/<branch>.
|
|
17
|
+
export function repoBranch(e) {
|
|
18
|
+
const m = /\/([^/]+)\/([^/]+)\/tree\/([^/]+)/.exec(e.cwd || "");
|
|
19
|
+
return m ? { owner: m[1], repo: m[2], branch: m[3] } : null;
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
// Identity string for the left panel. cap=true → repo/branch each clipped to
|
|
23
|
+
// 3 chars for the compact one-line view (e.g. "age/mai").
|
|
24
|
+
export function ident(e, cap) {
|
|
25
|
+
const rb = repoBranch(e);
|
|
26
|
+
if (!rb) return "";
|
|
27
|
+
const c = (s) => (cap && s.length > 3 ? s.slice(0, 3) : s);
|
|
28
|
+
return `${c(rb.repo)}/${c(rb.branch)}`;
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
// Derive codehost-style mnemonic tags from a cwd like .../ws/<owner>/<repo>/tree/<wt>.
|
|
32
|
+
export function tagsFor(e) {
|
|
33
|
+
const t = [];
|
|
34
|
+
const rb = repoBranch(e);
|
|
35
|
+
if (rb) {
|
|
36
|
+
t.push(["repo", `${rb.owner}/${rb.repo}`], ["wt", rb.branch]);
|
|
37
|
+
}
|
|
38
|
+
const cli = cliLabel(e);
|
|
39
|
+
if (cli) t.push(["cli", cli]);
|
|
40
|
+
if (e._host) t.push(["host", e._host]); // codehost rooms: which machine
|
|
41
|
+
return t;
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
// Human age of an agent ("12s" / "5m" / "3h"). `now` is injectable so tests
|
|
45
|
+
// don't depend on the wall clock; the browser calls age(e) and gets Date.now().
|
|
46
|
+
export function age(e, now = Date.now()) {
|
|
47
|
+
if (!e.started_at) return "";
|
|
48
|
+
const s = Math.max(0, (now - e.started_at) / 1000);
|
|
49
|
+
if (s < 60) return Math.floor(s) + "s";
|
|
50
|
+
if (s < 3600) return Math.floor(s / 60) + "m";
|
|
51
|
+
return Math.floor(s / 3600) + "h";
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
// Filter predicate: every space-separated token must match. A `key:value` token
|
|
55
|
+
// matches against the mnemonic tags (repo/wt/cli/host); a bare token is a
|
|
56
|
+
// case-insensitive substring search over title/prompt/cli/cwd/status.
|
|
57
|
+
export function matches(e, toks) {
|
|
58
|
+
const hay =
|
|
59
|
+
(e.title || "") + " " + (e.prompt || "") + " " + e.cli + " " + (e.cwd || "") + " " + e.status;
|
|
60
|
+
return toks.every((tok) => {
|
|
61
|
+
tok = tok.toLowerCase();
|
|
62
|
+
const ci = tok.indexOf(":");
|
|
63
|
+
if (ci > 0) {
|
|
64
|
+
const k = tok.slice(0, ci),
|
|
65
|
+
v = tok.slice(ci + 1);
|
|
66
|
+
return tagsFor(e).some(([tk, tv]) => tk === k && tv.toLowerCase().includes(v));
|
|
67
|
+
}
|
|
68
|
+
return hay.toLowerCase().includes(tok);
|
|
69
|
+
});
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
// Next selection index when stepping the list by `dir` (+1 down / -1 up).
|
|
73
|
+
// No current selection (i<0) lands on the first (down) or last (up) row;
|
|
74
|
+
// otherwise clamps at the ends. Returns -1 for an empty list.
|
|
75
|
+
export function nextIndex(len, i, dir) {
|
|
76
|
+
if (len <= 0) return -1;
|
|
77
|
+
if (i < 0) return dir > 0 ? 0 : len - 1;
|
|
78
|
+
return Math.max(0, Math.min(len - 1, i + dir));
|
|
79
|
+
}
|
package/lab/ui/index.html
CHANGED
|
@@ -650,7 +650,21 @@
|
|
|
650
650
|
<div class="launchoverlay" id="launch" style="display: none"></div>
|
|
651
651
|
<div class="launchoverlay" id="newform" style="display: none"></div>
|
|
652
652
|
|
|
653
|
-
<script>
|
|
653
|
+
<script type="module">
|
|
654
|
+
// Pure list/identity/filter helpers live in a sibling module so they can be
|
|
655
|
+
// unit-tested (tests/ui-logic/console-logic.spec.ts) without a DOM. This
|
|
656
|
+
// script is a module (deferred, runs after the codehost shim above sets
|
|
657
|
+
// window.__codehost), so a static import is safe.
|
|
658
|
+
import {
|
|
659
|
+
cliLabel,
|
|
660
|
+
repoBranch,
|
|
661
|
+
ident,
|
|
662
|
+
tagsFor,
|
|
663
|
+
age,
|
|
664
|
+
matches,
|
|
665
|
+
nextIndex,
|
|
666
|
+
} from "./console-logic.js";
|
|
667
|
+
|
|
654
668
|
let entries = [];
|
|
655
669
|
let sel = null; // selected keyword (pid as string)
|
|
656
670
|
let es = null; // live-tail subscription closer
|
|
@@ -984,66 +998,6 @@
|
|
|
984
998
|
},
|
|
985
999
|
};
|
|
986
1000
|
|
|
987
|
-
// claude is the default CLI — show the cli name only when it differs, so the
|
|
988
|
-
// common case stays uncluttered and the identity (repo/branch) leads instead.
|
|
989
|
-
const cliLabel = (e) => (e.cli && e.cli !== "claude" ? e.cli : "");
|
|
990
|
-
// Parse owner/repo/branch from a cwd like .../ws/<owner>/<repo>/tree/<branch>.
|
|
991
|
-
function repoBranch(e) {
|
|
992
|
-
const m = /\/([^/]+)\/([^/]+)\/tree\/([^/]+)/.exec(e.cwd || "");
|
|
993
|
-
return m ? { owner: m[1], repo: m[2], branch: m[3] } : null;
|
|
994
|
-
}
|
|
995
|
-
// Identity string for the left panel. cap=true → repo/branch each clipped to
|
|
996
|
-
// 3 chars for the compact one-line view (e.g. "age/mai").
|
|
997
|
-
function ident(e, cap) {
|
|
998
|
-
const rb = repoBranch(e);
|
|
999
|
-
if (!rb) return "";
|
|
1000
|
-
const c = (s) => (cap && s.length > 3 ? s.slice(0, 3) : s);
|
|
1001
|
-
return `${c(rb.repo)}/${c(rb.branch)}`;
|
|
1002
|
-
}
|
|
1003
|
-
|
|
1004
|
-
// Derive codehost-style mnemonic tags from a cwd like .../ws/<owner>/<repo>/tree/<wt>
|
|
1005
|
-
function tagsFor(e) {
|
|
1006
|
-
const t = [];
|
|
1007
|
-
const rb = repoBranch(e);
|
|
1008
|
-
if (rb) {
|
|
1009
|
-
t.push(["repo", `${rb.owner}/${rb.repo}`], ["wt", rb.branch]);
|
|
1010
|
-
}
|
|
1011
|
-
const cli = cliLabel(e);
|
|
1012
|
-
if (cli) t.push(["cli", cli]);
|
|
1013
|
-
if (e._host) t.push(["host", e._host]); // codehost rooms: which machine
|
|
1014
|
-
return t;
|
|
1015
|
-
}
|
|
1016
|
-
function age(e) {
|
|
1017
|
-
if (!e.started_at) return "";
|
|
1018
|
-
const s = Math.max(0, (Date.now() - e.started_at) / 1000);
|
|
1019
|
-
if (s < 60) return Math.floor(s) + "s";
|
|
1020
|
-
if (s < 3600) return Math.floor(s / 60) + "m";
|
|
1021
|
-
return Math.floor(s / 3600) + "h";
|
|
1022
|
-
}
|
|
1023
|
-
|
|
1024
|
-
function matches(e, toks) {
|
|
1025
|
-
const hay =
|
|
1026
|
-
(e.title || "") +
|
|
1027
|
-
" " +
|
|
1028
|
-
(e.prompt || "") +
|
|
1029
|
-
" " +
|
|
1030
|
-
e.cli +
|
|
1031
|
-
" " +
|
|
1032
|
-
(e.cwd || "") +
|
|
1033
|
-
" " +
|
|
1034
|
-
e.status;
|
|
1035
|
-
return toks.every((tok) => {
|
|
1036
|
-
tok = tok.toLowerCase();
|
|
1037
|
-
const ci = tok.indexOf(":");
|
|
1038
|
-
if (ci > 0) {
|
|
1039
|
-
const k = tok.slice(0, ci),
|
|
1040
|
-
v = tok.slice(ci + 1);
|
|
1041
|
-
return tagsFor(e).some(([tk, tv]) => tk === k && tv.toLowerCase().includes(v));
|
|
1042
|
-
}
|
|
1043
|
-
return hay.toLowerCase().includes(tok);
|
|
1044
|
-
});
|
|
1045
|
-
}
|
|
1046
|
-
|
|
1047
1001
|
// Compact list: one line per agent (dot + cli + title), persisted per device.
|
|
1048
1002
|
let compactList = localStorage.getItem("ay.compactList") === "1";
|
|
1049
1003
|
|
|
@@ -1238,6 +1192,32 @@
|
|
|
1238
1192
|
} catch {}
|
|
1239
1193
|
});
|
|
1240
1194
|
|
|
1195
|
+
// Step the selection up/down the (filtered) list — same order the left panel
|
|
1196
|
+
// renders. Clamps at the ends, scrolls the row into view.
|
|
1197
|
+
function stepSelection(dir) {
|
|
1198
|
+
const toks = $("q").value.trim().split(/\s+/).filter(Boolean);
|
|
1199
|
+
const shown = entries.filter((e) => matches(e, toks));
|
|
1200
|
+
if (!shown.length) return;
|
|
1201
|
+
const cur = shown.findIndex((e) => String(e.pid) === sel);
|
|
1202
|
+
const next = shown[nextIndex(shown.length, cur, dir)];
|
|
1203
|
+
select(String(next.pid));
|
|
1204
|
+
const row = $("list").querySelector('.row[data-pid="' + next.pid + '"]');
|
|
1205
|
+
if (row) row.scrollIntoView({ block: "nearest" });
|
|
1206
|
+
}
|
|
1207
|
+
// Alt+PageDown / Alt+PageUp cycles agents. Capture phase on window so it
|
|
1208
|
+
// fires BEFORE xterm's textarea handler — stopPropagation then keeps the
|
|
1209
|
+
// combo from being forwarded to the focused agent's PTY as keystrokes.
|
|
1210
|
+
window.addEventListener(
|
|
1211
|
+
"keydown",
|
|
1212
|
+
(e) => {
|
|
1213
|
+
if (!e.altKey || (e.key !== "PageDown" && e.key !== "PageUp")) return;
|
|
1214
|
+
e.preventDefault();
|
|
1215
|
+
e.stopPropagation();
|
|
1216
|
+
stepSelection(e.key === "PageDown" ? 1 : -1);
|
|
1217
|
+
},
|
|
1218
|
+
true,
|
|
1219
|
+
);
|
|
1220
|
+
|
|
1241
1221
|
// ---- rooms: localStorage cache + a manager you open by clicking the badge ----
|
|
1242
1222
|
const ROOMS_KEY = "ay.rooms";
|
|
1243
1223
|
let curRoom = null;
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "agent-yes",
|
|
3
|
-
"version": "1.
|
|
3
|
+
"version": "1.102.0",
|
|
4
4
|
"description": "A wrapper tool that automates interactions with various AI CLI tools by automatically handling common prompts and responses.",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"ai",
|
|
@@ -55,6 +55,7 @@
|
|
|
55
55
|
"ts/*.ts",
|
|
56
56
|
"!dist/**/*.map",
|
|
57
57
|
"dist/**/*.js",
|
|
58
|
+
"lab/ui/console-logic.js",
|
|
58
59
|
"lab/ui/index.html",
|
|
59
60
|
"lab/ui/room-client.js"
|
|
60
61
|
],
|
|
@@ -86,7 +87,8 @@
|
|
|
86
87
|
"release:beta": "standard-version && npm publish --tag beta",
|
|
87
88
|
"test": "vitest run",
|
|
88
89
|
"test:coverage": "vitest run --coverage",
|
|
89
|
-
"test:ui": "vitest run --config tests/ui-test/vitest.config.ts"
|
|
90
|
+
"test:ui": "vitest run --config tests/ui-test/vitest.config.ts",
|
|
91
|
+
"test:ui-dom": "vitest run --config tests/ui-dom/vitest.config.ts"
|
|
90
92
|
},
|
|
91
93
|
"dependencies": {
|
|
92
94
|
"@snomiao/bun-pty": "^0.3.4",
|
package/ts/serve.ts
CHANGED
|
@@ -620,6 +620,8 @@ export async function cmdServe(rest: string[]): Promise<number> {
|
|
|
620
620
|
return serveUiFile("index.html", "text/html; charset=utf-8");
|
|
621
621
|
if (req.method === "GET" && p === "/room-client.js")
|
|
622
622
|
return serveUiFile("room-client.js", "text/javascript; charset=utf-8");
|
|
623
|
+
if (req.method === "GET" && p === "/console-logic.js")
|
|
624
|
+
return serveUiFile("console-logic.js", "text/javascript; charset=utf-8");
|
|
623
625
|
if (req.method === "GET" && p === "/favicon.ico") return new Response(null, { status: 204 });
|
|
624
626
|
return apiFetch(req);
|
|
625
627
|
};
|
|
@@ -0,0 +1,71 @@
|
|
|
1
|
+
import { afterEach, beforeEach, describe, expect, it } from "vitest";
|
|
2
|
+
import { mkdtempSync, rmSync } from "fs";
|
|
3
|
+
import { homedir, tmpdir } from "os";
|
|
4
|
+
import path from "path";
|
|
5
|
+
import {
|
|
6
|
+
expandTilde,
|
|
7
|
+
getWorkspaceRoot,
|
|
8
|
+
resolveSpawnCwd,
|
|
9
|
+
setWorkspaceRoot,
|
|
10
|
+
} from "./workspaceConfig.ts";
|
|
11
|
+
|
|
12
|
+
describe("workspaceConfig", () => {
|
|
13
|
+
let original: string | undefined;
|
|
14
|
+
let tmp: string;
|
|
15
|
+
beforeEach(() => {
|
|
16
|
+
original = process.env.AGENT_YES_HOME;
|
|
17
|
+
tmp = mkdtempSync(path.join(tmpdir(), "ay-cfg-"));
|
|
18
|
+
process.env.AGENT_YES_HOME = tmp;
|
|
19
|
+
});
|
|
20
|
+
afterEach(() => {
|
|
21
|
+
if (original === undefined) delete process.env.AGENT_YES_HOME;
|
|
22
|
+
else process.env.AGENT_YES_HOME = original;
|
|
23
|
+
rmSync(tmp, { recursive: true, force: true });
|
|
24
|
+
});
|
|
25
|
+
|
|
26
|
+
it("defaults the workspace root to the home dir when unset", () => {
|
|
27
|
+
expect(getWorkspaceRoot()).toBe(homedir());
|
|
28
|
+
});
|
|
29
|
+
|
|
30
|
+
it("round-trips set/get and resolves to an absolute path", () => {
|
|
31
|
+
const saved = setWorkspaceRoot(path.join(tmp, "ws"));
|
|
32
|
+
expect(saved).toBe(path.join(tmp, "ws"));
|
|
33
|
+
expect(getWorkspaceRoot()).toBe(path.join(tmp, "ws"));
|
|
34
|
+
});
|
|
35
|
+
|
|
36
|
+
it("expands a leading ~", () => {
|
|
37
|
+
expect(expandTilde("~")).toBe(homedir());
|
|
38
|
+
expect(expandTilde("~/projects")).toBe(path.join(homedir(), "projects"));
|
|
39
|
+
expect(expandTilde("/abs/path")).toBe("/abs/path");
|
|
40
|
+
});
|
|
41
|
+
|
|
42
|
+
it("stores a tilde path as home-based absolute", () => {
|
|
43
|
+
const saved = setWorkspaceRoot("~/myws");
|
|
44
|
+
expect(saved).toBe(path.join(homedir(), "myws"));
|
|
45
|
+
});
|
|
46
|
+
|
|
47
|
+
describe("resolveSpawnCwd", () => {
|
|
48
|
+
beforeEach(() => setWorkspaceRoot(path.join(tmp, "ws")));
|
|
49
|
+
|
|
50
|
+
it("empty input → workspace root", () => {
|
|
51
|
+
expect(resolveSpawnCwd("")).toBe(path.join(tmp, "ws"));
|
|
52
|
+
expect(resolveSpawnCwd(undefined)).toBe(path.join(tmp, "ws"));
|
|
53
|
+
});
|
|
54
|
+
|
|
55
|
+
it("bare name → <workspace>/<name>", () => {
|
|
56
|
+
expect(resolveSpawnCwd("myproject")).toBe(path.join(tmp, "ws", "myproject"));
|
|
57
|
+
});
|
|
58
|
+
|
|
59
|
+
it("absolute path → used as-is", () => {
|
|
60
|
+
expect(resolveSpawnCwd("/tmp/elsewhere")).toBe("/tmp/elsewhere");
|
|
61
|
+
});
|
|
62
|
+
|
|
63
|
+
it("tilde path → home-based", () => {
|
|
64
|
+
expect(resolveSpawnCwd("~/docs")).toBe(path.join(homedir(), "docs"));
|
|
65
|
+
});
|
|
66
|
+
|
|
67
|
+
it("a relative path with a separator is resolved, not joined to the workspace", () => {
|
|
68
|
+
expect(resolveSpawnCwd("a/b")).toBe(path.resolve("a/b"));
|
|
69
|
+
});
|
|
70
|
+
});
|
|
71
|
+
});
|
|
@@ -0,0 +1,70 @@
|
|
|
1
|
+
import { mkdirSync, readFileSync, writeFileSync } from "fs";
|
|
2
|
+
import { homedir } from "os";
|
|
3
|
+
import path from "path";
|
|
4
|
+
import { agentYesHome } from "./agentYesHome.ts";
|
|
5
|
+
|
|
6
|
+
/**
|
|
7
|
+
* Machine-global agent-yes config (workspace root, etc.), stored alongside the
|
|
8
|
+
* pid index and serve token under `agentYesHome()`. Kept tiny and synchronous —
|
|
9
|
+
* it's read on the spawn hot path and written once during `ay setup`.
|
|
10
|
+
*
|
|
11
|
+
* The *workspace root* is the default directory new agents are spawned into when
|
|
12
|
+
* the console doesn't pass an explicit cwd. It defaults to the user's home dir so
|
|
13
|
+
* a non-engineer can just run agents in their files without knowing about paths.
|
|
14
|
+
*/
|
|
15
|
+
|
|
16
|
+
interface Config {
|
|
17
|
+
workspace?: string;
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
function configPath(): string {
|
|
21
|
+
return path.join(agentYesHome(), "config.json");
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
function readConfig(): Config {
|
|
25
|
+
try {
|
|
26
|
+
return JSON.parse(readFileSync(configPath(), "utf-8")) as Config;
|
|
27
|
+
} catch {
|
|
28
|
+
return {};
|
|
29
|
+
}
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
/** Expand a leading `~` (`~` or `~/x`) to an absolute home-based path. */
|
|
33
|
+
export function expandTilde(p: string): string {
|
|
34
|
+
const s = p.trim();
|
|
35
|
+
if (s === "~") return homedir();
|
|
36
|
+
if (s.startsWith("~/") || s.startsWith("~\\")) return path.join(homedir(), s.slice(2));
|
|
37
|
+
return s;
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
/** The configured workspace root (absolute), or the home dir if unset. */
|
|
41
|
+
export function getWorkspaceRoot(): string {
|
|
42
|
+
const w = readConfig().workspace;
|
|
43
|
+
return w && w.trim() ? w : homedir();
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
/** Persist the workspace root, tilde-expanded and resolved to an absolute path. */
|
|
47
|
+
export function setWorkspaceRoot(dir: string): string {
|
|
48
|
+
const abs = path.resolve(expandTilde(dir));
|
|
49
|
+
const cfg = readConfig();
|
|
50
|
+
cfg.workspace = abs;
|
|
51
|
+
mkdirSync(agentYesHome(), { recursive: true });
|
|
52
|
+
writeFileSync(configPath(), JSON.stringify(cfg, null, 2));
|
|
53
|
+
return abs;
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
/**
|
|
57
|
+
* Resolve a user-supplied spawn location to an absolute cwd:
|
|
58
|
+
* - empty → the workspace root
|
|
59
|
+
* - a bare name → `<workspace>/<name>` (so "myproject" lands under the root)
|
|
60
|
+
* - `~`-prefixed → home-based absolute
|
|
61
|
+
* - anything with a path separator → resolved as-is
|
|
62
|
+
*/
|
|
63
|
+
export function resolveSpawnCwd(input?: string): string {
|
|
64
|
+
const root = getWorkspaceRoot();
|
|
65
|
+
const v = (input ?? "").trim();
|
|
66
|
+
if (!v) return root;
|
|
67
|
+
if (v.startsWith("~")) return path.resolve(expandTilde(v));
|
|
68
|
+
if (v.includes("/") || v.includes("\\") || path.isAbsolute(v)) return path.resolve(v);
|
|
69
|
+
return path.join(root, v);
|
|
70
|
+
}
|
|
@@ -1,8 +0,0 @@
|
|
|
1
|
-
import "./ts-CUn393DD.js";
|
|
2
|
-
import "./logger-B9h0djqx.js";
|
|
3
|
-
import "./versionChecker-BWdncsn6.js";
|
|
4
|
-
import "./pidStore-DBjlqzo8.js";
|
|
5
|
-
import "./globalPidIndex-yVd3mbsV.js";
|
|
6
|
-
import { t as SUPPORTED_CLIS } from "./SUPPORTED_CLIS-DIHMEdRx.js";
|
|
7
|
-
|
|
8
|
-
export { SUPPORTED_CLIS };
|