agent-yes 1.96.0 → 1.97.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-CNO_pj9f.js +8 -0
- package/dist/{SUPPORTED_CLIS-B2FAlgXF.js → SUPPORTED_CLIS-eD-UlqO_.js} +2 -2
- package/dist/cli.js +6 -6
- package/dist/index.js +3 -3
- package/dist/pidStore-9b3YTuf4.js +5 -0
- package/dist/{pidStore-DTzl6zeh.js → pidStore-DBjlqzo8.js} +22 -22
- package/dist/{runningLock-C22d9SRJ.js → runningLock-CJxsoGdb.js} +1 -1
- package/dist/{serve-CuAPBK4y.js → serve-CKcbVPy6.js} +66 -40
- package/dist/{subcommands-EieqoC9Z.js → subcommands-B4gXEu5I.js} +1 -1
- package/dist/{subcommands-CcOYsLYD.js → subcommands-K242usI5.js} +2 -2
- package/dist/{tray-D4cJA4UH.js → tray-CWQe9DMY.js} +2 -2
- package/dist/{ts-DkjQJTcB.js → ts-BAc4Jcrw.js} +13 -4
- package/dist/{versionChecker-xqnqyGKE.js → versionChecker-MNvA73o9.js} +2 -2
- package/package.json +1 -1
- package/ts/index.ts +16 -0
- package/ts/serve.ts +82 -48
- package/dist/SUPPORTED_CLIS-G8izHOJP.js +0 -8
- package/dist/pidStore-iJY3JFTn.js +0 -5
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
import "./ts-BAc4Jcrw.js";
|
|
2
|
+
import "./logger-B9h0djqx.js";
|
|
3
|
+
import "./versionChecker-MNvA73o9.js";
|
|
4
|
+
import "./pidStore-DBjlqzo8.js";
|
|
5
|
+
import "./globalPidIndex-yVd3mbsV.js";
|
|
6
|
+
import { t as SUPPORTED_CLIS } from "./SUPPORTED_CLIS-eD-UlqO_.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-BAc4Jcrw.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-eD-UlqO_.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-MNvA73o9.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-B4gXEu5I.js");
|
|
486
486
|
if (isHelpFlag && process.argv.length === 3) {
|
|
487
487
|
cmdHelp();
|
|
488
488
|
process.exit(0);
|
|
@@ -496,12 +496,12 @@ await checkAndAutoUpdate();
|
|
|
496
496
|
logger.info(versionString());
|
|
497
497
|
const config = parseCliArgs(process.argv);
|
|
498
498
|
if (config.tray) {
|
|
499
|
-
const { startTray } = await import("./tray-
|
|
499
|
+
const { startTray } = await import("./tray-CWQe9DMY.js");
|
|
500
500
|
await startTray();
|
|
501
501
|
await new Promise(() => {});
|
|
502
502
|
}
|
|
503
503
|
{
|
|
504
|
-
const { ensureTray } = await import("./tray-
|
|
504
|
+
const { ensureTray } = await import("./tray-CWQe9DMY.js");
|
|
505
505
|
ensureTray();
|
|
506
506
|
}
|
|
507
507
|
if (config.useRust) {
|
|
@@ -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-CNO_pj9f.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}`);
|
|
@@ -545,7 +545,7 @@ if (config.showVersion) {
|
|
|
545
545
|
process.exit(0);
|
|
546
546
|
}
|
|
547
547
|
if (config.appendPrompt) {
|
|
548
|
-
const { PidStore } = await import("./pidStore-
|
|
548
|
+
const { PidStore } = await import("./pidStore-9b3YTuf4.js");
|
|
549
549
|
const ipcPath = await PidStore.findActiveFifo(process.cwd());
|
|
550
550
|
if (!ipcPath) {
|
|
551
551
|
console.error("No active agent with IPC found in current directory.");
|
package/dist/index.js
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
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-BAc4Jcrw.js";
|
|
2
2
|
import "./logger-B9h0djqx.js";
|
|
3
|
-
import "./versionChecker-
|
|
4
|
-
import "./pidStore-
|
|
3
|
+
import "./versionChecker-MNvA73o9.js";
|
|
4
|
+
import "./pidStore-DBjlqzo8.js";
|
|
5
5
|
import "./globalPidIndex-yVd3mbsV.js";
|
|
6
6
|
|
|
7
7
|
export { AgentContext, CLIS_CONFIG, config, agentYes as default, removeControlCharacters };
|
|
@@ -6,6 +6,26 @@ import { homedir } from "os";
|
|
|
6
6
|
import path from "path";
|
|
7
7
|
import { lock } from "proper-lockfile";
|
|
8
8
|
|
|
9
|
+
//#region ts/agentYesHome.ts
|
|
10
|
+
/**
|
|
11
|
+
* Root directory for cross-runtime, machine-global agent-yes state:
|
|
12
|
+
* the pid index (`pids.jsonl`), FIFO/named-pipe IPC endpoints (`fifo/`),
|
|
13
|
+
* winsize signals, notes, and the serve token.
|
|
14
|
+
*
|
|
15
|
+
* Durable per-session *logs* deliberately do NOT live here — they go under
|
|
16
|
+
* `<cwd>/.agent-yes/` so they stay colocated with the project that produced
|
|
17
|
+
* them (see `PidStore`). Only ephemeral IPC + the discovery index are global,
|
|
18
|
+
* which keeps FIFOs on the local home filesystem (reliable `mkfifo`) and lets
|
|
19
|
+
* `ay ls`/`ay attach` find every agent regardless of the caller's cwd.
|
|
20
|
+
*
|
|
21
|
+
* Resolved at call time (not module load) so tests and callers can override
|
|
22
|
+
* via `$AGENT_YES_HOME` without juggling the module cache.
|
|
23
|
+
*/
|
|
24
|
+
function agentYesHome() {
|
|
25
|
+
return process.env.AGENT_YES_HOME ?? path.join(homedir(), ".agent-yes");
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
//#endregion
|
|
9
29
|
//#region ts/JsonlStore.ts
|
|
10
30
|
/**
|
|
11
31
|
* A lightweight NeDB-style JSONL persistence layer.
|
|
@@ -184,26 +204,6 @@ function generateId() {
|
|
|
184
204
|
return Date.now().toString(36) + (idCounter++).toString(36) + Math.random().toString(36).slice(2, 6);
|
|
185
205
|
}
|
|
186
206
|
|
|
187
|
-
//#endregion
|
|
188
|
-
//#region ts/agentYesHome.ts
|
|
189
|
-
/**
|
|
190
|
-
* Root directory for cross-runtime, machine-global agent-yes state:
|
|
191
|
-
* the pid index (`pids.jsonl`), FIFO/named-pipe IPC endpoints (`fifo/`),
|
|
192
|
-
* winsize signals, notes, and the serve token.
|
|
193
|
-
*
|
|
194
|
-
* Durable per-session *logs* deliberately do NOT live here — they go under
|
|
195
|
-
* `<cwd>/.agent-yes/` so they stay colocated with the project that produced
|
|
196
|
-
* them (see `PidStore`). Only ephemeral IPC + the discovery index are global,
|
|
197
|
-
* which keeps FIFOs on the local home filesystem (reliable `mkfifo`) and lets
|
|
198
|
-
* `ay ls`/`ay attach` find every agent regardless of the caller's cwd.
|
|
199
|
-
*
|
|
200
|
-
* Resolved at call time (not module load) so tests and callers can override
|
|
201
|
-
* via `$AGENT_YES_HOME` without juggling the module cache.
|
|
202
|
-
*/
|
|
203
|
-
function agentYesHome() {
|
|
204
|
-
return process.env.AGENT_YES_HOME ?? path.join(homedir(), ".agent-yes");
|
|
205
|
-
}
|
|
206
|
-
|
|
207
207
|
//#endregion
|
|
208
208
|
//#region ts/pidStore.ts
|
|
209
209
|
var PidStore = class PidStore {
|
|
@@ -380,5 +380,5 @@ pid-db/
|
|
|
380
380
|
};
|
|
381
381
|
|
|
382
382
|
//#endregion
|
|
383
|
-
export { PidStore as t };
|
|
384
|
-
//# sourceMappingURL=pidStore-
|
|
383
|
+
export { agentYesHome as n, PidStore as t };
|
|
384
|
+
//# sourceMappingURL=pidStore-DBjlqzo8.js.map
|
|
@@ -1,15 +1,16 @@
|
|
|
1
|
-
import "./ts-
|
|
1
|
+
import "./ts-BAc4Jcrw.js";
|
|
2
2
|
import "./logger-B9h0djqx.js";
|
|
3
|
-
import "./versionChecker-
|
|
4
|
-
import "./pidStore-
|
|
3
|
+
import "./versionChecker-MNvA73o9.js";
|
|
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-eD-UlqO_.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-K242usI5.js";
|
|
9
9
|
import yargs from "yargs";
|
|
10
|
-
import { mkdir, readFile, writeFile } from "fs/promises";
|
|
10
|
+
import { mkdir, open, readFile, writeFile } from "fs/promises";
|
|
11
11
|
import { homedir } from "os";
|
|
12
12
|
import path from "path";
|
|
13
|
+
import { watch } from "node:fs";
|
|
13
14
|
import { randomBytes, timingSafeEqual } from "crypto";
|
|
14
15
|
|
|
15
16
|
//#region ts/serve.ts
|
|
@@ -111,7 +112,7 @@ async function cmdServe(rest) {
|
|
|
111
112
|
Start an HTTP API server so remote machines can list/tail/send agents.
|
|
112
113
|
|
|
113
114
|
Options:
|
|
114
|
-
--port N Port to listen on (default: ${DEFAULT_PORT})\n --host HOST Interface to bind (default: 127.0.0.1; use 0.0.0.0 to expose)\n --token TOKEN Auth token (auto-generated and saved if omitted)\n --share [URL] Share over WebRTC to agent-yes.com (bare flag mints a room+link)\n --allow-spawn
|
|
115
|
+
--port N Port to listen on (default: ${DEFAULT_PORT})\n --host HOST Interface to bind (default: 127.0.0.1; use 0.0.0.0 to expose)\n --token TOKEN Auth token (auto-generated and saved if omitted)\n --share [URL] Share over WebRTC to agent-yes.com (bare flag mints a room+link)\n --allow-spawn Deprecated no-op — the console can always spawn agents\n --tls-cert FILE TLS certificate PEM\n --tls-key FILE TLS private key PEM\n\nSubcommands:\n ay serve install install as background daemon via oxmgr\n ay serve uninstall remove daemon\n ay serve logs view daemon logs\n\nOnce running, connect from another machine:\n ay ls <token>@<host>:${DEFAULT_PORT}\n ay remote add <alias> http://<token>@<host>:${DEFAULT_PORT}\n`);
|
|
115
116
|
return 0;
|
|
116
117
|
}
|
|
117
118
|
const sub = rest[0];
|
|
@@ -139,7 +140,7 @@ Options:
|
|
|
139
140
|
}).option("allow-spawn", {
|
|
140
141
|
type: "boolean",
|
|
141
142
|
default: false,
|
|
142
|
-
description: "
|
|
143
|
+
description: "Deprecated no-op — the console can always spawn agents"
|
|
143
144
|
}).help(false).version(false).exitProcess(false).parseAsync();
|
|
144
145
|
const port = argv.port ?? DEFAULT_PORT;
|
|
145
146
|
const host = argv.host ?? "127.0.0.1";
|
|
@@ -154,20 +155,6 @@ Options:
|
|
|
154
155
|
const scheme = useHttps ? "https" : "http";
|
|
155
156
|
if (host !== "127.0.0.1" && host !== "localhost") process.stderr.write("ay serve: warning: binding to non-loopback — ensure your network is trusted or use Tailscale/VPN\n");
|
|
156
157
|
const token = await loadOrCreateToken(tokenFlag);
|
|
157
|
-
const allowSpawn = argv["allow-spawn"] === true;
|
|
158
|
-
const spawnQueue = [];
|
|
159
|
-
let stdinWired = false;
|
|
160
|
-
const confirmSpawn = (cli, cwd, prompt) => {
|
|
161
|
-
if (!process.stdin.isTTY) return Promise.resolve(true);
|
|
162
|
-
if (!stdinWired) {
|
|
163
|
-
stdinWired = true;
|
|
164
|
-
process.stdin.setEncoding("utf8");
|
|
165
|
-
process.stdin.on("data", (d) => spawnQueue.shift()?.(/^y/i.test(d.trim())));
|
|
166
|
-
process.stdin.resume();
|
|
167
|
-
}
|
|
168
|
-
process.stdout.write(`\n⚠ console requests spawn: ay ${cli}${prompt ? ` -- "${prompt.slice(0, 60)}"` : ""}\n cwd: ${cwd}\n allow? [y/N] `);
|
|
169
|
-
return new Promise((res) => spawnQueue.push(res));
|
|
170
|
-
};
|
|
171
158
|
const serverOpts = {
|
|
172
159
|
hostname: host,
|
|
173
160
|
port,
|
|
@@ -219,6 +206,30 @@ Options:
|
|
|
219
206
|
return new Response(e.message, { status: 404 });
|
|
220
207
|
}
|
|
221
208
|
}
|
|
209
|
+
const sizeM = /^\/api\/size\/(.+)$/.exec(p);
|
|
210
|
+
if (req.method === "GET" && sizeM) {
|
|
211
|
+
const keyword = decodeURIComponent(sizeM[1]);
|
|
212
|
+
try {
|
|
213
|
+
const record = await resolveOne(keyword, defaultOpts());
|
|
214
|
+
const ayHome = process.env.AGENT_YES_HOME ?? path.join(homedir(), ".agent-yes");
|
|
215
|
+
let cols = null;
|
|
216
|
+
let rows = null;
|
|
217
|
+
try {
|
|
218
|
+
const [c, r] = (await readFile(path.join(ayHome, "ptysize", String(record.pid)), "utf-8")).trim().split(/\s+/).map(Number);
|
|
219
|
+
if (c > 0 && r > 0) {
|
|
220
|
+
cols = c;
|
|
221
|
+
rows = r;
|
|
222
|
+
}
|
|
223
|
+
} catch {}
|
|
224
|
+
return Response.json({
|
|
225
|
+
pid: record.pid,
|
|
226
|
+
cols,
|
|
227
|
+
rows
|
|
228
|
+
});
|
|
229
|
+
} catch (e) {
|
|
230
|
+
return new Response(e.message, { status: 404 });
|
|
231
|
+
}
|
|
232
|
+
}
|
|
222
233
|
const tailM = /^\/api\/tail\/(.+)$/.exec(p);
|
|
223
234
|
if (req.method === "GET" && tailM) {
|
|
224
235
|
const keyword = decodeURIComponent(tailM[1]);
|
|
@@ -248,27 +259,43 @@ Options:
|
|
|
248
259
|
}, 15e3);
|
|
249
260
|
const ansiRe = /\x1b\[[0-?]*[ -/]*[@-~]|\x1b\][^\x07\x1b]*(?:\x07|\x1b\\)|\x1b[@-Z\\-_]/g;
|
|
250
261
|
const ctrlRe = /[\x00-\x08\x0b\x0c\x0e-\x1f\x7f]/g;
|
|
251
|
-
const
|
|
252
|
-
|
|
253
|
-
|
|
254
|
-
|
|
255
|
-
|
|
262
|
+
const fh = await open(logPath, "r").catch(() => null);
|
|
263
|
+
let reading = false;
|
|
264
|
+
const flush = async () => {
|
|
265
|
+
if (closed || reading || !fh) return;
|
|
266
|
+
reading = true;
|
|
256
267
|
try {
|
|
257
|
-
const
|
|
258
|
-
if (
|
|
259
|
-
|
|
260
|
-
|
|
261
|
-
|
|
262
|
-
|
|
263
|
-
|
|
264
|
-
|
|
268
|
+
const { size } = await fh.stat();
|
|
269
|
+
if (size < offset) offset = size;
|
|
270
|
+
if (size > offset) {
|
|
271
|
+
const len = size - offset;
|
|
272
|
+
const buf = Buffer.allocUnsafe(len);
|
|
273
|
+
const { bytesRead } = await fh.read(buf, 0, len, offset);
|
|
274
|
+
offset += bytesRead;
|
|
275
|
+
const chunk = buf.subarray(0, bytesRead);
|
|
276
|
+
if (raw) send(new TextDecoder().decode(chunk));
|
|
277
|
+
else {
|
|
278
|
+
const text = new TextDecoder().decode(chunk).replace(ansiRe, "").replace(ctrlRe, "");
|
|
279
|
+
if (text.trim()) send(text.trimStart());
|
|
280
|
+
}
|
|
265
281
|
}
|
|
266
|
-
} catch {}
|
|
267
|
-
|
|
282
|
+
} catch {} finally {
|
|
283
|
+
reading = false;
|
|
284
|
+
}
|
|
285
|
+
};
|
|
286
|
+
let watcher = null;
|
|
287
|
+
try {
|
|
288
|
+
watcher = watch(logPath, () => void flush());
|
|
289
|
+
} catch {}
|
|
290
|
+
const poller = setInterval(() => void flush(), 60);
|
|
268
291
|
req.signal.addEventListener("abort", () => {
|
|
269
292
|
closed = true;
|
|
270
293
|
clearInterval(heartbeat);
|
|
271
294
|
clearInterval(poller);
|
|
295
|
+
try {
|
|
296
|
+
watcher?.close();
|
|
297
|
+
} catch {}
|
|
298
|
+
fh?.close().catch(() => {});
|
|
272
299
|
try {
|
|
273
300
|
ctrl.close();
|
|
274
301
|
} catch {}
|
|
@@ -341,7 +368,6 @@ Options:
|
|
|
341
368
|
}
|
|
342
369
|
}
|
|
343
370
|
if (req.method === "POST" && p === "/api/spawn") {
|
|
344
|
-
if (!allowSpawn) return new Response("spawning disabled — start: ay serve --share --allow-spawn", { status: 403 });
|
|
345
371
|
let body;
|
|
346
372
|
try {
|
|
347
373
|
body = await req.json();
|
|
@@ -352,7 +378,7 @@ Options:
|
|
|
352
378
|
if (!SUPPORTED_CLIS.includes(cli)) return new Response(`unsupported cli: ${cli}`, { status: 400 });
|
|
353
379
|
const cwd = typeof body.cwd === "string" && body.cwd ? body.cwd : process.cwd();
|
|
354
380
|
const prompt = String(body.prompt ?? "");
|
|
355
|
-
|
|
381
|
+
process.stderr.write(`→ console spawned: ay ${cli}${prompt ? ` -- "${prompt.slice(0, 60)}"` : ""} (cwd: ${cwd})\n`);
|
|
356
382
|
try {
|
|
357
383
|
const child = Bun.spawn([
|
|
358
384
|
"ay",
|
|
@@ -422,4 +448,4 @@ Options:
|
|
|
422
448
|
|
|
423
449
|
//#endregion
|
|
424
450
|
export { cmdServe };
|
|
425
|
-
//# sourceMappingURL=serve-
|
|
451
|
+
//# sourceMappingURL=serve-CKcbVPy6.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-K242usI5.js";
|
|
5
5
|
|
|
6
6
|
export { cmdHelp, isSubcommand, runSubcommand };
|
|
@@ -162,7 +162,7 @@ async function runSubcommand(argv) {
|
|
|
162
162
|
case "restart": return await cmdRestart(rest);
|
|
163
163
|
case "note": return await cmdNote(rest);
|
|
164
164
|
case "serve": {
|
|
165
|
-
const { cmdServe } = await import("./serve-
|
|
165
|
+
const { cmdServe } = await import("./serve-CKcbVPy6.js");
|
|
166
166
|
return cmdServe(rest);
|
|
167
167
|
}
|
|
168
168
|
case "remote": {
|
|
@@ -1447,4 +1447,4 @@ async function cmdStatus(rest) {
|
|
|
1447
1447
|
|
|
1448
1448
|
//#endregion
|
|
1449
1449
|
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 };
|
|
1450
|
-
//# sourceMappingURL=subcommands-
|
|
1450
|
+
//# sourceMappingURL=subcommands-K242usI5.js.map
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { n as getRunningAgentCount } from "./runningLock-
|
|
1
|
+
import { n as getRunningAgentCount } from "./runningLock-CJxsoGdb.js";
|
|
2
2
|
import { existsSync } from "fs";
|
|
3
3
|
import { mkdir, readFile, unlink, writeFile } from "fs/promises";
|
|
4
4
|
import { homedir } from "os";
|
|
@@ -175,4 +175,4 @@ async function startTray() {
|
|
|
175
175
|
|
|
176
176
|
//#endregion
|
|
177
177
|
export { ensureTray, startTray };
|
|
178
|
-
//# sourceMappingURL=tray-
|
|
178
|
+
//# sourceMappingURL=tray-CWQe9DMY.js.map
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { n as logger, t as addTransport } from "./logger-B9h0djqx.js";
|
|
2
|
-
import { r as getInstalledPackage } from "./versionChecker-
|
|
3
|
-
import {
|
|
4
|
-
import { t as
|
|
2
|
+
import { r as getInstalledPackage } from "./versionChecker-MNvA73o9.js";
|
|
3
|
+
import { n as agentYesHome, t as PidStore } from "./pidStore-DBjlqzo8.js";
|
|
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";
|
|
6
6
|
import { arch, platform } from "process";
|
|
7
7
|
import { execSync } from "child_process";
|
|
@@ -1423,10 +1423,19 @@ async function agentYes({ cli, cliArgs = [], prompt, robust = true, cwd, env, ex
|
|
|
1423
1423
|
notifyWebhook("EXIT", `${exitReason} exitCode=${exitCode ?? "?"}`, workingDir).catch(() => null);
|
|
1424
1424
|
return pendingExitCode.resolve(exitCode);
|
|
1425
1425
|
});
|
|
1426
|
+
const writeCurrentPtysize = (cols, rows) => {
|
|
1427
|
+
const dir = path.join(agentYesHome(), "ptysize");
|
|
1428
|
+
mkdir(dir, { recursive: true }).then(() => writeFile(path.join(dir, String(process.pid)), `${cols} ${rows}\n`)).catch(() => null);
|
|
1429
|
+
};
|
|
1430
|
+
{
|
|
1431
|
+
const { cols, rows } = getTerminalDimensions();
|
|
1432
|
+
writeCurrentPtysize(cols, rows);
|
|
1433
|
+
}
|
|
1426
1434
|
process.stdout.on("resize", () => {
|
|
1427
1435
|
const { cols, rows } = getTerminalDimensions();
|
|
1428
1436
|
shell.resize(cols, rows);
|
|
1429
1437
|
xtermProxy.resize(cols, rows);
|
|
1438
|
+
writeCurrentPtysize(cols, rows);
|
|
1430
1439
|
});
|
|
1431
1440
|
const isStillWorkingQ = () => {
|
|
1432
1441
|
const rendered = xtermProxy.tail(24).replace(/\s+/g, " ");
|
|
@@ -1705,4 +1714,4 @@ function sleep(ms) {
|
|
|
1705
1714
|
|
|
1706
1715
|
//#endregion
|
|
1707
1716
|
export { removeControlCharacters as a, AgentContext as i, agentYes as n, config as r, CLIS_CONFIG as t };
|
|
1708
|
-
//# sourceMappingURL=ts-
|
|
1717
|
+
//# sourceMappingURL=ts-BAc4Jcrw.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.97.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-MNvA73o9.js.map
|
package/package.json
CHANGED
package/ts/index.ts
CHANGED
|
@@ -5,6 +5,7 @@ import path from "path";
|
|
|
5
5
|
import DIE from "phpdie";
|
|
6
6
|
import sflow from "sflow";
|
|
7
7
|
import { XtermProxy } from "./xterm-proxy.ts";
|
|
8
|
+
import { agentYesHome } from "./agentYesHome.ts";
|
|
8
9
|
import {
|
|
9
10
|
extractSessionId,
|
|
10
11
|
getSessionForCwd,
|
|
@@ -643,11 +644,26 @@ export default async function agentYes({
|
|
|
643
644
|
return pendingExitCode.resolve(exitCode);
|
|
644
645
|
});
|
|
645
646
|
|
|
647
|
+
// Record the agent's current PTY size to ~/.agent-yes/ptysize/<pid> so `ay serve`
|
|
648
|
+
// / the web console can render the existing buffer at the agent's real width
|
|
649
|
+
// before adapting. Mirrors the Rust runtime (rs/src/pty_spawner.rs).
|
|
650
|
+
const writeCurrentPtysize = (cols: number, rows: number) => {
|
|
651
|
+
const dir = path.join(agentYesHome(), "ptysize");
|
|
652
|
+
void mkdir(dir, { recursive: true })
|
|
653
|
+
.then(() => writeFile(path.join(dir, String(process.pid)), `${cols} ${rows}\n`))
|
|
654
|
+
.catch(() => null);
|
|
655
|
+
};
|
|
656
|
+
{
|
|
657
|
+
const { cols, rows } = getTerminalDimensions();
|
|
658
|
+
writeCurrentPtysize(cols, rows);
|
|
659
|
+
}
|
|
660
|
+
|
|
646
661
|
// when current tty resized, resize both pty and xterm proxy
|
|
647
662
|
process.stdout.on("resize", () => {
|
|
648
663
|
const { cols, rows } = getTerminalDimensions();
|
|
649
664
|
shell.resize(cols, rows);
|
|
650
665
|
xtermProxy.resize(cols, rows);
|
|
666
|
+
writeCurrentPtysize(cols, rows);
|
|
651
667
|
});
|
|
652
668
|
|
|
653
669
|
const isStillWorkingQ = () => {
|
package/ts/serve.ts
CHANGED
|
@@ -1,4 +1,5 @@
|
|
|
1
|
-
import { mkdir, readFile, writeFile } from "fs/promises";
|
|
1
|
+
import { mkdir, open, readFile, writeFile } from "fs/promises";
|
|
2
|
+
import { watch } from "node:fs";
|
|
2
3
|
import { createHash, randomBytes, timingSafeEqual } from "crypto";
|
|
3
4
|
import { homedir } from "os";
|
|
4
5
|
import path from "path";
|
|
@@ -125,7 +126,7 @@ export async function cmdServe(rest: string[]): Promise<number> {
|
|
|
125
126
|
` --host HOST Interface to bind (default: 127.0.0.1; use 0.0.0.0 to expose)\n` +
|
|
126
127
|
` --token TOKEN Auth token (auto-generated and saved if omitted)\n` +
|
|
127
128
|
` --share [URL] Share over WebRTC to agent-yes.com (bare flag mints a room+link)\n` +
|
|
128
|
-
` --allow-spawn
|
|
129
|
+
` --allow-spawn Deprecated no-op — the console can always spawn agents\n` +
|
|
129
130
|
` --tls-cert FILE TLS certificate PEM\n` +
|
|
130
131
|
` --tls-key FILE TLS private key PEM\n\n` +
|
|
131
132
|
`Subcommands:\n` +
|
|
@@ -164,7 +165,7 @@ export async function cmdServe(rest: string[]): Promise<number> {
|
|
|
164
165
|
.option("allow-spawn", {
|
|
165
166
|
type: "boolean",
|
|
166
167
|
default: false,
|
|
167
|
-
description: "
|
|
168
|
+
description: "Deprecated no-op — the console can always spawn agents",
|
|
168
169
|
})
|
|
169
170
|
.help(false)
|
|
170
171
|
.version(false)
|
|
@@ -191,26 +192,11 @@ export async function cmdServe(rest: string[]): Promise<number> {
|
|
|
191
192
|
}
|
|
192
193
|
|
|
193
194
|
const token = await loadOrCreateToken(tokenFlag);
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
//
|
|
197
|
-
//
|
|
198
|
-
|
|
199
|
-
let stdinWired = false;
|
|
200
|
-
const confirmSpawn = (cli: string, cwd: string, prompt: string): Promise<boolean> => {
|
|
201
|
-
if (!process.stdin.isTTY) return Promise.resolve(true); // flag is the consent when headless
|
|
202
|
-
if (!stdinWired) {
|
|
203
|
-
stdinWired = true;
|
|
204
|
-
process.stdin.setEncoding("utf8");
|
|
205
|
-
process.stdin.on("data", (d: string) => spawnQueue.shift()?.(/^y/i.test(d.trim())));
|
|
206
|
-
process.stdin.resume();
|
|
207
|
-
}
|
|
208
|
-
process.stdout.write(
|
|
209
|
-
`\n⚠ console requests spawn: ay ${cli}${prompt ? ` -- "${prompt.slice(0, 60)}"` : ""}\n` +
|
|
210
|
-
` cwd: ${cwd}\n allow? [y/N] `,
|
|
211
|
-
);
|
|
212
|
-
return new Promise((res) => spawnQueue.push(res));
|
|
213
|
-
};
|
|
195
|
+
// Spawning is always allowed: a connected console already has full read-write
|
|
196
|
+
// control over every running agent (it writes straight to their stdin), so it
|
|
197
|
+
// can already make an agent do anything — gating /api/spawn behind a flag or a
|
|
198
|
+
// y/N prompt bought no real safety. We just log each spawn so the host sees it.
|
|
199
|
+
// (--allow-spawn is still accepted as a no-op for older invocations.)
|
|
214
200
|
|
|
215
201
|
const serverOpts: any = {
|
|
216
202
|
hostname: host,
|
|
@@ -275,6 +261,32 @@ export async function cmdServe(rest: string[]): Promise<number> {
|
|
|
275
261
|
}
|
|
276
262
|
}
|
|
277
263
|
|
|
264
|
+
// GET /api/size/:keyword — the agent's current PTY size, so the console can
|
|
265
|
+
// render the existing buffer at the agent's real width before adapting.
|
|
266
|
+
const sizeM = /^\/api\/size\/(.+)$/.exec(p);
|
|
267
|
+
if (req.method === "GET" && sizeM) {
|
|
268
|
+
const keyword = decodeURIComponent(sizeM[1]!);
|
|
269
|
+
try {
|
|
270
|
+
const record = await resolveOne(keyword, defaultOpts());
|
|
271
|
+
const ayHome = process.env.AGENT_YES_HOME ?? path.join(homedir(), ".agent-yes");
|
|
272
|
+
let cols: number | null = null;
|
|
273
|
+
let rows: number | null = null;
|
|
274
|
+
try {
|
|
275
|
+
const txt = await readFile(path.join(ayHome, "ptysize", String(record.pid)), "utf-8");
|
|
276
|
+
const [c, r] = txt.trim().split(/\s+/).map(Number);
|
|
277
|
+
if (c > 0 && r > 0) {
|
|
278
|
+
cols = c;
|
|
279
|
+
rows = r;
|
|
280
|
+
}
|
|
281
|
+
} catch {
|
|
282
|
+
/* no ptysize sidecar (older agent or not yet written) */
|
|
283
|
+
}
|
|
284
|
+
return Response.json({ pid: record.pid, cols, rows });
|
|
285
|
+
} catch (e) {
|
|
286
|
+
return new Response((e as Error).message, { status: 404 });
|
|
287
|
+
}
|
|
288
|
+
}
|
|
289
|
+
|
|
278
290
|
// GET /api/tail/:keyword — SSE streaming
|
|
279
291
|
const tailM = /^\/api\/tail\/(.+)$/.exec(p);
|
|
280
292
|
if (req.method === "GET" && tailM) {
|
|
@@ -319,34 +331,59 @@ export async function cmdServe(rest: string[]): Promise<number> {
|
|
|
319
331
|
// eslint-disable-next-line no-control-regex
|
|
320
332
|
const ctrlRe = /[\x00-\x08\x0b\x0c\x0e-\x1f\x7f]/g;
|
|
321
333
|
|
|
322
|
-
|
|
323
|
-
|
|
324
|
-
|
|
325
|
-
|
|
326
|
-
|
|
334
|
+
// Stream only the bytes appended since `offset` (incremental read,
|
|
335
|
+
// not a full re-read), driven by fs.watch for near-instant echo with
|
|
336
|
+
// a short fallback poll in case the watcher misses an event. The old
|
|
337
|
+
// 300 ms full-file poll was the dominant typing-echo latency.
|
|
338
|
+
const fh = await open(logPath, "r").catch(() => null);
|
|
339
|
+
let reading = false;
|
|
340
|
+
const flush = async () => {
|
|
341
|
+
if (closed || reading || !fh) return;
|
|
342
|
+
reading = true;
|
|
327
343
|
try {
|
|
328
|
-
const
|
|
329
|
-
if (
|
|
330
|
-
|
|
331
|
-
|
|
332
|
-
|
|
333
|
-
|
|
334
|
-
|
|
335
|
-
const
|
|
336
|
-
|
|
337
|
-
|
|
338
|
-
|
|
339
|
-
|
|
344
|
+
const { size } = await fh.stat();
|
|
345
|
+
if (size < offset) offset = size; // truncated/rotated
|
|
346
|
+
if (size > offset) {
|
|
347
|
+
const len = size - offset;
|
|
348
|
+
const buf = Buffer.allocUnsafe(len);
|
|
349
|
+
const { bytesRead } = await fh.read(buf, 0, len, offset);
|
|
350
|
+
offset += bytesRead;
|
|
351
|
+
const chunk = buf.subarray(0, bytesRead);
|
|
352
|
+
if (raw) {
|
|
353
|
+
send(new TextDecoder().decode(chunk));
|
|
354
|
+
} else {
|
|
355
|
+
const text = new TextDecoder()
|
|
356
|
+
.decode(chunk)
|
|
357
|
+
.replace(ansiRe, "")
|
|
358
|
+
.replace(ctrlRe, "");
|
|
359
|
+
if (text.trim()) send(text.trimStart());
|
|
360
|
+
}
|
|
340
361
|
}
|
|
341
362
|
} catch {
|
|
342
363
|
/* log gone */
|
|
364
|
+
} finally {
|
|
365
|
+
reading = false;
|
|
343
366
|
}
|
|
344
|
-
}
|
|
367
|
+
};
|
|
368
|
+
|
|
369
|
+
let watcher: ReturnType<typeof watch> | null = null;
|
|
370
|
+
try {
|
|
371
|
+
watcher = watch(logPath, () => void flush());
|
|
372
|
+
} catch {
|
|
373
|
+
/* fs.watch unsupported — the fallback poll below still works */
|
|
374
|
+
}
|
|
375
|
+
const poller = setInterval(() => void flush(), 60);
|
|
345
376
|
|
|
346
377
|
req.signal.addEventListener("abort", () => {
|
|
347
378
|
closed = true;
|
|
348
379
|
clearInterval(heartbeat);
|
|
349
380
|
clearInterval(poller);
|
|
381
|
+
try {
|
|
382
|
+
watcher?.close();
|
|
383
|
+
} catch {
|
|
384
|
+
/* already closed */
|
|
385
|
+
}
|
|
386
|
+
void fh?.close().catch(() => {});
|
|
350
387
|
try {
|
|
351
388
|
ctrl.close();
|
|
352
389
|
} catch {
|
|
@@ -433,12 +470,8 @@ export async function cmdServe(rest: string[]): Promise<number> {
|
|
|
433
470
|
}
|
|
434
471
|
}
|
|
435
472
|
|
|
436
|
-
// POST /api/spawn body {cli, cwd, prompt} — launch a new agent
|
|
473
|
+
// POST /api/spawn body {cli, cwd, prompt} — launch a new agent
|
|
437
474
|
if (req.method === "POST" && p === "/api/spawn") {
|
|
438
|
-
if (!allowSpawn)
|
|
439
|
-
return new Response("spawning disabled — start: ay serve --share --allow-spawn", {
|
|
440
|
-
status: 403,
|
|
441
|
-
});
|
|
442
475
|
let body: { cli?: string; cwd?: string; prompt?: string };
|
|
443
476
|
try {
|
|
444
477
|
body = await req.json();
|
|
@@ -450,8 +483,9 @@ export async function cmdServe(rest: string[]): Promise<number> {
|
|
|
450
483
|
return new Response(`unsupported cli: ${cli}`, { status: 400 });
|
|
451
484
|
const cwd = typeof body.cwd === "string" && body.cwd ? body.cwd : process.cwd();
|
|
452
485
|
const prompt = String(body.prompt ?? "");
|
|
453
|
-
|
|
454
|
-
|
|
486
|
+
process.stderr.write(
|
|
487
|
+
`→ console spawned: ay ${cli}${prompt ? ` -- "${prompt.slice(0, 60)}"` : ""} (cwd: ${cwd})\n`,
|
|
488
|
+
);
|
|
455
489
|
try {
|
|
456
490
|
const child = Bun.spawn(["ay", cli, ...(prompt ? ["--", prompt] : [])], {
|
|
457
491
|
cwd,
|
|
@@ -1,8 +0,0 @@
|
|
|
1
|
-
import "./ts-DkjQJTcB.js";
|
|
2
|
-
import "./logger-B9h0djqx.js";
|
|
3
|
-
import "./versionChecker-xqnqyGKE.js";
|
|
4
|
-
import "./pidStore-DTzl6zeh.js";
|
|
5
|
-
import "./globalPidIndex-yVd3mbsV.js";
|
|
6
|
-
import { t as SUPPORTED_CLIS } from "./SUPPORTED_CLIS-B2FAlgXF.js";
|
|
7
|
-
|
|
8
|
-
export { SUPPORTED_CLIS };
|