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