agent-yes 1.143.0 → 1.145.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 +4 -2
- package/default.config.yaml +7 -0
- package/dist/SUPPORTED_CLIS-DDFMfNQu.js +8 -0
- package/dist/{SUPPORTED_CLIS-DdzFdshj.js → SUPPORTED_CLIS-D_aVmqPt.js} +2 -2
- package/dist/cli.js +6 -6
- package/dist/e2e-ClOI_aqV.js +175 -0
- package/dist/index.js +2 -2
- package/dist/{invokedCli-zdFbz1ST.js → invokedCli-uqM2YYA7.js} +5 -2
- package/dist/orcy.js +10 -0
- package/dist/{remotes-BdankQeI.js → remotes-5lHLAAqn.js} +3 -1
- package/dist/{remotes-PKKjfTI1.js → remotes-qK6uozO4.js} +28 -2
- package/dist/{schedule-C8QKzvq-.js → schedule-BDi11K0Y.js} +5 -5
- package/dist/{serve-Bathp8Fu.js → serve-CogqhRFd.js} +10 -8
- package/dist/{setup-ygcLSFBT.js → setup-H2coxV-T.js} +3 -3
- package/dist/{share-CoyAOa6e.js → share-ShLKJTUE.js} +2 -174
- package/dist/{subcommands-BthznoYM.js → subcommands-BcvCjFLt.js} +22 -10
- package/dist/{subcommands-BtCnrZmr.js → subcommands-Dm1UwXKC.js} +4 -2
- package/dist/{tray-DsTv-C04.js → tray-5Hezw9uj.js} +1 -1
- package/dist/{ts-CV4m7CUC.js → ts-Cg31cRC5.js} +7 -5
- package/dist/{versionChecker-DatX-QMn.js → versionChecker-DK7tFI0U.js} +2 -2
- package/dist/webrtcLink-BWhuA74k.js +45 -0
- package/dist/webrtcRemote-jGM3ZHK3.js +259 -0
- package/dist/{workspaceConfig-BCOqRBEW.js → workspaceConfig-B3ylOZAO.js} +1 -1
- package/package.json +3 -2
- package/ts/index.ts +12 -5
- package/ts/invokedCli.ts +2 -1
- package/ts/postbuild.ts +1 -1
- package/ts/remotes.ts +28 -1
- package/ts/subcommands.ts +0 -0
- package/ts/webrtcLink.spec.ts +45 -0
- package/ts/webrtcLink.ts +45 -0
- package/ts/webrtcRemote.ts +280 -0
- package/dist/SUPPORTED_CLIS-CPLtBfWE.js +0 -8
package/README.md
CHANGED
|
@@ -143,8 +143,10 @@ ZAI_API_KEY=... glm-yes -- help me with this code
|
|
|
143
143
|
|
|
144
144
|
# Use OpenRouter directly — runs Claude Code against OpenRouter's
|
|
145
145
|
# Anthropic-compatible endpoint. Set OPENROUTER_API_KEY first
|
|
146
|
-
# (https://openrouter.ai/keys).
|
|
147
|
-
|
|
146
|
+
# (https://openrouter.ai/keys). `orcy` is the short alias
|
|
147
|
+
# (openrouter-claude-yes) and defaults to the z-ai/glm-5.2 model
|
|
148
|
+
# (override via ANTHROPIC_DEFAULT_*_MODEL or ~/.claude/settings.json).
|
|
149
|
+
OPENROUTER_API_KEY=... orcy -- help me with this code
|
|
148
150
|
|
|
149
151
|
# Use Pi directly — minimal multi-provider coding agent
|
|
150
152
|
# (https://github.com/earendil-works/pi)
|
package/default.config.yaml
CHANGED
|
@@ -169,6 +169,13 @@ clis:
|
|
|
169
169
|
ANTHROPIC_BASE_URL: https://openrouter.ai/api
|
|
170
170
|
ANTHROPIC_AUTH_TOKEN: ${OPENROUTER_API_KEY}
|
|
171
171
|
ANTHROPIC_API_KEY: ""
|
|
172
|
+
# Default to GLM 5.2 (verified to work through OpenRouter's Anthropic skin).
|
|
173
|
+
# `${VAR:-default}` keeps it overridable: export ANTHROPIC_DEFAULT_*_MODEL or
|
|
174
|
+
# ANTHROPIC_MODEL (or set them in ~/.claude/settings.json) to use another
|
|
175
|
+
# OpenRouter slug. Reachable as `orcy` (openrouter-claude-yes).
|
|
176
|
+
ANTHROPIC_DEFAULT_SONNET_MODEL: ${ANTHROPIC_DEFAULT_SONNET_MODEL:-z-ai/glm-5.2}
|
|
177
|
+
ANTHROPIC_DEFAULT_OPUS_MODEL: ${ANTHROPIC_DEFAULT_OPUS_MODEL:-z-ai/glm-5.2}
|
|
178
|
+
ANTHROPIC_DEFAULT_HAIKU_MODEL: ${ANTHROPIC_DEFAULT_HAIKU_MODEL:-z-ai/glm-5.2}
|
|
172
179
|
promptArg: last-arg
|
|
173
180
|
systemPrompt: --append-system-prompt
|
|
174
181
|
yesArgs:
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
import "./ts-Cg31cRC5.js";
|
|
2
|
+
import "./logger-CDIsZ-Pp.js";
|
|
3
|
+
import "./versionChecker-DK7tFI0U.js";
|
|
4
|
+
import "./pidStore-fqXqTKkh.js";
|
|
5
|
+
import "./globalPidIndex-DlmmJlO8.js";
|
|
6
|
+
import { t as SUPPORTED_CLIS } from "./SUPPORTED_CLIS-D_aVmqPt.js";
|
|
7
|
+
|
|
8
|
+
export { SUPPORTED_CLIS };
|
|
@@ -1,8 +1,8 @@
|
|
|
1
|
-
import { t as CLIS_CONFIG } from "./ts-
|
|
1
|
+
import { t as CLIS_CONFIG } from "./ts-Cg31cRC5.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-
|
|
8
|
+
//# sourceMappingURL=SUPPORTED_CLIS-D_aVmqPt.js.map
|
package/dist/cli.js
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
#!/usr/bin/env bun
|
|
2
|
-
import { t as invokedCliName } from "./invokedCli-
|
|
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, r as getInstalledPackage, t as checkAndAutoUpdate } from "./versionChecker-
|
|
4
|
+
import { i as versionString, n as displayVersion, r as getInstalledPackage, t as checkAndAutoUpdate } from "./versionChecker-DK7tFI0U.js";
|
|
5
5
|
import { argv } from "process";
|
|
6
6
|
import { execFileSync, spawn } from "child_process";
|
|
7
7
|
import ms from "ms";
|
|
@@ -480,7 +480,7 @@ function buildRustArgs(argv, cliFromScript, supportedClis) {
|
|
|
480
480
|
const rawArg = process.argv[2];
|
|
481
481
|
const managerCommands = !invokedCliName(process.argv);
|
|
482
482
|
const isHelpFlag = rawArg === "-h" || rawArg === "--help";
|
|
483
|
-
const { isSubcommand, runSubcommand, cmdHelp } = await import("./subcommands-
|
|
483
|
+
const { isSubcommand, runSubcommand, cmdHelp } = await import("./subcommands-Dm1UwXKC.js");
|
|
484
484
|
if (isHelpFlag && process.argv.length === 3) {
|
|
485
485
|
cmdHelp(managerCommands);
|
|
486
486
|
process.exit(0);
|
|
@@ -494,12 +494,12 @@ await checkAndAutoUpdate();
|
|
|
494
494
|
logger.info(versionString());
|
|
495
495
|
const config = parseCliArgs(process.argv);
|
|
496
496
|
if (config.tray) {
|
|
497
|
-
const { startTray } = await import("./tray-
|
|
497
|
+
const { startTray } = await import("./tray-5Hezw9uj.js");
|
|
498
498
|
await startTray();
|
|
499
499
|
await new Promise(() => {});
|
|
500
500
|
}
|
|
501
501
|
{
|
|
502
|
-
const { ensureTray } = await import("./tray-
|
|
502
|
+
const { ensureTray } = await import("./tray-5Hezw9uj.js");
|
|
503
503
|
ensureTray();
|
|
504
504
|
}
|
|
505
505
|
if (config.useRust) {
|
|
@@ -513,7 +513,7 @@ if (config.useRust) {
|
|
|
513
513
|
}
|
|
514
514
|
}
|
|
515
515
|
if (rustBinary) {
|
|
516
|
-
const { SUPPORTED_CLIS } = await import("./SUPPORTED_CLIS-
|
|
516
|
+
const { SUPPORTED_CLIS } = await import("./SUPPORTED_CLIS-DDFMfNQu.js");
|
|
517
517
|
const rustArgs = buildRustArgs(process.argv, config.cli, SUPPORTED_CLIS);
|
|
518
518
|
if (config.verbose) {
|
|
519
519
|
console.log(`[rust] Using binary: ${rustBinary}`);
|
|
@@ -0,0 +1,175 @@
|
|
|
1
|
+
//#region lab/ui/e2e.js
|
|
2
|
+
const V = 1;
|
|
3
|
+
const PROTO = `ay-e2e-${V}`;
|
|
4
|
+
const MARKER = `e${V}.`;
|
|
5
|
+
const INFO_AUTH = `ay/${PROTO}/auth`;
|
|
6
|
+
const INFO_H2C = `ay/${PROTO}/key/host->client`;
|
|
7
|
+
const INFO_C2H = `ay/${PROTO}/key/client->host`;
|
|
8
|
+
const MAX_CHUNK = 12e3;
|
|
9
|
+
const CONFIRM_TIMEOUT_MS = 5e3;
|
|
10
|
+
const VER = 1;
|
|
11
|
+
const FLAG_CONFIRM = 1;
|
|
12
|
+
const HEADER_LEN = 14;
|
|
13
|
+
const NONCE_LEN = 12;
|
|
14
|
+
const TAG_LEN = 16;
|
|
15
|
+
const COUNTER_MAX = (1n << 64n) - 1n;
|
|
16
|
+
if (PROTO !== `ay-e2e-${V}` || MARKER !== `e${V}.` || !INFO_AUTH.startsWith(`ay/${PROTO}/`)) throw new Error("e2e: version constants disagree");
|
|
17
|
+
const subtle = globalThis.crypto.subtle;
|
|
18
|
+
const enc = new TextEncoder();
|
|
19
|
+
const dec = new TextDecoder();
|
|
20
|
+
const HEX64 = /^[0-9a-f]{64}$/;
|
|
21
|
+
function concatBytes(...arrs) {
|
|
22
|
+
let len = 0;
|
|
23
|
+
for (const a of arrs) len += a.length;
|
|
24
|
+
const out = new Uint8Array(len);
|
|
25
|
+
let o = 0;
|
|
26
|
+
for (const a of arrs) {
|
|
27
|
+
out.set(a, o);
|
|
28
|
+
o += a.length;
|
|
29
|
+
}
|
|
30
|
+
return out;
|
|
31
|
+
}
|
|
32
|
+
function hexToBytes(hex) {
|
|
33
|
+
const out = new Uint8Array(hex.length / 2);
|
|
34
|
+
for (let i = 0; i < out.length; i++) out[i] = parseInt(hex.substr(i * 2, 2), 16);
|
|
35
|
+
return out;
|
|
36
|
+
}
|
|
37
|
+
function bytesToHex(b) {
|
|
38
|
+
let s = "";
|
|
39
|
+
for (let i = 0; i < b.length; i++) s += b[i].toString(16).padStart(2, "0");
|
|
40
|
+
return s;
|
|
41
|
+
}
|
|
42
|
+
async function sha256(bytes) {
|
|
43
|
+
return new Uint8Array(await subtle.digest("SHA-256", bytes));
|
|
44
|
+
}
|
|
45
|
+
async function hkdf32(ikm, salt, info) {
|
|
46
|
+
const base = await subtle.importKey("raw", ikm, "HKDF", false, ["deriveBits"]);
|
|
47
|
+
const bits = await subtle.deriveBits({
|
|
48
|
+
name: "HKDF",
|
|
49
|
+
hash: "SHA-256",
|
|
50
|
+
salt,
|
|
51
|
+
info: enc.encode(info)
|
|
52
|
+
}, base, 256);
|
|
53
|
+
return new Uint8Array(bits);
|
|
54
|
+
}
|
|
55
|
+
function validateS(s) {
|
|
56
|
+
if (typeof s !== "string" || !HEX64.test(s)) throw new Error("invalid share token");
|
|
57
|
+
return s;
|
|
58
|
+
}
|
|
59
|
+
function ikmFromS(s) {
|
|
60
|
+
return hexToBytes(validateS(s));
|
|
61
|
+
}
|
|
62
|
+
async function deriveAuthToken(s, room, sighost) {
|
|
63
|
+
const salt = await sha256(enc.encode(`${room}\n${sighost}`));
|
|
64
|
+
return bytesToHex(await hkdf32(ikmFromS(s), salt, INFO_AUTH));
|
|
65
|
+
}
|
|
66
|
+
async function importAesKey(raw) {
|
|
67
|
+
return subtle.importKey("raw", raw, { name: "AES-GCM" }, false, ["encrypt", "decrypt"]);
|
|
68
|
+
}
|
|
69
|
+
async function deriveDirKeys(s, transcriptHash) {
|
|
70
|
+
const ikm = ikmFromS(s);
|
|
71
|
+
const h2c = await hkdf32(ikm, transcriptHash, INFO_H2C);
|
|
72
|
+
const c2h = await hkdf32(ikm, transcriptHash, INFO_C2H);
|
|
73
|
+
return {
|
|
74
|
+
keyH2C: await importAesKey(h2c),
|
|
75
|
+
keyC2H: await importAesKey(c2h)
|
|
76
|
+
};
|
|
77
|
+
}
|
|
78
|
+
function allFingerprints(sdp) {
|
|
79
|
+
const out = [];
|
|
80
|
+
const re = /^a=fingerprint:(.*)$/gim;
|
|
81
|
+
let m;
|
|
82
|
+
while (m = re.exec(sdp)) out.push(m[1].trim().toLowerCase());
|
|
83
|
+
return out;
|
|
84
|
+
}
|
|
85
|
+
function firstAttr(sdp, name) {
|
|
86
|
+
const m = new RegExp(`^a=${name}:(.*)$`, "im").exec(sdp);
|
|
87
|
+
return m ? m[1].trim().toLowerCase() : "";
|
|
88
|
+
}
|
|
89
|
+
async function computeTranscriptHash(offerSdp, answerSdp) {
|
|
90
|
+
const offerFps = allFingerprints(offerSdp).sort();
|
|
91
|
+
const answerFps = allFingerprints(answerSdp).sort();
|
|
92
|
+
if (!offerFps.length || !answerFps.length) throw new Error("e2e: missing DTLS fingerprint");
|
|
93
|
+
for (const fp of offerFps.concat(answerFps)) if (!fp.startsWith("sha-256")) throw new Error("e2e: non-sha-256 DTLS fingerprint");
|
|
94
|
+
const input = `${PROTO}\noffer=${offerFps.join(",")};setup=${firstAttr(offerSdp, "setup")};ufrag=${firstAttr(offerSdp, "ice-ufrag")}\nanswer=${answerFps.join(",")};setup=${firstAttr(answerSdp, "setup")};ufrag=${firstAttr(answerSdp, "ice-ufrag")}`;
|
|
95
|
+
return await sha256(enc.encode(input));
|
|
96
|
+
}
|
|
97
|
+
function nonceFromCounter(ctr) {
|
|
98
|
+
const n = new Uint8Array(NONCE_LEN);
|
|
99
|
+
new DataView(n.buffer).setBigUint64(4, ctr, false);
|
|
100
|
+
return n;
|
|
101
|
+
}
|
|
102
|
+
async function seal(key, sendState, flags, transcriptHash, plaintext) {
|
|
103
|
+
const ctr = sendState.sendCtr;
|
|
104
|
+
if (ctr >= COUNTER_MAX) throw new Error("e2e: nonce counter overflow");
|
|
105
|
+
sendState.sendCtr = ctr + 1n;
|
|
106
|
+
const nonce = nonceFromCounter(ctr);
|
|
107
|
+
const header = new Uint8Array(HEADER_LEN);
|
|
108
|
+
header[0] = VER;
|
|
109
|
+
header[1] = flags & 255;
|
|
110
|
+
header.set(nonce, 2);
|
|
111
|
+
const aad = concatBytes(header, transcriptHash);
|
|
112
|
+
return concatBytes(header, new Uint8Array(await subtle.encrypt({
|
|
113
|
+
name: "AES-GCM",
|
|
114
|
+
iv: nonce,
|
|
115
|
+
additionalData: aad,
|
|
116
|
+
tagLength: 128
|
|
117
|
+
}, key, plaintext))).buffer;
|
|
118
|
+
}
|
|
119
|
+
async function open(key, frame, transcriptHash, recvState) {
|
|
120
|
+
const buf = frame instanceof Uint8Array ? frame : new Uint8Array(frame);
|
|
121
|
+
if (buf.length < HEADER_LEN + TAG_LEN) throw new Error("e2e: short frame");
|
|
122
|
+
if (buf[0] !== VER) throw new Error("e2e: bad version");
|
|
123
|
+
const header = buf.subarray(0, HEADER_LEN);
|
|
124
|
+
const nonce = buf.subarray(2, HEADER_LEN);
|
|
125
|
+
const ndv = new DataView(nonce.buffer, nonce.byteOffset, NONCE_LEN);
|
|
126
|
+
if (ndv.getUint32(0, false) !== 0) throw new Error("e2e: bad epoch");
|
|
127
|
+
const ctr = ndv.getBigUint64(4, false);
|
|
128
|
+
const sealed = buf.subarray(HEADER_LEN);
|
|
129
|
+
const aad = concatBytes(header, transcriptHash);
|
|
130
|
+
const ptBuf = await subtle.decrypt({
|
|
131
|
+
name: "AES-GCM",
|
|
132
|
+
iv: nonce,
|
|
133
|
+
additionalData: aad,
|
|
134
|
+
tagLength: 128
|
|
135
|
+
}, key, sealed);
|
|
136
|
+
if (recvState.lastSeen === -1n && ctr !== 0n) throw new Error("e2e: first frame must be counter-0");
|
|
137
|
+
if (ctr <= recvState.lastSeen) throw new Error("e2e: replay/reorder");
|
|
138
|
+
recvState.lastSeen = ctr;
|
|
139
|
+
return {
|
|
140
|
+
counter: ctr,
|
|
141
|
+
flags: header[1],
|
|
142
|
+
plaintext: new Uint8Array(ptBuf)
|
|
143
|
+
};
|
|
144
|
+
}
|
|
145
|
+
function packEnvelope(obj) {
|
|
146
|
+
return enc.encode(JSON.stringify(obj));
|
|
147
|
+
}
|
|
148
|
+
function unpackEnvelope(bytes) {
|
|
149
|
+
return JSON.parse(dec.decode(bytes));
|
|
150
|
+
}
|
|
151
|
+
function parseSecret(token) {
|
|
152
|
+
const mk = /^e(\d+)\.(.*)$/.exec(token);
|
|
153
|
+
if (mk) {
|
|
154
|
+
if (mk[1] !== String(V)) throw new Error("update required");
|
|
155
|
+
if (!HEX64.test(mk[2])) throw new Error("malformed encrypted link");
|
|
156
|
+
return {
|
|
157
|
+
s: mk[2],
|
|
158
|
+
v2: true
|
|
159
|
+
};
|
|
160
|
+
}
|
|
161
|
+
if (/^e\d/i.test(token)) throw new Error("malformed encrypted link");
|
|
162
|
+
return {
|
|
163
|
+
s: token,
|
|
164
|
+
v2: false
|
|
165
|
+
};
|
|
166
|
+
}
|
|
167
|
+
function randomHex(n) {
|
|
168
|
+
const b = new Uint8Array(n);
|
|
169
|
+
globalThis.crypto.getRandomValues(b);
|
|
170
|
+
return bytesToHex(b);
|
|
171
|
+
}
|
|
172
|
+
|
|
173
|
+
//#endregion
|
|
174
|
+
export { computeTranscriptHash as a, open as c, randomHex as d, seal as f, MAX_CHUNK as i, packEnvelope as l, FLAG_CONFIRM as n, deriveAuthToken as o, unpackEnvelope as p, MARKER as r, deriveDirKeys as s, CONFIRM_TIMEOUT_MS as t, parseSecret as u };
|
|
175
|
+
//# sourceMappingURL=e2e-ClOI_aqV.js.map
|
package/dist/index.js
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
import { a as removeControlCharacters, i as AgentContext, n as agentYes, r as config, t as CLIS_CONFIG } from "./ts-
|
|
1
|
+
import { a as removeControlCharacters, i as AgentContext, n as agentYes, r as config, t as CLIS_CONFIG } from "./ts-Cg31cRC5.js";
|
|
2
2
|
import "./logger-CDIsZ-Pp.js";
|
|
3
|
-
import "./versionChecker-
|
|
3
|
+
import "./versionChecker-DK7tFI0U.js";
|
|
4
4
|
import "./pidStore-fqXqTKkh.js";
|
|
5
5
|
import "./globalPidIndex-DlmmJlO8.js";
|
|
6
6
|
|
|
@@ -10,7 +10,10 @@
|
|
|
10
10
|
* resolves to `undefined`. Callers use that `undefined` to tell "the agent-yes
|
|
11
11
|
* manager" apart from "a cli-bound runner alias".
|
|
12
12
|
*/
|
|
13
|
-
const CLI_ALIASES = {
|
|
13
|
+
const CLI_ALIASES = {
|
|
14
|
+
cy: "claude",
|
|
15
|
+
orcy: "openrouter"
|
|
16
|
+
};
|
|
14
17
|
/**
|
|
15
18
|
* The agent CLI implied by argv[1] (cy / claude-yes → "claude", codex-yes →
|
|
16
19
|
* "codex", …), or `undefined` for the generic `ay` / `agent-yes` / `cli` entry.
|
|
@@ -22,4 +25,4 @@ function invokedCliName(argv) {
|
|
|
22
25
|
|
|
23
26
|
//#endregion
|
|
24
27
|
export { invokedCliName as t };
|
|
25
|
-
//# sourceMappingURL=invokedCli-
|
|
28
|
+
//# sourceMappingURL=invokedCli-uqM2YYA7.js.map
|
package/dist/orcy.js
ADDED
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
#!/usr/bin/env bun
|
|
2
|
+
import { existsSync } from "node:fs";
|
|
3
|
+
import { join, dirname } from "node:path";
|
|
4
|
+
import { fileURLToPath } from "node:url";
|
|
5
|
+
const root = join(dirname(fileURLToPath(import.meta.url)), "..");
|
|
6
|
+
if (typeof Bun !== "undefined" && existsSync(join(root, ".git"))) {
|
|
7
|
+
await import("../ts/cli.ts");
|
|
8
|
+
} else {
|
|
9
|
+
await import("./cli.js");
|
|
10
|
+
}
|
|
@@ -1,3 +1,5 @@
|
|
|
1
|
-
import
|
|
1
|
+
import "./e2e-ClOI_aqV.js";
|
|
2
|
+
import "./webrtcLink-BWhuA74k.js";
|
|
3
|
+
import { a as resolveRemoteSpec, i as readRemotes, n as deleteRemoteAlias, o as writeRemoteAlias, r as parseDirectRemoteSpec, t as cmdRemote } from "./remotes-qK6uozO4.js";
|
|
2
4
|
|
|
3
5
|
export { cmdRemote };
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { n as isWebrtcSpec } from "./webrtcLink-BWhuA74k.js";
|
|
1
2
|
import { mkdir, readFile, writeFile } from "fs/promises";
|
|
2
3
|
import { homedir } from "os";
|
|
3
4
|
import path from "path";
|
|
@@ -60,6 +61,7 @@ function parseDirectRemoteSpec(spec) {
|
|
|
60
61
|
* Returns null if the spec doesn't match any remote.
|
|
61
62
|
*/
|
|
62
63
|
async function resolveRemoteSpec(spec) {
|
|
64
|
+
if (isWebrtcSpec(spec)) return resolveWebrtc(spec, void 0);
|
|
63
65
|
const direct = parseDirectRemoteSpec(spec);
|
|
64
66
|
if (direct) return {
|
|
65
67
|
url: direct.baseUrl,
|
|
@@ -71,16 +73,31 @@ async function resolveRemoteSpec(spec) {
|
|
|
71
73
|
const keyword = colonIdx >= 0 ? spec.slice(colonIdx + 1) || void 0 : void 0;
|
|
72
74
|
const cfg = (await readRemotes()).get(alias);
|
|
73
75
|
if (!cfg) return null;
|
|
76
|
+
if (isWebrtcSpec(cfg.url)) return resolveWebrtc(cfg.url, keyword);
|
|
74
77
|
return {
|
|
75
78
|
url: cfg.url,
|
|
76
79
|
token: cfg.token,
|
|
77
80
|
keyword
|
|
78
81
|
};
|
|
79
82
|
}
|
|
83
|
+
/**
|
|
84
|
+
* Start a local HTTP↔WebRTC bridge for a share link and present it as an
|
|
85
|
+
* ordinary http remote, so every fetch-based remote command works unchanged.
|
|
86
|
+
* The bridge lives for the rest of the process (torn down on `process.exit`).
|
|
87
|
+
*/
|
|
88
|
+
async function resolveWebrtc(link, keyword) {
|
|
89
|
+
const { startWebrtcBridge } = await import("./webrtcRemote-jGM3ZHK3.js");
|
|
90
|
+
const bridge = await startWebrtcBridge(link);
|
|
91
|
+
return {
|
|
92
|
+
url: bridge.baseUrl,
|
|
93
|
+
token: bridge.token,
|
|
94
|
+
keyword
|
|
95
|
+
};
|
|
96
|
+
}
|
|
80
97
|
async function cmdRemote(rest) {
|
|
81
98
|
const sub = rest[0];
|
|
82
99
|
if (sub === "-h" || sub === "--help") {
|
|
83
|
-
process.stdout.write("Usage: ay remote <subcommand>\n\nManage saved remote server aliases.\n\nSubcommands:\n ay remote ls list configured remotes\n ay remote add <alias> http://<token>@<host>:<port> add a remote\n ay remote rm <alias> remove a remote\n\nOnce added, use the alias anywhere a keyword is accepted:\n ay ls <alias>\n ay tail <alias>:<keyword>\n ay send <alias>:<keyword> \"message\"\n");
|
|
100
|
+
process.stdout.write("Usage: ay remote <subcommand>\n\nManage saved remote server aliases.\n\nSubcommands:\n ay remote ls list configured remotes\n ay remote add <alias> http://<token>@<host>:<port> add an http remote\n ay remote add <alias> webrtc://<room>:<token>@<host> add a WebRTC share remote\n ay remote add <alias> https://agent-yes.com/w/#<room>:<token> (share link form)\n ay remote rm <alias> remove a remote\n\nOnce added, use the alias anywhere a keyword is accepted:\n ay ls <alias>\n ay tail <alias>:<keyword>\n ay send <alias>:<keyword> \"message\"\n");
|
|
84
101
|
return 0;
|
|
85
102
|
}
|
|
86
103
|
if (!sub || sub === "ls" || sub === "list") {
|
|
@@ -103,6 +120,15 @@ async function cmdRemote(rest) {
|
|
|
103
120
|
process.stderr.write(" example: ay remote add work-mac http://mytoken123@192.168.1.5:7432\n");
|
|
104
121
|
return 1;
|
|
105
122
|
}
|
|
123
|
+
if (isWebrtcSpec(rawUrl)) {
|
|
124
|
+
await writeRemoteAlias(alias, {
|
|
125
|
+
url: rawUrl,
|
|
126
|
+
token: ""
|
|
127
|
+
});
|
|
128
|
+
process.stdout.write(`remote '${alias}' added → ${rawUrl} (webrtc)\n`);
|
|
129
|
+
process.stderr.write(`\n ay ls ${alias} # list agents on ${alias}\n`);
|
|
130
|
+
return 0;
|
|
131
|
+
}
|
|
106
132
|
let url, token;
|
|
107
133
|
try {
|
|
108
134
|
const parsed = new URL(rawUrl);
|
|
@@ -147,4 +173,4 @@ async function cmdRemote(rest) {
|
|
|
147
173
|
|
|
148
174
|
//#endregion
|
|
149
175
|
export { resolveRemoteSpec as a, readRemotes as i, deleteRemoteAlias as n, writeRemoteAlias as o, parseDirectRemoteSpec as r, cmdRemote as t };
|
|
150
|
-
//# sourceMappingURL=remotes-
|
|
176
|
+
//# sourceMappingURL=remotes-qK6uozO4.js.map
|
|
@@ -1,10 +1,10 @@
|
|
|
1
|
-
import "./ts-
|
|
1
|
+
import "./ts-Cg31cRC5.js";
|
|
2
2
|
import "./logger-CDIsZ-Pp.js";
|
|
3
|
-
import "./versionChecker-
|
|
3
|
+
import "./versionChecker-DK7tFI0U.js";
|
|
4
4
|
import "./pidStore-fqXqTKkh.js";
|
|
5
5
|
import "./globalPidIndex-DlmmJlO8.js";
|
|
6
|
-
import { t as SUPPORTED_CLIS } from "./SUPPORTED_CLIS-
|
|
7
|
-
import { n as resolveSpawnCwd } from "./workspaceConfig-
|
|
6
|
+
import { t as SUPPORTED_CLIS } from "./SUPPORTED_CLIS-D_aVmqPt.js";
|
|
7
|
+
import { n as resolveSpawnCwd } from "./workspaceConfig-B3ylOZAO.js";
|
|
8
8
|
import { createHash } from "node:crypto";
|
|
9
9
|
|
|
10
10
|
//#region ts/oxmgrService.ts
|
|
@@ -141,4 +141,4 @@ async function cmdSchedule(rest) {
|
|
|
141
141
|
|
|
142
142
|
//#endregion
|
|
143
143
|
export { cmdSchedule };
|
|
144
|
-
//# sourceMappingURL=schedule-
|
|
144
|
+
//# sourceMappingURL=schedule-BDi11K0Y.js.map
|
|
@@ -1,13 +1,15 @@
|
|
|
1
|
-
import "./ts-
|
|
1
|
+
import "./ts-Cg31cRC5.js";
|
|
2
2
|
import "./logger-CDIsZ-Pp.js";
|
|
3
|
-
import { r as getInstalledPackage } from "./versionChecker-
|
|
3
|
+
import { r as getInstalledPackage } from "./versionChecker-DK7tFI0U.js";
|
|
4
4
|
import "./pidStore-fqXqTKkh.js";
|
|
5
5
|
import { a as updateGlobalPidStatus } from "./globalPidIndex-DlmmJlO8.js";
|
|
6
6
|
import { t as pgidForWrapper } from "./reaper-C-eWAxIj.js";
|
|
7
7
|
import "./configShared-C1C04bbq.js";
|
|
8
|
-
import { t as SUPPORTED_CLIS } from "./SUPPORTED_CLIS-
|
|
9
|
-
import "./
|
|
10
|
-
import
|
|
8
|
+
import { t as SUPPORTED_CLIS } from "./SUPPORTED_CLIS-D_aVmqPt.js";
|
|
9
|
+
import "./e2e-ClOI_aqV.js";
|
|
10
|
+
import "./webrtcLink-BWhuA74k.js";
|
|
11
|
+
import "./remotes-qK6uozO4.js";
|
|
12
|
+
import { S as snapshotStatus, _ as renderRawLog, c as extractTaskCounts, g as readNotes, i as controlCodeFromName, m as listRecords, o as deriveLiveStatus, w as writeToIpc, y as resolveOne } from "./subcommands-BcvCjFLt.js";
|
|
11
13
|
import yargs from "yargs";
|
|
12
14
|
import { mkdir, open, readFile, stat, writeFile } from "fs/promises";
|
|
13
15
|
import { homedir, hostname, userInfo } from "os";
|
|
@@ -248,7 +250,7 @@ async function cmdServeDaemon(sub, args) {
|
|
|
248
250
|
let shareLink = null;
|
|
249
251
|
let shareLinkMinted = false;
|
|
250
252
|
if (webrtcDaemon) try {
|
|
251
|
-
const { loadOrCreateShareRoom, shareLinkFromRoomUrl } = await import("./share-
|
|
253
|
+
const { loadOrCreateShareRoom, shareLinkFromRoomUrl } = await import("./share-ShLKJTUE.js");
|
|
252
254
|
const explicit = explicitWebrtcUrl(effArgs);
|
|
253
255
|
shareLink = shareLinkFromRoomUrl(explicit ?? await loadOrCreateShareRoom());
|
|
254
256
|
shareLinkMinted = !explicit;
|
|
@@ -1122,7 +1124,7 @@ Options:
|
|
|
1122
1124
|
const webrtcVal = argv.webrtc ?? argv.share;
|
|
1123
1125
|
const explicitUrl = typeof webrtcVal === "string" && webrtcVal.startsWith("webrtc://") ? webrtcVal : void 0;
|
|
1124
1126
|
try {
|
|
1125
|
-
const { startShare, loadOrCreateShareRoom } = await import("./share-
|
|
1127
|
+
const { startShare, loadOrCreateShareRoom } = await import("./share-ShLKJTUE.js");
|
|
1126
1128
|
const linkFile = path.join(process.env.AGENT_YES_HOME ?? path.join(homedir(), ".agent-yes"), ".share-link");
|
|
1127
1129
|
const announce = async (room, link, rotated) => {
|
|
1128
1130
|
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)";
|
|
@@ -1177,4 +1179,4 @@ Options:
|
|
|
1177
1179
|
|
|
1178
1180
|
//#endregion
|
|
1179
1181
|
export { cmdServe };
|
|
1180
|
-
//# sourceMappingURL=serve-
|
|
1182
|
+
//# sourceMappingURL=serve-CogqhRFd.js.map
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { r as setWorkspaceRoot, t as getWorkspaceRoot } from "./workspaceConfig-
|
|
1
|
+
import { r as setWorkspaceRoot, t as getWorkspaceRoot } from "./workspaceConfig-B3ylOZAO.js";
|
|
2
2
|
import { existsSync } from "node:fs";
|
|
3
3
|
import { stdin, stdout } from "node:process";
|
|
4
4
|
import { createInterface } from "node:readline/promises";
|
|
@@ -32,7 +32,7 @@ async function cmdSetup(rest) {
|
|
|
32
32
|
if (!existsSync(abs)) process.stderr.write(` note: that directory doesn't exist yet — create it, or agents spawned there will fail\n`);
|
|
33
33
|
if (noShare) return 0;
|
|
34
34
|
process.stdout.write(`\nsharing this machine to agent-yes.com…\n`);
|
|
35
|
-
const { cmdServe } = await import("./serve-
|
|
35
|
+
const { cmdServe } = await import("./serve-CogqhRFd.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-
|
|
45
|
+
//# sourceMappingURL=setup-H2coxV-T.js.map
|
|
@@ -1,181 +1,9 @@
|
|
|
1
|
+
import { a as computeTranscriptHash, c as open$1, d as randomHex, f as seal, i as MAX_CHUNK, l as packEnvelope, n as FLAG_CONFIRM, o as deriveAuthToken, p as unpackEnvelope, r as MARKER, s as deriveDirKeys, t as CONFIRM_TIMEOUT_MS, u as parseSecret } from "./e2e-ClOI_aqV.js";
|
|
1
2
|
import { mkdir, readFile, writeFile } from "fs/promises";
|
|
2
3
|
import { homedir } from "os";
|
|
3
4
|
import path from "path";
|
|
4
5
|
import { randomBytes } from "crypto";
|
|
5
6
|
|
|
6
|
-
//#region lab/ui/e2e.js
|
|
7
|
-
const V = 1;
|
|
8
|
-
const PROTO = `ay-e2e-${V}`;
|
|
9
|
-
const MARKER = `e${V}.`;
|
|
10
|
-
const INFO_AUTH = `ay/${PROTO}/auth`;
|
|
11
|
-
const INFO_H2C = `ay/${PROTO}/key/host->client`;
|
|
12
|
-
const INFO_C2H = `ay/${PROTO}/key/client->host`;
|
|
13
|
-
const MAX_CHUNK = 12e3;
|
|
14
|
-
const CONFIRM_TIMEOUT_MS = 5e3;
|
|
15
|
-
const VER = 1;
|
|
16
|
-
const FLAG_CONFIRM = 1;
|
|
17
|
-
const HEADER_LEN = 14;
|
|
18
|
-
const NONCE_LEN = 12;
|
|
19
|
-
const TAG_LEN = 16;
|
|
20
|
-
const COUNTER_MAX = (1n << 64n) - 1n;
|
|
21
|
-
if (PROTO !== `ay-e2e-${V}` || MARKER !== `e${V}.` || !INFO_AUTH.startsWith(`ay/${PROTO}/`)) throw new Error("e2e: version constants disagree");
|
|
22
|
-
const subtle = globalThis.crypto.subtle;
|
|
23
|
-
const enc = new TextEncoder();
|
|
24
|
-
const dec = new TextDecoder();
|
|
25
|
-
const HEX64 = /^[0-9a-f]{64}$/;
|
|
26
|
-
function concatBytes(...arrs) {
|
|
27
|
-
let len = 0;
|
|
28
|
-
for (const a of arrs) len += a.length;
|
|
29
|
-
const out = new Uint8Array(len);
|
|
30
|
-
let o = 0;
|
|
31
|
-
for (const a of arrs) {
|
|
32
|
-
out.set(a, o);
|
|
33
|
-
o += a.length;
|
|
34
|
-
}
|
|
35
|
-
return out;
|
|
36
|
-
}
|
|
37
|
-
function hexToBytes(hex) {
|
|
38
|
-
const out = new Uint8Array(hex.length / 2);
|
|
39
|
-
for (let i = 0; i < out.length; i++) out[i] = parseInt(hex.substr(i * 2, 2), 16);
|
|
40
|
-
return out;
|
|
41
|
-
}
|
|
42
|
-
function bytesToHex(b) {
|
|
43
|
-
let s = "";
|
|
44
|
-
for (let i = 0; i < b.length; i++) s += b[i].toString(16).padStart(2, "0");
|
|
45
|
-
return s;
|
|
46
|
-
}
|
|
47
|
-
async function sha256(bytes) {
|
|
48
|
-
return new Uint8Array(await subtle.digest("SHA-256", bytes));
|
|
49
|
-
}
|
|
50
|
-
async function hkdf32(ikm, salt, info) {
|
|
51
|
-
const base = await subtle.importKey("raw", ikm, "HKDF", false, ["deriveBits"]);
|
|
52
|
-
const bits = await subtle.deriveBits({
|
|
53
|
-
name: "HKDF",
|
|
54
|
-
hash: "SHA-256",
|
|
55
|
-
salt,
|
|
56
|
-
info: enc.encode(info)
|
|
57
|
-
}, base, 256);
|
|
58
|
-
return new Uint8Array(bits);
|
|
59
|
-
}
|
|
60
|
-
function validateS(s) {
|
|
61
|
-
if (typeof s !== "string" || !HEX64.test(s)) throw new Error("invalid share token");
|
|
62
|
-
return s;
|
|
63
|
-
}
|
|
64
|
-
function ikmFromS(s) {
|
|
65
|
-
return hexToBytes(validateS(s));
|
|
66
|
-
}
|
|
67
|
-
async function deriveAuthToken(s, room, sighost) {
|
|
68
|
-
const salt = await sha256(enc.encode(`${room}\n${sighost}`));
|
|
69
|
-
return bytesToHex(await hkdf32(ikmFromS(s), salt, INFO_AUTH));
|
|
70
|
-
}
|
|
71
|
-
async function importAesKey(raw) {
|
|
72
|
-
return subtle.importKey("raw", raw, { name: "AES-GCM" }, false, ["encrypt", "decrypt"]);
|
|
73
|
-
}
|
|
74
|
-
async function deriveDirKeys(s, transcriptHash) {
|
|
75
|
-
const ikm = ikmFromS(s);
|
|
76
|
-
const h2c = await hkdf32(ikm, transcriptHash, INFO_H2C);
|
|
77
|
-
const c2h = await hkdf32(ikm, transcriptHash, INFO_C2H);
|
|
78
|
-
return {
|
|
79
|
-
keyH2C: await importAesKey(h2c),
|
|
80
|
-
keyC2H: await importAesKey(c2h)
|
|
81
|
-
};
|
|
82
|
-
}
|
|
83
|
-
function allFingerprints(sdp) {
|
|
84
|
-
const out = [];
|
|
85
|
-
const re = /^a=fingerprint:(.*)$/gim;
|
|
86
|
-
let m;
|
|
87
|
-
while (m = re.exec(sdp)) out.push(m[1].trim().toLowerCase());
|
|
88
|
-
return out;
|
|
89
|
-
}
|
|
90
|
-
function firstAttr(sdp, name) {
|
|
91
|
-
const m = new RegExp(`^a=${name}:(.*)$`, "im").exec(sdp);
|
|
92
|
-
return m ? m[1].trim().toLowerCase() : "";
|
|
93
|
-
}
|
|
94
|
-
async function computeTranscriptHash(offerSdp, answerSdp) {
|
|
95
|
-
const offerFps = allFingerprints(offerSdp).sort();
|
|
96
|
-
const answerFps = allFingerprints(answerSdp).sort();
|
|
97
|
-
if (!offerFps.length || !answerFps.length) throw new Error("e2e: missing DTLS fingerprint");
|
|
98
|
-
for (const fp of offerFps.concat(answerFps)) if (!fp.startsWith("sha-256")) throw new Error("e2e: non-sha-256 DTLS fingerprint");
|
|
99
|
-
const input = `${PROTO}\noffer=${offerFps.join(",")};setup=${firstAttr(offerSdp, "setup")};ufrag=${firstAttr(offerSdp, "ice-ufrag")}\nanswer=${answerFps.join(",")};setup=${firstAttr(answerSdp, "setup")};ufrag=${firstAttr(answerSdp, "ice-ufrag")}`;
|
|
100
|
-
return await sha256(enc.encode(input));
|
|
101
|
-
}
|
|
102
|
-
function nonceFromCounter(ctr) {
|
|
103
|
-
const n = new Uint8Array(NONCE_LEN);
|
|
104
|
-
new DataView(n.buffer).setBigUint64(4, ctr, false);
|
|
105
|
-
return n;
|
|
106
|
-
}
|
|
107
|
-
async function seal(key, sendState, flags, transcriptHash, plaintext) {
|
|
108
|
-
const ctr = sendState.sendCtr;
|
|
109
|
-
if (ctr >= COUNTER_MAX) throw new Error("e2e: nonce counter overflow");
|
|
110
|
-
sendState.sendCtr = ctr + 1n;
|
|
111
|
-
const nonce = nonceFromCounter(ctr);
|
|
112
|
-
const header = new Uint8Array(HEADER_LEN);
|
|
113
|
-
header[0] = VER;
|
|
114
|
-
header[1] = flags & 255;
|
|
115
|
-
header.set(nonce, 2);
|
|
116
|
-
const aad = concatBytes(header, transcriptHash);
|
|
117
|
-
return concatBytes(header, new Uint8Array(await subtle.encrypt({
|
|
118
|
-
name: "AES-GCM",
|
|
119
|
-
iv: nonce,
|
|
120
|
-
additionalData: aad,
|
|
121
|
-
tagLength: 128
|
|
122
|
-
}, key, plaintext))).buffer;
|
|
123
|
-
}
|
|
124
|
-
async function open$1(key, frame, transcriptHash, recvState) {
|
|
125
|
-
const buf = frame instanceof Uint8Array ? frame : new Uint8Array(frame);
|
|
126
|
-
if (buf.length < HEADER_LEN + TAG_LEN) throw new Error("e2e: short frame");
|
|
127
|
-
if (buf[0] !== VER) throw new Error("e2e: bad version");
|
|
128
|
-
const header = buf.subarray(0, HEADER_LEN);
|
|
129
|
-
const nonce = buf.subarray(2, HEADER_LEN);
|
|
130
|
-
const ndv = new DataView(nonce.buffer, nonce.byteOffset, NONCE_LEN);
|
|
131
|
-
if (ndv.getUint32(0, false) !== 0) throw new Error("e2e: bad epoch");
|
|
132
|
-
const ctr = ndv.getBigUint64(4, false);
|
|
133
|
-
const sealed = buf.subarray(HEADER_LEN);
|
|
134
|
-
const aad = concatBytes(header, transcriptHash);
|
|
135
|
-
const ptBuf = await subtle.decrypt({
|
|
136
|
-
name: "AES-GCM",
|
|
137
|
-
iv: nonce,
|
|
138
|
-
additionalData: aad,
|
|
139
|
-
tagLength: 128
|
|
140
|
-
}, key, sealed);
|
|
141
|
-
if (recvState.lastSeen === -1n && ctr !== 0n) throw new Error("e2e: first frame must be counter-0");
|
|
142
|
-
if (ctr <= recvState.lastSeen) throw new Error("e2e: replay/reorder");
|
|
143
|
-
recvState.lastSeen = ctr;
|
|
144
|
-
return {
|
|
145
|
-
counter: ctr,
|
|
146
|
-
flags: header[1],
|
|
147
|
-
plaintext: new Uint8Array(ptBuf)
|
|
148
|
-
};
|
|
149
|
-
}
|
|
150
|
-
function packEnvelope(obj) {
|
|
151
|
-
return enc.encode(JSON.stringify(obj));
|
|
152
|
-
}
|
|
153
|
-
function unpackEnvelope(bytes) {
|
|
154
|
-
return JSON.parse(dec.decode(bytes));
|
|
155
|
-
}
|
|
156
|
-
function parseSecret(token) {
|
|
157
|
-
const mk = /^e(\d+)\.(.*)$/.exec(token);
|
|
158
|
-
if (mk) {
|
|
159
|
-
if (mk[1] !== String(V)) throw new Error("update required");
|
|
160
|
-
if (!HEX64.test(mk[2])) throw new Error("malformed encrypted link");
|
|
161
|
-
return {
|
|
162
|
-
s: mk[2],
|
|
163
|
-
v2: true
|
|
164
|
-
};
|
|
165
|
-
}
|
|
166
|
-
if (/^e\d/i.test(token)) throw new Error("malformed encrypted link");
|
|
167
|
-
return {
|
|
168
|
-
s: token,
|
|
169
|
-
v2: false
|
|
170
|
-
};
|
|
171
|
-
}
|
|
172
|
-
function randomHex(n) {
|
|
173
|
-
const b = new Uint8Array(n);
|
|
174
|
-
globalThis.crypto.getRandomValues(b);
|
|
175
|
-
return bytesToHex(b);
|
|
176
|
-
}
|
|
177
|
-
|
|
178
|
-
//#endregion
|
|
179
7
|
//#region ts/share.ts
|
|
180
8
|
const SUB = "ay-signal-1";
|
|
181
9
|
const DEFAULT_SIGHOST = "s.agent-yes.com";
|
|
@@ -706,4 +534,4 @@ async function startShare(opts) {
|
|
|
706
534
|
|
|
707
535
|
//#endregion
|
|
708
536
|
export { loadOrCreateShareRoom, shareLinkFromRoomUrl, startShare };
|
|
709
|
-
//# sourceMappingURL=share-
|
|
537
|
+
//# sourceMappingURL=share-ShLKJTUE.js.map
|