@openacp/cli 2026.331.1 → 2026.331.2

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 (181) hide show
  1. package/README.md +2 -1
  2. package/dist/cli.js +24932 -270
  3. package/dist/cli.js.map +1 -1
  4. package/dist/data/registry-snapshot.json +1 -1
  5. package/dist/index.js +17626 -409
  6. package/dist/index.js.map +1 -1
  7. package/package.json +2 -2
  8. package/dist/adapter-ELG3VRZ3.js +0 -14
  9. package/dist/adapter-ELG3VRZ3.js.map +0 -1
  10. package/dist/agent-catalog-UYD26QDK.js +0 -10
  11. package/dist/agent-catalog-UYD26QDK.js.map +0 -1
  12. package/dist/agent-dependencies-ED2ZTUHG.js +0 -23
  13. package/dist/agent-dependencies-ED2ZTUHG.js.map +0 -1
  14. package/dist/agent-registry-YOGP656W.js +0 -8
  15. package/dist/agent-registry-YOGP656W.js.map +0 -1
  16. package/dist/agent-store-5UHZH2XI.js +0 -8
  17. package/dist/agent-store-5UHZH2XI.js.map +0 -1
  18. package/dist/api-client-PEMHYL5U.js +0 -13
  19. package/dist/api-client-PEMHYL5U.js.map +0 -1
  20. package/dist/api-server-DATG2KBR.js +0 -10
  21. package/dist/api-server-DATG2KBR.js.map +0 -1
  22. package/dist/api-server-L5Z7XACW.js +0 -7
  23. package/dist/api-server-L5Z7XACW.js.map +0 -1
  24. package/dist/autostart-CUPZMKKC.js +0 -22
  25. package/dist/autostart-CUPZMKKC.js.map +0 -1
  26. package/dist/chunk-23SRIVG4.js +0 -50
  27. package/dist/chunk-23SRIVG4.js.map +0 -1
  28. package/dist/chunk-2KT6TROD.js +0 -129
  29. package/dist/chunk-2KT6TROD.js.map +0 -1
  30. package/dist/chunk-2R5XM3ES.js +0 -154
  31. package/dist/chunk-2R5XM3ES.js.map +0 -1
  32. package/dist/chunk-3EWTPOF7.js +0 -51
  33. package/dist/chunk-3EWTPOF7.js.map +0 -1
  34. package/dist/chunk-566W6INH.js +0 -83
  35. package/dist/chunk-566W6INH.js.map +0 -1
  36. package/dist/chunk-5WGVYX3C.js +0 -55
  37. package/dist/chunk-5WGVYX3C.js.map +0 -1
  38. package/dist/chunk-7GXEMMEV.js +0 -44
  39. package/dist/chunk-7GXEMMEV.js.map +0 -1
  40. package/dist/chunk-7U6IZIJP.js +0 -186
  41. package/dist/chunk-7U6IZIJP.js.map +0 -1
  42. package/dist/chunk-7YIKTRSM.js +0 -105
  43. package/dist/chunk-7YIKTRSM.js.map +0 -1
  44. package/dist/chunk-7ZCQF6QM.js +0 -27
  45. package/dist/chunk-7ZCQF6QM.js.map +0 -1
  46. package/dist/chunk-AFKX424Q.js +0 -92
  47. package/dist/chunk-AFKX424Q.js.map +0 -1
  48. package/dist/chunk-BYCJQPMN.js +0 -543
  49. package/dist/chunk-BYCJQPMN.js.map +0 -1
  50. package/dist/chunk-CDAUYTVP.js +0 -41
  51. package/dist/chunk-CDAUYTVP.js.map +0 -1
  52. package/dist/chunk-EWVXSTQK.js +0 -6544
  53. package/dist/chunk-EWVXSTQK.js.map +0 -1
  54. package/dist/chunk-FNRSWA2K.js +0 -1
  55. package/dist/chunk-FNRSWA2K.js.map +0 -1
  56. package/dist/chunk-FPKQYCQS.js +0 -776
  57. package/dist/chunk-FPKQYCQS.js.map +0 -1
  58. package/dist/chunk-IZ5UEZF7.js +0 -138
  59. package/dist/chunk-IZ5UEZF7.js.map +0 -1
  60. package/dist/chunk-K6UY5M75.js +0 -653
  61. package/dist/chunk-K6UY5M75.js.map +0 -1
  62. package/dist/chunk-KGAQW6F4.js +0 -106
  63. package/dist/chunk-KGAQW6F4.js.map +0 -1
  64. package/dist/chunk-LGFWH3AE.js +0 -26
  65. package/dist/chunk-LGFWH3AE.js.map +0 -1
  66. package/dist/chunk-LRV56K2M.js +0 -4106
  67. package/dist/chunk-LRV56K2M.js.map +0 -1
  68. package/dist/chunk-MDJHCCFS.js +0 -485
  69. package/dist/chunk-MDJHCCFS.js.map +0 -1
  70. package/dist/chunk-MLF4W5R6.js +0 -101
  71. package/dist/chunk-MLF4W5R6.js.map +0 -1
  72. package/dist/chunk-NHD5XDD2.js +0 -686
  73. package/dist/chunk-NHD5XDD2.js.map +0 -1
  74. package/dist/chunk-NJX75BLK.js +0 -259
  75. package/dist/chunk-NJX75BLK.js.map +0 -1
  76. package/dist/chunk-NOEAJNTK.js +0 -156
  77. package/dist/chunk-NOEAJNTK.js.map +0 -1
  78. package/dist/chunk-ON7HB5O7.js +0 -58
  79. package/dist/chunk-ON7HB5O7.js.map +0 -1
  80. package/dist/chunk-OSBZXY2W.js +0 -126
  81. package/dist/chunk-OSBZXY2W.js.map +0 -1
  82. package/dist/chunk-OYSAN7UX.js +0 -15
  83. package/dist/chunk-OYSAN7UX.js.map +0 -1
  84. package/dist/chunk-P3HHJANC.js +0 -209
  85. package/dist/chunk-P3HHJANC.js.map +0 -1
  86. package/dist/chunk-R2YLDQLI.js +0 -1115
  87. package/dist/chunk-R2YLDQLI.js.map +0 -1
  88. package/dist/chunk-R6KZYF7D.js +0 -231
  89. package/dist/chunk-R6KZYF7D.js.map +0 -1
  90. package/dist/chunk-S64CB6J3.js +0 -98
  91. package/dist/chunk-S64CB6J3.js.map +0 -1
  92. package/dist/chunk-SSLVNCEA.js +0 -236
  93. package/dist/chunk-SSLVNCEA.js.map +0 -1
  94. package/dist/chunk-TGP34LQN.js +0 -681
  95. package/dist/chunk-TGP34LQN.js.map +0 -1
  96. package/dist/chunk-VUSCVRJL.js +0 -229
  97. package/dist/chunk-VUSCVRJL.js.map +0 -1
  98. package/dist/chunk-W26AUH5B.js +0 -61
  99. package/dist/chunk-W26AUH5B.js.map +0 -1
  100. package/dist/chunk-WQCJTU2C.js +0 -84
  101. package/dist/chunk-WQCJTU2C.js.map +0 -1
  102. package/dist/chunk-XRJUS6FE.js +0 -53
  103. package/dist/chunk-XRJUS6FE.js.map +0 -1
  104. package/dist/chunk-YZCKSNRN.js +0 -453
  105. package/dist/chunk-YZCKSNRN.js.map +0 -1
  106. package/dist/chunk-ZIRH6QWW.js +0 -69
  107. package/dist/chunk-ZIRH6QWW.js.map +0 -1
  108. package/dist/chunk-ZSLHHQPQ.js +0 -282
  109. package/dist/chunk-ZSLHHQPQ.js.map +0 -1
  110. package/dist/config-X4UP7H6R.js +0 -13
  111. package/dist/config-X4UP7H6R.js.map +0 -1
  112. package/dist/config-editor-7BENRVG5.js +0 -11
  113. package/dist/config-editor-7BENRVG5.js.map +0 -1
  114. package/dist/config-registry-M3FFWEVM.js +0 -18
  115. package/dist/config-registry-M3FFWEVM.js.map +0 -1
  116. package/dist/context-FVGCU5TI.js +0 -9
  117. package/dist/context-FVGCU5TI.js.map +0 -1
  118. package/dist/core-plugins-JSY2I44L.js +0 -25
  119. package/dist/core-plugins-JSY2I44L.js.map +0 -1
  120. package/dist/daemon-UOSRDEXW.js +0 -34
  121. package/dist/daemon-UOSRDEXW.js.map +0 -1
  122. package/dist/dev-loader-7P3HZCIA.js +0 -37
  123. package/dist/dev-loader-7P3HZCIA.js.map +0 -1
  124. package/dist/doctor-6DLACBR4.js +0 -10
  125. package/dist/doctor-6DLACBR4.js.map +0 -1
  126. package/dist/file-service-FQQYME7M.js +0 -8
  127. package/dist/file-service-FQQYME7M.js.map +0 -1
  128. package/dist/install-cloudflared-LNS5L5FR.js +0 -33
  129. package/dist/install-cloudflared-LNS5L5FR.js.map +0 -1
  130. package/dist/install-context-KZO5FR4D.js +0 -78
  131. package/dist/install-context-KZO5FR4D.js.map +0 -1
  132. package/dist/install-jq-SN4IA5K4.js +0 -31
  133. package/dist/install-jq-SN4IA5K4.js.map +0 -1
  134. package/dist/instance-context-FLCE7VZ4.js +0 -13
  135. package/dist/instance-context-FLCE7VZ4.js.map +0 -1
  136. package/dist/instance-registry-SW5FWKHO.js +0 -7
  137. package/dist/instance-registry-SW5FWKHO.js.map +0 -1
  138. package/dist/integrate-JIEZYDOR.js +0 -371
  139. package/dist/integrate-JIEZYDOR.js.map +0 -1
  140. package/dist/log-YZ243M5G.js +0 -25
  141. package/dist/log-YZ243M5G.js.map +0 -1
  142. package/dist/main-D7M2AKRM.js +0 -697
  143. package/dist/main-D7M2AKRM.js.map +0 -1
  144. package/dist/menu-ALFN37IR.js +0 -15
  145. package/dist/menu-ALFN37IR.js.map +0 -1
  146. package/dist/notifications-MO23S7S3.js +0 -8
  147. package/dist/notifications-MO23S7S3.js.map +0 -1
  148. package/dist/plugin-create-HFKS23JY.js +0 -968
  149. package/dist/plugin-create-HFKS23JY.js.map +0 -1
  150. package/dist/plugin-installer-VSTYZSXC.js +0 -9
  151. package/dist/plugin-installer-VSTYZSXC.js.map +0 -1
  152. package/dist/plugin-registry-6J3YSFHF.js +0 -7
  153. package/dist/plugin-registry-6J3YSFHF.js.map +0 -1
  154. package/dist/plugin-search-MGKAL5JM.js +0 -39
  155. package/dist/plugin-search-MGKAL5JM.js.map +0 -1
  156. package/dist/post-upgrade-F4YPMTUT.js +0 -79
  157. package/dist/post-upgrade-F4YPMTUT.js.map +0 -1
  158. package/dist/read-text-file-DJBTITIB.js +0 -7
  159. package/dist/read-text-file-DJBTITIB.js.map +0 -1
  160. package/dist/registry-client-GTBWLXYU.js +0 -7
  161. package/dist/registry-client-GTBWLXYU.js.map +0 -1
  162. package/dist/security-O4XGN2CM.js +0 -8
  163. package/dist/security-O4XGN2CM.js.map +0 -1
  164. package/dist/settings-manager-B4UN2LAC.js +0 -7
  165. package/dist/settings-manager-B4UN2LAC.js.map +0 -1
  166. package/dist/setup-44WLBIOT.js +0 -989
  167. package/dist/setup-44WLBIOT.js.map +0 -1
  168. package/dist/speech-GHTSWDAN.js +0 -9
  169. package/dist/speech-GHTSWDAN.js.map +0 -1
  170. package/dist/suggest-RST5VOHB.js +0 -36
  171. package/dist/suggest-RST5VOHB.js.map +0 -1
  172. package/dist/telegram-D7ASLVEB.js +0 -7
  173. package/dist/telegram-D7ASLVEB.js.map +0 -1
  174. package/dist/tunnel-ALJDPFDQ.js +0 -10
  175. package/dist/tunnel-ALJDPFDQ.js.map +0 -1
  176. package/dist/tunnel-service-TBAHDXMF.js +0 -755
  177. package/dist/tunnel-service-TBAHDXMF.js.map +0 -1
  178. package/dist/validators-GITLOFXC.js +0 -11
  179. package/dist/validators-GITLOFXC.js.map +0 -1
  180. package/dist/version-AXXV6IV2.js +0 -15
  181. package/dist/version-AXXV6IV2.js.map +0 -1
