@openacp/cli 0.6.6 → 0.6.7

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 (68) hide show
  1. package/dist/{adapter-RKK7A5GI.js → adapter-7GY3N4ZH.js} +9 -9
  2. package/dist/{admin-SCP25TN2.js → admin-2HAFXQBG.js} +6 -4
  3. package/dist/{chunk-WVMSP4AF.js → chunk-2J2RBYWN.js} +2 -2
  4. package/dist/{chunk-ZKTIZME6.js → chunk-47B7GNOE.js} +2 -2
  5. package/dist/{chunk-XVL6AGMG.js → chunk-5OVPEDUB.js} +2 -2
  6. package/dist/{chunk-AHPRT3RY.js → chunk-5SXG7X5D.js} +523 -251
  7. package/dist/chunk-5SXG7X5D.js.map +1 -0
  8. package/dist/{chunk-F3AICYO4.js → chunk-JHYXKVV2.js} +19 -1
  9. package/dist/chunk-JHYXKVV2.js.map +1 -0
  10. package/dist/{chunk-FCLGYYTY.js → chunk-JUYDFUSN.js} +224 -2
  11. package/dist/chunk-JUYDFUSN.js.map +1 -0
  12. package/dist/{chunk-774Y4RAK.js → chunk-KIRH7TUJ.js} +94 -24
  13. package/dist/chunk-KIRH7TUJ.js.map +1 -0
  14. package/dist/{chunk-4GQ3I65A.js → chunk-LBIKITQT.js} +1 -2
  15. package/dist/{chunk-4GQ3I65A.js.map → chunk-LBIKITQT.js.map} +1 -1
  16. package/dist/{chunk-ZMVVW3BK.js → chunk-LO4Y5WQ7.js} +127 -18
  17. package/dist/chunk-LO4Y5WQ7.js.map +1 -0
  18. package/dist/{chunk-3IRAWHMC.js → chunk-MZXWCDBU.js} +3 -3
  19. package/dist/{chunk-YQRF3IOR.js → chunk-O7CPGUAI.js} +2 -2
  20. package/dist/{chunk-7KZI2236.js → chunk-RHE2JSYE.js} +2 -2
  21. package/dist/{chunk-3ZO3MHZN.js → chunk-SHHMBGB3.js} +4 -3
  22. package/dist/chunk-SHHMBGB3.js.map +1 -0
  23. package/dist/{chunk-JV6XQRAE.js → chunk-XANPHG7W.js} +2 -2
  24. package/dist/{chunk-PJVKOZTR.js → chunk-YEOY2PBJ.js} +2 -2
  25. package/dist/cli.js +21 -21
  26. package/dist/{config-B26J3XXN.js → config-CQAS6YHR.js} +2 -2
  27. package/dist/{config-editor-QTGUK3CD.js → config-editor-37BM56WF.js} +4 -4
  28. package/dist/{config-registry-7I6GGDOY.js → config-registry-HDXFES2D.js} +2 -2
  29. package/dist/{daemon-5DS5BQXJ.js → daemon-K33ZPSEZ.js} +3 -3
  30. package/dist/{discord-QKT3JMRW.js → discord-VOHXRTCH.js} +113 -131
  31. package/dist/discord-VOHXRTCH.js.map +1 -0
  32. package/dist/{doctor-QQ3YZEYV.js → doctor-HASEBMUD.js} +4 -4
  33. package/dist/doctor-W4VGLDVM.js +9 -0
  34. package/dist/index.d.ts +25 -9
  35. package/dist/index.js +11 -11
  36. package/dist/{main-B5L3DD3Y.js → main-DUXVFTDD.js} +19 -19
  37. package/dist/{new-session-K6UCWYOP.js → new-session-NHK7TOEW.js} +3 -3
  38. package/dist/{settings-RRF77IC4.js → settings-6TF4WIGJ.js} +3 -3
  39. package/dist/{setup-5ZKSUR26.js → setup-RJCEB6FS.js} +3 -3
  40. package/package.json +1 -1
  41. package/dist/chunk-3ZO3MHZN.js.map +0 -1
  42. package/dist/chunk-774Y4RAK.js.map +0 -1
  43. package/dist/chunk-AHPRT3RY.js.map +0 -1
  44. package/dist/chunk-F3AICYO4.js.map +0 -1
  45. package/dist/chunk-FCLGYYTY.js.map +0 -1
  46. package/dist/chunk-ZMVVW3BK.js.map +0 -1
  47. package/dist/discord-QKT3JMRW.js.map +0 -1
  48. package/dist/doctor-6SUCVUZB.js +0 -9
  49. /package/dist/{adapter-RKK7A5GI.js.map → adapter-7GY3N4ZH.js.map} +0 -0
  50. /package/dist/{admin-SCP25TN2.js.map → admin-2HAFXQBG.js.map} +0 -0
  51. /package/dist/{chunk-WVMSP4AF.js.map → chunk-2J2RBYWN.js.map} +0 -0
  52. /package/dist/{chunk-ZKTIZME6.js.map → chunk-47B7GNOE.js.map} +0 -0
  53. /package/dist/{chunk-XVL6AGMG.js.map → chunk-5OVPEDUB.js.map} +0 -0
  54. /package/dist/{chunk-3IRAWHMC.js.map → chunk-MZXWCDBU.js.map} +0 -0
  55. /package/dist/{chunk-YQRF3IOR.js.map → chunk-O7CPGUAI.js.map} +0 -0
  56. /package/dist/{chunk-7KZI2236.js.map → chunk-RHE2JSYE.js.map} +0 -0
  57. /package/dist/{chunk-JV6XQRAE.js.map → chunk-XANPHG7W.js.map} +0 -0
  58. /package/dist/{chunk-PJVKOZTR.js.map → chunk-YEOY2PBJ.js.map} +0 -0
  59. /package/dist/{config-B26J3XXN.js.map → config-CQAS6YHR.js.map} +0 -0
  60. /package/dist/{config-editor-QTGUK3CD.js.map → config-editor-37BM56WF.js.map} +0 -0
  61. /package/dist/{config-registry-7I6GGDOY.js.map → config-registry-HDXFES2D.js.map} +0 -0
  62. /package/dist/{daemon-5DS5BQXJ.js.map → daemon-K33ZPSEZ.js.map} +0 -0
  63. /package/dist/{doctor-6SUCVUZB.js.map → doctor-HASEBMUD.js.map} +0 -0
  64. /package/dist/{doctor-QQ3YZEYV.js.map → doctor-W4VGLDVM.js.map} +0 -0
  65. /package/dist/{main-B5L3DD3Y.js.map → main-DUXVFTDD.js.map} +0 -0
  66. /package/dist/{new-session-K6UCWYOP.js.map → new-session-NHK7TOEW.js.map} +0 -0
  67. /package/dist/{settings-RRF77IC4.js.map → settings-6TF4WIGJ.js.map} +0 -0
  68. /package/dist/{setup-5ZKSUR26.js.map → setup-RJCEB6FS.js.map} +0 -0
@@ -1,31 +1,31 @@
1
1
  #!/usr/bin/env node
2
2
  import {
3
3
  TelegramAdapter
4
- } from "./chunk-AHPRT3RY.js";
5
- import "./chunk-FCLGYYTY.js";
6
- import "./chunk-PJVKOZTR.js";
4
+ } from "./chunk-5SXG7X5D.js";
5
+ import "./chunk-JUYDFUSN.js";
6
+ import "./chunk-YEOY2PBJ.js";
7
7
  import "./chunk-7QJS2XBD.js";
