@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.
Files changed (109) hide show
  1. package/dist/adapter-YSEIZJBA.js +798 -0
  2. package/dist/adapter-YSEIZJBA.js.map +1 -0
  3. package/dist/{admin-3ZHEO5VP.js → admin-SCP25TN2.js} +3 -3
  4. package/dist/agent-catalog-SBZQRYOD.js +10 -0
  5. package/dist/agent-store-CGE4G6PA.js +8 -0
  6. package/dist/{agents-SXIY4IEF.js → agents-QJPHNWK2.js} +3 -3
  7. package/dist/{autostart-A7JRU4WJ.js → autostart-6M3FZAKW.js} +3 -3
  8. package/dist/{chunk-PMGNLNSH.js → chunk-2CJ46J3C.js} +2 -2
  9. package/dist/{chunk-5HGXUCMX.js → chunk-34M4OS5P.js} +2 -2
  10. package/dist/{chunk-AVCHZESZ.js → chunk-3IRAWHMC.js} +49 -20
  11. package/dist/chunk-3IRAWHMC.js.map +1 -0
  12. package/dist/{chunk-EWYNCHUH.js → chunk-3ZO3MHZN.js} +22 -3
  13. package/dist/chunk-3ZO3MHZN.js.map +1 -0
  14. package/dist/{chunk-TTDSLV35.js → chunk-4CTX774K.js} +3 -3
  15. package/dist/chunk-4GQ3I65A.js +23 -0
  16. package/dist/chunk-4GQ3I65A.js.map +1 -0
  17. package/dist/{chunk-NXEQXRQR.js → chunk-774Y4RAK.js} +2 -2
  18. package/dist/{chunk-6LSFRNHE.js → chunk-7KZI2236.js} +3 -3
  19. package/dist/{chunk-SM3G6UAX.js → chunk-BNLGTZ34.js} +2 -2
  20. package/dist/{chunk-FMWSVLRM.js → chunk-FCLGYYTY.js} +1 -21
  21. package/dist/chunk-FCLGYYTY.js.map +1 -0
  22. package/dist/chunk-FEWSQT3U.js +3949 -0
  23. package/dist/chunk-FEWSQT3U.js.map +1 -0
  24. package/dist/{chunk-HP2IJYCA.js → chunk-FW6HM4VU.js} +91 -4030
  25. package/dist/chunk-FW6HM4VU.js.map +1 -0
  26. package/dist/{chunk-ESOPMQAY.js → chunk-GAK6PIBW.js} +25 -2
  27. package/dist/chunk-GAK6PIBW.js.map +1 -0
  28. package/dist/{chunk-3KGRVAEV.js → chunk-J4SJTKIK.js} +2 -2
  29. package/dist/{chunk-FZ5BIWG5.js → chunk-JV6XQRAE.js} +4 -4
  30. package/dist/{chunk-OHR6SBMC.js → chunk-PJVKOZTR.js} +3 -3
  31. package/dist/{chunk-EVFJW45N.js → chunk-S64CB6J3.js} +13 -13
  32. package/dist/{chunk-EVFJW45N.js.map → chunk-S64CB6J3.js.map} +1 -1
  33. package/dist/{chunk-CKOK7JW6.js → chunk-UKT3G5IA.js} +3 -3
  34. package/dist/{chunk-PWFPTG5X.js → chunk-V5GZQEIY.js} +2 -2
  35. package/dist/{chunk-KO5RL7MZ.js → chunk-WVMSP4AF.js} +2 -2
  36. package/dist/{chunk-TMCQZAXN.js → chunk-XVL6AGMG.js} +3 -3
  37. package/dist/{chunk-IER5UCY7.js → chunk-YQRF3IOR.js} +2 -2
  38. package/dist/{chunk-G3OHCXZG.js → chunk-ZKTIZME6.js} +194 -133
  39. package/dist/chunk-ZKTIZME6.js.map +1 -0
  40. package/dist/cli.js +54 -44
  41. package/dist/cli.js.map +1 -1
  42. package/dist/{config-4YSJ4NCI.js → config-B26J3XXN.js} +3 -3
  43. package/dist/config-editor-QTGUK3CD.js +12 -0
  44. package/dist/{daemon-I6XMRQ6P.js → daemon-5DS5BQXJ.js} +4 -4
  45. package/dist/{discord-VHCBN3JJ.js → discord-QKT3JMRW.js} +28 -26
  46. package/dist/{discord-VHCBN3JJ.js.map → discord-QKT3JMRW.js.map} +1 -1
  47. package/dist/doctor-6SUCVUZB.js +9 -0
  48. package/dist/doctor-QQ3YZEYV.js +14 -0
  49. package/dist/index.d.ts +166 -11
  50. package/dist/index.js +17 -14
  51. package/dist/{install-cloudflared-G2GUKCHA.js → install-cloudflared-FSILDS5J.js} +3 -3
  52. package/dist/{install-jq-7QTU7XYY.js → install-jq-P6RUBKPV.js} +3 -3
  53. package/dist/{log-SPS2S6FO.js → log-RCVBXLTN.js} +8 -4
  54. package/dist/{main-P4X6SAPZ.js → main-TSZR4HPP.js} +57 -29
  55. package/dist/main-TSZR4HPP.js.map +1 -0
  56. package/dist/{new-session-PUNUHGYP.js → new-session-K6UCWYOP.js} +5 -5
  57. package/dist/{post-upgrade-6N4JCV5S.js → post-upgrade-62LUHDJO.js} +5 -5
  58. package/dist/{session-ZMAM67AA.js → session-O6ZPLJIZ.js} +4 -4
  59. package/dist/{settings-OEQEZS5Y.js → settings-RRF77IC4.js} +3 -3
  60. package/dist/{setup-7YBFKRG7.js → setup-5ZKSUR26.js} +4 -4
  61. package/dist/{tunnel-service-BMIBHUBK.js → tunnel-service-NJJH4I26.js} +3 -3
  62. package/dist/{version-ALWGGVKM.js → version-AXXV6IV2.js} +2 -2
  63. package/package.json +6 -1
  64. package/dist/agent-catalog-IVU2KANH.js +0 -10
  65. package/dist/agent-store-ZBXGOFPH.js +0 -8
  66. package/dist/chunk-AVCHZESZ.js.map +0 -1
  67. package/dist/chunk-ESOPMQAY.js.map +0 -1
  68. package/dist/chunk-EWYNCHUH.js.map +0 -1
  69. package/dist/chunk-FMWSVLRM.js.map +0 -1
  70. package/dist/chunk-G3OHCXZG.js.map +0 -1
  71. package/dist/chunk-HP2IJYCA.js.map +0 -1
  72. package/dist/config-editor-F25HEMGL.js +0 -12
  73. package/dist/doctor-GPW5ECK6.js +0 -14
  74. package/dist/doctor-Y3SCSVPI.js +0 -9
  75. package/dist/main-P4X6SAPZ.js.map +0 -1
  76. /package/dist/{admin-3ZHEO5VP.js.map → admin-SCP25TN2.js.map} +0 -0
  77. /package/dist/{agent-catalog-IVU2KANH.js.map → agent-catalog-SBZQRYOD.js.map} +0 -0
  78. /package/dist/{agent-store-ZBXGOFPH.js.map → agent-store-CGE4G6PA.js.map} +0 -0
  79. /package/dist/{agents-SXIY4IEF.js.map → agents-QJPHNWK2.js.map} +0 -0
  80. /package/dist/{autostart-A7JRU4WJ.js.map → autostart-6M3FZAKW.js.map} +0 -0
  81. /package/dist/{chunk-PMGNLNSH.js.map → chunk-2CJ46J3C.js.map} +0 -0
  82. /package/dist/{chunk-5HGXUCMX.js.map → chunk-34M4OS5P.js.map} +0 -0
  83. /package/dist/{chunk-TTDSLV35.js.map → chunk-4CTX774K.js.map} +0 -0
  84. /package/dist/{chunk-NXEQXRQR.js.map → chunk-774Y4RAK.js.map} +0 -0
  85. /package/dist/{chunk-6LSFRNHE.js.map → chunk-7KZI2236.js.map} +0 -0
  86. /package/dist/{chunk-SM3G6UAX.js.map → chunk-BNLGTZ34.js.map} +0 -0
  87. /package/dist/{chunk-3KGRVAEV.js.map → chunk-J4SJTKIK.js.map} +0 -0
  88. /package/dist/{chunk-FZ5BIWG5.js.map → chunk-JV6XQRAE.js.map} +0 -0
  89. /package/dist/{chunk-OHR6SBMC.js.map → chunk-PJVKOZTR.js.map} +0 -0
  90. /package/dist/{chunk-CKOK7JW6.js.map → chunk-UKT3G5IA.js.map} +0 -0
  91. /package/dist/{chunk-PWFPTG5X.js.map → chunk-V5GZQEIY.js.map} +0 -0
  92. /package/dist/{chunk-KO5RL7MZ.js.map → chunk-WVMSP4AF.js.map} +0 -0
  93. /package/dist/{chunk-TMCQZAXN.js.map → chunk-XVL6AGMG.js.map} +0 -0
  94. /package/dist/{chunk-IER5UCY7.js.map → chunk-YQRF3IOR.js.map} +0 -0
  95. /package/dist/{config-4YSJ4NCI.js.map → config-B26J3XXN.js.map} +0 -0
  96. /package/dist/{config-editor-F25HEMGL.js.map → config-editor-QTGUK3CD.js.map} +0 -0
  97. /package/dist/{daemon-I6XMRQ6P.js.map → daemon-5DS5BQXJ.js.map} +0 -0
  98. /package/dist/{doctor-GPW5ECK6.js.map → doctor-6SUCVUZB.js.map} +0 -0
  99. /package/dist/{doctor-Y3SCSVPI.js.map → doctor-QQ3YZEYV.js.map} +0 -0
  100. /package/dist/{install-cloudflared-G2GUKCHA.js.map → install-cloudflared-FSILDS5J.js.map} +0 -0
  101. /package/dist/{install-jq-7QTU7XYY.js.map → install-jq-P6RUBKPV.js.map} +0 -0
  102. /package/dist/{log-SPS2S6FO.js.map → log-RCVBXLTN.js.map} +0 -0
  103. /package/dist/{new-session-PUNUHGYP.js.map → new-session-K6UCWYOP.js.map} +0 -0
  104. /package/dist/{post-upgrade-6N4JCV5S.js.map → post-upgrade-62LUHDJO.js.map} +0 -0
  105. /package/dist/{session-ZMAM67AA.js.map → session-O6ZPLJIZ.js.map} +0 -0
  106. /package/dist/{settings-OEQEZS5Y.js.map → settings-RRF77IC4.js.map} +0 -0
  107. /package/dist/{setup-7YBFKRG7.js.map → setup-5ZKSUR26.js.map} +0 -0
  108. /package/dist/{tunnel-service-BMIBHUBK.js.map → tunnel-service-NJJH4I26.js.map} +0 -0
  109. /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-EWYNCHUH.js";
