agent-yes 1.193.0 → 1.194.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.
@@ -1,8 +1,8 @@
1
- import { t as CLIS_CONFIG } from "./ts-Cg0IpitM.js";
1
+ import { t as CLIS_CONFIG } from "./ts-6JcbtJh1.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-eK4A0Nql.js.map
8
+ //# sourceMappingURL=SUPPORTED_CLIS--WH2XfM2.js.map
@@ -0,0 +1,8 @@
1
+ import "./ts-6JcbtJh1.js";
2
+ import "./logger-CDIsZ-Pp.js";
3
+ import "./versionChecker-DDNKcQRx.js";
4
+ import "./pidStore-BIvsBQ8X.js";
5
+ import "./globalPidIndex-CoNr7tS8.js";
6
+ import { t as SUPPORTED_CLIS } from "./SUPPORTED_CLIS--WH2XfM2.js";
7
+
8
+ export { SUPPORTED_CLIS };
@@ -1,7 +1,7 @@
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-CYAk7q_c.js";
4
+ import { j as resolveOne } from "./subcommands-Ba0V9EEH.js";
5
5
  import "./e2e-BeKjLhmO.js";
6
6
  import "./webrtcLink-BG0Xc4-W.js";
7
7
  import "./remotes-oSmwSYaV.js";
@@ -228,4 +228,4 @@ function transformEvent(rawEvent, agentId, forwarded) {
228
228
 
229
229
  //#endregion
230
230
  export { createScopedShare, listShares, revokeAllShares, revokeShare };
231
- //# sourceMappingURL=agentShare-C2PSaiaa.js.map
231
+ //# sourceMappingURL=agentShare-BEXN8bNT.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-C_ztEPMs.js";
5
- import { n as getRustBinary } from "./rustBinary-BEEvKYm_.js";
4
+ import { i as versionString, n as displayVersion, t as checkAndAutoUpdate } from "./versionChecker-DDNKcQRx.js";
5
+ import { n as getRustBinary } from "./rustBinary-cTIMKGQp.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-B9-HhxcS.js");
288
+ const { isSubcommand, runSubcommand, cmdHelp } = await import("./subcommands-LP1Z8g-h.js");
289
289
  if (isHelpFlag && process.argv.length === 3) {
290
290
  await cmdHelp(managerCommands);
291
291
  process.exit(0);
@@ -327,7 +327,7 @@ if (config.useRust) {
327
327
  }
328
328
  }
