@openma/cli 0.3.2 → 0.4.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/index.js +3708 -270
- package/package.json +2 -1
package/dist/index.js
CHANGED
|
@@ -47,30 +47,45 @@ function currentPlatform() {
|
|
|
47
47
|
if (p === "darwin" || p === "linux" || p === "win32") return p;
|
|
48
48
|
return "unknown";
|
|
49
49
|
}
|
|
50
|
+
function currentProfile() {
|
|
51
|
+
const raw = (process.env.OMA_PROFILE ?? "").trim();
|
|
52
|
+
if (raw === "") return "";
|
|
53
|
+
if (!PROFILE_SLUG_RE.test(raw)) {
|
|
54
|
+
throw new Error(
|
|
55
|
+
`OMA_PROFILE="${raw}" is not a valid profile slug. Expected: lowercase letters/digits/dashes, starting with letter or digit, max 32 chars.`
|
|
56
|
+
);
|
|
57
|
+
}
|
|
58
|
+
return raw;
|
|
59
|
+
}
|
|
50
60
|
function paths() {
|
|
51
61
|
const home = homedir();
|
|
52
62
|
const p = currentPlatform();
|
|
53
|
-
const
|
|
63
|
+
const profile = currentProfile();
|
|
64
|
+
const dirSuffix = profile ? `-${profile}` : "";
|
|
65
|
+
const labelSuffix = profile ? `.${profile}` : "";
|
|
66
|
+
const configDir = join(home, `.oma/bridge${dirSuffix}`);
|
|
54
67
|
const credsFile = join(configDir, "credentials.json");
|
|
55
68
|
const machineIdFile = join(configDir, "machine-id");
|
|
56
69
|
const sessionsDir = join(configDir, "sessions");
|
|
57
70
|
const logFile = join(configDir, "logs", "bridge.log");
|
|
71
|
+
const serviceLabel = `${SERVICE_LABEL_BASE}${labelSuffix}`;
|
|
58
72
|
let serviceFile = null;
|
|
59
73
|
if (p === "darwin") {
|
|
60
|
-
serviceFile = join(home, "Library", "LaunchAgents", `${
|
|
74
|
+
serviceFile = join(home, "Library", "LaunchAgents", `${serviceLabel}.plist`);
|
|
61
75
|
} else if (p === "linux") {
|
|
62
|
-
serviceFile = join(home, ".config", "systemd", "user", `${
|
|
76
|
+
serviceFile = join(home, ".config", "systemd", "user", `${serviceLabel}.service`);
|
|
63
77
|
}
|
|
64
|
-
return { configDir, credsFile, machineIdFile, sessionsDir, logFile, serviceFile, serviceLabel
|
|
78
|
+
return { configDir, credsFile, machineIdFile, sessionsDir, logFile, serviceFile, serviceLabel };
|
|
65
79
|
}
|
|
66
80
|
function osTag() {
|
|
67
81
|
return `${platform()}/${process.arch}`;
|
|
68
82
|
}
|
|
69
|
-
var
|
|
83
|
+
var PROFILE_SLUG_RE, SERVICE_LABEL_BASE;
|
|
70
84
|
var init_platform = __esm({
|
|
71
85
|
"src/bridge/lib/platform.ts"() {
|
|
72
86
|
"use strict";
|
|
73
|
-
|
|
87
|
+
PROFILE_SLUG_RE = /^[a-z0-9](?:[a-z0-9-]{0,30}[a-z0-9])?$/;
|
|
88
|
+
SERVICE_LABEL_BASE = "dev.openma.bridge";
|
|
74
89
|
}
|
|
75
90
|
});
|
|
76
91
|
|
|
@@ -94,9 +109,9 @@ async function writeCreds(creds) {
|
|
|
94
109
|
await chmod(file2, 384);
|
|
95
110
|
}
|
|
96
111
|
async function deleteCreds() {
|
|
97
|
-
const { unlink:
|
|
112
|
+
const { unlink: unlink4 } = await import("node:fs/promises");
|
|
98
113
|
try {
|
|
99
|
-
await
|
|
114
|
+
await unlink4(paths().credsFile);
|
|
100
115
|
} catch (e) {
|
|
101
116
|
if (e.code !== "ENOENT") throw e;
|
|
102
117
|
}
|
|
@@ -121,15 +136,40 @@ var init_config = __esm({
|
|
|
121
136
|
}
|
|
122
137
|
});
|
|
123
138
|
|
|
124
|
-
// src/bridge/lib/
|
|
125
|
-
import { mkdir as mkdir2, writeFile as writeFile2, unlink, readFile as readFile2 } from "node:fs/promises";
|
|
139
|
+
// src/bridge/lib/service-templates.ts
|
|
126
140
|
import { dirname as dirname2 } from "node:path";
|
|
127
|
-
|
|
141
|
+
function escapeXml(s) {
|
|
142
|
+
return s.replace(/&/g, "&").replace(/</g, "<").replace(/>/g, ">");
|
|
143
|
+
}
|
|
144
|
+
function dedupColon(p) {
|
|
145
|
+
const seen = /* @__PURE__ */ new Set();
|
|
146
|
+
return p.split(":").filter((part) => {
|
|
147
|
+
if (!part || seen.has(part)) return false;
|
|
148
|
+
seen.add(part);
|
|
149
|
+
return true;
|
|
150
|
+
}).join(":");
|
|
151
|
+
}
|
|
152
|
+
function dedupSemicolon(p) {
|
|
153
|
+
const seen = /* @__PURE__ */ new Set();
|
|
154
|
+
return p.split(";").filter((part) => {
|
|
155
|
+
if (!part || seen.has(part)) return false;
|
|
156
|
+
seen.add(part);
|
|
157
|
+
return true;
|
|
158
|
+
}).join(";");
|
|
159
|
+
}
|
|
128
160
|
function buildPlist(opts) {
|
|
129
161
|
const p = paths();
|
|
130
162
|
const nodeDir = dirname2(opts.nodePath);
|
|
131
163
|
const setupPath = process.env.PATH ?? "";
|
|
132
|
-
const envPath = opts.envPath ??
|
|
164
|
+
const envPath = opts.envPath ?? dedupColon(setupPath ? `${nodeDir}:${setupPath}` : nodeDir);
|
|
165
|
+
const profile = currentProfile();
|
|
166
|
+
const envBlock = `<key>EnvironmentVariables</key>
|
|
167
|
+
<dict>
|
|
168
|
+
<key>PATH</key>
|
|
169
|
+
<string>${escapeXml(envPath)}</string>
|
|
170
|
+
` + (profile ? ` <key>OMA_PROFILE</key>
|
|
171
|
+
<string>${escapeXml(profile)}</string>
|
|
172
|
+
` : "") + ` </dict>`;
|
|
133
173
|
return `<?xml version="1.0" encoding="UTF-8"?>
|
|
134
174
|
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
|
|
135
175
|
<plist version="1.0">
|
|
@@ -153,26 +193,63 @@ function buildPlist(opts) {
|
|
|
153
193
|
<string>${p.logFile}</string>
|
|
154
194
|
<key>StandardErrorPath</key>
|
|
155
195
|
<string>${p.logFile}</string>
|
|
156
|
-
|
|
157
|
-
<dict>
|
|
158
|
-
<key>PATH</key>
|
|
159
|
-
<string>${escapeXml(envPath)}</string>
|
|
160
|
-
</dict>
|
|
196
|
+
${envBlock}
|
|
161
197
|
</dict>
|
|
162
198
|
</plist>
|
|
163
199
|
`;
|
|
164
200
|
}
|
|
165
|
-
function
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
const
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
201
|
+
function buildUnit(opts) {
|
|
202
|
+
const p = paths();
|
|
203
|
+
const nodeDir = dirname2(opts.nodePath);
|
|
204
|
+
const setupPath = process.env.PATH ?? "";
|
|
205
|
+
const envPath = opts.envPath ?? dedupColon(setupPath ? `${nodeDir}:${setupPath}` : nodeDir);
|
|
206
|
+
const profile = currentProfile();
|
|
207
|
+
const profileLine = profile ? `
|
|
208
|
+
Environment=OMA_PROFILE=${profile}` : "";
|
|
209
|
+
return `[Unit]
|
|
210
|
+
Description=OMA Bridge Daemon
|
|
211
|
+
Documentation=https://github.com/open-ma/open-managed-agents
|
|
212
|
+
After=network-online.target
|
|
213
|
+
Wants=network-online.target
|
|
214
|
+
|
|
215
|
+
[Service]
|
|
216
|
+
Type=simple
|
|
217
|
+
ExecStart=${opts.nodePath} ${opts.cliEntry} bridge daemon
|
|
218
|
+
Restart=always
|
|
219
|
+
RestartSec=10
|
|
220
|
+
Environment=PATH=${envPath}${profileLine}
|
|
221
|
+
StandardOutput=append:${p.logFile}
|
|
222
|
+
StandardError=append:${p.logFile}
|
|
223
|
+
|
|
224
|
+
[Install]
|
|
225
|
+
WantedBy=default.target
|
|
226
|
+
`;
|
|
175
227
|
}
|
|
228
|
+
function buildShim(opts) {
|
|
229
|
+
const nodeDir = dirname2(opts.nodePath);
|
|
230
|
+
const setupPath = process.env.PATH ?? "";
|
|
231
|
+
const envPath = opts.envPath ?? dedupSemicolon(setupPath ? `${nodeDir};${setupPath}` : nodeDir);
|
|
232
|
+
const logFile = paths().logFile;
|
|
233
|
+
const profile = currentProfile();
|
|
234
|
+
const lines = [
|
|
235
|
+
"@echo off",
|
|
236
|
+
`set "PATH=${envPath}"`,
|
|
237
|
+
profile ? `set "OMA_PROFILE=${profile}"` : "",
|
|
238
|
+
`"${opts.nodePath}" "${opts.cliEntry}" bridge daemon >> "${logFile}" 2>&1`
|
|
239
|
+
].filter(Boolean);
|
|
240
|
+
return lines.join("\r\n") + "\r\n";
|
|
241
|
+
}
|
|
242
|
+
var init_service_templates = __esm({
|
|
243
|
+
"src/bridge/lib/service-templates.ts"() {
|
|
244
|
+
"use strict";
|
|
245
|
+
init_platform();
|
|
246
|
+
}
|
|
247
|
+
});
|
|
248
|
+
|
|
249
|
+
// src/bridge/lib/launchd.ts
|
|
250
|
+
import { mkdir as mkdir2, writeFile as writeFile2, unlink, readFile as readFile2 } from "node:fs/promises";
|
|
251
|
+
import { dirname as dirname3 } from "node:path";
|
|
252
|
+
import { spawn } from "node:child_process";
|
|
176
253
|
async function install(opts) {
|
|
177
254
|
if (currentPlatform() !== "darwin") {
|
|
178
255
|
throw new Error(
|
|
@@ -181,8 +258,8 @@ async function install(opts) {
|
|
|
181
258
|
}
|
|
182
259
|
const p = paths();
|
|
183
260
|
if (!p.serviceFile) throw new Error("no service file path on this platform");
|
|
184
|
-
await mkdir2(
|
|
185
|
-
await mkdir2(
|
|
261
|
+
await mkdir2(dirname3(p.logFile), { recursive: true });
|
|
262
|
+
await mkdir2(dirname3(p.serviceFile), { recursive: true });
|
|
186
263
|
await writeFile2(p.serviceFile, buildPlist(opts), "utf-8");
|
|
187
264
|
await runLaunchctl(["unload", p.serviceFile]).catch(() => void 0);
|
|
188
265
|
await runLaunchctl(["load", "-w", p.serviceFile]);
|
|
@@ -232,83 +309,628 @@ var init_launchd = __esm({
|
|
|
232
309
|
"src/bridge/lib/launchd.ts"() {
|
|
233
310
|
"use strict";
|
|
234
311
|
init_platform();
|
|
312
|
+
init_service_templates();
|
|
235
313
|
}
|
|
236
314
|
});
|
|
237
315
|
|
|
238
|
-
//
|
|
316
|
+
// src/bridge/lib/systemd.ts
|
|
317
|
+
import { mkdir as mkdir3, writeFile as writeFile3, unlink as unlink2, readFile as readFile3 } from "node:fs/promises";
|
|
318
|
+
import { dirname as dirname4 } from "node:path";
|
|
239
319
|
import { spawn as spawn2 } from "node:child_process";
|
|
240
|
-
async function
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
|
|
320
|
+
async function install2(opts) {
|
|
321
|
+
if (currentPlatform() !== "linux") {
|
|
322
|
+
throw new Error(
|
|
323
|
+
`systemd install only supported on Linux. Run \`oma bridge daemon\` in foreground or use the platform's service mechanism.`
|
|
324
|
+
);
|
|
325
|
+
}
|
|
326
|
+
const p = paths();
|
|
327
|
+
if (!p.serviceFile) throw new Error("no service file path on this platform");
|
|
328
|
+
await mkdir3(dirname4(p.logFile), { recursive: true });
|
|
329
|
+
await mkdir3(dirname4(p.serviceFile), { recursive: true });
|
|
330
|
+
await writeFile3(p.serviceFile, buildUnit(opts), "utf-8");
|
|
331
|
+
let warning;
|
|
332
|
+
let started = true;
|
|
333
|
+
try {
|
|
334
|
+
await runSystemctl(["--user", "daemon-reload"]);
|
|
335
|
+
await runSystemctl(["--user", "enable", "--now", `${p.serviceLabel}.service`]);
|
|
336
|
+
} catch (e) {
|
|
337
|
+
started = false;
|
|
338
|
+
warning = e.message;
|
|
339
|
+
}
|
|
340
|
+
const lingerEnabled = await isLingerEnabled().catch(() => false);
|
|
341
|
+
return { started, lingerEnabled, warning };
|
|
244
342
|
}
|
|
245
|
-
function
|
|
343
|
+
async function uninstall2() {
|
|
344
|
+
if (currentPlatform() !== "linux") return { removed: false };
|
|
345
|
+
const p = paths();
|
|
346
|
+
if (!p.serviceFile) return { removed: false };
|
|
347
|
+
let warning;
|
|
348
|
+
await runSystemctl(["--user", "disable", "--now", `${p.serviceLabel}.service`]).catch((e) => {
|
|
349
|
+
warning = e.message;
|
|
350
|
+
});
|
|
351
|
+
try {
|
|
352
|
+
await unlink2(p.serviceFile);
|
|
353
|
+
await runSystemctl(["--user", "daemon-reload"]).catch(() => void 0);
|
|
354
|
+
return { removed: true, warning };
|
|
355
|
+
} catch (e) {
|
|
356
|
+
if (e.code === "ENOENT") return { removed: false };
|
|
357
|
+
throw e;
|
|
358
|
+
}
|
|
359
|
+
}
|
|
360
|
+
function runSystemctl(args) {
|
|
361
|
+
return new Promise((resolve, reject) => {
|
|
362
|
+
const p = spawn2("systemctl", args, { stdio: ["ignore", "pipe", "pipe"] });
|
|
363
|
+
let stderr = "";
|
|
364
|
+
p.stderr.on("data", (chunk) => stderr += chunk.toString());
|
|
365
|
+
p.once("error", (e) => reject(new Error(`systemctl spawn failed: ${e.message}`)));
|
|
366
|
+
p.once("exit", (code) => {
|
|
367
|
+
if (code === 0) resolve();
|
|
368
|
+
else reject(new Error(`systemctl ${args.join(" ")} exited ${code}: ${stderr.trim()}`));
|
|
369
|
+
});
|
|
370
|
+
});
|
|
371
|
+
}
|
|
372
|
+
async function isLingerEnabled() {
|
|
373
|
+
const user = process.env.USER ?? process.env.LOGNAME ?? "";
|
|
374
|
+
if (!user) return false;
|
|
246
375
|
return new Promise((resolve) => {
|
|
247
|
-
const
|
|
248
|
-
|
|
376
|
+
const p = spawn2("loginctl", ["show-user", user, "--property=Linger", "--value"], {
|
|
377
|
+
stdio: ["ignore", "pipe", "pipe"]
|
|
378
|
+
});
|
|
379
|
+
let out = "";
|
|
380
|
+
p.stdout.on("data", (c3) => out += c3.toString());
|
|
249
381
|
p.once("error", () => resolve(false));
|
|
250
|
-
p.once("exit", (
|
|
382
|
+
p.once("exit", () => resolve(out.trim().toLowerCase() === "yes"));
|
|
251
383
|
});
|
|
252
384
|
}
|
|
253
|
-
|
|
254
|
-
const
|
|
255
|
-
return
|
|
385
|
+
function lingerHint() {
|
|
386
|
+
const user = process.env.USER ?? process.env.LOGNAME ?? "$USER";
|
|
387
|
+
return `sudo loginctl enable-linger ${user} # so daemon survives logout`;
|
|
256
388
|
}
|
|
257
|
-
|
|
258
|
-
|
|
259
|
-
|
|
389
|
+
async function readInstalledCliEntry2() {
|
|
390
|
+
const p = paths();
|
|
391
|
+
if (!p.serviceFile) return null;
|
|
392
|
+
let unit;
|
|
393
|
+
try {
|
|
394
|
+
unit = await readFile3(p.serviceFile, "utf-8");
|
|
395
|
+
} catch {
|
|
396
|
+
return null;
|
|
397
|
+
}
|
|
398
|
+
const m = unit.match(/^ExecStart=([^\s]+)\s+([^\s]+)\s+bridge\s+daemon\s*$/m);
|
|
399
|
+
return m?.[2] ?? null;
|
|
400
|
+
}
|
|
401
|
+
var init_systemd = __esm({
|
|
402
|
+
"src/bridge/lib/systemd.ts"() {
|
|
403
|
+
"use strict";
|
|
404
|
+
init_platform();
|
|
405
|
+
init_service_templates();
|
|
406
|
+
}
|
|
407
|
+
});
|
|
408
|
+
|
|
409
|
+
// src/bridge/lib/windows-task.ts
|
|
410
|
+
import { mkdir as mkdir4, writeFile as writeFile4, unlink as unlink3, readFile as readFile4 } from "node:fs/promises";
|
|
411
|
+
import { dirname as dirname5, join as join2 } from "node:path";
|
|
412
|
+
import { spawn as spawn3 } from "node:child_process";
|
|
413
|
+
function shimPath() {
|
|
414
|
+
return join2(paths().configDir, "daemon.cmd");
|
|
415
|
+
}
|
|
416
|
+
async function install3(opts) {
|
|
417
|
+
if (currentPlatform() !== "win32") {
|
|
418
|
+
throw new Error(`Windows Task Scheduler install only supported on Windows.`);
|
|
419
|
+
}
|
|
420
|
+
const p = paths();
|
|
421
|
+
await mkdir4(dirname5(p.logFile), { recursive: true });
|
|
422
|
+
await mkdir4(p.configDir, { recursive: true });
|
|
423
|
+
const shim = shimPath();
|
|
424
|
+
await writeFile4(shim, buildShim(opts), "utf-8");
|
|
425
|
+
const taskName = p.serviceLabel;
|
|
426
|
+
const args = [
|
|
427
|
+
"/create",
|
|
428
|
+
"/tn",
|
|
429
|
+
taskName,
|
|
430
|
+
"/tr",
|
|
431
|
+
`"${shim}"`,
|
|
432
|
+
"/sc",
|
|
433
|
+
"onlogon",
|
|
434
|
+
"/it",
|
|
435
|
+
"/rl",
|
|
436
|
+
"limited",
|
|
437
|
+
"/f"
|
|
438
|
+
];
|
|
439
|
+
let warning;
|
|
440
|
+
try {
|
|
441
|
+
await runSchtasks(args);
|
|
442
|
+
} catch (e) {
|
|
443
|
+
return { registered: false, startedNow: false, shimPath: shim, warning: e.message };
|
|
444
|
+
}
|
|
445
|
+
let startedNow = true;
|
|
446
|
+
try {
|
|
447
|
+
await runSchtasks(["/run", "/tn", taskName]);
|
|
448
|
+
} catch (e) {
|
|
449
|
+
startedNow = false;
|
|
450
|
+
warning = e.message;
|
|
451
|
+
}
|
|
452
|
+
return { registered: true, startedNow, shimPath: shim, warning };
|
|
453
|
+
}
|
|
454
|
+
async function uninstall3() {
|
|
455
|
+
if (currentPlatform() !== "win32") return { removed: false };
|
|
456
|
+
const p = paths();
|
|
457
|
+
const taskName = p.serviceLabel;
|
|
458
|
+
let warning;
|
|
459
|
+
await runSchtasks(["/end", "/tn", taskName]).catch(() => void 0);
|
|
460
|
+
let removed = false;
|
|
461
|
+
try {
|
|
462
|
+
await runSchtasks(["/delete", "/tn", taskName, "/f"]);
|
|
463
|
+
removed = true;
|
|
464
|
+
} catch (e) {
|
|
465
|
+
warning = e.message;
|
|
466
|
+
}
|
|
467
|
+
try {
|
|
468
|
+
await unlink3(shimPath());
|
|
469
|
+
} catch {
|
|
470
|
+
}
|
|
471
|
+
return { removed, warning };
|
|
472
|
+
}
|
|
473
|
+
function runSchtasks(args) {
|
|
474
|
+
return new Promise((resolve, reject) => {
|
|
475
|
+
const p = spawn3("schtasks.exe", args, { stdio: ["ignore", "pipe", "pipe"] });
|
|
476
|
+
let stderr = "";
|
|
477
|
+
let stdout = "";
|
|
478
|
+
p.stdout.on("data", (c3) => stdout += c3.toString());
|
|
479
|
+
p.stderr.on("data", (c3) => stderr += c3.toString());
|
|
480
|
+
p.once("error", (e) => reject(new Error(`schtasks spawn failed: ${e.message}`)));
|
|
481
|
+
p.once("exit", (code) => {
|
|
482
|
+
if (code === 0) resolve();
|
|
483
|
+
else reject(new Error(`schtasks ${args.join(" ")} exited ${code}: ${(stderr || stdout).trim()}`));
|
|
484
|
+
});
|
|
485
|
+
});
|
|
486
|
+
}
|
|
487
|
+
async function readInstalledCliEntry3() {
|
|
488
|
+
let shim;
|
|
489
|
+
try {
|
|
490
|
+
shim = await readFile4(shimPath(), "utf-8");
|
|
491
|
+
} catch {
|
|
492
|
+
return null;
|
|
493
|
+
}
|
|
494
|
+
const m = shim.match(/^"([^"]+)"\s+"([^"]+)"\s+bridge\s+daemon/m);
|
|
495
|
+
return m?.[2] ?? null;
|
|
496
|
+
}
|
|
497
|
+
var init_windows_task = __esm({
|
|
498
|
+
"src/bridge/lib/windows-task.ts"() {
|
|
499
|
+
"use strict";
|
|
500
|
+
init_platform();
|
|
501
|
+
init_service_templates();
|
|
502
|
+
}
|
|
503
|
+
});
|
|
504
|
+
|
|
505
|
+
// src/bridge/lib/service-manager.ts
|
|
506
|
+
function detectServiceKind() {
|
|
507
|
+
switch (currentPlatform()) {
|
|
508
|
+
case "darwin":
|
|
509
|
+
return "launchd";
|
|
510
|
+
case "linux":
|
|
511
|
+
return "systemd";
|
|
512
|
+
case "win32":
|
|
513
|
+
return "windows-task";
|
|
514
|
+
default:
|
|
515
|
+
return "unsupported";
|
|
516
|
+
}
|
|
517
|
+
}
|
|
518
|
+
async function install4(opts) {
|
|
519
|
+
const kind = detectServiceKind();
|
|
520
|
+
if (kind === "launchd") {
|
|
521
|
+
await install(opts);
|
|
522
|
+
return {
|
|
523
|
+
kind,
|
|
524
|
+
installedAt: paths().serviceFile,
|
|
525
|
+
started: true,
|
|
526
|
+
// launchctl load -w starts immediately
|
|
527
|
+
lingerEnabled: true
|
|
528
|
+
// n/a on macOS
|
|
529
|
+
};
|
|
530
|
+
}
|
|
531
|
+
if (kind === "systemd") {
|
|
532
|
+
const r = await install2(opts);
|
|
533
|
+
return {
|
|
534
|
+
kind,
|
|
535
|
+
installedAt: paths().serviceFile,
|
|
536
|
+
started: r.started,
|
|
537
|
+
warning: r.warning,
|
|
538
|
+
lingerEnabled: r.lingerEnabled
|
|
539
|
+
};
|
|
540
|
+
}
|
|
541
|
+
if (kind === "windows-task") {
|
|
542
|
+
const r = await install3(opts);
|
|
543
|
+
return {
|
|
544
|
+
kind,
|
|
545
|
+
installedAt: r.shimPath,
|
|
546
|
+
started: r.startedNow,
|
|
547
|
+
warning: r.warning,
|
|
548
|
+
lingerEnabled: true
|
|
549
|
+
// n/a on windows
|
|
550
|
+
};
|
|
551
|
+
}
|
|
552
|
+
return { kind, installedAt: null, started: false, lingerEnabled: true };
|
|
553
|
+
}
|
|
554
|
+
async function uninstall4() {
|
|
555
|
+
const kind = detectServiceKind();
|
|
556
|
+
if (kind === "launchd") {
|
|
557
|
+
const r = await uninstall();
|
|
558
|
+
return { kind, removed: r.removed };
|
|
559
|
+
}
|
|
560
|
+
if (kind === "systemd") {
|
|
561
|
+
const r = await uninstall2();
|
|
562
|
+
return { kind, removed: r.removed, warning: r.warning };
|
|
563
|
+
}
|
|
564
|
+
if (kind === "windows-task") {
|
|
565
|
+
const r = await uninstall3();
|
|
566
|
+
return { kind, removed: r.removed, warning: r.warning };
|
|
567
|
+
}
|
|
568
|
+
return { kind, removed: false };
|
|
569
|
+
}
|
|
570
|
+
async function readInstalledCliEntry4() {
|
|
571
|
+
const kind = detectServiceKind();
|
|
572
|
+
if (kind === "launchd") return readInstalledCliEntry();
|
|
573
|
+
if (kind === "systemd") return readInstalledCliEntry2();
|
|
574
|
+
if (kind === "windows-task") return readInstalledCliEntry3();
|
|
575
|
+
return null;
|
|
576
|
+
}
|
|
577
|
+
function lingerHint2() {
|
|
578
|
+
return detectServiceKind() === "systemd" ? lingerHint() : "";
|
|
579
|
+
}
|
|
580
|
+
var init_service_manager = __esm({
|
|
581
|
+
"src/bridge/lib/service-manager.ts"() {
|
|
582
|
+
"use strict";
|
|
583
|
+
init_platform();
|
|
584
|
+
init_launchd();
|
|
585
|
+
init_systemd();
|
|
586
|
+
init_windows_task();
|
|
587
|
+
}
|
|
588
|
+
});
|
|
589
|
+
|
|
590
|
+
// ../acp-runtime/src/known-agents.ts
|
|
591
|
+
var OMA_OVERLAY_AGENTS;
|
|
592
|
+
var init_known_agents = __esm({
|
|
593
|
+
"../acp-runtime/src/known-agents.ts"() {
|
|
260
594
|
"use strict";
|
|
261
|
-
|
|
595
|
+
OMA_OVERLAY_AGENTS = [
|
|
596
|
+
// claude-acp: ACP wrapper around the user's `claude` binary. setup
|
|
597
|
+
// and `bridge agents refresh` offer y/N install via npm. spec uses
|
|
598
|
+
// the bare binary (faster spawn than `npx -y` per turn); install
|
|
599
|
+
// tells the audit how to get the binary onto PATH.
|
|
262
600
|
{
|
|
263
|
-
id: "claude-
|
|
264
|
-
label: "Claude
|
|
601
|
+
id: "claude-acp",
|
|
602
|
+
label: "Claude Agent",
|
|
265
603
|
spec: { command: "claude-agent-acp" },
|
|
604
|
+
aliases: ["claude-agent-acp", "claude-code-acp"],
|
|
605
|
+
featured: true,
|
|
606
|
+
wraps: "claude",
|
|
607
|
+
install: { kind: "npm", package: "@agentclientprotocol/claude-agent-acp" },
|
|
266
608
|
installHint: "npm install -g @agentclientprotocol/claude-agent-acp",
|
|
267
609
|
homepage: "https://github.com/agentclientprotocol/claude-agent-acp"
|
|
268
610
|
},
|
|
611
|
+
// codex-acp: ACP wrapper around the user's `codex` binary. Zed
|
|
612
|
+
// Industries' Rust binary; distributed as GitHub release tarballs +
|
|
613
|
+
// an npm mirror. We leave `install` unset here so mergeOverlay picks
|
|
614
|
+
// up the per-platform archives from the live registry — keeps overlay
|
|
615
|
+
// a single source of truth (no version-pinned URLs to bit-rot).
|
|
269
616
|
{
|
|
270
|
-
id: "codex-
|
|
617
|
+
id: "codex-acp",
|
|
271
618
|
label: "Codex CLI",
|
|
272
|
-
spec: { command: "codex
|
|
273
|
-
|
|
274
|
-
|
|
619
|
+
spec: { command: "codex-acp" },
|
|
620
|
+
aliases: ["codex-cli", "codex-acp-bridge"],
|
|
621
|
+
featured: true,
|
|
622
|
+
wraps: "codex",
|
|
623
|
+
installHint: "download from https://github.com/zed-industries/codex-acp/releases and place on PATH",
|
|
624
|
+
homepage: "https://github.com/zed-industries/codex-acp"
|
|
275
625
|
},
|
|
626
|
+
// gemini: official id is `gemini`. Pre-registry OMA had `gemini-cli`.
|
|
276
627
|
{
|
|
277
|
-
id: "gemini
|
|
628
|
+
id: "gemini",
|
|
278
629
|
label: "Gemini CLI",
|
|
279
|
-
spec: { command: "gemini", args: ["--
|
|
630
|
+
spec: { command: "gemini", args: ["--acp"] },
|
|
631
|
+
aliases: ["gemini-cli"],
|
|
280
632
|
installHint: "npm install -g @google/gemini-cli",
|
|
281
633
|
homepage: "https://github.com/google-gemini/gemini-cli"
|
|
282
634
|
},
|
|
635
|
+
// opencode: official id matches ours, no alias needed. Listed here
|
|
636
|
+
// anyway so the Console (overlay-only) still sees it without needing
|
|
637
|
+
// a CDN fetch.
|
|
283
638
|
{
|
|
284
639
|
id: "opencode",
|
|
285
640
|
label: "OpenCode",
|
|
286
641
|
spec: { command: "opencode", args: ["acp"] },
|
|
287
|
-
installHint: "
|
|
642
|
+
installHint: "npm install -g opencode-ai@latest # or curl -fsSL https://opencode.ai/install | bash",
|
|
288
643
|
homepage: "https://opencode.ai/"
|
|
289
644
|
},
|
|
645
|
+
// hermes: NOT in official registry. Python-packaged; the official
|
|
646
|
+
// installer downloads + sets up the global `hermes` binary. We ship a
|
|
647
|
+
// full entry so it appears in install hints even though the registry
|
|
648
|
+
// doesn't know about it.
|
|
290
649
|
{
|
|
291
650
|
id: "hermes",
|
|
292
651
|
label: "Hermes (Nous Research)",
|
|
293
652
|
spec: { command: "hermes", args: ["acp"] },
|
|
294
|
-
|
|
653
|
+
featured: true,
|
|
654
|
+
installHint: "curl -fsSL https://raw.githubusercontent.com/NousResearch/hermes-agent/main/scripts/install.sh | bash",
|
|
295
655
|
homepage: "https://github.com/NousResearch/hermes-agent"
|
|
296
656
|
},
|
|
657
|
+
// openclaw: NOT in official registry. The `openclaw` cli's `acp`
|
|
658
|
+
// subcommand exposes an ACP bridge that forwards to the OpenClaw
|
|
659
|
+
// Gateway. Distinct from `acpx` (an ACP CLIENT, same GH org).
|
|
297
660
|
{
|
|
298
|
-
// Meta-CLI from openclaw that can wrap many non-native-ACP agents
|
|
299
|
-
// (openclaw, cursor, pi, kiro, qwen). We ship one entry pointing at
|
|
300
|
-
// openclaw because that's the most-asked-for; users can always pass
|
|
301
|
-
// their own AgentSpec to wrap a different one.
|
|
302
661
|
id: "openclaw",
|
|
303
|
-
label: "OpenClaw
|
|
304
|
-
spec: { command: "
|
|
305
|
-
|
|
306
|
-
|
|
662
|
+
label: "OpenClaw",
|
|
663
|
+
spec: { command: "openclaw", args: ["acp"] },
|
|
664
|
+
featured: true,
|
|
665
|
+
installHint: "npm install -g openclaw",
|
|
666
|
+
homepage: "https://github.com/openclaw/openclaw"
|
|
307
667
|
}
|
|
308
668
|
];
|
|
309
669
|
}
|
|
310
670
|
});
|
|
311
671
|
|
|
672
|
+
// ../acp-runtime/src/registry-fetch.ts
|
|
673
|
+
import { readFile as readFile5, writeFile as writeFile5, mkdir as mkdir5 } from "node:fs/promises";
|
|
674
|
+
import { dirname as dirname6 } from "node:path";
|
|
675
|
+
async function fetchOfficialRegistry(opts) {
|
|
676
|
+
const ttl = opts?.ttlMs ?? DEFAULT_TTL_MS;
|
|
677
|
+
const cachePath = opts?.cachePath;
|
|
678
|
+
if (cachePath) {
|
|
679
|
+
const cached2 = await readCache(cachePath);
|
|
680
|
+
if (cached2 && Date.now() - cached2.fetchedAt < ttl) {
|
|
681
|
+
return cached2.data;
|
|
682
|
+
}
|
|
683
|
+
if (cached2 && opts?.cacheOnly) return cached2.data;
|
|
684
|
+
}
|
|
685
|
+
if (opts?.cacheOnly) {
|
|
686
|
+
throw new Error("registry cacheOnly=true but no cache exists");
|
|
687
|
+
}
|
|
688
|
+
const controller = new AbortController();
|
|
689
|
+
const timer = setTimeout(() => controller.abort(), 5e3);
|
|
690
|
+
try {
|
|
691
|
+
const res = await fetch(REGISTRY_URL, { signal: controller.signal });
|
|
692
|
+
if (!res.ok) throw new Error(`registry fetch HTTP ${res.status}`);
|
|
693
|
+
const data = await res.json();
|
|
694
|
+
if (!Array.isArray(data?.agents)) {
|
|
695
|
+
throw new Error("registry JSON malformed (no .agents array)");
|
|
696
|
+
}
|
|
697
|
+
if (cachePath) {
|
|
698
|
+
await writeCache(cachePath, { fetchedAt: Date.now(), data }).catch(() => {
|
|
699
|
+
});
|
|
700
|
+
}
|
|
701
|
+
return data;
|
|
702
|
+
} catch (e) {
|
|
703
|
+
if (cachePath) {
|
|
704
|
+
const stale = await readCache(cachePath);
|
|
705
|
+
if (stale) return stale.data;
|
|
706
|
+
}
|
|
707
|
+
throw e;
|
|
708
|
+
} finally {
|
|
709
|
+
clearTimeout(timer);
|
|
710
|
+
}
|
|
711
|
+
}
|
|
712
|
+
async function readCache(path2) {
|
|
713
|
+
try {
|
|
714
|
+
const text = await readFile5(path2, "utf-8");
|
|
715
|
+
const obj = JSON.parse(text);
|
|
716
|
+
if (typeof obj?.fetchedAt !== "number" || !Array.isArray(obj?.data?.agents)) return null;
|
|
717
|
+
return obj;
|
|
718
|
+
} catch {
|
|
719
|
+
return null;
|
|
720
|
+
}
|
|
721
|
+
}
|
|
722
|
+
async function writeCache(path2, c3) {
|
|
723
|
+
await mkdir5(dirname6(path2), { recursive: true });
|
|
724
|
+
await writeFile5(path2, JSON.stringify(c3, null, 2), "utf-8");
|
|
725
|
+
}
|
|
726
|
+
function mapOfficialAgent(o) {
|
|
727
|
+
const platformKey2 = `${process.platform === "win32" ? "windows" : process.platform}-${process.arch === "arm64" ? "aarch64" : process.arch === "x64" ? "x86_64" : process.arch}`;
|
|
728
|
+
let spec = null;
|
|
729
|
+
let installHint;
|
|
730
|
+
let install5;
|
|
731
|
+
if (o.distribution.binary?.[platformKey2]) {
|
|
732
|
+
const b = o.distribution.binary[platformKey2];
|
|
733
|
+
const command = b.cmd.replace(/^\.\//, "").replace(/\.exe$/, "");
|
|
734
|
+
spec = { command, args: b.args };
|
|
735
|
+
installHint = `download ${b.archive} and place \`${command}\` on PATH`;
|
|
736
|
+
const archives = {};
|
|
737
|
+
for (const [k, v] of Object.entries(o.distribution.binary)) {
|
|
738
|
+
archives[k] = { url: v.archive, cmd: v.cmd };
|
|
739
|
+
}
|
|
740
|
+
install5 = { kind: "binary", archives, downloadUrl: o.repository };
|
|
741
|
+
} else if (o.distribution.npx) {
|
|
742
|
+
const n = o.distribution.npx;
|
|
743
|
+
spec = { command: "npx", args: ["-y", n.package, ...n.args ?? []], env: n.env };
|
|
744
|
+
installHint = `npx -y ${n.package}` + (n.args ? " " + n.args.join(" ") : "");
|
|
745
|
+
const lastAt = n.package.lastIndexOf("@");
|
|
746
|
+
const pkgName = lastAt > 0 ? n.package.slice(0, lastAt) : n.package;
|
|
747
|
+
install5 = { kind: "npm", package: pkgName };
|
|
748
|
+
} else if (o.distribution.uvx) {
|
|
749
|
+
const u = o.distribution.uvx;
|
|
750
|
+
spec = { command: "uvx", args: [u.package, ...u.args ?? []], env: u.env };
|
|
751
|
+
installHint = `uvx ${u.package}` + (u.args ? " " + u.args.join(" ") : "");
|
|
752
|
+
}
|
|
753
|
+
if (!spec) return null;
|
|
754
|
+
return {
|
|
755
|
+
id: o.id,
|
|
756
|
+
label: o.name,
|
|
757
|
+
spec,
|
|
758
|
+
installHint,
|
|
759
|
+
install: install5,
|
|
760
|
+
homepage: o.website ?? o.repository
|
|
761
|
+
};
|
|
762
|
+
}
|
|
763
|
+
var REGISTRY_URL, DEFAULT_TTL_MS;
|
|
764
|
+
var init_registry_fetch = __esm({
|
|
765
|
+
"../acp-runtime/src/registry-fetch.ts"() {
|
|
766
|
+
"use strict";
|
|
767
|
+
REGISTRY_URL = "https://cdn.agentclientprotocol.com/registry/v1/latest/registry.json";
|
|
768
|
+
DEFAULT_TTL_MS = 60 * 60 * 1e3;
|
|
769
|
+
}
|
|
770
|
+
});
|
|
771
|
+
|
|
772
|
+
// ../acp-runtime/src/registry.ts
|
|
773
|
+
import { spawn as spawn4, spawnSync } from "node:child_process";
|
|
774
|
+
async function loadRegistry(opts) {
|
|
775
|
+
if (_mergedCache && !opts?.forceRefresh) return _mergedCache;
|
|
776
|
+
let officialMapped = [];
|
|
777
|
+
try {
|
|
778
|
+
const reg = await fetchOfficialRegistry({ cachePath: opts?.cachePath, ttlMs: opts?.ttlMs });
|
|
779
|
+
for (const o of reg.agents) {
|
|
780
|
+
const m = mapOfficialAgent(o);
|
|
781
|
+
if (m) officialMapped.push(m);
|
|
782
|
+
}
|
|
783
|
+
} catch (e) {
|
|
784
|
+
process.stderr.write(
|
|
785
|
+
`! ACP registry fetch failed (${e.message}); using OMA overlay only
|
|
786
|
+
`
|
|
787
|
+
);
|
|
788
|
+
officialMapped = [];
|
|
789
|
+
}
|
|
790
|
+
_mergedCache = mergeOverlay(officialMapped, OMA_OVERLAY_AGENTS);
|
|
791
|
+
_npmGlobalCache = snapshotNpmGlobal();
|
|
792
|
+
_uvToolCache = snapshotUvTool();
|
|
793
|
+
return _mergedCache;
|
|
794
|
+
}
|
|
795
|
+
function getKnownAgents() {
|
|
796
|
+
return _mergedCache ?? OMA_OVERLAY_AGENTS;
|
|
797
|
+
}
|
|
798
|
+
function resolveKnownAgent(id) {
|
|
799
|
+
const list = getKnownAgents();
|
|
800
|
+
for (const e of list) {
|
|
801
|
+
if (e.id === id) return e;
|
|
802
|
+
if (e.aliases?.includes(id)) return e;
|
|
803
|
+
}
|
|
804
|
+
return null;
|
|
805
|
+
}
|
|
806
|
+
function mergeOverlay(official, overlay) {
|
|
807
|
+
const overlayById = new Map(overlay.map((e) => [e.id, e]));
|
|
808
|
+
const seenOverlay = /* @__PURE__ */ new Set();
|
|
809
|
+
const merged = [];
|
|
810
|
+
for (const o of official) {
|
|
811
|
+
const ov = overlayById.get(o.id);
|
|
812
|
+
if (ov) {
|
|
813
|
+
seenOverlay.add(o.id);
|
|
814
|
+
merged.push({
|
|
815
|
+
id: o.id,
|
|
816
|
+
label: ov.label || o.label,
|
|
817
|
+
spec: ov.spec,
|
|
818
|
+
// overlay wins — usually carries our preferred binary
|
|
819
|
+
installHint: ov.installHint || o.installHint,
|
|
820
|
+
homepage: ov.homepage || o.homepage,
|
|
821
|
+
aliases: ov.aliases,
|
|
822
|
+
featured: ov.featured,
|
|
823
|
+
wraps: ov.wraps,
|
|
824
|
+
// Overlay's install wins when set (lets us pin a specific
|
|
825
|
+
// package). When unset, fall back to whatever mapOfficialAgent
|
|
826
|
+
// derived from the live registry — that's how codex-acp picks
|
|
827
|
+
// up its per-platform archives without overlay duplicating
|
|
828
|
+
// version-pinned URLs that bit-rot.
|
|
829
|
+
install: ov.install ?? o.install
|
|
830
|
+
});
|
|
831
|
+
} else {
|
|
832
|
+
merged.push(o);
|
|
833
|
+
}
|
|
834
|
+
}
|
|
835
|
+
for (const ov of overlay) {
|
|
836
|
+
if (!seenOverlay.has(ov.id)) merged.push(ov);
|
|
837
|
+
}
|
|
838
|
+
return merged;
|
|
839
|
+
}
|
|
840
|
+
async function detect(id) {
|
|
841
|
+
const entry = resolveKnownAgent(id);
|
|
842
|
+
if (!entry) return null;
|
|
843
|
+
if (!await isOnPath(entry.spec.command)) return null;
|
|
844
|
+
if (entry.spec.command === "npx" && !isNpxPackageInstalled(entry)) return null;
|
|
845
|
+
if (entry.spec.command === "uvx" && !isUvxPackageInstalled(entry)) return null;
|
|
846
|
+
return entry;
|
|
847
|
+
}
|
|
848
|
+
function isNpxPackageInstalled(entry) {
|
|
849
|
+
const pkgSpec = entry.spec.args?.[1];
|
|
850
|
+
if (!pkgSpec) return false;
|
|
851
|
+
const lastAt = pkgSpec.lastIndexOf("@");
|
|
852
|
+
const pkgName = lastAt > 0 ? pkgSpec.slice(0, lastAt) : pkgSpec;
|
|
853
|
+
const cache = _npmGlobalCache ?? (_npmGlobalCache = snapshotNpmGlobal());
|
|
854
|
+
return cache.has(pkgName);
|
|
855
|
+
}
|
|
856
|
+
function isUvxPackageInstalled(entry) {
|
|
857
|
+
const pkgSpec = entry.spec.args?.[0];
|
|
858
|
+
if (!pkgSpec) return false;
|
|
859
|
+
let pkgName = pkgSpec;
|
|
860
|
+
for (const sep of ["==", "@"]) {
|
|
861
|
+
const idx = pkgName.indexOf(sep, 1);
|
|
862
|
+
if (idx > 0) {
|
|
863
|
+
pkgName = pkgName.slice(0, idx);
|
|
864
|
+
break;
|
|
865
|
+
}
|
|
866
|
+
}
|
|
867
|
+
const cache = _uvToolCache ?? (_uvToolCache = snapshotUvTool());
|
|
868
|
+
return cache.has(pkgName);
|
|
869
|
+
}
|
|
870
|
+
function snapshotNpmGlobal() {
|
|
871
|
+
try {
|
|
872
|
+
const r = spawnSync("npm", ["ls", "-g", "--depth=0", "--parseable"], {
|
|
873
|
+
encoding: "utf-8",
|
|
874
|
+
timeout: 1e4
|
|
875
|
+
});
|
|
876
|
+
if (r.status !== 0 && !r.stdout) return /* @__PURE__ */ new Set();
|
|
877
|
+
const out = /* @__PURE__ */ new Set();
|
|
878
|
+
for (const line of (r.stdout ?? "").split("\n")) {
|
|
879
|
+
const trimmed = line.trim();
|
|
880
|
+
if (!trimmed) continue;
|
|
881
|
+
const idx = trimmed.lastIndexOf("/node_modules/");
|
|
882
|
+
if (idx < 0) continue;
|
|
883
|
+
const tail = trimmed.slice(idx + "/node_modules/".length);
|
|
884
|
+
if (!tail) continue;
|
|
885
|
+
out.add(tail);
|
|
886
|
+
}
|
|
887
|
+
return out;
|
|
888
|
+
} catch {
|
|
889
|
+
return /* @__PURE__ */ new Set();
|
|
890
|
+
}
|
|
891
|
+
}
|
|
892
|
+
function snapshotUvTool() {
|
|
893
|
+
try {
|
|
894
|
+
const r = spawnSync("uv", ["tool", "list"], { encoding: "utf-8", timeout: 1e4 });
|
|
895
|
+
if (r.status !== 0 && !r.stdout) return /* @__PURE__ */ new Set();
|
|
896
|
+
const out = /* @__PURE__ */ new Set();
|
|
897
|
+
for (const line of (r.stdout ?? "").split("\n")) {
|
|
898
|
+
if (!line || line.startsWith(" ") || line.startsWith("warning:")) continue;
|
|
899
|
+
const m = line.match(/^([a-zA-Z0-9._-]+)\s+v?\d/);
|
|
900
|
+
if (m) out.add(m[1]);
|
|
901
|
+
}
|
|
902
|
+
return out;
|
|
903
|
+
} catch {
|
|
904
|
+
return /* @__PURE__ */ new Set();
|
|
905
|
+
}
|
|
906
|
+
}
|
|
907
|
+
function isOnPath(cmd) {
|
|
908
|
+
return new Promise((resolve) => {
|
|
909
|
+
const probe = process.platform === "win32" ? "where" : "which";
|
|
910
|
+
const p = spawn4(probe, [cmd], { stdio: "ignore" });
|
|
911
|
+
p.once("error", () => resolve(false));
|
|
912
|
+
p.once("exit", (code) => resolve(code === 0));
|
|
913
|
+
});
|
|
914
|
+
}
|
|
915
|
+
async function detectAll() {
|
|
916
|
+
const list = getKnownAgents();
|
|
917
|
+
const results = await Promise.all(list.map((e) => detect(e.id)));
|
|
918
|
+
return results.filter((e) => e !== null);
|
|
919
|
+
}
|
|
920
|
+
var _mergedCache, _npmGlobalCache, _uvToolCache;
|
|
921
|
+
var init_registry = __esm({
|
|
922
|
+
"../acp-runtime/src/registry.ts"() {
|
|
923
|
+
"use strict";
|
|
924
|
+
init_known_agents();
|
|
925
|
+
init_registry_fetch();
|
|
926
|
+
init_known_agents();
|
|
927
|
+
init_known_agents();
|
|
928
|
+
_mergedCache = null;
|
|
929
|
+
_npmGlobalCache = null;
|
|
930
|
+
_uvToolCache = null;
|
|
931
|
+
}
|
|
932
|
+
});
|
|
933
|
+
|
|
312
934
|
// src/bridge/lib/style.ts
|
|
313
935
|
function wrap(open, close) {
|
|
314
936
|
return (s) => isTty ? `\x1B[${open}m${s}\x1B[${close}m` : s;
|
|
@@ -387,9 +1009,9 @@ var init_version = __esm({
|
|
|
387
1009
|
"use strict";
|
|
388
1010
|
req = createRequire(import.meta.url);
|
|
389
1011
|
PKG_VERSION = (() => {
|
|
390
|
-
for (const
|
|
1012
|
+
for (const path2 of ["../package.json", "../../package.json"]) {
|
|
391
1013
|
try {
|
|
392
|
-
return req(
|
|
1014
|
+
return req(path2).version;
|
|
393
1015
|
} catch {
|
|
394
1016
|
}
|
|
395
1017
|
}
|
|
@@ -2693,8 +3315,8 @@ var require_websocket = __commonJS({
|
|
|
2693
3315
|
var http = __require("http");
|
|
2694
3316
|
var net = __require("net");
|
|
2695
3317
|
var tls = __require("tls");
|
|
2696
|
-
var { randomBytes:
|
|
2697
|
-
var { Duplex, Readable:
|
|
3318
|
+
var { randomBytes: randomBytes4, createHash: createHash2 } = __require("crypto");
|
|
3319
|
+
var { Duplex, Readable: Readable3 } = __require("stream");
|
|
2698
3320
|
var { URL: URL2 } = __require("url");
|
|
2699
3321
|
var PerMessageDeflate = require_permessage_deflate();
|
|
2700
3322
|
var Receiver2 = require_receiver();
|
|
@@ -3220,7 +3842,7 @@ var require_websocket = __commonJS({
|
|
|
3220
3842
|
}
|
|
3221
3843
|
}
|
|
3222
3844
|
const defaultPort = isSecure ? 443 : 80;
|
|
3223
|
-
const key =
|
|
3845
|
+
const key = randomBytes4(16).toString("base64");
|
|
3224
3846
|
const request = isSecure ? https.request : http.request;
|
|
3225
3847
|
const protocolSet = /* @__PURE__ */ new Set();
|
|
3226
3848
|
let perMessageDeflate;
|
|
@@ -4056,22 +4678,2410 @@ async function probeRuntimeToken(serverUrl, token, timeoutMs = 8e3) {
|
|
|
4056
4678
|
if (status === 401 || status === 403 || status === 404) {
|
|
4057
4679
|
settle({ ok: false, reason: "invalid", detail: `HTTP ${status}` });
|
|
4058
4680
|
} else {
|
|
4059
|
-
settle({ ok: true });
|
|
4681
|
+
settle({ ok: true });
|
|
4682
|
+
}
|
|
4683
|
+
});
|
|
4684
|
+
ws.once("error", (e) => {
|
|
4685
|
+
clearTimeout(timer);
|
|
4686
|
+
settle({
|
|
4687
|
+
ok: false,
|
|
4688
|
+
reason: "unreachable",
|
|
4689
|
+
detail: e instanceof Error ? e.message : String(e)
|
|
4690
|
+
});
|
|
4691
|
+
});
|
|
4692
|
+
});
|
|
4693
|
+
}
|
|
4694
|
+
var init_probe = __esm({
|
|
4695
|
+
"src/bridge/lib/probe.ts"() {
|
|
4696
|
+
"use strict";
|
|
4697
|
+
}
|
|
4698
|
+
});
|
|
4699
|
+
|
|
4700
|
+
// ../../node_modules/.pnpm/@inquirer+core@11.1.9_@types+node@22.19.17/node_modules/@inquirer/core/dist/lib/key.js
|
|
4701
|
+
var isUpKey, isDownKey, isSpaceKey, isNumberKey, isEnterKey;
|
|
4702
|
+
var init_key = __esm({
|
|
4703
|
+
"../../node_modules/.pnpm/@inquirer+core@11.1.9_@types+node@22.19.17/node_modules/@inquirer/core/dist/lib/key.js"() {
|
|
4704
|
+
isUpKey = (key, keybindings = []) => (
|
|
4705
|
+
// The up key
|
|
4706
|
+
key.name === "up" || // Vim keybinding: hjkl keys map to left/down/up/right
|
|
4707
|
+
keybindings.includes("vim") && key.name === "k" || // Emacs keybinding: Ctrl+P means "previous" in Emacs navigation conventions
|
|
4708
|
+
keybindings.includes("emacs") && key.ctrl && key.name === "p"
|
|
4709
|
+
);
|
|
4710
|
+
isDownKey = (key, keybindings = []) => (
|
|
4711
|
+
// The down key
|
|
4712
|
+
key.name === "down" || // Vim keybinding: hjkl keys map to left/down/up/right
|
|
4713
|
+
keybindings.includes("vim") && key.name === "j" || // Emacs keybinding: Ctrl+N means "next" in Emacs navigation conventions
|
|
4714
|
+
keybindings.includes("emacs") && key.ctrl && key.name === "n"
|
|
4715
|
+
);
|
|
4716
|
+
isSpaceKey = (key) => key.name === "space";
|
|
4717
|
+
isNumberKey = (key) => "1234567890".includes(key.name);
|
|
4718
|
+
isEnterKey = (key) => key.name === "enter" || key.name === "return";
|
|
4719
|
+
}
|
|
4720
|
+
});
|
|
4721
|
+
|
|
4722
|
+
// ../../node_modules/.pnpm/@inquirer+core@11.1.9_@types+node@22.19.17/node_modules/@inquirer/core/dist/lib/errors.js
|
|
4723
|
+
var AbortPromptError, CancelPromptError, ExitPromptError, HookError, ValidationError;
|
|
4724
|
+
var init_errors = __esm({
|
|
4725
|
+
"../../node_modules/.pnpm/@inquirer+core@11.1.9_@types+node@22.19.17/node_modules/@inquirer/core/dist/lib/errors.js"() {
|
|
4726
|
+
AbortPromptError = class extends Error {
|
|
4727
|
+
name = "AbortPromptError";
|
|
4728
|
+
message = "Prompt was aborted";
|
|
4729
|
+
constructor(options) {
|
|
4730
|
+
super();
|
|
4731
|
+
this.cause = options?.cause;
|
|
4732
|
+
}
|
|
4733
|
+
};
|
|
4734
|
+
CancelPromptError = class extends Error {
|
|
4735
|
+
name = "CancelPromptError";
|
|
4736
|
+
message = "Prompt was canceled";
|
|
4737
|
+
};
|
|
4738
|
+
ExitPromptError = class extends Error {
|
|
4739
|
+
name = "ExitPromptError";
|
|
4740
|
+
};
|
|
4741
|
+
HookError = class extends Error {
|
|
4742
|
+
name = "HookError";
|
|
4743
|
+
};
|
|
4744
|
+
ValidationError = class extends Error {
|
|
4745
|
+
name = "ValidationError";
|
|
4746
|
+
};
|
|
4747
|
+
}
|
|
4748
|
+
});
|
|
4749
|
+
|
|
4750
|
+
// ../../node_modules/.pnpm/@inquirer+core@11.1.9_@types+node@22.19.17/node_modules/@inquirer/core/dist/lib/hook-engine.js
|
|
4751
|
+
import { AsyncLocalStorage, AsyncResource } from "node:async_hooks";
|
|
4752
|
+
function createStore(rl) {
|
|
4753
|
+
const store = {
|
|
4754
|
+
rl,
|
|
4755
|
+
hooks: [],
|
|
4756
|
+
hooksCleanup: [],
|
|
4757
|
+
hooksEffect: [],
|
|
4758
|
+
index: 0,
|
|
4759
|
+
handleChange() {
|
|
4760
|
+
}
|
|
4761
|
+
};
|
|
4762
|
+
return store;
|
|
4763
|
+
}
|
|
4764
|
+
function withHooks(rl, cb) {
|
|
4765
|
+
const store = createStore(rl);
|
|
4766
|
+
return hookStorage.run(store, () => {
|
|
4767
|
+
function cycle(render) {
|
|
4768
|
+
store.handleChange = () => {
|
|
4769
|
+
store.index = 0;
|
|
4770
|
+
render();
|
|
4771
|
+
};
|
|
4772
|
+
store.handleChange();
|
|
4773
|
+
}
|
|
4774
|
+
return cb(cycle);
|
|
4775
|
+
});
|
|
4776
|
+
}
|
|
4777
|
+
function getStore() {
|
|
4778
|
+
const store = hookStorage.getStore();
|
|
4779
|
+
if (!store) {
|
|
4780
|
+
throw new HookError("[Inquirer] Hook functions can only be called from within a prompt");
|
|
4781
|
+
}
|
|
4782
|
+
return store;
|
|
4783
|
+
}
|
|
4784
|
+
function readline() {
|
|
4785
|
+
return getStore().rl;
|
|
4786
|
+
}
|
|
4787
|
+
function withUpdates(fn) {
|
|
4788
|
+
const wrapped = (...args) => {
|
|
4789
|
+
const store = getStore();
|
|
4790
|
+
let shouldUpdate = false;
|
|
4791
|
+
const oldHandleChange = store.handleChange;
|
|
4792
|
+
store.handleChange = () => {
|
|
4793
|
+
shouldUpdate = true;
|
|
4794
|
+
};
|
|
4795
|
+
const returnValue = fn(...args);
|
|
4796
|
+
if (shouldUpdate) {
|
|
4797
|
+
oldHandleChange();
|
|
4798
|
+
}
|
|
4799
|
+
store.handleChange = oldHandleChange;
|
|
4800
|
+
return returnValue;
|
|
4801
|
+
};
|
|
4802
|
+
return AsyncResource.bind(wrapped);
|
|
4803
|
+
}
|
|
4804
|
+
function withPointer(cb) {
|
|
4805
|
+
const store = getStore();
|
|
4806
|
+
const { index } = store;
|
|
4807
|
+
const pointer = {
|
|
4808
|
+
get() {
|
|
4809
|
+
return store.hooks[index];
|
|
4810
|
+
},
|
|
4811
|
+
set(value) {
|
|
4812
|
+
store.hooks[index] = value;
|
|
4813
|
+
},
|
|
4814
|
+
initialized: index in store.hooks
|
|
4815
|
+
};
|
|
4816
|
+
const returnValue = cb(pointer);
|
|
4817
|
+
store.index++;
|
|
4818
|
+
return returnValue;
|
|
4819
|
+
}
|
|
4820
|
+
function handleChange() {
|
|
4821
|
+
getStore().handleChange();
|
|
4822
|
+
}
|
|
4823
|
+
var hookStorage, effectScheduler;
|
|
4824
|
+
var init_hook_engine = __esm({
|
|
4825
|
+
"../../node_modules/.pnpm/@inquirer+core@11.1.9_@types+node@22.19.17/node_modules/@inquirer/core/dist/lib/hook-engine.js"() {
|
|
4826
|
+
init_errors();
|
|
4827
|
+
hookStorage = new AsyncLocalStorage();
|
|
4828
|
+
effectScheduler = {
|
|
4829
|
+
queue(cb) {
|
|
4830
|
+
const store = getStore();
|
|
4831
|
+
const { index } = store;
|
|
4832
|
+
store.hooksEffect.push(() => {
|
|
4833
|
+
store.hooksCleanup[index]?.();
|
|
4834
|
+
const cleanFn = cb(readline());
|
|
4835
|
+
if (cleanFn != null && typeof cleanFn !== "function") {
|
|
4836
|
+
throw new ValidationError("useEffect return value must be a cleanup function or nothing.");
|
|
4837
|
+
}
|
|
4838
|
+
store.hooksCleanup[index] = cleanFn;
|
|
4839
|
+
});
|
|
4840
|
+
},
|
|
4841
|
+
run() {
|
|
4842
|
+
const store = getStore();
|
|
4843
|
+
withUpdates(() => {
|
|
4844
|
+
store.hooksEffect.forEach((effect) => {
|
|
4845
|
+
effect();
|
|
4846
|
+
});
|
|
4847
|
+
store.hooksEffect.length = 0;
|
|
4848
|
+
})();
|
|
4849
|
+
},
|
|
4850
|
+
clearAll() {
|
|
4851
|
+
const store = getStore();
|
|
4852
|
+
store.hooksCleanup.forEach((cleanFn) => {
|
|
4853
|
+
cleanFn?.();
|
|
4854
|
+
});
|
|
4855
|
+
store.hooksEffect.length = 0;
|
|
4856
|
+
store.hooksCleanup.length = 0;
|
|
4857
|
+
}
|
|
4858
|
+
};
|
|
4859
|
+
}
|
|
4860
|
+
});
|
|
4861
|
+
|
|
4862
|
+
// ../../node_modules/.pnpm/@inquirer+core@11.1.9_@types+node@22.19.17/node_modules/@inquirer/core/dist/lib/use-state.js
|
|
4863
|
+
import { AsyncResource as AsyncResource2 } from "node:async_hooks";
|
|
4864
|
+
function isFactory(value) {
|
|
4865
|
+
return typeof value === "function";
|
|
4866
|
+
}
|
|
4867
|
+
function useState(defaultValue) {
|
|
4868
|
+
return withPointer((pointer) => {
|
|
4869
|
+
const setState = AsyncResource2.bind(function setState2(newValue) {
|
|
4870
|
+
if (pointer.get() !== newValue) {
|
|
4871
|
+
pointer.set(newValue);
|
|
4872
|
+
handleChange();
|
|
4873
|
+
}
|
|
4874
|
+
});
|
|
4875
|
+
if (pointer.initialized) {
|
|
4876
|
+
return [pointer.get(), setState];
|
|
4877
|
+
}
|
|
4878
|
+
const value = isFactory(defaultValue) ? defaultValue() : defaultValue;
|
|
4879
|
+
pointer.set(value);
|
|
4880
|
+
return [value, setState];
|
|
4881
|
+
});
|
|
4882
|
+
}
|
|
4883
|
+
var init_use_state = __esm({
|
|
4884
|
+
"../../node_modules/.pnpm/@inquirer+core@11.1.9_@types+node@22.19.17/node_modules/@inquirer/core/dist/lib/use-state.js"() {
|
|
4885
|
+
init_hook_engine();
|
|
4886
|
+
}
|
|
4887
|
+
});
|
|
4888
|
+
|
|
4889
|
+
// ../../node_modules/.pnpm/@inquirer+core@11.1.9_@types+node@22.19.17/node_modules/@inquirer/core/dist/lib/use-effect.js
|
|
4890
|
+
function useEffect(cb, depArray) {
|
|
4891
|
+
withPointer((pointer) => {
|
|
4892
|
+
const oldDeps = pointer.get();
|
|
4893
|
+
const hasChanged = !Array.isArray(oldDeps) || depArray.some((dep, i) => !Object.is(dep, oldDeps[i]));
|
|
4894
|
+
if (hasChanged) {
|
|
4895
|
+
effectScheduler.queue(cb);
|
|
4896
|
+
}
|
|
4897
|
+
pointer.set(depArray);
|
|
4898
|
+
});
|
|
4899
|
+
}
|
|
4900
|
+
var init_use_effect = __esm({
|
|
4901
|
+
"../../node_modules/.pnpm/@inquirer+core@11.1.9_@types+node@22.19.17/node_modules/@inquirer/core/dist/lib/use-effect.js"() {
|
|
4902
|
+
init_hook_engine();
|
|
4903
|
+
}
|
|
4904
|
+
});
|
|
4905
|
+
|
|
4906
|
+
// ../../node_modules/.pnpm/@inquirer+figures@2.0.5/node_modules/@inquirer/figures/dist/index.js
|
|
4907
|
+
import process2 from "node:process";
|
|
4908
|
+
function isUnicodeSupported() {
|
|
4909
|
+
if (!process2.platform.startsWith("win")) {
|
|
4910
|
+
return process2.env["TERM"] !== "linux";
|
|
4911
|
+
}
|
|
4912
|
+
return Boolean(process2.env["CI"]) || // CI environments generally support unicode
|
|
4913
|
+
Boolean(process2.env["WT_SESSION"]) || // Windows Terminal
|
|
4914
|
+
Boolean(process2.env["TERMINUS_SUBLIME"]) || // Terminus (<0.2.27)
|
|
4915
|
+
process2.env["ConEmuTask"] === "{cmd::Cmder}" || // ConEmu and cmder
|
|
4916
|
+
process2.env["TERM_PROGRAM"] === "Terminus-Sublime" || process2.env["TERM_PROGRAM"] === "vscode" || process2.env["TERM"] === "xterm-256color" || process2.env["TERM"] === "alacritty" || process2.env["TERMINAL_EMULATOR"] === "JetBrains-JediTerm";
|
|
4917
|
+
}
|
|
4918
|
+
var common, specialMainSymbols, specialFallbackSymbols, mainSymbols, fallbackSymbols, shouldUseMain, figures, dist_default, replacements;
|
|
4919
|
+
var init_dist = __esm({
|
|
4920
|
+
"../../node_modules/.pnpm/@inquirer+figures@2.0.5/node_modules/@inquirer/figures/dist/index.js"() {
|
|
4921
|
+
common = {
|
|
4922
|
+
circleQuestionMark: "(?)",
|
|
4923
|
+
questionMarkPrefix: "(?)",
|
|
4924
|
+
square: "\u2588",
|
|
4925
|
+
squareDarkShade: "\u2593",
|
|
4926
|
+
squareMediumShade: "\u2592",
|
|
4927
|
+
squareLightShade: "\u2591",
|
|
4928
|
+
squareTop: "\u2580",
|
|
4929
|
+
squareBottom: "\u2584",
|
|
4930
|
+
squareLeft: "\u258C",
|
|
4931
|
+
squareRight: "\u2590",
|
|
4932
|
+
squareCenter: "\u25A0",
|
|
4933
|
+
bullet: "\u25CF",
|
|
4934
|
+
dot: "\u2024",
|
|
4935
|
+
ellipsis: "\u2026",
|
|
4936
|
+
pointerSmall: "\u203A",
|
|
4937
|
+
triangleUp: "\u25B2",
|
|
4938
|
+
triangleUpSmall: "\u25B4",
|
|
4939
|
+
triangleDown: "\u25BC",
|
|
4940
|
+
triangleDownSmall: "\u25BE",
|
|
4941
|
+
triangleLeftSmall: "\u25C2",
|
|
4942
|
+
triangleRightSmall: "\u25B8",
|
|
4943
|
+
home: "\u2302",
|
|
4944
|
+
heart: "\u2665",
|
|
4945
|
+
musicNote: "\u266A",
|
|
4946
|
+
musicNoteBeamed: "\u266B",
|
|
4947
|
+
arrowUp: "\u2191",
|
|
4948
|
+
arrowDown: "\u2193",
|
|
4949
|
+
arrowLeft: "\u2190",
|
|
4950
|
+
arrowRight: "\u2192",
|
|
4951
|
+
arrowLeftRight: "\u2194",
|
|
4952
|
+
arrowUpDown: "\u2195",
|
|
4953
|
+
almostEqual: "\u2248",
|
|
4954
|
+
notEqual: "\u2260",
|
|
4955
|
+
lessOrEqual: "\u2264",
|
|
4956
|
+
greaterOrEqual: "\u2265",
|
|
4957
|
+
identical: "\u2261",
|
|
4958
|
+
infinity: "\u221E",
|
|
4959
|
+
subscriptZero: "\u2080",
|
|
4960
|
+
subscriptOne: "\u2081",
|
|
4961
|
+
subscriptTwo: "\u2082",
|
|
4962
|
+
subscriptThree: "\u2083",
|
|
4963
|
+
subscriptFour: "\u2084",
|
|
4964
|
+
subscriptFive: "\u2085",
|
|
4965
|
+
subscriptSix: "\u2086",
|
|
4966
|
+
subscriptSeven: "\u2087",
|
|
4967
|
+
subscriptEight: "\u2088",
|
|
4968
|
+
subscriptNine: "\u2089",
|
|
4969
|
+
oneHalf: "\xBD",
|
|
4970
|
+
oneThird: "\u2153",
|
|
4971
|
+
oneQuarter: "\xBC",
|
|
4972
|
+
oneFifth: "\u2155",
|
|
4973
|
+
oneSixth: "\u2159",
|
|
4974
|
+
oneEighth: "\u215B",
|
|
4975
|
+
twoThirds: "\u2154",
|
|
4976
|
+
twoFifths: "\u2156",
|
|
4977
|
+
threeQuarters: "\xBE",
|
|
4978
|
+
threeFifths: "\u2157",
|
|
4979
|
+
threeEighths: "\u215C",
|
|
4980
|
+
fourFifths: "\u2158",
|
|
4981
|
+
fiveSixths: "\u215A",
|
|
4982
|
+
fiveEighths: "\u215D",
|
|
4983
|
+
sevenEighths: "\u215E",
|
|
4984
|
+
line: "\u2500",
|
|
4985
|
+
lineBold: "\u2501",
|
|
4986
|
+
lineDouble: "\u2550",
|
|
4987
|
+
lineDashed0: "\u2504",
|
|
4988
|
+
lineDashed1: "\u2505",
|
|
4989
|
+
lineDashed2: "\u2508",
|
|
4990
|
+
lineDashed3: "\u2509",
|
|
4991
|
+
lineDashed4: "\u254C",
|
|
4992
|
+
lineDashed5: "\u254D",
|
|
4993
|
+
lineDashed6: "\u2574",
|
|
4994
|
+
lineDashed7: "\u2576",
|
|
4995
|
+
lineDashed8: "\u2578",
|
|
4996
|
+
lineDashed9: "\u257A",
|
|
4997
|
+
lineDashed10: "\u257C",
|
|
4998
|
+
lineDashed11: "\u257E",
|
|
4999
|
+
lineDashed12: "\u2212",
|
|
5000
|
+
lineDashed13: "\u2013",
|
|
5001
|
+
lineDashed14: "\u2010",
|
|
5002
|
+
lineDashed15: "\u2043",
|
|
5003
|
+
lineVertical: "\u2502",
|
|
5004
|
+
lineVerticalBold: "\u2503",
|
|
5005
|
+
lineVerticalDouble: "\u2551",
|
|
5006
|
+
lineVerticalDashed0: "\u2506",
|
|
5007
|
+
lineVerticalDashed1: "\u2507",
|
|
5008
|
+
lineVerticalDashed2: "\u250A",
|
|
5009
|
+
lineVerticalDashed3: "\u250B",
|
|
5010
|
+
lineVerticalDashed4: "\u254E",
|
|
5011
|
+
lineVerticalDashed5: "\u254F",
|
|
5012
|
+
lineVerticalDashed6: "\u2575",
|
|
5013
|
+
lineVerticalDashed7: "\u2577",
|
|
5014
|
+
lineVerticalDashed8: "\u2579",
|
|
5015
|
+
lineVerticalDashed9: "\u257B",
|
|
5016
|
+
lineVerticalDashed10: "\u257D",
|
|
5017
|
+
lineVerticalDashed11: "\u257F",
|
|
5018
|
+
lineDownLeft: "\u2510",
|
|
5019
|
+
lineDownLeftArc: "\u256E",
|
|
5020
|
+
lineDownBoldLeftBold: "\u2513",
|
|
5021
|
+
lineDownBoldLeft: "\u2512",
|
|
5022
|
+
lineDownLeftBold: "\u2511",
|
|
5023
|
+
lineDownDoubleLeftDouble: "\u2557",
|
|
5024
|
+
lineDownDoubleLeft: "\u2556",
|
|
5025
|
+
lineDownLeftDouble: "\u2555",
|
|
5026
|
+
lineDownRight: "\u250C",
|
|
5027
|
+
lineDownRightArc: "\u256D",
|
|
5028
|
+
lineDownBoldRightBold: "\u250F",
|
|
5029
|
+
lineDownBoldRight: "\u250E",
|
|
5030
|
+
lineDownRightBold: "\u250D",
|
|
5031
|
+
lineDownDoubleRightDouble: "\u2554",
|
|
5032
|
+
lineDownDoubleRight: "\u2553",
|
|
5033
|
+
lineDownRightDouble: "\u2552",
|
|
5034
|
+
lineUpLeft: "\u2518",
|
|
5035
|
+
lineUpLeftArc: "\u256F",
|
|
5036
|
+
lineUpBoldLeftBold: "\u251B",
|
|
5037
|
+
lineUpBoldLeft: "\u251A",
|
|
5038
|
+
lineUpLeftBold: "\u2519",
|
|
5039
|
+
lineUpDoubleLeftDouble: "\u255D",
|
|
5040
|
+
lineUpDoubleLeft: "\u255C",
|
|
5041
|
+
lineUpLeftDouble: "\u255B",
|
|
5042
|
+
lineUpRight: "\u2514",
|
|
5043
|
+
lineUpRightArc: "\u2570",
|
|
5044
|
+
lineUpBoldRightBold: "\u2517",
|
|
5045
|
+
lineUpBoldRight: "\u2516",
|
|
5046
|
+
lineUpRightBold: "\u2515",
|
|
5047
|
+
lineUpDoubleRightDouble: "\u255A",
|
|
5048
|
+
lineUpDoubleRight: "\u2559",
|
|
5049
|
+
lineUpRightDouble: "\u2558",
|
|
5050
|
+
lineUpDownLeft: "\u2524",
|
|
5051
|
+
lineUpBoldDownBoldLeftBold: "\u252B",
|
|
5052
|
+
lineUpBoldDownBoldLeft: "\u2528",
|
|
5053
|
+
lineUpDownLeftBold: "\u2525",
|
|
5054
|
+
lineUpBoldDownLeftBold: "\u2529",
|
|
5055
|
+
lineUpDownBoldLeftBold: "\u252A",
|
|
5056
|
+
lineUpDownBoldLeft: "\u2527",
|
|
5057
|
+
lineUpBoldDownLeft: "\u2526",
|
|
5058
|
+
lineUpDoubleDownDoubleLeftDouble: "\u2563",
|
|
5059
|
+
lineUpDoubleDownDoubleLeft: "\u2562",
|
|
5060
|
+
lineUpDownLeftDouble: "\u2561",
|
|
5061
|
+
lineUpDownRight: "\u251C",
|
|
5062
|
+
lineUpBoldDownBoldRightBold: "\u2523",
|
|
5063
|
+
lineUpBoldDownBoldRight: "\u2520",
|
|
5064
|
+
lineUpDownRightBold: "\u251D",
|
|
5065
|
+
lineUpBoldDownRightBold: "\u2521",
|
|
5066
|
+
lineUpDownBoldRightBold: "\u2522",
|
|
5067
|
+
lineUpDownBoldRight: "\u251F",
|
|
5068
|
+
lineUpBoldDownRight: "\u251E",
|
|
5069
|
+
lineUpDoubleDownDoubleRightDouble: "\u2560",
|
|
5070
|
+
lineUpDoubleDownDoubleRight: "\u255F",
|
|
5071
|
+
lineUpDownRightDouble: "\u255E",
|
|
5072
|
+
lineDownLeftRight: "\u252C",
|
|
5073
|
+
lineDownBoldLeftBoldRightBold: "\u2533",
|
|
5074
|
+
lineDownLeftBoldRightBold: "\u252F",
|
|
5075
|
+
lineDownBoldLeftRight: "\u2530",
|
|
5076
|
+
lineDownBoldLeftBoldRight: "\u2531",
|
|
5077
|
+
lineDownBoldLeftRightBold: "\u2532",
|
|
5078
|
+
lineDownLeftRightBold: "\u252E",
|
|
5079
|
+
lineDownLeftBoldRight: "\u252D",
|
|
5080
|
+
lineDownDoubleLeftDoubleRightDouble: "\u2566",
|
|
5081
|
+
lineDownDoubleLeftRight: "\u2565",
|
|
5082
|
+
lineDownLeftDoubleRightDouble: "\u2564",
|
|
5083
|
+
lineUpLeftRight: "\u2534",
|
|
5084
|
+
lineUpBoldLeftBoldRightBold: "\u253B",
|
|
5085
|
+
lineUpLeftBoldRightBold: "\u2537",
|
|
5086
|
+
lineUpBoldLeftRight: "\u2538",
|
|
5087
|
+
lineUpBoldLeftBoldRight: "\u2539",
|
|
5088
|
+
lineUpBoldLeftRightBold: "\u253A",
|
|
5089
|
+
lineUpLeftRightBold: "\u2536",
|
|
5090
|
+
lineUpLeftBoldRight: "\u2535",
|
|
5091
|
+
lineUpDoubleLeftDoubleRightDouble: "\u2569",
|
|
5092
|
+
lineUpDoubleLeftRight: "\u2568",
|
|
5093
|
+
lineUpLeftDoubleRightDouble: "\u2567",
|
|
5094
|
+
lineUpDownLeftRight: "\u253C",
|
|
5095
|
+
lineUpBoldDownBoldLeftBoldRightBold: "\u254B",
|
|
5096
|
+
lineUpDownBoldLeftBoldRightBold: "\u2548",
|
|
5097
|
+
lineUpBoldDownLeftBoldRightBold: "\u2547",
|
|
5098
|
+
lineUpBoldDownBoldLeftRightBold: "\u254A",
|
|
5099
|
+
lineUpBoldDownBoldLeftBoldRight: "\u2549",
|
|
5100
|
+
lineUpBoldDownLeftRight: "\u2540",
|
|
5101
|
+
lineUpDownBoldLeftRight: "\u2541",
|
|
5102
|
+
lineUpDownLeftBoldRight: "\u253D",
|
|
5103
|
+
lineUpDownLeftRightBold: "\u253E",
|
|
5104
|
+
lineUpBoldDownBoldLeftRight: "\u2542",
|
|
5105
|
+
lineUpDownLeftBoldRightBold: "\u253F",
|
|
5106
|
+
lineUpBoldDownLeftBoldRight: "\u2543",
|
|
5107
|
+
lineUpBoldDownLeftRightBold: "\u2544",
|
|
5108
|
+
lineUpDownBoldLeftBoldRight: "\u2545",
|
|
5109
|
+
lineUpDownBoldLeftRightBold: "\u2546",
|
|
5110
|
+
lineUpDoubleDownDoubleLeftDoubleRightDouble: "\u256C",
|
|
5111
|
+
lineUpDoubleDownDoubleLeftRight: "\u256B",
|
|
5112
|
+
lineUpDownLeftDoubleRightDouble: "\u256A",
|
|
5113
|
+
lineCross: "\u2573",
|
|
5114
|
+
lineBackslash: "\u2572",
|
|
5115
|
+
lineSlash: "\u2571"
|
|
5116
|
+
};
|
|
5117
|
+
specialMainSymbols = {
|
|
5118
|
+
tick: "\u2714",
|
|
5119
|
+
info: "\u2139",
|
|
5120
|
+
warning: "\u26A0",
|
|
5121
|
+
cross: "\u2718",
|
|
5122
|
+
squareSmall: "\u25FB",
|
|
5123
|
+
squareSmallFilled: "\u25FC",
|
|
5124
|
+
circle: "\u25EF",
|
|
5125
|
+
circleFilled: "\u25C9",
|
|
5126
|
+
circleDotted: "\u25CC",
|
|
5127
|
+
circleDouble: "\u25CE",
|
|
5128
|
+
circleCircle: "\u24DE",
|
|
5129
|
+
circleCross: "\u24E7",
|
|
5130
|
+
circlePipe: "\u24BE",
|
|
5131
|
+
radioOn: "\u25C9",
|
|
5132
|
+
radioOff: "\u25EF",
|
|
5133
|
+
checkboxOn: "\u2612",
|
|
5134
|
+
checkboxOff: "\u2610",
|
|
5135
|
+
checkboxCircleOn: "\u24E7",
|
|
5136
|
+
checkboxCircleOff: "\u24BE",
|
|
5137
|
+
pointer: "\u276F",
|
|
5138
|
+
triangleUpOutline: "\u25B3",
|
|
5139
|
+
triangleLeft: "\u25C0",
|
|
5140
|
+
triangleRight: "\u25B6",
|
|
5141
|
+
lozenge: "\u25C6",
|
|
5142
|
+
lozengeOutline: "\u25C7",
|
|
5143
|
+
hamburger: "\u2630",
|
|
5144
|
+
smiley: "\u32E1",
|
|
5145
|
+
mustache: "\u0DF4",
|
|
5146
|
+
star: "\u2605",
|
|
5147
|
+
play: "\u25B6",
|
|
5148
|
+
nodejs: "\u2B22",
|
|
5149
|
+
oneSeventh: "\u2150",
|
|
5150
|
+
oneNinth: "\u2151",
|
|
5151
|
+
oneTenth: "\u2152"
|
|
5152
|
+
};
|
|
5153
|
+
specialFallbackSymbols = {
|
|
5154
|
+
tick: "\u221A",
|
|
5155
|
+
info: "i",
|
|
5156
|
+
warning: "\u203C",
|
|
5157
|
+
cross: "\xD7",
|
|
5158
|
+
squareSmall: "\u25A1",
|
|
5159
|
+
squareSmallFilled: "\u25A0",
|
|
5160
|
+
circle: "( )",
|
|
5161
|
+
circleFilled: "(*)",
|
|
5162
|
+
circleDotted: "( )",
|
|
5163
|
+
circleDouble: "( )",
|
|
5164
|
+
circleCircle: "(\u25CB)",
|
|
5165
|
+
circleCross: "(\xD7)",
|
|
5166
|
+
circlePipe: "(\u2502)",
|
|
5167
|
+
radioOn: "(*)",
|
|
5168
|
+
radioOff: "( )",
|
|
5169
|
+
checkboxOn: "[\xD7]",
|
|
5170
|
+
checkboxOff: "[ ]",
|
|
5171
|
+
checkboxCircleOn: "(\xD7)",
|
|
5172
|
+
checkboxCircleOff: "( )",
|
|
5173
|
+
pointer: ">",
|
|
5174
|
+
triangleUpOutline: "\u2206",
|
|
5175
|
+
triangleLeft: "\u25C4",
|
|
5176
|
+
triangleRight: "\u25BA",
|
|
5177
|
+
lozenge: "\u2666",
|
|
5178
|
+
lozengeOutline: "\u25CA",
|
|
5179
|
+
hamburger: "\u2261",
|
|
5180
|
+
smiley: "\u263A",
|
|
5181
|
+
mustache: "\u250C\u2500\u2510",
|
|
5182
|
+
star: "\u2736",
|
|
5183
|
+
play: "\u25BA",
|
|
5184
|
+
nodejs: "\u2666",
|
|
5185
|
+
oneSeventh: "1/7",
|
|
5186
|
+
oneNinth: "1/9",
|
|
5187
|
+
oneTenth: "1/10"
|
|
5188
|
+
};
|
|
5189
|
+
mainSymbols = {
|
|
5190
|
+
...common,
|
|
5191
|
+
...specialMainSymbols
|
|
5192
|
+
};
|
|
5193
|
+
fallbackSymbols = {
|
|
5194
|
+
...common,
|
|
5195
|
+
...specialFallbackSymbols
|
|
5196
|
+
};
|
|
5197
|
+
shouldUseMain = isUnicodeSupported();
|
|
5198
|
+
figures = shouldUseMain ? mainSymbols : fallbackSymbols;
|
|
5199
|
+
dist_default = figures;
|
|
5200
|
+
replacements = Object.entries(specialMainSymbols);
|
|
5201
|
+
}
|
|
5202
|
+
});
|
|
5203
|
+
|
|
5204
|
+
// ../../node_modules/.pnpm/@inquirer+core@11.1.9_@types+node@22.19.17/node_modules/@inquirer/core/dist/lib/theme.js
|
|
5205
|
+
import { styleText } from "node:util";
|
|
5206
|
+
var defaultTheme;
|
|
5207
|
+
var init_theme = __esm({
|
|
5208
|
+
"../../node_modules/.pnpm/@inquirer+core@11.1.9_@types+node@22.19.17/node_modules/@inquirer/core/dist/lib/theme.js"() {
|
|
5209
|
+
init_dist();
|
|
5210
|
+
defaultTheme = {
|
|
5211
|
+
prefix: {
|
|
5212
|
+
idle: styleText("blue", "?"),
|
|
5213
|
+
done: styleText("green", dist_default.tick)
|
|
5214
|
+
},
|
|
5215
|
+
spinner: {
|
|
5216
|
+
interval: 80,
|
|
5217
|
+
frames: ["\u280B", "\u2819", "\u2839", "\u2838", "\u283C", "\u2834", "\u2826", "\u2827", "\u2807", "\u280F"].map((frame) => styleText("yellow", frame))
|
|
5218
|
+
},
|
|
5219
|
+
style: {
|
|
5220
|
+
answer: (text) => styleText("cyan", text),
|
|
5221
|
+
message: (text) => styleText("bold", text),
|
|
5222
|
+
error: (text) => styleText("red", `> ${text}`),
|
|
5223
|
+
defaultAnswer: (text) => styleText("dim", `(${text})`),
|
|
5224
|
+
help: (text) => styleText("dim", text),
|
|
5225
|
+
highlight: (text) => styleText("cyan", text),
|
|
5226
|
+
key: (text) => styleText("cyan", styleText("bold", `<${text}>`))
|
|
5227
|
+
}
|
|
5228
|
+
};
|
|
5229
|
+
}
|
|
5230
|
+
});
|
|
5231
|
+
|
|
5232
|
+
// ../../node_modules/.pnpm/@inquirer+core@11.1.9_@types+node@22.19.17/node_modules/@inquirer/core/dist/lib/make-theme.js
|
|
5233
|
+
function isPlainObject(value) {
|
|
5234
|
+
if (typeof value !== "object" || value === null)
|
|
5235
|
+
return false;
|
|
5236
|
+
let proto = value;
|
|
5237
|
+
while (Object.getPrototypeOf(proto) !== null) {
|
|
5238
|
+
proto = Object.getPrototypeOf(proto);
|
|
5239
|
+
}
|
|
5240
|
+
return Object.getPrototypeOf(value) === proto;
|
|
5241
|
+
}
|
|
5242
|
+
function deepMerge(...objects) {
|
|
5243
|
+
const output = {};
|
|
5244
|
+
for (const obj of objects) {
|
|
5245
|
+
for (const [key, value] of Object.entries(obj)) {
|
|
5246
|
+
const prevValue = output[key];
|
|
5247
|
+
output[key] = isPlainObject(prevValue) && isPlainObject(value) ? deepMerge(prevValue, value) : value;
|
|
5248
|
+
}
|
|
5249
|
+
}
|
|
5250
|
+
return output;
|
|
5251
|
+
}
|
|
5252
|
+
function makeTheme(...themes) {
|
|
5253
|
+
const themesToMerge = [
|
|
5254
|
+
defaultTheme,
|
|
5255
|
+
...themes.filter((theme) => theme != null)
|
|
5256
|
+
];
|
|
5257
|
+
return deepMerge(...themesToMerge);
|
|
5258
|
+
}
|
|
5259
|
+
var init_make_theme = __esm({
|
|
5260
|
+
"../../node_modules/.pnpm/@inquirer+core@11.1.9_@types+node@22.19.17/node_modules/@inquirer/core/dist/lib/make-theme.js"() {
|
|
5261
|
+
init_theme();
|
|
5262
|
+
}
|
|
5263
|
+
});
|
|
5264
|
+
|
|
5265
|
+
// ../../node_modules/.pnpm/@inquirer+core@11.1.9_@types+node@22.19.17/node_modules/@inquirer/core/dist/lib/use-prefix.js
|
|
5266
|
+
function usePrefix({ status = "idle", theme }) {
|
|
5267
|
+
const [showLoader, setShowLoader] = useState(false);
|
|
5268
|
+
const [tick, setTick] = useState(0);
|
|
5269
|
+
const { prefix, spinner } = makeTheme(theme);
|
|
5270
|
+
useEffect(() => {
|
|
5271
|
+
if (status === "loading") {
|
|
5272
|
+
let tickInterval;
|
|
5273
|
+
let inc = -1;
|
|
5274
|
+
const delayTimeout = setTimeout(() => {
|
|
5275
|
+
setShowLoader(true);
|
|
5276
|
+
tickInterval = setInterval(() => {
|
|
5277
|
+
inc = inc + 1;
|
|
5278
|
+
setTick(inc % spinner.frames.length);
|
|
5279
|
+
}, spinner.interval);
|
|
5280
|
+
}, 300);
|
|
5281
|
+
return () => {
|
|
5282
|
+
clearTimeout(delayTimeout);
|
|
5283
|
+
clearInterval(tickInterval);
|
|
5284
|
+
};
|
|
5285
|
+
} else {
|
|
5286
|
+
setShowLoader(false);
|
|
5287
|
+
}
|
|
5288
|
+
}, [status]);
|
|
5289
|
+
if (showLoader) {
|
|
5290
|
+
return spinner.frames[tick];
|
|
5291
|
+
}
|
|
5292
|
+
const iconName = status === "loading" ? "idle" : status;
|
|
5293
|
+
return typeof prefix === "string" ? prefix : prefix[iconName] ?? prefix["idle"];
|
|
5294
|
+
}
|
|
5295
|
+
var init_use_prefix = __esm({
|
|
5296
|
+
"../../node_modules/.pnpm/@inquirer+core@11.1.9_@types+node@22.19.17/node_modules/@inquirer/core/dist/lib/use-prefix.js"() {
|
|
5297
|
+
init_use_state();
|
|
5298
|
+
init_use_effect();
|
|
5299
|
+
init_make_theme();
|
|
5300
|
+
}
|
|
5301
|
+
});
|
|
5302
|
+
|
|
5303
|
+
// ../../node_modules/.pnpm/@inquirer+core@11.1.9_@types+node@22.19.17/node_modules/@inquirer/core/dist/lib/use-memo.js
|
|
5304
|
+
function useMemo(fn, dependencies) {
|
|
5305
|
+
return withPointer((pointer) => {
|
|
5306
|
+
const prev = pointer.get();
|
|
5307
|
+
if (!prev || prev.dependencies.length !== dependencies.length || prev.dependencies.some((dep, i) => dep !== dependencies[i])) {
|
|
5308
|
+
const value = fn();
|
|
5309
|
+
pointer.set({ value, dependencies });
|
|
5310
|
+
return value;
|
|
5311
|
+
}
|
|
5312
|
+
return prev.value;
|
|
5313
|
+
});
|
|
5314
|
+
}
|
|
5315
|
+
var init_use_memo = __esm({
|
|
5316
|
+
"../../node_modules/.pnpm/@inquirer+core@11.1.9_@types+node@22.19.17/node_modules/@inquirer/core/dist/lib/use-memo.js"() {
|
|
5317
|
+
init_hook_engine();
|
|
5318
|
+
}
|
|
5319
|
+
});
|
|
5320
|
+
|
|
5321
|
+
// ../../node_modules/.pnpm/@inquirer+core@11.1.9_@types+node@22.19.17/node_modules/@inquirer/core/dist/lib/use-ref.js
|
|
5322
|
+
function useRef(val) {
|
|
5323
|
+
return useState({ current: val })[0];
|
|
5324
|
+
}
|
|
5325
|
+
var init_use_ref = __esm({
|
|
5326
|
+
"../../node_modules/.pnpm/@inquirer+core@11.1.9_@types+node@22.19.17/node_modules/@inquirer/core/dist/lib/use-ref.js"() {
|
|
5327
|
+
init_use_state();
|
|
5328
|
+
}
|
|
5329
|
+
});
|
|
5330
|
+
|
|
5331
|
+
// ../../node_modules/.pnpm/@inquirer+core@11.1.9_@types+node@22.19.17/node_modules/@inquirer/core/dist/lib/use-keypress.js
|
|
5332
|
+
function useKeypress(userHandler) {
|
|
5333
|
+
const signal = useRef(userHandler);
|
|
5334
|
+
signal.current = userHandler;
|
|
5335
|
+
useEffect((rl) => {
|
|
5336
|
+
let ignore = false;
|
|
5337
|
+
const handler = withUpdates((_input, event) => {
|
|
5338
|
+
if (ignore)
|
|
5339
|
+
return;
|
|
5340
|
+
void signal.current(event, rl);
|
|
5341
|
+
});
|
|
5342
|
+
rl.input.on("keypress", handler);
|
|
5343
|
+
return () => {
|
|
5344
|
+
ignore = true;
|
|
5345
|
+
rl.input.removeListener("keypress", handler);
|
|
5346
|
+
};
|
|
5347
|
+
}, []);
|
|
5348
|
+
}
|
|
5349
|
+
var init_use_keypress = __esm({
|
|
5350
|
+
"../../node_modules/.pnpm/@inquirer+core@11.1.9_@types+node@22.19.17/node_modules/@inquirer/core/dist/lib/use-keypress.js"() {
|
|
5351
|
+
init_use_ref();
|
|
5352
|
+
init_use_effect();
|
|
5353
|
+
init_hook_engine();
|
|
5354
|
+
}
|
|
5355
|
+
});
|
|
5356
|
+
|
|
5357
|
+
// ../../node_modules/.pnpm/cli-width@4.1.0/node_modules/cli-width/index.js
|
|
5358
|
+
var require_cli_width = __commonJS({
|
|
5359
|
+
"../../node_modules/.pnpm/cli-width@4.1.0/node_modules/cli-width/index.js"(exports, module) {
|
|
5360
|
+
"use strict";
|
|
5361
|
+
module.exports = cliWidth2;
|
|
5362
|
+
function normalizeOpts(options) {
|
|
5363
|
+
const defaultOpts = {
|
|
5364
|
+
defaultWidth: 0,
|
|
5365
|
+
output: process.stdout,
|
|
5366
|
+
tty: __require("tty")
|
|
5367
|
+
};
|
|
5368
|
+
if (!options) {
|
|
5369
|
+
return defaultOpts;
|
|
5370
|
+
}
|
|
5371
|
+
Object.keys(defaultOpts).forEach(function(key) {
|
|
5372
|
+
if (!options[key]) {
|
|
5373
|
+
options[key] = defaultOpts[key];
|
|
5374
|
+
}
|
|
5375
|
+
});
|
|
5376
|
+
return options;
|
|
5377
|
+
}
|
|
5378
|
+
function cliWidth2(options) {
|
|
5379
|
+
const opts = normalizeOpts(options);
|
|
5380
|
+
if (opts.output.getWindowSize) {
|
|
5381
|
+
return opts.output.getWindowSize()[0] || opts.defaultWidth;
|
|
5382
|
+
}
|
|
5383
|
+
if (opts.tty.getWindowSize) {
|
|
5384
|
+
return opts.tty.getWindowSize()[1] || opts.defaultWidth;
|
|
5385
|
+
}
|
|
5386
|
+
if (opts.output.columns) {
|
|
5387
|
+
return opts.output.columns;
|
|
5388
|
+
}
|
|
5389
|
+
if (process.env.CLI_WIDTH) {
|
|
5390
|
+
const width = parseInt(process.env.CLI_WIDTH, 10);
|
|
5391
|
+
if (!isNaN(width) && width !== 0) {
|
|
5392
|
+
return width;
|
|
5393
|
+
}
|
|
5394
|
+
}
|
|
5395
|
+
return opts.defaultWidth;
|
|
5396
|
+
}
|
|
5397
|
+
}
|
|
5398
|
+
});
|
|
5399
|
+
|
|
5400
|
+
// ../../node_modules/.pnpm/fast-string-truncated-width@3.0.3/node_modules/fast-string-truncated-width/dist/utils.js
|
|
5401
|
+
var getCodePointsLength, isFullWidth, isWideNotCJKTNotEmoji;
|
|
5402
|
+
var init_utils = __esm({
|
|
5403
|
+
"../../node_modules/.pnpm/fast-string-truncated-width@3.0.3/node_modules/fast-string-truncated-width/dist/utils.js"() {
|
|
5404
|
+
getCodePointsLength = /* @__PURE__ */ (() => {
|
|
5405
|
+
const SURROGATE_PAIR_RE = /[\uD800-\uDBFF][\uDC00-\uDFFF]/g;
|
|
5406
|
+
return (input) => {
|
|
5407
|
+
let surrogatePairsNr = 0;
|
|
5408
|
+
SURROGATE_PAIR_RE.lastIndex = 0;
|
|
5409
|
+
while (SURROGATE_PAIR_RE.test(input)) {
|
|
5410
|
+
surrogatePairsNr += 1;
|
|
5411
|
+
}
|
|
5412
|
+
return input.length - surrogatePairsNr;
|
|
5413
|
+
};
|
|
5414
|
+
})();
|
|
5415
|
+
isFullWidth = (x) => {
|
|
5416
|
+
return x === 12288 || x >= 65281 && x <= 65376 || x >= 65504 && x <= 65510;
|
|
5417
|
+
};
|
|
5418
|
+
isWideNotCJKTNotEmoji = (x) => {
|
|
5419
|
+
return x === 8987 || x === 9001 || x >= 12272 && x <= 12287 || x >= 12289 && x <= 12350 || x >= 12441 && x <= 12543 || x >= 12549 && x <= 12591 || x >= 12593 && x <= 12686 || x >= 12688 && x <= 12771 || x >= 12783 && x <= 12830 || x >= 12832 && x <= 12871 || x >= 12880 && x <= 19903 || x >= 65040 && x <= 65049 || x >= 65072 && x <= 65106 || x >= 65108 && x <= 65126 || x >= 65128 && x <= 65131 || x >= 127488 && x <= 127490 || x >= 127504 && x <= 127547 || x >= 127552 && x <= 127560 || x >= 131072 && x <= 196605 || x >= 196608 && x <= 262141;
|
|
5420
|
+
};
|
|
5421
|
+
}
|
|
5422
|
+
});
|
|
5423
|
+
|
|
5424
|
+
// ../../node_modules/.pnpm/fast-string-truncated-width@3.0.3/node_modules/fast-string-truncated-width/dist/index.js
|
|
5425
|
+
var ANSI_RE, CONTROL_RE, CJKT_WIDE_RE, TAB_RE, EMOJI_RE, LATIN_RE, MODIFIER_RE, NO_TRUNCATION, getStringTruncatedWidth, dist_default2;
|
|
5426
|
+
var init_dist2 = __esm({
|
|
5427
|
+
"../../node_modules/.pnpm/fast-string-truncated-width@3.0.3/node_modules/fast-string-truncated-width/dist/index.js"() {
|
|
5428
|
+
init_utils();
|
|
5429
|
+
ANSI_RE = /[\u001b\u009b][[()#;?]*(?:[0-9]{1,4}(?:;[0-9]{0,4})*)?[0-9A-ORZcf-nqry=><]|\u001b\]8;[^;]*;.*?(?:\u0007|\u001b\u005c)/y;
|
|
5430
|
+
CONTROL_RE = /[\x00-\x08\x0A-\x1F\x7F-\x9F]{1,1000}/y;
|
|
5431
|
+
CJKT_WIDE_RE = /(?:(?![\uFF61-\uFF9F\uFF00-\uFFEF])[\p{Script=Han}\p{Script=Hiragana}\p{Script=Katakana}\p{Script=Hangul}\p{Script=Tangut}]){1,1000}/yu;
|
|
5432
|
+
TAB_RE = /\t{1,1000}/y;
|
|
5433
|
+
EMOJI_RE = /[\u{1F1E6}-\u{1F1FF}]{2}|\u{1F3F4}[\u{E0061}-\u{E007A}]{2}[\u{E0030}-\u{E0039}\u{E0061}-\u{E007A}]{1,3}\u{E007F}|(?:\p{Emoji}\uFE0F\u20E3?|\p{Emoji_Modifier_Base}\p{Emoji_Modifier}?|\p{Emoji_Presentation})(?:\u200D(?:\p{Emoji_Modifier_Base}\p{Emoji_Modifier}?|\p{Emoji_Presentation}|\p{Emoji}\uFE0F\u20E3?))*/yu;
|
|
5434
|
+
LATIN_RE = /(?:[\x20-\x7E\xA0-\xFF](?!\uFE0F)){1,1000}/y;
|
|
5435
|
+
MODIFIER_RE = /\p{M}+/gu;
|
|
5436
|
+
NO_TRUNCATION = { limit: Infinity, ellipsis: "" };
|
|
5437
|
+
getStringTruncatedWidth = (input, truncationOptions = {}, widthOptions = {}) => {
|
|
5438
|
+
const LIMIT = truncationOptions.limit ?? Infinity;
|
|
5439
|
+
const ELLIPSIS = truncationOptions.ellipsis ?? "";
|
|
5440
|
+
const ELLIPSIS_WIDTH = truncationOptions?.ellipsisWidth ?? (ELLIPSIS ? getStringTruncatedWidth(ELLIPSIS, NO_TRUNCATION, widthOptions).width : 0);
|
|
5441
|
+
const ANSI_WIDTH = 0;
|
|
5442
|
+
const CONTROL_WIDTH = widthOptions.controlWidth ?? 0;
|
|
5443
|
+
const TAB_WIDTH = widthOptions.tabWidth ?? 8;
|
|
5444
|
+
const EMOJI_WIDTH = widthOptions.emojiWidth ?? 2;
|
|
5445
|
+
const FULL_WIDTH_WIDTH = 2;
|
|
5446
|
+
const REGULAR_WIDTH = widthOptions.regularWidth ?? 1;
|
|
5447
|
+
const WIDE_WIDTH = widthOptions.wideWidth ?? FULL_WIDTH_WIDTH;
|
|
5448
|
+
const PARSE_BLOCKS = [
|
|
5449
|
+
[LATIN_RE, REGULAR_WIDTH],
|
|
5450
|
+
[ANSI_RE, ANSI_WIDTH],
|
|
5451
|
+
[CONTROL_RE, CONTROL_WIDTH],
|
|
5452
|
+
[TAB_RE, TAB_WIDTH],
|
|
5453
|
+
[EMOJI_RE, EMOJI_WIDTH],
|
|
5454
|
+
[CJKT_WIDE_RE, WIDE_WIDTH]
|
|
5455
|
+
];
|
|
5456
|
+
let indexPrev = 0;
|
|
5457
|
+
let index = 0;
|
|
5458
|
+
let length = input.length;
|
|
5459
|
+
let lengthExtra = 0;
|
|
5460
|
+
let truncationEnabled = false;
|
|
5461
|
+
let truncationIndex = length;
|
|
5462
|
+
let truncationLimit = Math.max(0, LIMIT - ELLIPSIS_WIDTH);
|
|
5463
|
+
let unmatchedStart = 0;
|
|
5464
|
+
let unmatchedEnd = 0;
|
|
5465
|
+
let width = 0;
|
|
5466
|
+
let widthExtra = 0;
|
|
5467
|
+
outer: while (true) {
|
|
5468
|
+
if (unmatchedEnd > unmatchedStart || index >= length && index > indexPrev) {
|
|
5469
|
+
const unmatched = input.slice(unmatchedStart, unmatchedEnd) || input.slice(indexPrev, index);
|
|
5470
|
+
lengthExtra = 0;
|
|
5471
|
+
for (const char of unmatched.replaceAll(MODIFIER_RE, "")) {
|
|
5472
|
+
const codePoint = char.codePointAt(0) || 0;
|
|
5473
|
+
if (isFullWidth(codePoint)) {
|
|
5474
|
+
widthExtra = FULL_WIDTH_WIDTH;
|
|
5475
|
+
} else if (isWideNotCJKTNotEmoji(codePoint)) {
|
|
5476
|
+
widthExtra = WIDE_WIDTH;
|
|
5477
|
+
} else {
|
|
5478
|
+
widthExtra = REGULAR_WIDTH;
|
|
5479
|
+
}
|
|
5480
|
+
if (width + widthExtra > truncationLimit) {
|
|
5481
|
+
truncationIndex = Math.min(truncationIndex, Math.max(unmatchedStart, indexPrev) + lengthExtra);
|
|
5482
|
+
}
|
|
5483
|
+
if (width + widthExtra > LIMIT) {
|
|
5484
|
+
truncationEnabled = true;
|
|
5485
|
+
break outer;
|
|
5486
|
+
}
|
|
5487
|
+
lengthExtra += char.length;
|
|
5488
|
+
width += widthExtra;
|
|
5489
|
+
}
|
|
5490
|
+
unmatchedStart = unmatchedEnd = 0;
|
|
5491
|
+
}
|
|
5492
|
+
if (index >= length) {
|
|
5493
|
+
break outer;
|
|
5494
|
+
}
|
|
5495
|
+
for (let i = 0, l = PARSE_BLOCKS.length; i < l; i++) {
|
|
5496
|
+
const [BLOCK_RE, BLOCK_WIDTH] = PARSE_BLOCKS[i];
|
|
5497
|
+
BLOCK_RE.lastIndex = index;
|
|
5498
|
+
if (BLOCK_RE.test(input)) {
|
|
5499
|
+
lengthExtra = BLOCK_RE === CJKT_WIDE_RE ? getCodePointsLength(input.slice(index, BLOCK_RE.lastIndex)) : BLOCK_RE === EMOJI_RE ? 1 : BLOCK_RE.lastIndex - index;
|
|
5500
|
+
widthExtra = lengthExtra * BLOCK_WIDTH;
|
|
5501
|
+
if (width + widthExtra > truncationLimit) {
|
|
5502
|
+
truncationIndex = Math.min(truncationIndex, index + Math.floor((truncationLimit - width) / BLOCK_WIDTH));
|
|
5503
|
+
}
|
|
5504
|
+
if (width + widthExtra > LIMIT) {
|
|
5505
|
+
truncationEnabled = true;
|
|
5506
|
+
break outer;
|
|
5507
|
+
}
|
|
5508
|
+
width += widthExtra;
|
|
5509
|
+
unmatchedStart = indexPrev;
|
|
5510
|
+
unmatchedEnd = index;
|
|
5511
|
+
index = indexPrev = BLOCK_RE.lastIndex;
|
|
5512
|
+
continue outer;
|
|
5513
|
+
}
|
|
5514
|
+
}
|
|
5515
|
+
index += 1;
|
|
5516
|
+
}
|
|
5517
|
+
return {
|
|
5518
|
+
width: truncationEnabled ? truncationLimit : width,
|
|
5519
|
+
index: truncationEnabled ? truncationIndex : length,
|
|
5520
|
+
truncated: truncationEnabled,
|
|
5521
|
+
ellipsed: truncationEnabled && LIMIT >= ELLIPSIS_WIDTH
|
|
5522
|
+
};
|
|
5523
|
+
};
|
|
5524
|
+
dist_default2 = getStringTruncatedWidth;
|
|
5525
|
+
}
|
|
5526
|
+
});
|
|
5527
|
+
|
|
5528
|
+
// ../../node_modules/.pnpm/fast-string-width@3.0.2/node_modules/fast-string-width/dist/index.js
|
|
5529
|
+
var NO_TRUNCATION2, fastStringWidth, dist_default3;
|
|
5530
|
+
var init_dist3 = __esm({
|
|
5531
|
+
"../../node_modules/.pnpm/fast-string-width@3.0.2/node_modules/fast-string-width/dist/index.js"() {
|
|
5532
|
+
init_dist2();
|
|
5533
|
+
NO_TRUNCATION2 = {
|
|
5534
|
+
limit: Infinity,
|
|
5535
|
+
ellipsis: "",
|
|
5536
|
+
ellipsisWidth: 0
|
|
5537
|
+
};
|
|
5538
|
+
fastStringWidth = (input, options = {}) => {
|
|
5539
|
+
return dist_default2(input, NO_TRUNCATION2, options).width;
|
|
5540
|
+
};
|
|
5541
|
+
dist_default3 = fastStringWidth;
|
|
5542
|
+
}
|
|
5543
|
+
});
|
|
5544
|
+
|
|
5545
|
+
// ../../node_modules/.pnpm/fast-wrap-ansi@0.2.0/node_modules/fast-wrap-ansi/lib/main.js
|
|
5546
|
+
function wrapAnsi(string4, columns, options) {
|
|
5547
|
+
return String(string4).normalize().split(CRLF_OR_LF).map((line) => exec(line, columns, options)).join("\n");
|
|
5548
|
+
}
|
|
5549
|
+
var ESC, CSI, END_CODE, ANSI_ESCAPE_BELL, ANSI_CSI, ANSI_OSC, ANSI_SGR_TERMINATOR, ANSI_ESCAPE_LINK, GROUP_REGEX, getClosingCode, wrapAnsiCode, wrapAnsiHyperlink, wrapWord, stringVisibleTrimSpacesRight, exec, CRLF_OR_LF;
|
|
5550
|
+
var init_main = __esm({
|
|
5551
|
+
"../../node_modules/.pnpm/fast-wrap-ansi@0.2.0/node_modules/fast-wrap-ansi/lib/main.js"() {
|
|
5552
|
+
init_dist3();
|
|
5553
|
+
ESC = "\x1B";
|
|
5554
|
+
CSI = "\x9B";
|
|
5555
|
+
END_CODE = 39;
|
|
5556
|
+
ANSI_ESCAPE_BELL = "\x07";
|
|
5557
|
+
ANSI_CSI = "[";
|
|
5558
|
+
ANSI_OSC = "]";
|
|
5559
|
+
ANSI_SGR_TERMINATOR = "m";
|
|
5560
|
+
ANSI_ESCAPE_LINK = `${ANSI_OSC}8;;`;
|
|
5561
|
+
GROUP_REGEX = new RegExp(`(?:\\${ANSI_CSI}(?<code>\\d+)m|\\${ANSI_ESCAPE_LINK}(?<uri>.*)${ANSI_ESCAPE_BELL})`, "y");
|
|
5562
|
+
getClosingCode = (openingCode) => {
|
|
5563
|
+
if (openingCode >= 30 && openingCode <= 37)
|
|
5564
|
+
return 39;
|
|
5565
|
+
if (openingCode >= 90 && openingCode <= 97)
|
|
5566
|
+
return 39;
|
|
5567
|
+
if (openingCode >= 40 && openingCode <= 47)
|
|
5568
|
+
return 49;
|
|
5569
|
+
if (openingCode >= 100 && openingCode <= 107)
|
|
5570
|
+
return 49;
|
|
5571
|
+
if (openingCode === 1 || openingCode === 2)
|
|
5572
|
+
return 22;
|
|
5573
|
+
if (openingCode === 3)
|
|
5574
|
+
return 23;
|
|
5575
|
+
if (openingCode === 4)
|
|
5576
|
+
return 24;
|
|
5577
|
+
if (openingCode === 7)
|
|
5578
|
+
return 27;
|
|
5579
|
+
if (openingCode === 8)
|
|
5580
|
+
return 28;
|
|
5581
|
+
if (openingCode === 9)
|
|
5582
|
+
return 29;
|
|
5583
|
+
if (openingCode === 0)
|
|
5584
|
+
return 0;
|
|
5585
|
+
return void 0;
|
|
5586
|
+
};
|
|
5587
|
+
wrapAnsiCode = (code) => `${ESC}${ANSI_CSI}${code}${ANSI_SGR_TERMINATOR}`;
|
|
5588
|
+
wrapAnsiHyperlink = (url2) => `${ESC}${ANSI_ESCAPE_LINK}${url2}${ANSI_ESCAPE_BELL}`;
|
|
5589
|
+
wrapWord = (rows, word, columns) => {
|
|
5590
|
+
const characters = word[Symbol.iterator]();
|
|
5591
|
+
let isInsideEscape = false;
|
|
5592
|
+
let isInsideLinkEscape = false;
|
|
5593
|
+
let lastRow = rows.at(-1);
|
|
5594
|
+
let visible = lastRow === void 0 ? 0 : dist_default3(lastRow);
|
|
5595
|
+
let currentCharacter = characters.next();
|
|
5596
|
+
let nextCharacter = characters.next();
|
|
5597
|
+
let rawCharacterIndex = 0;
|
|
5598
|
+
while (!currentCharacter.done) {
|
|
5599
|
+
const character = currentCharacter.value;
|
|
5600
|
+
const characterLength = dist_default3(character);
|
|
5601
|
+
if (visible + characterLength <= columns) {
|
|
5602
|
+
rows[rows.length - 1] += character;
|
|
5603
|
+
} else {
|
|
5604
|
+
rows.push(character);
|
|
5605
|
+
visible = 0;
|
|
5606
|
+
}
|
|
5607
|
+
if (character === ESC || character === CSI) {
|
|
5608
|
+
isInsideEscape = true;
|
|
5609
|
+
isInsideLinkEscape = word.startsWith(ANSI_ESCAPE_LINK, rawCharacterIndex + 1);
|
|
5610
|
+
}
|
|
5611
|
+
if (isInsideEscape) {
|
|
5612
|
+
if (isInsideLinkEscape) {
|
|
5613
|
+
if (character === ANSI_ESCAPE_BELL) {
|
|
5614
|
+
isInsideEscape = false;
|
|
5615
|
+
isInsideLinkEscape = false;
|
|
5616
|
+
}
|
|
5617
|
+
} else if (character === ANSI_SGR_TERMINATOR) {
|
|
5618
|
+
isInsideEscape = false;
|
|
5619
|
+
}
|
|
5620
|
+
} else {
|
|
5621
|
+
visible += characterLength;
|
|
5622
|
+
if (visible === columns && !nextCharacter.done) {
|
|
5623
|
+
rows.push("");
|
|
5624
|
+
visible = 0;
|
|
5625
|
+
}
|
|
5626
|
+
}
|
|
5627
|
+
currentCharacter = nextCharacter;
|
|
5628
|
+
nextCharacter = characters.next();
|
|
5629
|
+
rawCharacterIndex += character.length;
|
|
5630
|
+
}
|
|
5631
|
+
lastRow = rows.at(-1);
|
|
5632
|
+
if (!visible && lastRow !== void 0 && lastRow.length && rows.length > 1) {
|
|
5633
|
+
rows[rows.length - 2] += rows.pop();
|
|
5634
|
+
}
|
|
5635
|
+
};
|
|
5636
|
+
stringVisibleTrimSpacesRight = (string4) => {
|
|
5637
|
+
const words = string4.split(" ");
|
|
5638
|
+
let last = words.length;
|
|
5639
|
+
while (last) {
|
|
5640
|
+
if (dist_default3(words[last - 1])) {
|
|
5641
|
+
break;
|
|
5642
|
+
}
|
|
5643
|
+
last--;
|
|
5644
|
+
}
|
|
5645
|
+
if (last === words.length) {
|
|
5646
|
+
return string4;
|
|
5647
|
+
}
|
|
5648
|
+
return words.slice(0, last).join(" ") + words.slice(last).join("");
|
|
5649
|
+
};
|
|
5650
|
+
exec = (string4, columns, options = {}) => {
|
|
5651
|
+
if (options.trim !== false && string4.trim() === "") {
|
|
5652
|
+
return "";
|
|
5653
|
+
}
|
|
5654
|
+
let returnValue = "";
|
|
5655
|
+
let escapeCode;
|
|
5656
|
+
let escapeUrl;
|
|
5657
|
+
const words = string4.split(" ");
|
|
5658
|
+
let rows = [""];
|
|
5659
|
+
let rowLength = 0;
|
|
5660
|
+
for (let index = 0; index < words.length; index++) {
|
|
5661
|
+
const word = words[index];
|
|
5662
|
+
if (options.trim !== false) {
|
|
5663
|
+
const row = rows.at(-1) ?? "";
|
|
5664
|
+
const trimmed = row.trimStart();
|
|
5665
|
+
if (row.length !== trimmed.length) {
|
|
5666
|
+
rows[rows.length - 1] = trimmed;
|
|
5667
|
+
rowLength = dist_default3(trimmed);
|
|
5668
|
+
}
|
|
5669
|
+
}
|
|
5670
|
+
if (index !== 0) {
|
|
5671
|
+
if (rowLength >= columns && (options.wordWrap === false || options.trim === false)) {
|
|
5672
|
+
rows.push("");
|
|
5673
|
+
rowLength = 0;
|
|
5674
|
+
}
|
|
5675
|
+
if (rowLength || options.trim === false) {
|
|
5676
|
+
rows[rows.length - 1] += " ";
|
|
5677
|
+
rowLength++;
|
|
5678
|
+
}
|
|
5679
|
+
}
|
|
5680
|
+
const wordLength = dist_default3(word);
|
|
5681
|
+
if (options.hard && wordLength > columns) {
|
|
5682
|
+
const remainingColumns = columns - rowLength;
|
|
5683
|
+
const breaksStartingThisLine = 1 + Math.floor((wordLength - remainingColumns - 1) / columns);
|
|
5684
|
+
const breaksStartingNextLine = Math.floor((wordLength - 1) / columns);
|
|
5685
|
+
if (breaksStartingNextLine < breaksStartingThisLine) {
|
|
5686
|
+
rows.push("");
|
|
5687
|
+
}
|
|
5688
|
+
wrapWord(rows, word, columns);
|
|
5689
|
+
rowLength = dist_default3(rows.at(-1) ?? "");
|
|
5690
|
+
continue;
|
|
5691
|
+
}
|
|
5692
|
+
if (rowLength + wordLength > columns && rowLength && wordLength) {
|
|
5693
|
+
if (options.wordWrap === false && rowLength < columns) {
|
|
5694
|
+
wrapWord(rows, word, columns);
|
|
5695
|
+
rowLength = dist_default3(rows.at(-1) ?? "");
|
|
5696
|
+
continue;
|
|
5697
|
+
}
|
|
5698
|
+
rows.push("");
|
|
5699
|
+
rowLength = 0;
|
|
5700
|
+
}
|
|
5701
|
+
if (rowLength + wordLength > columns && options.wordWrap === false) {
|
|
5702
|
+
wrapWord(rows, word, columns);
|
|
5703
|
+
rowLength = dist_default3(rows.at(-1) ?? "");
|
|
5704
|
+
continue;
|
|
5705
|
+
}
|
|
5706
|
+
rows[rows.length - 1] += word;
|
|
5707
|
+
rowLength += wordLength;
|
|
5708
|
+
}
|
|
5709
|
+
if (options.trim !== false) {
|
|
5710
|
+
rows = rows.map((row) => stringVisibleTrimSpacesRight(row));
|
|
5711
|
+
}
|
|
5712
|
+
const preString = rows.join("\n");
|
|
5713
|
+
let inSurrogate = false;
|
|
5714
|
+
for (let i = 0; i < preString.length; i++) {
|
|
5715
|
+
const character = preString[i];
|
|
5716
|
+
returnValue += character;
|
|
5717
|
+
if (!inSurrogate) {
|
|
5718
|
+
inSurrogate = character >= "\uD800" && character <= "\uDBFF";
|
|
5719
|
+
if (inSurrogate) {
|
|
5720
|
+
continue;
|
|
5721
|
+
}
|
|
5722
|
+
} else {
|
|
5723
|
+
inSurrogate = false;
|
|
5724
|
+
}
|
|
5725
|
+
if (character === ESC || character === CSI) {
|
|
5726
|
+
GROUP_REGEX.lastIndex = i + 1;
|
|
5727
|
+
const groupsResult = GROUP_REGEX.exec(preString);
|
|
5728
|
+
const groups = groupsResult?.groups;
|
|
5729
|
+
if (groups?.code !== void 0) {
|
|
5730
|
+
const code = Number.parseFloat(groups.code);
|
|
5731
|
+
escapeCode = code === END_CODE ? void 0 : code;
|
|
5732
|
+
} else if (groups?.uri !== void 0) {
|
|
5733
|
+
escapeUrl = groups.uri.length === 0 ? void 0 : groups.uri;
|
|
5734
|
+
}
|
|
5735
|
+
}
|
|
5736
|
+
if (preString[i + 1] === "\n") {
|
|
5737
|
+
if (escapeUrl) {
|
|
5738
|
+
returnValue += wrapAnsiHyperlink("");
|
|
5739
|
+
}
|
|
5740
|
+
const closingCode = escapeCode ? getClosingCode(escapeCode) : void 0;
|
|
5741
|
+
if (escapeCode && closingCode) {
|
|
5742
|
+
returnValue += wrapAnsiCode(closingCode);
|
|
5743
|
+
}
|
|
5744
|
+
} else if (character === "\n") {
|
|
5745
|
+
if (escapeCode && getClosingCode(escapeCode)) {
|
|
5746
|
+
returnValue += wrapAnsiCode(escapeCode);
|
|
5747
|
+
}
|
|
5748
|
+
if (escapeUrl) {
|
|
5749
|
+
returnValue += wrapAnsiHyperlink(escapeUrl);
|
|
5750
|
+
}
|
|
5751
|
+
}
|
|
5752
|
+
}
|
|
5753
|
+
return returnValue;
|
|
5754
|
+
};
|
|
5755
|
+
CRLF_OR_LF = /\r?\n/;
|
|
5756
|
+
}
|
|
5757
|
+
});
|
|
5758
|
+
|
|
5759
|
+
// ../../node_modules/.pnpm/@inquirer+core@11.1.9_@types+node@22.19.17/node_modules/@inquirer/core/dist/lib/utils.js
|
|
5760
|
+
function breakLines(content, width) {
|
|
5761
|
+
return content.split("\n").flatMap((line) => wrapAnsi(line, width, { trim: false, hard: true }).split("\n").map((str) => str.trimEnd())).join("\n");
|
|
5762
|
+
}
|
|
5763
|
+
function readlineWidth() {
|
|
5764
|
+
return (0, import_cli_width.default)({ defaultWidth: 80, output: readline().output });
|
|
5765
|
+
}
|
|
5766
|
+
var import_cli_width;
|
|
5767
|
+
var init_utils2 = __esm({
|
|
5768
|
+
"../../node_modules/.pnpm/@inquirer+core@11.1.9_@types+node@22.19.17/node_modules/@inquirer/core/dist/lib/utils.js"() {
|
|
5769
|
+
import_cli_width = __toESM(require_cli_width(), 1);
|
|
5770
|
+
init_main();
|
|
5771
|
+
init_hook_engine();
|
|
5772
|
+
}
|
|
5773
|
+
});
|
|
5774
|
+
|
|
5775
|
+
// ../../node_modules/.pnpm/@inquirer+core@11.1.9_@types+node@22.19.17/node_modules/@inquirer/core/dist/lib/pagination/use-pagination.js
|
|
5776
|
+
function usePointerPosition({ active, renderedItems, pageSize, loop }) {
|
|
5777
|
+
const state = useRef({
|
|
5778
|
+
lastPointer: active,
|
|
5779
|
+
lastActive: void 0
|
|
5780
|
+
});
|
|
5781
|
+
const { lastPointer, lastActive } = state.current;
|
|
5782
|
+
const middle = Math.floor(pageSize / 2);
|
|
5783
|
+
const renderedLength = renderedItems.reduce((acc, item) => acc + item.length, 0);
|
|
5784
|
+
const defaultPointerPosition = renderedItems.slice(0, active).reduce((acc, item) => acc + item.length, 0);
|
|
5785
|
+
let pointer = defaultPointerPosition;
|
|
5786
|
+
if (renderedLength > pageSize) {
|
|
5787
|
+
if (loop) {
|
|
5788
|
+
pointer = lastPointer;
|
|
5789
|
+
if (
|
|
5790
|
+
// First render, skip this logic.
|
|
5791
|
+
lastActive != null && // Only move the pointer down when the user moves down.
|
|
5792
|
+
lastActive < active && // Check user didn't move up across page boundary.
|
|
5793
|
+
active - lastActive < pageSize
|
|
5794
|
+
) {
|
|
5795
|
+
pointer = Math.min(
|
|
5796
|
+
// Furthest allowed position for the pointer is the middle of the list
|
|
5797
|
+
middle,
|
|
5798
|
+
Math.abs(active - lastActive) === 1 ? Math.min(
|
|
5799
|
+
// Move the pointer at most the height of the last active item.
|
|
5800
|
+
lastPointer + (renderedItems[lastActive]?.length ?? 0),
|
|
5801
|
+
// If the user moved by one item, move the pointer to the natural position of the active item as
|
|
5802
|
+
// long as it doesn't move the cursor up.
|
|
5803
|
+
Math.max(defaultPointerPosition, lastPointer)
|
|
5804
|
+
) : (
|
|
5805
|
+
// Otherwise, move the pointer down by the difference between the active and last active item.
|
|
5806
|
+
lastPointer + active - lastActive
|
|
5807
|
+
)
|
|
5808
|
+
);
|
|
5809
|
+
}
|
|
5810
|
+
} else {
|
|
5811
|
+
const spaceUnderActive = renderedItems.slice(active).reduce((acc, item) => acc + item.length, 0);
|
|
5812
|
+
pointer = spaceUnderActive < pageSize - middle ? (
|
|
5813
|
+
// If the active item is near the end of the list, progressively move the cursor towards the end.
|
|
5814
|
+
pageSize - spaceUnderActive
|
|
5815
|
+
) : (
|
|
5816
|
+
// Otherwise, progressively move the pointer to the middle of the list.
|
|
5817
|
+
Math.min(defaultPointerPosition, middle)
|
|
5818
|
+
);
|
|
5819
|
+
}
|
|
5820
|
+
}
|
|
5821
|
+
state.current.lastPointer = pointer;
|
|
5822
|
+
state.current.lastActive = active;
|
|
5823
|
+
return pointer;
|
|
5824
|
+
}
|
|
5825
|
+
function usePagination({ items, active, renderItem, pageSize, loop = true }) {
|
|
5826
|
+
const width = readlineWidth();
|
|
5827
|
+
const bound = (num) => (num % items.length + items.length) % items.length;
|
|
5828
|
+
const renderedItems = items.map((item, index) => {
|
|
5829
|
+
if (item == null)
|
|
5830
|
+
return [];
|
|
5831
|
+
return breakLines(renderItem({ item, index, isActive: index === active }), width).split("\n");
|
|
5832
|
+
});
|
|
5833
|
+
const renderedLength = renderedItems.reduce((acc, item) => acc + item.length, 0);
|
|
5834
|
+
const renderItemAtIndex = (index) => renderedItems[index] ?? [];
|
|
5835
|
+
const pointer = usePointerPosition({ active, renderedItems, pageSize, loop });
|
|
5836
|
+
const activeItem = renderItemAtIndex(active).slice(0, pageSize);
|
|
5837
|
+
const activeItemPosition = pointer + activeItem.length <= pageSize ? pointer : pageSize - activeItem.length;
|
|
5838
|
+
const pageBuffer = Array.from({ length: pageSize });
|
|
5839
|
+
pageBuffer.splice(activeItemPosition, activeItem.length, ...activeItem);
|
|
5840
|
+
const itemVisited = /* @__PURE__ */ new Set([active]);
|
|
5841
|
+
let bufferPointer = activeItemPosition + activeItem.length;
|
|
5842
|
+
let itemPointer = bound(active + 1);
|
|
5843
|
+
while (bufferPointer < pageSize && !itemVisited.has(itemPointer) && (loop && renderedLength > pageSize ? itemPointer !== active : itemPointer > active)) {
|
|
5844
|
+
const lines = renderItemAtIndex(itemPointer);
|
|
5845
|
+
const linesToAdd = lines.slice(0, pageSize - bufferPointer);
|
|
5846
|
+
pageBuffer.splice(bufferPointer, linesToAdd.length, ...linesToAdd);
|
|
5847
|
+
itemVisited.add(itemPointer);
|
|
5848
|
+
bufferPointer += linesToAdd.length;
|
|
5849
|
+
itemPointer = bound(itemPointer + 1);
|
|
5850
|
+
}
|
|
5851
|
+
bufferPointer = activeItemPosition - 1;
|
|
5852
|
+
itemPointer = bound(active - 1);
|
|
5853
|
+
while (bufferPointer >= 0 && !itemVisited.has(itemPointer) && (loop && renderedLength > pageSize ? itemPointer !== active : itemPointer < active)) {
|
|
5854
|
+
const lines = renderItemAtIndex(itemPointer);
|
|
5855
|
+
const linesToAdd = lines.slice(Math.max(0, lines.length - bufferPointer - 1));
|
|
5856
|
+
pageBuffer.splice(bufferPointer - linesToAdd.length + 1, linesToAdd.length, ...linesToAdd);
|
|
5857
|
+
itemVisited.add(itemPointer);
|
|
5858
|
+
bufferPointer -= linesToAdd.length;
|
|
5859
|
+
itemPointer = bound(itemPointer - 1);
|
|
5860
|
+
}
|
|
5861
|
+
return pageBuffer.filter((line) => typeof line === "string").join("\n");
|
|
5862
|
+
}
|
|
5863
|
+
var init_use_pagination = __esm({
|
|
5864
|
+
"../../node_modules/.pnpm/@inquirer+core@11.1.9_@types+node@22.19.17/node_modules/@inquirer/core/dist/lib/pagination/use-pagination.js"() {
|
|
5865
|
+
init_use_ref();
|
|
5866
|
+
init_utils2();
|
|
5867
|
+
}
|
|
5868
|
+
});
|
|
5869
|
+
|
|
5870
|
+
// ../../node_modules/.pnpm/mute-stream@3.0.0/node_modules/mute-stream/lib/index.js
|
|
5871
|
+
var require_lib = __commonJS({
|
|
5872
|
+
"../../node_modules/.pnpm/mute-stream@3.0.0/node_modules/mute-stream/lib/index.js"(exports, module) {
|
|
5873
|
+
var Stream = __require("stream");
|
|
5874
|
+
var MuteStream2 = class extends Stream {
|
|
5875
|
+
#isTTY = null;
|
|
5876
|
+
constructor(opts = {}) {
|
|
5877
|
+
super(opts);
|
|
5878
|
+
this.writable = this.readable = true;
|
|
5879
|
+
this.muted = false;
|
|
5880
|
+
this.on("pipe", this._onpipe);
|
|
5881
|
+
this.replace = opts.replace;
|
|
5882
|
+
this._prompt = opts.prompt || null;
|
|
5883
|
+
this._hadControl = false;
|
|
5884
|
+
}
|
|
5885
|
+
#destSrc(key, def) {
|
|
5886
|
+
if (this._dest) {
|
|
5887
|
+
return this._dest[key];
|
|
5888
|
+
}
|
|
5889
|
+
if (this._src) {
|
|
5890
|
+
return this._src[key];
|
|
5891
|
+
}
|
|
5892
|
+
return def;
|
|
5893
|
+
}
|
|
5894
|
+
#proxy(method, ...args) {
|
|
5895
|
+
if (typeof this._dest?.[method] === "function") {
|
|
5896
|
+
this._dest[method](...args);
|
|
5897
|
+
}
|
|
5898
|
+
if (typeof this._src?.[method] === "function") {
|
|
5899
|
+
this._src[method](...args);
|
|
5900
|
+
}
|
|
5901
|
+
}
|
|
5902
|
+
get isTTY() {
|
|
5903
|
+
if (this.#isTTY !== null) {
|
|
5904
|
+
return this.#isTTY;
|
|
5905
|
+
}
|
|
5906
|
+
return this.#destSrc("isTTY", false);
|
|
5907
|
+
}
|
|
5908
|
+
// basically just get replace the getter/setter with a regular value
|
|
5909
|
+
set isTTY(val) {
|
|
5910
|
+
this.#isTTY = val;
|
|
5911
|
+
}
|
|
5912
|
+
get rows() {
|
|
5913
|
+
return this.#destSrc("rows");
|
|
5914
|
+
}
|
|
5915
|
+
get columns() {
|
|
5916
|
+
return this.#destSrc("columns");
|
|
5917
|
+
}
|
|
5918
|
+
mute() {
|
|
5919
|
+
this.muted = true;
|
|
5920
|
+
}
|
|
5921
|
+
unmute() {
|
|
5922
|
+
this.muted = false;
|
|
5923
|
+
}
|
|
5924
|
+
_onpipe(src) {
|
|
5925
|
+
this._src = src;
|
|
5926
|
+
}
|
|
5927
|
+
pipe(dest, options) {
|
|
5928
|
+
this._dest = dest;
|
|
5929
|
+
return super.pipe(dest, options);
|
|
5930
|
+
}
|
|
5931
|
+
pause() {
|
|
5932
|
+
if (this._src) {
|
|
5933
|
+
return this._src.pause();
|
|
5934
|
+
}
|
|
5935
|
+
}
|
|
5936
|
+
resume() {
|
|
5937
|
+
if (this._src) {
|
|
5938
|
+
return this._src.resume();
|
|
5939
|
+
}
|
|
5940
|
+
}
|
|
5941
|
+
write(c3) {
|
|
5942
|
+
if (this.muted) {
|
|
5943
|
+
if (!this.replace) {
|
|
5944
|
+
return true;
|
|
5945
|
+
}
|
|
5946
|
+
if (c3.match(/^\u001b/)) {
|
|
5947
|
+
if (c3.indexOf(this._prompt) === 0) {
|
|
5948
|
+
c3 = c3.slice(this._prompt.length);
|
|
5949
|
+
c3 = c3.replace(/./g, this.replace);
|
|
5950
|
+
c3 = this._prompt + c3;
|
|
5951
|
+
}
|
|
5952
|
+
this._hadControl = true;
|
|
5953
|
+
return this.emit("data", c3);
|
|
5954
|
+
} else {
|
|
5955
|
+
if (this._prompt && this._hadControl && c3.indexOf(this._prompt) === 0) {
|
|
5956
|
+
this._hadControl = false;
|
|
5957
|
+
this.emit("data", this._prompt);
|
|
5958
|
+
c3 = c3.slice(this._prompt.length);
|
|
5959
|
+
}
|
|
5960
|
+
c3 = c3.toString().replace(/./g, this.replace);
|
|
5961
|
+
}
|
|
5962
|
+
}
|
|
5963
|
+
this.emit("data", c3);
|
|
5964
|
+
}
|
|
5965
|
+
end(c3) {
|
|
5966
|
+
if (this.muted) {
|
|
5967
|
+
if (c3 && this.replace) {
|
|
5968
|
+
c3 = c3.toString().replace(/./g, this.replace);
|
|
5969
|
+
} else {
|
|
5970
|
+
c3 = null;
|
|
5971
|
+
}
|
|
5972
|
+
}
|
|
5973
|
+
if (c3) {
|
|
5974
|
+
this.emit("data", c3);
|
|
5975
|
+
}
|
|
5976
|
+
this.emit("end");
|
|
5977
|
+
}
|
|
5978
|
+
destroy(...args) {
|
|
5979
|
+
return this.#proxy("destroy", ...args);
|
|
5980
|
+
}
|
|
5981
|
+
destroySoon(...args) {
|
|
5982
|
+
return this.#proxy("destroySoon", ...args);
|
|
5983
|
+
}
|
|
5984
|
+
close(...args) {
|
|
5985
|
+
return this.#proxy("close", ...args);
|
|
5986
|
+
}
|
|
5987
|
+
};
|
|
5988
|
+
module.exports = MuteStream2;
|
|
5989
|
+
}
|
|
5990
|
+
});
|
|
5991
|
+
|
|
5992
|
+
// ../../node_modules/.pnpm/signal-exit@4.1.0/node_modules/signal-exit/dist/mjs/signals.js
|
|
5993
|
+
var signals;
|
|
5994
|
+
var init_signals = __esm({
|
|
5995
|
+
"../../node_modules/.pnpm/signal-exit@4.1.0/node_modules/signal-exit/dist/mjs/signals.js"() {
|
|
5996
|
+
signals = [];
|
|
5997
|
+
signals.push("SIGHUP", "SIGINT", "SIGTERM");
|
|
5998
|
+
if (process.platform !== "win32") {
|
|
5999
|
+
signals.push(
|
|
6000
|
+
"SIGALRM",
|
|
6001
|
+
"SIGABRT",
|
|
6002
|
+
"SIGVTALRM",
|
|
6003
|
+
"SIGXCPU",
|
|
6004
|
+
"SIGXFSZ",
|
|
6005
|
+
"SIGUSR2",
|
|
6006
|
+
"SIGTRAP",
|
|
6007
|
+
"SIGSYS",
|
|
6008
|
+
"SIGQUIT",
|
|
6009
|
+
"SIGIOT"
|
|
6010
|
+
// should detect profiler and enable/disable accordingly.
|
|
6011
|
+
// see #21
|
|
6012
|
+
// 'SIGPROF'
|
|
6013
|
+
);
|
|
6014
|
+
}
|
|
6015
|
+
if (process.platform === "linux") {
|
|
6016
|
+
signals.push("SIGIO", "SIGPOLL", "SIGPWR", "SIGSTKFLT");
|
|
6017
|
+
}
|
|
6018
|
+
}
|
|
6019
|
+
});
|
|
6020
|
+
|
|
6021
|
+
// ../../node_modules/.pnpm/signal-exit@4.1.0/node_modules/signal-exit/dist/mjs/index.js
|
|
6022
|
+
var processOk, kExitEmitter, global, ObjectDefineProperty, Emitter, SignalExitBase, signalExitWrap, SignalExitFallback, SignalExit, process3, onExit, load, unload;
|
|
6023
|
+
var init_mjs = __esm({
|
|
6024
|
+
"../../node_modules/.pnpm/signal-exit@4.1.0/node_modules/signal-exit/dist/mjs/index.js"() {
|
|
6025
|
+
init_signals();
|
|
6026
|
+
processOk = (process4) => !!process4 && typeof process4 === "object" && typeof process4.removeListener === "function" && typeof process4.emit === "function" && typeof process4.reallyExit === "function" && typeof process4.listeners === "function" && typeof process4.kill === "function" && typeof process4.pid === "number" && typeof process4.on === "function";
|
|
6027
|
+
kExitEmitter = Symbol.for("signal-exit emitter");
|
|
6028
|
+
global = globalThis;
|
|
6029
|
+
ObjectDefineProperty = Object.defineProperty.bind(Object);
|
|
6030
|
+
Emitter = class {
|
|
6031
|
+
emitted = {
|
|
6032
|
+
afterExit: false,
|
|
6033
|
+
exit: false
|
|
6034
|
+
};
|
|
6035
|
+
listeners = {
|
|
6036
|
+
afterExit: [],
|
|
6037
|
+
exit: []
|
|
6038
|
+
};
|
|
6039
|
+
count = 0;
|
|
6040
|
+
id = Math.random();
|
|
6041
|
+
constructor() {
|
|
6042
|
+
if (global[kExitEmitter]) {
|
|
6043
|
+
return global[kExitEmitter];
|
|
6044
|
+
}
|
|
6045
|
+
ObjectDefineProperty(global, kExitEmitter, {
|
|
6046
|
+
value: this,
|
|
6047
|
+
writable: false,
|
|
6048
|
+
enumerable: false,
|
|
6049
|
+
configurable: false
|
|
6050
|
+
});
|
|
6051
|
+
}
|
|
6052
|
+
on(ev, fn) {
|
|
6053
|
+
this.listeners[ev].push(fn);
|
|
6054
|
+
}
|
|
6055
|
+
removeListener(ev, fn) {
|
|
6056
|
+
const list = this.listeners[ev];
|
|
6057
|
+
const i = list.indexOf(fn);
|
|
6058
|
+
if (i === -1) {
|
|
6059
|
+
return;
|
|
6060
|
+
}
|
|
6061
|
+
if (i === 0 && list.length === 1) {
|
|
6062
|
+
list.length = 0;
|
|
6063
|
+
} else {
|
|
6064
|
+
list.splice(i, 1);
|
|
6065
|
+
}
|
|
6066
|
+
}
|
|
6067
|
+
emit(ev, code, signal) {
|
|
6068
|
+
if (this.emitted[ev]) {
|
|
6069
|
+
return false;
|
|
6070
|
+
}
|
|
6071
|
+
this.emitted[ev] = true;
|
|
6072
|
+
let ret = false;
|
|
6073
|
+
for (const fn of this.listeners[ev]) {
|
|
6074
|
+
ret = fn(code, signal) === true || ret;
|
|
6075
|
+
}
|
|
6076
|
+
if (ev === "exit") {
|
|
6077
|
+
ret = this.emit("afterExit", code, signal) || ret;
|
|
6078
|
+
}
|
|
6079
|
+
return ret;
|
|
6080
|
+
}
|
|
6081
|
+
};
|
|
6082
|
+
SignalExitBase = class {
|
|
6083
|
+
};
|
|
6084
|
+
signalExitWrap = (handler) => {
|
|
6085
|
+
return {
|
|
6086
|
+
onExit(cb, opts) {
|
|
6087
|
+
return handler.onExit(cb, opts);
|
|
6088
|
+
},
|
|
6089
|
+
load() {
|
|
6090
|
+
return handler.load();
|
|
6091
|
+
},
|
|
6092
|
+
unload() {
|
|
6093
|
+
return handler.unload();
|
|
6094
|
+
}
|
|
6095
|
+
};
|
|
6096
|
+
};
|
|
6097
|
+
SignalExitFallback = class extends SignalExitBase {
|
|
6098
|
+
onExit() {
|
|
6099
|
+
return () => {
|
|
6100
|
+
};
|
|
6101
|
+
}
|
|
6102
|
+
load() {
|
|
6103
|
+
}
|
|
6104
|
+
unload() {
|
|
6105
|
+
}
|
|
6106
|
+
};
|
|
6107
|
+
SignalExit = class extends SignalExitBase {
|
|
6108
|
+
// "SIGHUP" throws an `ENOSYS` error on Windows,
|
|
6109
|
+
// so use a supported signal instead
|
|
6110
|
+
/* c8 ignore start */
|
|
6111
|
+
#hupSig = process3.platform === "win32" ? "SIGINT" : "SIGHUP";
|
|
6112
|
+
/* c8 ignore stop */
|
|
6113
|
+
#emitter = new Emitter();
|
|
6114
|
+
#process;
|
|
6115
|
+
#originalProcessEmit;
|
|
6116
|
+
#originalProcessReallyExit;
|
|
6117
|
+
#sigListeners = {};
|
|
6118
|
+
#loaded = false;
|
|
6119
|
+
constructor(process4) {
|
|
6120
|
+
super();
|
|
6121
|
+
this.#process = process4;
|
|
6122
|
+
this.#sigListeners = {};
|
|
6123
|
+
for (const sig of signals) {
|
|
6124
|
+
this.#sigListeners[sig] = () => {
|
|
6125
|
+
const listeners = this.#process.listeners(sig);
|
|
6126
|
+
let { count } = this.#emitter;
|
|
6127
|
+
const p = process4;
|
|
6128
|
+
if (typeof p.__signal_exit_emitter__ === "object" && typeof p.__signal_exit_emitter__.count === "number") {
|
|
6129
|
+
count += p.__signal_exit_emitter__.count;
|
|
6130
|
+
}
|
|
6131
|
+
if (listeners.length === count) {
|
|
6132
|
+
this.unload();
|
|
6133
|
+
const ret = this.#emitter.emit("exit", null, sig);
|
|
6134
|
+
const s = sig === "SIGHUP" ? this.#hupSig : sig;
|
|
6135
|
+
if (!ret)
|
|
6136
|
+
process4.kill(process4.pid, s);
|
|
6137
|
+
}
|
|
6138
|
+
};
|
|
6139
|
+
}
|
|
6140
|
+
this.#originalProcessReallyExit = process4.reallyExit;
|
|
6141
|
+
this.#originalProcessEmit = process4.emit;
|
|
6142
|
+
}
|
|
6143
|
+
onExit(cb, opts) {
|
|
6144
|
+
if (!processOk(this.#process)) {
|
|
6145
|
+
return () => {
|
|
6146
|
+
};
|
|
6147
|
+
}
|
|
6148
|
+
if (this.#loaded === false) {
|
|
6149
|
+
this.load();
|
|
6150
|
+
}
|
|
6151
|
+
const ev = opts?.alwaysLast ? "afterExit" : "exit";
|
|
6152
|
+
this.#emitter.on(ev, cb);
|
|
6153
|
+
return () => {
|
|
6154
|
+
this.#emitter.removeListener(ev, cb);
|
|
6155
|
+
if (this.#emitter.listeners["exit"].length === 0 && this.#emitter.listeners["afterExit"].length === 0) {
|
|
6156
|
+
this.unload();
|
|
6157
|
+
}
|
|
6158
|
+
};
|
|
6159
|
+
}
|
|
6160
|
+
load() {
|
|
6161
|
+
if (this.#loaded) {
|
|
6162
|
+
return;
|
|
6163
|
+
}
|
|
6164
|
+
this.#loaded = true;
|
|
6165
|
+
this.#emitter.count += 1;
|
|
6166
|
+
for (const sig of signals) {
|
|
6167
|
+
try {
|
|
6168
|
+
const fn = this.#sigListeners[sig];
|
|
6169
|
+
if (fn)
|
|
6170
|
+
this.#process.on(sig, fn);
|
|
6171
|
+
} catch (_) {
|
|
6172
|
+
}
|
|
6173
|
+
}
|
|
6174
|
+
this.#process.emit = (ev, ...a) => {
|
|
6175
|
+
return this.#processEmit(ev, ...a);
|
|
6176
|
+
};
|
|
6177
|
+
this.#process.reallyExit = (code) => {
|
|
6178
|
+
return this.#processReallyExit(code);
|
|
6179
|
+
};
|
|
6180
|
+
}
|
|
6181
|
+
unload() {
|
|
6182
|
+
if (!this.#loaded) {
|
|
6183
|
+
return;
|
|
6184
|
+
}
|
|
6185
|
+
this.#loaded = false;
|
|
6186
|
+
signals.forEach((sig) => {
|
|
6187
|
+
const listener = this.#sigListeners[sig];
|
|
6188
|
+
if (!listener) {
|
|
6189
|
+
throw new Error("Listener not defined for signal: " + sig);
|
|
6190
|
+
}
|
|
6191
|
+
try {
|
|
6192
|
+
this.#process.removeListener(sig, listener);
|
|
6193
|
+
} catch (_) {
|
|
6194
|
+
}
|
|
6195
|
+
});
|
|
6196
|
+
this.#process.emit = this.#originalProcessEmit;
|
|
6197
|
+
this.#process.reallyExit = this.#originalProcessReallyExit;
|
|
6198
|
+
this.#emitter.count -= 1;
|
|
6199
|
+
}
|
|
6200
|
+
#processReallyExit(code) {
|
|
6201
|
+
if (!processOk(this.#process)) {
|
|
6202
|
+
return 0;
|
|
6203
|
+
}
|
|
6204
|
+
this.#process.exitCode = code || 0;
|
|
6205
|
+
this.#emitter.emit("exit", this.#process.exitCode, null);
|
|
6206
|
+
return this.#originalProcessReallyExit.call(this.#process, this.#process.exitCode);
|
|
6207
|
+
}
|
|
6208
|
+
#processEmit(ev, ...args) {
|
|
6209
|
+
const og = this.#originalProcessEmit;
|
|
6210
|
+
if (ev === "exit" && processOk(this.#process)) {
|
|
6211
|
+
if (typeof args[0] === "number") {
|
|
6212
|
+
this.#process.exitCode = args[0];
|
|
6213
|
+
}
|
|
6214
|
+
const ret = og.call(this.#process, ev, ...args);
|
|
6215
|
+
this.#emitter.emit("exit", this.#process.exitCode, null);
|
|
6216
|
+
return ret;
|
|
6217
|
+
} else {
|
|
6218
|
+
return og.call(this.#process, ev, ...args);
|
|
6219
|
+
}
|
|
6220
|
+
}
|
|
6221
|
+
};
|
|
6222
|
+
process3 = globalThis.process;
|
|
6223
|
+
({
|
|
6224
|
+
onExit: (
|
|
6225
|
+
/**
|
|
6226
|
+
* Called when the process is exiting, whether via signal, explicit
|
|
6227
|
+
* exit, or running out of stuff to do.
|
|
6228
|
+
*
|
|
6229
|
+
* If the global process object is not suitable for instrumentation,
|
|
6230
|
+
* then this will be a no-op.
|
|
6231
|
+
*
|
|
6232
|
+
* Returns a function that may be used to unload signal-exit.
|
|
6233
|
+
*/
|
|
6234
|
+
onExit
|
|
6235
|
+
),
|
|
6236
|
+
load: (
|
|
6237
|
+
/**
|
|
6238
|
+
* Load the listeners. Likely you never need to call this, unless
|
|
6239
|
+
* doing a rather deep integration with signal-exit functionality.
|
|
6240
|
+
* Mostly exposed for the benefit of testing.
|
|
6241
|
+
*
|
|
6242
|
+
* @internal
|
|
6243
|
+
*/
|
|
6244
|
+
load
|
|
6245
|
+
),
|
|
6246
|
+
unload: (
|
|
6247
|
+
/**
|
|
6248
|
+
* Unload the listeners. Likely you never need to call this, unless
|
|
6249
|
+
* doing a rather deep integration with signal-exit functionality.
|
|
6250
|
+
* Mostly exposed for the benefit of testing.
|
|
6251
|
+
*
|
|
6252
|
+
* @internal
|
|
6253
|
+
*/
|
|
6254
|
+
unload
|
|
6255
|
+
)
|
|
6256
|
+
} = signalExitWrap(processOk(process3) ? new SignalExit(process3) : new SignalExitFallback()));
|
|
6257
|
+
}
|
|
6258
|
+
});
|
|
6259
|
+
|
|
6260
|
+
// ../../node_modules/.pnpm/@inquirer+ansi@2.0.5/node_modules/@inquirer/ansi/dist/index.js
|
|
6261
|
+
var ESC2, cursorLeft, cursorHide, cursorShow, cursorUp, cursorDown, cursorTo, eraseLine, eraseLines;
|
|
6262
|
+
var init_dist4 = __esm({
|
|
6263
|
+
"../../node_modules/.pnpm/@inquirer+ansi@2.0.5/node_modules/@inquirer/ansi/dist/index.js"() {
|
|
6264
|
+
ESC2 = "\x1B[";
|
|
6265
|
+
cursorLeft = ESC2 + "G";
|
|
6266
|
+
cursorHide = ESC2 + "?25l";
|
|
6267
|
+
cursorShow = ESC2 + "?25h";
|
|
6268
|
+
cursorUp = (rows = 1) => rows > 0 ? `${ESC2}${rows}A` : "";
|
|
6269
|
+
cursorDown = (rows = 1) => rows > 0 ? `${ESC2}${rows}B` : "";
|
|
6270
|
+
cursorTo = (x, y) => {
|
|
6271
|
+
if (typeof y === "number" && !Number.isNaN(y)) {
|
|
6272
|
+
return `${ESC2}${y + 1};${x + 1}H`;
|
|
6273
|
+
}
|
|
6274
|
+
return `${ESC2}${x + 1}G`;
|
|
6275
|
+
};
|
|
6276
|
+
eraseLine = ESC2 + "2K";
|
|
6277
|
+
eraseLines = (lines) => lines > 0 ? (eraseLine + cursorUp(1)).repeat(lines - 1) + eraseLine + cursorLeft : "";
|
|
6278
|
+
}
|
|
6279
|
+
});
|
|
6280
|
+
|
|
6281
|
+
// ../../node_modules/.pnpm/@inquirer+core@11.1.9_@types+node@22.19.17/node_modules/@inquirer/core/dist/lib/screen-manager.js
|
|
6282
|
+
import { stripVTControlCharacters } from "node:util";
|
|
6283
|
+
var height, lastLine, ScreenManager;
|
|
6284
|
+
var init_screen_manager = __esm({
|
|
6285
|
+
"../../node_modules/.pnpm/@inquirer+core@11.1.9_@types+node@22.19.17/node_modules/@inquirer/core/dist/lib/screen-manager.js"() {
|
|
6286
|
+
init_utils2();
|
|
6287
|
+
init_dist4();
|
|
6288
|
+
height = (content) => content.split("\n").length;
|
|
6289
|
+
lastLine = (content) => content.split("\n").pop() ?? "";
|
|
6290
|
+
ScreenManager = class {
|
|
6291
|
+
// These variables are keeping information to allow correct prompt re-rendering
|
|
6292
|
+
height = 0;
|
|
6293
|
+
extraLinesUnderPrompt = 0;
|
|
6294
|
+
cursorPos;
|
|
6295
|
+
rl;
|
|
6296
|
+
constructor(rl) {
|
|
6297
|
+
this.rl = rl;
|
|
6298
|
+
this.cursorPos = rl.getCursorPos();
|
|
6299
|
+
}
|
|
6300
|
+
write(content) {
|
|
6301
|
+
this.rl.output.unmute();
|
|
6302
|
+
this.rl.output.write(content);
|
|
6303
|
+
this.rl.output.mute();
|
|
6304
|
+
}
|
|
6305
|
+
render(content, bottomContent = "") {
|
|
6306
|
+
const promptLine = lastLine(content);
|
|
6307
|
+
const rawPromptLine = stripVTControlCharacters(promptLine);
|
|
6308
|
+
let prompt = rawPromptLine;
|
|
6309
|
+
if (this.rl.line.length > 0) {
|
|
6310
|
+
prompt = prompt.slice(0, -this.rl.line.length);
|
|
6311
|
+
}
|
|
6312
|
+
this.rl.setPrompt(prompt);
|
|
6313
|
+
this.cursorPos = this.rl.getCursorPos();
|
|
6314
|
+
const width = readlineWidth();
|
|
6315
|
+
content = breakLines(content, width);
|
|
6316
|
+
bottomContent = breakLines(bottomContent, width);
|
|
6317
|
+
if (rawPromptLine.length % width === 0) {
|
|
6318
|
+
content += "\n";
|
|
6319
|
+
}
|
|
6320
|
+
let output = content + (bottomContent ? "\n" + bottomContent : "");
|
|
6321
|
+
const promptLineUpDiff = Math.floor(rawPromptLine.length / width) - this.cursorPos.rows;
|
|
6322
|
+
const bottomContentHeight = promptLineUpDiff + (bottomContent ? height(bottomContent) : 0);
|
|
6323
|
+
if (bottomContentHeight > 0)
|
|
6324
|
+
output += cursorUp(bottomContentHeight);
|
|
6325
|
+
output += cursorTo(this.cursorPos.cols);
|
|
6326
|
+
this.write(cursorDown(this.extraLinesUnderPrompt) + eraseLines(this.height) + output);
|
|
6327
|
+
this.extraLinesUnderPrompt = bottomContentHeight;
|
|
6328
|
+
this.height = height(output);
|
|
6329
|
+
}
|
|
6330
|
+
checkCursorPos() {
|
|
6331
|
+
const cursorPos = this.rl.getCursorPos();
|
|
6332
|
+
if (cursorPos.cols !== this.cursorPos.cols) {
|
|
6333
|
+
this.write(cursorTo(cursorPos.cols));
|
|
6334
|
+
this.cursorPos = cursorPos;
|
|
6335
|
+
}
|
|
6336
|
+
}
|
|
6337
|
+
done({ clearContent }) {
|
|
6338
|
+
this.rl.setPrompt("");
|
|
6339
|
+
let output = cursorDown(this.extraLinesUnderPrompt);
|
|
6340
|
+
output += clearContent ? eraseLines(this.height) : "\n";
|
|
6341
|
+
output += cursorShow;
|
|
6342
|
+
this.write(output);
|
|
6343
|
+
this.rl.close();
|
|
6344
|
+
}
|
|
6345
|
+
};
|
|
6346
|
+
}
|
|
6347
|
+
});
|
|
6348
|
+
|
|
6349
|
+
// ../../node_modules/.pnpm/@inquirer+core@11.1.9_@types+node@22.19.17/node_modules/@inquirer/core/dist/lib/promise-polyfill.js
|
|
6350
|
+
var PromisePolyfill;
|
|
6351
|
+
var init_promise_polyfill = __esm({
|
|
6352
|
+
"../../node_modules/.pnpm/@inquirer+core@11.1.9_@types+node@22.19.17/node_modules/@inquirer/core/dist/lib/promise-polyfill.js"() {
|
|
6353
|
+
PromisePolyfill = class extends Promise {
|
|
6354
|
+
// Available starting from Node 22
|
|
6355
|
+
// https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Promise/withResolvers
|
|
6356
|
+
static withResolver() {
|
|
6357
|
+
let resolve;
|
|
6358
|
+
let reject;
|
|
6359
|
+
const promise2 = new Promise((res, rej) => {
|
|
6360
|
+
resolve = res;
|
|
6361
|
+
reject = rej;
|
|
6362
|
+
});
|
|
6363
|
+
return { promise: promise2, resolve, reject };
|
|
6364
|
+
}
|
|
6365
|
+
};
|
|
6366
|
+
}
|
|
6367
|
+
});
|
|
6368
|
+
|
|
6369
|
+
// ../../node_modules/.pnpm/@inquirer+core@11.1.9_@types+node@22.19.17/node_modules/@inquirer/core/dist/lib/create-prompt.js
|
|
6370
|
+
import * as readline2 from "node:readline";
|
|
6371
|
+
import { AsyncResource as AsyncResource3 } from "node:async_hooks";
|
|
6372
|
+
import path from "node:path";
|
|
6373
|
+
function getCallSites() {
|
|
6374
|
+
const _prepareStackTrace = Error.prepareStackTrace;
|
|
6375
|
+
let result = [];
|
|
6376
|
+
try {
|
|
6377
|
+
Error.prepareStackTrace = (_, callSites) => {
|
|
6378
|
+
const callSitesWithoutCurrent = callSites.slice(1);
|
|
6379
|
+
result = callSitesWithoutCurrent;
|
|
6380
|
+
return callSitesWithoutCurrent;
|
|
6381
|
+
};
|
|
6382
|
+
new Error().stack;
|
|
6383
|
+
} catch {
|
|
6384
|
+
return result;
|
|
6385
|
+
}
|
|
6386
|
+
Error.prepareStackTrace = _prepareStackTrace;
|
|
6387
|
+
return result;
|
|
6388
|
+
}
|
|
6389
|
+
function createPrompt(view) {
|
|
6390
|
+
const callSites = getCallSites();
|
|
6391
|
+
const prompt = (config2, context = {}) => {
|
|
6392
|
+
const { input = process.stdin, signal } = context;
|
|
6393
|
+
const cleanups = /* @__PURE__ */ new Set();
|
|
6394
|
+
const output = new import_mute_stream.default();
|
|
6395
|
+
output.pipe(context.output ?? process.stdout);
|
|
6396
|
+
const rl = readline2.createInterface({
|
|
6397
|
+
terminal: true,
|
|
6398
|
+
input,
|
|
6399
|
+
output
|
|
6400
|
+
});
|
|
6401
|
+
output.mute();
|
|
6402
|
+
const screen = new ScreenManager(rl);
|
|
6403
|
+
const { promise: promise2, resolve, reject } = PromisePolyfill.withResolver();
|
|
6404
|
+
const cancel = () => reject(new CancelPromptError());
|
|
6405
|
+
if (signal) {
|
|
6406
|
+
const abort = () => reject(new AbortPromptError({ cause: signal.reason }));
|
|
6407
|
+
if (signal.aborted) {
|
|
6408
|
+
abort();
|
|
6409
|
+
return Object.assign(promise2, { cancel });
|
|
6410
|
+
}
|
|
6411
|
+
signal.addEventListener("abort", abort);
|
|
6412
|
+
cleanups.add(() => signal.removeEventListener("abort", abort));
|
|
6413
|
+
}
|
|
6414
|
+
cleanups.add(onExit((code, signal2) => {
|
|
6415
|
+
reject(new ExitPromptError(`User force closed the prompt with ${code} ${signal2}`));
|
|
6416
|
+
}));
|
|
6417
|
+
const sigint = () => reject(new ExitPromptError(`User force closed the prompt with SIGINT`));
|
|
6418
|
+
rl.on("SIGINT", sigint);
|
|
6419
|
+
cleanups.add(() => rl.removeListener("SIGINT", sigint));
|
|
6420
|
+
return withHooks(rl, (cycle) => {
|
|
6421
|
+
const hooksCleanup = AsyncResource3.bind(() => effectScheduler.clearAll());
|
|
6422
|
+
rl.on("close", hooksCleanup);
|
|
6423
|
+
cleanups.add(() => rl.removeListener("close", hooksCleanup));
|
|
6424
|
+
const startCycle = () => {
|
|
6425
|
+
const checkCursorPos = () => screen.checkCursorPos();
|
|
6426
|
+
rl.input.on("keypress", checkCursorPos);
|
|
6427
|
+
cleanups.add(() => rl.input.removeListener("keypress", checkCursorPos));
|
|
6428
|
+
let pendingDone = null;
|
|
6429
|
+
cycle(() => {
|
|
6430
|
+
let effectsSettled = false;
|
|
6431
|
+
try {
|
|
6432
|
+
const nextView = view(config2, (value) => {
|
|
6433
|
+
if (effectsSettled) {
|
|
6434
|
+
resolve(value);
|
|
6435
|
+
} else {
|
|
6436
|
+
pendingDone = { value };
|
|
6437
|
+
}
|
|
6438
|
+
});
|
|
6439
|
+
if (nextView === void 0) {
|
|
6440
|
+
let callerFilename = callSites[1]?.getFileName();
|
|
6441
|
+
if (callerFilename && !callerFilename.startsWith("file://")) {
|
|
6442
|
+
callerFilename = path.resolve(callerFilename);
|
|
6443
|
+
}
|
|
6444
|
+
throw new Error(`Prompt functions must return a string.
|
|
6445
|
+
at ${callerFilename}`);
|
|
6446
|
+
}
|
|
6447
|
+
const [content, bottomContent] = typeof nextView === "string" ? [nextView] : nextView;
|
|
6448
|
+
screen.render(content, bottomContent);
|
|
6449
|
+
effectScheduler.run();
|
|
6450
|
+
} catch (error40) {
|
|
6451
|
+
reject(error40);
|
|
6452
|
+
}
|
|
6453
|
+
effectsSettled = true;
|
|
6454
|
+
if (pendingDone !== null) {
|
|
6455
|
+
const { value } = pendingDone;
|
|
6456
|
+
pendingDone = null;
|
|
6457
|
+
resolve(value);
|
|
6458
|
+
}
|
|
6459
|
+
});
|
|
6460
|
+
};
|
|
6461
|
+
if ("readableFlowing" in input) {
|
|
6462
|
+
nativeSetImmediate(startCycle);
|
|
6463
|
+
} else {
|
|
6464
|
+
startCycle();
|
|
6465
|
+
}
|
|
6466
|
+
return Object.assign(promise2.then((answer) => {
|
|
6467
|
+
effectScheduler.clearAll();
|
|
6468
|
+
return answer;
|
|
6469
|
+
}, (error40) => {
|
|
6470
|
+
effectScheduler.clearAll();
|
|
6471
|
+
throw error40;
|
|
6472
|
+
}).finally(() => {
|
|
6473
|
+
cleanups.forEach((cleanup) => cleanup());
|
|
6474
|
+
screen.done({ clearContent: Boolean(context.clearPromptOnDone) });
|
|
6475
|
+
output.end();
|
|
6476
|
+
}).then(() => promise2), { cancel });
|
|
6477
|
+
});
|
|
6478
|
+
};
|
|
6479
|
+
return prompt;
|
|
6480
|
+
}
|
|
6481
|
+
var import_mute_stream, nativeSetImmediate;
|
|
6482
|
+
var init_create_prompt = __esm({
|
|
6483
|
+
"../../node_modules/.pnpm/@inquirer+core@11.1.9_@types+node@22.19.17/node_modules/@inquirer/core/dist/lib/create-prompt.js"() {
|
|
6484
|
+
import_mute_stream = __toESM(require_lib(), 1);
|
|
6485
|
+
init_mjs();
|
|
6486
|
+
init_screen_manager();
|
|
6487
|
+
init_promise_polyfill();
|
|
6488
|
+
init_hook_engine();
|
|
6489
|
+
init_errors();
|
|
6490
|
+
nativeSetImmediate = globalThis.setImmediate;
|
|
6491
|
+
}
|
|
6492
|
+
});
|
|
6493
|
+
|
|
6494
|
+
// ../../node_modules/.pnpm/@inquirer+core@11.1.9_@types+node@22.19.17/node_modules/@inquirer/core/dist/lib/Separator.js
|
|
6495
|
+
import { styleText as styleText2 } from "node:util";
|
|
6496
|
+
var Separator;
|
|
6497
|
+
var init_Separator = __esm({
|
|
6498
|
+
"../../node_modules/.pnpm/@inquirer+core@11.1.9_@types+node@22.19.17/node_modules/@inquirer/core/dist/lib/Separator.js"() {
|
|
6499
|
+
init_dist();
|
|
6500
|
+
Separator = class {
|
|
6501
|
+
separator = styleText2("dim", Array.from({ length: 15 }).join(dist_default.line));
|
|
6502
|
+
type = "separator";
|
|
6503
|
+
constructor(separator) {
|
|
6504
|
+
if (separator) {
|
|
6505
|
+
this.separator = separator;
|
|
6506
|
+
}
|
|
6507
|
+
}
|
|
6508
|
+
static isSeparator(choice) {
|
|
6509
|
+
return Boolean(choice && typeof choice === "object" && "type" in choice && choice.type === "separator");
|
|
6510
|
+
}
|
|
6511
|
+
};
|
|
6512
|
+
}
|
|
6513
|
+
});
|
|
6514
|
+
|
|
6515
|
+
// ../../node_modules/.pnpm/@inquirer+core@11.1.9_@types+node@22.19.17/node_modules/@inquirer/core/dist/index.js
|
|
6516
|
+
var init_dist5 = __esm({
|
|
6517
|
+
"../../node_modules/.pnpm/@inquirer+core@11.1.9_@types+node@22.19.17/node_modules/@inquirer/core/dist/index.js"() {
|
|
6518
|
+
init_key();
|
|
6519
|
+
init_errors();
|
|
6520
|
+
init_use_prefix();
|
|
6521
|
+
init_use_state();
|
|
6522
|
+
init_use_memo();
|
|
6523
|
+
init_use_keypress();
|
|
6524
|
+
init_make_theme();
|
|
6525
|
+
init_use_pagination();
|
|
6526
|
+
init_create_prompt();
|
|
6527
|
+
init_Separator();
|
|
6528
|
+
}
|
|
6529
|
+
});
|
|
6530
|
+
|
|
6531
|
+
// ../../node_modules/.pnpm/@inquirer+checkbox@5.1.4_@types+node@22.19.17/node_modules/@inquirer/checkbox/dist/index.js
|
|
6532
|
+
import { styleText as styleText3 } from "node:util";
|
|
6533
|
+
function isSelectable(item) {
|
|
6534
|
+
return !Separator.isSeparator(item) && !item.disabled;
|
|
6535
|
+
}
|
|
6536
|
+
function isNavigable(item) {
|
|
6537
|
+
return !Separator.isSeparator(item);
|
|
6538
|
+
}
|
|
6539
|
+
function isChecked(item) {
|
|
6540
|
+
return !Separator.isSeparator(item) && item.checked;
|
|
6541
|
+
}
|
|
6542
|
+
function toggle(item) {
|
|
6543
|
+
return isSelectable(item) ? { ...item, checked: !item.checked } : item;
|
|
6544
|
+
}
|
|
6545
|
+
function check(checked) {
|
|
6546
|
+
return function(item) {
|
|
6547
|
+
return isSelectable(item) ? { ...item, checked } : item;
|
|
6548
|
+
};
|
|
6549
|
+
}
|
|
6550
|
+
function normalizeChoices(choices) {
|
|
6551
|
+
return choices.map((choice) => {
|
|
6552
|
+
if (Separator.isSeparator(choice))
|
|
6553
|
+
return choice;
|
|
6554
|
+
if (typeof choice !== "object" || choice === null || !("value" in choice)) {
|
|
6555
|
+
const name2 = String(choice);
|
|
6556
|
+
return {
|
|
6557
|
+
value: choice,
|
|
6558
|
+
name: name2,
|
|
6559
|
+
short: name2,
|
|
6560
|
+
checkedName: name2,
|
|
6561
|
+
disabled: false,
|
|
6562
|
+
checked: false
|
|
6563
|
+
};
|
|
6564
|
+
}
|
|
6565
|
+
const name = choice.name ?? String(choice.value);
|
|
6566
|
+
const normalizedChoice = {
|
|
6567
|
+
value: choice.value,
|
|
6568
|
+
name,
|
|
6569
|
+
short: choice.short ?? name,
|
|
6570
|
+
checkedName: choice.checkedName ?? name,
|
|
6571
|
+
disabled: choice.disabled ?? false,
|
|
6572
|
+
checked: choice.checked ?? false
|
|
6573
|
+
};
|
|
6574
|
+
if (choice.description) {
|
|
6575
|
+
normalizedChoice.description = choice.description;
|
|
6576
|
+
}
|
|
6577
|
+
return normalizedChoice;
|
|
6578
|
+
});
|
|
6579
|
+
}
|
|
6580
|
+
var checkboxTheme, dist_default4;
|
|
6581
|
+
var init_dist6 = __esm({
|
|
6582
|
+
"../../node_modules/.pnpm/@inquirer+checkbox@5.1.4_@types+node@22.19.17/node_modules/@inquirer/checkbox/dist/index.js"() {
|
|
6583
|
+
init_dist5();
|
|
6584
|
+
init_dist4();
|
|
6585
|
+
init_dist();
|
|
6586
|
+
init_dist5();
|
|
6587
|
+
checkboxTheme = {
|
|
6588
|
+
icon: {
|
|
6589
|
+
checked: styleText3("green", dist_default.circleFilled),
|
|
6590
|
+
unchecked: dist_default.circle,
|
|
6591
|
+
cursor: dist_default.pointer,
|
|
6592
|
+
disabledChecked: styleText3("green", dist_default.circleDouble),
|
|
6593
|
+
disabledUnchecked: "-"
|
|
6594
|
+
},
|
|
6595
|
+
style: {
|
|
6596
|
+
disabled: (text) => styleText3("dim", text),
|
|
6597
|
+
renderSelectedChoices: (selectedChoices) => selectedChoices.map((choice) => choice.short).join(", "),
|
|
6598
|
+
description: (text) => styleText3("cyan", text),
|
|
6599
|
+
keysHelpTip: (keys) => keys.map(([key, action]) => `${styleText3("bold", key)} ${styleText3("dim", action)}`).join(styleText3("dim", " \u2022 "))
|
|
6600
|
+
},
|
|
6601
|
+
i18n: { disabledError: "This option is disabled and cannot be toggled." },
|
|
6602
|
+
keybindings: []
|
|
6603
|
+
};
|
|
6604
|
+
dist_default4 = createPrompt((config2, done) => {
|
|
6605
|
+
const { pageSize = 7, loop = true, required: required2, validate = () => true } = config2;
|
|
6606
|
+
const shortcuts = { all: "a", invert: "i", ...config2.shortcuts };
|
|
6607
|
+
const theme = makeTheme(checkboxTheme, config2.theme);
|
|
6608
|
+
const { keybindings } = theme;
|
|
6609
|
+
const [status, setStatus] = useState("idle");
|
|
6610
|
+
const prefix = usePrefix({ status, theme });
|
|
6611
|
+
const [items, setItems] = useState(normalizeChoices(config2.choices));
|
|
6612
|
+
const bounds = useMemo(() => {
|
|
6613
|
+
const first = items.findIndex(isNavigable);
|
|
6614
|
+
const last = items.findLastIndex(isNavigable);
|
|
6615
|
+
if (first === -1) {
|
|
6616
|
+
throw new ValidationError("[checkbox prompt] No selectable choices. All choices are disabled.");
|
|
6617
|
+
}
|
|
6618
|
+
return { first, last };
|
|
6619
|
+
}, [items]);
|
|
6620
|
+
const [active, setActive] = useState(bounds.first);
|
|
6621
|
+
const [errorMsg, setError] = useState();
|
|
6622
|
+
useKeypress(async (key) => {
|
|
6623
|
+
if (isEnterKey(key)) {
|
|
6624
|
+
const selection = items.filter(isChecked);
|
|
6625
|
+
const isValid = await validate([...selection]);
|
|
6626
|
+
if (required2 && !selection.length) {
|
|
6627
|
+
setError("At least one choice must be selected");
|
|
6628
|
+
} else if (isValid === true) {
|
|
6629
|
+
setStatus("done");
|
|
6630
|
+
done(selection.map((choice) => choice.value));
|
|
6631
|
+
} else {
|
|
6632
|
+
setError(isValid || "You must select a valid value");
|
|
6633
|
+
}
|
|
6634
|
+
} else if (isUpKey(key, keybindings) || isDownKey(key, keybindings)) {
|
|
6635
|
+
if (errorMsg) {
|
|
6636
|
+
setError(void 0);
|
|
6637
|
+
}
|
|
6638
|
+
if (loop || isUpKey(key, keybindings) && active !== bounds.first || isDownKey(key, keybindings) && active !== bounds.last) {
|
|
6639
|
+
const offset = isUpKey(key, keybindings) ? -1 : 1;
|
|
6640
|
+
let next = active;
|
|
6641
|
+
do {
|
|
6642
|
+
next = (next + offset + items.length) % items.length;
|
|
6643
|
+
} while (!isNavigable(items[next]));
|
|
6644
|
+
setActive(next);
|
|
6645
|
+
}
|
|
6646
|
+
} else if (isSpaceKey(key)) {
|
|
6647
|
+
const activeItem = items[active];
|
|
6648
|
+
if (activeItem && !Separator.isSeparator(activeItem)) {
|
|
6649
|
+
if (activeItem.disabled) {
|
|
6650
|
+
setError(theme.i18n.disabledError);
|
|
6651
|
+
} else {
|
|
6652
|
+
setError(void 0);
|
|
6653
|
+
setItems(items.map((choice, i) => i === active ? toggle(choice) : choice));
|
|
6654
|
+
}
|
|
6655
|
+
}
|
|
6656
|
+
} else if (key.name === shortcuts.all) {
|
|
6657
|
+
const selectAll = items.some((choice) => isSelectable(choice) && !choice.checked);
|
|
6658
|
+
setItems(items.map(check(selectAll)));
|
|
6659
|
+
} else if (key.name === shortcuts.invert) {
|
|
6660
|
+
setItems(items.map(toggle));
|
|
6661
|
+
} else if (isNumberKey(key)) {
|
|
6662
|
+
const selectedIndex = Number(key.name) - 1;
|
|
6663
|
+
let selectableIndex = -1;
|
|
6664
|
+
const position = items.findIndex((item) => {
|
|
6665
|
+
if (Separator.isSeparator(item))
|
|
6666
|
+
return false;
|
|
6667
|
+
selectableIndex++;
|
|
6668
|
+
return selectableIndex === selectedIndex;
|
|
6669
|
+
});
|
|
6670
|
+
const selectedItem = items[position];
|
|
6671
|
+
if (selectedItem && isSelectable(selectedItem)) {
|
|
6672
|
+
setActive(position);
|
|
6673
|
+
setItems(items.map((choice, i) => i === position ? toggle(choice) : choice));
|
|
6674
|
+
}
|
|
6675
|
+
}
|
|
6676
|
+
});
|
|
6677
|
+
const message = theme.style.message(config2.message, status);
|
|
6678
|
+
let description;
|
|
6679
|
+
const page = usePagination({
|
|
6680
|
+
items,
|
|
6681
|
+
active,
|
|
6682
|
+
renderItem({ item, isActive }) {
|
|
6683
|
+
if (Separator.isSeparator(item)) {
|
|
6684
|
+
return ` ${item.separator}`;
|
|
6685
|
+
}
|
|
6686
|
+
const cursor = isActive ? theme.icon.cursor : " ";
|
|
6687
|
+
if (item.disabled) {
|
|
6688
|
+
const disabledLabel = typeof item.disabled === "string" ? item.disabled : "(disabled)";
|
|
6689
|
+
const checkbox2 = item.checked ? theme.icon.disabledChecked : theme.icon.disabledUnchecked;
|
|
6690
|
+
return theme.style.disabled(`${cursor}${checkbox2} ${item.name} ${disabledLabel}`);
|
|
6691
|
+
}
|
|
6692
|
+
if (isActive) {
|
|
6693
|
+
description = item.description;
|
|
6694
|
+
}
|
|
6695
|
+
const checkbox = item.checked ? theme.icon.checked : theme.icon.unchecked;
|
|
6696
|
+
const name = item.checked ? item.checkedName : item.name;
|
|
6697
|
+
const color = isActive ? theme.style.highlight : (x) => x;
|
|
6698
|
+
return color(`${cursor}${checkbox} ${name}`);
|
|
6699
|
+
},
|
|
6700
|
+
pageSize,
|
|
6701
|
+
loop
|
|
6702
|
+
});
|
|
6703
|
+
if (status === "done") {
|
|
6704
|
+
const selection = items.filter(isChecked);
|
|
6705
|
+
const answer = theme.style.answer(theme.style.renderSelectedChoices(selection, items));
|
|
6706
|
+
return [prefix, message, answer].filter(Boolean).join(" ");
|
|
6707
|
+
}
|
|
6708
|
+
const keys = [
|
|
6709
|
+
["\u2191\u2193", "navigate"],
|
|
6710
|
+
["space", "select"]
|
|
6711
|
+
];
|
|
6712
|
+
if (shortcuts.all)
|
|
6713
|
+
keys.push([shortcuts.all, "all"]);
|
|
6714
|
+
if (shortcuts.invert)
|
|
6715
|
+
keys.push([shortcuts.invert, "invert"]);
|
|
6716
|
+
keys.push(["\u23CE", "submit"]);
|
|
6717
|
+
const helpLine = theme.style.keysHelpTip(keys);
|
|
6718
|
+
const lines = [
|
|
6719
|
+
[prefix, message].filter(Boolean).join(" "),
|
|
6720
|
+
page,
|
|
6721
|
+
" ",
|
|
6722
|
+
description ? theme.style.description(description) : "",
|
|
6723
|
+
errorMsg ? theme.style.error(errorMsg) : "",
|
|
6724
|
+
helpLine
|
|
6725
|
+
].filter(Boolean).join("\n").trimEnd();
|
|
6726
|
+
return `${lines}${cursorHide}`;
|
|
6727
|
+
});
|
|
6728
|
+
}
|
|
6729
|
+
});
|
|
6730
|
+
|
|
6731
|
+
// src/bridge/lib/binary-installer.ts
|
|
6732
|
+
import { spawn as spawn5 } from "node:child_process";
|
|
6733
|
+
import { homedir as homedir2, tmpdir } from "node:os";
|
|
6734
|
+
import { join as join3, basename } from "node:path";
|
|
6735
|
+
import { mkdirSync, rmSync, chmodSync, existsSync, symlinkSync, unlinkSync, createWriteStream } from "node:fs";
|
|
6736
|
+
import { randomBytes } from "node:crypto";
|
|
6737
|
+
import { Readable } from "node:stream";
|
|
6738
|
+
import { pipeline } from "node:stream/promises";
|
|
6739
|
+
function platformKey() {
|
|
6740
|
+
const os = process.platform === "win32" ? "windows" : process.platform;
|
|
6741
|
+
const arch = process.arch === "arm64" ? "aarch64" : process.arch === "x64" ? "x86_64" : process.arch;
|
|
6742
|
+
return `${os}-${arch}`;
|
|
6743
|
+
}
|
|
6744
|
+
async function installBinaryWrapper(opts) {
|
|
6745
|
+
const archive = opts.install.archives[platformKey()];
|
|
6746
|
+
if (!archive) {
|
|
6747
|
+
return {
|
|
6748
|
+
ok: false,
|
|
6749
|
+
error: `no archive for ${platformKey()}`,
|
|
6750
|
+
hint: opts.install.downloadUrl ? `manual install: ${opts.install.downloadUrl}` : void 0
|
|
6751
|
+
};
|
|
6752
|
+
}
|
|
6753
|
+
const cmdRel = archive.cmd.replace(/^\.\//, "");
|
|
6754
|
+
const binName = basename(cmdRel).replace(/\.exe$/, "");
|
|
6755
|
+
const wrapperDir = join3(WRAPPERS_DIR, opts.id);
|
|
6756
|
+
const cmdAbs = join3(wrapperDir, cmdRel);
|
|
6757
|
+
const linkPath = join3(BIN_DIR, binName);
|
|
6758
|
+
try {
|
|
6759
|
+
rmSync(wrapperDir, { recursive: true, force: true });
|
|
6760
|
+
} catch (e) {
|
|
6761
|
+
return { ok: false, error: `wipe stale wrapper dir failed: ${e.message}` };
|
|
6762
|
+
}
|
|
6763
|
+
mkdirSync(wrapperDir, { recursive: true });
|
|
6764
|
+
mkdirSync(BIN_DIR, { recursive: true });
|
|
6765
|
+
const ext = guessExtension(archive.url);
|
|
6766
|
+
const tmpFile = join3(tmpdir(), `oma-${opts.id}-${randomBytes(4).toString("hex")}${ext}`);
|
|
6767
|
+
try {
|
|
6768
|
+
opts.onProgress?.(`downloading ${archive.url}`);
|
|
6769
|
+
await downloadToFile(archive.url, tmpFile, opts.onProgress);
|
|
6770
|
+
opts.onProgress?.(`extracting to ${wrapperDir}`);
|
|
6771
|
+
await extractArchive(tmpFile, wrapperDir, ext);
|
|
6772
|
+
if (!existsSync(cmdAbs)) {
|
|
6773
|
+
return {
|
|
6774
|
+
ok: false,
|
|
6775
|
+
error: `extracted archive missing expected cmd: ${cmdRel}`
|
|
6776
|
+
};
|
|
6777
|
+
}
|
|
6778
|
+
chmodSync(cmdAbs, 493);
|
|
6779
|
+
try {
|
|
6780
|
+
unlinkSync(linkPath);
|
|
6781
|
+
} catch {
|
|
6782
|
+
}
|
|
6783
|
+
symlinkSync(cmdAbs, linkPath);
|
|
6784
|
+
const result = { ok: true, binPath: linkPath, installedAt: wrapperDir };
|
|
6785
|
+
if (!isOnPath2(BIN_DIR)) {
|
|
6786
|
+
result.hint = `add \`${BIN_DIR}\` to your PATH (it's where OMA installs wrappers)`;
|
|
6787
|
+
}
|
|
6788
|
+
return result;
|
|
6789
|
+
} catch (e) {
|
|
6790
|
+
return { ok: false, error: e.message };
|
|
6791
|
+
} finally {
|
|
6792
|
+
try {
|
|
6793
|
+
unlinkSync(tmpFile);
|
|
6794
|
+
} catch {
|
|
6795
|
+
}
|
|
6796
|
+
}
|
|
6797
|
+
}
|
|
6798
|
+
function guessExtension(url2) {
|
|
6799
|
+
const path2 = (() => {
|
|
6800
|
+
try {
|
|
6801
|
+
return new URL(url2).pathname;
|
|
6802
|
+
} catch {
|
|
6803
|
+
return url2;
|
|
6804
|
+
}
|
|
6805
|
+
})();
|
|
6806
|
+
for (const ext of [".tar.gz", ".tgz", ".tar.bz2", ".tbz2", ".tar.xz", ".txz", ".zip"]) {
|
|
6807
|
+
if (path2.toLowerCase().endsWith(ext)) return ext;
|
|
6808
|
+
}
|
|
6809
|
+
return "";
|
|
6810
|
+
}
|
|
6811
|
+
async function downloadToFile(url2, dest, onProgress) {
|
|
6812
|
+
const res = await fetch(url2, { redirect: "follow" });
|
|
6813
|
+
if (!res.ok) throw new Error(`download HTTP ${res.status}`);
|
|
6814
|
+
const total = Number(res.headers.get("content-length") ?? "0");
|
|
6815
|
+
if (!res.body) throw new Error("download returned empty body");
|
|
6816
|
+
let last = Date.now();
|
|
6817
|
+
let read = 0;
|
|
6818
|
+
const stream = res.body;
|
|
6819
|
+
const node = Readable.fromWeb(stream);
|
|
6820
|
+
node.on("data", (chunk) => {
|
|
6821
|
+
read += chunk.byteLength;
|
|
6822
|
+
if (Date.now() - last > 1e3 && onProgress) {
|
|
6823
|
+
last = Date.now();
|
|
6824
|
+
const pct = total ? `${Math.floor(read / total * 100)}%` : "";
|
|
6825
|
+
onProgress(` \u2026${formatBytes(read)}${total ? `/${formatBytes(total)} ${pct}` : ""}`);
|
|
6826
|
+
}
|
|
6827
|
+
});
|
|
6828
|
+
await pipeline(node, createWriteStream(dest));
|
|
6829
|
+
}
|
|
6830
|
+
function formatBytes(n) {
|
|
6831
|
+
if (n < 1024) return `${n}B`;
|
|
6832
|
+
if (n < 1024 * 1024) return `${(n / 1024).toFixed(1)}KB`;
|
|
6833
|
+
return `${(n / 1024 / 1024).toFixed(1)}MB`;
|
|
6834
|
+
}
|
|
6835
|
+
function extractArchive(archive, dest, ext) {
|
|
6836
|
+
const isWin = process.platform === "win32";
|
|
6837
|
+
let cmd;
|
|
6838
|
+
let args;
|
|
6839
|
+
if (ext === ".zip") {
|
|
6840
|
+
if (isWin) {
|
|
6841
|
+
cmd = "tar";
|
|
6842
|
+
args = ["-xf", archive, "-C", dest];
|
|
6843
|
+
} else {
|
|
6844
|
+
cmd = "unzip";
|
|
6845
|
+
args = ["-q", "-o", archive, "-d", dest];
|
|
6846
|
+
}
|
|
6847
|
+
} else if (ext === ".tar.gz" || ext === ".tgz") {
|
|
6848
|
+
cmd = "tar";
|
|
6849
|
+
args = ["-xzf", archive, "-C", dest];
|
|
6850
|
+
} else if (ext === ".tar.bz2" || ext === ".tbz2") {
|
|
6851
|
+
cmd = "tar";
|
|
6852
|
+
args = ["-xjf", archive, "-C", dest];
|
|
6853
|
+
} else if (ext === ".tar.xz" || ext === ".txz") {
|
|
6854
|
+
cmd = "tar";
|
|
6855
|
+
args = ["-xJf", archive, "-C", dest];
|
|
6856
|
+
} else {
|
|
6857
|
+
return Promise.reject(new Error(`unsupported archive extension '${ext || "?"}'`));
|
|
6858
|
+
}
|
|
6859
|
+
return new Promise((resolve, reject) => {
|
|
6860
|
+
const p = spawn5(cmd, args, { stdio: ["ignore", "ignore", "pipe"] });
|
|
6861
|
+
let err = "";
|
|
6862
|
+
p.stderr?.on("data", (d) => {
|
|
6863
|
+
err += d.toString();
|
|
6864
|
+
});
|
|
6865
|
+
p.once("error", (e) => reject(new Error(`${cmd} spawn failed: ${e.message}`)));
|
|
6866
|
+
p.once("exit", (code) => {
|
|
6867
|
+
if (code === 0) resolve();
|
|
6868
|
+
else reject(new Error(`${cmd} exited ${code}: ${err.trim().slice(0, 400)}`));
|
|
6869
|
+
});
|
|
6870
|
+
});
|
|
6871
|
+
}
|
|
6872
|
+
function isOnPath2(dir) {
|
|
6873
|
+
const sep = process.platform === "win32" ? ";" : ":";
|
|
6874
|
+
return (process.env.PATH ?? "").split(sep).includes(dir);
|
|
6875
|
+
}
|
|
6876
|
+
var WRAPPERS_DIR, BIN_DIR, binDir;
|
|
6877
|
+
var init_binary_installer = __esm({
|
|
6878
|
+
"src/bridge/lib/binary-installer.ts"() {
|
|
6879
|
+
"use strict";
|
|
6880
|
+
WRAPPERS_DIR = join3(homedir2(), ".local", "share", "oma", "wrappers");
|
|
6881
|
+
BIN_DIR = join3(homedir2(), ".local", "bin");
|
|
6882
|
+
binDir = BIN_DIR;
|
|
6883
|
+
}
|
|
6884
|
+
});
|
|
6885
|
+
|
|
6886
|
+
// src/bridge/lib/wrapper-audit.ts
|
|
6887
|
+
import { spawn as spawn6 } from "node:child_process";
|
|
6888
|
+
async function auditAndOfferWrappers(initialAgents, opts = {}) {
|
|
6889
|
+
let agents = initialAgents.map((a) => ({ id: a.id }));
|
|
6890
|
+
const detectedIds = new Set(agents.map((a) => a.id));
|
|
6891
|
+
const rows = [];
|
|
6892
|
+
for (const e of getKnownAgents()) {
|
|
6893
|
+
if (detectedIds.has(e.id)) {
|
|
6894
|
+
if (e.wraps) {
|
|
6895
|
+
rows.push({ id: e.id, label: e.label, status: { kind: "wrapper-detected", wraps: e.wraps } });
|
|
6896
|
+
} else {
|
|
6897
|
+
rows.push({ id: e.id, label: e.label, status: { kind: "builtin-detected" } });
|
|
6898
|
+
}
|
|
6899
|
+
continue;
|
|
6900
|
+
}
|
|
6901
|
+
if (e.wraps && e.install && await isOnPath3(e.wraps)) {
|
|
6902
|
+
rows.push({
|
|
6903
|
+
id: e.id,
|
|
6904
|
+
label: e.label,
|
|
6905
|
+
status: { kind: "wrapper-needs-install", wraps: e.wraps, install: e.install }
|
|
6906
|
+
});
|
|
6907
|
+
}
|
|
6908
|
+
}
|
|
6909
|
+
if (rows.length === 0) return agents;
|
|
6910
|
+
const tty2 = Boolean(process.stdin.isTTY) && Boolean(process.stdout.isTTY);
|
|
6911
|
+
if (opts.dryRun) {
|
|
6912
|
+
printAuditPlain(rows);
|
|
6913
|
+
return agents;
|
|
6914
|
+
}
|
|
6915
|
+
if (!tty2 && !opts.yes) {
|
|
6916
|
+
printAuditPlain(rows);
|
|
6917
|
+
log.hint("non-interactive context \u2014 skipping prompts. Re-run from a terminal to install.");
|
|
6918
|
+
return agents;
|
|
6919
|
+
}
|
|
6920
|
+
let toInstall;
|
|
6921
|
+
if (opts.yes) {
|
|
6922
|
+
toInstall = rows.filter((r) => {
|
|
6923
|
+
if (r.status.kind !== "wrapper-needs-install") return false;
|
|
6924
|
+
const inst = r.status.install;
|
|
6925
|
+
if (inst.kind === "npm") return true;
|
|
6926
|
+
if (inst.kind === "binary") return Boolean(inst.archives[platformKey()]);
|
|
6927
|
+
return false;
|
|
6928
|
+
});
|
|
6929
|
+
} else {
|
|
6930
|
+
const choices = buildChoices(rows);
|
|
6931
|
+
if (!choices.some((c3) => "value" in c3 && !("disabled" in c3 && c3.disabled))) {
|
|
6932
|
+
printAuditPlain(rows);
|
|
6933
|
+
log.hint("nothing to install \u2014 your ACP agents are already in sync");
|
|
6934
|
+
return agents;
|
|
6935
|
+
}
|
|
6936
|
+
const selected = await dist_default4({
|
|
6937
|
+
message: "Install ACP wrappers? (space to toggle, enter to confirm)",
|
|
6938
|
+
choices,
|
|
6939
|
+
pageSize: Math.min(20, choices.length + 2),
|
|
6940
|
+
loop: false
|
|
6941
|
+
}).catch(() => []);
|
|
6942
|
+
toInstall = rows.filter((r) => {
|
|
6943
|
+
if (r.status.kind !== "wrapper-needs-install") return false;
|
|
6944
|
+
if (!selected.includes(r.id)) return false;
|
|
6945
|
+
const inst = r.status.install;
|
|
6946
|
+
if (inst.kind === "npm") return true;
|
|
6947
|
+
if (inst.kind === "binary") return Boolean(inst.archives[platformKey()]);
|
|
6948
|
+
return false;
|
|
6949
|
+
});
|
|
6950
|
+
}
|
|
6951
|
+
if (toInstall.length === 0) {
|
|
6952
|
+
log.hint("nothing to install");
|
|
6953
|
+
return agents;
|
|
6954
|
+
}
|
|
6955
|
+
let installed = 0;
|
|
6956
|
+
for (const r of toInstall) {
|
|
6957
|
+
if (r.status.kind !== "wrapper-needs-install") continue;
|
|
6958
|
+
const inst = r.status.install;
|
|
6959
|
+
if (inst.kind === "npm") {
|
|
6960
|
+
log.step(`installing ${inst.package}`);
|
|
6961
|
+
const ok = await npmInstallGlobal(inst.package);
|
|
6962
|
+
if (ok) {
|
|
6963
|
+
log.ok(`${r.id} installed`);
|
|
6964
|
+
installed += 1;
|
|
6965
|
+
} else {
|
|
6966
|
+
log.warn(`install failed \u2014 try manually: npm i -g ${inst.package}`);
|
|
6967
|
+
}
|
|
6968
|
+
} else if (inst.kind === "binary") {
|
|
6969
|
+
log.step(`downloading ${r.id} (binary, ${platformKey()})`);
|
|
6970
|
+
const result = await installBinaryWrapper({
|
|
6971
|
+
id: r.id,
|
|
6972
|
+
install: inst,
|
|
6973
|
+
onProgress: (m) => process.stderr.write(` ${c.dim(m)}
|
|
6974
|
+
`)
|
|
6975
|
+
});
|
|
6976
|
+
if (result.ok) {
|
|
6977
|
+
log.ok(`${r.id} installed \u2192 ${c.dim(result.binPath ?? "")}`);
|
|
6978
|
+
if (result.hint) log.hint(result.hint);
|
|
6979
|
+
installed += 1;
|
|
6980
|
+
} else {
|
|
6981
|
+
log.warn(`${r.id} install failed: ${result.error ?? "unknown"}`);
|
|
6982
|
+
if (result.hint) log.hint(result.hint);
|
|
6983
|
+
if (inst.downloadUrl) log.hint(`manual: ${inst.downloadUrl}`);
|
|
4060
6984
|
}
|
|
4061
|
-
}
|
|
4062
|
-
|
|
4063
|
-
|
|
4064
|
-
|
|
4065
|
-
|
|
4066
|
-
|
|
4067
|
-
|
|
6985
|
+
}
|
|
6986
|
+
}
|
|
6987
|
+
if (installed > 0) {
|
|
6988
|
+
agents = (await detectAll()).map((a) => ({ id: a.id, binary: a.spec.command }));
|
|
6989
|
+
}
|
|
6990
|
+
return agents;
|
|
6991
|
+
}
|
|
6992
|
+
function buildChoices(rows) {
|
|
6993
|
+
const detected = rows.filter((r) => r.status.kind !== "wrapper-needs-install");
|
|
6994
|
+
const missing = rows.filter((r) => r.status.kind === "wrapper-needs-install");
|
|
6995
|
+
const out = [];
|
|
6996
|
+
if (detected.length) {
|
|
6997
|
+
out.push(new Separator(c.dim("\u2500\u2500\u2500 already detected on this machine \u2500\u2500\u2500")));
|
|
6998
|
+
for (const r of detected) {
|
|
6999
|
+
const tag = r.status.kind === "wrapper-detected" ? `wrapper for \`${r.status.wraps}\`` : "built-in ACP";
|
|
7000
|
+
out.push({
|
|
7001
|
+
name: `${r.id.padEnd(18)}${c.dim(tag)}`,
|
|
7002
|
+
value: r.id,
|
|
7003
|
+
disabled: " (already installed)"
|
|
4068
7004
|
});
|
|
4069
|
-
}
|
|
7005
|
+
}
|
|
7006
|
+
}
|
|
7007
|
+
if (missing.length) {
|
|
7008
|
+
out.push(new Separator(c.dim("\u2500\u2500\u2500 ACP wrappers available to install \u2500\u2500\u2500")));
|
|
7009
|
+
const pk = platformKey();
|
|
7010
|
+
for (const r of missing) {
|
|
7011
|
+
if (r.status.kind !== "wrapper-needs-install") continue;
|
|
7012
|
+
const wrapsLabel = c.dim(`wraps \`${r.status.wraps}\``);
|
|
7013
|
+
const inst = r.status.install;
|
|
7014
|
+
if (inst.kind === "npm") {
|
|
7015
|
+
out.push({
|
|
7016
|
+
name: `${r.id.padEnd(18)}${wrapsLabel} ${c.dim(`\u2014 npm i -g ${inst.package}`)}`,
|
|
7017
|
+
value: r.id,
|
|
7018
|
+
checked: false
|
|
7019
|
+
});
|
|
7020
|
+
} else {
|
|
7021
|
+
const archive = inst.archives[pk];
|
|
7022
|
+
if (archive) {
|
|
7023
|
+
out.push({
|
|
7024
|
+
name: `${r.id.padEnd(18)}${wrapsLabel} ${c.dim(`\u2014 binary release (${pk}) \u2192 ~/.local/bin/`)}`,
|
|
7025
|
+
value: r.id,
|
|
7026
|
+
checked: false
|
|
7027
|
+
});
|
|
7028
|
+
} else {
|
|
7029
|
+
out.push({
|
|
7030
|
+
name: `${r.id.padEnd(18)}${wrapsLabel} ${c.dim(`\u2014 no ${pk} build` + (inst.downloadUrl ? `; see ${inst.downloadUrl}` : ""))}`,
|
|
7031
|
+
value: r.id,
|
|
7032
|
+
disabled: " (manual download required)"
|
|
7033
|
+
});
|
|
7034
|
+
}
|
|
7035
|
+
}
|
|
7036
|
+
}
|
|
7037
|
+
}
|
|
7038
|
+
return out;
|
|
7039
|
+
}
|
|
7040
|
+
function printAuditPlain(rows) {
|
|
7041
|
+
process.stderr.write("\n");
|
|
7042
|
+
log.step(`ACP audit (${rows.length} relevant on this machine):`);
|
|
7043
|
+
const pk = platformKey();
|
|
7044
|
+
for (const r of rows) {
|
|
7045
|
+
let line;
|
|
7046
|
+
if (r.status.kind === "builtin-detected") {
|
|
7047
|
+
line = ` ${c.green("\u2713")} ${r.id.padEnd(18)} ${c.dim("built-in ACP")}`;
|
|
7048
|
+
} else if (r.status.kind === "wrapper-detected") {
|
|
7049
|
+
line = ` ${c.green("\u2713")} ${r.id.padEnd(18)} ${c.dim(`wrapper for \`${r.status.wraps}\``)}`;
|
|
7050
|
+
} else {
|
|
7051
|
+
const inst = r.status.install;
|
|
7052
|
+
if (inst.kind === "npm") {
|
|
7053
|
+
line = ` ${c.yellow("\u25CB")} ${r.id.padEnd(18)} ${c.dim(`wraps \`${r.status.wraps}\` \u2014 npm i -g ${inst.package}`)}`;
|
|
7054
|
+
} else if (inst.archives[pk]) {
|
|
7055
|
+
line = ` ${c.yellow("\u25CB")} ${r.id.padEnd(18)} ${c.dim(`wraps \`${r.status.wraps}\` \u2014 binary release (${pk}) \u2192 ${binDir}`)}`;
|
|
7056
|
+
} else {
|
|
7057
|
+
line = ` ${c.yellow("\u25CB")} ${r.id.padEnd(18)} ${c.dim(`wraps \`${r.status.wraps}\` \u2014 no ${pk} build` + (inst.downloadUrl ? `, see ${inst.downloadUrl}` : ""))}`;
|
|
7058
|
+
}
|
|
7059
|
+
}
|
|
7060
|
+
process.stderr.write(line + "\n");
|
|
7061
|
+
}
|
|
7062
|
+
}
|
|
7063
|
+
function isOnPath3(cmd) {
|
|
7064
|
+
return new Promise((resolve) => {
|
|
7065
|
+
const probe = process.platform === "win32" ? "where" : "which";
|
|
7066
|
+
const p = spawn6(probe, [cmd], { stdio: "ignore" });
|
|
7067
|
+
p.once("error", () => resolve(false));
|
|
7068
|
+
p.once("exit", (code) => resolve(code === 0));
|
|
4070
7069
|
});
|
|
4071
7070
|
}
|
|
4072
|
-
|
|
4073
|
-
|
|
7071
|
+
function npmInstallGlobal(pkg) {
|
|
7072
|
+
return new Promise((resolve) => {
|
|
7073
|
+
const p = spawn6("npm", ["install", "-g", pkg], { stdio: "inherit" });
|
|
7074
|
+
p.once("error", () => resolve(false));
|
|
7075
|
+
p.once("exit", (code) => resolve(code === 0));
|
|
7076
|
+
});
|
|
7077
|
+
}
|
|
7078
|
+
var init_wrapper_audit = __esm({
|
|
7079
|
+
"src/bridge/lib/wrapper-audit.ts"() {
|
|
4074
7080
|
"use strict";
|
|
7081
|
+
init_dist6();
|
|
7082
|
+
init_registry();
|
|
7083
|
+
init_style();
|
|
7084
|
+
init_binary_installer();
|
|
4075
7085
|
}
|
|
4076
7086
|
});
|
|
4077
7087
|
|
|
@@ -4081,18 +7091,22 @@ __export(setup_exports, {
|
|
|
4081
7091
|
runSetup: () => runSetup
|
|
4082
7092
|
});
|
|
4083
7093
|
import { createServer } from "node:http";
|
|
4084
|
-
import { spawn as
|
|
7094
|
+
import { spawn as spawn7 } from "node:child_process";
|
|
4085
7095
|
import { hostname } from "node:os";
|
|
4086
|
-
import { randomBytes } from "node:crypto";
|
|
7096
|
+
import { randomBytes as randomBytes2 } from "node:crypto";
|
|
4087
7097
|
import { realpathSync } from "node:fs";
|
|
4088
|
-
|
|
7098
|
+
import { join as join4 } from "node:path";
|
|
7099
|
+
function serviceInstallOpts() {
|
|
4089
7100
|
return {
|
|
4090
7101
|
nodePath: process.execPath,
|
|
4091
7102
|
cliEntry: realpathSync(process.argv[1])
|
|
4092
7103
|
};
|
|
4093
7104
|
}
|
|
4094
7105
|
async function runSetup(opts) {
|
|
4095
|
-
|
|
7106
|
+
const profile = currentProfile();
|
|
7107
|
+
const profileTag = profile ? ` [profile=${profile}]` : "";
|
|
7108
|
+
printBanner(`setup \u2014 register this machine with ${opts.serverUrl}${profileTag}`, PKG_VERSION);
|
|
7109
|
+
await loadRegistry({ cachePath: join4(paths().configDir, "registry-cache.json") });
|
|
4096
7110
|
if (!opts.force) {
|
|
4097
7111
|
const existing = await readCreds();
|
|
4098
7112
|
if (existing) {
|
|
@@ -4109,30 +7123,19 @@ async function runSetup(opts) {
|
|
|
4109
7123
|
} else {
|
|
4110
7124
|
log.hint(`runtime ${existing.runtimeId.slice(0, 8)}\u2026 (use --force to re-register)`);
|
|
4111
7125
|
}
|
|
4112
|
-
|
|
4113
|
-
|
|
4114
|
-
const currentEntry = launchdInstallOpts().cliEntry;
|
|
4115
|
-
if (installedEntry && installedEntry !== currentEntry) {
|
|
4116
|
-
log.warn(`plist was pointing at a different binary; updating`);
|
|
4117
|
-
log.hint(`old: ${c.dim(installedEntry)}`);
|
|
4118
|
-
log.hint(`new: ${c.dim(currentEntry)}`);
|
|
4119
|
-
}
|
|
4120
|
-
await install(launchdInstallOpts());
|
|
4121
|
-
log.ok(`launchd plist refreshed ${c.dim(paths().serviceFile ?? "")}`);
|
|
4122
|
-
log.ok(`daemon restarted ${c.dim("logs: " + paths().logFile)}`);
|
|
4123
|
-
} else {
|
|
4124
|
-
log.hint("run `oma bridge daemon` to start the bridge");
|
|
4125
|
-
}
|
|
7126
|
+
const fastPathAgents = (await detectAll()).map((a) => ({ id: a.id, binary: a.spec.command }));
|
|
7127
|
+
await auditAndOfferWrappers(fastPathAgents, { yes: opts.yes });
|
|
4126
7128
|
process.stderr.write(`
|
|
4127
7129
|
${c.bold("Up to date.")}
|
|
4128
7130
|
|
|
4129
7131
|
`);
|
|
7132
|
+
await refreshServiceOrFallback(opts);
|
|
4130
7133
|
return;
|
|
4131
7134
|
}
|
|
4132
7135
|
}
|
|
4133
7136
|
}
|
|
4134
7137
|
log.step("waiting for browser to authorize");
|
|
4135
|
-
const state =
|
|
7138
|
+
const state = randomBytes2(16).toString("hex");
|
|
4136
7139
|
const code = await waitForCallback(state, opts.browserOrigin);
|
|
4137
7140
|
log.ok("received code from browser");
|
|
4138
7141
|
const machineId = await getOrCreateMachineId();
|
|
@@ -4154,38 +7157,105 @@ ${c.bold("Up to date.")}
|
|
|
4154
7157
|
createdAt: Math.floor(Date.now() / 1e3)
|
|
4155
7158
|
});
|
|
4156
7159
|
log.ok(`credentials written ${c.dim(paths().credsFile)}`);
|
|
4157
|
-
let agents = await detectAll();
|
|
4158
|
-
|
|
4159
|
-
if (!hasClaudeAcp && await isOnPath2("claude")) {
|
|
4160
|
-
log.step("found `claude` on PATH \u2014 installing ACP wrapper @agentclientprotocol/claude-agent-acp");
|
|
4161
|
-
const ok = await npmInstallGlobal("@agentclientprotocol/claude-agent-acp");
|
|
4162
|
-
if (ok) {
|
|
4163
|
-
log.ok("claude-agent-acp installed");
|
|
4164
|
-
agents = await detectAll();
|
|
4165
|
-
} else {
|
|
4166
|
-
log.warn("auto-install failed \u2014 install manually: npm i -g @agentclientprotocol/claude-agent-acp");
|
|
4167
|
-
}
|
|
4168
|
-
}
|
|
7160
|
+
let agents = (await detectAll()).map((a) => ({ id: a.id, binary: a.spec.command }));
|
|
7161
|
+
agents = await auditAndOfferWrappers(agents, { yes: opts.yes });
|
|
4169
7162
|
if (agents.length > 0) {
|
|
4170
7163
|
log.ok(`agents detected ${c.dim(agents.map((a) => a.id).join(", "))}`);
|
|
4171
7164
|
} else {
|
|
4172
7165
|
log.warn("no ACP agents on PATH yet");
|
|
4173
7166
|
log.hint("install one, e.g. `npm i -g @agentclientprotocol/claude-agent-acp`");
|
|
4174
7167
|
}
|
|
4175
|
-
|
|
7168
|
+
await installServiceOrFallback(opts);
|
|
7169
|
+
}
|
|
7170
|
+
async function installServiceOrFallback(opts) {
|
|
7171
|
+
const kind = detectServiceKind();
|
|
7172
|
+
if (opts.noService || kind === "unsupported") {
|
|
7173
|
+
process.stderr.write("\n");
|
|
7174
|
+
if (kind === "unsupported") {
|
|
7175
|
+
log.warn(`platform service install not supported on ${process.platform}; running daemon in foreground`);
|
|
7176
|
+
} else {
|
|
7177
|
+
log.step("--no-service: starting daemon in foreground");
|
|
7178
|
+
}
|
|
7179
|
+
log.hint("Ctrl-C to stop. To run as a system service, re-run setup without --no-service.");
|
|
7180
|
+
process.stderr.write("\n");
|
|
7181
|
+
execIntoDaemon();
|
|
7182
|
+
return;
|
|
7183
|
+
}
|
|
7184
|
+
await installAndReport(opts);
|
|
7185
|
+
}
|
|
7186
|
+
async function refreshServiceOrFallback(opts) {
|
|
7187
|
+
const kind = detectServiceKind();
|
|
7188
|
+
if (opts.noService || kind === "unsupported") {
|
|
4176
7189
|
process.stderr.write("\n");
|
|
4177
|
-
log.step("service install
|
|
4178
|
-
log.hint("
|
|
7190
|
+
log.step(opts.noService ? "--no-service: starting daemon in foreground" : `service install not supported on ${process.platform}; running daemon in foreground`);
|
|
7191
|
+
log.hint("Ctrl-C to stop. To run as a system service, re-run setup without --no-service.");
|
|
7192
|
+
process.stderr.write("\n");
|
|
7193
|
+
execIntoDaemon();
|
|
4179
7194
|
return;
|
|
4180
7195
|
}
|
|
4181
|
-
await
|
|
4182
|
-
|
|
4183
|
-
|
|
7196
|
+
const installedEntry = await readInstalledCliEntry4();
|
|
7197
|
+
const currentEntry = serviceInstallOpts().cliEntry;
|
|
7198
|
+
if (installedEntry && installedEntry !== currentEntry) {
|
|
7199
|
+
log.warn(`service was pointing at a different binary; updating`);
|
|
7200
|
+
log.hint(`old: ${c.dim(installedEntry)}`);
|
|
7201
|
+
log.hint(`new: ${c.dim(currentEntry)}`);
|
|
7202
|
+
}
|
|
7203
|
+
await installAndReport(opts);
|
|
7204
|
+
}
|
|
7205
|
+
async function installAndReport(opts) {
|
|
7206
|
+
void opts;
|
|
7207
|
+
const result = await install4(serviceInstallOpts());
|
|
7208
|
+
const where = result.installedAt ? c.dim(result.installedAt) : c.dim("(no install path)");
|
|
7209
|
+
switch (result.kind) {
|
|
7210
|
+
case "launchd":
|
|
7211
|
+
log.ok(`launchd plist installed ${where}`);
|
|
7212
|
+
log.ok(`daemon started ${c.dim("logs: " + paths().logFile)}`);
|
|
7213
|
+
break;
|
|
7214
|
+
case "systemd":
|
|
7215
|
+
log.ok(`systemd unit installed ${where}`);
|
|
7216
|
+
if (result.started) {
|
|
7217
|
+
log.ok(`daemon started ${c.dim("logs: " + paths().logFile)}`);
|
|
7218
|
+
} else {
|
|
7219
|
+
log.warn(`unit installed but failed to start: ${result.warning ?? "unknown"}`);
|
|
7220
|
+
log.hint(`try: systemctl --user status ${paths().serviceLabel}`);
|
|
7221
|
+
}
|
|
7222
|
+
if (!result.lingerEnabled) {
|
|
7223
|
+
log.hint(lingerHint2());
|
|
7224
|
+
}
|
|
7225
|
+
break;
|
|
7226
|
+
case "windows-task":
|
|
7227
|
+
log.ok(`Task Scheduler task registered ${where}`);
|
|
7228
|
+
if (result.started) {
|
|
7229
|
+
log.ok(`daemon started ${c.dim("logs: " + paths().logFile)}`);
|
|
7230
|
+
} else {
|
|
7231
|
+
log.warn(`task registered but failed to start now: ${result.warning ?? "unknown"}`);
|
|
7232
|
+
log.hint(`it will run at next logon. To start manually: schtasks /run /tn ${paths().serviceLabel}`);
|
|
7233
|
+
}
|
|
7234
|
+
break;
|
|
7235
|
+
case "unsupported":
|
|
7236
|
+
log.err(`platform unsupported`);
|
|
7237
|
+
return;
|
|
7238
|
+
}
|
|
4184
7239
|
process.stderr.write("\n");
|
|
4185
7240
|
process.stderr.write(`${c.bold("Done.")} the runtime should appear online at ${c.cyan(opts.browserOrigin)}
|
|
4186
7241
|
|
|
4187
7242
|
`);
|
|
4188
7243
|
}
|
|
7244
|
+
function execIntoDaemon() {
|
|
7245
|
+
const profile = currentProfile();
|
|
7246
|
+
const child = spawn7(process.execPath, [process.argv[1], "bridge", "daemon"], {
|
|
7247
|
+
stdio: "inherit",
|
|
7248
|
+
env: { ...process.env, ...profile ? { OMA_PROFILE: profile } : {} }
|
|
7249
|
+
});
|
|
7250
|
+
child.once("exit", (code, signal) => {
|
|
7251
|
+
if (signal) {
|
|
7252
|
+
process.kill(process.pid, signal);
|
|
7253
|
+
return;
|
|
7254
|
+
}
|
|
7255
|
+
process.exit(code ?? 0);
|
|
7256
|
+
});
|
|
7257
|
+
return new Promise(() => void 0);
|
|
7258
|
+
}
|
|
4189
7259
|
function waitForCallback(state, browserOrigin) {
|
|
4190
7260
|
return new Promise((resolve, reject) => {
|
|
4191
7261
|
const timeoutMs = 5 * 60 * 1e3;
|
|
@@ -4269,37 +7339,23 @@ function openBrowser(url2) {
|
|
|
4269
7339
|
return new Promise((resolve, reject) => {
|
|
4270
7340
|
const cmd = process.platform === "darwin" ? "open" : process.platform === "win32" ? "start" : "xdg-open";
|
|
4271
7341
|
const args = process.platform === "win32" ? ["", url2] : [url2];
|
|
4272
|
-
const p =
|
|
7342
|
+
const p = spawn7(cmd, args, { stdio: "ignore", detached: true, shell: process.platform === "win32" });
|
|
4273
7343
|
p.once("error", reject);
|
|
4274
7344
|
p.unref();
|
|
4275
7345
|
setTimeout(() => resolve(), 100);
|
|
4276
7346
|
});
|
|
4277
7347
|
}
|
|
4278
|
-
function isOnPath2(cmd) {
|
|
4279
|
-
return new Promise((resolve) => {
|
|
4280
|
-
const probe = process.platform === "win32" ? "where" : "which";
|
|
4281
|
-
const p = spawn3(probe, [cmd], { stdio: "ignore" });
|
|
4282
|
-
p.once("error", () => resolve(false));
|
|
4283
|
-
p.once("exit", (code) => resolve(code === 0));
|
|
4284
|
-
});
|
|
4285
|
-
}
|
|
4286
|
-
function npmInstallGlobal(pkg) {
|
|
4287
|
-
return new Promise((resolve) => {
|
|
4288
|
-
const p = spawn3("npm", ["install", "-g", pkg], { stdio: "inherit" });
|
|
4289
|
-
p.once("error", () => resolve(false));
|
|
4290
|
-
p.once("exit", (code) => resolve(code === 0));
|
|
4291
|
-
});
|
|
4292
|
-
}
|
|
4293
7348
|
var init_setup = __esm({
|
|
4294
7349
|
"src/bridge/commands/setup.ts"() {
|
|
4295
7350
|
"use strict";
|
|
4296
7351
|
init_config();
|
|
4297
7352
|
init_platform();
|
|
4298
|
-
|
|
7353
|
+
init_service_manager();
|
|
4299
7354
|
init_registry();
|
|
4300
7355
|
init_style();
|
|
4301
7356
|
init_version();
|
|
4302
7357
|
init_probe();
|
|
7358
|
+
init_wrapper_audit();
|
|
4303
7359
|
}
|
|
4304
7360
|
});
|
|
4305
7361
|
|
|
@@ -4400,7 +7456,7 @@ __export(util_exports, {
|
|
|
4400
7456
|
getParsedType: () => getParsedType,
|
|
4401
7457
|
getSizableOrigin: () => getSizableOrigin,
|
|
4402
7458
|
isObject: () => isObject,
|
|
4403
|
-
isPlainObject: () =>
|
|
7459
|
+
isPlainObject: () => isPlainObject2,
|
|
4404
7460
|
issue: () => issue,
|
|
4405
7461
|
joinValues: () => joinValues,
|
|
4406
7462
|
jsonStringifyReplacer: () => jsonStringifyReplacer,
|
|
@@ -4504,10 +7560,10 @@ function assignProp(target, prop, value) {
|
|
|
4504
7560
|
configurable: true
|
|
4505
7561
|
});
|
|
4506
7562
|
}
|
|
4507
|
-
function getElementAtPath(obj,
|
|
4508
|
-
if (!
|
|
7563
|
+
function getElementAtPath(obj, path2) {
|
|
7564
|
+
if (!path2)
|
|
4509
7565
|
return obj;
|
|
4510
|
-
return
|
|
7566
|
+
return path2.reduce((acc, key) => acc?.[key], obj);
|
|
4511
7567
|
}
|
|
4512
7568
|
function promiseAllObject(promisesObj) {
|
|
4513
7569
|
const keys = Object.keys(promisesObj);
|
|
@@ -4534,7 +7590,7 @@ function esc(str) {
|
|
|
4534
7590
|
function isObject(data) {
|
|
4535
7591
|
return typeof data === "object" && data !== null && !Array.isArray(data);
|
|
4536
7592
|
}
|
|
4537
|
-
function
|
|
7593
|
+
function isPlainObject2(o) {
|
|
4538
7594
|
if (isObject(o) === false)
|
|
4539
7595
|
return false;
|
|
4540
7596
|
const ctor = o.constructor;
|
|
@@ -4662,7 +7718,7 @@ function omit(schema, mask) {
|
|
|
4662
7718
|
});
|
|
4663
7719
|
}
|
|
4664
7720
|
function extend(schema, shape) {
|
|
4665
|
-
if (!
|
|
7721
|
+
if (!isPlainObject2(shape)) {
|
|
4666
7722
|
throw new Error("Invalid input to extend: expected a plain object");
|
|
4667
7723
|
}
|
|
4668
7724
|
const def = {
|
|
@@ -4756,11 +7812,11 @@ function aborted(x, startIndex = 0) {
|
|
|
4756
7812
|
}
|
|
4757
7813
|
return false;
|
|
4758
7814
|
}
|
|
4759
|
-
function prefixIssues(
|
|
7815
|
+
function prefixIssues(path2, issues) {
|
|
4760
7816
|
return issues.map((iss) => {
|
|
4761
7817
|
var _a;
|
|
4762
7818
|
(_a = iss).path ?? (_a.path = []);
|
|
4763
|
-
iss.path.unshift(
|
|
7819
|
+
iss.path.unshift(path2);
|
|
4764
7820
|
return iss;
|
|
4765
7821
|
});
|
|
4766
7822
|
}
|
|
@@ -4949,7 +8005,7 @@ function treeifyError(error40, _mapper) {
|
|
|
4949
8005
|
return issue2.message;
|
|
4950
8006
|
};
|
|
4951
8007
|
const result = { errors: [] };
|
|
4952
|
-
const processError = (error41,
|
|
8008
|
+
const processError = (error41, path2 = []) => {
|
|
4953
8009
|
var _a, _b;
|
|
4954
8010
|
for (const issue2 of error41.issues) {
|
|
4955
8011
|
if (issue2.code === "invalid_union" && issue2.errors.length) {
|
|
@@ -4959,7 +8015,7 @@ function treeifyError(error40, _mapper) {
|
|
|
4959
8015
|
} else if (issue2.code === "invalid_element") {
|
|
4960
8016
|
processError({ issues: issue2.issues }, issue2.path);
|
|
4961
8017
|
} else {
|
|
4962
|
-
const fullpath = [...
|
|
8018
|
+
const fullpath = [...path2, ...issue2.path];
|
|
4963
8019
|
if (fullpath.length === 0) {
|
|
4964
8020
|
result.errors.push(mapper(issue2));
|
|
4965
8021
|
continue;
|
|
@@ -4989,9 +8045,9 @@ function treeifyError(error40, _mapper) {
|
|
|
4989
8045
|
processError(error40);
|
|
4990
8046
|
return result;
|
|
4991
8047
|
}
|
|
4992
|
-
function toDotPath(
|
|
8048
|
+
function toDotPath(path2) {
|
|
4993
8049
|
const segs = [];
|
|
4994
|
-
for (const seg of
|
|
8050
|
+
for (const seg of path2) {
|
|
4995
8051
|
if (typeof seg === "number")
|
|
4996
8052
|
segs.push(`[${seg}]`);
|
|
4997
8053
|
else if (typeof seg === "symbol")
|
|
@@ -5017,7 +8073,7 @@ function prettifyError(error40) {
|
|
|
5017
8073
|
return lines.join("\n");
|
|
5018
8074
|
}
|
|
5019
8075
|
var initializer, $ZodError, $ZodRealError;
|
|
5020
|
-
var
|
|
8076
|
+
var init_errors2 = __esm({
|
|
5021
8077
|
"../../node_modules/.pnpm/zod@3.25.76/node_modules/zod/v4/core/errors.js"() {
|
|
5022
8078
|
init_core();
|
|
5023
8079
|
init_util();
|
|
@@ -5053,7 +8109,7 @@ var _parse, parse, _parseAsync, parseAsync, _safeParse, safeParse, _safeParseAsy
|
|
|
5053
8109
|
var init_parse = __esm({
|
|
5054
8110
|
"../../node_modules/.pnpm/zod@3.25.76/node_modules/zod/v4/core/parse.js"() {
|
|
5055
8111
|
init_core();
|
|
5056
|
-
|
|
8112
|
+
init_errors2();
|
|
5057
8113
|
init_util();
|
|
5058
8114
|
_parse = (_Err) => (schema, value, _ctx, _params) => {
|
|
5059
8115
|
const ctx = _ctx ? Object.assign(_ctx, { async: false }) : { async: false };
|
|
@@ -5841,7 +8897,7 @@ function isValidBase64(data) {
|
|
|
5841
8897
|
function isValidBase64URL(data) {
|
|
5842
8898
|
if (!base64url.test(data))
|
|
5843
8899
|
return false;
|
|
5844
|
-
const base643 = data.replace(/[-_]/g, (
|
|
8900
|
+
const base643 = data.replace(/[-_]/g, (c3) => c3 === "-" ? "+" : "/");
|
|
5845
8901
|
const padded = base643.padEnd(Math.ceil(base643.length / 4) * 4, "=");
|
|
5846
8902
|
return isValidBase64(padded);
|
|
5847
8903
|
}
|
|
@@ -5917,7 +8973,7 @@ function mergeValues(a, b) {
|
|
|
5917
8973
|
if (a instanceof Date && b instanceof Date && +a === +b) {
|
|
5918
8974
|
return { valid: true, data: a };
|
|
5919
8975
|
}
|
|
5920
|
-
if (
|
|
8976
|
+
if (isPlainObject2(a) && isPlainObject2(b)) {
|
|
5921
8977
|
const bKeys = Object.keys(b);
|
|
5922
8978
|
const sharedKeys = Object.keys(a).filter((key) => bKeys.indexOf(key) !== -1);
|
|
5923
8979
|
const newObj = { ...a, ...b };
|
|
@@ -6994,7 +10050,7 @@ var init_schemas = __esm({
|
|
|
6994
10050
|
$ZodType.init(inst, def);
|
|
6995
10051
|
inst._zod.parse = (payload, ctx) => {
|
|
6996
10052
|
const input = payload.value;
|
|
6997
|
-
if (!
|
|
10053
|
+
if (!isPlainObject2(input)) {
|
|
6998
10054
|
payload.issues.push({
|
|
6999
10055
|
expected: "record",
|
|
7000
10056
|
code: "invalid_type",
|
|
@@ -14535,7 +17591,7 @@ var init_core2 = __esm({
|
|
|
14535
17591
|
"../../node_modules/.pnpm/zod@3.25.76/node_modules/zod/v4/core/index.js"() {
|
|
14536
17592
|
init_core();
|
|
14537
17593
|
init_parse();
|
|
14538
|
-
|
|
17594
|
+
init_errors2();
|
|
14539
17595
|
init_schemas();
|
|
14540
17596
|
init_checks();
|
|
14541
17597
|
init_versions();
|
|
@@ -14608,7 +17664,7 @@ var init_iso = __esm({
|
|
|
14608
17664
|
|
|
14609
17665
|
// ../../node_modules/.pnpm/zod@3.25.76/node_modules/zod/v4/classic/errors.js
|
|
14610
17666
|
var initializer2, ZodError, ZodRealError;
|
|
14611
|
-
var
|
|
17667
|
+
var init_errors3 = __esm({
|
|
14612
17668
|
"../../node_modules/.pnpm/zod@3.25.76/node_modules/zod/v4/classic/errors.js"() {
|
|
14613
17669
|
init_core2();
|
|
14614
17670
|
init_core2();
|
|
@@ -14652,7 +17708,7 @@ var parse2, parseAsync2, safeParse2, safeParseAsync2;
|
|
|
14652
17708
|
var init_parse2 = __esm({
|
|
14653
17709
|
"../../node_modules/.pnpm/zod@3.25.76/node_modules/zod/v4/classic/parse.js"() {
|
|
14654
17710
|
init_core2();
|
|
14655
|
-
|
|
17711
|
+
init_errors3();
|
|
14656
17712
|
parse2 = /* @__PURE__ */ _parse(ZodRealError);
|
|
14657
17713
|
parseAsync2 = /* @__PURE__ */ _parseAsync(ZodRealError);
|
|
14658
17714
|
safeParse2 = /* @__PURE__ */ _safeParse(ZodRealError);
|
|
@@ -15011,7 +18067,7 @@ function promise(innerType) {
|
|
|
15011
18067
|
innerType
|
|
15012
18068
|
});
|
|
15013
18069
|
}
|
|
15014
|
-
function
|
|
18070
|
+
function check2(fn) {
|
|
15015
18071
|
const ch = new $ZodCheck({
|
|
15016
18072
|
check: "custom"
|
|
15017
18073
|
// ...util.normalizeParams(params),
|
|
@@ -15026,7 +18082,7 @@ function refine(fn, _params = {}) {
|
|
|
15026
18082
|
return _refine(ZodCustom, fn, _params);
|
|
15027
18083
|
}
|
|
15028
18084
|
function superRefine(fn) {
|
|
15029
|
-
const ch =
|
|
18085
|
+
const ch = check2((payload) => {
|
|
15030
18086
|
payload.addIssue = (issue2) => {
|
|
15031
18087
|
if (typeof issue2 === "string") {
|
|
15032
18088
|
payload.issues.push(util_exports.issue(issue2, payload.value, ch._zod.def));
|
|
@@ -15102,7 +18158,7 @@ var init_schemas2 = __esm({
|
|
|
15102
18158
|
inst.parseAsync = async (data, params) => parseAsync2(inst, data, params, { callee: inst.parseAsync });
|
|
15103
18159
|
inst.safeParseAsync = async (data, params) => safeParseAsync2(inst, data, params);
|
|
15104
18160
|
inst.spa = inst.safeParseAsync;
|
|
15105
|
-
inst.refine = (
|
|
18161
|
+
inst.refine = (check3, params) => inst.check(refine(check3, params));
|
|
15106
18162
|
inst.superRefine = (refinement) => inst.check(superRefine(refinement));
|
|
15107
18163
|
inst.overwrite = (fn) => inst.check(_overwrite(fn));
|
|
15108
18164
|
inst.optional = () => optional(inst);
|
|
@@ -15369,9 +18425,9 @@ var init_schemas2 = __esm({
|
|
|
15369
18425
|
ZodType.init(inst, def);
|
|
15370
18426
|
inst.min = (value, params) => inst.check(_gte(value, params));
|
|
15371
18427
|
inst.max = (value, params) => inst.check(_lte(value, params));
|
|
15372
|
-
const
|
|
15373
|
-
inst.minDate =
|
|
15374
|
-
inst.maxDate =
|
|
18428
|
+
const c3 = inst._zod.bag;
|
|
18429
|
+
inst.minDate = c3.minimum ? new Date(c3.minimum) : null;
|
|
18430
|
+
inst.maxDate = c3.maximum ? new Date(c3.maximum) : null;
|
|
15375
18431
|
});
|
|
15376
18432
|
ZodArray = /* @__PURE__ */ $constructor("ZodArray", (inst, def) => {
|
|
15377
18433
|
$ZodArray.init(inst, def);
|
|
@@ -15754,7 +18810,7 @@ __export(external_exports, {
|
|
|
15754
18810
|
bigint: () => bigint2,
|
|
15755
18811
|
boolean: () => boolean2,
|
|
15756
18812
|
catch: () => _catch2,
|
|
15757
|
-
check: () =>
|
|
18813
|
+
check: () => check2,
|
|
15758
18814
|
cidrv4: () => cidrv42,
|
|
15759
18815
|
cidrv6: () => cidrv62,
|
|
15760
18816
|
clone: () => clone,
|
|
@@ -15883,7 +18939,7 @@ var init_external = __esm({
|
|
|
15883
18939
|
init_core2();
|
|
15884
18940
|
init_schemas2();
|
|
15885
18941
|
init_checks2();
|
|
15886
|
-
|
|
18942
|
+
init_errors3();
|
|
15887
18943
|
init_parse2();
|
|
15888
18944
|
init_compat();
|
|
15889
18945
|
init_core2();
|
|
@@ -18415,7 +21471,7 @@ var init_src = __esm({
|
|
|
18415
21471
|
|
|
18416
21472
|
// ../acp-runtime/src/spawners/node.ts
|
|
18417
21473
|
import { spawn as nodeSpawn } from "node:child_process";
|
|
18418
|
-
import { Readable, Writable } from "node:stream";
|
|
21474
|
+
import { Readable as Readable2, Writable } from "node:stream";
|
|
18419
21475
|
var NodeSpawner;
|
|
18420
21476
|
var init_node = __esm({
|
|
18421
21477
|
"../acp-runtime/src/spawners/node.ts"() {
|
|
@@ -18436,8 +21492,8 @@ var init_node = __esm({
|
|
|
18436
21492
|
stdio: ["pipe", "pipe", "pipe"]
|
|
18437
21493
|
});
|
|
18438
21494
|
const stdin = Writable.toWeb(child.stdin);
|
|
18439
|
-
const stdout =
|
|
18440
|
-
const stderr =
|
|
21495
|
+
const stdout = Readable2.toWeb(child.stdout);
|
|
21496
|
+
const stderr = Readable2.toWeb(child.stderr);
|
|
18441
21497
|
const exited = new Promise((resolve) => {
|
|
18442
21498
|
let settled = false;
|
|
18443
21499
|
const settle = (code, signal) => {
|
|
@@ -18461,28 +21517,28 @@ var init_node = __esm({
|
|
|
18461
21517
|
});
|
|
18462
21518
|
|
|
18463
21519
|
// src/bridge/lib/session-cwd.ts
|
|
18464
|
-
import { mkdir as
|
|
21520
|
+
import { mkdir as mkdir6, rm, writeFile as writeFile6 } from "node:fs/promises";
|
|
18465
21521
|
import { createHash } from "node:crypto";
|
|
18466
|
-
import { dirname as
|
|
21522
|
+
import { dirname as dirname8, join as join5 } from "node:path";
|
|
18467
21523
|
function dirNameFor(sessionId) {
|
|
18468
21524
|
if (/^[a-f0-9]{1,12}$/i.test(sessionId)) return sessionId.toLowerCase();
|
|
18469
21525
|
return createHash("sha256").update(sessionId).digest("hex").slice(0, DIR_NAME_LEN);
|
|
18470
21526
|
}
|
|
18471
21527
|
async function ensureSessionCwd(sessionId) {
|
|
18472
|
-
const cwd =
|
|
18473
|
-
await
|
|
21528
|
+
const cwd = join5(paths().sessionsDir, dirNameFor(sessionId));
|
|
21529
|
+
await mkdir6(cwd, { recursive: true });
|
|
18474
21530
|
return cwd;
|
|
18475
21531
|
}
|
|
18476
21532
|
async function writeBundle(cwd, files) {
|
|
18477
21533
|
for (const f of files) {
|
|
18478
21534
|
if (f.path.startsWith("/") || f.path.includes("..")) continue;
|
|
18479
|
-
const dst =
|
|
18480
|
-
await
|
|
18481
|
-
await
|
|
21535
|
+
const dst = join5(cwd, f.path);
|
|
21536
|
+
await mkdir6(dirname8(dst), { recursive: true });
|
|
21537
|
+
await writeFile6(dst, f.content);
|
|
18482
21538
|
}
|
|
18483
21539
|
}
|
|
18484
21540
|
async function removeSessionCwd(sessionId) {
|
|
18485
|
-
const cwd =
|
|
21541
|
+
const cwd = join5(paths().sessionsDir, dirNameFor(sessionId));
|
|
18486
21542
|
try {
|
|
18487
21543
|
await rm(cwd, { recursive: true, force: true });
|
|
18488
21544
|
} catch {
|
|
@@ -18498,12 +21554,12 @@ var init_session_cwd = __esm({
|
|
|
18498
21554
|
});
|
|
18499
21555
|
|
|
18500
21556
|
// src/bridge/lib/claude-config-dir.ts
|
|
18501
|
-
import { mkdir as
|
|
18502
|
-
import { join as
|
|
18503
|
-
import { homedir as
|
|
21557
|
+
import { mkdir as mkdir7, readdir, rm as rm2, symlink } from "node:fs/promises";
|
|
21558
|
+
import { join as join6 } from "node:path";
|
|
21559
|
+
import { homedir as homedir3 } from "node:os";
|
|
18504
21560
|
async function setupClaudeConfigDir(cwd, blocklist) {
|
|
18505
|
-
const cfgDir =
|
|
18506
|
-
await
|
|
21561
|
+
const cfgDir = join6(cwd, ".claude-config");
|
|
21562
|
+
await mkdir7(cfgDir, { recursive: true });
|
|
18507
21563
|
await mirrorClaudeHome(cfgDir);
|
|
18508
21564
|
await rebuildSkills(cfgDir, blocklist);
|
|
18509
21565
|
return cfgDir;
|
|
@@ -18517,11 +21573,11 @@ async function mirrorClaudeHome(cfgDir) {
|
|
|
18517
21573
|
}
|
|
18518
21574
|
for (const entry of entries) {
|
|
18519
21575
|
if (entry === "skills") continue;
|
|
18520
|
-
const dst =
|
|
21576
|
+
const dst = join6(cfgDir, entry);
|
|
18521
21577
|
await rm2(dst, { recursive: true, force: true }).catch(() => {
|
|
18522
21578
|
});
|
|
18523
21579
|
try {
|
|
18524
|
-
await symlink(
|
|
21580
|
+
await symlink(join6(CLAUDE_HOME, entry), dst);
|
|
18525
21581
|
} catch (e) {
|
|
18526
21582
|
process.stderr.write(
|
|
18527
21583
|
` ! claude-config symlink ${entry} failed (non-fatal): ${e.message}
|
|
@@ -18531,11 +21587,11 @@ async function mirrorClaudeHome(cfgDir) {
|
|
|
18531
21587
|
}
|
|
18532
21588
|
}
|
|
18533
21589
|
async function rebuildSkills(cfgDir, blocklist) {
|
|
18534
|
-
const dst =
|
|
21590
|
+
const dst = join6(cfgDir, "skills");
|
|
18535
21591
|
await rm2(dst, { recursive: true, force: true }).catch(() => {
|
|
18536
21592
|
});
|
|
18537
|
-
await
|
|
18538
|
-
const src =
|
|
21593
|
+
await mkdir7(dst, { recursive: true });
|
|
21594
|
+
const src = join6(CLAUDE_HOME, "skills");
|
|
18539
21595
|
let ids = [];
|
|
18540
21596
|
try {
|
|
18541
21597
|
ids = await readdir(src);
|
|
@@ -18545,7 +21601,7 @@ async function rebuildSkills(cfgDir, blocklist) {
|
|
|
18545
21601
|
for (const id of ids) {
|
|
18546
21602
|
if (id.startsWith(".")) continue;
|
|
18547
21603
|
if (blocklist.has(id)) continue;
|
|
18548
|
-
await symlink(
|
|
21604
|
+
await symlink(join6(src, id), join6(dst, id)).catch((e) => {
|
|
18549
21605
|
process.stderr.write(
|
|
18550
21606
|
` ! claude-config skill symlink ${id} failed (non-fatal): ${e.message}
|
|
18551
21607
|
`
|
|
@@ -18557,11 +21613,12 @@ var CLAUDE_HOME;
|
|
|
18557
21613
|
var init_claude_config_dir = __esm({
|
|
18558
21614
|
"src/bridge/lib/claude-config-dir.ts"() {
|
|
18559
21615
|
"use strict";
|
|
18560
|
-
CLAUDE_HOME =
|
|
21616
|
+
CLAUDE_HOME = join6(homedir3(), ".claude");
|
|
18561
21617
|
}
|
|
18562
21618
|
});
|
|
18563
21619
|
|
|
18564
21620
|
// src/bridge/lib/session-manager.ts
|
|
21621
|
+
import { spawn as childSpawn } from "node:child_process";
|
|
18565
21622
|
function scrubAcpSpawnEnv(base) {
|
|
18566
21623
|
return {
|
|
18567
21624
|
...base,
|
|
@@ -18585,6 +21642,11 @@ var init_session_manager = __esm({
|
|
|
18585
21642
|
#runtime = new AcpRuntimeImpl(this.#spawner);
|
|
18586
21643
|
#sessions = /* @__PURE__ */ new Map();
|
|
18587
21644
|
#env = { apiKey: "", apiUrl: "", runtimeToken: "" };
|
|
21645
|
+
/** Set by `drain()` to refuse new session.start while in-flight turns
|
|
21646
|
+
* finish. Existing sessions keep accepting prompts so a user mid-turn
|
|
21647
|
+
* doesn't hit "session not ready" mid-stream just because the daemon
|
|
21648
|
+
* is on its way out. */
|
|
21649
|
+
#draining = false;
|
|
18588
21650
|
constructor(send) {
|
|
18589
21651
|
this.#send = send;
|
|
18590
21652
|
}
|
|
@@ -18597,6 +21659,18 @@ var init_session_manager = __esm({
|
|
|
18597
21659
|
has(session_id) {
|
|
18598
21660
|
return this.#sessions.has(session_id);
|
|
18599
21661
|
}
|
|
21662
|
+
/** Sum of in-flight turns across all sessions. A turn registers itself
|
|
21663
|
+
* in `sess.turns` when `prompt()` starts and removes itself in the
|
|
21664
|
+
* finally block when the ACP child finishes streaming. drain() polls
|
|
21665
|
+
* this to know when it's safe to exit. */
|
|
21666
|
+
activeTurnCount() {
|
|
21667
|
+
let n = 0;
|
|
21668
|
+
for (const s of this.#sessions.values()) n += s.turns.size;
|
|
21669
|
+
return n;
|
|
21670
|
+
}
|
|
21671
|
+
sessionCount() {
|
|
21672
|
+
return this.#sessions.size;
|
|
21673
|
+
}
|
|
18600
21674
|
/** Re-announce alive sessions to the server (used after WS reconnect). */
|
|
18601
21675
|
announceAll() {
|
|
18602
21676
|
for (const [session_id, sess] of this.#sessions) {
|
|
@@ -18604,6 +21678,15 @@ var init_session_manager = __esm({
|
|
|
18604
21678
|
}
|
|
18605
21679
|
}
|
|
18606
21680
|
async start(p) {
|
|
21681
|
+
if (this.#draining) {
|
|
21682
|
+
this.#send({
|
|
21683
|
+
type: "session.error",
|
|
21684
|
+
session_id: p.session_id,
|
|
21685
|
+
turn_id: "",
|
|
21686
|
+
message: "daemon draining for restart \u2014 retry in a few seconds"
|
|
21687
|
+
});
|
|
21688
|
+
return;
|
|
21689
|
+
}
|
|
18607
21690
|
const existing = this.#sessions.get(p.session_id);
|
|
18608
21691
|
if (existing) {
|
|
18609
21692
|
this.#send({
|
|
@@ -18613,7 +21696,7 @@ var init_session_manager = __esm({
|
|
|
18613
21696
|
});
|
|
18614
21697
|
return;
|
|
18615
21698
|
}
|
|
18616
|
-
const agent =
|
|
21699
|
+
const agent = resolveKnownAgent(p.agent_id);
|
|
18617
21700
|
if (!agent) {
|
|
18618
21701
|
this.#send({
|
|
18619
21702
|
type: "session.error",
|
|
@@ -18622,12 +21705,32 @@ var init_session_manager = __esm({
|
|
|
18622
21705
|
});
|
|
18623
21706
|
return;
|
|
18624
21707
|
}
|
|
21708
|
+
if (agent.id !== p.agent_id) {
|
|
21709
|
+
process.stderr.write(
|
|
21710
|
+
` \u21AA canonicalized acp_agent_id ${p.agent_id} \u2192 ${agent.id} (legacy alias)
|
|
21711
|
+
`
|
|
21712
|
+
);
|
|
21713
|
+
}
|
|
21714
|
+
const onPath = await new Promise((resolve) => {
|
|
21715
|
+
const probe = process.platform === "win32" ? "where" : "which";
|
|
21716
|
+
const p2 = childSpawn(probe, [agent.spec.command], { stdio: "ignore" });
|
|
21717
|
+
p2.once("error", () => resolve(false));
|
|
21718
|
+
p2.once("exit", (code) => resolve(code === 0));
|
|
21719
|
+
});
|
|
21720
|
+
if (!onPath) {
|
|
21721
|
+
this.#send({
|
|
21722
|
+
type: "session.error",
|
|
21723
|
+
session_id: p.session_id,
|
|
21724
|
+
message: `binary not on PATH for ${agent.id}: \`${agent.spec.command}\`` + (agent.installHint ? `. Install: ${agent.installHint}` : "")
|
|
21725
|
+
});
|
|
21726
|
+
return;
|
|
21727
|
+
}
|
|
18625
21728
|
const sessionCwd = await ensureSessionCwd(p.session_id);
|
|
18626
21729
|
let blocklist = [];
|
|
18627
21730
|
let bundleMcpServers = [];
|
|
18628
21731
|
let bundleEnv = [];
|
|
18629
21732
|
try {
|
|
18630
|
-
const bundle = await this.#fetchBundle(p.session_id,
|
|
21733
|
+
const bundle = await this.#fetchBundle(p.session_id, agent.id);
|
|
18631
21734
|
if (bundle) {
|
|
18632
21735
|
await writeBundle(sessionCwd, bundle.files);
|
|
18633
21736
|
blocklist = bundle.local_skill_blocklist ?? [];
|
|
@@ -18639,7 +21742,7 @@ var init_session_manager = __esm({
|
|
|
18639
21742
|
`);
|
|
18640
21743
|
}
|
|
18641
21744
|
const extraEnv = {};
|
|
18642
|
-
if (
|
|
21745
|
+
if (agent.id === "claude-acp") {
|
|
18643
21746
|
try {
|
|
18644
21747
|
const cfgDir = await setupClaudeConfigDir(sessionCwd, new Set(blocklist));
|
|
18645
21748
|
extraEnv.CLAUDE_CONFIG_DIR = cfgDir;
|
|
@@ -18760,6 +21863,66 @@ var init_session_manager = __esm({
|
|
|
18760
21863
|
const ids = [...this.#sessions.keys()];
|
|
18761
21864
|
await Promise.all(ids.map((id) => this.#killChild(id)));
|
|
18762
21865
|
}
|
|
21866
|
+
/**
|
|
21867
|
+
* Graceful drain for upgrade/restart. Caller (daemon SIGTERM handler)
|
|
21868
|
+
* awaits this before exiting so in-flight ACP turns get to finish
|
|
21869
|
+
* naturally instead of being SIGTERM'd mid-stream.
|
|
21870
|
+
*
|
|
21871
|
+
* Recovery model — mirrors the cloud agent's DO-eviction recovery
|
|
21872
|
+
* (apps/agent/src/runtime/turn-runtime.ts:268 recoverAgentTurn):
|
|
21873
|
+
*
|
|
21874
|
+
* 1. Set #draining → start() rejects new sessions; server retries.
|
|
21875
|
+
* 2. Poll activeTurnCount every 200ms until either:
|
|
21876
|
+
* - all turns drained naturally (clean session.complete) → break
|
|
21877
|
+
* - deadline elapsed → abort remaining turns. Their prompt()
|
|
21878
|
+
* loops unwind, emit session.error, and the ACP children
|
|
21879
|
+
* checkpoint their conversation state to disk (each ACP
|
|
21880
|
+
* implementation owns its own persistence; e.g. claude-acp
|
|
21881
|
+
* stores into ~/.claude/projects/...).
|
|
21882
|
+
* 3. disposeAll() — KEEPS spawn cwds. Same shape as a clean
|
|
21883
|
+
* shutdown.
|
|
21884
|
+
*
|
|
21885
|
+
* The next time the server sends session.start for any of these ids
|
|
21886
|
+
* it includes `resume.acp_session_id`. The new daemon respawns a
|
|
21887
|
+
* fresh ACP child in the preserved cwd and calls session/load to
|
|
21888
|
+
* restore conversation history (session-manager.ts:311 →
|
|
21889
|
+
* session.ts:108). Worst case the user re-prompts the cut-off turn;
|
|
21890
|
+
* partial response on their screen is the only artifact.
|
|
21891
|
+
*
|
|
21892
|
+
* Idempotent: a second call while one is in progress no-ops past the
|
|
21893
|
+
* existing drain.
|
|
21894
|
+
*/
|
|
21895
|
+
async drain(deadlineMs, opts) {
|
|
21896
|
+
if (this.#draining) {
|
|
21897
|
+
const t02 = Date.now();
|
|
21898
|
+
while (this.#sessions.size > 0 && Date.now() - t02 < deadlineMs) {
|
|
21899
|
+
await new Promise((r) => setTimeout(r, 200));
|
|
21900
|
+
}
|
|
21901
|
+
return { initialTurns: 0, abortedTurns: 0, sessions: 0 };
|
|
21902
|
+
}
|
|
21903
|
+
this.#draining = true;
|
|
21904
|
+
const initialTurns = this.activeTurnCount();
|
|
21905
|
+
const initialSessions = this.#sessions.size;
|
|
21906
|
+
const t0 = Date.now();
|
|
21907
|
+
while (this.activeTurnCount() > 0) {
|
|
21908
|
+
const elapsed = Date.now() - t0;
|
|
21909
|
+
if (elapsed >= deadlineMs) break;
|
|
21910
|
+
opts?.onProgress?.(this.activeTurnCount(), deadlineMs - elapsed);
|
|
21911
|
+
await new Promise((r) => setTimeout(r, 200));
|
|
21912
|
+
}
|
|
21913
|
+
let aborted2 = 0;
|
|
21914
|
+
for (const sess of this.#sessions.values()) {
|
|
21915
|
+
for (const ctrl of sess.turns.values()) {
|
|
21916
|
+
ctrl.abort();
|
|
21917
|
+
aborted2 += 1;
|
|
21918
|
+
}
|
|
21919
|
+
}
|
|
21920
|
+
if (aborted2 > 0) {
|
|
21921
|
+
await new Promise((r) => setTimeout(r, 2e3));
|
|
21922
|
+
}
|
|
21923
|
+
await this.disposeAll();
|
|
21924
|
+
return { initialTurns, abortedTurns: aborted2, sessions: initialSessions };
|
|
21925
|
+
}
|
|
18763
21926
|
/** Kill the ACP child + drop in-memory state. Does NOT touch the spawn
|
|
18764
21927
|
* cwd — caller decides whether the cwd should outlive this. */
|
|
18765
21928
|
async #killChild(session_id) {
|
|
@@ -18788,27 +21951,34 @@ var init_session_manager = __esm({
|
|
|
18788
21951
|
});
|
|
18789
21952
|
|
|
18790
21953
|
// src/bridge/lib/local-skills.ts
|
|
18791
|
-
import { readdir as readdir2, readFile as
|
|
18792
|
-
import { join as
|
|
18793
|
-
import { homedir as
|
|
21954
|
+
import { readdir as readdir2, readFile as readFile6, stat } from "node:fs/promises";
|
|
21955
|
+
import { join as join7 } from "node:path";
|
|
21956
|
+
import { homedir as homedir4 } from "node:os";
|
|
18794
21957
|
async function detectLocalSkills() {
|
|
18795
|
-
|
|
18796
|
-
|
|
18797
|
-
|
|
21958
|
+
const [claude, gemini, opencode] = await Promise.all([
|
|
21959
|
+
detectClaudeCodeSkills(),
|
|
21960
|
+
detectGeminiExtensions(),
|
|
21961
|
+
detectOpencodeAgents()
|
|
21962
|
+
]);
|
|
21963
|
+
const out = {};
|
|
21964
|
+
if (claude.length) out["claude-acp"] = claude;
|
|
21965
|
+
if (gemini.length) out["gemini"] = gemini;
|
|
21966
|
+
if (opencode.length) out["opencode"] = opencode;
|
|
21967
|
+
return out;
|
|
18798
21968
|
}
|
|
18799
21969
|
async function detectClaudeCodeSkills() {
|
|
18800
21970
|
const seen = /* @__PURE__ */ new Map();
|
|
18801
|
-
for (const skill of await scanSkillsDir(
|
|
21971
|
+
for (const skill of await scanSkillsDir(join7(HOME, ".claude", "skills"), "global")) {
|
|
18802
21972
|
seen.set(skill.id, skill);
|
|
18803
21973
|
}
|
|
18804
|
-
const pluginsRoot =
|
|
21974
|
+
const pluginsRoot = join7(HOME, ".claude", "plugins");
|
|
18805
21975
|
let plugins = [];
|
|
18806
21976
|
try {
|
|
18807
21977
|
plugins = await readdir2(pluginsRoot);
|
|
18808
21978
|
} catch {
|
|
18809
21979
|
}
|
|
18810
21980
|
for (const plugin of plugins) {
|
|
18811
|
-
const pluginSkillsDir =
|
|
21981
|
+
const pluginSkillsDir = join7(pluginsRoot, plugin, "skills");
|
|
18812
21982
|
for (const skill of await scanSkillsDir(pluginSkillsDir, "plugin", plugin)) {
|
|
18813
21983
|
const key = `${plugin}/${skill.id}`;
|
|
18814
21984
|
seen.set(key, skill);
|
|
@@ -18826,7 +21996,7 @@ async function scanSkillsDir(dir, source, source_label) {
|
|
|
18826
21996
|
const out = [];
|
|
18827
21997
|
for (const id of entries) {
|
|
18828
21998
|
if (id.startsWith(".")) continue;
|
|
18829
|
-
const skillDir =
|
|
21999
|
+
const skillDir = join7(dir, id);
|
|
18830
22000
|
let st;
|
|
18831
22001
|
try {
|
|
18832
22002
|
st = await stat(skillDir);
|
|
@@ -18834,7 +22004,7 @@ async function scanSkillsDir(dir, source, source_label) {
|
|
|
18834
22004
|
continue;
|
|
18835
22005
|
}
|
|
18836
22006
|
if (!st.isDirectory()) continue;
|
|
18837
|
-
const meta = await readSkillMeta(
|
|
22007
|
+
const meta = await readSkillMeta(join7(skillDir, "SKILL.md"));
|
|
18838
22008
|
out.push({
|
|
18839
22009
|
id,
|
|
18840
22010
|
name: meta.name ?? id,
|
|
@@ -18849,7 +22019,7 @@ async function scanSkillsDir(dir, source, source_label) {
|
|
|
18849
22019
|
async function readSkillMeta(file2) {
|
|
18850
22020
|
let text;
|
|
18851
22021
|
try {
|
|
18852
|
-
text = await
|
|
22022
|
+
text = await readFile6(file2, "utf-8");
|
|
18853
22023
|
} catch {
|
|
18854
22024
|
return {};
|
|
18855
22025
|
}
|
|
@@ -18873,11 +22043,89 @@ async function readSkillMeta(file2) {
|
|
|
18873
22043
|
}
|
|
18874
22044
|
return { name, description };
|
|
18875
22045
|
}
|
|
22046
|
+
async function detectGeminiExtensions() {
|
|
22047
|
+
const root = join7(HOME, ".gemini", "extensions");
|
|
22048
|
+
let entries;
|
|
22049
|
+
try {
|
|
22050
|
+
entries = await readdir2(root);
|
|
22051
|
+
} catch {
|
|
22052
|
+
return [];
|
|
22053
|
+
}
|
|
22054
|
+
const out = [];
|
|
22055
|
+
for (const id of entries) {
|
|
22056
|
+
if (id.startsWith(".")) continue;
|
|
22057
|
+
const extDir = join7(root, id);
|
|
22058
|
+
let st;
|
|
22059
|
+
try {
|
|
22060
|
+
st = await stat(extDir);
|
|
22061
|
+
} catch {
|
|
22062
|
+
continue;
|
|
22063
|
+
}
|
|
22064
|
+
if (!st.isDirectory()) continue;
|
|
22065
|
+
let manifest = {};
|
|
22066
|
+
try {
|
|
22067
|
+
const raw = await readFile6(join7(extDir, "gemini-extension.json"), "utf-8");
|
|
22068
|
+
manifest = JSON.parse(raw);
|
|
22069
|
+
} catch {
|
|
22070
|
+
continue;
|
|
22071
|
+
}
|
|
22072
|
+
let description = manifest.description;
|
|
22073
|
+
if (!description) {
|
|
22074
|
+
const ctxName = manifest.contextFileName ?? "GEMINI.md";
|
|
22075
|
+
const meta = await readSkillMeta(join7(extDir, ctxName));
|
|
22076
|
+
description = meta.description;
|
|
22077
|
+
}
|
|
22078
|
+
out.push({
|
|
22079
|
+
id,
|
|
22080
|
+
name: manifest.name ?? id,
|
|
22081
|
+
description,
|
|
22082
|
+
source: "global",
|
|
22083
|
+
path: extDir
|
|
22084
|
+
});
|
|
22085
|
+
}
|
|
22086
|
+
return out;
|
|
22087
|
+
}
|
|
22088
|
+
async function detectOpencodeAgents() {
|
|
22089
|
+
const seen = /* @__PURE__ */ new Map();
|
|
22090
|
+
const dirs = [
|
|
22091
|
+
join7(HOME, ".opencode", "agents"),
|
|
22092
|
+
join7(HOME, ".config", "opencode", "agents")
|
|
22093
|
+
];
|
|
22094
|
+
for (const dir of dirs) {
|
|
22095
|
+
let entries;
|
|
22096
|
+
try {
|
|
22097
|
+
entries = await readdir2(dir);
|
|
22098
|
+
} catch {
|
|
22099
|
+
continue;
|
|
22100
|
+
}
|
|
22101
|
+
for (const file2 of entries) {
|
|
22102
|
+
if (!file2.endsWith(".md") || file2.startsWith(".")) continue;
|
|
22103
|
+
const id = file2.slice(0, -3);
|
|
22104
|
+
const path2 = join7(dir, file2);
|
|
22105
|
+
let st;
|
|
22106
|
+
try {
|
|
22107
|
+
st = await stat(path2);
|
|
22108
|
+
} catch {
|
|
22109
|
+
continue;
|
|
22110
|
+
}
|
|
22111
|
+
if (!st.isFile()) continue;
|
|
22112
|
+
const meta = await readSkillMeta(path2);
|
|
22113
|
+
seen.set(id, {
|
|
22114
|
+
id,
|
|
22115
|
+
name: meta.name ?? id,
|
|
22116
|
+
description: meta.description,
|
|
22117
|
+
source: "global",
|
|
22118
|
+
path: path2
|
|
22119
|
+
});
|
|
22120
|
+
}
|
|
22121
|
+
}
|
|
22122
|
+
return [...seen.values()];
|
|
22123
|
+
}
|
|
18876
22124
|
var HOME;
|
|
18877
22125
|
var init_local_skills = __esm({
|
|
18878
22126
|
"src/bridge/lib/local-skills.ts"() {
|
|
18879
22127
|
"use strict";
|
|
18880
|
-
HOME =
|
|
22128
|
+
HOME = homedir4();
|
|
18881
22129
|
}
|
|
18882
22130
|
});
|
|
18883
22131
|
|
|
@@ -18887,6 +22135,8 @@ __export(daemon_exports, {
|
|
|
18887
22135
|
runDaemon: () => runDaemon
|
|
18888
22136
|
});
|
|
18889
22137
|
import { hostname as hostname3 } from "node:os";
|
|
22138
|
+
import { join as join8 } from "node:path";
|
|
22139
|
+
import { mkdirSync as mkdirSync2, writeFileSync, unlinkSync as unlinkSync2 } from "node:fs";
|
|
18890
22140
|
async function runDaemon() {
|
|
18891
22141
|
const creds = await readCreds();
|
|
18892
22142
|
if (!creds) {
|
|
@@ -18895,25 +22145,108 @@ async function runDaemon() {
|
|
|
18895
22145
|
);
|
|
18896
22146
|
process.exit(2);
|
|
18897
22147
|
}
|
|
18898
|
-
|
|
22148
|
+
const profile = currentProfile();
|
|
22149
|
+
const profileTag = profile ? ` [profile=${profile}]` : "";
|
|
22150
|
+
printBanner(`daemon \u2014 runtime ${creds.runtimeId.slice(0, 8)}\u2026 \u2192 ${creds.serverUrl}${profileTag}`, PKG_VERSION);
|
|
22151
|
+
const cachePath = join8(paths().configDir, "registry-cache.json");
|
|
22152
|
+
await loadRegistry({ cachePath });
|
|
18899
22153
|
const wsBase = creds.serverUrl.replace(/^http(s?):\/\//, "ws$1://").replace(/\/$/, "");
|
|
18900
22154
|
const wsUrl = `${wsBase}/agents/runtime/_attach`;
|
|
18901
22155
|
let backoffMs = RECONNECT_BACKOFF_MIN_MS;
|
|
22156
|
+
const DRAIN_DEADLINE_MS = 1e4;
|
|
22157
|
+
let draining = false;
|
|
18902
22158
|
let stopping = false;
|
|
18903
|
-
const stop = (sig) => {
|
|
22159
|
+
const stop = (sig, force = false) => {
|
|
18904
22160
|
if (stopping) return;
|
|
18905
|
-
|
|
18906
|
-
|
|
18907
|
-
|
|
18908
|
-
if (currentWs) {
|
|
22161
|
+
if (draining && !force) {
|
|
22162
|
+
log.warn(`${sig} again \u2014 abandoning drain, exiting now`);
|
|
22163
|
+
stopping = true;
|
|
18909
22164
|
try {
|
|
18910
|
-
|
|
22165
|
+
unlinkSync2(join8(paths().configDir, "daemon.pid"));
|
|
18911
22166
|
} catch {
|
|
18912
22167
|
}
|
|
22168
|
+
void sessions.disposeAll();
|
|
22169
|
+
if (currentWs) {
|
|
22170
|
+
try {
|
|
22171
|
+
currentWs.close(1e3, "shutdown");
|
|
22172
|
+
} catch {
|
|
22173
|
+
}
|
|
22174
|
+
}
|
|
22175
|
+
return;
|
|
22176
|
+
}
|
|
22177
|
+
draining = true;
|
|
22178
|
+
log.step(`${sig} received, draining (${DRAIN_DEADLINE_MS / 1e3}s deadline; sessions recover via session/load on reconnect)`);
|
|
22179
|
+
try {
|
|
22180
|
+
unlinkSync2(join8(paths().configDir, "daemon.pid"));
|
|
22181
|
+
} catch {
|
|
18913
22182
|
}
|
|
22183
|
+
void (async () => {
|
|
22184
|
+
const r = await sessions.drain(DRAIN_DEADLINE_MS, {
|
|
22185
|
+
onProgress: (active, msLeft) => {
|
|
22186
|
+
log.hint(`${active} turns active, ${Math.ceil(msLeft / 1e3)}s left`);
|
|
22187
|
+
}
|
|
22188
|
+
}).catch((e) => {
|
|
22189
|
+
log.err(`drain failed: ${e.message}`);
|
|
22190
|
+
return { initialTurns: 0, abortedTurns: 0, sessions: 0 };
|
|
22191
|
+
});
|
|
22192
|
+
const naturallyCompleted = r.initialTurns - r.abortedTurns;
|
|
22193
|
+
if (r.abortedTurns > 0) {
|
|
22194
|
+
log.warn(
|
|
22195
|
+
`deadline reached \u2014 aborted ${r.abortedTurns} in-flight turn(s); they'll resume via ACP session/load when the server reconnects`
|
|
22196
|
+
);
|
|
22197
|
+
}
|
|
22198
|
+
log.ok(
|
|
22199
|
+
`drained ${r.sessions} session(s) (${naturallyCompleted}/${r.initialTurns} turns completed cleanly)`
|
|
22200
|
+
);
|
|
22201
|
+
stopping = true;
|
|
22202
|
+
if (currentWs) {
|
|
22203
|
+
try {
|
|
22204
|
+
currentWs.close(1e3, "shutdown");
|
|
22205
|
+
} catch {
|
|
22206
|
+
}
|
|
22207
|
+
}
|
|
22208
|
+
})();
|
|
18914
22209
|
};
|
|
18915
22210
|
process.on("SIGTERM", () => stop("SIGTERM"));
|
|
18916
22211
|
process.on("SIGINT", () => stop("SIGINT"));
|
|
22212
|
+
try {
|
|
22213
|
+
mkdirSync2(paths().configDir, { recursive: true });
|
|
22214
|
+
writeFileSync(join8(paths().configDir, "daemon.pid"), String(process.pid), "utf-8");
|
|
22215
|
+
} catch (e) {
|
|
22216
|
+
process.stderr.write(`! pid file write failed (non-fatal): ${e.message}
|
|
22217
|
+
`);
|
|
22218
|
+
}
|
|
22219
|
+
process.on("SIGHUP", () => {
|
|
22220
|
+
void (async () => {
|
|
22221
|
+
log.step("SIGHUP \u2014 refreshing agent detection");
|
|
22222
|
+
try {
|
|
22223
|
+
await loadRegistry({ cachePath, forceRefresh: true });
|
|
22224
|
+
const agents = (await detectAll()).map((a) => ({ id: a.id, binary: a.spec.command }));
|
|
22225
|
+
const localSkillsDetailed = await detectLocalSkills();
|
|
22226
|
+
const localSkills = {};
|
|
22227
|
+
for (const [agentId, skills] of Object.entries(localSkillsDetailed)) {
|
|
22228
|
+
if (!skills) continue;
|
|
22229
|
+
localSkills[agentId] = skills.map(({ path: _path, ...rest }) => rest);
|
|
22230
|
+
}
|
|
22231
|
+
if (currentWs && currentWs.readyState === wrapper_default.OPEN) {
|
|
22232
|
+
currentWs.send(JSON.stringify({
|
|
22233
|
+
type: "hello",
|
|
22234
|
+
machine_id: creds.machineId,
|
|
22235
|
+
hostname: hostname3(),
|
|
22236
|
+
os: osTag(),
|
|
22237
|
+
version: PKG_VERSION,
|
|
22238
|
+
agents,
|
|
22239
|
+
local_skills: localSkills
|
|
22240
|
+
}));
|
|
22241
|
+
log.ok(`re-published manifest (${agents.length} agents)`);
|
|
22242
|
+
} else {
|
|
22243
|
+
log.warn("WS not attached \u2014 manifest will be re-sent on next connect");
|
|
22244
|
+
}
|
|
22245
|
+
} catch (e) {
|
|
22246
|
+
log.warn(`refresh failed: ${e.message}`);
|
|
22247
|
+
}
|
|
22248
|
+
})();
|
|
22249
|
+
});
|
|
18917
22250
|
let currentWs = null;
|
|
18918
22251
|
const sessions = new SessionManager(() => {
|
|
18919
22252
|
});
|
|
@@ -19060,7 +22393,9 @@ __export(status_exports, {
|
|
|
19060
22393
|
runStatus: () => runStatus
|
|
19061
22394
|
});
|
|
19062
22395
|
async function runStatus() {
|
|
19063
|
-
|
|
22396
|
+
const profile = currentProfile();
|
|
22397
|
+
const profileTag = profile ? ` [profile=${profile}]` : "";
|
|
22398
|
+
printBanner(`status${profileTag}`, PKG_VERSION);
|
|
19064
22399
|
const p = paths();
|
|
19065
22400
|
const creds = await readCreds();
|
|
19066
22401
|
if (!creds) {
|
|
@@ -19068,6 +22403,7 @@ async function runStatus() {
|
|
|
19068
22403
|
log.hint(`looked for ${p.credsFile}`);
|
|
19069
22404
|
process.exit(1);
|
|
19070
22405
|
}
|
|
22406
|
+
const kind = detectServiceKind();
|
|
19071
22407
|
const row = (k, v) => process.stderr.write(` ${c.dim(k.padEnd(11))} ${v}
|
|
19072
22408
|
`);
|
|
19073
22409
|
row("server", creds.serverUrl);
|
|
@@ -19076,7 +22412,7 @@ async function runStatus() {
|
|
|
19076
22412
|
row("registered", new Date(creds.createdAt * 1e3).toISOString());
|
|
19077
22413
|
row("creds file", c.dim(p.credsFile));
|
|
19078
22414
|
row("log file", c.dim(p.logFile));
|
|
19079
|
-
|
|
22415
|
+
row("service", c.dim(`${kind}${p.serviceFile ? ` \u2192 ${p.serviceFile}` : ""}`));
|
|
19080
22416
|
process.stderr.write("\n");
|
|
19081
22417
|
log.step("probing server");
|
|
19082
22418
|
const probe = await probeRuntimeToken(creds.serverUrl, creds.token);
|
|
@@ -19101,6 +22437,7 @@ var init_status = __esm({
|
|
|
19101
22437
|
"use strict";
|
|
19102
22438
|
init_config();
|
|
19103
22439
|
init_platform();
|
|
22440
|
+
init_service_manager();
|
|
19104
22441
|
init_style();
|
|
19105
22442
|
init_version();
|
|
19106
22443
|
init_probe();
|
|
@@ -19114,15 +22451,15 @@ __export(uninstall_exports, {
|
|
|
19114
22451
|
});
|
|
19115
22452
|
async function runUninstall() {
|
|
19116
22453
|
printBanner("uninstall \u2014 remove daemon + local credentials", PKG_VERSION);
|
|
19117
|
-
|
|
19118
|
-
|
|
19119
|
-
|
|
19120
|
-
|
|
19121
|
-
|
|
22454
|
+
try {
|
|
22455
|
+
const r = await uninstall4();
|
|
22456
|
+
const tag = r.kind === "launchd" ? "launchd plist" : r.kind === "systemd" ? "systemd unit" : r.kind === "windows-task" ? "Task Scheduler task" : "service";
|
|
22457
|
+
if (r.removed) log.ok(`${tag} removed ${c.dim(paths().serviceFile ?? paths().configDir)}`);
|
|
22458
|
+
else process.stderr.write(`${sym.dot()} ${c.dim(`${tag} not present`)}
|
|
19122
22459
|
`);
|
|
19123
|
-
|
|
19124
|
-
|
|
19125
|
-
}
|
|
22460
|
+
if (r.warning) log.hint(c.dim(r.warning));
|
|
22461
|
+
} catch (e) {
|
|
22462
|
+
log.warn(`service uninstall failed: ${e instanceof Error ? e.message : String(e)}`);
|
|
19126
22463
|
}
|
|
19127
22464
|
const creds = await readCreds();
|
|
19128
22465
|
if (creds) {
|
|
@@ -19157,7 +22494,7 @@ ${c.bold("Done.")}
|
|
|
19157
22494
|
var init_uninstall = __esm({
|
|
19158
22495
|
"src/bridge/commands/uninstall.ts"() {
|
|
19159
22496
|
"use strict";
|
|
19160
|
-
|
|
22497
|
+
init_service_manager();
|
|
19161
22498
|
init_config();
|
|
19162
22499
|
init_platform();
|
|
19163
22500
|
init_style();
|
|
@@ -19165,17 +22502,87 @@ var init_uninstall = __esm({
|
|
|
19165
22502
|
}
|
|
19166
22503
|
});
|
|
19167
22504
|
|
|
22505
|
+
// src/bridge/commands/agents.ts
|
|
22506
|
+
var agents_exports = {};
|
|
22507
|
+
__export(agents_exports, {
|
|
22508
|
+
runAgents: () => runAgents
|
|
22509
|
+
});
|
|
22510
|
+
import { readFileSync, statSync } from "node:fs";
|
|
22511
|
+
import { join as join9 } from "node:path";
|
|
22512
|
+
async function runAgents(args) {
|
|
22513
|
+
const sub = args[0] ?? "";
|
|
22514
|
+
switch (sub) {
|
|
22515
|
+
case "refresh":
|
|
22516
|
+
await refresh(args.slice(1));
|
|
22517
|
+
return;
|
|
22518
|
+
default:
|
|
22519
|
+
process.stderr.write(
|
|
22520
|
+
"oma bridge agents \u2014 manage local agent detection\n\n oma bridge agents refresh [--yes] re-scan + offer-install missing ACP wrappers + signal daemon\n"
|
|
22521
|
+
);
|
|
22522
|
+
process.exit(sub ? 1 : 0);
|
|
22523
|
+
}
|
|
22524
|
+
}
|
|
22525
|
+
async function refresh(args) {
|
|
22526
|
+
const profile = currentProfile();
|
|
22527
|
+
const profileTag = profile ? ` [profile=${profile}]` : "";
|
|
22528
|
+
const yes = args.includes("--yes") || args.includes("-y");
|
|
22529
|
+
const cachePath = join9(paths().configDir, "registry-cache.json");
|
|
22530
|
+
await loadRegistry({ cachePath, forceRefresh: true });
|
|
22531
|
+
const detected = (await detectAll()).map((a) => ({ id: a.id, binary: a.spec.command }));
|
|
22532
|
+
await auditAndOfferWrappers(detected, { yes });
|
|
22533
|
+
const pidFile = join9(paths().configDir, "daemon.pid");
|
|
22534
|
+
let pid = 0;
|
|
22535
|
+
try {
|
|
22536
|
+
pid = parseInt(readFileSync(pidFile, "utf-8").trim(), 10);
|
|
22537
|
+
if (!Number.isFinite(pid) || pid <= 0) pid = 0;
|
|
22538
|
+
if (pid) process.kill(pid, 0);
|
|
22539
|
+
} catch {
|
|
22540
|
+
pid = 0;
|
|
22541
|
+
}
|
|
22542
|
+
if (pid === 0) {
|
|
22543
|
+
log.hint(`no running daemon${profileTag}; manifest will reflect on next \`oma bridge daemon\``);
|
|
22544
|
+
return;
|
|
22545
|
+
}
|
|
22546
|
+
try {
|
|
22547
|
+
const ageMs = Date.now() - statSync(pidFile).mtimeMs;
|
|
22548
|
+
if (ageMs > 7 * 24 * 3600 * 1e3) {
|
|
22549
|
+
log.hint(`pid file is ${Math.floor(ageMs / 864e5)} days old`);
|
|
22550
|
+
}
|
|
22551
|
+
} catch {
|
|
22552
|
+
}
|
|
22553
|
+
try {
|
|
22554
|
+
process.kill(pid, "SIGHUP");
|
|
22555
|
+
log.ok(`daemon${profileTag} re-detecting (pid ${pid})`);
|
|
22556
|
+
log.hint("Console dropdown will reflect the new state in 1\u20132s");
|
|
22557
|
+
} catch (e) {
|
|
22558
|
+
log.warn(`signal failed: ${e.message}`);
|
|
22559
|
+
process.exit(2);
|
|
22560
|
+
}
|
|
22561
|
+
}
|
|
22562
|
+
var init_agents = __esm({
|
|
22563
|
+
"src/bridge/commands/agents.ts"() {
|
|
22564
|
+
"use strict";
|
|
22565
|
+
init_platform();
|
|
22566
|
+
init_registry();
|
|
22567
|
+
init_wrapper_audit();
|
|
22568
|
+
init_style();
|
|
22569
|
+
}
|
|
22570
|
+
});
|
|
22571
|
+
|
|
19168
22572
|
// src/index.ts
|
|
22573
|
+
init_platform();
|
|
19169
22574
|
import { createServer as createServer2 } from "node:http";
|
|
19170
22575
|
import { execSync } from "node:child_process";
|
|
19171
|
-
import { homedir as
|
|
19172
|
-
import { join as
|
|
19173
|
-
import { mkdirSync, readFileSync, writeFileSync, unlinkSync, existsSync, chmodSync } from "node:fs";
|
|
19174
|
-
import { randomBytes as
|
|
22576
|
+
import { homedir as homedir5, hostname as hostname4 } from "node:os";
|
|
22577
|
+
import { join as join10, dirname as dirname9 } from "node:path";
|
|
22578
|
+
import { mkdirSync as mkdirSync3, readFileSync as readFileSync2, writeFileSync as writeFileSync2, unlinkSync as unlinkSync3, existsSync as existsSync2, chmodSync as chmodSync2 } from "node:fs";
|
|
22579
|
+
import { randomBytes as randomBytes3 } from "node:crypto";
|
|
19175
22580
|
function credentialsPath() {
|
|
19176
22581
|
const xdg = process.env.XDG_CONFIG_HOME;
|
|
19177
|
-
const base = xdg && xdg.length > 0 ? xdg :
|
|
19178
|
-
|
|
22582
|
+
const base = xdg && xdg.length > 0 ? xdg : join10(homedir5(), ".config");
|
|
22583
|
+
const profile = currentProfile();
|
|
22584
|
+
const file2 = profile ? `credentials.${profile}.json` : "credentials.json";
|
|
22585
|
+
return join10(base, "oma", file2);
|
|
19179
22586
|
}
|
|
19180
22587
|
function migrateV1ToV2(v1) {
|
|
19181
22588
|
return {
|
|
@@ -19195,10 +22602,10 @@ function migrateV1ToV2(v1) {
|
|
|
19195
22602
|
};
|
|
19196
22603
|
}
|
|
19197
22604
|
function readCredentials() {
|
|
19198
|
-
const
|
|
22605
|
+
const path2 = credentialsPath();
|
|
19199
22606
|
try {
|
|
19200
|
-
if (!
|
|
19201
|
-
const raw =
|
|
22607
|
+
if (!existsSync2(path2)) return null;
|
|
22608
|
+
const raw = readFileSync2(path2, "utf8");
|
|
19202
22609
|
const parsed = JSON.parse(raw);
|
|
19203
22610
|
if (parsed.version === 2) return parsed;
|
|
19204
22611
|
if (parsed.version === 1) {
|
|
@@ -19215,18 +22622,18 @@ function readCredentials() {
|
|
|
19215
22622
|
}
|
|
19216
22623
|
}
|
|
19217
22624
|
function writeCredentials(creds) {
|
|
19218
|
-
const
|
|
19219
|
-
|
|
19220
|
-
|
|
22625
|
+
const path2 = credentialsPath();
|
|
22626
|
+
mkdirSync3(dirname9(path2), { recursive: true, mode: 448 });
|
|
22627
|
+
writeFileSync2(path2, JSON.stringify(creds, null, 2), { mode: 384 });
|
|
19221
22628
|
try {
|
|
19222
|
-
|
|
22629
|
+
chmodSync2(path2, 384);
|
|
19223
22630
|
} catch {
|
|
19224
22631
|
}
|
|
19225
22632
|
}
|
|
19226
22633
|
function clearCredentials() {
|
|
19227
|
-
const
|
|
19228
|
-
if (!
|
|
19229
|
-
|
|
22634
|
+
const path2 = credentialsPath();
|
|
22635
|
+
if (!existsSync2(path2)) return false;
|
|
22636
|
+
unlinkSync3(path2);
|
|
19230
22637
|
return true;
|
|
19231
22638
|
}
|
|
19232
22639
|
function loadConfig() {
|
|
@@ -19291,8 +22698,8 @@ async function fetchWithRetry(url2, init, maxRetries = 3) {
|
|
|
19291
22698
|
attempt += 1;
|
|
19292
22699
|
}
|
|
19293
22700
|
}
|
|
19294
|
-
async function apiFetch(config2,
|
|
19295
|
-
const url2 = `${config2.baseUrl}${
|
|
22701
|
+
async function apiFetch(config2, path2, init) {
|
|
22702
|
+
const url2 = `${config2.baseUrl}${path2}`;
|
|
19296
22703
|
const res = await fetchWithRetry(url2, {
|
|
19297
22704
|
...init,
|
|
19298
22705
|
headers: {
|
|
@@ -19312,8 +22719,8 @@ async function apiFetch(config2, path, init) {
|
|
|
19312
22719
|
}
|
|
19313
22720
|
return res.json();
|
|
19314
22721
|
}
|
|
19315
|
-
async function rawStream(config2,
|
|
19316
|
-
const res = await fetchWithRetry(`${config2.baseUrl}${
|
|
22722
|
+
async function rawStream(config2, path2, init) {
|
|
22723
|
+
const res = await fetchWithRetry(`${config2.baseUrl}${path2}`, {
|
|
19317
22724
|
...init,
|
|
19318
22725
|
headers: {
|
|
19319
22726
|
"x-api-key": config2.apiKey,
|
|
@@ -19456,7 +22863,7 @@ function table(rows) {
|
|
|
19456
22863
|
if (!rows.length) return;
|
|
19457
22864
|
const widths = rows[0].map((_, i) => Math.max(...rows.map((r) => (r[i] || "").length)));
|
|
19458
22865
|
for (const row of rows) {
|
|
19459
|
-
console.log(row.map((
|
|
22866
|
+
console.log(row.map((c3, i) => (c3 || "").padEnd(widths[i])).join(" "));
|
|
19460
22867
|
}
|
|
19461
22868
|
}
|
|
19462
22869
|
function capsPreview(caps) {
|
|
@@ -19476,7 +22883,7 @@ function isPubliclyReachable(url2) {
|
|
|
19476
22883
|
}
|
|
19477
22884
|
}
|
|
19478
22885
|
async function authLogin(baseUrl, requestedTenant) {
|
|
19479
|
-
const state =
|
|
22886
|
+
const state = randomBytes3(16).toString("hex");
|
|
19480
22887
|
const port = 19500 + Math.floor(Math.random() * 500);
|
|
19481
22888
|
const callback = `http://127.0.0.1:${port}/callback`;
|
|
19482
22889
|
const params = new URLSearchParams({
|
|
@@ -20000,7 +23407,7 @@ Version: v${a.version}`);
|
|
|
20000
23407
|
console.log("No model cards. Create one with: oma models create");
|
|
20001
23408
|
return;
|
|
20002
23409
|
}
|
|
20003
|
-
table([["NAME", "PROVIDER", "MODEL", "KEY", "DEFAULT"], ...data.map((
|
|
23410
|
+
table([["NAME", "PROVIDER", "MODEL", "KEY", "DEFAULT"], ...data.map((c3) => [c3.name, c3.provider, c3.model_id, `****${c3.api_key_preview || ""}`, c3.is_default ? "yes" : ""])]);
|
|
20004
23411
|
}
|
|
20005
23412
|
},
|
|
20006
23413
|
{
|
|
@@ -20107,7 +23514,7 @@ Save this key \u2014 it won't be shown again.`);
|
|
|
20107
23514
|
console.log("No credentials in this vault.");
|
|
20108
23515
|
return;
|
|
20109
23516
|
}
|
|
20110
|
-
table([["NAME", "TYPE", "DETAIL"], ...data.map((
|
|
23517
|
+
table([["NAME", "TYPE", "DETAIL"], ...data.map((c3) => [c3.display_name, c3.auth.type, c3.auth.mcp_server_url || c3.auth.command_prefixes?.join(", ") || ""])]);
|
|
20111
23518
|
}
|
|
20112
23519
|
},
|
|
20113
23520
|
{
|
|
@@ -21257,14 +24664,14 @@ Expires in ${r.expiresInDays} days.`);
|
|
|
21257
24664
|
http: "POST /v1/memory_stores/:id/memories {path, content, precondition?}",
|
|
21258
24665
|
async run(config2, args) {
|
|
21259
24666
|
const storeId = args[0];
|
|
21260
|
-
const
|
|
24667
|
+
const path2 = args[1];
|
|
21261
24668
|
const content = readContentArg(args);
|
|
21262
24669
|
const sha = flag(args, "--precondition-sha256");
|
|
21263
|
-
if (!storeId || !
|
|
24670
|
+
if (!storeId || !path2 || content === void 0) {
|
|
21264
24671
|
console.error("Usage: oma memory write <store-id> <path> (--content <c> | --from-file <f>) [--precondition-sha256 <h>]");
|
|
21265
24672
|
process.exit(1);
|
|
21266
24673
|
}
|
|
21267
|
-
const body = { path, content };
|
|
24674
|
+
const body = { path: path2, content };
|
|
21268
24675
|
if (sha) body.precondition = { type: "content_sha256", content_sha256: sha };
|
|
21269
24676
|
const mem = await apiFetch(
|
|
21270
24677
|
config2,
|
|
@@ -21345,19 +24752,19 @@ Expires in ${r.expiresInDays} days.`);
|
|
|
21345
24752
|
async run(config2, args) {
|
|
21346
24753
|
const storeId = args[0];
|
|
21347
24754
|
const memId = args[1];
|
|
21348
|
-
const
|
|
24755
|
+
const path2 = flag(args, "--path");
|
|
21349
24756
|
const content = readContentArg(args);
|
|
21350
24757
|
const sha = flag(args, "--precondition-sha256");
|
|
21351
24758
|
if (!storeId || !memId) {
|
|
21352
24759
|
console.error("Usage: oma memory update <store-id> <memory-id> [--path <p>] [--content <c> | --from-file <f>] [--precondition-sha256 <h>]");
|
|
21353
24760
|
process.exit(1);
|
|
21354
24761
|
}
|
|
21355
|
-
if (
|
|
24762
|
+
if (path2 === void 0 && content === void 0) {
|
|
21356
24763
|
console.error("Pass at least --path or --content/--from-file.");
|
|
21357
24764
|
process.exit(1);
|
|
21358
24765
|
}
|
|
21359
24766
|
const body = {};
|
|
21360
|
-
if (
|
|
24767
|
+
if (path2 !== void 0) body.path = path2;
|
|
21361
24768
|
if (content !== void 0) body.content = content;
|
|
21362
24769
|
if (sha) body.precondition = { type: "content_sha256", content_sha256: sha };
|
|
21363
24770
|
const mem = await apiFetch(
|
|
@@ -21571,10 +24978,10 @@ async function connectMcp(config2, mcpServerUrl, vaultId) {
|
|
|
21571
24978
|
}
|
|
21572
24979
|
function apiRef(resource) {
|
|
21573
24980
|
const groups = /* @__PURE__ */ new Map();
|
|
21574
|
-
for (const
|
|
21575
|
-
const list = groups.get(
|
|
21576
|
-
list.push(` ${
|
|
21577
|
-
groups.set(
|
|
24981
|
+
for (const c3 of commands) {
|
|
24982
|
+
const list = groups.get(c3.group) || [];
|
|
24983
|
+
list.push(` ${c3.http}`);
|
|
24984
|
+
groups.set(c3.group, list);
|
|
21578
24985
|
}
|
|
21579
24986
|
for (const e of extraEndpoints) {
|
|
21580
24987
|
const list = groups.get(e.group) || [];
|
|
@@ -21631,20 +25038,21 @@ oma \u2014 Open Managed Agents CLI
|
|
|
21631
25038
|
|
|
21632
25039
|
Usage:`);
|
|
21633
25040
|
let lastGroup = "";
|
|
21634
|
-
for (const
|
|
21635
|
-
if (
|
|
25041
|
+
for (const c3 of commands) {
|
|
25042
|
+
if (c3.group !== lastGroup) {
|
|
21636
25043
|
console.log(`
|
|
21637
|
-
${
|
|
21638
|
-
lastGroup =
|
|
25044
|
+
${c3.group}:`);
|
|
25045
|
+
lastGroup = c3.group;
|
|
21639
25046
|
}
|
|
21640
|
-
console.log(` ${
|
|
25047
|
+
console.log(` ${c3.usage.padEnd(42)} ${c3.desc}`);
|
|
21641
25048
|
}
|
|
21642
25049
|
console.log(`
|
|
21643
25050
|
Bridge (local runtime):
|
|
21644
|
-
oma bridge setup [--force] [--no-service] Pair this machine with OMA
|
|
21645
|
-
oma bridge daemon Run the bridge in foreground
|
|
25051
|
+
oma bridge setup [--force] [--no-service] Pair this machine with OMA + start daemon
|
|
21646
25052
|
oma bridge status Show creds + probe server reachability
|
|
21647
|
-
oma bridge
|
|
25053
|
+
oma bridge agents refresh Re-detect agents + offer wrapper installs
|
|
25054
|
+
oma bridge uninstall Stop service + remove creds
|
|
25055
|
+
(oma bridge daemon Internal: launched by service mgr / debugging)
|
|
21648
25056
|
|
|
21649
25057
|
API Reference:
|
|
21650
25058
|
oma api Show all HTTP endpoints
|
|
@@ -21669,17 +25077,42 @@ async function main() {
|
|
|
21669
25077
|
apiRef(args[1]);
|
|
21670
25078
|
return;
|
|
21671
25079
|
}
|
|
25080
|
+
for (let i = 0; i < args.length; i++) {
|
|
25081
|
+
if (args[i] === "--profile" && i + 1 < args.length) {
|
|
25082
|
+
process.env.OMA_PROFILE = args[i + 1];
|
|
25083
|
+
args.splice(i, 2);
|
|
25084
|
+
const argvIdx = process.argv.indexOf("--profile");
|
|
25085
|
+
if (argvIdx !== -1) process.argv.splice(argvIdx, 2);
|
|
25086
|
+
break;
|
|
25087
|
+
}
|
|
25088
|
+
const eq = args[i].match(/^--profile=(.+)$/);
|
|
25089
|
+
if (eq) {
|
|
25090
|
+
process.env.OMA_PROFILE = eq[1];
|
|
25091
|
+
args.splice(i, 1);
|
|
25092
|
+
const argvIdx = process.argv.findIndex((a) => a.startsWith("--profile="));
|
|
25093
|
+
if (argvIdx !== -1) process.argv.splice(argvIdx, 1);
|
|
25094
|
+
break;
|
|
25095
|
+
}
|
|
25096
|
+
}
|
|
25097
|
+
try {
|
|
25098
|
+
currentProfile();
|
|
25099
|
+
} catch (e) {
|
|
25100
|
+
console.error(`Error: ${e.message}`);
|
|
25101
|
+
process.exit(2);
|
|
25102
|
+
}
|
|
21672
25103
|
if (args[0] === "bridge") {
|
|
21673
25104
|
const sub = args[1] ?? "";
|
|
21674
25105
|
process.argv.splice(2, 2);
|
|
21675
25106
|
switch (sub) {
|
|
21676
25107
|
case "setup": {
|
|
25108
|
+
const serverUrl = flag(args, "--server-url") ?? "https://openma.dev";
|
|
21677
25109
|
const { runSetup: runSetup2 } = await Promise.resolve().then(() => (init_setup(), setup_exports));
|
|
21678
25110
|
await runSetup2({
|
|
21679
|
-
serverUrl
|
|
21680
|
-
browserOrigin: flag(args, "--browser-origin") ??
|
|
25111
|
+
serverUrl,
|
|
25112
|
+
browserOrigin: flag(args, "--browser-origin") ?? serverUrl,
|
|
21681
25113
|
noService: args.includes("--no-service"),
|
|
21682
|
-
force: args.includes("--force")
|
|
25114
|
+
force: args.includes("--force"),
|
|
25115
|
+
yes: args.includes("--yes") || args.includes("-y")
|
|
21683
25116
|
});
|
|
21684
25117
|
return;
|
|
21685
25118
|
}
|
|
@@ -21698,9 +25131,14 @@ async function main() {
|
|
|
21698
25131
|
await runUninstall2();
|
|
21699
25132
|
return;
|
|
21700
25133
|
}
|
|
25134
|
+
case "agents": {
|
|
25135
|
+
const { runAgents: runAgents2 } = await Promise.resolve().then(() => (init_agents(), agents_exports));
|
|
25136
|
+
await runAgents2(args.slice(2));
|
|
25137
|
+
return;
|
|
25138
|
+
}
|
|
21701
25139
|
default:
|
|
21702
25140
|
console.error(
|
|
21703
|
-
"oma bridge \u2014 pair a local ACP agent with OMA\n\n oma bridge setup [--server-url=\u2026] [--no-service] [--force]\n oma bridge
|
|
25141
|
+
"oma bridge \u2014 pair a local ACP agent with OMA\n\n oma bridge setup [--server-url=\u2026] [--no-service] [--force] [--yes]\n Pair + install service + start daemon\n oma bridge status Creds + service kind + probe server\n oma bridge agents refresh [--yes] Re-scan + offer-install wrappers + reload\n oma bridge uninstall Stop service + remove creds\n oma bridge daemon (internal \u2014 launched by service mgr / for debug)\n\n Use --profile <name> (or OMA_PROFILE=<name>) to run multiple\n daemons side-by-side (e.g. prod in launchd + staging foreground).\n"
|
|
21704
25142
|
);
|
|
21705
25143
|
process.exit(sub ? 1 : 0);
|
|
21706
25144
|
}
|
|
@@ -21711,15 +25149,15 @@ async function main() {
|
|
|
21711
25149
|
const config2 = isPreAuth ? loadConfigOptional() : loadConfig();
|
|
21712
25150
|
config2.json = wantJson;
|
|
21713
25151
|
let needsArgMatch = null;
|
|
21714
|
-
for (const
|
|
21715
|
-
const verbMatch =
|
|
25152
|
+
for (const c3 of commands) {
|
|
25153
|
+
const verbMatch = c3.match.every((tok, i) => args[i] === tok);
|
|
21716
25154
|
if (!verbMatch) continue;
|
|
21717
|
-
if (
|
|
21718
|
-
needsArgMatch =
|
|
25155
|
+
if (c3.needsArg && !args[c3.match.length]) {
|
|
25156
|
+
needsArgMatch = c3;
|
|
21719
25157
|
continue;
|
|
21720
25158
|
}
|
|
21721
|
-
const rest = args.slice(
|
|
21722
|
-
return
|
|
25159
|
+
const rest = args.slice(c3.match.length);
|
|
25160
|
+
return c3.run(config2, rest);
|
|
21723
25161
|
}
|
|
21724
25162
|
if (needsArgMatch) {
|
|
21725
25163
|
console.error(`${needsArgMatch.usage}
|