agent-yes 1.95.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-eD-UlqO_.js +8 -0
- 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/{remotes-Bjp2GYPz.js → remotes-C3xPRtfg.js} +1 -1
- package/dist/{remotes-oNI1fR7_.js → remotes-C9WMt5PY.js} +1 -1
- package/dist/{runningLock-C22d9SRJ.js → runningLock-CJxsoGdb.js} +1 -1
- package/dist/{serve-CixOwENN.js → serve-CKcbVPy6.js} +155 -19
- package/dist/share-DUhUA1Pi.js +184 -0
- package/dist/{subcommands-DjrOWqD9.js → subcommands-B4gXEu5I.js} +2 -2
- package/dist/{subcommands-D9wmaZ3U.js → subcommands-K242usI5.js} +4 -4
- package/dist/{tray-DHuD0nEk.js → tray-CWQe9DMY.js} +2 -2
- package/dist/{ts-BvWaEGsr.js → ts-BAc4Jcrw.js} +13 -4
- package/dist/{versionChecker-DfIPG9ui.js → versionChecker-MNvA73o9.js} +2 -2
- package/package.json +6 -2
- package/scripts/cf.ts +51 -0
- package/ts/index.ts +16 -0
- package/ts/rustBinary.ts +10 -35
- package/ts/serve.ts +184 -19
- package/ts/share.ts +190 -0
- package/dist/SUPPORTED_CLIS-CrlcmUcE.js +0 -12
- 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 };
|
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
|
|
@@ -147,4 +147,4 @@ async function cmdRemote(rest) {
|
|
|
147
147
|
|
|
148
148
|
//#endregion
|
|
149
149
|
export { resolveRemoteSpec as a, readRemotes as i, deleteRemoteAlias as n, writeRemoteAlias as o, parseDirectRemoteSpec as r, cmdRemote as t };
|
|
150
|
-
//# sourceMappingURL=remotes-
|
|
150
|
+
//# sourceMappingURL=remotes-C3xPRtfg.js.map
|
|
@@ -1,3 +1,3 @@
|
|
|
1
|
-
import { a as resolveRemoteSpec, i as readRemotes, n as deleteRemoteAlias, o as writeRemoteAlias, r as parseDirectRemoteSpec, t as cmdRemote } from "./remotes-
|
|
1
|
+
import { a as resolveRemoteSpec, i as readRemotes, n as deleteRemoteAlias, o as writeRemoteAlias, r as parseDirectRemoteSpec, t as cmdRemote } from "./remotes-C3xPRtfg.js";
|
|
2
2
|
|
|
3
3
|
export { cmdRemote };
|
|
@@ -1,11 +1,16 @@
|
|
|
1
|
+
import "./ts-BAc4Jcrw.js";
|
|
1
2
|
import "./logger-B9h0djqx.js";
|
|
3
|
+
import "./versionChecker-MNvA73o9.js";
|
|
4
|
+
import "./pidStore-DBjlqzo8.js";
|
|
2
5
|
import "./globalPidIndex-yVd3mbsV.js";
|
|
3
|
-
import "./
|
|
4
|
-
import
|
|
6
|
+
import { t as SUPPORTED_CLIS } from "./SUPPORTED_CLIS-eD-UlqO_.js";
|
|
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-K242usI5.js";
|
|
5
9
|
import yargs from "yargs";
|
|
6
|
-
import { mkdir, readFile, writeFile } from "fs/promises";
|
|
10
|
+
import { mkdir, open, readFile, writeFile } from "fs/promises";
|
|
7
11
|
import { homedir } from "os";
|
|
8
12
|
import path from "path";
|
|
13
|
+
import { watch } from "node:fs";
|
|
9
14
|
import { randomBytes, timingSafeEqual } from "crypto";
|
|
10
15
|
|
|
11
16
|
//#region ts/serve.ts
|
|
@@ -107,7 +112,7 @@ async function cmdServe(rest) {
|
|
|
107
112
|
Start an HTTP API server so remote machines can list/tail/send agents.
|
|
108
113
|
|
|
109
114
|
Options:
|
|
110
|
-
--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 --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
|
+
--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`);
|
|
111
116
|
return 0;
|
|
112
117
|
}
|
|
113
118
|
const sub = rest[0];
|
|
@@ -129,6 +134,13 @@ Options:
|
|
|
129
134
|
}).option("tls-key", {
|
|
130
135
|
type: "string",
|
|
131
136
|
description: "TLS private key file (PEM)"
|
|
137
|
+
}).option("share", {
|
|
138
|
+
type: "string",
|
|
139
|
+
description: "Share over WebRTC: bare flag mints a room+link, or pass webrtc://room:token@host"
|
|
140
|
+
}).option("allow-spawn", {
|
|
141
|
+
type: "boolean",
|
|
142
|
+
default: false,
|
|
143
|
+
description: "Deprecated no-op — the console can always spawn agents"
|
|
132
144
|
}).help(false).version(false).exitProcess(false).parseAsync();
|
|
133
145
|
const port = argv.port ?? DEFAULT_PORT;
|
|
134
146
|
const host = argv.host ?? "127.0.0.1";
|
|
@@ -194,9 +206,34 @@ Options:
|
|
|
194
206
|
return new Response(e.message, { status: 404 });
|
|
195
207
|
}
|
|
196
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
|
+
}
|
|
197
233
|
const tailM = /^\/api\/tail\/(.+)$/.exec(p);
|
|
198
234
|
if (req.method === "GET" && tailM) {
|
|
199
235
|
const keyword = decodeURIComponent(tailM[1]);
|
|
236
|
+
const raw = url.searchParams.get("raw") === "1";
|
|
200
237
|
try {
|
|
201
238
|
const record = await resolveOne(keyword, defaultOpts());
|
|
202
239
|
if (!record.log_file) return new Response(`pid ${record.pid}: no log_file`, { status: 404 });
|
|
@@ -206,7 +243,8 @@ Options:
|
|
|
206
243
|
const send = (text) => ctrl.enqueue(enc.encode(`data: ${JSON.stringify(text)}\n\n`));
|
|
207
244
|
const ping = () => ctrl.enqueue(enc.encode(": ping\n\n"));
|
|
208
245
|
const initBuf = await readFile(logPath).catch(() => Buffer.alloc(0));
|
|
209
|
-
send(
|
|
246
|
+
if (raw) send(new TextDecoder().decode(initBuf.slice(Math.max(0, initBuf.length - 65536))));
|
|
247
|
+
else send(await renderRawLog(initBuf, {
|
|
210
248
|
mode: "tail",
|
|
211
249
|
n: 96
|
|
212
250
|
}));
|
|
@@ -221,24 +259,43 @@ Options:
|
|
|
221
259
|
}, 15e3);
|
|
222
260
|
const ansiRe = /\x1b\[[0-?]*[ -/]*[@-~]|\x1b\][^\x07\x1b]*(?:\x07|\x1b\\)|\x1b[@-Z\\-_]/g;
|
|
223
261
|
const ctrlRe = /[\x00-\x08\x0b\x0c\x0e-\x1f\x7f]/g;
|
|
224
|
-
const
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
|
|
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;
|
|
229
267
|
try {
|
|
230
|
-
const
|
|
231
|
-
if (
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
|
|
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
|
+
}
|
|
281
|
+
}
|
|
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);
|
|
238
291
|
req.signal.addEventListener("abort", () => {
|
|
239
292
|
closed = true;
|
|
240
293
|
clearInterval(heartbeat);
|
|
241
294
|
clearInterval(poller);
|
|
295
|
+
try {
|
|
296
|
+
watcher?.close();
|
|
297
|
+
} catch {}
|
|
298
|
+
fh?.close().catch(() => {});
|
|
242
299
|
try {
|
|
243
300
|
ctrl.close();
|
|
244
301
|
} catch {}
|
|
@@ -279,6 +336,71 @@ Options:
|
|
|
279
336
|
return new Response(e.message, { status: 404 });
|
|
280
337
|
}
|
|
281
338
|
}
|
|
339
|
+
const resizeM = /^\/api\/resize\/(.+)$/.exec(p);
|
|
340
|
+
if (req.method === "POST" && resizeM) {
|
|
341
|
+
const keyword = decodeURIComponent(resizeM[1]);
|
|
342
|
+
let body;
|
|
343
|
+
try {
|
|
344
|
+
body = await req.json();
|
|
345
|
+
} catch {
|
|
346
|
+
return new Response("invalid JSON body", { status: 400 });
|
|
347
|
+
}
|
|
348
|
+
const cols = Math.max(1, Math.floor(Number(body.cols) || 0));
|
|
349
|
+
const rows = Math.max(1, Math.floor(Number(body.rows) || 0));
|
|
350
|
+
if (!cols || !rows) return new Response("missing cols/rows", { status: 400 });
|
|
351
|
+
try {
|
|
352
|
+
const record = await resolveOne(keyword, defaultOpts());
|
|
353
|
+
const ayHome = process.env.AGENT_YES_HOME ?? path.join(homedir(), ".agent-yes");
|
|
354
|
+
const winsizeDir = path.join(ayHome, "winsize");
|
|
355
|
+
await mkdir(winsizeDir, { recursive: true });
|
|
356
|
+
await writeFile(path.join(winsizeDir, String(record.pid)), `${cols} ${rows} ${Date.now()}\n`);
|
|
357
|
+
try {
|
|
358
|
+
process.kill(record.pid, "SIGWINCH");
|
|
359
|
+
} catch {}
|
|
360
|
+
return Response.json({
|
|
361
|
+
ok: true,
|
|
362
|
+
pid: record.pid,
|
|
363
|
+
cols,
|
|
364
|
+
rows
|
|
365
|
+
});
|
|
366
|
+
} catch (e) {
|
|
367
|
+
return new Response(e.message, { status: 404 });
|
|
368
|
+
}
|
|
369
|
+
}
|
|
370
|
+
if (req.method === "POST" && p === "/api/spawn") {
|
|
371
|
+
let body;
|
|
372
|
+
try {
|
|
373
|
+
body = await req.json();
|
|
374
|
+
} catch {
|
|
375
|
+
return new Response("invalid JSON body", { status: 400 });
|
|
376
|
+
}
|
|
377
|
+
const cli = String(body.cli ?? "claude");
|
|
378
|
+
if (!SUPPORTED_CLIS.includes(cli)) return new Response(`unsupported cli: ${cli}`, { status: 400 });
|
|
379
|
+
const cwd = typeof body.cwd === "string" && body.cwd ? body.cwd : process.cwd();
|
|
380
|
+
const prompt = String(body.prompt ?? "");
|
|
381
|
+
process.stderr.write(`→ console spawned: ay ${cli}${prompt ? ` -- "${prompt.slice(0, 60)}"` : ""} (cwd: ${cwd})\n`);
|
|
382
|
+
try {
|
|
383
|
+
const child = Bun.spawn([
|
|
384
|
+
"ay",
|
|
385
|
+
cli,
|
|
386
|
+
...prompt ? ["--", prompt] : []
|
|
387
|
+
], {
|
|
388
|
+
cwd,
|
|
389
|
+
stdin: "ignore",
|
|
390
|
+
stdout: "ignore",
|
|
391
|
+
stderr: "ignore"
|
|
392
|
+
});
|
|
393
|
+
child.unref();
|
|
394
|
+
return Response.json({
|
|
395
|
+
ok: true,
|
|
396
|
+
pid: child.pid,
|
|
397
|
+
cli,
|
|
398
|
+
cwd
|
|
399
|
+
});
|
|
400
|
+
} catch (e) {
|
|
401
|
+
return new Response(e.message, { status: 500 });
|
|
402
|
+
}
|
|
403
|
+
}
|
|
282
404
|
return new Response("Not Found", { status: 404 });
|
|
283
405
|
}
|
|
284
406
|
};
|
|
@@ -296,6 +418,20 @@ Options:
|
|
|
296
418
|
process.stdout.write(`save as alias:\n`);
|
|
297
419
|
process.stdout.write(` ay remote add <alias> ${scheme}://${token}@<host>:${port}\n\n`);
|
|
298
420
|
if (!useHttps) process.stdout.write("for HTTPS: ay serve --tls-cert cert.pem --tls-key key.pem\n openssl req -x509 -newkey rsa:2048 -keyout key.pem -out cert.pem -days 365 -nodes -subj '/CN=localhost'\n\n");
|
|
421
|
+
if (argv.share !== void 0) {
|
|
422
|
+
const shareUrl = typeof argv.share === "string" && argv.share.startsWith("webrtc://") ? argv.share : void 0;
|
|
423
|
+
try {
|
|
424
|
+
const { startShare } = await import("./share-DUhUA1Pi.js");
|
|
425
|
+
const { link } = await startShare({
|
|
426
|
+
url: shareUrl,
|
|
427
|
+
apiUrl: `http://127.0.0.1:${port}`,
|
|
428
|
+
apiToken: token
|
|
429
|
+
});
|
|
430
|
+
process.stdout.write(`\nshared over WebRTC — open this link (the token is eaten from the URL on open):\n ${link}\n\n`);
|
|
431
|
+
} catch (e) {
|
|
432
|
+
process.stderr.write(`ay serve --share failed: ${e.message}\n`);
|
|
433
|
+
}
|
|
434
|
+
}
|
|
299
435
|
process.stdout.write(`(Ctrl-C to stop)\n`);
|
|
300
436
|
await new Promise((resolve) => {
|
|
301
437
|
process.on("SIGINT", () => {
|
|
@@ -312,4 +448,4 @@ Options:
|
|
|
312
448
|
|
|
313
449
|
//#endregion
|
|
314
450
|
export { cmdServe };
|
|
315
|
-
//# sourceMappingURL=serve-
|
|
451
|
+
//# sourceMappingURL=serve-CKcbVPy6.js.map
|
|
@@ -0,0 +1,184 @@
|
|
|
1
|
+
import { randomBytes } from "crypto";
|
|
2
|
+
|
|
3
|
+
//#region ts/share.ts
|
|
4
|
+
const SUB = "ay-signal-1";
|
|
5
|
+
const ICE = [{ urls: "stun:stun.l.google.com:19302" }];
|
|
6
|
+
const MAX_CHUNK = 15e3;
|
|
7
|
+
const DEFAULT_SIGHOST = "s.agent-yes.com";
|
|
8
|
+
function parseShareUrl(s) {
|
|
9
|
+
const m = /^webrtc:\/\/([^:@/]+):([^@/]+)@(.+)$/.exec(s);
|
|
10
|
+
if (!m) throw new Error(`bad --share url: ${s} (want webrtc://room:token@host)`);
|
|
11
|
+
return {
|
|
12
|
+
room: m[1],
|
|
13
|
+
token: m[2],
|
|
14
|
+
host: m[3]
|
|
15
|
+
};
|
|
16
|
+
}
|
|
17
|
+
async function importRTC() {
|
|
18
|
+
try {
|
|
19
|
+
return (await import("node-datachannel/polyfill")).RTCPeerConnection;
|
|
20
|
+
} catch {
|
|
21
|
+
try {
|
|
22
|
+
const { existsSync, symlinkSync, mkdirSync, readdirSync } = await import("fs");
|
|
23
|
+
const path = (await import("path")).default;
|
|
24
|
+
const { createRequire } = await import("module");
|
|
25
|
+
const require = createRequire(import.meta.url);
|
|
26
|
+
const pkg = path.dirname(require.resolve("node-datachannel/package.json"));
|
|
27
|
+
const bin = path.join(pkg, "build", "Release", "node_datachannel.node");
|
|
28
|
+
const cacheRoot = path.join((await import("os")).homedir(), ".bun", "install", "cache");
|
|
29
|
+
if (existsSync(bin) && existsSync(cacheRoot)) for (const d of readdirSync(cacheRoot)) {
|
|
30
|
+
if (!d.startsWith("node-datachannel@")) continue;
|
|
31
|
+
const dst = path.join(cacheRoot, d, "build", "Release");
|
|
32
|
+
mkdirSync(dst, { recursive: true });
|
|
33
|
+
const link = path.join(dst, "node_datachannel.node");
|
|
34
|
+
if (!existsSync(link)) symlinkSync(bin, link);
|
|
35
|
+
}
|
|
36
|
+
} catch {}
|
|
37
|
+
return (await import("node-datachannel/polyfill")).RTCPeerConnection;
|
|
38
|
+
}
|
|
39
|
+
}
|
|
40
|
+
/** Start the share bridge. Resolves once signaling is connected; runs until the
|
|
41
|
+
* process exits, reconnecting signaling on drop. Returns the shareable link. */
|
|
42
|
+
async function startShare(opts) {
|
|
43
|
+
opts.url;
|
|
44
|
+
const sighost = opts.sighost ?? DEFAULT_SIGHOST;
|
|
45
|
+
const { room, token, host } = opts.url ? parseShareUrl(opts.url) : {
|
|
46
|
+
room: "r" + randomBytes(3).toString("hex"),
|
|
47
|
+
token: randomBytes(32).toString("hex"),
|
|
48
|
+
host: sighost
|
|
49
|
+
};
|
|
50
|
+
const RTCPeerConnection = await importRTC();
|
|
51
|
+
const wsScheme = host.startsWith("localhost") || host.startsWith("127.") ? "ws" : "wss";
|
|
52
|
+
const link = `${host === "s.agent-yes.com" ? "https://agent-yes.com" : "http://localhost:7778"}/#${room}:${token}${host === "s.agent-yes.com" ? "" : "@" + host}`;
|
|
53
|
+
const peers = /* @__PURE__ */ new Map();
|
|
54
|
+
const connectSignaling = (onReady) => {
|
|
55
|
+
const ws = new WebSocket(`${wsScheme}://${host}/${room}`, [SUB]);
|
|
56
|
+
let ready = false;
|
|
57
|
+
ws.onopen = () => {
|
|
58
|
+
ws.send(JSON.stringify({
|
|
59
|
+
type: "hello",
|
|
60
|
+
role: "host",
|
|
61
|
+
token
|
|
62
|
+
}));
|
|
63
|
+
ready = true;
|
|
64
|
+
onReady();
|
|
65
|
+
};
|
|
66
|
+
ws.onmessage = async (ev) => {
|
|
67
|
+
const m = JSON.parse(ev.data);
|
|
68
|
+
if (m.type === "peer-join") startPeer(ws, m.peer);
|
|
69
|
+
else if (m.type === "answer") await peers.get(m.from)?.pc.setRemoteDescription({
|
|
70
|
+
type: "answer",
|
|
71
|
+
sdp: m.sdp
|
|
72
|
+
});
|
|
73
|
+
else if (m.type === "candidate") await peers.get(m.from)?.pc.addIceCandidate(m.candidate).catch(() => {});
|
|
74
|
+
else if (m.type === "peer-leave") closePeer(m.peer);
|
|
75
|
+
};
|
|
76
|
+
ws.onclose = () => {
|
|
77
|
+
setTimeout(() => connectSignaling(() => {}), ready ? 1500 : 4e3);
|
|
78
|
+
};
|
|
79
|
+
ws.onerror = () => {};
|
|
80
|
+
return ws;
|
|
81
|
+
};
|
|
82
|
+
function startPeer(ws, peerId) {
|
|
83
|
+
const pc = new RTCPeerConnection({ iceServers: ICE });
|
|
84
|
+
const aborts = /* @__PURE__ */ new Map();
|
|
85
|
+
peers.set(peerId, {
|
|
86
|
+
pc,
|
|
87
|
+
aborts
|
|
88
|
+
});
|
|
89
|
+
pc.onicecandidate = (e) => {
|
|
90
|
+
if (e.candidate) ws.send(JSON.stringify({
|
|
91
|
+
type: "candidate",
|
|
92
|
+
to: peerId,
|
|
93
|
+
candidate: e.candidate
|
|
94
|
+
}));
|
|
95
|
+
};
|
|
96
|
+
pc.onconnectionstatechange = () => {
|
|
97
|
+
if ([
|
|
98
|
+
"failed",
|
|
99
|
+
"closed",
|
|
100
|
+
"disconnected"
|
|
101
|
+
].includes(pc.connectionState)) closePeer(peerId);
|
|
102
|
+
};
|
|
103
|
+
const dc = pc.createDataChannel("api");
|
|
104
|
+
dc.onmessage = (e) => onReq(dc, aborts, JSON.parse(e.data));
|
|
105
|
+
pc.createOffer().then((o) => pc.setLocalDescription(o)).then(() => ws.send(JSON.stringify({
|
|
106
|
+
type: "offer",
|
|
107
|
+
to: peerId,
|
|
108
|
+
sdp: pc.localDescription.sdp
|
|
109
|
+
})));
|
|
110
|
+
}
|
|
111
|
+
function closePeer(peerId) {
|
|
112
|
+
const p = peers.get(peerId);
|
|
113
|
+
if (!p) return;
|
|
114
|
+
for (const a of p.aborts.values()) a.abort();
|
|
115
|
+
try {
|
|
116
|
+
p.pc.close();
|
|
117
|
+
} catch {}
|
|
118
|
+
peers.delete(peerId);
|
|
119
|
+
}
|
|
120
|
+
function send(dc, obj) {
|
|
121
|
+
if (dc.readyState === "open") dc.send(JSON.stringify(obj));
|
|
122
|
+
}
|
|
123
|
+
async function onReq(dc, aborts, req) {
|
|
124
|
+
if (req.t === "abort") {
|
|
125
|
+
aborts.get(req.id)?.abort();
|
|
126
|
+
aborts.delete(req.id);
|
|
127
|
+
return;
|
|
128
|
+
}
|
|
129
|
+
if (req.t !== "req") return;
|
|
130
|
+
const { id, method, path: p, body } = req;
|
|
131
|
+
const ac = new AbortController();
|
|
132
|
+
aborts.set(id, ac);
|
|
133
|
+
try {
|
|
134
|
+
const res = await fetch(opts.apiUrl + p, {
|
|
135
|
+
method,
|
|
136
|
+
headers: {
|
|
137
|
+
Authorization: `Bearer ${opts.apiToken}`,
|
|
138
|
+
...body ? { "Content-Type": "application/json" } : {}
|
|
139
|
+
},
|
|
140
|
+
body: body ?? void 0,
|
|
141
|
+
signal: ac.signal
|
|
142
|
+
});
|
|
143
|
+
send(dc, {
|
|
144
|
+
t: "res",
|
|
145
|
+
id,
|
|
146
|
+
status: res.status,
|
|
147
|
+
ct: res.headers.get("content-type") ?? ""
|
|
148
|
+
});
|
|
149
|
+
const reader = res.body.getReader();
|
|
150
|
+
const dec = new TextDecoder();
|
|
151
|
+
for (;;) {
|
|
152
|
+
const { done, value } = await reader.read();
|
|
153
|
+
if (done) break;
|
|
154
|
+
const text = dec.decode(value, { stream: true });
|
|
155
|
+
for (let i = 0; i < text.length; i += MAX_CHUNK) send(dc, {
|
|
156
|
+
t: "data",
|
|
157
|
+
id,
|
|
158
|
+
chunk: text.slice(i, i + MAX_CHUNK)
|
|
159
|
+
});
|
|
160
|
+
}
|
|
161
|
+
send(dc, {
|
|
162
|
+
t: "end",
|
|
163
|
+
id
|
|
164
|
+
});
|
|
165
|
+
} catch (e) {
|
|
166
|
+
if (e.name !== "AbortError") send(dc, {
|
|
167
|
+
t: "end",
|
|
168
|
+
id,
|
|
169
|
+
error: String(e)
|
|
170
|
+
});
|
|
171
|
+
} finally {
|
|
172
|
+
aborts.delete(id);
|
|
173
|
+
}
|
|
174
|
+
}
|
|
175
|
+
await new Promise((resolve) => connectSignaling(resolve));
|
|
176
|
+
return {
|
|
177
|
+
room,
|
|
178
|
+
link
|
|
179
|
+
};
|
|
180
|
+
}
|
|
181
|
+
|
|
182
|
+
//#endregion
|
|
183
|
+
export { startShare };
|
|
184
|
+
//# sourceMappingURL=share-DUhUA1Pi.js.map
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import "./logger-B9h0djqx.js";
|
|
2
2
|
import "./globalPidIndex-yVd3mbsV.js";
|
|
3
|
-
import "./remotes-
|
|
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-
|
|
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-K242usI5.js";
|
|
5
5
|
|
|
6
6
|
export { cmdHelp, isSubcommand, runSubcommand };
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { i as readGlobalPids } from "./globalPidIndex-yVd3mbsV.js";
|
|
2
|
-
import { a as resolveRemoteSpec, i as readRemotes } from "./remotes-
|
|
2
|
+
import { a as resolveRemoteSpec, i as readRemotes } from "./remotes-C3xPRtfg.js";
|
|
3
3
|
import ms from "ms";
|
|
4
4
|
import yargs from "yargs";
|
|
5
5
|
import { appendFile, mkdir, open, readFile, stat, writeFile } from "fs/promises";
|
|
@@ -162,11 +162,11 @@ 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": {
|
|
169
|
-
const { cmdRemote } = await import("./remotes-
|
|
169
|
+
const { cmdRemote } = await import("./remotes-C9WMt5PY.js");
|
|
170
170
|
return cmdRemote(rest);
|
|
171
171
|
}
|
|
172
172
|
case "help": return cmdHelp();
|
|
@@ -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
|