6
+ } from "./chunk-3ZO3MHZN.js";
7
7
 
8
8
  // src/core/setup.ts
9
9
  import { execFileSync } from "child_process";
10
- import { input, select } from "@inquirer/prompts";
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
- return input({
106
- message: "Supergroup chat ID (e.g. -1001234567890):",
107
- validate: (val) => {
108
- const n = Number(val.trim());
109
- if (isNaN(n) || !Number.isInteger(n)) return "Chat ID must be an integer";
110
- return true;
111
- }
112
- }).then((val) => Number(val.trim()));
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 choices = [...groups.entries()].map(([id, title]) => ({
195
- name: `${title} (${id})`,
204
+ const options = [...groups.entries()].map(([id, title]) => ({
205
+ label: `${title} (${id})`,
196
206
  value: id
197
207
  }));
198
- return select({
199
- message: "Multiple groups found. Pick one:",
200
- choices
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 = await input({
249
- message: "Bot token (from @BotFather):",
250
- validate: (val) => val.trim().length > 0 || "Token cannot be empty"
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 = await select({
260
- message: "What to do?",
261
- choices: [
262
- { name: "Re-enter token", value: "retry" },
263
- { name: "Use as-is (skip validation)", value: "skip" }
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 input({ message: "Press Enter to try again..." });
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 input({ message: "Press Enter to check again..." });
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 = await input({
343
- message: "Bot token (from Discord Developer Portal):",
344
- validate: (val) => val.trim().length > 0 || "Token cannot be empty"
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 = await select({
354
- message: "What to do?",
355
- choices: [
356
- { name: "Re-enter token", value: "retry" },
357
- { name: "Use as-is (skip validation)", value: "skip" }
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 = await input({
363
- message: "Guild (server) ID:",
364
- validate: (val) => {
365
- const trimmed = val.trim();
366
- if (!trimmed) return "Guild ID cannot be empty";
367
- if (!/^\d{17,20}$/.test(trimmed)) return "Guild ID must be a numeric Discord snowflake (17-20 digits)";
368
- return true;
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-IVU2KANH.js");
382
- const { select: select2, checkbox } = await import("@inquirer/prompts");
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
- console.log(dim(" Checking available agents..."));
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-ZBXGOFPH.js");
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
- console.log(ok("Claude Agent ready"));
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 choices = [
414
- ...installed.map((a) => ({
415
- name: `${a.name} (installed)`,
416
- value: a.key,
417
- checked: true,
418
- disabled: "(already installed)"
419
- })),
420
- ...installable.slice(0, 10).map((a) => ({
421
- name: `${a.name} (${a.distribution})`,
422
- value: a.key,
423
- checked: false
424
- }))
425
- ];
426
- const selected = await checkbox({
427
- message: "Install additional agents? (Space to select, Enter to continue)",
428
- choices
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
- process.stdout.write(` Installing ${regAgent.name}... `);
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
- console.log(ok("done"));
482
+ installSpinner.stop(ok("done"));
437
483
  } else {
438
- console.log(warn(`skipped: ${result.error}`));
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 = await select2({
447
- message: "Which agent should be the default?",
448
- choices: installedAgents.map((key) => {
449
- const agent = catalog.getInstalledAgent(key);
450
- return { name: `${agent.name} (${key})`, value: key };
451
- }),
452
- default: "claude"
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 = await input({
461
- message: "Base directory for workspaces:",
462
- default: "~/openacp-workspace",
463
- validate: (val) => val.trim().length > 0 || "Path cannot be empty"
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 = await select({
474
- message: "How would you like to run OpenACP?",
475
- choices: [
476
- {
477
- name: "Background (daemon)",
478
- value: "daemon",
479
- description: "Runs silently, auto-starts on boot. Manage with: openacp status | stop | logs"
480
- },
481
- {
482
- name: "Foreground (terminal)",
483
- value: "foreground",
484
- description: "Runs in current terminal session. Start with: openacp"
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-A7JRU4WJ.js");
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(text) {
555
+ function applyGradient(text2) {
504
556
  const colors = [135, 99, 63, 33, 39, 44, 44];
505
- const lines = text.split("\n");
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-ALWGGVKM.js");
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 { select: selectChannel } = await import("@inquirer/prompts");
537
- const channelChoice = await selectChannel({
538
- message: "Which messaging platform do you want to use?",
539
- choices: [
540
- { name: "Telegram", value: "telegram" },
541
- { name: "Discord", value: "discord" },
542
- { name: "Both", value: "both" }
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 totalSteps = channelSteps + 2;
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 { confirm } = await import("@inquirer/prompts");
561
- const installClaude = await confirm({
562
- message: "Install session transfer for Claude? (enables /openacp:handoff in your terminal)",
563
- default: true
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
- currentStep++;
585
- const { runMode, autoStart } = await setupRunMode(currentStep, totalSteps);
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
- console.log("");
644
- console.log(
645
- ok(`Config saved to ${c.bold}${configManager.getConfigPath()}`)
646
- );
647
- console.log(ok("Starting OpenACP..."));
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
- console.log(dim("\nSetup cancelled."));
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-G3OHCXZG.js.map
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":"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","names":["val","text"]}