@openma/cli 0.3.2 → 0.4.1
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 +3743 -278
- 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;
|
|
@@ -4048,30 +4670,2418 @@ async function probeRuntimeToken(serverUrl, token, timeoutMs = 8e3) {
|
|
|
4048
4670
|
ws.close(1e3, "probe");
|
|
4049
4671
|
} catch {
|
|
4050
4672
|
}
|
|
4051
|
-
settle({ ok: true });
|
|
4052
|
-
});
|
|
4053
|
-
ws.once("unexpected-response", (_req, res) => {
|
|
4054
|
-
clearTimeout(timer);
|
|
4055
|
-
const status = res.statusCode ?? 0;
|
|
4056
|
-
if (status === 401 || status === 403 || status === 404) {
|
|
4057
|
-
settle({ ok: false, reason: "invalid", detail: `HTTP ${status}` });
|
|
4673
|
+
settle({ ok: true });
|
|
4674
|
+
});
|
|
4675
|
+
ws.once("unexpected-response", (_req, res) => {
|
|
4676
|
+
clearTimeout(timer);
|
|
4677
|
+
const status = res.statusCode ?? 0;
|
|
4678
|
+
if (status === 401 || status === 403 || status === 404) {
|
|
4679
|
+
settle({ ok: false, reason: "invalid", detail: `HTTP ${status}` });
|
|
4680
|
+
} else {
|
|
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}`);
|
|
6984
|
+
}
|
|
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)"
|
|
7004
|
+
});
|
|
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}`)}`;
|
|
4058
7056
|
} else {
|
|
4059
|
-
|
|
7057
|
+
line = ` ${c.yellow("\u25CB")} ${r.id.padEnd(18)} ${c.dim(`wraps \`${r.status.wraps}\` \u2014 no ${pk} build` + (inst.downloadUrl ? `, see ${inst.downloadUrl}` : ""))}`;
|
|
4060
7058
|
}
|
|
4061
|
-
}
|
|
4062
|
-
|
|
4063
|
-
|
|
4064
|
-
|
|
4065
|
-
|
|
4066
|
-
|
|
4067
|
-
|
|
4068
|
-
|
|
4069
|
-
|
|
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,49 @@ __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
|
+
if (process.env.OMA_DEBUG_HANDLES) {
|
|
7107
|
+
let tick = 0;
|
|
7108
|
+
const probe = setInterval(() => {
|
|
7109
|
+
tick += 1;
|
|
7110
|
+
const handles = process._getActiveHandles();
|
|
7111
|
+
const requests = process._getActiveRequests();
|
|
7112
|
+
const hsum = handles.map((h) => h?.constructor?.name ?? "?").reduce((a, k) => {
|
|
7113
|
+
a[k] = (a[k] ?? 0) + 1;
|
|
7114
|
+
return a;
|
|
7115
|
+
}, {});
|
|
7116
|
+
const rsum = requests.map((r) => r?.constructor?.name ?? "?").reduce((a, k) => {
|
|
7117
|
+
a[k] = (a[k] ?? 0) + 1;
|
|
7118
|
+
return a;
|
|
7119
|
+
}, {});
|
|
7120
|
+
process.stderr.write(`
|
|
7121
|
+
[debug t=${tick * 2}s] handles: ${JSON.stringify(hsum)} requests: ${JSON.stringify(rsum)}
|
|
7122
|
+
`);
|
|
7123
|
+
}, 2e3);
|
|
7124
|
+
probe.unref();
|
|
7125
|
+
}
|
|
7126
|
+
try {
|
|
7127
|
+
await runSetupInner(opts);
|
|
7128
|
+
} finally {
|
|
7129
|
+
setImmediate(() => process.exit(0));
|
|
7130
|
+
}
|
|
7131
|
+
}
|
|
7132
|
+
async function runSetupInner(opts) {
|
|
7133
|
+
const profile = currentProfile();
|
|
7134
|
+
const profileTag = profile ? ` [profile=${profile}]` : "";
|
|
7135
|
+
printBanner(`setup \u2014 register this machine with ${opts.serverUrl}${profileTag}`, PKG_VERSION);
|
|
7136
|
+
await loadRegistry({ cachePath: join4(paths().configDir, "registry-cache.json") });
|
|
4096
7137
|
if (!opts.force) {
|
|
4097
7138
|
const existing = await readCreds();
|
|
4098
7139
|
if (existing) {
|
|
@@ -4109,30 +7150,19 @@ async function runSetup(opts) {
|
|
|
4109
7150
|
} else {
|
|
4110
7151
|
log.hint(`runtime ${existing.runtimeId.slice(0, 8)}\u2026 (use --force to re-register)`);
|
|
4111
7152
|
}
|
|
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
|
-
}
|
|
7153
|
+
const fastPathAgents = (await detectAll()).map((a) => ({ id: a.id, binary: a.spec.command }));
|
|
7154
|
+
await auditAndOfferWrappers(fastPathAgents, { yes: opts.yes });
|
|
4126
7155
|
process.stderr.write(`
|
|
4127
7156
|
${c.bold("Up to date.")}
|
|
4128
7157
|
|
|
4129
7158
|
`);
|
|
7159
|
+
await refreshServiceOrFallback(opts);
|
|
4130
7160
|
return;
|
|
4131
7161
|
}
|
|
4132
7162
|
}
|
|
4133
7163
|
}
|
|
4134
7164
|
log.step("waiting for browser to authorize");
|
|
4135
|
-
const state =
|
|
7165
|
+
const state = randomBytes2(16).toString("hex");
|
|
4136
7166
|
const code = await waitForCallback(state, opts.browserOrigin);
|
|
4137
7167
|
log.ok("received code from browser");
|
|
4138
7168
|
const machineId = await getOrCreateMachineId();
|
|
@@ -4154,38 +7184,105 @@ ${c.bold("Up to date.")}
|
|
|
4154
7184
|
createdAt: Math.floor(Date.now() / 1e3)
|
|
4155
7185
|
});
|
|
4156
7186
|
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
|
-
}
|
|
7187
|
+
let agents = (await detectAll()).map((a) => ({ id: a.id, binary: a.spec.command }));
|
|
7188
|
+
agents = await auditAndOfferWrappers(agents, { yes: opts.yes });
|
|
4169
7189
|
if (agents.length > 0) {
|
|
4170
7190
|
log.ok(`agents detected ${c.dim(agents.map((a) => a.id).join(", "))}`);
|
|
4171
7191
|
} else {
|
|
4172
7192
|
log.warn("no ACP agents on PATH yet");
|
|
4173
7193
|
log.hint("install one, e.g. `npm i -g @agentclientprotocol/claude-agent-acp`");
|
|
4174
7194
|
}
|
|
4175
|
-
|
|
7195
|
+
await installServiceOrFallback(opts);
|
|
7196
|
+
}
|
|
7197
|
+
async function installServiceOrFallback(opts) {
|
|
7198
|
+
const kind = detectServiceKind();
|
|
7199
|
+
if (opts.noService || kind === "unsupported") {
|
|
7200
|
+
process.stderr.write("\n");
|
|
7201
|
+
if (kind === "unsupported") {
|
|
7202
|
+
log.warn(`platform service install not supported on ${process.platform}; running daemon in foreground`);
|
|
7203
|
+
} else {
|
|
7204
|
+
log.step("--no-service: starting daemon in foreground");
|
|
7205
|
+
}
|
|
7206
|
+
log.hint("Ctrl-C to stop. To run as a system service, re-run setup without --no-service.");
|
|
7207
|
+
process.stderr.write("\n");
|
|
7208
|
+
execIntoDaemon();
|
|
7209
|
+
return;
|
|
7210
|
+
}
|
|
7211
|
+
await installAndReport(opts);
|
|
7212
|
+
}
|
|
7213
|
+
async function refreshServiceOrFallback(opts) {
|
|
7214
|
+
const kind = detectServiceKind();
|
|
7215
|
+
if (opts.noService || kind === "unsupported") {
|
|
4176
7216
|
process.stderr.write("\n");
|
|
4177
|
-
log.step("service install
|
|
4178
|
-
log.hint("
|
|
7217
|
+
log.step(opts.noService ? "--no-service: starting daemon in foreground" : `service install not supported on ${process.platform}; running daemon in foreground`);
|
|
7218
|
+
log.hint("Ctrl-C to stop. To run as a system service, re-run setup without --no-service.");
|
|
7219
|
+
process.stderr.write("\n");
|
|
7220
|
+
execIntoDaemon();
|
|
4179
7221
|
return;
|
|
4180
7222
|
}
|
|
4181
|
-
await
|
|
4182
|
-
|
|
4183
|
-
|
|
7223
|
+
const installedEntry = await readInstalledCliEntry4();
|
|
7224
|
+
const currentEntry = serviceInstallOpts().cliEntry;
|
|
7225
|
+
if (installedEntry && installedEntry !== currentEntry) {
|
|
7226
|
+
log.warn(`service was pointing at a different binary; updating`);
|
|
7227
|
+
log.hint(`old: ${c.dim(installedEntry)}`);
|
|
7228
|
+
log.hint(`new: ${c.dim(currentEntry)}`);
|
|
7229
|
+
}
|
|
7230
|
+
await installAndReport(opts);
|
|
7231
|
+
}
|
|
7232
|
+
async function installAndReport(opts) {
|
|
7233
|
+
void opts;
|
|
7234
|
+
const result = await install4(serviceInstallOpts());
|
|
7235
|
+
const where = result.installedAt ? c.dim(result.installedAt) : c.dim("(no install path)");
|
|
7236
|
+
switch (result.kind) {
|
|
7237
|
+
case "launchd":
|
|
7238
|
+
log.ok(`launchd plist installed ${where}`);
|
|
7239
|
+
log.ok(`daemon started ${c.dim("logs: " + paths().logFile)}`);
|
|
7240
|
+
break;
|
|
7241
|
+
case "systemd":
|
|
7242
|
+
log.ok(`systemd unit installed ${where}`);
|
|
7243
|
+
if (result.started) {
|
|
7244
|
+
log.ok(`daemon started ${c.dim("logs: " + paths().logFile)}`);
|
|
7245
|
+
} else {
|
|
7246
|
+
log.warn(`unit installed but failed to start: ${result.warning ?? "unknown"}`);
|
|
7247
|
+
log.hint(`try: systemctl --user status ${paths().serviceLabel}`);
|
|
7248
|
+
}
|
|
7249
|
+
if (!result.lingerEnabled) {
|
|
7250
|
+
log.hint(lingerHint2());
|
|
7251
|
+
}
|
|
7252
|
+
break;
|
|
7253
|
+
case "windows-task":
|
|
7254
|
+
log.ok(`Task Scheduler task registered ${where}`);
|
|
7255
|
+
if (result.started) {
|
|
7256
|
+
log.ok(`daemon started ${c.dim("logs: " + paths().logFile)}`);
|
|
7257
|
+
} else {
|
|
7258
|
+
log.warn(`task registered but failed to start now: ${result.warning ?? "unknown"}`);
|
|
7259
|
+
log.hint(`it will run at next logon. To start manually: schtasks /run /tn ${paths().serviceLabel}`);
|
|
7260
|
+
}
|
|
7261
|
+
break;
|
|
7262
|
+
case "unsupported":
|
|
7263
|
+
log.err(`platform unsupported`);
|
|
7264
|
+
return;
|
|
7265
|
+
}
|
|
4184
7266
|
process.stderr.write("\n");
|
|
4185
7267
|
process.stderr.write(`${c.bold("Done.")} the runtime should appear online at ${c.cyan(opts.browserOrigin)}
|
|
4186
7268
|
|
|
4187
7269
|
`);
|
|
4188
7270
|
}
|
|
7271
|
+
function execIntoDaemon() {
|
|
7272
|
+
const profile = currentProfile();
|
|
7273
|
+
const child = spawn7(process.execPath, [process.argv[1], "bridge", "daemon"], {
|
|
7274
|
+
stdio: "inherit",
|
|
7275
|
+
env: { ...process.env, ...profile ? { OMA_PROFILE: profile } : {} }
|
|
7276
|
+
});
|
|
7277
|
+
child.once("exit", (code, signal) => {
|
|
7278
|
+
if (signal) {
|
|
7279
|
+
process.kill(process.pid, signal);
|
|
7280
|
+
return;
|
|
7281
|
+
}
|
|
7282
|
+
process.exit(code ?? 0);
|
|
7283
|
+
});
|
|
7284
|
+
return new Promise(() => void 0);
|
|
7285
|
+
}
|
|
4189
7286
|
function waitForCallback(state, browserOrigin) {
|
|
4190
7287
|
return new Promise((resolve, reject) => {
|
|
4191
7288
|
const timeoutMs = 5 * 60 * 1e3;
|
|
@@ -4269,37 +7366,23 @@ function openBrowser(url2) {
|
|
|
4269
7366
|
return new Promise((resolve, reject) => {
|
|
4270
7367
|
const cmd = process.platform === "darwin" ? "open" : process.platform === "win32" ? "start" : "xdg-open";
|
|
4271
7368
|
const args = process.platform === "win32" ? ["", url2] : [url2];
|
|
4272
|
-
const p =
|
|
7369
|
+
const p = spawn7(cmd, args, { stdio: "ignore", detached: true, shell: process.platform === "win32" });
|
|
4273
7370
|
p.once("error", reject);
|
|
4274
7371
|
p.unref();
|
|
4275
7372
|
setTimeout(() => resolve(), 100);
|
|
4276
7373
|
});
|
|
4277
7374
|
}
|
|
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
7375
|
var init_setup = __esm({
|
|
4294
7376
|
"src/bridge/commands/setup.ts"() {
|
|
4295
7377
|
"use strict";
|
|
4296
7378
|
init_config();
|
|
4297
7379
|
init_platform();
|
|
4298
|
-
|
|
7380
|
+
init_service_manager();
|
|
4299
7381
|
init_registry();
|
|
4300
7382
|
init_style();
|
|
4301
7383
|
init_version();
|
|
4302
7384
|
init_probe();
|
|
7385
|
+
init_wrapper_audit();
|
|
4303
7386
|
}
|
|
4304
7387
|
});
|
|
4305
7388
|
|
|
@@ -4400,7 +7483,7 @@ __export(util_exports, {
|
|
|
4400
7483
|
getParsedType: () => getParsedType,
|
|
4401
7484
|
getSizableOrigin: () => getSizableOrigin,
|
|
4402
7485
|
isObject: () => isObject,
|
|
4403
|
-
isPlainObject: () =>
|
|
7486
|
+
isPlainObject: () => isPlainObject2,
|
|
4404
7487
|
issue: () => issue,
|
|
4405
7488
|
joinValues: () => joinValues,
|
|
4406
7489
|
jsonStringifyReplacer: () => jsonStringifyReplacer,
|
|
@@ -4504,10 +7587,10 @@ function assignProp(target, prop, value) {
|
|
|
4504
7587
|
configurable: true
|
|
4505
7588
|
});
|
|
4506
7589
|
}
|
|
4507
|
-
function getElementAtPath(obj,
|
|
4508
|
-
if (!
|
|
7590
|
+
function getElementAtPath(obj, path2) {
|
|
7591
|
+
if (!path2)
|
|
4509
7592
|
return obj;
|
|
4510
|
-
return
|
|
7593
|
+
return path2.reduce((acc, key) => acc?.[key], obj);
|
|
4511
7594
|
}
|
|
4512
7595
|
function promiseAllObject(promisesObj) {
|
|
4513
7596
|
const keys = Object.keys(promisesObj);
|
|
@@ -4534,7 +7617,7 @@ function esc(str) {
|
|
|
4534
7617
|
function isObject(data) {
|
|
4535
7618
|
return typeof data === "object" && data !== null && !Array.isArray(data);
|
|
4536
7619
|
}
|
|
4537
|
-
function
|
|
7620
|
+
function isPlainObject2(o) {
|
|
4538
7621
|
if (isObject(o) === false)
|
|
4539
7622
|
return false;
|
|
4540
7623
|
const ctor = o.constructor;
|
|
@@ -4662,7 +7745,7 @@ function omit(schema, mask) {
|
|
|
4662
7745
|
});
|
|
4663
7746
|
}
|
|
4664
7747
|
function extend(schema, shape) {
|
|
4665
|
-
if (!
|
|
7748
|
+
if (!isPlainObject2(shape)) {
|
|
4666
7749
|
throw new Error("Invalid input to extend: expected a plain object");
|
|
4667
7750
|
}
|
|
4668
7751
|
const def = {
|
|
@@ -4756,11 +7839,11 @@ function aborted(x, startIndex = 0) {
|
|
|
4756
7839
|
}
|
|
4757
7840
|
return false;
|
|
4758
7841
|
}
|
|
4759
|
-
function prefixIssues(
|
|
7842
|
+
function prefixIssues(path2, issues) {
|
|
4760
7843
|
return issues.map((iss) => {
|
|
4761
7844
|
var _a;
|
|
4762
7845
|
(_a = iss).path ?? (_a.path = []);
|
|
4763
|
-
iss.path.unshift(
|
|
7846
|
+
iss.path.unshift(path2);
|
|
4764
7847
|
return iss;
|
|
4765
7848
|
});
|
|
4766
7849
|
}
|
|
@@ -4949,7 +8032,7 @@ function treeifyError(error40, _mapper) {
|
|
|
4949
8032
|
return issue2.message;
|
|
4950
8033
|
};
|
|
4951
8034
|
const result = { errors: [] };
|
|
4952
|
-
const processError = (error41,
|
|
8035
|
+
const processError = (error41, path2 = []) => {
|
|
4953
8036
|
var _a, _b;
|
|
4954
8037
|
for (const issue2 of error41.issues) {
|
|
4955
8038
|
if (issue2.code === "invalid_union" && issue2.errors.length) {
|
|
@@ -4959,7 +8042,7 @@ function treeifyError(error40, _mapper) {
|
|
|
4959
8042
|
} else if (issue2.code === "invalid_element") {
|
|
4960
8043
|
processError({ issues: issue2.issues }, issue2.path);
|
|
4961
8044
|
} else {
|
|
4962
|
-
const fullpath = [...
|
|
8045
|
+
const fullpath = [...path2, ...issue2.path];
|
|
4963
8046
|
if (fullpath.length === 0) {
|
|
4964
8047
|
result.errors.push(mapper(issue2));
|
|
4965
8048
|
continue;
|
|
@@ -4989,9 +8072,9 @@ function treeifyError(error40, _mapper) {
|
|
|
4989
8072
|
processError(error40);
|
|
4990
8073
|
return result;
|
|
4991
8074
|
}
|
|
4992
|
-
function toDotPath(
|
|
8075
|
+
function toDotPath(path2) {
|
|
4993
8076
|
const segs = [];
|
|
4994
|
-
for (const seg of
|
|
8077
|
+
for (const seg of path2) {
|
|
4995
8078
|
if (typeof seg === "number")
|
|
4996
8079
|
segs.push(`[${seg}]`);
|
|
4997
8080
|
else if (typeof seg === "symbol")
|
|
@@ -5017,7 +8100,7 @@ function prettifyError(error40) {
|
|
|
5017
8100
|
return lines.join("\n");
|
|
5018
8101
|
}
|
|
5019
8102
|
var initializer, $ZodError, $ZodRealError;
|
|
5020
|
-
var
|
|
8103
|
+
var init_errors2 = __esm({
|
|
5021
8104
|
"../../node_modules/.pnpm/zod@3.25.76/node_modules/zod/v4/core/errors.js"() {
|
|
5022
8105
|
init_core();
|
|
5023
8106
|
init_util();
|
|
@@ -5053,7 +8136,7 @@ var _parse, parse, _parseAsync, parseAsync, _safeParse, safeParse, _safeParseAsy
|
|
|
5053
8136
|
var init_parse = __esm({
|
|
5054
8137
|
"../../node_modules/.pnpm/zod@3.25.76/node_modules/zod/v4/core/parse.js"() {
|
|
5055
8138
|
init_core();
|
|
5056
|
-
|
|
8139
|
+
init_errors2();
|
|
5057
8140
|
init_util();
|
|
5058
8141
|
_parse = (_Err) => (schema, value, _ctx, _params) => {
|
|
5059
8142
|
const ctx = _ctx ? Object.assign(_ctx, { async: false }) : { async: false };
|
|
@@ -5841,7 +8924,7 @@ function isValidBase64(data) {
|
|
|
5841
8924
|
function isValidBase64URL(data) {
|
|
5842
8925
|
if (!base64url.test(data))
|
|
5843
8926
|
return false;
|
|
5844
|
-
const base643 = data.replace(/[-_]/g, (
|
|
8927
|
+
const base643 = data.replace(/[-_]/g, (c3) => c3 === "-" ? "+" : "/");
|
|
5845
8928
|
const padded = base643.padEnd(Math.ceil(base643.length / 4) * 4, "=");
|
|
5846
8929
|
return isValidBase64(padded);
|
|
5847
8930
|
}
|
|
@@ -5917,7 +9000,7 @@ function mergeValues(a, b) {
|
|
|
5917
9000
|
if (a instanceof Date && b instanceof Date && +a === +b) {
|
|
5918
9001
|
return { valid: true, data: a };
|
|
5919
9002
|
}
|
|
5920
|
-
if (
|
|
9003
|
+
if (isPlainObject2(a) && isPlainObject2(b)) {
|
|
5921
9004
|
const bKeys = Object.keys(b);
|
|
5922
9005
|
const sharedKeys = Object.keys(a).filter((key) => bKeys.indexOf(key) !== -1);
|
|
5923
9006
|
const newObj = { ...a, ...b };
|
|
@@ -6994,7 +10077,7 @@ var init_schemas = __esm({
|
|
|
6994
10077
|
$ZodType.init(inst, def);
|
|
6995
10078
|
inst._zod.parse = (payload, ctx) => {
|
|
6996
10079
|
const input = payload.value;
|
|
6997
|
-
if (!
|
|
10080
|
+
if (!isPlainObject2(input)) {
|
|
6998
10081
|
payload.issues.push({
|
|
6999
10082
|
expected: "record",
|
|
7000
10083
|
code: "invalid_type",
|
|
@@ -14535,7 +17618,7 @@ var init_core2 = __esm({
|
|
|
14535
17618
|
"../../node_modules/.pnpm/zod@3.25.76/node_modules/zod/v4/core/index.js"() {
|
|
14536
17619
|
init_core();
|
|
14537
17620
|
init_parse();
|
|
14538
|
-
|
|
17621
|
+
init_errors2();
|
|
14539
17622
|
init_schemas();
|
|
14540
17623
|
init_checks();
|
|
14541
17624
|
init_versions();
|
|
@@ -14608,7 +17691,7 @@ var init_iso = __esm({
|
|
|
14608
17691
|
|
|
14609
17692
|
// ../../node_modules/.pnpm/zod@3.25.76/node_modules/zod/v4/classic/errors.js
|
|
14610
17693
|
var initializer2, ZodError, ZodRealError;
|
|
14611
|
-
var
|
|
17694
|
+
var init_errors3 = __esm({
|
|
14612
17695
|
"../../node_modules/.pnpm/zod@3.25.76/node_modules/zod/v4/classic/errors.js"() {
|
|
14613
17696
|
init_core2();
|
|
14614
17697
|
init_core2();
|
|
@@ -14652,7 +17735,7 @@ var parse2, parseAsync2, safeParse2, safeParseAsync2;
|
|
|
14652
17735
|
var init_parse2 = __esm({
|
|
14653
17736
|
"../../node_modules/.pnpm/zod@3.25.76/node_modules/zod/v4/classic/parse.js"() {
|
|
14654
17737
|
init_core2();
|
|
14655
|
-
|
|
17738
|
+
init_errors3();
|
|
14656
17739
|
parse2 = /* @__PURE__ */ _parse(ZodRealError);
|
|
14657
17740
|
parseAsync2 = /* @__PURE__ */ _parseAsync(ZodRealError);
|
|
14658
17741
|
safeParse2 = /* @__PURE__ */ _safeParse(ZodRealError);
|
|
@@ -15011,7 +18094,7 @@ function promise(innerType) {
|
|
|
15011
18094
|
innerType
|
|
15012
18095
|
});
|
|
15013
18096
|
}
|
|
15014
|
-
function
|
|
18097
|
+
function check2(fn) {
|
|
15015
18098
|
const ch = new $ZodCheck({
|
|
15016
18099
|
check: "custom"
|
|
15017
18100
|
// ...util.normalizeParams(params),
|
|
@@ -15026,7 +18109,7 @@ function refine(fn, _params = {}) {
|
|
|
15026
18109
|
return _refine(ZodCustom, fn, _params);
|
|
15027
18110
|
}
|
|
15028
18111
|
function superRefine(fn) {
|
|
15029
|
-
const ch =
|
|
18112
|
+
const ch = check2((payload) => {
|
|
15030
18113
|
payload.addIssue = (issue2) => {
|
|
15031
18114
|
if (typeof issue2 === "string") {
|
|
15032
18115
|
payload.issues.push(util_exports.issue(issue2, payload.value, ch._zod.def));
|
|
@@ -15102,7 +18185,7 @@ var init_schemas2 = __esm({
|
|
|
15102
18185
|
inst.parseAsync = async (data, params) => parseAsync2(inst, data, params, { callee: inst.parseAsync });
|
|
15103
18186
|
inst.safeParseAsync = async (data, params) => safeParseAsync2(inst, data, params);
|
|
15104
18187
|
inst.spa = inst.safeParseAsync;
|
|
15105
|
-
inst.refine = (
|
|
18188
|
+
inst.refine = (check3, params) => inst.check(refine(check3, params));
|
|
15106
18189
|
inst.superRefine = (refinement) => inst.check(superRefine(refinement));
|
|
15107
18190
|
inst.overwrite = (fn) => inst.check(_overwrite(fn));
|
|
15108
18191
|
inst.optional = () => optional(inst);
|
|
@@ -15369,9 +18452,9 @@ var init_schemas2 = __esm({
|
|
|
15369
18452
|
ZodType.init(inst, def);
|
|
15370
18453
|
inst.min = (value, params) => inst.check(_gte(value, params));
|
|
15371
18454
|
inst.max = (value, params) => inst.check(_lte(value, params));
|
|
15372
|
-
const
|
|
15373
|
-
inst.minDate =
|
|
15374
|
-
inst.maxDate =
|
|
18455
|
+
const c3 = inst._zod.bag;
|
|
18456
|
+
inst.minDate = c3.minimum ? new Date(c3.minimum) : null;
|
|
18457
|
+
inst.maxDate = c3.maximum ? new Date(c3.maximum) : null;
|
|
15375
18458
|
});
|
|
15376
18459
|
ZodArray = /* @__PURE__ */ $constructor("ZodArray", (inst, def) => {
|
|
15377
18460
|
$ZodArray.init(inst, def);
|
|
@@ -15754,7 +18837,7 @@ __export(external_exports, {
|
|
|
15754
18837
|
bigint: () => bigint2,
|
|
15755
18838
|
boolean: () => boolean2,
|
|
15756
18839
|
catch: () => _catch2,
|
|
15757
|
-
check: () =>
|
|
18840
|
+
check: () => check2,
|
|
15758
18841
|
cidrv4: () => cidrv42,
|
|
15759
18842
|
cidrv6: () => cidrv62,
|
|
15760
18843
|
clone: () => clone,
|
|
@@ -15883,7 +18966,7 @@ var init_external = __esm({
|
|
|
15883
18966
|
init_core2();
|
|
15884
18967
|
init_schemas2();
|
|
15885
18968
|
init_checks2();
|
|
15886
|
-
|
|
18969
|
+
init_errors3();
|
|
15887
18970
|
init_parse2();
|
|
15888
18971
|
init_compat();
|
|
15889
18972
|
init_core2();
|
|
@@ -18415,7 +21498,7 @@ var init_src = __esm({
|
|
|
18415
21498
|
|
|
18416
21499
|
// ../acp-runtime/src/spawners/node.ts
|
|
18417
21500
|
import { spawn as nodeSpawn } from "node:child_process";
|
|
18418
|
-
import { Readable, Writable } from "node:stream";
|
|
21501
|
+
import { Readable as Readable2, Writable } from "node:stream";
|
|
18419
21502
|
var NodeSpawner;
|
|
18420
21503
|
var init_node = __esm({
|
|
18421
21504
|
"../acp-runtime/src/spawners/node.ts"() {
|
|
@@ -18436,8 +21519,8 @@ var init_node = __esm({
|
|
|
18436
21519
|
stdio: ["pipe", "pipe", "pipe"]
|
|
18437
21520
|
});
|
|
18438
21521
|
const stdin = Writable.toWeb(child.stdin);
|
|
18439
|
-
const stdout =
|
|
18440
|
-
const stderr =
|
|
21522
|
+
const stdout = Readable2.toWeb(child.stdout);
|
|
21523
|
+
const stderr = Readable2.toWeb(child.stderr);
|
|
18441
21524
|
const exited = new Promise((resolve) => {
|
|
18442
21525
|
let settled = false;
|
|
18443
21526
|
const settle = (code, signal) => {
|
|
@@ -18461,28 +21544,28 @@ var init_node = __esm({
|
|
|
18461
21544
|
});
|
|
18462
21545
|
|
|
18463
21546
|
// src/bridge/lib/session-cwd.ts
|
|
18464
|
-
import { mkdir as
|
|
21547
|
+
import { mkdir as mkdir6, rm, writeFile as writeFile6 } from "node:fs/promises";
|
|
18465
21548
|
import { createHash } from "node:crypto";
|
|
18466
|
-
import { dirname as
|
|
21549
|
+
import { dirname as dirname8, join as join5 } from "node:path";
|
|
18467
21550
|
function dirNameFor(sessionId) {
|
|
18468
21551
|
if (/^[a-f0-9]{1,12}$/i.test(sessionId)) return sessionId.toLowerCase();
|
|
18469
21552
|
return createHash("sha256").update(sessionId).digest("hex").slice(0, DIR_NAME_LEN);
|
|
18470
21553
|
}
|
|
18471
21554
|
async function ensureSessionCwd(sessionId) {
|
|
18472
|
-
const cwd =
|
|
18473
|
-
await
|
|
21555
|
+
const cwd = join5(paths().sessionsDir, dirNameFor(sessionId));
|
|
21556
|
+
await mkdir6(cwd, { recursive: true });
|
|
18474
21557
|
return cwd;
|
|
18475
21558
|
}
|
|
18476
21559
|
async function writeBundle(cwd, files) {
|
|
18477
21560
|
for (const f of files) {
|
|
18478
21561
|
if (f.path.startsWith("/") || f.path.includes("..")) continue;
|
|
18479
|
-
const dst =
|
|
18480
|
-
await
|
|
18481
|
-
await
|
|
21562
|
+
const dst = join5(cwd, f.path);
|
|
21563
|
+
await mkdir6(dirname8(dst), { recursive: true });
|
|
21564
|
+
await writeFile6(dst, f.content);
|
|
18482
21565
|
}
|
|
18483
21566
|
}
|
|
18484
21567
|
async function removeSessionCwd(sessionId) {
|
|
18485
|
-
const cwd =
|
|
21568
|
+
const cwd = join5(paths().sessionsDir, dirNameFor(sessionId));
|
|
18486
21569
|
try {
|
|
18487
21570
|
await rm(cwd, { recursive: true, force: true });
|
|
18488
21571
|
} catch {
|
|
@@ -18498,12 +21581,12 @@ var init_session_cwd = __esm({
|
|
|
18498
21581
|
});
|
|
18499
21582
|
|
|
18500
21583
|
// src/bridge/lib/claude-config-dir.ts
|
|
18501
|
-
import { mkdir as
|
|
18502
|
-
import { join as
|
|
18503
|
-
import { homedir as
|
|
21584
|
+
import { mkdir as mkdir7, readdir, rm as rm2, symlink } from "node:fs/promises";
|
|
21585
|
+
import { join as join6 } from "node:path";
|
|
21586
|
+
import { homedir as homedir3 } from "node:os";
|
|
18504
21587
|
async function setupClaudeConfigDir(cwd, blocklist) {
|
|
18505
|
-
const cfgDir =
|
|
18506
|
-
await
|
|
21588
|
+
const cfgDir = join6(cwd, ".claude-config");
|
|
21589
|
+
await mkdir7(cfgDir, { recursive: true });
|
|
18507
21590
|
await mirrorClaudeHome(cfgDir);
|
|
18508
21591
|
await rebuildSkills(cfgDir, blocklist);
|
|
18509
21592
|
return cfgDir;
|
|
@@ -18517,11 +21600,11 @@ async function mirrorClaudeHome(cfgDir) {
|
|
|
18517
21600
|
}
|
|
18518
21601
|
for (const entry of entries) {
|
|
18519
21602
|
if (entry === "skills") continue;
|
|
18520
|
-
const dst =
|
|
21603
|
+
const dst = join6(cfgDir, entry);
|
|
18521
21604
|
await rm2(dst, { recursive: true, force: true }).catch(() => {
|
|
18522
21605
|
});
|
|
18523
21606
|
try {
|
|
18524
|
-
await symlink(
|
|
21607
|
+
await symlink(join6(CLAUDE_HOME, entry), dst);
|
|
18525
21608
|
} catch (e) {
|
|
18526
21609
|
process.stderr.write(
|
|
18527
21610
|
` ! claude-config symlink ${entry} failed (non-fatal): ${e.message}
|
|
@@ -18531,11 +21614,11 @@ async function mirrorClaudeHome(cfgDir) {
|
|
|
18531
21614
|
}
|
|
18532
21615
|
}
|
|
18533
21616
|
async function rebuildSkills(cfgDir, blocklist) {
|
|
18534
|
-
const dst =
|
|
21617
|
+
const dst = join6(cfgDir, "skills");
|
|
18535
21618
|
await rm2(dst, { recursive: true, force: true }).catch(() => {
|
|
18536
21619
|
});
|
|
18537
|
-
await
|
|
18538
|
-
const src =
|
|
21620
|
+
await mkdir7(dst, { recursive: true });
|
|
21621
|
+
const src = join6(CLAUDE_HOME, "skills");
|
|
18539
21622
|
let ids = [];
|
|
18540
21623
|
try {
|
|
18541
21624
|
ids = await readdir(src);
|
|
@@ -18545,7 +21628,7 @@ async function rebuildSkills(cfgDir, blocklist) {
|
|
|
18545
21628
|
for (const id of ids) {
|
|
18546
21629
|
if (id.startsWith(".")) continue;
|
|
18547
21630
|
if (blocklist.has(id)) continue;
|
|
18548
|
-
await symlink(
|
|
21631
|
+
await symlink(join6(src, id), join6(dst, id)).catch((e) => {
|
|
18549
21632
|
process.stderr.write(
|
|
18550
21633
|
` ! claude-config skill symlink ${id} failed (non-fatal): ${e.message}
|
|
18551
21634
|
`
|
|
@@ -18557,11 +21640,12 @@ var CLAUDE_HOME;
|
|
|
18557
21640
|
var init_claude_config_dir = __esm({
|
|
18558
21641
|
"src/bridge/lib/claude-config-dir.ts"() {
|
|
18559
21642
|
"use strict";
|
|
18560
|
-
CLAUDE_HOME =
|
|
21643
|
+
CLAUDE_HOME = join6(homedir3(), ".claude");
|
|
18561
21644
|
}
|
|
18562
21645
|
});
|
|
18563
21646
|
|
|
18564
21647
|
// src/bridge/lib/session-manager.ts
|
|
21648
|
+
import { spawn as childSpawn } from "node:child_process";
|
|
18565
21649
|
function scrubAcpSpawnEnv(base) {
|
|
18566
21650
|
return {
|
|
18567
21651
|
...base,
|
|
@@ -18585,6 +21669,11 @@ var init_session_manager = __esm({
|
|
|
18585
21669
|
#runtime = new AcpRuntimeImpl(this.#spawner);
|
|
18586
21670
|
#sessions = /* @__PURE__ */ new Map();
|
|
18587
21671
|
#env = { apiKey: "", apiUrl: "", runtimeToken: "" };
|
|
21672
|
+
/** Set by `drain()` to refuse new session.start while in-flight turns
|
|
21673
|
+
* finish. Existing sessions keep accepting prompts so a user mid-turn
|
|
21674
|
+
* doesn't hit "session not ready" mid-stream just because the daemon
|
|
21675
|
+
* is on its way out. */
|
|
21676
|
+
#draining = false;
|
|
18588
21677
|
constructor(send) {
|
|
18589
21678
|
this.#send = send;
|
|
18590
21679
|
}
|
|
@@ -18597,6 +21686,18 @@ var init_session_manager = __esm({
|
|
|
18597
21686
|
has(session_id) {
|
|
18598
21687
|
return this.#sessions.has(session_id);
|
|
18599
21688
|
}
|
|
21689
|
+
/** Sum of in-flight turns across all sessions. A turn registers itself
|
|
21690
|
+
* in `sess.turns` when `prompt()` starts and removes itself in the
|
|
21691
|
+
* finally block when the ACP child finishes streaming. drain() polls
|
|
21692
|
+
* this to know when it's safe to exit. */
|
|
21693
|
+
activeTurnCount() {
|
|
21694
|
+
let n = 0;
|
|
21695
|
+
for (const s of this.#sessions.values()) n += s.turns.size;
|
|
21696
|
+
return n;
|
|
21697
|
+
}
|
|
21698
|
+
sessionCount() {
|
|
21699
|
+
return this.#sessions.size;
|
|
21700
|
+
}
|
|
18600
21701
|
/** Re-announce alive sessions to the server (used after WS reconnect). */
|
|
18601
21702
|
announceAll() {
|
|
18602
21703
|
for (const [session_id, sess] of this.#sessions) {
|
|
@@ -18604,6 +21705,15 @@ var init_session_manager = __esm({
|
|
|
18604
21705
|
}
|
|
18605
21706
|
}
|
|
18606
21707
|
async start(p) {
|
|
21708
|
+
if (this.#draining) {
|
|
21709
|
+
this.#send({
|
|
21710
|
+
type: "session.error",
|
|
21711
|
+
session_id: p.session_id,
|
|
21712
|
+
turn_id: "",
|
|
21713
|
+
message: "daemon draining for restart \u2014 retry in a few seconds"
|
|
21714
|
+
});
|
|
21715
|
+
return;
|
|
21716
|
+
}
|
|
18607
21717
|
const existing = this.#sessions.get(p.session_id);
|
|
18608
21718
|
if (existing) {
|
|
18609
21719
|
this.#send({
|
|
@@ -18613,7 +21723,7 @@ var init_session_manager = __esm({
|
|
|
18613
21723
|
});
|
|
18614
21724
|
return;
|
|
18615
21725
|
}
|
|
18616
|
-
const agent =
|
|
21726
|
+
const agent = resolveKnownAgent(p.agent_id);
|
|
18617
21727
|
if (!agent) {
|
|
18618
21728
|
this.#send({
|
|
18619
21729
|
type: "session.error",
|
|
@@ -18622,12 +21732,32 @@ var init_session_manager = __esm({
|
|
|
18622
21732
|
});
|
|
18623
21733
|
return;
|
|
18624
21734
|
}
|
|
21735
|
+
if (agent.id !== p.agent_id) {
|
|
21736
|
+
process.stderr.write(
|
|
21737
|
+
` \u21AA canonicalized acp_agent_id ${p.agent_id} \u2192 ${agent.id} (legacy alias)
|
|
21738
|
+
`
|
|
21739
|
+
);
|
|
21740
|
+
}
|
|
21741
|
+
const onPath = await new Promise((resolve) => {
|
|
21742
|
+
const probe = process.platform === "win32" ? "where" : "which";
|
|
21743
|
+
const p2 = childSpawn(probe, [agent.spec.command], { stdio: "ignore" });
|
|
21744
|
+
p2.once("error", () => resolve(false));
|
|
21745
|
+
p2.once("exit", (code) => resolve(code === 0));
|
|
21746
|
+
});
|
|
21747
|
+
if (!onPath) {
|
|
21748
|
+
this.#send({
|
|
21749
|
+
type: "session.error",
|
|
21750
|
+
session_id: p.session_id,
|
|
21751
|
+
message: `binary not on PATH for ${agent.id}: \`${agent.spec.command}\`` + (agent.installHint ? `. Install: ${agent.installHint}` : "")
|
|
21752
|
+
});
|
|
21753
|
+
return;
|
|
21754
|
+
}
|
|
18625
21755
|
const sessionCwd = await ensureSessionCwd(p.session_id);
|
|
18626
21756
|
let blocklist = [];
|
|
18627
21757
|
let bundleMcpServers = [];
|
|
18628
21758
|
let bundleEnv = [];
|
|
18629
21759
|
try {
|
|
18630
|
-
const bundle = await this.#fetchBundle(p.session_id,
|
|
21760
|
+
const bundle = await this.#fetchBundle(p.session_id, agent.id);
|
|
18631
21761
|
if (bundle) {
|
|
18632
21762
|
await writeBundle(sessionCwd, bundle.files);
|
|
18633
21763
|
blocklist = bundle.local_skill_blocklist ?? [];
|
|
@@ -18639,7 +21769,7 @@ var init_session_manager = __esm({
|
|
|
18639
21769
|
`);
|
|
18640
21770
|
}
|
|
18641
21771
|
const extraEnv = {};
|
|
18642
|
-
if (
|
|
21772
|
+
if (agent.id === "claude-acp") {
|
|
18643
21773
|
try {
|
|
18644
21774
|
const cfgDir = await setupClaudeConfigDir(sessionCwd, new Set(blocklist));
|
|
18645
21775
|
extraEnv.CLAUDE_CONFIG_DIR = cfgDir;
|
|
@@ -18760,6 +21890,66 @@ var init_session_manager = __esm({
|
|
|
18760
21890
|
const ids = [...this.#sessions.keys()];
|
|
18761
21891
|
await Promise.all(ids.map((id) => this.#killChild(id)));
|
|
18762
21892
|
}
|
|
21893
|
+
/**
|
|
21894
|
+
* Graceful drain for upgrade/restart. Caller (daemon SIGTERM handler)
|
|
21895
|
+
* awaits this before exiting so in-flight ACP turns get to finish
|
|
21896
|
+
* naturally instead of being SIGTERM'd mid-stream.
|
|
21897
|
+
*
|
|
21898
|
+
* Recovery model — mirrors the cloud agent's DO-eviction recovery
|
|
21899
|
+
* (apps/agent/src/runtime/turn-runtime.ts:268 recoverAgentTurn):
|
|
21900
|
+
*
|
|
21901
|
+
* 1. Set #draining → start() rejects new sessions; server retries.
|
|
21902
|
+
* 2. Poll activeTurnCount every 200ms until either:
|
|
21903
|
+
* - all turns drained naturally (clean session.complete) → break
|
|
21904
|
+
* - deadline elapsed → abort remaining turns. Their prompt()
|
|
21905
|
+
* loops unwind, emit session.error, and the ACP children
|
|
21906
|
+
* checkpoint their conversation state to disk (each ACP
|
|
21907
|
+
* implementation owns its own persistence; e.g. claude-acp
|
|
21908
|
+
* stores into ~/.claude/projects/...).
|
|
21909
|
+
* 3. disposeAll() — KEEPS spawn cwds. Same shape as a clean
|
|
21910
|
+
* shutdown.
|
|
21911
|
+
*
|
|
21912
|
+
* The next time the server sends session.start for any of these ids
|
|
21913
|
+
* it includes `resume.acp_session_id`. The new daemon respawns a
|
|
21914
|
+
* fresh ACP child in the preserved cwd and calls session/load to
|
|
21915
|
+
* restore conversation history (session-manager.ts:311 →
|
|
21916
|
+
* session.ts:108). Worst case the user re-prompts the cut-off turn;
|
|
21917
|
+
* partial response on their screen is the only artifact.
|
|
21918
|
+
*
|
|
21919
|
+
* Idempotent: a second call while one is in progress no-ops past the
|
|
21920
|
+
* existing drain.
|
|
21921
|
+
*/
|
|
21922
|
+
async drain(deadlineMs, opts) {
|
|
21923
|
+
if (this.#draining) {
|
|
21924
|
+
const t02 = Date.now();
|
|
21925
|
+
while (this.#sessions.size > 0 && Date.now() - t02 < deadlineMs) {
|
|
21926
|
+
await new Promise((r) => setTimeout(r, 200));
|
|
21927
|
+
}
|
|
21928
|
+
return { initialTurns: 0, abortedTurns: 0, sessions: 0 };
|
|
21929
|
+
}
|
|
21930
|
+
this.#draining = true;
|
|
21931
|
+
const initialTurns = this.activeTurnCount();
|
|
21932
|
+
const initialSessions = this.#sessions.size;
|
|
21933
|
+
const t0 = Date.now();
|
|
21934
|
+
while (this.activeTurnCount() > 0) {
|
|
21935
|
+
const elapsed = Date.now() - t0;
|
|
21936
|
+
if (elapsed >= deadlineMs) break;
|
|
21937
|
+
opts?.onProgress?.(this.activeTurnCount(), deadlineMs - elapsed);
|
|
21938
|
+
await new Promise((r) => setTimeout(r, 200));
|
|
21939
|
+
}
|
|
21940
|
+
let aborted2 = 0;
|
|
21941
|
+
for (const sess of this.#sessions.values()) {
|
|
21942
|
+
for (const ctrl of sess.turns.values()) {
|
|
21943
|
+
ctrl.abort();
|
|
21944
|
+
aborted2 += 1;
|
|
21945
|
+
}
|
|
21946
|
+
}
|
|
21947
|
+
if (aborted2 > 0) {
|
|
21948
|
+
await new Promise((r) => setTimeout(r, 2e3));
|
|
21949
|
+
}
|
|
21950
|
+
await this.disposeAll();
|
|
21951
|
+
return { initialTurns, abortedTurns: aborted2, sessions: initialSessions };
|
|
21952
|
+
}
|
|
18763
21953
|
/** Kill the ACP child + drop in-memory state. Does NOT touch the spawn
|
|
18764
21954
|
* cwd — caller decides whether the cwd should outlive this. */
|
|
18765
21955
|
async #killChild(session_id) {
|
|
@@ -18788,27 +21978,34 @@ var init_session_manager = __esm({
|
|
|
18788
21978
|
});
|
|
18789
21979
|
|
|
18790
21980
|
// src/bridge/lib/local-skills.ts
|
|
18791
|
-
import { readdir as readdir2, readFile as
|
|
18792
|
-
import { join as
|
|
18793
|
-
import { homedir as
|
|
21981
|
+
import { readdir as readdir2, readFile as readFile6, stat } from "node:fs/promises";
|
|
21982
|
+
import { join as join7 } from "node:path";
|
|
21983
|
+
import { homedir as homedir4 } from "node:os";
|
|
18794
21984
|
async function detectLocalSkills() {
|
|
18795
|
-
|
|
18796
|
-
|
|
18797
|
-
|
|
21985
|
+
const [claude, gemini, opencode] = await Promise.all([
|
|
21986
|
+
detectClaudeCodeSkills(),
|
|
21987
|
+
detectGeminiExtensions(),
|
|
21988
|
+
detectOpencodeAgents()
|
|
21989
|
+
]);
|
|
21990
|
+
const out = {};
|
|
21991
|
+
if (claude.length) out["claude-acp"] = claude;
|
|
21992
|
+
if (gemini.length) out["gemini"] = gemini;
|
|
21993
|
+
if (opencode.length) out["opencode"] = opencode;
|
|
21994
|
+
return out;
|
|
18798
21995
|
}
|
|
18799
21996
|
async function detectClaudeCodeSkills() {
|
|
18800
21997
|
const seen = /* @__PURE__ */ new Map();
|
|
18801
|
-
for (const skill of await scanSkillsDir(
|
|
21998
|
+
for (const skill of await scanSkillsDir(join7(HOME, ".claude", "skills"), "global")) {
|
|
18802
21999
|
seen.set(skill.id, skill);
|
|
18803
22000
|
}
|
|
18804
|
-
const pluginsRoot =
|
|
22001
|
+
const pluginsRoot = join7(HOME, ".claude", "plugins");
|
|
18805
22002
|
let plugins = [];
|
|
18806
22003
|
try {
|
|
18807
22004
|
plugins = await readdir2(pluginsRoot);
|
|
18808
22005
|
} catch {
|
|
18809
22006
|
}
|
|
18810
22007
|
for (const plugin of plugins) {
|
|
18811
|
-
const pluginSkillsDir =
|
|
22008
|
+
const pluginSkillsDir = join7(pluginsRoot, plugin, "skills");
|
|
18812
22009
|
for (const skill of await scanSkillsDir(pluginSkillsDir, "plugin", plugin)) {
|
|
18813
22010
|
const key = `${plugin}/${skill.id}`;
|
|
18814
22011
|
seen.set(key, skill);
|
|
@@ -18826,7 +22023,7 @@ async function scanSkillsDir(dir, source, source_label) {
|
|
|
18826
22023
|
const out = [];
|
|
18827
22024
|
for (const id of entries) {
|
|
18828
22025
|
if (id.startsWith(".")) continue;
|
|
18829
|
-
const skillDir =
|
|
22026
|
+
const skillDir = join7(dir, id);
|
|
18830
22027
|
let st;
|
|
18831
22028
|
try {
|
|
18832
22029
|
st = await stat(skillDir);
|
|
@@ -18834,7 +22031,7 @@ async function scanSkillsDir(dir, source, source_label) {
|
|
|
18834
22031
|
continue;
|
|
18835
22032
|
}
|
|
18836
22033
|
if (!st.isDirectory()) continue;
|
|
18837
|
-
const meta = await readSkillMeta(
|
|
22034
|
+
const meta = await readSkillMeta(join7(skillDir, "SKILL.md"));
|
|
18838
22035
|
out.push({
|
|
18839
22036
|
id,
|
|
18840
22037
|
name: meta.name ?? id,
|
|
@@ -18849,7 +22046,7 @@ async function scanSkillsDir(dir, source, source_label) {
|
|
|
18849
22046
|
async function readSkillMeta(file2) {
|
|
18850
22047
|
let text;
|
|
18851
22048
|
try {
|
|
18852
|
-
text = await
|
|
22049
|
+
text = await readFile6(file2, "utf-8");
|
|
18853
22050
|
} catch {
|
|
18854
22051
|
return {};
|
|
18855
22052
|
}
|
|
@@ -18873,11 +22070,89 @@ async function readSkillMeta(file2) {
|
|
|
18873
22070
|
}
|
|
18874
22071
|
return { name, description };
|
|
18875
22072
|
}
|
|
22073
|
+
async function detectGeminiExtensions() {
|
|
22074
|
+
const root = join7(HOME, ".gemini", "extensions");
|
|
22075
|
+
let entries;
|
|
22076
|
+
try {
|
|
22077
|
+
entries = await readdir2(root);
|
|
22078
|
+
} catch {
|
|
22079
|
+
return [];
|
|
22080
|
+
}
|
|
22081
|
+
const out = [];
|
|
22082
|
+
for (const id of entries) {
|
|
22083
|
+
if (id.startsWith(".")) continue;
|
|
22084
|
+
const extDir = join7(root, id);
|
|
22085
|
+
let st;
|
|
22086
|
+
try {
|
|
22087
|
+
st = await stat(extDir);
|
|
22088
|
+
} catch {
|
|
22089
|
+
continue;
|
|
22090
|
+
}
|
|
22091
|
+
if (!st.isDirectory()) continue;
|
|
22092
|
+
let manifest = {};
|
|
22093
|
+
try {
|
|
22094
|
+
const raw = await readFile6(join7(extDir, "gemini-extension.json"), "utf-8");
|
|
22095
|
+
manifest = JSON.parse(raw);
|
|
22096
|
+
} catch {
|
|
22097
|
+
continue;
|
|
22098
|
+
}
|
|
22099
|
+
let description = manifest.description;
|
|
22100
|
+
if (!description) {
|
|
22101
|
+
const ctxName = manifest.contextFileName ?? "GEMINI.md";
|
|
22102
|
+
const meta = await readSkillMeta(join7(extDir, ctxName));
|
|
22103
|
+
description = meta.description;
|
|
22104
|
+
}
|
|
22105
|
+
out.push({
|
|
22106
|
+
id,
|
|
22107
|
+
name: manifest.name ?? id,
|
|
22108
|
+
description,
|
|
22109
|
+
source: "global",
|
|
22110
|
+
path: extDir
|
|
22111
|
+
});
|
|
22112
|
+
}
|
|
22113
|
+
return out;
|
|
22114
|
+
}
|
|
22115
|
+
async function detectOpencodeAgents() {
|
|
22116
|
+
const seen = /* @__PURE__ */ new Map();
|
|
22117
|
+
const dirs = [
|
|
22118
|
+
join7(HOME, ".opencode", "agents"),
|
|
22119
|
+
join7(HOME, ".config", "opencode", "agents")
|
|
22120
|
+
];
|
|
22121
|
+
for (const dir of dirs) {
|
|
22122
|
+
let entries;
|
|
22123
|
+
try {
|
|
22124
|
+
entries = await readdir2(dir);
|
|
22125
|
+
} catch {
|
|
22126
|
+
continue;
|
|
22127
|
+
}
|
|
22128
|
+
for (const file2 of entries) {
|
|
22129
|
+
if (!file2.endsWith(".md") || file2.startsWith(".")) continue;
|
|
22130
|
+
const id = file2.slice(0, -3);
|
|
22131
|
+
const path2 = join7(dir, file2);
|
|
22132
|
+
let st;
|
|
22133
|
+
try {
|
|
22134
|
+
st = await stat(path2);
|
|
22135
|
+
} catch {
|
|
22136
|
+
continue;
|
|
22137
|
+
}
|
|
22138
|
+
if (!st.isFile()) continue;
|
|
22139
|
+
const meta = await readSkillMeta(path2);
|
|
22140
|
+
seen.set(id, {
|
|
22141
|
+
id,
|
|
22142
|
+
name: meta.name ?? id,
|
|
22143
|
+
description: meta.description,
|
|
22144
|
+
source: "global",
|
|
22145
|
+
path: path2
|
|
22146
|
+
});
|
|
22147
|
+
}
|
|
22148
|
+
}
|
|
22149
|
+
return [...seen.values()];
|
|
22150
|
+
}
|
|
18876
22151
|
var HOME;
|
|
18877
22152
|
var init_local_skills = __esm({
|
|
18878
22153
|
"src/bridge/lib/local-skills.ts"() {
|
|
18879
22154
|
"use strict";
|
|
18880
|
-
HOME =
|
|
22155
|
+
HOME = homedir4();
|
|
18881
22156
|
}
|
|
18882
22157
|
});
|
|
18883
22158
|
|
|
@@ -18887,6 +22162,8 @@ __export(daemon_exports, {
|
|
|
18887
22162
|
runDaemon: () => runDaemon
|
|
18888
22163
|
});
|
|
18889
22164
|
import { hostname as hostname3 } from "node:os";
|
|
22165
|
+
import { join as join8 } from "node:path";
|
|
22166
|
+
import { mkdirSync as mkdirSync2, writeFileSync, unlinkSync as unlinkSync2 } from "node:fs";
|
|
18890
22167
|
async function runDaemon() {
|
|
18891
22168
|
const creds = await readCreds();
|
|
18892
22169
|
if (!creds) {
|
|
@@ -18895,25 +22172,108 @@ async function runDaemon() {
|
|
|
18895
22172
|
);
|
|
18896
22173
|
process.exit(2);
|
|
18897
22174
|
}
|
|
18898
|
-
|
|
22175
|
+
const profile = currentProfile();
|
|
22176
|
+
const profileTag = profile ? ` [profile=${profile}]` : "";
|
|
22177
|
+
printBanner(`daemon \u2014 runtime ${creds.runtimeId.slice(0, 8)}\u2026 \u2192 ${creds.serverUrl}${profileTag}`, PKG_VERSION);
|
|
22178
|
+
const cachePath = join8(paths().configDir, "registry-cache.json");
|
|
22179
|
+
await loadRegistry({ cachePath });
|
|
18899
22180
|
const wsBase = creds.serverUrl.replace(/^http(s?):\/\//, "ws$1://").replace(/\/$/, "");
|
|
18900
22181
|
const wsUrl = `${wsBase}/agents/runtime/_attach`;
|
|
18901
22182
|
let backoffMs = RECONNECT_BACKOFF_MIN_MS;
|
|
22183
|
+
const DRAIN_DEADLINE_MS = 1e4;
|
|
22184
|
+
let draining = false;
|
|
18902
22185
|
let stopping = false;
|
|
18903
|
-
const stop = (sig) => {
|
|
22186
|
+
const stop = (sig, force = false) => {
|
|
18904
22187
|
if (stopping) return;
|
|
18905
|
-
|
|
18906
|
-
|
|
18907
|
-
|
|
18908
|
-
if (currentWs) {
|
|
22188
|
+
if (draining && !force) {
|
|
22189
|
+
log.warn(`${sig} again \u2014 abandoning drain, exiting now`);
|
|
22190
|
+
stopping = true;
|
|
18909
22191
|
try {
|
|
18910
|
-
|
|
22192
|
+
unlinkSync2(join8(paths().configDir, "daemon.pid"));
|
|
18911
22193
|
} catch {
|
|
18912
22194
|
}
|
|
22195
|
+
void sessions.disposeAll();
|
|
22196
|
+
if (currentWs) {
|
|
22197
|
+
try {
|
|
22198
|
+
currentWs.close(1e3, "shutdown");
|
|
22199
|
+
} catch {
|
|
22200
|
+
}
|
|
22201
|
+
}
|
|
22202
|
+
return;
|
|
22203
|
+
}
|
|
22204
|
+
draining = true;
|
|
22205
|
+
log.step(`${sig} received, draining (${DRAIN_DEADLINE_MS / 1e3}s deadline; sessions recover via session/load on reconnect)`);
|
|
22206
|
+
try {
|
|
22207
|
+
unlinkSync2(join8(paths().configDir, "daemon.pid"));
|
|
22208
|
+
} catch {
|
|
18913
22209
|
}
|
|
22210
|
+
void (async () => {
|
|
22211
|
+
const r = await sessions.drain(DRAIN_DEADLINE_MS, {
|
|
22212
|
+
onProgress: (active, msLeft) => {
|
|
22213
|
+
log.hint(`${active} turns active, ${Math.ceil(msLeft / 1e3)}s left`);
|
|
22214
|
+
}
|
|
22215
|
+
}).catch((e) => {
|
|
22216
|
+
log.err(`drain failed: ${e.message}`);
|
|
22217
|
+
return { initialTurns: 0, abortedTurns: 0, sessions: 0 };
|
|
22218
|
+
});
|
|
22219
|
+
const naturallyCompleted = r.initialTurns - r.abortedTurns;
|
|
22220
|
+
if (r.abortedTurns > 0) {
|
|
22221
|
+
log.warn(
|
|
22222
|
+
`deadline reached \u2014 aborted ${r.abortedTurns} in-flight turn(s); they'll resume via ACP session/load when the server reconnects`
|
|
22223
|
+
);
|
|
22224
|
+
}
|
|
22225
|
+
log.ok(
|
|
22226
|
+
`drained ${r.sessions} session(s) (${naturallyCompleted}/${r.initialTurns} turns completed cleanly)`
|
|
22227
|
+
);
|
|
22228
|
+
stopping = true;
|
|
22229
|
+
if (currentWs) {
|
|
22230
|
+
try {
|
|
22231
|
+
currentWs.close(1e3, "shutdown");
|
|
22232
|
+
} catch {
|
|
22233
|
+
}
|
|
22234
|
+
}
|
|
22235
|
+
})();
|
|
18914
22236
|
};
|
|
18915
22237
|
process.on("SIGTERM", () => stop("SIGTERM"));
|
|
18916
22238
|
process.on("SIGINT", () => stop("SIGINT"));
|
|
22239
|
+
try {
|
|
22240
|
+
mkdirSync2(paths().configDir, { recursive: true });
|
|
22241
|
+
writeFileSync(join8(paths().configDir, "daemon.pid"), String(process.pid), "utf-8");
|
|
22242
|
+
} catch (e) {
|
|
22243
|
+
process.stderr.write(`! pid file write failed (non-fatal): ${e.message}
|
|
22244
|
+
`);
|
|
22245
|
+
}
|
|
22246
|
+
process.on("SIGHUP", () => {
|
|
22247
|
+
void (async () => {
|
|
22248
|
+
log.step("SIGHUP \u2014 refreshing agent detection");
|
|
22249
|
+
try {
|
|
22250
|
+
await loadRegistry({ cachePath, forceRefresh: true });
|
|
22251
|
+
const agents = (await detectAll()).map((a) => ({ id: a.id, binary: a.spec.command }));
|
|
22252
|
+
const localSkillsDetailed = await detectLocalSkills();
|
|
22253
|
+
const localSkills = {};
|
|
22254
|
+
for (const [agentId, skills] of Object.entries(localSkillsDetailed)) {
|
|
22255
|
+
if (!skills) continue;
|
|
22256
|
+
localSkills[agentId] = skills.map(({ path: _path, ...rest }) => rest);
|
|
22257
|
+
}
|
|
22258
|
+
if (currentWs && currentWs.readyState === wrapper_default.OPEN) {
|
|
22259
|
+
currentWs.send(JSON.stringify({
|
|
22260
|
+
type: "hello",
|
|
22261
|
+
machine_id: creds.machineId,
|
|
22262
|
+
hostname: hostname3(),
|
|
22263
|
+
os: osTag(),
|
|
22264
|
+
version: PKG_VERSION,
|
|
22265
|
+
agents,
|
|
22266
|
+
local_skills: localSkills
|
|
22267
|
+
}));
|
|
22268
|
+
log.ok(`re-published manifest (${agents.length} agents)`);
|
|
22269
|
+
} else {
|
|
22270
|
+
log.warn("WS not attached \u2014 manifest will be re-sent on next connect");
|
|
22271
|
+
}
|
|
22272
|
+
} catch (e) {
|
|
22273
|
+
log.warn(`refresh failed: ${e.message}`);
|
|
22274
|
+
}
|
|
22275
|
+
})();
|
|
22276
|
+
});
|
|
18917
22277
|
let currentWs = null;
|
|
18918
22278
|
const sessions = new SessionManager(() => {
|
|
18919
22279
|
});
|
|
@@ -19060,7 +22420,9 @@ __export(status_exports, {
|
|
|
19060
22420
|
runStatus: () => runStatus
|
|
19061
22421
|
});
|
|
19062
22422
|
async function runStatus() {
|
|
19063
|
-
|
|
22423
|
+
const profile = currentProfile();
|
|
22424
|
+
const profileTag = profile ? ` [profile=${profile}]` : "";
|
|
22425
|
+
printBanner(`status${profileTag}`, PKG_VERSION);
|
|
19064
22426
|
const p = paths();
|
|
19065
22427
|
const creds = await readCreds();
|
|
19066
22428
|
if (!creds) {
|
|
@@ -19068,6 +22430,7 @@ async function runStatus() {
|
|
|
19068
22430
|
log.hint(`looked for ${p.credsFile}`);
|
|
19069
22431
|
process.exit(1);
|
|
19070
22432
|
}
|
|
22433
|
+
const kind = detectServiceKind();
|
|
19071
22434
|
const row = (k, v) => process.stderr.write(` ${c.dim(k.padEnd(11))} ${v}
|
|
19072
22435
|
`);
|
|
19073
22436
|
row("server", creds.serverUrl);
|
|
@@ -19076,7 +22439,7 @@ async function runStatus() {
|
|
|
19076
22439
|
row("registered", new Date(creds.createdAt * 1e3).toISOString());
|
|
19077
22440
|
row("creds file", c.dim(p.credsFile));
|
|
19078
22441
|
row("log file", c.dim(p.logFile));
|
|
19079
|
-
|
|
22442
|
+
row("service", c.dim(`${kind}${p.serviceFile ? ` \u2192 ${p.serviceFile}` : ""}`));
|
|
19080
22443
|
process.stderr.write("\n");
|
|
19081
22444
|
log.step("probing server");
|
|
19082
22445
|
const probe = await probeRuntimeToken(creds.serverUrl, creds.token);
|
|
@@ -19101,6 +22464,7 @@ var init_status = __esm({
|
|
|
19101
22464
|
"use strict";
|
|
19102
22465
|
init_config();
|
|
19103
22466
|
init_platform();
|
|
22467
|
+
init_service_manager();
|
|
19104
22468
|
init_style();
|
|
19105
22469
|
init_version();
|
|
19106
22470
|
init_probe();
|
|
@@ -19114,15 +22478,15 @@ __export(uninstall_exports, {
|
|
|
19114
22478
|
});
|
|
19115
22479
|
async function runUninstall() {
|
|
19116
22480
|
printBanner("uninstall \u2014 remove daemon + local credentials", PKG_VERSION);
|
|
19117
|
-
|
|
19118
|
-
|
|
19119
|
-
|
|
19120
|
-
|
|
19121
|
-
|
|
22481
|
+
try {
|
|
22482
|
+
const r = await uninstall4();
|
|
22483
|
+
const tag = r.kind === "launchd" ? "launchd plist" : r.kind === "systemd" ? "systemd unit" : r.kind === "windows-task" ? "Task Scheduler task" : "service";
|
|
22484
|
+
if (r.removed) log.ok(`${tag} removed ${c.dim(paths().serviceFile ?? paths().configDir)}`);
|
|
22485
|
+
else process.stderr.write(`${sym.dot()} ${c.dim(`${tag} not present`)}
|
|
19122
22486
|
`);
|
|
19123
|
-
|
|
19124
|
-
|
|
19125
|
-
}
|
|
22487
|
+
if (r.warning) log.hint(c.dim(r.warning));
|
|
22488
|
+
} catch (e) {
|
|
22489
|
+
log.warn(`service uninstall failed: ${e instanceof Error ? e.message : String(e)}`);
|
|
19126
22490
|
}
|
|
19127
22491
|
const creds = await readCreds();
|
|
19128
22492
|
if (creds) {
|
|
@@ -19157,7 +22521,7 @@ ${c.bold("Done.")}
|
|
|
19157
22521
|
var init_uninstall = __esm({
|
|
19158
22522
|
"src/bridge/commands/uninstall.ts"() {
|
|
19159
22523
|
"use strict";
|
|
19160
|
-
|
|
22524
|
+
init_service_manager();
|
|
19161
22525
|
init_config();
|
|
19162
22526
|
init_platform();
|
|
19163
22527
|
init_style();
|
|
@@ -19165,17 +22529,87 @@ var init_uninstall = __esm({
|
|
|
19165
22529
|
}
|
|
19166
22530
|
});
|
|
19167
22531
|
|
|
22532
|
+
// src/bridge/commands/agents.ts
|
|
22533
|
+
var agents_exports = {};
|
|
22534
|
+
__export(agents_exports, {
|
|
22535
|
+
runAgents: () => runAgents
|
|
22536
|
+
});
|
|
22537
|
+
import { readFileSync, statSync } from "node:fs";
|
|
22538
|
+
import { join as join9 } from "node:path";
|
|
22539
|
+
async function runAgents(args) {
|
|
22540
|
+
const sub = args[0] ?? "";
|
|
22541
|
+
switch (sub) {
|
|
22542
|
+
case "refresh":
|
|
22543
|
+
await refresh(args.slice(1));
|
|
22544
|
+
return;
|
|
22545
|
+
default:
|
|
22546
|
+
process.stderr.write(
|
|
22547
|
+
"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"
|
|
22548
|
+
);
|
|
22549
|
+
process.exit(sub ? 1 : 0);
|
|
22550
|
+
}
|
|
22551
|
+
}
|
|
22552
|
+
async function refresh(args) {
|
|
22553
|
+
const profile = currentProfile();
|
|
22554
|
+
const profileTag = profile ? ` [profile=${profile}]` : "";
|
|
22555
|
+
const yes = args.includes("--yes") || args.includes("-y");
|
|
22556
|
+
const cachePath = join9(paths().configDir, "registry-cache.json");
|
|
22557
|
+
await loadRegistry({ cachePath, forceRefresh: true });
|
|
22558
|
+
const detected = (await detectAll()).map((a) => ({ id: a.id, binary: a.spec.command }));
|
|
22559
|
+
await auditAndOfferWrappers(detected, { yes });
|
|
22560
|
+
const pidFile = join9(paths().configDir, "daemon.pid");
|
|
22561
|
+
let pid = 0;
|
|
22562
|
+
try {
|
|
22563
|
+
pid = parseInt(readFileSync(pidFile, "utf-8").trim(), 10);
|
|
22564
|
+
if (!Number.isFinite(pid) || pid <= 0) pid = 0;
|
|
22565
|
+
if (pid) process.kill(pid, 0);
|
|
22566
|
+
} catch {
|
|
22567
|
+
pid = 0;
|
|
22568
|
+
}
|
|
22569
|
+
if (pid === 0) {
|
|
22570
|
+
log.hint(`no running daemon${profileTag}; manifest will reflect on next \`oma bridge daemon\``);
|
|
22571
|
+
return;
|
|
22572
|
+
}
|
|
22573
|
+
try {
|
|
22574
|
+
const ageMs = Date.now() - statSync(pidFile).mtimeMs;
|
|
22575
|
+
if (ageMs > 7 * 24 * 3600 * 1e3) {
|
|
22576
|
+
log.hint(`pid file is ${Math.floor(ageMs / 864e5)} days old`);
|
|
22577
|
+
}
|
|
22578
|
+
} catch {
|
|
22579
|
+
}
|
|
22580
|
+
try {
|
|
22581
|
+
process.kill(pid, "SIGHUP");
|
|
22582
|
+
log.ok(`daemon${profileTag} re-detecting (pid ${pid})`);
|
|
22583
|
+
log.hint("Console dropdown will reflect the new state in 1\u20132s");
|
|
22584
|
+
} catch (e) {
|
|
22585
|
+
log.warn(`signal failed: ${e.message}`);
|
|
22586
|
+
process.exit(2);
|
|
22587
|
+
}
|
|
22588
|
+
}
|
|
22589
|
+
var init_agents = __esm({
|
|
22590
|
+
"src/bridge/commands/agents.ts"() {
|
|
22591
|
+
"use strict";
|
|
22592
|
+
init_platform();
|
|
22593
|
+
init_registry();
|
|
22594
|
+
init_wrapper_audit();
|
|
22595
|
+
init_style();
|
|
22596
|
+
}
|
|
22597
|
+
});
|
|
22598
|
+
|
|
19168
22599
|
// src/index.ts
|
|
22600
|
+
init_platform();
|
|
19169
22601
|
import { createServer as createServer2 } from "node:http";
|
|
19170
22602
|
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
|
|
22603
|
+
import { homedir as homedir5, hostname as hostname4 } from "node:os";
|
|
22604
|
+
import { join as join10, dirname as dirname9 } from "node:path";
|
|
22605
|
+
import { mkdirSync as mkdirSync3, readFileSync as readFileSync2, writeFileSync as writeFileSync2, unlinkSync as unlinkSync3, existsSync as existsSync2, chmodSync as chmodSync2 } from "node:fs";
|
|
22606
|
+
import { randomBytes as randomBytes3 } from "node:crypto";
|
|
19175
22607
|
function credentialsPath() {
|
|
19176
22608
|
const xdg = process.env.XDG_CONFIG_HOME;
|
|
19177
|
-
const base = xdg && xdg.length > 0 ? xdg :
|
|
19178
|
-
|
|
22609
|
+
const base = xdg && xdg.length > 0 ? xdg : join10(homedir5(), ".config");
|
|
22610
|
+
const profile = currentProfile();
|
|
22611
|
+
const file2 = profile ? `credentials.${profile}.json` : "credentials.json";
|
|
22612
|
+
return join10(base, "oma", file2);
|
|
19179
22613
|
}
|
|
19180
22614
|
function migrateV1ToV2(v1) {
|
|
19181
22615
|
return {
|
|
@@ -19195,10 +22629,10 @@ function migrateV1ToV2(v1) {
|
|
|
19195
22629
|
};
|
|
19196
22630
|
}
|
|
19197
22631
|
function readCredentials() {
|
|
19198
|
-
const
|
|
22632
|
+
const path2 = credentialsPath();
|
|
19199
22633
|
try {
|
|
19200
|
-
if (!
|
|
19201
|
-
const raw =
|
|
22634
|
+
if (!existsSync2(path2)) return null;
|
|
22635
|
+
const raw = readFileSync2(path2, "utf8");
|
|
19202
22636
|
const parsed = JSON.parse(raw);
|
|
19203
22637
|
if (parsed.version === 2) return parsed;
|
|
19204
22638
|
if (parsed.version === 1) {
|
|
@@ -19215,18 +22649,18 @@ function readCredentials() {
|
|
|
19215
22649
|
}
|
|
19216
22650
|
}
|
|
19217
22651
|
function writeCredentials(creds) {
|
|
19218
|
-
const
|
|
19219
|
-
|
|
19220
|
-
|
|
22652
|
+
const path2 = credentialsPath();
|
|
22653
|
+
mkdirSync3(dirname9(path2), { recursive: true, mode: 448 });
|
|
22654
|
+
writeFileSync2(path2, JSON.stringify(creds, null, 2), { mode: 384 });
|
|
19221
22655
|
try {
|
|
19222
|
-
|
|
22656
|
+
chmodSync2(path2, 384);
|
|
19223
22657
|
} catch {
|
|
19224
22658
|
}
|
|
19225
22659
|
}
|
|
19226
22660
|
function clearCredentials() {
|
|
19227
|
-
const
|
|
19228
|
-
if (!
|
|
19229
|
-
|
|
22661
|
+
const path2 = credentialsPath();
|
|
22662
|
+
if (!existsSync2(path2)) return false;
|
|
22663
|
+
unlinkSync3(path2);
|
|
19230
22664
|
return true;
|
|
19231
22665
|
}
|
|
19232
22666
|
function loadConfig() {
|
|
@@ -19291,8 +22725,8 @@ async function fetchWithRetry(url2, init, maxRetries = 3) {
|
|
|
19291
22725
|
attempt += 1;
|
|
19292
22726
|
}
|
|
19293
22727
|
}
|
|
19294
|
-
async function apiFetch(config2,
|
|
19295
|
-
const url2 = `${config2.baseUrl}${
|
|
22728
|
+
async function apiFetch(config2, path2, init) {
|
|
22729
|
+
const url2 = `${config2.baseUrl}${path2}`;
|
|
19296
22730
|
const res = await fetchWithRetry(url2, {
|
|
19297
22731
|
...init,
|
|
19298
22732
|
headers: {
|
|
@@ -19312,8 +22746,8 @@ async function apiFetch(config2, path, init) {
|
|
|
19312
22746
|
}
|
|
19313
22747
|
return res.json();
|
|
19314
22748
|
}
|
|
19315
|
-
async function rawStream(config2,
|
|
19316
|
-
const res = await fetchWithRetry(`${config2.baseUrl}${
|
|
22749
|
+
async function rawStream(config2, path2, init) {
|
|
22750
|
+
const res = await fetchWithRetry(`${config2.baseUrl}${path2}`, {
|
|
19317
22751
|
...init,
|
|
19318
22752
|
headers: {
|
|
19319
22753
|
"x-api-key": config2.apiKey,
|
|
@@ -19456,7 +22890,7 @@ function table(rows) {
|
|
|
19456
22890
|
if (!rows.length) return;
|
|
19457
22891
|
const widths = rows[0].map((_, i) => Math.max(...rows.map((r) => (r[i] || "").length)));
|
|
19458
22892
|
for (const row of rows) {
|
|
19459
|
-
console.log(row.map((
|
|
22893
|
+
console.log(row.map((c3, i) => (c3 || "").padEnd(widths[i])).join(" "));
|
|
19460
22894
|
}
|
|
19461
22895
|
}
|
|
19462
22896
|
function capsPreview(caps) {
|
|
@@ -19476,7 +22910,7 @@ function isPubliclyReachable(url2) {
|
|
|
19476
22910
|
}
|
|
19477
22911
|
}
|
|
19478
22912
|
async function authLogin(baseUrl, requestedTenant) {
|
|
19479
|
-
const state =
|
|
22913
|
+
const state = randomBytes3(16).toString("hex");
|
|
19480
22914
|
const port = 19500 + Math.floor(Math.random() * 500);
|
|
19481
22915
|
const callback = `http://127.0.0.1:${port}/callback`;
|
|
19482
22916
|
const params = new URLSearchParams({
|
|
@@ -20000,7 +23434,7 @@ Version: v${a.version}`);
|
|
|
20000
23434
|
console.log("No model cards. Create one with: oma models create");
|
|
20001
23435
|
return;
|
|
20002
23436
|
}
|
|
20003
|
-
table([["NAME", "PROVIDER", "MODEL", "KEY", "DEFAULT"], ...data.map((
|
|
23437
|
+
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
23438
|
}
|
|
20005
23439
|
},
|
|
20006
23440
|
{
|
|
@@ -20107,7 +23541,7 @@ Save this key \u2014 it won't be shown again.`);
|
|
|
20107
23541
|
console.log("No credentials in this vault.");
|
|
20108
23542
|
return;
|
|
20109
23543
|
}
|
|
20110
|
-
table([["NAME", "TYPE", "DETAIL"], ...data.map((
|
|
23544
|
+
table([["NAME", "TYPE", "DETAIL"], ...data.map((c3) => [c3.display_name, c3.auth.type, c3.auth.mcp_server_url || c3.auth.command_prefixes?.join(", ") || ""])]);
|
|
20111
23545
|
}
|
|
20112
23546
|
},
|
|
20113
23547
|
{
|
|
@@ -21257,14 +24691,14 @@ Expires in ${r.expiresInDays} days.`);
|
|
|
21257
24691
|
http: "POST /v1/memory_stores/:id/memories {path, content, precondition?}",
|
|
21258
24692
|
async run(config2, args) {
|
|
21259
24693
|
const storeId = args[0];
|
|
21260
|
-
const
|
|
24694
|
+
const path2 = args[1];
|
|
21261
24695
|
const content = readContentArg(args);
|
|
21262
24696
|
const sha = flag(args, "--precondition-sha256");
|
|
21263
|
-
if (!storeId || !
|
|
24697
|
+
if (!storeId || !path2 || content === void 0) {
|
|
21264
24698
|
console.error("Usage: oma memory write <store-id> <path> (--content <c> | --from-file <f>) [--precondition-sha256 <h>]");
|
|
21265
24699
|
process.exit(1);
|
|
21266
24700
|
}
|
|
21267
|
-
const body = { path, content };
|
|
24701
|
+
const body = { path: path2, content };
|
|
21268
24702
|
if (sha) body.precondition = { type: "content_sha256", content_sha256: sha };
|
|
21269
24703
|
const mem = await apiFetch(
|
|
21270
24704
|
config2,
|
|
@@ -21345,19 +24779,19 @@ Expires in ${r.expiresInDays} days.`);
|
|
|
21345
24779
|
async run(config2, args) {
|
|
21346
24780
|
const storeId = args[0];
|
|
21347
24781
|
const memId = args[1];
|
|
21348
|
-
const
|
|
24782
|
+
const path2 = flag(args, "--path");
|
|
21349
24783
|
const content = readContentArg(args);
|
|
21350
24784
|
const sha = flag(args, "--precondition-sha256");
|
|
21351
24785
|
if (!storeId || !memId) {
|
|
21352
24786
|
console.error("Usage: oma memory update <store-id> <memory-id> [--path <p>] [--content <c> | --from-file <f>] [--precondition-sha256 <h>]");
|
|
21353
24787
|
process.exit(1);
|
|
21354
24788
|
}
|
|
21355
|
-
if (
|
|
24789
|
+
if (path2 === void 0 && content === void 0) {
|
|
21356
24790
|
console.error("Pass at least --path or --content/--from-file.");
|
|
21357
24791
|
process.exit(1);
|
|
21358
24792
|
}
|
|
21359
24793
|
const body = {};
|
|
21360
|
-
if (
|
|
24794
|
+
if (path2 !== void 0) body.path = path2;
|
|
21361
24795
|
if (content !== void 0) body.content = content;
|
|
21362
24796
|
if (sha) body.precondition = { type: "content_sha256", content_sha256: sha };
|
|
21363
24797
|
const mem = await apiFetch(
|
|
@@ -21571,10 +25005,10 @@ async function connectMcp(config2, mcpServerUrl, vaultId) {
|
|
|
21571
25005
|
}
|
|
21572
25006
|
function apiRef(resource) {
|
|
21573
25007
|
const groups = /* @__PURE__ */ new Map();
|
|
21574
|
-
for (const
|
|
21575
|
-
const list = groups.get(
|
|
21576
|
-
list.push(` ${
|
|
21577
|
-
groups.set(
|
|
25008
|
+
for (const c3 of commands) {
|
|
25009
|
+
const list = groups.get(c3.group) || [];
|
|
25010
|
+
list.push(` ${c3.http}`);
|
|
25011
|
+
groups.set(c3.group, list);
|
|
21578
25012
|
}
|
|
21579
25013
|
for (const e of extraEndpoints) {
|
|
21580
25014
|
const list = groups.get(e.group) || [];
|
|
@@ -21631,20 +25065,21 @@ oma \u2014 Open Managed Agents CLI
|
|
|
21631
25065
|
|
|
21632
25066
|
Usage:`);
|
|
21633
25067
|
let lastGroup = "";
|
|
21634
|
-
for (const
|
|
21635
|
-
if (
|
|
25068
|
+
for (const c3 of commands) {
|
|
25069
|
+
if (c3.group !== lastGroup) {
|
|
21636
25070
|
console.log(`
|
|
21637
|
-
${
|
|
21638
|
-
lastGroup =
|
|
25071
|
+
${c3.group}:`);
|
|
25072
|
+
lastGroup = c3.group;
|
|
21639
25073
|
}
|
|
21640
|
-
console.log(` ${
|
|
25074
|
+
console.log(` ${c3.usage.padEnd(42)} ${c3.desc}`);
|
|
21641
25075
|
}
|
|
21642
25076
|
console.log(`
|
|
21643
25077
|
Bridge (local runtime):
|
|
21644
|
-
oma bridge setup [--force] [--no-service] Pair this machine with OMA
|
|
21645
|
-
oma bridge daemon Run the bridge in foreground
|
|
25078
|
+
oma bridge setup [--force] [--no-service] Pair this machine with OMA + start daemon
|
|
21646
25079
|
oma bridge status Show creds + probe server reachability
|
|
21647
|
-
oma bridge
|
|
25080
|
+
oma bridge agents refresh Re-detect agents + offer wrapper installs
|
|
25081
|
+
oma bridge uninstall Stop service + remove creds
|
|
25082
|
+
(oma bridge daemon Internal: launched by service mgr / debugging)
|
|
21648
25083
|
|
|
21649
25084
|
API Reference:
|
|
21650
25085
|
oma api Show all HTTP endpoints
|
|
@@ -21669,17 +25104,42 @@ async function main() {
|
|
|
21669
25104
|
apiRef(args[1]);
|
|
21670
25105
|
return;
|
|
21671
25106
|
}
|
|
25107
|
+
for (let i = 0; i < args.length; i++) {
|
|
25108
|
+
if (args[i] === "--profile" && i + 1 < args.length) {
|
|
25109
|
+
process.env.OMA_PROFILE = args[i + 1];
|
|
25110
|
+
args.splice(i, 2);
|
|
25111
|
+
const argvIdx = process.argv.indexOf("--profile");
|
|
25112
|
+
if (argvIdx !== -1) process.argv.splice(argvIdx, 2);
|
|
25113
|
+
break;
|
|
25114
|
+
}
|
|
25115
|
+
const eq = args[i].match(/^--profile=(.+)$/);
|
|
25116
|
+
if (eq) {
|
|
25117
|
+
process.env.OMA_PROFILE = eq[1];
|
|
25118
|
+
args.splice(i, 1);
|
|
25119
|
+
const argvIdx = process.argv.findIndex((a) => a.startsWith("--profile="));
|
|
25120
|
+
if (argvIdx !== -1) process.argv.splice(argvIdx, 1);
|
|
25121
|
+
break;
|
|
25122
|
+
}
|
|
25123
|
+
}
|
|
25124
|
+
try {
|
|
25125
|
+
currentProfile();
|
|
25126
|
+
} catch (e) {
|
|
25127
|
+
console.error(`Error: ${e.message}`);
|
|
25128
|
+
process.exit(2);
|
|
25129
|
+
}
|
|
21672
25130
|
if (args[0] === "bridge") {
|
|
21673
25131
|
const sub = args[1] ?? "";
|
|
21674
25132
|
process.argv.splice(2, 2);
|
|
21675
25133
|
switch (sub) {
|
|
21676
25134
|
case "setup": {
|
|
25135
|
+
const serverUrl = flag(args, "--server-url") ?? "https://openma.dev";
|
|
21677
25136
|
const { runSetup: runSetup2 } = await Promise.resolve().then(() => (init_setup(), setup_exports));
|
|
21678
25137
|
await runSetup2({
|
|
21679
|
-
serverUrl
|
|
21680
|
-
browserOrigin: flag(args, "--browser-origin") ??
|
|
25138
|
+
serverUrl,
|
|
25139
|
+
browserOrigin: flag(args, "--browser-origin") ?? serverUrl,
|
|
21681
25140
|
noService: args.includes("--no-service"),
|
|
21682
|
-
force: args.includes("--force")
|
|
25141
|
+
force: args.includes("--force"),
|
|
25142
|
+
yes: args.includes("--yes") || args.includes("-y")
|
|
21683
25143
|
});
|
|
21684
25144
|
return;
|
|
21685
25145
|
}
|
|
@@ -21698,9 +25158,14 @@ async function main() {
|
|
|
21698
25158
|
await runUninstall2();
|
|
21699
25159
|
return;
|
|
21700
25160
|
}
|
|
25161
|
+
case "agents": {
|
|
25162
|
+
const { runAgents: runAgents2 } = await Promise.resolve().then(() => (init_agents(), agents_exports));
|
|
25163
|
+
await runAgents2(args.slice(2));
|
|
25164
|
+
return;
|
|
25165
|
+
}
|
|
21701
25166
|
default:
|
|
21702
25167
|
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
|
|
25168
|
+
"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
25169
|
);
|
|
21705
25170
|
process.exit(sub ? 1 : 0);
|
|
21706
25171
|
}
|
|
@@ -21711,15 +25176,15 @@ async function main() {
|
|
|
21711
25176
|
const config2 = isPreAuth ? loadConfigOptional() : loadConfig();
|
|
21712
25177
|
config2.json = wantJson;
|
|
21713
25178
|
let needsArgMatch = null;
|
|
21714
|
-
for (const
|
|
21715
|
-
const verbMatch =
|
|
25179
|
+
for (const c3 of commands) {
|
|
25180
|
+
const verbMatch = c3.match.every((tok, i) => args[i] === tok);
|
|
21716
25181
|
if (!verbMatch) continue;
|
|
21717
|
-
if (
|
|
21718
|
-
needsArgMatch =
|
|
25182
|
+
if (c3.needsArg && !args[c3.match.length]) {
|
|
25183
|
+
needsArgMatch = c3;
|
|
21719
25184
|
continue;
|
|
21720
25185
|
}
|
|
21721
|
-
const rest = args.slice(
|
|
21722
|
-
return
|
|
25186
|
+
const rest = args.slice(c3.match.length);
|
|
25187
|
+
return c3.run(config2, rest);
|
|
21723
25188
|
}
|
|
21724
25189
|
if (needsArgMatch) {
|
|
21725
25190
|
console.error(`${needsArgMatch.usage}
|