@agentprojectcontext/apx 1.24.0 → 1.27.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (718) hide show
  1. package/package.json +42 -12
  2. package/skills/apx/SKILL.md +50 -119
  3. package/skills/apx-agency-agents/SKILL.md +141 -0
  4. package/skills/apx-agent/SKILL.md +100 -0
  5. package/skills/apx-mcp/SKILL.md +114 -0
  6. package/skills/apx-mcp-builder/SKILL.md +186 -0
  7. package/skills/apx-project/SKILL.md +100 -0
  8. package/skills/apx-routine/SKILL.md +138 -0
  9. package/skills/apx-runtime/SKILL.md +115 -0
  10. package/skills/apx-sessions/SKILL.md +281 -0
  11. package/skills/apx-skill-builder/SKILL.md +149 -0
  12. package/skills/apx-task/SKILL.md +95 -0
  13. package/skills/apx-telegram/SKILL.md +115 -0
  14. package/skills/apx-voice/SKILL.md +135 -0
  15. package/src/core/agent/constants.js +3 -0
  16. package/src/core/agent/ghost-guard.js +24 -0
  17. package/src/core/agent/index.js +35 -0
  18. package/src/core/agent/model-router.js +257 -0
  19. package/src/core/agent/prompt-builder.js +313 -0
  20. package/src/core/agent/prompts/channels/api.md +7 -0
  21. package/src/core/agent/prompts/channels/cli.md +6 -0
  22. package/src/core/agent/prompts/channels/code.md +20 -0
  23. package/src/core/agent/prompts/channels/deck.md +6 -0
  24. package/src/core/agent/prompts/channels/desktop.md +24 -0
  25. package/src/core/agent/prompts/channels/routine.md +9 -0
  26. package/src/core/agent/prompts/channels/telegram.md +9 -0
  27. package/src/core/agent/prompts/channels/terminal.md +16 -0
  28. package/src/core/agent/prompts/channels/web.md +7 -0
  29. package/src/core/agent/prompts/channels/web_sidebar.md +7 -0
  30. package/src/core/agent/prompts/modes/voice.md +4 -0
  31. package/src/core/agent/prompts/super-agent-base.md +42 -0
  32. package/src/core/agent/pseudo-tools.js +40 -0
  33. package/src/core/agent/retry.js +85 -0
  34. package/src/core/agent/run-agent.js +423 -0
  35. package/src/core/agent/self-memory.js +155 -0
  36. package/src/{daemon → core/agent}/tool-call-parser.js +83 -10
  37. package/src/core/agent/tools-overlap.js +66 -0
  38. package/src/core/apc-skill-sync.js +97 -0
  39. package/src/core/code-sessions-store.js +150 -0
  40. package/src/core/config.js +473 -11
  41. package/src/core/desktop/autostart.js +162 -0
  42. package/src/core/engines/_health.js +63 -0
  43. package/src/{daemon → core}/engines/anthropic.js +16 -0
  44. package/src/core/engines/gemini.js +168 -0
  45. package/src/core/engines/groq.js +8 -0
  46. package/src/{daemon → core}/engines/index.js +3 -1
  47. package/src/{daemon → core}/engines/mock.js +22 -0
  48. package/src/{daemon → core}/engines/ollama.js +35 -0
  49. package/src/core/engines/openai-compatible.js +145 -0
  50. package/src/core/engines/openai.js +8 -0
  51. package/src/core/engines/openrouter.js +8 -0
  52. package/src/core/git-baseline.js +147 -0
  53. package/src/core/identity.js +21 -0
  54. package/src/core/logging.js +1 -1
  55. package/src/core/mcp/index.js +14 -0
  56. package/src/{daemon/mcp-runner.js → core/mcp/runner.js} +18 -6
  57. package/src/core/mcp/sources.js +246 -0
  58. package/src/core/memory/active-threads.js +124 -0
  59. package/src/core/memory/broker.js +144 -0
  60. package/src/core/memory/compactor.js +186 -0
  61. package/src/core/memory/embed-engines/gemini.js +62 -0
  62. package/src/core/memory/embed-engines/index.js +148 -0
  63. package/src/core/memory/embed-engines/ollama.js +55 -0
  64. package/src/core/memory/embed-engines/openai.js +64 -0
  65. package/src/core/memory/embed-engines/tf.js +20 -0
  66. package/src/core/memory/embeddings.js +132 -0
  67. package/src/core/memory/index.js +161 -0
  68. package/src/core/memory/indexer.js +257 -0
  69. package/src/core/memory/store.js +231 -0
  70. package/src/core/messages-store.js +143 -25
  71. package/src/core/parser.js +78 -16
  72. package/src/core/scaffold.js +175 -79
  73. package/src/core/tasks-store.js +264 -0
  74. package/src/core/telegram-identity.js +126 -0
  75. package/src/core/tools/index.js +6 -0
  76. package/src/core/voice/engines/elevenlabs.js +96 -0
  77. package/src/core/voice/engines/gemini.js +148 -0
  78. package/src/core/voice/engines/index.js +144 -0
  79. package/src/core/voice/engines/mock.js +59 -0
  80. package/src/core/voice/engines/openai.js +82 -0
  81. package/src/core/voice/engines/piper.js +93 -0
  82. package/src/core/voice/index.js +3 -0
  83. package/src/core/voice/tts.js +89 -0
  84. package/src/{daemon → host/daemon}/apc-runtime-context.js +1 -1
  85. package/src/host/daemon/api/admin-config.js +159 -0
  86. package/src/host/daemon/api/admin.js +72 -0
  87. package/src/host/daemon/api/agents.js +284 -0
  88. package/src/host/daemon/api/artifacts.js +52 -0
  89. package/src/host/daemon/api/code.js +351 -0
  90. package/src/host/daemon/api/config.js +104 -0
  91. package/src/host/daemon/api/connections.js +42 -0
  92. package/src/host/daemon/api/conversations.js +161 -0
  93. package/src/host/daemon/api/deck.js +511 -0
  94. package/src/host/daemon/api/desktop.js +71 -0
  95. package/src/host/daemon/api/embeddings.js +65 -0
  96. package/src/host/daemon/api/engines.js +80 -0
  97. package/src/host/daemon/api/exec.js +193 -0
  98. package/src/host/daemon/api/health.js +10 -0
  99. package/src/host/daemon/api/identity.js +36 -0
  100. package/src/host/daemon/api/mcps.js +205 -0
  101. package/src/host/daemon/api/messages.js +83 -0
  102. package/src/host/daemon/api/pairing.js +194 -0
  103. package/src/host/daemon/api/plugins.js +19 -0
  104. package/src/host/daemon/api/projects.js +35 -0
  105. package/src/host/daemon/api/routines.js +84 -0
  106. package/src/host/daemon/api/run.js +55 -0
  107. package/src/host/daemon/api/runtimes.js +219 -0
  108. package/src/host/daemon/api/sessions-search.js +177 -0
  109. package/src/host/daemon/api/sessions.js +115 -0
  110. package/src/host/daemon/api/shared.js +217 -0
  111. package/src/host/daemon/api/super-agent.js +208 -0
  112. package/src/host/daemon/api/tasks.js +118 -0
  113. package/src/host/daemon/api/telegram.js +325 -0
  114. package/src/host/daemon/api/tools.js +21 -0
  115. package/src/host/daemon/api/top-level.js +131 -0
  116. package/src/host/daemon/api/transcribe.js +35 -0
  117. package/src/host/daemon/api/tts.js +44 -0
  118. package/src/host/daemon/api/voice.js +519 -0
  119. package/src/host/daemon/api/web.js +123 -0
  120. package/src/host/daemon/api.js +152 -0
  121. package/src/{daemon → host/daemon}/compact.js +1 -1
  122. package/src/{daemon → host/daemon}/db.js +19 -5
  123. package/src/{daemon/overlay-ws.js → host/daemon/desktop-ws.js} +7 -7
  124. package/src/host/daemon/engine-sessions.js +245 -0
  125. package/src/{daemon → host/daemon}/index.js +27 -10
  126. package/src/{daemon/plugins/overlay.js → host/daemon/plugins/desktop.js} +36 -28
  127. package/src/{daemon → host/daemon}/plugins/index.js +2 -2
  128. package/src/{daemon → host/daemon}/plugins/telegram.js +165 -33
  129. package/src/{daemon → host/daemon}/project-config.js +31 -7
  130. package/src/{daemon → host/daemon}/routines.js +27 -8
  131. package/src/{daemon → host/daemon}/skills-loader.js +4 -2
  132. package/src/{daemon → host/daemon}/smoke.js +9 -5
  133. package/src/{daemon → host/daemon}/super-agent-tools/helpers.js +1 -1
  134. package/src/host/daemon/super-agent-tools/index.js +157 -0
  135. package/src/{daemon → host/daemon}/super-agent-tools/registry-bridge.js +1 -1
  136. package/src/{daemon → host/daemon}/super-agent-tools/tools/add-project.js +2 -2
  137. package/src/{daemon → host/daemon}/super-agent-tools/tools/ask-questions.js +4 -0
  138. package/src/{daemon → host/daemon}/super-agent-tools/tools/call-agent.js +5 -2
  139. package/src/{daemon → host/daemon}/super-agent-tools/tools/call-runtime.js +117 -8
  140. package/src/host/daemon/super-agent-tools/tools/create-task.js +52 -0
  141. package/src/{daemon → host/daemon}/super-agent-tools/tools/import-agent.js +2 -3
  142. package/src/{daemon → host/daemon}/super-agent-tools/tools/list-agents.js +1 -1
  143. package/src/host/daemon/super-agent-tools/tools/list-tasks.js +52 -0
  144. package/src/{daemon → host/daemon}/super-agent-tools/tools/list-vault-agents.js +1 -1
  145. package/src/host/daemon/super-agent-tools/tools/read-self-memory.js +21 -0
  146. package/src/host/daemon/super-agent-tools/tools/remember.js +40 -0
  147. package/src/{daemon → host/daemon}/super-agent-tools/tools/search-messages.js +1 -1
  148. package/src/host/daemon/super-agent-tools/tools/search-sessions.js +134 -0
  149. package/src/{daemon → host/daemon}/super-agent-tools/tools/send-telegram.js +2 -2
  150. package/src/{daemon → host/daemon}/super-agent-tools/tools/set-identity.js +1 -1
  151. package/src/{daemon → host/daemon}/super-agent-tools/tools/set-permission-mode.js +1 -1
  152. package/src/{daemon → host/daemon}/super-agent-tools/tools/tail-messages.js +1 -1
  153. package/src/host/daemon/super-agent.js +129 -0
  154. package/src/host/daemon/token-store.js +118 -0
  155. package/src/host/daemon/tool-call-parser.js +2 -0
  156. package/src/{daemon → host/daemon}/transcription.js +1 -1
  157. package/src/{daemon → host/daemon}/wakeup.js +2 -2
  158. package/src/interfaces/cli/claude-permissions.js +33 -0
  159. package/src/{cli → interfaces/cli}/commands/agent.js +43 -8
  160. package/src/{cli → interfaces/cli}/commands/command.js +1 -1
  161. package/src/{cli → interfaces/cli}/commands/config.js +1 -1
  162. package/src/{cli → interfaces/cli}/commands/daemon.js +67 -0
  163. package/src/interfaces/cli/commands/desktop.js +335 -0
  164. package/src/interfaces/cli/commands/exec.js +92 -0
  165. package/src/{cli → interfaces/cli}/commands/identity.js +6 -63
  166. package/src/{cli → interfaces/cli}/commands/init.js +1 -1
  167. package/src/{cli → interfaces/cli}/commands/mcp.js +69 -10
  168. package/src/{cli → interfaces/cli}/commands/memory.js +2 -2
  169. package/src/interfaces/cli/commands/model.js +136 -0
  170. package/src/interfaces/cli/commands/pair.js +170 -0
  171. package/src/interfaces/cli/commands/project-config.js +131 -0
  172. package/src/{cli → interfaces/cli}/commands/project.js +1 -1
  173. package/src/{cli → interfaces/cli}/commands/search.js +1 -1
  174. package/src/interfaces/cli/commands/session.js +892 -0
  175. package/src/interfaces/cli/commands/sessions.js +997 -0
  176. package/src/{cli → interfaces/cli}/commands/setup.js +98 -4
  177. package/src/{cli → interfaces/cli}/commands/skills.js +117 -9
  178. package/src/{cli → interfaces/cli}/commands/status.js +9 -1
  179. package/src/{cli → interfaces/cli}/commands/sys.js +96 -17
  180. package/src/interfaces/cli/commands/task.js +179 -0
  181. package/src/interfaces/cli/commands/telegram.js +366 -0
  182. package/src/{cli → interfaces/cli}/commands/update.js +1 -1
  183. package/src/interfaces/cli/commands/voice.js +258 -0
  184. package/src/{cli → interfaces/cli}/http.js +6 -2
  185. package/src/{cli → interfaces/cli}/index.js +955 -63
  186. package/src/interfaces/cli/postinstall.js +34 -0
  187. package/src/interfaces/desktop/assets/app-icon-180.png +0 -0
  188. package/src/interfaces/desktop/assets/app-icon-32.png +0 -0
  189. package/src/interfaces/desktop/assets/app-icon.png +0 -0
  190. package/src/interfaces/desktop/assets/apx-logo.png +0 -0
  191. package/src/interfaces/desktop/assets/superagent.png +0 -0
  192. package/src/interfaces/desktop/assets/tray-icon.png +0 -0
  193. package/src/interfaces/desktop/index.html +18 -0
  194. package/src/interfaces/desktop/main.js +652 -0
  195. package/src/interfaces/desktop/preload.js +48 -0
  196. package/src/interfaces/desktop/renderer.js +1006 -0
  197. package/src/interfaces/desktop/style.css +400 -0
  198. package/src/{mcp → interfaces/mcp-server}/index.js +2 -2
  199. package/src/interfaces/tui/_shims/util-which.ts +53 -0
  200. package/src/{tui → interfaces/tui}/app.tsx +2 -2
  201. package/src/{tui → interfaces/tui}/component/prompt/index.tsx +4 -1
  202. package/src/{tui → interfaces/tui}/context/sdk-apx.tsx +84 -16
  203. package/src/interfaces/tui/context/sync-apx.tsx +398 -0
  204. package/src/interfaces/tui/routes/session/index.tsx +368 -0
  205. package/src/interfaces/tui/routes/session/message-actions.tsx +58 -0
  206. package/src/interfaces/tui/routes/session/sidebar-apx.tsx +114 -0
  207. package/src/{tui → interfaces/tui}/tsconfig.json +1 -0
  208. package/src/{tui → interfaces/tui}/util/clipboard.ts +1 -1
  209. package/src/interfaces/web/README.md +102 -0
  210. package/src/interfaces/web/coming-soon.html +65 -0
  211. package/src/interfaces/web/components.json +25 -0
  212. package/src/interfaces/web/dist/assets/index-BDUsA6L6.css +1 -0
  213. package/src/interfaces/web/dist/assets/index-CfWyjPBa.js +548 -0
  214. package/src/interfaces/web/dist/assets/index-CfWyjPBa.js.map +1 -0
  215. package/src/interfaces/web/dist/favicon/dark/android-chrome-192x192.png +0 -0
  216. package/src/interfaces/web/dist/favicon/dark/android-chrome-512x512.png +0 -0
  217. package/src/interfaces/web/dist/favicon/dark/apple-touch-icon.png +0 -0
  218. package/src/interfaces/web/dist/favicon/dark/favicon-16x16.png +0 -0
  219. package/src/interfaces/web/dist/favicon/dark/favicon-32x32.png +0 -0
  220. package/src/interfaces/web/dist/favicon/dark/favicon-48x48.png +0 -0
  221. package/src/interfaces/web/dist/favicon/dark/favicon.ico +0 -0
  222. package/src/interfaces/web/dist/favicon/dark/favicon.webp +0 -0
  223. package/src/interfaces/web/dist/favicon/dark/site.webmanifest +18 -0
  224. package/src/interfaces/web/dist/favicon/white/android-chrome-192x192.png +0 -0
  225. package/src/interfaces/web/dist/favicon/white/android-chrome-512x512.png +0 -0
  226. package/src/interfaces/web/dist/favicon/white/apple-touch-icon.png +0 -0
  227. package/src/interfaces/web/dist/favicon/white/favicon-16x16.png +0 -0
  228. package/src/interfaces/web/dist/favicon/white/favicon-32x32.png +0 -0
  229. package/src/interfaces/web/dist/favicon/white/favicon-48x48.png +0 -0
  230. package/src/interfaces/web/dist/favicon/white/favicon.ico +0 -0
  231. package/src/interfaces/web/dist/favicon/white/favicon.webp +0 -0
  232. package/src/interfaces/web/dist/favicon/white/site.webmanifest +18 -0
  233. package/src/interfaces/web/dist/index.html +27 -0
  234. package/src/interfaces/web/dist/logo/logo_dark.webp +0 -0
  235. package/src/interfaces/web/dist/logo/logo_only_dark.webp +0 -0
  236. package/src/interfaces/web/dist/logo/logo_only_white.webp +0 -0
  237. package/src/interfaces/web/dist/logo/logo_vertical_dark.webp +0 -0
  238. package/src/interfaces/web/dist/logo/logo_vertical_white.webp +0 -0
  239. package/src/interfaces/web/dist/logo/logo_white.webp +0 -0
  240. package/src/interfaces/web/dist/modules/superagent.png +0 -0
  241. package/src/interfaces/web/index.html +26 -0
  242. package/src/interfaces/web/package-lock.json +4253 -0
  243. package/src/interfaces/web/package.json +55 -0
  244. package/src/interfaces/web/playwright.config.ts +45 -0
  245. package/src/interfaces/web/pnpm-lock.yaml +2946 -0
  246. package/src/interfaces/web/public/favicon/dark/android-chrome-192x192.png +0 -0
  247. package/src/interfaces/web/public/favicon/dark/android-chrome-512x512.png +0 -0
  248. package/src/interfaces/web/public/favicon/dark/apple-touch-icon.png +0 -0
  249. package/src/interfaces/web/public/favicon/dark/favicon-16x16.png +0 -0
  250. package/src/interfaces/web/public/favicon/dark/favicon-32x32.png +0 -0
  251. package/src/interfaces/web/public/favicon/dark/favicon-48x48.png +0 -0
  252. package/src/interfaces/web/public/favicon/dark/favicon.ico +0 -0
  253. package/src/interfaces/web/public/favicon/dark/favicon.webp +0 -0
  254. package/src/interfaces/web/public/favicon/dark/site.webmanifest +18 -0
  255. package/src/interfaces/web/public/favicon/white/android-chrome-192x192.png +0 -0
  256. package/src/interfaces/web/public/favicon/white/android-chrome-512x512.png +0 -0
  257. package/src/interfaces/web/public/favicon/white/apple-touch-icon.png +0 -0
  258. package/src/interfaces/web/public/favicon/white/favicon-16x16.png +0 -0
  259. package/src/interfaces/web/public/favicon/white/favicon-32x32.png +0 -0
  260. package/src/interfaces/web/public/favicon/white/favicon-48x48.png +0 -0
  261. package/src/interfaces/web/public/favicon/white/favicon.ico +0 -0
  262. package/src/interfaces/web/public/favicon/white/favicon.webp +0 -0
  263. package/src/interfaces/web/public/favicon/white/site.webmanifest +18 -0
  264. package/src/interfaces/web/public/logo/logo_dark.webp +0 -0
  265. package/src/interfaces/web/public/logo/logo_only_dark.webp +0 -0
  266. package/src/interfaces/web/public/logo/logo_only_white.webp +0 -0
  267. package/src/interfaces/web/public/logo/logo_vertical_dark.webp +0 -0
  268. package/src/interfaces/web/public/logo/logo_vertical_white.webp +0 -0
  269. package/src/interfaces/web/public/logo/logo_white.webp +0 -0
  270. package/src/interfaces/web/public/modules/superagent.png +0 -0
  271. package/src/interfaces/web/src/App.tsx +199 -0
  272. package/src/interfaces/web/src/components/AddProjectDialog.tsx +121 -0
  273. package/src/interfaces/web/src/components/ModelCombobox.tsx +96 -0
  274. package/src/interfaces/web/src/components/RobyBubble.tsx +213 -0
  275. package/src/interfaces/web/src/components/Section.tsx +44 -0
  276. package/src/interfaces/web/src/components/TelegramChannelDialog.tsx +97 -0
  277. package/src/interfaces/web/src/components/TelegramSendDialog.tsx +48 -0
  278. package/src/interfaces/web/src/components/Toast.tsx +84 -0
  279. package/src/interfaces/web/src/components/UiSelect.tsx +74 -0
  280. package/src/interfaces/web/src/components/chat/Composer.tsx +43 -0
  281. package/src/interfaces/web/src/components/chat/ContextBar.tsx +111 -0
  282. package/src/interfaces/web/src/components/chat/MessageBubble.tsx +95 -0
  283. package/src/interfaces/web/src/components/chat/MessageList.tsx +35 -0
  284. package/src/interfaces/web/src/components/chat/ModelPicker.tsx +145 -0
  285. package/src/interfaces/web/src/components/chat/ToolCall.tsx +141 -0
  286. package/src/interfaces/web/src/components/code/CodeChangesTab.tsx +87 -0
  287. package/src/interfaces/web/src/components/code/CodeComposer.tsx +87 -0
  288. package/src/interfaces/web/src/components/code/CodeContextTab.tsx +83 -0
  289. package/src/interfaces/web/src/components/code/CodeProjectPicker.tsx +39 -0
  290. package/src/interfaces/web/src/components/code/CodeSessionList.tsx +97 -0
  291. package/src/interfaces/web/src/components/code/CodeSidePanel.tsx +44 -0
  292. package/src/interfaces/web/src/components/code/CodeToolTrail.tsx +29 -0
  293. package/src/interfaces/web/src/components/code/DiffView.tsx +67 -0
  294. package/src/interfaces/web/src/components/common/Qr.tsx +27 -0
  295. package/src/interfaces/web/src/components/common/TabLayout.tsx +46 -0
  296. package/src/interfaces/web/src/components/common/TabNav.tsx +113 -0
  297. package/src/interfaces/web/src/components/config/ConfigTabsEditor.tsx +202 -0
  298. package/src/interfaces/web/src/components/config/GlobalConfigEditor.tsx +42 -0
  299. package/src/interfaces/web/src/components/config/global-config-sections.ts +60 -0
  300. package/src/interfaces/web/src/components/config/project-config-sections.ts +58 -0
  301. package/src/interfaces/web/src/components/deck/DaemonCard.tsx +58 -0
  302. package/src/interfaces/web/src/components/deck/DesktopGroup.tsx +33 -0
  303. package/src/interfaces/web/src/components/deck/WidgetRow.tsx +100 -0
  304. package/src/interfaces/web/src/components/layout/Logo.tsx +59 -0
  305. package/src/interfaces/web/src/components/layout/ProjectAvatar.tsx +116 -0
  306. package/src/interfaces/web/src/components/layout/ProjectSidebar.tsx +151 -0
  307. package/src/interfaces/web/src/components/settings/AdvancedPanel.tsx +45 -0
  308. package/src/interfaces/web/src/components/settings/AppearancePanel.tsx +72 -0
  309. package/src/interfaces/web/src/components/settings/DefaultRouterCard.tsx +232 -0
  310. package/src/interfaces/web/src/components/settings/DevicesPanel.tsx +60 -0
  311. package/src/interfaces/web/src/components/settings/EnginesPanel.tsx +127 -0
  312. package/src/interfaces/web/src/components/settings/IdentityPanel.tsx +69 -0
  313. package/src/interfaces/web/src/components/settings/MemoryPanel.tsx +226 -0
  314. package/src/interfaces/web/src/components/settings/PairDeviceDialog.tsx +175 -0
  315. package/src/interfaces/web/src/components/settings/SuperAgentPanel.tsx +93 -0
  316. package/src/interfaces/web/src/components/settings/TelegramChannelsPanel.tsx +90 -0
  317. package/src/interfaces/web/src/components/settings/TelegramContactsPanel.tsx +101 -0
  318. package/src/interfaces/web/src/components/settings/TelegramGlobalPanel.tsx +100 -0
  319. package/src/interfaces/web/src/components/settings/TelegramRolesPanel.tsx +108 -0
  320. package/src/interfaces/web/src/components/settings/TelegramSettingsTabs.tsx +55 -0
  321. package/src/interfaces/web/src/components/settings/providers/ProviderCard.tsx +95 -0
  322. package/src/interfaces/web/src/components/settings/providers/ProviderModal.tsx +405 -0
  323. package/src/interfaces/web/src/components/settings/providers/typeStyles.ts +155 -0
  324. package/src/interfaces/web/src/components/settings/providers/types.ts +26 -0
  325. package/src/interfaces/web/src/components/ui/accordion.tsx +72 -0
  326. package/src/interfaces/web/src/components/ui/alert-dialog.tsx +187 -0
  327. package/src/interfaces/web/src/components/ui/alert.tsx +76 -0
  328. package/src/interfaces/web/src/components/ui/aspect-ratio.tsx +22 -0
  329. package/src/interfaces/web/src/components/ui/avatar.tsx +107 -0
  330. package/src/interfaces/web/src/components/ui/badge.tsx +52 -0
  331. package/src/interfaces/web/src/components/ui/breadcrumb.tsx +125 -0
  332. package/src/interfaces/web/src/components/ui/button-group.tsx +87 -0
  333. package/src/interfaces/web/src/components/ui/button.tsx +58 -0
  334. package/src/interfaces/web/src/components/ui/calendar.tsx +221 -0
  335. package/src/interfaces/web/src/components/ui/card.tsx +103 -0
  336. package/src/interfaces/web/src/components/ui/carousel.tsx +242 -0
  337. package/src/interfaces/web/src/components/ui/chart.tsx +371 -0
  338. package/src/interfaces/web/src/components/ui/chat-input.tsx +122 -0
  339. package/src/interfaces/web/src/components/ui/checkbox.tsx +29 -0
  340. package/src/interfaces/web/src/components/ui/collapsible.tsx +19 -0
  341. package/src/interfaces/web/src/components/ui/combobox.tsx +295 -0
  342. package/src/interfaces/web/src/components/ui/command.tsx +196 -0
  343. package/src/interfaces/web/src/components/ui/context-menu.tsx +271 -0
  344. package/src/interfaces/web/src/components/ui/dialog.tsx +158 -0
  345. package/src/interfaces/web/src/components/ui/direction.tsx +4 -0
  346. package/src/interfaces/web/src/components/ui/drawer.tsx +134 -0
  347. package/src/interfaces/web/src/components/ui/dropdown-menu.tsx +266 -0
  348. package/src/interfaces/web/src/components/ui/empty.tsx +104 -0
  349. package/src/interfaces/web/src/components/ui/field.tsx +236 -0
  350. package/src/interfaces/web/src/components/ui/hover-card.tsx +51 -0
  351. package/src/interfaces/web/src/components/ui/input-group.tsx +158 -0
  352. package/src/interfaces/web/src/components/ui/input-otp.tsx +85 -0
  353. package/src/interfaces/web/src/components/ui/input.tsx +20 -0
  354. package/src/interfaces/web/src/components/ui/item.tsx +201 -0
  355. package/src/interfaces/web/src/components/ui/kbd.tsx +26 -0
  356. package/src/interfaces/web/src/components/ui/label.tsx +20 -0
  357. package/src/interfaces/web/src/components/ui/menubar.tsx +280 -0
  358. package/src/interfaces/web/src/components/ui/native-select.tsx +61 -0
  359. package/src/interfaces/web/src/components/ui/navigation-menu.tsx +168 -0
  360. package/src/interfaces/web/src/components/ui/pagination.tsx +130 -0
  361. package/src/interfaces/web/src/components/ui/popover.tsx +88 -0
  362. package/src/interfaces/web/src/components/ui/progress.tsx +83 -0
  363. package/src/interfaces/web/src/components/ui/radio-group.tsx +36 -0
  364. package/src/interfaces/web/src/components/ui/resizable.tsx +50 -0
  365. package/src/interfaces/web/src/components/ui/scroll-area.tsx +53 -0
  366. package/src/interfaces/web/src/components/ui/select.tsx +201 -0
  367. package/src/interfaces/web/src/components/ui/separator.tsx +23 -0
  368. package/src/interfaces/web/src/components/ui/sheet.tsx +138 -0
  369. package/src/interfaces/web/src/components/ui/sidebar.tsx +723 -0
  370. package/src/interfaces/web/src/components/ui/skeleton.tsx +13 -0
  371. package/src/interfaces/web/src/components/ui/slider.tsx +52 -0
  372. package/src/interfaces/web/src/components/ui/sonner.tsx +49 -0
  373. package/src/interfaces/web/src/components/ui/spinner.tsx +10 -0
  374. package/src/interfaces/web/src/components/ui/switch.tsx +30 -0
  375. package/src/interfaces/web/src/components/ui/table.tsx +116 -0
  376. package/src/interfaces/web/src/components/ui/tabs.tsx +72 -0
  377. package/src/interfaces/web/src/components/ui/textarea.tsx +18 -0
  378. package/src/interfaces/web/src/components/ui/tip.tsx +21 -0
  379. package/src/interfaces/web/src/components/ui/toggle-group.tsx +87 -0
  380. package/src/interfaces/web/src/components/ui/toggle.tsx +45 -0
  381. package/src/interfaces/web/src/components/ui/tooltip.tsx +64 -0
  382. package/src/interfaces/web/src/components/ui.tsx +211 -0
  383. package/src/interfaces/web/src/components/voice/VoiceProviderList.tsx +197 -0
  384. package/src/interfaces/web/src/components/voice/VoiceProviderModal.tsx +213 -0
  385. package/src/interfaces/web/src/components/voice/VoiceSttCard.tsx +72 -0
  386. package/src/interfaces/web/src/components/voice/VoiceTestCard.tsx +112 -0
  387. package/src/interfaces/web/src/components/voice/useTtsPlayer.ts +59 -0
  388. package/src/interfaces/web/src/constants/index.ts +91 -0
  389. package/src/interfaces/web/src/hooks/use-mobile.ts +19 -0
  390. package/src/interfaces/web/src/hooks/useChat.ts +276 -0
  391. package/src/interfaces/web/src/hooks/useDaemonStatus.ts +12 -0
  392. package/src/interfaces/web/src/hooks/useDevices.ts +12 -0
  393. package/src/interfaces/web/src/hooks/useEngines.ts +10 -0
  394. package/src/interfaces/web/src/hooks/useGlobalConfig.ts +24 -0
  395. package/src/interfaces/web/src/hooks/useIdentity.ts +16 -0
  396. package/src/interfaces/web/src/hooks/useProjects.ts +27 -0
  397. package/src/interfaces/web/src/hooks/useTelegram.ts +35 -0
  398. package/src/interfaces/web/src/hooks/useTheme.tsx +57 -0
  399. package/src/interfaces/web/src/hooks/useTokenBootstrap.ts +122 -0
  400. package/src/interfaces/web/src/i18n/en.ts +767 -0
  401. package/src/interfaces/web/src/i18n/es.ts +770 -0
  402. package/src/interfaces/web/src/i18n/index.ts +86 -0
  403. package/src/interfaces/web/src/lib/api/admin.ts +30 -0
  404. package/src/interfaces/web/src/lib/api/agents.ts +46 -0
  405. package/src/interfaces/web/src/lib/api/code.ts +122 -0
  406. package/src/interfaces/web/src/lib/api/conversations.ts +16 -0
  407. package/src/interfaces/web/src/lib/api/deck.ts +106 -0
  408. package/src/interfaces/web/src/lib/api/desktop.ts +54 -0
  409. package/src/interfaces/web/src/lib/api/embeddings.ts +44 -0
  410. package/src/interfaces/web/src/lib/api/engines.ts +17 -0
  411. package/src/interfaces/web/src/lib/api/filesystem.ts +12 -0
  412. package/src/interfaces/web/src/lib/api/health.ts +6 -0
  413. package/src/interfaces/web/src/lib/api/identity.ts +7 -0
  414. package/src/interfaces/web/src/lib/api/mcps.ts +29 -0
  415. package/src/interfaces/web/src/lib/api/messages.ts +24 -0
  416. package/src/interfaces/web/src/lib/api/projects.ts +29 -0
  417. package/src/interfaces/web/src/lib/api/routines.ts +14 -0
  418. package/src/interfaces/web/src/lib/api/sessions.ts +16 -0
  419. package/src/interfaces/web/src/lib/api/super_agent.ts +29 -0
  420. package/src/interfaces/web/src/lib/api/tasks.ts +19 -0
  421. package/src/interfaces/web/src/lib/api/telegram.ts +57 -0
  422. package/src/interfaces/web/src/lib/api/tools.ts +13 -0
  423. package/src/interfaces/web/src/lib/api/voice.ts +169 -0
  424. package/src/interfaces/web/src/lib/api.ts +48 -0
  425. package/src/interfaces/web/src/lib/cn.ts +6 -0
  426. package/src/interfaces/web/src/lib/code-context.ts +83 -0
  427. package/src/interfaces/web/src/lib/config-values.ts +29 -0
  428. package/src/interfaces/web/src/lib/device.ts +10 -0
  429. package/src/interfaces/web/src/lib/http.ts +104 -0
  430. package/src/interfaces/web/src/lib/secrets.ts +15 -0
  431. package/src/interfaces/web/src/lib/utils.ts +6 -0
  432. package/src/interfaces/web/src/main.tsx +16 -0
  433. package/src/interfaces/web/src/screens/ApxAdminScreen.tsx +174 -0
  434. package/src/interfaces/web/src/screens/PairingScreen.tsx +105 -0
  435. package/src/interfaces/web/src/screens/ProjectScreen.tsx +178 -0
  436. package/src/interfaces/web/src/screens/SettingsScreen.tsx +111 -0
  437. package/src/interfaces/web/src/screens/base/AgentDefaultsTab.tsx +274 -0
  438. package/src/interfaces/web/src/screens/base/ComingSoon.tsx +16 -0
  439. package/src/interfaces/web/src/screens/base/GlobalTasksTab.tsx +53 -0
  440. package/src/interfaces/web/src/screens/base/LogsTab.tsx +188 -0
  441. package/src/interfaces/web/src/screens/base/ModelsTab.tsx +13 -0
  442. package/src/interfaces/web/src/screens/base/SessionsTab.tsx +58 -0
  443. package/src/interfaces/web/src/screens/base/WorkspacesTab.tsx +49 -0
  444. package/src/interfaces/web/src/screens/modules/CodeScreen.tsx +295 -0
  445. package/src/interfaces/web/src/screens/modules/DeckScreen.tsx +173 -0
  446. package/src/interfaces/web/src/screens/modules/DesktopScreen.tsx +304 -0
  447. package/src/interfaces/web/src/screens/modules/VoiceScreen.tsx +174 -0
  448. package/src/interfaces/web/src/screens/project/AgentBrainGraph.tsx +152 -0
  449. package/src/interfaces/web/src/screens/project/AgentDetailScreen.tsx +455 -0
  450. package/src/interfaces/web/src/screens/project/AgentsTab.tsx +364 -0
  451. package/src/interfaces/web/src/screens/project/ChatTab.tsx +198 -0
  452. package/src/interfaces/web/src/screens/project/ConfigTab.tsx +94 -0
  453. package/src/interfaces/web/src/screens/project/McpsTab.tsx +149 -0
  454. package/src/interfaces/web/src/screens/project/MemoriesTab.tsx +134 -0
  455. package/src/interfaces/web/src/screens/project/Overview.tsx +37 -0
  456. package/src/interfaces/web/src/screens/project/RoutinesTab.tsx +386 -0
  457. package/src/interfaces/web/src/screens/project/TasksTab.tsx +116 -0
  458. package/src/interfaces/web/src/screens/project/TelegramTab.tsx +126 -0
  459. package/src/interfaces/web/src/screens/project/ThreadsTab.tsx +100 -0
  460. package/src/interfaces/web/src/styles.css +128 -0
  461. package/src/interfaces/web/src/types/daemon.ts +289 -0
  462. package/src/interfaces/web/tailwind.config.js +53 -0
  463. package/src/interfaces/web/tsconfig.json +24 -0
  464. package/src/interfaces/web/vite.config.ts +50 -0
  465. package/src/cli/commands/exec.js +0 -56
  466. package/src/cli/commands/overlay.js +0 -253
  467. package/src/cli/commands/session.js +0 -395
  468. package/src/cli/commands/sessions.js +0 -517
  469. package/src/cli/commands/telegram.js +0 -77
  470. package/src/cli/postinstall.js +0 -75
  471. package/src/cli-ts/commands/agent.ts +0 -173
  472. package/src/cli-ts/commands/chat.ts +0 -119
  473. package/src/cli-ts/commands/daemon.ts +0 -112
  474. package/src/cli-ts/commands/exec.ts +0 -109
  475. package/src/cli-ts/commands/mcp.ts +0 -235
  476. package/src/cli-ts/commands/session.ts +0 -224
  477. package/src/cli-ts/commands/status.ts +0 -61
  478. package/src/cli-ts/http.ts +0 -36
  479. package/src/cli-ts/index.ts +0 -73
  480. package/src/cli-ts/ui.ts +0 -107
  481. package/src/daemon/api.js +0 -1558
  482. package/src/daemon/engines/gemini.js +0 -56
  483. package/src/daemon/engines/openai.js +0 -79
  484. package/src/daemon/mcp-sources.js +0 -114
  485. package/src/daemon/super-agent-tools/index.js +0 -84
  486. package/src/daemon/super-agent-tools.js +0 -1
  487. package/src/daemon/super-agent.js +0 -541
  488. package/src/overlay/index.html +0 -44
  489. package/src/overlay/main.js +0 -480
  490. package/src/overlay/preload.js +0 -34
  491. package/src/overlay/renderer.js +0 -371
  492. package/src/overlay/style.css +0 -250
  493. package/src/tui/context/sync-apx.tsx +0 -284
  494. package/src/tui/routes/session/index.tsx +0 -274
  495. package/src/tui/routes/session/sidebar-apx.tsx +0 -90
  496. /package/src/{daemon → core}/tools/browser.js +0 -0
  497. /package/src/{daemon → core}/tools/fetch.js +0 -0
  498. /package/src/{daemon → core}/tools/glob.js +0 -0
  499. /package/src/{daemon → core}/tools/grep.js +0 -0
  500. /package/src/{daemon → core}/tools/registry.js +0 -0
  501. /package/src/{daemon → core}/tools/search.js +0 -0
  502. /package/src/{daemon → host/daemon}/conversations.js +0 -0
  503. /package/src/{daemon → host/daemon}/env-detect.js +0 -0
  504. /package/src/{daemon → host/daemon}/runtimes/_spawn.js +0 -0
  505. /package/src/{daemon → host/daemon}/runtimes/aider.js +0 -0
  506. /package/src/{daemon → host/daemon}/runtimes/claude-code.js +0 -0
  507. /package/src/{daemon → host/daemon}/runtimes/codex.js +0 -0
  508. /package/src/{daemon → host/daemon}/runtimes/cursor-agent.js +0 -0
  509. /package/src/{daemon → host/daemon}/runtimes/gemini-cli.js +0 -0
  510. /package/src/{daemon → host/daemon}/runtimes/index.js +0 -0
  511. /package/src/{daemon → host/daemon}/runtimes/opencode.js +0 -0
  512. /package/src/{daemon → host/daemon}/runtimes/qwen-code.js +0 -0
  513. /package/src/{daemon → host/daemon}/super-agent-tools/tools/call-mcp.js +0 -0
  514. /package/src/{daemon → host/daemon}/super-agent-tools/tools/edit-file.js +0 -0
  515. /package/src/{daemon → host/daemon}/super-agent-tools/tools/list-files.js +0 -0
  516. /package/src/{daemon → host/daemon}/super-agent-tools/tools/list-mcps.js +0 -0
  517. /package/src/{daemon → host/daemon}/super-agent-tools/tools/list-projects.js +0 -0
  518. /package/src/{daemon → host/daemon}/super-agent-tools/tools/list-skills.js +0 -0
  519. /package/src/{daemon → host/daemon}/super-agent-tools/tools/load-skill.js +0 -0
  520. /package/src/{daemon → host/daemon}/super-agent-tools/tools/read-agent-memory.js +0 -0
  521. /package/src/{daemon → host/daemon}/super-agent-tools/tools/read-file.js +0 -0
  522. /package/src/{daemon → host/daemon}/super-agent-tools/tools/run-shell.js +0 -0
  523. /package/src/{daemon → host/daemon}/super-agent-tools/tools/search-files.js +0 -0
  524. /package/src/{daemon → host/daemon}/super-agent-tools/tools/transcribe-audio.js +0 -0
  525. /package/src/{daemon → host/daemon}/super-agent-tools/tools/write-file.js +0 -0
  526. /package/src/{daemon → host/daemon}/thinking.js +0 -0
  527. /package/src/{daemon → host/daemon}/whisper-server.py +0 -0
  528. /package/src/{daemon → host/daemon}/whisper-transcribe.py +0 -0
  529. /package/src/{cli → interfaces/cli}/commands/a2a.js +0 -0
  530. /package/src/{cli → interfaces/cli}/commands/artifact.js +0 -0
  531. /package/src/{cli → interfaces/cli}/commands/chat.js +0 -0
  532. /package/src/{cli → interfaces/cli}/commands/log.js +0 -0
  533. /package/src/{cli → interfaces/cli}/commands/messages.js +0 -0
  534. /package/src/{cli → interfaces/cli}/commands/plugins.js +0 -0
  535. /package/src/{cli → interfaces/cli}/commands/routine.js +0 -0
  536. /package/src/{cli → interfaces/cli}/commands/runtime.js +0 -0
  537. /package/src/{cli → interfaces/cli}/terminal-chat/renderer.js +0 -0
  538. /package/src/{overlay → interfaces/desktop}/package.json +0 -0
  539. /package/src/{tui → interfaces/tui}/_shims/cli-error.ts +0 -0
  540. /package/src/{tui → interfaces/tui}/_shims/cli-logo.ts +0 -0
  541. /package/src/{tui → interfaces/tui}/_shims/cli-ui.ts +0 -0
  542. /package/src/{tui → interfaces/tui}/_shims/config-console-state.ts +0 -0
  543. /package/src/{tui → interfaces/tui}/_shims/core-any.ts +0 -0
  544. /package/src/{tui → interfaces/tui}/_shims/core-binary.ts +0 -0
  545. /package/src/{tui → interfaces/tui}/_shims/core-flag.ts +0 -0
  546. /package/src/{tui → interfaces/tui}/_shims/core-log.ts +0 -0
  547. /package/src/{tui → interfaces/tui}/_shims/lsp-language.ts +0 -0
  548. /package/src/{tui → interfaces/tui}/_shims/opencode-any.ts +0 -0
  549. /package/src/{tui → interfaces/tui}/_shims/opencode-sdk-v2.ts +0 -0
  550. /package/src/{tui → interfaces/tui}/_shims/plugin-tui.ts +0 -0
  551. /package/src/{tui → interfaces/tui}/_shims/prompt-display.ts +0 -0
  552. /package/src/{tui → interfaces/tui}/_shims/provider-provider.ts +0 -0
  553. /package/src/{tui → interfaces/tui}/_shims/session-retry.ts +0 -0
  554. /package/src/{tui → interfaces/tui}/_shims/session-schema.ts +0 -0
  555. /package/src/{tui → interfaces/tui}/_shims/session-session.ts +0 -0
  556. /package/src/{tui → interfaces/tui}/_shims/snapshot.ts +0 -0
  557. /package/src/{tui → interfaces/tui}/_shims/tool-any.ts +0 -0
  558. /package/src/{tui → interfaces/tui}/_shims/util-error.ts +0 -0
  559. /package/src/{tui → interfaces/tui}/_shims/util-filesystem.ts +0 -0
  560. /package/src/{tui → interfaces/tui}/_shims/util-format.ts +0 -0
  561. /package/src/{tui → interfaces/tui}/_shims/util-iife.ts +0 -0
  562. /package/src/{tui → interfaces/tui}/_shims/util-locale.ts +0 -0
  563. /package/src/{tui → interfaces/tui}/_shims/util-process.ts +0 -0
  564. /package/src/{tui → interfaces/tui}/asset/charge.wav +0 -0
  565. /package/src/{tui → interfaces/tui}/asset/pulse-a.wav +0 -0
  566. /package/src/{tui → interfaces/tui}/asset/pulse-b.wav +0 -0
  567. /package/src/{tui → interfaces/tui}/asset/pulse-c.wav +0 -0
  568. /package/src/{tui → interfaces/tui}/attach.ts +0 -0
  569. /package/src/{tui → interfaces/tui}/component/bg-pulse-render.ts +0 -0
  570. /package/src/{tui → interfaces/tui}/component/bg-pulse.tsx +0 -0
  571. /package/src/{tui → interfaces/tui}/component/border.tsx +0 -0
  572. /package/src/{tui → interfaces/tui}/component/dialog-agent.tsx +0 -0
  573. /package/src/{tui → interfaces/tui}/component/dialog-console-org.tsx +0 -0
  574. /package/src/{tui → interfaces/tui}/component/dialog-mcp.tsx +0 -0
  575. /package/src/{tui → interfaces/tui}/component/dialog-model.tsx +0 -0
  576. /package/src/{tui → interfaces/tui}/component/dialog-provider.tsx +0 -0
  577. /package/src/{tui → interfaces/tui}/component/dialog-retry-action.tsx +0 -0
  578. /package/src/{tui → interfaces/tui}/component/dialog-session-delete-failed.tsx +0 -0
  579. /package/src/{tui → interfaces/tui}/component/dialog-session-list.tsx +0 -0
  580. /package/src/{tui → interfaces/tui}/component/dialog-session-rename.tsx +0 -0
  581. /package/src/{tui → interfaces/tui}/component/dialog-skill.tsx +0 -0
  582. /package/src/{tui → interfaces/tui}/component/dialog-stash.tsx +0 -0
  583. /package/src/{tui → interfaces/tui}/component/dialog-status.tsx +0 -0
  584. /package/src/{tui → interfaces/tui}/component/dialog-tag.tsx +0 -0
  585. /package/src/{tui → interfaces/tui}/component/dialog-theme-list.tsx +0 -0
  586. /package/src/{tui → interfaces/tui}/component/dialog-variant.tsx +0 -0
  587. /package/src/{tui → interfaces/tui}/component/dialog-workspace-create.tsx +0 -0
  588. /package/src/{tui → interfaces/tui}/component/dialog-workspace-file-changes.tsx +0 -0
  589. /package/src/{tui → interfaces/tui}/component/dialog-workspace-unavailable.tsx +0 -0
  590. /package/src/{tui → interfaces/tui}/component/error-component.tsx +0 -0
  591. /package/src/{tui → interfaces/tui}/component/logo.tsx +0 -0
  592. /package/src/{tui → interfaces/tui}/component/plugin-route-missing.tsx +0 -0
  593. /package/src/{tui → interfaces/tui}/component/prompt/autocomplete.tsx +0 -0
  594. /package/src/{tui → interfaces/tui}/component/prompt/cwd.ts +0 -0
  595. /package/src/{tui → interfaces/tui}/component/prompt/frecency.tsx +0 -0
  596. /package/src/{tui → interfaces/tui}/component/prompt/history.tsx +0 -0
  597. /package/src/{tui → interfaces/tui}/component/prompt/part.ts +0 -0
  598. /package/src/{tui → interfaces/tui}/component/prompt/stash.tsx +0 -0
  599. /package/src/{tui → interfaces/tui}/component/prompt/traits.ts +0 -0
  600. /package/src/{tui → interfaces/tui}/component/spinner.tsx +0 -0
  601. /package/src/{tui → interfaces/tui}/component/startup-loading.tsx +0 -0
  602. /package/src/{tui → interfaces/tui}/component/todo-item.tsx +0 -0
  603. /package/src/{tui → interfaces/tui}/component/use-connected.tsx +0 -0
  604. /package/src/{tui → interfaces/tui}/component/workspace-label.tsx +0 -0
  605. /package/src/{tui → interfaces/tui}/config/cwd.ts +0 -0
  606. /package/src/{tui → interfaces/tui}/config/keybind.ts +0 -0
  607. /package/src/{tui → interfaces/tui}/config/tui-migrate.ts +0 -0
  608. /package/src/{tui → interfaces/tui}/config/tui-schema.ts +0 -0
  609. /package/src/{tui → interfaces/tui}/config/tui.ts +0 -0
  610. /package/src/{tui → interfaces/tui}/context/aggregate-failures.ts +0 -0
  611. /package/src/{tui → interfaces/tui}/context/args.tsx +0 -0
  612. /package/src/{tui → interfaces/tui}/context/command-palette.tsx +0 -0
  613. /package/src/{tui → interfaces/tui}/context/directory.ts +0 -0
  614. /package/src/{tui → interfaces/tui}/context/editor-zed.ts +0 -0
  615. /package/src/{tui → interfaces/tui}/context/editor.ts +0 -0
  616. /package/src/{tui → interfaces/tui}/context/event-apx.ts +0 -0
  617. /package/src/{tui → interfaces/tui}/context/event.ts +0 -0
  618. /package/src/{tui → interfaces/tui}/context/exit.tsx +0 -0
  619. /package/src/{tui → interfaces/tui}/context/helper.tsx +0 -0
  620. /package/src/{tui → interfaces/tui}/context/kv.tsx +0 -0
  621. /package/src/{tui → interfaces/tui}/context/local.tsx +0 -0
  622. /package/src/{tui → interfaces/tui}/context/path-format.tsx +0 -0
  623. /package/src/{tui → interfaces/tui}/context/project-apx.tsx +0 -0
  624. /package/src/{tui → interfaces/tui}/context/project.tsx +0 -0
  625. /package/src/{tui → interfaces/tui}/context/prompt.tsx +0 -0
  626. /package/src/{tui → interfaces/tui}/context/route.tsx +0 -0
  627. /package/src/{tui → interfaces/tui}/context/sdk.tsx +0 -0
  628. /package/src/{tui → interfaces/tui}/context/sync-v2.tsx +0 -0
  629. /package/src/{tui → interfaces/tui}/context/sync.tsx +0 -0
  630. /package/src/{tui → interfaces/tui}/context/theme/aura.json +0 -0
  631. /package/src/{tui → interfaces/tui}/context/theme/ayu.json +0 -0
  632. /package/src/{tui → interfaces/tui}/context/theme/carbonfox.json +0 -0
  633. /package/src/{tui → interfaces/tui}/context/theme/catppuccin-frappe.json +0 -0
  634. /package/src/{tui → interfaces/tui}/context/theme/catppuccin-macchiato.json +0 -0
  635. /package/src/{tui → interfaces/tui}/context/theme/catppuccin.json +0 -0
  636. /package/src/{tui → interfaces/tui}/context/theme/cobalt2.json +0 -0
  637. /package/src/{tui → interfaces/tui}/context/theme/cursor.json +0 -0
  638. /package/src/{tui → interfaces/tui}/context/theme/dracula.json +0 -0
  639. /package/src/{tui → interfaces/tui}/context/theme/everforest.json +0 -0
  640. /package/src/{tui → interfaces/tui}/context/theme/flexoki.json +0 -0
  641. /package/src/{tui → interfaces/tui}/context/theme/github.json +0 -0
  642. /package/src/{tui → interfaces/tui}/context/theme/gruvbox.json +0 -0
  643. /package/src/{tui → interfaces/tui}/context/theme/kanagawa.json +0 -0
  644. /package/src/{tui → interfaces/tui}/context/theme/lucent-orng.json +0 -0
  645. /package/src/{tui → interfaces/tui}/context/theme/material.json +0 -0
  646. /package/src/{tui → interfaces/tui}/context/theme/matrix.json +0 -0
  647. /package/src/{tui → interfaces/tui}/context/theme/mercury.json +0 -0
  648. /package/src/{tui → interfaces/tui}/context/theme/monokai.json +0 -0
  649. /package/src/{tui → interfaces/tui}/context/theme/nightowl.json +0 -0
  650. /package/src/{tui → interfaces/tui}/context/theme/nord.json +0 -0
  651. /package/src/{tui → interfaces/tui}/context/theme/one-dark.json +0 -0
  652. /package/src/{tui → interfaces/tui}/context/theme/opencode.json +0 -0
  653. /package/src/{tui → interfaces/tui}/context/theme/orng.json +0 -0
  654. /package/src/{tui → interfaces/tui}/context/theme/osaka-jade.json +0 -0
  655. /package/src/{tui → interfaces/tui}/context/theme/palenight.json +0 -0
  656. /package/src/{tui → interfaces/tui}/context/theme/rosepine.json +0 -0
  657. /package/src/{tui → interfaces/tui}/context/theme/solarized.json +0 -0
  658. /package/src/{tui → interfaces/tui}/context/theme/synthwave84.json +0 -0
  659. /package/src/{tui → interfaces/tui}/context/theme/tokyonight.json +0 -0
  660. /package/src/{tui → interfaces/tui}/context/theme/vercel.json +0 -0
  661. /package/src/{tui → interfaces/tui}/context/theme/vesper.json +0 -0
  662. /package/src/{tui → interfaces/tui}/context/theme/zenburn.json +0 -0
  663. /package/src/{tui → interfaces/tui}/context/theme.tsx +0 -0
  664. /package/src/{tui → interfaces/tui}/context/tui-config.tsx +0 -0
  665. /package/src/{tui → interfaces/tui}/event.ts +0 -0
  666. /package/src/{tui → interfaces/tui}/feature-plugins/home/footer.tsx +0 -0
  667. /package/src/{tui → interfaces/tui}/feature-plugins/home/tips-view.tsx +0 -0
  668. /package/src/{tui → interfaces/tui}/feature-plugins/home/tips.tsx +0 -0
  669. /package/src/{tui → interfaces/tui}/feature-plugins/sidebar/context.tsx +0 -0
  670. /package/src/{tui → interfaces/tui}/feature-plugins/sidebar/files.tsx +0 -0
  671. /package/src/{tui → interfaces/tui}/feature-plugins/sidebar/footer.tsx +0 -0
  672. /package/src/{tui → interfaces/tui}/feature-plugins/sidebar/lsp.tsx +0 -0
  673. /package/src/{tui → interfaces/tui}/feature-plugins/sidebar/mcp.tsx +0 -0
  674. /package/src/{tui → interfaces/tui}/feature-plugins/sidebar/todo.tsx +0 -0
  675. /package/src/{tui → interfaces/tui}/feature-plugins/system/plugins.tsx +0 -0
  676. /package/src/{tui → interfaces/tui}/feature-plugins/system/session-v2.tsx +0 -0
  677. /package/src/{tui → interfaces/tui}/feature-plugins/system/which-key.tsx +0 -0
  678. /package/src/{tui → interfaces/tui}/keymap.tsx +0 -0
  679. /package/src/{tui → interfaces/tui}/layer.ts +0 -0
  680. /package/src/{tui → interfaces/tui}/plugin/api.tsx +0 -0
  681. /package/src/{tui → interfaces/tui}/plugin/command-shim.ts +0 -0
  682. /package/src/{tui → interfaces/tui}/plugin/internal.ts +0 -0
  683. /package/src/{tui → interfaces/tui}/plugin/runtime.ts +0 -0
  684. /package/src/{tui → interfaces/tui}/plugin/slots.tsx +0 -0
  685. /package/src/{tui → interfaces/tui}/routes/home.tsx +0 -0
  686. /package/src/{tui → interfaces/tui}/routes/session/dialog-fork-from-timeline.tsx +0 -0
  687. /package/src/{tui → interfaces/tui}/routes/session/dialog-message.tsx +0 -0
  688. /package/src/{tui → interfaces/tui}/routes/session/dialog-subagent.tsx +0 -0
  689. /package/src/{tui → interfaces/tui}/routes/session/dialog-timeline.tsx +0 -0
  690. /package/src/{tui → interfaces/tui}/routes/session/footer.tsx +0 -0
  691. /package/src/{tui → interfaces/tui}/routes/session/permission.tsx +0 -0
  692. /package/src/{tui → interfaces/tui}/routes/session/question.tsx +0 -0
  693. /package/src/{tui → interfaces/tui}/routes/session/sidebar.tsx +0 -0
  694. /package/src/{tui → interfaces/tui}/routes/session/subagent-footer.tsx +0 -0
  695. /package/src/{tui → interfaces/tui}/run.ts +0 -0
  696. /package/src/{tui → interfaces/tui}/thread.ts +0 -0
  697. /package/src/{tui → interfaces/tui}/ui/dialog-alert.tsx +0 -0
  698. /package/src/{tui → interfaces/tui}/ui/dialog-confirm.tsx +0 -0
  699. /package/src/{tui → interfaces/tui}/ui/dialog-export-options.tsx +0 -0
  700. /package/src/{tui → interfaces/tui}/ui/dialog-help.tsx +0 -0
  701. /package/src/{tui → interfaces/tui}/ui/dialog-prompt.tsx +0 -0
  702. /package/src/{tui → interfaces/tui}/ui/dialog-select.tsx +0 -0
  703. /package/src/{tui → interfaces/tui}/ui/dialog.tsx +0 -0
  704. /package/src/{tui → interfaces/tui}/ui/link.tsx +0 -0
  705. /package/src/{tui → interfaces/tui}/ui/spinner.ts +0 -0
  706. /package/src/{tui → interfaces/tui}/ui/toast.tsx +0 -0
  707. /package/src/{tui → interfaces/tui}/util/editor.ts +0 -0
  708. /package/src/{tui → interfaces/tui}/util/model.ts +0 -0
  709. /package/src/{tui → interfaces/tui}/util/provider-origin.ts +0 -0
  710. /package/src/{tui → interfaces/tui}/util/revert-diff.ts +0 -0
  711. /package/src/{tui → interfaces/tui}/util/scroll.ts +0 -0
  712. /package/src/{tui → interfaces/tui}/util/selection.ts +0 -0
  713. /package/src/{tui → interfaces/tui}/util/signal.ts +0 -0
  714. /package/src/{tui → interfaces/tui}/util/sound.ts +0 -0
  715. /package/src/{tui → interfaces/tui}/util/transcript.ts +0 -0
  716. /package/src/{tui → interfaces/tui}/validate-session.ts +0 -0
  717. /package/src/{tui → interfaces/tui}/win32.ts +0 -0
  718. /package/src/{tui → interfaces/tui}/worker.ts +0 -0
