agent-yes 1.189.1 → 1.190.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.
Files changed (28) hide show
  1. package/dist/SUPPORTED_CLIS-B729E086.js +8 -0
  2. package/dist/{SUPPORTED_CLIS-DcA00P5Z.js → SUPPORTED_CLIS-BB7Br0fS.js} +2 -2
  3. package/dist/{agentShare-D5qYAXeL.js → agentShare-BXfWzPJu.js} +3 -3
  4. package/dist/cli.js +8 -8
  5. package/dist/expose-DUYH0tvh.js +466 -0
  6. package/dist/{forkNested-C8q7E6mp.js → forkNested-C1kKsXi5.js} +1 -1
  7. package/dist/index.js +2 -2
  8. package/dist/{notifyDaemon-BZmlbBqN.js → notifyDaemon-APkkoCzC.js} +3 -3
  9. package/dist/{openBrowser-BO5RVYwL.js → openBrowser-DQVkxCyj.js} +1 -1
  10. package/dist/{remotes-DsTnQhyx.js → remotes-CgT91bMo.js} +2 -2
  11. package/dist/{remotes-BIHNxn1a.js → remotes-WVJBNajZ.js} +1 -1
  12. package/dist/{rustBinary-xhXsfVn-.js → rustBinary-C8YZUZGT.js} +2 -2
  13. package/dist/{schedule-BUp_RUVP.js → schedule-BYG6MGpH.js} +5 -5
  14. package/dist/{serve-CM9NHaCH.js → serve-Df3wcUU-.js} +15 -15
  15. package/dist/{setup-BE9NyUE3.js → setup-C65eaHZ8.js} +3 -3
  16. package/dist/{spawnGate-C5nBiUZQ.js → spawnGate-BejtWiMJ.js} +1 -1
  17. package/dist/{spawnGate-Clp9xBPX.js → spawnGate-CA5QD7D4.js} +2 -2
  18. package/dist/{subcommands-qe4h_Cvx.js → subcommands-D6TbKFTF.js} +2 -2
  19. package/dist/{subcommands-BYKJkWNP.js → subcommands-Deaq1dOk.js} +15 -10
  20. package/dist/{tray-DKwVRBwr.js → tray-PMOWFOfk.js} +1 -1
  21. package/dist/{ts-1qx-QhAe.js → ts-CeGEhsC9.js} +2 -2
  22. package/dist/{versionChecker-Do5ex5Wm.js → versionChecker-DXwf5ip7.js} +2 -2
  23. package/dist/{webrtcRemote-BLEbZnbY.js → webrtcRemote-CD5EQ3uX.js} +1 -1
  24. package/dist/{workspaceConfig-DKd6UvVm.js → workspaceConfig-_GtAZtsi.js} +1 -1
  25. package/package.json +3 -2
  26. package/ts/expose.ts +188 -0
  27. package/ts/subcommands.ts +6 -0
  28. package/dist/SUPPORTED_CLIS-D8ocFVqe.js +0 -8
@@ -0,0 +1,8 @@
1
+ import "./ts-CeGEhsC9.js";
2
+ import "./logger-CDIsZ-Pp.js";
3
+ import "./versionChecker-DXwf5ip7.js";
4
+ import "./pidStore-BIvsBQ8X.js";
5
+ import "./globalPidIndex-CoNr7tS8.js";
6
+ import { t as SUPPORTED_CLIS } from "./SUPPORTED_CLIS-BB7Br0fS.js";
7
+
8
+ export { SUPPORTED_CLIS };
@@ -1,8 +1,8 @@
1
- import { t as CLIS_CONFIG } from "./ts-1qx-QhAe.js";
1
+ import { t as CLIS_CONFIG } from "./ts-CeGEhsC9.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-DcA00P5Z.js.map
8
+ //# sourceMappingURL=SUPPORTED_CLIS-BB7Br0fS.js.map
@@ -1,10 +1,10 @@
1
1
  import "./logger-CDIsZ-Pp.js";
2
2
  import "./globalPidIndex-CoNr7tS8.js";
3
3
  import "./configShared-0MnIQ652.js";
4
- import { j as resolveOne } from "./subcommands-BYKJkWNP.js";
4
+ import { j as resolveOne } from "./subcommands-Deaq1dOk.js";
5
5
  import "./e2e-BeKjLhmO.js";
6
6
  import "./webrtcLink-BG0Xc4-W.js";
7
- import "./remotes-DsTnQhyx.js";
7
+ import "./remotes-CgT91bMo.js";
8
8
  import { r as startShare } from "./share-29YbzpbU.js";
9
9
 
10
10
  //#region ts/agentShare.ts
@@ -228,4 +228,4 @@ function transformEvent(rawEvent, agentId, forwarded) {
228
228
 
229
229
  //#endregion
230
230
  export { createScopedShare, listShares, revokeAllShares, revokeShare };
231
- //# sourceMappingURL=agentShare-D5qYAXeL.js.map
231
+ //# sourceMappingURL=agentShare-BXfWzPJu.js.map
package/dist/cli.js CHANGED
@@ -1,8 +1,8 @@
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, t as checkAndAutoUpdate } from "./versionChecker-Do5ex5Wm.js";
5
- import { n as getRustBinary } from "./rustBinary-xhXsfVn-.js";
4
+ import { i as versionString, n as displayVersion, t as checkAndAutoUpdate } from "./versionChecker-DXwf5ip7.js";
5
+ import { n as getRustBinary } from "./rustBinary-C8YZUZGT.js";
6
6
  import { argv } from "process";
7
7
  import { spawn } from "child_process";
8
8
  import ms from "ms";
