@openacp/cli 0.4.11 → 0.5.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (74) hide show
  1. package/README.md +41 -3
  2. package/dist/agent-catalog-LAAVBVLY.js +10 -0
  3. package/dist/agent-dependencies-FCLRGMZM.js +23 -0
  4. package/dist/agent-registry-KZANAFXQ.js +8 -0
  5. package/dist/agent-store-ZBXGOFPH.js +8 -0
  6. package/dist/chunk-5HGXUCMX.js +83 -0
  7. package/dist/chunk-5HGXUCMX.js.map +1 -0
  8. package/dist/chunk-5MH66WUY.js +424 -0
  9. package/dist/chunk-5MH66WUY.js.map +1 -0
  10. package/dist/{chunk-FKOARMAE.js → chunk-776VAU3T.js} +3 -3
  11. package/dist/chunk-GUHCS6X7.js +282 -0
  12. package/dist/chunk-GUHCS6X7.js.map +1 -0
  13. package/dist/{chunk-3DIPXFZJ.js → chunk-IRGYTNLP.js} +2 -2
  14. package/dist/chunk-IURZ4QHG.js +91 -0
  15. package/dist/chunk-IURZ4QHG.js.map +1 -0
  16. package/dist/{chunk-WYZFGHHI.js → chunk-JRF4G4X7.js} +60 -24
  17. package/dist/chunk-JRF4G4X7.js.map +1 -0
  18. package/dist/chunk-NAMYZIS5.js +1 -0
  19. package/dist/{chunk-ZW444AQY.js → chunk-NDR5JCS7.js} +2 -2
  20. package/dist/{chunk-66RVSUAR.js → chunk-PHC67OP4.js} +567 -103
  21. package/dist/chunk-PHC67OP4.js.map +1 -0
  22. package/dist/{chunk-W7QQA6CW.js → chunk-QODDJ4PH.js} +83 -36
  23. package/dist/chunk-QODDJ4PH.js.map +1 -0
  24. package/dist/{chunk-YRJEZD7R.js → chunk-VBEWSWVL.js} +2 -2
  25. package/dist/{chunk-C33LTDZV.js → chunk-Z46LGZ7R.js} +21 -8
  26. package/dist/chunk-Z46LGZ7R.js.map +1 -0
  27. package/dist/cli.js +440 -64
  28. package/dist/cli.js.map +1 -1
  29. package/dist/{config-XURP6B3S.js → config-PCPIBPUA.js} +2 -2
  30. package/dist/config-editor-RGV6VKPZ.js +12 -0
  31. package/dist/{config-registry-OGX4YM2U.js → config-registry-SNKA2EH2.js} +2 -2
  32. package/dist/{daemon-GWJM2S4A.js → daemon-JZLFRUW6.js} +3 -3
  33. package/dist/daemon-JZLFRUW6.js.map +1 -0
  34. package/dist/data/registry-snapshot.json +876 -0
  35. package/dist/doctor-N2HKKUUQ.js +9 -0
  36. package/dist/doctor-N2HKKUUQ.js.map +1 -0
  37. package/dist/index.d.ts +138 -17
  38. package/dist/index.js +24 -15
  39. package/dist/integrate-X7LI6MUO.js +257 -0
  40. package/dist/integrate-X7LI6MUO.js.map +1 -0
  41. package/dist/{main-2QKD2EI2.js → main-DSQBCJHR.js} +18 -15
  42. package/dist/{main-2QKD2EI2.js.map → main-DSQBCJHR.js.map} +1 -1
  43. package/dist/{menu-CARRTW2F.js → menu-J5YVH665.js} +2 -4
  44. package/dist/menu-J5YVH665.js.map +1 -0
  45. package/dist/{setup-TTOL7XAN.js → setup-3A3XDGCM.js} +4 -3
  46. package/dist/setup-3A3XDGCM.js.map +1 -0
  47. package/dist/suggest-RST5VOHB.js +36 -0
  48. package/dist/suggest-RST5VOHB.js.map +1 -0
  49. package/package.json +11 -2
  50. package/dist/agent-registry-7HC6D4CH.js +0 -7
  51. package/dist/chunk-66RVSUAR.js.map +0 -1
  52. package/dist/chunk-BGKQHQB4.js +0 -276
  53. package/dist/chunk-BGKQHQB4.js.map +0 -1
  54. package/dist/chunk-C33LTDZV.js.map +0 -1
  55. package/dist/chunk-VA2M52CM.js +0 -15
  56. package/dist/chunk-VA2M52CM.js.map +0 -1
  57. package/dist/chunk-W7QQA6CW.js.map +0 -1
  58. package/dist/chunk-WYZFGHHI.js.map +0 -1
  59. package/dist/config-editor-AALY3URF.js +0 -11
  60. package/dist/doctor-X477CVZN.js +0 -9
  61. package/dist/integrate-WUPLRJD3.js +0 -145
  62. package/dist/integrate-WUPLRJD3.js.map +0 -1
  63. /package/dist/{agent-registry-7HC6D4CH.js.map → agent-catalog-LAAVBVLY.js.map} +0 -0
  64. /package/dist/{config-XURP6B3S.js.map → agent-dependencies-FCLRGMZM.js.map} +0 -0
  65. /package/dist/{config-editor-AALY3URF.js.map → agent-registry-KZANAFXQ.js.map} +0 -0
  66. /package/dist/{config-registry-OGX4YM2U.js.map → agent-store-ZBXGOFPH.js.map} +0 -0
  67. /package/dist/{chunk-FKOARMAE.js.map → chunk-776VAU3T.js.map} +0 -0
  68. /package/dist/{chunk-3DIPXFZJ.js.map → chunk-IRGYTNLP.js.map} +0 -0
  69. /package/dist/{daemon-GWJM2S4A.js.map → chunk-NAMYZIS5.js.map} +0 -0
  70. /package/dist/{chunk-ZW444AQY.js.map → chunk-NDR5JCS7.js.map} +0 -0
  71. /package/dist/{chunk-YRJEZD7R.js.map → chunk-VBEWSWVL.js.map} +0 -0
  72. /package/dist/{doctor-X477CVZN.js.map → config-PCPIBPUA.js.map} +0 -0
  73. /package/dist/{menu-CARRTW2F.js.map → config-editor-RGV6VKPZ.js.map} +0 -0
  74. /package/dist/{setup-TTOL7XAN.js.map → config-registry-SNKA2EH2.js.map} +0 -0
