@openacp/cli 0.4.6 → 0.4.8

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 (35) hide show
  1. package/README.md +8 -8
  2. package/dist/{chunk-IUPHAXGA.js → chunk-6MJLVZXV.js} +3 -3
  3. package/dist/{chunk-2M4O7AFI.js → chunk-BBPWAWE3.js} +392 -37
  4. package/dist/chunk-BBPWAWE3.js.map +1 -0
  5. package/dist/{chunk-3QACY5E3.js → chunk-C6YIUTGR.js} +2 -2
  6. package/dist/{chunk-2SY7Y2VB.js → chunk-HZD3CGPK.js} +2 -2
  7. package/dist/{chunk-ARWC4S35.js → chunk-UAUTLC4E.js} +13 -7
  8. package/dist/{chunk-ARWC4S35.js.map → chunk-UAUTLC4E.js.map} +1 -1
  9. package/dist/{chunk-WF5XDN4D.js → chunk-ZRFBLD3W.js} +6 -2
  10. package/dist/chunk-ZRFBLD3W.js.map +1 -0
  11. package/dist/cli.js +37 -31
  12. package/dist/cli.js.map +1 -1
  13. package/dist/{config-J5YQOMDU.js → config-H2DSEHNW.js} +2 -2
  14. package/dist/config-editor-SKS4LJLT.js +11 -0
  15. package/dist/{daemon-SLGQGRKO.js → daemon-VF6HJQXD.js} +3 -3
  16. package/dist/index.d.ts +18 -0
  17. package/dist/index.js +6 -6
  18. package/dist/integrate-WUPLRJD3.js +145 -0
  19. package/dist/integrate-WUPLRJD3.js.map +1 -0
  20. package/dist/{main-3POGUQPY.js → main-NV7YN3VY.js} +11 -11
  21. package/dist/{setup-CEDO6VWV.js → setup-FCVL75K6.js} +3 -3
  22. package/package.json +1 -1
  23. package/dist/chunk-2M4O7AFI.js.map +0 -1
  24. package/dist/chunk-WF5XDN4D.js.map +0 -1
  25. package/dist/config-editor-EPOKAEP6.js +0 -11
  26. package/dist/integrate-HYDSHAF3.js +0 -123
  27. package/dist/integrate-HYDSHAF3.js.map +0 -1
  28. /package/dist/{chunk-IUPHAXGA.js.map → chunk-6MJLVZXV.js.map} +0 -0
  29. /package/dist/{chunk-3QACY5E3.js.map → chunk-C6YIUTGR.js.map} +0 -0
  30. /package/dist/{chunk-2SY7Y2VB.js.map → chunk-HZD3CGPK.js.map} +0 -0
  31. /package/dist/{config-J5YQOMDU.js.map → config-H2DSEHNW.js.map} +0 -0
  32. /package/dist/{config-editor-EPOKAEP6.js.map → config-editor-SKS4LJLT.js.map} +0 -0
  33. /package/dist/{daemon-SLGQGRKO.js.map → daemon-VF6HJQXD.js.map} +0 -0
  34. /package/dist/{main-3POGUQPY.js.map → main-NV7YN3VY.js.map} +0 -0
  35. /package/dist/{setup-CEDO6VWV.js.map → setup-FCVL75K6.js.map} +0 -0
@@ -1,6 +1,6 @@
1
1
  import {
2
2
  expandHome
3
- } from "./chunk-WF5XDN4D.js";
3
+ } from "./chunk-ZRFBLD3W.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-3QACY5E3.js.map
129
+ //# sourceMappingURL=chunk-C6YIUTGR.js.map
@@ -1,6 +1,6 @@
1
1
  import {
2
2
  PLUGINS_DIR
3
- } from "./chunk-WF5XDN4D.js";
3
+ } from "./chunk-ZRFBLD3W.js";
4
4
  import {
5
5
  createChildLogger
6
6
  } from "./chunk-LYKCQTH5.js";
@@ -60,4 +60,4 @@ export {
60
60
  listPlugins,
61
61
  loadAdapterFactory
62
62
  };
63
- //# sourceMappingURL=chunk-2SY7Y2VB.js.map
63
+ //# sourceMappingURL=chunk-HZD3CGPK.js.map
@@ -1,6 +1,6 @@
1
1
  import {
2
2
  expandHome
3
- } from "./chunk-WF5XDN4D.js";
3
+ } from "./chunk-ZRFBLD3W.js";
4
4
 
5
5
  // src/core/setup.ts
6
6
  import { execFileSync } from "child_process";