@@ -285,7 +285,7 @@ function buildRustArgs(argv, cliFromScript, supportedClis) {
285
285
  const rawArg = process.argv[2];
286
286
  const managerCommands = !invokedCliName(process.argv);
287
287
  const isHelpFlag = rawArg === "-h" || rawArg === "--help";
288
- const { isSubcommand, runSubcommand, cmdHelp } = await import("./subcommands-qe4h_Cvx.js");
288
+ const { isSubcommand, runSubcommand, cmdHelp } = await import("./subcommands-D6TbKFTF.js");
289
289
  if (isHelpFlag && process.argv.length === 3) {
290
290
  await cmdHelp(managerCommands);
291
291
  process.exit(0);
@@ -299,16 +299,16 @@ await checkAndAutoUpdate();
299
299
  logger.info(versionString());
300
300
  const config = parseCliArgs(process.argv);
301
301
  if (config.tray) {
302
- const { startTray } = await import("./tray-DKwVRBwr.js");
302
+ const { startTray } = await import("./tray-PMOWFOfk.js");
303
303
  await startTray();
304
304
  await new Promise(() => {});
305
305
  }
306
306
  {
307
- const { ensureTray } = await import("./tray-DKwVRBwr.js");
307
+ const { ensureTray } = await import("./tray-PMOWFOfk.js");
308
308
  ensureTray();
309
309
  }
310
310
  if (!config.showVersion && !config.appendPrompt && !config.tray) {
311
- const { waitForSpawnCapacity } = await import("./spawnGate-C5nBiUZQ.js");
311
+ const { waitForSpawnCapacity } = await import("./spawnGate-BejtWiMJ.js");
312
312
  await waitForSpawnCapacity({
313
313
  onWait: (reason, waitedMs) => {
314
314
  if (config.verbose || waitedMs === 0) console.error(`[agent-yes] spawn gate: ${reason} — waiting…`);
@@ -327,14 +327,14 @@ if (config.useRust) {
327
327
  }
328
328
  }
329
329
  if (rustBinary) {
330
- const { SUPPORTED_CLIS } = await import("./SUPPORTED_CLIS-D8ocFVqe.js");
330
+ const { SUPPORTED_CLIS } = await import("./SUPPORTED_CLIS-B729E086.js");
331
331
  const rustArgs = buildRustArgs(process.argv, config.cli, SUPPORTED_CLIS);
332
332
  if (config.verbose) {
333
333
  console.log(`[rust] Using binary: ${rustBinary}`);
334
334
  console.log(`[rust] Args: ${rustArgs.join(" ")}`);
335
335
  }
336
336
  const attach = config.attach || process.env.AGENT_YES_ATTACH === "1";
337
- const { shouldForkNested, buildSpawnTutorial, waitForFifo } = await import("./forkNested-C8q7E6mp.js");
337
+ const { shouldForkNested, buildSpawnTutorial, waitForFifo } = await import("./forkNested-C1kKsXi5.js");
338
338
  if (shouldForkNested({
339
339
  isTTY: Boolean(process.stdout.isTTY),
340
340
  ayPid: process.env.AGENT_YES_PID,
@@ -0,0 +1,466 @@
1
+ import { createHash, randomBytes } from "node:crypto";
2
+ import { homedir } from "node:os";
3
+ import path from "node:path";
4
+ import { chmodSync, mkdirSync, readFileSync, renameSync, writeFileSync } from "node:fs";
5
+
6
+ //#region node_modules/codehost/src/tunnel/protocol.ts
7
+ let Op = /* @__PURE__ */ function(Op) {
8
+ Op[Op["HttpReq"] = 1] = "HttpReq";
9
+ Op[Op["HttpReqBody"] = 2] = "HttpReqBody";
10
+ Op[Op["HttpReqEnd"] = 3] = "HttpReqEnd";
11
+ Op[Op["HttpResHead"] = 4] = "HttpResHead";
12
+ Op[Op["HttpResBody"] = 5] = "HttpResBody";
13
+ Op[Op["HttpResEnd"] = 6] = "HttpResEnd";
14
+ Op[Op["WsOpen"] = 7] = "WsOpen";
15
+ Op[Op["WsText"] = 9] = "WsText";
16
+ Op[Op["WsBin"] = 10] = "WsBin";
17
+ Op[Op["WsClose"] = 11] = "WsClose";
18
+ Op[Op["WsOpenAck"] = 8] = "WsOpenAck";
19
+ Op[Op["Error"] = 12] = "Error";
20
+ Op[Op["WsCont"] = 13] = "WsCont";
21
+ return Op;
22
+ }({});
23
+ const FRAME_HEADER = 5;
24
+ const MAX_FRAME = 64 * 1024;
25
+ /** Max payload bytes per frame; larger bodies/messages are split across frames. */
26
+ const MAX_CHUNK = MAX_FRAME - FRAME_HEADER;
27
+ const enc = new TextEncoder();
28
+ const dec = new TextDecoder();
29
+ function encodeFrame(op, streamId, payload) {
30
+ const len = payload?.byteLength ?? 0;
31
+ const buf = new Uint8Array(5 + len);
32
+ buf[0] = op;
33
+ new DataView(buf.buffer).setUint32(1, streamId >>> 0, false);
34
+ if (payload && len) buf.set(payload, 5);
35
+ return buf;
36
+ }
37
+ function encodeJson(op, streamId, obj) {
38
+ return encodeFrame(op, streamId, enc.encode(JSON.stringify(obj)));
39
+ }
40
+ function decodeFrame(data) {
41
+ const u8 = data instanceof Uint8Array ? data : new Uint8Array(data);
42
+ return {
43
+ op: u8[0],
44
+ streamId: new DataView(u8.buffer, u8.byteOffset, u8.byteLength).getUint32(1, false),
45
+ payload: u8.subarray(5)
46
+ };
47
+ }
48
+ function payloadJson(payload) {
49
+ return JSON.parse(dec.decode(payload));
50
+ }
51
+ /** Split a body into MAX_CHUNK-sized slices (copies, safe to transfer). */
52
+ function* chunk(body) {
53
+ for (let off = 0; off < body.byteLength; off += MAX_CHUNK) yield body.slice(off, Math.min(off + MAX_CHUNK, body.byteLength));
54
+ }
55
+ function concatBytes(parts) {
56
+ if (parts.length === 1) return parts[0];
57
+ const total = parts.reduce((n, p) => n + p.byteLength, 0);
58
+ const out = new Uint8Array(total);
59
+ let off = 0;
60
+ for (const p of parts) {
61
+ out.set(p, off);
62
+ off += p.byteLength;
63
+ }
64
+ return out;
65
+ }
66
+ /**
67
+ * Frames for one WebSocket message. Messages that fit in a single frame emit
68
+ * just a WsText/WsBin frame (back-compatible). Larger ones are split into
69
+ * WsCont frames carrying the leading bytes, terminated by the WsText/WsBin
70
+ * frame with the final bytes; the receiver concatenates them in order.
71
+ */
72
+ function* wsMessageFrames(terminal, streamId, payload) {
73
+ let off = 0;
74
+ while (payload.byteLength - off > MAX_CHUNK) {
75
+ yield encodeFrame(Op.WsCont, streamId, payload.subarray(off, off + MAX_CHUNK));
76
+ off += MAX_CHUNK;
77
+ }
78
+ yield encodeFrame(terminal, streamId, payload.subarray(off));
79
+ }
80
+ /**
81
+ * Reassembles WsCont + terminal frames back into whole WebSocket messages,
82
+ * keyed by streamId. Feed it every WsCont/WsText/WsBin payload; it returns the
83
+ * complete message bytes on a terminal frame, or null while buffering.
84
+ */
85
+ var WsReassembler = class {
86
+ pending = /* @__PURE__ */ new Map();
87
+ cont(streamId, payload) {
88
+ const buf = this.pending.get(streamId);
89
+ if (buf) buf.push(payload.slice());
90
+ else this.pending.set(streamId, [payload.slice()]);
91
+ }
92
+ finish(streamId, payload) {
93
+ const buf = this.pending.get(streamId);
94
+ if (!buf) return payload;
95
+ this.pending.delete(streamId);
96
+ buf.push(payload);
97
+ return concatBytes(buf);
98
+ }
99
+ drop(streamId) {
100
+ this.pending.delete(streamId);
101
+ }
102
+ };
103
+
104
+ //#endregion
105
+ //#region node_modules/codehost/src/tunnel/host.ts
106
+ const textDecoder = new TextDecoder();
107
+ const HIGH_WATER = 4 * 1024 * 1024;
108
+ const LOW_WATER = 1 * 1024 * 1024;
109
+ const HOP_BY_HOP = new Set([
110
+ "connection",
111
+ "keep-alive",
112
+ "proxy-authenticate",
113
+ "proxy-authorization",
114
+ "te",
115
+ "trailer",
116
+ "transfer-encoding",
117
+ "upgrade",
118
+ "content-length",
119
+ "host"
120
+ ]);
121
+ /**
122
+ * Server half of the tunnel: bridges one transport to a local HTTP/WS server
123
+ * on 127.0.0.1. Multiplexes concurrent HTTP requests and WebSocket
124
+ * connections by streamId.
125
+ */
126
+ var TunnelHost = class {
127
+ httpStreams = /* @__PURE__ */ new Map();
128
+ wsConns = /* @__PURE__ */ new Map();
129
+ wsRx = new WsReassembler();
130
+ origin;
131
+ wsOrigin;
132
+ port;
133
+ stripPrefix;
134
+ onLocal;
135
+ constructor(transport, opts) {
136
+ this.transport = transport;
137
+ this.port = opts.port;
138
+ this.stripPrefix = opts.stripPrefix;
139
+ this.onLocal = opts.onLocal;
140
+ this.origin = `http://127.0.0.1:${opts.port}`;
141
+ this.wsOrigin = `ws://127.0.0.1:${opts.port}`;
142
+ transport.setBufferedAmountLow?.(LOW_WATER, () => this.drainWaiter?.());
143
+ transport.onFrame((data) => void this.onFrame(data));
144
+ transport.onClose(() => this.closeAll());
145
+ }
146
+ /** Map a tunneled path to the local server's path, stripping the base prefix. */
147
+ localPath(path) {
148
+ if (this.stripPrefix && path.startsWith(this.stripPrefix)) {
149
+ const rest = path.slice(this.stripPrefix.length);
150
+ return rest.startsWith("/") ? rest : `/${rest}`;
151
+ }
152
+ return path;
153
+ }
154
+ async onFrame(data) {
155
+ const { op, streamId, payload } = decodeFrame(data);
156
+ switch (op) {
157
+ case Op.HttpReq:
158
+ this.httpStreams.set(streamId, {
159
+ head: payloadJson(payload),
160
+ body: []
161
+ });
162
+ break;
163
+ case Op.HttpReqBody:
164
+ this.httpStreams.get(streamId)?.body.push(payload.slice());
165
+ break;
166
+ case Op.HttpReqEnd:
167
+ await this.doHttp(streamId);
168
+ break;
169
+ case Op.WsOpen:
170
+ this.openWs(streamId, payloadJson(payload));
171
+ break;
172
+ case Op.WsCont:
173
+ this.wsRx.cont(streamId, payload);
174
+ break;
175
+ case Op.WsText:
176
+ this.wsConns.get(streamId)?.send(textDecoder.decode(this.wsRx.finish(streamId, payload)));
177
+ break;
178
+ case Op.WsBin:
179
+ this.wsConns.get(streamId)?.send(this.wsRx.finish(streamId, payload));
180
+ break;
181
+ case Op.WsClose:
182
+ this.wsRx.drop(streamId);
183
+ this.wsConns.get(streamId)?.close();
184
+ this.wsConns.delete(streamId);
185
+ break;
186
+ }
187
+ }
188
+ async doHttp(streamId) {
189
+ const stream = this.httpStreams.get(streamId);
190
+ if (!stream) return;
191
+ this.httpStreams.delete(streamId);
192
+ const { method, path, headers } = stream.head;
193
+ const reqHeaders = new Headers();
194
+ let forwardedHost = "";
195
+ for (const [k, v] of Object.entries(headers)) {
196
+ const lk = k.toLowerCase();
197
+ if (lk === "x-forwarded-host") {
198
+ forwardedHost = v;
199
+ continue;
200
+ }
201
+ if (!HOP_BY_HOP.has(lk)) reqHeaders.set(k, v);
202
+ }
203
+ reqHeaders.set("host", forwardedHost || `127.0.0.1:${this.port}`);
204
+ const body = method !== "GET" && method !== "HEAD" && stream.body.length > 0 ? concatBytes(stream.body) : void 0;
205
+ const wantsGzip = reqHeaders.get("x-codehost-accept-gzip") === "1";
206
+ reqHeaders.delete("x-codehost-accept-gzip");
207
+ if (wantsGzip) reqHeaders.set("accept-encoding", "gzip");
208
+ try {
209
+ const local = this.onLocal?.({
210
+ method,
211
+ path,
212
+ headers: reqHeaders,
213
+ body
214
+ });
215
+ const res = local ? await local : await fetch(this.origin + this.localPath(path), {
216
+ method,
217
+ headers: reqHeaders,
218
+ body,
219
+ redirect: "manual",
220
+ ...wantsGzip ? { decompress: false } : {}
221
+ });
222
+ const resHeaders = {};
223
+ res.headers.forEach((v, k) => {
224
+ if (!HOP_BY_HOP.has(k.toLowerCase())) resHeaders[k] = v;
225
+ });
226
+ await this.send(encodeJson(Op.HttpResHead, streamId, {
227
+ status: res.status,
228
+ statusText: res.statusText,
229
+ headers: resHeaders
230
+ }));
231
+ if (res.body) {
232
+ const reader = res.body.getReader();
233
+ for (;;) {
234
+ const { done, value } = await reader.read();
235
+ if (done) break;
236
+ for (const part of chunk(value)) await this.send(encodeFrame(Op.HttpResBody, streamId, part));
237
+ }
238
+ }
239
+ await this.send(encodeFrame(Op.HttpResEnd, streamId));
240
+ } catch (err) {
241
+ await this.send(encodeJson(Op.Error, streamId, { message: `proxy error: ${String(err)}` }));
242
+ }
243
+ }
244
+ openWs(streamId, info) {
245
+ let ws;
246
+ try {
247
+ ws = new WebSocket(this.wsOrigin + this.localPath(info.path), info.protocols);
248
+ } catch (err) {
249
+ this.send(encodeJson(Op.WsOpenAck, streamId, {
250
+ ok: false,
251
+ error: String(err)
252
+ }));
253
+ return;
254
+ }
255
+ ws.binaryType = "arraybuffer";
256
+ this.wsConns.set(streamId, ws);
257
+ ws.onopen = () => {
258
+ this.send(encodeJson(Op.WsOpenAck, streamId, {
259
+ ok: true,
260
+ protocol: ws.protocol
261
+ }));
262
+ };
263
+ ws.onmessage = (ev) => {
264
+ const [terminal, u8] = typeof ev.data === "string" ? [Op.WsText, new TextEncoder().encode(ev.data)] : [Op.WsBin, ev.data instanceof ArrayBuffer ? new Uint8Array(ev.data) : new Uint8Array(ev.data)];
265
+ for (const frame of wsMessageFrames(terminal, streamId, u8)) this.send(frame);
266
+ };
267
+ ws.onclose = (ev) => {
268
+ this.send(encodeJson(Op.WsClose, streamId, {
269
+ code: ev.code,
270
+ reason: ev.reason
271
+ }));
272
+ this.wsConns.delete(streamId);
273
+ };
274
+ ws.onerror = () => {
275
+ this.send(encodeJson(Op.WsClose, streamId, {
276
+ code: 1006,
277
+ reason: "error"
278
+ }));
279
+ this.wsConns.delete(streamId);
280
+ };
281
+ }
282
+ sendTail = Promise.resolve();
283
+ send(frame) {
284
+ const p = this.sendTail.then(async () => {
285
+ await this.waitForDrain();
286
+ if (!this.transport.isOpen()) return;
287
+ this.transport.send(frame);
288
+ });
289
+ this.sendTail = p.catch(() => {});
290
+ return p;
291
+ }
292
+ drainWaiter = null;
293
+ waitForDrain() {
294
+ if (!this.transport.isOpen() || this.transport.bufferedAmount() < HIGH_WATER) return Promise.resolve();
295
+ return new Promise((resolve) => {
296
+ let settled = false;
297
+ const finish = () => {
298
+ if (settled) return;
299
+ settled = true;
300
+ clearInterval(timer);
301
+ this.drainWaiter = null;
302
+ resolve();
303
+ };
304
+ this.drainWaiter = finish;
305
+ const timer = setInterval(() => {
306
+ if (!this.transport.isOpen() || this.transport.bufferedAmount() < HIGH_WATER) finish();
307
+ }, 100);
308
+ });
309
+ }
310
+ closeAll() {
311
+ for (const ws of this.wsConns.values()) try {
312
+ ws.close();
313
+ } catch {}
314
+ this.wsConns.clear();
315
+ this.httpStreams.clear();
316
+ }
317
+ };
318
+
319
+ //#endregion
320
+ //#region ts/expose.ts
321
+ const DEFAULT_RELAY = "https://agent-yes.com";
322
+ const PING_MS = 25e3;
323
+ const RECONNECT_MIN_MS = 1e3;
324
+ const RECONNECT_MAX_MS = 3e4;
325
+ function exposuresPath() {
326
+ const home = process.env.AGENT_YES_HOME ?? path.join(homedir(), ".agent-yes");
327
+ mkdirSync(home, { recursive: true });
328
+ return path.join(home, "exposures.json");
329
+ }
330
+ /** Stable id+key per (relay, port): re-running `ay expose 5173` keeps its URL. */
331
+ function loadOrCreateExposure(relayHost, port) {
332
+ const file = exposuresPath();
333
+ let all = {};
334
+ try {
335
+ all = JSON.parse(readFileSync(file, "utf8"));
336
+ } catch {}
337
+ const slot = `${relayHost}:${port}`;
338
+ const existing = all[slot];
339
+ if (existing?.id && existing.key) return existing;
340
+ const rec = {
341
+ id: "x" + randomBytes(8).toString("hex").slice(0, 15),
342
+ key: randomBytes(32).toString("hex")
343
+ };
344
+ all[slot] = rec;
345
+ const tmp = file + ".tmp";
346
+ writeFileSync(tmp, JSON.stringify(all, null, 2) + "\n");
347
+ chmodSync(tmp, 384);
348
+ renameSync(tmp, file);
349
+ return rec;
350
+ }
351
+ /** Bun's browser-style WebSocket as a TunnelTransport. No bufferedAmountLow
352
+ * event exists here — TunnelHost's 100ms safety poll covers drain resume. */
353
+ function wsTransport(ws) {
354
+ return {
355
+ send: (frame) => {
356
+ const copy = new Uint8Array(frame.byteLength);
357
+ copy.set(frame);
358
+ ws.send(copy);
359
+ },
360
+ isOpen: () => ws.readyState === WebSocket.OPEN,
361
+ bufferedAmount: () => ws.bufferedAmount,
362
+ onFrame: (cb) => {
363
+ ws.addEventListener("message", (ev) => {
364
+ if (typeof ev.data === "string") return;
365
+ const d = ev.data;
366
+ cb(d instanceof Uint8Array ? d : new Uint8Array(d));
367
+ });
368
+ },
369
+ onClose: (cb) => ws.addEventListener("close", () => cb())
370
+ };
371
+ }
372
+ async function cmdExpose(args) {
373
+ let relay = DEFAULT_RELAY;
374
+ let port = 0;
375
+ for (let i = 0; i < args.length; i++) {
376
+ const a = args[i];
377
+ if (a === "--relay") relay = args[++i] ?? relay;
378
+ else if (a.startsWith("--relay=")) relay = a.slice(8);
379
+ else if (/^\d+$/.test(a)) port = Number(a);
380
+ else if (a === "-h" || a === "--help") {
381
+ console.log(`Usage: ay expose <port> [--relay ${DEFAULT_RELAY}]\n\nShares http://127.0.0.1:<port> at https://<id>.agent-yes.com (private:\nvisitors need the printed one-time claim link, which sets an 8h cookie).\nThe URL is stable per port on this machine. Ctrl-C stops sharing.`);
382
+ return 0;
383
+ }
384
+ }
385
+ if (!port || port < 1 || port > 65535) {
386
+ console.error("usage: ay expose <port> [--relay https://…] (see ay expose --help)");
387
+ return 1;
388
+ }
389
+ const relayUrl = new URL(relay);
390
+ const rec = loadOrCreateExposure(relayUrl.host, port);
391
+ const tunnelUrl = `${relayUrl.protocol === "http:" ? "ws:" : "wss:"}//${relayUrl.host}/_ay/tunnel/${rec.id}`;
392
+ const publicHost = relayUrl.host === "agent-yes.com" ? `${rec.id}.agent-yes.com` : relayUrl.host;
393
+ const claimToken = randomBytes(18).toString("base64url");
394
+ const claimHash = createHash("sha256").update(claimToken).digest("hex");
395
+ let stopped = false;
396
+ let ws = null;
397
+ let backoff = RECONNECT_MIN_MS;
398
+ let announced = false;
399
+ const connect = () => {
400
+ if (stopped) return;
401
+ ws = new WebSocket(tunnelUrl);
402
+ ws.binaryType = "arraybuffer";
403
+ const sock = ws;
404
+ let ping = null;
405
+ sock.addEventListener("open", () => {
406
+ sock.send(JSON.stringify({
407
+ t: "hello",
408
+ key: rec.key,
409
+ port,
410
+ claims: [claimHash],
411
+ v: 1
412
+ }));
413
+ });
414
+ sock.addEventListener("message", (ev) => {
415
+ if (typeof ev.data !== "string") return;
416
+ let msg;
417
+ try {
418
+ msg = JSON.parse(ev.data);
419
+ } catch {
420
+ return;
421
+ }
422
+ if (msg.t === "ready") {
423
+ backoff = RECONNECT_MIN_MS;
424
+ new TunnelHost(wsTransport(sock), { port });
425
+ ping = setInterval(() => {
426
+ if (sock.readyState === WebSocket.OPEN) sock.send("ping");
427
+ }, PING_MS);
428
+ if (!announced) {
429
+ announced = true;
430
+ console.log(`[ay expose] sharing 127.0.0.1:${port}`);
431
+ console.log(` url: https://${publicHost}/`);
432
+ console.log(` claim: https://${publicHost}/_ay/claim?t=${claimToken}`);
433
+ console.log(` (one-time link — opens access for 8h in that browser)`);
434
+ } else console.log(`[ay expose] reconnected`);
435
+ }
436
+ });
437
+ sock.addEventListener("close", (ev) => {
438
+ if (ping) clearInterval(ping);
439
+ if (stopped) return;
440
+ if (ev.code === 1008) {
441
+ console.error(`[ay expose] relay refused this exposure (${ev.reason || "forbidden"}) — giving up`);
442
+ process.exit(1);
443
+ }
444
+ console.log(`[ay expose] connection lost, retrying in ${Math.round(backoff / 1e3)}s…`);
445
+ setTimeout(connect, backoff);
446
+ backoff = Math.min(backoff * 2, RECONNECT_MAX_MS);
447
+ });
448
+ sock.addEventListener("error", () => {});
449
+ };
450
+ connect();
451
+ const shutdown = () => {
452
+ stopped = true;
453
+ console.log("\n[ay expose] stopped — the URL now answers 502 until you expose again");
454
+ try {
455
+ ws?.close();
456
+ } catch {}
457
+ process.exit(0);
458
+ };
459
+ process.on("SIGINT", shutdown);
460
+ process.on("SIGTERM", shutdown);
461
+ return new Promise(() => {});
462
+ }
463
+
464
+ //#endregion
465
+ export { cmdExpose };
466
+ //# sourceMappingURL=expose-DUYH0tvh.js.map
@@ -56,4 +56,4 @@ async function waitForFifo(pid, timeoutMs = 2e3, aborted) {
56
56
 
57
57
  //#endregion
58
58
  export { buildSpawnTutorial, shouldForkNested, waitForFifo };
59
- //# sourceMappingURL=forkNested-C8q7E6mp.js.map
59
+ //# sourceMappingURL=forkNested-C1kKsXi5.js.map
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-1qx-QhAe.js";
1
+ import { a as removeControlCharacters, i as AgentContext, n as agentYes, r as config, t as CLIS_CONFIG } from "./ts-CeGEhsC9.js";
2
2
  import "./logger-CDIsZ-Pp.js";
3
- import "./versionChecker-Do5ex5Wm.js";
3
+ import "./versionChecker-DXwf5ip7.js";
4
4
  import "./pidStore-BIvsBQ8X.js";
5
5
  import "./globalPidIndex-CoNr7tS8.js";
6
6
 
@@ -1,10 +1,10 @@
1
1
  import { n as logger } from "./logger-CDIsZ-Pp.js";
2
2
  import "./globalPidIndex-CoNr7tS8.js";
3
3
  import "./configShared-0MnIQ652.js";
4
- import { G as hostId, J as readInbox, K as listInboxParents, O as renderLogTailLines, Q as notifyDir, S as listRecords, U as appendEvent, W as gcInboxes, X as daemonLockDir, Y as shouldStealLock, Z as daemonLockOwnerPath, _ as isPidAlive, c as deriveLiveState, q as liveWatchers } from "./subcommands-BYKJkWNP.js";
4
+ import { G as hostId, J as readInbox, K as listInboxParents, O as renderLogTailLines, Q as notifyDir, S as listRecords, U as appendEvent, W as gcInboxes, X as daemonLockDir, Y as shouldStealLock, Z as daemonLockOwnerPath, _ as isPidAlive, c as deriveLiveState, q as liveWatchers } from "./subcommands-Deaq1dOk.js";
5
5
  import "./e2e-BeKjLhmO.js";
6
6
  import "./webrtcLink-BG0Xc4-W.js";
7
- import "./remotes-DsTnQhyx.js";
7
+ import "./remotes-CgT91bMo.js";
8
8
  import { mkdir, readFile, rename, rm, stat, writeFile } from "fs/promises";
9
9
  import { randomUUID } from "node:crypto";
10
10
  import { execFile } from "node:child_process";
@@ -588,4 +588,4 @@ async function ensureDaemon() {
588
588
 
589
589
  //#endregion
590
590
  export { daemonStatus, ensureDaemon, requestDaemonStop, runDaemon };
591
- //# sourceMappingURL=notifyDaemon-BZmlbBqN.js.map
591
+ //# sourceMappingURL=notifyDaemon-APkkoCzC.js.map
@@ -68,4 +68,4 @@ async function offerOpenInBrowser(url, prompt = "Open in browser now? [Y/n] ") {
68
68
 
69
69
  //#endregion
70
70
  export { offerOpenInBrowser };
71
- //# sourceMappingURL=openBrowser-BO5RVYwL.js.map
71
+ //# sourceMappingURL=openBrowser-DQVkxCyj.js.map
@@ -86,7 +86,7 @@ async function resolveRemoteSpec(spec) {
86
86
  * The bridge lives for the rest of the process (torn down on `process.exit`).
87
87
  */
88
88
  async function resolveWebrtc(link, keyword) {
89
- const { startWebrtcBridge } = await import("./webrtcRemote-BLEbZnbY.js");
89
+ const { startWebrtcBridge } = await import("./webrtcRemote-CD5EQ3uX.js");
90
90
  const bridge = await startWebrtcBridge(link);
91
91
  return {
92
92
  url: bridge.baseUrl,
@@ -173,4 +173,4 @@ async function cmdRemote(rest) {
173
173
 
174
174
  //#endregion
175
175
  export { resolveRemoteSpec as a, readRemotes as i, deleteRemoteAlias as n, writeRemoteAlias as o, parseDirectRemoteSpec as r, cmdRemote as t };
176
- //# sourceMappingURL=remotes-DsTnQhyx.js.map
176
+ //# sourceMappingURL=remotes-CgT91bMo.js.map
@@ -1,5 +1,5 @@
1
1
  import "./e2e-BeKjLhmO.js";
2
2
  import "./webrtcLink-BG0Xc4-W.js";
3
- import { a as resolveRemoteSpec, i as readRemotes, n as deleteRemoteAlias, o as writeRemoteAlias, r as parseDirectRemoteSpec, t as cmdRemote } from "./remotes-DsTnQhyx.js";
3
+ import { a as resolveRemoteSpec, i as readRemotes, n as deleteRemoteAlias, o as writeRemoteAlias, r as parseDirectRemoteSpec, t as cmdRemote } from "./remotes-CgT91bMo.js";
4
4
 
5
5
  export { cmdRemote };
@@ -1,4 +1,4 @@
1
- import { r as getInstalledPackage } from "./versionChecker-Do5ex5Wm.js";
1
+ import { r as getInstalledPackage } from "./versionChecker-DXwf5ip7.js";
2
2
  import { execFileSync } from "child_process";
3
3
  import { existsSync, mkdirSync, unlinkSync } from "fs";
4
4
  import { chmod, copyFile } from "fs/promises";
@@ -225,4 +225,4 @@ async function getRustBinary(options = {}) {
225
225
 
226
226
  //#endregion
227
227
  export { getRustBinary as n, findSpawnHiddenLauncher as t };
228
- //# sourceMappingURL=rustBinary-xhXsfVn-.js.map
228
+ //# sourceMappingURL=rustBinary-C8YZUZGT.js.map
@@ -1,10 +1,10 @@
1
- import "./ts-1qx-QhAe.js";
1
+ import "./ts-CeGEhsC9.js";
2
2
  import "./logger-CDIsZ-Pp.js";
3
- import "./versionChecker-Do5ex5Wm.js";
3
+ import "./versionChecker-DXwf5ip7.js";
4
4
  import "./pidStore-BIvsBQ8X.js";
5
5
  import "./globalPidIndex-CoNr7tS8.js";
6
- import { t as SUPPORTED_CLIS } from "./SUPPORTED_CLIS-DcA00P5Z.js";
7
- import { d as resolveSpawnCwd } from "./workspaceConfig-DKd6UvVm.js";
6
+ import { t as SUPPORTED_CLIS } from "./SUPPORTED_CLIS-BB7Br0fS.js";
7
+ import { d as resolveSpawnCwd } from "./workspaceConfig-_GtAZtsi.js";
8
8
  import { createHash } from "node:crypto";
9
9
 
10
10
  //#region ts/oxmgrService.ts
@@ -141,4 +141,4 @@ async function cmdSchedule(rest) {
141
141
 
142
142
  //#endregion
143
143
  export { cmdSchedule };
144
- //# sourceMappingURL=schedule-BUp_RUVP.js.map
144
+ //# sourceMappingURL=schedule-BYG6MGpH.js.map
@@ -1,18 +1,18 @@
1
- import "./ts-1qx-QhAe.js";
1
+ import "./ts-CeGEhsC9.js";
2
2
  import "./logger-CDIsZ-Pp.js";
3
- import { r as getInstalledPackage } from "./versionChecker-Do5ex5Wm.js";
4
- import { t as findSpawnHiddenLauncher } from "./rustBinary-xhXsfVn-.js";
3
+ import { r as getInstalledPackage } from "./versionChecker-DXwf5ip7.js";
4
+ import { t as findSpawnHiddenLauncher } from "./rustBinary-C8YZUZGT.js";
5
5
  import "./pidStore-BIvsBQ8X.js";
6
6
  import { a as updateGlobalPidStatus } from "./globalPidIndex-CoNr7tS8.js";
7
7
  import { t as pgidForWrapper } from "./reaper-CWF2_ATd.js";
8
8
  import "./configShared-0MnIQ652.js";
9
- import { t as SUPPORTED_CLIS } from "./SUPPORTED_CLIS-DcA00P5Z.js";
10
- import { $ as TYPING_BADGE, D as recentReadEdges, E as readPtysize, H as writeToIpc, I as snapshotStatus, O as renderLogTailLines, S as listRecords, T as readNotes, b as isUserTyping, f as extractNeedsInput, j as resolveOne, k as renderRawLog, l as deriveLiveStatus, o as controlCodeFromName, p as extractTaskCounts, u as extractBadges } from "./subcommands-BYKJkWNP.js";
9
+ import { t as SUPPORTED_CLIS } from "./SUPPORTED_CLIS-BB7Br0fS.js";
10
+ import { $ as TYPING_BADGE, D as recentReadEdges, E as readPtysize, H as writeToIpc, I as snapshotStatus, O as renderLogTailLines, S as listRecords, T as readNotes, b as isUserTyping, f as extractNeedsInput, j as resolveOne, k as renderRawLog, l as deriveLiveStatus, o as controlCodeFromName, p as extractTaskCounts, u as extractBadges } from "./subcommands-Deaq1dOk.js";
11
11
  import "./e2e-BeKjLhmO.js";
12
12
  import "./webrtcLink-BG0Xc4-W.js";
13
- import "./remotes-DsTnQhyx.js";
14
- import { a as getSpawnHook, c as hasProvisionHook, d as resolveSpawnCwd, i as getProvisionRoot, l as hasSpawnHook, r as getProvisionHook, u as isProvisionAllowed } from "./workspaceConfig-DKd6UvVm.js";
15
- import { r as spawnRejectionReason } from "./spawnGate-Clp9xBPX.js";
13
+ import "./remotes-CgT91bMo.js";
14
+ import { a as getSpawnHook, c as hasProvisionHook, d as resolveSpawnCwd, i as getProvisionRoot, l as hasSpawnHook, r as getProvisionHook, u as isProvisionAllowed } from "./workspaceConfig-_GtAZtsi.js";
15
+ import { r as spawnRejectionReason } from "./spawnGate-CA5QD7D4.js";
16
16
  import yargs from "yargs";
17
17
  import { mkdir, open, readFile, stat, unlink, writeFile } from "fs/promises";
18
18
  import { arch, cpus, freemem, homedir, hostname, loadavg, platform, totalmem, uptime, userInfo } from "os";
@@ -515,7 +515,7 @@ async function cmdServeDaemon(sub, args) {
515
515
  if (!webrtcDaemon) return;
516
516
  if (shareLink) {
517
517
  process.stdout.write(`\nshared over WebRTC — open this link (the token is eaten from the URL on open):\n ${shareLink}\n` + (shareLinkMinted ? ` (persistent room — same link across restarts; delete ~/.agent-yes/.share-room to rotate)\n` : ``));
518
- const { offerOpenInBrowser } = await import("./openBrowser-BO5RVYwL.js");
518
+ const { offerOpenInBrowser } = await import("./openBrowser-DQVkxCyj.js");
519
519
  await offerOpenInBrowser(shareLink);
520
520
  } else process.stdout.write("\nthe WebRTC share link carries a secret, so the daemon does NOT log it —\nread it from ~/.agent-yes/.share-link (mode 0600). The room persists in\n~/.agent-yes/.share-room, so the link survives restarts.\n");
521
521
  };
@@ -1851,7 +1851,7 @@ Options:
1851
1851
  const perm = body.perm ?? "r";
1852
1852
  if (perm !== "r" && perm !== "rw") return new Response(`invalid perm ${perm} (want r or rw)`, { status: 400 });
1853
1853
  try {
1854
- const { createScopedShare } = await import("./agentShare-D5qYAXeL.js");
1854
+ const { createScopedShare } = await import("./agentShare-BXfWzPJu.js");
1855
1855
  const share = await createScopedShare({
1856
1856
  agent: body.agent,
1857
1857
  perm,
@@ -1866,12 +1866,12 @@ Options:
1866
1866
  }
1867
1867
  }
1868
1868
  if (req.method === "GET" && p === "/api/shares") {
1869
- const { listShares } = await import("./agentShare-D5qYAXeL.js");
1869
+ const { listShares } = await import("./agentShare-BXfWzPJu.js");
1870
1870
  return Response.json(listShares());
1871
1871
  }
1872
1872
  const revokeM = /^\/api\/share\/([^/]+)$/.exec(p);
1873
1873
  if (req.method === "DELETE" && revokeM) {
1874
- const { revokeShare } = await import("./agentShare-D5qYAXeL.js");
1874
+ const { revokeShare } = await import("./agentShare-BXfWzPJu.js");
1875
1875
  const ok = revokeShare(decodeURIComponent(revokeM[1]));
1876
1876
  return new Response(ok ? "revoked" : "no such share", { status: ok ? 200 : 404 });
1877
1877
  }
@@ -1977,7 +1977,7 @@ Options:
1977
1977
  const persistNote = explicitUrl ? "\n" : ` (persistent room — same link across restarts; delete ~/.agent-yes/.share-room to rotate)\n\n`;
1978
1978
  process.stdout.write(`${wantHttp ? "\n" : ""}${lead}:\n ${link}\n` + persistNote);
1979
1979
  if (!rotated) {
1980
- const { offerOpenInBrowser } = await import("./openBrowser-BO5RVYwL.js");
1980
+ const { offerOpenInBrowser } = await import("./openBrowser-DQVkxCyj.js");
1981
1981
  await offerOpenInBrowser(link);
1982
1982
  }
1983
1983
  } else {
@@ -2016,7 +2016,7 @@ Options:
2016
2016
  const shutdown = (resolve) => {
2017
2017
  if (heartbeat) clearInterval(heartbeat);
2018
2018
  closeShare?.();
2019
- import("./agentShare-D5qYAXeL.js").then((m) => m.revokeAllShares()).catch(() => {});
2019
+ import("./agentShare-BXfWzPJu.js").then((m) => m.revokeAllShares()).catch(() => {});
2020
2020
  server?.stop();
2021
2021
  resolve();
2022
2022
  };
@@ -2029,4 +2029,4 @@ Options:
2029
2029
 
2030
2030
  //#endregion
2031
2031
  export { cmdServe };
2032
- //# sourceMappingURL=serve-CM9NHaCH.js.map
2032
+ //# sourceMappingURL=serve-Df3wcUU-.js.map
@@ -1,4 +1,4 @@
1
- import { f as setWorkspaceRoot, s as getWorkspaceRoot } from "./workspaceConfig-DKd6UvVm.js";
1
+ import { f as setWorkspaceRoot, s as getWorkspaceRoot } from "./workspaceConfig-_GtAZtsi.js";
2
2
  import { existsSync } from "node:fs";
3
3
  import { stdin, stdout } from "node:process";
4
4
  import { createInterface } from "node:readline/promises";
@@ -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-CM9NHaCH.js");
35
+ const { cmdServe } = await import("./serve-Df3wcUU-.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-BE9NyUE3.js.map
45
+ //# sourceMappingURL=setup-C65eaHZ8.js.map
@@ -1,5 +1,5 @@
1
1
  import "./logger-CDIsZ-Pp.js";
2
2
  import "./globalPidIndex-CoNr7tS8.js";
3
- import { i as waitForSpawnCapacity, n as spawnGateEnabled, r as spawnRejectionReason, t as memAvailableMb } from "./spawnGate-Clp9xBPX.js";
3
+ import { i as waitForSpawnCapacity, n as spawnGateEnabled, r as spawnRejectionReason, t as memAvailableMb } from "./spawnGate-CA5QD7D4.js";
4
4
 
5
5
  export { waitForSpawnCapacity };
@@ -1,5 +1,5 @@
1
1
  import { i as readGlobalPids } from "./globalPidIndex-CoNr7tS8.js";
2
- import { n as getMinFreeMb, o as getSpawnWaitMs, t as getMaxAgents } from "./workspaceConfig-DKd6UvVm.js";
2
+ import { n as getMinFreeMb, o as getSpawnWaitMs, t as getMaxAgents } from "./workspaceConfig-_GtAZtsi.js";
3
3
  import { readFile } from "fs/promises";
4
4
 
5
5
  //#region ts/spawnGate.ts
@@ -104,4 +104,4 @@ async function waitForSpawnCapacity(opts) {
104
104
 
105
105
  //#endregion
106
106
  export { waitForSpawnCapacity as i, spawnGateEnabled as n, spawnRejectionReason as r, memAvailableMb as t };
107
- //# sourceMappingURL=spawnGate-Clp9xBPX.js.map
107
+ //# sourceMappingURL=spawnGate-CA5QD7D4.js.map
@@ -1,9 +1,9 @@
1
1
  import "./logger-CDIsZ-Pp.js";
2
2
  import "./globalPidIndex-CoNr7tS8.js";
3
3
  import "./configShared-0MnIQ652.js";
4
- import { A as renderRawLogLines, B as waitForLogQuiet, C as matchKeyword, D as recentReadEdges, E as readPtysize, F as runSubcommand, H as writeToIpc, I as snapshotStatus, L as stdinActivityPath, M as resolveReadWindow, N as resolveResumeArgs, O as renderLogTailLines, P as restartHintLines, R as stopTipForCli, S as listRecords, T as readNotes, V as writeKeysPaced, _ as isPidAlive, a as cmdHelp, b as isUserTyping, c as deriveLiveState, d as extractMenu, f as extractNeedsInput, g as isExitRequest, h as isAgentStuck, i as backoffWhileTyping, j as resolveOne, k as renderRawLog, l as deriveLiveStatus, m as finalizedLines, n as READ_PAGE_DEFAULT, o as controlCodeFromName, p as extractTaskCounts, r as TYPING_WINDOW_MS, s as cursorAbs, t as GRACEFUL_EXIT_COMMANDS, u as extractBadges, v as isSlashCommand, w as menuSelectKeys, x as lastStdinAt, y as isSubcommand, z as submitAndConfirm } from "./subcommands-BYKJkWNP.js";
4
+ import { A as renderRawLogLines, B as waitForLogQuiet, C as matchKeyword, D as recentReadEdges, E as readPtysize, F as runSubcommand, H as writeToIpc, I as snapshotStatus, L as stdinActivityPath, M as resolveReadWindow, N as resolveResumeArgs, O as renderLogTailLines, P as restartHintLines, R as stopTipForCli, S as listRecords, T as readNotes, V as writeKeysPaced, _ as isPidAlive, a as cmdHelp, b as isUserTyping, c as deriveLiveState, d as extractMenu, f as extractNeedsInput, g as isExitRequest, h as isAgentStuck, i as backoffWhileTyping, j as resolveOne, k as renderRawLog, l as deriveLiveStatus, m as finalizedLines, n as READ_PAGE_DEFAULT, o as controlCodeFromName, p as extractTaskCounts, r as TYPING_WINDOW_MS, s as cursorAbs, t as GRACEFUL_EXIT_COMMANDS, u as extractBadges, v as isSlashCommand, w as menuSelectKeys, x as lastStdinAt, y as isSubcommand, z as submitAndConfirm } from "./subcommands-Deaq1dOk.js";
5
5
  import "./e2e-BeKjLhmO.js";
6
6
  import "./webrtcLink-BG0Xc4-W.js";
7
- import "./remotes-DsTnQhyx.js";
7
+ import "./remotes-CgT91bMo.js";
8
8
 
9
9
  export { cmdHelp, isSubcommand, runSubcommand };
@@ -4,7 +4,7 @@ import { t as agentYesHome } from "./agentYesHome-CtHb5b71.js";
4
4
  import { a as updateGlobalPidStatus, i as readGlobalPids } from "./globalPidIndex-CoNr7tS8.js";
5
5
  import { t as loadSharedCliDefaults } from "./configShared-0MnIQ652.js";
6
6
  import { n as isWebrtcSpec } from "./webrtcLink-BG0Xc4-W.js";
7
- import { a as resolveRemoteSpec, i as readRemotes } from "./remotes-DsTnQhyx.js";
7
+ import { a as resolveRemoteSpec, i as readRemotes } from "./remotes-CgT91bMo.js";
8
8
  import ms from "ms";
9
9
  import yargs from "yargs";
10
10
  import { appendFile, mkdir, open, readFile, readdir, rename, rm, stat, writeFile } from "fs/promises";
@@ -1086,6 +1086,7 @@ const SUBCOMMANDS = new Set([
1086
1086
  "serve",
1087
1087
  "schedule",
1088
1088
  "remote",
1089
+ "expose",
1089
1090
  "reap",
1090
1091
  "help"
1091
1092
  ]);
@@ -1145,21 +1146,25 @@ async function runSubcommand(argv) {
1145
1146
  case "restart": return await cmdRestart(rest);
1146
1147
  case "note": return await cmdNote(rest);
1147
1148
  case "serve": {
1148
- const { cmdServe } = await import("./serve-CM9NHaCH.js");
1149
+ const { cmdServe } = await import("./serve-Df3wcUU-.js");
1149
1150
  return cmdServe(rest);
1150
1151
  }
1151
1152
  case "setup": {
1152
- const { cmdSetup } = await import("./setup-BE9NyUE3.js");
1153
+ const { cmdSetup } = await import("./setup-C65eaHZ8.js");
1153
1154
  return cmdSetup(rest);
1154
1155
  }
1155
1156
  case "schedule": {
1156
- const { cmdSchedule } = await import("./schedule-BUp_RUVP.js");
1157
+ const { cmdSchedule } = await import("./schedule-BYG6MGpH.js");
1157
1158
  return cmdSchedule(rest);
1158
1159
  }
1159
1160
  case "remote": {
1160
- const { cmdRemote } = await import("./remotes-BIHNxn1a.js");
1161
+ const { cmdRemote } = await import("./remotes-WVJBNajZ.js");
1161
1162
  return cmdRemote(rest);
1162
1163
  }
1164
+ case "expose": {
1165
+ const { cmdExpose } = await import("./expose-DUYH0tvh.js");
1166
+ return cmdExpose(rest);
1167
+ }
1163
1168
  case "reap":
1164
1169
  await (await import("./reaper-jfSmog15.js")).sweep();
1165
1170
  return 0;
@@ -1194,7 +1199,7 @@ async function cmdHelp(managerCommands = true) {
1194
1199
  const setupLine = managerCommands ? ` ay setup guided setup: pick a workspace, share to agent-yes.com\n` : ``;
1195
1200
  const self = process.env.AGENT_YES_PID ? await resolveSender() : null;
1196
1201
  const agentSection = self ? await buildAgentContextSection(self) : "";
1197
- process.stdout.write(agentSection + "ay - agent-yes CLI\n\nManagement:\n ay ls [keyword] list running agents\n ay tail [-f] [-n N] <keyword> last N lines (96), -f to follow\n ay read <keyword> [page opts] paginate: --last/--head N, --range A:B,\n --before-line L [--limit N]\n ay cat <keyword> full log\n ay head <keyword> first N lines\n ay send <keyword> <msg> send a message\n ay key <keyword> <key...> send raw keystrokes (down/up/enter/esc/…) — drives menus\n ay select <keyword> <N> pick option N of a needs_input selection menu\n ay attach <keyword> interactive attach (detach: Ctrl-\\)\n ay stop <keyword> graceful shutdown (/exit for claude/codex)\n ay exit <keyword> [reason] graceful shutdown, recording who/why (= 'ay send <kw> exit')\n ay restart <keyword> [--fresh] stop (if live) + relaunch resuming the session; --fresh replays the prompt\n ay status <keyword> agent status snapshot\n ay result <keyword> [--wait] pull an agent's structured result envelope\n ay result set '<json>' (inside an agent) deposit your result envelope\n ay reap kill process groups leaked by dead agents\n\nRemote:\n" + setupLine + " ay schedule <when> <cli> -- <msg> run an agent on a schedule (HH:MM or cron)\n ay serve [--port N] start HTTP API server (prints token)\n ay serve status show serve daemon/server status\n ay remote add <alias> http://<token>@<host>:<port>\n ay remote ls / rm <alias> manage saved remotes\n ay ls <token>@<host>:<port> connect inline (no alias needed)\n ay send <token>@<host>:<port>:<kw> <msg>\n\nRun an agent:\n ay [claude|codex|gemini|...] [options] -- [prompt]\n ay claude -- \"fix the bug in auth.ts\"\n ay claude --help full agent-runner options\n\nLabs (examples at https://github.com/snomiao/agent-yes/tree/main/lab):\n local-role-play/ designer + builder on one machine\n http-remote/ ay serve remote access demo\n p2p-pairing/ libp2p P2P (needs: cargo build --features swarm)\n");
1202
+ process.stdout.write(agentSection + "ay - agent-yes CLI\n\nManagement:\n ay ls [keyword] list running agents\n ay tail [-f] [-n N] <keyword> last N lines (96), -f to follow\n ay read <keyword> [page opts] paginate: --last/--head N, --range A:B,\n --before-line L [--limit N]\n ay cat <keyword> full log\n ay head <keyword> first N lines\n ay send <keyword> <msg> send a message\n ay key <keyword> <key...> send raw keystrokes (down/up/enter/esc/…) — drives menus\n ay select <keyword> <N> pick option N of a needs_input selection menu\n ay attach <keyword> interactive attach (detach: Ctrl-\\)\n ay stop <keyword> graceful shutdown (/exit for claude/codex)\n ay exit <keyword> [reason] graceful shutdown, recording who/why (= 'ay send <kw> exit')\n ay restart <keyword> [--fresh] stop (if live) + relaunch resuming the session; --fresh replays the prompt\n ay status <keyword> agent status snapshot\n ay result <keyword> [--wait] pull an agent's structured result envelope\n ay result set '<json>' (inside an agent) deposit your result envelope\n ay reap kill process groups leaked by dead agents\n\nRemote:\n" + setupLine + " ay schedule <when> <cli> -- <msg> run an agent on a schedule (HH:MM or cron)\n ay serve [--port N] start HTTP API server (prints token)\n ay serve status show serve daemon/server status\n ay remote add <alias> http://<token>@<host>:<port>\n ay remote ls / rm <alias> manage saved remotes\n ay expose <port> share localhost:<port> at https://<id>.agent-yes.com (private link)\n ay ls <token>@<host>:<port> connect inline (no alias needed)\n ay send <token>@<host>:<port>:<kw> <msg>\n\nRun an agent:\n ay [claude|codex|gemini|...] [options] -- [prompt]\n ay claude -- \"fix the bug in auth.ts\"\n ay claude --help full agent-runner options\n\nLabs (examples at https://github.com/snomiao/agent-yes/tree/main/lab):\n local-role-play/ designer + builder on one machine\n http-remote/ ay serve remote access demo\n p2p-pairing/ libp2p P2P (needs: cargo build --features swarm)\n");
1198
1203
  return 0;
1199
1204
  }
1200
1205
  function matchKeyword(record, keyword) {
@@ -1550,7 +1555,7 @@ async function fetchRemoteRecordsRaw(url, token, opts) {
1550
1555
  let base = url;
1551
1556
  let bearer = token;
1552
1557
  if (isWebrtcSpec(url)) {
1553
- const { startWebrtcBridge } = await import("./webrtcRemote-BLEbZnbY.js");
1558
+ const { startWebrtcBridge } = await import("./webrtcRemote-CD5EQ3uX.js");
1554
1559
  bridge = await startWebrtcBridge(url);
1555
1560
  base = bridge.baseUrl;
1556
1561
  bearer = bridge.token;
@@ -3991,7 +3996,7 @@ async function cmdNotify(rest) {
3991
3996
  }
3992
3997
  const ensure = async () => {
3993
3998
  if (!argv["ensure-daemon"]) return;
3994
- const { ensureDaemon } = await import("./notifyDaemon-BZmlbBqN.js");
3999
+ const { ensureDaemon } = await import("./notifyDaemon-APkkoCzC.js");
3995
4000
  await ensureDaemon().catch(() => null);
3996
4001
  };
3997
4002
  await heartbeatWatcher(parent, selfStartedAt);
@@ -4065,7 +4070,7 @@ async function cmdNotifyCursor(args) {
4065
4070
  }
4066
4071
  async function cmdNotifyd(rest) {
4067
4072
  const sub = rest[0] ?? "status";
4068
- const daemon = await import("./notifyDaemon-BZmlbBqN.js");
4073
+ const daemon = await import("./notifyDaemon-APkkoCzC.js");
4069
4074
  switch (sub) {
4070
4075
  case "run": return daemon.runDaemon();
4071
4076
  case "once": return daemon.runDaemon({ once: true });
@@ -4092,4 +4097,4 @@ async function cmdNotifyd(rest) {
4092
4097
 
4093
4098
  //#endregion
4094
4099
  export { TYPING_BADGE as $, renderRawLogLines as A, waitForLogQuiet as B, matchKeyword as C, recentReadEdges as D, readPtysize as E, runSubcommand as F, hostId as G, writeToIpc as H, snapshotStatus as I, readInbox as J, listInboxParents as K, stdinActivityPath as L, resolveReadWindow as M, resolveResumeArgs as N, renderLogTailLines as O, restartHintLines as P, notifyDir as Q, stopTipForCli as R, listRecords as S, readNotes as T, appendEvent as U, writeKeysPaced as V, gcInboxes as W, daemonLockDir as X, shouldStealLock as Y, daemonLockOwnerPath as Z, isPidAlive as _, cmdHelp as a, isUserTyping as b, deriveLiveState as c, extractMenu as d, extractNeedsInput as f, isExitRequest as g, isAgentStuck as h, backoffWhileTyping as i, resolveOne as j, renderRawLog as k, deriveLiveStatus as l, finalizedLines as m, READ_PAGE_DEFAULT as n, controlCodeFromName as o, extractTaskCounts as p, liveWatchers as q, TYPING_WINDOW_MS as r, cursorAbs as s, GRACEFUL_EXIT_COMMANDS as t, extractBadges as u, isSlashCommand as v, menuSelectKeys as w, lastStdinAt as x, isSubcommand as y, submitAndConfirm as z };
4095
- //# sourceMappingURL=subcommands-BYKJkWNP.js.map
4100
+ //# sourceMappingURL=subcommands-Deaq1dOk.js.map
@@ -187,4 +187,4 @@ async function startTray() {
187
187
 
188
188
  //#endregion
189
189
  export { ensureTray, startTray };
190
- //# sourceMappingURL=tray-DKwVRBwr.js.map
190
+ //# sourceMappingURL=tray-PMOWFOfk.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-Do5ex5Wm.js";
2
+ import { r as getInstalledPackage } from "./versionChecker-DXwf5ip7.js";
3
3
  import { t as agentYesHome } from "./agentYesHome-CtHb5b71.js";
4
4
  import { i as shouldUseLock, r as releaseLock, t as acquireLock } from "./runningLock-CNMl13dC.js";
5
5
  import { t as PidStore } from "./pidStore-BIvsBQ8X.js";
@@ -1824,4 +1824,4 @@ function sleep(ms) {
1824
1824
 
1825
1825
  //#endregion
1826
1826
  export { removeControlCharacters as a, AgentContext as i, agentYes as n, config as r, CLIS_CONFIG as t };
1827
- //# sourceMappingURL=ts-1qx-QhAe.js.map
1827
+ //# sourceMappingURL=ts-CeGEhsC9.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.189.1";
10
+ var version = "1.190.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-Do5ex5Wm.js.map
218
+ //# sourceMappingURL=versionChecker-DXwf5ip7.js.map
@@ -256,4 +256,4 @@ async function startWebrtcBridge(link) {
256
256
 
257
257
  //#endregion
258
258
  export { startWebrtcBridge };
259
- //# sourceMappingURL=webrtcRemote-BLEbZnbY.js.map
259
+ //# sourceMappingURL=webrtcRemote-CD5EQ3uX.js.map
@@ -193,4 +193,4 @@ function resolveSpawnCwd(input) {
193
193
 
194
194
  //#endregion
195
195
  export { getSpawnHook as a, hasProvisionHook as c, resolveSpawnCwd as d, setWorkspaceRoot as f, getProvisionRoot as i, hasSpawnHook as l, getMinFreeMb as n, getSpawnWaitMs as o, getProvisionHook as r, getWorkspaceRoot as s, getMaxAgents as t, isProvisionAllowed as u };
196
- //# sourceMappingURL=workspaceConfig-DKd6UvVm.js.map
196
+ //# sourceMappingURL=workspaceConfig-_GtAZtsi.js.map
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "agent-yes",
3
- "version": "1.189.1",
3
+ "version": "1.190.0",
4
4
  "description": "A wrapper tool that automates interactions with various AI CLI tools by automatically handling common prompts and responses.",
5
5
  "keywords": [
6
6
  "ai",
@@ -150,7 +150,8 @@
150
150
  "tsdown": "^0.20.3",
151
151
  "vitest": "4.1.0",
152
152
  "ws": "^8.20.0",
153
- "zod": "^3.23.0"
153
+ "zod": "^3.23.0",
154
+ "codehost": "^0.32.0"
154
155
  },
155
156
  "peerDependencies": {
156
157
  "node-pty": "latest",
package/ts/expose.ts ADDED
@@ -0,0 +1,188 @@
1
+ // `ay expose <port>` — share a local HTTP/WS server through the agent-yes edge
2
+ // relay: https://<id>.agent-yes.com/* ⇄ Exposure DO ⇄ this daemon ⇄ 127.0.0.1:<port>.
3
+ //
4
+ // The daemon dials OUT (wss://<relay>/_ay/tunnel/<id>), so it works behind any
5
+ // NAT, and runs the codehost tunnel protocol's host half against the local
6
+ // port. Private by default: visitors need the single-use claim link printed
7
+ // below (it swaps for an 8h HttpOnly cookie at the edge; unauthenticated
8
+ // requests never reach this machine). See lab/ui/cf/exposure.ts for the edge.
9
+
10
+ import { randomBytes, createHash } from "node:crypto";
11
+ import { chmodSync, mkdirSync, readFileSync, renameSync, writeFileSync } from "node:fs";
12
+ import { homedir } from "node:os";
13
+ import path from "node:path";
14
+ import { TunnelHost } from "codehost/tunnel";
15
+ import type { TunnelTransport } from "codehost/tunnel";
16
+
17
+ const DEFAULT_RELAY = "https://agent-yes.com";
18
+ const PING_MS = 25_000;
19
+ const RECONNECT_MIN_MS = 1_000;
20
+ const RECONNECT_MAX_MS = 30_000;
21
+
22
+ interface ExposureRecord {
23
+ id: string;
24
+ key: string;
25
+ }
26
+
27
+ function exposuresPath(): string {
28
+ const home = process.env.AGENT_YES_HOME ?? path.join(homedir(), ".agent-yes");
29
+ mkdirSync(home, { recursive: true });
30
+ return path.join(home, "exposures.json");
31
+ }
32
+
33
+ /** Stable id+key per (relay, port): re-running `ay expose 5173` keeps its URL. */
34
+ function loadOrCreateExposure(relayHost: string, port: number): ExposureRecord {
35
+ const file = exposuresPath();
36
+ let all: Record<string, ExposureRecord> = {};
37
+ try {
38
+ all = JSON.parse(readFileSync(file, "utf8"));
39
+ } catch {
40
+ /* first run */
41
+ }
42
+ const slot = `${relayHost}:${port}`;
43
+ const existing = all[slot];
44
+ if (existing?.id && existing.key) return existing;
45
+ const rec: ExposureRecord = {
46
+ // "x" prefix: exposure hostnames can never collide with named subdomains.
47
+ id: "x" + randomBytes(8).toString("hex").slice(0, 15),
48
+ key: randomBytes(32).toString("hex"),
49
+ };
50
+ all[slot] = rec;
51
+ const tmp = file + ".tmp";
52
+ writeFileSync(tmp, JSON.stringify(all, null, 2) + "\n");
53
+ chmodSync(tmp, 0o600);
54
+ renameSync(tmp, file);
55
+ return rec;
56
+ }
57
+
58
+ /** Bun's browser-style WebSocket as a TunnelTransport. No bufferedAmountLow
59
+ * event exists here — TunnelHost's 100ms safety poll covers drain resume. */
60
+ function wsTransport(ws: WebSocket): TunnelTransport {
61
+ return {
62
+ // Copy into a fresh ArrayBuffer-backed view: Bun's ws.send mishandles a
63
+ // subarray view (byteOffset > 0), which the protocol's fragmentation emits.
64
+ send: (frame) => {
65
+ const copy = new Uint8Array(frame.byteLength);
66
+ copy.set(frame);
67
+ ws.send(copy);
68
+ },
69
+ isOpen: () => ws.readyState === WebSocket.OPEN,
70
+ bufferedAmount: () => ws.bufferedAmount,
71
+ onFrame: (cb) => {
72
+ ws.addEventListener("message", (ev) => {
73
+ if (typeof ev.data === "string") return;
74
+ const d = ev.data as ArrayBuffer | Uint8Array;
75
+ cb(d instanceof Uint8Array ? d : new Uint8Array(d));
76
+ });
77
+ },
78
+ onClose: (cb) => ws.addEventListener("close", () => cb()),
79
+ };
80
+ }
81
+
82
+ export async function cmdExpose(args: string[]): Promise<number> {
83
+ let relay = DEFAULT_RELAY;
84
+ let port = 0;
85
+ for (let i = 0; i < args.length; i++) {
86
+ const a = args[i]!;
87
+ if (a === "--relay") relay = args[++i] ?? relay;
88
+ else if (a.startsWith("--relay=")) relay = a.slice("--relay=".length);
89
+ else if (/^\d+$/.test(a)) port = Number(a);
90
+ else if (a === "-h" || a === "--help") {
91
+ console.log(
92
+ `Usage: ay expose <port> [--relay ${DEFAULT_RELAY}]\n\n` +
93
+ `Shares http://127.0.0.1:<port> at https://<id>.agent-yes.com (private:\n` +
94
+ `visitors need the printed one-time claim link, which sets an 8h cookie).\n` +
95
+ `The URL is stable per port on this machine. Ctrl-C stops sharing.`,
96
+ );
97
+ return 0;
98
+ }
99
+ }
100
+ if (!port || port < 1 || port > 65535) {
101
+ console.error("usage: ay expose <port> [--relay https://…] (see ay expose --help)");
102
+ return 1;
103
+ }
104
+
105
+ const relayUrl = new URL(relay);
106
+ const rec = loadOrCreateExposure(relayUrl.host, port);
107
+ const wsProto = relayUrl.protocol === "http:" ? "ws:" : "wss:";
108
+ const tunnelUrl = `${wsProto}//${relayUrl.host}/_ay/tunnel/${rec.id}`;
109
+ // Public hostname: <id>.<zone> on the real relay; the relay host itself (with
110
+ // a Host-header spoof) when pointing at wrangler dev.
111
+ const publicHost = relayUrl.host === "agent-yes.com" ? `${rec.id}.agent-yes.com` : relayUrl.host;
112
+
113
+ // Fresh single-use claim token every run; only its hash goes to the edge.
114
+ const claimToken = randomBytes(18).toString("base64url");
115
+ const claimHash = createHash("sha256").update(claimToken).digest("hex");
116
+
117
+ let stopped = false;
118
+ let ws: WebSocket | null = null;
119
+ let backoff = RECONNECT_MIN_MS;
120
+ let announced = false;
121
+
122
+ const connect = () => {
123
+ if (stopped) return;
124
+ ws = new WebSocket(tunnelUrl);
125
+ ws.binaryType = "arraybuffer";
126
+ const sock = ws;
127
+ let ping: ReturnType<typeof setInterval> | null = null;
128
+
129
+ sock.addEventListener("open", () => {
130
+ sock.send(JSON.stringify({ t: "hello", key: rec.key, port, claims: [claimHash], v: 1 }));
131
+ });
132
+ sock.addEventListener("message", (ev) => {
133
+ if (typeof ev.data !== "string") return; // binary frames belong to the TunnelHost
134
+ let msg: { t?: string };
135
+ try {
136
+ msg = JSON.parse(ev.data);
137
+ } catch {
138
+ return;
139
+ }
140
+ if (msg.t === "ready") {
141
+ backoff = RECONNECT_MIN_MS;
142
+ new TunnelHost(wsTransport(sock), { port });
143
+ ping = setInterval(() => {
144
+ if (sock.readyState === WebSocket.OPEN) sock.send("ping");
145
+ }, PING_MS);
146
+ if (!announced) {
147
+ announced = true;
148
+ console.log(`[ay expose] sharing 127.0.0.1:${port}`);
149
+ console.log(` url: https://${publicHost}/`);
150
+ console.log(` claim: https://${publicHost}/_ay/claim?t=${claimToken}`);
151
+ console.log(` (one-time link — opens access for 8h in that browser)`);
152
+ } else {
153
+ console.log(`[ay expose] reconnected`);
154
+ }
155
+ }
156
+ });
157
+ sock.addEventListener("close", (ev) => {
158
+ if (ping) clearInterval(ping);
159
+ if (stopped) return;
160
+ if (ev.code === 1008) {
161
+ console.error(`[ay expose] relay refused this exposure (${ev.reason || "forbidden"}) — giving up`);
162
+ process.exit(1);
163
+ }
164
+ console.log(`[ay expose] connection lost, retrying in ${Math.round(backoff / 1000)}s…`);
165
+ setTimeout(connect, backoff);
166
+ backoff = Math.min(backoff * 2, RECONNECT_MAX_MS);
167
+ });
168
+ sock.addEventListener("error", () => {
169
+ /* close fires right after; retry there */
170
+ });
171
+ };
172
+ connect();
173
+
174
+ const shutdown = () => {
175
+ stopped = true;
176
+ console.log("\n[ay expose] stopped — the URL now answers 502 until you expose again");
177
+ try {
178
+ ws?.close();
179
+ } catch {
180
+ /* ignore */
181
+ }
182
+ process.exit(0);
183
+ };
184
+ process.on("SIGINT", shutdown);
185
+ process.on("SIGTERM", shutdown);
186
+
187
+ return new Promise<number>(() => {}); // runs until signal
188
+ }
package/ts/subcommands.ts CHANGED
@@ -306,6 +306,7 @@ const SUBCOMMANDS = new Set([
306
306
  "serve",
307
307
  "schedule",
308
308
  "remote",
309
+ "expose",
309
310
  "reap",
310
311
  "help",
311
312
  ]);
@@ -427,6 +428,10 @@ export async function runSubcommand(argv: string[]): Promise<number | null> {
427
428
  const { cmdRemote } = await import("./remotes.ts");
428
429
  return cmdRemote(rest);
429
430
  }
431
+ case "expose": {
432
+ const { cmdExpose } = await import("./expose.ts");
433
+ return cmdExpose(rest);
434
+ }
430
435
  case "reap": {
431
436
  const reaper = await import("./reaper.ts");
432
437
  await reaper.sweep();
@@ -546,6 +551,7 @@ export async function cmdHelp(managerCommands = true): Promise<number> {
546
551
  ` ay serve status show serve daemon/server status\n` +
547
552
  ` ay remote add <alias> http://<token>@<host>:<port>\n` +
548
553
  ` ay remote ls / rm <alias> manage saved remotes\n` +
554
+ ` ay expose <port> share localhost:<port> at https://<id>.agent-yes.com (private link)\n` +
549
555
  ` ay ls <token>@<host>:<port> connect inline (no alias needed)\n` +
550
556
  ` ay send <token>@<host>:<port>:<kw> <msg>\n` +
551
557
  `\n` +
@@ -1,8 +0,0 @@
1
- import "./ts-1qx-QhAe.js";
2
- import "./logger-CDIsZ-Pp.js";
3
- import "./versionChecker-Do5ex5Wm.js";
4
- import "./pidStore-BIvsBQ8X.js";
5
- import "./globalPidIndex-CoNr7tS8.js";
6
- import { t as SUPPORTED_CLIS } from "./SUPPORTED_CLIS-DcA00P5Z.js";
7
-
8
- export { SUPPORTED_CLIS };