agent-yes 1.205.0 → 1.207.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 (31) hide show
  1. package/README.md +2 -0
  2. package/dist/{SUPPORTED_CLIS-C8-qh98a.js → SUPPORTED_CLIS-B1CDJwYn.js} +2 -2
  3. package/dist/SUPPORTED_CLIS-vH8hvcZr.js +9 -0
  4. package/dist/{agentShare-99IGGOkv.js → agentShare-DdEbHtAn.js} +3 -3
  5. package/dist/cli.js +4 -4
  6. package/dist/index.js +2 -2
  7. package/dist/{notifyDaemon-DK1HOMjj.js → notifyDaemon-DivHVzZx.js} +2 -2
  8. package/dist/{rustBinary-Tgn948GR.js → rustBinary-CuBIr-zX.js} +2 -2
  9. package/dist/{schedule-CBoM67Vy.js → schedule-Bg_CDt2j.js} +4 -4
  10. package/dist/{serve-IvOlaL-7.js → serve-B-ZCy67S.js} +258 -41
  11. package/dist/{setup-BaKdS-3i.js → setup-D6UBzk4-.js} +2 -2
  12. package/dist/{share-Ciw1mWVN.js → share-_QYjPN7q.js} +1 -1
  13. package/dist/{share-BfIU8t_h.js → share-vchIyVd8.js} +98 -5
  14. package/dist/{subcommands-Bs7wJRBB.js → subcommands-6AQ8egRn.js} +7 -7
  15. package/dist/{subcommands-DyDHZ5YI.js → subcommands-CeRH9-_h.js} +1 -1
  16. package/dist/{ts-Dm6jjLwC.js → ts-DZWZvbLM.js} +2 -2
  17. package/dist/{versionChecker-BomfUpSo.js → versionChecker-C2CV9VOX.js} +2 -2
  18. package/dist/{ws-CSkP2mkD.js → ws-CGNmxCPD.js} +2 -2
  19. package/lab/ui/console-logic.js +23 -1
  20. package/lab/ui/index.html +188 -29
  21. package/package.json +1 -1
  22. package/ts/serve.spec.ts +13 -1
  23. package/ts/serve.ts +263 -34
  24. package/ts/serveLock.spec.ts +15 -14
  25. package/ts/share.ts +80 -1
  26. package/ts/sizeNego.spec.ts +61 -0
  27. package/ts/sizeNego.ts +59 -0
  28. package/ts/statusText.spec.ts +17 -0
  29. package/ts/statusText.ts +19 -0
  30. package/ts/ws.spec.ts +8 -10
  31. package/dist/SUPPORTED_CLIS-D3XTFfS7.js +0 -9
@@ -16,7 +16,29 @@ const MAX_PEER_JOIN_QUEUE = 50;
16
16
  const IDLE_RESTART_UPTIME_MS = 25 * 6e4;
17
17
  const HARD_RESTART_UPTIME_MS = 45 * 6e4;
18
18
  const IDLE_RESTART_CHECK_MS = 6e4;
19
+ const PERF_SLOW_MS = Number(process.env.AGENT_YES_WEBRTC_PERF_SLOW_MS) || 750;
20
+ const PERF_BUFFERED_BYTES = Number(process.env.AGENT_YES_WEBRTC_PERF_BUFFERED_BYTES) || 1e6;
21
+ const PERF_VERBOSE = process.env.AGENT_YES_WEBRTC_PERF === "1";
19
22
  const STUN = [{ urls: "stun:stun.l.google.com:19302" }];
23
+ function perfLog(event, data, force = false) {
24
+ if (!force && !PERF_VERBOSE) return;
25
+ process.stderr.write(`[share:perf] ${JSON.stringify({
26
+ t: Date.now(),
27
+ event,
28
+ ...data
29
+ })}\n`);
30
+ }
31
+ function maybeSlow(event, startedAt, data = {}) {
32
+ const ms = Math.round(performance.now() - startedAt);
33
+ perfLog(event, {
34
+ ms,
35
+ ...data
36
+ }, ms >= PERF_SLOW_MS);
37
+ }
38
+ function dcBufferedAmount(dc) {
39
+ const n = Number(dc?.bufferedAmount ?? 0);
40
+ return Number.isFinite(n) ? n : 0;
41
+ }
20
42
  let iceCache = null;
