@habemus-papadum/aiui 0.2.0 → 0.5.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +6 -1
- package/dist/cli.js +1481 -832
- package/dist/cli.js.map +1 -1
- package/dist/commands/browser.d.ts +50 -0
- package/dist/commands/clean.d.ts +49 -0
- package/dist/commands/config-tui.d.ts +1 -0
- package/dist/commands/config.d.ts +43 -0
- package/dist/commands/debug.d.ts +7 -0
- package/dist/commands/env.d.ts +36 -0
- package/dist/commands/extension.d.ts +46 -0
- package/dist/commands/mcp.d.ts +10 -0
- package/dist/commands/native-host.d.ts +16 -0
- package/dist/commands/pencil-url.d.ts +18 -0
- package/dist/commands/vite.d.ts +54 -28
- package/dist/config-Cis6kCik.js +293 -0
- package/dist/config-Cis6kCik.js.map +1 -0
- package/dist/index.d.ts +6 -0
- package/dist/index.js +6 -4
- package/dist/index.js.map +1 -1
- package/dist/util/aiui-args.d.ts +26 -0
- package/dist/util/channel-launch.d.ts +67 -0
- package/dist/util/channel-target.d.ts +33 -0
- package/dist/util/chrome.d.ts +48 -27
- package/dist/util/config-schema.d.ts +96 -0
- package/dist/util/config.d.ts +31 -59
- package/dist/util/first-run.d.ts +11 -8
- package/dist/util/gemini-preflight.d.ts +56 -0
- package/dist/util/openai-preflight.d.ts +4 -3
- package/dist/util/resolve-cli.d.ts +1 -11
- package/package.json +12 -8
- package/dist/commands/demo.d.ts +0 -28
- package/dist/util/browser.d.ts +0 -44
- package/templates/demo/CLAUDE.md +0 -16
- package/templates/demo/README.md +0 -36
- package/templates/demo/gitignore +0 -4
- package/templates/demo/index.html +0 -11
- package/templates/demo/package.json +0 -21
- package/templates/demo/src/main.ts +0 -51
- package/templates/demo/tsconfig.json +0 -11
- package/templates/demo/vite.config.ts +0 -17
package/dist/cli.js
CHANGED
|
@@ -1,381 +1,147 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
|
-
import { Command as
|
|
3
|
-
import { join as
|
|
4
|
-
import { cacheDir as
|
|
5
|
-
import { execa as
|
|
6
|
-
import {
|
|
7
|
-
import {
|
|
8
|
-
import {
|
|
9
|
-
import { createInterface as
|
|
10
|
-
import
|
|
11
|
-
import {
|
|
12
|
-
import {
|
|
13
|
-
import {
|
|
14
|
-
|
|
15
|
-
async function
|
|
16
|
-
const
|
|
17
|
-
if (t !== void 0 && await at(t))
|
|
18
|
-
return { browserUrl: `http://127.0.0.1:${t}`, port: t };
|
|
19
|
-
}
|
|
20
|
-
function it(e) {
|
|
21
|
-
try {
|
|
22
|
-
const [t] = P(l(e, Ce), "utf8").split(`
|
|
23
|
-
`), o = Number(t);
|
|
24
|
-
return Number.isInteger(o) && o > 0 ? o : void 0;
|
|
25
|
-
} catch {
|
|
26
|
-
return;
|
|
27
|
-
}
|
|
28
|
-
}
|
|
29
|
-
async function at(e) {
|
|
30
|
-
try {
|
|
31
|
-
return (await fetch(`http://127.0.0.1:${e}/json/version`, {
|
|
32
|
-
signal: AbortSignal.timeout(1e3)
|
|
33
|
-
})).ok;
|
|
34
|
-
} catch {
|
|
35
|
-
return !1;
|
|
36
|
-
}
|
|
37
|
-
}
|
|
38
|
-
function Ee(e) {
|
|
39
|
-
return e.executablePath ? e.executablePath : ze({
|
|
40
|
-
browser: x.CHROME,
|
|
41
|
-
channel: st[e.channel ?? "stable"]
|
|
42
|
-
});
|
|
43
|
-
}
|
|
44
|
-
const st = {
|
|
45
|
-
stable: O.STABLE,
|
|
46
|
-
beta: O.BETA,
|
|
47
|
-
dev: O.DEV,
|
|
48
|
-
canary: O.CANARY
|
|
49
|
-
};
|
|
50
|
-
async function $e(e) {
|
|
51
|
-
k(e.userDataDir, { recursive: !0 }), Ye(l(e.userDataDir, Ce), { force: !0 });
|
|
52
|
-
const t = [
|
|
53
|
-
`--remote-debugging-port=${e.debugPort ?? 0}`,
|
|
54
|
-
`--user-data-dir=${e.userDataDir}`,
|
|
55
|
-
"--no-first-run",
|
|
56
|
-
"--no-default-browser-check"
|
|
57
|
-
];
|
|
58
|
-
e.extensionDir && t.push(`--load-extension=${e.extensionDir}`), e.headless && t.push("--headless"), t.push(e.startUrl ?? "about:blank");
|
|
59
|
-
const o = p(e.binary, t, {
|
|
60
|
-
detached: !0,
|
|
61
|
-
stdio: "ignore",
|
|
62
|
-
reject: !1,
|
|
63
|
-
cleanup: !1
|
|
64
|
-
});
|
|
65
|
-
o.unref();
|
|
66
|
-
let n = !1;
|
|
67
|
-
o.then(() => {
|
|
68
|
-
n = !0;
|
|
69
|
-
});
|
|
70
|
-
const r = Date.now() + ae;
|
|
71
|
-
for (; Date.now() < r; ) {
|
|
72
|
-
const i = await I(e.userDataDir);
|
|
73
|
-
if (i) {
|
|
74
|
-
try {
|
|
75
|
-
T(
|
|
76
|
-
l(e.userDataDir, "aiui-browser.json"),
|
|
77
|
-
`${JSON.stringify({ pid: o.pid, startedAt: (/* @__PURE__ */ new Date()).toISOString() })}
|
|
78
|
-
`
|
|
79
|
-
);
|
|
80
|
-
} catch {
|
|
81
|
-
}
|
|
82
|
-
return i;
|
|
83
|
-
}
|
|
84
|
-
if (n)
|
|
85
|
-
throw new Error(
|
|
86
|
-
"the browser exited before exposing its DevTools endpoint — is another Chrome already running on this profile without a debug port? Close it and retry."
|
|
87
|
-
);
|
|
88
|
-
await ct(250);
|
|
89
|
-
}
|
|
90
|
-
throw new Error(
|
|
91
|
-
`the browser did not expose its DevTools endpoint within ${ae / 1e3}s`
|
|
92
|
-
);
|
|
93
|
-
}
|
|
94
|
-
async function Pe(e, t) {
|
|
95
|
-
const o = e.replace(/\/+$/, ""), n = await fetch(`${o}/json/new?${encodeURI(t)}`, {
|
|
96
|
-
method: "PUT",
|
|
97
|
-
signal: AbortSignal.timeout(3e3)
|
|
98
|
-
});
|
|
99
|
-
if (!n.ok)
|
|
100
|
-
throw new Error(`the browser refused to open the tab (${n.status} ${n.statusText})`);
|
|
101
|
-
}
|
|
102
|
-
function ct(e) {
|
|
103
|
-
return new Promise((t) => setTimeout(t, e));
|
|
104
|
-
}
|
|
105
|
-
const se = "config.json", ce = ["stable", "beta", "dev", "canary"], le = ["prompt", "auto", "off"], ue = ["attach", "launch"];
|
|
106
|
-
function De(e = process.cwd()) {
|
|
107
|
-
return {
|
|
108
|
-
user: l(q(void 0, { create: !1 }), se),
|
|
109
|
-
project: l(xe(e), se)
|
|
110
|
-
};
|
|
111
|
-
}
|
|
112
|
-
function N(e = process.cwd()) {
|
|
113
|
-
const t = De(e);
|
|
114
|
-
return lt(Y(t.user) ?? {}, Y(t.project) ?? {});
|
|
115
|
-
}
|
|
116
|
-
function lt(e, t) {
|
|
117
|
-
return {
|
|
118
|
-
claude: { ...e.claude, ...t.claude },
|
|
119
|
-
chrome: { ...e.chrome, ...t.chrome }
|
|
120
|
-
};
|
|
121
|
-
}
|
|
122
|
-
function Y(e) {
|
|
123
|
-
let t;
|
|
124
|
-
try {
|
|
125
|
-
t = P(e, "utf8");
|
|
126
|
-
} catch {
|
|
127
|
-
return;
|
|
128
|
-
}
|
|
129
|
-
let o;
|
|
130
|
-
try {
|
|
131
|
-
o = JSON.parse(t);
|
|
132
|
-
} catch (n) {
|
|
133
|
-
throw new Error(
|
|
134
|
-
`invalid JSON in ${e}: ${n instanceof Error ? n.message : String(n)}`
|
|
135
|
-
);
|
|
136
|
-
}
|
|
137
|
-
return ut(o, e);
|
|
138
|
-
}
|
|
139
|
-
function ut(e, t) {
|
|
140
|
-
const o = H(e, t, "the top level");
|
|
141
|
-
B(o, ["claude", "chrome"], t, "the top level");
|
|
142
|
-
const n = {};
|
|
143
|
-
if (o.claude !== void 0) {
|
|
144
|
-
const r = H(o.claude, t, '"claude"');
|
|
145
|
-
B(r, ["skipPermissions", "enterNudge"], t, '"claude"'), n.claude = de({
|
|
146
|
-
skipPermissions: w(
|
|
147
|
-
r.skipPermissions,
|
|
148
|
-
"boolean",
|
|
149
|
-
t,
|
|
150
|
-
"claude.skipPermissions"
|
|
151
|
-
),
|
|
152
|
-
enterNudge: w(r.enterNudge, "boolean", t, "claude.enterNudge")
|
|
153
|
-
});
|
|
154
|
-
}
|
|
155
|
-
if (o.chrome !== void 0) {
|
|
156
|
-
const r = H(o.chrome, t, '"chrome"');
|
|
157
|
-
B(
|
|
158
|
-
r,
|
|
159
|
-
[
|
|
160
|
-
"enabled",
|
|
161
|
-
"mode",
|
|
162
|
-
"browserUrl",
|
|
163
|
-
"debugPort",
|
|
164
|
-
"profile",
|
|
165
|
-
"dataDir",
|
|
166
|
-
"executablePath",
|
|
167
|
-
"channel",
|
|
168
|
-
"forTesting",
|
|
169
|
-
"headless",
|
|
170
|
-
"buildExtension"
|
|
171
|
-
],
|
|
172
|
-
t,
|
|
173
|
-
'"chrome"'
|
|
174
|
-
);
|
|
175
|
-
const i = w(r.channel, "string", t, "chrome.channel");
|
|
176
|
-
if (i !== void 0 && !ce.includes(i))
|
|
177
|
-
throw new Error(
|
|
178
|
-
`invalid chrome.channel "${i}" in ${t} — expected one of: ${ce.join(", ")}`
|
|
179
|
-
);
|
|
180
|
-
const a = w(r.forTesting, "string", t, "chrome.forTesting");
|
|
181
|
-
if (a !== void 0 && !le.includes(a))
|
|
182
|
-
throw new Error(
|
|
183
|
-
`invalid chrome.forTesting "${a}" in ${t} — expected one of: ${le.join(", ")}`
|
|
184
|
-
);
|
|
185
|
-
const s = w(r.mode, "string", t, "chrome.mode");
|
|
186
|
-
if (s !== void 0 && !ue.includes(s))
|
|
187
|
-
throw new Error(
|
|
188
|
-
`invalid chrome.mode "${s}" in ${t} — expected one of: ${ue.join(", ")}`
|
|
189
|
-
);
|
|
190
|
-
const c = w(r.browserUrl, "string", t, "chrome.browserUrl");
|
|
191
|
-
if (c !== void 0 && !dt(c))
|
|
192
|
-
throw new Error(
|
|
193
|
-
`invalid chrome.browserUrl "${c}" in ${t} — expected an http(s) URL like "http://127.0.0.1:9222"`
|
|
194
|
-
);
|
|
195
|
-
const u = w(r.debugPort, "number", t, "chrome.debugPort");
|
|
196
|
-
if (u !== void 0 && !(Number.isInteger(u) && u >= 0 && u <= 65535))
|
|
197
|
-
throw new Error(`invalid chrome.debugPort ${u} in ${t} — expected 0..65535`);
|
|
198
|
-
n.chrome = de({
|
|
199
|
-
enabled: w(r.enabled, "boolean", t, "chrome.enabled"),
|
|
200
|
-
mode: s,
|
|
201
|
-
browserUrl: c,
|
|
202
|
-
debugPort: u,
|
|
203
|
-
profile: w(r.profile, "string", t, "chrome.profile"),
|
|
204
|
-
dataDir: w(r.dataDir, "string", t, "chrome.dataDir"),
|
|
205
|
-
executablePath: w(r.executablePath, "string", t, "chrome.executablePath"),
|
|
206
|
-
channel: i,
|
|
207
|
-
forTesting: a,
|
|
208
|
-
headless: w(r.headless, "boolean", t, "chrome.headless"),
|
|
209
|
-
buildExtension: w(r.buildExtension, "boolean", t, "chrome.buildExtension")
|
|
210
|
-
});
|
|
211
|
-
}
|
|
212
|
-
return n;
|
|
213
|
-
}
|
|
214
|
-
function dt(e) {
|
|
215
|
-
try {
|
|
216
|
-
const t = new URL(e);
|
|
217
|
-
return t.protocol === "http:" || t.protocol === "https:";
|
|
218
|
-
} catch {
|
|
219
|
-
return !1;
|
|
220
|
-
}
|
|
221
|
-
}
|
|
222
|
-
function U(e) {
|
|
223
|
-
const t = De().user, o = Y(t) ?? {};
|
|
224
|
-
return e(o), k(S(t), { recursive: !0 }), T(t, `${JSON.stringify(o, null, 2)}
|
|
225
|
-
`), t;
|
|
226
|
-
}
|
|
227
|
-
function de(e) {
|
|
228
|
-
return Object.fromEntries(Object.entries(e).filter(([, t]) => t !== void 0));
|
|
229
|
-
}
|
|
230
|
-
function H(e, t, o) {
|
|
231
|
-
if (typeof e != "object" || e === null || Array.isArray(e))
|
|
232
|
-
throw new Error(`expected an object at ${o} of ${t}`);
|
|
233
|
-
return e;
|
|
234
|
-
}
|
|
235
|
-
function B(e, t, o, n) {
|
|
236
|
-
for (const r of Object.keys(e))
|
|
237
|
-
if (!t.includes(r))
|
|
238
|
-
throw new Error(
|
|
239
|
-
`unknown key "${r}" at ${n} of ${o} — known keys: ${t.join(", ")}`
|
|
240
|
-
);
|
|
241
|
-
}
|
|
242
|
-
function w(e, t, o, n) {
|
|
243
|
-
if (e !== void 0) {
|
|
244
|
-
if (typeof e !== t)
|
|
245
|
-
throw new Error(`expected a ${t} for ${n} in ${o}`);
|
|
246
|
-
return e;
|
|
247
|
-
}
|
|
248
|
-
}
|
|
249
|
-
async function G(e, t, o) {
|
|
250
|
-
const n = tt({ input: process.stdin, output: process.stderr });
|
|
2
|
+
import { Command as wt } from "commander";
|
|
3
|
+
import { join as d, resolve as C, delimiter as gt, dirname as bt } from "node:path";
|
|
4
|
+
import { cacheDir as F, packageRoot as V, runningFromSource as yt, isCi as ie, discoverSessionBrowser as U, openInSessionBrowser as R, sessionBrowserBinary as Oe, launchSessionBrowser as je, decideBrowserAction as vt } from "@habemus-papadum/aiui-util";
|
|
5
|
+
import { execa as T } from "execa";
|
|
6
|
+
import { existsSync as v, mkdirSync as G, writeFileSync as K, readFileSync as L, realpathSync as $t, readdirSync as Y, chmodSync as Ct, accessSync as kt, constants as xt, rmSync as Tt, lstatSync as It } from "node:fs";
|
|
7
|
+
import { detectBrowserPlatform as Ne, resolveBuildId as Ue, Browser as E, getInstalledBrowsers as Le, install as Et, uninstall as Pt } from "@puppeteer/browsers";
|
|
8
|
+
import { u as _, l as S, C as ve, m as Dt, d as ee, p as te, c as St, r as ne, a as Me, f as k, b as Re, e as At } from "./config-Cis6kCik.js";
|
|
9
|
+
import { createInterface as _t } from "node:readline/promises";
|
|
10
|
+
import u from "chalk";
|
|
11
|
+
import { projectCacheDir as Be, listMcpServers as M, selectMcpServer as He, agentsByPid as Fe, listClaudeAgents as Ve } from "@habemus-papadum/aiui-claude-channel";
|
|
12
|
+
import { homedir as se, networkInterfaces as Ge } from "node:os";
|
|
13
|
+
import { spawn as Ot } from "node:child_process";
|
|
14
|
+
import { Separator as oe, select as O, input as jt } from "@inquirer/prompts";
|
|
15
|
+
async function W(e, t, n) {
|
|
16
|
+
const o = _t({ input: process.stdin, output: process.stderr });
|
|
251
17
|
try {
|
|
252
18
|
const r = t.map(
|
|
253
|
-
(i) => ` ${
|
|
19
|
+
(i) => ` ${u.bold(`[${i.key === n ? i.key.toUpperCase() : i.key}]`)} ${i.label}`
|
|
254
20
|
).join(`
|
|
255
21
|
`);
|
|
256
22
|
for (; ; ) {
|
|
257
|
-
const
|
|
23
|
+
const s = (await o.question(`${u.cyan(e)}
|
|
258
24
|
${r}
|
|
259
25
|
> `)).trim().toLowerCase();
|
|
260
|
-
if (!
|
|
261
|
-
if (
|
|
262
|
-
return
|
|
26
|
+
if (!s) {
|
|
27
|
+
if (n !== void 0)
|
|
28
|
+
return n;
|
|
263
29
|
continue;
|
|
264
30
|
}
|
|
265
|
-
const
|
|
266
|
-
if (
|
|
267
|
-
return
|
|
31
|
+
const c = t.find((a) => a.key === s) ?? t.find((a) => a.label.toLowerCase().startsWith(s));
|
|
32
|
+
if (c)
|
|
33
|
+
return c.key;
|
|
268
34
|
}
|
|
269
35
|
} finally {
|
|
270
|
-
|
|
36
|
+
o.close();
|
|
271
37
|
}
|
|
272
38
|
}
|
|
273
|
-
function
|
|
274
|
-
console.error(`${
|
|
39
|
+
function b(e, t) {
|
|
40
|
+
console.error(`${u.bgRed.white.bold(" ERROR ")} ${u.red.bold(e)}`), t && console.error(u.dim(t));
|
|
275
41
|
}
|
|
276
|
-
function
|
|
277
|
-
console.error(`${
|
|
42
|
+
function $(e, t) {
|
|
43
|
+
console.error(`${u.bgYellow.black.bold(" WARN ")} ${u.yellow.bold(e)}`), t && console.error(u.dim(t));
|
|
278
44
|
}
|
|
279
|
-
function
|
|
280
|
-
console.error(`${
|
|
45
|
+
function w(e, t) {
|
|
46
|
+
console.error(`${u.bgCyan.black.bold(" NOTE ")} ${u.cyan(e)}`), t && console.error(u.dim(t));
|
|
281
47
|
}
|
|
282
|
-
const
|
|
48
|
+
const Ke = 1440 * 60 * 1e3, Nt = 4e3;
|
|
283
49
|
function A(e = !0) {
|
|
284
|
-
return
|
|
50
|
+
return F("chrome", { create: e });
|
|
285
51
|
}
|
|
286
|
-
const
|
|
287
|
-
function
|
|
52
|
+
const Ye = "update-state.json";
|
|
53
|
+
function q() {
|
|
288
54
|
try {
|
|
289
|
-
return JSON.parse(
|
|
55
|
+
return JSON.parse(L(d(A(!1), Ye), "utf8"));
|
|
290
56
|
} catch {
|
|
291
57
|
return {};
|
|
292
58
|
}
|
|
293
59
|
}
|
|
294
|
-
function
|
|
60
|
+
function z(e) {
|
|
295
61
|
const t = A();
|
|
296
|
-
|
|
62
|
+
G(t, { recursive: !0 }), K(d(t, Ye), `${JSON.stringify({ ...q(), ...e })}
|
|
297
63
|
`);
|
|
298
64
|
}
|
|
299
|
-
function
|
|
300
|
-
const
|
|
301
|
-
for (let r = 0; r < Math.max(
|
|
302
|
-
const i = (
|
|
65
|
+
function ae(e, t) {
|
|
66
|
+
const n = e.split(".").map(Number), o = t.split(".").map(Number);
|
|
67
|
+
for (let r = 0; r < Math.max(n.length, o.length); r++) {
|
|
68
|
+
const i = (n[r] ?? 0) - (o[r] ?? 0);
|
|
303
69
|
if (i)
|
|
304
70
|
return i < 0 ? -1 : 1;
|
|
305
71
|
}
|
|
306
72
|
return 0;
|
|
307
73
|
}
|
|
308
|
-
async function
|
|
74
|
+
async function ce() {
|
|
309
75
|
const e = A(!1);
|
|
310
|
-
if (!
|
|
76
|
+
if (!v(e))
|
|
311
77
|
return;
|
|
312
|
-
const
|
|
313
|
-
return
|
|
78
|
+
const o = (await Le({ cacheDir: e })).filter((r) => r.browser === E.CHROME).sort((r, i) => ae(r.buildId, i.buildId)).at(-1);
|
|
79
|
+
return o && { buildId: o.buildId, executablePath: o.executablePath };
|
|
314
80
|
}
|
|
315
|
-
async function
|
|
316
|
-
const { maxAgeMs: t =
|
|
317
|
-
if (r.latestBuildId && r.checkedAt &&
|
|
81
|
+
async function le(e = {}) {
|
|
82
|
+
const { maxAgeMs: t = Ke, timeoutMs: n = Nt, now: o = Date.now() } = e, r = q();
|
|
83
|
+
if (r.latestBuildId && r.checkedAt && o - r.checkedAt < t)
|
|
318
84
|
return r.latestBuildId;
|
|
319
|
-
const i =
|
|
85
|
+
const i = Ne();
|
|
320
86
|
if (i)
|
|
321
87
|
try {
|
|
322
|
-
const
|
|
323
|
-
|
|
324
|
-
|
|
88
|
+
const s = await Rt(
|
|
89
|
+
Ue(E.CHROME, i, "stable"),
|
|
90
|
+
n
|
|
325
91
|
);
|
|
326
|
-
return
|
|
92
|
+
return z({ checkedAt: o, latestBuildId: s }), s;
|
|
327
93
|
} catch {
|
|
328
94
|
return r.latestBuildId;
|
|
329
95
|
}
|
|
330
96
|
}
|
|
331
|
-
async function
|
|
332
|
-
const t = A(),
|
|
333
|
-
browser:
|
|
97
|
+
async function P(e) {
|
|
98
|
+
const t = A(), n = await Et({
|
|
99
|
+
browser: E.CHROME,
|
|
334
100
|
buildId: e,
|
|
335
101
|
cacheDir: t,
|
|
336
102
|
downloadProgressCallback: "default"
|
|
337
|
-
}),
|
|
338
|
-
(r) => r.browser ===
|
|
103
|
+
}), o = (await Le({ cacheDir: t })).filter(
|
|
104
|
+
(r) => r.browser === E.CHROME && r.buildId !== e
|
|
339
105
|
);
|
|
340
|
-
for (const r of
|
|
341
|
-
await
|
|
342
|
-
return { buildId: e, executablePath:
|
|
106
|
+
for (const r of o)
|
|
107
|
+
await Pt({ browser: E.CHROME, buildId: r.buildId, cacheDir: t });
|
|
108
|
+
return { buildId: e, executablePath: n.executablePath };
|
|
343
109
|
}
|
|
344
|
-
async function
|
|
345
|
-
const t =
|
|
110
|
+
async function Ut(e) {
|
|
111
|
+
const t = Ne();
|
|
346
112
|
if (!t)
|
|
347
113
|
throw new Error("could not detect a supported platform for Chrome for Testing");
|
|
348
|
-
const
|
|
349
|
-
|
|
350
|
-
const
|
|
351
|
-
if (
|
|
352
|
-
return e(`Chrome for Testing ${
|
|
114
|
+
const n = await Ue(E.CHROME, t, "stable");
|
|
115
|
+
z({ checkedAt: Date.now(), latestBuildId: n });
|
|
116
|
+
const o = await ce();
|
|
117
|
+
if (o && ae(o.buildId, n) >= 0)
|
|
118
|
+
return e(`Chrome for Testing ${o.buildId} is up to date`), { ...o, outcome: "current" };
|
|
353
119
|
e(
|
|
354
|
-
|
|
120
|
+
o ? `updating Chrome for Testing ${o.buildId} → ${n}…` : `installing Chrome for Testing ${n}…`
|
|
355
121
|
);
|
|
356
|
-
const r = await
|
|
357
|
-
return e(`Chrome for Testing ${
|
|
122
|
+
const r = await P(n);
|
|
123
|
+
return e(`Chrome for Testing ${n} installed at ${r.executablePath}`), { ...r, outcome: o ? "updated" : "installed" };
|
|
358
124
|
}
|
|
359
|
-
async function
|
|
360
|
-
const { mode: t, interactive:
|
|
361
|
-
if (t === "off" || !
|
|
125
|
+
async function We(e) {
|
|
126
|
+
const { mode: t, interactive: n, now: o = Date.now() } = e, r = await ce();
|
|
127
|
+
if (t === "off" || !n)
|
|
362
128
|
return r == null ? void 0 : r.executablePath;
|
|
363
129
|
if (!r)
|
|
364
|
-
return
|
|
365
|
-
const i = await
|
|
366
|
-
return !i ||
|
|
130
|
+
return Lt(t, o);
|
|
131
|
+
const i = await le({ now: o });
|
|
132
|
+
return !i || ae(i, r.buildId) <= 0 ? r.executablePath : Mt(t, r, i);
|
|
367
133
|
}
|
|
368
|
-
async function
|
|
369
|
-
const
|
|
370
|
-
if (!
|
|
134
|
+
async function Lt(e, t) {
|
|
135
|
+
const n = await le({ now: t });
|
|
136
|
+
if (!n)
|
|
371
137
|
return;
|
|
372
138
|
if (e === "auto")
|
|
373
|
-
return
|
|
374
|
-
const
|
|
375
|
-
if (
|
|
139
|
+
return w(`installing Chrome for Testing ${n} (chrome.forTesting: "auto")…`), (await P(n)).executablePath;
|
|
140
|
+
const o = q();
|
|
141
|
+
if (o.installDeclinedAt && t - o.installDeclinedAt < Ke)
|
|
376
142
|
return;
|
|
377
|
-
const r = await
|
|
378
|
-
`Chrome for Testing isn't installed. It's the recommended browser for aiui — version-pinned, separate from your real Chrome, and it auto-loads the aiui DevTools panel (branded Chrome can't). Download ${
|
|
143
|
+
const r = await W(
|
|
144
|
+
`Chrome for Testing isn't installed. It's the recommended browser for aiui — version-pinned, separate from your real Chrome, and it auto-loads the aiui DevTools panel (branded Chrome can't). Download ${n} (~160 MB) to ${A(!1)}?`,
|
|
379
145
|
[
|
|
380
146
|
{ key: "y", label: "yes, install it" },
|
|
381
147
|
{ key: "n", label: "not now — use the regular Chrome (asks again tomorrow)" },
|
|
@@ -384,279 +150,414 @@ async function mt(e, t) {
|
|
|
384
150
|
"y"
|
|
385
151
|
);
|
|
386
152
|
if (r === "y")
|
|
387
|
-
return (await
|
|
153
|
+
return (await P(n)).executablePath;
|
|
388
154
|
if (r === "never") {
|
|
389
|
-
const i =
|
|
390
|
-
|
|
155
|
+
const i = _((s) => {
|
|
156
|
+
s.chrome = { ...s.chrome, forTesting: "off" };
|
|
391
157
|
});
|
|
392
|
-
|
|
158
|
+
w(`wrote chrome.forTesting: "off" to ${i}`);
|
|
393
159
|
} else
|
|
394
|
-
|
|
160
|
+
z({ installDeclinedAt: t });
|
|
395
161
|
}
|
|
396
|
-
async function
|
|
162
|
+
async function Mt(e, t, n) {
|
|
397
163
|
if (e === "auto")
|
|
398
|
-
return
|
|
399
|
-
`updating Chrome for Testing ${t.buildId} → ${
|
|
400
|
-
), (await
|
|
401
|
-
if (
|
|
164
|
+
return w(
|
|
165
|
+
`updating Chrome for Testing ${t.buildId} → ${n} (chrome.forTesting: "auto")…`
|
|
166
|
+
), (await P(n)).executablePath;
|
|
167
|
+
if (q().skippedBuildId === n)
|
|
402
168
|
return t.executablePath;
|
|
403
|
-
switch (await
|
|
404
|
-
`Your Chrome for Testing (${t.buildId}) is out of date — latest stable is ${
|
|
169
|
+
switch (await W(
|
|
170
|
+
`Your Chrome for Testing (${t.buildId}) is out of date — latest stable is ${n}. Update?`,
|
|
405
171
|
[
|
|
406
172
|
{ key: "y", label: "yes, just this once" },
|
|
407
173
|
{ key: "a", label: 'automatically, now and from here on (writes chrome.forTesting: "auto")' },
|
|
408
174
|
{
|
|
409
175
|
key: "s",
|
|
410
|
-
label: `skip ${
|
|
176
|
+
label: `skip ${n} — keep ${t.buildId}, don't ask again for this version`
|
|
411
177
|
},
|
|
412
178
|
{ key: "never", label: 'never ask again (writes chrome.forTesting: "off")' }
|
|
413
179
|
],
|
|
414
180
|
"y"
|
|
415
181
|
)) {
|
|
416
182
|
case "y":
|
|
417
|
-
return (await
|
|
183
|
+
return (await P(n)).executablePath;
|
|
418
184
|
case "a": {
|
|
419
|
-
const r =
|
|
185
|
+
const r = _((i) => {
|
|
420
186
|
i.chrome = { ...i.chrome, forTesting: "auto" };
|
|
421
187
|
});
|
|
422
|
-
return
|
|
188
|
+
return w(`wrote chrome.forTesting: "auto" to ${r}`), (await P(n)).executablePath;
|
|
423
189
|
}
|
|
424
190
|
case "never": {
|
|
425
|
-
const r =
|
|
191
|
+
const r = _((i) => {
|
|
426
192
|
i.chrome = { ...i.chrome, forTesting: "off" };
|
|
427
193
|
});
|
|
428
|
-
return
|
|
194
|
+
return w(`wrote chrome.forTesting: "off" to ${r}`), t.executablePath;
|
|
429
195
|
}
|
|
430
196
|
default:
|
|
431
|
-
return
|
|
197
|
+
return z({ skippedBuildId: n }), t.executablePath;
|
|
432
198
|
}
|
|
433
199
|
}
|
|
434
|
-
async function
|
|
435
|
-
let
|
|
200
|
+
async function Rt(e, t) {
|
|
201
|
+
let n;
|
|
436
202
|
try {
|
|
437
203
|
return await Promise.race([
|
|
438
204
|
e,
|
|
439
|
-
new Promise((
|
|
440
|
-
|
|
205
|
+
new Promise((o, r) => {
|
|
206
|
+
n = setTimeout(() => r(new Error(`timed out after ${t}ms`)), t);
|
|
441
207
|
})
|
|
442
208
|
]);
|
|
443
209
|
} finally {
|
|
444
|
-
clearTimeout(
|
|
210
|
+
clearTimeout(n);
|
|
445
211
|
}
|
|
446
212
|
}
|
|
447
|
-
|
|
448
|
-
|
|
449
|
-
const t = e.split("/");
|
|
450
|
-
for (const o of gt.resolve.paths(e) ?? []) {
|
|
451
|
-
const n = l(o, ...t, "package.json");
|
|
452
|
-
if (b(n))
|
|
453
|
-
return S(n);
|
|
454
|
-
}
|
|
455
|
-
throw new Error(`could not locate the "${e}" package (is it installed?)`);
|
|
456
|
-
}
|
|
457
|
-
function X(e, t) {
|
|
458
|
-
const o = D(e), n = JSON.parse(P(l(o, "package.json"), "utf8")), r = typeof n.bin == "string" ? n.bin : bt(n.bin);
|
|
213
|
+
function J(e, t) {
|
|
214
|
+
const n = V(e), o = JSON.parse(L(d(n, "package.json"), "utf8")), r = typeof o.bin == "string" ? o.bin : Bt(o.bin);
|
|
459
215
|
if (!r)
|
|
460
216
|
throw new Error(
|
|
461
217
|
`package ${e} declares no bin`
|
|
462
218
|
);
|
|
463
|
-
if (
|
|
219
|
+
if (yt(n)) {
|
|
464
220
|
const i = r.replace(/^\.?\/?dist\//, "src/").replace(/\.js$/, ".ts");
|
|
465
|
-
return { command: process.execPath, args: ["--import", "tsx",
|
|
221
|
+
return { command: process.execPath, args: ["--import", "tsx", C(n, i)] };
|
|
466
222
|
}
|
|
467
|
-
return { command: process.execPath, args: [
|
|
223
|
+
return { command: process.execPath, args: [C(n, r)] };
|
|
468
224
|
}
|
|
469
|
-
function
|
|
225
|
+
function Bt(e) {
|
|
470
226
|
return e ? Object.values(e)[0] : void 0;
|
|
471
227
|
}
|
|
472
|
-
const
|
|
473
|
-
function
|
|
474
|
-
return e.noChrome ? !1 : e.chrome ? !0 : t.enabled === !1 ? !1 : !
|
|
228
|
+
const Ht = "chrome-devtools", Ft = "@habemus-papadum/aiui-intent-client", Vt = "default", Gt = /^[A-Za-z0-9][A-Za-z0-9._-]*$/;
|
|
229
|
+
function qe(e, t = {}, n = process.env) {
|
|
230
|
+
return e.noChrome ? !1 : e.chrome ? !0 : t.enabled === !1 ? !1 : !ie(n);
|
|
475
231
|
}
|
|
476
|
-
function
|
|
477
|
-
const t = e.CI;
|
|
478
|
-
return t !== void 0 && t !== "" && t !== "0" && t.toLowerCase() !== "false";
|
|
479
|
-
}
|
|
480
|
-
function $(e, t = {}, o = process.cwd()) {
|
|
232
|
+
function x(e, t = {}, n = process.cwd()) {
|
|
481
233
|
if (t.executablePath && t.channel)
|
|
482
234
|
throw new Error(
|
|
483
235
|
"config sets both chrome.executablePath and chrome.channel — they pick the browser two different ways; keep exactly one"
|
|
484
236
|
);
|
|
485
|
-
const
|
|
237
|
+
const o = e.chromeProfile !== void 0 || e.chromeDataDir !== void 0, r = e.chromeDataDir ?? (o ? void 0 : t.dataDir), i = e.chromeProfile ?? (o ? void 0 : t.profile);
|
|
486
238
|
return {
|
|
487
|
-
userDataDir:
|
|
239
|
+
userDataDir: ze({ dataDir: r, profile: i }, n),
|
|
488
240
|
// A configured endpoint means the browser is managed elsewhere (usually
|
|
489
241
|
// another machine) — that's always attach, whatever `mode` says.
|
|
490
242
|
mode: t.browserUrl ? "attach" : t.mode ?? "attach",
|
|
491
243
|
browserUrl: t.browserUrl,
|
|
492
244
|
debugPort: t.debugPort ?? 0,
|
|
493
|
-
executablePath: t.executablePath &&
|
|
245
|
+
executablePath: t.executablePath && C(n, t.executablePath),
|
|
494
246
|
channel: t.channel,
|
|
495
|
-
headless: t.headless ?? !1
|
|
496
|
-
buildExtension: t.buildExtension ?? !0
|
|
247
|
+
headless: t.headless ?? !1
|
|
497
248
|
};
|
|
498
249
|
}
|
|
499
|
-
function
|
|
250
|
+
function ze(e, t = process.cwd()) {
|
|
500
251
|
if (e.dataDir)
|
|
501
|
-
return
|
|
502
|
-
const
|
|
503
|
-
if (!
|
|
252
|
+
return C(t, e.dataDir);
|
|
253
|
+
const n = e.profile ?? Vt;
|
|
254
|
+
if (!Gt.test(n))
|
|
504
255
|
throw new Error(
|
|
505
|
-
`invalid chrome profile name "${
|
|
256
|
+
`invalid chrome profile name "${n}" — use letters, digits, ".", "_", "-" (or --aiui-chrome-data-dir for an arbitrary path)`
|
|
506
257
|
);
|
|
507
|
-
return
|
|
258
|
+
return d(Be(t), "chrome", n);
|
|
508
259
|
}
|
|
509
|
-
|
|
510
|
-
|
|
260
|
+
const Kt = "dist-ext";
|
|
261
|
+
function Yt() {
|
|
511
262
|
try {
|
|
512
|
-
e =
|
|
263
|
+
const e = $t(V(Ft));
|
|
264
|
+
return { root: e, outDir: d(e, Kt) };
|
|
513
265
|
} catch {
|
|
514
266
|
return;
|
|
515
267
|
}
|
|
516
|
-
return b(l(e, "js")) ? e : void 0;
|
|
517
268
|
}
|
|
518
|
-
|
|
519
|
-
|
|
520
|
-
|
|
521
|
-
|
|
522
|
-
|
|
523
|
-
|
|
524
|
-
|
|
525
|
-
|
|
526
|
-
|
|
527
|
-
|
|
528
|
-
|
|
529
|
-
|
|
530
|
-
all: !0
|
|
531
|
-
});
|
|
532
|
-
if (o.exitCode) {
|
|
533
|
-
_(
|
|
534
|
-
"aiui-devtools-extension failed to compile — the DevTools panel will be stale or missing",
|
|
535
|
-
o.all || o.message
|
|
536
|
-
);
|
|
537
|
-
return;
|
|
538
|
-
}
|
|
539
|
-
const n = l(e, "build-debug-ui.mjs");
|
|
540
|
-
if (!b(n))
|
|
541
|
-
return;
|
|
542
|
-
const r = await p(process.execPath, [n], {
|
|
543
|
-
cwd: e,
|
|
544
|
-
reject: !1,
|
|
545
|
-
all: !0
|
|
546
|
-
});
|
|
547
|
-
r.exitCode && _(
|
|
548
|
-
"aiui-devtools-extension debug-ui bundle failed — the Intent pane will be degraded",
|
|
549
|
-
r.all || r.message
|
|
269
|
+
function Wt(e) {
|
|
270
|
+
return e === void 0 ? { state: "absent" } : v(d(e.outDir, "manifest.json")) ? { state: "ready", dir: e.outDir } : { state: "unbuilt", root: e.root };
|
|
271
|
+
}
|
|
272
|
+
function j() {
|
|
273
|
+
return Wt(Yt());
|
|
274
|
+
}
|
|
275
|
+
function Je(e) {
|
|
276
|
+
e.state === "unbuilt" && w(
|
|
277
|
+
"the aiui intent client has no MV3 bundle yet, so this launch won't load it",
|
|
278
|
+
`Build it once: pnpm -C packages/aiui-intent-client build:ext
|
|
279
|
+
then relaunch — or load it into the RUNNING browser:
|
|
280
|
+
pnpm -C packages/aiui-intent-client ext`
|
|
550
281
|
);
|
|
551
282
|
}
|
|
552
|
-
function
|
|
553
|
-
if (!t || e.executablePath)
|
|
283
|
+
function Xe(e, t) {
|
|
284
|
+
if (!t.length || e.executablePath)
|
|
554
285
|
return;
|
|
555
|
-
const
|
|
556
|
-
if (!
|
|
557
|
-
|
|
558
|
-
"the aiui
|
|
286
|
+
const n = d(e.userDataDir, "aiui-extension-autoload-hint");
|
|
287
|
+
if (!v(n)) {
|
|
288
|
+
w(
|
|
289
|
+
"the aiui intent client can't auto-load into regular Chrome (≥ 137 ignores --load-extension)",
|
|
559
290
|
`Load it once in the launched Chrome — chrome://extensions → Developer mode → Load unpacked →
|
|
560
|
-
${t
|
|
291
|
+
${t.join(`
|
|
292
|
+
`)}
|
|
561
293
|
— and this profile remembers it. Or switch to Chrome for Testing (\`aiui chrome install\`),
|
|
562
294
|
which auto-loads it. This note won't repeat for this profile.`
|
|
563
295
|
);
|
|
564
296
|
try {
|
|
565
|
-
|
|
297
|
+
K(n, `${(/* @__PURE__ */ new Date()).toISOString()}
|
|
566
298
|
`);
|
|
567
299
|
} catch {
|
|
568
300
|
}
|
|
569
301
|
}
|
|
570
302
|
}
|
|
571
|
-
function
|
|
303
|
+
function Z(e) {
|
|
572
304
|
return {
|
|
573
305
|
command: "npx",
|
|
574
306
|
args: ["-y", "chrome-devtools-mcp@latest", "--browser-url", e]
|
|
575
307
|
};
|
|
576
308
|
}
|
|
577
|
-
function
|
|
578
|
-
const
|
|
309
|
+
function qt(e, t = []) {
|
|
310
|
+
const n = [
|
|
579
311
|
"-y",
|
|
580
312
|
"chrome-devtools-mcp@latest",
|
|
581
313
|
"--userDataDir",
|
|
582
314
|
e.userDataDir,
|
|
583
315
|
"--ignoreDefaultChromeArg=--disable-extensions"
|
|
584
316
|
];
|
|
585
|
-
return e.executablePath &&
|
|
586
|
-
}
|
|
587
|
-
const
|
|
588
|
-
|
|
589
|
-
|
|
590
|
-
|
|
591
|
-
|
|
592
|
-
|
|
317
|
+
return e.executablePath && n.push("--executablePath", e.executablePath), e.channel && n.push("--channel", e.channel), e.headless && n.push("--headless"), t.length && n.push(`--chromeArg=--load-extension=${t.join(",")}`), { command: "npx", args: n };
|
|
318
|
+
}
|
|
319
|
+
const N = "com.habemus_papadum.aiui", ue = "cdpbfpcelmifhagikjlfpgfipggcmdeg";
|
|
320
|
+
function Ze(e, t) {
|
|
321
|
+
if (e === "darwin") {
|
|
322
|
+
const n = d(t, "Library", "Application Support");
|
|
323
|
+
return [
|
|
324
|
+
d(n, "Google", "Chrome", "NativeMessagingHosts"),
|
|
325
|
+
d(n, "Chromium", "NativeMessagingHosts"),
|
|
326
|
+
d(n, "Microsoft Edge", "NativeMessagingHosts")
|
|
327
|
+
];
|
|
328
|
+
}
|
|
329
|
+
if (e === "linux")
|
|
330
|
+
return [
|
|
331
|
+
d(t, ".config", "google-chrome", "NativeMessagingHosts"),
|
|
332
|
+
d(t, ".config", "chromium", "NativeMessagingHosts"),
|
|
333
|
+
d(t, ".config", "microsoft-edge", "NativeMessagingHosts")
|
|
334
|
+
];
|
|
335
|
+
throw new Error(`aiui extension: unsupported platform ${e} (macOS/Linux only for now)`);
|
|
336
|
+
}
|
|
337
|
+
function zt(e, t, n) {
|
|
338
|
+
const o = (r) => `"${r.replace(/(["\\$`])/g, "\\$1")}"`;
|
|
339
|
+
return [
|
|
340
|
+
"#!/bin/sh",
|
|
341
|
+
"# aiui native-messaging host wrapper — generated by `aiui extension install-native-host`.",
|
|
342
|
+
"# Chrome spawns this with a minimal env and cwd /; everything below is absolute.",
|
|
343
|
+
`cd ${o(e)} || exit 1`,
|
|
344
|
+
`exec ${[t, ...n].map(o).join(" ")} native-host`,
|
|
345
|
+
""
|
|
346
|
+
].join(`
|
|
347
|
+
`);
|
|
348
|
+
}
|
|
349
|
+
const Jt = ["install-native-host", "status"];
|
|
350
|
+
async function Xt(e, t = {}) {
|
|
351
|
+
switch (e) {
|
|
352
|
+
case "install-native-host":
|
|
353
|
+
Qt(t);
|
|
354
|
+
return;
|
|
355
|
+
case "status":
|
|
356
|
+
en();
|
|
357
|
+
return;
|
|
358
|
+
case "dev":
|
|
359
|
+
case "reload":
|
|
360
|
+
b(
|
|
361
|
+
`aiui extension ${e} is gone — the frozen aiui-extension was deleted`,
|
|
362
|
+
`The intent client's extension is a static build:
|
|
363
|
+
pnpm -C packages/aiui-intent-client ext (build + load into the session browser)`
|
|
364
|
+
), process.exitCode = 1;
|
|
365
|
+
return;
|
|
366
|
+
default:
|
|
367
|
+
throw new Error(`aiui extension: unknown action "${e}" (${Jt.join(" | ")})`);
|
|
368
|
+
}
|
|
369
|
+
}
|
|
370
|
+
function Qe() {
|
|
371
|
+
return d(F("native-host", { create: !0 }), "aiui-native-host.sh");
|
|
372
|
+
}
|
|
373
|
+
function et(e) {
|
|
374
|
+
const t = J("@habemus-papadum/aiui"), n = V("@habemus-papadum/aiui"), o = Qe();
|
|
375
|
+
tt(o, zt(n, t.command, t.args)), Ct(o, 493);
|
|
376
|
+
const r = {
|
|
377
|
+
name: N,
|
|
378
|
+
description: "aiui native-messaging host: channel discovery for the aiui intent client",
|
|
379
|
+
path: o,
|
|
380
|
+
type: "stdio",
|
|
381
|
+
// The host answers one question — "which channels are up?" — for the
|
|
382
|
+
// intent client's cold start. An overridden id rides alongside the stable
|
|
383
|
+
// one so a custom build never locks the shipped client out.
|
|
384
|
+
allowed_origins: [
|
|
385
|
+
.../* @__PURE__ */ new Set([
|
|
386
|
+
`chrome-extension://${e}/`,
|
|
387
|
+
`chrome-extension://${ue}/`
|
|
388
|
+
])
|
|
389
|
+
]
|
|
390
|
+
};
|
|
391
|
+
return { wrapper: o, body: `${JSON.stringify(r, null, 2)}
|
|
392
|
+
` };
|
|
393
|
+
}
|
|
394
|
+
function tt(e, t) {
|
|
395
|
+
try {
|
|
396
|
+
if (L(e, "utf8") === t)
|
|
397
|
+
return !1;
|
|
398
|
+
} catch {
|
|
399
|
+
}
|
|
400
|
+
return K(e, t), !0;
|
|
401
|
+
}
|
|
402
|
+
function Zt(e, t = {}) {
|
|
403
|
+
const { body: n } = et(t.extensionId ?? ue), o = d(e, "NativeMessagingHosts");
|
|
404
|
+
G(o, { recursive: !0 }), tt(d(o, `${N}.json`), n);
|
|
405
|
+
}
|
|
406
|
+
function B(e, t, n) {
|
|
407
|
+
if (t)
|
|
408
|
+
try {
|
|
409
|
+
Zt(e);
|
|
410
|
+
} catch (o) {
|
|
411
|
+
n(
|
|
412
|
+
"couldn't install the native-messaging host into the browser profile — the intent extension will need a manually typed port",
|
|
413
|
+
o instanceof Error ? o.message : String(o)
|
|
414
|
+
);
|
|
415
|
+
}
|
|
416
|
+
}
|
|
417
|
+
function Qt(e) {
|
|
418
|
+
const t = e.extensionId ?? ue, { wrapper: n, body: o } = et(t);
|
|
419
|
+
process.stdout.write(`wrote ${n}
|
|
420
|
+
`);
|
|
421
|
+
for (const r of Ze(process.platform, se())) {
|
|
422
|
+
G(r, { recursive: !0 });
|
|
423
|
+
const i = d(r, `${N}.json`);
|
|
424
|
+
K(i, o), process.stdout.write(`wrote ${i}
|
|
425
|
+
`);
|
|
426
|
+
}
|
|
427
|
+
process.stdout.write(
|
|
428
|
+
`native host installed for extension ${t}.
|
|
429
|
+
No browser restart needed; reload the extension if it was already running.
|
|
430
|
+
(Session browsers launched by aiui get the manifest in their own profile
|
|
431
|
+
automatically — this global install is for browsers aiui does not manage.)
|
|
432
|
+
`
|
|
433
|
+
);
|
|
434
|
+
}
|
|
435
|
+
function en() {
|
|
436
|
+
const e = Qe();
|
|
437
|
+
process.stdout.write(`wrapper: ${e} ${v(e) ? "(present)" : "(MISSING)"}
|
|
438
|
+
`);
|
|
439
|
+
for (const o of Ze(process.platform, se()))
|
|
440
|
+
$e(d(o, `${N}.json`));
|
|
441
|
+
const t = d(process.cwd(), ".aiui-cache", "chrome");
|
|
442
|
+
let n = [];
|
|
443
|
+
try {
|
|
444
|
+
n = Y(t, { withFileTypes: !0 }).filter((o) => o.isDirectory()).map((o) => o.name);
|
|
445
|
+
} catch {
|
|
446
|
+
}
|
|
447
|
+
for (const o of n)
|
|
448
|
+
$e(d(t, o, "NativeMessagingHosts", `${N}.json`));
|
|
449
|
+
}
|
|
450
|
+
function $e(e) {
|
|
451
|
+
var t;
|
|
452
|
+
if (!v(e)) {
|
|
453
|
+
process.stdout.write(`absent: ${e}
|
|
454
|
+
`);
|
|
455
|
+
return;
|
|
456
|
+
}
|
|
457
|
+
try {
|
|
458
|
+
const n = JSON.parse(L(e, "utf8"));
|
|
459
|
+
process.stdout.write(`present: ${e} → ${(t = n.allowed_origins) == null ? void 0 : t.join(", ")}
|
|
460
|
+
`);
|
|
461
|
+
} catch {
|
|
462
|
+
process.stdout.write(`present: ${e} (unparseable)
|
|
463
|
+
`);
|
|
464
|
+
}
|
|
465
|
+
}
|
|
466
|
+
const tn = 9222;
|
|
467
|
+
async function nn(e) {
|
|
468
|
+
const n = { ...S().chrome };
|
|
469
|
+
if (n.browserUrl) {
|
|
470
|
+
w(
|
|
471
|
+
`config pins chrome.browserUrl to ${n.browserUrl} — the browser is managed elsewhere`,
|
|
593
472
|
"Run `aiui browser` on the machine that should host it (and drop browserUrl there)."
|
|
594
473
|
);
|
|
595
474
|
return;
|
|
596
475
|
}
|
|
597
|
-
let
|
|
476
|
+
let o, r;
|
|
598
477
|
try {
|
|
599
|
-
|
|
600
|
-
} catch (
|
|
601
|
-
|
|
478
|
+
o = Ce(e.remotePort, "--remote-port") ?? tn, r = Ce(e.port, "--port");
|
|
479
|
+
} catch (a) {
|
|
480
|
+
b(a instanceof Error ? a.message : String(a)), process.exitCode = 1;
|
|
602
481
|
return;
|
|
603
482
|
}
|
|
604
|
-
let r = o;
|
|
605
483
|
const i = {
|
|
606
484
|
chromeProfile: e.tunnel ? void 0 : e.profile,
|
|
607
|
-
chromeDataDir: e.dataDir ?? (e.tunnel ?
|
|
485
|
+
chromeDataDir: e.dataDir ?? (e.tunnel ? on(e.tunnel, e.profile) : void 0)
|
|
608
486
|
};
|
|
609
|
-
let
|
|
610
|
-
|
|
611
|
-
|
|
487
|
+
let s = x(i, n);
|
|
488
|
+
r !== void 0 && (s = { ...s, debugPort: r });
|
|
489
|
+
let c = await U(s.userDataDir);
|
|
490
|
+
if (c)
|
|
491
|
+
B(
|
|
492
|
+
s.userDataDir,
|
|
493
|
+
j().state === "ready",
|
|
494
|
+
w
|
|
495
|
+
), ke("session browser already running", s, c), e.open && (await R(c.browserUrl, e.open), console.log(`opened ${e.open}`));
|
|
612
496
|
else {
|
|
613
|
-
const
|
|
614
|
-
if (!r.executablePath && !r.channel) {
|
|
615
|
-
const h = await Ie({ mode: r.forTesting ?? "prompt", interactive: c });
|
|
616
|
-
h && (r = { ...r, executablePath: h }, a = he($(i, r), e));
|
|
617
|
-
}
|
|
618
|
-
a.buildExtension && await Q();
|
|
619
|
-
const u = M();
|
|
620
|
-
c && Ue(a, u);
|
|
621
|
-
let f;
|
|
497
|
+
const a = !!process.stdin.isTTY && !!process.stdout.isTTY && !ie();
|
|
622
498
|
try {
|
|
623
|
-
|
|
624
|
-
|
|
625
|
-
|
|
626
|
-
|
|
627
|
-
|
|
628
|
-
|
|
629
|
-
), process.exitCode = 1;
|
|
630
|
-
return;
|
|
631
|
-
}
|
|
632
|
-
try {
|
|
633
|
-
s = await $e({
|
|
634
|
-
binary: f,
|
|
635
|
-
userDataDir: a.userDataDir,
|
|
636
|
-
debugPort: a.debugPort,
|
|
637
|
-
extensionDir: u,
|
|
638
|
-
headless: a.headless || e.headless,
|
|
499
|
+
const l = await nt({
|
|
500
|
+
flags: i,
|
|
501
|
+
config: n,
|
|
502
|
+
interactive: a,
|
|
503
|
+
debugPort: r,
|
|
504
|
+
headless: e.headless,
|
|
639
505
|
startUrl: e.open
|
|
640
506
|
});
|
|
641
|
-
|
|
642
|
-
|
|
507
|
+
c = l.session, s = l.settings;
|
|
508
|
+
} catch (l) {
|
|
509
|
+
b(
|
|
643
510
|
"the session browser failed to start",
|
|
644
|
-
|
|
511
|
+
l instanceof Error ? l.message : String(l)
|
|
645
512
|
), process.exitCode = 1;
|
|
646
513
|
return;
|
|
647
514
|
}
|
|
648
|
-
|
|
515
|
+
ke("session browser started", s, c);
|
|
516
|
+
}
|
|
517
|
+
e.tunnel ? await an(e.tunnel, o, c.port) : cn(c, o);
|
|
518
|
+
}
|
|
519
|
+
async function nt(e) {
|
|
520
|
+
let t = e.config ?? {};
|
|
521
|
+
const n = e.flags ?? {}, o = () => {
|
|
522
|
+
const l = x(n, t);
|
|
523
|
+
return e.debugPort === void 0 ? l : { ...l, debugPort: e.debugPort };
|
|
524
|
+
};
|
|
525
|
+
let r = o();
|
|
526
|
+
if (!t.executablePath && !t.channel) {
|
|
527
|
+
const l = await We({
|
|
528
|
+
mode: t.forTesting ?? "prompt",
|
|
529
|
+
interactive: e.interactive
|
|
530
|
+
});
|
|
531
|
+
l && (t = { ...t, executablePath: l }, r = o());
|
|
532
|
+
}
|
|
533
|
+
const i = j(), s = i.state === "ready" ? [i.dir] : [];
|
|
534
|
+
B(r.userDataDir, i.state === "ready", w), e.interactive && (Xe(r, s), Je(i));
|
|
535
|
+
let c;
|
|
536
|
+
try {
|
|
537
|
+
c = Oe(r);
|
|
538
|
+
} catch (l) {
|
|
539
|
+
throw new Error(
|
|
540
|
+
`${l instanceof Error ? l.message : String(l)}
|
|
541
|
+
Install Chrome for Testing with \`aiui chrome install\`, or set chrome.executablePath.`
|
|
542
|
+
);
|
|
649
543
|
}
|
|
650
|
-
|
|
544
|
+
return { session: await je({
|
|
545
|
+
binary: c,
|
|
546
|
+
userDataDir: r.userDataDir,
|
|
547
|
+
debugPort: r.debugPort,
|
|
548
|
+
extensionDirs: s,
|
|
549
|
+
headless: r.headless || e.headless,
|
|
550
|
+
startUrl: e.startUrl
|
|
551
|
+
}), settings: r };
|
|
651
552
|
}
|
|
652
|
-
function
|
|
653
|
-
const
|
|
654
|
-
return
|
|
553
|
+
function on(e, t) {
|
|
554
|
+
const n = t ?? rn(e);
|
|
555
|
+
return d(F("browser-profiles", { create: !1 }), n);
|
|
655
556
|
}
|
|
656
|
-
function
|
|
557
|
+
function rn(e) {
|
|
657
558
|
return (e.includes("@") ? e.slice(e.indexOf("@") + 1) : e).replace(/[^A-Za-z0-9._-]/g, "-") || "remote";
|
|
658
559
|
}
|
|
659
|
-
function
|
|
560
|
+
function sn(e, t, n) {
|
|
660
561
|
return [
|
|
661
562
|
// No remote command — the connection exists only to carry the forward...
|
|
662
563
|
"-N",
|
|
@@ -665,114 +566,97 @@ function kt(e, t, o) {
|
|
|
665
566
|
"-o",
|
|
666
567
|
"ExitOnForwardFailure=yes",
|
|
667
568
|
"-R",
|
|
668
|
-
`${t}:localhost:${
|
|
569
|
+
`${t}:localhost:${n}`,
|
|
669
570
|
e
|
|
670
571
|
];
|
|
671
572
|
}
|
|
672
|
-
function
|
|
573
|
+
function ot(e) {
|
|
673
574
|
return `aiui claude --aiui-browser-url http://127.0.0.1:${e}`;
|
|
674
575
|
}
|
|
675
|
-
async function
|
|
576
|
+
async function an(e, t, n) {
|
|
676
577
|
console.log(
|
|
677
578
|
`
|
|
678
|
-
tunneling ${e}:${t} → localhost:${
|
|
579
|
+
tunneling ${e}:${t} → localhost:${n} — on ${e}, run:
|
|
679
580
|
|
|
680
|
-
${
|
|
581
|
+
${ot(t)}
|
|
681
582
|
|
|
682
583
|
(Ctrl-C closes the tunnel; the browser stays running.)`
|
|
683
584
|
);
|
|
684
|
-
const
|
|
585
|
+
const o = await T("ssh", sn(e, t, n), {
|
|
685
586
|
stdio: "inherit",
|
|
686
587
|
reject: !1
|
|
687
588
|
});
|
|
688
|
-
|
|
689
|
-
`the ssh tunnel to ${e} exited (code ${
|
|
589
|
+
o.failed && !o.isTerminated && (b(
|
|
590
|
+
`the ssh tunnel to ${e} exited (code ${o.exitCode})`,
|
|
690
591
|
"A taken remote port exits immediately (ExitOnForwardFailure) — try another --remote-port. The browser is still running; rerun `aiui browser --tunnel …` to reconnect."
|
|
691
592
|
), process.exitCode = 1);
|
|
692
593
|
}
|
|
693
|
-
function
|
|
594
|
+
function Ce(e, t) {
|
|
694
595
|
if (e === void 0)
|
|
695
596
|
return;
|
|
696
|
-
const
|
|
697
|
-
if (!(Number.isInteger(
|
|
597
|
+
const n = Number(e);
|
|
598
|
+
if (!(Number.isInteger(n) && n >= 0 && n <= 65535))
|
|
698
599
|
throw new Error(`invalid ${t} ${e} — expected 0..65535`);
|
|
699
|
-
return
|
|
700
|
-
}
|
|
701
|
-
function he(e, t) {
|
|
702
|
-
const o = Ne(t.port, "--port");
|
|
703
|
-
return o === void 0 ? e : { ...e, debugPort: o };
|
|
600
|
+
return n;
|
|
704
601
|
}
|
|
705
|
-
function
|
|
706
|
-
console.log(e), console.log(` profile: ${t.userDataDir}`), console.log(` debug endpoint: ${
|
|
602
|
+
function ke(e, t, n) {
|
|
603
|
+
console.log(e), console.log(` profile: ${t.userDataDir}`), console.log(` debug endpoint: ${n.browserUrl}`);
|
|
707
604
|
}
|
|
708
|
-
function
|
|
605
|
+
function cn(e, t) {
|
|
709
606
|
console.log(
|
|
710
607
|
`
|
|
711
608
|
An \`aiui claude\` in this profile's project attaches automatically. For a *remote*
|
|
712
609
|
session, rerun with \`--tunnel <[user@]host>\` — or do it by hand:
|
|
713
610
|
ssh -N -o ExitOnForwardFailure=yes -R ${t}:localhost:${e.port} <host>
|
|
714
|
-
then, on the remote: ${
|
|
611
|
+
then, on the remote: ${ot(t)}`
|
|
715
612
|
);
|
|
716
613
|
}
|
|
717
|
-
async function
|
|
718
|
-
var i,
|
|
719
|
-
const
|
|
614
|
+
async function ln(e, t) {
|
|
615
|
+
var i, s;
|
|
616
|
+
const n = S(), o = x(
|
|
720
617
|
{ chromeProfile: t.profile, chromeDataDir: t.dataDir },
|
|
721
|
-
|
|
722
|
-
), r = ((i =
|
|
618
|
+
n.chrome ?? {}
|
|
619
|
+
), r = ((i = n.chrome) == null ? void 0 : i.browserUrl) ?? ((s = await U(o.userDataDir)) == null ? void 0 : s.browserUrl);
|
|
723
620
|
if (!r) {
|
|
724
|
-
|
|
621
|
+
b(
|
|
725
622
|
"no session browser is running for this profile",
|
|
726
|
-
`Start one with \`aiui browser\` (profile: ${
|
|
623
|
+
`Start one with \`aiui browser\` (profile: ${o.userDataDir}).`
|
|
727
624
|
), process.exitCode = 1;
|
|
728
625
|
return;
|
|
729
626
|
}
|
|
730
627
|
try {
|
|
731
|
-
await
|
|
732
|
-
} catch (
|
|
733
|
-
|
|
628
|
+
await R(r, e), console.log(`opened ${e}`);
|
|
629
|
+
} catch (c) {
|
|
630
|
+
b(`couldn't open ${e}`, c instanceof Error ? c.message : String(c)), process.exitCode = 1;
|
|
734
631
|
}
|
|
735
632
|
}
|
|
736
|
-
async function
|
|
633
|
+
async function un(e) {
|
|
737
634
|
const [t] = e;
|
|
738
635
|
switch (t) {
|
|
739
636
|
case "install":
|
|
740
637
|
case "update":
|
|
741
|
-
await
|
|
638
|
+
await Ut((n) => console.log(n));
|
|
742
639
|
return;
|
|
743
640
|
case "status":
|
|
744
|
-
await
|
|
745
|
-
return;
|
|
746
|
-
case "extension": {
|
|
747
|
-
await Q();
|
|
748
|
-
const o = M();
|
|
749
|
-
if (!o) {
|
|
750
|
-
m(
|
|
751
|
-
"the aiui-devtools-extension is not available in this install",
|
|
752
|
-
"In a dev checkout, build it first: pnpm --filter @habemus-papadum/aiui-devtools-extension build"
|
|
753
|
-
), process.exitCode = 1;
|
|
754
|
-
return;
|
|
755
|
-
}
|
|
756
|
-
console.log(o);
|
|
641
|
+
await dn();
|
|
757
642
|
return;
|
|
758
|
-
}
|
|
759
643
|
default:
|
|
760
|
-
|
|
644
|
+
b(
|
|
761
645
|
t ? `unknown aiui chrome action: ${t}` : "aiui chrome needs an action",
|
|
762
|
-
"Usage: aiui chrome <install | update | status
|
|
646
|
+
"Usage: aiui chrome <install | update | status>"
|
|
763
647
|
), process.exitCode = 1;
|
|
764
648
|
return;
|
|
765
649
|
}
|
|
766
650
|
}
|
|
767
|
-
async function
|
|
768
|
-
const t =
|
|
769
|
-
if (console.log("Chrome for Testing (managed):"),
|
|
770
|
-
const
|
|
771
|
-
console.log(` installed ${
|
|
651
|
+
async function dn() {
|
|
652
|
+
const t = S().chrome ?? {}, n = { chrome: !1, noChrome: !1 }, o = await ce(), r = await le();
|
|
653
|
+
if (console.log("Chrome for Testing (managed):"), o) {
|
|
654
|
+
const m = r === void 0 ? "(latest stable unknown — offline?)" : r === o.buildId ? "(latest stable)" : `(latest stable is ${r} — run \`aiui chrome update\`)`;
|
|
655
|
+
console.log(` installed ${o.buildId} ${m}`), console.log(` ${o.executablePath}`);
|
|
772
656
|
} else
|
|
773
657
|
console.log(" not installed — `aiui chrome install` (recommended; auto-loads the panel)");
|
|
774
658
|
if (console.log(` startup checks (chrome.forTesting): ${t.forTesting ?? "prompt"}`), console.log(`
|
|
775
|
-
This directory would launch:`), !
|
|
659
|
+
This directory would launch:`), !qe(n, t)) {
|
|
776
660
|
console.log(" nothing — the Chrome DevTools MCP is disabled here");
|
|
777
661
|
return;
|
|
778
662
|
}
|
|
@@ -781,181 +665,324 @@ This directory would launch:`), !Oe(o, t)) {
|
|
|
781
665
|
return;
|
|
782
666
|
}
|
|
783
667
|
const i = { ...t };
|
|
784
|
-
!i.executablePath && !i.channel &&
|
|
785
|
-
const
|
|
786
|
-
console.log(` connection: ${
|
|
787
|
-
const
|
|
788
|
-
console.log(` browser: ${
|
|
789
|
-
const
|
|
790
|
-
if (
|
|
791
|
-
const
|
|
792
|
-
|
|
668
|
+
!i.executablePath && !i.channel && o && (i.executablePath = o.executablePath);
|
|
669
|
+
const s = x({}, i), c = await U(s.userDataDir), a = s.mode === "attach" ? c ? `attach to the running session browser at ${c.browserUrl}` : "attach — a session browser starts with the next interactive launch (or `aiui browser`)" : "launch — chrome-devtools-mcp starts a private browser on the agent's first tool use";
|
|
670
|
+
console.log(` connection: ${a}`);
|
|
671
|
+
const l = s.executablePath ? s.executablePath === (o == null ? void 0 : o.executablePath) ? `Chrome for Testing ${o.buildId}` : s.executablePath : s.channel ? `installed Chrome (${s.channel} channel)` : "installed Chrome (stable)";
|
|
672
|
+
console.log(` browser: ${l}${s.headless ? " — headless" : ""}`), console.log(` user data dir: ${s.userDataDir}`);
|
|
673
|
+
const p = d(ze({}, process.cwd()), "..");
|
|
674
|
+
if (v(p)) {
|
|
675
|
+
const m = Y(p, { withFileTypes: !0 }).filter((g) => g.isDirectory()).map((g) => g.name);
|
|
676
|
+
m.length && console.log(` profiles here: ${m.join(", ")}`);
|
|
793
677
|
}
|
|
794
678
|
console.log(`
|
|
795
|
-
aiui
|
|
796
|
-
const
|
|
797
|
-
|
|
798
|
-
|
|
799
|
-
|
|
679
|
+
aiui intent client (the extension launches auto-load):`);
|
|
680
|
+
const f = j();
|
|
681
|
+
switch (f.state) {
|
|
682
|
+
case "absent":
|
|
683
|
+
console.log(" not available in this install (aiui-intent-client is not resolvable)");
|
|
684
|
+
break;
|
|
685
|
+
case "unbuilt":
|
|
686
|
+
console.log(
|
|
687
|
+
` no MV3 bundle yet (${f.root})
|
|
688
|
+
build it: pnpm -C packages/aiui-intent-client build:ext
|
|
689
|
+
build + load into the running browser: pnpm -C packages/aiui-intent-client ext`
|
|
690
|
+
);
|
|
691
|
+
break;
|
|
692
|
+
case "ready":
|
|
693
|
+
console.log(` ${f.dir}`), hn(s.executablePath);
|
|
694
|
+
break;
|
|
800
695
|
}
|
|
801
|
-
|
|
696
|
+
}
|
|
697
|
+
function hn(e) {
|
|
698
|
+
e ? console.log(" auto-loads via --load-extension (honored by Chrome for Testing/Chromium)") : (console.log(" can NOT auto-load into branded Chrome ≥ 137 — load it unpacked once"), console.log(
|
|
802
699
|
" (chrome://extensions → Developer mode → Load unpacked), or `aiui chrome install`"
|
|
803
700
|
));
|
|
804
701
|
}
|
|
805
|
-
const
|
|
806
|
-
function
|
|
702
|
+
const fn = "--aiui-";
|
|
703
|
+
function rt(e) {
|
|
807
704
|
if (e.includes("--help") || e.includes("-h"))
|
|
808
705
|
return "help";
|
|
809
706
|
if (e.includes("--version") || e.includes("-v"))
|
|
810
707
|
return "version";
|
|
811
708
|
}
|
|
812
|
-
function
|
|
813
|
-
let t,
|
|
814
|
-
const
|
|
815
|
-
for (let
|
|
816
|
-
const
|
|
817
|
-
if (!
|
|
818
|
-
|
|
709
|
+
function de(e) {
|
|
710
|
+
let t, n, o = !1, r = !1, i = !1, s = !1, c, a, l, p;
|
|
711
|
+
const f = [];
|
|
712
|
+
for (let m = 0; m < e.length; m++) {
|
|
713
|
+
const g = e[m];
|
|
714
|
+
if (!g.startsWith(fn)) {
|
|
715
|
+
f.push(g);
|
|
819
716
|
continue;
|
|
820
717
|
}
|
|
821
|
-
const
|
|
822
|
-
let
|
|
823
|
-
switch (
|
|
718
|
+
const y = g.indexOf("="), I = y === -1 ? g : g.slice(0, y);
|
|
719
|
+
let h = y === -1 ? void 0 : g.slice(y + 1);
|
|
720
|
+
switch (I) {
|
|
824
721
|
case "--aiui-tag": {
|
|
825
|
-
if (
|
|
722
|
+
if (h === void 0 && (h = e[++m]), !h)
|
|
826
723
|
throw new Error("--aiui-tag requires a non-empty value");
|
|
827
|
-
t =
|
|
724
|
+
t = h;
|
|
828
725
|
break;
|
|
829
726
|
}
|
|
830
727
|
case "--aiui-mcp": {
|
|
831
|
-
if (
|
|
728
|
+
if (h === void 0 && (h = e[++m]), !h)
|
|
832
729
|
throw new Error("--aiui-mcp requires a non-empty value");
|
|
833
|
-
|
|
730
|
+
n = h;
|
|
834
731
|
break;
|
|
835
732
|
}
|
|
836
733
|
case "--aiui-chrome": {
|
|
837
|
-
if (
|
|
734
|
+
if (h !== void 0)
|
|
838
735
|
throw new Error("--aiui-chrome takes no value");
|
|
839
|
-
|
|
736
|
+
o = !0;
|
|
840
737
|
break;
|
|
841
738
|
}
|
|
842
739
|
case "--aiui-no-chrome": {
|
|
843
|
-
if (
|
|
740
|
+
if (h !== void 0)
|
|
844
741
|
throw new Error("--aiui-no-chrome takes no value");
|
|
845
742
|
r = !0;
|
|
846
743
|
break;
|
|
847
744
|
}
|
|
745
|
+
case "--aiui-browser": {
|
|
746
|
+
if (h !== void 0)
|
|
747
|
+
throw new Error("--aiui-browser takes no value");
|
|
748
|
+
i = !0;
|
|
749
|
+
break;
|
|
750
|
+
}
|
|
751
|
+
case "--aiui-no-browser": {
|
|
752
|
+
if (h !== void 0)
|
|
753
|
+
throw new Error("--aiui-no-browser takes no value");
|
|
754
|
+
s = !0;
|
|
755
|
+
break;
|
|
756
|
+
}
|
|
848
757
|
case "--aiui-chrome-profile": {
|
|
849
|
-
if (
|
|
758
|
+
if (h === void 0 && (h = e[++m]), !h)
|
|
850
759
|
throw new Error("--aiui-chrome-profile requires a non-empty value");
|
|
851
|
-
|
|
760
|
+
c = h;
|
|
852
761
|
break;
|
|
853
762
|
}
|
|
854
763
|
case "--aiui-chrome-data-dir": {
|
|
855
|
-
if (
|
|
764
|
+
if (h === void 0 && (h = e[++m]), !h)
|
|
856
765
|
throw new Error("--aiui-chrome-data-dir requires a non-empty value");
|
|
857
|
-
a =
|
|
766
|
+
a = h;
|
|
858
767
|
break;
|
|
859
768
|
}
|
|
860
769
|
case "--aiui-browser-url": {
|
|
861
|
-
if (
|
|
770
|
+
if (h === void 0 && (h = e[++m]), !h)
|
|
862
771
|
throw new Error("--aiui-browser-url requires a non-empty value");
|
|
863
|
-
|
|
772
|
+
l = h;
|
|
773
|
+
break;
|
|
774
|
+
}
|
|
775
|
+
case "--aiui-bind": {
|
|
776
|
+
if (h === void 0 && (h = e[++m]), !h || !ve.includes(h))
|
|
777
|
+
throw new Error(`--aiui-bind requires one of: ${ve.join(", ")}`);
|
|
778
|
+
p = h;
|
|
864
779
|
break;
|
|
865
780
|
}
|
|
866
781
|
default:
|
|
867
|
-
throw new Error(`unknown aiui option: ${
|
|
782
|
+
throw new Error(`unknown aiui option: ${I}`);
|
|
868
783
|
}
|
|
869
784
|
}
|
|
870
|
-
if (
|
|
785
|
+
if (o && r)
|
|
871
786
|
throw new Error("--aiui-chrome and --aiui-no-chrome are mutually exclusive");
|
|
872
|
-
if (i
|
|
787
|
+
if (i && s)
|
|
788
|
+
throw new Error("--aiui-browser and --aiui-no-browser are mutually exclusive");
|
|
789
|
+
if (c !== void 0 && a !== void 0)
|
|
873
790
|
throw new Error("--aiui-chrome-profile and --aiui-chrome-data-dir are mutually exclusive");
|
|
874
|
-
if (
|
|
791
|
+
if (l !== void 0 && (c !== void 0 || a !== void 0))
|
|
875
792
|
throw new Error(
|
|
876
793
|
"--aiui-browser-url means the browser is managed elsewhere — it can't be combined with --aiui-chrome-profile or --aiui-chrome-data-dir"
|
|
877
794
|
);
|
|
878
|
-
return {
|
|
795
|
+
return {
|
|
796
|
+
tag: t,
|
|
797
|
+
mcp: n,
|
|
798
|
+
chrome: o,
|
|
799
|
+
noChrome: r,
|
|
800
|
+
browser: i,
|
|
801
|
+
noBrowser: s,
|
|
802
|
+
chromeProfile: c,
|
|
803
|
+
chromeDataDir: a,
|
|
804
|
+
browserUrl: l,
|
|
805
|
+
bind: p,
|
|
806
|
+
passthrough: f
|
|
807
|
+
};
|
|
808
|
+
}
|
|
809
|
+
function it(e) {
|
|
810
|
+
var t;
|
|
811
|
+
return { bind: e.bind ?? ((t = e.config.channel) == null ? void 0 : t.bind) ?? "loopback" };
|
|
812
|
+
}
|
|
813
|
+
function st(e) {
|
|
814
|
+
return ["--bind", e.bind];
|
|
815
|
+
}
|
|
816
|
+
const pn = /* @__PURE__ */ new Set(["serve", "mcp"]);
|
|
817
|
+
function mn(e, t) {
|
|
818
|
+
return e.some((n) => n === t || n.startsWith(`${t}=`));
|
|
819
|
+
}
|
|
820
|
+
function at(e) {
|
|
821
|
+
const t = e.find((n) => !n.startsWith("-"));
|
|
822
|
+
return t !== void 0 && pn.has(t);
|
|
879
823
|
}
|
|
880
|
-
|
|
824
|
+
function wn(e, t) {
|
|
825
|
+
if (!at(e))
|
|
826
|
+
return e;
|
|
827
|
+
const n = st(t), o = [...e];
|
|
828
|
+
for (let r = 0; r < n.length; r += 2) {
|
|
829
|
+
const i = n[r], s = n[r + 1];
|
|
830
|
+
mn(e, i) || o.push(i, s);
|
|
831
|
+
}
|
|
832
|
+
return o;
|
|
833
|
+
}
|
|
834
|
+
const gn = {
|
|
881
835
|
darwin: 2147578994,
|
|
882
836
|
linux: 21522
|
|
883
|
-
},
|
|
884
|
-
function
|
|
885
|
-
const t =
|
|
837
|
+
}, bn = 'open(my $t,"+<","/dev/tty") or exit 0; my $c="\\r"; ioctl($t,$ARGV[0]+0,$c);', yn = [250, 750];
|
|
838
|
+
function vn(e = yn) {
|
|
839
|
+
const t = gn[process.platform];
|
|
886
840
|
if (t !== void 0)
|
|
887
|
-
for (const
|
|
841
|
+
for (const n of e)
|
|
888
842
|
setTimeout(() => {
|
|
889
843
|
try {
|
|
890
|
-
|
|
844
|
+
Ot("perl", ["-e", bn, String(t)], { stdio: "ignore" }).on("error", () => {
|
|
891
845
|
});
|
|
892
846
|
} catch {
|
|
893
847
|
}
|
|
894
|
-
},
|
|
848
|
+
}, n).unref();
|
|
895
849
|
}
|
|
896
|
-
const
|
|
850
|
+
const $n = `One-time setup — how should aiui launch Claude Code?
|
|
897
851
|
With --dangerously-skip-permissions, every agent action (shell commands, file writes,
|
|
898
852
|
network, the browser) runs without asking you first. Fast, and dangerous. It's a personal
|
|
899
853
|
preference — aiui works fine either way. Saved as claude.skipPermissions in your user
|
|
900
|
-
config; edit or delete it there to change your mind.`,
|
|
854
|
+
config; edit or delete it there to change your mind.`, Cn = `One-time setup — where should the channel's web server bind?
|
|
855
|
+
Binding the HOST interface puts the session's whole web surface on your network,
|
|
856
|
+
UNAUTHENTICATED — the iPad paint page (\`aiui paint url\` prints its URL), but also prompt
|
|
857
|
+
injection, /debug, and every sidecar. That's the simple, single-port way to use the iPad —
|
|
858
|
+
on a network that is yours alone (a home LAN), not on café Wi-Fi. LOOPBACK keeps everything
|
|
859
|
+
this-machine-only; reaching it from an iPad is then up to you — tunnel the channel port
|
|
860
|
+
however you like (Tailscale, \`ssh -L\`). Saved as channel.bind in your user config;
|
|
861
|
+
--aiui-bind wins per launch.`, kn = `One-time setup — auto-dismiss Claude Code's channel prompt?
|
|
901
862
|
aiui loads a custom development channel, so Claude Code shows a one-key acknowledgement
|
|
902
863
|
prompt at every startup. aiui can dismiss it for you: shortly after launch it injects a
|
|
903
864
|
single Enter keystroke into this terminal (a best-effort TIOCSTI ioctl on /dev/tty — it
|
|
904
865
|
literally "types" the Enter for you; on platforms that forbid that, nothing happens and
|
|
905
866
|
you press it yourself). Saying no just means pressing Enter once per launch. Saved as
|
|
906
867
|
claude.enterNudge in your user config.`;
|
|
907
|
-
async function
|
|
908
|
-
var
|
|
909
|
-
let
|
|
910
|
-
if (((
|
|
911
|
-
const
|
|
868
|
+
async function xn(e, t = W) {
|
|
869
|
+
var o, r, i;
|
|
870
|
+
let n = e;
|
|
871
|
+
if (((o = n.claude) == null ? void 0 : o.skipPermissions) === void 0) {
|
|
872
|
+
const s = await t($n, [
|
|
912
873
|
{ key: "y", label: "yes — skip permissions; nothing asks before acting" },
|
|
913
874
|
{ key: "n", label: "no — keep Claude Code's own permission prompts" }
|
|
914
875
|
]);
|
|
915
|
-
|
|
876
|
+
n = xe(n, "skipPermissions", s === "y");
|
|
916
877
|
}
|
|
917
|
-
if (((r =
|
|
918
|
-
const
|
|
878
|
+
if (((r = n.claude) == null ? void 0 : r.enterNudge) === void 0) {
|
|
879
|
+
const s = await t(kn, [
|
|
919
880
|
{ key: "y", label: "yes — press Enter for me at startup" },
|
|
920
881
|
{ key: "n", label: "no — I'll press it myself each launch" }
|
|
921
882
|
]);
|
|
922
|
-
|
|
883
|
+
n = xe(n, "enterNudge", s === "y");
|
|
923
884
|
}
|
|
924
|
-
|
|
885
|
+
if (((i = n.channel) == null ? void 0 : i.bind) === void 0) {
|
|
886
|
+
const s = await t(Cn, [
|
|
887
|
+
{ key: "h", label: "host — reachable on my (trusted) network; the iPad just works" },
|
|
888
|
+
{ key: "l", label: "loopback — this machine only; I'll tunnel when I want the iPad" }
|
|
889
|
+
]);
|
|
890
|
+
n = Tn(n, s === "h" ? "host" : "loopback");
|
|
891
|
+
}
|
|
892
|
+
return n;
|
|
925
893
|
}
|
|
926
|
-
function
|
|
927
|
-
const
|
|
928
|
-
r.claude = { ...r.claude, [t]:
|
|
894
|
+
function xe(e, t, n) {
|
|
895
|
+
const o = _((r) => {
|
|
896
|
+
r.claude = { ...r.claude, [t]: n };
|
|
929
897
|
});
|
|
930
|
-
return
|
|
898
|
+
return w(`wrote claude.${t}: ${n} to ${o}`), { ...e, claude: { ...e.claude, [t]: n } };
|
|
931
899
|
}
|
|
932
|
-
|
|
933
|
-
|
|
934
|
-
|
|
900
|
+
function Tn(e, t) {
|
|
901
|
+
const n = _((o) => {
|
|
902
|
+
o.channel = { ...o.channel, bind: t };
|
|
903
|
+
});
|
|
904
|
+
return w(`wrote channel.bind: ${t} to ${n}`), { ...e, channel: { ...e.channel, bind: t } };
|
|
905
|
+
}
|
|
906
|
+
const In = "https://generativelanguage.googleapis.com/v1beta/models", En = 3e3;
|
|
907
|
+
async function Pn(e = {}) {
|
|
908
|
+
var a;
|
|
909
|
+
const {
|
|
910
|
+
verify: t = !0,
|
|
911
|
+
env: n = process.env,
|
|
912
|
+
fetchImpl: o = fetch,
|
|
913
|
+
timeoutMs: r = En
|
|
914
|
+
} = e, i = (a = n.GEMINI_API_KEY) == null ? void 0 : a.trim();
|
|
915
|
+
if (!i)
|
|
916
|
+
return "missing";
|
|
917
|
+
if (!t)
|
|
918
|
+
return "unverified";
|
|
919
|
+
const s = new AbortController(), c = setTimeout(() => s.abort(), r);
|
|
920
|
+
try {
|
|
921
|
+
const l = await o(`${In}?key=${encodeURIComponent(i)}`, {
|
|
922
|
+
signal: s.signal
|
|
923
|
+
});
|
|
924
|
+
return l.ok ? "valid" : l.status === 400 || l.status === 401 || l.status === 403 ? "invalid" : "unverified";
|
|
925
|
+
} catch {
|
|
926
|
+
return "unverified";
|
|
927
|
+
} finally {
|
|
928
|
+
clearTimeout(c);
|
|
929
|
+
}
|
|
930
|
+
}
|
|
931
|
+
function Dn(e) {
|
|
932
|
+
switch (e) {
|
|
933
|
+
case "valid":
|
|
934
|
+
return null;
|
|
935
|
+
case "missing":
|
|
936
|
+
return {
|
|
937
|
+
level: "note",
|
|
938
|
+
title: "GEMINI_API_KEY is not set — the realtime (Gemini Live) tier is unavailable",
|
|
939
|
+
detail: "Only the realtime conversational submode needs it; transcription tiers are unaffected. To enable it, export the key in the shell you run `aiui claude` from:\n export GEMINI_API_KEY=…\nIt flows through to the channel process, where the Gemini Live session runs."
|
|
940
|
+
};
|
|
941
|
+
case "invalid":
|
|
942
|
+
return {
|
|
943
|
+
level: "warn",
|
|
944
|
+
title: "GEMINI_API_KEY was rejected by Google — the realtime tier will fail",
|
|
945
|
+
detail: "The key in your environment isn't valid, so every Gemini Live session will close immediately. The usual cause is a stale shell export shadowing your real key — check what's actually set (this prints only a short prefix, not the whole secret):\n echo $GEMINI_API_KEY | head -c 8\nFix the export and relaunch `aiui claude`."
|
|
946
|
+
};
|
|
947
|
+
case "unverified":
|
|
948
|
+
return {
|
|
949
|
+
level: "note",
|
|
950
|
+
title: "couldn't verify GEMINI_API_KEY with Google — continuing",
|
|
951
|
+
detail: "The check didn't complete (offline, a timeout, or a transient error), so the key is unverified — not known-bad. Launch continues; if the realtime tier turns out unavailable, an unreachable or invalid key may be why."
|
|
952
|
+
};
|
|
953
|
+
}
|
|
954
|
+
}
|
|
955
|
+
function Sn(e) {
|
|
956
|
+
const t = Dn(e);
|
|
957
|
+
t && (t.level === "warn" ? $(t.title, t.detail) : w(t.title, t.detail));
|
|
958
|
+
}
|
|
959
|
+
const An = "https://api.openai.com/v1/models", _n = 3e3;
|
|
960
|
+
async function On(e = {}) {
|
|
961
|
+
var a;
|
|
935
962
|
const {
|
|
936
963
|
verify: t = !0,
|
|
937
|
-
env:
|
|
938
|
-
fetchImpl:
|
|
939
|
-
timeoutMs: r =
|
|
940
|
-
} = e, i = (
|
|
964
|
+
env: n = process.env,
|
|
965
|
+
fetchImpl: o = fetch,
|
|
966
|
+
timeoutMs: r = _n
|
|
967
|
+
} = e, i = (a = n.OPENAI_API_KEY) == null ? void 0 : a.trim();
|
|
941
968
|
if (!i)
|
|
942
969
|
return "missing";
|
|
943
970
|
if (!t)
|
|
944
971
|
return "unverified";
|
|
945
|
-
const
|
|
972
|
+
const s = new AbortController(), c = setTimeout(() => s.abort(), r);
|
|
946
973
|
try {
|
|
947
|
-
const
|
|
974
|
+
const l = await o(An, {
|
|
948
975
|
headers: { authorization: `Bearer ${i}` },
|
|
949
|
-
signal:
|
|
976
|
+
signal: s.signal
|
|
950
977
|
});
|
|
951
|
-
return
|
|
978
|
+
return l.ok ? "valid" : l.status === 401 || l.status === 403 ? "invalid" : "unverified";
|
|
952
979
|
} catch {
|
|
953
980
|
return "unverified";
|
|
954
981
|
} finally {
|
|
955
|
-
clearTimeout(
|
|
982
|
+
clearTimeout(c);
|
|
956
983
|
}
|
|
957
984
|
}
|
|
958
|
-
function
|
|
985
|
+
function jn(e) {
|
|
959
986
|
switch (e) {
|
|
960
987
|
case "valid":
|
|
961
988
|
return null;
|
|
@@ -963,7 +990,7 @@ function Kt(e) {
|
|
|
963
990
|
return {
|
|
964
991
|
level: "warn",
|
|
965
992
|
title: "OPENAI_API_KEY is not set — the intent pipeline will run degraded",
|
|
966
|
-
detail: "Speech transcription and dictation correction
|
|
993
|
+
detail: "Speech transcription and dictation correction are unavailable — the overlay says so when you try to dictate. To enable them, export the key in the shell you run `aiui claude` from:\n export OPENAI_API_KEY=sk-…\nIt flows through to the channel process, which is where those calls happen. (For offline work, switch the overlay to the mock backends — see the intent-overlay guide.)"
|
|
967
994
|
};
|
|
968
995
|
case "invalid":
|
|
969
996
|
return {
|
|
@@ -971,96 +998,101 @@ function Kt(e) {
|
|
|
971
998
|
title: "OPENAI_API_KEY was rejected by OpenAI (401) — the intent pipeline will run degraded",
|
|
972
999
|
detail: `The key in your environment isn't valid. The usual cause is a stale shell export shadowing your real key — check what's actually set (this prints only a short prefix, not the whole secret):
|
|
973
1000
|
echo $OPENAI_API_KEY | head -c 12
|
|
974
|
-
and compare that against the start of your real key. Until it's fixed, transcription and correction
|
|
1001
|
+
and compare that against the start of your real key. Until it's fixed, transcription and correction are unavailable.`
|
|
975
1002
|
};
|
|
976
1003
|
case "unverified":
|
|
977
1004
|
return {
|
|
978
1005
|
level: "note",
|
|
979
1006
|
title: "couldn't verify OPENAI_API_KEY with OpenAI — continuing",
|
|
980
|
-
detail: "The check didn't complete (offline, a timeout, or a transient OpenAI error), so the key is unverified — not known-bad. Launch continues; if
|
|
1007
|
+
detail: "The check didn't complete (offline, a timeout, or a transient OpenAI error), so the key is unverified — not known-bad. Launch continues; if transcription and correction turn out unavailable, an unreachable or invalid key may be why."
|
|
981
1008
|
};
|
|
982
1009
|
}
|
|
983
1010
|
}
|
|
984
|
-
function
|
|
985
|
-
const t =
|
|
986
|
-
t && (t.level === "warn" ?
|
|
1011
|
+
function Nn(e) {
|
|
1012
|
+
const t = jn(e);
|
|
1013
|
+
t && (t.level === "warn" ? $(t.title, t.detail) : w(t.title, t.detail));
|
|
987
1014
|
}
|
|
988
|
-
const
|
|
989
|
-
function
|
|
990
|
-
const t = (process.env.PATH ?? "").split(
|
|
991
|
-
for (const
|
|
992
|
-
for (const r of
|
|
1015
|
+
const he = "0.5.0";
|
|
1016
|
+
function Un(e) {
|
|
1017
|
+
const t = (process.env.PATH ?? "").split(gt).filter(Boolean), n = process.platform === "win32" ? (process.env.PATHEXT ?? ".EXE;.CMD;.BAT;.COM").split(";") : [""];
|
|
1018
|
+
for (const o of t)
|
|
1019
|
+
for (const r of n)
|
|
993
1020
|
try {
|
|
994
|
-
return
|
|
1021
|
+
return kt(d(o, e + r), xt.X_OK), !0;
|
|
995
1022
|
} catch {
|
|
996
1023
|
}
|
|
997
1024
|
return !1;
|
|
998
1025
|
}
|
|
999
|
-
const
|
|
1000
|
-
async function
|
|
1001
|
-
var
|
|
1002
|
-
const t =
|
|
1026
|
+
const Ln = "@habemus-papadum/aiui-claude-channel", Mn = "@habemus-papadum/aiui-claude-plugin", Te = "aiui";
|
|
1027
|
+
async function Rn(e = []) {
|
|
1028
|
+
var ge, be;
|
|
1029
|
+
const t = de(e), { tag: n, passthrough: o } = t, r = rt(o);
|
|
1003
1030
|
if (r) {
|
|
1004
|
-
r === "help" ?
|
|
1031
|
+
r === "help" ? Hn() : console.log(`aiui ${he}`), await Bn(o);
|
|
1005
1032
|
return;
|
|
1006
1033
|
}
|
|
1007
|
-
let i =
|
|
1008
|
-
const
|
|
1009
|
-
|
|
1010
|
-
const
|
|
1011
|
-
|
|
1034
|
+
let i = S();
|
|
1035
|
+
const s = Vn(o) && !ie();
|
|
1036
|
+
s && (i = await xn(i));
|
|
1037
|
+
const c = await On({ verify: s });
|
|
1038
|
+
s && Nn(c);
|
|
1039
|
+
const a = await Pn({ verify: s });
|
|
1040
|
+
if (s && Sn(a), !ct())
|
|
1012
1041
|
return;
|
|
1013
|
-
const
|
|
1014
|
-
|
|
1015
|
-
const
|
|
1016
|
-
|
|
1042
|
+
const l = C(V(Mn), "marketplace", "plugins"), p = J(Ln), f = [...p.args, "mcp"];
|
|
1043
|
+
n && f.push("--tag", n);
|
|
1044
|
+
const m = it({ config: i, bind: t.bind });
|
|
1045
|
+
f.push(...st(m));
|
|
1046
|
+
const g = {
|
|
1047
|
+
[Te]: { command: p.command, args: f }
|
|
1017
1048
|
};
|
|
1018
1049
|
let y = { enabled: !1 };
|
|
1019
|
-
if (
|
|
1020
|
-
const
|
|
1050
|
+
if (qe(t, i.chrome)) {
|
|
1051
|
+
const X = {
|
|
1021
1052
|
...i.chrome,
|
|
1022
1053
|
...t.browserUrl ? { browserUrl: t.browserUrl } : {}
|
|
1023
|
-
},
|
|
1024
|
-
|
|
1054
|
+
}, ye = await Fn(t, X, s);
|
|
1055
|
+
g[Ht] = ye.entry, y = ye.info;
|
|
1025
1056
|
}
|
|
1026
|
-
const
|
|
1057
|
+
const I = {
|
|
1027
1058
|
launcher: "aiui claude",
|
|
1028
1059
|
chromeDevtools: y,
|
|
1029
|
-
openaiKey:
|
|
1060
|
+
openaiKey: c,
|
|
1061
|
+
geminiKey: a
|
|
1030
1062
|
};
|
|
1031
|
-
f.push("--launch-info", JSON.stringify(
|
|
1032
|
-
const
|
|
1033
|
-
y.enabled &&
|
|
1034
|
-
const
|
|
1035
|
-
...((
|
|
1063
|
+
f.push("--launch-info", JSON.stringify(I));
|
|
1064
|
+
const h = JSON.stringify({ mcpServers: g }), me = [d(l, "aiui"), d(l, "frontend-design")];
|
|
1065
|
+
y.enabled && me.push(d(l, "session-browser"));
|
|
1066
|
+
const mt = [
|
|
1067
|
+
...((ge = i.claude) == null ? void 0 : ge.skipPermissions) ?? !0 ? ["--dangerously-skip-permissions"] : [],
|
|
1036
1068
|
"--mcp-config",
|
|
1037
|
-
|
|
1038
|
-
...
|
|
1069
|
+
h,
|
|
1070
|
+
...me.flatMap((X) => ["--plugin-dir", X]),
|
|
1039
1071
|
// Custom channels are a research preview and not on the approved allowlist,
|
|
1040
1072
|
// so opt this session into loading ours as a development channel.
|
|
1041
1073
|
"--dangerously-load-development-channels",
|
|
1042
|
-
`server:${
|
|
1074
|
+
`server:${Te}`
|
|
1043
1075
|
];
|
|
1044
|
-
|
|
1045
|
-
const
|
|
1076
|
+
s && (((be = i.claude) == null ? void 0 : be.enterNudge) ?? !0) && vn();
|
|
1077
|
+
const we = await T("claude", [...mt, ...o], {
|
|
1046
1078
|
stdio: "inherit",
|
|
1047
1079
|
reject: !1
|
|
1048
1080
|
});
|
|
1049
|
-
|
|
1081
|
+
we.exitCode && (process.exitCode = we.exitCode);
|
|
1050
1082
|
}
|
|
1051
|
-
function
|
|
1052
|
-
return
|
|
1083
|
+
function ct() {
|
|
1084
|
+
return Un("claude") ? !0 : (b(
|
|
1053
1085
|
"`claude` was not found on your PATH",
|
|
1054
1086
|
"Install Claude Code and make sure the `claude` command is available, then try again."
|
|
1055
1087
|
), process.exitCode = 1, !1);
|
|
1056
1088
|
}
|
|
1057
|
-
async function
|
|
1058
|
-
if (!
|
|
1089
|
+
async function Bn(e) {
|
|
1090
|
+
if (!ct())
|
|
1059
1091
|
return;
|
|
1060
|
-
const t = await
|
|
1092
|
+
const t = await T("claude", e, { stdio: "inherit", reject: !1 });
|
|
1061
1093
|
t.exitCode && (process.exitCode = t.exitCode);
|
|
1062
1094
|
}
|
|
1063
|
-
function
|
|
1095
|
+
function Hn() {
|
|
1064
1096
|
console.log(`aiui claude — launch Claude Code wired with the aiui channel, plugin, and browser MCP
|
|
1065
1097
|
|
|
1066
1098
|
aiui's own flags (everything else forwards to claude verbatim):
|
|
@@ -1071,277 +1103,890 @@ aiui's own flags (everything else forwards to claude verbatim):
|
|
|
1071
1103
|
--aiui-chrome-data-dir <path> explicit browser user data dir
|
|
1072
1104
|
--aiui-browser-url <url> attach to a browser at this DevTools endpoint
|
|
1073
1105
|
(e.g. a tunnel from \`aiui browser --tunnel\`)
|
|
1106
|
+
--aiui-bind <loopback|host> where the channel's web server binds: loopback
|
|
1107
|
+
(this machine only, the default) or host (your
|
|
1108
|
+
whole network can reach the session's web
|
|
1109
|
+
surface — the iPad paint page included;
|
|
1110
|
+
trusted networks only)
|
|
1074
1111
|
|
|
1112
|
+
Every channel hosts the same session sidecars — paint (iPad ink), the intent panel
|
|
1113
|
+
at /intent/, the remote bar, and the remote pencil — reachable per --aiui-bind.
|
|
1075
1114
|
Durable settings live in config.json (project .aiui-cache/ + user cache) — see the
|
|
1076
1115
|
Configuration guide. What follows is claude's own --help:
|
|
1077
1116
|
`);
|
|
1078
1117
|
}
|
|
1079
|
-
async function
|
|
1118
|
+
async function Fn(e, t, n) {
|
|
1080
1119
|
if (t.browserUrl)
|
|
1081
1120
|
return {
|
|
1082
|
-
entry:
|
|
1121
|
+
entry: Z(t.browserUrl),
|
|
1083
1122
|
info: { enabled: !0, connection: "attach", browserUrl: t.browserUrl }
|
|
1084
1123
|
};
|
|
1085
|
-
let
|
|
1124
|
+
let o = { ...t }, r = x(e, o);
|
|
1086
1125
|
if (r.mode === "attach") {
|
|
1087
|
-
const
|
|
1088
|
-
if (
|
|
1089
|
-
return
|
|
1090
|
-
|
|
1126
|
+
const a = await U(r.userDataDir);
|
|
1127
|
+
if (a)
|
|
1128
|
+
return B(
|
|
1129
|
+
r.userDataDir,
|
|
1130
|
+
j().state === "ready",
|
|
1131
|
+
$
|
|
1132
|
+
), {
|
|
1133
|
+
entry: Z(a.browserUrl),
|
|
1091
1134
|
info: {
|
|
1092
1135
|
enabled: !0,
|
|
1093
1136
|
connection: "attach",
|
|
1094
|
-
browserUrl:
|
|
1137
|
+
browserUrl: a.browserUrl,
|
|
1095
1138
|
userDataDir: r.userDataDir
|
|
1096
1139
|
}
|
|
1097
1140
|
};
|
|
1098
1141
|
}
|
|
1099
|
-
if (!
|
|
1100
|
-
const
|
|
1101
|
-
|
|
1142
|
+
if (!o.executablePath && !o.channel) {
|
|
1143
|
+
const a = await We({ mode: o.forTesting ?? "prompt", interactive: n });
|
|
1144
|
+
a && (o = { ...o, executablePath: a }, r = x(e, o));
|
|
1102
1145
|
}
|
|
1103
|
-
|
|
1104
|
-
const i =
|
|
1105
|
-
|
|
1106
|
-
const
|
|
1146
|
+
G(r.userDataDir, { recursive: !0 });
|
|
1147
|
+
const i = j(), s = i.state === "ready" ? [i.dir] : [];
|
|
1148
|
+
B(r.userDataDir, i.state === "ready", $), n && (Xe(r, s), Je(i));
|
|
1149
|
+
const c = {
|
|
1107
1150
|
userDataDir: r.userDataDir,
|
|
1108
1151
|
executablePath: r.executablePath,
|
|
1109
1152
|
channel: r.channel,
|
|
1110
1153
|
headless: r.headless,
|
|
1111
|
-
|
|
1154
|
+
extensionDirs: s
|
|
1112
1155
|
};
|
|
1113
|
-
if (r.mode === "attach" &&
|
|
1156
|
+
if (r.mode === "attach" && n)
|
|
1114
1157
|
try {
|
|
1115
|
-
const
|
|
1116
|
-
binary:
|
|
1158
|
+
const a = await je({
|
|
1159
|
+
binary: Oe(r),
|
|
1117
1160
|
userDataDir: r.userDataDir,
|
|
1118
1161
|
debugPort: r.debugPort,
|
|
1119
|
-
|
|
1162
|
+
extensionDirs: s,
|
|
1120
1163
|
headless: r.headless
|
|
1121
1164
|
});
|
|
1122
1165
|
return {
|
|
1123
|
-
entry:
|
|
1166
|
+
entry: Z(a.browserUrl),
|
|
1124
1167
|
info: {
|
|
1125
1168
|
enabled: !0,
|
|
1126
1169
|
connection: "attach",
|
|
1127
|
-
browserUrl:
|
|
1128
|
-
...
|
|
1170
|
+
browserUrl: a.browserUrl,
|
|
1171
|
+
...c
|
|
1129
1172
|
}
|
|
1130
1173
|
};
|
|
1131
|
-
} catch (
|
|
1132
|
-
|
|
1174
|
+
} catch (a) {
|
|
1175
|
+
$(
|
|
1133
1176
|
"couldn't start the session browser — falling back to a browser private to the MCP",
|
|
1134
|
-
|
|
1177
|
+
a instanceof Error ? a.message : String(a)
|
|
1135
1178
|
);
|
|
1136
1179
|
}
|
|
1137
1180
|
return {
|
|
1138
|
-
entry:
|
|
1139
|
-
info: { enabled: !0, connection: "launch", ...
|
|
1181
|
+
entry: qt(r, s),
|
|
1182
|
+
info: { enabled: !0, connection: "launch", ...c }
|
|
1140
1183
|
};
|
|
1141
1184
|
}
|
|
1142
|
-
function
|
|
1185
|
+
function Vn(e) {
|
|
1143
1186
|
return !process.stdin.isTTY || !process.stdout.isTTY ? !1 : !e.some((t) => t === "-p" || t === "--print");
|
|
1144
1187
|
}
|
|
1145
|
-
|
|
1146
|
-
|
|
1147
|
-
|
|
1148
|
-
|
|
1149
|
-
|
|
1150
|
-
|
|
1151
|
-
|
|
1188
|
+
function Gn(e = process.cwd()) {
|
|
1189
|
+
return {
|
|
1190
|
+
project: Be(e),
|
|
1191
|
+
user: F(void 0, { create: !1 }),
|
|
1192
|
+
browser: A(!1)
|
|
1193
|
+
};
|
|
1194
|
+
}
|
|
1195
|
+
function Kn(e, t) {
|
|
1196
|
+
const n = [];
|
|
1197
|
+
return e.userOnly || n.push({ label: "project cache", path: t.project }), e.projectOnly || n.push(
|
|
1198
|
+
e.keepBrowser ? {
|
|
1199
|
+
label: "user cache (keeping Chrome for Testing)",
|
|
1200
|
+
path: t.user,
|
|
1201
|
+
keep: [t.browser]
|
|
1202
|
+
} : { label: "user cache", path: t.user }
|
|
1203
|
+
), n;
|
|
1204
|
+
}
|
|
1205
|
+
function Yn(e) {
|
|
1206
|
+
var o;
|
|
1207
|
+
if (!v(e.path))
|
|
1208
|
+
return [];
|
|
1209
|
+
if (!((o = e.keep) != null && o.length))
|
|
1210
|
+
return [e.path];
|
|
1211
|
+
const t = new Set(e.keep.map((r) => C(r)));
|
|
1212
|
+
let n;
|
|
1213
|
+
try {
|
|
1214
|
+
n = Y(e.path);
|
|
1215
|
+
} catch {
|
|
1216
|
+
return [];
|
|
1217
|
+
}
|
|
1218
|
+
return n.map((r) => C(d(e.path, r))).filter((r) => !t.has(r));
|
|
1219
|
+
}
|
|
1220
|
+
async function Wn(e = {}) {
|
|
1221
|
+
if (e.projectOnly && e.userOnly) {
|
|
1222
|
+
b(
|
|
1223
|
+
"pass at most one of --project-only / --user-only",
|
|
1224
|
+
"with neither, `aiui clean` removes both"
|
|
1225
|
+
), process.exitCode = 1;
|
|
1226
|
+
return;
|
|
1227
|
+
}
|
|
1228
|
+
const t = process.cwd(), o = Kn(e, Gn(t)).map((f) => ({ target: f, paths: Yn(f) })).filter((f) => f.paths.length > 0);
|
|
1229
|
+
if (o.length === 0) {
|
|
1230
|
+
console.log("nothing to clean — no aiui state here or in the user cache.");
|
|
1231
|
+
return;
|
|
1232
|
+
}
|
|
1233
|
+
let r = 0;
|
|
1234
|
+
console.log(`aiui clean will remove:
|
|
1235
|
+
`);
|
|
1236
|
+
for (const { target: f, paths: m } of o) {
|
|
1237
|
+
const g = m.reduce((y, I) => y + re(I), 0);
|
|
1238
|
+
r += g, console.log(` ${Q(g).padStart(9)} ${f.label}`), console.log(` ${" ".repeat(9)} ${u.dim(f.path)}`);
|
|
1239
|
+
}
|
|
1240
|
+
console.log(`
|
|
1241
|
+
${Q(r).padStart(9)} total
|
|
1242
|
+
`);
|
|
1243
|
+
const i = !e.projectOnly, s = i && !e.keepBrowser, c = [
|
|
1244
|
+
"traces and session-browser logins are cleared",
|
|
1245
|
+
i && "the Claude permission prompt (claude.skipPermissions) returns on next launch",
|
|
1246
|
+
s && "Chrome for Testing re-downloads (~160 MB) on the next `aiui claude`"
|
|
1247
|
+
].filter((f) => !!f);
|
|
1248
|
+
console.log("This resets aiui toward a fresh install:");
|
|
1249
|
+
for (const f of c)
|
|
1250
|
+
console.log(` • ${f}`);
|
|
1251
|
+
console.log("");
|
|
1252
|
+
const a = M(t);
|
|
1253
|
+
if (a.length && $(
|
|
1254
|
+
`${a.length} aiui session${a.length === 1 ? "" : "s"} still running`,
|
|
1255
|
+
"stop them first — a live session rewrites its registry entry as it exits, and an open browser can lock files being deleted"
|
|
1256
|
+
), e.dryRun) {
|
|
1257
|
+
w("dry run — nothing was deleted");
|
|
1258
|
+
return;
|
|
1259
|
+
}
|
|
1260
|
+
if (!e.yes) {
|
|
1261
|
+
if (!process.stdin.isTTY) {
|
|
1262
|
+
b(
|
|
1263
|
+
"refusing to delete without confirmation",
|
|
1264
|
+
"re-run with --yes for a non-interactive clean, or from a terminal"
|
|
1152
1265
|
), process.exitCode = 1;
|
|
1153
1266
|
return;
|
|
1154
|
-
|
|
1155
|
-
|
|
1156
|
-
|
|
1157
|
-
|
|
1158
|
-
|
|
1159
|
-
|
|
1160
|
-
|
|
1161
|
-
|
|
1162
|
-
|
|
1163
|
-
|
|
1164
|
-
|
|
1267
|
+
}
|
|
1268
|
+
if (await W(
|
|
1269
|
+
"Delete these now?",
|
|
1270
|
+
[
|
|
1271
|
+
{ key: "y", label: "yes, delete" },
|
|
1272
|
+
{ key: "n", label: "no, cancel" }
|
|
1273
|
+
],
|
|
1274
|
+
"n"
|
|
1275
|
+
) !== "y") {
|
|
1276
|
+
console.log("cancelled — nothing was deleted.");
|
|
1277
|
+
return;
|
|
1165
1278
|
}
|
|
1166
1279
|
}
|
|
1167
|
-
|
|
1168
|
-
|
|
1169
|
-
|
|
1170
|
-
|
|
1171
|
-
|
|
1172
|
-
|
|
1173
|
-
|
|
1174
|
-
|
|
1175
|
-
|
|
1176
|
-
|
|
1177
|
-
|
|
1178
|
-
m("npm install failed — fix that, then re-run this command to continue"), process.exitCode = n.exitCode;
|
|
1179
|
-
return;
|
|
1280
|
+
let l = 0, p = 0;
|
|
1281
|
+
for (const { paths: f } of o)
|
|
1282
|
+
for (const m of f) {
|
|
1283
|
+
const g = re(m);
|
|
1284
|
+
try {
|
|
1285
|
+
Tt(m, { recursive: !0, force: !0 }), l += g;
|
|
1286
|
+
} catch (y) {
|
|
1287
|
+
p++, $(
|
|
1288
|
+
`could not remove ${m}`,
|
|
1289
|
+
y instanceof Error ? y.message : String(y)
|
|
1290
|
+
);
|
|
1180
1291
|
}
|
|
1181
1292
|
}
|
|
1182
|
-
|
|
1293
|
+
p && $(
|
|
1294
|
+
`${p} path${p === 1 ? "" : "s"} could not be deleted`,
|
|
1295
|
+
"a running browser can lock its files — close the session browser and re-run"
|
|
1296
|
+
), console.log(`clean complete — freed ~${Q(l)}.`);
|
|
1183
1297
|
}
|
|
1184
|
-
function
|
|
1185
|
-
var o;
|
|
1186
|
-
if (!b(e))
|
|
1187
|
-
return "new";
|
|
1298
|
+
function re(e) {
|
|
1188
1299
|
let t;
|
|
1189
1300
|
try {
|
|
1190
|
-
t =
|
|
1301
|
+
t = It(e);
|
|
1191
1302
|
} catch {
|
|
1192
|
-
return
|
|
1303
|
+
return 0;
|
|
1193
1304
|
}
|
|
1194
|
-
if (t.
|
|
1195
|
-
return
|
|
1305
|
+
if (t.isSymbolicLink() || !t.isDirectory())
|
|
1306
|
+
return t.size;
|
|
1307
|
+
let n;
|
|
1196
1308
|
try {
|
|
1197
|
-
|
|
1198
|
-
return "existing-demo";
|
|
1309
|
+
n = Y(e);
|
|
1199
1310
|
} catch {
|
|
1311
|
+
return 0;
|
|
1200
1312
|
}
|
|
1201
|
-
|
|
1313
|
+
let o = 0;
|
|
1314
|
+
for (const r of n)
|
|
1315
|
+
o += re(d(e, r));
|
|
1316
|
+
return o;
|
|
1202
1317
|
}
|
|
1203
|
-
function
|
|
1204
|
-
|
|
1318
|
+
function Q(e) {
|
|
1319
|
+
if (e < 1024)
|
|
1320
|
+
return `${e} B`;
|
|
1321
|
+
const t = ["KB", "MB", "GB", "TB"];
|
|
1322
|
+
let n = e / 1024, o = 0;
|
|
1323
|
+
for (; n >= 1024 && o < t.length - 1; )
|
|
1324
|
+
n /= 1024, o++;
|
|
1325
|
+
return `${n.toFixed(1)} ${t[o]}`;
|
|
1326
|
+
}
|
|
1327
|
+
function D(e = process.cwd()) {
|
|
1328
|
+
const t = St(e);
|
|
1329
|
+
return {
|
|
1330
|
+
paths: t,
|
|
1331
|
+
user: ne(t.user) ?? {},
|
|
1332
|
+
project: ne(t.project) ?? {}
|
|
1333
|
+
};
|
|
1205
1334
|
}
|
|
1206
|
-
function
|
|
1207
|
-
|
|
1208
|
-
|
|
1209
|
-
|
|
1210
|
-
|
|
1211
|
-
|
|
1212
|
-
|
|
1213
|
-
|
|
1335
|
+
function fe(e) {
|
|
1336
|
+
return Me().map((t) => {
|
|
1337
|
+
const n = Ie(e.user, t), o = Ie(e.project, t), r = o ?? n, i = o !== void 0 ? "project" : n !== void 0 ? "user" : t.field.default !== void 0 ? "default" : "unset";
|
|
1338
|
+
return { ...t, userValue: n, projectValue: o, effective: r, source: i };
|
|
1339
|
+
});
|
|
1340
|
+
}
|
|
1341
|
+
function Ie(e, t) {
|
|
1342
|
+
var o;
|
|
1343
|
+
return (o = e[t.section.name]) == null ? void 0 : o[t.field.key];
|
|
1344
|
+
}
|
|
1345
|
+
function pe(e, t) {
|
|
1346
|
+
const n = fe(t).find((o) => o.path === e);
|
|
1347
|
+
return n || (b(
|
|
1348
|
+
`unknown config key: ${e}`,
|
|
1349
|
+
`Known keys:
|
|
1350
|
+
${Me().map((o) => o.path).join(`
|
|
1351
|
+
`)}`
|
|
1352
|
+
), process.exitCode = 1), n;
|
|
1353
|
+
}
|
|
1354
|
+
function qn(e = {}, t = process.cwd()) {
|
|
1355
|
+
const n = D(t), o = fe(n);
|
|
1356
|
+
if (e.json) {
|
|
1357
|
+
console.log(
|
|
1358
|
+
JSON.stringify(
|
|
1359
|
+
{
|
|
1360
|
+
files: {
|
|
1361
|
+
user: { path: n.paths.user, exists: v(n.paths.user) },
|
|
1362
|
+
project: { path: n.paths.project, exists: v(n.paths.project) }
|
|
1363
|
+
},
|
|
1364
|
+
user: n.user,
|
|
1365
|
+
project: n.project,
|
|
1366
|
+
effective: Dt(n.user, n.project)
|
|
1367
|
+
},
|
|
1368
|
+
null,
|
|
1369
|
+
2
|
|
1370
|
+
)
|
|
1371
|
+
);
|
|
1372
|
+
return;
|
|
1373
|
+
}
|
|
1374
|
+
console.log(`user: ${n.paths.user}${Ee(n.paths.user)}`), console.log(`project: ${n.paths.project}${Ee(n.paths.project)}`);
|
|
1375
|
+
const r = Math.max(...o.map((s) => s.path.length));
|
|
1376
|
+
let i = "";
|
|
1377
|
+
for (const s of o)
|
|
1378
|
+
s.section.name !== i && (i = s.section.name, console.log(`
|
|
1379
|
+
${u.bold(i)} ${u.dim(`— ${s.section.summary}`)}`)), console.log(` ${s.path.padEnd(r + 2)}${lt(s)}`);
|
|
1380
|
+
console.log(
|
|
1381
|
+
u.dim(
|
|
1382
|
+
"\nProject beats user per key; CLI flags beat both. `aiui config` browses the docs interactively."
|
|
1214
1383
|
)
|
|
1215
1384
|
);
|
|
1216
1385
|
}
|
|
1217
|
-
|
|
1218
|
-
|
|
1219
|
-
|
|
1220
|
-
|
|
1221
|
-
|
|
1222
|
-
|
|
1386
|
+
function Ee(e) {
|
|
1387
|
+
return v(e) ? "" : u.dim(" (not present)");
|
|
1388
|
+
}
|
|
1389
|
+
function lt(e) {
|
|
1390
|
+
return e.effective !== void 0 ? `${u.cyan(k(e.effective))} ${u.dim(`(${e.source})`)}` : u.dim(
|
|
1391
|
+
e.field.default !== void 0 ? `default: ${k(e.field.default)}` : "unset"
|
|
1392
|
+
);
|
|
1223
1393
|
}
|
|
1224
|
-
function
|
|
1225
|
-
|
|
1226
|
-
|
|
1227
|
-
|
|
1228
|
-
|
|
1229
|
-
|
|
1230
|
-
|
|
1394
|
+
function zn(e, t = process.cwd()) {
|
|
1395
|
+
const n = D(t), o = pe(e, n);
|
|
1396
|
+
if (o) {
|
|
1397
|
+
if (o.effective !== void 0) {
|
|
1398
|
+
console.log(String(o.effective));
|
|
1399
|
+
const r = o.source === "project" ? n.paths.project : n.paths.user;
|
|
1400
|
+
console.error(u.dim(`# set in the ${o.source} config: ${r}`));
|
|
1401
|
+
return;
|
|
1402
|
+
}
|
|
1403
|
+
if (o.field.default !== void 0) {
|
|
1404
|
+
console.log(String(o.field.default)), console.error(u.dim(`# built-in default — ${ee(o.field)}`));
|
|
1405
|
+
return;
|
|
1406
|
+
}
|
|
1407
|
+
console.error(
|
|
1408
|
+
u.dim(`# not set in any config file — default: ${ee(o.field)}`)
|
|
1409
|
+
);
|
|
1231
1410
|
}
|
|
1232
1411
|
}
|
|
1233
|
-
function
|
|
1234
|
-
const
|
|
1235
|
-
|
|
1236
|
-
|
|
1237
|
-
|
|
1238
|
-
|
|
1239
|
-
|
|
1240
|
-
|
|
1241
|
-
|
|
1242
|
-
|
|
1243
|
-
|
|
1244
|
-
npx aiui open http://localhost:5173
|
|
1245
|
-
|
|
1246
|
-
Click the ✳ aiui button on the page and type an intent — it lands in the session
|
|
1247
|
-
as a prompt. Re-run \`${o}\` anytime to continue this sandbox.`);
|
|
1412
|
+
function Jn(e, t, n = {}, o = process.cwd()) {
|
|
1413
|
+
const r = D(o), i = pe(e, r);
|
|
1414
|
+
if (!i)
|
|
1415
|
+
return;
|
|
1416
|
+
const s = te(i.field, t);
|
|
1417
|
+
if ("error" in s) {
|
|
1418
|
+
b(`invalid value for ${i.path}: ${t}`, s.error), process.exitCode = 1;
|
|
1419
|
+
return;
|
|
1420
|
+
}
|
|
1421
|
+
ut(r, i, s.value, n.project ? "project" : "user");
|
|
1248
1422
|
}
|
|
1249
|
-
|
|
1250
|
-
|
|
1251
|
-
|
|
1252
|
-
|
|
1253
|
-
|
|
1254
|
-
}
|
|
1255
|
-
|
|
1256
|
-
|
|
1257
|
-
|
|
1423
|
+
function ut(e, t, n, o) {
|
|
1424
|
+
const r = Re(e.paths[o], (i) => {
|
|
1425
|
+
const s = i;
|
|
1426
|
+
s[t.section.name] = { ...s[t.section.name], [t.field.key]: n };
|
|
1427
|
+
});
|
|
1428
|
+
w(`wrote ${t.path}: ${k(n)} to ${r}`);
|
|
1429
|
+
}
|
|
1430
|
+
function Xn(e, t = {}, n = process.cwd()) {
|
|
1431
|
+
const o = D(n), r = pe(e, o);
|
|
1432
|
+
r && dt(o, r, t.project ? "project" : "user");
|
|
1433
|
+
}
|
|
1434
|
+
function dt(e, t, n) {
|
|
1435
|
+
var c;
|
|
1436
|
+
const o = e.paths[n];
|
|
1437
|
+
if (((c = (ne(o) ?? {})[t.section.name]) == null ? void 0 : c[t.field.key]) === void 0) {
|
|
1438
|
+
w(`${t.path} is not set in the ${n} config (${o})`);
|
|
1439
|
+
return;
|
|
1440
|
+
}
|
|
1441
|
+
const s = Re(o, (a) => {
|
|
1442
|
+
const l = a, p = { ...l[t.section.name] };
|
|
1443
|
+
delete p[t.field.key], Object.keys(p).length === 0 ? delete l[t.section.name] : l[t.section.name] = p;
|
|
1444
|
+
});
|
|
1445
|
+
w(`removed ${t.path} from ${s}`);
|
|
1446
|
+
}
|
|
1447
|
+
async function Pe(e = process.cwd()) {
|
|
1448
|
+
if (!process.stdin.isTTY || !process.stdout.isTTY) {
|
|
1449
|
+
b(
|
|
1450
|
+
"aiui config tui needs an interactive terminal",
|
|
1451
|
+
"In scripts and non-TTY sessions use `aiui config show` (or `show --json`)."
|
|
1258
1452
|
), process.exitCode = 1;
|
|
1259
1453
|
return;
|
|
1260
1454
|
}
|
|
1261
|
-
const
|
|
1262
|
-
|
|
1263
|
-
|
|
1455
|
+
const t = D(e).paths;
|
|
1456
|
+
console.log(u.dim(`user: ${Se(t.user)}`)), console.log(u.dim(`project: ${Se(t.project)}`));
|
|
1457
|
+
try {
|
|
1458
|
+
for (; ; ) {
|
|
1459
|
+
const n = D(e), o = await Zn(n);
|
|
1460
|
+
if (!o)
|
|
1461
|
+
return;
|
|
1462
|
+
await eo(n, o);
|
|
1463
|
+
}
|
|
1464
|
+
} catch (n) {
|
|
1465
|
+
if (n instanceof Error && n.name === "ExitPromptError")
|
|
1466
|
+
return;
|
|
1467
|
+
throw n;
|
|
1468
|
+
}
|
|
1469
|
+
}
|
|
1470
|
+
async function Zn(e) {
|
|
1471
|
+
const t = fe(e), n = Math.max(...t.map((r) => r.path.length)) + 2, o = [];
|
|
1472
|
+
for (const r of At) {
|
|
1473
|
+
o.push(new oe(u.dim(`── ${r.name} — ${r.summary}`)));
|
|
1474
|
+
for (const i of t.filter((s) => s.section.name === r.name))
|
|
1475
|
+
o.push({
|
|
1476
|
+
name: `${i.path.padEnd(n)}${lt(i)}`,
|
|
1477
|
+
value: i,
|
|
1478
|
+
description: Qn(i)
|
|
1479
|
+
});
|
|
1480
|
+
}
|
|
1481
|
+
return o.push(new oe(" ")), o.push({ name: "exit", value: void 0, description: "Leave the config browser." }), O({
|
|
1482
|
+
message: "aiui config",
|
|
1483
|
+
choices: o,
|
|
1484
|
+
pageSize: o.length,
|
|
1485
|
+
loop: !1
|
|
1264
1486
|
});
|
|
1265
|
-
o.exitCode && (process.exitCode = o.exitCode);
|
|
1266
1487
|
}
|
|
1267
|
-
|
|
1268
|
-
|
|
1488
|
+
function Qn(e) {
|
|
1489
|
+
const t = [u.bold(e.field.summary)];
|
|
1490
|
+
return e.field.doc && t.push(no(e.field.doc, 76)), t.push(""), e.field.type === "enum" && t.push(`allowed: ${(e.field.values ?? []).join(" | ")}`), t.push(`default: ${ee(e.field)}`), t.push(`user: ${De(e.userValue)}`), t.push(`project: ${De(e.projectValue)}`), t.push(
|
|
1491
|
+
`effective: ${e.effective !== void 0 ? `${k(e.effective)} (from the ${e.source} config)` : "the built-in default"}`
|
|
1492
|
+
), t.join(`
|
|
1493
|
+
`);
|
|
1494
|
+
}
|
|
1495
|
+
function De(e) {
|
|
1496
|
+
return e === void 0 ? u.dim("(not set)") : k(e);
|
|
1497
|
+
}
|
|
1498
|
+
async function eo(e, t) {
|
|
1499
|
+
const n = [
|
|
1500
|
+
{
|
|
1501
|
+
name: "set in the user config",
|
|
1502
|
+
value: "set-user",
|
|
1503
|
+
description: `${e.paths.user}
|
|
1504
|
+
Personal preference — applies to every project.`
|
|
1505
|
+
},
|
|
1506
|
+
{
|
|
1507
|
+
name: "set in the project config",
|
|
1508
|
+
value: "set-project",
|
|
1509
|
+
description: `${e.paths.project}
|
|
1510
|
+
This project only; the file may be shared or committed by a team.`
|
|
1511
|
+
}
|
|
1512
|
+
];
|
|
1513
|
+
t.userValue !== void 0 && n.push({
|
|
1514
|
+
name: `unset in the user config (currently ${k(t.userValue)})`,
|
|
1515
|
+
value: "unset-user"
|
|
1516
|
+
}), t.projectValue !== void 0 && n.push({
|
|
1517
|
+
name: `unset in the project config (currently ${k(t.projectValue)})`,
|
|
1518
|
+
value: "unset-project"
|
|
1519
|
+
}), n.push(new oe()), n.push({ name: "back", value: "back" });
|
|
1520
|
+
const o = await O({
|
|
1521
|
+
message: `${t.path} — ${t.field.summary}`,
|
|
1522
|
+
choices: n
|
|
1523
|
+
});
|
|
1524
|
+
if (o === "back")
|
|
1525
|
+
return;
|
|
1526
|
+
const r = o.endsWith("project") ? "project" : "user";
|
|
1527
|
+
if (o.startsWith("unset")) {
|
|
1528
|
+
dt(e, t, r);
|
|
1529
|
+
return;
|
|
1530
|
+
}
|
|
1531
|
+
const i = await to(t);
|
|
1532
|
+
i !== void 0 && ut(e, t, i, r);
|
|
1533
|
+
}
|
|
1534
|
+
async function to(e) {
|
|
1535
|
+
const t = (r) => r === e.effective ? " (current)" : r === e.field.default ? " (default)" : "";
|
|
1536
|
+
if (e.field.type === "boolean")
|
|
1537
|
+
return O({
|
|
1538
|
+
message: `${e.path} =`,
|
|
1539
|
+
choices: [!0, !1].map((r) => ({
|
|
1540
|
+
name: `${r}${u.dim(t(r))}`,
|
|
1541
|
+
value: r
|
|
1542
|
+
}))
|
|
1543
|
+
});
|
|
1544
|
+
if (e.field.type === "enum")
|
|
1545
|
+
return O({
|
|
1546
|
+
message: `${e.path} =`,
|
|
1547
|
+
choices: (e.field.values ?? []).map((r) => ({
|
|
1548
|
+
name: `${r}${u.dim(t(r))}`,
|
|
1549
|
+
value: r
|
|
1550
|
+
}))
|
|
1551
|
+
});
|
|
1552
|
+
const n = await jt({
|
|
1553
|
+
message: `${e.path} = `,
|
|
1554
|
+
default: e.effective !== void 0 ? String(e.effective) : void 0,
|
|
1555
|
+
validate: (r) => {
|
|
1556
|
+
const i = te(e.field, r);
|
|
1557
|
+
return "error" in i ? i.error : !0;
|
|
1558
|
+
}
|
|
1559
|
+
}), o = te(e.field, n);
|
|
1560
|
+
return "error" in o ? void 0 : o.value;
|
|
1561
|
+
}
|
|
1562
|
+
function Se(e) {
|
|
1563
|
+
const t = se();
|
|
1564
|
+
return e.startsWith(t) ? `~${e.slice(t.length)}` : e;
|
|
1565
|
+
}
|
|
1566
|
+
function no(e, t) {
|
|
1567
|
+
const n = [];
|
|
1568
|
+
let o = "";
|
|
1569
|
+
for (const r of e.split(/\s+/))
|
|
1570
|
+
o && o.length + 1 + r.length > t ? (n.push(o), o = r) : o = o ? `${o} ${r}` : r;
|
|
1571
|
+
return o && n.push(o), n.join(`
|
|
1572
|
+
`);
|
|
1573
|
+
}
|
|
1574
|
+
function oo(e, t) {
|
|
1269
1575
|
if (t !== void 0) {
|
|
1270
|
-
const
|
|
1271
|
-
if (!
|
|
1272
|
-
const
|
|
1576
|
+
const n = e.find((o) => o.tag === t);
|
|
1577
|
+
if (!n) {
|
|
1578
|
+
const o = e.length > 0 ? e.map((r) => r.tag).join(", ") : "(none running)";
|
|
1273
1579
|
return {
|
|
1274
|
-
error: `no running aiui channel with tag "${t}" — running tags: ${
|
|
1580
|
+
error: `no running aiui channel with tag "${t}" — running tags: ${o}`
|
|
1275
1581
|
};
|
|
1276
1582
|
}
|
|
1277
|
-
return { server:
|
|
1583
|
+
return { server: n };
|
|
1278
1584
|
}
|
|
1279
1585
|
return e.length > 0 ? { select: e } : {};
|
|
1280
1586
|
}
|
|
1281
|
-
|
|
1282
|
-
|
|
1283
|
-
|
|
1284
|
-
|
|
1587
|
+
const ro = "vite";
|
|
1588
|
+
async function io(e = []) {
|
|
1589
|
+
const t = de(e), { mcp: n, tag: o, passthrough: r } = t, i = rt(r);
|
|
1590
|
+
if (i) {
|
|
1591
|
+
i === "help" ? uo() : console.log(`aiui ${he}`), await lo(r);
|
|
1285
1592
|
return;
|
|
1286
1593
|
}
|
|
1287
|
-
|
|
1288
|
-
|
|
1289
|
-
|
|
1290
|
-
|
|
1291
|
-
|
|
1292
|
-
|
|
1293
|
-
let c;
|
|
1294
|
-
s ? (c = String(s.port), console.error(
|
|
1295
|
-
g.dim(
|
|
1296
|
-
`aiui: connecting vite to channel "${s.tag}" (${s.cwd}) on port ${c} via ${K}`
|
|
1297
|
-
)
|
|
1298
|
-
)) : console.error(g.dim(`aiui: no running channel found — ${K} left unset`));
|
|
1299
|
-
const u = Le();
|
|
1300
|
-
if (!u)
|
|
1594
|
+
(n !== void 0 || o !== void 0) && $(
|
|
1595
|
+
"aiui vite no longer connects the app to a channel",
|
|
1596
|
+
"--aiui-mcp / --aiui-tag are ignored. The app reaches the channel through the intent client served at /intent/, not a build-time port. (The standalone panel's own `pnpm dev` still selects a channel — that page is served on Vite's origin, not the channel's.)"
|
|
1597
|
+
);
|
|
1598
|
+
const s = ft();
|
|
1599
|
+
if (!s)
|
|
1301
1600
|
return;
|
|
1302
|
-
const
|
|
1303
|
-
|
|
1601
|
+
const c = {};
|
|
1602
|
+
process.stdout.isTTY && !("FORCE_COLOR" in process.env) && !("NO_COLOR" in process.env) && (c.FORCE_COLOR = "1");
|
|
1603
|
+
const a = T(s.command, [...s.args, ...r], {
|
|
1604
|
+
stdio: ["inherit", "pipe", "inherit"],
|
|
1605
|
+
buffer: !1,
|
|
1304
1606
|
reject: !1,
|
|
1305
|
-
|
|
1607
|
+
env: c
|
|
1608
|
+
});
|
|
1609
|
+
a.stdout && co(a.stdout, process.stdout, (p) => {
|
|
1610
|
+
ht(p, t);
|
|
1306
1611
|
});
|
|
1307
|
-
|
|
1612
|
+
const l = await a;
|
|
1613
|
+
l.exitCode && (process.exitCode = l.exitCode);
|
|
1614
|
+
}
|
|
1615
|
+
const so = /\x1b\[[0-9;?]*[ -/]*[@-~]/g;
|
|
1616
|
+
function ao(e) {
|
|
1617
|
+
const n = e.replace(so, "").match(
|
|
1618
|
+
/\bLocal:\s+(https?:\/\/(?:localhost|127\.0\.0\.1|\[::1\])(?::\d+)?\/?\S*)/
|
|
1619
|
+
);
|
|
1620
|
+
return n == null ? void 0 : n[1];
|
|
1621
|
+
}
|
|
1622
|
+
function co(e, t, n) {
|
|
1623
|
+
let o = "", r = !1;
|
|
1624
|
+
e.on("data", (i) => {
|
|
1625
|
+
if (t.write(i), !r) {
|
|
1626
|
+
for (o += i.toString(); ; ) {
|
|
1627
|
+
const s = o.indexOf(`
|
|
1628
|
+
`);
|
|
1629
|
+
if (s === -1)
|
|
1630
|
+
break;
|
|
1631
|
+
const c = o.slice(0, s);
|
|
1632
|
+
o = o.slice(s + 1);
|
|
1633
|
+
const a = ao(c);
|
|
1634
|
+
if (a) {
|
|
1635
|
+
r = !0, o = "", n(a);
|
|
1636
|
+
return;
|
|
1637
|
+
}
|
|
1638
|
+
}
|
|
1639
|
+
o.length > 8192 && (o = o.slice(-8192));
|
|
1640
|
+
}
|
|
1641
|
+
});
|
|
1642
|
+
}
|
|
1643
|
+
async function ht(e, t) {
|
|
1644
|
+
try {
|
|
1645
|
+
const n = {
|
|
1646
|
+
...S().chrome,
|
|
1647
|
+
...t.browserUrl ? { browserUrl: t.browserUrl } : {}
|
|
1648
|
+
}, o = vt(t, n);
|
|
1649
|
+
if (o.kind === "skip")
|
|
1650
|
+
return;
|
|
1651
|
+
if (o.kind === "hint") {
|
|
1652
|
+
w(
|
|
1653
|
+
`detected a headless environment (${o.reason}) — not opening a browser`,
|
|
1654
|
+
`Assuming the dev server's port is already forwarded, open ${e} in the browser
|
|
1655
|
+
on your local machine. (Pass --aiui-browser to open one here anyway.)`
|
|
1656
|
+
);
|
|
1657
|
+
return;
|
|
1658
|
+
}
|
|
1659
|
+
if (n.browserUrl) {
|
|
1660
|
+
await R(n.browserUrl, e), console.error(u.dim(`aiui: opened ${e} in the browser at ${n.browserUrl}`));
|
|
1661
|
+
return;
|
|
1662
|
+
}
|
|
1663
|
+
const r = x(t, n), i = await U(r.userDataDir);
|
|
1664
|
+
i ? (await R(i.browserUrl, e), console.error(u.dim(`aiui: opened ${e} in the session browser`))) : (await nt({
|
|
1665
|
+
flags: t,
|
|
1666
|
+
config: n,
|
|
1667
|
+
interactive: !1,
|
|
1668
|
+
startUrl: e
|
|
1669
|
+
}), console.error(u.dim(`aiui: opened ${e} in a new session browser`)));
|
|
1670
|
+
} catch (n) {
|
|
1671
|
+
$(
|
|
1672
|
+
"couldn't open the app in the session browser — the dev server is unaffected",
|
|
1673
|
+
n instanceof Error ? n.message : String(n)
|
|
1674
|
+
);
|
|
1675
|
+
}
|
|
1308
1676
|
}
|
|
1309
|
-
function
|
|
1677
|
+
function ft() {
|
|
1310
1678
|
try {
|
|
1311
|
-
return
|
|
1679
|
+
return J(ro);
|
|
1312
1680
|
} catch {
|
|
1313
|
-
|
|
1681
|
+
b(
|
|
1314
1682
|
"Vite is not available",
|
|
1315
1683
|
"`vite` should be installed as a dependency of aiui — try reinstalling."
|
|
1316
1684
|
), process.exitCode = 1;
|
|
1317
1685
|
return;
|
|
1318
1686
|
}
|
|
1319
1687
|
}
|
|
1320
|
-
async function
|
|
1321
|
-
const t =
|
|
1688
|
+
async function lo(e) {
|
|
1689
|
+
const t = ft();
|
|
1322
1690
|
if (!t)
|
|
1323
1691
|
return;
|
|
1324
|
-
const
|
|
1692
|
+
const n = await T(t.command, [...t.args, ...e], {
|
|
1325
1693
|
stdio: "inherit",
|
|
1326
1694
|
reject: !1
|
|
1327
1695
|
});
|
|
1328
|
-
|
|
1696
|
+
n.exitCode && (process.exitCode = n.exitCode);
|
|
1329
1697
|
}
|
|
1330
|
-
function
|
|
1331
|
-
console.log(`aiui vite — launch Vite
|
|
1698
|
+
function uo() {
|
|
1699
|
+
console.log(`aiui vite — launch Vite and open the app in the session browser
|
|
1332
1700
|
|
|
1333
1701
|
aiui's own flags (everything else forwards to vite verbatim):
|
|
1334
|
-
--aiui-
|
|
1335
|
-
|
|
1702
|
+
--aiui-browser open the app in the session browser even when
|
|
1703
|
+
the environment looks headless (CI, SSH, no display)
|
|
1704
|
+
--aiui-no-browser never open a browser for this run
|
|
1705
|
+
--aiui-chrome-profile <name> browser profile at .aiui-cache/chrome/<name>
|
|
1706
|
+
--aiui-chrome-data-dir <path> explicit browser user data dir
|
|
1707
|
+
|
|
1708
|
+
When Vite prints its Local: URL, aiui opens it in the shared session browser
|
|
1709
|
+
(the one \`aiui claude\` and \`aiui open\` use); in headless environments it
|
|
1710
|
+
prints the URL to open on your own machine instead.
|
|
1336
1711
|
|
|
1337
|
-
The
|
|
1338
|
-
|
|
1339
|
-
|
|
1712
|
+
The app reaches the aiui channel through the intent client served at /intent/,
|
|
1713
|
+
not through this command — so there is no channel to pick here. (The standalone
|
|
1714
|
+
intent panel, served on Vite's own origin, is the exception: its \`pnpm dev\`
|
|
1715
|
+
selects a channel itself.) What follows is vite's own --help:
|
|
1340
1716
|
`);
|
|
1341
1717
|
}
|
|
1342
|
-
function
|
|
1343
|
-
const
|
|
1344
|
-
|
|
1718
|
+
async function ho(e = {}) {
|
|
1719
|
+
const t = oo(M(), e.mcp);
|
|
1720
|
+
if (t.error) {
|
|
1721
|
+
b("Could not resolve an aiui channel", t.error), process.exitCode = 1;
|
|
1722
|
+
return;
|
|
1723
|
+
}
|
|
1724
|
+
const n = t.select ? await He(t.select) : t.server;
|
|
1725
|
+
if (!n) {
|
|
1726
|
+
console.log("No running aiui channel to open — start one with `aiui claude`."), process.exitCode = 1;
|
|
1727
|
+
return;
|
|
1728
|
+
}
|
|
1729
|
+
const o = `http://127.0.0.1:${n.port}/`;
|
|
1730
|
+
console.log(`${u.cyan("aiui debug")} — the channel console`), console.log(` ${u.bold(o)}`), console.log(
|
|
1731
|
+
u.dim(` channel "${n.tag}" (${n.cwd}) on port ${n.port}`) + u.dim(" — the dashboard links to the trace debugger at /__aiui/debug.")
|
|
1732
|
+
), e.open !== !1 && await ht(o, de([]));
|
|
1733
|
+
}
|
|
1734
|
+
const Ae = [".env", ".env.local", ".env.dev", ".env.dev.local"];
|
|
1735
|
+
function fo(e) {
|
|
1736
|
+
let t = e;
|
|
1737
|
+
for (; ; ) {
|
|
1738
|
+
if (v(d(t, "pnpm-workspace.yaml")) || v(d(t, ".git")))
|
|
1739
|
+
return t;
|
|
1740
|
+
const n = bt(t);
|
|
1741
|
+
if (n === t)
|
|
1742
|
+
return e;
|
|
1743
|
+
t = n;
|
|
1744
|
+
}
|
|
1745
|
+
}
|
|
1746
|
+
function po(e) {
|
|
1747
|
+
const t = /* @__PURE__ */ new Map();
|
|
1748
|
+
for (const n of e.split(`
|
|
1749
|
+
`)) {
|
|
1750
|
+
const o = n.trim();
|
|
1751
|
+
if (o === "" || o.startsWith("#"))
|
|
1752
|
+
continue;
|
|
1753
|
+
const r = /^(?:export\s+)?([A-Za-z_][A-Za-z0-9_]*)\s*=\s*(.*)$/.exec(o);
|
|
1754
|
+
if (!r)
|
|
1755
|
+
continue;
|
|
1756
|
+
let i = r[2].trim();
|
|
1757
|
+
i.length >= 2 && (i[0] === '"' || i[0] === "'") && i[i.length - 1] === i[0] && (i = i.slice(1, -1)), t.set(r[1], i);
|
|
1758
|
+
}
|
|
1759
|
+
return t;
|
|
1760
|
+
}
|
|
1761
|
+
function _e(e) {
|
|
1762
|
+
return `'${e.replace(/'/g, "'\\''")}'`;
|
|
1763
|
+
}
|
|
1764
|
+
function mo(e) {
|
|
1765
|
+
const t = [];
|
|
1766
|
+
t.push(
|
|
1767
|
+
// biome-ignore lint/suspicious/noTemplateCurlyInString: shell parameter expansion, not a JS template
|
|
1768
|
+
'if [ -z "${_AIUI_OLD_PATH:-}" ]; then _AIUI_OLD_PATH="$PATH"; export _AIUI_OLD_PATH; fi;'
|
|
1769
|
+
);
|
|
1770
|
+
for (const o of [...e.pathDirs].reverse()) {
|
|
1771
|
+
const r = _e(o);
|
|
1772
|
+
t.push(`case ":$PATH:" in *":"${r}":"*) : ;; *) PATH=${r}":$PATH"; export PATH ;; esac;`);
|
|
1773
|
+
}
|
|
1774
|
+
for (const [o, r] of e.vars)
|
|
1775
|
+
t.push(`export ${o}=${_e(r)};`);
|
|
1776
|
+
const n = e.vars.size > 0 ? ` unset ${[...e.vars.keys()].join(" ")};` : "";
|
|
1777
|
+
return t.push(
|
|
1778
|
+
`aiui_deactivate () { if [ -n "\${_AIUI_OLD_PATH:-}" ]; then PATH="$_AIUI_OLD_PATH"; export PATH; unset _AIUI_OLD_PATH; fi;${n} unset -f aiui_deactivate; };`
|
|
1779
|
+
), `${t.join(`
|
|
1780
|
+
`)}
|
|
1781
|
+
`;
|
|
1782
|
+
}
|
|
1783
|
+
function wo() {
|
|
1784
|
+
const e = process.cwd(), t = fo(e), n = [d(t, "bin"), d(t, "node_modules", ".bin")];
|
|
1785
|
+
e !== t && n.push(d(e, "node_modules", ".bin"));
|
|
1786
|
+
const o = n.filter((c) => v(c)), r = /* @__PURE__ */ new Map(), i = /* @__PURE__ */ new Map();
|
|
1787
|
+
for (const c of Ae) {
|
|
1788
|
+
const a = d(t, c);
|
|
1789
|
+
if (v(a))
|
|
1790
|
+
for (const [l, p] of po(L(a, "utf8")))
|
|
1791
|
+
r.set(l, p), i.set(l, c);
|
|
1792
|
+
}
|
|
1793
|
+
process.stdout.write(mo({ pathDirs: o, vars: r }));
|
|
1794
|
+
const s = [...r.keys()].map((c) => `${c} (${i.get(c)})`);
|
|
1795
|
+
process.stderr.write(
|
|
1796
|
+
u.dim(
|
|
1797
|
+
`aiui env: root ${t}
|
|
1798
|
+
aiui env: PATH + ${o.length > 0 ? o.join(", ") : "(nothing found)"}
|
|
1799
|
+
aiui env: export ${s.length > 0 ? s.join(", ") : `(none — no ${Ae.join("/")} at root)`}
|
|
1800
|
+
aiui env: activate with eval "$(aiui env)" — undo with aiui_deactivate
|
|
1801
|
+
`
|
|
1802
|
+
)
|
|
1803
|
+
);
|
|
1804
|
+
}
|
|
1805
|
+
const go = "@habemus-papadum/aiui-claude-channel";
|
|
1806
|
+
async function bo(e = []) {
|
|
1807
|
+
let t;
|
|
1808
|
+
try {
|
|
1809
|
+
t = J(go);
|
|
1810
|
+
} catch {
|
|
1811
|
+
b(
|
|
1812
|
+
"The aiui Claude channel CLI is not available",
|
|
1813
|
+
"`@habemus-papadum/aiui-claude-channel` should be installed as a dependency of aiui — try reinstalling."
|
|
1814
|
+
), process.exitCode = 1;
|
|
1815
|
+
return;
|
|
1816
|
+
}
|
|
1817
|
+
const n = at(e) ? wn(e, it({ config: S() })) : e, o = await T(t.command, [...t.args, ...n], {
|
|
1818
|
+
stdio: "inherit",
|
|
1819
|
+
reject: !1
|
|
1820
|
+
});
|
|
1821
|
+
o.exitCode && (process.exitCode = o.exitCode);
|
|
1822
|
+
}
|
|
1823
|
+
function yo(e) {
|
|
1824
|
+
const t = Buffer.from(JSON.stringify(e), "utf8"), n = Buffer.allocUnsafe(4 + t.length);
|
|
1825
|
+
return pt() ? n.writeUInt32LE(t.length, 0) : n.writeUInt32BE(t.length, 0), t.copy(n, 4), n;
|
|
1826
|
+
}
|
|
1827
|
+
function vo(e) {
|
|
1828
|
+
const t = [];
|
|
1829
|
+
let n = 0;
|
|
1830
|
+
for (; e.length - n >= 4; ) {
|
|
1831
|
+
const o = pt() ? e.readUInt32LE(n) : e.readUInt32BE(n);
|
|
1832
|
+
if (e.length - n - 4 < o)
|
|
1833
|
+
break;
|
|
1834
|
+
const r = e.subarray(n + 4, n + 4 + o);
|
|
1835
|
+
n += 4 + o;
|
|
1836
|
+
try {
|
|
1837
|
+
t.push(JSON.parse(r.toString("utf8")));
|
|
1838
|
+
} catch {
|
|
1839
|
+
t.push(void 0);
|
|
1840
|
+
}
|
|
1841
|
+
}
|
|
1842
|
+
return { messages: t, rest: e.subarray(n) };
|
|
1843
|
+
}
|
|
1844
|
+
function pt() {
|
|
1845
|
+
return new Uint8Array(new Uint32Array([1]).buffer)[0] === 1;
|
|
1846
|
+
}
|
|
1847
|
+
function $o(e) {
|
|
1848
|
+
const t = e !== null && typeof e == "object" ? e.cmd : void 0;
|
|
1849
|
+
return t === "ping" ? { ok: !0, at: (/* @__PURE__ */ new Date()).toISOString() } : t === "version" ? { ok: !0, version: 1 } : t === "listChannels" ? { ok: !0, channels: M().map((o) => ({
|
|
1850
|
+
tag: o.tag,
|
|
1851
|
+
port: o.port,
|
|
1852
|
+
pid: o.pid,
|
|
1853
|
+
cwd: o.cwd,
|
|
1854
|
+
startedAt: o.startedAt,
|
|
1855
|
+
...o.name !== void 0 ? { name: o.name } : {},
|
|
1856
|
+
...o.debug === !0 ? { debug: !0 } : {}
|
|
1857
|
+
})) } : { ok: !1, error: `unknown cmd ${JSON.stringify(t)}` };
|
|
1858
|
+
}
|
|
1859
|
+
async function Co() {
|
|
1860
|
+
let e = Buffer.alloc(0);
|
|
1861
|
+
process.stdin.on("data", (t) => {
|
|
1862
|
+
e = Buffer.concat([e, t]);
|
|
1863
|
+
const { messages: n, rest: o } = vo(e);
|
|
1864
|
+
e = o;
|
|
1865
|
+
for (const r of n) {
|
|
1866
|
+
let i;
|
|
1867
|
+
try {
|
|
1868
|
+
i = $o(r);
|
|
1869
|
+
} catch (s) {
|
|
1870
|
+
i = { ok: !1, error: s instanceof Error ? s.message : String(s) };
|
|
1871
|
+
}
|
|
1872
|
+
process.stdout.write(yo(i));
|
|
1873
|
+
}
|
|
1874
|
+
}), await new Promise((t) => {
|
|
1875
|
+
process.stdin.on("end", t), process.stdin.on("close", t);
|
|
1876
|
+
});
|
|
1877
|
+
}
|
|
1878
|
+
function ko() {
|
|
1879
|
+
const e = [];
|
|
1880
|
+
for (const t of Object.values(Ge()))
|
|
1881
|
+
for (const n of t ?? [])
|
|
1882
|
+
n.family === "IPv4" && !n.internal && e.push(n.address);
|
|
1883
|
+
return e;
|
|
1884
|
+
}
|
|
1885
|
+
async function H(e, t) {
|
|
1886
|
+
try {
|
|
1887
|
+
const n = await fetch(`http://127.0.0.1:${e}${t}`, {
|
|
1888
|
+
signal: AbortSignal.timeout(1500)
|
|
1889
|
+
});
|
|
1890
|
+
return n.ok ? await n.json() : void 0;
|
|
1891
|
+
} catch {
|
|
1892
|
+
return;
|
|
1893
|
+
}
|
|
1894
|
+
}
|
|
1895
|
+
async function xo(e, t) {
|
|
1896
|
+
const n = await H(
|
|
1897
|
+
e,
|
|
1898
|
+
`${t}/info`
|
|
1899
|
+
);
|
|
1900
|
+
if (!(n != null && n.ok))
|
|
1901
|
+
return;
|
|
1902
|
+
const o = await H(e, "/health"), r = (o == null ? void 0 : o.host) !== void 0 && o.host !== "127.0.0.1";
|
|
1903
|
+
return {
|
|
1904
|
+
lan: r,
|
|
1905
|
+
urls: r ? ko().map((i) => `http://${i}:${e}${t}/`) : [`http://127.0.0.1:${e}${t}/`],
|
|
1906
|
+
hosts: n.hosts ?? 0,
|
|
1907
|
+
clients: n.clients ?? 0
|
|
1908
|
+
};
|
|
1909
|
+
}
|
|
1910
|
+
function To(e) {
|
|
1911
|
+
const t = { name: "loopback", address: "127.0.0.1" };
|
|
1912
|
+
if (e === void 0 || e === "127.0.0.1")
|
|
1913
|
+
return [t];
|
|
1914
|
+
const n = [];
|
|
1915
|
+
for (const [o, r] of Object.entries(Ge()))
|
|
1916
|
+
for (const i of r ?? [])
|
|
1917
|
+
i.family === "IPv4" && !i.internal && n.push({ name: o, address: i.address });
|
|
1918
|
+
return [...n, t];
|
|
1919
|
+
}
|
|
1920
|
+
async function Io(e) {
|
|
1921
|
+
if (process.platform !== "darwin")
|
|
1922
|
+
return !1;
|
|
1923
|
+
try {
|
|
1924
|
+
return await T("pbcopy", { input: e }), !0;
|
|
1925
|
+
} catch {
|
|
1926
|
+
return !1;
|
|
1927
|
+
}
|
|
1928
|
+
}
|
|
1929
|
+
function Eo(e, t) {
|
|
1930
|
+
var n;
|
|
1931
|
+
return e.name ?? ((n = t.get(e.ppid)) == null ? void 0 : n.name) ?? e.cwd;
|
|
1932
|
+
}
|
|
1933
|
+
function Po(e = {}) {
|
|
1934
|
+
return e.json ? Ao("/pencil") : Do("/pencil", "pencil");
|
|
1935
|
+
}
|
|
1936
|
+
async function Do(e, t) {
|
|
1937
|
+
const n = M();
|
|
1938
|
+
if (n.length === 0) {
|
|
1939
|
+
So(t);
|
|
1940
|
+
return;
|
|
1941
|
+
}
|
|
1942
|
+
const o = await He(n), r = await H(o.port, `${e}/info`);
|
|
1943
|
+
if (!(r != null && r.ok)) {
|
|
1944
|
+
console.log(
|
|
1945
|
+
`${u.bold(Eo(o, Fe(Ve())))} is not hosting the ${t} surface.`
|
|
1946
|
+
), process.exitCode = 1;
|
|
1947
|
+
return;
|
|
1948
|
+
}
|
|
1949
|
+
const i = await H(o.port, "/health"), s = To(i == null ? void 0 : i.host), c = (i == null ? void 0 : i.host) !== void 0 && i.host !== "127.0.0.1", l = `http://${(s.length === 1 ? s[0] : await O({
|
|
1950
|
+
message: "Which host interface should the iPad reach the channel on?",
|
|
1951
|
+
choices: s.map((f) => ({
|
|
1952
|
+
name: `${f.address} ${u.dim(`(${f.name})`)}`,
|
|
1953
|
+
value: f
|
|
1954
|
+
}))
|
|
1955
|
+
})).address}:${o.port}${e}/`, p = await Io(l);
|
|
1956
|
+
console.log(""), console.log(` ${u.cyan(l)}`), console.log(""), p ? (console.log(u.dim(" Copied to your clipboard.")), console.log(
|
|
1957
|
+
u.dim(" Use Universal Clipboard (⌘V on the iPad) to paste it into Safari there.")
|
|
1958
|
+
)) : console.log(u.dim(" (Copy it to the iPad however you like.)")), c || console.log(
|
|
1959
|
+
u.dim(
|
|
1960
|
+
" This channel is loopback-only: the iPad needs a tunnel to this port (Tailscale, ssh -L), or relaunch with --aiui-bind host."
|
|
1961
|
+
)
|
|
1962
|
+
), console.log("");
|
|
1963
|
+
}
|
|
1964
|
+
function So(e) {
|
|
1965
|
+
console.log(`No running channel is hosting the ${e} surface.`), console.log(""), console.log(`Every channel hosts it — start a session with ${u.cyan("aiui claude")} (or a`), console.log(
|
|
1966
|
+
`standalone ${u.cyan("aiui mcp serve")}), then run this again to reach the ${e} surface.`
|
|
1967
|
+
), process.exitCode = 1;
|
|
1968
|
+
}
|
|
1969
|
+
async function Ao(e, t) {
|
|
1970
|
+
var i;
|
|
1971
|
+
const n = M(), o = n.length > 0 ? Fe(Ve()) : /* @__PURE__ */ new Map(), r = [];
|
|
1972
|
+
for (const s of n) {
|
|
1973
|
+
const c = await xo(s.port, e);
|
|
1974
|
+
if (c) {
|
|
1975
|
+
const a = s.name ?? ((i = o.get(s.ppid)) == null ? void 0 : i.name);
|
|
1976
|
+
r.push({
|
|
1977
|
+
cwd: s.cwd,
|
|
1978
|
+
pid: s.pid,
|
|
1979
|
+
port: s.port,
|
|
1980
|
+
...a !== void 0 ? { session: a } : {},
|
|
1981
|
+
...c
|
|
1982
|
+
});
|
|
1983
|
+
}
|
|
1984
|
+
}
|
|
1985
|
+
console.log(JSON.stringify({ targets: r }, null, 2));
|
|
1986
|
+
}
|
|
1987
|
+
function _o() {
|
|
1988
|
+
const e = new wt();
|
|
1989
|
+
e.name("aiui").description("ai ui frontends — thin launchers for Claude, Vite, and the channel CLI").version(he).enablePositionalOptions(), e.command("claude").description("launch Claude (extra args are forwarded, e.g. `aiui claude --resume`)").allowUnknownOption().allowExcessArguments().helpOption(!1).argument("[args...]", "arguments forwarded to claude").action((o) => Rn(o)), e.command("vite").description("launch Vite (extra args are forwarded, e.g. `aiui vite dev`)").allowUnknownOption().allowExcessArguments().helpOption(!1).argument("[args...]", "arguments forwarded to vite").action((o) => io(o)), e.command("debug").description("open the channel console (dashboard + trace debugger) in the session browser").option("--mcp <tag>", "target a channel by registry tag (skips the selector)").option("--no-open", "print the URL but don't open the browser").action((o) => ho(o)), e.command("chrome").description("manage the agent's browser: install | update | status").argument("<action>", "install | update | status").action((o) => un([o])), e.command("browser").description(
|
|
1345
1990
|
"start (or find) the shared session browser; --tunnel does the whole remote-dev local half"
|
|
1346
1991
|
).option(
|
|
1347
1992
|
"--profile <name>",
|
|
@@ -1349,9 +1994,13 @@ function mo() {
|
|
|
1349
1994
|
).option("--data-dir <path>", "explicit Chrome user data dir").option("--port <port>", "fixed local DevTools debug port (default: OS-assigned)").option("--headless", "launch with no UI").option("--open <url>", "also open this URL in it").option(
|
|
1350
1995
|
"--tunnel <[user@]host>",
|
|
1351
1996
|
"reverse-tunnel the debug port to this host (Ctrl-C closes it)"
|
|
1352
|
-
).option("--remote-port <port>", "fixed port on the tunnel's remote side (default: 9222)").action((
|
|
1997
|
+
).option("--remote-port <port>", "fixed port on the tunnel's remote side (default: 9222)").action((o) => nn(o)), e.command("extension").description("the intent client extension's native host: install-native-host | status").argument("<action>", "install-native-host | status").option("--extension-id <id>", "extension id for allowed_origins (default: the pinned id)").action((o, r) => Xt(o, r)), e.command("native-host", { hidden: !0 }).description("(internal) Chrome native-messaging host — spawned by the browser").action(() => Co()), e.command("clean").description(
|
|
1998
|
+
"reset aiui state (project + user cache, incl. Chrome for Testing) for a clean-slate demo"
|
|
1999
|
+
).option("--project-only", "only this repo's .aiui-cache/").option("--user-only", "only the user cache (~/.cache/aiui)").option("--keep-browser", "keep Chrome for Testing (skip the ~160 MB re-download)").option("-n, --dry-run", "print what would be deleted, then stop").option("-y, --yes", "delete without the confirmation prompt").action((o) => Wn(o)), e.command("open").description("open a URL in the session browser, e.g. `aiui open http://localhost:5173`").argument("<url>", "the URL to open").option("--profile <name>", "named profile under .aiui-cache/chrome/").option("--data-dir <path>", "explicit Chrome user data dir").action((o, r) => ln(o, r)), e.command("env").description('print shell code to activate this checkout — use as: eval "$(aiui env)"').action(() => wo());
|
|
2000
|
+
const t = e.command("config").description("inspect and edit aiui's config.json — tui | show | get | set | unset").action(() => Pe());
|
|
2001
|
+
return t.command("tui").description("browse every setting interactively: docs, defaults, current values, editing").action(() => Pe()), t.command("show").description("every key with its effective value and which file set it").option("--json", "machine-readable: file paths, per-level values, effective merge").action((o) => qn(o)), t.command("get").description("print a key's effective value (provenance goes to stderr)").argument("<key>", 'dotted key, e.g. "chrome.mode"').action((o) => zn(o)), t.command("set").description("set a key in the user config (or the project's with --project)").argument("<key>", 'dotted key, e.g. "chrome.mode"').argument("<value>", "the new value, validated against the schema").option("--project", "write .aiui-cache/config.json here instead of the user config").action((o, r, i) => Jn(o, r, i)), t.command("unset").description("remove a key from the user config (or the project's with --project)").argument("<key>", 'dotted key, e.g. "claude.skipPermissions"').option("--project", "remove from .aiui-cache/config.json here instead of the user config").action((o, r) => Xn(o, r)), e.command("mcp").description("run a channel command (forwards to aiui-claude-channel), e.g. `aiui mcp quick`").allowUnknownOption().allowExcessArguments().helpOption(!1).argument("[args...]", "arguments forwarded to the aiui-claude-channel CLI").action((o) => bo(o)), e.command("pencil").description("the remote pencil — url (where the iPad should connect)").command("url").description("pick a channel + interface, print the iPad URL and copy it to the clipboard").option("--json", "machine-readable targets (every hosting channel, no prompts)").action((o) => Po(o)), e;
|
|
1353
2002
|
}
|
|
1354
|
-
|
|
2003
|
+
_o().parseAsync().catch((e) => {
|
|
1355
2004
|
console.error(e instanceof Error ? e.message : e), process.exitCode = 1;
|
|
1356
2005
|
});
|
|
1357
2006
|
//# sourceMappingURL=cli.js.map
|