329
329
  if (rustBinary) {
330
- const { SUPPORTED_CLIS } = await import("./SUPPORTED_CLIS-wAOAd_rx.js");
330
+ const { SUPPORTED_CLIS } = await import("./SUPPORTED_CLIS-NfXUfiWY.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}`);
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-Cg0IpitM.js";
1
+ import { a as removeControlCharacters, i as AgentContext, n as agentYes, r as config, t as CLIS_CONFIG } from "./ts-6JcbtJh1.js";
2
2
  import "./logger-CDIsZ-Pp.js";
3
- import "./versionChecker-C_ztEPMs.js";
3
+ import "./versionChecker-DDNKcQRx.js";
4
4
  import "./pidStore-BIvsBQ8X.js";
5
5
  import "./globalPidIndex-CoNr7tS8.js";
6
6
 
@@ -1,7 +1,7 @@
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-CYAk7q_c.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-Ba0V9EEH.js";
5
5
  import "./e2e-BeKjLhmO.js";
6
6
  import "./webrtcLink-BG0Xc4-W.js";
7
7
  import "./remotes-oSmwSYaV.js";
@@ -588,4 +588,4 @@ async function ensureDaemon() {
588
588
 
589
589
  //#endregion
590
590
  export { daemonStatus, ensureDaemon, requestDaemonStop, runDaemon };
591
- //# sourceMappingURL=notifyDaemon-pJJzfvcJ.js.map
591
+ //# sourceMappingURL=notifyDaemon-Deisyrbn.js.map
@@ -1,4 +1,4 @@
1
- import { r as getInstalledPackage } from "./versionChecker-C_ztEPMs.js";
1
+ import { r as getInstalledPackage } from "./versionChecker-DDNKcQRx.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-BEEvKYm_.js.map
228
+ //# sourceMappingURL=rustBinary-cTIMKGQp.js.map
@@ -1,9 +1,9 @@
1
- import "./ts-Cg0IpitM.js";
1
+ import "./ts-6JcbtJh1.js";
2
2
  import "./logger-CDIsZ-Pp.js";
3
- import "./versionChecker-C_ztEPMs.js";
3
+ import "./versionChecker-DDNKcQRx.js";
4
4
  import "./pidStore-BIvsBQ8X.js";
5
5
  import "./globalPidIndex-CoNr7tS8.js";
6
- import { t as SUPPORTED_CLIS } from "./SUPPORTED_CLIS-eK4A0Nql.js";
6
+ import { t as SUPPORTED_CLIS } from "./SUPPORTED_CLIS--WH2XfM2.js";
7
7
  import { d as resolveSpawnCwd } from "./workspaceConfig-_GtAZtsi.js";
8
8
  import { n as liveEnv, t as ensureNodeRuntime } from "./nodeRuntime-DZRjxpNp.js";
9
9
  import { createHash } from "node:crypto";
@@ -150,4 +150,4 @@ async function cmdSchedule(rest) {
150
150
 
151
151
  //#endregion
152
152
  export { cmdSchedule };
153
- //# sourceMappingURL=schedule-BuWv8206.js.map
153
+ //# sourceMappingURL=schedule-MQZjDaY6.js.map
@@ -1,13 +1,13 @@
1
- import "./ts-Cg0IpitM.js";
1
+ import "./ts-6JcbtJh1.js";
2
2
  import "./logger-CDIsZ-Pp.js";
3
- import { r as getInstalledPackage } from "./versionChecker-C_ztEPMs.js";
4
- import { t as findSpawnHiddenLauncher } from "./rustBinary-BEEvKYm_.js";
3
+ import { r as getInstalledPackage } from "./versionChecker-DDNKcQRx.js";
4
+ import { t as findSpawnHiddenLauncher } from "./rustBinary-cTIMKGQp.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-eK4A0Nql.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-CYAk7q_c.js";
9
+ import { t as SUPPORTED_CLIS } from "./SUPPORTED_CLIS--WH2XfM2.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-Ba0V9EEH.js";
11
11
  import "./e2e-BeKjLhmO.js";
12
12
  import "./webrtcLink-BG0Xc4-W.js";
13
13
  import "./remotes-oSmwSYaV.js";
@@ -1893,7 +1893,7 @@ Options:
1893
1893
  const perm = body.perm ?? "r";
1894
1894
  if (perm !== "r" && perm !== "rw") return new Response(`invalid perm ${perm} (want r or rw)`, { status: 400 });
1895
1895
  try {
1896
- const { createScopedShare } = await import("./agentShare-C2PSaiaa.js");
1896
+ const { createScopedShare } = await import("./agentShare-BEXN8bNT.js");
1897
1897
  const share = await createScopedShare({
1898
1898
  agent: body.agent,
1899
1899
  perm,
@@ -1908,12 +1908,12 @@ Options:
1908
1908
  }
1909
1909
  }
1910
1910
  if (req.method === "GET" && p === "/api/shares") {
1911
- const { listShares } = await import("./agentShare-C2PSaiaa.js");
1911
+ const { listShares } = await import("./agentShare-BEXN8bNT.js");
1912
1912
  return Response.json(listShares());
1913
1913
  }
1914
1914
  const revokeM = /^\/api\/share\/([^/]+)$/.exec(p);
1915
1915
  if (req.method === "DELETE" && revokeM) {
1916
- const { revokeShare } = await import("./agentShare-C2PSaiaa.js");
1916
+ const { revokeShare } = await import("./agentShare-BEXN8bNT.js");
1917
1917
  const ok = revokeShare(decodeURIComponent(revokeM[1]));
1918
1918
  return new Response(ok ? "revoked" : "no such share", { status: ok ? 200 : 404 });
1919
1919
  }
@@ -1990,6 +1990,7 @@ Options:
1990
1990
  if (req.method === "GET" && p === "/rtc.js") return serveUiFile("rtc.js", "text/javascript; charset=utf-8");
1991
1991
  if (req.method === "GET" && p === "/e2e.js") return serveUiFile("e2e.js", "text/javascript; charset=utf-8");
1992
1992
  if (req.method === "GET" && p === "/qrcode.js") return serveUiFile("qrcode.js", "text/javascript; charset=utf-8");
1993
+ if (req.method === "GET" && p === "/sw.js") return serveUiFile("sw.js", "text/javascript; charset=utf-8");
1993
1994
  if (req.method === "GET" && p === "/manifest.webmanifest") return serveUiFile("manifest.webmanifest", "application/manifest+json");
1994
1995
  if (req.method === "GET" && p === "/icon.svg") return serveUiFile("icon.svg", "image/svg+xml");
1995
1996
  if (req.method === "GET" && p === "/favicon.ico") return new Response(null, { status: 204 });
@@ -2094,7 +2095,7 @@ Options:
2094
2095
  const shutdown = (resolve) => {
2095
2096
  if (heartbeat) clearInterval(heartbeat);
2096
2097
  closeShare?.();
2097
- import("./agentShare-C2PSaiaa.js").then((m) => m.revokeAllShares()).catch(() => {});
2098
+ import("./agentShare-BEXN8bNT.js").then((m) => m.revokeAllShares()).catch(() => {});
2098
2099
  server?.stop();
2099
2100
  resolve();
2100
2101
  };
@@ -2107,4 +2108,4 @@ Options:
2107
2108
 
2108
2109
  //#endregion
2109
2110
  export { cmdServe };
2110
- //# sourceMappingURL=serve-BrCvRObJ.js.map
2111
+ //# sourceMappingURL=serve-hA23xPpg.js.map
@@ -32,7 +32,7 @@ async function cmdSetup(rest) {
32
32
  if (!existsSync(abs)) process.stderr.write(` note: that directory doesn't exist yet — create it, or agents spawned there will fail\n`);
33
33
  if (noShare) return 0;
34
34
  process.stdout.write(`\nsharing this machine to agent-yes.com…\n`);
35
- const { cmdServe } = await import("./serve-BrCvRObJ.js");
35
+ const { cmdServe } = await import("./serve-hA23xPpg.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-CL-giduA.js.map
45
+ //# sourceMappingURL=setup-C6grPf1R.js.map
@@ -1147,15 +1147,15 @@ async function runSubcommand(argv) {
1147
1147
  case "restart": return await cmdRestart(rest);
1148
1148
  case "note": return await cmdNote(rest);
1149
1149
  case "serve": {
1150
- const { cmdServe } = await import("./serve-BrCvRObJ.js");
1150
+ const { cmdServe } = await import("./serve-hA23xPpg.js");
1151
1151
  return cmdServe(rest);
1152
1152
  }
1153
1153
  case "setup": {
1154
- const { cmdSetup } = await import("./setup-CL-giduA.js");
1154
+ const { cmdSetup } = await import("./setup-C6grPf1R.js");
1155
1155
  return cmdSetup(rest);
1156
1156
  }
1157
1157
  case "schedule": {
1158
- const { cmdSchedule } = await import("./schedule-BuWv8206.js");
1158
+ const { cmdSchedule } = await import("./schedule-MQZjDaY6.js");
1159
1159
  return cmdSchedule(rest);
1160
1160
  }
1161
1161
  case "remote": {
@@ -4004,7 +4004,7 @@ async function cmdNotify(rest) {
4004
4004
  }
4005
4005
  const ensure = async () => {
4006
4006
  if (!argv["ensure-daemon"]) return;
4007
- const { ensureDaemon } = await import("./notifyDaemon-pJJzfvcJ.js");
4007
+ const { ensureDaemon } = await import("./notifyDaemon-Deisyrbn.js");
4008
4008
  await ensureDaemon().catch(() => null);
4009
4009
  };
4010
4010
  await heartbeatWatcher(parent, selfStartedAt);
@@ -4078,7 +4078,7 @@ async function cmdNotifyCursor(args) {
4078
4078
  }
4079
4079
  async function cmdNotifyd(rest) {
4080
4080
  const sub = rest[0] ?? "status";
4081
- const daemon = await import("./notifyDaemon-pJJzfvcJ.js");
4081
+ const daemon = await import("./notifyDaemon-Deisyrbn.js");
4082
4082
  switch (sub) {
4083
4083
  case "run": return daemon.runDaemon();
4084
4084
  case "once": return daemon.runDaemon({ once: true });
@@ -4105,4 +4105,4 @@ async function cmdNotifyd(rest) {
4105
4105
 
4106
4106
  //#endregion
4107
4107
  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 };
4108
- //# sourceMappingURL=subcommands-CYAk7q_c.js.map
4108
+ //# sourceMappingURL=subcommands-Ba0V9EEH.js.map
@@ -1,7 +1,7 @@
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-CYAk7q_c.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-Ba0V9EEH.js";
5
5
  import "./e2e-BeKjLhmO.js";
6
6
  import "./webrtcLink-BG0Xc4-W.js";
7
7
  import "./remotes-oSmwSYaV.js";
@@ -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-C_ztEPMs.js";
2
+ import { r as getInstalledPackage } from "./versionChecker-DDNKcQRx.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-Cg0IpitM.js.map
1827
+ //# sourceMappingURL=ts-6JcbtJh1.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.193.0";
10
+ var version = "1.194.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-C_ztEPMs.js.map
218
+ //# sourceMappingURL=versionChecker-DDNKcQRx.js.map
package/lab/ui/index.html CHANGED
@@ -392,6 +392,60 @@
392
392
  padding-bottom: 10px;
393
393
  margin-bottom: 4px;
394
394
  }
395
+ /* P2P preview overlay — full-window iframe of the exposed app. */
396
+ .preview-overlay {
397
+ position: fixed;
398
+ inset: 0;
399
+ z-index: 70;
400
+ display: flex;
401
+ flex-direction: column;
402
+ background: var(--bg);
403
+ }
404
+ .preview-overlay[hidden] {
405
+ display: none;
406
+ }
407
+ .preview-bar {
408
+ display: flex;
409
+ align-items: center;
410
+ gap: 10px;
411
+ padding: 6px 10px;
412
+ border-bottom: 1px solid var(--line);
413
+ background: var(--panel, var(--bg));
414
+ flex: 0 0 auto;
415
+ }
416
+ .preview-bar .preview-badge {
417
+ font-size: 11px;
418
+ font-weight: 600;
419
+ color: #3fb950;
420
+ border: 1px solid #3fb95055;
421
+ border-radius: 6px;
422
+ padding: 2px 7px;
423
+ white-space: nowrap;
424
+ }
425
+ .preview-bar .preview-title {
426
+ flex: 1;
427
+ min-width: 0;
428
+ overflow: hidden;
429
+ text-overflow: ellipsis;
430
+ white-space: nowrap;
431
+ opacity: 0.8;
432
+ font-size: 13px;
433
+ }
434
+ .preview-bar button {
435
+ border: 1px solid var(--line);
436
+ background: transparent;
437
+ color: var(--fg);
438
+ border-radius: 6px;
439
+ padding: 3px 9px;
440
+ cursor: pointer;
441
+ font-size: 13px;
442
+ }
443
+ .preview-frame {
444
+ flex: 1 1 auto;
445
+ border: 0;
446
+ width: 100%;
447
+ background: #fff;
448
+ }
395
449
  /* Share modal — QR + link for a single-agent view-only share. */
396
450
  .modal-backdrop {
397
451
  position: fixed;
@@ -1960,6 +2014,19 @@
1960
2014
  </div>
1961
2015
  </div>
1962
2016
 
2017
+ <!-- P2P preview: the exposed app rendered in-console over the machine's
2018
+ WebRTC tunnel (Service Worker proxies /w/p/<src>/<port>/*, no relay). -->
2019
+ <div class="preview-overlay" id="previewOverlay" hidden>
2020
+ <div class="preview-bar">
2021
+ <span class="preview-badge" title="served over a direct P2P WebRTC tunnel — traffic does not go through agent-yes.com">⚡ P2P · no relay</span>
2022
+ <span class="preview-title" id="previewTitle"></span>
2023
+ <button id="previewReload" type="button" title="reload">↻</button>
2024
+ <button id="previewPop" type="button" title="open in a new tab">↗</button>
2025
+ <button id="previewClose" type="button" title="close">✕</button>
2026
+ </div>
2027
+ <iframe class="preview-frame" id="previewFrame" title="preview"></iframe>
2028
+ </div>
2029
+
1963
2030
  <!-- Cmd/Ctrl+K omnibox: search agents by title (instant) then output (tail),
1964
2031
  or spawn a new agent in the highlighted agent's cwd with the typed prompt. -->
1965
2032
  <div class="omni" id="omni" style="display: none">
@@ -2176,6 +2243,15 @@
2176
2243
  started_at: a.startedAt,
2177
2244
  }));
2178
2245
  return {
2246
+ // Marker + raw tunnel access for the P2P preview: only a codehost
2247
+ // (`ch`) source can proxy a local port over its WebRTC DataChannel via
2248
+ // the daemon's `preview` plugin (/__codehost/port/<PORT>/*), so the
2249
+ // viewer's preview traffic stays peer-to-peer, off the edge relay.
2250
+ ch: true,
2251
+ peerId,
2252
+ previewFetch(port, method, path, init) {
2253
+ return chRoom.room.fetch(peerId, method, "/__codehost/port/" + port + path, init || {});
2254
+ },
2179
2255
  async fetchJSON(path) {
2180
2256
  let res;
2181
2257
  try {
@@ -2432,6 +2508,43 @@
2432
2508
  const sources = new Map(); // id -> { id, room, host, kind, tx, client, live, devices, serverCount }
2433
2509
  const srcFor = (e) => (e && sources.get(e._src)) || sources.get(LOCAL) || null;
2434
2510
  const txFor = (e) => srcFor(e)?.tx || localTx;
2511
+
2512
+ // Preview bridge: the Service Worker (which can't own the RTCPeerConnection)
2513
+ // forwards each /w/p/<src>/<port>/* request here; we run it over that
2514
+ // source's codehost tunnel (previewFetch → the daemon's `preview` plugin →
2515
+ // 127.0.0.1:<port>) and stream the response back through the message port.
2516
+ // This keeps the viewer's preview traffic peer-to-peer, off the edge relay.
2517
+ if ("serviceWorker" in navigator) {
2518
+ navigator.serviceWorker.addEventListener("message", (event) => {
2519
+ const msg = event.data;
2520
+ if (!msg || msg.type !== "ay-preview-fetch") return;
2521
+ const port = event.ports[0];
2522
+ const tx = sources.get(msg.src)?.tx;
2523
+ if (!tx || !tx.ch || !tx.previewFetch) {
2524
+ port.postMessage({ type: "error", message: "no P2P preview for this machine" });
2525
+ return;
2526
+ }
2527
+ const init = { headers: msg.headers };
2528
+ if (msg.body) init.body = new Uint8Array(msg.body);
2529
+ tx.previewFetch(msg.port, msg.method, msg.path, init)
2530
+ .then(async (res) => {
2531
+ const headers = {};
2532
+ res.headers.forEach((v, k) => (headers[k] = v));
2533
+ port.postMessage({ type: "head", status: res.status, statusText: res.statusText, headers });
2534
+ if (res.body) {
2535
+ const reader = res.body.getReader();
2536
+ for (;;) {
2537
+ const { done, value } = await reader.read();
2538
+ if (done) break;
2539
+ const buf = value.buffer.slice(value.byteOffset, value.byteOffset + value.byteLength);
2540
+ port.postMessage({ type: "body", chunk: buf }, [buf]);
2541
+ }
2542
+ }
2543
+ port.postMessage({ type: "end" });
2544
+ })
2545
+ .catch((err) => port.postMessage({ type: "error", message: String(err) }));
2546
+ });
2547
+ }
2435
2548
  // Every machine belonging to a room (for an ay-share room, the room itself).
2436
2549
  const roomSources = (name) => [...sources.values()].filter((s) => (s.room || s.id) === name);
2437
2550
  const roomLive = (name) =>
@@ -3397,6 +3510,23 @@
3397
3510
  btn.textContent = orig;
3398
3511
  }, 1200);
3399
3512
  }
3513
+ // In-console P2P preview: an iframe served from /w/p/<src>/<port>/, which
3514
+ // the Service Worker proxies over the machine's WebRTC tunnel (no relay).
3515
+ function openPreview(src, port) {
3516
+ // Scope-relative so it works at both /w/ (agent-yes.com) and / (ay serve).
3517
+ const url = new URL("p/" + encodeURIComponent(src) + "/" + port + "/", location.href).pathname;
3518
+ const frame = $("previewFrame");
3519
+ if (!frame) return window.open(url, "_blank");
3520
+ $("previewTitle").textContent = "localhost:" + port;
3521
+ frame.src = url;
3522
+ $("previewOverlay").hidden = false;
3523
+ }
3524
+ function closePreview() {
3525
+ const ov = $("previewOverlay");
3526
+ if (ov) ov.hidden = true;
3527
+ const frame = $("previewFrame");
3528
+ if (frame) frame.src = "about:blank"; // tear down the app + its tunnel
3529
+ }
3400
3530
  async function doExpose() {
3401
3531
  const tx = exposePendingTx || localTx;
3402
3532
  const port = exposePendingPort;
@@ -3435,7 +3565,7 @@
3435
3565
  return;
3436
3566
  }
3437
3567
  if (Array.isArray(arr))
3438
- for (const ex of arr) rows.push({ ...ex, _srcName: s.name || s.id, _tx: tx });
3568
+ for (const ex of arr) rows.push({ ...ex, _srcName: s.name || s.id, _src: s.id, _tx: tx });
3439
3569
  }),
3440
3570
  );
3441
3571
  list.textContent = "";
@@ -3470,8 +3600,19 @@
3470
3600
  meta.appendChild(host);
3471
3601
  row.appendChild(meta);
3472
3602
 
3603
+ // Preview here: render the app P2P over this machine's WebRTC tunnel
3604
+ // (no edge relay), in an in-console iframe. Only offered for a codehost
3605
+ // (ch) source, which has the `preview` plugin.
3606
+ if (ex._tx && ex._tx.ch) {
3607
+ const preview = document.createElement("button");
3608
+ preview.className = "primary";
3609
+ preview.textContent = "Preview";
3610
+ preview.title = "view in-console over a direct P2P tunnel (no relay)";
3611
+ preview.onclick = () => openPreview(ex._src, ex.port);
3612
+ row.appendChild(preview);
3613
+ }
3614
+
3473
3615
  const openBtn = document.createElement("button");
3474
- openBtn.className = "primary";
3475
3616
  openBtn.textContent = "Open";
3476
3617
  // Re-mint a fresh claim so the owner (or a guest) gets a usable link.
3477
3618
  openBtn.onclick = async () => {
@@ -3574,6 +3715,15 @@
3574
3715
  $("exposeModal")?.addEventListener("click", (e) => {
3575
3716
  if (e.target === $("exposeModal")) closeExposeModal();
3576
3717
  });
3718
+ $("previewClose")?.addEventListener("click", closePreview);
3719
+ $("previewReload")?.addEventListener("click", () => {
3720
+ const f = $("previewFrame");
3721
+ if (f) f.src = f.src;
3722
+ });
3723
+ $("previewPop")?.addEventListener("click", () => {
3724
+ const f = $("previewFrame");
3725
+ if (f && f.src && f.src !== "about:blank") window.open(f.src, "_blank");
3726
+ });
3577
3727
  })();
3578
3728
  (function shareModalBoot() {
3579
3729
  $("shareClose")?.addEventListener("click", closeShareModal);
package/lab/ui/sw.js CHANGED
@@ -6,7 +6,60 @@
6
6
  // fallback when offline, which is what makes the installed app launchable with no
7
7
  // network. WebSocket signaling and cross-origin CDN scripts are not GET fetches we
8
8
  // own, so they pass straight through.
9
- const CACHE = "agent-yes-w-v2";
9
+ const CACHE = "agent-yes-w-v3";
10
+ // Preview proxy: <scope>p/<encSrc>/<port>/* renders a machine's local dev
11
+ // server INSIDE the console's existing WebRTC tunnel (peer-to-peer, off the
12
+ // edge relay). We can't own the RTCPeerConnection here, so we forward each
13
+ // request to the controlling page (which does), streaming the response back.
14
+ // Scope-relative so it works at both /w/ (agent-yes.com) and / (ay serve --http).
15
+ const BASE = new URL("./", self.location.href).pathname; // "/w/" or "/"
16
+ const PREVIEW = new RegExp("^" + BASE.replace(/[.*+?^${}()|[\]\\]/g, "\\$&") + "p/([^/]+)/(\\d{1,5})(/.*)?$");
17
+
18
+ async function pickClient() {
19
+ const all = await self.clients.matchAll({ type: "window", includeUncontrolled: true });
20
+ // Prefer a real console tab (not the preview iframe itself).
21
+ return all.find((c) => !new URL(c.url).pathname.startsWith(BASE + "p/")) || all[0] || null;
22
+ }
23
+
24
+ async function proxyPreview(request, src, port, rest) {
25
+ const client = await pickClient();
26
+ if (!client) return new Response("open the agent-yes console to preview", { status: 502 });
27
+ const headers = {};
28
+ request.headers.forEach((v, k) => (headers[k] = v));
29
+ const body =
30
+ request.method === "GET" || request.method === "HEAD"
31
+ ? undefined
32
+ : new Uint8Array(await request.arrayBuffer());
33
+ return new Promise((resolve) => {
34
+ const mc = new MessageChannel();
35
+ let resolved = false;
36
+ mc.port1.onmessage = (ev) => {
37
+ const msg = ev.data;
38
+ if (msg.type === "head") {
39
+ const stream = new ReadableStream({
40
+ start(controller) {
41
+ mc.port1.onmessage = (e2) => {
42
+ const m2 = e2.data;
43
+ if (m2.type === "body") controller.enqueue(new Uint8Array(m2.chunk));
44
+ else if (m2.type === "end") controller.close();
45
+ else if (m2.type === "error") controller.error(new Error(m2.message));
46
+ };
47
+ },
48
+ });
49
+ resolved = true;
50
+ resolve(new Response(stream, { status: msg.status, statusText: msg.statusText, headers: msg.headers }));
51
+ } else if (msg.type === "error" && !resolved) {
52
+ resolved = true;
53
+ resolve(new Response("preview tunnel error: " + msg.message, { status: 502 }));
54
+ }
55
+ };
56
+ client.postMessage(
57
+ { type: "ay-preview-fetch", src, port: Number(port), method: request.method, path: rest, headers, body },
58
+ [mc.port2, ...(body ? [body.buffer] : [])],
59
+ );
60
+ });
61
+ }
62
+
10
63
  const SHELL = [
11
64
  "./",
12
65
  "./index.html",
@@ -35,23 +88,52 @@ self.addEventListener("activate", (e) => {
35
88
 
36
89
  self.addEventListener("fetch", (e) => {
37
90
  const req = e.request;
38
- if (req.method !== "GET") return;
39
91
  const url = new URL(req.url);
40
- // Only the same-origin /w/ shell; let everything else (CDN, signaling) be.
41
- if (url.origin !== self.location.origin || !url.pathname.startsWith("/w/")) return;
42
- e.respondWith(
43
- (async () => {
44
- try {
45
- const res = await fetch(req);
46
- if (res && res.ok) {
47
- const c = await caches.open(CACHE);
48
- c.put(req, res.clone());
49
- }
50
- return res;
51
- } catch {
52
- const cached = await caches.match(req);
53
- return cached || (await caches.match("./index.html")) || Response.error();
54
- }
55
- })(),
56
- );
92
+ if (url.origin !== self.location.origin) return; // CDN / signaling pass through
93
+ // Preview proxy (any method): a request is a preview request if its own path
94
+ // is under <base>p/<src>/<port>/ (the iframe navigation + relative URLs), OR
95
+ // it comes from a preview-iframe CLIENT (an app's absolute-path subresource
96
+ // like Vite's /@vite/client — which resolves to the origin root, not our
97
+ // prefix). Either way we proxy it to that machine's port over the tunnel.
98
+ const own = PREVIEW.exec(url.pathname);
99
+ if (own) {
100
+ const rest = (own[3] || "/") + url.search;
101
+ e.respondWith(proxyPreview(req, decodeURIComponent(own[1]), own[2], rest));
102
+ return;
103
+ }
104
+ e.respondWith(maybePreviewFromClient(e, req, url));
57
105
  });
106
+
107
+ // If the request came from a preview iframe, proxy it to that iframe's port
108
+ // (appPath = the request's own path); otherwise fall back to the shell handler.
109
+ async function maybePreviewFromClient(e, req, url) {
110
+ const clientId = e.clientId || e.resultingClientId;
111
+ if (clientId) {
112
+ const client = await self.clients.get(clientId).catch(() => null);
113
+ const cm = client && PREVIEW.exec(new URL(client.url).pathname);
114
+ if (cm) {
115
+ return proxyPreview(req, decodeURIComponent(cm[1]), cm[2], url.pathname + url.search);
116
+ }
117
+ }
118
+ return shellFetch(req, url);
119
+ }
120
+
121
+ async function shellFetch(req, url) {
122
+ const p = url.pathname;
123
+ // Pass through non-GET, the API (SSE/POST — never cache), and anything off the
124
+ // shell. Only cache the static console shell for offline launch.
125
+ const isApi = p === "/api" || p.startsWith("/api/");
126
+ if (req.method !== "GET" || isApi || !p.startsWith(BASE)) return fetch(req);
127
+ // Network-first for the same-origin shell; cache is the offline fallback.
128
+ try {
129
+ const res = await fetch(req);
130
+ if (res && res.ok) {
131
+ const c = await caches.open(CACHE);
132
+ c.put(req, res.clone());
133
+ }
134
+ return res;
135
+ } catch {
136
+ const cached = await caches.match(req);
137
+ return cached || (await caches.match("./index.html")) || Response.error();
138
+ }
139
+ }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "agent-yes",
3
- "version": "1.193.0",
3
+ "version": "1.194.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",
package/ts/serve.ts CHANGED
@@ -2887,6 +2887,11 @@ export async function cmdServe(rest: string[]): Promise<number> {
2887
2887
  return serveUiFile("e2e.js", "text/javascript; charset=utf-8");
2888
2888
  if (req.method === "GET" && p === "/qrcode.js")
2889
2889
  return serveUiFile("qrcode.js", "text/javascript; charset=utf-8");
2890
+ // The PWA / preview Service Worker. Without it, --http never registers a SW
2891
+ // (so the in-console P2P preview can't proxy). Served at the console root so
2892
+ // its scope covers /p/<src>/<port>/*.
2893
+ if (req.method === "GET" && p === "/sw.js")
2894
+ return serveUiFile("sw.js", "text/javascript; charset=utf-8");
2890
2895
  if (req.method === "GET" && p === "/manifest.webmanifest")
2891
2896
  return serveUiFile("manifest.webmanifest", "application/manifest+json");
2892
2897
  if (req.method === "GET" && p === "/icon.svg")
@@ -1,8 +0,0 @@
1
- import "./ts-Cg0IpitM.js";
2
- import "./logger-CDIsZ-Pp.js";
3
- import "./versionChecker-C_ztEPMs.js";
4
- import "./pidStore-BIvsBQ8X.js";
5
- import "./globalPidIndex-CoNr7tS8.js";
6
- import { t as SUPPORTED_CLIS } from "./SUPPORTED_CLIS-eK4A0Nql.js";
7
-
8
- export { SUPPORTED_CLIS };