@@ -1 +0,0 @@
1
- {"version":3,"sources":["../../src/core/config/config-editor.ts"],"sourcesContent":["import * as path from 'node:path'\nimport * as clack from '@clack/prompts'\nimport type { Config, ConfigManager } from './config.js'\n\n// Compatibility wrappers — convert @inquirer/prompts API to @clack/prompts\nasync function select<T extends string>(opts: { message: string; choices: Array<{ name: string; value: T; description?: string }>; default?: T }): Promise<T> {\n const result = await clack.select({\n message: opts.message,\n options: opts.choices.map(ch => ({ label: ch.name, value: ch.value, hint: ch.description })) as any,\n initialValue: opts.default,\n })\n if (clack.isCancel(result)) { clack.cancel('Cancelled.'); process.exit(0) }\n return result as T\n}\n\nasync function input(opts: { message: string; default?: string; validate?: (val: string) => string | boolean }): Promise<string> {\n const result = await clack.text({\n message: opts.message,\n initialValue: opts.default,\n validate: opts.validate ? (val) => {\n const r = opts.validate!((val ?? \"\") as string)\n if (r === true || r === undefined) return undefined\n if (typeof r === 'string') return r\n return undefined\n } : undefined,\n })\n if (clack.isCancel(result)) { clack.cancel('Cancelled.'); process.exit(0) }\n return result as string\n}\nimport { installAutoStart, uninstallAutoStart, isAutoStartInstalled, isAutoStartSupported } from '../../cli/autostart.js'\nimport { expandHome } from './config.js'\n\n// ANSI color helpers\nconst c = {\n reset: '\\x1b[0m',\n bold: '\\x1b[1m',\n dim: '\\x1b[2m',\n green: '\\x1b[32m',\n yellow: '\\x1b[33m',\n cyan: '\\x1b[36m',\n}\n\nconst ok = (msg: string) => `${c.green}${c.bold}✓${c.reset} ${c.green}${msg}${c.reset}`\nconst warn = (msg: string) => `${c.yellow}⚠ ${msg}${c.reset}`\nconst dim = (msg: string) => `${c.dim}${msg}${c.reset}`\nconst header = (title: string) => `\\n${c.cyan}${c.bold}[${title}]${c.reset}\\n`\n\ntype ConfigUpdates = Record<string, unknown>\n\n// --- Edit: Telegram ---\n\nasync function editTelegram(config: Config, updates: ConfigUpdates): Promise<void> {\n const tg = (config.channels?.telegram ?? {}) as Record<string, unknown>\n const currentToken = (tg.botToken as string) ?? ''\n const currentChatId = (tg.chatId as number) ?? 0\n const currentEnabled = (tg.enabled as boolean) ?? false\n\n console.log(header('Telegram'))\n console.log(` Enabled : ${currentEnabled ? ok('yes') : dim('no')}`)\n const tokenDisplay = currentToken.length > 12\n ? currentToken.slice(0, 6) + '...' + currentToken.slice(-6)\n : currentToken || dim('(not set)')\n console.log(` Bot Token : ${tokenDisplay}`)\n console.log(` Chat ID : ${currentChatId || dim('(not set)')}`)\n console.log('')\n\n const ensureTelegramUpdates = () => {\n if (!updates.channels) updates.channels = {}\n if (!(updates.channels as Record<string, unknown>).telegram) {\n (updates.channels as Record<string, unknown>).telegram = {}\n }\n return (updates.channels as Record<string, unknown>).telegram as Record<string, unknown>\n }\n\n while (true) {\n const isEnabled = (() => {\n const ch = updates.channels as Record<string, unknown> | undefined\n const tgUp = ch?.telegram as Record<string, unknown> | undefined\n if (tgUp && 'enabled' in tgUp) return tgUp.enabled as boolean\n return currentEnabled\n })()\n\n const choice = await select({\n message: 'Telegram settings:',\n choices: [\n { name: isEnabled ? 'Disable Telegram' : 'Enable Telegram', value: 'toggle' },\n { name: 'Change Bot Token', value: 'token' },\n { name: 'Change Chat ID', value: 'chatid' },\n { name: 'Back', value: 'back' },\n ],\n })\n\n if (choice === 'back') break\n\n if (choice === 'toggle') {\n const tgUp = ensureTelegramUpdates()\n tgUp.enabled = !isEnabled\n console.log(!isEnabled ? ok('Telegram enabled') : ok('Telegram disabled'))\n }\n\n if (choice === 'token') {\n const token = await input({\n message: 'New bot token:',\n default: currentToken,\n validate: (val) => val.trim().length > 0 || 'Token cannot be empty',\n })\n\n try {\n const { validateBotToken } = await import('../../plugins/telegram/validators.js')\n const result = await validateBotToken(token.trim())\n if (result.ok) {\n console.log(ok(`Connected to @${result.botUsername}`))\n } else {\n console.log(warn(`Validation failed: ${result.error} — saving anyway`))\n }\n } catch {\n console.log(warn('Telegram validator not available — skipping validation'))\n }\n\n const tgUp = ensureTelegramUpdates()\n tgUp.botToken = token.trim()\n tgUp.enabled = true\n }\n\n if (choice === 'chatid') {\n const chatIdStr = await input({\n message: 'New chat ID (e.g. -1001234567890):',\n default: String(currentChatId),\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 })\n\n const chatId = Number(chatIdStr.trim())\n\n // Use the current (or already-updated) token for validation\n const tokenForValidation = (() => {\n const ch = updates.channels as Record<string, unknown> | undefined\n const tgUp = ch?.telegram as Record<string, unknown> | undefined\n if (typeof tgUp?.botToken === 'string') return tgUp.botToken\n return currentToken\n })()\n\n try {\n const { validateChatId } = await import('../../plugins/telegram/validators.js')\n const result = await validateChatId(tokenForValidation, chatId)\n if (result.ok) {\n console.log(ok(`Group: ${result.title}${result.isForum ? '' : warn(' (topics not enabled)')}`))\n } else {\n console.log(warn(`Validation failed: ${result.error} — saving anyway`))\n }\n } catch {\n console.log(warn('Telegram validator not available — skipping validation'))\n }\n\n const tgUp = ensureTelegramUpdates()\n tgUp.chatId = chatId\n }\n }\n}\n\n// --- Edit: Discord (delegates to plugin's configure()) ---\n\nconst DISCORD_PACKAGE = '@openacp/adapter-discord'\n\nasync function ensureDiscordPlugin(): Promise<any | null> {\n try {\n return await import(DISCORD_PACKAGE)\n } catch {\n const shouldInstall = await select({\n message: `${DISCORD_PACKAGE} is not installed. Install it now?`,\n choices: [\n { name: 'Yes, install now', value: 'yes' },\n { name: 'No, skip', value: 'no' },\n ],\n })\n if (shouldInstall === 'no') {\n console.log(warn(`Install later with: openacp plugin add ${DISCORD_PACKAGE}`))\n return null\n }\n try {\n console.log(dim(`Installing ${DISCORD_PACKAGE}...`))\n const { installNpmPlugin } = await import('../plugin/plugin-installer.js')\n const mod = await installNpmPlugin(DISCORD_PACKAGE)\n console.log(ok(`${DISCORD_PACKAGE} installed`))\n return mod\n } catch (err) {\n console.log(warn(`Failed to install: ${(err as Error).message}`))\n return null\n }\n }\n}\n\nasync function editDiscord(_config: Config, _updates: ConfigUpdates): Promise<void> {\n const pluginModule = await ensureDiscordPlugin()\n if (!pluginModule) return\n\n const plugin = pluginModule.default\n if (plugin?.configure) {\n const { SettingsManager } = await import('../plugin/settings-manager.js')\n const { createInstallContext } = await import('../plugin/install-context.js')\n const { getGlobalRoot } = await import('../instance-context.js')\n const root = getGlobalRoot()\n const basePath = path.join(root, 'plugins')\n const settingsManager = new SettingsManager(basePath)\n const ctx = createInstallContext({\n pluginName: plugin.name,\n settingsManager,\n basePath,\n instanceRoot: root,\n })\n await plugin.configure(ctx)\n } else {\n console.log(warn('This plugin does not have a configure() method yet.'))\n }\n}\n\n// --- Edit: Channels (parent menu) ---\n\nasync function editChannels(config: Config, updates: ConfigUpdates): Promise<void> {\n const tgEnabled = (config.channels?.telegram as Record<string, unknown>)?.enabled !== false && config.channels?.telegram\n const dcEnabled = (config.channels?.discord as Record<string, unknown>)?.enabled !== false && config.channels?.discord\n\n console.log(header('Channels'))\n console.log(` Telegram : ${tgEnabled ? ok('configured') : dim('not configured')}`)\n console.log(` Discord : ${dcEnabled ? ok('configured') : dim('not configured')}`)\n console.log('')\n\n while (true) {\n const choice = await select({\n message: 'Channel settings:',\n choices: [\n { name: 'Telegram', value: 'telegram' },\n { name: 'Discord', value: 'discord' },\n { name: 'Back', value: 'back' },\n ],\n })\n\n if (choice === 'back') break\n\n if (choice === 'telegram') await editTelegram(config, updates)\n if (choice === 'discord') await editDiscord(config, updates)\n }\n}\n\n// --- Edit: Agent ---\n\nasync function editAgent(config: Config, updates: ConfigUpdates): Promise<void> {\n const agentNames = Object.keys(config.agents ?? {})\n const currentDefault = config.defaultAgent\n\n console.log(header('Agent'))\n console.log(` Default agent : ${c.bold}${currentDefault}${c.reset}`)\n console.log(` Available : ${agentNames.join(', ') || dim('(none)')}`)\n console.log('')\n\n while (true) {\n const choice = await select({\n message: 'Agent settings:',\n choices: [\n { name: 'Change default agent', value: 'default' },\n { name: 'Back', value: 'back' },\n ],\n })\n\n if (choice === 'back') break\n\n if (choice === 'default') {\n if (agentNames.length === 0) {\n console.log(warn('No agents configured.'))\n continue\n }\n\n const chosen = await select({\n message: 'Select default agent:',\n choices: agentNames.map((name) => ({ name, value: name })),\n })\n\n updates.defaultAgent = chosen\n console.log(ok(`Default agent set to ${chosen}`))\n }\n }\n}\n\n// --- Edit: Workspace ---\n\nasync function editWorkspace(config: Config, updates: ConfigUpdates): Promise<void> {\n const currentDir = config.workspace?.baseDir ?? '~/openacp-workspace'\n\n console.log(header('Workspace'))\n console.log(` Base directory : ${currentDir}`)\n console.log('')\n\n const newDir = await input({\n message: 'Workspace base directory:',\n default: currentDir,\n validate: (val) => val.trim().length > 0 || 'Path cannot be empty',\n })\n\n updates.workspace = { baseDir: newDir.trim() }\n console.log(ok(`Workspace set to ${newDir.trim()}`))\n}\n\n// --- Edit: Security ---\n\nasync function editSecurity(config: Config, updates: ConfigUpdates): Promise<void> {\n const sec = config.security ?? { allowedUserIds: [], maxConcurrentSessions: 20, sessionTimeoutMinutes: 60 }\n\n console.log(header('Security'))\n console.log(` Allowed user IDs : ${sec.allowedUserIds?.length ? sec.allowedUserIds.join(', ') : dim('(all users allowed)')}`)\n console.log(` Max concurrent sessions : ${sec.maxConcurrentSessions}`)\n console.log(` Session timeout (min) : ${sec.sessionTimeoutMinutes}`)\n console.log('')\n\n while (true) {\n const choice = await select({\n message: 'Security settings:',\n choices: [\n { name: 'Max concurrent sessions', value: 'maxSessions' },\n { name: 'Session timeout (minutes)', value: 'timeout' },\n { name: 'Back', value: 'back' },\n ],\n })\n\n if (choice === 'back') break\n\n if (choice === 'maxSessions') {\n const val = await input({\n message: 'Max concurrent sessions:',\n default: String(sec.maxConcurrentSessions),\n validate: (v) => {\n const n = Number(v.trim())\n if (!Number.isInteger(n) || n < 1) return 'Must be a positive integer'\n return true\n },\n })\n\n if (!updates.security) updates.security = {}\n ;(updates.security as Record<string, unknown>).maxConcurrentSessions = Number(val.trim())\n console.log(ok(`Max concurrent sessions set to ${val.trim()}`))\n }\n\n if (choice === 'timeout') {\n const val = await input({\n message: 'Session timeout in minutes:',\n default: String(sec.sessionTimeoutMinutes),\n validate: (v) => {\n const n = Number(v.trim())\n if (!Number.isInteger(n) || n < 1) return 'Must be a positive integer'\n return true\n },\n })\n\n if (!updates.security) updates.security = {}\n ;(updates.security as Record<string, unknown>).sessionTimeoutMinutes = Number(val.trim())\n console.log(ok(`Session timeout set to ${val.trim()} minutes`))\n }\n }\n}\n\n// --- Edit: Logging ---\n\nasync function editLogging(config: Config, updates: ConfigUpdates): Promise<void> {\n const logging = config.logging ?? { level: 'info', logDir: '~/.openacp/logs', maxFileSize: '10m', maxFiles: 7, sessionLogRetentionDays: 30 }\n\n console.log(header('Logging'))\n console.log(` Log level : ${logging.level}`)\n console.log(` Log dir : ${logging.logDir}`)\n console.log('')\n\n while (true) {\n const choice = await select({\n message: 'Logging settings:',\n choices: [\n { name: 'Log level', value: 'level' },\n { name: 'Log directory', value: 'logDir' },\n { name: 'Back', value: 'back' },\n ],\n })\n\n if (choice === 'back') break\n\n if (choice === 'level') {\n const level = await select({\n message: 'Select log level:',\n choices: [\n { name: 'silent', value: 'silent' },\n { name: 'debug', value: 'debug' },\n { name: 'info', value: 'info' },\n { name: 'warn', value: 'warn' },\n { name: 'error', value: 'error' },\n { name: 'fatal', value: 'fatal' },\n ],\n })\n\n if (!updates.logging) updates.logging = {}\n ;(updates.logging as Record<string, unknown>).level = level\n console.log(ok(`Log level set to ${level}`))\n }\n\n if (choice === 'logDir') {\n const dir = await input({\n message: 'Log directory:',\n default: logging.logDir,\n validate: (val) => val.trim().length > 0 || 'Path cannot be empty',\n })\n\n if (!updates.logging) updates.logging = {}\n ;(updates.logging as Record<string, unknown>).logDir = dir.trim()\n console.log(ok(`Log directory set to ${dir.trim()}`))\n }\n }\n}\n\n// --- Edit: Run Mode ---\n\nasync function editRunMode(config: Config, updates: ConfigUpdates): Promise<void> {\n const currentMode = config.runMode ?? 'foreground'\n const currentAutoStart = config.autoStart ?? false\n const autoStartInstalled = isAutoStartInstalled()\n const autoStartSupported = isAutoStartSupported()\n\n console.log(header('Run Mode'))\n console.log(` Current mode : ${c.bold}${currentMode}${c.reset}`)\n console.log(` Auto-start : ${currentAutoStart ? ok('enabled') : dim('disabled')}${autoStartInstalled ? ` ${dim('(installed)')}` : ''}`)\n console.log('')\n\n while (true) {\n const isDaemon = (() => {\n if ('runMode' in updates) return updates.runMode === 'daemon'\n return currentMode === 'daemon'\n })()\n\n const choices = [\n isDaemon\n ? { name: 'Switch to foreground mode', value: 'foreground' }\n : { name: 'Switch to daemon mode', value: 'daemon' },\n ]\n\n if (autoStartSupported) {\n const autoStartCurrent = (() => {\n if ('autoStart' in updates) return updates.autoStart as boolean\n return currentAutoStart\n })()\n choices.push({\n name: autoStartCurrent ? 'Disable auto-start' : 'Enable auto-start',\n value: 'toggleAutoStart',\n })\n }\n\n choices.push({ name: 'Back', value: 'back' })\n\n const choice = await select({\n message: 'Run mode settings:',\n choices,\n })\n\n if (choice === 'back') break\n\n if (choice === 'daemon') {\n updates.runMode = 'daemon'\n const logDir = (config.logging?.logDir) ?? '~/.openacp/logs'\n const result = installAutoStart(expandHome(logDir))\n if (result.success) {\n updates.autoStart = true\n console.log(ok('Switched to daemon mode with auto-start'))\n } else {\n console.log(warn(`Switched to daemon mode (auto-start failed: ${result.error})`))\n }\n }\n\n if (choice === 'foreground') {\n updates.runMode = 'foreground'\n updates.autoStart = false\n uninstallAutoStart()\n console.log(ok('Switched to foreground mode'))\n }\n\n if (choice === 'toggleAutoStart') {\n const autoStartCurrent = (() => {\n if ('autoStart' in updates) return updates.autoStart as boolean\n return currentAutoStart\n })()\n\n if (autoStartCurrent) {\n const result = uninstallAutoStart()\n updates.autoStart = false\n if (result.success) {\n console.log(ok('Auto-start disabled'))\n } else {\n console.log(warn(`Auto-start uninstall failed: ${result.error}`))\n }\n } else {\n const logDir = (config.logging?.logDir) ?? '~/.openacp/logs'\n const result = installAutoStart(expandHome(logDir))\n updates.autoStart = result.success\n if (result.success) {\n console.log(ok('Auto-start enabled'))\n } else {\n console.log(warn(`Auto-start install failed: ${result.error}`))\n }\n }\n }\n }\n}\n\n// --- Edit: API ---\n\nasync function editApi(config: Config, updates: ConfigUpdates): Promise<void> {\n const api = config.api ?? { port: 21420, host: '127.0.0.1' }\n\n console.log(header('API'))\n console.log(` Port : ${api.port}`)\n console.log(` Host : ${api.host} ${dim('(localhost only)')}`)\n console.log('')\n\n const newPort = await input({\n message: 'API port:',\n default: String(api.port),\n validate: (v) => {\n const n = Number(v.trim())\n if (!Number.isInteger(n) || n < 1 || n > 65535) return 'Must be a valid port (1-65535)'\n return true\n },\n })\n\n updates.api = { port: Number(newPort.trim()) }\n console.log(ok(`API port set to ${newPort.trim()}`))\n}\n\n// --- Edit: Tunnel ---\n\nasync function editTunnel(config: Config, updates: ConfigUpdates): Promise<void> {\n const tunnel = config.tunnel ?? { enabled: false, port: 3100, provider: 'cloudflare', options: {}, storeTtlMinutes: 60, auth: { enabled: false } }\n const currentUpdates = (updates.tunnel ?? {}) as Record<string, unknown>\n\n const getVal = <T>(key: string, fallback: T): T =>\n (key in currentUpdates ? currentUpdates[key] : (tunnel as Record<string, unknown>)[key] ?? fallback) as T\n\n console.log(header('Tunnel'))\n console.log(` Enabled : ${getVal('enabled', false) ? ok('yes') : dim('no')}`)\n console.log(` Provider : ${c.bold}${getVal('provider', 'cloudflare')}${c.reset}`)\n console.log(` Port : ${getVal('port', 3100)}`)\n const authEnabled = (getVal('auth', { enabled: false }) as { enabled: boolean }).enabled\n console.log(` Auth : ${authEnabled ? ok('enabled') : dim('disabled')}`)\n console.log('')\n\n while (true) {\n const choice = await select({\n message: 'Tunnel settings:',\n choices: [\n { name: getVal('enabled', false) ? 'Disable tunnel' : 'Enable tunnel', value: 'toggle' },\n { name: 'Change provider', value: 'provider' },\n { name: 'Change port', value: 'port' },\n { name: 'Provider options', value: 'options' },\n { name: authEnabled ? 'Disable auth' : 'Enable auth', value: 'auth' },\n { name: 'Back', value: 'back' },\n ],\n })\n\n if (choice === 'back') break\n\n if (!updates.tunnel) updates.tunnel = { ...tunnel }\n const tun = updates.tunnel as Record<string, unknown>\n\n if (choice === 'toggle') {\n const current = getVal('enabled', false)\n tun.enabled = !current\n console.log(!current ? ok('Tunnel enabled') : ok('Tunnel disabled'))\n }\n\n if (choice === 'provider') {\n const provider = await select({\n message: 'Select tunnel provider:',\n choices: [\n { name: 'Cloudflare (default)', value: 'cloudflare' },\n { name: 'ngrok', value: 'ngrok' },\n { name: 'bore', value: 'bore' },\n { name: 'Tailscale Funnel', value: 'tailscale' },\n ],\n })\n tun.provider = provider\n tun.options = {} // reset options when switching provider\n console.log(ok(`Provider set to ${provider}`))\n }\n\n if (choice === 'port') {\n const val = await input({\n message: 'Tunnel port:',\n default: String(getVal('port', 3100)),\n validate: (v) => {\n const n = Number(v.trim())\n if (!Number.isInteger(n) || n < 1 || n > 65535) return 'Must be a valid port (1-65535)'\n return true\n },\n })\n tun.port = Number(val.trim())\n console.log(ok(`Tunnel port set to ${val.trim()}`))\n }\n\n if (choice === 'options') {\n const provider = getVal('provider', 'cloudflare')\n const currentOptions = getVal('options', {}) as Record<string, unknown>\n await editProviderOptions(provider, currentOptions, tun)\n }\n\n if (choice === 'auth') {\n const currentAuth = getVal('auth', { enabled: false }) as { enabled: boolean; token?: string }\n if (currentAuth.enabled) {\n tun.auth = { enabled: false }\n console.log(ok('Tunnel auth disabled'))\n } else {\n const token = await input({\n message: 'Auth token (leave empty to auto-generate):',\n default: '',\n })\n tun.auth = token.trim()\n ? { enabled: true, token: token.trim() }\n : { enabled: true }\n console.log(ok('Tunnel auth enabled'))\n }\n }\n }\n}\n\nasync function editProviderOptions(\n provider: string,\n currentOptions: Record<string, unknown>,\n tun: Record<string, unknown>,\n): Promise<void> {\n if (provider === 'cloudflare') {\n const domain = await input({\n message: 'Custom domain (leave empty for random):',\n default: (currentOptions.domain as string) ?? '',\n })\n tun.options = domain.trim() ? { domain: domain.trim() } : {}\n if (domain.trim()) console.log(ok(`Domain set to ${domain.trim()}`))\n else console.log(dim('Using random cloudflare domain'))\n } else if (provider === 'ngrok') {\n const authtoken = await input({\n message: 'ngrok authtoken (leave empty to skip):',\n default: (currentOptions.authtoken as string) ?? '',\n })\n const domain = await input({\n message: 'ngrok domain (leave empty for random):',\n default: (currentOptions.domain as string) ?? '',\n })\n const region = await input({\n message: 'ngrok region (us, eu, ap — leave empty for default):',\n default: (currentOptions.region as string) ?? '',\n })\n const opts: Record<string, string> = {}\n if (authtoken.trim()) opts.authtoken = authtoken.trim()\n if (domain.trim()) opts.domain = domain.trim()\n if (region.trim()) opts.region = region.trim()\n tun.options = opts\n console.log(ok('ngrok options saved'))\n } else if (provider === 'bore') {\n const server = await input({\n message: 'bore server:',\n default: (currentOptions.server as string) ?? 'bore.pub',\n })\n const port = await input({\n message: 'bore port (leave empty for auto):',\n default: currentOptions.port ? String(currentOptions.port) : '',\n })\n const secret = await input({\n message: 'bore secret (leave empty to skip):',\n default: (currentOptions.secret as string) ?? '',\n })\n const opts: Record<string, unknown> = { server: server.trim() }\n if (port.trim()) opts.port = Number(port.trim())\n if (secret.trim()) opts.secret = secret.trim()\n tun.options = opts\n console.log(ok('bore options saved'))\n } else if (provider === 'tailscale') {\n const bg = await select({\n message: 'Run Tailscale Funnel in background?',\n choices: [\n { name: 'No', value: 'no' },\n { name: 'Yes', value: 'yes' },\n ],\n })\n tun.options = bg === 'yes' ? { bg: true } : {}\n console.log(ok('Tailscale options saved'))\n } else {\n console.log(dim(`No configurable options for provider \"${provider}\"`))\n }\n}\n\n// --- Main Config Editor ---\n\nexport async function runConfigEditor(\n configManager: ConfigManager,\n mode: 'file' | 'api' = 'file',\n apiPort?: number,\n): Promise<void> {\n await configManager.load()\n const config = configManager.get()\n const updates: ConfigUpdates = {}\n\n console.log(`\\n${c.cyan}${c.bold}OpenACP Config Editor${c.reset}`)\n console.log(dim(`Config: ${configManager.getConfigPath()}`))\n console.log('')\n\n try {\n while (true) {\n const hasChanges = mode === 'file' ? Object.keys(updates).length > 0 : false\n const choice = await select({\n message: `What would you like to edit?${hasChanges ? ` ${c.yellow}(unsaved changes)${c.reset}` : ''}`,\n choices: [\n { name: 'Channels', value: 'channels' },\n { name: 'Agent', value: 'agent' },\n { name: 'Workspace', value: 'workspace' },\n { name: 'Security', value: 'security' },\n { name: 'Logging', value: 'logging' },\n { name: 'Run Mode', value: 'runMode' },\n { name: 'API', value: 'api' },\n { name: 'Tunnel', value: 'tunnel' },\n { name: hasChanges ? 'Save & Exit' : 'Exit', value: 'exit' },\n ],\n })\n\n if (choice === 'exit') {\n if (mode === 'file' && hasChanges) {\n await configManager.save(updates)\n console.log(ok(`Config saved to ${configManager.getConfigPath()}`))\n } else if (mode === 'file') {\n console.log(dim('No changes made.'))\n }\n break\n }\n\n const sectionUpdates: ConfigUpdates = {}\n\n if (choice === 'channels') await editChannels(config, sectionUpdates)\n else if (choice === 'agent') await editAgent(config, sectionUpdates)\n else if (choice === 'workspace') await editWorkspace(config, sectionUpdates)\n else if (choice === 'security') await editSecurity(config, sectionUpdates)\n else if (choice === 'logging') await editLogging(config, sectionUpdates)\n else if (choice === 'runMode') await editRunMode(config, sectionUpdates)\n else if (choice === 'api') await editApi(config, sectionUpdates)\n else if (choice === 'tunnel') await editTunnel(config, sectionUpdates)\n\n if (mode === 'api' && Object.keys(sectionUpdates).length > 0) {\n await sendConfigViaApi(apiPort!, sectionUpdates)\n // Refresh in-memory config\n await configManager.load()\n Object.assign(config, configManager.get())\n } else {\n // Accumulate for file mode\n Object.assign(updates, sectionUpdates)\n }\n }\n } catch (err) {\n if ((err as Error).name === 'ExitPromptError') {\n console.log(dim('\\nConfig editor cancelled. Changes discarded.'))\n return\n }\n throw err\n }\n}\n\nasync function sendConfigViaApi(port: number, updates: ConfigUpdates): Promise<void> {\n const { apiCall: call } = await import('../../cli/api-client.js')\n\n const paths = flattenToPaths(updates)\n for (const { path, value } of paths) {\n const res = await call(port, '/api/config', {\n method: 'PATCH',\n headers: { 'Content-Type': 'application/json' },\n body: JSON.stringify({ path, value }),\n })\n const data = await res.json() as Record<string, unknown>\n if (!res.ok) {\n console.log(warn(`Failed to update ${path}: ${data.error}`))\n } else if (data.needsRestart) {\n console.log(warn(`${path} updated — restart required`))\n }\n }\n}\n\nfunction flattenToPaths(obj: Record<string, unknown>, prefix = ''): Array<{ path: string; value: unknown }> {\n const result: Array<{ path: string; value: unknown }> = []\n for (const [key, val] of Object.entries(obj)) {\n const fullPath = prefix ? `${prefix}.${key}` : key\n if (val && typeof val === 'object' && !Array.isArray(val)) {\n result.push(...flattenToPaths(val as Record<string, unknown>, fullPath))\n } else {\n result.push({ path: fullPath, value: val })\n }\n }\n return result\n}\n"],"mappings":"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","names":["select","tgUp","path"]}
@@ -1,229 +0,0 @@
1
- import {
2
- installNpmPlugin
3
- } from "./chunk-5WGVYX3C.js";
4
- import {
5
- GroqSTT,
6
- SpeechService
7
- } from "./chunk-2KT6TROD.js";
8
-
9
- // src/plugins/speech/index.ts
10
- var EDGE_TTS_PLUGIN = "@openacp/msedge-tts-plugin";
11
- var speechPlugin = {
12
- name: "@openacp/speech",
13
- version: "1.0.0",
14
- description: "Text-to-speech and speech-to-text with pluggable providers",
15
- essential: false,
16
- optionalPluginDependencies: { "@openacp/file-service": "^1.0.0" },
17
- permissions: ["services:register", "commands:register", "kernel:access"],
18
- inheritableKeys: ["tts"],
19
- async install(ctx) {
20
- const { terminal, settings, legacyConfig } = ctx;
21
- if (legacyConfig) {
22
- const speechCfg = legacyConfig.speech;
23
- if (speechCfg) {
24
- const stt = speechCfg.stt;
25
- const tts = speechCfg.tts;
26
- const groqProviders = stt?.providers;
27
- const groqConfig = groqProviders?.groq;
28
- await settings.setAll({
29
- sttProvider: stt?.provider ?? null,
30
- groqApiKey: groqConfig?.apiKey ?? "",
31
- ttsProvider: tts?.provider ?? "edge-tts",
32
- ttsVoice: ""
33
- });
34
- terminal.log.success("Speech settings migrated from legacy config");
35
- return;
36
- }
37
- }
38
- const enableStt = await terminal.confirm({
39
- message: "Enable speech-to-text (STT)?",
40
- initialValue: false
41
- });
42
- let sttProvider = null;
43
- let groqApiKey = "";
44
- if (enableStt) {
45
- sttProvider = await terminal.select({
46
- message: "STT provider:",
47
- options: [{ value: "groq", label: "Groq (Whisper)", hint: "Fast and affordable" }]
48
- });
49
- if (sttProvider === "groq") {
50
- groqApiKey = await terminal.text({
51
- message: "Groq API key:",
52
- validate: (v) => !v.trim() ? "API key cannot be empty" : void 0
53
- });
54
- groqApiKey = groqApiKey.trim();
55
- }
56
- }
57
- const ttsProvider = await terminal.select({
58
- message: "TTS provider:",
59
- options: [
60
- { value: "edge-tts", label: "Edge TTS", hint: "Free, good quality" },
61
- { value: "none", label: "None (disable TTS)" }
62
- ]
63
- });
64
- let ttsVoice = "";
65
- if (ttsProvider === "edge-tts") {
66
- terminal.log.info("Installing Edge TTS plugin...");
67
- try {
68
- await installNpmPlugin(EDGE_TTS_PLUGIN);
69
- terminal.log.success("Edge TTS plugin installed");
70
- } catch (err) {
71
- terminal.log.warning(`Failed to install Edge TTS plugin: ${err}. You can install it later with: openacp plugin install ${EDGE_TTS_PLUGIN}`);
72
- }
73
- ttsVoice = await terminal.text({
74
- message: "TTS voice (leave blank for default):",
75
- placeholder: "e.g. en-US-AriaNeural"
76
- });
77
- ttsVoice = ttsVoice.trim();
78
- }
79
- await settings.setAll({
80
- sttProvider,
81
- groqApiKey,
82
- ttsProvider: ttsProvider === "none" ? null : ttsProvider,
83
- ttsVoice
84
- });
85
- terminal.log.success("Speech settings saved");
86
- },
87
- async configure(ctx) {
88
- const { terminal, settings } = ctx;
89
- const current = await settings.getAll();
90
- const choice = await terminal.select({
91
- message: "What to configure?",
92
- options: [
93
- { value: "stt", label: "Change STT provider/key" },
94
- { value: "tts", label: "Change TTS provider/voice" },
95
- { value: "done", label: "Done" }
96
- ]
97
- });
98
- if (choice === "stt") {
99
- const key = await terminal.text({
100
- message: "Groq API key (leave blank to disable STT):",
101
- defaultValue: current.groqApiKey ?? ""
102
- });
103
- const trimmed = key.trim();
104
- await settings.set("sttProvider", trimmed ? "groq" : null);
105
- await settings.set("groqApiKey", trimmed);
106
- terminal.log.success("STT settings updated");
107
- } else if (choice === "tts") {
108
- const voice = await terminal.text({
109
- message: "TTS voice (leave blank for default):",
110
- defaultValue: current.ttsVoice ?? ""
111
- });
112
- await settings.set("ttsVoice", voice.trim());
113
- terminal.log.success("TTS settings updated");
114
- }
115
- },
116
- async uninstall(ctx, opts) {
117
- if (opts.purge) {
118
- await ctx.settings.clear();
119
- ctx.terminal.log.success("Speech settings cleared");
120
- }
121
- },
122
- async setup(ctx) {
123
- const config = ctx.pluginConfig;
124
- const groqApiKey = config.groqApiKey;
125
- const sttProvider = groqApiKey ? "groq" : null;
126
- const speechConfig = {
127
- stt: {
128
- provider: sttProvider,
129
- providers: groqApiKey ? { groq: { apiKey: groqApiKey } } : {}
130
- },
131
- tts: {
132
- provider: config.ttsProvider ?? "edge-tts",
133
- providers: {}
134
- }
135
- };
136
- const service = new SpeechService(speechConfig);
137
- if (groqApiKey) {
138
- service.registerSTTProvider("groq", new GroqSTT(groqApiKey));
139
- }
140
- service.setProviderFactory((cfg) => {
141
- const sttMap = /* @__PURE__ */ new Map();
142
- const ttsMap = /* @__PURE__ */ new Map();
143
- const groqCfg = cfg.stt?.providers?.groq;
144
- if (groqCfg?.apiKey) {
145
- sttMap.set("groq", new GroqSTT(groqCfg.apiKey, groqCfg.model));
146
- }
147
- return { stt: sttMap, tts: ttsMap };
148
- });
149
- ctx.registerService("speech", service);
150
- const setSessionVoiceMode = (pluginCtx, sessionId, voiceMode) => {
151
- if (!sessionId) return;
152
- try {
153
- const sessionManager = pluginCtx.sessions;
154
- const session = sessionManager.getSession(sessionId);
155
- if (session) {
156
- session.setVoiceMode(voiceMode);
157
- }
158
- } catch {
159
- }
160
- };
161
- ctx.registerCommand({
162
- name: "tts",
163
- description: "Toggle text-to-speech",
164
- usage: "on|off|next|install",
165
- category: "plugin",
166
- handler: async (args) => {
167
- const mode = args.raw.trim().toLowerCase();
168
- if ((mode === "on" || mode === "" || mode === "next") && !service.isTTSAvailable()) {
169
- return {
170
- type: "menu",
171
- title: "TTS provider not installed. Install Edge TTS plugin?",
172
- options: [
173
- { label: "Install Edge TTS", command: "/tts install" },
174
- { label: "Cancel", command: "/tts off" }
175
- ]
176
- };
177
- }
178
- if (mode === "install") {
179
- try {
180
- const mod = await installNpmPlugin(EDGE_TTS_PLUGIN);
181
- const plugin = mod.default;
182
- if (plugin && ctx.core) {
183
- const lm = ctx.core.lifecycleManager;
184
- const registry = lm.registry;
185
- if (registry) {
186
- registry.register(plugin.name, {
187
- version: plugin.version,
188
- source: "npm",
189
- enabled: true,
190
- settingsPath: "",
191
- description: plugin.description
192
- });
193
- await registry.save();
194
- }
195
- await lm.boot([plugin]);
196
- }
197
- return { type: "text", text: "Edge TTS plugin installed and ready! Use /tts on to enable." };
198
- } catch (err) {
199
- return { type: "error", message: `Failed to install Edge TTS plugin: ${err}. Try manually: openacp plugin install ${EDGE_TTS_PLUGIN}` };
200
- }
201
- }
202
- if (mode === "on") {
203
- setSessionVoiceMode(ctx, args.sessionId, "on");
204
- return { type: "text", text: "Text-to-speech enabled" };
205
- }
206
- if (mode === "off") {
207
- setSessionVoiceMode(ctx, args.sessionId, "off");
208
- return { type: "text", text: "Text-to-speech disabled" };
209
- }
210
- if (mode === "next") {
211
- setSessionVoiceMode(ctx, args.sessionId, "next");
212
- return { type: "text", text: "Text-to-speech enabled for next message" };
213
- }
214
- return { type: "menu", title: "Text to Speech", options: [
215
- { label: "Enable", command: "/tts on" },
216
- { label: "Disable", command: "/tts off" },
217
- { label: "Next message only", command: "/tts next" }
218
- ] };
219
- }
220
- });
221
- ctx.log.info("Speech service ready");
222
- }
223
- };
224
- var speech_default = speechPlugin;
225
-
226
- export {
227
- speech_default
228
- };
229
- //# sourceMappingURL=chunk-VUSCVRJL.js.map
@@ -1 +0,0 @@
1
- {"version":3,"sources":["../../src/plugins/speech/index.ts"],"sourcesContent":["import type { OpenACPPlugin, InstallContext, PluginContext } from '../../core/plugin/types.js'\nimport type { OpenACPCore } from '../../core/core.js'\nimport type { Session } from '../../core/sessions/session.js'\nimport { SpeechService, GroqSTT } from './exports.js'\nimport type { SpeechServiceConfig } from './exports.js'\nimport { installNpmPlugin } from '../../core/plugin/plugin-installer.js'\n\nconst EDGE_TTS_PLUGIN = '@openacp/msedge-tts-plugin'\n\nconst speechPlugin: OpenACPPlugin = {\n name: '@openacp/speech',\n version: '1.0.0',\n description: 'Text-to-speech and speech-to-text with pluggable providers',\n essential: false,\n optionalPluginDependencies: { '@openacp/file-service': '^1.0.0' },\n permissions: ['services:register', 'commands:register', 'kernel:access'],\n inheritableKeys: ['tts'],\n\n async install(ctx: InstallContext) {\n const { terminal, settings, legacyConfig } = ctx\n\n // Migrate from legacy config if present\n if (legacyConfig) {\n const speechCfg = legacyConfig.speech as Record<string, unknown> | undefined\n if (speechCfg) {\n const stt = speechCfg.stt as Record<string, unknown> | undefined\n const tts = speechCfg.tts as Record<string, unknown> | undefined\n const groqProviders = stt?.providers as Record<string, unknown> | undefined\n const groqConfig = groqProviders?.groq as Record<string, unknown> | undefined\n await settings.setAll({\n sttProvider: stt?.provider ?? null,\n groqApiKey: groqConfig?.apiKey ?? '',\n ttsProvider: tts?.provider ?? 'edge-tts',\n ttsVoice: '',\n })\n terminal.log.success('Speech settings migrated from legacy config')\n return\n }\n }\n\n // Interactive setup\n const enableStt = await terminal.confirm({\n message: 'Enable speech-to-text (STT)?',\n initialValue: false,\n })\n\n let sttProvider: string | null = null\n let groqApiKey = ''\n\n if (enableStt) {\n sttProvider = await terminal.select({\n message: 'STT provider:',\n options: [{ value: 'groq', label: 'Groq (Whisper)', hint: 'Fast and affordable' }],\n })\n\n if (sttProvider === 'groq') {\n groqApiKey = await terminal.text({\n message: 'Groq API key:',\n validate: (v) => (!v.trim() ? 'API key cannot be empty' : undefined),\n })\n groqApiKey = groqApiKey.trim()\n }\n }\n\n const ttsProvider = await terminal.select({\n message: 'TTS provider:',\n options: [\n { value: 'edge-tts', label: 'Edge TTS', hint: 'Free, good quality' },\n { value: 'none', label: 'None (disable TTS)' },\n ],\n })\n\n let ttsVoice = ''\n if (ttsProvider === 'edge-tts') {\n terminal.log.info('Installing Edge TTS plugin...')\n try {\n await installNpmPlugin(EDGE_TTS_PLUGIN)\n terminal.log.success('Edge TTS plugin installed')\n } catch (err) {\n terminal.log.warning(`Failed to install Edge TTS plugin: ${err}. You can install it later with: openacp plugin install ${EDGE_TTS_PLUGIN}`)\n }\n\n ttsVoice = await terminal.text({\n message: 'TTS voice (leave blank for default):',\n placeholder: 'e.g. en-US-AriaNeural',\n })\n ttsVoice = ttsVoice.trim()\n }\n\n await settings.setAll({\n sttProvider,\n groqApiKey,\n ttsProvider: ttsProvider === 'none' ? null : ttsProvider,\n ttsVoice,\n })\n terminal.log.success('Speech settings saved')\n },\n\n async configure(ctx: InstallContext) {\n const { terminal, settings } = ctx\n const current = await settings.getAll()\n\n const choice = await terminal.select({\n message: 'What to configure?',\n options: [\n { value: 'stt', label: 'Change STT provider/key' },\n { value: 'tts', label: 'Change TTS provider/voice' },\n { value: 'done', label: 'Done' },\n ],\n })\n\n if (choice === 'stt') {\n const key = await terminal.text({\n message: 'Groq API key (leave blank to disable STT):',\n defaultValue: (current.groqApiKey as string) ?? '',\n })\n const trimmed = key.trim()\n await settings.set('sttProvider', trimmed ? 'groq' : null)\n await settings.set('groqApiKey', trimmed)\n terminal.log.success('STT settings updated')\n } else if (choice === 'tts') {\n const voice = await terminal.text({\n message: 'TTS voice (leave blank for default):',\n defaultValue: (current.ttsVoice as string) ?? '',\n })\n await settings.set('ttsVoice', voice.trim())\n terminal.log.success('TTS settings updated')\n }\n },\n\n async uninstall(ctx: InstallContext, opts: { purge: boolean }) {\n if (opts.purge) {\n await ctx.settings.clear()\n ctx.terminal.log.success('Speech settings cleared')\n }\n },\n\n async setup(ctx) {\n const config = ctx.pluginConfig as Record<string, unknown>\n const groqApiKey = config.groqApiKey as string | undefined\n\n const sttProvider = groqApiKey ? 'groq' : null\n const speechConfig: SpeechServiceConfig = {\n stt: {\n provider: sttProvider,\n providers: groqApiKey ? { groq: { apiKey: groqApiKey } } : {},\n },\n tts: {\n provider: (config.ttsProvider as string) ?? 'edge-tts',\n providers: {},\n },\n }\n\n const service = new SpeechService(speechConfig)\n\n if (groqApiKey) {\n service.registerSTTProvider('groq', new GroqSTT(groqApiKey))\n }\n\n // TTS provider is now registered by @openacp/msedge-tts-plugin (no EdgeTTS here)\n\n // Register provider factory for hot-reload (STT only — TTS providers are managed by external plugins)\n service.setProviderFactory((cfg) => {\n const sttMap = new Map()\n const ttsMap = new Map()\n const groqCfg = cfg.stt?.providers?.groq\n if (groqCfg?.apiKey) {\n sttMap.set('groq', new GroqSTT(groqCfg.apiKey, groqCfg.model))\n }\n return { stt: sttMap, tts: ttsMap }\n })\n\n ctx.registerService('speech', service)\n\n // Helper to look up the session and set voiceMode\n const setSessionVoiceMode = (pluginCtx: PluginContext, sessionId: string | null, voiceMode: 'off' | 'next' | 'on'): void => {\n if (!sessionId) return\n try {\n const sessionManager = pluginCtx.sessions as { getSession(id: string): Session | undefined }\n const session = sessionManager.getSession(sessionId)\n if (session) {\n session.setVoiceMode(voiceMode)\n }\n } catch {\n // Session lookup may fail if kernel:access is unavailable; silently ignore\n }\n }\n\n ctx.registerCommand({\n name: 'tts',\n description: 'Toggle text-to-speech',\n usage: 'on|off|next|install',\n category: 'plugin',\n handler: async (args) => {\n const mode = args.raw.trim().toLowerCase()\n\n // Check if TTS provider is available\n if ((mode === 'on' || mode === '' || mode === 'next') && !service.isTTSAvailable()) {\n return {\n type: 'menu' as const,\n title: 'TTS provider not installed. Install Edge TTS plugin?',\n options: [\n { label: 'Install Edge TTS', command: '/tts install' },\n { label: 'Cancel', command: '/tts off' },\n ],\n }\n }\n\n if (mode === 'install') {\n try {\n const mod = await installNpmPlugin(EDGE_TTS_PLUGIN)\n const plugin = mod.default\n if (plugin && ctx.core) {\n const lm = (ctx.core as OpenACPCore).lifecycleManager\n const registry = lm.registry\n if (registry) {\n registry.register(plugin.name, {\n version: plugin.version,\n source: 'npm',\n enabled: true,\n settingsPath: '',\n description: plugin.description,\n })\n await registry.save()\n }\n await lm.boot([plugin])\n }\n return { type: 'text' as const, text: 'Edge TTS plugin installed and ready! Use /tts on to enable.' }\n } catch (err) {\n return { type: 'error' as const, message: `Failed to install Edge TTS plugin: ${err}. Try manually: openacp plugin install ${EDGE_TTS_PLUGIN}` }\n }\n }\n\n if (mode === 'on') {\n setSessionVoiceMode(ctx, args.sessionId, 'on')\n return { type: 'text' as const, text: 'Text-to-speech enabled' }\n }\n if (mode === 'off') {\n setSessionVoiceMode(ctx, args.sessionId, 'off')\n return { type: 'text' as const, text: 'Text-to-speech disabled' }\n }\n if (mode === 'next') {\n setSessionVoiceMode(ctx, args.sessionId, 'next')\n return { type: 'text' as const, text: 'Text-to-speech enabled for next message' }\n }\n return { type: 'menu' as const, title: 'Text to Speech', options: [\n { label: 'Enable', command: '/tts on' },\n { label: 'Disable', command: '/tts off' },\n { label: 'Next message only', command: '/tts next' },\n ]}\n },\n })\n\n ctx.log.info('Speech service ready')\n },\n}\n\nexport default speechPlugin\n"],"mappings":"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","names":[]}
@@ -1,61 +0,0 @@
1
- // src/core/plugin/plugin-registry.ts
2
- import fs from "fs";
3
- import path from "path";
4
- var PluginRegistry = class {
5
- constructor(registryPath) {
6
- this.registryPath = registryPath;
7
- }
8
- data = { installed: {} };
9
- list() {
10
- return new Map(Object.entries(this.data.installed));
11
- }
12
- get(name) {
13
- return this.data.installed[name];
14
- }
15
- register(name, entry) {
16
- const now = (/* @__PURE__ */ new Date()).toISOString();
17
- this.data.installed[name] = { ...entry, installedAt: now, updatedAt: now };
18
- }
19
- remove(name) {
20
- delete this.data.installed[name];
21
- }
22
- setEnabled(name, enabled) {
23
- const entry = this.data.installed[name];
24
- if (!entry) return;
25
- entry.enabled = enabled;
26
- entry.updatedAt = (/* @__PURE__ */ new Date()).toISOString();
27
- }
28
- updateVersion(name, version) {
29
- const entry = this.data.installed[name];
30
- if (!entry) return;
31
- entry.version = version;
32
- entry.updatedAt = (/* @__PURE__ */ new Date()).toISOString();
33
- }
34
- listEnabled() {
35
- return new Map(Object.entries(this.data.installed).filter(([, e]) => e.enabled));
36
- }
37
- listBySource(source) {
38
- return new Map(Object.entries(this.data.installed).filter(([, e]) => e.source === source));
39
- }
40
- async load() {
41
- try {
42
- const content = fs.readFileSync(this.registryPath, "utf-8");
43
- const parsed = JSON.parse(content);
44
- if (parsed && typeof parsed.installed === "object") {
45
- this.data = parsed;
46
- }
47
- } catch {
48
- this.data = { installed: {} };
49
- }
50
- }
51
- async save() {
52
- const dir = path.dirname(this.registryPath);
53
- fs.mkdirSync(dir, { recursive: true });
54
- fs.writeFileSync(this.registryPath, JSON.stringify(this.data, null, 2));
55
- }
56
- };
57
-
58
- export {
59
- PluginRegistry
60
- };
61
- //# sourceMappingURL=chunk-W26AUH5B.js.map
@@ -1 +0,0 @@
1
- {"version":3,"sources":["../../src/core/plugin/plugin-registry.ts"],"sourcesContent":["import fs from 'node:fs'\nimport path from 'node:path'\n\nexport interface PluginEntry {\n version: string\n installedAt: string\n updatedAt: string\n source: 'builtin' | 'npm' | 'local'\n enabled: boolean\n settingsPath: string\n description?: string\n}\n\ntype RegisterInput = Omit<PluginEntry, 'installedAt' | 'updatedAt'>\n\ninterface RegistryData {\n installed: Record<string, PluginEntry>\n}\n\nexport class PluginRegistry {\n private data: RegistryData = { installed: {} }\n\n constructor(private registryPath: string) {}\n\n list(): Map<string, PluginEntry> {\n return new Map(Object.entries(this.data.installed))\n }\n\n get(name: string): PluginEntry | undefined {\n return this.data.installed[name]\n }\n\n register(name: string, entry: RegisterInput): void {\n const now = new Date().toISOString()\n this.data.installed[name] = { ...entry, installedAt: now, updatedAt: now }\n }\n\n remove(name: string): void {\n delete this.data.installed[name]\n }\n\n setEnabled(name: string, enabled: boolean): void {\n const entry = this.data.installed[name]\n if (!entry) return\n entry.enabled = enabled\n entry.updatedAt = new Date().toISOString()\n }\n\n updateVersion(name: string, version: string): void {\n const entry = this.data.installed[name]\n if (!entry) return\n entry.version = version\n entry.updatedAt = new Date().toISOString()\n }\n\n listEnabled(): Map<string, PluginEntry> {\n return new Map(Object.entries(this.data.installed).filter(([, e]) => e.enabled))\n }\n\n listBySource(source: PluginEntry['source']): Map<string, PluginEntry> {\n return new Map(Object.entries(this.data.installed).filter(([, e]) => e.source === source))\n }\n\n async load(): Promise<void> {\n try {\n const content = fs.readFileSync(this.registryPath, 'utf-8')\n const parsed = JSON.parse(content)\n if (parsed && typeof parsed.installed === 'object') {\n this.data = parsed\n }\n } catch {\n this.data = { installed: {} }\n }\n }\n\n async save(): Promise<void> {\n const dir = path.dirname(this.registryPath)\n fs.mkdirSync(dir, { recursive: true })\n fs.writeFileSync(this.registryPath, JSON.stringify(this.data, null, 2))\n }\n}\n"],"mappings":";AAAA,OAAO,QAAQ;AACf,OAAO,UAAU;AAkBV,IAAM,iBAAN,MAAqB;AAAA,EAG1B,YAAoB,cAAsB;AAAtB;AAAA,EAAuB;AAAA,EAFnC,OAAqB,EAAE,WAAW,CAAC,EAAE;AAAA,EAI7C,OAAiC;AAC/B,WAAO,IAAI,IAAI,OAAO,QAAQ,KAAK,KAAK,SAAS,CAAC;AAAA,EACpD;AAAA,EAEA,IAAI,MAAuC;AACzC,WAAO,KAAK,KAAK,UAAU,IAAI;AAAA,EACjC;AAAA,EAEA,SAAS,MAAc,OAA4B;AACjD,UAAM,OAAM,oBAAI,KAAK,GAAE,YAAY;AACnC,SAAK,KAAK,UAAU,IAAI,IAAI,EAAE,GAAG,OAAO,aAAa,KAAK,WAAW,IAAI;AAAA,EAC3E;AAAA,EAEA,OAAO,MAAoB;AACzB,WAAO,KAAK,KAAK,UAAU,IAAI;AAAA,EACjC;AAAA,EAEA,WAAW,MAAc,SAAwB;AAC/C,UAAM,QAAQ,KAAK,KAAK,UAAU,IAAI;AACtC,QAAI,CAAC,MAAO;AACZ,UAAM,UAAU;AAChB,UAAM,aAAY,oBAAI,KAAK,GAAE,YAAY;AAAA,EAC3C;AAAA,EAEA,cAAc,MAAc,SAAuB;AACjD,UAAM,QAAQ,KAAK,KAAK,UAAU,IAAI;AACtC,QAAI,CAAC,MAAO;AACZ,UAAM,UAAU;AAChB,UAAM,aAAY,oBAAI,KAAK,GAAE,YAAY;AAAA,EAC3C;AAAA,EAEA,cAAwC;AACtC,WAAO,IAAI,IAAI,OAAO,QAAQ,KAAK,KAAK,SAAS,EAAE,OAAO,CAAC,CAAC,EAAE,CAAC,MAAM,EAAE,OAAO,CAAC;AAAA,EACjF;AAAA,EAEA,aAAa,QAAyD;AACpE,WAAO,IAAI,IAAI,OAAO,QAAQ,KAAK,KAAK,SAAS,EAAE,OAAO,CAAC,CAAC,EAAE,CAAC,MAAM,EAAE,WAAW,MAAM,CAAC;AAAA,EAC3F;AAAA,EAEA,MAAM,OAAsB;AAC1B,QAAI;AACF,YAAM,UAAU,GAAG,aAAa,KAAK,cAAc,OAAO;AAC1D,YAAM,SAAS,KAAK,MAAM,OAAO;AACjC,UAAI,UAAU,OAAO,OAAO,cAAc,UAAU;AAClD,aAAK,OAAO;AAAA,MACd;AAAA,IACF,QAAQ;AACN,WAAK,OAAO,EAAE,WAAW,CAAC,EAAE;AAAA,IAC9B;AAAA,EACF;AAAA,EAEA,MAAM,OAAsB;AAC1B,UAAM,MAAM,KAAK,QAAQ,KAAK,YAAY;AAC1C,OAAG,UAAU,KAAK,EAAE,WAAW,KAAK,CAAC;AACrC,OAAG,cAAc,KAAK,cAAc,KAAK,UAAU,KAAK,MAAM,MAAM,CAAC,CAAC;AAAA,EACxE;AACF;","names":[]}
@@ -1,84 +0,0 @@
1
- // src/plugins/telegram/validators.ts
2
- async function validateBotToken(token) {
3
- try {
4
- const res = await fetch(`https://api.telegram.org/bot${token}/getMe`);
5
- const data = await res.json();
6
- if (data.ok && data.result) {
7
- return {
8
- ok: true,
9
- botName: data.result.first_name,
10
- botUsername: data.result.username
11
- };
12
- }
13
- return { ok: false, error: data.description || "Invalid token" };
14
- } catch (err) {
15
- return { ok: false, error: err.message };
16
- }
17
- }
18
- async function validateChatId(token, chatId) {
19
- try {
20
- const res = await fetch(`https://api.telegram.org/bot${token}/getChat`, {
21
- method: "POST",
22
- headers: { "Content-Type": "application/json" },
23
- body: JSON.stringify({ chat_id: chatId })
24
- });
25
- const data = await res.json();
26
- if (!data.ok || !data.result) {
27
- return { ok: false, error: data.description || "Invalid chat ID" };
28
- }
29
- if (data.result.type !== "supergroup") {
30
- return {
31
- ok: false,
32
- error: `Chat is "${data.result.type}", must be a supergroup`
33
- };
34
- }
35
- return {
36
- ok: true,
37
- title: data.result.title,
38
- isForum: data.result.is_forum === true
39
- };
40
- } catch (err) {
41
- return { ok: false, error: err.message };
42
- }
43
- }
44
- async function validateBotAdmin(token, chatId) {
45
- try {
46
- const meRes = await fetch(`https://api.telegram.org/bot${token}/getMe`);
47
- const meData = await meRes.json();
48
- if (!meData.ok || !meData.result) {
49
- return { ok: false, error: "Could not retrieve bot info" };
50
- }
51
- const res = await fetch(
52
- `https://api.telegram.org/bot${token}/getChatMember`,
53
- {
54
- method: "POST",
55
- headers: { "Content-Type": "application/json" },
56
- body: JSON.stringify({ chat_id: chatId, user_id: meData.result.id })
57
- }
58
- );
59
- const data = await res.json();
60
- if (!data.ok || !data.result) {
61
- return {
62
- ok: false,
63
- error: data.description || "Could not check bot membership"
64
- };
65
- }
66
- const { status } = data.result;
67
- if (status === "administrator" || status === "creator") {
68
- return { ok: true };
69
- }
70
- return {
71
- ok: false,
72
- error: `Bot is "${status}" in this group. It must be an admin. Please promote the bot to admin in group settings.`
73
- };
74
- } catch (err) {
75
- return { ok: false, error: err.message };
76
- }
77
- }
78
-
79
- export {
80
- validateBotToken,
81
- validateChatId,
82
- validateBotAdmin
83
- };
84
- //# sourceMappingURL=chunk-WQCJTU2C.js.map
@@ -1 +0,0 @@
1
- {"version":3,"sources":["../../src/plugins/telegram/validators.ts"],"sourcesContent":["export 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"],"mappings":";AAAA,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;","names":[]}
@@ -1,53 +0,0 @@
1
- // src/cli/api-client.ts
2
- import * as fs from "fs";
3
- import * as path from "path";
4
- import * as os from "os";
5
- var DEFAULT_ROOT = path.join(os.homedir(), ".openacp");
6
- function defaultPortFile(root) {
7
- return path.join(root ?? DEFAULT_ROOT, "api.port");
8
- }
9
- function defaultSecretFile(root) {
10
- return path.join(root ?? DEFAULT_ROOT, "api-secret");
11
- }
12
- function readApiPort(portFilePath, instanceRoot) {
13
- const filePath = portFilePath ?? defaultPortFile(instanceRoot);
14
- try {
15
- const content = fs.readFileSync(filePath, "utf-8").trim();
16
- const port = parseInt(content, 10);
17
- return isNaN(port) ? null : port;
18
- } catch {
19
- return null;
20
- }
21
- }
22
- function readApiSecret(secretFilePath, instanceRoot) {
23
- const filePath = secretFilePath ?? defaultSecretFile(instanceRoot);
24
- try {
25
- const content = fs.readFileSync(filePath, "utf-8").trim();
26
- return content || null;
27
- } catch {
28
- return null;
29
- }
30
- }
31
- function removeStalePortFile(portFilePath, instanceRoot) {
32
- const filePath = portFilePath ?? defaultPortFile(instanceRoot);
33
- try {
34
- fs.unlinkSync(filePath);
35
- } catch {
36
- }
37
- }
38
- async function apiCall(port, urlPath, options, instanceRoot) {
39
- const secret = readApiSecret(void 0, instanceRoot);
40
- const headers = new Headers(options?.headers);
41
- if (secret) {
42
- headers.set("Authorization", `Bearer ${secret}`);
43
- }
44
- return fetch(`http://127.0.0.1:${port}${urlPath}`, { ...options, headers });
45
- }
46
-
47
- export {
48
- readApiPort,
49
- readApiSecret,
50
- removeStalePortFile,
51
- apiCall
52
- };
53
- //# sourceMappingURL=chunk-XRJUS6FE.js.map
@@ -1 +0,0 @@
1
- {"version":3,"sources":["../../src/cli/api-client.ts"],"sourcesContent":["import * as fs from 'node:fs'\nimport * as path from 'node:path'\nimport * as os from 'node:os'\n\nconst DEFAULT_ROOT = path.join(os.homedir(), '.openacp')\n\nfunction defaultPortFile(root?: string): string {\n return path.join(root ?? DEFAULT_ROOT, 'api.port')\n}\n\nfunction defaultSecretFile(root?: string): string {\n return path.join(root ?? DEFAULT_ROOT, 'api-secret')\n}\n\nexport function readApiPort(portFilePath?: string, instanceRoot?: string): number | null {\n const filePath = portFilePath ?? defaultPortFile(instanceRoot)\n try {\n const content = fs.readFileSync(filePath, 'utf-8').trim()\n const port = parseInt(content, 10)\n return isNaN(port) ? null : port\n } catch {\n return null\n }\n}\n\nexport function readApiSecret(secretFilePath?: string, instanceRoot?: string): string | null {\n const filePath = secretFilePath ?? defaultSecretFile(instanceRoot)\n try {\n const content = fs.readFileSync(filePath, 'utf-8').trim()\n return content || null\n } catch {\n return null\n }\n}\n\nexport function removeStalePortFile(portFilePath?: string, instanceRoot?: string): void {\n const filePath = portFilePath ?? defaultPortFile(instanceRoot)\n try {\n fs.unlinkSync(filePath)\n } catch {\n // ignore\n }\n}\n\nexport async function apiCall(\n port: number,\n urlPath: string,\n options?: RequestInit,\n instanceRoot?: string,\n): Promise<Response> {\n const secret = readApiSecret(undefined, instanceRoot)\n const headers = new Headers(options?.headers)\n if (secret) {\n headers.set('Authorization', `Bearer ${secret}`)\n }\n return fetch(`http://127.0.0.1:${port}${urlPath}`, { ...options, headers })\n}\n"],"mappings":";AAAA,YAAY,QAAQ;AACpB,YAAY,UAAU;AACtB,YAAY,QAAQ;AAEpB,IAAM,eAAoB,UAAQ,WAAQ,GAAG,UAAU;AAEvD,SAAS,gBAAgB,MAAuB;AAC9C,SAAY,UAAK,QAAQ,cAAc,UAAU;AACnD;AAEA,SAAS,kBAAkB,MAAuB;AAChD,SAAY,UAAK,QAAQ,cAAc,YAAY;AACrD;AAEO,SAAS,YAAY,cAAuB,cAAsC;AACvF,QAAM,WAAW,gBAAgB,gBAAgB,YAAY;AAC7D,MAAI;AACF,UAAM,UAAa,gBAAa,UAAU,OAAO,EAAE,KAAK;AACxD,UAAM,OAAO,SAAS,SAAS,EAAE;AACjC,WAAO,MAAM,IAAI,IAAI,OAAO;AAAA,EAC9B,QAAQ;AACN,WAAO;AAAA,EACT;AACF;AAEO,SAAS,cAAc,gBAAyB,cAAsC;AAC3F,QAAM,WAAW,kBAAkB,kBAAkB,YAAY;AACjE,MAAI;AACF,UAAM,UAAa,gBAAa,UAAU,OAAO,EAAE,KAAK;AACxD,WAAO,WAAW;AAAA,EACpB,QAAQ;AACN,WAAO;AAAA,EACT;AACF;AAEO,SAAS,oBAAoB,cAAuB,cAA6B;AACtF,QAAM,WAAW,gBAAgB,gBAAgB,YAAY;AAC7D,MAAI;AACF,IAAG,cAAW,QAAQ;AAAA,EACxB,QAAQ;AAAA,EAER;AACF;AAEA,eAAsB,QACpB,MACA,SACA,SACA,cACmB;AACnB,QAAM,SAAS,cAAc,QAAW,YAAY;AACpD,QAAM,UAAU,IAAI,QAAQ,SAAS,OAAO;AAC5C,MAAI,QAAQ;AACV,YAAQ,IAAI,iBAAiB,UAAU,MAAM,EAAE;AAAA,EACjD;AACA,SAAO,MAAM,oBAAoB,IAAI,GAAG,OAAO,IAAI,EAAE,GAAG,SAAS,QAAQ,CAAC;AAC5E;","names":[]}