agent-yes 1.298.1 → 1.299.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/dist/{SUPPORTED_CLIS-AzChegaJ.js → SUPPORTED_CLIS-BIlQQJa6.js} +3 -3
- package/dist/{SUPPORTED_CLIS-sxjBFTrE.js → SUPPORTED_CLIS-Ct9reIJH.js} +2 -2
- package/dist/{agentShare-CDOvU64K.js → agentShare-uzFuaLUH.js} +4 -4
- package/dist/{callback-DBOgmPV6.js → callback-BxTZx3xJ.js} +3 -3
- package/dist/{callback-Dr5rqkUu.js → callback-DRrURxmb.js} +4 -4
- package/dist/cli.js +7 -7
- package/dist/{cmdPs-DKuMlynW.js → cmdPs-BGIWbeBM.js} +4 -4
- package/dist/index.js +2 -2
- package/dist/{notifyDaemon-Ceyhz4el.js → notifyDaemon-EEbnpoYp.js} +4 -4
- package/dist/{parentPingLoop-C0hekeg6.js → parentPingLoop-C1XXpKK7.js} +2 -2
- package/dist/remotes-BDMnvGI6.js +5 -0
- package/dist/{remotes-5P__pAXA.js → remotes-DrYe_nfw.js} +101 -18
- package/dist/{rustBinary-BW3BGZ4y.js → rustBinary--pof-MTj.js} +2 -2
- package/dist/{rustBinary-0cD4pQIE.js → rustBinary-B7rq3nuz.js} +2 -2
- package/dist/{schedule-BRC5cDkf.js → schedule-BFUe9-Mf.js} +4 -4
- package/dist/{serve-BD-7GaKa.js → serve-Q4dnZc5l.js} +40 -21
- package/dist/{setup-Dad2A_-o.js → setup-aEuGSFjB.js} +3 -3
- package/dist/shareCmd-DkITELaM.js +415 -0
- package/dist/{subcommands--9gcc0ew.js → subcommands-CUWPMI_r.js} +36 -22
- package/dist/{subcommands-ClQCwxvk.js → subcommands-CuRZt3X6.js} +3 -3
- package/dist/{systemPathLink-VV-Vm6y2.js → systemPathLink-DoyBuRQq.js} +1 -1
- package/dist/{terminal-Bam4XVWi.js → terminal-CUn1_oPd.js} +2 -2
- package/dist/{todoCli-BDttv8mk.js → todoCli-DwYlxIAY.js} +1 -1
- package/dist/{tray-DWWsVS7Y.js → tray-BcpHVeMk.js} +1 -1
- package/dist/{trayApp-DOgsH0en.js → trayApp-BHwAJFzl.js} +2 -2
- package/dist/trayApp-ucuB_j5l.js +5 -0
- package/dist/{ts-BePSXUQl.js → ts-oIxnyQbE.js} +3 -3
- package/dist/{versionChecker-D6zM6Pdv.js → versionChecker-DOgDaagD.js} +2 -2
- package/dist/{webrtcLink-CnQf9pmu.js → webrtcLink-DFRyWNMs.js} +2 -2
- package/dist/{webrtcRemote-0RGrSwqd.js → webrtcRemote-Cd4vTrgv.js} +2 -2
- package/dist/{widget-DJgiOfgE.js → widget-CuagzQwz.js} +3 -3
- package/dist/{ws-Covfyaxn.js → ws-DcJBGzQP.js} +2 -2
- package/dist/{ws-DjGQGPCq.js → ws-ID7-zDiJ.js} +4 -4
- package/lab/ui/index.html +9 -3
- package/package.json +1 -1
- package/ts/remotes.ts +128 -13
- package/ts/serve.ts +22 -0
- package/ts/shareCmd.ts +369 -0
- package/ts/shareCore.spec.ts +236 -0
- package/ts/shareCore.ts +148 -0
- package/ts/subcommands.spec.ts +19 -0
- package/ts/subcommands.ts +33 -5
- package/ts/webrtcLink.ts +3 -1
- package/dist/remotes-CY69MeQB.js +0 -5
- package/dist/trayApp-s2VuJUP4.js +0 -5
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { o as findTrayLauncher } from "./rustBinary-
|
|
1
|
+
import { o as findTrayLauncher } from "./rustBinary--pof-MTj.js";
|
|
2
2
|
import { t as agentYesHome } from "./agentYesHome-BNtn19J4.js";
|
|
3
3
|
import { existsSync } from "node:fs";
|
|
4
4
|
import path from "node:path";
|
|
@@ -97,4 +97,4 @@ async function cmdTray(args) {
|
|
|
97
97
|
|
|
98
98
|
//#endregion
|
|
99
99
|
export { trayHiddenMarker as a, launchTray as i, hasDesktop as n, isTrayHidden as r, cmdTray as t };
|
|
100
|
-
//# sourceMappingURL=trayApp-
|
|
100
|
+
//# sourceMappingURL=trayApp-BHwAJFzl.js.map
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { n as __esmMin, r as __exportAll } from "./chunk-cZBX9HZv.js";
|
|
2
2
|
import { n as logger, t as addTransport } from "./logger-CDIsZ-Pp.js";
|
|
3
|
-
import { i as getInstalledPackage } from "./versionChecker-
|
|
3
|
+
import { i as getInstalledPackage } from "./versionChecker-DOgDaagD.js";
|
|
4
4
|
import { t as agentYesHome } from "./agentYesHome-BNtn19J4.js";
|
|
5
5
|
import { u as removeControlCharacters } from "./todoAutomation-CbVVS4re.js";
|
|
6
6
|
import { i as shouldUseLock, r as releaseLock, t as acquireLock } from "./runningLock-BOIPD_Vs.js";
|
|
@@ -2086,7 +2086,7 @@ async function agentYes({ cli, cliArgs = [], skipPermissions = false, prompt, ro
|
|
|
2086
2086
|
}, 100);
|
|
2087
2087
|
const cleanupHeartbeat = () => clearInterval(heartbeatInterval);
|
|
2088
2088
|
shell.onExit(cleanupHeartbeat);
|
|
2089
|
-
const { startParentPingLoop } = await import("./parentPingLoop-
|
|
2089
|
+
const { startParentPingLoop } = await import("./parentPingLoop-C1XXpKK7.js");
|
|
2090
2090
|
const parentPingLoop = startParentPingLoop({
|
|
2091
2091
|
parentPid,
|
|
2092
2092
|
selfWrapperPid: process.pid,
|
|
@@ -2349,4 +2349,4 @@ function sleep(ms) {
|
|
|
2349
2349
|
|
|
2350
2350
|
//#endregion
|
|
2351
2351
|
export { hasTodoStore as a, permissionBadge as c, answerAsk as i, AgentContext as l, agentYes as n, listAsks as o, config as r, listAsksForProject as s, CLIS_CONFIG as t, CLAUDE_SESSION_PIN_ENV as u };
|
|
2352
|
-
//# sourceMappingURL=ts-
|
|
2352
|
+
//# sourceMappingURL=ts-oIxnyQbE.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.
|
|
10
|
+
var version = "1.299.0";
|
|
11
11
|
|
|
12
12
|
//#endregion
|
|
13
13
|
//#region ts/versionChecker.ts
|
|
@@ -285,4 +285,4 @@ async function displayVersion() {
|
|
|
285
285
|
|
|
286
286
|
//#endregion
|
|
287
287
|
export { versionString as a, getInstalledPackage as i, compareVersions as n, displayVersion as r, checkAndAutoUpdate as t };
|
|
288
|
-
//# sourceMappingURL=versionChecker-
|
|
288
|
+
//# sourceMappingURL=versionChecker-DOgDaagD.js.map
|
|
@@ -65,9 +65,9 @@ function toWebrtcUrl(link) {
|
|
|
65
65
|
}
|
|
66
66
|
/** True if `spec` looks like a WebRTC share link (vs. an http remote or alias). */
|
|
67
67
|
function isWebrtcSpec(spec) {
|
|
68
|
-
return spec.startsWith("webrtc://") ||
|
|
68
|
+
return spec.startsWith("webrtc://") || parseRaw(spec) !== null;
|
|
69
69
|
}
|
|
70
70
|
|
|
71
71
|
//#endregion
|
|
72
72
|
export { toWebrtcUrl as i, isWebrtcSpec as n, parseWebrtcLink as r, SIGNAL_SUBPROTOCOL as t };
|
|
73
|
-
//# sourceMappingURL=webrtcLink-
|
|
73
|
+
//# sourceMappingURL=webrtcLink-DFRyWNMs.js.map
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { a as computeTranscriptHash, c as open, d as randomHex, f as seal, l as packEnvelope, n as FLAG_CONFIRM, o as deriveAuthToken, p as unpackEnvelope, s as deriveDirKeys } from "./e2e-z1xpwSAg.js";
|
|
2
|
-
import { n as isWebrtcSpec, r as parseWebrtcLink, t as SIGNAL_SUBPROTOCOL } from "./webrtcLink-
|
|
2
|
+
import { n as isWebrtcSpec, r as parseWebrtcLink, t as SIGNAL_SUBPROTOCOL } from "./webrtcLink-DFRyWNMs.js";
|
|
3
3
|
import { RTCPeerConnection } from "node-datachannel/polyfill";
|
|
4
4
|
|
|
5
5
|
//#region ts/signalingHint.ts
|
|
@@ -297,4 +297,4 @@ async function startWebrtcBridge(link) {
|
|
|
297
297
|
|
|
298
298
|
//#endregion
|
|
299
299
|
export { startWebrtcBridge };
|
|
300
|
-
//# sourceMappingURL=webrtcRemote-
|
|
300
|
+
//# sourceMappingURL=webrtcRemote-Cd4vTrgv.js.map
|
|
@@ -28,7 +28,7 @@ function parseFlags(args, known) {
|
|
|
28
28
|
}
|
|
29
29
|
/** Resolve the local daemon base URL + token (flags override discovery). */
|
|
30
30
|
async function daemonTarget(flags) {
|
|
31
|
-
const { resolveDaemonHttpBase, loadTokenReadOnly } = await import("./serve-
|
|
31
|
+
const { resolveDaemonHttpBase, loadTokenReadOnly } = await import("./serve-Q4dnZc5l.js");
|
|
32
32
|
const base = typeof flags.base === "string" ? flags.base : await resolveDaemonHttpBase();
|
|
33
33
|
if (!base) throw new Error("no running ay serve daemon found — start `ay serve` or pass --base <url> (e.g. http://127.0.0.1:PORT)");
|
|
34
34
|
const token = typeof flags.token === "string" ? flags.token : await loadTokenReadOnly() ?? "";
|
|
@@ -186,7 +186,7 @@ async function cmdMint(args) {
|
|
|
186
186
|
const bad = caps.filter((c) => !KNOWN_CAPS.has(c));
|
|
187
187
|
if (bad.length) throw new Error(`unknown cap(s): ${bad.join(", ")} (valid: ${[...KNOWN_CAPS].join(", ")})`);
|
|
188
188
|
const ttlSec = parseTtlSec(typeof flags.ttl === "string" ? flags.ttl : "15m");
|
|
189
|
-
const { mintScopedTermToken } = await import("./serve-
|
|
189
|
+
const { mintScopedTermToken } = await import("./serve-Q4dnZc5l.js");
|
|
190
190
|
const r = await mintScopedTermToken(target, {
|
|
191
191
|
ttlSec,
|
|
192
192
|
caps
|
|
@@ -202,4 +202,4 @@ async function cmdMint(args) {
|
|
|
202
202
|
|
|
203
203
|
//#endregion
|
|
204
204
|
export { cmdMint, cmdWidget };
|
|
205
|
-
//# sourceMappingURL=widget-
|
|
205
|
+
//# sourceMappingURL=widget-CuagzQwz.js.map
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { F as listRecords } from "./subcommands
|
|
1
|
+
import { F as listRecords } from "./subcommands-CUWPMI_r.js";
|
|
2
2
|
import { a as getProvisionRoot } from "./workspaceConfig-DTvPtr5j.js";
|
|
3
3
|
import { existsSync } from "fs";
|
|
4
4
|
import { lstat, opendir } from "fs/promises";
|
|
@@ -424,4 +424,4 @@ async function cmdWs(args) {
|
|
|
424
424
|
|
|
425
425
|
//#endregion
|
|
426
426
|
export { isPathInside as a, walkWorkspaces as c, importProvisionModule as i, workspaceStatus as l, cmdWs as n, loadProvision as o, collectWorkspaces as r, resolveOperand as s, WS_JSON_SCHEMA as t };
|
|
427
|
-
//# sourceMappingURL=ws-
|
|
427
|
+
//# sourceMappingURL=ws-DcJBGzQP.js.map
|
|
@@ -5,10 +5,10 @@ import "./pidStore-DXWqzTSz.js";
|
|
|
5
5
|
import "./messageLog-Brx3w6zT.js";
|
|
6
6
|
import "./e2e-z1xpwSAg.js";
|
|
7
7
|
import "./configShared-DKTgiz7K.js";
|
|
8
|
-
import "./subcommands
|
|
8
|
+
import "./subcommands-CUWPMI_r.js";
|
|
9
9
|
import "./notifyStore-2SWKGwZI.js";
|
|
10
|
-
import "./webrtcLink-
|
|
11
|
-
import "./remotes-
|
|
12
|
-
import { a as isPathInside, c as walkWorkspaces, i as importProvisionModule, l as workspaceStatus, n as cmdWs, o as loadProvision, r as collectWorkspaces, s as resolveOperand, t as WS_JSON_SCHEMA } from "./ws-
|
|
10
|
+
import "./webrtcLink-DFRyWNMs.js";
|
|
11
|
+
import "./remotes-DrYe_nfw.js";
|
|
12
|
+
import { a as isPathInside, c as walkWorkspaces, i as importProvisionModule, l as workspaceStatus, n as cmdWs, o as loadProvision, r as collectWorkspaces, s as resolveOperand, t as WS_JSON_SCHEMA } from "./ws-DcJBGzQP.js";
|
|
13
13
|
|
|
14
14
|
export { WS_JSON_SCHEMA, cmdWs, collectWorkspaces, isPathInside, loadProvision, walkWorkspaces, workspaceStatus };
|
package/lab/ui/index.html
CHANGED
|
@@ -3064,11 +3064,17 @@
|
|
|
3064
3064
|
// boot() stores the token and local /api calls carry it as ?token= (query,
|
|
3065
3065
|
// not header — EventSource can't set headers). When served via the lab
|
|
3066
3066
|
// proxy instead, no token is stored and paths stay bare (proxy injects).
|
|
3067
|
+
// The page may be mounted under a sub-path by a reverse proxy that strips
|
|
3068
|
+
// it before forwarding (`tailscale serve --set-path=/ay` → console at
|
|
3069
|
+
// https://<host>.ts.net/ay/), so local calls resolve against the page's
|
|
3070
|
+
// own directory: "/ay/" → "/ay/api/…", "/" → "/api/…".
|
|
3071
|
+
const LOCAL_BASE = location.pathname.replace(/\/[^/]*$/, "");
|
|
3067
3072
|
const withTok = (path) => {
|
|
3068
3073
|
const t = localStorage.getItem("ay.localToken");
|
|
3069
|
-
return
|
|
3070
|
-
|
|
3071
|
-
: path
|
|
3074
|
+
return (
|
|
3075
|
+
LOCAL_BASE +
|
|
3076
|
+
(t ? path + (path.includes("?") ? "&" : "?") + "token=" + encodeURIComponent(t) : path)
|
|
3077
|
+
);
|
|
3072
3078
|
};
|
|
3073
3079
|
|
|
3074
3080
|
// ---- transports: a uniform { fetchJSON, post, subscribe } over each wire ----
|
package/package.json
CHANGED
package/ts/remotes.ts
CHANGED
|
@@ -80,6 +80,47 @@ export function parseDirectRemoteSpec(
|
|
|
80
80
|
};
|
|
81
81
|
}
|
|
82
82
|
|
|
83
|
+
/**
|
|
84
|
+
* Parse an http(s) share URL into {url, token}. This is the ONE link `ay share`
|
|
85
|
+
* hands out for both the web console and the CLI:
|
|
86
|
+
* https://host.ts.net/ay/#k=<token> console link (token in the fragment)
|
|
87
|
+
* http://<token>@192.168.1.5:7432 legacy userinfo form (`ay remote add`)
|
|
88
|
+
* The base keeps any path prefix (a reverse proxy mount like /ay), minus a
|
|
89
|
+
* trailing slash / index.html. Null when there's no token or it isn't http(s).
|
|
90
|
+
*
|
|
91
|
+
* Never throws: every http(s) spec reaches here through resolveRemoteSpec, so a
|
|
92
|
+
* malformed one must come back as "not a share URL", not as an exception.
|
|
93
|
+
*/
|
|
94
|
+
function decodeMaybe(s: string): string {
|
|
95
|
+
try {
|
|
96
|
+
return decodeURIComponent(s);
|
|
97
|
+
} catch {
|
|
98
|
+
return s; // not valid percent-encoding — take it literally
|
|
99
|
+
}
|
|
100
|
+
}
|
|
101
|
+
|
|
102
|
+
export function parseShareUrl(spec: string): { url: string; token: string } | null {
|
|
103
|
+
if (!/^https?:\/\//i.test(spec)) return null;
|
|
104
|
+
let u: URL;
|
|
105
|
+
try {
|
|
106
|
+
u = new URL(spec);
|
|
107
|
+
} catch {
|
|
108
|
+
return null;
|
|
109
|
+
}
|
|
110
|
+
const hash = new URLSearchParams(u.hash.replace(/^#/, ""));
|
|
111
|
+
// URLSearchParams decodes `#k=` leniently; match that for the userinfo form.
|
|
112
|
+
// `decodeURIComponent` alone THREW a URIError on a stray percent
|
|
113
|
+
// (`http://100%@host/`), which surfaced as a crash from `ay ls <url>`.
|
|
114
|
+
const token = hash.get("k") || decodeMaybe(u.username);
|
|
115
|
+
if (!token) return null;
|
|
116
|
+
u.username = "";
|
|
117
|
+
u.password = "";
|
|
118
|
+
u.hash = "";
|
|
119
|
+
u.search = "";
|
|
120
|
+
u.pathname = u.pathname.replace(/\/index\.html$/, "/").replace(/\/+$/, "");
|
|
121
|
+
return { url: u.toString().replace(/\/+$/, ""), token };
|
|
122
|
+
}
|
|
123
|
+
|
|
83
124
|
/**
|
|
84
125
|
* Resolve a spec to connection details.
|
|
85
126
|
* Accepts:
|
|
@@ -92,6 +133,10 @@ export async function resolveRemoteSpec(spec: string): Promise<ResolvedRemote |
|
|
|
92
133
|
// These carry their own secret and have no keyword (use an alias to add one).
|
|
93
134
|
if (isWebrtcSpec(spec)) return resolveWebrtc(spec, undefined, webrtcLabel(spec));
|
|
94
135
|
|
|
136
|
+
// Inline http(s) share URL: `ay ls 'https://host.ts.net/ay/#k=<token>'`.
|
|
137
|
+
const shared = parseShareUrl(spec);
|
|
138
|
+
if (shared) return { ...shared, label: new URL(shared.url).host };
|
|
139
|
+
|
|
95
140
|
const direct = parseDirectRemoteSpec(spec);
|
|
96
141
|
if (direct) {
|
|
97
142
|
return {
|
|
@@ -146,6 +191,7 @@ export async function cmdRemote(rest: string[]): Promise<number> {
|
|
|
146
191
|
` ay remote add <alias> http://<token>@<host>:<port> add an http remote\n` +
|
|
147
192
|
` ay remote add <alias> webrtc://<room>:<token>@<host> add a WebRTC share remote\n` +
|
|
148
193
|
` ay remote add <alias> https://agent-yes.com/w/#<room>:<token> (share link form)\n` +
|
|
194
|
+
` ay remote add <alias> https://<host>/ay/#k=<token> (an \`ay share\` URL)\n` +
|
|
149
195
|
` ay remote rm <alias> remove a remote\n\n` +
|
|
150
196
|
`Once added, use the alias anywhere a keyword is accepted:\n` +
|
|
151
197
|
` ay ls <alias>\n` +
|
|
@@ -189,23 +235,15 @@ export async function cmdRemote(rest: string[]): Promise<number> {
|
|
|
189
235
|
process.stderr.write(`\n ay ls ${alias} # list agents on ${alias}\n`);
|
|
190
236
|
return 0;
|
|
191
237
|
}
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
const parsed = new URL(rawUrl);
|
|
195
|
-
token = parsed.username;
|
|
196
|
-
parsed.username = "";
|
|
197
|
-
parsed.password = "";
|
|
198
|
-
url = parsed.toString().replace(/\/$/, "");
|
|
199
|
-
} catch {
|
|
200
|
-
process.stderr.write(`ay remote add: invalid URL '${rawUrl}'\n`);
|
|
201
|
-
return 1;
|
|
202
|
-
}
|
|
203
|
-
if (!token) {
|
|
238
|
+
const parsed = parseShareUrl(rawUrl);
|
|
239
|
+
if (!parsed) {
|
|
204
240
|
process.stderr.write(
|
|
205
|
-
`ay remote add: no token in
|
|
241
|
+
`ay remote add: no token in '${rawUrl}' — expected http://<token>@<host>:<port>\n` +
|
|
242
|
+
` or a share URL like https://<host>/ay/#k=<token> (from \`ay share\`)\n`,
|
|
206
243
|
);
|
|
207
244
|
return 1;
|
|
208
245
|
}
|
|
246
|
+
const { url, token } = parsed;
|
|
209
247
|
await writeRemoteAlias(alias, { url, token });
|
|
210
248
|
process.stdout.write(`remote '${alias}' added → ${url}\n`);
|
|
211
249
|
process.stderr.write(`\n ay ls ${alias} # list agents on ${alias}\n`);
|
|
@@ -236,3 +274,80 @@ export async function cmdRemote(rest: string[]): Promise<number> {
|
|
|
236
274
|
);
|
|
237
275
|
return 1;
|
|
238
276
|
}
|
|
277
|
+
|
|
278
|
+
/**
|
|
279
|
+
* Default alias for a share URL: the machine's short name. Call only on a link
|
|
280
|
+
* that already parsed (a webrtc link or `parseShareUrl` hit) — it assumes a
|
|
281
|
+
* valid URL and throws otherwise.
|
|
282
|
+
*/
|
|
283
|
+
export function defaultConnectAlias(link: string): string {
|
|
284
|
+
const w = parseWebrtcLink(link);
|
|
285
|
+
if (w) return `webrtc-${w.room.slice(0, 8)}`;
|
|
286
|
+
const host = new URL(link).hostname;
|
|
287
|
+
// box.tailnet.ts.net → box; 192.168.1.5 → 192-168-1-5
|
|
288
|
+
if (/^[\d.]+$/.test(host) || host.includes(":")) return host.replace(/[.:]/g, "-");
|
|
289
|
+
return host.split(".")[0] || host;
|
|
290
|
+
}
|
|
291
|
+
|
|
292
|
+
// ay connect <share-url> [alias] — the CLI half of `ay share`: the same URL that
|
|
293
|
+
// opens the web console is saved as a remote alias here (after a reachability
|
|
294
|
+
// check), so `ay ls <alias>` / `ay tail <alias>:<kw>` work from this machine.
|
|
295
|
+
export async function cmdConnect(rest: string[]): Promise<number> {
|
|
296
|
+
const positional = rest.filter((a) => !a.startsWith("-"));
|
|
297
|
+
const [link, aliasArg] = positional;
|
|
298
|
+
if (!link || rest.includes("-h") || rest.includes("--help")) {
|
|
299
|
+
process.stdout.write(
|
|
300
|
+
`Usage: ay connect <share-url> [alias]\n\n` +
|
|
301
|
+
`Save another machine's \`ay share\` URL as a remote, so this CLI can drive it.\n` +
|
|
302
|
+
`The same URL opens that machine's web console in a browser.\n\n` +
|
|
303
|
+
` ay connect 'https://box.tailnet.ts.net/ay/#k=<token>' # tailscale\n` +
|
|
304
|
+
` ay connect 'http://192.168.1.5:7432/#k=<token>' # lan\n` +
|
|
305
|
+
` ay connect 'https://agent-yes.com/w/#<room>:<secret>' box # webrtc\n\n` +
|
|
306
|
+
`alias defaults to the host's short name. Then:\n` +
|
|
307
|
+
` ay ls <alias> ay tail <alias>:<keyword> ay send <alias>:<keyword> "msg"\n`,
|
|
308
|
+
);
|
|
309
|
+
return link ? 0 : 1;
|
|
310
|
+
}
|
|
311
|
+
// Recognise the link BEFORE naming it: defaultConnectAlias parses it as a URL,
|
|
312
|
+
// so deriving the alias first turned a scheme-less paste
|
|
313
|
+
// (`box.ts.net/ay/#k=…`) into a bare "Invalid URL" and buried the message
|
|
314
|
+
// below, which is the one that explains the actual mistake.
|
|
315
|
+
const webrtc = isWebrtcSpec(link);
|
|
316
|
+
const parsed = webrtc ? null : parseShareUrl(link);
|
|
317
|
+
if (!webrtc && !parsed) {
|
|
318
|
+
process.stderr.write(
|
|
319
|
+
`ay connect: not a share URL: '${link}' — expected https://<host>/ay/#k=<token>\n` +
|
|
320
|
+
` (quote it: the # starts a comment in most shells)\n`,
|
|
321
|
+
);
|
|
322
|
+
return 1;
|
|
323
|
+
}
|
|
324
|
+
const alias = aliasArg ?? defaultConnectAlias(link);
|
|
325
|
+
|
|
326
|
+
if (!parsed) {
|
|
327
|
+
await writeRemoteAlias(alias, { url: link, token: "" });
|
|
328
|
+
} else {
|
|
329
|
+
try {
|
|
330
|
+
const r = await fetch(`${parsed.url}/api/version`, {
|
|
331
|
+
headers: { Authorization: `Bearer ${parsed.token}` },
|
|
332
|
+
signal: AbortSignal.timeout(5000),
|
|
333
|
+
});
|
|
334
|
+
if (r.status === 401 || r.status === 403) {
|
|
335
|
+
process.stderr.write(`ay connect: ${parsed.url} rejected the token (HTTP ${r.status})\n`);
|
|
336
|
+
return 1;
|
|
337
|
+
}
|
|
338
|
+
if (!r.ok) throw new Error(`HTTP ${r.status}`);
|
|
339
|
+
} catch (e) {
|
|
340
|
+
process.stderr.write(
|
|
341
|
+
`ay connect: warning: ${parsed.url} is not reachable right now (${(e as Error).message}) — saving anyway\n`,
|
|
342
|
+
);
|
|
343
|
+
}
|
|
344
|
+
await writeRemoteAlias(alias, parsed);
|
|
345
|
+
}
|
|
346
|
+
process.stdout.write(`connected '${alias}'\n`);
|
|
347
|
+
process.stderr.write(
|
|
348
|
+
`\n ay ls ${alias} # list its agents\n` +
|
|
349
|
+
` ay tail ${alias}:<keyword> # read one\n` +
|
|
350
|
+
` ay remote rm ${alias} # forget it\n`,
|
|
351
|
+
);
|
|
352
|
+
return 0;
|
|
353
|
+
}
|
package/ts/serve.ts
CHANGED
|
@@ -1139,6 +1139,28 @@ export async function resolveLocalServeUrl(): Promise<string | null> {
|
|
|
1139
1139
|
return port ? `http://127.0.0.1:${port}` : null;
|
|
1140
1140
|
}
|
|
1141
1141
|
|
|
1142
|
+
/**
|
|
1143
|
+
* What `ay share` needs to know about this host's daemon: the args it was
|
|
1144
|
+
* installed with (null = none installed), whether its HTTP API answers, and the token.
|
|
1145
|
+
* `port` is the loopback HTTP port (fixed --port, else the portless backend).
|
|
1146
|
+
*/
|
|
1147
|
+
export async function inspectServeDaemon(): Promise<{
|
|
1148
|
+
args: string[] | null;
|
|
1149
|
+
port: number | null;
|
|
1150
|
+
httpUp: boolean; // answers /api/version on `port` (a webrtc-only daemon never does)
|
|
1151
|
+
token: string;
|
|
1152
|
+
consoleUrl: string | null;
|
|
1153
|
+
}> {
|
|
1154
|
+
const mgr = await resolveActiveManager();
|
|
1155
|
+
const args = mgr ? await readDaemonServeArgs(mgr) : null;
|
|
1156
|
+
const token = await loadOrCreateToken(undefined);
|
|
1157
|
+
const portless = args !== null && argsUsePortless(args);
|
|
1158
|
+
const port = args === null ? null : portless ? await portlessAppPort() : portFromArgs(args);
|
|
1159
|
+
const httpUp = args !== null && (await fetchDaemonVersion(port, token)) !== null;
|
|
1160
|
+
const consoleUrl = portless ? await resolvedPortlessConsoleUrl(token) : null;
|
|
1161
|
+
return { args, port, httpUp, token, consoleUrl };
|
|
1162
|
+
}
|
|
1163
|
+
|
|
1142
1164
|
/**
|
|
1143
1165
|
* Best-effort HTTP base URL of the LOCAL running daemon, for CLI→daemon calls
|
|
1144
1166
|
* (`ay widget`). More robust than resolveLocalServeUrl for UNMANAGED daemons: it
|