@@ -0,0 +1,126 @@
1
+ // Sender identity resolution for Telegram (and, by reuse, any future channel).
2
+ //
3
+ // The unit of identity is the PERSON, keyed by their stable platform user id
4
+ // (Telegram `msg.from.id`) — never the chat_id (breaks in groups) nor the phone
5
+ // (Telegram doesn't expose it). A person is the same across every channel/chat;
6
+ // their role lives on the global contact entry. The per-channel `owner_user_id`
7
+ // only marks who owns *that* channel and overrides the role to "owner" there.
8
+ //
9
+ // resolveSender() is pure (read-only). registerSender() has the side effect of
10
+ // recording unknown senders and claiming the first private-chat sender as the
11
+ // channel owner when none is set yet.
12
+
13
+ import {
14
+ readConfig,
15
+ findContact,
16
+ findTelegramChannel,
17
+ upsertContact,
18
+ upsertTelegramChannel,
19
+ } from "./config.js";
20
+
21
+ function telegramDisplayName(from) {
22
+ const full = [from?.first_name, from?.last_name].filter(Boolean).join(" ").trim();
23
+ return full || from?.username || "unknown";
24
+ }
25
+
26
+ /**
27
+ * Resolve who the sender is, relative to a channel. Read-only.
28
+ * @returns {{userId, username, name, role, isOwner, isGroup, known, note}}
29
+ */
30
+ export function resolveSender({ cfg, channelName, from, chatType }) {
31
+ const userId = from?.id ?? null;
32
+ const username = from?.username || "";
33
+ const channel = channelName ? findTelegramChannel(cfg, channelName) : null;
34
+ const contact = userId != null ? findContact(cfg, userId) : null;
35
+ const isGroup = chatType === "group" || chatType === "supergroup";
36
+ const isOwner =
37
+ channel?.owner_user_id != null &&
38
+ String(channel.owner_user_id) === String(userId);
39
+ const role = isOwner ? "owner" : contact?.role || "guest";
40
+ return {
41
+ userId,
42
+ username,
43
+ name: contact?.name || telegramDisplayName(from),
44
+ role,
45
+ isOwner,
46
+ isGroup,
47
+ known: !!contact || isOwner,
48
+ note: contact?.note || "",
49
+ };
50
+ }
51
+
52
+ /**
53
+ * Resolve the tool allowlist for a sender's role.
54
+ * - owner → "*" (all tools)
55
+ * - guest → [] (no tools; text only)
56
+ * - a role defined in telegram.roles → its `tools` ("*" or an array)
57
+ * - any other named role with no definition → "*" (an admin assigned it
58
+ * deliberately; default permissive rather than silently muting it)
59
+ * Returns "*" or an array of tool names.
60
+ */
61
+ export function resolveAllowedTools(cfg, sender) {
62
+ if (sender?.isOwner) return "*";
63
+ const def = cfg?.telegram?.roles?.[sender?.role];
64
+ if (def && def.tools !== undefined) return def.tools;
65
+ if (sender?.role === "guest") return [];
66
+ return "*";
67
+ }
68
+
69
+ /**
70
+ * Like resolveSender(), but records the sender if unrecognized.
71
+ * - Private chat + channel has no owner yet → claim this sender as owner.
72
+ * - Otherwise an unknown sender is recorded as a role-less guest.
73
+ * - A known sender's last_seen is refreshed at most once per day.
74
+ *
75
+ * Persistence is done against a FRESH on-disk config (so concurrent edits from
76
+ * the web/CLI aren't clobbered and the file isn't ballooned with merged
77
+ * defaults). The in-memory `cfg.telegram` subtree is then refreshed so later
78
+ * messages in this daemon session see the change without a reload.
79
+ * Returns { sender, mutated }.
80
+ */
81
+ export function registerSender({ cfg, channelName, from, chatType }) {
82
+ const userId = from?.id ?? null;
83
+
84
+ // Always refresh the in-memory telegram subtree from disk so role/owner
85
+ // edits made via CLI/web/API are honored on the very next message without a
86
+ // daemon reload. Telegram traffic is low-frequency, so a config read per
87
+ // inbound message is cheap. The helpers below mutate `disk` in place and
88
+ // persist; since cfg.telegram now references it, the session stays current.
89
+ const disk = readConfig();
90
+ cfg.telegram = disk.telegram;
91
+
92
+ const base = () => resolveSender({ cfg, channelName, from, chatType });
93
+ if (userId == null) return { sender: base(), mutated: false };
94
+
95
+ const channel = channelName ? findTelegramChannel(disk, channelName) : null;
96
+ const isPrivate = chatType === "private";
97
+ const existing = findContact(disk, userId);
98
+ const now = new Date().toISOString();
99
+ const username = from?.username || "";
100
+ const name = telegramDisplayName(from);
101
+
102
+ const ownerUnset =
103
+ channel && (channel.owner_user_id == null || channel.owner_user_id === "");
104
+
105
+ let kind = null; // "claim" | "guest" | "touch"
106
+ if (isPrivate && ownerUnset) kind = "claim";
107
+ else if (!existing) kind = "guest";
108
+ else if (existing.last_seen?.slice(0, 10) !== now.slice(0, 10)) kind = "touch";
109
+
110
+ if (!kind) return { sender: base(), mutated: false };
111
+
112
+ if (kind === "claim") {
113
+ upsertTelegramChannel(disk, channelName, { owner_user_id: userId });
114
+ upsertContact(disk, userId, {
115
+ name, username, role: "owner", first_seen: now, last_seen: now,
116
+ });
117
+ } else if (kind === "guest") {
118
+ upsertContact(disk, userId, {
119
+ name, username, role: "guest", first_seen: now, last_seen: now,
120
+ });
121
+ } else {
122
+ upsertContact(disk, userId, { last_seen: now });
123
+ }
124
+
125
+ return { sender: base(), mutated: true };
126
+ }
@@ -0,0 +1,6 @@
1
+ export * from "./registry.js";
2
+ export { buildBrowserRouter } from "./browser.js";
3
+ export { buildFetchRouter } from "./fetch.js";
4
+ export { buildSearchRouter } from "./search.js";
5
+ export { buildGlobRouter } from "./glob.js";
6
+ export { buildGrepRouter } from "./grep.js";
@@ -0,0 +1,96 @@
1
+ // ElevenLabs TTS adapter.
2
+ // API docs: https://elevenlabs.io/docs/api-reference/text-to-speech
3
+ //
4
+ // Config (~/.apx/config.json → voice.tts.elevenlabs):
5
+ // {
6
+ // "api_key": "sk_...", // or env ELEVENLABS_API_KEY
7
+ // "model": "eleven_multilingual_v2",
8
+ // "voice_id": "EXAVITQu4vr4xnSDxMaL", // default voice (Bella)
9
+ // "output_format": "mp3_44100_128"
10
+ // }
11
+ //
12
+ // Returns audio as mp3 by default.
13
+
14
+ import fs from "node:fs";
15
+ import path from "node:path";
16
+ import { randomUUID } from "node:crypto";
17
+
18
+ const API_BASE = "https://api.elevenlabs.io/v1/text-to-speech";
19
+
20
+ // Reasonable Spanish-friendly default voice (multilingual model handles it).
21
+ const DEFAULT_VOICE_ID = "EXAVITQu4vr4xnSDxMaL";
22
+ const DEFAULT_MODEL = "eleven_multilingual_v2";
23
+ const DEFAULT_FORMAT = "mp3_44100_128";
24
+
25
+ function getKey(config) {
26
+ return config.api_key || process.env.ELEVENLABS_API_KEY || "";
27
+ }
28
+
29
+ function formatToExt(fmt) {
30
+ if (!fmt) return "mp3";
31
+ if (fmt.startsWith("mp3")) return "mp3";
32
+ if (fmt.startsWith("pcm")) return "wav";
33
+ if (fmt.startsWith("ulaw")) return "ulaw";
34
+ if (fmt.startsWith("opus") || fmt.startsWith("ogg")) return "ogg";
35
+ return "mp3";
36
+ }
37
+
38
+ function formatToMime(fmt) {
39
+ const ext = formatToExt(fmt);
40
+ return {
41
+ mp3: "audio/mpeg",
42
+ wav: "audio/wav",
43
+ ogg: "audio/ogg",
44
+ ulaw: "audio/basic",
45
+ }[ext] || "audio/mpeg";
46
+ }
47
+
48
+ export default {
49
+ id: "elevenlabs",
50
+
51
+ async isAvailable(config = {}) {
52
+ return Boolean(getKey(config));
53
+ },
54
+
55
+ async synthesize({ text, voice, outDir, config = {}, signal }) {
56
+ if (!text) throw new Error("elevenlabs: empty text");
57
+ const key = getKey(config);
58
+ if (!key) throw new Error("elevenlabs: no api_key (set ELEVENLABS_API_KEY or voice.tts.elevenlabs.api_key)");
59
+
60
+ const voiceId = voice || config.voice_id || DEFAULT_VOICE_ID;
61
+ const model = config.model || DEFAULT_MODEL;
62
+ const outputFormat = config.output_format || DEFAULT_FORMAT;
63
+
64
+ const url = `${API_BASE}/${encodeURIComponent(voiceId)}?output_format=${encodeURIComponent(outputFormat)}`;
65
+ const res = await fetch(url, {
66
+ method: "POST",
67
+ headers: {
68
+ "xi-api-key": key,
69
+ "content-type": "application/json",
70
+ accept: "audio/mpeg",
71
+ },
72
+ body: JSON.stringify({
73
+ text,
74
+ model_id: model,
75
+ }),
76
+ signal,
77
+ });
78
+ if (!res.ok) {
79
+ const err = await res.text().catch(() => "");
80
+ throw new Error(`elevenlabs ${res.status}: ${err.slice(0, 300)}`);
81
+ }
82
+ const buf = Buffer.from(await res.arrayBuffer());
83
+
84
+ fs.mkdirSync(outDir, { recursive: true });
85
+ const ext = formatToExt(outputFormat);
86
+ const audioPath = path.join(outDir, `elevenlabs-${randomUUID()}.${ext}`);
87
+ fs.writeFileSync(audioPath, buf);
88
+
89
+ return {
90
+ audio_path: audioPath,
91
+ duration_s: null, // ElevenLabs doesn't return duration in this endpoint
92
+ mime: formatToMime(outputFormat),
93
+ provider: "elevenlabs",
94
+ };
95
+ },
96
+ };
@@ -0,0 +1,148 @@
1
+ // Gemini TTS adapter.
2
+ // At the time of writing the Gemini TTS surface is gated and not stable across
3
+ // SDK versions: some models (gemini-2.5-flash-preview-tts) expose synthesize
4
+ // via the v1beta REST surface, others require Vertex. To keep APX engine-
5
+ // agnostic, this adapter performs a best-effort call against the documented
6
+ // REST shape, but flags itself as not-implemented when the response does not
7
+ // include inline audio data.
8
+ //
9
+ // Config (~/.apx/config.json → voice.tts.gemini):
10
+ // { "api_key": "...", "model": "gemini-2.5-flash-preview-tts", "voice": "Kore",
11
+ // "style": "habla en tono alegre y enérgico" }
12
+ //
13
+ // `style` is an optional natural-language instruction describing HOW the voice
14
+ // should speak. Gemini single-speaker TTS controls delivery by prefixing the
15
+ // text with such an instruction, so we prepend "<style>: <text>" before
16
+ // synthesizing. A per-call `style` arg overrides the saved config.style.
17
+ //
18
+ // If you need a guaranteed-working Gemini TTS path today, prefer ElevenLabs or
19
+ // OpenAI engines and revisit this once Google stabilises the API.
20
+
21
+ import fs from "node:fs";
22
+ import path from "node:path";
23
+ import { randomUUID } from "node:crypto";
24
+
25
+ const DEFAULT_MODEL = "gemini-2.5-flash-preview-tts";
26
+
27
+ function getKey(config, parentEnginesCfg) {
28
+ return (
29
+ config.api_key ||
30
+ parentEnginesCfg?.gemini?.api_key ||
31
+ process.env.GEMINI_API_KEY ||
32
+ ""
33
+ );
34
+ }
35
+
36
+ export default {
37
+ id: "gemini",
38
+
39
+ async isAvailable(config = {}, parentEnginesCfg) {
40
+ // Marked "available" if a key exists — but synthesize() may still throw
41
+ // not-implemented if the SDK surface changes. Selector will fall back.
42
+ return Boolean(getKey(config, parentEnginesCfg));
43
+ },
44
+
45
+ async synthesize({ text, voice, style, outDir, config = {}, signal, parentEnginesCfg }) {
46
+ if (!text) throw new Error("gemini-tts: empty text");
47
+ const key = getKey(config, parentEnginesCfg);
48
+ if (!key) throw new Error("gemini-tts: no api_key (set GEMINI_API_KEY or engines.gemini.api_key)");
49
+
50
+ const model = config.model || DEFAULT_MODEL;
51
+ const voiceName = voice || config.voice || "Kore";
52
+
53
+ // Speaking-style instruction: per-call `style` wins over saved config.style.
54
+ const styleHint = (style ?? config.style ?? "").trim();
55
+ const promptText = styleHint ? `${styleHint}: ${text}` : text;
56
+
57
+ const url = `https://generativelanguage.googleapis.com/v1beta/models/${encodeURIComponent(model)}:generateContent?key=${encodeURIComponent(key)}`;
58
+ const body = {
59
+ contents: [{ parts: [{ text: promptText }] }],
60
+ generationConfig: {
61
+ responseModalities: ["AUDIO"],
62
+ speechConfig: {
63
+ voiceConfig: {
64
+ prebuiltVoiceConfig: { voiceName },
65
+ },
66
+ },
67
+ },
68
+ };
69
+
70
+ const res = await fetch(url, {
71
+ method: "POST",
72
+ headers: { "content-type": "application/json" },
73
+ body: JSON.stringify(body),
74
+ signal,
75
+ });
76
+ if (!res.ok) {
77
+ const err = await res.text().catch(() => "");
78
+ throw new Error(`gemini-tts: not implemented for this account/model (status ${res.status}). Details: ${err.slice(0, 200)}`);
79
+ }
80
+ const json = await res.json().catch(() => ({}));
81
+ // The REST surface returns inlineData.data (base64) + mimeType.
82
+ const parts = json?.candidates?.[0]?.content?.parts || [];
83
+ const audioPart = parts.find((p) => p.inlineData?.data || p.inline_data?.data);
84
+ const inline = audioPart?.inlineData || audioPart?.inline_data;
85
+ if (!inline?.data) {
86
+ throw new Error("gemini-tts: not implemented (response did not include inline audio data)");
87
+ }
88
+ const mime = inline.mimeType || inline.mime_type || "audio/wav";
89
+ const rawBuf = Buffer.from(inline.data, "base64");
90
+
91
+ // Gemini commonly returns mime like "audio/L16;codec=pcm;rate=24000" —
92
+ // raw signed 16-bit little-endian PCM with no RIFF header. macOS afplay
93
+ // and most other players won't decode it. Wrap it in a WAV container if
94
+ // the mime signals PCM; pass through anything that's already a container.
95
+ const isRawPcm = /audio\/L16|audio\/pcm|codec=pcm/i.test(mime);
96
+ const isOgg = /audio\/ogg/i.test(mime);
97
+ const isMpeg = /audio\/mpeg/i.test(mime);
98
+
99
+ let buf = rawBuf;
100
+ let ext = "wav";
101
+ let outMime = mime;
102
+ if (isMpeg) { ext = "mp3"; outMime = "audio/mpeg"; }
103
+ else if (isOgg) { ext = "ogg"; outMime = "audio/ogg"; }
104
+ else if (isRawPcm || !/audio\/wav|audio\/x-wav/i.test(mime)) {
105
+ // Default any unknown / L16 mime to wrapped WAV.
106
+ const rateMatch = /rate=(\d+)/i.exec(mime || "");
107
+ const sampleRate = rateMatch ? parseInt(rateMatch[1], 10) : 24000;
108
+ buf = wrapPcmAsWav(rawBuf, { sampleRate, channels: 1, bitsPerSample: 16 });
109
+ ext = "wav";
110
+ outMime = "audio/wav";
111
+ }
112
+
113
+ fs.mkdirSync(outDir, { recursive: true });
114
+ const audioPath = path.join(outDir, `gemini-${randomUUID()}.${ext}`);
115
+ fs.writeFileSync(audioPath, buf);
116
+
117
+ return {
118
+ audio_path: audioPath,
119
+ duration_s: null,
120
+ mime: outMime,
121
+ provider: "gemini",
122
+ };
123
+ },
124
+ };
125
+
126
+ // Build a minimal 44-byte RIFF/WAVE header for signed PCM and prepend it to
127
+ // `pcm`. Used when an engine (today: Gemini) returns raw L16 PCM bytes that
128
+ // players can't decode without a container.
129
+ function wrapPcmAsWav(pcm, { sampleRate = 24000, channels = 1, bitsPerSample = 16 } = {}) {
130
+ const byteRate = sampleRate * channels * (bitsPerSample / 8);
131
+ const blockAlign = channels * (bitsPerSample / 8);
132
+ const dataSize = pcm.length;
133
+ const header = Buffer.alloc(44);
134
+ header.write("RIFF", 0, "ascii");
135
+ header.writeUInt32LE(36 + dataSize, 4);
136
+ header.write("WAVE", 8, "ascii");
137
+ header.write("fmt ", 12, "ascii");
138
+ header.writeUInt32LE(16, 16); // PCM fmt chunk size
139
+ header.writeUInt16LE(1, 20); // audio format = PCM
140
+ header.writeUInt16LE(channels, 22);
141
+ header.writeUInt32LE(sampleRate, 24);
142
+ header.writeUInt32LE(byteRate, 28);
143
+ header.writeUInt16LE(blockAlign, 32);
144
+ header.writeUInt16LE(bitsPerSample, 34);
145
+ header.write("data", 36, "ascii");
146
+ header.writeUInt32LE(dataSize, 40);
147
+ return Buffer.concat([header, pcm]);
148
+ }
@@ -0,0 +1,144 @@
1
+ // TTS engine registry. Mirrors the LLM engine selector at src/core/engines/.
2
+ //
3
+ // Two selection modes (config.voice.tts.mode):
4
+ // "chain" — ordered fallback router. Walk the engine order (config.voice.tts
5
+ // .order, falling back to AUTO_PREFERENCE) skipping engines turned
6
+ // off (config.voice.tts.<id>.enabled === false) and pick the first
7
+ // one whose isAvailable() returns true. "mock" is always kept as
8
+ // the final guaranteed fallback.
9
+ // "single" — use exactly config.voice.tts.provider, no fallback. Lets you keep
10
+ // several engines configured but only ever use the chosen one by
11
+ // default (the others stay available for explicit overrides).
12
+ //
13
+ // An explicit `provider` argument to synthesize()/selectTtsEngine() always wins
14
+ // (used by the "Probar voz" tester to force a specific engine).
15
+ //
16
+ // Backward compat: when `mode` is absent it's derived from `provider`
17
+ // (provider set & not "auto" → single; otherwise chain), so existing configs
18
+ // keep working unchanged.
19
+
20
+ import piper from "./piper.js";
21
+ import elevenlabs from "./elevenlabs.js";
22
+ import openai from "./openai.js";
23
+ import gemini from "./gemini.js";
24
+ import mock from "./mock.js";
25
+
26
+ const ADAPTERS = { piper, elevenlabs, openai, gemini, mock };
27
+ export const TTS_ENGINE_IDS = Object.keys(ADAPTERS);
28
+
29
+ export const AUTO_PREFERENCE = ["piper", "elevenlabs", "openai", "gemini", "mock"];
30
+
31
+ export function getTtsAdapter(provider) {
32
+ const a = ADAPTERS[provider];
33
+ if (!a) {
34
+ throw new Error(
35
+ `unknown TTS provider "${provider}". Known: ${TTS_ENGINE_IDS.join(", ")}`
36
+ );
37
+ }
38
+ return a;
39
+ }
40
+
41
+ function ttsConfig(globalConfig) {
42
+ return globalConfig?.voice?.tts || {};
43
+ }
44
+
45
+ function providerConfig(globalConfig, provider) {
46
+ return ttsConfig(globalConfig)?.[provider] || {};
47
+ }
48
+
49
+ function isEnabled(ttsCfg, id) {
50
+ return ttsCfg?.[id]?.enabled !== false;
51
+ }
52
+
53
+ /** Effective routing mode for the chain/single decision. */
54
+ export function resolveMode(ttsCfg) {
55
+ if (ttsCfg?.mode === "chain" || ttsCfg?.mode === "single") return ttsCfg.mode;
56
+ const p = ttsCfg?.provider;
57
+ return p && p !== "auto" ? "single" : "chain";
58
+ }
59
+
60
+ /**
61
+ * Full engine order for chain mode: the user's custom order first (only known
62
+ * ids), then any remaining AUTO_PREFERENCE engines. Includes disabled engines
63
+ * so the UI can render + reorder every row; filtering happens at selection time.
64
+ */
65
+ export function resolveChainOrder(ttsCfg) {
66
+ const custom = Array.isArray(ttsCfg?.order)
67
+ ? ttsCfg.order.filter((id) => TTS_ENGINE_IDS.includes(id))
68
+ : [];
69
+ const rest = AUTO_PREFERENCE.filter((id) => !custom.includes(id));
70
+ const full = [...custom, ...rest];
71
+ // Guarantee mock is present as the ultimate fallback.
72
+ if (!full.includes("mock")) full.push("mock");
73
+ return full;
74
+ }
75
+
76
+ /**
77
+ * Resolve which engine should handle a synthesize() call.
78
+ * Returns { provider, adapter, engineConfig }.
79
+ */
80
+ export async function selectTtsEngine({ globalConfig, provider }) {
81
+ const ttsCfg = ttsConfig(globalConfig);
82
+
83
+ // 1. Explicit override (tester / API caller) always wins.
84
+ if (provider && provider !== "auto") {
85
+ const adapter = getTtsAdapter(provider);
86
+ return { provider, adapter, engineConfig: providerConfig(globalConfig, provider) };
87
+ }
88
+
89
+ const mode = resolveMode(ttsCfg);
90
+
91
+ // 2. Single mode: use the configured engine verbatim, no fallback.
92
+ if (mode === "single") {
93
+ const id = ttsCfg?.provider;
94
+ if (id && id !== "auto") {
95
+ const adapter = getTtsAdapter(id);
96
+ return { provider: id, adapter, engineConfig: providerConfig(globalConfig, id) };
97
+ }
98
+ // Misconfigured single mode (no concrete provider) → fall through to chain.
99
+ }
100
+
101
+ // 3. Chain mode: probe the (enabled) order, first available wins.
102
+ for (const id of resolveChainOrder(ttsCfg)) {
103
+ if (id !== "mock" && !isEnabled(ttsCfg, id)) continue;
104
+ const adapter = ADAPTERS[id];
105
+ const cfg = providerConfig(globalConfig, id);
106
+ try {
107
+ if (await adapter.isAvailable(cfg, globalConfig?.engines)) {
108
+ return { provider: id, adapter, engineConfig: cfg };
109
+ }
110
+ } catch { /* probe failures fall through */ }
111
+ }
112
+ // mock is always available, but guard anyway.
113
+ return {
114
+ provider: "mock",
115
+ adapter: mock,
116
+ engineConfig: providerConfig(globalConfig, "mock"),
117
+ };
118
+ }
119
+
120
+ /**
121
+ * Discover which engines are configured/available right now. Pure read of
122
+ * config + cheap probes; safe to call frequently.
123
+ */
124
+ export async function listAvailableTtsEngines(globalConfig) {
125
+ const ttsCfg = ttsConfig(globalConfig);
126
+ const out = [];
127
+ for (const id of TTS_ENGINE_IDS) {
128
+ const adapter = ADAPTERS[id];
129
+ const cfg = providerConfig(globalConfig, id);
130
+ let available = false;
131
+ try {
132
+ available = await adapter.isAvailable(cfg, globalConfig?.engines);
133
+ } catch { available = false; }
134
+ out.push({
135
+ id,
136
+ available,
137
+ // `enabled` is a routing flag, not real config — exclude it from the
138
+ // "configured" heuristic so toggling on/off doesn't fake-mark an engine.
139
+ configured: Object.keys(cfg).filter((k) => k !== "enabled").length > 0,
140
+ enabled: isEnabled(ttsCfg, id),
141
+ });
142
+ }
143
+ return out;
144
+ }
@@ -0,0 +1,59 @@
1
+ // Mock TTS engine. Writes a tiny placeholder WAV (silent) so callers get a real
2
+ // playable file without external dependencies. Used in tests and as a fallback
3
+ // when no real engine is configured.
4
+ //
5
+ // The "audio" produced is a minimally valid 8 kHz mono PCM-16 WAV with `n_ms`
6
+ // milliseconds of silence so duration_s is meaningful. Total size grows with
7
+ // text length so different inputs produce different files (handy in tests).
8
+
9
+ import fs from "node:fs";
10
+ import path from "node:path";
11
+ import { randomUUID } from "node:crypto";
12
+
13
+ function buildSilentWav(ms) {
14
+ const sampleRate = 8000;
15
+ const numSamples = Math.max(1, Math.floor((sampleRate * ms) / 1000));
16
+ const byteRate = sampleRate * 2; // 16-bit mono
17
+ const dataSize = numSamples * 2;
18
+ const buf = Buffer.alloc(44 + dataSize);
19
+ buf.write("RIFF", 0);
20
+ buf.writeUInt32LE(36 + dataSize, 4);
21
+ buf.write("WAVE", 8);
22
+ buf.write("fmt ", 12);
23
+ buf.writeUInt32LE(16, 16); // PCM chunk size
24
+ buf.writeUInt16LE(1, 20); // PCM format
25
+ buf.writeUInt16LE(1, 22); // mono
26
+ buf.writeUInt32LE(sampleRate, 24);
27
+ buf.writeUInt32LE(byteRate, 28);
28
+ buf.writeUInt16LE(2, 32); // block align
29
+ buf.writeUInt16LE(16, 34); // bits per sample
30
+ buf.write("data", 36);
31
+ buf.writeUInt32LE(dataSize, 40);
32
+ // samples already zero-filled by Buffer.alloc → silence
33
+ return buf;
34
+ }
35
+
36
+ export default {
37
+ id: "mock",
38
+
39
+ async isAvailable() {
40
+ return true;
41
+ },
42
+
43
+ async synthesize({ text, outDir, format = "wav" }) {
44
+ if (!text) throw new Error("mock-tts: empty text");
45
+ // Roughly 60 ms per character — gives test assertions something to check.
46
+ const durationMs = Math.max(100, Math.min(60_000, text.length * 60));
47
+ const wav = buildSilentWav(durationMs);
48
+ const filename = `mock-${randomUUID()}.${format === "wav" ? "wav" : "wav"}`;
49
+ fs.mkdirSync(outDir, { recursive: true });
50
+ const audioPath = path.join(outDir, filename);
51
+ fs.writeFileSync(audioPath, wav);
52
+ return {
53
+ audio_path: audioPath,
54
+ duration_s: durationMs / 1000,
55
+ mime: "audio/wav",
56
+ provider: "mock",
57
+ };
58
+ },
59
+ };
@@ -0,0 +1,82 @@
1
+ // OpenAI TTS adapter (tts-1 / tts-1-hd).
2
+ // Docs: https://platform.openai.com/docs/api-reference/audio/createSpeech
3
+ //
4
+ // Reuses engines.openai.api_key from ~/.apx/config.json. Per-engine voice
5
+ // config (~/.apx/config.json → voice.tts.openai) can override model/voice.
6
+
7
+ import fs from "node:fs";
8
+ import path from "node:path";
9
+ import { randomUUID } from "node:crypto";
10
+
11
+ const API_URL = "https://api.openai.com/v1/audio/speech";
12
+ const DEFAULT_MODEL = "tts-1";
13
+ const DEFAULT_VOICE = "alloy"; // alloy|echo|fable|onyx|nova|shimmer
14
+
15
+ function getKey(config, parentEnginesCfg) {
16
+ return (
17
+ config.api_key ||
18
+ parentEnginesCfg?.openai?.api_key ||
19
+ process.env.OPENAI_API_KEY ||
20
+ ""
21
+ );
22
+ }
23
+
24
+ function mimeFor(format) {
25
+ return {
26
+ mp3: "audio/mpeg",
27
+ opus: "audio/ogg",
28
+ aac: "audio/aac",
29
+ flac: "audio/flac",
30
+ wav: "audio/wav",
31
+ pcm: "audio/L16",
32
+ }[format] || "audio/mpeg";
33
+ }
34
+
35
+ export default {
36
+ id: "openai",
37
+
38
+ async isAvailable(config = {}, parentEnginesCfg) {
39
+ return Boolean(getKey(config, parentEnginesCfg));
40
+ },
41
+
42
+ async synthesize({ text, voice, outDir, config = {}, format, signal, parentEnginesCfg }) {
43
+ if (!text) throw new Error("openai-tts: empty text");
44
+ const key = getKey(config, parentEnginesCfg);
45
+ if (!key) throw new Error("openai-tts: no api_key (set OPENAI_API_KEY or engines.openai.api_key)");
46
+
47
+ const model = config.model || DEFAULT_MODEL;
48
+ const chosenVoice = voice || config.voice || DEFAULT_VOICE;
49
+ const responseFormat = format || config.format || "mp3";
50
+
51
+ const res = await fetch(API_URL, {
52
+ method: "POST",
53
+ headers: {
54
+ authorization: `Bearer ${key}`,
55
+ "content-type": "application/json",
56
+ },
57
+ body: JSON.stringify({
58
+ model,
59
+ voice: chosenVoice,
60
+ input: text,
61
+ response_format: responseFormat,
62
+ }),
63
+ signal,
64
+ });
65
+ if (!res.ok) {
66
+ const err = await res.text().catch(() => "");
67
+ throw new Error(`openai-tts ${res.status}: ${err.slice(0, 300)}`);
68
+ }
69
+ const buf = Buffer.from(await res.arrayBuffer());
70
+
71
+ fs.mkdirSync(outDir, { recursive: true });
72
+ const audioPath = path.join(outDir, `openai-${randomUUID()}.${responseFormat}`);
73
+ fs.writeFileSync(audioPath, buf);
74
+
75
+ return {
76
+ audio_path: audioPath,
77
+ duration_s: null,
78
+ mime: mimeFor(responseFormat),
79
+ provider: "openai",
80
+ };
81
+ },
82
+ };