@openacp/cli 0.6.3 → 0.6.5
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/adapter-YSEIZJBA.js +798 -0
- package/dist/adapter-YSEIZJBA.js.map +1 -0
- package/dist/{admin-3ZHEO5VP.js → admin-SCP25TN2.js} +3 -3
- package/dist/agent-catalog-SBZQRYOD.js +10 -0
- package/dist/agent-store-CGE4G6PA.js +8 -0
- package/dist/{agents-SXIY4IEF.js → agents-QJPHNWK2.js} +3 -3
- package/dist/{autostart-A7JRU4WJ.js → autostart-6M3FZAKW.js} +3 -3
- package/dist/{chunk-PMGNLNSH.js → chunk-2CJ46J3C.js} +2 -2
- package/dist/{chunk-5HGXUCMX.js → chunk-34M4OS5P.js} +2 -2
- package/dist/{chunk-AVCHZESZ.js → chunk-3IRAWHMC.js} +49 -20
- package/dist/chunk-3IRAWHMC.js.map +1 -0
- package/dist/{chunk-EWYNCHUH.js → chunk-3ZO3MHZN.js} +22 -3
- package/dist/chunk-3ZO3MHZN.js.map +1 -0
- package/dist/{chunk-TTDSLV35.js → chunk-4CTX774K.js} +3 -3
- package/dist/chunk-4GQ3I65A.js +23 -0
- package/dist/chunk-4GQ3I65A.js.map +1 -0
- package/dist/{chunk-NXEQXRQR.js → chunk-774Y4RAK.js} +2 -2
- package/dist/{chunk-6LSFRNHE.js → chunk-7KZI2236.js} +3 -3
- package/dist/{chunk-SM3G6UAX.js → chunk-BNLGTZ34.js} +2 -2
- package/dist/{chunk-FMWSVLRM.js → chunk-FCLGYYTY.js} +1 -21
- package/dist/chunk-FCLGYYTY.js.map +1 -0
- package/dist/chunk-FEWSQT3U.js +3949 -0
- package/dist/chunk-FEWSQT3U.js.map +1 -0
- package/dist/{chunk-HP2IJYCA.js → chunk-FW6HM4VU.js} +91 -4030
- package/dist/chunk-FW6HM4VU.js.map +1 -0
- package/dist/{chunk-ESOPMQAY.js → chunk-GAK6PIBW.js} +25 -2
- package/dist/chunk-GAK6PIBW.js.map +1 -0
- package/dist/{chunk-3KGRVAEV.js → chunk-J4SJTKIK.js} +2 -2
- package/dist/{chunk-FZ5BIWG5.js → chunk-JV6XQRAE.js} +4 -4
- package/dist/{chunk-OHR6SBMC.js → chunk-PJVKOZTR.js} +3 -3
- package/dist/{chunk-EVFJW45N.js → chunk-S64CB6J3.js} +13 -13
- package/dist/{chunk-EVFJW45N.js.map → chunk-S64CB6J3.js.map} +1 -1
- package/dist/{chunk-CKOK7JW6.js → chunk-UKT3G5IA.js} +3 -3
- package/dist/{chunk-PWFPTG5X.js → chunk-V5GZQEIY.js} +2 -2
- package/dist/{chunk-KO5RL7MZ.js → chunk-WVMSP4AF.js} +2 -2
- package/dist/{chunk-TMCQZAXN.js → chunk-XVL6AGMG.js} +3 -3
- package/dist/{chunk-IER5UCY7.js → chunk-YQRF3IOR.js} +2 -2
- package/dist/{chunk-G3OHCXZG.js → chunk-ZKTIZME6.js} +194 -133
- package/dist/chunk-ZKTIZME6.js.map +1 -0
- package/dist/cli.js +54 -44
- package/dist/cli.js.map +1 -1
- package/dist/{config-4YSJ4NCI.js → config-B26J3XXN.js} +3 -3
- package/dist/config-editor-QTGUK3CD.js +12 -0
- package/dist/{daemon-I6XMRQ6P.js → daemon-5DS5BQXJ.js} +4 -4
- package/dist/{discord-VHCBN3JJ.js → discord-QKT3JMRW.js} +28 -26
- package/dist/{discord-VHCBN3JJ.js.map → discord-QKT3JMRW.js.map} +1 -1
- package/dist/doctor-6SUCVUZB.js +9 -0
- package/dist/doctor-QQ3YZEYV.js +14 -0
- package/dist/index.d.ts +166 -11
- package/dist/index.js +17 -14
- package/dist/{install-cloudflared-G2GUKCHA.js → install-cloudflared-FSILDS5J.js} +3 -3
- package/dist/{install-jq-7QTU7XYY.js → install-jq-P6RUBKPV.js} +3 -3
- package/dist/{log-SPS2S6FO.js → log-RCVBXLTN.js} +8 -4
- package/dist/{main-P4X6SAPZ.js → main-TSZR4HPP.js} +57 -29
- package/dist/main-TSZR4HPP.js.map +1 -0
- package/dist/{new-session-PUNUHGYP.js → new-session-K6UCWYOP.js} +5 -5
- package/dist/{post-upgrade-6N4JCV5S.js → post-upgrade-62LUHDJO.js} +5 -5
- package/dist/{session-ZMAM67AA.js → session-O6ZPLJIZ.js} +4 -4
- package/dist/{settings-OEQEZS5Y.js → settings-RRF77IC4.js} +3 -3
- package/dist/{setup-7YBFKRG7.js → setup-5ZKSUR26.js} +4 -4
- package/dist/{tunnel-service-BMIBHUBK.js → tunnel-service-NJJH4I26.js} +3 -3
- package/dist/{version-ALWGGVKM.js → version-AXXV6IV2.js} +2 -2
- package/package.json +6 -1
- package/dist/agent-catalog-IVU2KANH.js +0 -10
- package/dist/agent-store-ZBXGOFPH.js +0 -8
- package/dist/chunk-AVCHZESZ.js.map +0 -1
- package/dist/chunk-ESOPMQAY.js.map +0 -1
- package/dist/chunk-EWYNCHUH.js.map +0 -1
- package/dist/chunk-FMWSVLRM.js.map +0 -1
- package/dist/chunk-G3OHCXZG.js.map +0 -1
- package/dist/chunk-HP2IJYCA.js.map +0 -1
- package/dist/config-editor-F25HEMGL.js +0 -12
- package/dist/doctor-GPW5ECK6.js +0 -14
- package/dist/doctor-Y3SCSVPI.js +0 -9
- package/dist/main-P4X6SAPZ.js.map +0 -1
- /package/dist/{admin-3ZHEO5VP.js.map → admin-SCP25TN2.js.map} +0 -0
- /package/dist/{agent-catalog-IVU2KANH.js.map → agent-catalog-SBZQRYOD.js.map} +0 -0
- /package/dist/{agent-store-ZBXGOFPH.js.map → agent-store-CGE4G6PA.js.map} +0 -0
- /package/dist/{agents-SXIY4IEF.js.map → agents-QJPHNWK2.js.map} +0 -0
- /package/dist/{autostart-A7JRU4WJ.js.map → autostart-6M3FZAKW.js.map} +0 -0
- /package/dist/{chunk-PMGNLNSH.js.map → chunk-2CJ46J3C.js.map} +0 -0
- /package/dist/{chunk-5HGXUCMX.js.map → chunk-34M4OS5P.js.map} +0 -0
- /package/dist/{chunk-TTDSLV35.js.map → chunk-4CTX774K.js.map} +0 -0
- /package/dist/{chunk-NXEQXRQR.js.map → chunk-774Y4RAK.js.map} +0 -0
- /package/dist/{chunk-6LSFRNHE.js.map → chunk-7KZI2236.js.map} +0 -0
- /package/dist/{chunk-SM3G6UAX.js.map → chunk-BNLGTZ34.js.map} +0 -0
- /package/dist/{chunk-3KGRVAEV.js.map → chunk-J4SJTKIK.js.map} +0 -0
- /package/dist/{chunk-FZ5BIWG5.js.map → chunk-JV6XQRAE.js.map} +0 -0
- /package/dist/{chunk-OHR6SBMC.js.map → chunk-PJVKOZTR.js.map} +0 -0
- /package/dist/{chunk-CKOK7JW6.js.map → chunk-UKT3G5IA.js.map} +0 -0
- /package/dist/{chunk-PWFPTG5X.js.map → chunk-V5GZQEIY.js.map} +0 -0
- /package/dist/{chunk-KO5RL7MZ.js.map → chunk-WVMSP4AF.js.map} +0 -0
- /package/dist/{chunk-TMCQZAXN.js.map → chunk-XVL6AGMG.js.map} +0 -0
- /package/dist/{chunk-IER5UCY7.js.map → chunk-YQRF3IOR.js.map} +0 -0
- /package/dist/{config-4YSJ4NCI.js.map → config-B26J3XXN.js.map} +0 -0
- /package/dist/{config-editor-F25HEMGL.js.map → config-editor-QTGUK3CD.js.map} +0 -0
- /package/dist/{daemon-I6XMRQ6P.js.map → daemon-5DS5BQXJ.js.map} +0 -0
- /package/dist/{doctor-GPW5ECK6.js.map → doctor-6SUCVUZB.js.map} +0 -0
- /package/dist/{doctor-Y3SCSVPI.js.map → doctor-QQ3YZEYV.js.map} +0 -0
- /package/dist/{install-cloudflared-G2GUKCHA.js.map → install-cloudflared-FSILDS5J.js.map} +0 -0
- /package/dist/{install-jq-7QTU7XYY.js.map → install-jq-P6RUBKPV.js.map} +0 -0
- /package/dist/{log-SPS2S6FO.js.map → log-RCVBXLTN.js.map} +0 -0
- /package/dist/{new-session-PUNUHGYP.js.map → new-session-K6UCWYOP.js.map} +0 -0
- /package/dist/{post-upgrade-6N4JCV5S.js.map → post-upgrade-62LUHDJO.js.map} +0 -0
- /package/dist/{session-ZMAM67AA.js.map → session-O6ZPLJIZ.js.map} +0 -0
- /package/dist/{settings-OEQEZS5Y.js.map → settings-RRF77IC4.js.map} +0 -0
- /package/dist/{setup-7YBFKRG7.js.map → setup-5ZKSUR26.js.map} +0 -0
- /package/dist/{tunnel-service-BMIBHUBK.js.map → tunnel-service-NJJH4I26.js.map} +0 -0
- /package/dist/{version-ALWGGVKM.js.map → version-AXXV6IV2.js.map} +0 -0
|
@@ -3,11 +3,18 @@ import {
|
|
|
3
3
|
} from "./chunk-JKBFUAJK.js";
|
|
4
4
|
import {
|
|
5
5
|
expandHome
|
|
6
|
-
} from "./chunk-
|
|
6
|
+
} from "./chunk-3ZO3MHZN.js";
|
|
7
7
|
|
|
8
8
|
// src/core/setup.ts
|
|
9
9
|
import { execFileSync } from "child_process";
|
|
10
|
-
import
|
|
10
|
+
import * as clack from "@clack/prompts";
|
|
11
|
+
function guardCancel(value) {
|
|
12
|
+
if (clack.isCancel(value)) {
|
|
13
|
+
clack.cancel("Setup cancelled.");
|
|
14
|
+
process.exit(0);
|
|
15
|
+
}
|
|
16
|
+
return value;
|
|
17
|
+
}
|
|
11
18
|
var c = {
|
|
12
19
|
reset: "\x1B[0m",
|
|
13
20
|
bold: "\x1B[1m",
|
|
@@ -101,15 +108,18 @@ async function validateBotAdmin(token, chatId) {
|
|
|
101
108
|
return { ok: false, error: err.message };
|
|
102
109
|
}
|
|
103
110
|
}
|
|
104
|
-
function promptManualChatId() {
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
111
|
+
async function promptManualChatId() {
|
|
112
|
+
const val = guardCancel(
|
|
113
|
+
await clack.text({
|
|
114
|
+
message: "Supergroup chat ID (e.g. -1001234567890):",
|
|
115
|
+
validate: (val2) => {
|
|
116
|
+
const n = Number((val2 ?? "").toString().trim());
|
|
117
|
+
if (isNaN(n) || !Number.isInteger(n)) return "Chat ID must be an integer";
|
|
118
|
+
return void 0;
|
|
119
|
+
}
|
|
120
|
+
})
|
|
121
|
+
);
|
|
122
|
+
return Number(val.trim());
|
|
113
123
|
}
|
|
114
124
|
async function detectChatId(token) {
|
|
115
125
|
let lastUpdateId = 0;
|
|
@@ -191,14 +201,16 @@ async function detectChatId(token) {
|
|
|
191
201
|
}
|
|
192
202
|
if (groups.size > 1) {
|
|
193
203
|
cleanup();
|
|
194
|
-
const
|
|
195
|
-
|
|
204
|
+
const options = [...groups.entries()].map(([id, title]) => ({
|
|
205
|
+
label: `${title} (${id})`,
|
|
196
206
|
value: id
|
|
197
207
|
}));
|
|
198
|
-
return
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
208
|
+
return guardCancel(
|
|
209
|
+
await clack.select({
|
|
210
|
+
message: "Multiple groups found. Pick one:",
|
|
211
|
+
options
|
|
212
|
+
})
|
|
213
|
+
);
|
|
202
214
|
}
|
|
203
215
|
} catch {
|
|
204
216
|
}
|
|
@@ -245,24 +257,31 @@ async function setupTelegram(stepNum = 1, totalSteps = 3) {
|
|
|
245
257
|
console.log(step(stepNum, totalSteps, "Telegram Bot"));
|
|
246
258
|
let botToken = "";
|
|
247
259
|
while (true) {
|
|
248
|
-
botToken =
|
|
249
|
-
|
|
250
|
-
|
|
251
|
-
|
|
260
|
+
botToken = guardCancel(
|
|
261
|
+
await clack.text({
|
|
262
|
+
message: "Bot token (from @BotFather):",
|
|
263
|
+
validate: (val) => (val ?? "").toString().trim().length > 0 ? void 0 : "Token cannot be empty"
|
|
264
|
+
})
|
|
265
|
+
);
|
|
252
266
|
botToken = botToken.trim();
|
|
267
|
+
const s = clack.spinner();
|
|
268
|
+
s.start("Validating token...");
|
|
253
269
|
const result = await validateBotToken(botToken);
|
|
270
|
+
s.stop("Token validated");
|
|
254
271
|
if (result.ok) {
|
|
255
272
|
console.log(ok(`Connected to @${result.botUsername}`));
|
|
256
273
|
break;
|
|
257
274
|
}
|
|
258
275
|
console.log(fail(result.error));
|
|
259
|
-
const action =
|
|
260
|
-
|
|
261
|
-
|
|
262
|
-
|
|
263
|
-
|
|
264
|
-
|
|
265
|
-
|
|
276
|
+
const action = guardCancel(
|
|
277
|
+
await clack.select({
|
|
278
|
+
message: "What to do?",
|
|
279
|
+
options: [
|
|
280
|
+
{ label: "Re-enter token", value: "retry" },
|
|
281
|
+
{ label: "Use as-is (skip validation)", value: "skip" }
|
|
282
|
+
]
|
|
283
|
+
})
|
|
284
|
+
);
|
|
266
285
|
if (action === "skip") break;
|
|
267
286
|
}
|
|
268
287
|
let chatId;
|
|
@@ -277,7 +296,7 @@ async function setupTelegram(stepNum = 1, totalSteps = 3) {
|
|
|
277
296
|
console.log(dim(" 2. The group must be a Supergroup (Group Settings \u2192 convert)"));
|
|
278
297
|
console.log(dim(" 3. Send a message in the group after adding the bot"));
|
|
279
298
|
console.log("");
|
|
280
|
-
await
|
|
299
|
+
guardCancel(await clack.text({ message: "Press Enter to try again..." }));
|
|
281
300
|
continue;
|
|
282
301
|
}
|
|
283
302
|
console.log(
|
|
@@ -294,7 +313,7 @@ async function setupTelegram(stepNum = 1, totalSteps = 3) {
|
|
|
294
313
|
console.log(dim(" 2. Go to Group Settings \u2192 Administrators"));
|
|
295
314
|
console.log(dim(" 3. Add the bot as an administrator"));
|
|
296
315
|
console.log("");
|
|
297
|
-
await
|
|
316
|
+
guardCancel(await clack.text({ message: "Press Enter to check again..." }));
|
|
298
317
|
continue;
|
|
299
318
|
}
|
|
300
319
|
console.log(ok("Bot has admin privileges"));
|
|
@@ -339,35 +358,44 @@ async function setupDiscord() {
|
|
|
339
358
|
console.log("");
|
|
340
359
|
let botToken = "";
|
|
341
360
|
while (true) {
|
|
342
|
-
botToken =
|
|
343
|
-
|
|
344
|
-
|
|
345
|
-
|
|
361
|
+
botToken = guardCancel(
|
|
362
|
+
await clack.text({
|
|
363
|
+
message: "Bot token (from Discord Developer Portal):",
|
|
364
|
+
validate: (val) => (val ?? "").toString().trim().length > 0 ? void 0 : "Token cannot be empty"
|
|
365
|
+
})
|
|
366
|
+
);
|
|
346
367
|
botToken = botToken.trim();
|
|
368
|
+
const s = clack.spinner();
|
|
369
|
+
s.start("Validating token...");
|
|
347
370
|
const result = await validateDiscordToken(botToken);
|
|
371
|
+
s.stop("Token validated");
|
|
348
372
|
if (result.ok) {
|
|
349
373
|
console.log(ok(`Connected as @${result.username} (id: ${result.id})`));
|
|
350
374
|
break;
|
|
351
375
|
}
|
|
352
376
|
console.log(fail(result.error));
|
|
353
|
-
const action =
|
|
354
|
-
|
|
355
|
-
|
|
356
|
-
|
|
357
|
-
|
|
358
|
-
|
|
359
|
-
|
|
377
|
+
const action = guardCancel(
|
|
378
|
+
await clack.select({
|
|
379
|
+
message: "What to do?",
|
|
380
|
+
options: [
|
|
381
|
+
{ label: "Re-enter token", value: "retry" },
|
|
382
|
+
{ label: "Use as-is (skip validation)", value: "skip" }
|
|
383
|
+
]
|
|
384
|
+
})
|
|
385
|
+
);
|
|
360
386
|
if (action === "skip") break;
|
|
361
387
|
}
|
|
362
|
-
const guildId =
|
|
363
|
-
|
|
364
|
-
|
|
365
|
-
|
|
366
|
-
|
|
367
|
-
|
|
368
|
-
|
|
369
|
-
|
|
370
|
-
|
|
388
|
+
const guildId = guardCancel(
|
|
389
|
+
await clack.text({
|
|
390
|
+
message: "Guild (server) ID:",
|
|
391
|
+
validate: (val) => {
|
|
392
|
+
const trimmed = (val ?? "").toString().trim();
|
|
393
|
+
if (!trimmed) return "Guild ID cannot be empty";
|
|
394
|
+
if (!/^\d{17,20}$/.test(trimmed)) return "Guild ID must be a numeric Discord snowflake (17-20 digits)";
|
|
395
|
+
return void 0;
|
|
396
|
+
}
|
|
397
|
+
})
|
|
398
|
+
);
|
|
371
399
|
return {
|
|
372
400
|
enabled: true,
|
|
373
401
|
botToken,
|
|
@@ -378,18 +406,20 @@ async function setupDiscord() {
|
|
|
378
406
|
};
|
|
379
407
|
}
|
|
380
408
|
async function setupAgents() {
|
|
381
|
-
const { AgentCatalog } = await import("./agent-catalog-
|
|
382
|
-
const {
|
|
409
|
+
const { AgentCatalog } = await import("./agent-catalog-SBZQRYOD.js");
|
|
410
|
+
const { muteLogger, unmuteLogger } = await import("./log-RCVBXLTN.js");
|
|
411
|
+
muteLogger();
|
|
383
412
|
const catalog = new AgentCatalog();
|
|
384
413
|
catalog.load();
|
|
385
|
-
|
|
414
|
+
const s = clack.spinner();
|
|
415
|
+
s.start("Checking available agents...");
|
|
386
416
|
await catalog.refreshRegistryIfStale();
|
|
387
417
|
if (!catalog.getInstalledAgent("claude")) {
|
|
388
418
|
const claudeRegistry = catalog.findRegistryAgent("claude-acp");
|
|
389
419
|
if (claudeRegistry) {
|
|
390
420
|
await catalog.install("claude-acp");
|
|
391
421
|
} else {
|
|
392
|
-
const { AgentStore } = await import("./agent-store-
|
|
422
|
+
const { AgentStore } = await import("./agent-store-CGE4G6PA.js");
|
|
393
423
|
const store = new AgentStore();
|
|
394
424
|
store.load();
|
|
395
425
|
store.addAgent("claude", {
|
|
@@ -405,37 +435,53 @@ async function setupAgents() {
|
|
|
405
435
|
});
|
|
406
436
|
}
|
|
407
437
|
}
|
|
408
|
-
|
|
438
|
+
s.stop(ok("Claude Agent ready"));
|
|
439
|
+
unmuteLogger();
|
|
409
440
|
const available = catalog.getAvailable();
|
|
410
441
|
const installed = available.filter((a) => a.installed);
|
|
411
442
|
const installable = available.filter((a) => !a.installed && a.available);
|
|
412
443
|
if (installed.length > 0 || installable.length > 0) {
|
|
413
|
-
const
|
|
414
|
-
|
|
415
|
-
|
|
416
|
-
|
|
417
|
-
|
|
418
|
-
|
|
419
|
-
|
|
420
|
-
|
|
421
|
-
|
|
422
|
-
|
|
423
|
-
|
|
424
|
-
|
|
425
|
-
|
|
426
|
-
|
|
427
|
-
|
|
428
|
-
|
|
429
|
-
|
|
444
|
+
const seen = /* @__PURE__ */ new Set();
|
|
445
|
+
const options = [];
|
|
446
|
+
for (const a of installed) {
|
|
447
|
+
const dedupeKey = `${a.key}::${a.name}`;
|
|
448
|
+
if (seen.has(dedupeKey)) continue;
|
|
449
|
+
seen.add(dedupeKey);
|
|
450
|
+
options.push({
|
|
451
|
+
label: `${a.name} (installed)`,
|
|
452
|
+
value: a.key
|
|
453
|
+
});
|
|
454
|
+
}
|
|
455
|
+
for (const a of installable) {
|
|
456
|
+
const dedupeKey = `${a.key}::${a.name}`;
|
|
457
|
+
if (seen.has(dedupeKey)) continue;
|
|
458
|
+
seen.add(dedupeKey);
|
|
459
|
+
options.push({
|
|
460
|
+
label: `${a.name} (${a.distribution})`,
|
|
461
|
+
value: a.key
|
|
462
|
+
});
|
|
463
|
+
}
|
|
464
|
+
const installedKeys = installed.map((a) => a.key);
|
|
465
|
+
const selected = guardCancel(
|
|
466
|
+
await clack.autocompleteMultiselect({
|
|
467
|
+
message: "Install additional agents? (type to search, Space to select)",
|
|
468
|
+
options,
|
|
469
|
+
initialValues: installedKeys,
|
|
470
|
+
required: false
|
|
471
|
+
})
|
|
472
|
+
);
|
|
430
473
|
for (const key of selected) {
|
|
431
474
|
const regAgent = catalog.findRegistryAgent(key);
|
|
432
475
|
if (regAgent) {
|
|
433
|
-
|
|
476
|
+
const installSpinner = clack.spinner();
|
|
477
|
+
installSpinner.start(`Installing ${regAgent.name}...`);
|
|
478
|
+
muteLogger();
|
|
434
479
|
const result = await catalog.install(key);
|
|
480
|
+
unmuteLogger();
|
|
435
481
|
if (result.ok) {
|
|
436
|
-
|
|
482
|
+
installSpinner.stop(ok("done"));
|
|
437
483
|
} else {
|
|
438
|
-
|
|
484
|
+
installSpinner.stop(warn(`skipped: ${result.error}`));
|
|
439
485
|
}
|
|
440
486
|
}
|
|
441
487
|
}
|
|
@@ -443,25 +489,29 @@ async function setupAgents() {
|
|
|
443
489
|
const installedAgents = Object.keys(catalog.getInstalledEntries());
|
|
444
490
|
let defaultAgent = "claude";
|
|
445
491
|
if (installedAgents.length > 1) {
|
|
446
|
-
defaultAgent =
|
|
447
|
-
|
|
448
|
-
|
|
449
|
-
|
|
450
|
-
|
|
451
|
-
|
|
452
|
-
|
|
453
|
-
|
|
492
|
+
defaultAgent = guardCancel(
|
|
493
|
+
await clack.select({
|
|
494
|
+
message: "Which agent should be the default?",
|
|
495
|
+
options: installedAgents.map((key) => {
|
|
496
|
+
const agent = catalog.getInstalledAgent(key);
|
|
497
|
+
return { label: `${agent.name} (${key})`, value: key };
|
|
498
|
+
}),
|
|
499
|
+
initialValue: "claude"
|
|
500
|
+
})
|
|
501
|
+
);
|
|
454
502
|
}
|
|
455
503
|
console.log(ok(`Default agent: ${c.bold}${defaultAgent}${c.reset}`));
|
|
456
504
|
return { defaultAgent };
|
|
457
505
|
}
|
|
458
506
|
async function setupWorkspace(stepNum = 2, totalSteps = 3) {
|
|
459
507
|
console.log(step(stepNum, totalSteps, "Workspace"));
|
|
460
|
-
const baseDir =
|
|
461
|
-
|
|
462
|
-
|
|
463
|
-
|
|
464
|
-
|
|
508
|
+
const baseDir = guardCancel(
|
|
509
|
+
await clack.text({
|
|
510
|
+
message: "Base directory for workspaces:",
|
|
511
|
+
initialValue: "~/openacp-workspace",
|
|
512
|
+
validate: (val) => (val ?? "").toString().trim().length > 0 ? void 0 : "Path cannot be empty"
|
|
513
|
+
})
|
|
514
|
+
);
|
|
465
515
|
return { baseDir: baseDir.trim().replace(/^['"]|['"]$/g, "") };
|
|
466
516
|
}
|
|
467
517
|
async function setupRunMode(stepNum = 3, totalSteps = 3) {
|
|
@@ -470,23 +520,25 @@ async function setupRunMode(stepNum = 3, totalSteps = 3) {
|
|
|
470
520
|
console.log(dim(" (Daemon mode not available on Windows)"));
|
|
471
521
|
return { runMode: "foreground", autoStart: false };
|
|
472
522
|
}
|
|
473
|
-
const mode =
|
|
474
|
-
|
|
475
|
-
|
|
476
|
-
|
|
477
|
-
|
|
478
|
-
|
|
479
|
-
|
|
480
|
-
|
|
481
|
-
|
|
482
|
-
|
|
483
|
-
|
|
484
|
-
|
|
485
|
-
|
|
486
|
-
|
|
487
|
-
|
|
523
|
+
const mode = guardCancel(
|
|
524
|
+
await clack.select({
|
|
525
|
+
message: "How would you like to run OpenACP?",
|
|
526
|
+
options: [
|
|
527
|
+
{
|
|
528
|
+
label: "Background (daemon)",
|
|
529
|
+
value: "daemon",
|
|
530
|
+
hint: "Runs silently, auto-starts on boot. Manage with: openacp status | stop | logs"
|
|
531
|
+
},
|
|
532
|
+
{
|
|
533
|
+
label: "Foreground (terminal)",
|
|
534
|
+
value: "foreground",
|
|
535
|
+
hint: "Runs in current terminal session. Start with: openacp"
|
|
536
|
+
}
|
|
537
|
+
]
|
|
538
|
+
})
|
|
539
|
+
);
|
|
488
540
|
if (mode === "daemon") {
|
|
489
|
-
const { installAutoStart, isAutoStartSupported } = await import("./autostart-
|
|
541
|
+
const { installAutoStart, isAutoStartSupported } = await import("./autostart-6M3FZAKW.js");
|
|
490
542
|
const autoStart = isAutoStartSupported();
|
|
491
543
|
if (autoStart) {
|
|
492
544
|
const result = installAutoStart(expandHome("~/.openacp/logs"));
|
|
@@ -500,9 +552,9 @@ async function setupRunMode(stepNum = 3, totalSteps = 3) {
|
|
|
500
552
|
}
|
|
501
553
|
return { runMode: "foreground", autoStart: false };
|
|
502
554
|
}
|
|
503
|
-
function applyGradient(
|
|
555
|
+
function applyGradient(text2) {
|
|
504
556
|
const colors = [135, 99, 63, 33, 39, 44, 44];
|
|
505
|
-
const lines =
|
|
557
|
+
const lines = text2.split("\n");
|
|
506
558
|
return lines.map((line, i) => {
|
|
507
559
|
const colorIdx = Math.min(i, colors.length - 1);
|
|
508
560
|
return `\x1B[38;5;${colors[colorIdx]}m${line}\x1B[0m`;
|
|
@@ -519,7 +571,7 @@ var BANNER = `
|
|
|
519
571
|
async function printStartBanner() {
|
|
520
572
|
let version = "0.0.0";
|
|
521
573
|
try {
|
|
522
|
-
const { getCurrentVersion } = await import("./version-
|
|
574
|
+
const { getCurrentVersion } = await import("./version-AXXV6IV2.js");
|
|
523
575
|
version = getCurrentVersion();
|
|
524
576
|
} catch {
|
|
525
577
|
}
|
|
@@ -530,22 +582,25 @@ async function printStartBanner() {
|
|
|
530
582
|
async function printWelcomeBanner() {
|
|
531
583
|
await printStartBanner();
|
|
532
584
|
}
|
|
533
|
-
async function runSetup(configManager) {
|
|
585
|
+
async function runSetup(configManager, opts) {
|
|
534
586
|
await printWelcomeBanner();
|
|
587
|
+
clack.intro("Let's set up OpenACP");
|
|
535
588
|
try {
|
|
536
|
-
const
|
|
537
|
-
|
|
538
|
-
|
|
539
|
-
|
|
540
|
-
|
|
541
|
-
|
|
542
|
-
|
|
543
|
-
|
|
544
|
-
|
|
589
|
+
const channelChoice = guardCancel(
|
|
590
|
+
await clack.select({
|
|
591
|
+
message: "Which messaging platform do you want to use?",
|
|
592
|
+
options: [
|
|
593
|
+
{ label: "Telegram", value: "telegram" },
|
|
594
|
+
{ label: "Discord", value: "discord" },
|
|
595
|
+
{ label: "Both", value: "both" }
|
|
596
|
+
]
|
|
597
|
+
})
|
|
598
|
+
);
|
|
545
599
|
let telegram;
|
|
546
600
|
let discord;
|
|
547
601
|
const channelSteps = channelChoice === "both" ? 2 : 1;
|
|
548
|
-
const
|
|
602
|
+
const runModeSteps = opts?.skipRunMode ? 0 : 1;
|
|
603
|
+
const totalSteps = channelSteps + 1 + runModeSteps;
|
|
549
604
|
let currentStep = 0;
|
|
550
605
|
if (channelChoice === "telegram" || channelChoice === "both") {
|
|
551
606
|
currentStep++;
|
|
@@ -557,11 +612,12 @@ async function runSetup(configManager) {
|
|
|
557
612
|
}
|
|
558
613
|
const { defaultAgent } = await setupAgents();
|
|
559
614
|
{
|
|
560
|
-
const
|
|
561
|
-
|
|
562
|
-
|
|
563
|
-
|
|
564
|
-
|
|
615
|
+
const installClaude = guardCancel(
|
|
616
|
+
await clack.confirm({
|
|
617
|
+
message: "Install session transfer for Claude? (enables /openacp:handoff in your terminal)",
|
|
618
|
+
initialValue: true
|
|
619
|
+
})
|
|
620
|
+
);
|
|
565
621
|
if (installClaude) {
|
|
566
622
|
try {
|
|
567
623
|
const { getIntegration } = await import("./integrate-O4OCR4SN.js");
|
|
@@ -581,8 +637,14 @@ async function runSetup(configManager) {
|
|
|
581
637
|
}
|
|
582
638
|
currentStep++;
|
|
583
639
|
const workspace = await setupWorkspace(currentStep, totalSteps);
|
|
584
|
-
|
|
585
|
-
|
|
640
|
+
let runMode = "foreground";
|
|
641
|
+
let autoStart = false;
|
|
642
|
+
if (!opts?.skipRunMode) {
|
|
643
|
+
currentStep++;
|
|
644
|
+
const result = await setupRunMode(currentStep, totalSteps);
|
|
645
|
+
runMode = result.runMode;
|
|
646
|
+
autoStart = result.autoStart;
|
|
647
|
+
}
|
|
586
648
|
const security = {
|
|
587
649
|
allowedUserIds: [],
|
|
588
650
|
maxConcurrentSessions: 20,
|
|
@@ -640,16 +702,15 @@ async function runSetup(configManager) {
|
|
|
640
702
|
);
|
|
641
703
|
return false;
|
|
642
704
|
}
|
|
643
|
-
|
|
644
|
-
|
|
645
|
-
ok(
|
|
646
|
-
|
|
647
|
-
|
|
648
|
-
console.log("");
|
|
705
|
+
clack.outro(`Config saved to ${configManager.getConfigPath()}`);
|
|
706
|
+
if (!opts?.skipRunMode) {
|
|
707
|
+
console.log(ok("Starting OpenACP..."));
|
|
708
|
+
console.log("");
|
|
709
|
+
}
|
|
649
710
|
return true;
|
|
650
711
|
} catch (err) {
|
|
651
712
|
if (err.name === "ExitPromptError") {
|
|
652
|
-
|
|
713
|
+
clack.cancel("Setup cancelled.");
|
|
653
714
|
return false;
|
|
654
715
|
}
|
|
655
716
|
throw err;
|
|
@@ -671,4 +732,4 @@ export {
|
|
|
671
732
|
printStartBanner,
|
|
672
733
|
runSetup
|
|
673
734
|
};
|
|
674
|
-
//# sourceMappingURL=chunk-
|
|
735
|
+
//# sourceMappingURL=chunk-ZKTIZME6.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../../src/core/setup.ts"],"sourcesContent":["import { execFileSync } from \"node:child_process\";\nimport * as clack from \"@clack/prompts\";\nimport type { Config, ConfigManager } from \"./config.js\";\nimport { expandHome } from \"./config.js\";\nimport { commandExists } from \"./agent-dependencies.js\";\nimport type { DiscordChannelConfig } from \"../adapters/discord/types.js\";\n\nfunction guardCancel<T>(value: T | symbol): T {\n if (clack.isCancel(value)) {\n clack.cancel(\"Setup cancelled.\");\n process.exit(0);\n }\n return value as T;\n}\n\n// --- ANSI colors ---\n\nconst c = {\n reset: \"\\x1b[0m\",\n bold: \"\\x1b[1m\",\n dim: \"\\x1b[2m\",\n green: \"\\x1b[32m\",\n yellow: \"\\x1b[33m\",\n red: \"\\x1b[31m\",\n cyan: \"\\x1b[36m\",\n white: \"\\x1b[37m\",\n};\n\nconst ok = (msg: string) =>\n `${c.green}${c.bold}✓${c.reset} ${c.green}${msg}${c.reset}`;\nconst warn = (msg: string) => `${c.yellow}⚠ ${msg}${c.reset}`;\nconst fail = (msg: string) => `${c.red}✗ ${msg}${c.reset}`;\nconst step = (n: number, total: number, title: string) =>\n `\\n${c.cyan}${c.bold}[${n}/${total}]${c.reset} ${c.bold}${title}${c.reset}\\n`;\nconst dim = (msg: string) => `${c.dim}${msg}${c.reset}`;\n\n// --- Telegram validation ---\n\nexport async function validateBotToken(\n token: string,\n): Promise<\n | { ok: true; botName: string; botUsername: string }\n | { ok: false; error: string }\n> {\n try {\n const res = await fetch(`https://api.telegram.org/bot${token}/getMe`);\n const data = (await res.json()) as {\n ok: boolean;\n result?: { first_name: string; username: string };\n description?: string;\n };\n if (data.ok && data.result) {\n return {\n ok: true,\n botName: data.result.first_name,\n botUsername: data.result.username,\n };\n }\n return { ok: false, error: data.description || \"Invalid token\" };\n } catch (err) {\n return { ok: false, error: (err as Error).message };\n }\n}\n\nexport async function validateChatId(\n token: string,\n chatId: number,\n): Promise<\n { ok: true; title: string; isForum: boolean } | { ok: false; error: string }\n> {\n try {\n const res = await fetch(`https://api.telegram.org/bot${token}/getChat`, {\n method: \"POST\",\n headers: { \"Content-Type\": \"application/json\" },\n body: JSON.stringify({ chat_id: chatId }),\n });\n const data = (await res.json()) as {\n ok: boolean;\n result?: { title: string; type: string; is_forum?: boolean };\n description?: string;\n };\n if (!data.ok || !data.result) {\n return { ok: false, error: data.description || \"Invalid chat ID\" };\n }\n if (data.result.type !== \"supergroup\") {\n return {\n ok: false,\n error: `Chat is \"${data.result.type}\", must be a supergroup`,\n };\n }\n return {\n ok: true,\n title: data.result.title,\n isForum: data.result.is_forum === true,\n };\n } catch (err) {\n return { ok: false, error: (err as Error).message };\n }\n}\n\nexport async function validateBotAdmin(\n token: string,\n chatId: number,\n): Promise<{ ok: true } | { ok: false; error: string }> {\n try {\n // Get bot's own user ID\n const meRes = await fetch(`https://api.telegram.org/bot${token}/getMe`);\n const meData = (await meRes.json()) as {\n ok: boolean;\n result?: { id: number };\n };\n if (!meData.ok || !meData.result) {\n return { ok: false, error: \"Could not retrieve bot info\" };\n }\n\n const res = await fetch(\n `https://api.telegram.org/bot${token}/getChatMember`,\n {\n method: \"POST\",\n headers: { \"Content-Type\": \"application/json\" },\n body: JSON.stringify({ chat_id: chatId, user_id: meData.result.id }),\n },\n );\n const data = (await res.json()) as {\n ok: boolean;\n result?: { status: string };\n description?: string;\n };\n if (!data.ok || !data.result) {\n return {\n ok: false,\n error: data.description || \"Could not check bot membership\",\n };\n }\n\n const { status } = data.result;\n if (status === \"administrator\" || status === \"creator\") {\n return { ok: true };\n }\n return {\n ok: false,\n error: `Bot is \"${status}\" in this group. It must be an admin. Please promote the bot to admin in group settings.`,\n };\n } catch (err) {\n return { ok: false, error: (err as Error).message };\n }\n}\n\n// --- Chat ID auto-detection ---\n\nasync function promptManualChatId(): Promise<number> {\n const val = guardCancel(\n await clack.text({\n message: \"Supergroup chat ID (e.g. -1001234567890):\",\n validate: (val) => {\n const n = Number((val ?? \"\").toString().trim());\n if (isNaN(n) || !Number.isInteger(n)) return \"Chat ID must be an integer\";\n return undefined;\n },\n }),\n ) as string;\n return Number(val.trim());\n}\n\nasync function detectChatId(token: string): Promise<number> {\n // Clear old updates\n let lastUpdateId = 0;\n try {\n const clearRes = await fetch(\n `https://api.telegram.org/bot${token}/getUpdates?offset=-1`,\n );\n const clearData = (await clearRes.json()) as {\n ok: boolean;\n result?: Array<{ update_id: number }>;\n };\n if (clearData.ok && clearData.result?.length) {\n lastUpdateId = clearData.result[clearData.result.length - 1].update_id;\n }\n } catch {\n // ignore\n }\n\n console.log(\"\");\n console.log(` ${c.bold}If you don't have a supergroup yet:${c.reset}`);\n console.log(dim(\" 1. Open Telegram → New Group → add your bot\"));\n console.log(dim(\" 2. Group Settings → convert to Supergroup\"));\n console.log(dim(\" 3. Enable Topics in group settings\"));\n console.log(\"\");\n console.log(` ${c.bold}Then send \"hi\" in the group.${c.reset}`);\n console.log(\n dim(\n ` Listening... press ${c.reset}${c.yellow}m${c.reset}${c.dim} to enter ID manually`,\n ),\n );\n console.log(\"\");\n\n const MAX_ATTEMPTS = 120;\n const POLL_INTERVAL = 1000;\n\n // Listen for 'm' keypress to switch to manual\n let cancelled = false;\n const onKeypress = (data: Buffer) => {\n const key = data.toString();\n if (key === \"m\" || key === \"M\") {\n cancelled = true;\n }\n };\n if (process.stdin.isTTY) {\n process.stdin.setRawMode(true);\n process.stdin.resume();\n process.stdin.on(\"data\", onKeypress);\n }\n\n const cleanup = () => {\n if (process.stdin.isTTY) {\n process.stdin.removeListener(\"data\", onKeypress);\n process.stdin.setRawMode(false);\n process.stdin.pause();\n }\n };\n\n try {\n for (let i = 0; i < MAX_ATTEMPTS; i++) {\n if (cancelled) {\n cleanup();\n return promptManualChatId();\n }\n\n try {\n const offset = lastUpdateId ? lastUpdateId + 1 : 0;\n const res = await fetch(\n `https://api.telegram.org/bot${token}/getUpdates?offset=${offset}&timeout=1`,\n );\n const data = (await res.json()) as {\n ok: boolean;\n result?: Array<{\n update_id: number;\n message?: {\n chat: { id: number; title?: string; type: string };\n };\n my_chat_member?: {\n chat: { id: number; title?: string; type: string };\n };\n }>;\n };\n\n if (!data.ok || !data.result?.length) {\n await new Promise((r) => setTimeout(r, POLL_INTERVAL));\n continue;\n }\n\n const groups = new Map<number, string>();\n for (const update of data.result) {\n lastUpdateId = update.update_id;\n const chat = update.message?.chat ?? update.my_chat_member?.chat;\n if (chat && (chat.type === \"supergroup\" || chat.type === \"group\")) {\n groups.set(chat.id, chat.title ?? String(chat.id));\n }\n }\n\n if (groups.size === 1) {\n const [id, title] = [...groups.entries()][0];\n console.log(\n ok(`Group detected: ${c.bold}${title}${c.reset}${c.green} (${id})`),\n );\n cleanup();\n return id;\n }\n\n if (groups.size > 1) {\n cleanup();\n const options = [...groups.entries()].map(([id, title]) => ({\n label: `${title} (${id})`,\n value: id,\n }));\n return guardCancel(\n await clack.select({\n message: \"Multiple groups found. Pick one:\",\n options,\n }),\n );\n }\n } catch {\n // Network error, retry\n }\n await new Promise((r) => setTimeout(r, POLL_INTERVAL));\n }\n\n console.log(warn(\"Timed out waiting for messages.\"));\n cleanup();\n return promptManualChatId();\n } catch (err) {\n cleanup();\n throw err;\n }\n}\n\n// --- Agent detection ---\n\nconst KNOWN_AGENTS: Array<{ name: string; commands: string[] }> = [\n // claude-agent-acp is bundled as a dependency — no detection needed, but\n // kept here so detectAgents() still returns it for display purposes.\n { name: \"claude\", commands: [\"claude-agent-acp\"] },\n { name: \"codex\", commands: [\"codex\"] },\n];\n\nexport async function detectAgents(): Promise<\n Array<{ name: string; command: string }>\n> {\n const found: Array<{ name: string; command: string }> = [];\n for (const agent of KNOWN_AGENTS) {\n // Find all available commands for this agent (PATH + node_modules/.bin)\n const available: string[] = [];\n for (const cmd of agent.commands) {\n if (commandExists(cmd)) {\n available.push(cmd);\n }\n }\n if (available.length > 0) {\n // Prefer claude-agent-acp over claude/claude-code (priority order)\n found.push({ name: agent.name, command: available[0] });\n }\n }\n return found;\n}\n\nexport async function validateAgentCommand(command: string): Promise<boolean> {\n try {\n execFileSync(\"which\", [command], { stdio: \"pipe\" });\n return true;\n } catch {\n return false;\n }\n}\n\n// --- Setup steps ---\n\nexport async function setupTelegram(stepNum = 1, totalSteps = 3): Promise<Config[\"channels\"][string]> {\n console.log(step(stepNum, totalSteps, \"Telegram Bot\"));\n\n let botToken = \"\";\n\n while (true) {\n botToken = guardCancel(\n await clack.text({\n message: \"Bot token (from @BotFather):\",\n validate: (val) => (val ?? \"\").toString().trim().length > 0 ? undefined : \"Token cannot be empty\",\n }),\n ) as string;\n botToken = botToken.trim();\n\n const s = clack.spinner();\n s.start(\"Validating token...\");\n const result = await validateBotToken(botToken);\n s.stop(\"Token validated\");\n\n if (result.ok) {\n console.log(ok(`Connected to @${result.botUsername}`));\n break;\n }\n console.log(fail(result.error));\n const action = guardCancel(\n await clack.select({\n message: \"What to do?\",\n options: [\n { label: \"Re-enter token\", value: \"retry\" },\n { label: \"Use as-is (skip validation)\", value: \"skip\" },\n ],\n }),\n );\n if (action === \"skip\") break;\n }\n\n let chatId: number;\n\n while (true) {\n chatId = await detectChatId(botToken);\n\n // Validate bot can access this chat and it's a supergroup\n const chatResult = await validateChatId(botToken, chatId);\n if (!chatResult.ok) {\n console.log(fail(chatResult.error));\n console.log(\"\");\n console.log(` ${c.bold}How to fix:${c.reset}`);\n console.log(dim(\" 1. Make sure the bot is added to the group\"));\n console.log(dim(\" 2. The group must be a Supergroup (Group Settings → convert)\"));\n console.log(dim(\" 3. Send a message in the group after adding the bot\"));\n console.log(\"\");\n guardCancel(await clack.text({ message: \"Press Enter to try again...\" }));\n continue;\n }\n console.log(\n ok(\n `Group: ${c.bold}${chatResult.title}${c.reset}${c.green}${chatResult.isForum ? \" (Topics enabled)\" : \"\"}`,\n ),\n );\n\n // Check bot has admin privileges\n const adminResult = await validateBotAdmin(botToken, chatId);\n if (!adminResult.ok) {\n console.log(fail(adminResult.error));\n console.log(\"\");\n console.log(` ${c.bold}How to fix:${c.reset}`);\n console.log(dim(\" 1. Open the group in Telegram\"));\n console.log(dim(\" 2. Go to Group Settings → Administrators\"));\n console.log(dim(\" 3. Add the bot as an administrator\"));\n console.log(\"\");\n guardCancel(await clack.text({ message: \"Press Enter to check again...\" }));\n continue;\n }\n console.log(ok(\"Bot has admin privileges\"));\n break;\n }\n\n return {\n enabled: true,\n botToken,\n chatId,\n notificationTopicId: null,\n assistantTopicId: null,\n };\n}\n\n// --- Discord validation ---\n\nexport async function validateDiscordToken(token: string): Promise<\n | { ok: true; username: string; id: string }\n | { ok: false; error: string }\n> {\n try {\n const res = await fetch(\"https://discord.com/api/v10/users/@me\", {\n headers: { Authorization: `Bot ${token}` },\n });\n if (res.status === 200) {\n const data = (await res.json()) as { username: string; id: string };\n return { ok: true, username: data.username, id: data.id };\n }\n if (res.status === 401) {\n return { ok: false, error: \"Token rejected by Discord (401 Unauthorized)\" };\n }\n return { ok: false, error: `Discord API returned ${res.status}` };\n } catch (err) {\n return { ok: false, error: (err as Error).message };\n }\n}\n\nexport async function setupDiscord(): Promise<DiscordChannelConfig> {\n console.log('\\n📱 Discord Setup\\n');\n\n console.log(` ${c.bold}Quick setup:${c.reset}`);\n console.log(dim(' 1. Create app at https://discord.com/developers/applications'));\n console.log(dim(' 2. Go to Bot → Reset Token → copy it'));\n console.log(dim(' 3. Enable Message Content Intent (Bot → Privileged Intents)'));\n console.log(dim(' 4. OAuth2 → URL Generator → scopes: bot + applications.commands'));\n console.log(dim(' 5. Bot Permissions: Manage Channels, Send Messages, Manage Threads, Attach Files'));\n console.log(dim(' 6. Open generated URL → invite bot to your server'));\n console.log('');\n console.log(dim(` 📖 Detailed guide: https://github.com/Open-ACP/OpenACP/blob/main/docs/guide/discord-setup.md`));\n console.log('');\n\n let botToken = '';\n\n while (true) {\n botToken = guardCancel(\n await clack.text({\n message: 'Bot token (from Discord Developer Portal):',\n validate: (val) => (val ?? \"\").toString().trim().length > 0 ? undefined : 'Token cannot be empty',\n }),\n ) as string;\n botToken = botToken.trim();\n\n const s = clack.spinner();\n s.start(\"Validating token...\");\n const result = await validateDiscordToken(botToken);\n s.stop(\"Token validated\");\n\n if (result.ok) {\n console.log(ok(`Connected as @${result.username} (id: ${result.id})`));\n break;\n }\n console.log(fail(result.error));\n const action = guardCancel(\n await clack.select({\n message: 'What to do?',\n options: [\n { label: 'Re-enter token', value: 'retry' },\n { label: 'Use as-is (skip validation)', value: 'skip' },\n ],\n }),\n );\n if (action === 'skip') break;\n }\n\n const guildId = guardCancel(\n await clack.text({\n message: 'Guild (server) ID:',\n validate: (val) => {\n const trimmed = (val ?? \"\").toString().trim();\n if (!trimmed) return 'Guild ID cannot be empty';\n if (!/^\\d{17,20}$/.test(trimmed)) return 'Guild ID must be a numeric Discord snowflake (17-20 digits)';\n return undefined;\n },\n }),\n ) as string;\n\n return {\n enabled: true,\n botToken,\n guildId: guildId.trim(),\n forumChannelId: null,\n notificationChannelId: null,\n assistantThreadId: null,\n };\n}\n\nexport async function setupAgents(): Promise<{\n defaultAgent: string;\n}> {\n const { AgentCatalog } = await import(\"./agent-catalog.js\");\n const { muteLogger, unmuteLogger } = await import(\"./log.js\");\n\n muteLogger();\n const catalog = new AgentCatalog();\n catalog.load();\n\n const s = clack.spinner();\n s.start(\"Checking available agents...\");\n await catalog.refreshRegistryIfStale();\n\n // Claude is always pre-installed (bundled dependency)\n if (!catalog.getInstalledAgent(\"claude\")) {\n const claudeRegistry = catalog.findRegistryAgent(\"claude-acp\");\n if (claudeRegistry) {\n await catalog.install(\"claude-acp\");\n } else {\n // Fallback: register bundled claude-agent-acp directly\n const { AgentStore } = await import(\"./agent-store.js\");\n const store = new AgentStore();\n store.load();\n store.addAgent(\"claude\", {\n registryId: \"claude-acp\",\n name: \"Claude Agent\",\n version: \"bundled\",\n distribution: \"npx\",\n command: \"npx\",\n args: [\"@zed-industries/claude-agent-acp\"],\n env: {},\n installedAt: new Date().toISOString(),\n binaryPath: null,\n });\n }\n }\n s.stop(ok(\"Claude Agent ready\"));\n unmuteLogger();\n\n const available = catalog.getAvailable();\n const installed = available.filter((a) => a.installed);\n const installable = available.filter((a) => !a.installed && a.available);\n\n // Offer agent selection — show installed agents as pre-checked + installable agents\n if (installed.length > 0 || installable.length > 0) {\n // Deduplicate by key AND name\n const seen = new Set<string>();\n const options: Array<{ label: string; value: string }> = [];\n\n for (const a of installed) {\n const dedupeKey = `${a.key}::${a.name}`;\n if (seen.has(dedupeKey)) continue;\n seen.add(dedupeKey);\n options.push({\n label: `${a.name} (installed)`,\n value: a.key,\n });\n }\n for (const a of installable) {\n const dedupeKey = `${a.key}::${a.name}`;\n if (seen.has(dedupeKey)) continue;\n seen.add(dedupeKey);\n options.push({\n label: `${a.name} (${a.distribution})`,\n value: a.key,\n });\n }\n\n const installedKeys = installed.map(a => a.key);\n const selected = guardCancel(\n await clack.autocompleteMultiselect({\n message: \"Install additional agents? (type to search, Space to select)\",\n options,\n initialValues: installedKeys,\n required: false,\n }),\n ) as string[];\n\n for (const key of selected) {\n const regAgent = catalog.findRegistryAgent(key);\n if (regAgent) {\n const installSpinner = clack.spinner();\n installSpinner.start(`Installing ${regAgent.name}...`);\n muteLogger();\n const result = await catalog.install(key);\n unmuteLogger();\n if (result.ok) {\n installSpinner.stop(ok(\"done\"));\n } else {\n installSpinner.stop(warn(`skipped: ${result.error}`));\n }\n }\n }\n }\n\n // Choose default agent\n const installedAgents = Object.keys(catalog.getInstalledEntries());\n let defaultAgent = \"claude\";\n\n if (installedAgents.length > 1) {\n defaultAgent = guardCancel(\n await clack.select({\n message: \"Which agent should be the default?\",\n options: installedAgents.map((key) => {\n const agent = catalog.getInstalledAgent(key)!;\n return { label: `${agent.name} (${key})`, value: key };\n }),\n initialValue: \"claude\",\n }),\n ) as string;\n }\n\n console.log(ok(`Default agent: ${c.bold}${defaultAgent}${c.reset}`));\n return { defaultAgent };\n}\n\nexport async function setupWorkspace(stepNum = 2, totalSteps = 3): Promise<{ baseDir: string }> {\n console.log(step(stepNum, totalSteps, \"Workspace\"));\n\n const baseDir = guardCancel(\n await clack.text({\n message: \"Base directory for workspaces:\",\n initialValue: \"~/openacp-workspace\",\n validate: (val) => (val ?? \"\").toString().trim().length > 0 ? undefined : \"Path cannot be empty\",\n }),\n ) as string;\n\n return { baseDir: baseDir.trim().replace(/^['\"]|['\"]$/g, \"\") };\n}\n\nexport async function setupRunMode(stepNum = 3, totalSteps = 3): Promise<{ runMode: 'foreground' | 'daemon'; autoStart: boolean }> {\n console.log(step(stepNum, totalSteps, 'Run Mode'))\n\n // Don't show daemon option on Windows\n if (process.platform === 'win32') {\n console.log(dim(' (Daemon mode not available on Windows)'))\n return { runMode: 'foreground', autoStart: false }\n }\n\n const mode = guardCancel(\n await clack.select({\n message: 'How would you like to run OpenACP?',\n options: [\n {\n label: 'Background (daemon)',\n value: 'daemon' as const,\n hint: 'Runs silently, auto-starts on boot. Manage with: openacp status | stop | logs',\n },\n {\n label: 'Foreground (terminal)',\n value: 'foreground' as const,\n hint: 'Runs in current terminal session. Start with: openacp',\n },\n ],\n }),\n );\n\n if (mode === 'daemon') {\n const { installAutoStart, isAutoStartSupported } = await import('./autostart.js')\n const autoStart = isAutoStartSupported()\n if (autoStart) {\n const result = installAutoStart(expandHome('~/.openacp/logs'))\n if (result.success) {\n console.log(ok('Auto-start on boot enabled'))\n } else {\n console.log(warn(`Auto-start failed: ${result.error}`))\n }\n }\n return { runMode: 'daemon', autoStart }\n }\n\n return { runMode: 'foreground', autoStart: false }\n}\n\n// --- Orchestrator ---\n\nfunction applyGradient(text: string): string {\n const colors = [135, 99, 63, 33, 39, 44, 44];\n const lines = text.split(\"\\n\");\n return lines\n .map((line, i) => {\n const colorIdx = Math.min(i, colors.length - 1);\n return `\\x1b[38;5;${colors[colorIdx]}m${line}\\x1b[0m`;\n })\n .join(\"\\n\");\n}\n\nconst BANNER = `\n ██████╗ ██████╗ ███████╗███╗ ██╗ █████╗ ██████╗██████╗\n ██╔═══██╗██╔══██╗██╔════╝████╗ ██║██╔══██╗██╔════╝██╔══██╗\n ██║ ██║██████╔╝█████╗ ██╔██╗ ██║███████║██║ ██████╔╝\n ██║ ██║██╔═══╝ ██╔══╝ ██║╚██╗██║██╔══██║██║ ██╔═══╝\n ╚██████╔╝██║ ███████╗██║ ╚████║██║ ██║╚██████╗██║\n ╚═════╝ ╚═╝ ╚══════╝╚═╝ ╚═══╝╚═╝ ╚═╝ ╚═════╝╚═╝\n`;\n\n/** Compact banner for normal startup (foreground mode) */\nexport async function printStartBanner(): Promise<void> {\n let version = \"0.0.0\";\n try {\n const { getCurrentVersion } = await import(\"../cli/version.js\");\n version = getCurrentVersion();\n } catch {\n // ignore\n }\n console.log(applyGradient(BANNER));\n console.log(`${c.dim} AI coding agents, anywhere. v${version}${c.reset}\\n`);\n}\n\nasync function printWelcomeBanner(): Promise<void> {\n await printStartBanner();\n}\n\nexport async function runSetup(configManager: ConfigManager, opts?: { skipRunMode?: boolean }): Promise<boolean> {\n await printWelcomeBanner();\n clack.intro(\"Let's set up OpenACP\");\n\n try {\n const channelChoice = guardCancel(\n await clack.select({\n message: 'Which messaging platform do you want to use?',\n options: [\n { label: 'Telegram', value: 'telegram' },\n { label: 'Discord', value: 'discord' },\n { label: 'Both', value: 'both' },\n ],\n }),\n );\n\n let telegram: Config[\"channels\"][string] | undefined;\n let discord: DiscordChannelConfig | undefined;\n\n // Calculate total steps dynamically: channel(s) + workspace + run mode\n const channelSteps = channelChoice === 'both' ? 2 : 1;\n const runModeSteps = opts?.skipRunMode ? 0 : 1;\n const totalSteps = channelSteps + 1 + runModeSteps; // + workspace + optional run mode\n\n let currentStep = 0;\n\n if (channelChoice === 'telegram' || channelChoice === 'both') {\n currentStep++;\n telegram = await setupTelegram(currentStep, totalSteps);\n }\n if (channelChoice === 'discord' || channelChoice === 'both') {\n currentStep++;\n discord = await setupDiscord();\n }\n\n const { defaultAgent } = await setupAgents();\n\n // Offer Claude CLI integration\n {\n const installClaude = guardCancel(\n await clack.confirm({\n message: \"Install session transfer for Claude? (enables /openacp:handoff in your terminal)\",\n initialValue: true,\n }),\n );\n\n if (installClaude) {\n try {\n const { getIntegration } = await import(\"../cli/integrate.js\");\n const integration = getIntegration(\"claude\");\n if (integration) {\n for (const item of integration.items) {\n const result = await item.install();\n for (const log of result.logs) console.log(` ${log}`);\n }\n }\n console.log(\"Claude CLI integration installed.\\n\");\n } catch (err) {\n console.log(`Could not install Claude CLI integration: ${err instanceof Error ? err.message : err}`);\n console.log(\" You can install it later with: openacp integrate claude\\n\");\n }\n }\n }\n\n currentStep++;\n const workspace = await setupWorkspace(currentStep, totalSteps);\n\n let runMode: 'foreground' | 'daemon' = 'foreground';\n let autoStart = false;\n if (!opts?.skipRunMode) {\n currentStep++;\n const result = await setupRunMode(currentStep, totalSteps);\n runMode = result.runMode;\n autoStart = result.autoStart;\n }\n\n const security = {\n allowedUserIds: [] as string[],\n maxConcurrentSessions: 20,\n sessionTimeoutMinutes: 60,\n };\n\n const channels: Config[\"channels\"] = {};\n if (telegram) channels.telegram = telegram;\n // DiscordChannelConfig is structurally compatible with the base channel schema\n if (discord) channels.discord = discord as Config[\"channels\"][string];\n\n const config: Config = {\n channels,\n agents: {},\n defaultAgent,\n workspace,\n security,\n logging: {\n level: \"info\",\n logDir: \"~/.openacp/logs\",\n maxFileSize: \"10m\",\n maxFiles: 7,\n sessionLogRetentionDays: 30,\n },\n runMode,\n autoStart,\n api: {\n port: 21420,\n host: '127.0.0.1',\n },\n sessionStore: { ttlDays: 30 },\n tunnel: {\n enabled: true,\n port: 3100,\n provider: \"cloudflare\",\n options: {},\n maxUserTunnels: 5,\n storeTtlMinutes: 60,\n auth: { enabled: false },\n },\n usage: {\n enabled: true,\n warningThreshold: 0.8,\n currency: \"USD\",\n retentionDays: 90,\n },\n integrations: {},\n speech: {\n stt: { provider: null, providers: {} },\n tts: { provider: null, providers: {} },\n },\n };\n\n try {\n await configManager.writeNew(config);\n } catch (writeErr) {\n console.log(\n fail(`Could not save config: ${(writeErr as Error).message}`),\n );\n return false;\n }\n\n clack.outro(`Config saved to ${configManager.getConfigPath()}`);\n\n if (!opts?.skipRunMode) {\n console.log(ok(\"Starting OpenACP...\"));\n console.log(\"\");\n }\n\n return true;\n } catch (err) {\n if ((err as Error).name === \"ExitPromptError\") {\n clack.cancel(\"Setup cancelled.\");\n return false;\n }\n throw err;\n }\n}\n"],"mappings":";;;;;;;;AAAA,SAAS,oBAAoB;AAC7B,YAAY,WAAW;AAMvB,SAAS,YAAe,OAAsB;AAC5C,MAAU,eAAS,KAAK,GAAG;AACzB,IAAM,aAAO,kBAAkB;AAC/B,YAAQ,KAAK,CAAC;AAAA,EAChB;AACA,SAAO;AACT;AAIA,IAAM,IAAI;AAAA,EACR,OAAO;AAAA,EACP,MAAM;AAAA,EACN,KAAK;AAAA,EACL,OAAO;AAAA,EACP,QAAQ;AAAA,EACR,KAAK;AAAA,EACL,MAAM;AAAA,EACN,OAAO;AACT;AAEA,IAAM,KAAK,CAAC,QACV,GAAG,EAAE,KAAK,GAAG,EAAE,IAAI,SAAI,EAAE,KAAK,IAAI,EAAE,KAAK,GAAG,GAAG,GAAG,EAAE,KAAK;AAC3D,IAAM,OAAO,CAAC,QAAgB,GAAG,EAAE,MAAM,UAAK,GAAG,GAAG,EAAE,KAAK;AAC3D,IAAM,OAAO,CAAC,QAAgB,GAAG,EAAE,GAAG,UAAK,GAAG,GAAG,EAAE,KAAK;AACxD,IAAM,OAAO,CAAC,GAAW,OAAe,UACtC;AAAA,EAAK,EAAE,IAAI,GAAG,EAAE,IAAI,IAAI,CAAC,IAAI,KAAK,IAAI,EAAE,KAAK,IAAI,EAAE,IAAI,GAAG,KAAK,GAAG,EAAE,KAAK;AAAA;AAC3E,IAAM,MAAM,CAAC,QAAgB,GAAG,EAAE,GAAG,GAAG,GAAG,GAAG,EAAE,KAAK;AAIrD,eAAsB,iBACpB,OAIA;AACA,MAAI;AACF,UAAM,MAAM,MAAM,MAAM,+BAA+B,KAAK,QAAQ;AACpE,UAAM,OAAQ,MAAM,IAAI,KAAK;AAK7B,QAAI,KAAK,MAAM,KAAK,QAAQ;AAC1B,aAAO;AAAA,QACL,IAAI;AAAA,QACJ,SAAS,KAAK,OAAO;AAAA,QACrB,aAAa,KAAK,OAAO;AAAA,MAC3B;AAAA,IACF;AACA,WAAO,EAAE,IAAI,OAAO,OAAO,KAAK,eAAe,gBAAgB;AAAA,EACjE,SAAS,KAAK;AACZ,WAAO,EAAE,IAAI,OAAO,OAAQ,IAAc,QAAQ;AAAA,EACpD;AACF;AAEA,eAAsB,eACpB,OACA,QAGA;AACA,MAAI;AACF,UAAM,MAAM,MAAM,MAAM,+BAA+B,KAAK,YAAY;AAAA,MACtE,QAAQ;AAAA,MACR,SAAS,EAAE,gBAAgB,mBAAmB;AAAA,MAC9C,MAAM,KAAK,UAAU,EAAE,SAAS,OAAO,CAAC;AAAA,IAC1C,CAAC;AACD,UAAM,OAAQ,MAAM,IAAI,KAAK;AAK7B,QAAI,CAAC,KAAK,MAAM,CAAC,KAAK,QAAQ;AAC5B,aAAO,EAAE,IAAI,OAAO,OAAO,KAAK,eAAe,kBAAkB;AAAA,IACnE;AACA,QAAI,KAAK,OAAO,SAAS,cAAc;AACrC,aAAO;AAAA,QACL,IAAI;AAAA,QACJ,OAAO,YAAY,KAAK,OAAO,IAAI;AAAA,MACrC;AAAA,IACF;AACA,WAAO;AAAA,MACL,IAAI;AAAA,MACJ,OAAO,KAAK,OAAO;AAAA,MACnB,SAAS,KAAK,OAAO,aAAa;AAAA,IACpC;AAAA,EACF,SAAS,KAAK;AACZ,WAAO,EAAE,IAAI,OAAO,OAAQ,IAAc,QAAQ;AAAA,EACpD;AACF;AAEA,eAAsB,iBACpB,OACA,QACsD;AACtD,MAAI;AAEF,UAAM,QAAQ,MAAM,MAAM,+BAA+B,KAAK,QAAQ;AACtE,UAAM,SAAU,MAAM,MAAM,KAAK;AAIjC,QAAI,CAAC,OAAO,MAAM,CAAC,OAAO,QAAQ;AAChC,aAAO,EAAE,IAAI,OAAO,OAAO,8BAA8B;AAAA,IAC3D;AAEA,UAAM,MAAM,MAAM;AAAA,MAChB,+BAA+B,KAAK;AAAA,MACpC;AAAA,QACE,QAAQ;AAAA,QACR,SAAS,EAAE,gBAAgB,mBAAmB;AAAA,QAC9C,MAAM,KAAK,UAAU,EAAE,SAAS,QAAQ,SAAS,OAAO,OAAO,GAAG,CAAC;AAAA,MACrE;AAAA,IACF;AACA,UAAM,OAAQ,MAAM,IAAI,KAAK;AAK7B,QAAI,CAAC,KAAK,MAAM,CAAC,KAAK,QAAQ;AAC5B,aAAO;AAAA,QACL,IAAI;AAAA,QACJ,OAAO,KAAK,eAAe;AAAA,MAC7B;AAAA,IACF;AAEA,UAAM,EAAE,OAAO,IAAI,KAAK;AACxB,QAAI,WAAW,mBAAmB,WAAW,WAAW;AACtD,aAAO,EAAE,IAAI,KAAK;AAAA,IACpB;AACA,WAAO;AAAA,MACL,IAAI;AAAA,MACJ,OAAO,WAAW,MAAM;AAAA,IAC1B;AAAA,EACF,SAAS,KAAK;AACZ,WAAO,EAAE,IAAI,OAAO,OAAQ,IAAc,QAAQ;AAAA,EACpD;AACF;AAIA,eAAe,qBAAsC;AACnD,QAAM,MAAM;AAAA,IACV,MAAY,WAAK;AAAA,MACf,SAAS;AAAA,MACT,UAAU,CAACA,SAAQ;AACjB,cAAM,IAAI,QAAQA,QAAO,IAAI,SAAS,EAAE,KAAK,CAAC;AAC9C,YAAI,MAAM,CAAC,KAAK,CAAC,OAAO,UAAU,CAAC,EAAG,QAAO;AAC7C,eAAO;AAAA,MACT;AAAA,IACF,CAAC;AAAA,EACH;AACA,SAAO,OAAO,IAAI,KAAK,CAAC;AAC1B;AAEA,eAAe,aAAa,OAAgC;AAE1D,MAAI,eAAe;AACnB,MAAI;AACF,UAAM,WAAW,MAAM;AAAA,MACrB,+BAA+B,KAAK;AAAA,IACtC;AACA,UAAM,YAAa,MAAM,SAAS,KAAK;AAIvC,QAAI,UAAU,MAAM,UAAU,QAAQ,QAAQ;AAC5C,qBAAe,UAAU,OAAO,UAAU,OAAO,SAAS,CAAC,EAAE;AAAA,IAC/D;AAAA,EACF,QAAQ;AAAA,EAER;AAEA,UAAQ,IAAI,EAAE;AACd,UAAQ,IAAI,KAAK,EAAE,IAAI,sCAAsC,EAAE,KAAK,EAAE;AACtE,UAAQ,IAAI,IAAI,yDAA+C,CAAC;AAChE,UAAQ,IAAI,IAAI,kDAA6C,CAAC;AAC9D,UAAQ,IAAI,IAAI,sCAAsC,CAAC;AACvD,UAAQ,IAAI,EAAE;AACd,UAAQ,IAAI,KAAK,EAAE,IAAI,+BAA+B,EAAE,KAAK,EAAE;AAC/D,UAAQ;AAAA,IACN;AAAA,MACE,wBAAwB,EAAE,KAAK,GAAG,EAAE,MAAM,IAAI,EAAE,KAAK,GAAG,EAAE,GAAG;AAAA,IAC/D;AAAA,EACF;AACA,UAAQ,IAAI,EAAE;AAEd,QAAM,eAAe;AACrB,QAAM,gBAAgB;AAGtB,MAAI,YAAY;AAChB,QAAM,aAAa,CAAC,SAAiB;AACnC,UAAM,MAAM,KAAK,SAAS;AAC1B,QAAI,QAAQ,OAAO,QAAQ,KAAK;AAC9B,kBAAY;AAAA,IACd;AAAA,EACF;AACA,MAAI,QAAQ,MAAM,OAAO;AACvB,YAAQ,MAAM,WAAW,IAAI;AAC7B,YAAQ,MAAM,OAAO;AACrB,YAAQ,MAAM,GAAG,QAAQ,UAAU;AAAA,EACrC;AAEA,QAAM,UAAU,MAAM;AACpB,QAAI,QAAQ,MAAM,OAAO;AACvB,cAAQ,MAAM,eAAe,QAAQ,UAAU;AAC/C,cAAQ,MAAM,WAAW,KAAK;AAC9B,cAAQ,MAAM,MAAM;AAAA,IACtB;AAAA,EACF;AAEA,MAAI;AACF,aAAS,IAAI,GAAG,IAAI,cAAc,KAAK;AACrC,UAAI,WAAW;AACb,gBAAQ;AACR,eAAO,mBAAmB;AAAA,MAC5B;AAEA,UAAI;AACF,cAAM,SAAS,eAAe,eAAe,IAAI;AACjD,cAAM,MAAM,MAAM;AAAA,UAChB,+BAA+B,KAAK,sBAAsB,MAAM;AAAA,QAClE;AACA,cAAM,OAAQ,MAAM,IAAI,KAAK;AAa7B,YAAI,CAAC,KAAK,MAAM,CAAC,KAAK,QAAQ,QAAQ;AACpC,gBAAM,IAAI,QAAQ,CAAC,MAAM,WAAW,GAAG,aAAa,CAAC;AACrD;AAAA,QACF;AAEA,cAAM,SAAS,oBAAI,IAAoB;AACvC,mBAAW,UAAU,KAAK,QAAQ;AAChC,yBAAe,OAAO;AACtB,gBAAM,OAAO,OAAO,SAAS,QAAQ,OAAO,gBAAgB;AAC5D,cAAI,SAAS,KAAK,SAAS,gBAAgB,KAAK,SAAS,UAAU;AACjE,mBAAO,IAAI,KAAK,IAAI,KAAK,SAAS,OAAO,KAAK,EAAE,CAAC;AAAA,UACnD;AAAA,QACF;AAEA,YAAI,OAAO,SAAS,GAAG;AACrB,gBAAM,CAAC,IAAI,KAAK,IAAI,CAAC,GAAG,OAAO,QAAQ,CAAC,EAAE,CAAC;AAC3C,kBAAQ;AAAA,YACN,GAAG,mBAAmB,EAAE,IAAI,GAAG,KAAK,GAAG,EAAE,KAAK,GAAG,EAAE,KAAK,KAAK,EAAE,GAAG;AAAA,UACpE;AACA,kBAAQ;AACR,iBAAO;AAAA,QACT;AAEA,YAAI,OAAO,OAAO,GAAG;AACnB,kBAAQ;AACR,gBAAM,UAAU,CAAC,GAAG,OAAO,QAAQ,CAAC,EAAE,IAAI,CAAC,CAAC,IAAI,KAAK,OAAO;AAAA,YAC1D,OAAO,GAAG,KAAK,KAAK,EAAE;AAAA,YACtB,OAAO;AAAA,UACT,EAAE;AACF,iBAAO;AAAA,YACL,MAAY,aAAO;AAAA,cACjB,SAAS;AAAA,cACT;AAAA,YACF,CAAC;AAAA,UACH;AAAA,QACF;AAAA,MACF,QAAQ;AAAA,MAER;AACA,YAAM,IAAI,QAAQ,CAAC,MAAM,WAAW,GAAG,aAAa,CAAC;AAAA,IACvD;AAEA,YAAQ,IAAI,KAAK,iCAAiC,CAAC;AACnD,YAAQ;AACR,WAAO,mBAAmB;AAAA,EAC5B,SAAS,KAAK;AACZ,YAAQ;AACR,UAAM;AAAA,EACR;AACF;AAIA,IAAM,eAA4D;AAAA;AAAA;AAAA,EAGhE,EAAE,MAAM,UAAU,UAAU,CAAC,kBAAkB,EAAE;AAAA,EACjD,EAAE,MAAM,SAAS,UAAU,CAAC,OAAO,EAAE;AACvC;AAEA,eAAsB,eAEpB;AACA,QAAM,QAAkD,CAAC;AACzD,aAAW,SAAS,cAAc;AAEhC,UAAM,YAAsB,CAAC;AAC7B,eAAW,OAAO,MAAM,UAAU;AAChC,UAAI,cAAc,GAAG,GAAG;AACtB,kBAAU,KAAK,GAAG;AAAA,MACpB;AAAA,IACF;AACA,QAAI,UAAU,SAAS,GAAG;AAExB,YAAM,KAAK,EAAE,MAAM,MAAM,MAAM,SAAS,UAAU,CAAC,EAAE,CAAC;AAAA,IACxD;AAAA,EACF;AACA,SAAO;AACT;AAEA,eAAsB,qBAAqB,SAAmC;AAC5E,MAAI;AACF,iBAAa,SAAS,CAAC,OAAO,GAAG,EAAE,OAAO,OAAO,CAAC;AAClD,WAAO;AAAA,EACT,QAAQ;AACN,WAAO;AAAA,EACT;AACF;AAIA,eAAsB,cAAc,UAAU,GAAG,aAAa,GAAwC;AACpG,UAAQ,IAAI,KAAK,SAAS,YAAY,cAAc,CAAC;AAErD,MAAI,WAAW;AAEf,SAAO,MAAM;AACX,eAAW;AAAA,MACT,MAAY,WAAK;AAAA,QACf,SAAS;AAAA,QACT,UAAU,CAAC,SAAS,OAAO,IAAI,SAAS,EAAE,KAAK,EAAE,SAAS,IAAI,SAAY;AAAA,MAC5E,CAAC;AAAA,IACH;AACA,eAAW,SAAS,KAAK;AAEzB,UAAM,IAAU,cAAQ;AACxB,MAAE,MAAM,qBAAqB;AAC7B,UAAM,SAAS,MAAM,iBAAiB,QAAQ;AAC9C,MAAE,KAAK,iBAAiB;AAExB,QAAI,OAAO,IAAI;AACb,cAAQ,IAAI,GAAG,iBAAiB,OAAO,WAAW,EAAE,CAAC;AACrD;AAAA,IACF;AACA,YAAQ,IAAI,KAAK,OAAO,KAAK,CAAC;AAC9B,UAAM,SAAS;AAAA,MACb,MAAY,aAAO;AAAA,QACjB,SAAS;AAAA,QACT,SAAS;AAAA,UACP,EAAE,OAAO,kBAAkB,OAAO,QAAQ;AAAA,UAC1C,EAAE,OAAO,+BAA+B,OAAO,OAAO;AAAA,QACxD;AAAA,MACF,CAAC;AAAA,IACH;AACA,QAAI,WAAW,OAAQ;AAAA,EACzB;AAEA,MAAI;AAEJ,SAAO,MAAM;AACX,aAAS,MAAM,aAAa,QAAQ;AAGpC,UAAM,aAAa,MAAM,eAAe,UAAU,MAAM;AACxD,QAAI,CAAC,WAAW,IAAI;AAClB,cAAQ,IAAI,KAAK,WAAW,KAAK,CAAC;AAClC,cAAQ,IAAI,EAAE;AACd,cAAQ,IAAI,KAAK,EAAE,IAAI,cAAc,EAAE,KAAK,EAAE;AAC9C,cAAQ,IAAI,IAAI,8CAA8C,CAAC;AAC/D,cAAQ,IAAI,IAAI,qEAAgE,CAAC;AACjF,cAAQ,IAAI,IAAI,uDAAuD,CAAC;AACxE,cAAQ,IAAI,EAAE;AACd,kBAAY,MAAY,WAAK,EAAE,SAAS,8BAA8B,CAAC,CAAC;AACxE;AAAA,IACF;AACA,YAAQ;AAAA,MACN;AAAA,QACE,UAAU,EAAE,IAAI,GAAG,WAAW,KAAK,GAAG,EAAE,KAAK,GAAG,EAAE,KAAK,GAAG,WAAW,UAAU,sBAAsB,EAAE;AAAA,MACzG;AAAA,IACF;AAGA,UAAM,cAAc,MAAM,iBAAiB,UAAU,MAAM;AAC3D,QAAI,CAAC,YAAY,IAAI;AACnB,cAAQ,IAAI,KAAK,YAAY,KAAK,CAAC;AACnC,cAAQ,IAAI,EAAE;AACd,cAAQ,IAAI,KAAK,EAAE,IAAI,cAAc,EAAE,KAAK,EAAE;AAC9C,cAAQ,IAAI,IAAI,iCAAiC,CAAC;AAClD,cAAQ,IAAI,IAAI,iDAA4C,CAAC;AAC7D,cAAQ,IAAI,IAAI,sCAAsC,CAAC;AACvD,cAAQ,IAAI,EAAE;AACd,kBAAY,MAAY,WAAK,EAAE,SAAS,gCAAgC,CAAC,CAAC;AAC1E;AAAA,IACF;AACA,YAAQ,IAAI,GAAG,0BAA0B,CAAC;AAC1C;AAAA,EACF;AAEA,SAAO;AAAA,IACL,SAAS;AAAA,IACT;AAAA,IACA;AAAA,IACA,qBAAqB;AAAA,IACrB,kBAAkB;AAAA,EACpB;AACF;AAIA,eAAsB,qBAAqB,OAGzC;AACA,MAAI;AACF,UAAM,MAAM,MAAM,MAAM,yCAAyC;AAAA,MAC/D,SAAS,EAAE,eAAe,OAAO,KAAK,GAAG;AAAA,IAC3C,CAAC;AACD,QAAI,IAAI,WAAW,KAAK;AACtB,YAAM,OAAQ,MAAM,IAAI,KAAK;AAC7B,aAAO,EAAE,IAAI,MAAM,UAAU,KAAK,UAAU,IAAI,KAAK,GAAG;AAAA,IAC1D;AACA,QAAI,IAAI,WAAW,KAAK;AACtB,aAAO,EAAE,IAAI,OAAO,OAAO,+CAA+C;AAAA,IAC5E;AACA,WAAO,EAAE,IAAI,OAAO,OAAO,wBAAwB,IAAI,MAAM,GAAG;AAAA,EAClE,SAAS,KAAK;AACZ,WAAO,EAAE,IAAI,OAAO,OAAQ,IAAc,QAAQ;AAAA,EACpD;AACF;AAEA,eAAsB,eAA8C;AAClE,UAAQ,IAAI,6BAAsB;AAElC,UAAQ,IAAI,KAAK,EAAE,IAAI,eAAe,EAAE,KAAK,EAAE;AAC/C,UAAQ,IAAI,IAAI,gEAAgE,CAAC;AACjF,UAAQ,IAAI,IAAI,kDAAwC,CAAC;AACzD,UAAQ,IAAI,IAAI,oEAA+D,CAAC;AAChF,UAAQ,IAAI,IAAI,6EAAmE,CAAC;AACpF,UAAQ,IAAI,IAAI,oFAAoF,CAAC;AACrG,UAAQ,IAAI,IAAI,0DAAqD,CAAC;AACtE,UAAQ,IAAI,EAAE;AACd,UAAQ,IAAI,IAAI,uGAAgG,CAAC;AACjH,UAAQ,IAAI,EAAE;AAEd,MAAI,WAAW;AAEf,SAAO,MAAM;AACX,eAAW;AAAA,MACT,MAAY,WAAK;AAAA,QACf,SAAS;AAAA,QACT,UAAU,CAAC,SAAS,OAAO,IAAI,SAAS,EAAE,KAAK,EAAE,SAAS,IAAI,SAAY;AAAA,MAC5E,CAAC;AAAA,IACH;AACA,eAAW,SAAS,KAAK;AAEzB,UAAM,IAAU,cAAQ;AACxB,MAAE,MAAM,qBAAqB;AAC7B,UAAM,SAAS,MAAM,qBAAqB,QAAQ;AAClD,MAAE,KAAK,iBAAiB;AAExB,QAAI,OAAO,IAAI;AACb,cAAQ,IAAI,GAAG,iBAAiB,OAAO,QAAQ,SAAS,OAAO,EAAE,GAAG,CAAC;AACrE;AAAA,IACF;AACA,YAAQ,IAAI,KAAK,OAAO,KAAK,CAAC;AAC9B,UAAM,SAAS;AAAA,MACb,MAAY,aAAO;AAAA,QACjB,SAAS;AAAA,QACT,SAAS;AAAA,UACP,EAAE,OAAO,kBAAkB,OAAO,QAAQ;AAAA,UAC1C,EAAE,OAAO,+BAA+B,OAAO,OAAO;AAAA,QACxD;AAAA,MACF,CAAC;AAAA,IACH;AACA,QAAI,WAAW,OAAQ;AAAA,EACzB;AAEA,QAAM,UAAU;AAAA,IACd,MAAY,WAAK;AAAA,MACf,SAAS;AAAA,MACT,UAAU,CAAC,QAAQ;AACjB,cAAM,WAAW,OAAO,IAAI,SAAS,EAAE,KAAK;AAC5C,YAAI,CAAC,QAAS,QAAO;AACrB,YAAI,CAAC,cAAc,KAAK,OAAO,EAAG,QAAO;AACzC,eAAO;AAAA,MACT;AAAA,IACF,CAAC;AAAA,EACH;AAEA,SAAO;AAAA,IACL,SAAS;AAAA,IACT;AAAA,IACA,SAAS,QAAQ,KAAK;AAAA,IACtB,gBAAgB;AAAA,IAChB,uBAAuB;AAAA,IACvB,mBAAmB;AAAA,EACrB;AACF;AAEA,eAAsB,cAEnB;AACD,QAAM,EAAE,aAAa,IAAI,MAAM,OAAO,6BAAoB;AAC1D,QAAM,EAAE,YAAY,aAAa,IAAI,MAAM,OAAO,mBAAU;AAE5D,aAAW;AACX,QAAM,UAAU,IAAI,aAAa;AACjC,UAAQ,KAAK;AAEb,QAAM,IAAU,cAAQ;AACxB,IAAE,MAAM,8BAA8B;AACtC,QAAM,QAAQ,uBAAuB;AAGrC,MAAI,CAAC,QAAQ,kBAAkB,QAAQ,GAAG;AACxC,UAAM,iBAAiB,QAAQ,kBAAkB,YAAY;AAC7D,QAAI,gBAAgB;AAClB,YAAM,QAAQ,QAAQ,YAAY;AAAA,IACpC,OAAO;AAEL,YAAM,EAAE,WAAW,IAAI,MAAM,OAAO,2BAAkB;AACtD,YAAM,QAAQ,IAAI,WAAW;AAC7B,YAAM,KAAK;AACX,YAAM,SAAS,UAAU;AAAA,QACvB,YAAY;AAAA,QACZ,MAAM;AAAA,QACN,SAAS;AAAA,QACT,cAAc;AAAA,QACd,SAAS;AAAA,QACT,MAAM,CAAC,kCAAkC;AAAA,QACzC,KAAK,CAAC;AAAA,QACN,cAAa,oBAAI,KAAK,GAAE,YAAY;AAAA,QACpC,YAAY;AAAA,MACd,CAAC;AAAA,IACH;AAAA,EACF;AACA,IAAE,KAAK,GAAG,oBAAoB,CAAC;AAC/B,eAAa;AAEb,QAAM,YAAY,QAAQ,aAAa;AACvC,QAAM,YAAY,UAAU,OAAO,CAAC,MAAM,EAAE,SAAS;AACrD,QAAM,cAAc,UAAU,OAAO,CAAC,MAAM,CAAC,EAAE,aAAa,EAAE,SAAS;AAGvE,MAAI,UAAU,SAAS,KAAK,YAAY,SAAS,GAAG;AAElD,UAAM,OAAO,oBAAI,IAAY;AAC7B,UAAM,UAAmD,CAAC;AAE1D,eAAW,KAAK,WAAW;AACzB,YAAM,YAAY,GAAG,EAAE,GAAG,KAAK,EAAE,IAAI;AACrC,UAAI,KAAK,IAAI,SAAS,EAAG;AACzB,WAAK,IAAI,SAAS;AAClB,cAAQ,KAAK;AAAA,QACX,OAAO,GAAG,EAAE,IAAI;AAAA,QAChB,OAAO,EAAE;AAAA,MACX,CAAC;AAAA,IACH;AACA,eAAW,KAAK,aAAa;AAC3B,YAAM,YAAY,GAAG,EAAE,GAAG,KAAK,EAAE,IAAI;AACrC,UAAI,KAAK,IAAI,SAAS,EAAG;AACzB,WAAK,IAAI,SAAS;AAClB,cAAQ,KAAK;AAAA,QACX,OAAO,GAAG,EAAE,IAAI,KAAK,EAAE,YAAY;AAAA,QACnC,OAAO,EAAE;AAAA,MACX,CAAC;AAAA,IACH;AAEA,UAAM,gBAAgB,UAAU,IAAI,OAAK,EAAE,GAAG;AAC9C,UAAM,WAAW;AAAA,MACf,MAAY,8BAAwB;AAAA,QAClC,SAAS;AAAA,QACT;AAAA,QACA,eAAe;AAAA,QACf,UAAU;AAAA,MACZ,CAAC;AAAA,IACH;AAEA,eAAW,OAAO,UAAU;AAC1B,YAAM,WAAW,QAAQ,kBAAkB,GAAG;AAC9C,UAAI,UAAU;AACZ,cAAM,iBAAuB,cAAQ;AACrC,uBAAe,MAAM,cAAc,SAAS,IAAI,KAAK;AACrD,mBAAW;AACX,cAAM,SAAS,MAAM,QAAQ,QAAQ,GAAG;AACxC,qBAAa;AACb,YAAI,OAAO,IAAI;AACb,yBAAe,KAAK,GAAG,MAAM,CAAC;AAAA,QAChC,OAAO;AACL,yBAAe,KAAK,KAAK,YAAY,OAAO,KAAK,EAAE,CAAC;AAAA,QACtD;AAAA,MACF;AAAA,IACF;AAAA,EACF;AAGA,QAAM,kBAAkB,OAAO,KAAK,QAAQ,oBAAoB,CAAC;AACjE,MAAI,eAAe;AAEnB,MAAI,gBAAgB,SAAS,GAAG;AAC9B,mBAAe;AAAA,MACb,MAAY,aAAO;AAAA,QACjB,SAAS;AAAA,QACT,SAAS,gBAAgB,IAAI,CAAC,QAAQ;AACpC,gBAAM,QAAQ,QAAQ,kBAAkB,GAAG;AAC3C,iBAAO,EAAE,OAAO,GAAG,MAAM,IAAI,KAAK,GAAG,KAAK,OAAO,IAAI;AAAA,QACvD,CAAC;AAAA,QACD,cAAc;AAAA,MAChB,CAAC;AAAA,IACH;AAAA,EACF;AAEA,UAAQ,IAAI,GAAG,kBAAkB,EAAE,IAAI,GAAG,YAAY,GAAG,EAAE,KAAK,EAAE,CAAC;AACnE,SAAO,EAAE,aAAa;AACxB;AAEA,eAAsB,eAAe,UAAU,GAAG,aAAa,GAAiC;AAC9F,UAAQ,IAAI,KAAK,SAAS,YAAY,WAAW,CAAC;AAElD,QAAM,UAAU;AAAA,IACd,MAAY,WAAK;AAAA,MACf,SAAS;AAAA,MACT,cAAc;AAAA,MACd,UAAU,CAAC,SAAS,OAAO,IAAI,SAAS,EAAE,KAAK,EAAE,SAAS,IAAI,SAAY;AAAA,IAC5E,CAAC;AAAA,EACH;AAEA,SAAO,EAAE,SAAS,QAAQ,KAAK,EAAE,QAAQ,gBAAgB,EAAE,EAAE;AAC/D;AAEA,eAAsB,aAAa,UAAU,GAAG,aAAa,GAAsE;AACjI,UAAQ,IAAI,KAAK,SAAS,YAAY,UAAU,CAAC;AAGjD,MAAI,QAAQ,aAAa,SAAS;AAChC,YAAQ,IAAI,IAAI,0CAA0C,CAAC;AAC3D,WAAO,EAAE,SAAS,cAAc,WAAW,MAAM;AAAA,EACnD;AAEA,QAAM,OAAO;AAAA,IACX,MAAY,aAAO;AAAA,MACjB,SAAS;AAAA,MACT,SAAS;AAAA,QACP;AAAA,UACE,OAAO;AAAA,UACP,OAAO;AAAA,UACP,MAAM;AAAA,QACR;AAAA,QACA;AAAA,UACE,OAAO;AAAA,UACP,OAAO;AAAA,UACP,MAAM;AAAA,QACR;AAAA,MACF;AAAA,IACF,CAAC;AAAA,EACH;AAEA,MAAI,SAAS,UAAU;AACrB,UAAM,EAAE,kBAAkB,qBAAqB,IAAI,MAAM,OAAO,yBAAgB;AAChF,UAAM,YAAY,qBAAqB;AACvC,QAAI,WAAW;AACb,YAAM,SAAS,iBAAiB,WAAW,iBAAiB,CAAC;AAC7D,UAAI,OAAO,SAAS;AAClB,gBAAQ,IAAI,GAAG,4BAA4B,CAAC;AAAA,MAC9C,OAAO;AACL,gBAAQ,IAAI,KAAK,sBAAsB,OAAO,KAAK,EAAE,CAAC;AAAA,MACxD;AAAA,IACF;AACA,WAAO,EAAE,SAAS,UAAU,UAAU;AAAA,EACxC;AAEA,SAAO,EAAE,SAAS,cAAc,WAAW,MAAM;AACnD;AAIA,SAAS,cAAcC,OAAsB;AAC3C,QAAM,SAAS,CAAC,KAAK,IAAI,IAAI,IAAI,IAAI,IAAI,EAAE;AAC3C,QAAM,QAAQA,MAAK,MAAM,IAAI;AAC7B,SAAO,MACJ,IAAI,CAAC,MAAM,MAAM;AAChB,UAAM,WAAW,KAAK,IAAI,GAAG,OAAO,SAAS,CAAC;AAC9C,WAAO,aAAa,OAAO,QAAQ,CAAC,IAAI,IAAI;AAAA,EAC9C,CAAC,EACA,KAAK,IAAI;AACd;AAEA,IAAM,SAAS;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAUf,eAAsB,mBAAkC;AACtD,MAAI,UAAU;AACd,MAAI;AACF,UAAM,EAAE,kBAAkB,IAAI,MAAM,OAAO,uBAAmB;AAC9D,cAAU,kBAAkB;AAAA,EAC9B,QAAQ;AAAA,EAER;AACA,UAAQ,IAAI,cAAc,MAAM,CAAC;AACjC,UAAQ,IAAI,GAAG,EAAE,GAAG,+CAA+C,OAAO,GAAG,EAAE,KAAK;AAAA,CAAI;AAC1F;AAEA,eAAe,qBAAoC;AACjD,QAAM,iBAAiB;AACzB;AAEA,eAAsB,SAAS,eAA8B,MAAoD;AAC/G,QAAM,mBAAmB;AACzB,EAAM,YAAM,sBAAsB;AAElC,MAAI;AACF,UAAM,gBAAgB;AAAA,MACpB,MAAY,aAAO;AAAA,QACjB,SAAS;AAAA,QACT,SAAS;AAAA,UACP,EAAE,OAAO,YAAY,OAAO,WAAW;AAAA,UACvC,EAAE,OAAO,WAAW,OAAO,UAAU;AAAA,UACrC,EAAE,OAAO,QAAQ,OAAO,OAAO;AAAA,QACjC;AAAA,MACF,CAAC;AAAA,IACH;AAEA,QAAI;AACJ,QAAI;AAGJ,UAAM,eAAe,kBAAkB,SAAS,IAAI;AACpD,UAAM,eAAe,MAAM,cAAc,IAAI;AAC7C,UAAM,aAAa,eAAe,IAAI;AAEtC,QAAI,cAAc;AAElB,QAAI,kBAAkB,cAAc,kBAAkB,QAAQ;AAC5D;AACA,iBAAW,MAAM,cAAc,aAAa,UAAU;AAAA,IACxD;AACA,QAAI,kBAAkB,aAAa,kBAAkB,QAAQ;AAC3D;AACA,gBAAU,MAAM,aAAa;AAAA,IAC/B;AAEA,UAAM,EAAE,aAAa,IAAI,MAAM,YAAY;AAG3C;AACE,YAAM,gBAAgB;AAAA,QACpB,MAAY,cAAQ;AAAA,UAClB,SAAS;AAAA,UACT,cAAc;AAAA,QAChB,CAAC;AAAA,MACH;AAEA,UAAI,eAAe;AACjB,YAAI;AACF,gBAAM,EAAE,eAAe,IAAI,MAAM,OAAO,yBAAqB;AAC7D,gBAAM,cAAc,eAAe,QAAQ;AAC3C,cAAI,aAAa;AACf,uBAAW,QAAQ,YAAY,OAAO;AACpC,oBAAM,SAAS,MAAM,KAAK,QAAQ;AAClC,yBAAW,OAAO,OAAO,KAAM,SAAQ,IAAI,KAAK,GAAG,EAAE;AAAA,YACvD;AAAA,UACF;AACA,kBAAQ,IAAI,qCAAqC;AAAA,QACnD,SAAS,KAAK;AACZ,kBAAQ,IAAI,6CAA6C,eAAe,QAAQ,IAAI,UAAU,GAAG,EAAE;AACnG,kBAAQ,IAAI,6DAA6D;AAAA,QAC3E;AAAA,MACF;AAAA,IACF;AAEA;AACA,UAAM,YAAY,MAAM,eAAe,aAAa,UAAU;AAE9D,QAAI,UAAmC;AACvC,QAAI,YAAY;AAChB,QAAI,CAAC,MAAM,aAAa;AACtB;AACA,YAAM,SAAS,MAAM,aAAa,aAAa,UAAU;AACzD,gBAAU,OAAO;AACjB,kBAAY,OAAO;AAAA,IACrB;AAEA,UAAM,WAAW;AAAA,MACf,gBAAgB,CAAC;AAAA,MACjB,uBAAuB;AAAA,MACvB,uBAAuB;AAAA,IACzB;AAEA,UAAM,WAA+B,CAAC;AACtC,QAAI,SAAU,UAAS,WAAW;AAElC,QAAI,QAAS,UAAS,UAAU;AAEhC,UAAM,SAAiB;AAAA,MACrB;AAAA,MACA,QAAQ,CAAC;AAAA,MACT;AAAA,MACA;AAAA,MACA;AAAA,MACA,SAAS;AAAA,QACP,OAAO;AAAA,QACP,QAAQ;AAAA,QACR,aAAa;AAAA,QACb,UAAU;AAAA,QACV,yBAAyB;AAAA,MAC3B;AAAA,MACA;AAAA,MACA;AAAA,MACA,KAAK;AAAA,QACH,MAAM;AAAA,QACN,MAAM;AAAA,MACR;AAAA,MACA,cAAc,EAAE,SAAS,GAAG;AAAA,MAC5B,QAAQ;AAAA,QACN,SAAS;AAAA,QACT,MAAM;AAAA,QACN,UAAU;AAAA,QACV,SAAS,CAAC;AAAA,QACV,gBAAgB;AAAA,QAChB,iBAAiB;AAAA,QACjB,MAAM,EAAE,SAAS,MAAM;AAAA,MACzB;AAAA,MACA,OAAO;AAAA,QACL,SAAS;AAAA,QACT,kBAAkB;AAAA,QAClB,UAAU;AAAA,QACV,eAAe;AAAA,MACjB;AAAA,MACA,cAAc,CAAC;AAAA,MACf,QAAQ;AAAA,QACN,KAAK,EAAE,UAAU,MAAM,WAAW,CAAC,EAAE;AAAA,QACrC,KAAK,EAAE,UAAU,MAAM,WAAW,CAAC,EAAE;AAAA,MACvC;AAAA,IACF;AAEA,QAAI;AACF,YAAM,cAAc,SAAS,MAAM;AAAA,IACrC,SAAS,UAAU;AACjB,cAAQ;AAAA,QACN,KAAK,0BAA2B,SAAmB,OAAO,EAAE;AAAA,MAC9D;AACA,aAAO;AAAA,IACT;AAEA,IAAM,YAAM,mBAAmB,cAAc,cAAc,CAAC,EAAE;AAE9D,QAAI,CAAC,MAAM,aAAa;AACtB,cAAQ,IAAI,GAAG,qBAAqB,CAAC;AACrC,cAAQ,IAAI,EAAE;AAAA,IAChB;AAEA,WAAO;AAAA,EACT,SAAS,KAAK;AACZ,QAAK,IAAc,SAAS,mBAAmB;AAC7C,MAAM,aAAO,kBAAkB;AAC/B,aAAO;AAAA,IACT;AACA,UAAM;AAAA,EACR;AACF;","names":["val","text"]}
|