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.
- package/README.md +2 -0
- package/dist/{SUPPORTED_CLIS-C8-qh98a.js → SUPPORTED_CLIS-B1CDJwYn.js} +2 -2
- package/dist/SUPPORTED_CLIS-vH8hvcZr.js +9 -0
- package/dist/{agentShare-99IGGOkv.js → agentShare-DdEbHtAn.js} +3 -3
- package/dist/cli.js +4 -4
- package/dist/index.js +2 -2
- package/dist/{notifyDaemon-DK1HOMjj.js → notifyDaemon-DivHVzZx.js} +2 -2
- package/dist/{rustBinary-Tgn948GR.js → rustBinary-CuBIr-zX.js} +2 -2
- package/dist/{schedule-CBoM67Vy.js → schedule-Bg_CDt2j.js} +4 -4
- package/dist/{serve-IvOlaL-7.js → serve-B-ZCy67S.js} +258 -41
- package/dist/{setup-BaKdS-3i.js → setup-D6UBzk4-.js} +2 -2
- package/dist/{share-Ciw1mWVN.js → share-_QYjPN7q.js} +1 -1
- package/dist/{share-BfIU8t_h.js → share-vchIyVd8.js} +98 -5
- package/dist/{subcommands-Bs7wJRBB.js → subcommands-6AQ8egRn.js} +7 -7
- package/dist/{subcommands-DyDHZ5YI.js → subcommands-CeRH9-_h.js} +1 -1
- package/dist/{ts-Dm6jjLwC.js → ts-DZWZvbLM.js} +2 -2
- package/dist/{versionChecker-BomfUpSo.js → versionChecker-C2CV9VOX.js} +2 -2
- package/dist/{ws-CSkP2mkD.js → ws-CGNmxCPD.js} +2 -2
- package/lab/ui/console-logic.js +23 -1
- package/lab/ui/index.html +188 -29
- package/package.json +1 -1
- package/ts/serve.spec.ts +13 -1
- package/ts/serve.ts +263 -34
- package/ts/serveLock.spec.ts +15 -14
- package/ts/share.ts +80 -1
- package/ts/sizeNego.spec.ts +61 -0
- package/ts/sizeNego.ts +59 -0
- package/ts/statusText.spec.ts +17 -0
- package/ts/statusText.ts +19 -0
- package/ts/ws.spec.ts +8 -10
- package/dist/SUPPORTED_CLIS-D3XTFfS7.js +0 -9
package/ts/share.ts
CHANGED
|
@@ -66,10 +66,28 @@ const MAX_PEER_JOIN_QUEUE = 50;
|
|
|
66
66
|
const IDLE_RESTART_UPTIME_MS = 25 * 60_000;
|
|
67
67
|
const HARD_RESTART_UPTIME_MS = 45 * 60_000;
|
|
68
68
|
const IDLE_RESTART_CHECK_MS = 60_000;
|
|
69
|
+
const PERF_SLOW_MS = Number(process.env.AGENT_YES_WEBRTC_PERF_SLOW_MS) || 750;
|
|
70
|
+
const PERF_BUFFERED_BYTES = Number(process.env.AGENT_YES_WEBRTC_PERF_BUFFERED_BYTES) || 1_000_000;
|
|
71
|
+
const PERF_VERBOSE = process.env.AGENT_YES_WEBRTC_PERF === "1";
|
|
69
72
|
|
|
70
73
|
type IceServer = { urls: string | string[]; username?: string; credential?: string };
|
|
71
74
|
const STUN: IceServer[] = [{ urls: "stun:stun.l.google.com:19302" }];
|
|
72
75
|
|
|
76
|
+
function perfLog(event: string, data: Record<string, unknown>, force = false) {
|
|
77
|
+
if (!force && !PERF_VERBOSE) return;
|
|
78
|
+
process.stderr.write(`[share:perf] ${JSON.stringify({ t: Date.now(), event, ...data })}\n`);
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
function maybeSlow(event: string, startedAt: number, data: Record<string, unknown> = {}) {
|
|
82
|
+
const ms = Math.round(performance.now() - startedAt);
|
|
83
|
+
perfLog(event, { ms, ...data }, ms >= PERF_SLOW_MS);
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
function dcBufferedAmount(dc: any): number {
|
|
87
|
+
const n = Number(dc?.bufferedAmount ?? 0);
|
|
88
|
+
return Number.isFinite(n) ? n : 0;
|
|
89
|
+
}
|
|
90
|
+
|
|
73
91
|
// Short-lived Cloudflare TURN credentials, minted from a long-term TURN key, so
|
|
74
92
|
// browsers can RELAY when a direct P2P path is impossible (symmetric NAT /
|
|
75
93
|
// CGNAT — the main cause of "rooms offline"). Set CF_TURN_KEY_ID +
|
|
@@ -428,6 +446,7 @@ export async function startShare(
|
|
|
428
446
|
if (closed) return; // a reconnect timer queued before close() must not revive it
|
|
429
447
|
const ws = new WebSocket(`${wsScheme}://${host}/${room}`, [SUB]);
|
|
430
448
|
currentWs = ws;
|
|
449
|
+
const signalStartedAt = performance.now();
|
|
431
450
|
let ready = false;
|
|
432
451
|
let lastRecv = Date.now();
|
|
433
452
|
let hb: ReturnType<typeof setInterval> | undefined;
|
|
@@ -443,6 +462,7 @@ export async function startShare(
|
|
|
443
462
|
}
|
|
444
463
|
};
|
|
445
464
|
ws.onopen = () => {
|
|
465
|
+
maybeSlow("signal.open", signalStartedAt, { room, host });
|
|
446
466
|
ws.send(JSON.stringify({ type: "hello", role: "host", v: 2, token: authToken }));
|
|
447
467
|
ready = true;
|
|
448
468
|
lastRecv = Date.now();
|
|
@@ -480,6 +500,12 @@ export async function startShare(
|
|
|
480
500
|
const m = JSON.parse(ev.data as string);
|
|
481
501
|
if (m.type === "pong") return; // heartbeat ack — liveness already recorded
|
|
482
502
|
if (m.type === "peer-join") {
|
|
503
|
+
perfLog("peer.join", {
|
|
504
|
+
room,
|
|
505
|
+
peer: String(m.peer),
|
|
506
|
+
queue: peerJoinQueue.length,
|
|
507
|
+
peers: peers.size,
|
|
508
|
+
});
|
|
483
509
|
// Serialized in drainPeerJoins() to avoid a storm. Skip dupes (already
|
|
484
510
|
// queued or already an active peer) and cap the queue so a pathological
|
|
485
511
|
// burst can't grow it unboundedly — dropped joins retry via the browser.
|
|
@@ -554,6 +580,7 @@ export async function startShare(
|
|
|
554
580
|
};
|
|
555
581
|
|
|
556
582
|
async function startPeer(ws: WebSocket, peerId: string) {
|
|
583
|
+
const startedAt = performance.now();
|
|
557
584
|
const iceServers = await getIceServers();
|
|
558
585
|
const pc = new RTCPeerConnection({ iceServers });
|
|
559
586
|
let resolveKeys!: () => void;
|
|
@@ -584,6 +611,11 @@ export async function startShare(
|
|
|
584
611
|
dc.binaryType = "arraybuffer";
|
|
585
612
|
dc.onopen = async () => {
|
|
586
613
|
try {
|
|
614
|
+
maybeSlow("peer.dc_open", startedAt, {
|
|
615
|
+
room,
|
|
616
|
+
peer: peerId,
|
|
617
|
+
buffered: dcBufferedAmount(dc),
|
|
618
|
+
});
|
|
587
619
|
await peer.keysReady; // keys derived in the answer handler
|
|
588
620
|
// Open the mandatory bidirectional key-confirmation handshake. Nothing
|
|
589
621
|
// the peer sends is acted on until BOTH directions confirm (see onFrame).
|
|
@@ -624,6 +656,7 @@ export async function startShare(
|
|
|
624
656
|
ws.send(
|
|
625
657
|
JSON.stringify({ type: "offer", to: peerId, sdp: pc.localDescription.sdp, iceServers }),
|
|
626
658
|
);
|
|
659
|
+
maybeSlow("peer.offer", startedAt, { room, peer: peerId, iceServers: iceServers.length });
|
|
627
660
|
}
|
|
628
661
|
|
|
629
662
|
function closePeer(peerId: string) {
|
|
@@ -642,8 +675,10 @@ export async function startShare(
|
|
|
642
675
|
// Seal an envelope and send it, serialized per peer so the wire order matches
|
|
643
676
|
// the nonce-counter order (so the receiver's monotonic check never trips).
|
|
644
677
|
function enqueueSeal(peerId: string, dc: any, peer: Peer, flags: number, obj: object) {
|
|
678
|
+
const queuedAt = performance.now();
|
|
645
679
|
peer.sendChain = peer.sendChain.then(async () => {
|
|
646
680
|
if (dc.readyState !== "open" || !peer.keyH2C || !peer.th) return;
|
|
681
|
+
const queuedMs = Math.round(performance.now() - queuedAt);
|
|
647
682
|
let frame: ArrayBuffer;
|
|
648
683
|
try {
|
|
649
684
|
frame = await e2eSeal(peer.keyH2C, peer.send, flags, peer.th, packEnvelope(obj));
|
|
@@ -653,6 +688,19 @@ export async function startShare(
|
|
|
653
688
|
}
|
|
654
689
|
try {
|
|
655
690
|
dc.send(frame);
|
|
691
|
+
const buffered = dcBufferedAmount(dc);
|
|
692
|
+
perfLog(
|
|
693
|
+
"send",
|
|
694
|
+
{
|
|
695
|
+
room,
|
|
696
|
+
peer: peerId,
|
|
697
|
+
kind: (obj as any)?.t,
|
|
698
|
+
queuedMs,
|
|
699
|
+
buffered,
|
|
700
|
+
bytes: frame.byteLength,
|
|
701
|
+
},
|
|
702
|
+
queuedMs >= PERF_SLOW_MS || buffered >= PERF_BUFFERED_BYTES,
|
|
703
|
+
);
|
|
656
704
|
} catch {
|
|
657
705
|
/* peer vanished mid-send; dropping the frame is correct */
|
|
658
706
|
}
|
|
@@ -703,6 +751,8 @@ export async function startShare(
|
|
|
703
751
|
}
|
|
704
752
|
if (req.t !== "req") return;
|
|
705
753
|
const { id, method, path: p, body } = req;
|
|
754
|
+
const startedAt = performance.now();
|
|
755
|
+
perfLog("req.start", { room, peer: peerId, id, method, path: p });
|
|
706
756
|
const ac = new AbortController();
|
|
707
757
|
peer.aborts.set(id, ac);
|
|
708
758
|
try {
|
|
@@ -718,6 +768,14 @@ export async function startShare(
|
|
|
718
768
|
signal: ac.signal,
|
|
719
769
|
}),
|
|
720
770
|
);
|
|
771
|
+
maybeSlow("req.head", startedAt, {
|
|
772
|
+
room,
|
|
773
|
+
peer: peerId,
|
|
774
|
+
id,
|
|
775
|
+
method,
|
|
776
|
+
path: p,
|
|
777
|
+
status: res.status,
|
|
778
|
+
});
|
|
721
779
|
enqueueSeal(peerId, dc, peer, 0, {
|
|
722
780
|
t: "res",
|
|
723
781
|
id,
|
|
@@ -727,9 +785,11 @@ export async function startShare(
|
|
|
727
785
|
const reader = res.body!.getReader();
|
|
728
786
|
const dec = new TextDecoder();
|
|
729
787
|
let seq = 0;
|
|
788
|
+
let bytes = 0;
|
|
730
789
|
for (;;) {
|
|
731
790
|
const { done, value } = await reader.read();
|
|
732
791
|
if (done) break;
|
|
792
|
+
bytes += value.byteLength;
|
|
733
793
|
const text = dec.decode(value, { stream: true });
|
|
734
794
|
// Slice on UTF-16 boundaries: JSON round-trips lone surrogates as \uXXXX,
|
|
735
795
|
// so the receiver reassembles the exact text by concatenating in seq order.
|
|
@@ -742,13 +802,32 @@ export async function startShare(
|
|
|
742
802
|
});
|
|
743
803
|
}
|
|
744
804
|
enqueueSeal(peerId, dc, peer, 0, { t: "end", id, seq });
|
|
805
|
+
maybeSlow("req.end", startedAt, {
|
|
806
|
+
room,
|
|
807
|
+
peer: peerId,
|
|
808
|
+
id,
|
|
809
|
+
method,
|
|
810
|
+
path: p,
|
|
811
|
+
status: res.status,
|
|
812
|
+
chunks: seq,
|
|
813
|
+
bytes,
|
|
814
|
+
});
|
|
745
815
|
} catch (e) {
|
|
746
|
-
if ((e as Error).name !== "AbortError")
|
|
816
|
+
if ((e as Error).name !== "AbortError") {
|
|
817
|
+
maybeSlow("req.error", startedAt, {
|
|
818
|
+
room,
|
|
819
|
+
peer: peerId,
|
|
820
|
+
id,
|
|
821
|
+
method,
|
|
822
|
+
path: p,
|
|
823
|
+
error: String((e as Error).message ?? e),
|
|
824
|
+
});
|
|
747
825
|
enqueueSeal(peerId, dc, peer, 0, {
|
|
748
826
|
t: "end",
|
|
749
827
|
id,
|
|
750
828
|
error: String((e as Error).message ?? e),
|
|
751
829
|
});
|
|
830
|
+
}
|
|
752
831
|
} finally {
|
|
753
832
|
peer.aborts.delete(id);
|
|
754
833
|
}
|
|
@@ -0,0 +1,61 @@
|
|
|
1
|
+
import { describe, expect, it } from "vitest";
|
|
2
|
+
import {
|
|
3
|
+
NEGO_FLOOR_COLS,
|
|
4
|
+
NEGO_FLOOR_ROWS,
|
|
5
|
+
negotiateSize,
|
|
6
|
+
sanitizeCap,
|
|
7
|
+
} from "./sizeNego.ts";
|
|
8
|
+
|
|
9
|
+
describe("sanitizeCap", () => {
|
|
10
|
+
it("accepts a normal viewer capacity", () => {
|
|
11
|
+
expect(sanitizeCap({ cols: 80, rows: 24 })).toEqual({ cols: 80, rows: 24 });
|
|
12
|
+
});
|
|
13
|
+
it("floors fractional values", () => {
|
|
14
|
+
expect(sanitizeCap({ cols: 80.9, rows: 24.7 })).toEqual({ cols: 80, rows: 24 });
|
|
15
|
+
});
|
|
16
|
+
it("rejects null / non-object / missing fields", () => {
|
|
17
|
+
expect(sanitizeCap(null)).toBeNull();
|
|
18
|
+
expect(sanitizeCap(undefined)).toBeNull();
|
|
19
|
+
expect(sanitizeCap("80x24")).toBeNull();
|
|
20
|
+
expect(sanitizeCap({})).toBeNull();
|
|
21
|
+
expect(sanitizeCap({ cols: 80 })).toBeNull();
|
|
22
|
+
});
|
|
23
|
+
it("rejects out-of-range junk (mid-layout 0x0, absurd sizes)", () => {
|
|
24
|
+
expect(sanitizeCap({ cols: 0, rows: 0 })).toBeNull();
|
|
25
|
+
expect(sanitizeCap({ cols: 10, rows: 24 })).toBeNull(); // below min cols
|
|
26
|
+
expect(sanitizeCap({ cols: 80, rows: 2 })).toBeNull(); // below min rows
|
|
27
|
+
expect(sanitizeCap({ cols: 9999, rows: 24 })).toBeNull();
|
|
28
|
+
expect(sanitizeCap({ cols: 80, rows: 9999 })).toBeNull();
|
|
29
|
+
expect(sanitizeCap({ cols: NaN, rows: 24 })).toBeNull();
|
|
30
|
+
});
|
|
31
|
+
});
|
|
32
|
+
|
|
33
|
+
describe("negotiateSize", () => {
|
|
34
|
+
it("returns null with no caps (withdraw → tty size rules)", () => {
|
|
35
|
+
expect(negotiateSize([])).toBeNull();
|
|
36
|
+
});
|
|
37
|
+
it("single viewer: adopts its capacity", () => {
|
|
38
|
+
expect(negotiateSize([{ cols: 133, rows: 40 }])).toEqual({ cols: 133, rows: 40 });
|
|
39
|
+
});
|
|
40
|
+
it("phone + desktop: elementwise min (the tmux rule)", () => {
|
|
41
|
+
// phone is narrow but tall, desktop is wide but short → min of each axis
|
|
42
|
+
const phone = { cols: 51, rows: 60 };
|
|
43
|
+
const desktop = { cols: 200, rows: 50 };
|
|
44
|
+
expect(negotiateSize([phone, desktop])).toEqual({ cols: 51, rows: 50 });
|
|
45
|
+
});
|
|
46
|
+
it("clamps to the floor so a tiny viewer can't wedge the agent", () => {
|
|
47
|
+
expect(negotiateSize([{ cols: 20, rows: 5 }])).toEqual({
|
|
48
|
+
cols: NEGO_FLOOR_COLS,
|
|
49
|
+
rows: NEGO_FLOOR_ROWS,
|
|
50
|
+
});
|
|
51
|
+
});
|
|
52
|
+
it("three viewers: min wins per axis", () => {
|
|
53
|
+
expect(
|
|
54
|
+
negotiateSize([
|
|
55
|
+
{ cols: 100, rows: 30 },
|
|
56
|
+
{ cols: 80, rows: 50 },
|
|
57
|
+
{ cols: 120, rows: 24 },
|
|
58
|
+
]),
|
|
59
|
+
).toEqual({ cols: 80, rows: 24 });
|
|
60
|
+
});
|
|
61
|
+
});
|
package/ts/sizeNego.ts
ADDED
|
@@ -0,0 +1,59 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Multi-viewer PTY size negotiation — the tmux "smallest client wins" rule.
|
|
3
|
+
*
|
|
4
|
+
* Every writable web viewer reports its readable capacity (the cols×rows its
|
|
5
|
+
* pane can render at its chosen font size) via /api/presence. The host resizes
|
|
6
|
+
* the agent's PTY to the elementwise minimum across live viewers, so the
|
|
7
|
+
* narrowest screen (a phone) gets a grid it can actually read while wider
|
|
8
|
+
* viewers simply render fewer columns. When the last capacity-reporting viewer
|
|
9
|
+
* leaves, the negotiated size is withdrawn and the PTY falls back to the real
|
|
10
|
+
* terminal's size (the wrapper re-reads the tty once the winsize file is gone).
|
|
11
|
+
*
|
|
12
|
+
* Pure logic only — the serve layer owns presence bookkeeping, the winsize
|
|
13
|
+
* file, and SIGWINCH delivery.
|
|
14
|
+
*/
|
|
15
|
+
|
|
16
|
+
export interface SizeCap {
|
|
17
|
+
cols: number;
|
|
18
|
+
rows: number;
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
/** Reject junk caps (a viewer mid-layout can report 0×0 or absurd numbers). */
|
|
22
|
+
const CAP_MIN_COLS = 20;
|
|
23
|
+
const CAP_MIN_ROWS = 5;
|
|
24
|
+
const CAP_MAX_COLS = 500;
|
|
25
|
+
const CAP_MAX_ROWS = 200;
|
|
26
|
+
|
|
27
|
+
/** Never negotiate below this — TUIs (claude, codex) break down when the grid
|
|
28
|
+
* gets absurdly narrow, so a tiny watch-sized viewer can't wedge the agent. */
|
|
29
|
+
export const NEGO_FLOOR_COLS = 40;
|
|
30
|
+
export const NEGO_FLOOR_ROWS = 10;
|
|
31
|
+
|
|
32
|
+
/** Parse a presence-reported cap into a sane SizeCap, or null if unusable. */
|
|
33
|
+
export function sanitizeCap(cap: unknown): SizeCap | null {
|
|
34
|
+
if (typeof cap !== "object" || cap === null) return null;
|
|
35
|
+
const c = Math.floor(Number((cap as SizeCap).cols) || 0);
|
|
36
|
+
const r = Math.floor(Number((cap as SizeCap).rows) || 0);
|
|
37
|
+
if (c < CAP_MIN_COLS || c > CAP_MAX_COLS) return null;
|
|
38
|
+
if (r < CAP_MIN_ROWS || r > CAP_MAX_ROWS) return null;
|
|
39
|
+
return { cols: c, rows: r };
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
/**
|
|
43
|
+
* Elementwise minimum over the live viewers' capacities, clamped to the floor.
|
|
44
|
+
* Returns null when no viewer reports a capacity — meaning "withdraw the
|
|
45
|
+
* negotiated size, let the real tty size rule again".
|
|
46
|
+
*/
|
|
47
|
+
export function negotiateSize(caps: ReadonlyArray<SizeCap>): SizeCap | null {
|
|
48
|
+
let cols = Infinity;
|
|
49
|
+
let rows = Infinity;
|
|
50
|
+
for (const cap of caps) {
|
|
51
|
+
if (cap.cols < cols) cols = cap.cols;
|
|
52
|
+
if (cap.rows < rows) rows = cap.rows;
|
|
53
|
+
}
|
|
54
|
+
if (!Number.isFinite(cols) || !Number.isFinite(rows)) return null;
|
|
55
|
+
return {
|
|
56
|
+
cols: Math.max(NEGO_FLOOR_COLS, cols),
|
|
57
|
+
rows: Math.max(NEGO_FLOOR_ROWS, rows),
|
|
58
|
+
};
|
|
59
|
+
}
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
import { describe, expect, it } from "vitest";
|
|
2
|
+
import { parseStatusText } from "./statusText.ts";
|
|
3
|
+
|
|
4
|
+
describe("parseStatusText", () => {
|
|
5
|
+
it("returns the latest Claude spinner/status line", () => {
|
|
6
|
+
expect(
|
|
7
|
+
parseStatusText([
|
|
8
|
+
"older output",
|
|
9
|
+
"✶ Verifying calendar meetings with real data… (6m 30s · ↓ 19.5k tokens)",
|
|
10
|
+
]),
|
|
11
|
+
).toBe("✶ Verifying calendar meetings with real data… (6m 30s · ↓ 19.5k tokens)");
|
|
12
|
+
});
|
|
13
|
+
|
|
14
|
+
it("ignores non-status terminal prose", () => {
|
|
15
|
+
expect(parseStatusText(["hello", "Done", ""])).toBe(null);
|
|
16
|
+
});
|
|
17
|
+
});
|
package/ts/statusText.ts
ADDED
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Extract a short "what is the agent doing right now?" line from the rendered
|
|
3
|
+
* terminal screen. Claude Code paints this as a spinner/status line, e.g.
|
|
4
|
+
* "✶ Verifying calendar meetings with real data… (6m 30s · ↓ 19.5k tokens)".
|
|
5
|
+
*/
|
|
6
|
+
|
|
7
|
+
const SPINNER_PREFIX = /^[\u2800-\u28ff✶✻✢✳✽✦✧✩✷✸✹✺✼·•●◐◓◒◑]\s+/u;
|
|
8
|
+
const CONTROL = /[\x00-\x1f\x7f-\x9f]/g;
|
|
9
|
+
|
|
10
|
+
export function parseStatusText(lines: string[]): string | null {
|
|
11
|
+
for (let i = lines.length - 1; i >= 0; i--) {
|
|
12
|
+
const line = lines[i]?.replace(CONTROL, "").trim();
|
|
13
|
+
if (!line || line.length < 3) continue;
|
|
14
|
+
if (!SPINNER_PREFIX.test(line)) continue;
|
|
15
|
+
if (/^(?:[•·]\s*)?(?:esc|ctrl|enter|return|shift|tab)\b/i.test(line)) continue;
|
|
16
|
+
return line.slice(0, 220).trim();
|
|
17
|
+
}
|
|
18
|
+
return null;
|
|
19
|
+
}
|
package/ts/ws.spec.ts
CHANGED
|
@@ -468,16 +468,14 @@ describe("collectWorkspaces / workspaceStatus (mocked provision)", () => {
|
|
|
468
468
|
beforeEach(() => {
|
|
469
469
|
root = realpathSync(mkdtempSync(path.join(os.tmpdir(), "ay-ws-api-")));
|
|
470
470
|
prov.wsRoot = root;
|
|
471
|
-
prov.readStatus
|
|
472
|
-
|
|
473
|
-
|
|
474
|
-
|
|
475
|
-
|
|
476
|
-
|
|
477
|
-
|
|
478
|
-
|
|
479
|
-
hasUpstream: true,
|
|
480
|
-
});
|
|
471
|
+
prov.readStatus.mockReset().mockResolvedValue({
|
|
472
|
+
branch: "main",
|
|
473
|
+
head: "abc123",
|
|
474
|
+
ahead: 1,
|
|
475
|
+
behind: 0,
|
|
476
|
+
dirty: true,
|
|
477
|
+
hasUpstream: true,
|
|
478
|
+
});
|
|
481
479
|
homeBackup = process.env.AGENT_YES_HOME;
|
|
482
480
|
process.env.AGENT_YES_HOME = path.join(root, ".ay-home");
|
|
483
481
|
});
|
|
@@ -1,9 +0,0 @@
|
|
|
1
|
-
import "./ts-Dm6jjLwC.js";
|
|
2
|
-
import "./logger-CDIsZ-Pp.js";
|
|
3
|
-
import "./versionChecker-BomfUpSo.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-C8-qh98a.js";
|
|
8
|
-
|
|
9
|
-
export { SUPPORTED_CLIS };
|