8
8
  import {
9
9
  ApiServer,
10
10
  OpenACPCore,
11
11
  TopicManager
12
- } from "./chunk-ZMVVW3BK.js";
13
- import "./chunk-4GQ3I65A.js";
12
+ } from "./chunk-LO4Y5WQ7.js";
13
+ import "./chunk-LBIKITQT.js";
14
14
  import "./chunk-NAMYZIS5.js";
15
- import "./chunk-WVMSP4AF.js";
15
+ import "./chunk-2J2RBYWN.js";
16
16
  import "./chunk-UKT3G5IA.js";
17
17
  import "./chunk-34M4OS5P.js";
18
- import "./chunk-3IRAWHMC.js";
18
+ import "./chunk-MZXWCDBU.js";
19
19
  import "./chunk-2CJ46J3C.js";
20
- import "./chunk-ZKTIZME6.js";
20
+ import "./chunk-47B7GNOE.js";
21
21
  import "./chunk-JKBFUAJK.js";
22
22
  import {
23
23
  loadAdapterFactory
24
- } from "./chunk-XVL6AGMG.js";
25
- import "./chunk-F3AICYO4.js";
24
+ } from "./chunk-5OVPEDUB.js";
25
+ import "./chunk-JHYXKVV2.js";
26
26
  import {
27
27
  ConfigManager
28
- } from "./chunk-3ZO3MHZN.js";
28
+ } from "./chunk-SHHMBGB3.js";
29
29
  import {
30
30
  cleanupOldSessionLogs,
31
31
  initLogger,
@@ -40,7 +40,7 @@ var RESTART_EXIT_CODE = 75;
40
40
  var shuttingDown = false;
41
41
  async function startServer() {
42
42
  if (process.argv.includes("--daemon-child")) {
43
- const { writePidFile, readPidFile, getPidPath, shouldAutoStart } = await import("./daemon-5DS5BQXJ.js");
43
+ const { writePidFile, readPidFile, getPidPath, shouldAutoStart } = await import("./daemon-K33ZPSEZ.js");
44
44
  if (!shouldAutoStart()) {
45
45
  process.exit(0);
46
46
  }
@@ -59,7 +59,7 @@ async function startServer() {
59
59
  const configManager = new ConfigManager();
60
60
  const configExists = await configManager.exists();
61
61
  if (!configExists) {
62
- const { runSetup } = await import("./setup-5ZKSUR26.js");
62
+ const { runSetup } = await import("./setup-RJCEB6FS.js");
63
63
  const shouldStart = await runSetup(configManager);
64
64
  if (!shouldStart) process.exit(0);
65
65
  }
@@ -69,7 +69,7 @@ async function startServer() {
69
69
  log.debug({ configPath: configManager.getConfigPath() }, "Config loaded");
70
70
  const isForegroundTTY = !!(process.stdout.isTTY && !process.env.NO_COLOR && config.runMode !== "daemon");
71
71
  if (isForegroundTTY) {
72
- const { printStartBanner } = await import("./setup-5ZKSUR26.js");
72
+ const { printStartBanner } = await import("./setup-RJCEB6FS.js");
73
73
  await printStartBanner();
74
74
  }
75
75
  let spinner;
@@ -102,12 +102,12 @@ async function startServer() {
102
102
  core.registerAdapter("telegram", new TelegramAdapter(core, channelConfig));
103
103
  log.info({ adapter: "telegram" }, "Adapter registered");
104
104
  } else if (channelName === "slack") {
105
- const { SlackAdapter } = await import("./adapter-RKK7A5GI.js");
105
+ const { SlackAdapter } = await import("./adapter-7GY3N4ZH.js");
106
106
  const slackConfig = channelConfig;
107
107
  core.registerAdapter("slack", new SlackAdapter(core, slackConfig));
108
108
  log.info({ adapter: "slack" }, "Adapter registered");
109
109
  } else if (channelName === "discord") {
110
- const { DiscordAdapter } = await import("./discord-QKT3JMRW.js");
110
+ const { DiscordAdapter } = await import("./discord-VOHXRTCH.js");
111
111
  const discordConfig = channelConfig;
112
112
  core.registerAdapter("discord", new DiscordAdapter(core, discordConfig));
113
113
  log.info({ adapter: "discord" }, "Adapter registered");
@@ -144,13 +144,13 @@ async function startServer() {
144
144
  }
145
145
  const isDaemon = process.argv.includes("--daemon-child");
146
146
  if (isDaemon) {
147
- const { removePidFile, getPidPath } = await import("./daemon-5DS5BQXJ.js");
147
+ const { removePidFile, getPidPath } = await import("./daemon-K33ZPSEZ.js");
148
148
  removePidFile(getPidPath());
149
149
  }
150
150
  if (exitCode === RESTART_EXIT_CODE) {
151
151
  if (isDaemon) {
152
152
  const { spawn: spawnChild } = await import("child_process");
153
- const { expandHome } = await import("./config-B26J3XXN.js");
153
+ const { expandHome } = await import("./config-CQAS6YHR.js");
154
154
  const fs = await import("fs");
155
155
  const pathMod = await import("path");
156
156
  const cliPath = pathMod.resolve(process.argv[1]);
@@ -234,4 +234,4 @@ export {
234
234
  RESTART_EXIT_CODE,
235
235
  startServer
236
236
  };
237
- //# sourceMappingURL=main-B5L3DD3Y.js.map
237
+ //# sourceMappingURL=main-DUXVFTDD.js.map
@@ -3,8 +3,8 @@ import {
3
3
  handleNew,
4
4
  handleNewChat,
5
5
  handleNewSessionButton
6
- } from "./chunk-JV6XQRAE.js";
7
- import "./chunk-774Y4RAK.js";
6
+ } from "./chunk-XANPHG7W.js";
7
+ import "./chunk-KIRH7TUJ.js";
8
8
  import "./chunk-BNLGTZ34.js";
9
9
  import "./chunk-GAK6PIBW.js";
10
10
  export {
@@ -13,4 +13,4 @@ export {
13
13
  handleNewChat,
14
14
  handleNewSessionButton
15
15
  };
16
- //# sourceMappingURL=new-session-K6UCWYOP.js.map
16
+ //# sourceMappingURL=new-session-NHK7TOEW.js.map
@@ -2,12 +2,12 @@ import {
2
2
  handleSettings,
3
3
  handleSettingsButton,
4
4
  showSettingsInfo
5
- } from "./chunk-YQRF3IOR.js";
6
- import "./chunk-F3AICYO4.js";
5
+ } from "./chunk-O7CPGUAI.js";
6
+ import "./chunk-JHYXKVV2.js";
7
7
  import "./chunk-GAK6PIBW.js";
8
8
  export {
9
9
  handleSettings,
10
10
  handleSettingsButton,
11
11
  showSettingsInfo
12
12
  };
13
- //# sourceMappingURL=settings-RRF77IC4.js.map
13
+ //# sourceMappingURL=settings-6TF4WIGJ.js.map
@@ -12,9 +12,9 @@ import {
12
12
  validateBotToken,
13
13
  validateChatId,
14
14
  validateDiscordToken
15
- } from "./chunk-ZKTIZME6.js";
15
+ } from "./chunk-47B7GNOE.js";
16
16
  import "./chunk-JKBFUAJK.js";
17
- import "./chunk-3ZO3MHZN.js";
17
+ import "./chunk-SHHMBGB3.js";
18
18
  import "./chunk-GAK6PIBW.js";
19
19
  export {
20
20
  detectAgents,
@@ -31,4 +31,4 @@ export {
31
31
  validateChatId,
32
32
  validateDiscordToken
33
33
  };
34
- //# sourceMappingURL=setup-5ZKSUR26.js.map
34
+ //# sourceMappingURL=setup-RJCEB6FS.js.map
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@openacp/cli",
3
- "version": "0.6.6",
3
+ "version": "0.6.7",
4
4
  "description": "Self-hosted bridge for AI coding agents via ACP protocol",
5
5
  "type": "module",
6
6
  "bin": {
@@ -1 +0,0 @@
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 { EventEmitter } from \"node:events\";\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\n .enum([\"cloudflare\", \"ngrok\", \"bore\", \"tailscale\"])\n .default(\"cloudflare\"),\n options: z.record(z.string(), z.unknown()).default({}),\n maxUserTunnels: z.number().default(5),\n storeTtlMinutes: z.number().default(60),\n auth: TunnelAuthSchema,\n })\n .default({});\n\nexport type TunnelConfig = z.infer<typeof TunnelSchema>;\n\nconst SlackChannelConfigSchema = z.object({\n enabled: z.boolean().default(false),\n adapter: z.literal(\"slack\").optional(),\n botToken: z.string().optional(), // xoxb-...\n appToken: z.string().optional(), // xapp-... (Socket Mode)\n signingSecret: z.string().optional(),\n notificationChannelId: z.string().optional(),\n allowedUserIds: z.array(z.string()).default([]),\n channelPrefix: z.string().default(\"openacp\"),\n autoCreateSession: z.boolean().default(true),\n startupChannelId: z.string().optional(),\n});\n\nexport type SlackChannelConfig = z.infer<typeof SlackChannelConfigSchema>;\n\nconst UsageSchema = z\n .object({\n enabled: z.boolean().default(true),\n monthlyBudget: z.number().optional(),\n warningThreshold: z.number().default(0.8),\n currency: z.string().default(\"USD\"),\n retentionDays: z.number().default(90),\n })\n .default({});\n\nexport type UsageConfig = z.infer<typeof UsageSchema>;\n\nconst SpeechProviderSchema = z\n .object({\n apiKey: z.string().min(1).optional(),\n model: z.string().optional(),\n })\n .passthrough();\n\nconst SpeechSchema = z\n .object({\n stt: z\n .object({\n provider: z.string().nullable().default(null),\n providers: z.record(SpeechProviderSchema).default({}),\n })\n .default({}),\n tts: z\n .object({\n provider: z.string().nullable().default(null),\n providers: z.record(SpeechProviderSchema).default({}),\n })\n .default({}),\n })\n .optional()\n .default({});\n\nexport const ConfigSchema = z.object({\n channels: z.object({\n slack: SlackChannelConfigSchema.optional(),\n }).catchall(BaseChannelSchema),\n agents: z.record(z.string(), AgentSchema).optional().default({}),\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\n .object({\n port: z.number().default(21420),\n host: z.string().default(\"127.0.0.1\"),\n })\n .default({}),\n sessionStore: z\n .object({\n ttlDays: z.number().default(30),\n })\n .default({}),\n tunnel: TunnelSchema,\n usage: UsageSchema,\n integrations: z\n .record(\n z.string(),\n z.object({\n installed: z.boolean(),\n installedAt: z.string().optional(),\n }),\n )\n .default({}),\n speech: SpeechSchema,\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 discord: {\n enabled: false,\n botToken: \"YOUR_DISCORD_BOT_TOKEN_HERE\",\n guildId: \"\",\n forumChannelId: null,\n notificationChannelId: null,\n assistantThreadId: 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 usage: {},\n};\n\nexport class ConfigManager extends EventEmitter {\n private config!: Config;\n private configPath: string;\n\n constructor() {\n super();\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 channel credentials (Telegram bot token, Discord bot token, etc.), 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(\n updates: Record<string, unknown>,\n changePath?: string,\n ): Promise<void> {\n const oldConfig = this.config ? structuredClone(this.config) : undefined;\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 // Emit change event if path provided\n if (changePath) {\n const { getConfigValue } = await import(\"./config-registry.js\");\n const value = getConfigValue(this.config, changePath);\n const oldValue = oldConfig\n ? getConfigValue(oldConfig, changePath)\n : undefined;\n this.emit(\"config:changed\", { path: changePath, value, oldValue });\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_DISCORD_BOT_TOKEN\", [\"channels\", \"discord\", \"botToken\"]],\n [\"OPENACP_DISCORD_GUILD_ID\", [\"channels\", \"discord\", \"guildId\"]],\n [\"OPENACP_SLACK_BOT_TOKEN\", [\"channels\", \"slack\", \"botToken\"]],\n [\"OPENACP_SLACK_APP_TOKEN\", [\"channels\", \"slack\", \"appToken\"]],\n [\"OPENACP_SLACK_SIGNING_SECRET\", [\"channels\", \"slack\", \"signingSecret\"]],\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: Record<string, unknown> = raw;\n for (let i = 0; i < configPath.length - 1; i++) {\n if (!target[configPath[i]]) target[configPath[i]] = {};\n target = target[configPath[i]] as Record<string, unknown>;\n }\n const key = configPath[configPath.length - 1];\n // Convert numeric fields to number\n target[key] =\n 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 // Speech env var overrides\n if (process.env.OPENACP_SPEECH_STT_PROVIDER) {\n raw.speech = raw.speech || {};\n const speech = raw.speech as Record<string, unknown>;\n speech.stt = speech.stt || {};\n (speech.stt as Record<string, unknown>).provider = process.env.OPENACP_SPEECH_STT_PROVIDER;\n }\n if (process.env.OPENACP_SPEECH_GROQ_API_KEY) {\n raw.speech = raw.speech || {};\n const speech = raw.speech as Record<string, unknown>;\n speech.stt = speech.stt || {};\n const stt = speech.stt as Record<string, unknown>;\n stt.providers = stt.providers || {};\n const providers = stt.providers as Record<string, unknown>;\n providers.groq = providers.groq || {};\n (providers.groq as Record<string, unknown>).apiKey =\n process.env.OPENACP_SPEECH_GROQ_API_KEY;\n }\n }\n\n private deepMerge(\n target: Record<string, unknown>,\n source: Record<string, unknown>,\n ): void {\n for (const key of Object.keys(source)) {\n const val = source[key];\n if (\n val &&\n typeof val === \"object\" &&\n !Array.isArray(val)\n ) {\n if (!target[key]) target[key] = {};\n this.deepMerge(\n target[key] as Record<string, unknown>,\n val as Record<string, unknown>,\n );\n } else {\n target[key] = val;\n }\n }\n }\n}\n","import * as fs from \"node:fs\";\nimport * as path from \"node:path\";\nimport * as os from \"node:os\";\nimport { 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, unknown>)) {\n if (!agentDef || typeof agentDef !== \"object\" || !(\"command\" in agentDef)) continue;\n const def = agentDef as Record<string, unknown>;\n if (typeof def.command !== \"string\") continue;\n for (const [correctCmd, legacyCmds] of Object.entries(COMMAND_MIGRATIONS)) {\n if (legacyCmds.includes(def.command as string)) {\n log.warn(\n { agent: agentName, oldCommand: def.command, newCommand: correctCmd },\n `Auto-migrating agent command: \"${def.command}\" → \"${correctCmd}\"`,\n );\n def.command = correctCmd;\n changed = true;\n }\n }\n }\n return changed;\n },\n },\n {\n name: \"migrate-agents-to-store\",\n apply(raw) {\n const agentsJsonPath = path.join(os.homedir(), \".openacp\", \"agents.json\");\n if (fs.existsSync(agentsJsonPath)) return false;\n\n const agents = raw.agents as Record<string, unknown> | undefined;\n if (!agents || Object.keys(agents).length === 0) return false;\n\n const COMMAND_TO_REGISTRY: Record<string, string> = {\n \"claude-agent-acp\": \"claude-acp\",\n \"codex\": \"codex-acp\",\n };\n\n const installed: Record<string, unknown> = {};\n for (const [key, val] of Object.entries(agents)) {\n const cfg = val as Record<string, unknown>;\n const command = typeof cfg.command === \"string\" ? cfg.command : \"\";\n const registryId = COMMAND_TO_REGISTRY[command] ?? null;\n installed[key] = {\n registryId,\n name: key.charAt(0).toUpperCase() + key.slice(1),\n version: \"unknown\",\n distribution: \"custom\",\n command: cfg.command,\n args: cfg.args ?? [],\n env: cfg.env ?? {},\n workingDirectory: cfg.workingDirectory ?? undefined,\n installedAt: new Date().toISOString(),\n binaryPath: null,\n };\n }\n\n fs.mkdirSync(path.dirname(agentsJsonPath), { recursive: true });\n fs.writeFileSync(agentsJsonPath, JSON.stringify({ version: 1, installed }, null, 2));\n\n raw.agents = {};\n return true;\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":";;;;;AAAA,SAAS,SAAS;AAClB,YAAYA,SAAQ;AACpB,YAAYC,WAAU;AACtB,YAAYC,SAAQ;AACpB,SAAS,oBAAoB;;;ACJ7B,YAAY,QAAQ;AACpB,YAAY,UAAU;AACtB,YAAY,QAAQ;AAEpB,IAAM,MAAM,kBAAkB,EAAE,QAAQ,oBAAoB,CAAC;AAStD,IAAM,aAA0B;AAAA,EACrC;AAAA,IACE,MAAM;AAAA,IACN,MAAM,KAAK;AACT,UAAI,IAAI,OAAQ,QAAO;AACvB,UAAI,SAAS;AAAA,QACX,SAAS;AAAA,QACT,MAAM;AAAA,QACN,UAAU;AAAA,QACV,SAAS,CAAC;AAAA,QACV,iBAAiB;AAAA,QACjB,MAAM,EAAE,SAAS,MAAM;AAAA,MACzB;AACA,UAAI,KAAK,qEAAqE;AAC9E,aAAO;AAAA,IACT;AAAA,EACF;AAAA,EACA;AAAA,IACE,MAAM;AAAA,IACN,MAAM,KAAK;AACT,YAAM,qBAA+C;AAAA,QACnD,oBAAoB,CAAC,UAAU,aAAa;AAAA,MAC9C;AAEA,YAAM,SAAS,IAAI;AACnB,UAAI,CAAC,UAAU,OAAO,WAAW,SAAU,QAAO;AAElD,UAAI,UAAU;AACd,iBAAW,CAAC,WAAW,QAAQ,KAAK,OAAO,QAAQ,MAAiC,GAAG;AACrF,YAAI,CAAC,YAAY,OAAO,aAAa,YAAY,EAAE,aAAa,UAAW;AAC3E,cAAM,MAAM;AACZ,YAAI,OAAO,IAAI,YAAY,SAAU;AACrC,mBAAW,CAAC,YAAY,UAAU,KAAK,OAAO,QAAQ,kBAAkB,GAAG;AACzE,cAAI,WAAW,SAAS,IAAI,OAAiB,GAAG;AAC9C,gBAAI;AAAA,cACF,EAAE,OAAO,WAAW,YAAY,IAAI,SAAS,YAAY,WAAW;AAAA,cACpE,kCAAkC,IAAI,OAAO,aAAQ,UAAU;AAAA,YACjE;AACA,gBAAI,UAAU;AACd,sBAAU;AAAA,UACZ;AAAA,QACF;AAAA,MACF;AACA,aAAO;AAAA,IACT;AAAA,EACF;AAAA,EACA;AAAA,IACE,MAAM;AAAA,IACN,MAAM,KAAK;AACT,YAAM,iBAAsB,UAAQ,WAAQ,GAAG,YAAY,aAAa;AACxE,UAAO,cAAW,cAAc,EAAG,QAAO;AAE1C,YAAM,SAAS,IAAI;AACnB,UAAI,CAAC,UAAU,OAAO,KAAK,MAAM,EAAE,WAAW,EAAG,QAAO;AAExD,YAAM,sBAA8C;AAAA,QAClD,oBAAoB;AAAA,QACpB,SAAS;AAAA,MACX;AAEA,YAAM,YAAqC,CAAC;AAC5C,iBAAW,CAAC,KAAK,GAAG,KAAK,OAAO,QAAQ,MAAM,GAAG;AAC/C,cAAM,MAAM;AACZ,cAAM,UAAU,OAAO,IAAI,YAAY,WAAW,IAAI,UAAU;AAChE,cAAM,aAAa,oBAAoB,OAAO,KAAK;AACnD,kBAAU,GAAG,IAAI;AAAA,UACf;AAAA,UACA,MAAM,IAAI,OAAO,CAAC,EAAE,YAAY,IAAI,IAAI,MAAM,CAAC;AAAA,UAC/C,SAAS;AAAA,UACT,cAAc;AAAA,UACd,SAAS,IAAI;AAAA,UACb,MAAM,IAAI,QAAQ,CAAC;AAAA,UACnB,KAAK,IAAI,OAAO,CAAC;AAAA,UACjB,kBAAkB,IAAI,oBAAoB;AAAA,UAC1C,cAAa,oBAAI,KAAK,GAAE,YAAY;AAAA,UACpC,YAAY;AAAA,QACd;AAAA,MACF;AAEA,MAAG,aAAe,aAAQ,cAAc,GAAG,EAAE,WAAW,KAAK,CAAC;AAC9D,MAAG,iBAAc,gBAAgB,KAAK,UAAU,EAAE,SAAS,GAAG,UAAU,GAAG,MAAM,CAAC,CAAC;AAEnF,UAAI,SAAS,CAAC;AACd,aAAO;AAAA,IACT;AAAA,EACF;AACF;AAMO,SAAS,gBACd,KACA,gBAA6B,YACP;AACtB,MAAI,UAAU;AACd,aAAW,aAAa,eAAe;AACrC,QAAI,UAAU,MAAM,GAAG,GAAG;AACxB,gBAAU;AAAA,IACZ;AAAA,EACF;AACA,SAAO,EAAE,QAAQ;AACnB;;;AD7GA,IAAMC,OAAM,kBAAkB,EAAE,QAAQ,SAAS,CAAC;AAElD,IAAM,oBAAoB,EACvB,OAAO;AAAA,EACN,SAAS,EAAE,QAAQ,EAAE,QAAQ,KAAK;AAAA,EAClC,SAAS,EAAE,OAAO,EAAE,SAAS;AAAA;AAC/B,CAAC,EACA,YAAY;AAER,IAAM,cAAmB,WAAQ,YAAQ,GAAG,YAAY,SAAS;AAExE,IAAM,cAAc,EAAE,OAAO;AAAA,EAC3B,SAAS,EAAE,OAAO;AAAA,EAClB,MAAM,EAAE,MAAM,EAAE,OAAO,CAAC,EAAE,QAAQ,CAAC,CAAC;AAAA,EACpC,kBAAkB,EAAE,OAAO,EAAE,SAAS;AAAA,EACtC,KAAK,EAAE,OAAO,EAAE,OAAO,GAAG,EAAE,OAAO,CAAC,EAAE,QAAQ,CAAC,CAAC;AAClD,CAAC;AAED,IAAM,gBAAgB,EACnB,OAAO;AAAA,EACN,OAAO,EACJ,KAAK,CAAC,UAAU,SAAS,QAAQ,QAAQ,SAAS,OAAO,CAAC,EAC1D,QAAQ,MAAM;AAAA,EACjB,QAAQ,EAAE,OAAO,EAAE,QAAQ,iBAAiB;AAAA,EAC5C,aAAa,EAAE,MAAM,CAAC,EAAE,OAAO,GAAG,EAAE,OAAO,CAAC,CAAC,EAAE,QAAQ,KAAK;AAAA,EAC5D,UAAU,EAAE,OAAO,EAAE,QAAQ,CAAC;AAAA,EAC9B,yBAAyB,EAAE,OAAO,EAAE,QAAQ,EAAE;AAChD,CAAC,EACA,QAAQ,CAAC,CAAC;AAIb,IAAM,mBAAmB,EACtB,OAAO;AAAA,EACN,SAAS,EAAE,QAAQ,EAAE,QAAQ,KAAK;AAAA,EAClC,OAAO,EAAE,OAAO,EAAE,SAAS;AAC7B,CAAC,EACA,QAAQ,CAAC,CAAC;AAEb,IAAM,eAAe,EAClB,OAAO;AAAA,EACN,SAAS,EAAE,QAAQ,EAAE,QAAQ,KAAK;AAAA,EAClC,MAAM,EAAE,OAAO,EAAE,QAAQ,IAAI;AAAA,EAC7B,UAAU,EACP,KAAK,CAAC,cAAc,SAAS,QAAQ,WAAW,CAAC,EACjD,QAAQ,YAAY;AAAA,EACvB,SAAS,EAAE,OAAO,EAAE,OAAO,GAAG,EAAE,QAAQ,CAAC,EAAE,QAAQ,CAAC,CAAC;AAAA,EACrD,gBAAgB,EAAE,OAAO,EAAE,QAAQ,CAAC;AAAA,EACpC,iBAAiB,EAAE,OAAO,EAAE,QAAQ,EAAE;AAAA,EACtC,MAAM;AACR,CAAC,EACA,QAAQ,CAAC,CAAC;AAIb,IAAM,2BAA2B,EAAE,OAAO;AAAA,EACxC,SAAS,EAAE,QAAQ,EAAE,QAAQ,KAAK;AAAA,EAClC,SAAS,EAAE,QAAQ,OAAO,EAAE,SAAS;AAAA,EACrC,UAAU,EAAE,OAAO,EAAE,SAAS;AAAA;AAAA,EAC9B,UAAU,EAAE,OAAO,EAAE,SAAS;AAAA;AAAA,EAC9B,eAAe,EAAE,OAAO,EAAE,SAAS;AAAA,EACnC,uBAAuB,EAAE,OAAO,EAAE,SAAS;AAAA,EAC3C,gBAAgB,EAAE,MAAM,EAAE,OAAO,CAAC,EAAE,QAAQ,CAAC,CAAC;AAAA,EAC9C,eAAe,EAAE,OAAO,EAAE,QAAQ,SAAS;AAAA,EAC3C,mBAAmB,EAAE,QAAQ,EAAE,QAAQ,IAAI;AAAA,EAC3C,kBAAkB,EAAE,OAAO,EAAE,SAAS;AACxC,CAAC;AAID,IAAM,cAAc,EACjB,OAAO;AAAA,EACN,SAAS,EAAE,QAAQ,EAAE,QAAQ,IAAI;AAAA,EACjC,eAAe,EAAE,OAAO,EAAE,SAAS;AAAA,EACnC,kBAAkB,EAAE,OAAO,EAAE,QAAQ,GAAG;AAAA,EACxC,UAAU,EAAE,OAAO,EAAE,QAAQ,KAAK;AAAA,EAClC,eAAe,EAAE,OAAO,EAAE,QAAQ,EAAE;AACtC,CAAC,EACA,QAAQ,CAAC,CAAC;AAIb,IAAM,uBAAuB,EAC1B,OAAO;AAAA,EACN,QAAQ,EAAE,OAAO,EAAE,IAAI,CAAC,EAAE,SAAS;AAAA,EACnC,OAAO,EAAE,OAAO,EAAE,SAAS;AAC7B,CAAC,EACA,YAAY;AAEf,IAAM,eAAe,EAClB,OAAO;AAAA,EACN,KAAK,EACF,OAAO;AAAA,IACN,UAAU,EAAE,OAAO,EAAE,SAAS,EAAE,QAAQ,IAAI;AAAA,IAC5C,WAAW,EAAE,OAAO,oBAAoB,EAAE,QAAQ,CAAC,CAAC;AAAA,EACtD,CAAC,EACA,QAAQ,CAAC,CAAC;AAAA,EACb,KAAK,EACF,OAAO;AAAA,IACN,UAAU,EAAE,OAAO,EAAE,SAAS,EAAE,QAAQ,IAAI;AAAA,IAC5C,WAAW,EAAE,OAAO,oBAAoB,EAAE,QAAQ,CAAC,CAAC;AAAA,EACtD,CAAC,EACA,QAAQ,CAAC,CAAC;AACf,CAAC,EACA,SAAS,EACT,QAAQ,CAAC,CAAC;AAEN,IAAM,eAAe,EAAE,OAAO;AAAA,EACnC,UAAU,EAAE,OAAO;AAAA,IACjB,OAAO,yBAAyB,SAAS;AAAA,EAC3C,CAAC,EAAE,SAAS,iBAAiB;AAAA,EAC7B,QAAQ,EAAE,OAAO,EAAE,OAAO,GAAG,WAAW,EAAE,SAAS,EAAE,QAAQ,CAAC,CAAC;AAAA,EAC/D,cAAc,EAAE,OAAO;AAAA,EACvB,WAAW,EACR,OAAO;AAAA,IACN,SAAS,EAAE,OAAO,EAAE,QAAQ,qBAAqB;AAAA,EACnD,CAAC,EACA,QAAQ,CAAC,CAAC;AAAA,EACb,UAAU,EACP,OAAO;AAAA,IACN,gBAAgB,EAAE,MAAM,EAAE,OAAO,CAAC,EAAE,QAAQ,CAAC,CAAC;AAAA,IAC9C,uBAAuB,EAAE,OAAO,EAAE,QAAQ,EAAE;AAAA,IAC5C,uBAAuB,EAAE,OAAO,EAAE,QAAQ,EAAE;AAAA,EAC9C,CAAC,EACA,QAAQ,CAAC,CAAC;AAAA,EACb,SAAS;AAAA,EACT,SAAS,EAAE,KAAK,CAAC,cAAc,QAAQ,CAAC,EAAE,QAAQ,YAAY;AAAA,EAC9D,WAAW,EAAE,QAAQ,EAAE,QAAQ,KAAK;AAAA,EACpC,KAAK,EACF,OAAO;AAAA,IACN,MAAM,EAAE,OAAO,EAAE,QAAQ,KAAK;AAAA,IAC9B,MAAM,EAAE,OAAO,EAAE,QAAQ,WAAW;AAAA,EACtC,CAAC,EACA,QAAQ,CAAC,CAAC;AAAA,EACb,cAAc,EACX,OAAO;AAAA,IACN,SAAS,EAAE,OAAO,EAAE,QAAQ,EAAE;AAAA,EAChC,CAAC,EACA,QAAQ,CAAC,CAAC;AAAA,EACb,QAAQ;AAAA,EACR,OAAO;AAAA,EACP,cAAc,EACX;AAAA,IACC,EAAE,OAAO;AAAA,IACT,EAAE,OAAO;AAAA,MACP,WAAW,EAAE,QAAQ;AAAA,MACrB,aAAa,EAAE,OAAO,EAAE,SAAS;AAAA,IACnC,CAAC;AAAA,EACH,EACC,QAAQ,CAAC,CAAC;AAAA,EACb,QAAQ;AACV,CAAC;AAIM,SAAS,WAAW,GAAmB;AAC5C,MAAI,EAAE,WAAW,GAAG,GAAG;AACrB,WAAY,WAAQ,YAAQ,GAAG,EAAE,MAAM,CAAC,CAAC;AAAA,EAC3C;AACA,SAAO;AACT;AAEA,IAAM,iBAAiB;AAAA,EACrB,UAAU;AAAA,IACR,UAAU;AAAA,MACR,SAAS;AAAA,MACT,UAAU;AAAA,MACV,QAAQ;AAAA,MACR,qBAAqB;AAAA,MACrB,kBAAkB;AAAA,IACpB;AAAA,IACA,SAAS;AAAA,MACP,SAAS;AAAA,MACT,UAAU;AAAA,MACV,SAAS;AAAA,MACT,gBAAgB;AAAA,MAChB,uBAAuB;AAAA,MACvB,mBAAmB;AAAA,IACrB;AAAA,EACF;AAAA,EACA,QAAQ;AAAA,IACN,QAAQ,EAAE,SAAS,oBAAoB,MAAM,CAAC,GAAG,KAAK,CAAC,EAAE;AAAA,IACzD,OAAO,EAAE,SAAS,SAAS,MAAM,CAAC,OAAO,GAAG,KAAK,CAAC,EAAE;AAAA,EACtD;AAAA,EACA,cAAc;AAAA,EACd,WAAW,EAAE,SAAS,sBAAsB;AAAA,EAC5C,UAAU;AAAA,IACR,gBAAgB,CAAC;AAAA,IACjB,uBAAuB;AAAA,IACvB,uBAAuB;AAAA,EACzB;AAAA,EACA,cAAc,EAAE,SAAS,GAAG;AAAA,EAC5B,QAAQ;AAAA,IACN,SAAS;AAAA,IACT,MAAM;AAAA,IACN,UAAU;AAAA,IACV,SAAS,CAAC;AAAA,IACV,iBAAiB;AAAA,IACjB,MAAM,EAAE,SAAS,MAAM;AAAA,EACzB;AAAA,EACA,OAAO,CAAC;AACV;AAEO,IAAM,gBAAN,cAA4B,aAAa;AAAA,EACtC;AAAA,EACA;AAAA,EAER,cAAc;AACZ,UAAM;AACN,SAAK,aACH,QAAQ,IAAI,uBAAuB,WAAW,wBAAwB;AAAA,EAC1E;AAAA,EAEA,MAAM,OAAsB;AAE1B,UAAM,MAAW,cAAQ,KAAK,UAAU;AACxC,IAAG,cAAU,KAAK,EAAE,WAAW,KAAK,CAAC;AAGrC,QAAI,CAAI,eAAW,KAAK,UAAU,GAAG;AACnC,MAAG;AAAA,QACD,KAAK;AAAA,QACL,KAAK,UAAU,gBAAgB,MAAM,CAAC;AAAA,MACxC;AACA,MAAAA,KAAI,KAAK,EAAE,YAAY,KAAK,WAAW,GAAG,gBAAgB;AAC1D,MAAAA,KAAI;AAAA,QACF;AAAA,MACF;AACA,cAAQ,KAAK,CAAC;AAAA,IAChB;AAGA,UAAM,MAAM,KAAK,MAAS,iBAAa,KAAK,YAAY,OAAO,CAAC;AAGhE,UAAM,EAAE,SAAS,cAAc,IAAI,gBAAgB,GAAG;AACtD,QAAI,eAAe;AACjB,MAAG,kBAAc,KAAK,YAAY,KAAK,UAAU,KAAK,MAAM,CAAC,CAAC;AAAA,IAChE;AAGA,SAAK,kBAAkB,GAAG;AAG1B,UAAM,SAAS,aAAa,UAAU,GAAG;AACzC,QAAI,CAAC,OAAO,SAAS;AACnB,MAAAA,KAAI,MAAM,0BAA0B;AACpC,iBAAW,SAAS,OAAO,MAAM,QAAQ;AACvC,QAAAA,KAAI;AAAA,UACF,EAAE,MAAM,MAAM,KAAK,KAAK,GAAG,GAAG,SAAS,MAAM,QAAQ;AAAA,UACrD;AAAA,QACF;AAAA,MACF;AACA,cAAQ,KAAK,CAAC;AAAA,IAChB;AACA,SAAK,SAAS,OAAO;AAAA,EACvB;AAAA,EAEA,MAAc;AACZ,WAAO,KAAK;AAAA,EACd;AAAA,EAEA,MAAM,KACJ,SACA,YACe;AACf,UAAM,YAAY,KAAK,SAAS,gBAAgB,KAAK,MAAM,IAAI;AAE/D,UAAM,MAAM,KAAK,MAAS,iBAAa,KAAK,YAAY,OAAO,CAAC;AAChE,SAAK,UAAU,KAAK,OAAO;AAC3B,IAAG,kBAAc,KAAK,YAAY,KAAK,UAAU,KAAK,MAAM,CAAC,CAAC;AAE9D,UAAM,SAAS,aAAa,UAAU,GAAG;AACzC,QAAI,OAAO,SAAS;AAClB,WAAK,SAAS,OAAO;AAAA,IACvB;AAEA,QAAI,YAAY;AACd,YAAM,EAAE,eAAe,IAAI,MAAM,OAAO,+BAAsB;AAC9D,YAAM,QAAQ,eAAe,KAAK,QAAQ,UAAU;AACpD,YAAM,WAAW,YACb,eAAe,WAAW,UAAU,IACpC;AACJ,WAAK,KAAK,kBAAkB,EAAE,MAAM,YAAY,OAAO,SAAS,CAAC;AAAA,IACnE;AAAA,EACF;AAAA,EAEA,iBAAiB,OAAwB;AACvC,QAAI,CAAC,OAAO;AACV,YAAMC,YAAW,WAAW,KAAK,OAAO,UAAU,OAAO;AACzD,MAAG,cAAUA,WAAU,EAAE,WAAW,KAAK,CAAC;AAC1C,aAAOA;AAAA,IACT;AACA,QAAI,MAAM,WAAW,GAAG,KAAK,MAAM,WAAW,GAAG,GAAG;AAClD,YAAMA,YAAW,WAAW,KAAK;AACjC,MAAG,cAAUA,WAAU,EAAE,WAAW,KAAK,CAAC;AAC1C,aAAOA;AAAA,IACT;AAEA,UAAM,OAAO,MAAM,YAAY;AAC/B,UAAM,WAAgB,WAAK,WAAW,KAAK,OAAO,UAAU,OAAO,GAAG,IAAI;AAC1E,IAAG,cAAU,UAAU,EAAE,WAAW,KAAK,CAAC;AAC1C,WAAO;AAAA,EACT;AAAA,EAEA,MAAM,SAA2B;AAC/B,WAAU,eAAW,KAAK,UAAU;AAAA,EACtC;AAAA,EAEA,gBAAwB;AACtB,WAAO,KAAK;AAAA,EACd;AAAA,EAEA,MAAM,SAAS,QAA+B;AAC5C,UAAM,MAAW,cAAQ,KAAK,UAAU;AACxC,IAAG,cAAU,KAAK,EAAE,WAAW,KAAK,CAAC;AACrC,IAAG,kBAAc,KAAK,YAAY,KAAK,UAAU,QAAQ,MAAM,CAAC,CAAC;AAAA,EACnE;AAAA,EAEQ,kBAAkB,KAAoC;AAC5D,UAAM,YAAkC;AAAA,MACtC,CAAC,8BAA8B,CAAC,YAAY,YAAY,UAAU,CAAC;AAAA,MACnE,CAAC,4BAA4B,CAAC,YAAY,YAAY,QAAQ,CAAC;AAAA,MAC/D,CAAC,6BAA6B,CAAC,YAAY,WAAW,UAAU,CAAC;AAAA,MACjE,CAAC,4BAA4B,CAAC,YAAY,WAAW,SAAS,CAAC;AAAA,MAC/D,CAAC,2BAA2B,CAAC,YAAY,SAAS,UAAU,CAAC;AAAA,MAC7D,CAAC,2BAA2B,CAAC,YAAY,SAAS,UAAU,CAAC;AAAA,MAC7D,CAAC,gCAAgC,CAAC,YAAY,SAAS,eAAe,CAAC;AAAA,MACvE,CAAC,yBAAyB,CAAC,cAAc,CAAC;AAAA,MAC1C,CAAC,oBAAoB,CAAC,SAAS,CAAC;AAAA,MAChC,CAAC,oBAAoB,CAAC,OAAO,MAAM,CAAC;AAAA,IACtC;AACA,eAAW,CAAC,QAAQ,UAAU,KAAK,WAAW;AAC5C,YAAM,QAAQ,QAAQ,IAAI,MAAM;AAChC,UAAI,UAAU,QAAW;AACvB,YAAI,SAAkC;AACtC,iBAAS,IAAI,GAAG,IAAI,WAAW,SAAS,GAAG,KAAK;AAC9C,cAAI,CAAC,OAAO,WAAW,CAAC,CAAC,EAAG,QAAO,WAAW,CAAC,CAAC,IAAI,CAAC;AACrD,mBAAS,OAAO,WAAW,CAAC,CAAC;AAAA,QAC/B;AACA,cAAM,MAAM,WAAW,WAAW,SAAS,CAAC;AAE5C,eAAO,GAAG,IACR,QAAQ,YAAY,QAAQ,SAAS,OAAO,KAAK,IAAI;AAAA,MACzD;AAAA,IACF;AAGA,QAAI,QAAQ,IAAI,mBAAmB;AACjC,UAAI,UAAU,IAAI,WAAW,CAAC;AAC9B,MAAC,IAAI,QAAoC,QACvC,QAAQ,IAAI;AAAA,IAChB;AACA,QAAI,QAAQ,IAAI,iBAAiB;AAC/B,UAAI,UAAU,IAAI,WAAW,CAAC;AAC9B,MAAC,IAAI,QAAoC,SACvC,QAAQ,IAAI;AAAA,IAChB;AACA,QAAI,QAAQ,IAAI,iBAAiB,CAAC,QAAQ,IAAI,mBAAmB;AAC/D,UAAI,UAAU,IAAI,WAAW,CAAC;AAC9B,MAAC,IAAI,QAAoC,QAAQ;AAAA,IACnD;AAGA,QAAI,QAAQ,IAAI,wBAAwB;AACtC,UAAI,SAAS,IAAI,UAAU,CAAC;AAC5B,MAAC,IAAI,OAAmC,UACtC,QAAQ,IAAI,2BAA2B;AAAA,IAC3C;AACA,QAAI,QAAQ,IAAI,qBAAqB;AACnC,UAAI,SAAS,IAAI,UAAU,CAAC;AAC5B,MAAC,IAAI,OAAmC,OAAO;AAAA,QAC7C,QAAQ,IAAI;AAAA,MACd;AAAA,IACF;AACA,QAAI,QAAQ,IAAI,yBAAyB;AACvC,UAAI,SAAS,IAAI,UAAU,CAAC;AAC5B,MAAC,IAAI,OAAmC,WACtC,QAAQ,IAAI;AAAA,IAChB;AAGA,QAAI,QAAQ,IAAI,6BAA6B;AAC3C,UAAI,SAAS,IAAI,UAAU,CAAC;AAC5B,YAAM,SAAS,IAAI;AACnB,aAAO,MAAM,OAAO,OAAO,CAAC;AAC5B,MAAC,OAAO,IAAgC,WAAW,QAAQ,IAAI;AAAA,IACjE;AACA,QAAI,QAAQ,IAAI,6BAA6B;AAC3C,UAAI,SAAS,IAAI,UAAU,CAAC;AAC5B,YAAM,SAAS,IAAI;AACnB,aAAO,MAAM,OAAO,OAAO,CAAC;AAC5B,YAAM,MAAM,OAAO;AACnB,UAAI,YAAY,IAAI,aAAa,CAAC;AAClC,YAAM,YAAY,IAAI;AACtB,gBAAU,OAAO,UAAU,QAAQ,CAAC;AACpC,MAAC,UAAU,KAAiC,SAC1C,QAAQ,IAAI;AAAA,IAChB;AAAA,EACF;AAAA,EAEQ,UACN,QACA,QACM;AACN,eAAW,OAAO,OAAO,KAAK,MAAM,GAAG;AACrC,YAAM,MAAM,OAAO,GAAG;AACtB,UACE,OACA,OAAO,QAAQ,YACf,CAAC,MAAM,QAAQ,GAAG,GAClB;AACA,YAAI,CAAC,OAAO,GAAG,EAAG,QAAO,GAAG,IAAI,CAAC;AACjC,aAAK;AAAA,UACH,OAAO,GAAG;AAAA,UACV;AAAA,QACF;AAAA,MACF,OAAO;AACL,eAAO,GAAG,IAAI;AAAA,MAChB;AAAA,IACF;AAAA,EACF;AACF;","names":["fs","path","os","log","resolved"]}
@@ -1 +0,0 @@
1
- {"version":3,"sources":["../../src/adapters/discord/commands/admin.ts"],"sourcesContent":["import {\n ActionRowBuilder,\n ButtonBuilder,\n ButtonStyle,\n} from 'discord.js'\nimport type { ChatInputCommandInteraction, ButtonInteraction } from 'discord.js'\nimport { log } from '../../../core/log.js'\nimport type { DiscordAdapter } from '../adapter.js'\n\nexport async function handleDangerous(\n interaction: ChatInputCommandInteraction,\n adapter: DiscordAdapter,\n): Promise<void> {\n await interaction.deferReply({ ephemeral: true })\n\n const channelId = interaction.channelId\n const session = adapter.core.sessionManager.getSessionByThread('discord', channelId)\n\n if (session) {\n session.dangerousMode = !session.dangerousMode\n adapter.core.sessionManager.patchRecord(session.id, { dangerousMode: session.dangerousMode }).catch(() => {})\n log.info({ sessionId: session.id, dangerousMode: session.dangerousMode }, '[discord-admin] Dangerous mode toggled via command')\n\n const msg = session.dangerousMode\n ? '☠️ **Dangerous mode enabled** — All permission requests will be auto-approved.'\n : '🔐 **Dangerous mode disabled** — Permission requests will be shown normally.'\n await interaction.editReply(msg)\n return\n }\n\n // Session not in memory — update store directly\n const record = adapter.core.sessionManager.getRecordByThread('discord', channelId)\n if (!record || record.status === 'cancelled' || record.status === 'error') {\n await interaction.editReply('⚠️ No active session in this channel.')\n return\n }\n\n const newDangerousMode = !(record.dangerousMode ?? false)\n adapter.core.sessionManager.patchRecord(record.sessionId, { dangerousMode: newDangerousMode }).catch(() => {})\n log.info({ sessionId: record.sessionId, dangerousMode: newDangerousMode }, '[discord-admin] Dangerous mode toggled via command (store-only)')\n\n const msg = newDangerousMode\n ? '☠️ **Dangerous mode enabled** — All permission requests will be auto-approved.'\n : '🔐 **Dangerous mode disabled** — Permission requests will be shown normally.'\n await interaction.editReply(msg)\n}\n\nexport async function handleDangerousButton(\n interaction: ButtonInteraction,\n adapter: DiscordAdapter,\n): Promise<void> {\n const sessionId = interaction.customId.slice(2) // strip 'd:'\n const session = adapter.core.sessionManager.getSession(sessionId)\n\n // Session live in memory — toggle directly\n if (session) {\n session.dangerousMode = !session.dangerousMode\n adapter.core.sessionManager.patchRecord(sessionId, { dangerousMode: session.dangerousMode }).catch(() => {})\n log.info({ sessionId, dangerousMode: session.dangerousMode }, '[discord-admin] Dangerous mode toggled via button')\n\n const toastText = session.dangerousMode\n ? '☠️ Dangerous mode enabled — permissions auto-approved'\n : '🔐 Dangerous mode disabled — permissions shown normally'\n\n try {\n await interaction.update({\n components: [buildSessionControlKeyboard(sessionId, session.dangerousMode, session.voiceMode === 'on')],\n })\n } catch { /* ignore */ }\n\n try { await interaction.followUp({ content: toastText, ephemeral: true }) } catch { /* ignore */ }\n return\n }\n\n // Session not in memory — toggle in store\n const record = adapter.core.sessionManager.getSessionRecord(sessionId)\n if (!record || record.status === 'cancelled' || record.status === 'error') {\n await interaction.reply({ content: '⚠️ Session not found or already ended.', ephemeral: true })\n return\n }\n\n const newDangerousMode = !(record.dangerousMode ?? false)\n adapter.core.sessionManager.patchRecord(sessionId, { dangerousMode: newDangerousMode }).catch(() => {})\n log.info({ sessionId, dangerousMode: newDangerousMode }, '[discord-admin] Dangerous mode toggled via button (store-only)')\n\n const toastText = newDangerousMode\n ? '☠️ Dangerous mode enabled — permissions auto-approved'\n : '🔐 Dangerous mode disabled — permissions shown normally'\n\n try {\n // Store-only path: voiceMode unknown, default to off\n await interaction.update({\n components: [buildSessionControlKeyboard(sessionId, newDangerousMode, false)],\n })\n } catch { /* ignore */ }\n\n try { await interaction.followUp({ content: toastText, ephemeral: true }) } catch { /* ignore */ }\n}\n\n// ─── TTS ──────────────────────────────────────────────────────────────────────\n\nexport function buildSessionControlKeyboard(\n sessionId: string,\n dangerousMode: boolean,\n voiceMode: boolean,\n): ActionRowBuilder<ButtonBuilder> {\n return new ActionRowBuilder<ButtonBuilder>().addComponents(\n new ButtonBuilder()\n .setCustomId(`d:${sessionId}`)\n .setLabel(dangerousMode ? '🔐 Disable Dangerous Mode' : '☠️ Enable Dangerous Mode')\n .setStyle(dangerousMode ? ButtonStyle.Secondary : ButtonStyle.Danger),\n new ButtonBuilder()\n .setCustomId(`v:${sessionId}`)\n .setLabel(voiceMode ? '🔊 Text to Speech' : '🔇 Text to Speech')\n .setStyle(voiceMode ? ButtonStyle.Success : ButtonStyle.Secondary),\n )\n}\n\nexport async function handleTTS(\n interaction: ChatInputCommandInteraction,\n adapter: DiscordAdapter,\n): Promise<void> {\n await interaction.deferReply({ ephemeral: true })\n\n const channelId = interaction.channelId\n const session = adapter.core.sessionManager.getSessionByThread('discord', channelId)\n\n if (!session) {\n await interaction.editReply('⚠️ No active session in this channel.')\n return\n }\n\n const mode = interaction.options.getString('mode')\n\n if (mode === 'on') {\n session.setVoiceMode('on')\n await interaction.editReply('🔊 Text to Speech enabled for this session.')\n } else if (mode === 'off') {\n session.setVoiceMode('off')\n await interaction.editReply('🔇 Text to Speech disabled.')\n } else {\n session.setVoiceMode('next')\n await interaction.editReply('🔊 Text to Speech enabled for the next message.')\n }\n}\n\nexport async function handleTTSButton(\n interaction: ButtonInteraction,\n adapter: DiscordAdapter,\n): Promise<void> {\n const sessionId = interaction.customId.slice(2) // strip 'v:'\n const session = adapter.core.sessionManager.getSession(sessionId)\n\n if (!session) {\n await interaction.reply({ content: '⚠️ Session not found or not active.', ephemeral: true })\n return\n }\n\n const newMode = session.voiceMode === 'on' ? 'off' : 'on'\n session.setVoiceMode(newMode)\n\n const toastText = newMode === 'on'\n ? '🔊 Text to Speech enabled'\n : '🔇 Text to Speech disabled'\n\n try {\n await interaction.update({\n components: [buildSessionControlKeyboard(sessionId, session.dangerousMode, newMode === 'on')],\n })\n } catch { /* ignore */ }\n\n try { await interaction.followUp({ content: toastText, ephemeral: true }) } catch { /* ignore */ }\n}\n\nexport async function handleRestart(\n interaction: ChatInputCommandInteraction,\n adapter: DiscordAdapter,\n): Promise<void> {\n await interaction.deferReply({ ephemeral: true })\n\n if (!adapter.core.requestRestart) {\n await interaction.editReply('⚠️ Restart is not available (no restart handler registered).')\n return\n }\n\n await interaction.editReply('🔄 **Restarting OpenACP...**\\nRebuilding and restarting. Be back shortly.')\n await new Promise((r) => setTimeout(r, 500))\n await adapter.core.requestRestart()\n}\n\nexport async function handleUpdate(\n interaction: ChatInputCommandInteraction,\n adapter: DiscordAdapter,\n): Promise<void> {\n await interaction.deferReply({ ephemeral: true })\n // Stub: not implemented yet\n await interaction.editReply('⚠️ Update via Discord is not implemented yet. Run `npm install -g @openacp/cli@latest` in your terminal, then use `/restart`.')\n}\n"],"mappings":"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","names":["msg","toastText"]}