21
43
  async function getIceServers() {
22
44
  const keyId = process.env.CF_TURN_KEY_ID;
@@ -222,6 +244,7 @@ async function startShare(opts) {
222
244
  if (closed) return;
223
245
  const ws = new WebSocket(`${wsScheme}://${host}/${room}`, [SUB]);
224
246
  currentWs = ws;
247
+ const signalStartedAt = performance.now();
225
248
  let ready = false;
226
249
  let lastRecv = Date.now();
227
250
  let hb;
@@ -237,6 +260,10 @@ async function startShare(opts) {
237
260
  }
238
261
  };
239
262
  ws.onopen = () => {
263
+ maybeSlow("signal.open", signalStartedAt, {
264
+ room,
265
+ host
266
+ });
240
267
  ws.send(JSON.stringify({
241
268
  type: "hello",
242
269
  role: "host",
@@ -271,6 +298,12 @@ async function startShare(opts) {
271
298
  const m = JSON.parse(ev.data);
272
299
  if (m.type === "pong") return;
273
300
  if (m.type === "peer-join") {
301
+ perfLog("peer.join", {
302
+ room,
303
+ peer: String(m.peer),
304
+ queue: peerJoinQueue.length,
305
+ peers: peers.size
306
+ });
274
307
  const pid = String(m.peer);
275
308
  if (!peers.has(pid) && !peerJoinQueue.includes(pid) && peerJoinQueue.length < MAX_PEER_JOIN_QUEUE) {
276
309
  peerJoinQueue.push(pid);
@@ -317,6 +350,7 @@ async function startShare(opts) {
317
350
  return ws;
318
351
  };
319
352
  async function startPeer(ws, peerId) {
353
+ const startedAt = performance.now();
320
354
  const iceServers = await getIceServers();
321
355
  const pc = new RTCPeerConnection({ iceServers });
322
356
  let resolveKeys;
@@ -354,6 +388,11 @@ async function startShare(opts) {
354
388
  dc.binaryType = "arraybuffer";
355
389
  dc.onopen = async () => {
356
390
  try {
391
+ maybeSlow("peer.dc_open", startedAt, {
392
+ room,
393
+ peer: peerId,
394
+ buffered: dcBufferedAmount(dc)
395
+ });
357
396
  await peer.keysReady;
358
397
  enqueueSeal(peerId, dc, peer, FLAG_CONFIRM, {
359
398
  t: "confirm",
@@ -387,6 +426,11 @@ async function startShare(opts) {
387
426
  sdp: pc.localDescription.sdp,
388
427
  iceServers
389
428
  }));
429
+ maybeSlow("peer.offer", startedAt, {
430
+ room,
431
+ peer: peerId,
432
+ iceServers: iceServers.length
433
+ });
390
434
  }
391
435
  function closePeer(peerId) {
392
436
  const p = peers.get(peerId);
@@ -399,8 +443,10 @@ async function startShare(opts) {
399
443
  peers.delete(peerId);
400
444
  }
401
445
  function enqueueSeal(peerId, dc, peer, flags, obj) {
446
+ const queuedAt = performance.now();
402
447
  peer.sendChain = peer.sendChain.then(async () => {
403
448
  if (dc.readyState !== "open" || !peer.keyH2C || !peer.th) return;
449
+ const queuedMs = Math.round(performance.now() - queuedAt);
404
450
  let frame;
405
451
  try {
406
452
  frame = await seal(peer.keyH2C, peer.send, flags, peer.th, packEnvelope(obj));
@@ -410,6 +456,15 @@ async function startShare(opts) {
410
456
  }
411
457
  try {
412
458
  dc.send(frame);
459
+ const buffered = dcBufferedAmount(dc);
460
+ perfLog("send", {
461
+ room,
462
+ peer: peerId,
463
+ kind: obj?.t,
464
+ queuedMs,
465
+ buffered,
466
+ bytes: frame.byteLength
467
+ }, queuedMs >= PERF_SLOW_MS || buffered >= PERF_BUFFERED_BYTES);
413
468
  } catch {}
414
469
  });
415
470
  return peer.sendChain;
@@ -452,6 +507,14 @@ async function startShare(opts) {
452
507
  }
453
508
  if (req.t !== "req") return;
454
509
  const { id, method, path: p, body } = req;
510
+ const startedAt = performance.now();
511
+ perfLog("req.start", {
512
+ room,
513
+ peer: peerId,
514
+ id,
515
+ method,
516
+ path: p
517
+ });
455
518
  const ac = new AbortController();
456
519
  peer.aborts.set(id, ac);
457
520
  try {
@@ -464,6 +527,14 @@ async function startShare(opts) {
464
527
  body: body ?? void 0,
465
528
  signal: ac.signal
466
529
  }));
530
+ maybeSlow("req.head", startedAt, {
531
+ room,
532
+ peer: peerId,
533
+ id,
534
+ method,
535
+ path: p,
536
+ status: res.status
537
+ });
467
538
  enqueueSeal(peerId, dc, peer, 0, {
468
539
  t: "res",
469
540
  id,
@@ -473,9 +544,11 @@ async function startShare(opts) {
473
544
  const reader = res.body.getReader();
474
545
  const dec = new TextDecoder();
475
546
  let seq = 0;
547
+ let bytes = 0;
476
548
  for (;;) {
477
549
  const { done, value } = await reader.read();
478
550
  if (done) break;
551
+ bytes += value.byteLength;
479
552
  const text = dec.decode(value, { stream: true });
480
553
  for (let i = 0; i < text.length; i += MAX_CHUNK) enqueueSeal(peerId, dc, peer, 0, {
481
554
  t: "data",
@@ -489,12 +562,32 @@ async function startShare(opts) {
489
562
  id,
490
563
  seq
491
564
  });
492
- } catch (e) {
493
- if (e.name !== "AbortError") enqueueSeal(peerId, dc, peer, 0, {
494
- t: "end",
565
+ maybeSlow("req.end", startedAt, {
566
+ room,
567
+ peer: peerId,
495
568
  id,
496
- error: String(e.message ?? e)
569
+ method,
570
+ path: p,
571
+ status: res.status,
572
+ chunks: seq,
573
+ bytes
497
574
  });
575
+ } catch (e) {
576
+ if (e.name !== "AbortError") {
577
+ maybeSlow("req.error", startedAt, {
578
+ room,
579
+ peer: peerId,
580
+ id,
581
+ method,
582
+ path: p,
583
+ error: String(e.message ?? e)
584
+ });
585
+ enqueueSeal(peerId, dc, peer, 0, {
586
+ t: "end",
587
+ id,
588
+ error: String(e.message ?? e)
589
+ });
590
+ }
498
591
  } finally {
499
592
  peer.aborts.delete(id);
500
593
  }
@@ -534,4 +627,4 @@ async function startShare(opts) {
534
627
 
535
628
  //#endregion
536
629
  export { shareLinkFromRoomUrl as n, startShare as r, loadOrCreateShareRoom as t };
537
- //# sourceMappingURL=share-BfIU8t_h.js.map
630
+ //# sourceMappingURL=share-vchIyVd8.js.map
@@ -1237,19 +1237,19 @@ async function runSubcommand(argv) {
1237
1237
  case "restart": return await cmdRestart(rest);
1238
1238
  case "note": return await cmdNote(rest);
1239
1239
  case "serve": {
1240
- const { cmdServe } = await import("./serve-IvOlaL-7.js");
1240
+ const { cmdServe } = await import("./serve-B-ZCy67S.js");
1241
1241
  return cmdServe(rest);
1242
1242
  }
1243
1243
  case "setup": {
1244
- const { cmdSetup } = await import("./setup-BaKdS-3i.js");
1244
+ const { cmdSetup } = await import("./setup-D6UBzk4-.js");
1245
1245
  return cmdSetup(rest);
1246
1246
  }
1247
1247
  case "ws": {
1248
- const { cmdWs } = await import("./ws-CSkP2mkD.js");
1248
+ const { cmdWs } = await import("./ws-CGNmxCPD.js");
1249
1249
  return cmdWs(rest);
1250
1250
  }
1251
1251
  case "schedule": {
1252
- const { cmdSchedule } = await import("./schedule-CBoM67Vy.js");
1252
+ const { cmdSchedule } = await import("./schedule-Bg_CDt2j.js");
1253
1253
  return cmdSchedule(rest);
1254
1254
  }
1255
1255
  case "remote": {
@@ -4269,7 +4269,7 @@ async function cmdNotify(rest) {
4269
4269
  }
4270
4270
  const ensure = async () => {
4271
4271
  if (!argv["ensure-daemon"]) return;
4272
- const { ensureDaemon } = await import("./notifyDaemon-DK1HOMjj.js");
4272
+ const { ensureDaemon } = await import("./notifyDaemon-DivHVzZx.js");
4273
4273
  await ensureDaemon().catch(() => null);
4274
4274
  };
4275
4275
  await heartbeatWatcher(parent, selfStartedAt);
@@ -4343,7 +4343,7 @@ async function cmdNotifyCursor(args) {
4343
4343
  }
4344
4344
  async function cmdNotifyd(rest) {
4345
4345
  const sub = rest[0] ?? "status";
4346
- const daemon = await import("./notifyDaemon-DK1HOMjj.js");
4346
+ const daemon = await import("./notifyDaemon-DivHVzZx.js");
4347
4347
  switch (sub) {
4348
4348
  case "run": return daemon.runDaemon();
4349
4349
  case "once": return daemon.runDaemon({ once: true });
@@ -4370,4 +4370,4 @@ async function cmdNotifyd(rest) {
4370
4370
 
4371
4371
  //#endregion
4372
4372
  export { daemonLockOwnerPath as $, renderRawLog as A, submitAndConfirm as B, matchKeyword as C, recentMessageEdges as D, readPtysize as E, restartHintLines as F, gcInboxes as G, writeKeysPaced as H, runSubcommand as I, listInboxParents as J, hostId as K, snapshotStatus as L, resolveOne as M, resolveReadWindow as N, recentReadEdges as O, resolveResumeArgs as P, daemonLockDir as Q, stdinActivityPath as R, listRecords as S, readNotes as T, writeToIpc as U, waitForLogQuiet as V, appendEvent as W, readInbox as X, liveWatchers as Y, shouldStealLock as Z, isPidAlive as _, cmdHelp as a, isUserTyping as b, deriveLiveState as c, extractMenu as d, notifyDir as et, extractNeedsInput as f, isExitRequest as g, isAgentStuck as h, backoffWhileTyping as i, renderRawLogLines as j, renderLogTailLines as k, deriveLiveStatus as l, finalizedLines as m, READ_PAGE_DEFAULT as n, controlCodeFromName as o, extractTaskCounts as p, isTransientLockMkdirError as q, TYPING_WINDOW_MS as r, cursorAbs as s, GRACEFUL_EXIT_COMMANDS as t, TYPING_BADGE as tt, extractBadges as u, isSlashCommand as v, menuSelectKeys as w, lastStdinAt as x, isSubcommand as y, stopTipForCli as z };
4373
- //# sourceMappingURL=subcommands-Bs7wJRBB.js.map
4373
+ //# sourceMappingURL=subcommands-6AQ8egRn.js.map
@@ -2,7 +2,7 @@ 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 { A as renderRawLog, B as submitAndConfirm, C as matchKeyword, D as recentMessageEdges, E as readPtysize, F as restartHintLines, H as writeKeysPaced, I as runSubcommand, L as snapshotStatus, M as resolveOne, N as resolveReadWindow, O as recentReadEdges, P as resolveResumeArgs, R as stdinActivityPath, S as listRecords, T as readNotes, U as writeToIpc, V as waitForLogQuiet, _ 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 renderRawLogLines, k as renderLogTailLines, 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 stopTipForCli } from "./subcommands-Bs7wJRBB.js";
5
+ import { A as renderRawLog, B as submitAndConfirm, C as matchKeyword, D as recentMessageEdges, E as readPtysize, F as restartHintLines, H as writeKeysPaced, I as runSubcommand, L as snapshotStatus, M as resolveOne, N as resolveReadWindow, O as recentReadEdges, P as resolveResumeArgs, R as stdinActivityPath, S as listRecords, T as readNotes, U as writeToIpc, V as waitForLogQuiet, _ 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 renderRawLogLines, k as renderLogTailLines, 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 stopTipForCli } from "./subcommands-6AQ8egRn.js";
6
6
  import "./e2e-jb0Hp43q.js";
7
7
  import "./webrtcLink-B7REGtK2.js";
8
8
  import "./remotes-Cim0dBU7.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-BomfUpSo.js";
2
+ import { r as getInstalledPackage } from "./versionChecker-C2CV9VOX.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";
@@ -1901,4 +1901,4 @@ function sleep(ms) {
1901
1901
 
1902
1902
  //#endregion
1903
1903
  export { removeControlCharacters as a, AgentContext as i, agentYes as n, config as r, CLIS_CONFIG as t };
1904
- //# sourceMappingURL=ts-Dm6jjLwC.js.map
1904
+ //# sourceMappingURL=ts-DZWZvbLM.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.205.0";
10
+ var version = "1.207.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-BomfUpSo.js.map
218
+ //# sourceMappingURL=versionChecker-C2CV9VOX.js.map
@@ -2,7 +2,7 @@ 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 { S as listRecords } from "./subcommands-Bs7wJRBB.js";
5
+ import { S as listRecords } from "./subcommands-6AQ8egRn.js";
6
6
  import "./e2e-jb0Hp43q.js";
7
7
  import "./webrtcLink-B7REGtK2.js";
8
8
  import "./remotes-Cim0dBU7.js";
@@ -418,4 +418,4 @@ async function cmdWs(args) {
418
418
 
419
419
  //#endregion
420
420
  export { WS_JSON_SCHEMA, cmdWs, collectWorkspaces, isPathInside, loadProvision, workspaceStatus };
421
- //# sourceMappingURL=ws-CSkP2mkD.js.map
421
+ //# sourceMappingURL=ws-CGNmxCPD.js.map
@@ -7,7 +7,7 @@
7
7
  // `now` so age() is deterministic under test.
8
8
 
9
9
  // An agent entry as surfaced by /api/ls (the fields this module reads):
10
- // { cli, cwd, title, prompt, status, started_at, pid, _host }
10
+ // { cli, cwd, title, status_text, prompt, status, started_at, pid, _host }
11
11
 
12
12
  // claude is the default CLI — show the cli name only when it differs, so the
13
13
  // common case stays uncluttered and the identity (repo/branch) leads instead.
@@ -261,6 +261,8 @@ export function matches(e, toks) {
261
261
  const hay =
262
262
  (e.title || "") +
263
263
  " " +
264
+ (e.status_text || "") +
265
+ " " +
264
266
  (e.prompt || "") +
265
267
  " " +
266
268
  e.cli +
@@ -699,6 +701,26 @@ export function fitTransform(gridW, gridH, paneW, paneH) {
699
701
  return s > 0.985 && s < 1.04 ? "none" : "scale(" + s.toFixed(4) + ")";
700
702
  }
701
703
 
704
+ // Centered variant: same scale selection as fitTransform, plus a translate that
705
+ // centers the scaled grid in the pane (fit-width → vertically centered,
706
+ // fit-height → horizontally centered). transform-origin stays top-left, so the
707
+ // translate is in pane px and consumers mapping grid→screen coords (peer
708
+ // overlays) can read the offset back off this same object. "none" (the crisp
709
+ // driver path) never gets a translate — grid ≈ pane, nothing to center.
710
+ export function fitTransformCentered(gridW, gridH, paneW, paneH) {
711
+ const t = fitTransform(gridW, gridH, paneW, paneH);
712
+ if (t === "none") return { transform: "none", scale: 1, dx: 0, dy: 0 };
713
+ const s = Math.min(paneW / gridW, paneH / gridH);
714
+ const dx = Math.max(0, (paneW - gridW * s) / 2);
715
+ const dy = Math.max(0, (paneH - gridH * s) / 2);
716
+ return {
717
+ transform: `translate(${dx.toFixed(1)}px, ${dy.toFixed(1)}px) ` + t,
718
+ scale: s,
719
+ dx,
720
+ dy,
721
+ };
722
+ }
723
+
702
724
  // Browser-tab title: "<glyph> <selected agent title> - agent-yes", or the bare
703
725
  // console title when nothing is selected (blank/whitespace name). The leading
704
726
  // glyph mirrors the agent's status dot — ⌨ needs_input ("your turn"), ⚠ stuck,