agent-yes 1.205.0 → 1.206.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -26,6 +26,8 @@ bun add -g agent-yes # or: npm install -g agent-yes
26
26
 
27
27
  Then: `ay claude` (run an agent with auto-yes) · `ay serve --share` (web console + shareable link) · live console at https://agent-yes.com
28
28
 
29
+ For the local web console, install [Portless](https://portless.sh/) once with `npm install -g portless`, then run `ay serve`. It assigns a free internal port and serves the console at `https://agent-yes.localhost/`. `ay serve --port N` remains available for a fixed-port API listener.
30
+
29
31
  ## Features
30
32
 
31
33
  - **Multi-CLI Support**: Works with Claude, Gemini, Codex, Copilot, and Cursor CLI tools
@@ -0,0 +1,9 @@
1
+ import "./ts-DnqRreF4.js";
2
+ import "./logger-CDIsZ-Pp.js";
3
+ import "./versionChecker-d5c6_vgS.js";
4
+ import "./pidStore-BIvsBQ8X.js";
5
+ import "./globalPidIndex-CoNr7tS8.js";
6
+ import "./messageLog-CxrKJj77.js";
7
+ import { t as SUPPORTED_CLIS } from "./SUPPORTED_CLIS-DQSgURGW.js";
8
+
9
+ export { SUPPORTED_CLIS };
@@ -1,8 +1,8 @@
1
- import { t as CLIS_CONFIG } from "./ts-Dm6jjLwC.js";
1
+ import { t as CLIS_CONFIG } from "./ts-DnqRreF4.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-C8-qh98a.js.map
8
+ //# sourceMappingURL=SUPPORTED_CLIS-DQSgURGW.js.map
@@ -2,11 +2,11 @@ import "./logger-CDIsZ-Pp.js";
2
2
  import "./globalPidIndex-CoNr7tS8.js";
3
3
  import "./messageLog-CxrKJj77.js";
4
4
  import "./configShared-aKTg-sa5.js";
5
- import { M as resolveOne } from "./subcommands-Bs7wJRBB.js";
5
+ import { M as resolveOne } from "./subcommands-DkrMRVNh.js";
6
6
  import "./e2e-jb0Hp43q.js";
7
7
  import "./webrtcLink-B7REGtK2.js";
8
8
  import "./remotes-Cim0dBU7.js";
9
- import { r as startShare } from "./share-BfIU8t_h.js";
9
+ import { r as startShare } from "./share-vchIyVd8.js";
10
10
 
11
11
  //#region ts/agentShare.ts
12
12
  const MAX_SHARES = 8;
@@ -229,4 +229,4 @@ function transformEvent(rawEvent, agentId, forwarded) {
229
229
 
230
230
  //#endregion
231
231
  export { createScopedShare, listShares, revokeAllShares, revokeShare };
232
- //# sourceMappingURL=agentShare-99IGGOkv.js.map
232
+ //# sourceMappingURL=agentShare-k8224qiZ.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-BomfUpSo.js";
5
- import { n as getRustBinary } from "./rustBinary-Tgn948GR.js";
4
+ import { i as versionString, n as displayVersion, t as checkAndAutoUpdate } from "./versionChecker-d5c6_vgS.js";
5
+ import { n as getRustBinary } from "./rustBinary-BjRvvEs8.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-DyDHZ5YI.js");
288
+ const { isSubcommand, runSubcommand, cmdHelp } = await import("./subcommands-DCGZjr4t.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-D3XTFfS7.js");
330
+ const { SUPPORTED_CLIS } = await import("./SUPPORTED_CLIS-CQ6e94ln.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-Dm6jjLwC.js";
1
+ import { a as removeControlCharacters, i as AgentContext, n as agentYes, r as config, t as CLIS_CONFIG } from "./ts-DnqRreF4.js";
2
2
  import "./logger-CDIsZ-Pp.js";
3
- import "./versionChecker-BomfUpSo.js";
3
+ import "./versionChecker-d5c6_vgS.js";
4
4
  import "./pidStore-BIvsBQ8X.js";
5
5
  import "./globalPidIndex-CoNr7tS8.js";
6
6
  import "./messageLog-CxrKJj77.js";
@@ -2,7 +2,7 @@ import { n as logger } from "./logger-CDIsZ-Pp.js";
2
2
  import "./globalPidIndex-CoNr7tS8.js";
3
3
  import "./messageLog-CxrKJj77.js";
4
4
  import "./configShared-aKTg-sa5.js";
5
- import { $ as daemonLockOwnerPath, G as gcInboxes, J as listInboxParents, K as hostId, Q as daemonLockDir, S as listRecords, W as appendEvent, X as readInbox, Y as liveWatchers, Z as shouldStealLock, _ as isPidAlive, c as deriveLiveState, et as notifyDir, k as renderLogTailLines } from "./subcommands-Bs7wJRBB.js";
5
+ import { $ as daemonLockOwnerPath, G as gcInboxes, J as listInboxParents, K as hostId, Q as daemonLockDir, S as listRecords, W as appendEvent, X as readInbox, Y as liveWatchers, Z as shouldStealLock, _ as isPidAlive, c as deriveLiveState, et as notifyDir, k as renderLogTailLines } from "./subcommands-DkrMRVNh.js";
6
6
  import "./e2e-jb0Hp43q.js";
7
7
  import "./webrtcLink-B7REGtK2.js";
8
8
  import "./remotes-Cim0dBU7.js";
@@ -589,4 +589,4 @@ async function ensureDaemon() {
589
589
 
590
590
  //#endregion
591
591
  export { daemonStatus, ensureDaemon, requestDaemonStop, runDaemon };
592
- //# sourceMappingURL=notifyDaemon-DK1HOMjj.js.map
592
+ //# sourceMappingURL=notifyDaemon-BbVnNvlo.js.map
@@ -1,4 +1,4 @@
1
- import { r as getInstalledPackage } from "./versionChecker-BomfUpSo.js";
1
+ import { r as getInstalledPackage } from "./versionChecker-d5c6_vgS.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-Tgn948GR.js.map
228
+ //# sourceMappingURL=rustBinary-BjRvvEs8.js.map
@@ -1,10 +1,10 @@
1
- import "./ts-Dm6jjLwC.js";
1
+ import "./ts-DnqRreF4.js";
2
2
  import "./logger-CDIsZ-Pp.js";
3
- import "./versionChecker-BomfUpSo.js";
3
+ import "./versionChecker-d5c6_vgS.js";
4
4
  import "./pidStore-BIvsBQ8X.js";
5
5
  import "./globalPidIndex-CoNr7tS8.js";
6
6
  import "./messageLog-CxrKJj77.js";
7
- import { t as SUPPORTED_CLIS } from "./SUPPORTED_CLIS-C8-qh98a.js";
7
+ import { t as SUPPORTED_CLIS } from "./SUPPORTED_CLIS-DQSgURGW.js";
8
8
  import { d as resolveSpawnCwd } from "./workspaceConfig-CjaRvTjf.js";
9
9
  import { n as liveEnv, t as ensureNodeRuntime } from "./nodeRuntime-CwNJuwH5.js";
10
10
  import { createHash } from "node:crypto";
@@ -151,4 +151,4 @@ async function cmdSchedule(rest) {
151
151
 
152
152
  //#endregion
153
153
  export { cmdSchedule };
154
- //# sourceMappingURL=schedule-CBoM67Vy.js.map
154
+ //# sourceMappingURL=schedule-DJ-v4yVa.js.map
@@ -1,15 +1,15 @@
1
- import "./ts-Dm6jjLwC.js";
1
+ import "./ts-DnqRreF4.js";
2
2
  import "./logger-CDIsZ-Pp.js";
3
- import { r as getInstalledPackage } from "./versionChecker-BomfUpSo.js";
4
- import { t as findSpawnHiddenLauncher } from "./rustBinary-Tgn948GR.js";
3
+ import { r as getInstalledPackage } from "./versionChecker-d5c6_vgS.js";
4
+ import { t as findSpawnHiddenLauncher } from "./rustBinary-BjRvvEs8.js";
5
5
  import { t as agentYesHome$1 } from "./agentYesHome-CtHb5b71.js";
6
6
  import "./pidStore-BIvsBQ8X.js";
7
7
  import { a as updateGlobalPidStatus } from "./globalPidIndex-CoNr7tS8.js";
8
8
  import { r as recordInbox } from "./messageLog-CxrKJj77.js";
9
9
  import { t as pgidForWrapper } from "./reaper-BUHCyxdF.js";
10
10
  import "./configShared-aKTg-sa5.js";
11
- import { t as SUPPORTED_CLIS } from "./SUPPORTED_CLIS-C8-qh98a.js";
12
- import { A as renderRawLog, D as recentMessageEdges, E as readPtysize, L as snapshotStatus, M as resolveOne, O as recentReadEdges, S as listRecords, T as readNotes, U as writeToIpc, b as isUserTyping, f as extractNeedsInput, k as renderLogTailLines, l as deriveLiveStatus, o as controlCodeFromName, p as extractTaskCounts, q as isTransientLockMkdirError, tt as TYPING_BADGE, u as extractBadges } from "./subcommands-Bs7wJRBB.js";
11
+ import { t as SUPPORTED_CLIS } from "./SUPPORTED_CLIS-DQSgURGW.js";
12
+ import { A as renderRawLog, D as recentMessageEdges, E as readPtysize, L as snapshotStatus, M as resolveOne, O as recentReadEdges, S as listRecords, T as readNotes, U as writeToIpc, b as isUserTyping, f as extractNeedsInput, k as renderLogTailLines, l as deriveLiveStatus, o as controlCodeFromName, p as extractTaskCounts, q as isTransientLockMkdirError, tt as TYPING_BADGE, u as extractBadges } from "./subcommands-DkrMRVNh.js";
13
13
  import "./e2e-jb0Hp43q.js";
14
14
  import "./webrtcLink-B7REGtK2.js";
15
15
  import "./remotes-Cim0dBU7.js";
@@ -43,6 +43,26 @@ import { existsSync, renameSync, watch, writeFileSync } from "node:fs";
43
43
  */
44
44
  const isTerminalReply = (s) => /^(?:\x1b\[(?:\??\d+(?:;\d+)*R|\?[\d;]*c|>[\d;]*c|\d*n))+$/.test(s);
45
45
 
46
+ //#endregion
47
+ //#region ts/statusText.ts
48
+ /**
49
+ * Extract a short "what is the agent doing right now?" line from the rendered
50
+ * terminal screen. Claude Code paints this as a spinner/status line, e.g.
51
+ * "✶ Verifying calendar meetings with real data… (6m 30s · ↓ 19.5k tokens)".
52
+ */
53
+ const SPINNER_PREFIX = /^[\u2800-\u28ff✶✻✢✳✽✦✧✩✷✸✹✺✼·•●◐◓◒◑]\s+/u;
54
+ const CONTROL = /[\x00-\x1f\x7f-\x9f]/g;
55
+ function parseStatusText(lines) {
56
+ for (let i = lines.length - 1; i >= 0; i--) {
57
+ const line = lines[i]?.replace(CONTROL, "").trim();
58
+ if (!line || line.length < 3) continue;
59
+ if (!SPINNER_PREFIX.test(line)) continue;
60
+ if (/^(?:[•·]\s*)?(?:esc|ctrl|enter|return|shift|tab)\b/i.test(line)) continue;
61
+ return line.slice(0, 220).trim();
62
+ }
63
+ return null;
64
+ }
65
+
46
66
  //#endregion
47
67
  //#region ts/serveLock.ts
48
68
  /**
@@ -236,7 +256,49 @@ async function listStrayServeProcesses() {
236
256
 
237
257
  //#endregion
238
258
  //#region ts/serve.ts
239
- const DEFAULT_PORT = 7432;
259
+ const DEFAULT_PORT = 0;
260
+ const PORTLESS_APP_NAME = "agent-yes";
261
+ const PORTLESS_CHILD_ENV = "AGENT_YES_PORTLESS_CHILD";
262
+ function portlessConsoleUrl(token) {
263
+ return portlessConsoleUrlForOrigin(process.env.PORTLESS_URL?.replace(/\/$/, "") || `https://${PORTLESS_APP_NAME}.localhost`, token);
264
+ }
265
+ function portlessConsoleUrlForOrigin(origin, token) {
266
+ return `${origin}${token ? `/#k=${encodeURIComponent(token)}` : "/"}`;
267
+ }
268
+ async function resolvedPortlessConsoleUrl(token) {
269
+ if (process.env.PORTLESS_URL) return portlessConsoleUrl(token);
270
+ try {
271
+ const port = Number((await readFile(path.join(homedir(), ".portless", "proxy.port"), "utf-8")).trim());
272
+ if (Number.isInteger(port) && port > 0) return portlessConsoleUrlForOrigin(`https://${PORTLESS_APP_NAME}.localhost${port === 443 ? "" : `:${port}`}`, token);
273
+ } catch {}
274
+ return portlessConsoleUrl(token);
275
+ }
276
+ async function runWithPortless(rest) {
277
+ const portless = Bun.which("portless");
278
+ if (!portless) {
279
+ process.stderr.write("ay serve: Portless is required for local HTTPS. Install it with: npm install -g portless\n");
280
+ return 1;
281
+ }
282
+ const script = process.argv[1];
283
+ const self = script && /\.[cm]?[jt]s$/.test(script) ? [process.execPath, script] : [process.execPath];
284
+ return await Bun.spawn([
285
+ portless,
286
+ PORTLESS_APP_NAME,
287
+ ...self,
288
+ "serve",
289
+ ...rest
290
+ ], {
291
+ stdio: [
292
+ "inherit",
293
+ "inherit",
294
+ "inherit"
295
+ ],
296
+ env: {
297
+ ...liveEnv(),
298
+ [PORTLESS_CHILD_ENV]: "1"
299
+ }
300
+ }).exited ?? 1;
301
+ }
240
302
  /**
241
303
  * Normalize a user-supplied GitHub-ish source into the standard
242
304
  * `<owner>/<repo>/tree/<branch>` path that codehost/provision's `parseSpec`
@@ -710,7 +772,18 @@ async function readDaemonServeArgs(mgr) {
710
772
  }
711
773
  function portFromArgs(args) {
712
774
  const m = /--port[=\s](\d+)/.exec(args.join(" "));
713
- return m ? Number(m[1]) : DEFAULT_PORT;
775
+ return m ? Number(m[1]) : null;
776
+ }
777
+ function argsUsePortless(args) {
778
+ return (args.some((a) => a.startsWith("--http") || a.startsWith("--share")) || !args.some((a) => a.startsWith("--webrtc"))) && portFromArgs(args) === null;
779
+ }
780
+ async function portlessAppPort() {
781
+ try {
782
+ const route = JSON.parse(await readFile(path.join(homedir(), ".portless", "routes.json"), "utf-8")).find((r) => r.hostname === `${PORTLESS_APP_NAME}.localhost`);
783
+ return typeof route?.port === "number" ? route.port : null;
784
+ } catch {
785
+ return null;
786
+ }
714
787
  }
715
788
  async function warnStrayServeProcesses() {
716
789
  const stray = await listStrayServeProcesses();
@@ -731,6 +804,7 @@ function explicitWebrtcUrl(args) {
731
804
  }
732
805
  }
733
806
  async function fetchDaemonVersion(port, token) {
807
+ if (port === null) return null;
734
808
  try {
735
809
  const r = await fetch(`http://127.0.0.1:${port}/api/version`, {
736
810
  headers: { Authorization: `Bearer ${token}` },
@@ -818,7 +892,7 @@ async function cmdServeDaemon(sub, args) {
818
892
  let shareLink = null;
819
893
  let shareLinkMinted = false;
820
894
  if (webrtcDaemon) try {
821
- const { loadOrCreateShareRoom, shareLinkFromRoomUrl } = await import("./share-Ciw1mWVN.js");
895
+ const { loadOrCreateShareRoom, shareLinkFromRoomUrl } = await import("./share-_QYjPN7q.js");
822
896
  const explicit = explicitWebrtcUrl(effArgs);
823
897
  shareLink = shareLinkFromRoomUrl(explicit ?? await loadOrCreateShareRoom());
824
898
  shareLinkMinted = !explicit;
@@ -833,7 +907,7 @@ async function cmdServeDaemon(sub, args) {
833
907
  };
834
908
  if (priorArgs !== null) {
835
909
  const sameConfig = JSON.stringify(effArgs) === JSON.stringify(priorArgs);
836
- const runningVer = await fetchDaemonVersion(portFromArgs(effArgs), token);
910
+ const runningVer = await fetchDaemonVersion(argsUsePortless(effArgs) ? await portlessAppPort() : portFromArgs(effArgs), token);
837
911
  if (runningVer === current && sameConfig) {
838
912
  await ensureBootAutostart(mgr);
839
913
  process.stdout.write(`'${DAEMON_NAME}' already running v${current} (up to date)\n`);
@@ -900,7 +974,8 @@ async function cmdServeDaemon(sub, args) {
900
974
  }).exited;
901
975
  if (code === 0) {
902
976
  const onBoot = await ensureBootAutostart(mgr);
903
- const port = portFromArgs(effArgs);
977
+ const port = argsUsePortless(effArgs) ? await portlessAppPort() : portFromArgs(effArgs);
978
+ const localUrl = argsUsePortless(effArgs) ? await resolvedPortlessConsoleUrl(token) : null;
904
979
  const httpish = effArgs.some((a) => a.startsWith("--http") || a.startsWith("--share")) || !effArgs.some((a) => a.startsWith("--webrtc"));
905
980
  process.stdout.write(`\n${priorArgs !== null ? `rolled '${DAEMON_NAME}' forward to` : `installed '${DAEMON_NAME}' as a daemon via ${mgr.id} —`} v${current}\n`);
906
981
  if (mgr.id === "oxmgr" && process.platform === "win32") process.stdout.write(onBoot ? `start-on-login: enabled (Task Scheduler ONLOGON runs \`oxmgr daemon run\`)\n` : `start-on-login: not registered — run \`oxmgr service install\` to enable\n`);
@@ -909,8 +984,11 @@ async function cmdServeDaemon(sub, args) {
909
984
  else process.stdout.write(onBoot ? `start-on-boot: enabled (pm2 startup registered with the system init)\n` : `start-on-boot: not registered — run \`pm2 startup\` (may need sudo) to enable\n`);
910
985
  process.stdout.write(`token: ${token}\n\n`);
911
986
  if (httpish) {
912
- process.stdout.write(` ay ls ${token}@<host>:${port}\n`);
913
- process.stdout.write(` ay remote add <alias> http://${token}@<host>:${port}\n`);
987
+ if (argsUsePortless(effArgs)) process.stdout.write(` web console: ${localUrl}\n`);
988
+ else if (port !== null) {
989
+ process.stdout.write(` ay ls ${token}@<host>:${port}\n`);
990
+ process.stdout.write(` ay remote add <alias> http://${token}@<host>:${port}\n`);
991
+ }
914
992
  }
915
993
  process.stdout.write(` ay serve logs # view server logs\n`);
916
994
  process.stdout.write(` ay serve uninstall # remove daemon\n`);
@@ -941,7 +1019,9 @@ async function cmdServeStatus(args) {
941
1019
  const daemonArgs = mgr ? await readDaemonServeArgs(mgr) : null;
942
1020
  const installed = daemonArgs !== null;
943
1021
  const a = daemonArgs ?? [];
944
- const port = portFromArgs(a);
1022
+ const local = argsUsePortless(a);
1023
+ const port = local ? await portlessAppPort() : portFromArgs(a);
1024
+ const localUrl = local ? await resolvedPortlessConsoleUrl(token ?? void 0) : null;
945
1025
  const webrtcish = a.some((x) => x.startsWith("--webrtc") || x.startsWith("--share"));
946
1026
  const httpish = a.some((x) => x.startsWith("--http") || x.startsWith("--share")) || !a.some((x) => x.startsWith("--webrtc"));
947
1027
  const mode = httpish && webrtcish ? "http+webrtc" : webrtcish ? "webrtc" : "http";
@@ -953,6 +1033,7 @@ async function cmdServeStatus(args) {
953
1033
  installed,
954
1034
  mode,
955
1035
  port: httpish ? port : null,
1036
+ localUrl: httpish ? localUrl : null,
956
1037
  reachable: runningVersion !== null,
957
1038
  runningVersion,
958
1039
  currentVersion: current,
@@ -968,18 +1049,23 @@ async function cmdServeStatus(args) {
968
1049
  w(`manager: ${mgr ? mgr.id : "none — install pm2 or oxmgr to daemonize"}`);
969
1050
  if (installed) {
970
1051
  w(`installed: yes (via ${mgr.id})`);
971
- w(`mode: ${mode}${httpish ? ` (port ${port})` : ""}`);
1052
+ w(`mode: ${mode}${httpish ? local ? ` (${localUrl})` : ` (port ${port})` : ""}`);
972
1053
  if (a.length) w(`args: ${a.join(" ")}`);
973
1054
  } else w(`installed: no — start a daemon with: ay serve install [--share]`);
974
- if (runningVersion !== null) w(`http api: reachable on 127.0.0.1:${port} — v${runningVersion} (${runningVersion === current ? "up to date" : `outdated (current v${current})`})`);
975
- else if (mode === "webrtc") w(`http api: none (webrtc-only)`);
976
- else w(`http api: not reachable on 127.0.0.1:${port} (not running)`);
1055
+ if (runningVersion !== null) {
1056
+ const tag = runningVersion === current ? "up to date" : `outdated (current v${current})`;
1057
+ w(`http api: reachable ${local ? `via ${localUrl}` : `on 127.0.0.1:${port}`} — v${runningVersion} (${tag})`);
1058
+ } else if (mode === "webrtc") w(`http api: none (webrtc-only)`);
1059
+ else w(`http api: not reachable ${local ? `via ${localUrl}` : `on 127.0.0.1:${port}`} (not running)`);
977
1060
  w(`token: ${token ?? "(none yet — created on first serve)"}`);
978
1061
  if (shareLink) w(`share link: ${shareLink}`);
979
1062
  if (token && httpish) {
980
1063
  w();
981
- w(`connect: ay ls ${token}@<host>:${port}`);
982
- w(` ay remote add <alias> http://${token}@<host>:${port}`);
1064
+ if (local) w(`console: ${localUrl}`);
1065
+ else if (port !== null) {
1066
+ w(`connect: ay ls ${token}@<host>:${port}`);
1067
+ w(` ay remote add <alias> http://${token}@<host>:${port}`);
1068
+ }
983
1069
  }
984
1070
  return 0;
985
1071
  }
@@ -1000,7 +1086,13 @@ Modes (default: --http):
1000
1086
  --share [URL] Legacy alias for --http --webrtc
1001
1087
 
1002
1088
  Options:
1003
- --port N Port to listen on (default: ${DEFAULT_PORT})\n --host HOST Interface to bind (default: 127.0.0.1; use 0.0.0.0 to expose)\n --token TOKEN Auth token (auto-generated and saved if omitted)\n -d, --daemon Install these flags as a background daemon (pm2/oxmgr)\n (same as: ay serve install <flags>)\n --allow-spawn Deprecated no-op — the console can always spawn agents\n --tls-cert FILE TLS certificate PEM\n --tls-key FILE TLS private key PEM\n\nSubcommands:\n ay serve install install as background daemon (oxmgr; pm2 fallback on Windows without the winfix build)\n ay serve status show daemon/server status (add --json for scripts)\n ay serve uninstall remove daemon\n ay serve logs view daemon logs\n\nOnce running, connect from another machine:\n ay ls <token>@<host>:${DEFAULT_PORT}\n ay remote add <alias> http://<token>@<host>:${DEFAULT_PORT}\n`);
1089
+ --port N Bypass Portless and listen on a fixed HTTP port
1090
+ --host HOST Interface to bind (default: 127.0.0.1; use 0.0.0.0 to expose)
1091
+ --token TOKEN Auth token (auto-generated and saved if omitted)
1092
+ -d, --daemon Install these flags as a background daemon (pm2/oxmgr)
1093
+ (same as: ay serve install <flags>)
1094
+ --local Explicitly use Portless (the default for HTTP mode)
1095
+ ${portlessConsoleUrl()}\n --allow-spawn Deprecated no-op — the console can always spawn agents\n --tls-cert FILE TLS certificate PEM\n --tls-key FILE TLS private key PEM\n\nSubcommands:\n ay serve install install as background daemon (oxmgr; pm2 fallback on Windows without the winfix build)\n ay serve status show daemon/server status (add --json for scripts)\n ay serve uninstall remove daemon\n ay serve logs view daemon logs\n\nOnce running, connect from another machine:\n ay ls <token>@<host>:<port>\n ay remote add <alias> http://<token>@<host>:<port>\n`);
1004
1096
  return 0;
1005
1097
  }
1006
1098
  const sub = rest[0];
@@ -1020,8 +1112,7 @@ Options:
1020
1112
  if (sub === "install" || sub === "uninstall" || sub === "logs") return cmdServeDaemon(sub, rest.slice(1));
1021
1113
  const argv = await yargs(rest).usage("Usage: ay serve [options]").option("port", {
1022
1114
  type: "number",
1023
- default: DEFAULT_PORT,
1024
- description: "Port to listen on"
1115
+ description: "Bypass Portless and listen on a fixed port"
1025
1116
  }).option("host", {
1026
1117
  type: "string",
1027
1118
  default: "127.0.0.1",
@@ -1049,6 +1140,10 @@ Options:
1049
1140
  type: "boolean",
1050
1141
  default: false,
1051
1142
  description: "Install as a background daemon (same as: ay serve install <flags>)"
1143
+ }).option("local", {
1144
+ type: "boolean",
1145
+ default: false,
1146
+ description: `Use Portless at ${portlessConsoleUrl()} (default for HTTP mode)`
1052
1147
  }).option("allow-spawn", {
1053
1148
  type: "boolean",
1054
1149
  default: false,
@@ -1059,13 +1154,22 @@ Options:
1059
1154
  description: "If another ay serve already hosts this home's WebRTC room, stop it and take the room"
1060
1155
  }).help(false).version(false).exitProcess(false).parseAsync();
1061
1156
  if (argv.daemon) return cmdServeDaemon("install", rest.filter((a) => a !== "--daemon" && a !== "-d"));
1157
+ const wantWebrtc = argv.webrtc !== void 0 || argv.share !== void 0;
1158
+ const wantHttp = argv.http === true || argv.share !== void 0 || argv.webrtc === void 0;
1159
+ const fixedPort = typeof argv.port === "number";
1160
+ const usePortless = wantHttp && !fixedPort;
1161
+ if (argv.local === true && fixedPort) {
1162
+ process.stderr.write("ay serve: --local and --port cannot be used together\n");
1163
+ return 1;
1164
+ }
1165
+ if (usePortless && process.env[PORTLESS_CHILD_ENV] !== "1" && process.env.PORTLESS !== "0") return runWithPortless(rest);
1062
1166
  const stray = argv._.map(String);
1063
1167
  if (stray.length) {
1064
1168
  const hint = stray.includes("share") ? " (did you mean --share?)" : "";
1065
1169
  process.stderr.write(`ay serve: ignoring unknown argument${stray.length > 1 ? "s" : ""}: ${stray.join(" ")}${hint}\n`);
1066
1170
  }
1067
1171
  delete process.env.AGENT_YES_PID;
1068
- const port = argv.port ?? DEFAULT_PORT;
1172
+ const port = argv.port ?? (Number(process.env.PORT) || DEFAULT_PORT);
1069
1173
  const host = argv.host ?? "127.0.0.1";
1070
1174
  const tokenFlag = typeof argv.token === "string" ? argv.token : void 0;
1071
1175
  const certPath = typeof argv["tls-cert"] === "string" ? argv["tls-cert"] : void 0;
@@ -1076,8 +1180,6 @@ Options:
1076
1180
  }
1077
1181
  const useHttps = !!(certPath && keyPath);
1078
1182
  const scheme = useHttps ? "https" : "http";
1079
- const wantWebrtc = argv.webrtc !== void 0 || argv.share !== void 0;
1080
- const wantHttp = argv.http === true || argv.share !== void 0 || argv.webrtc === void 0;
1081
1183
  let releaseHostLock = null;
1082
1184
  if (wantWebrtc && process.env.AGENT_YES_NO_SERVE_LOCK !== "1") {
1083
1185
  const lock = await acquireWebrtcHostLock({ takeover: argv.takeover === true });
@@ -1177,6 +1279,25 @@ Options:
1177
1279
  return [];
1178
1280
  }
1179
1281
  };
1282
+ const statusTextCache = /* @__PURE__ */ new Map();
1283
+ const logStatusText = async (logFile) => {
1284
+ if (!logFile) return null;
1285
+ try {
1286
+ const { size, mtimeMs } = await stat(logFile);
1287
+ const hit = statusTextCache.get(logFile);
1288
+ if (hit && hit.size === size && hit.mtimeMs === mtimeMs) return hit.statusText;
1289
+ const lines = await renderLogTailLines(logFile, 40);
1290
+ const statusText = lines ? parseStatusText(lines) : null;
1291
+ statusTextCache.set(logFile, {
1292
+ size,
1293
+ mtimeMs,
1294
+ statusText
1295
+ });
1296
+ return statusText;
1297
+ } catch {
1298
+ return null;
1299
+ }
1300
+ };
1180
1301
  const niCache = /* @__PURE__ */ new Map();
1181
1302
  const logNeedsInput = async (logFile, cli) => {
1182
1303
  if (!logFile) return null;
@@ -1338,6 +1459,7 @@ Options:
1338
1459
  status: status === "exited" ? status : r.unresponsive ? "stuck" : question ? "needs_input" : status,
1339
1460
  question,
1340
1461
  title: await logTitle(r.log_file),
1462
+ status_text: status === "exited" ? null : await logStatusText(r.log_file),
1341
1463
  git: status === "exited" ? null : await gitStatus(r.cwd),
1342
1464
  tasks: status === "exited" ? null : await logTasks(r.log_file),
1343
1465
  badges: status === "exited" ? [] : await logBadges(r.log_file).then(async (b) => await isUserTyping(r.pid) ? [...b, TYPING_BADGE.id] : b)
@@ -1657,7 +1779,7 @@ Options:
1657
1779
  }
1658
1780
  });
1659
1781
  if (req.method === "GET" && p === "/api/ws") {
1660
- const ws = await import("./ws-CSkP2mkD.js");
1782
+ const ws = await import("./ws-BmHpWaG_.js");
1661
1783
  try {
1662
1784
  await ws.loadProvision();
1663
1785
  } catch (e) {
@@ -1677,7 +1799,7 @@ Options:
1677
1799
  if (req.method === "GET" && p === "/api/ws/status") {
1678
1800
  const dirRaw = url.searchParams.get("path");
1679
1801
  if (!dirRaw) return new Response("missing ?path=<workspace dir>", { status: 400 });
1680
- const ws = await import("./ws-CSkP2mkD.js");
1802
+ const ws = await import("./ws-BmHpWaG_.js");
1681
1803
  let prov;
1682
1804
  try {
1683
1805
  prov = await ws.loadProvision();
@@ -2233,7 +2355,7 @@ Options:
2233
2355
  const perm = body.perm ?? "r";
2234
2356
  if (perm !== "r" && perm !== "rw") return new Response(`invalid perm ${perm} (want r or rw)`, { status: 400 });
2235
2357
  try {
2236
- const { createScopedShare } = await import("./agentShare-99IGGOkv.js");
2358
+ const { createScopedShare } = await import("./agentShare-k8224qiZ.js");
2237
2359
  const share = await createScopedShare({
2238
2360
  agent: body.agent,
2239
2361
  perm,
@@ -2248,12 +2370,12 @@ Options:
2248
2370
  }
2249
2371
  }
2250
2372
  if (req.method === "GET" && p === "/api/shares") {
2251
- const { listShares } = await import("./agentShare-99IGGOkv.js");
2373
+ const { listShares } = await import("./agentShare-k8224qiZ.js");
2252
2374
  return Response.json(listShares());
2253
2375
  }
2254
2376
  const revokeM = /^\/api\/share\/([^/]+)$/.exec(p);
2255
2377
  if (req.method === "DELETE" && revokeM) {
2256
- const { revokeShare } = await import("./agentShare-99IGGOkv.js");
2378
+ const { revokeShare } = await import("./agentShare-k8224qiZ.js");
2257
2379
  const ok = revokeShare(decodeURIComponent(revokeM[1]));
2258
2380
  return new Response(ok ? "revoked" : "no such share", { status: ok ? 200 : 404 });
2259
2381
  }
@@ -2369,17 +2491,18 @@ Options:
2369
2491
  throw e;
2370
2492
  }
2371
2493
  if (server) {
2494
+ const listenPort = server.port;
2372
2495
  const uiHost = host === "0.0.0.0" || host === "::" ? "127.0.0.1" : host;
2373
- process.stdout.write(`ay serve ${scheme}://${host}:${port}\n`);
2496
+ process.stdout.write(`ay serve ${scheme}://${host}:${listenPort}\n`);
2374
2497
  process.stdout.write(`token: ${token}\n\n`);
2375
2498
  process.stdout.write(`web console (token in the # is eaten on open):\n`);
2376
- process.stdout.write(` ${scheme}://${uiHost}:${port}/#k=${token}\n\n`);
2499
+ process.stdout.write(` ${usePortless ? portlessConsoleUrl(token) : `${scheme}://${uiHost}:${listenPort}/#k=${token}`}\n\n`);
2377
2500
  process.stdout.write(`connect from another machine:\n`);
2378
- process.stdout.write(` ay ls ${token}@<host>:${port}\n`);
2379
- process.stdout.write(` ay tail ${token}@<host>:${port}:<keyword>\n`);
2380
- process.stdout.write(` ay send ${token}@<host>:${port}:<keyword> "message"\n\n`);
2501
+ process.stdout.write(` ay ls ${token}@<host>:${listenPort}\n`);
2502
+ process.stdout.write(` ay tail ${token}@<host>:${listenPort}:<keyword>\n`);
2503
+ process.stdout.write(` ay send ${token}@<host>:${listenPort}:<keyword> "message"\n\n`);
2381
2504
  process.stdout.write(`save as alias:\n`);
2382
- process.stdout.write(` ay remote add <alias> ${scheme}://${token}@<host>:${port}\n\n`);
2505
+ process.stdout.write(` ay remote add <alias> ${scheme}://${token}@<host>:${listenPort}\n\n`);
2383
2506
  if (!useHttps) process.stdout.write("for HTTPS: ay serve --tls-cert cert.pem --tls-key key.pem\n openssl req -x509 -newkey rsa:2048 -keyout key.pem -out cert.pem -days 365 -nodes -subj '/CN=localhost'\n\n");
2384
2507
  }
2385
2508
  }
@@ -2388,7 +2511,7 @@ Options:
2388
2511
  const webrtcVal = argv.webrtc ?? argv.share;
2389
2512
  const explicitUrl = typeof webrtcVal === "string" && webrtcVal.startsWith("webrtc://") ? webrtcVal : void 0;
2390
2513
  try {
2391
- const { startShare, loadOrCreateShareRoom } = await import("./share-Ciw1mWVN.js");
2514
+ const { startShare, loadOrCreateShareRoom } = await import("./share-_QYjPN7q.js");
2392
2515
  const linkFile = path.join(process.env.AGENT_YES_HOME ?? path.join(homedir(), ".agent-yes"), ".share-link");
2393
2516
  const announce = async (room, link, rotated) => {
2394
2517
  const lead = rotated ? "the room was rejected by signaling (stale generation) — rotated to a fresh link" : "shared over WebRTC — open this link (the token is eaten from the URL on open)";
@@ -2438,7 +2561,7 @@ Options:
2438
2561
  const shutdown = (resolve) => {
2439
2562
  if (heartbeat) clearInterval(heartbeat);
2440
2563
  closeShare?.();
2441
- import("./agentShare-99IGGOkv.js").then((m) => m.revokeAllShares()).catch(() => {});
2564
+ import("./agentShare-k8224qiZ.js").then((m) => m.revokeAllShares()).catch(() => {});
2442
2565
  server?.stop();
2443
2566
  Promise.resolve(releaseHostLock?.()).catch(() => {}).then(resolve);
2444
2567
  };
@@ -2451,4 +2574,4 @@ Options:
2451
2574
 
2452
2575
  //#endregion
2453
2576
  export { cmdServe };
2454
- //# sourceMappingURL=serve-IvOlaL-7.js.map
2577
+ //# sourceMappingURL=serve-crLypY_c.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-IvOlaL-7.js");
35
+ const { cmdServe } = await import("./serve-crLypY_c.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-BaKdS-3i.js.map
45
+ //# sourceMappingURL=setup-BPNkeSmY.js.map
@@ -1,4 +1,4 @@
1
1
  import "./e2e-jb0Hp43q.js";
2
- import { n as shareLinkFromRoomUrl, r as startShare, t as loadOrCreateShareRoom } from "./share-BfIU8t_h.js";
2
+ import { n as shareLinkFromRoomUrl, r as startShare, t as loadOrCreateShareRoom } from "./share-vchIyVd8.js";
3
3
 
4
4
  export { loadOrCreateShareRoom, shareLinkFromRoomUrl, startShare };