@@ -1,11 +1,12 @@
1
+ import {
2
+ commandExists
3
+ } from "./chunk-GUHCS6X7.js";
1
4
  import {
2
5
  expandHome
3
- } from "./chunk-WYZFGHHI.js";
6
+ } from "./chunk-JRF4G4X7.js";
4
7
 
5
8
  // src/core/setup.ts
6
9
  import { execFileSync } from "child_process";
7
- import * as fs from "fs";
8
- import * as path from "path";
9
10
  import { input, select } from "@inquirer/prompts";
10
11
  var c = {
11
12
  reset: "\x1B[0m",
@@ -217,22 +218,6 @@ var KNOWN_AGENTS = [
217
218
  { name: "claude", commands: ["claude-agent-acp"] },
218
219
  { name: "codex", commands: ["codex"] }
219
220
  ];
220
- function commandExists(cmd) {
221
- try {
222
- execFileSync("which", [cmd], { stdio: "pipe" });
223
- return true;
224
- } catch {
225
- }
226
- let dir = process.cwd();
227
- while (true) {
228
- const binPath = path.join(dir, "node_modules", ".bin", cmd);
229
- if (fs.existsSync(binPath)) return true;
230
- const parent = path.dirname(dir);
231
- if (parent === dir) break;
232
- dir = parent;
233
- }
234
- return false;
235
- }
236
221
  async function detectAgents() {
237
222
  const found = [];
238
223
  for (const agent of KNOWN_AGENTS) {
@@ -324,20 +309,82 @@ async function setupTelegram() {
324
309
  };
325
310
  }
326
311
  async function setupAgents() {
327
- const detected = await detectAgents();
328
- const agents = {};
329
- agents["claude"] = { command: "claude-agent-acp", args: [], env: {} };
330
- for (const agent of detected) {
331
- if (agent.name !== "claude") {
332
- agents[agent.name] = { command: agent.command, args: [], env: {} };
312
+ const { AgentCatalog } = await import("./agent-catalog-LAAVBVLY.js");
313
+ const { select: select2, checkbox } = await import("@inquirer/prompts");
314
+ const catalog = new AgentCatalog();
315
+ catalog.load();
316
+ console.log(dim(" Checking available agents..."));
317
+ await catalog.refreshRegistryIfStale();
318
+ if (!catalog.getInstalledAgent("claude")) {
319
+ const claudeRegistry = catalog.findRegistryAgent("claude-acp");
320
+ if (claudeRegistry) {
321
+ await catalog.install("claude-acp");
322
+ } else {
323
+ const { AgentStore } = await import("./agent-store-ZBXGOFPH.js");
324
+ const store = new AgentStore();
325
+ store.load();
326
+ store.addAgent("claude", {
327
+ registryId: "claude-acp",
328
+ name: "Claude Agent",
329
+ version: "bundled",
330
+ distribution: "npx",
331
+ command: "npx",
332
+ args: ["@zed-industries/claude-agent-acp"],
333
+ env: {},
334
+ installedAt: (/* @__PURE__ */ new Date()).toISOString(),
335
+ binaryPath: null
336
+ });
333
337
  }
334
338
  }
335
- const defaultAgent = Object.keys(agents)[0];
336
- const agentCmd = agents[defaultAgent].command;
337
- console.log(
338
- ok(`Agent: ${c.bold}${defaultAgent}${c.reset}${c.green} (${agentCmd})`)
339
- );
340
- return { agents, defaultAgent };
339
+ console.log(ok("Claude Agent ready"));
340
+ const available = catalog.getAvailable();
341
+ const installed = available.filter((a) => a.installed);
342
+ const installable = available.filter((a) => !a.installed && a.available);
343
+ if (installed.length > 0 || installable.length > 0) {
344
+ const choices = [
345
+ ...installed.map((a) => ({
346
+ name: `${a.name} (installed)`,
347
+ value: a.key,
348
+ checked: true,
349
+ disabled: "(already installed)"
350
+ })),
351
+ ...installable.slice(0, 10).map((a) => ({
352
+ name: `${a.name} (${a.distribution})`,
353
+ value: a.key,
354
+ checked: false
355
+ }))
356
+ ];
357
+ const selected = await checkbox({
358
+ message: "Install additional agents? (Space to select, Enter to continue)",
359
+ choices
360
+ });
361
+ for (const key of selected) {
362
+ const regAgent = catalog.findRegistryAgent(key);
363
+ if (regAgent) {
364
+ process.stdout.write(` Installing ${regAgent.name}... `);
365
+ const result = await catalog.install(key);
366
+ if (result.ok) {
367
+ console.log(ok("done"));
368
+ } else {
369
+ console.log(warn(`skipped: ${result.error}`));
370
+ }
371
+ }
372
+ }
373
+ }
374
+ const installedAgents = Object.keys(catalog.getInstalledEntries());
375
+ let defaultAgent = "claude";
376
+ if (installedAgents.length > 1) {
377
+ defaultAgent = await select2({
378
+ message: "Which agent should be the default?",
379
+ choices: installedAgents.map((key) => {
380
+ const agent = catalog.getInstalledAgent(key);
381
+ return { name: `${agent.name} (${key})`, value: key };
382
+ }),
383
+ default: "claude"
384
+ });
385
+ }
386
+ console.log(ok(`Default agent: ${c.bold}${defaultAgent}${c.reset}`));
387
+ return { defaultAgent };
341
388
  }
342
389
  async function setupWorkspace() {
343
390
  console.log(step(2, "Workspace"));
@@ -395,8 +442,8 @@ async function runSetup(configManager) {
395
442
  printWelcomeBanner();
396
443
  try {
397
444
  const telegram = await setupTelegram();
398
- const { agents, defaultAgent } = await setupAgents();
399
- if (agents["claude"]) {
445
+ const { defaultAgent } = await setupAgents();
446
+ {
400
447
  const { confirm } = await import("@inquirer/prompts");
401
448
  const installClaude = await confirm({
402
449
  message: "Install session transfer for Claude? (enables /openacp:handoff in your terminal)",
@@ -404,7 +451,7 @@ async function runSetup(configManager) {
404
451
  });
405
452
  if (installClaude) {
406
453
  try {
407
- const { getIntegration } = await import("./integrate-WUPLRJD3.js");
454
+ const { getIntegration } = await import("./integrate-X7LI6MUO.js");
408
455
  const integration = getIntegration("claude");
409
456
  if (integration) {
410
457
  for (const item of integration.items) {
@@ -428,7 +475,7 @@ async function runSetup(configManager) {
428
475
  };
429
476
  const config = {
430
477
  channels: { telegram },
431
- agents,
478
+ agents: {},
432
479
  defaultAgent,
433
480
  workspace,
434
481
  security,
@@ -506,4 +553,4 @@ export {
506
553
  setupRunMode,
507
554
  runSetup
508
555
  };
509
- //# sourceMappingURL=chunk-W7QQA6CW.js.map
556
+ //# sourceMappingURL=chunk-QODDJ4PH.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../../src/core/setup.ts"],"sourcesContent":["import { execFileSync } from \"node:child_process\";\nimport { input, select } from \"@inquirer/prompts\";\nimport type { Config, ConfigManager } from \"./config.js\";\nimport { expandHome } from \"./config.js\";\nimport { commandExists } from \"./agent-dependencies.js\";\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, title: string) =>\n `\\n${c.cyan}${c.bold}[${n}/3]${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\nfunction promptManualChatId(): Promise<number> {\n return input({\n message: \"Supergroup chat ID (e.g. -1001234567890):\",\n validate: (val) => {\n const n = Number(val.trim());\n if (isNaN(n) || !Number.isInteger(n)) return \"Chat ID must be an integer\";\n return true;\n },\n }).then((val) => 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 choices = [...groups.entries()].map(([id, title]) => ({\n name: `${title} (${id})`,\n value: id,\n }));\n return select({\n message: \"Multiple groups found. Pick one:\",\n choices,\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(): Promise<Config[\"channels\"][string]> {\n console.log(step(1, \"Telegram Bot\"));\n\n let botToken = \"\";\n\n while (true) {\n botToken = await input({\n message: \"Bot token (from @BotFather):\",\n validate: (val) => val.trim().length > 0 || \"Token cannot be empty\",\n });\n botToken = botToken.trim();\n\n const result = await validateBotToken(botToken);\n if (result.ok) {\n console.log(ok(`Connected to @${result.botUsername}`));\n break;\n }\n console.log(fail(result.error));\n const action = await select({\n message: \"What to do?\",\n choices: [\n { name: \"Re-enter token\", value: \"retry\" },\n { name: \"Use as-is (skip validation)\", value: \"skip\" },\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 await input({ 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 await input({ 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\nexport async function setupAgents(): Promise<{\n defaultAgent: string;\n}> {\n const { AgentCatalog } = await import(\"./agent-catalog.js\");\n const { select, checkbox } = await import(\"@inquirer/prompts\");\n\n const catalog = new AgentCatalog();\n catalog.load();\n\n console.log(dim(\" 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 console.log(ok(\"Claude Agent ready\"));\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 + disabled\n if (installed.length > 0 || installable.length > 0) {\n const choices = [\n ...installed.map((a) => ({\n name: `${a.name} (installed)`,\n value: a.key,\n checked: true,\n disabled: \"(already installed)\",\n })),\n ...installable.slice(0, 10).map((a) => ({\n name: `${a.name} (${a.distribution})`,\n value: a.key,\n checked: false,\n })),\n ];\n\n const selected = await checkbox({\n message: \"Install additional agents? (Space to select, Enter to continue)\",\n choices,\n });\n\n for (const key of selected) {\n const regAgent = catalog.findRegistryAgent(key);\n if (regAgent) {\n process.stdout.write(` Installing ${regAgent.name}... `);\n const result = await catalog.install(key);\n if (result.ok) {\n console.log(ok(\"done\"));\n } else {\n console.log(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 = await select({\n message: \"Which agent should be the default?\",\n choices: installedAgents.map((key) => {\n const agent = catalog.getInstalledAgent(key)!;\n return { name: `${agent.name} (${key})`, value: key };\n }),\n default: \"claude\",\n });\n }\n\n console.log(ok(`Default agent: ${c.bold}${defaultAgent}${c.reset}`));\n return { defaultAgent };\n}\n\nexport async function setupWorkspace(): Promise<{ baseDir: string }> {\n console.log(step(2, \"Workspace\"));\n\n const baseDir = await input({\n message: \"Base directory for workspaces:\",\n default: \"~/openacp-workspace\",\n validate: (val) => val.trim().length > 0 || \"Path cannot be empty\",\n });\n\n return { baseDir: baseDir.trim().replace(/^['\"]|['\"]$/g, \"\") };\n}\n\nexport async function setupRunMode(): Promise<{ runMode: 'foreground' | 'daemon'; autoStart: boolean }> {\n console.log(step(3, '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 = await select({\n message: 'How would you like to run OpenACP?',\n choices: [\n {\n name: 'Background (daemon)',\n value: 'daemon' as const,\n description: 'Runs silently, auto-starts on boot. Manage with: openacp status | stop | logs',\n },\n {\n name: 'Foreground (terminal)',\n value: 'foreground' as const,\n description: 'Runs in current terminal session. Start with: openacp',\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 printWelcomeBanner(): void {\n console.log(`\n${c.cyan}${c.bold} ╔══════════════════════════════╗\n ║ Welcome to OpenACP ║\n ╚══════════════════════════════╝${c.reset}\n`);\n}\n\nexport async function runSetup(configManager: ConfigManager): Promise<boolean> {\n printWelcomeBanner();\n\n try {\n const telegram = await setupTelegram();\n const { defaultAgent } = await setupAgents();\n\n // Offer Claude CLI integration\n {\n const { confirm } = await import(\"@inquirer/prompts\");\n const installClaude = await confirm({\n message: \"Install session transfer for Claude? (enables /openacp:handoff in your terminal)\",\n default: true,\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 const workspace = await setupWorkspace();\n const { runMode, autoStart } = await setupRunMode();\n const security = {\n allowedUserIds: [] as string[],\n maxConcurrentSessions: 20,\n sessionTimeoutMinutes: 60,\n };\n\n const config: Config = {\n channels: { telegram },\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 storeTtlMinutes: 60,\n auth: { enabled: false },\n },\n integrations: {},\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 console.log(\"\");\n console.log(\n ok(`Config saved to ${c.bold}${configManager.getConfigPath()}`),\n );\n\n // Pre-download cloudflared if tunnel enabled\n if (config.tunnel.enabled && config.tunnel.provider === \"cloudflare\") {\n console.log(dim(\" Ensuring cloudflared is installed...\"));\n try {\n const { ensureCloudflared } = await import(\n \"../tunnel/providers/install-cloudflared.js\"\n );\n const binPath = await ensureCloudflared();\n console.log(ok(`cloudflared ready at ${dim(binPath)}`));\n } catch (err) {\n console.log(\n warn(\n `Could not install cloudflared: ${(err as Error).message}. Tunnel may not work.`,\n ),\n );\n }\n }\n\n console.log(ok(\"Starting OpenACP...\"));\n console.log(\"\");\n\n return true;\n } catch (err) {\n if ((err as Error).name === \"ExitPromptError\") {\n console.log(dim(\"\\nSetup cancelled.\"));\n return false;\n }\n throw err;\n }\n}\n"],"mappings":"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","names":["select"]}
@@ -1,6 +1,6 @@
1
1
  import {
2
2
  expandHome
3
- } from "./chunk-WYZFGHHI.js";
3
+ } from "./chunk-JRF4G4X7.js";
4
4
 
5
5
  // src/core/daemon.ts
6
6
  import { spawn } from "child_process";
@@ -126,4 +126,4 @@ export {
126
126
  clearRunning,
127
127
  shouldAutoStart
128
128
  };
129
- //# sourceMappingURL=chunk-YRJEZD7R.js.map
129
+ //# sourceMappingURL=chunk-VBEWSWVL.js.map
@@ -1,11 +1,24 @@
1
1
  // src/core/config-registry.ts
2
+ import * as fs from "fs";
3
+ import * as path from "path";
4
+ import * as os from "os";
2
5
  var CONFIG_REGISTRY = [
3
6
  {
4
7
  path: "defaultAgent",
5
8
  displayName: "Default Agent",
6
9
  group: "agent",
7
10
  type: "select",
8
- options: (config) => Object.keys(config.agents),
11
+ options: (config) => {
12
+ try {
13
+ const agentsPath = path.join(os.homedir(), ".openacp", "agents.json");
14
+ if (fs.existsSync(agentsPath)) {
15
+ const data = JSON.parse(fs.readFileSync(agentsPath, "utf-8"));
16
+ return Object.keys(data.installed ?? {});
17
+ }
18
+ } catch {
19
+ }
20
+ return Object.keys(config.agents ?? {});
21
+ },
9
22
  scope: "safe",
10
23
  hotReload: true
11
24
  },
@@ -59,22 +72,22 @@ var CONFIG_REGISTRY = [
59
72
  hotReload: true
60
73
  }
61
74
  ];
62
- function getFieldDef(path) {
63
- return CONFIG_REGISTRY.find((f) => f.path === path);
75
+ function getFieldDef(path2) {
76
+ return CONFIG_REGISTRY.find((f) => f.path === path2);
64
77
  }
65
78
  function getSafeFields() {
66
79
  return CONFIG_REGISTRY.filter((f) => f.scope === "safe");
67
80
  }
68
- function isHotReloadable(path) {
69
- const def = getFieldDef(path);
81
+ function isHotReloadable(path2) {
82
+ const def = getFieldDef(path2);
70
83
  return def?.hotReload ?? false;
71
84
  }
72
85
  function resolveOptions(def, config) {
73
86
  if (!def.options) return void 0;
74
87
  return typeof def.options === "function" ? def.options(config) : def.options;
75
88
  }
76
- function getConfigValue(config, path) {
77
- const parts = path.split(".");
89
+ function getConfigValue(config, path2) {
90
+ const parts = path2.split(".");
78
91
  let current = config;
79
92
  for (const part of parts) {
80
93
  if (current && typeof current === "object" && part in current) {
@@ -94,4 +107,4 @@ export {
94
107
  resolveOptions,
95
108
  getConfigValue
96
109
  };
97
- //# sourceMappingURL=chunk-C33LTDZV.js.map
110
+ //# sourceMappingURL=chunk-Z46LGZ7R.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../../src/core/config-registry.ts"],"sourcesContent":["import * as fs from \"node:fs\";\nimport * as path from \"node:path\";\nimport * as os from \"node:os\";\nimport type { Config } from './config.js'\n\nexport interface ConfigFieldDef {\n path: string\n displayName: string\n group: string\n type: 'toggle' | 'select' | 'number' | 'string'\n options?: string[] | ((config: Config) => string[])\n scope: 'safe' | 'sensitive'\n hotReload: boolean\n}\n\nexport const CONFIG_REGISTRY: ConfigFieldDef[] = [\n {\n path: 'defaultAgent',\n displayName: 'Default Agent',\n group: 'agent',\n type: 'select',\n options: (config) => {\n try {\n const agentsPath = path.join(os.homedir(), \".openacp\", \"agents.json\");\n if (fs.existsSync(agentsPath)) {\n const data = JSON.parse(fs.readFileSync(agentsPath, \"utf-8\"));\n return Object.keys(data.installed ?? {});\n }\n } catch { /* fallback */ }\n return Object.keys(config.agents ?? {});\n },\n scope: 'safe',\n hotReload: true,\n },\n {\n path: 'logging.level',\n displayName: 'Log Level',\n group: 'logging',\n type: 'select',\n options: ['silent', 'debug', 'info', 'warn', 'error', 'fatal'],\n scope: 'safe',\n hotReload: true,\n },\n {\n path: 'tunnel.enabled',\n displayName: 'Tunnel',\n group: 'tunnel',\n type: 'toggle',\n scope: 'safe',\n hotReload: false,\n },\n {\n path: 'security.maxConcurrentSessions',\n displayName: 'Max Concurrent Sessions',\n group: 'security',\n type: 'number',\n scope: 'safe',\n hotReload: true,\n },\n {\n path: 'security.sessionTimeoutMinutes',\n displayName: 'Session Timeout (min)',\n group: 'security',\n type: 'number',\n scope: 'safe',\n hotReload: true,\n },\n {\n path: 'workspace.baseDir',\n displayName: 'Workspace Directory',\n group: 'workspace',\n type: 'string',\n scope: 'safe',\n hotReload: true,\n },\n {\n path: 'sessionStore.ttlDays',\n displayName: 'Session Store TTL (days)',\n group: 'storage',\n type: 'number',\n scope: 'safe',\n hotReload: true,\n },\n]\n\nexport function getFieldDef(path: string): ConfigFieldDef | undefined {\n return CONFIG_REGISTRY.find((f) => f.path === path)\n}\n\nexport function getSafeFields(): ConfigFieldDef[] {\n return CONFIG_REGISTRY.filter((f) => f.scope === 'safe')\n}\n\nexport function isHotReloadable(path: string): boolean {\n const def = getFieldDef(path)\n return def?.hotReload ?? false\n}\n\nexport function resolveOptions(def: ConfigFieldDef, config: Config): string[] | undefined {\n if (!def.options) return undefined\n return typeof def.options === 'function' ? def.options(config) : def.options\n}\n\nexport function getConfigValue(config: Config, path: string): unknown {\n const parts = path.split('.')\n let current: unknown = config\n for (const part of parts) {\n if (current && typeof current === 'object' && part in current) {\n current = (current as Record<string, unknown>)[part]\n } else {\n return undefined\n }\n }\n return current\n}\n"],"mappings":";AAAA,YAAY,QAAQ;AACpB,YAAY,UAAU;AACtB,YAAY,QAAQ;AAab,IAAM,kBAAoC;AAAA,EAC/C;AAAA,IACE,MAAM;AAAA,IACN,aAAa;AAAA,IACb,OAAO;AAAA,IACP,MAAM;AAAA,IACN,SAAS,CAAC,WAAW;AACnB,UAAI;AACF,cAAM,aAAkB,UAAQ,WAAQ,GAAG,YAAY,aAAa;AACpE,YAAO,cAAW,UAAU,GAAG;AAC7B,gBAAM,OAAO,KAAK,MAAS,gBAAa,YAAY,OAAO,CAAC;AAC5D,iBAAO,OAAO,KAAK,KAAK,aAAa,CAAC,CAAC;AAAA,QACzC;AAAA,MACF,QAAQ;AAAA,MAAiB;AACzB,aAAO,OAAO,KAAK,OAAO,UAAU,CAAC,CAAC;AAAA,IACxC;AAAA,IACA,OAAO;AAAA,IACP,WAAW;AAAA,EACb;AAAA,EACA;AAAA,IACE,MAAM;AAAA,IACN,aAAa;AAAA,IACb,OAAO;AAAA,IACP,MAAM;AAAA,IACN,SAAS,CAAC,UAAU,SAAS,QAAQ,QAAQ,SAAS,OAAO;AAAA,IAC7D,OAAO;AAAA,IACP,WAAW;AAAA,EACb;AAAA,EACA;AAAA,IACE,MAAM;AAAA,IACN,aAAa;AAAA,IACb,OAAO;AAAA,IACP,MAAM;AAAA,IACN,OAAO;AAAA,IACP,WAAW;AAAA,EACb;AAAA,EACA;AAAA,IACE,MAAM;AAAA,IACN,aAAa;AAAA,IACb,OAAO;AAAA,IACP,MAAM;AAAA,IACN,OAAO;AAAA,IACP,WAAW;AAAA,EACb;AAAA,EACA;AAAA,IACE,MAAM;AAAA,IACN,aAAa;AAAA,IACb,OAAO;AAAA,IACP,MAAM;AAAA,IACN,OAAO;AAAA,IACP,WAAW;AAAA,EACb;AAAA,EACA;AAAA,IACE,MAAM;AAAA,IACN,aAAa;AAAA,IACb,OAAO;AAAA,IACP,MAAM;AAAA,IACN,OAAO;AAAA,IACP,WAAW;AAAA,EACb;AAAA,EACA;AAAA,IACE,MAAM;AAAA,IACN,aAAa;AAAA,IACb,OAAO;AAAA,IACP,MAAM;AAAA,IACN,OAAO;AAAA,IACP,WAAW;AAAA,EACb;AACF;AAEO,SAAS,YAAYA,OAA0C;AACpE,SAAO,gBAAgB,KAAK,CAAC,MAAM,EAAE,SAASA,KAAI;AACpD;AAEO,SAAS,gBAAkC;AAChD,SAAO,gBAAgB,OAAO,CAAC,MAAM,EAAE,UAAU,MAAM;AACzD;AAEO,SAAS,gBAAgBA,OAAuB;AACrD,QAAM,MAAM,YAAYA,KAAI;AAC5B,SAAO,KAAK,aAAa;AAC3B;AAEO,SAAS,eAAe,KAAqB,QAAsC;AACxF,MAAI,CAAC,IAAI,QAAS,QAAO;AACzB,SAAO,OAAO,IAAI,YAAY,aAAa,IAAI,QAAQ,MAAM,IAAI,IAAI;AACvE;AAEO,SAAS,eAAe,QAAgBA,OAAuB;AACpE,QAAM,QAAQA,MAAK,MAAM,GAAG;AAC5B,MAAI,UAAmB;AACvB,aAAW,QAAQ,OAAO;AACxB,QAAI,WAAW,OAAO,YAAY,YAAY,QAAQ,SAAS;AAC7D,gBAAW,QAAoC,IAAI;AAAA,IACrD,OAAO;AACL,aAAO;AAAA,IACT;AAAA,EACF;AACA,SAAO;AACT;","names":["path"]}