@agentprojectcontext/apx 1.25.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,519 @@
1
+ // Daemon HTTP routes for the unified "voice" channel.
2
+ //
3
+ // POST /voice/turn { audio?: <base64 or path>, format?, text?, agent?,
4
+ // channel?, provider?, voice?, language?,
5
+ // previousMessages? }
6
+ // → { user_text, reply_text, reply_audio_path,
7
+ // reply_duration_s, reply_mime, provider,
8
+ // conversation_id? }
9
+ //
10
+ // Conceptually a single bidirectional turn:
11
+ // 1. STT on the incoming audio (or use `text` if provided directly).
12
+ // 2. Run the APX default agent (super-agent mode) — or an explicit agent
13
+ // slug — on the transcribed text.
14
+ // 3. TTS on the reply text → playable audio file.
15
+ //
16
+ // Channel/agent surfaces (Telegram plugin, overlay) can keep their own
17
+ // pipelines, but they should delegate here when they want a hablada reply.
18
+ import fs from "node:fs";
19
+ import path from "node:path";
20
+ import os from "node:os";
21
+ import { randomUUID } from "node:crypto";
22
+ import { readConfig } from "../../../core/config.js";
23
+ import { synthesize } from "../../../core/voice/tts.js";
24
+ import { transcribe } from "../transcription.js";
25
+ import { runSuperAgent, isSuperAgentEnabled } from "../super-agent.js";
26
+ import { appendGlobalMessage } from "../../../core/messages-store.js";
27
+ import { appendErrorTrace, previewText } from "../../../core/logging.js";
28
+
29
+ // ── Channel-aware pre-processor ────────────────────────────────────
30
+ //
31
+ // Each surface that talks to the super-agent (voice overlay on the
32
+ // deck, deck buttons, telegram, raw API) has different ergonomics:
33
+ // what the response will look like, how long it can be, whether the
34
+ // UI can render structured suggestions. `buildChannelContext` is the
35
+ // single place where those decisions live — voice.js passes the
36
+ // channel string from the request body and gets back the context
37
+ // note + system suffix to feed into the super-agent.
38
+ //
39
+ // The shape is intentionally tiny: contextNote becomes the
40
+ // `contextNote` field on the super-agent call (gets prepended to the
41
+ // prompt), systemSuffix is concatenated onto the system prompt to
42
+ // teach the model surface-specific output rules (e.g. trailing
43
+ // ```suggestions JSON block``` on voice/deck).
44
+ function buildChannelContext(channel, { projectId, language = "es" } = {}) {
45
+ const base = {
46
+ contextNote: "",
47
+ systemSuffix: "",
48
+ wantsSuggestions: false,
49
+ // Channel id forwarded to runSuperAgent so the matching channels/*.md
50
+ // formatting block is injected.
51
+ channel: "",
52
+ // Forwarded as channelMeta; { voice: true } flags spoken mode.
53
+ channelMeta: {},
54
+ };
55
+ // Project resolution hint.
56
+ // - per-project mic (projectId set): use it imperatively, don't ask.
57
+ // - global deck mic (no projectId): default to project id=0
58
+ // ("default") for actions unless the user names a project out
59
+ // loud. Either way, don't pester the user with "¿en qué
60
+ // proyecto?" — pick a sensible default and act.
61
+ const projectHint = projectId
62
+ ? `\nThe active project is id=${projectId}. For ANY task/note/list ` +
63
+ `action, pass project_id=${projectId} automatically. Do NOT ask the ` +
64
+ `user which project — only switch if they explicitly name another.`
65
+ : `\nThis is the GLOBAL mic (no project in focus). For task/note/list ` +
66
+ `actions, default to project_id=0 ("default") UNLESS the user names ` +
67
+ `a project out loud (e.g. "en evolution-registry…", "en el proyecto ` +
68
+ `apx…") — then resolve that project by name. Never ask "¿en qué ` +
69
+ `proyecto?"; pick the default and act.`;
70
+ // Hard language directive — without this the model defaults to its
71
+ // training-bias English on short Spanish prompts, especially when
72
+ // the user mixes English-ish product names ("aicrm").
73
+ const langDirective = language === "es"
74
+ ? "IMPORTANT: Reply ALWAYS in Spanish (rioplatense/Argentina). The user speaks Spanish."
75
+ : `IMPORTANT: Reply in language "${language}".`;
76
+
77
+ // Surface mapping. Channels are surfaces; "voice" is NOT a surface — it's the
78
+ // spoken MODE of the deck. All channel FORMATTING now lives in the
79
+ // channels/*.md + modes/voice.md blocks (injected by buildSuperAgentSystem);
80
+ // contextNote here carries ONLY per-request dynamic bits (language + project).
81
+ // incoming "voice" → deck surface, spoken
82
+ // incoming "deck" → deck surface, text card
83
+ // incoming "desktop" → desktop module, spoken (voice-first)
84
+ const dynamicNote = `${langDirective}${projectHint}`;
85
+ switch (channel) {
86
+ case "voice":
87
+ return { ...base, contextNote: dynamicNote, systemSuffix: SUGGESTIONS_INSTRUCTION, wantsSuggestions: true, channel: "deck", channelMeta: { voice: true } };
88
+ case "deck":
89
+ return { ...base, contextNote: dynamicNote, systemSuffix: SUGGESTIONS_INSTRUCTION, wantsSuggestions: true, channel: "deck", channelMeta: {} };
90
+ case "desktop":
91
+ return { ...base, contextNote: dynamicNote, systemSuffix: SUGGESTIONS_INSTRUCTION, wantsSuggestions: true, channel: "desktop", channelMeta: { voice: true } };
92
+ case "telegram":
93
+ // Format rules live in channels/telegram.md; keep only the dynamic note.
94
+ return { ...base, contextNote: dynamicNote, channel: "telegram", channelMeta: {} };
95
+ default:
96
+ return { ...base, contextNote: dynamicNote, channel: channel || "api", channelMeta: {} };
97
+ }
98
+ }
99
+
100
+ // Balanced suffix. An earlier, more aggressive version ("EJECUTA, no
101
+ // narres — LLAMÁ A LA TOOL") made Gemini call tools for EVERYTHING,
102
+ // even "hola" → it fired send_telegram("hola"). The rule below gates
103
+ // tool use on a *clear* action request and explicitly tells the model
104
+ // to just talk for chit-chat.
105
+ const SUGGESTIONS_INSTRUCTION = `
106
+
107
+ # Cuándo usar tools
108
+ SOLO llamá una tool cuando el usuario pide CLARAMENTE una acción
109
+ concreta: "creá una tarea …", "mandá un telegram …", "listá …",
110
+ "abrí …", "marcá como hecha …". En esos casos ejecutá la tool (no
111
+ digas "lo voy a hacer" — hacelo) y después confirmá en una frase corta
112
+ en castellano lo que YA hiciste.
113
+
114
+ Si el mensaje es un saludo, una pregunta, o charla ("hola", "cómo
115
+ andás", "qué podés hacer") NO llames ninguna tool: respondé en texto,
116
+ breve, en castellano.
117
+
118
+ Nunca llames la misma tool dos veces en el mismo turno.
119
+
120
+ # Sugerencias (opcional)
121
+ Al final, en su propia línea, podés agregar un bloque fenced
122
+ \`suggestions\` con 2-3 próximos pasos. El usuario NO lo ve (la deck lo
123
+ quita):
124
+ \`\`\`suggestions
125
+ [{"label":"Ver tareas","command":"deck.view:tasks"}]
126
+ \`\`\`
127
+ Si no hay próximos pasos útiles, omití el bloque.`;
128
+
129
+ // Pull the trailing ```suggestions ... ``` block off the agent's
130
+ // reply. Returns { cleanText, suggestions[] } — cleanText is the
131
+ // reply with the block removed so the user (and TTS) never sees it.
132
+ const SUGGESTIONS_BLOCK_RE = /\n*```\s*suggestions\s*\n([\s\S]*?)\n?```\s*$/i;
133
+
134
+ function extractSuggestions(text) {
135
+ if (typeof text !== "string" || !text) return { cleanText: text || "", suggestions: [] };
136
+ const m = SUGGESTIONS_BLOCK_RE.exec(text);
137
+ if (!m) return { cleanText: text, suggestions: [] };
138
+ const cleanText = text.slice(0, m.index).trim();
139
+ let suggestions = [];
140
+ try {
141
+ const parsed = JSON.parse(m[1]);
142
+ if (Array.isArray(parsed)) {
143
+ suggestions = parsed
144
+ .filter((s) => s && typeof s === "object" && typeof s.label === "string")
145
+ .slice(0, 4)
146
+ .map((s) => ({
147
+ label: String(s.label).slice(0, 48),
148
+ ...(typeof s.command === "string" ? { command: s.command.slice(0, 96) } : {}),
149
+ }));
150
+ }
151
+ } catch {
152
+ // Malformed JSON — drop suggestions silently rather than fail the
153
+ // turn. Better UX to show the reply without chips than an error.
154
+ }
155
+ return { cleanText, suggestions };
156
+ }
157
+
158
+ // ── Voice intent classifier ────────────────────────────────────────
159
+ //
160
+ // A very small, regex-based router that catches a handful of "verb-y"
161
+ // utterances we want to short-circuit instead of sending to the LLM.
162
+ // Right now: "crear tarea ...", "creá tarea ...", "agregá una tarea ...",
163
+ // "nueva tarea ..." → POST to the project's tasks store directly.
164
+ //
165
+ // The classifier always returns either:
166
+ // - { handled: false } → caller falls through to the super-agent
167
+ // - { handled: true, reply: "...", meta?: {...} } → caller returns
168
+ //
169
+ // Keeping it dependency-free + sync lets us run it before any heavy
170
+ // work in the voice handler.
171
+ const TASK_INTENT_RE = new RegExp(
172
+ // Optional polite preamble: "podés / por favor"
173
+ "^\\s*(?:por favor|porfa|porfis|dale|che|apx)?[,!\\s]*" +
174
+ // Either:
175
+ // (a) verb cluster + optional article + "tarea"
176
+ // (b) standalone "nueva|otra tarea" (no verb)
177
+ "(?:" +
178
+ // (a) verbs — with optional clitic pronouns (-me, -te, -le)
179
+ "(?:crea[r]?|cre[áa]|agreg[áa](?:me|le)?|agreg[uú]e|sum[áa](?:me)?|" +
180
+ "anot[áa](?:me)?|an[oó]tame|guard[áa](?:me)?|met[ée](?:me)?|" +
181
+ "añad[íi]|añad[ée]|pone(?:me|le)?|recor[dáa]me)" +
182
+ "\\s+(?:una|la|el|esta|ese|otra|otro)?\\s*" +
183
+ "(?:tarea|task|pendiente|todo|to-do)" +
184
+ "|" +
185
+ // (b) "nueva tarea X" / "otra tarea X" without a verb
186
+ "(?:nueva|otra|nuevo)\\s+(?:tarea|task|pendiente)" +
187
+ ")" +
188
+ // Optional connectors before the title
189
+ "\\s+(?:que\\s+(?:diga|sea|es)|para|de|sobre|llamada|titulada|titul[áa]da|:|-|de:)?\\s*",
190
+ "i"
191
+ );
192
+
193
+ function extractTaskTitle(text) {
194
+ if (typeof text !== "string") return null;
195
+ const cleaned = text.trim().replace(/^[«"']|[«"'.,;:!?]+$/g, "");
196
+ if (!cleaned) return null;
197
+ const m = TASK_INTENT_RE.exec(cleaned);
198
+ if (!m) return null;
199
+ const title = cleaned.slice(m[0].length).trim().replace(/[.!?]+$/, "");
200
+ if (!title) return null;
201
+ return title;
202
+ }
203
+
204
+ function pickIntentProject({ projects, hintId }) {
205
+ if (!projects?.list) return null;
206
+ const list = projects.list();
207
+ if (hintId !== undefined && hintId !== null) {
208
+ const hit = list.find((p) => String(p.id) === String(hintId));
209
+ if (hit) return hit;
210
+ }
211
+ // Prefer the first non-default real project; fall back to default.
212
+ return list.find((p) => Number(p.id) !== 0) || list[0] || null;
213
+ }
214
+
215
+ async function tryVoiceTaskIntent({ projects, userText, hintProjectId }) {
216
+ const title = extractTaskTitle(userText);
217
+ if (!title) return { handled: false };
218
+ const listEntry = pickIntentProject({ projects, hintId: hintProjectId });
219
+ if (!listEntry) {
220
+ return {
221
+ handled: true,
222
+ reply: "No hay proyectos APX registrados. Agregá uno con `apx project add` y volvé a intentar.",
223
+ };
224
+ }
225
+ // projects.list() returns flat entries without storagePath; the
226
+ // resolver returns the full record. We need that for the JSONL store.
227
+ const project = projects.get(listEntry.id) || listEntry;
228
+ if (!project?.storagePath) {
229
+ return {
230
+ handled: true,
231
+ reply: `No pude crear la tarea: no encuentro el storage del proyecto ${project?.name || listEntry.name}.`,
232
+ };
233
+ }
234
+ try {
235
+ const { createTask } = await import("../../../core/tasks-store.js");
236
+ const task = createTask(project.storagePath, {
237
+ title,
238
+ source: "voice",
239
+ });
240
+ // Resolver may strip the human-readable name; fall back to the
241
+ // list entry which always has it.
242
+ const displayName = project.name || listEntry.name || `proyecto #${project.id}`;
243
+ return {
244
+ handled: true,
245
+ reply: `Listo. Anoté "${title}" en ${displayName}.`,
246
+ meta: { task_id: task.id, project_id: project.id },
247
+ };
248
+ } catch (e) {
249
+ return {
250
+ handled: true,
251
+ reply: `No pude crear la tarea: ${e.message || "error desconocido"}`,
252
+ };
253
+ }
254
+ }
255
+
256
+ async function decodeAudioInput({ audio, format = "webm" }) {
257
+ if (!audio) return null;
258
+ // A short string that starts with "/" and exists on disk is treated as a
259
+ // path. Anything else is interpreted as base64 (optionally with a data:
260
+ // prefix).
261
+ if (
262
+ typeof audio === "string" &&
263
+ audio.length < 1024 &&
264
+ audio.startsWith("/") &&
265
+ fs.existsSync(audio)
266
+ ) {
267
+ return { path: audio, cleanup: false };
268
+ }
269
+ let b64 = audio;
270
+ const m = /^data:[^;]+;base64,(.+)$/.exec(b64);
271
+ if (m) b64 = m[1];
272
+ const buf = Buffer.from(b64, "base64");
273
+ if (!buf.length) throw new Error("voice/turn: decoded audio is empty");
274
+ const ext = String(format || "webm").replace(/^\./, "");
275
+ const tmp = path.join(os.tmpdir(), `apx-voice-${Date.now()}-${randomUUID()}.${ext}`);
276
+ fs.writeFileSync(tmp, buf);
277
+ return { path: tmp, cleanup: true };
278
+ }
279
+
280
+ export function register(app, { projects, plugins, registries }) {
281
+ // GET /voice/tts?path=<abs>
282
+ //
283
+ // Streams a TTS audio file back to the caller. Sandboxed to the
284
+ // ~/.apx/tmp/tts directory so a client can't request arbitrary
285
+ // filesystem paths through a manifest-leaked reply_audio_path.
286
+ app.get("/voice/tts", async (req, res) => {
287
+ const rawPath = String(req.query.path || "");
288
+ if (!rawPath) return res.status(400).json({ error: "path required" });
289
+ try {
290
+ const os = await import("node:os");
291
+ const ttsRoot = path.resolve(os.homedir(), ".apx", "tmp", "tts");
292
+ const resolved = path.resolve(rawPath);
293
+ if (!resolved.startsWith(ttsRoot + path.sep)) {
294
+ return res.status(403).json({ error: "path outside tts dir" });
295
+ }
296
+ if (!fs.existsSync(resolved)) return res.status(404).json({ error: "not found" });
297
+ const ext = path.extname(resolved).toLowerCase();
298
+ const mime =
299
+ ext === ".wav" ? "audio/wav" :
300
+ ext === ".mp3" ? "audio/mpeg" :
301
+ ext === ".m4a" || ext === ".aac" ? "audio/mp4" :
302
+ ext === ".ogg" || ext === ".opus" ? "audio/ogg" :
303
+ "application/octet-stream";
304
+ res.setHeader("Content-Type", mime);
305
+ // Cache for a minute — the client fetches each reply once anyway,
306
+ // but a retry shouldn't re-hit disk if it's the same file.
307
+ res.setHeader("Cache-Control", "private, max-age=60");
308
+ fs.createReadStream(resolved).pipe(res);
309
+ } catch (e) {
310
+ res.status(500).json({ error: e?.message || "tts read failed" });
311
+ }
312
+ });
313
+
314
+ app.post("/voice/turn", async (req, res) => {
315
+ const body = req.body || {};
316
+ const cfg = readConfig();
317
+ let userText = (body.text || "").trim();
318
+ let decoded = null;
319
+
320
+ try {
321
+ // ── 1. STT (skip if caller already gave us text) ─────────────────
322
+ if (!userText) {
323
+ decoded = await decodeAudioInput({
324
+ audio: body.audio,
325
+ format: body.format,
326
+ });
327
+ if (!decoded) {
328
+ return res.status(400).json({ error: "audio or text required" });
329
+ }
330
+ const sttResult = await transcribe(decoded.path, {
331
+ language:
332
+ body.language && body.language !== "auto" ? body.language : undefined,
333
+ });
334
+ userText = (sttResult.text || "").trim();
335
+ }
336
+ if (!userText) {
337
+ return res.json({
338
+ user_text: "",
339
+ reply_text: "",
340
+ reply_audio_path: null,
341
+ provider: null,
342
+ empty: true,
343
+ });
344
+ }
345
+
346
+ // ── 1.5 Intent classifier (DISABLED) ──────────────────────────
347
+ // We used to regex-match "creá una tarea X" here and short-circuit
348
+ // the LLM. That fired far too eagerly — any sentence containing
349
+ // those words became a task title, even when the user's actual
350
+ // intent was different ("explicame cómo funciona crear una
351
+ // tarea" would create a bogus task).
352
+ //
353
+ // The right path is the agent's own tool calling: the super-agent
354
+ // already has `create_task`, `send_telegram`, `list_tasks`, etc.
355
+ // in its CORE schema (see super-agent-tools/index.js). We let
356
+ // the model decide; the system prompt below pushes it toward
357
+ // tool use instead of narrating the action in prose.
358
+ const intentResult = { handled: false };
359
+ let replyText = "";
360
+ const previousMessages = Array.isArray(body.previousMessages)
361
+ ? body.previousMessages
362
+ : [];
363
+ const channel = body.channel || "voice";
364
+
365
+ let intentMeta = null;
366
+ let suggestions = [];
367
+ let toolsUsed = [];
368
+ const channelCtx = buildChannelContext(channel, {
369
+ projectId: body.projectId,
370
+ language: body.language && body.language !== "auto" ? body.language : "es",
371
+ });
372
+ if (intentResult.handled) {
373
+ replyText = intentResult.reply;
374
+ intentMeta = intentResult.meta || null;
375
+ // Intent shortcut bypasses the LLM, so no model-generated
376
+ // suggestions either; we hand-craft a couple based on the
377
+ // outcome so the chips area isn't empty.
378
+ if (intentMeta?.task_id) {
379
+ suggestions = [
380
+ { label: "Ver tareas", command: "deck.view:tasks" },
381
+ { label: "Anotar otra", command: "voice.again" },
382
+ ];
383
+ }
384
+ } else if (isSuperAgentEnabled(cfg)) {
385
+ try {
386
+ const result = await runSuperAgent({
387
+ globalConfig: cfg,
388
+ projects,
389
+ plugins,
390
+ registries,
391
+ prompt: userText,
392
+ contextNote: channelCtx.contextNote,
393
+ channel: channelCtx.channel || "",
394
+ channelMeta: channelCtx.channelMeta || {},
395
+ systemSuffix: channelCtx.systemSuffix,
396
+ previousMessages,
397
+ });
398
+ const raw = (result?.text || "").trim();
399
+ // Surface the tools the agent actually executed this turn so
400
+ // the overlay can show "lo que APX hizo" instead of echoing
401
+ // the transcript. Dedup by name (a list_tasks before+after
402
+ // shows once) and map to a compact {name, summary} shape.
403
+ if (Array.isArray(result?.trace)) {
404
+ const seen = new Set();
405
+ for (const t of result.trace) {
406
+ const name = t?.tool;
407
+ if (!name || seen.has(name)) continue;
408
+ seen.add(name);
409
+ toolsUsed.push({
410
+ name,
411
+ ok: !(t?.result && t.result.error),
412
+ });
413
+ }
414
+ }
415
+ if (channelCtx.wantsSuggestions) {
416
+ const parsed = extractSuggestions(raw);
417
+ replyText = parsed.cleanText;
418
+ suggestions = parsed.suggestions;
419
+ // Safety net: small models sometimes return ONLY the
420
+ // suggestions block (no visible reply). Don't ship empty
421
+ // text to TTS — synthesize a generic confirmation so the
422
+ // user gets audible feedback that something happened.
423
+ if (!replyText && raw) {
424
+ replyText = suggestions.length
425
+ ? "Listo."
426
+ : raw;
427
+ }
428
+ } else {
429
+ replyText = raw;
430
+ }
431
+ } catch (e) {
432
+ appendErrorTrace({
433
+ trace_id: req.apxTraceId,
434
+ surface: "daemon_api",
435
+ route: "POST /voice/turn",
436
+ channel,
437
+ error: { message: e.message, stack: e.stack },
438
+ prompt_preview: previewText(userText),
439
+ });
440
+ return res.status(500).json({
441
+ user_text: userText,
442
+ reply_text: "",
443
+ error: `agent failed: ${e.message}`,
444
+ });
445
+ }
446
+ } else {
447
+ // No super-agent configured: still useful as a STT+TTS echo.
448
+ replyText = userText;
449
+ }
450
+
451
+ // Persist the turn to the cross-channel store (feeds RAG index,
452
+ // search_messages, and the "active threads" block). channelCtx.channel is
453
+ // the resolved surface ("deck"/"desktop"). Best-effort.
454
+ try {
455
+ const logCh = channelCtx.channel || channel;
456
+ if (logCh && logCh !== "api") {
457
+ appendGlobalMessage({ channel: logCh, direction: "in", type: "user", author: "user", body: userText });
458
+ if (replyText) appendGlobalMessage({ channel: logCh, direction: "out", type: "agent", body: replyText });
459
+ }
460
+ } catch { /* best-effort */ }
461
+
462
+ // ── 3. TTS on the reply ──────────────────────────────────────────
463
+ let tts = { audio_path: null, duration_s: null, mime: null, provider: null };
464
+ if (replyText) {
465
+ try {
466
+ tts = await synthesize({
467
+ text: replyText,
468
+ voice: body.voice,
469
+ language: body.language,
470
+ provider: body.provider,
471
+ format: body.format_out,
472
+ globalConfig: cfg,
473
+ });
474
+ } catch (e) {
475
+ // Don't fail the whole turn just because TTS broke; return text.
476
+ tts = {
477
+ audio_path: null,
478
+ duration_s: null,
479
+ mime: null,
480
+ provider: null,
481
+ error: e.message,
482
+ };
483
+ }
484
+ }
485
+
486
+ res.json({
487
+ user_text: userText,
488
+ reply_text: replyText,
489
+ reply_audio_path: tts.audio_path,
490
+ reply_duration_s: tts.duration_s,
491
+ reply_mime: tts.mime,
492
+ provider: tts.provider,
493
+ tts_error: tts.error || undefined,
494
+ intent: intentMeta || undefined,
495
+ suggestions: suggestions.length ? suggestions : undefined,
496
+ tools_used: toolsUsed.length ? toolsUsed : undefined,
497
+ channel: channel,
498
+ });
499
+ } catch (e) {
500
+ res.status(500).json({ error: e.message });
501
+ } finally {
502
+ if (decoded?.cleanup) {
503
+ try {
504
+ fs.unlinkSync(decoded.path);
505
+ } catch {
506
+ /* ignore */
507
+ }
508
+ }
509
+ }
510
+ });
511
+ }
512
+
513
+ // Note for plugin authors:
514
+ // Desktop (src/host/daemon/plugins/desktop.js) and Telegram
515
+ // (src/host/daemon/plugins/telegram.js) currently implement their own
516
+ // STT → agent → render pipelines. To get spoken replies via APX they can
517
+ // POST to /voice/turn (or call `synthesize()` directly) instead of
518
+ // re-implementing TTS. This module intentionally does NOT migrate them —
519
+ // it only exposes the unified channel.
@@ -0,0 +1,123 @@
1
+ // Serve the local admin panel from the daemon.
2
+ //
3
+ // The web bundle is built into src/interfaces/web/dist. When that folder
4
+ // exists, this module mounts it at `/` so users can open
5
+ // http://127.0.0.1:7430 and get the UI. SPA fallback: anything that isn't an
6
+ // /api/* / /projects/* / etc. route falls through to index.html so React
7
+ // Router can resolve client-side paths like /p/1/tasks.
8
+ //
9
+ // During development the user runs `vite dev` on :7431 with proxy → :7430,
10
+ // so this mount is a no-op (dist/ doesn't exist yet).
11
+ import fs from "node:fs";
12
+ import path from "node:path";
13
+ import { fileURLToPath } from "node:url";
14
+
15
+ const __filename = fileURLToPath(import.meta.url);
16
+ const __dirname = path.dirname(__filename);
17
+ // host/daemon/api/web.js → ../../.. = src/ then interfaces/web/dist
18
+ const WEB_DIST = path.resolve(__dirname, "..", "..", "..", "interfaces", "web", "dist");
19
+
20
+ // Paths the panel is NOT allowed to swallow with its SPA fallback. These are
21
+ // the real API surfaces; we keep the list flat so it doesn't drift away from
22
+ // the actual route registry.
23
+ const API_PREFIXES = [
24
+ "/health", "/admin", "/projects", "/telegram", "/engines", "/runtimes",
25
+ "/messages", "/sessions", "/tools", "/mcp", "/voice", "/tts", "/desktop", "/overlay",
26
+ "/transcribe", "/run", "/files", "/memory", "/env", "/pair", "/deck",
27
+ "/super-agent", "/identity",
28
+ ];
29
+
30
+ function isApiPath(p) {
31
+ for (const prefix of API_PREFIXES) {
32
+ if (p === prefix || p.startsWith(prefix + "/")) return true;
33
+ }
34
+ return false;
35
+ }
36
+
37
+ export function register(app, { express, token }) {
38
+ // /admin/web-token: localhost-only endpoint that returns the daemon token
39
+ // so the same-origin admin panel can authenticate every subsequent call.
40
+ // Refuses if the request didn't come from loopback. Also refuses if the
41
+ // request was tunneled in via Cloudflare/ngrok/etc. — those connect from
42
+ // a local agent so the socket IP IS loopback, but tunnel-specific headers
43
+ // give them away. When tunneled, the SPA must instead receive the token
44
+ // via URL fragment (#token=…) that the operator shares out-of-band.
45
+ app.get("/admin/web-token", (req, res) => {
46
+ const ra = req.ip || req.socket?.remoteAddress || "";
47
+ const isLocal =
48
+ ra === "127.0.0.1" ||
49
+ ra === "::1" ||
50
+ ra === "::ffff:127.0.0.1" ||
51
+ ra === "" /* in-process */;
52
+ if (!isLocal) {
53
+ return res.status(403).json({ error: "web-token is loopback-only" });
54
+ }
55
+ const tunneledHeaders = [
56
+ "cf-connecting-ip",
57
+ "cf-ray",
58
+ "x-forwarded-for",
59
+ "x-real-ip",
60
+ "x-forwarded-host",
61
+ "ngrok-trace-id",
62
+ ];
63
+ for (const h of tunneledHeaders) {
64
+ if (req.headers[h]) {
65
+ return res.status(403).json({
66
+ error: "web-token disabled for tunneled requests — share #token=… in URL fragment instead",
67
+ });
68
+ }
69
+ }
70
+ res.json({ token });
71
+ });
72
+
73
+ if (!fs.existsSync(WEB_DIST)) {
74
+ // No build present. Expose a hint endpoint so users hitting the daemon
75
+ // root know what to do.
76
+ app.get("/", (_req, res) => {
77
+ res
78
+ .status(200)
79
+ .type("text/html")
80
+ .send(
81
+ [
82
+ "<!doctype html><meta charset='utf-8'><title>APX</title>",
83
+ "<style>body{font:14px/1.5 system-ui;padding:2rem;color:#aab2bc;background:#0b0d10}",
84
+ "code{background:#1a1e23;padding:.1em .4em;border-radius:3px;font-family:ui-monospace,Menlo}</style>",
85
+ "<h1 style='color:#d6dbe1'>APX daemon</h1>",
86
+ "<p>The admin panel hasn't been built on this install.</p>",
87
+ "<p>From the apx repo run:</p>",
88
+ "<pre><code>cd src/interfaces/web && pnpm install && pnpm build</code></pre>",
89
+ "<p>Or develop with hot reload:</p>",
90
+ "<pre><code>cd src/interfaces/web && pnpm dev</code></pre>",
91
+ "<p>Meanwhile the CLI works as usual — try <code>apx status</code>.</p>",
92
+ ].join("")
93
+ );
94
+ });
95
+ return;
96
+ }
97
+
98
+ // Serve static assets. NB: we mount AFTER the API routes are registered
99
+ // in api.js so /projects, /admin/*, etc. always win over the catch-all.
100
+ app.use(
101
+ express.static(WEB_DIST, {
102
+ index: false,
103
+ etag: true,
104
+ maxAge: "1h",
105
+ setHeaders(res, filePath) {
106
+ // index.html is the SPA shell — never cache it, so a redeploy is
107
+ // picked up on the next reload.
108
+ if (filePath.endsWith("index.html")) {
109
+ res.setHeader("Cache-Control", "no-cache");
110
+ }
111
+ },
112
+ })
113
+ );
114
+
115
+ // SPA fallback: anything that isn't an API path AND doesn't have a file
116
+ // extension goes to index.html. The web app handles routing.
117
+ app.get("*", (req, res, next) => {
118
+ if (req.method !== "GET") return next();
119
+ if (isApiPath(req.path)) return next();
120
+ if (path.extname(req.path)) return next(); // let static handle 404 of /foo.png
121
+ res.sendFile(path.join(WEB_DIST, "index.html"));
122
+ });
123
+ }