@@ -399,14 +399,19 @@ async function runSetup(configManager) {
399
399
  if (agents["claude"]) {
400
400
  const { confirm } = await import("@inquirer/prompts");
401
401
  const installClaude = await confirm({
402
- message: "Install handoff command for Claude CLI? (enables /openacp:handoff in Claude CLI)",
402
+ message: "Install session transfer for Claude? (enables /openacp:handoff in your terminal)",
403
403
  default: true
404
404
  });
405
405
  if (installClaude) {
406
406
  try {
407
- const { ClaudeIntegration } = await import("./integrate-HYDSHAF3.js");
408
- const integration = new ClaudeIntegration();
409
- await integration.install();
407
+ const { getIntegration } = await import("./integrate-WUPLRJD3.js");
408
+ const integration = getIntegration("claude");
409
+ if (integration) {
410
+ for (const item of integration.items) {
411
+ const result = await item.install();
412
+ for (const log of result.logs) console.log(` ${log}`);
413
+ }
414
+ }
410
415
  console.log("Claude CLI integration installed.\n");
411
416
  } catch (err) {
412
417
  console.log(`Could not install Claude CLI integration: ${err instanceof Error ? err.message : err}`);
@@ -448,7 +453,8 @@ async function runSetup(configManager) {
448
453
  options: {},
449
454
  storeTtlMinutes: 60,
450
455
  auth: { enabled: false }
451
- }
456
+ },
457
+ integrations: {}
452
458
  };
453
459
  try {
454
460
  await configManager.writeNew(config);
@@ -500,4 +506,4 @@ export {
500
506
  setupRunMode,
501
507
  runSetup
502
508
  };
503
- //# sourceMappingURL=chunk-ARWC4S35.js.map
509
+ //# sourceMappingURL=chunk-UAUTLC4E.js.map
@@ -1 +1 @@
1
- {"version":3,"sources":["../../src/core/setup.ts"],"sourcesContent":["import { execFileSync } from \"node:child_process\";\nimport * as fs from \"node:fs\";\nimport * as path from \"node:path\";\nimport { input, select } from \"@inquirer/prompts\";\nimport type { Config, ConfigManager } from \"./config.js\";\nimport { expandHome } from \"./config.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\nfunction commandExists(cmd: string): boolean {\n try {\n execFileSync(\"which\", [cmd], { stdio: \"pipe\" });\n return true;\n } catch {\n // not in PATH\n }\n // Check node_modules/.bin (walks up from cwd)\n let dir = process.cwd();\n while (true) {\n const binPath = path.join(dir, \"node_modules\", \".bin\", cmd);\n if (fs.existsSync(binPath)) return true;\n const parent = path.dirname(dir);\n if (parent === dir) break;\n dir = parent;\n }\n return false;\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 agents: Config[\"agents\"];\n defaultAgent: string;\n}> {\n const detected = await detectAgents();\n const agents: Config[\"agents\"] = {};\n\n // claude-agent-acp is always bundled, so always include it\n agents[\"claude\"] = { command: \"claude-agent-acp\", args: [], env: {} };\n\n // Add any other detected agents (e.g. codex)\n for (const agent of detected) {\n if (agent.name !== \"claude\") {\n agents[agent.name] = { command: agent.command, args: [], env: {} };\n }\n }\n\n const defaultAgent = Object.keys(agents)[0];\n const agentCmd = agents[defaultAgent].command;\n console.log(\n ok(`Agent: ${c.bold}${defaultAgent}${c.reset}${c.green} (${agentCmd})`),\n );\n\n return { agents, 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 { agents, defaultAgent } = await setupAgents();\n\n // Offer Claude CLI integration if claude agent detected\n if (agents[\"claude\"]) {\n const { confirm } = await import(\"@inquirer/prompts\");\n const installClaude = await confirm({\n message: \"Install handoff command for Claude CLI? (enables /openacp:handoff in Claude CLI)\",\n default: true,\n });\n\n if (installClaude) {\n try {\n const { ClaudeIntegration } = await import(\"../cli/integrate.js\");\n const integration = new ClaudeIntegration();\n await integration.install();\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 };\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":";;;;;AAAA,SAAS,oBAAoB;AAC7B,YAAY,QAAQ;AACpB,YAAY,UAAU;AACtB,SAAS,OAAO,cAAc;AAM9B,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,UACvB;AAAA,EAAK,EAAE,IAAI,GAAG,EAAE,IAAI,IAAI,CAAC,MAAM,EAAE,KAAK,IAAI,EAAE,IAAI,GAAG,KAAK,GAAG,EAAE,KAAK;AAAA;AACpE,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,SAAS,qBAAsC;AAC7C,SAAO,MAAM;AAAA,IACX,SAAS;AAAA,IACT,UAAU,CAAC,QAAQ;AACjB,YAAM,IAAI,OAAO,IAAI,KAAK,CAAC;AAC3B,UAAI,MAAM,CAAC,KAAK,CAAC,OAAO,UAAU,CAAC,EAAG,QAAO;AAC7C,aAAO;AAAA,IACT;AAAA,EACF,CAAC,EAAE,KAAK,CAAC,QAAQ,OAAO,IAAI,KAAK,CAAC,CAAC;AACrC;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,MAAM,GAAG,KAAK,KAAK,EAAE;AAAA,YACrB,OAAO;AAAA,UACT,EAAE;AACF,iBAAO,OAAO;AAAA,YACZ,SAAS;AAAA,YACT;AAAA,UACF,CAAC;AAAA,QACH;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,SAAS,cAAc,KAAsB;AAC3C,MAAI;AACF,iBAAa,SAAS,CAAC,GAAG,GAAG,EAAE,OAAO,OAAO,CAAC;AAC9C,WAAO;AAAA,EACT,QAAQ;AAAA,EAER;AAEA,MAAI,MAAM,QAAQ,IAAI;AACtB,SAAO,MAAM;AACX,UAAM,UAAe,UAAK,KAAK,gBAAgB,QAAQ,GAAG;AAC1D,QAAO,cAAW,OAAO,EAAG,QAAO;AACnC,UAAM,SAAc,aAAQ,GAAG;AAC/B,QAAI,WAAW,IAAK;AACpB,UAAM;AAAA,EACR;AACA,SAAO;AACT;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,gBAAqD;AACzE,UAAQ,IAAI,KAAK,GAAG,cAAc,CAAC;AAEnC,MAAI,WAAW;AAEf,SAAO,MAAM;AACX,eAAW,MAAM,MAAM;AAAA,MACrB,SAAS;AAAA,MACT,UAAU,CAAC,QAAQ,IAAI,KAAK,EAAE,SAAS,KAAK;AAAA,IAC9C,CAAC;AACD,eAAW,SAAS,KAAK;AAEzB,UAAM,SAAS,MAAM,iBAAiB,QAAQ;AAC9C,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,MAAM,OAAO;AAAA,MAC1B,SAAS;AAAA,MACT,SAAS;AAAA,QACP,EAAE,MAAM,kBAAkB,OAAO,QAAQ;AAAA,QACzC,EAAE,MAAM,+BAA+B,OAAO,OAAO;AAAA,MACvD;AAAA,IACF,CAAC;AACD,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,YAAM,MAAM,EAAE,SAAS,8BAA8B,CAAC;AACtD;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,YAAM,MAAM,EAAE,SAAS,gCAAgC,CAAC;AACxD;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;AAEA,eAAsB,cAGnB;AACD,QAAM,WAAW,MAAM,aAAa;AACpC,QAAM,SAA2B,CAAC;AAGlC,SAAO,QAAQ,IAAI,EAAE,SAAS,oBAAoB,MAAM,CAAC,GAAG,KAAK,CAAC,EAAE;AAGpE,aAAW,SAAS,UAAU;AAC5B,QAAI,MAAM,SAAS,UAAU;AAC3B,aAAO,MAAM,IAAI,IAAI,EAAE,SAAS,MAAM,SAAS,MAAM,CAAC,GAAG,KAAK,CAAC,EAAE;AAAA,IACnE;AAAA,EACF;AAEA,QAAM,eAAe,OAAO,KAAK,MAAM,EAAE,CAAC;AAC1C,QAAM,WAAW,OAAO,YAAY,EAAE;AACtC,UAAQ;AAAA,IACN,GAAG,UAAU,EAAE,IAAI,GAAG,YAAY,GAAG,EAAE,KAAK,GAAG,EAAE,KAAK,KAAK,QAAQ,GAAG;AAAA,EACxE;AAEA,SAAO,EAAE,QAAQ,aAAa;AAChC;AAEA,eAAsB,iBAA+C;AACnE,UAAQ,IAAI,KAAK,GAAG,WAAW,CAAC;AAEhC,QAAM,UAAU,MAAM,MAAM;AAAA,IAC1B,SAAS;AAAA,IACT,SAAS;AAAA,IACT,UAAU,CAAC,QAAQ,IAAI,KAAK,EAAE,SAAS,KAAK;AAAA,EAC9C,CAAC;AAED,SAAO,EAAE,SAAS,QAAQ,KAAK,EAAE,QAAQ,gBAAgB,EAAE,EAAE;AAC/D;AAEA,eAAsB,eAAkF;AACtG,UAAQ,IAAI,KAAK,GAAG,UAAU,CAAC;AAG/B,MAAI,QAAQ,aAAa,SAAS;AAChC,YAAQ,IAAI,IAAI,0CAA0C,CAAC;AAC3D,WAAO,EAAE,SAAS,cAAc,WAAW,MAAM;AAAA,EACnD;AAEA,QAAM,OAAO,MAAM,OAAO;AAAA,IACxB,SAAS;AAAA,IACT,SAAS;AAAA,MACP;AAAA,QACE,MAAM;AAAA,QACN,OAAO;AAAA,QACP,aAAa;AAAA,MACf;AAAA,MACA;AAAA,QACE,MAAM;AAAA,QACN,OAAO;AAAA,QACP,aAAa;AAAA,MACf;AAAA,IACF;AAAA,EACF,CAAC;AAED,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,qBAA2B;AAClC,UAAQ,IAAI;AAAA,EACZ,EAAE,IAAI,GAAG,EAAE,IAAI;AAAA;AAAA,oMAEmB,EAAE,KAAK;AAAA,CAC1C;AACD;AAEA,eAAsB,SAAS,eAAgD;AAC7E,qBAAmB;AAEnB,MAAI;AACF,UAAM,WAAW,MAAM,cAAc;AACrC,UAAM,EAAE,QAAQ,aAAa,IAAI,MAAM,YAAY;AAGnD,QAAI,OAAO,QAAQ,GAAG;AACpB,YAAM,EAAE,QAAQ,IAAI,MAAM,OAAO,mBAAmB;AACpD,YAAM,gBAAgB,MAAM,QAAQ;AAAA,QAClC,SAAS;AAAA,QACT,SAAS;AAAA,MACX,CAAC;AAED,UAAI,eAAe;AACjB,YAAI;AACF,gBAAM,EAAE,kBAAkB,IAAI,MAAM,OAAO,yBAAqB;AAChE,gBAAM,cAAc,IAAI,kBAAkB;AAC1C,gBAAM,YAAY,QAAQ;AAC1B,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,UAAM,YAAY,MAAM,eAAe;AACvC,UAAM,EAAE,SAAS,UAAU,IAAI,MAAM,aAAa;AAClD,UAAM,WAAW;AAAA,MACf,gBAAgB,CAAC;AAAA,MACjB,uBAAuB;AAAA,MACvB,uBAAuB;AAAA,IACzB;AAEA,UAAM,SAAiB;AAAA,MACrB,UAAU,EAAE,SAAS;AAAA,MACrB;AAAA,MACA;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,iBAAiB;AAAA,QACjB,MAAM,EAAE,SAAS,MAAM;AAAA,MACzB;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,YAAQ,IAAI,EAAE;AACd,YAAQ;AAAA,MACN,GAAG,mBAAmB,EAAE,IAAI,GAAG,cAAc,cAAc,CAAC,EAAE;AAAA,IAChE;AAGA,QAAI,OAAO,OAAO,WAAW,OAAO,OAAO,aAAa,cAAc;AACpE,cAAQ,IAAI,IAAI,wCAAwC,CAAC;AACzD,UAAI;AACF,cAAM,EAAE,kBAAkB,IAAI,MAAM,OAClC,mCACF;AACA,cAAM,UAAU,MAAM,kBAAkB;AACxC,gBAAQ,IAAI,GAAG,wBAAwB,IAAI,OAAO,CAAC,EAAE,CAAC;AAAA,MACxD,SAAS,KAAK;AACZ,gBAAQ;AAAA,UACN;AAAA,YACE,kCAAmC,IAAc,OAAO;AAAA,UAC1D;AAAA,QACF;AAAA,MACF;AAAA,IACF;AAEA,YAAQ,IAAI,GAAG,qBAAqB,CAAC;AACrC,YAAQ,IAAI,EAAE;AAEd,WAAO;AAAA,EACT,SAAS,KAAK;AACZ,QAAK,IAAc,SAAS,mBAAmB;AAC7C,cAAQ,IAAI,IAAI,oBAAoB,CAAC;AACrC,aAAO;AAAA,IACT;AACA,UAAM;AAAA,EACR;AACF;","names":[]}
1
+ {"version":3,"sources":["../../src/core/setup.ts"],"sourcesContent":["import { execFileSync } from \"node:child_process\";\nimport * as fs from \"node:fs\";\nimport * as path from \"node:path\";\nimport { input, select } from \"@inquirer/prompts\";\nimport type { Config, ConfigManager } from \"./config.js\";\nimport { expandHome } from \"./config.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\nfunction commandExists(cmd: string): boolean {\n try {\n execFileSync(\"which\", [cmd], { stdio: \"pipe\" });\n return true;\n } catch {\n // not in PATH\n }\n // Check node_modules/.bin (walks up from cwd)\n let dir = process.cwd();\n while (true) {\n const binPath = path.join(dir, \"node_modules\", \".bin\", cmd);\n if (fs.existsSync(binPath)) return true;\n const parent = path.dirname(dir);\n if (parent === dir) break;\n dir = parent;\n }\n return false;\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 agents: Config[\"agents\"];\n defaultAgent: string;\n}> {\n const detected = await detectAgents();\n const agents: Config[\"agents\"] = {};\n\n // claude-agent-acp is always bundled, so always include it\n agents[\"claude\"] = { command: \"claude-agent-acp\", args: [], env: {} };\n\n // Add any other detected agents (e.g. codex)\n for (const agent of detected) {\n if (agent.name !== \"claude\") {\n agents[agent.name] = { command: agent.command, args: [], env: {} };\n }\n }\n\n const defaultAgent = Object.keys(agents)[0];\n const agentCmd = agents[defaultAgent].command;\n console.log(\n ok(`Agent: ${c.bold}${defaultAgent}${c.reset}${c.green} (${agentCmd})`),\n );\n\n return { agents, 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 { agents, defaultAgent } = await setupAgents();\n\n // Offer Claude CLI integration if claude agent detected\n if (agents[\"claude\"]) {\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":[]}
@@ -118,7 +118,11 @@ var ConfigSchema = z.object({
118
118
  sessionStore: z.object({
119
119
  ttlDays: z.number().default(30)
120
120
  }).default({}),
121
- tunnel: TunnelSchema
121
+ tunnel: TunnelSchema,
122
+ integrations: z.record(z.string(), z.object({
123
+ installed: z.boolean(),
124
+ installedAt: z.string().optional()
125
+ })).default({})
122
126
  });
123
127
  function expandHome(p) {
124
128
  if (p.startsWith("~")) {
@@ -300,4 +304,4 @@ export {
300
304
  expandHome,
301
305
  ConfigManager
302
306
  };
303
- //# sourceMappingURL=chunk-WF5XDN4D.js.map
307
+ //# sourceMappingURL=chunk-ZRFBLD3W.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../../src/core/config.ts","../../src/core/config-migrations.ts"],"sourcesContent":["import { z } from \"zod\";\nimport * as fs from \"node:fs\";\nimport * as path from \"node:path\";\nimport * as os from \"node:os\";\nimport { applyMigrations } from \"./config-migrations.js\";\nimport { createChildLogger } from \"./log.js\";\nconst log = createChildLogger({ module: \"config\" });\n\nconst BaseChannelSchema = z\n .object({\n enabled: z.boolean().default(false),\n adapter: z.string().optional(), // package name for plugin adapters\n })\n .passthrough();\n\nexport const PLUGINS_DIR = path.join(os.homedir(), \".openacp\", \"plugins\");\n\nconst AgentSchema = z.object({\n command: z.string(),\n args: z.array(z.string()).default([]),\n workingDirectory: z.string().optional(),\n env: z.record(z.string(), z.string()).default({}),\n});\n\nconst LoggingSchema = z\n .object({\n level: z\n .enum([\"silent\", \"debug\", \"info\", \"warn\", \"error\", \"fatal\"])\n .default(\"info\"),\n logDir: z.string().default(\"~/.openacp/logs\"),\n maxFileSize: z.union([z.string(), z.number()]).default(\"10m\"),\n maxFiles: z.number().default(7),\n sessionLogRetentionDays: z.number().default(30),\n })\n .default({});\n\nexport type LoggingConfig = z.infer<typeof LoggingSchema>;\n\nconst TunnelAuthSchema = z\n .object({\n enabled: z.boolean().default(false),\n token: z.string().optional(),\n })\n .default({});\n\nconst TunnelSchema = z\n .object({\n enabled: z.boolean().default(false),\n port: z.number().default(3100),\n provider: z.enum([\"cloudflare\", \"ngrok\", \"bore\", \"tailscale\"]).default(\"cloudflare\"),\n options: z.record(z.string(), z.unknown()).default({}),\n storeTtlMinutes: z.number().default(60),\n auth: TunnelAuthSchema,\n })\n .default({});\n\nexport type TunnelConfig = z.infer<typeof TunnelSchema>;\n\nexport const ConfigSchema = z.object({\n channels: z.record(z.string(), BaseChannelSchema),\n agents: z.record(z.string(), AgentSchema),\n defaultAgent: z.string(),\n workspace: z\n .object({\n baseDir: z.string().default(\"~/openacp-workspace\"),\n })\n .default({}),\n security: z\n .object({\n allowedUserIds: z.array(z.string()).default([]),\n maxConcurrentSessions: z.number().default(20),\n sessionTimeoutMinutes: z.number().default(60),\n })\n .default({}),\n logging: LoggingSchema,\n runMode: z.enum(['foreground', 'daemon']).default('foreground'),\n autoStart: z.boolean().default(false),\n api: z.object({\n port: z.number().default(21420),\n host: z.string().default('127.0.0.1'),\n }).default({}),\n sessionStore: z\n .object({\n ttlDays: z.number().default(30),\n })\n .default({}),\n tunnel: TunnelSchema,\n integrations: z.record(z.string(), z.object({\n installed: z.boolean(),\n installedAt: z.string().optional(),\n })).default({}),\n});\n\nexport type Config = z.infer<typeof ConfigSchema>;\n\nexport function expandHome(p: string): string {\n if (p.startsWith(\"~\")) {\n return path.join(os.homedir(), p.slice(1));\n }\n return p;\n}\n\nconst DEFAULT_CONFIG = {\n channels: {\n telegram: {\n enabled: false,\n botToken: \"YOUR_BOT_TOKEN_HERE\",\n chatId: 0,\n notificationTopicId: null,\n assistantTopicId: null,\n },\n },\n agents: {\n claude: { command: \"claude-agent-acp\", args: [], env: {} },\n codex: { command: \"codex\", args: [\"--acp\"], env: {} },\n },\n defaultAgent: \"claude\",\n workspace: { baseDir: \"~/openacp-workspace\" },\n security: {\n allowedUserIds: [],\n maxConcurrentSessions: 20,\n sessionTimeoutMinutes: 60,\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};\n\nexport class ConfigManager {\n private config!: Config;\n private configPath: string;\n\n constructor() {\n this.configPath =\n process.env.OPENACP_CONFIG_PATH || expandHome(\"~/.openacp/config.json\");\n }\n\n async load(): Promise<void> {\n // 1. Ensure directory exists\n const dir = path.dirname(this.configPath);\n fs.mkdirSync(dir, { recursive: true });\n\n // 2. If config file doesn't exist, create default\n if (!fs.existsSync(this.configPath)) {\n fs.writeFileSync(\n this.configPath,\n JSON.stringify(DEFAULT_CONFIG, null, 2),\n );\n log.info({ configPath: this.configPath }, \"Config created\");\n log.info(\n \"Please edit it with your Telegram bot token and chat ID, then restart.\",\n );\n process.exit(1);\n }\n\n // 3. Read and parse\n const raw = JSON.parse(fs.readFileSync(this.configPath, \"utf-8\"));\n\n // 3.5. Auto-migrate config\n const { changed: configUpdated } = applyMigrations(raw);\n if (configUpdated) {\n fs.writeFileSync(this.configPath, JSON.stringify(raw, null, 2));\n }\n\n // 4. Apply env var overrides\n this.applyEnvOverrides(raw);\n\n // 5. Validate with Zod\n const result = ConfigSchema.safeParse(raw);\n if (!result.success) {\n log.error(\"Config validation failed\");\n for (const issue of result.error.issues) {\n log.error(\n { path: issue.path.join(\".\"), message: issue.message },\n \"Validation error\",\n );\n }\n process.exit(1);\n }\n this.config = result.data;\n }\n\n get(): Config {\n return this.config;\n }\n\n async save(updates: Record<string, unknown>): Promise<void> {\n // Read current file, merge updates, write back\n const raw = JSON.parse(fs.readFileSync(this.configPath, \"utf-8\"));\n this.deepMerge(raw, updates);\n fs.writeFileSync(this.configPath, JSON.stringify(raw, null, 2));\n // Re-validate and update in-memory config\n const result = ConfigSchema.safeParse(raw);\n if (result.success) {\n this.config = result.data;\n }\n }\n\n resolveWorkspace(input?: string): string {\n if (!input) {\n const resolved = expandHome(this.config.workspace.baseDir);\n fs.mkdirSync(resolved, { recursive: true });\n return resolved;\n }\n if (input.startsWith(\"/\") || input.startsWith(\"~\")) {\n const resolved = expandHome(input);\n fs.mkdirSync(resolved, { recursive: true });\n return resolved;\n }\n // Named workspace → lowercase, under baseDir\n const name = input.toLowerCase();\n const resolved = path.join(expandHome(this.config.workspace.baseDir), name);\n fs.mkdirSync(resolved, { recursive: true });\n return resolved;\n }\n\n async exists(): Promise<boolean> {\n return fs.existsSync(this.configPath);\n }\n\n getConfigPath(): string {\n return this.configPath;\n }\n\n async writeNew(config: Config): Promise<void> {\n const dir = path.dirname(this.configPath);\n fs.mkdirSync(dir, { recursive: true });\n fs.writeFileSync(this.configPath, JSON.stringify(config, null, 2));\n }\n\n private applyEnvOverrides(raw: Record<string, unknown>): void {\n const overrides: [string, string[]][] = [\n [\"OPENACP_TELEGRAM_BOT_TOKEN\", [\"channels\", \"telegram\", \"botToken\"]],\n [\"OPENACP_TELEGRAM_CHAT_ID\", [\"channels\", \"telegram\", \"chatId\"]],\n [\"OPENACP_DEFAULT_AGENT\", [\"defaultAgent\"]],\n [\"OPENACP_RUN_MODE\", [\"runMode\"]],\n [\"OPENACP_API_PORT\", [\"api\", \"port\"]],\n ];\n for (const [envVar, configPath] of overrides) {\n const value = process.env[envVar];\n if (value !== undefined) {\n let target = raw as Record<string, any>;\n for (let i = 0; i < configPath.length - 1; i++) {\n if (!target[configPath[i]]) target[configPath[i]] = {};\n target = target[configPath[i]];\n }\n const key = configPath[configPath.length - 1];\n // Convert numeric fields to number\n target[key] = (key === \"chatId\" || key === \"port\") ? Number(value) : value;\n }\n }\n\n // Logging env var overrides\n if (process.env.OPENACP_LOG_LEVEL) {\n raw.logging = raw.logging || {};\n (raw.logging as Record<string, unknown>).level =\n process.env.OPENACP_LOG_LEVEL;\n }\n if (process.env.OPENACP_LOG_DIR) {\n raw.logging = raw.logging || {};\n (raw.logging as Record<string, unknown>).logDir =\n process.env.OPENACP_LOG_DIR;\n }\n if (process.env.OPENACP_DEBUG && !process.env.OPENACP_LOG_LEVEL) {\n raw.logging = raw.logging || {};\n (raw.logging as Record<string, unknown>).level = \"debug\";\n }\n\n // Tunnel env var overrides\n if (process.env.OPENACP_TUNNEL_ENABLED) {\n raw.tunnel = raw.tunnel || {};\n (raw.tunnel as Record<string, unknown>).enabled =\n process.env.OPENACP_TUNNEL_ENABLED === \"true\";\n }\n if (process.env.OPENACP_TUNNEL_PORT) {\n raw.tunnel = raw.tunnel || {};\n (raw.tunnel as Record<string, unknown>).port = Number(\n process.env.OPENACP_TUNNEL_PORT,\n );\n }\n if (process.env.OPENACP_TUNNEL_PROVIDER) {\n raw.tunnel = raw.tunnel || {};\n (raw.tunnel as Record<string, unknown>).provider =\n process.env.OPENACP_TUNNEL_PROVIDER;\n }\n }\n\n private deepMerge(\n target: Record<string, any>,\n source: Record<string, any>,\n ): void {\n for (const key of Object.keys(source)) {\n if (\n source[key] &&\n typeof source[key] === \"object\" &&\n !Array.isArray(source[key])\n ) {\n if (!target[key]) target[key] = {};\n this.deepMerge(target[key], source[key]);\n } else {\n target[key] = source[key];\n }\n }\n }\n}\n","import { createChildLogger } from \"./log.js\";\nconst log = createChildLogger({ module: \"config-migrations\" });\n\ntype RawConfig = Record<string, unknown>;\n\nexport interface Migration {\n name: string;\n apply: (raw: RawConfig) => boolean; // returns true if config was modified\n}\n\nexport const migrations: Migration[] = [\n {\n name: \"add-tunnel-section\",\n apply(raw) {\n if (raw.tunnel) return false;\n raw.tunnel = {\n enabled: true,\n port: 3100,\n provider: \"cloudflare\",\n options: {},\n storeTtlMinutes: 60,\n auth: { enabled: false },\n };\n log.info(\"Added tunnel section to config (enabled by default with cloudflare)\");\n return true;\n },\n },\n {\n name: \"fix-agent-commands\",\n apply(raw) {\n const COMMAND_MIGRATIONS: Record<string, string[]> = {\n \"claude-agent-acp\": [\"claude\", \"claude-code\"],\n };\n\n const agents = raw.agents;\n if (!agents || typeof agents !== \"object\") return false;\n\n let changed = false;\n for (const [agentName, agentDef] of Object.entries(agents as Record<string, any>)) {\n if (!agentDef?.command) continue;\n for (const [correctCmd, legacyCmds] of Object.entries(COMMAND_MIGRATIONS)) {\n if (legacyCmds.includes(agentDef.command)) {\n log.warn(\n { agent: agentName, oldCommand: agentDef.command, newCommand: correctCmd },\n `Auto-migrating agent command: \"${agentDef.command}\" → \"${correctCmd}\"`,\n );\n agentDef.command = correctCmd;\n changed = true;\n }\n }\n }\n return changed;\n },\n },\n];\n\n/**\n * Apply all migrations to raw config (mutates in place).\n * Returns whether any changes were made.\n */\nexport function applyMigrations(\n raw: RawConfig,\n migrationList: Migration[] = migrations,\n): { changed: boolean } {\n let changed = false;\n for (const migration of migrationList) {\n if (migration.apply(raw)) {\n changed = true;\n }\n }\n return { changed };\n}\n"],"mappings":"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","names":["log","resolved"]}
package/dist/cli.js CHANGED
@@ -3,7 +3,7 @@ import {
3
3
  installPlugin,
4
4
  listPlugins,
5
5
  uninstallPlugin
6
- } from "./chunk-2SY7Y2VB.js";
6
+ } from "./chunk-HZD3CGPK.js";
7
7
  import {
8
8
  checkAndPromptUpdate,
9
9
  compareVersions,
@@ -11,7 +11,7 @@ import {
11
11
  getLatestVersion,
12
12
  runUpdate
13
13
  } from "./chunk-KSIQZC3J.js";
14
- import "./chunk-WF5XDN4D.js";
14
+ import "./chunk-ZRFBLD3W.js";
15
15
  import "./chunk-LYKCQTH5.js";
16
16
 
17
17
  // src/cli.ts
@@ -62,7 +62,7 @@ Usage:
62
62
  openacp --version Show version
63
63
  openacp --help Show this help
64
64
  adopt <agent> <id> Adopt an external agent session into OpenACP
65
- integrate <agent> Install/uninstall CLI integration for an agent
65
+ integrate <agent> Install/uninstall agent integration for session transfer
66
66
 
67
67
  API (requires running daemon):
68
68
  openacp api status Show active sessions
@@ -475,8 +475,8 @@ async function cmdApi(args2) {
475
475
  }
476
476
  async function cmdStart() {
477
477
  await checkAndPromptUpdate();
478
- const { startDaemon, getPidPath } = await import("./daemon-SLGQGRKO.js");
479
- const { ConfigManager } = await import("./config-J5YQOMDU.js");
478
+ const { startDaemon, getPidPath } = await import("./daemon-VF6HJQXD.js");
479
+ const { ConfigManager } = await import("./config-H2DSEHNW.js");
480
480
  const cm = new ConfigManager();
481
481
  if (await cm.exists()) {
482
482
  await cm.load();
@@ -493,7 +493,7 @@ async function cmdStart() {
493
493
  }
494
494
  }
495
495
  async function cmdStop() {
496
- const { stopDaemon } = await import("./daemon-SLGQGRKO.js");
496
+ const { stopDaemon } = await import("./daemon-VF6HJQXD.js");
497
497
  const result = stopDaemon();
498
498
  if (result.stopped) {
499
499
  console.log(`OpenACP daemon stopped (was PID ${result.pid})`);
@@ -503,7 +503,7 @@ async function cmdStop() {
503
503
  }
504
504
  }
505
505
  async function cmdStatus() {
506
- const { getStatus } = await import("./daemon-SLGQGRKO.js");
506
+ const { getStatus } = await import("./daemon-VF6HJQXD.js");
507
507
  const status = getStatus();
508
508
  if (status.running) {
509
509
  console.log(`OpenACP is running (PID ${status.pid})`);
@@ -513,7 +513,7 @@ async function cmdStatus() {
513
513
  }
514
514
  async function cmdLogs() {
515
515
  const { spawn } = await import("child_process");
516
- const { ConfigManager, expandHome } = await import("./config-J5YQOMDU.js");
516
+ const { ConfigManager, expandHome } = await import("./config-H2DSEHNW.js");
517
517
  const pathMod = await import("path");
518
518
  const cm = new ConfigManager();
519
519
  let logDir = "~/.openacp/logs";
@@ -529,8 +529,8 @@ async function cmdLogs() {
529
529
  });
530
530
  }
531
531
  async function cmdConfig() {
532
- const { runConfigEditor } = await import("./config-editor-EPOKAEP6.js");
533
- const { ConfigManager } = await import("./config-J5YQOMDU.js");
532
+ const { runConfigEditor } = await import("./config-editor-SKS4LJLT.js");
533
+ const { ConfigManager } = await import("./config-H2DSEHNW.js");
534
534
  const cm = new ConfigManager();
535
535
  if (!await cm.exists()) {
536
536
  console.error('No config found. Run "openacp" first to set up.');
@@ -539,7 +539,7 @@ async function cmdConfig() {
539
539
  await runConfigEditor(cm);
540
540
  }
541
541
  async function cmdReset() {
542
- const { getStatus } = await import("./daemon-SLGQGRKO.js");
542
+ const { getStatus } = await import("./daemon-VF6HJQXD.js");
543
543
  const status = getStatus();
544
544
  if (status.running) {
545
545
  console.error("OpenACP is running. Stop it first: openacp stop");
@@ -623,7 +623,7 @@ async function cmdAdopt(args2) {
623
623
  }
624
624
  }
625
625
  async function cmdIntegrate(args2) {
626
- const { getIntegration, listIntegrations } = await import("./integrate-HYDSHAF3.js");
626
+ const { getIntegration, listIntegrations } = await import("./integrate-WUPLRJD3.js");
627
627
  const agent = args2[1];
628
628
  const uninstall = args2.includes("--uninstall");
629
629
  if (!agent) {
@@ -637,22 +637,28 @@ async function cmdIntegrate(args2) {
637
637
  console.log(`Available: ${listIntegrations().join(", ")}`);
638
638
  process.exit(1);
639
639
  }
640
- try {
640
+ for (const item of integration.items) {
641
641
  if (uninstall) {
642
- console.log(`Removing ${agent} CLI integration...`);
643
- await integration.uninstall();
644
- console.log(`
645
- ${agent} CLI integration removed.`);
642
+ console.log(`Removing ${agent}/${item.id}...`);
643
+ const result = await item.uninstall();
644
+ for (const log of result.logs) console.log(` ${log}`);
645
+ if (result.success) {
646
+ console.log(` ${item.name} removed.`);
647
+ } else {
648
+ console.log(` Failed to remove ${item.name}.`);
649
+ process.exit(1);
650
+ }
646
651
  } else {
647
- console.log(`Installing ${agent} CLI integration...`);
648
- await integration.install();
649
- console.log(`
650
- ${agent} CLI integration installed.`);
651
- console.log(` Use /openacp:handoff in Claude CLI to hand off sessions.`);
652
+ console.log(`Installing ${agent}/${item.id}...`);
653
+ const result = await item.install();
654
+ for (const log of result.logs) console.log(` ${log}`);
655
+ if (result.success) {
656
+ console.log(` ${item.name} installed.`);
657
+ } else {
658
+ console.log(` Failed to install ${item.name}.`);
659
+ process.exit(1);
660
+ }
652
661
  }
653
- } catch (err) {
654
- console.log(`Error: ${err instanceof Error ? err.message : err}`);
655
- process.exit(1);
656
662
  }
657
663
  }
658
664
  async function cmdDefault(command2) {
@@ -663,17 +669,17 @@ async function cmdDefault(command2) {
663
669
  process.exit(1);
664
670
  }
665
671
  await checkAndPromptUpdate();
666
- const { ConfigManager } = await import("./config-J5YQOMDU.js");
672
+ const { ConfigManager } = await import("./config-H2DSEHNW.js");
667
673
  const cm = new ConfigManager();
668
674
  if (!await cm.exists()) {
669
- const { runSetup } = await import("./setup-CEDO6VWV.js");
675
+ const { runSetup } = await import("./setup-FCVL75K6.js");
670
676
  const shouldStart = await runSetup(cm);
671
677
  if (!shouldStart) process.exit(0);
672
678
  }
673
679
  await cm.load();
674
680
  const config = cm.get();
675
681
  if (!forceForeground && config.runMode === "daemon") {
676
- const { startDaemon, getPidPath } = await import("./daemon-SLGQGRKO.js");
682
+ const { startDaemon, getPidPath } = await import("./daemon-VF6HJQXD.js");
677
683
  const result = startDaemon(getPidPath(), config.logging.logDir);
678
684
  if ("error" in result) {
679
685
  console.error(result.error);
@@ -682,9 +688,9 @@ async function cmdDefault(command2) {
682
688
  console.log(`OpenACP daemon started (PID ${result.pid})`);
683
689
  return;
684
690
  }
685
- const { markRunning } = await import("./daemon-SLGQGRKO.js");
691
+ const { markRunning } = await import("./daemon-VF6HJQXD.js");
686
692
  markRunning();
687
- const { startServer } = await import("./main-3POGUQPY.js");
693
+ const { startServer } = await import("./main-NV7YN3VY.js");
688
694
  await startServer();
689
695
  }
690
696
 
@@ -711,7 +717,7 @@ var commands = {
711
717
  "adopt": () => cmdAdopt(args),
712
718
  "integrate": () => cmdIntegrate(args),
713
719
  "--daemon-child": async () => {
714
- const { startServer } = await import("./main-3POGUQPY.js");
720
+ const { startServer } = await import("./main-NV7YN3VY.js");
715
721
  await startServer();
716
722
  }
717
723
  };