claude-yes 1.149.3 → 1.151.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-B52NvCuZ.js → SUPPORTED_CLIS-DLTCkxyO.js} +2 -2
- package/dist/SUPPORTED_CLIS-k3QHErEI.js +8 -0
- package/dist/cli.js +3 -3
- package/dist/index.js +2 -2
- package/dist/{schedule-BBxvNa3v.js → schedule-DeyoL8rw.js} +4 -4
- package/dist/{serve-CC4R9M3V.js → serve-ClS-lrfi.js} +43 -8
- package/dist/{setup-CKRssOuZ.js → setup-D2MYNwa9.js} +2 -2
- package/dist/{subcommands-CU3G6_N5.js → subcommands-BRNq_oYW.js} +1 -1
- package/dist/{subcommands-Dl8RuPbC.js → subcommands-CUHrqQ1h.js} +4 -4
- package/dist/{ts-DIrs0jef.js → ts-C1_ppO89.js} +2 -2
- package/dist/{versionChecker-D0pC8VFv.js → versionChecker-BvGC9SmN.js} +2 -2
- package/lab/ui/console-logic.js +12 -3
- package/lab/ui/index.html +62 -2
- package/package.json +1 -1
- package/ts/serve.ts +80 -5
- package/dist/SUPPORTED_CLIS-Cx4SPJk7.js +0 -8
|
@@ -1,8 +1,8 @@
|
|
|
1
|
-
import { t as CLIS_CONFIG } from "./ts-
|
|
1
|
+
import { t as CLIS_CONFIG } from "./ts-C1_ppO89.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-DLTCkxyO.js.map
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
import "./ts-C1_ppO89.js";
|
|
2
|
+
import "./logger-CDIsZ-Pp.js";
|
|
3
|
+
import "./versionChecker-BvGC9SmN.js";
|
|
4
|
+
import "./pidStore-fqXqTKkh.js";
|
|
5
|
+
import "./globalPidIndex-DlmmJlO8.js";
|
|
6
|
+
import { t as SUPPORTED_CLIS } from "./SUPPORTED_CLIS-DLTCkxyO.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-uqM2YYA7.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-BvGC9SmN.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-BRNq_oYW.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-k3QHErEI.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-C1_ppO89.js";
|
|
2
2
|
import "./logger-CDIsZ-Pp.js";
|
|
3
|
-
import "./versionChecker-
|
|
3
|
+
import "./versionChecker-BvGC9SmN.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-C1_ppO89.js";
|
|
2
2
|
import "./logger-CDIsZ-Pp.js";
|
|
3
|
-
import "./versionChecker-
|
|
3
|
+
import "./versionChecker-BvGC9SmN.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-DLTCkxyO.js";
|
|
7
7
|
import { i as resolveSpawnCwd } from "./workspaceConfig-B9VX8tVO.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-DeyoL8rw.js.map
|
|
@@ -1,20 +1,21 @@
|
|
|
1
|
-
import "./ts-
|
|
1
|
+
import "./ts-C1_ppO89.js";
|
|
2
2
|
import "./logger-CDIsZ-Pp.js";
|
|
3
|
-
import { r as getInstalledPackage } from "./versionChecker-
|
|
3
|
+
import { r as getInstalledPackage } from "./versionChecker-BvGC9SmN.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-DLTCkxyO.js";
|
|
9
9
|
import "./e2e-ClOI_aqV.js";
|
|
10
10
|
import "./webrtcLink-BWhuA74k.js";
|
|
11
11
|
import "./remotes-qK6uozO4.js";
|
|
12
12
|
import { i as resolveSpawnCwd, r as isProvisionAllowed, t as getProvisionRoot } from "./workspaceConfig-B9VX8tVO.js";
|
|
13
|
-
import { C as snapshotStatus, T as writeToIpc, _ as readPtysize, b as resolveOne, c as extractTaskCounts, g as readNotes, i as controlCodeFromName, m as listRecords, o as deriveLiveStatus, v as renderRawLog } from "./subcommands-
|
|
13
|
+
import { C as snapshotStatus, T as writeToIpc, _ as readPtysize, b as resolveOne, c as extractTaskCounts, g as readNotes, i as controlCodeFromName, m as listRecords, o as deriveLiveStatus, v as renderRawLog } from "./subcommands-CUHrqQ1h.js";
|
|
14
14
|
import yargs from "yargs";
|
|
15
15
|
import { mkdir, open, readFile, stat, writeFile } from "fs/promises";
|
|
16
16
|
import { homedir, hostname, userInfo } from "os";
|
|
17
17
|
import path from "path";
|
|
18
|
+
import { execFileSync } from "node:child_process";
|
|
18
19
|
import { fileURLToPath } from "node:url";
|
|
19
20
|
import { renameSync, watch, writeFileSync } from "node:fs";
|
|
20
21
|
import { randomBytes, timingSafeEqual } from "crypto";
|
|
@@ -774,7 +775,12 @@ Options:
|
|
|
774
775
|
if (req.method === "GET" && p === "/api/whoami") {
|
|
775
776
|
let user = "";
|
|
776
777
|
try {
|
|
777
|
-
|
|
778
|
+
const u = userInfo().username;
|
|
779
|
+
if (u && u !== "unknown") user = u;
|
|
780
|
+
} catch {}
|
|
781
|
+
user ||= process.env.USER || process.env.LOGNAME || process.env.USERNAME || "";
|
|
782
|
+
if (!user && process.platform !== "win32") try {
|
|
783
|
+
user = execFileSync("id", ["-un"], { encoding: "utf8" }).trim();
|
|
778
784
|
} catch {}
|
|
779
785
|
const host = hostname();
|
|
780
786
|
return Response.json({ host: user ? `${user}@${host}` : host });
|
|
@@ -1046,8 +1052,37 @@ Options:
|
|
|
1046
1052
|
const prompt = String(body.prompt ?? "");
|
|
1047
1053
|
let cwd;
|
|
1048
1054
|
let provisioned = null;
|
|
1055
|
+
const fork = body.fork && typeof body.fork.fromCwd === "string" && typeof body.fork.branch === "string" ? {
|
|
1056
|
+
fromCwd: body.fork.fromCwd,
|
|
1057
|
+
branch: body.fork.branch
|
|
1058
|
+
} : null;
|
|
1049
1059
|
const from = typeof body.from === "string" ? body.from.trim() : "";
|
|
1050
|
-
if (
|
|
1060
|
+
if (fork) {
|
|
1061
|
+
let prov;
|
|
1062
|
+
try {
|
|
1063
|
+
prov = await import("codehost/provision");
|
|
1064
|
+
} catch (e) {
|
|
1065
|
+
return new Response(`fork needs the 'codehost' package (codehost/provision) — install it (npm i -g codehost) or 'bun link' it for local dev: ${e.message}`, { status: 501 });
|
|
1066
|
+
}
|
|
1067
|
+
let result;
|
|
1068
|
+
try {
|
|
1069
|
+
const wsRoot = getProvisionRoot();
|
|
1070
|
+
result = await prov.forkWorktree({
|
|
1071
|
+
fromCwd: fork.fromCwd,
|
|
1072
|
+
branch: fork.branch,
|
|
1073
|
+
...wsRoot ? { wsRoot } : {}
|
|
1074
|
+
});
|
|
1075
|
+
} catch (e) {
|
|
1076
|
+
return new Response(`fork failed: ${e.message}`, { status: 502 });
|
|
1077
|
+
}
|
|
1078
|
+
if (!result?.ok) return new Response(result?.error ?? "fork failed", { status: 502 });
|
|
1079
|
+
if (result.spec && !isProvisionAllowed(result.spec.owner, result.spec.repo)) return new Response(`forking '${result.spec.owner}/${result.spec.repo}' is not allowed — add the owner to provisionAllowlist in ~/.agent-yes/config.json (or "*" to allow all)`, { status: 403 });
|
|
1080
|
+
cwd = result.folder;
|
|
1081
|
+
provisioned = {
|
|
1082
|
+
action: result.action,
|
|
1083
|
+
folder: result.folder
|
|
1084
|
+
};
|
|
1085
|
+
} else if (from) {
|
|
1051
1086
|
let prov;
|
|
1052
1087
|
try {
|
|
1053
1088
|
prov = await import("codehost/provision");
|
|
@@ -1083,7 +1118,7 @@ Options:
|
|
|
1083
1118
|
return new Response(`cannot create cwd ${cwd}: ${e.message}`, { status: 500 });
|
|
1084
1119
|
}
|
|
1085
1120
|
}
|
|
1086
|
-
process.stderr.write(`→ console spawned: ay ${cli}${prompt ? ` -- "${prompt.slice(0, 60)}"` : ""} (cwd: ${cwd}${provisioned ? `, ${provisioned.action}
|
|
1121
|
+
process.stderr.write(`→ console spawned: ay ${cli}${prompt ? ` -- "${prompt.slice(0, 60)}"` : ""} (cwd: ${cwd}${provisioned ? `, ${provisioned.action}` : ""})\n`);
|
|
1087
1122
|
const ayBin = Bun.which("ay") ?? process.argv[1];
|
|
1088
1123
|
const ayCmd = process.platform === "win32" && ayBin.toLowerCase().endsWith(".exe") ? [ayBin] : [process.execPath, ayBin];
|
|
1089
1124
|
try {
|
|
@@ -1230,4 +1265,4 @@ Options:
|
|
|
1230
1265
|
|
|
1231
1266
|
//#endregion
|
|
1232
1267
|
export { cmdServe };
|
|
1233
|
-
//# sourceMappingURL=serve-
|
|
1268
|
+
//# sourceMappingURL=serve-ClS-lrfi.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-ClS-lrfi.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-D2MYNwa9.js.map
|
|
@@ -4,6 +4,6 @@ import "./configShared-C1C04bbq.js";
|
|
|
4
4
|
import "./e2e-ClOI_aqV.js";
|
|
5
5
|
import "./webrtcLink-BWhuA74k.js";
|
|
6
6
|
import "./remotes-qK6uozO4.js";
|
|
7
|
-
import { C as snapshotStatus, S as runSubcommand, T as writeToIpc, _ as readPtysize, a as cursorAbs, b as resolveOne, c as extractTaskCounts, d as isExitRequest, f as isPidAlive, g as readNotes, h as matchKeyword, i as controlCodeFromName, l as finalizedLines, m as listRecords, n as READ_PAGE_DEFAULT, o as deriveLiveStatus, p as isSubcommand, r as cmdHelp, s as extractNeedsInput, t as GRACEFUL_EXIT_COMMANDS, u as isAgentStuck, v as renderRawLog, w as stopTipForCli, x as resolveReadWindow, y as renderRawLogLines } from "./subcommands-
|
|
7
|
+
import { C as snapshotStatus, S as runSubcommand, T as writeToIpc, _ as readPtysize, a as cursorAbs, b as resolveOne, c as extractTaskCounts, d as isExitRequest, f as isPidAlive, g as readNotes, h as matchKeyword, i as controlCodeFromName, l as finalizedLines, m as listRecords, n as READ_PAGE_DEFAULT, o as deriveLiveStatus, p as isSubcommand, r as cmdHelp, s as extractNeedsInput, t as GRACEFUL_EXIT_COMMANDS, u as isAgentStuck, v as renderRawLog, w as stopTipForCli, x as resolveReadWindow, y as renderRawLogLines } from "./subcommands-CUHrqQ1h.js";
|
|
8
8
|
|
|
9
9
|
export { cmdHelp, isSubcommand, runSubcommand };
|
|
@@ -554,15 +554,15 @@ async function runSubcommand(argv) {
|
|
|
554
554
|
case "restart": return await cmdRestart(rest);
|
|
555
555
|
case "note": return await cmdNote(rest);
|
|
556
556
|
case "serve": {
|
|
557
|
-
const { cmdServe } = await import("./serve-
|
|
557
|
+
const { cmdServe } = await import("./serve-ClS-lrfi.js");
|
|
558
558
|
return cmdServe(rest);
|
|
559
559
|
}
|
|
560
560
|
case "setup": {
|
|
561
|
-
const { cmdSetup } = await import("./setup-
|
|
561
|
+
const { cmdSetup } = await import("./setup-D2MYNwa9.js");
|
|
562
562
|
return cmdSetup(rest);
|
|
563
563
|
}
|
|
564
564
|
case "schedule": {
|
|
565
|
-
const { cmdSchedule } = await import("./schedule-
|
|
565
|
+
const { cmdSchedule } = await import("./schedule-DeyoL8rw.js");
|
|
566
566
|
return cmdSchedule(rest);
|
|
567
567
|
}
|
|
568
568
|
case "remote": {
|
|
@@ -2619,4 +2619,4 @@ async function cmdResultSet(rest) {
|
|
|
2619
2619
|
|
|
2620
2620
|
//#endregion
|
|
2621
2621
|
export { snapshotStatus as C, runSubcommand as S, writeToIpc as T, readPtysize as _, cursorAbs as a, resolveOne as b, extractTaskCounts as c, isExitRequest as d, isPidAlive as f, readNotes as g, matchKeyword as h, controlCodeFromName as i, finalizedLines as l, listRecords as m, READ_PAGE_DEFAULT as n, deriveLiveStatus as o, isSubcommand as p, cmdHelp as r, extractNeedsInput as s, GRACEFUL_EXIT_COMMANDS as t, isAgentStuck as u, renderRawLog as v, stopTipForCli as w, resolveReadWindow as x, renderRawLogLines as y };
|
|
2622
|
-
//# sourceMappingURL=subcommands-
|
|
2622
|
+
//# sourceMappingURL=subcommands-CUHrqQ1h.js.map
|
|
@@ -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-BvGC9SmN.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";
|
|
@@ -1802,4 +1802,4 @@ function sleep(ms) {
|
|
|
1802
1802
|
|
|
1803
1803
|
//#endregion
|
|
1804
1804
|
export { removeControlCharacters as a, AgentContext as i, agentYes as n, config as r, CLIS_CONFIG as t };
|
|
1805
|
-
//# sourceMappingURL=ts-
|
|
1805
|
+
//# sourceMappingURL=ts-C1_ppO89.js.map
|
|
@@ -7,7 +7,7 @@ import { fileURLToPath } from "url";
|
|
|
7
7
|
|
|
8
8
|
//#region package.json
|
|
9
9
|
var name = "claude-yes";
|
|
10
|
-
var version = "1.
|
|
10
|
+
var version = "1.151.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-BvGC9SmN.js.map
|
package/lab/ui/console-logic.js
CHANGED
|
@@ -13,6 +13,14 @@
|
|
|
13
13
|
// common case stays uncluttered and the identity (repo/branch) leads instead.
|
|
14
14
|
export const cliLabel = (e) => (e.cli && e.cli !== "claude" ? e.cli : "");
|
|
15
15
|
|
|
16
|
+
// Windows daemons report cwds with backslashes (C:\Users\…\tree\main); every
|
|
17
|
+
// cwd parser/comparator below assumes forward slashes, so normalize once here.
|
|
18
|
+
// Without this a Windows host's agents parse no owner/repo/branch and render as
|
|
19
|
+
// a bare "user@host://" with no path identity.
|
|
20
|
+
export function normCwd(cwd) {
|
|
21
|
+
return (cwd || "").replace(/\\/g, "/");
|
|
22
|
+
}
|
|
23
|
+
|
|
16
24
|
// Parse owner/repo/branch from a cwd like .../ws/<owner>/<repo>/tree/<branch>.
|
|
17
25
|
// A cwd inside a git submodule keeps trailing path after the worktree branch
|
|
18
26
|
// (e.g. .../tree/share/lib/bot, where lib/bot is a submodule). The owner/repo/
|
|
@@ -21,7 +29,7 @@ export const cliLabel = (e) => (e.cli && e.cli !== "claude" ? e.cli : "");
|
|
|
21
29
|
// leaf dir as `sub` to keep nested repos distinguishable. `sub` is "" when the
|
|
22
30
|
// cwd is the worktree root.
|
|
23
31
|
export function repoBranch(e) {
|
|
24
|
-
const m = /\/([^/]+)\/([^/]+)\/tree\/([^/]+)(\/.*)?$/.exec(e.cwd
|
|
32
|
+
const m = /\/([^/]+)\/([^/]+)\/tree\/([^/]+)(\/.*)?$/.exec(normCwd(e.cwd));
|
|
25
33
|
if (!m) return null;
|
|
26
34
|
const sub = (m[4] || "").split("/").filter(Boolean).pop() || "";
|
|
27
35
|
return { owner: m[1], repo: m[2], branch: m[3], sub };
|
|
@@ -261,13 +269,14 @@ function agentForestNodes(list) {
|
|
|
261
269
|
if (parentOf.has(e) || !e.cwd) continue;
|
|
262
270
|
const rb = repoBranch(e);
|
|
263
271
|
if (!rb) continue;
|
|
272
|
+
const ecwd = normCwd(e.cwd);
|
|
264
273
|
let best = null;
|
|
265
274
|
for (const c of list) {
|
|
266
|
-
if (c === e || !c.cwd || !
|
|
275
|
+
if (c === e || !c.cwd || !ecwd.startsWith(normCwd(c.cwd) + "/")) continue;
|
|
267
276
|
const crb = repoBranch(c);
|
|
268
277
|
if (!crb || crb.owner !== rb.owner || crb.repo !== rb.repo || crb.branch !== rb.branch)
|
|
269
278
|
continue;
|
|
270
|
-
if (!best || c.cwd.length > best.cwd.length) best = c;
|
|
279
|
+
if (!best || normCwd(c.cwd).length > normCwd(best.cwd).length) best = c;
|
|
271
280
|
}
|
|
272
281
|
if (best) parentOf.set(e, best);
|
|
273
282
|
}
|
package/lab/ui/index.html
CHANGED
|
@@ -3794,6 +3794,18 @@
|
|
|
3794
3794
|
}, 120);
|
|
3795
3795
|
}
|
|
3796
3796
|
|
|
3797
|
+
// Auto-derive a branch name from the typed prompt for the Cmd+K fork action
|
|
3798
|
+
// (editable at launch). e.g. "fix the auth bug" → "fork/fix-the-auth-bug".
|
|
3799
|
+
function forkSlug(q) {
|
|
3800
|
+
const s = q
|
|
3801
|
+
.toLowerCase()
|
|
3802
|
+
.replace(/[^a-z0-9]+/g, "-")
|
|
3803
|
+
.replace(/^-+|-+$/g, "")
|
|
3804
|
+
.slice(0, 40)
|
|
3805
|
+
.replace(/-+$/, "");
|
|
3806
|
+
return "fork/" + (s || "wip");
|
|
3807
|
+
}
|
|
3808
|
+
|
|
3797
3809
|
function renderOmni() {
|
|
3798
3810
|
const q = $("omni-input").value.trim();
|
|
3799
3811
|
if (omniIdx >= omniRows.length) omniIdx = Math.max(0, omniRows.length - 1);
|
|
@@ -3809,6 +3821,22 @@
|
|
|
3809
3821
|
<div class="omni-sub">${esc(anchor?.cwd || "(host default)")} · prompt: ${esc(q || "(empty)")}</div>
|
|
3810
3822
|
</div></div>`;
|
|
3811
3823
|
}
|
|
3824
|
+
if (r.kind === "fork") {
|
|
3825
|
+
return `<div class="omni-row omni-spawn${sc}" data-i="${i}">
|
|
3826
|
+
<span class="dot active"></span>
|
|
3827
|
+
<div class="omni-main">
|
|
3828
|
+
<div class="omni-title">⑂ Fork current branch & run <span style="opacity:.55">(carries uncommitted work)</span></div>
|
|
3829
|
+
<div class="omni-sub">${esc(anchor?.cwd || "?")} → new branch <b>${esc(r.branch)}</b> · ⏎ to edit & launch</div>
|
|
3830
|
+
</div></div>`;
|
|
3831
|
+
}
|
|
3832
|
+
if (r.kind === "spawncwd") {
|
|
3833
|
+
return `<div class="omni-row omni-spawn${sc}" data-i="${i}">
|
|
3834
|
+
<span class="dot active"></span>
|
|
3835
|
+
<div class="omni-main">
|
|
3836
|
+
<div class="omni-title">⊕ Spawn new ${esc(anchor?.cli || "claude")} agent in a directory…</div>
|
|
3837
|
+
<div class="omni-sub">⏎ to choose a working dir · prompt: ${esc(q || "(empty)")}</div>
|
|
3838
|
+
</div></div>`;
|
|
3839
|
+
}
|
|
3812
3840
|
const e = r.entry;
|
|
3813
3841
|
const snip = r.snippet ? `<div class="omni-snip">…${r.snippet}…</div>` : "";
|
|
3814
3842
|
return `<div class="omni-row${sc}" data-i="${i}">
|
|
@@ -3837,7 +3865,12 @@
|
|
|
3837
3865
|
)
|
|
3838
3866
|
.slice(0, 30);
|
|
3839
3867
|
omniRows = hits.map((entry) => ({ kind: "agent", entry }));
|
|
3840
|
-
if (q)
|
|
3868
|
+
if (q) {
|
|
3869
|
+
omniRows.push({ kind: "spawn" });
|
|
3870
|
+
const anchor = omniAnchor();
|
|
3871
|
+
if (anchor?.cwd) omniRows.push({ kind: "fork", branch: forkSlug(q) });
|
|
3872
|
+
omniRows.push({ kind: "spawncwd" });
|
|
3873
|
+
}
|
|
3841
3874
|
omniIdx = 0;
|
|
3842
3875
|
renderOmni();
|
|
3843
3876
|
// Tier 2 — debounced output (tail) search for alive agents not already shown.
|
|
@@ -3902,8 +3935,9 @@
|
|
|
3902
3935
|
async function omniActivate(forceSpawn) {
|
|
3903
3936
|
const q = $("omni-input").value.trim();
|
|
3904
3937
|
const row = omniRows[omniIdx];
|
|
3938
|
+
const anchor = omniAnchor();
|
|
3939
|
+
// ⌘⏎ always = spawn-here (the fast default), regardless of the selected row.
|
|
3905
3940
|
if (forceSpawn || (row && row.kind === "spawn")) {
|
|
3906
|
-
const anchor = omniAnchor();
|
|
3907
3941
|
closeOmni(false); // committing — keep the bg as-is, spawnAndSelect takes over
|
|
3908
3942
|
await spawnAndSelect(
|
|
3909
3943
|
{ cli: anchor?.cli || "claude", cwd: anchor?.cwd || undefined, prompt: q || undefined },
|
|
@@ -3911,6 +3945,31 @@
|
|
|
3911
3945
|
);
|
|
3912
3946
|
return;
|
|
3913
3947
|
}
|
|
3948
|
+
if (row && row.kind === "fork") {
|
|
3949
|
+
// Editable at launch (auto-slug is the default); carries the anchor's WIP.
|
|
3950
|
+
const branch = prompt("Fork to a new branch (carries your uncommitted work):", row.branch);
|
|
3951
|
+
if (!branch || !branch.trim()) return; // cancelled — leave the omnibox open
|
|
3952
|
+
closeOmni(false);
|
|
3953
|
+
await spawnAndSelect(
|
|
3954
|
+
{
|
|
3955
|
+
cli: anchor?.cli || "claude",
|
|
3956
|
+
prompt: q || undefined,
|
|
3957
|
+
fork: { fromCwd: anchor?.cwd, branch: branch.trim() },
|
|
3958
|
+
},
|
|
3959
|
+
anchor?._room,
|
|
3960
|
+
);
|
|
3961
|
+
return;
|
|
3962
|
+
}
|
|
3963
|
+
if (row && row.kind === "spawncwd") {
|
|
3964
|
+
const cwd = prompt("Spawn in which working directory?", anchor?.cwd || "");
|
|
3965
|
+
if (cwd == null) return; // cancelled
|
|
3966
|
+
closeOmni(false);
|
|
3967
|
+
await spawnAndSelect(
|
|
3968
|
+
{ cli: anchor?.cli || "claude", cwd: cwd.trim() || undefined, prompt: q || undefined },
|
|
3969
|
+
anchor?._room,
|
|
3970
|
+
);
|
|
3971
|
+
return;
|
|
3972
|
+
}
|
|
3914
3973
|
if (row && row.kind === "agent") {
|
|
3915
3974
|
closeOmni(false); // committing the previewed agent — don't restore the original
|
|
3916
3975
|
select(row.entry._key);
|
|
@@ -4335,6 +4394,7 @@
|
|
|
4335
4394
|
const res = await target.tx.post("/api/spawn", {
|
|
4336
4395
|
cli: spec.cli || "claude",
|
|
4337
4396
|
from: spec.from || undefined,
|
|
4397
|
+
fork: spec.fork || undefined,
|
|
4338
4398
|
cwd: spec.cwd || undefined,
|
|
4339
4399
|
prompt: spec.prompt || undefined,
|
|
4340
4400
|
});
|
package/package.json
CHANGED
package/ts/serve.ts
CHANGED
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import { mkdir, open, readFile, stat, writeFile } from "fs/promises";
|
|
2
2
|
import { renameSync, watch, writeFileSync } from "node:fs";
|
|
3
|
+
import { execFileSync } from "node:child_process";
|
|
3
4
|
import { fileURLToPath } from "node:url";
|
|
4
5
|
import { createHash, randomBytes, timingSafeEqual } from "crypto";
|
|
5
6
|
import { homedir, hostname, userInfo } from "os";
|
|
@@ -1119,9 +1120,24 @@ export async function cmdServe(rest: string[]): Promise<number> {
|
|
|
1119
1120
|
if (req.method === "GET" && p === "/api/whoami") {
|
|
1120
1121
|
let user = "";
|
|
1121
1122
|
try {
|
|
1122
|
-
|
|
1123
|
+
// Bun's userInfo() doesn't always throw on a uid with no /etc/passwd
|
|
1124
|
+
// entry (arbitrary-uid / minimal containers) — it can return the literal
|
|
1125
|
+
// "unknown". Treat that (and "") as a miss so the fallbacks run; without
|
|
1126
|
+
// this a root container surfaced as `unknown@host`, not `root@host`.
|
|
1127
|
+
const u = userInfo().username;
|
|
1128
|
+
if (u && u !== "unknown") user = u;
|
|
1123
1129
|
} catch {
|
|
1124
|
-
/* userInfo
|
|
1130
|
+
/* userInfo can still throw outright on some platforms */
|
|
1131
|
+
}
|
|
1132
|
+
user ||= process.env.USER || process.env.LOGNAME || process.env.USERNAME || "";
|
|
1133
|
+
// Last resort on Unix: resolve the uid against the passwd db directly,
|
|
1134
|
+
// which returns `root` for uid 0 even when the env carries no USER.
|
|
1135
|
+
if (!user && process.platform !== "win32") {
|
|
1136
|
+
try {
|
|
1137
|
+
user = execFileSync("id", ["-un"], { encoding: "utf8" }).trim();
|
|
1138
|
+
} catch {
|
|
1139
|
+
/* no `id` on PATH — leave user blank, host-only label */
|
|
1140
|
+
}
|
|
1125
1141
|
}
|
|
1126
1142
|
const host = hostname();
|
|
1127
1143
|
return Response.json({ host: user ? `${user}@${host}` : host });
|
|
@@ -1472,7 +1488,13 @@ export async function cmdServe(rest: string[]): Promise<number> {
|
|
|
1472
1488
|
// standard); otherwise `cwd` is resolved against the workspace root and
|
|
1473
1489
|
// created if missing (Layer-0 plain-dir provisioning — no more ENOENT 500).
|
|
1474
1490
|
if (req.method === "POST" && p === "/api/spawn") {
|
|
1475
|
-
let body: {
|
|
1491
|
+
let body: {
|
|
1492
|
+
cli?: string;
|
|
1493
|
+
cwd?: string;
|
|
1494
|
+
from?: string;
|
|
1495
|
+
prompt?: string;
|
|
1496
|
+
fork?: { fromCwd?: string; branch?: string };
|
|
1497
|
+
};
|
|
1476
1498
|
try {
|
|
1477
1499
|
body = (await req.json()) as typeof body;
|
|
1478
1500
|
} catch {
|
|
@@ -1488,8 +1510,61 @@ export async function cmdServe(rest: string[]): Promise<number> {
|
|
|
1488
1510
|
// workspace root and mkdir-p'd so a missing dir no longer ENOENTs.
|
|
1489
1511
|
let cwd: string;
|
|
1490
1512
|
let provisioned: { action: string; folder: string } | null = null;
|
|
1513
|
+
const fork =
|
|
1514
|
+
body.fork && typeof body.fork.fromCwd === "string" && typeof body.fork.branch === "string"
|
|
1515
|
+
? { fromCwd: body.fork.fromCwd, branch: body.fork.branch }
|
|
1516
|
+
: null;
|
|
1491
1517
|
const from = typeof body.from === "string" ? body.from.trim() : "";
|
|
1492
|
-
if (
|
|
1518
|
+
if (fork) {
|
|
1519
|
+
// Fork the anchor agent's branch (carrying its WIP) into a new sibling
|
|
1520
|
+
// worktree via codehost/provision (git worktree off HEAD, no clone), then
|
|
1521
|
+
// spawn the agent there.
|
|
1522
|
+
let prov: {
|
|
1523
|
+
forkWorktree: (o: { fromCwd: string; branch: string; wsRoot?: string }) => Promise<{
|
|
1524
|
+
ok: boolean;
|
|
1525
|
+
folder: string;
|
|
1526
|
+
action: string;
|
|
1527
|
+
error?: string;
|
|
1528
|
+
spec?: { owner: string; repo: string };
|
|
1529
|
+
}>;
|
|
1530
|
+
};
|
|
1531
|
+
try {
|
|
1532
|
+
prov = (await import("codehost/provision")) as typeof prov;
|
|
1533
|
+
} catch (e) {
|
|
1534
|
+
return new Response(
|
|
1535
|
+
`fork needs the 'codehost' package (codehost/provision) — install it ` +
|
|
1536
|
+
`(npm i -g codehost) or 'bun link' it for local dev: ${(e as Error).message}`,
|
|
1537
|
+
{ status: 501 },
|
|
1538
|
+
);
|
|
1539
|
+
}
|
|
1540
|
+
let result: {
|
|
1541
|
+
ok: boolean;
|
|
1542
|
+
folder: string;
|
|
1543
|
+
action: string;
|
|
1544
|
+
error?: string;
|
|
1545
|
+
spec?: { owner: string; repo: string };
|
|
1546
|
+
};
|
|
1547
|
+
try {
|
|
1548
|
+
const wsRoot = getProvisionRoot();
|
|
1549
|
+
result = await prov.forkWorktree({
|
|
1550
|
+
fromCwd: fork.fromCwd,
|
|
1551
|
+
branch: fork.branch,
|
|
1552
|
+
...(wsRoot ? { wsRoot } : {}),
|
|
1553
|
+
});
|
|
1554
|
+
} catch (e) {
|
|
1555
|
+
return new Response(`fork failed: ${(e as Error).message}`, { status: 502 });
|
|
1556
|
+
}
|
|
1557
|
+
if (!result?.ok) return new Response(result?.error ?? "fork failed", { status: 502 });
|
|
1558
|
+
// Same allowlist gate as `from` — the fork runs setup-repo.sh (code exec).
|
|
1559
|
+
if (result.spec && !isProvisionAllowed(result.spec.owner, result.spec.repo))
|
|
1560
|
+
return new Response(
|
|
1561
|
+
`forking '${result.spec.owner}/${result.spec.repo}' is not allowed — add the owner ` +
|
|
1562
|
+
`to provisionAllowlist in ~/.agent-yes/config.json (or "*" to allow all)`,
|
|
1563
|
+
{ status: 403 },
|
|
1564
|
+
);
|
|
1565
|
+
cwd = result.folder;
|
|
1566
|
+
provisioned = { action: result.action, folder: result.folder };
|
|
1567
|
+
} else if (from) {
|
|
1493
1568
|
type Spec = { owner: string; repo: string; branch: string };
|
|
1494
1569
|
let prov: {
|
|
1495
1570
|
parseSource?: (s: string) => Spec | null;
|
|
@@ -1547,7 +1622,7 @@ export async function cmdServe(rest: string[]): Promise<number> {
|
|
|
1547
1622
|
}
|
|
1548
1623
|
}
|
|
1549
1624
|
process.stderr.write(
|
|
1550
|
-
`→ console spawned: ay ${cli}${prompt ? ` -- "${prompt.slice(0, 60)}"` : ""} (cwd: ${cwd}${provisioned ? `, ${provisioned.action}
|
|
1625
|
+
`→ console spawned: ay ${cli}${prompt ? ` -- "${prompt.slice(0, 60)}"` : ""} (cwd: ${cwd}${provisioned ? `, ${provisioned.action}` : ""})\n`,
|
|
1551
1626
|
);
|
|
1552
1627
|
// Resolve `ay` to an absolute command. The detached daemon (oxmgr/launchd/
|
|
1553
1628
|
// pm2) usually has a PATH WITHOUT ~/.bun/bin, so a bare "ay" fails with
|
|
@@ -1,8 +0,0 @@
|
|
|
1
|
-
import "./ts-DIrs0jef.js";
|
|
2
|
-
import "./logger-CDIsZ-Pp.js";
|
|
3
|
-
import "./versionChecker-D0pC8VFv.js";
|
|
4
|
-
import "./pidStore-fqXqTKkh.js";
|
|
5
|
-
import "./globalPidIndex-DlmmJlO8.js";
|
|
6
|
-
import { t as SUPPORTED_CLIS } from "./SUPPORTED_CLIS-B52NvCuZ.js";
|
|
7
|
-
|
|
8
|
-
export { SUPPORTED_CLIS };
|