@agentprojectcontext/apx 1.80.2 → 1.89.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 (838) hide show
  1. package/package.json +9 -8
  2. package/skills/apc-context/SKILL.md +14 -7
  3. package/skills/apx/SKILL.md +62 -2
  4. package/skills/apx-mcp/SKILL.md +42 -15
  5. package/src/core/agent/a2a/peers.js +161 -0
  6. package/src/core/agent/a2a/reply.js +379 -27
  7. package/src/core/agent/abort.js +25 -0
  8. package/src/core/agent/agent-model.js +58 -0
  9. package/src/core/agent/agent-tools.js +101 -0
  10. package/src/core/agent/author-line.js +110 -0
  11. package/src/core/agent/build-agent-system.js +52 -18
  12. package/src/core/agent/channels/voice-context.js +17 -2
  13. package/src/core/agent/closing-floor.js +117 -0
  14. package/src/core/agent/constants.js +119 -11
  15. package/src/core/agent/engine-call.js +56 -0
  16. package/src/core/agent/group/run-group-turn.js +218 -0
  17. package/src/core/agent/group/turn-resolver.js +165 -0
  18. package/src/core/agent/judge.js +138 -11
  19. package/src/core/agent/loop/side-effects.js +106 -3
  20. package/src/core/agent/memory.js +31 -18
  21. package/src/core/agent/model-capabilities.js +47 -0
  22. package/src/core/agent/model-router.js +11 -40
  23. package/src/core/agent/prompt-builder.js +47 -0
  24. package/src/core/agent/prompts/channels/a2a.md +12 -0
  25. package/src/core/agent/prompts/channels/code.md +3 -1
  26. package/src/core/agent/prompts/channels/telegram.md +2 -0
  27. package/src/core/agent/prompts/channels/web_code.md +1 -1
  28. package/src/core/agent/prompts/channels/whatsapp.md +37 -0
  29. package/src/core/agent/prompts/core/agent-base.md +2 -0
  30. package/src/core/agent/prompts/discipline/action.md +1 -0
  31. package/src/core/agent/prompts/discipline/two-segment.md +2 -1
  32. package/src/core/agent/prompts/modes/mobility.md +36 -0
  33. package/src/core/agent/retry.js +42 -0
  34. package/src/core/agent/run-agent.js +322 -25
  35. package/src/core/agent/run-turn.js +253 -0
  36. package/src/core/agent/self-memory.js +18 -52
  37. package/src/core/agent/skills/agent-skills.js +118 -0
  38. package/src/core/agent/skills/catalog.js +1 -1
  39. package/src/core/agent/skills/declared.js +13 -0
  40. package/src/core/agent/skills/index-store.js +8 -1
  41. package/src/core/agent/skills/inspector.js +20 -3
  42. package/src/core/agent/skills/loader.js +18 -3
  43. package/src/core/agent/skills/media.js +121 -0
  44. package/src/core/agent/skills/origin.js +61 -0
  45. package/src/core/agent/skills/sections.js +136 -0
  46. package/src/core/agent/super-agent.js +54 -14
  47. package/src/core/agent/tools/handlers/_calendar.js +50 -0
  48. package/src/core/agent/tools/handlers/add-mcp.js +103 -0
  49. package/src/core/agent/tools/handlers/asana-create-task.js +3 -1
  50. package/src/core/agent/tools/handlers/attach-media.js +56 -0
  51. package/src/core/agent/tools/handlers/calendar-create-event.js +38 -0
  52. package/src/core/agent/tools/handlers/calendar-find-slot.js +39 -0
  53. package/src/core/agent/tools/handlers/calendar-list-events.js +39 -0
  54. package/src/core/agent/tools/handlers/calendar-update-event.js +35 -0
  55. package/src/core/agent/tools/handlers/call-agent.js +14 -6
  56. package/src/core/agent/tools/handlers/call-runtime.js +27 -49
  57. package/src/core/agent/tools/handlers/comment-task.js +78 -0
  58. package/src/core/agent/tools/handlers/complete-task.js +60 -0
  59. package/src/core/agent/tools/handlers/configure-agent.js +70 -0
  60. package/src/core/agent/tools/handlers/create-agent.js +68 -0
  61. package/src/core/agent/tools/handlers/create-task.js +41 -3
  62. package/src/core/agent/tools/handlers/import-agent.js +5 -5
  63. package/src/core/agent/tools/handlers/list-mcp-tools.js +83 -0
  64. package/src/core/agent/tools/handlers/list-routines.js +46 -0
  65. package/src/core/agent/tools/handlers/list-tasks.js +8 -1
  66. package/src/core/agent/tools/handlers/mark-commitment.js +57 -0
  67. package/src/core/agent/tools/handlers/read-skill.js +64 -0
  68. package/src/core/agent/tools/handlers/remember-routine.js +2 -8
  69. package/src/core/agent/tools/handlers/remember.js +82 -6
  70. package/src/core/agent/tools/handlers/remove-agent.js +42 -0
  71. package/src/core/agent/tools/handlers/run-routine.js +94 -0
  72. package/src/core/agent/tools/handlers/run-shell.js +44 -2
  73. package/src/core/agent/tools/handlers/send-telegram.js +41 -19
  74. package/src/core/agent/tools/handlers/set-agent-prompt.js +44 -0
  75. package/src/core/agent/tools/handlers/view-media.js +69 -0
  76. package/src/core/agent/tools/handlers/write-agent-memory.js +52 -0
  77. package/src/core/agent/tools/helpers.js +36 -4
  78. package/src/core/agent/tools/names.js +64 -0
  79. package/src/core/agent/tools/registry-bridge.js +24 -1
  80. package/src/core/agent/tools/registry.js +79 -0
  81. package/src/core/agent/tools/tool-call-parser.js +136 -13
  82. package/src/core/agent/vision-bridge.js +69 -0
  83. package/src/core/apc/agent-identity.js +74 -0
  84. package/src/core/apc/agent-rename-refs.js +187 -0
  85. package/src/core/apc/agent-write.js +312 -0
  86. package/src/core/apc/agents-vault.js +1 -1
  87. package/src/core/apc/blob-keys.js +42 -0
  88. package/src/core/apc/frontmatter.js +166 -10
  89. package/src/core/apc/parser.js +33 -83
  90. package/src/core/apc/paths.js +4 -6
  91. package/src/core/apc/project-memory.js +44 -0
  92. package/src/core/apc/projects-helpers.js +33 -0
  93. package/src/core/apc/scaffold.js +36 -16
  94. package/src/core/channels/telegram/ask-callbacks.js +103 -0
  95. package/src/core/channels/telegram/dispatch.js +154 -30
  96. package/src/core/channels/telegram/helpers.js +59 -7
  97. package/src/core/channels/telegram/inbound/audio.js +26 -30
  98. package/src/core/channels/telegram/inbound/file.js +22 -32
  99. package/src/core/channels/telegram/inbound/photo.js +24 -28
  100. package/src/core/channels/telegram/progress-gate.js +76 -0
  101. package/src/core/channels/telegram/reply.js +151 -43
  102. package/src/core/channels/telegram/voice-note.js +150 -0
  103. package/src/core/config/index.js +53 -54
  104. package/src/core/config/paths.js +117 -31
  105. package/src/core/config/redact.js +89 -4
  106. package/src/core/config/secret-values.js +2 -4
  107. package/src/core/constants/actors.js +5 -0
  108. package/src/core/constants/channels.js +3 -1
  109. package/src/core/constants/task-categories.js +73 -0
  110. package/src/core/constants/task-fields.js +28 -0
  111. package/src/core/engines/_globs.js +33 -0
  112. package/src/core/engines/anthropic.js +19 -1
  113. package/src/core/engines/catalog.js +20 -0
  114. package/src/core/engines/gemini.js +84 -16
  115. package/src/core/engines/index.js +19 -3
  116. package/src/core/engines/mock.js +145 -1
  117. package/src/core/engines/openai-compatible.js +150 -15
  118. package/src/core/engines/presets.js +36 -9
  119. package/src/core/engines/zen.js +131 -0
  120. package/src/core/events/bus.js +140 -0
  121. package/src/core/events/mascot-notify.js +156 -0
  122. package/src/core/http-tools/browser.js +366 -36
  123. package/src/core/http-tools/catalog.js +206 -22
  124. package/src/core/http-tools/grep.js +62 -7
  125. package/src/core/http-tools/registry.js +3 -1
  126. package/src/core/i18n/en.js +34 -3
  127. package/src/core/i18n/es.js +36 -4
  128. package/src/core/i18n/index.js +5 -5
  129. package/src/core/i18n/pt.js +32 -3
  130. package/src/core/identity/self.js +14 -1
  131. package/src/core/images/engines/a1111.js +219 -0
  132. package/src/core/images/engines/index.js +187 -0
  133. package/src/core/images/engines/mock.js +74 -0
  134. package/src/core/images/engines/openai.js +130 -0
  135. package/src/core/images/engines/sdcpp.js +204 -0
  136. package/src/core/images/engines/shared.js +218 -0
  137. package/src/core/images/generate.js +260 -0
  138. package/src/core/integrations/catalog.js +8 -3
  139. package/src/core/integrations/plugins/_google-oauth.js +179 -0
  140. package/src/core/integrations/plugins/asana.js +7 -3
  141. package/src/core/integrations/plugins/calendar.js +404 -0
  142. package/src/core/integrations/store.js +2 -0
  143. package/src/core/memory/broker.js +16 -1
  144. package/src/core/memory/compactor.js +19 -3
  145. package/src/core/memory/consolidate.js +2 -2
  146. package/src/core/memory/dated-log.js +66 -0
  147. package/src/core/memory/embed-engines/custom.js +59 -0
  148. package/src/core/memory/embed-engines/gemini.js +9 -3
  149. package/src/core/memory/embed-engines/index.js +87 -15
  150. package/src/core/memory/embeddings.js +52 -24
  151. package/src/core/memory/index.js +13 -3
  152. package/src/core/memory/indexer.js +83 -27
  153. package/src/core/memory/prune.js +182 -0
  154. package/src/core/memory/store.js +22 -0
  155. package/src/core/memory/summarizer.js +72 -8
  156. package/src/core/mobility/answer.js +80 -0
  157. package/src/core/mobility/geofence.js +667 -0
  158. package/src/core/mobility/osm-route.js +282 -0
  159. package/src/core/mobility/preferences.js +91 -0
  160. package/src/core/mobility/state.js +245 -0
  161. package/src/core/mobility/trip-event.js +384 -0
  162. package/src/core/net/tailscale.js +168 -0
  163. package/src/core/profiles/bundled/secretary/PROFILE.md +32 -42
  164. package/src/core/profiles/bundled/secretary/config.schema.es.json +68 -0
  165. package/src/core/profiles/bundled/secretary/config.schema.json +30 -2
  166. package/src/core/profiles/bundled/secretary/profile.json +3 -1
  167. package/src/core/profiles/bundled/secretary/routines/a2a-sweep.json +20 -0
  168. package/src/core/profiles/bundled/secretary/routines/day-close.json +4 -1
  169. package/src/core/profiles/bundled/secretary/routines/day-open.json +7 -1
  170. package/src/core/profiles/bundled/secretary/routines/watch.json +13 -2
  171. package/src/core/profiles/lifecycle.js +243 -19
  172. package/src/core/profiles/paths.js +12 -0
  173. package/src/core/profiles/store.js +47 -0
  174. package/src/core/routines/active-runs.js +213 -0
  175. package/src/core/routines/delivery.js +612 -0
  176. package/src/core/routines/header.js +88 -0
  177. package/src/core/routines/index.js +26 -0
  178. package/src/core/routines/run-log.js +78 -0
  179. package/src/core/routines/runner.js +629 -66
  180. package/src/core/routines/signals.js +75 -0
  181. package/src/core/runtime-skills/apc-context/SKILL.md +14 -7
  182. package/src/core/runtime-skills/apx/SKILL.md +93 -1
  183. package/src/core/runtime-skills/apx-agency-agents/SKILL.md +2 -2
  184. package/src/core/runtime-skills/apx-agent/SKILL.md +134 -19
  185. package/src/core/runtime-skills/apx-commitment/SKILL.md +134 -0
  186. package/src/core/runtime-skills/apx-image/SKILL.md +60 -0
  187. package/src/core/runtime-skills/apx-integrations/SKILL.md +82 -0
  188. package/src/core/runtime-skills/apx-mcp/SKILL.md +45 -14
  189. package/src/core/runtime-skills/apx-mcp-builder/SKILL.md +4 -4
  190. package/src/core/runtime-skills/apx-profile/SKILL.md +27 -2
  191. package/src/core/runtime-skills/apx-project/SKILL.md +23 -2
  192. package/src/core/runtime-skills/apx-routine/SKILL.md +40 -17
  193. package/src/core/runtime-skills/apx-runtime/SKILL.md +124 -14
  194. package/src/core/runtime-skills/apx-sessions/SKILL.md +7 -6
  195. package/src/core/runtime-skills/apx-skill-builder/SKILL.md +15 -13
  196. package/src/core/runtime-skills/apx-task/SKILL.md +79 -26
  197. package/src/core/runtime-skills/apx-telegram/SKILL.md +12 -12
  198. package/src/core/runtime-skills/apx-transcribe/SKILL.md +56 -0
  199. package/src/core/runtime-skills/apx-voice/SKILL.md +27 -8
  200. package/src/core/runtime-skills/claude-code/SKILL.md +8 -0
  201. package/src/core/runtime-skills/openrouter/SKILL.md +8 -2
  202. package/src/core/runtimes/_spawn.js +9 -1
  203. package/src/core/runtimes/claude-code.js +11 -2
  204. package/src/core/runtimes/codex.js +44 -10
  205. package/src/core/runtimes/index.js +17 -2
  206. package/src/core/runtimes/opencode.js +88 -9
  207. package/src/core/runtimes/outcome.js +119 -0
  208. package/src/core/sessions/index.js +193 -1
  209. package/src/core/stores/agent-inbox.js +109 -23
  210. package/src/core/stores/code-sessions.js +21 -0
  211. package/src/core/stores/commitments.js +27 -3
  212. package/src/core/stores/conversations.js +220 -20
  213. package/src/core/stores/deliveries.js +177 -0
  214. package/src/core/stores/media-archive.js +228 -0
  215. package/src/core/stores/messages.js +1096 -112
  216. package/src/core/stores/organization.js +34 -0
  217. package/src/core/stores/project-memory.js +71 -0
  218. package/src/core/stores/routine-memory.js +16 -8
  219. package/src/core/stores/routines.js +27 -49
  220. package/src/core/stores/sessions.js +4 -8
  221. package/src/core/stores/tasks.js +212 -18
  222. package/src/core/stores/turn-record.js +209 -0
  223. package/src/core/tasks/columns.js +136 -0
  224. package/src/core/tasks/comment-turn.js +258 -0
  225. package/src/core/util/time.js +13 -0
  226. package/src/core/voice/engines/index.js +54 -1
  227. package/src/core/voice/engines/openai.js +50 -4
  228. package/src/core/voice/opus.js +67 -0
  229. package/src/core/voice/pronounceable.js +43 -0
  230. package/src/core/voice/transcription.js +4 -0
  231. package/src/core/voice/tts.js +114 -24
  232. package/src/host/daemon/active-turns.js +188 -0
  233. package/src/host/daemon/api/admin-config.js +9 -0
  234. package/src/host/daemon/api/agents.js +99 -90
  235. package/src/host/daemon/api/artifact-preview.js +7 -6
  236. package/src/host/daemon/api/artifacts.js +3 -2
  237. package/src/host/daemon/api/code.js +55 -9
  238. package/src/host/daemon/api/commitments.js +11 -0
  239. package/src/host/daemon/api/confirm.js +3 -2
  240. package/src/host/daemon/api/conversations.js +543 -35
  241. package/src/host/daemon/api/deck.js +9 -8
  242. package/src/host/daemon/api/deliveries.js +33 -0
  243. package/src/host/daemon/api/desktop.js +5 -4
  244. package/src/host/daemon/api/embeddings.js +15 -6
  245. package/src/host/daemon/api/engines.js +59 -8
  246. package/src/host/daemon/api/exec.js +437 -121
  247. package/src/host/daemon/api/groups.js +215 -0
  248. package/src/host/daemon/api/images.js +107 -0
  249. package/src/host/daemon/api/inbox.js +123 -2
  250. package/src/host/daemon/api/integrations.js +64 -2
  251. package/src/host/daemon/api/mcps.js +7 -6
  252. package/src/host/daemon/api/media.js +283 -0
  253. package/src/host/daemon/api/mobility.js +177 -0
  254. package/src/host/daemon/api/net.js +182 -0
  255. package/src/host/daemon/api/pairing.js +38 -5
  256. package/src/host/daemon/api/profiles.js +30 -2
  257. package/src/host/daemon/api/routines.js +36 -4
  258. package/src/host/daemon/api/runtimes.js +74 -39
  259. package/src/host/daemon/api/sessions-search.js +7 -2
  260. package/src/host/daemon/api/sessions.js +44 -2
  261. package/src/host/daemon/api/shared.js +127 -20
  262. package/src/host/daemon/api/skills.js +11 -4
  263. package/src/host/daemon/api/super-agent.js +384 -53
  264. package/src/host/daemon/api/tasks.js +180 -10
  265. package/src/host/daemon/api/telegram.js +11 -10
  266. package/src/host/daemon/api/thread-faces.js +159 -0
  267. package/src/host/daemon/api/top-level.js +3 -3
  268. package/src/host/daemon/api/transcribe.js +11 -10
  269. package/src/host/daemon/api/tts.js +97 -4
  270. package/src/host/daemon/api/turn-abort.js +23 -0
  271. package/src/host/daemon/api/turns.js +49 -0
  272. package/src/host/daemon/api/voice.js +5 -4
  273. package/src/host/daemon/api/web.js +98 -0
  274. package/src/host/daemon/api.js +39 -0
  275. package/src/host/daemon/delivery-sweep.js +58 -0
  276. package/src/host/daemon/desktop-ws.js +5 -23
  277. package/src/host/daemon/events-ws.js +273 -0
  278. package/src/host/daemon/index.js +59 -15
  279. package/src/host/daemon/plugins/desktop/index.js +17 -4
  280. package/src/host/daemon/plugins/telegram/index.js +78 -40
  281. package/src/host/daemon/pty-bridge.py +99 -0
  282. package/src/host/daemon/routines-scheduler.js +1 -0
  283. package/src/host/daemon/smoke.js +1 -2
  284. package/src/host/daemon/terminal-ws.js +132 -0
  285. package/src/host/daemon/tts-keepwarm.js +87 -0
  286. package/src/host/daemon/wakeup.js +11 -6
  287. package/src/host/daemon/whisper-server.js +44 -0
  288. package/src/host/daemon/whisper-server.py +70 -13
  289. package/src/host/daemon/ws-auth.js +28 -0
  290. package/src/interfaces/android/app/build.gradle +42 -0
  291. package/src/interfaces/android/app/proguard-rules.pro +4 -0
  292. package/src/interfaces/android/app/src/main/AndroidManifest.xml +139 -0
  293. package/src/interfaces/android/app/src/main/java/dev/agentprojectcontext/apx/AlertScreen.java +139 -0
  294. package/src/interfaces/android/app/src/main/java/dev/agentprojectcontext/apx/AndroidAutoDetector.java +106 -0
  295. package/src/interfaces/android/app/src/main/java/dev/agentprojectcontext/apx/ApxCarAppService.java +57 -0
  296. package/src/interfaces/android/app/src/main/java/dev/agentprojectcontext/apx/ApxPreferences.java +165 -0
  297. package/src/interfaces/android/app/src/main/java/dev/agentprojectcontext/apx/CarAlertStore.java +84 -0
  298. package/src/interfaces/android/app/src/main/java/dev/agentprojectcontext/apx/CarMessageActionReceiver.java +47 -0
  299. package/src/interfaces/android/app/src/main/java/dev/agentprojectcontext/apx/CarMessageNotification.java +152 -0
  300. package/src/interfaces/android/app/src/main/java/dev/agentprojectcontext/apx/DaemonAddress.java +35 -0
  301. package/src/interfaces/android/app/src/main/java/dev/agentprojectcontext/apx/DaemonClient.java +339 -0
  302. package/src/interfaces/android/app/src/main/java/dev/agentprojectcontext/apx/DeviceLocation.java +38 -0
  303. package/src/interfaces/android/app/src/main/java/dev/agentprojectcontext/apx/ErrandScreen.java +127 -0
  304. package/src/interfaces/android/app/src/main/java/dev/agentprojectcontext/apx/MainActivity.java +872 -0
  305. package/src/interfaces/android/app/src/main/java/dev/agentprojectcontext/apx/MapsNavigationDetector.java +63 -0
  306. package/src/interfaces/android/app/src/main/java/dev/agentprojectcontext/apx/MapsNavigationListenerService.java +453 -0
  307. package/src/interfaces/android/app/src/main/java/dev/agentprojectcontext/apx/MapsShareIntentParser.java +93 -0
  308. package/src/interfaces/android/app/src/main/java/dev/agentprojectcontext/apx/MascotBlobCatalog.java +66 -0
  309. package/src/interfaces/android/app/src/main/java/dev/agentprojectcontext/apx/MascotOverlayService.java +448 -0
  310. package/src/interfaces/android/app/src/main/java/dev/agentprojectcontext/apx/MascotView.java +249 -0
  311. package/src/interfaces/android/app/src/main/java/dev/agentprojectcontext/apx/MessageFrameParser.java +240 -0
  312. package/src/interfaces/android/app/src/main/java/dev/agentprojectcontext/apx/NotifyChannels.java +69 -0
  313. package/src/interfaces/android/app/src/main/java/dev/agentprojectcontext/apx/ProximityActionReceiver.java +78 -0
  314. package/src/interfaces/android/app/src/main/java/dev/agentprojectcontext/apx/ProximityNotification.java +161 -0
  315. package/src/interfaces/android/app/src/main/java/dev/agentprojectcontext/apx/StartupReceiver.java +57 -0
  316. package/src/interfaces/android/app/src/main/java/dev/agentprojectcontext/apx/TravelEventGate.java +62 -0
  317. package/src/interfaces/android/app/src/main/java/dev/agentprojectcontext/apx/TravelStatusBanner.java +116 -0
  318. package/src/interfaces/android/app/src/main/java/dev/agentprojectcontext/apx/TripLocationService.java +272 -0
  319. package/src/interfaces/android/app/src/main/java/dev/agentprojectcontext/apx/TripPlacesSheet.java +203 -0
  320. package/src/interfaces/android/app/src/main/java/dev/agentprojectcontext/apx/TripScreen.java +182 -0
  321. package/src/interfaces/android/app/src/main/res/drawable/app_background.xml +12 -0
  322. package/src/interfaces/android/app/src/main/res/drawable/ic_apx_app.xml +10 -0
  323. package/src/interfaces/android/app/src/main/res/drawable/ic_apx_launcher_foreground.xml +12 -0
  324. package/src/interfaces/android/app/src/main/res/drawable/ic_apx_notification.xml +22 -0
  325. package/src/interfaces/android/app/src/main/res/drawable/ic_trip_car.xml +37 -0
  326. package/src/interfaces/android/app/src/main/res/drawable-nodpi/apx_logo.png +0 -0
  327. package/src/interfaces/android/app/src/main/res/drawable-nodpi/mascot_amatista.png +0 -0
  328. package/src/interfaces/android/app/src/main/res/drawable-nodpi/mascot_aqua.png +0 -0
  329. package/src/interfaces/android/app/src/main/res/drawable-nodpi/mascot_brasa.png +0 -0
  330. package/src/interfaces/android/app/src/main/res/drawable-nodpi/mascot_campana.png +0 -0
  331. package/src/interfaces/android/app/src/main/res/drawable-nodpi/mascot_caracol.png +0 -0
  332. package/src/interfaces/android/app/src/main/res/drawable-nodpi/mascot_carbon.png +0 -0
  333. package/src/interfaces/android/app/src/main/res/drawable-nodpi/mascot_cobalto.png +0 -0
  334. package/src/interfaces/android/app/src/main/res/drawable-nodpi/mascot_cometa.png +0 -0
  335. package/src/interfaces/android/app/src/main/res/drawable-nodpi/mascot_coral.png +0 -0
  336. package/src/interfaces/android/app/src/main/res/drawable-nodpi/mascot_cubi.png +0 -0
  337. package/src/interfaces/android/app/src/main/res/drawable-nodpi/mascot_eclipse.png +0 -0
  338. package/src/interfaces/android/app/src/main/res/drawable-nodpi/mascot_faro.png +0 -0
  339. package/src/interfaces/android/app/src/main/res/drawable-nodpi/mascot_gajo.png +0 -0
  340. package/src/interfaces/android/app/src/main/res/drawable-nodpi/mascot_iris.png +0 -0
  341. package/src/interfaces/android/app/src/main/res/drawable-nodpi/mascot_kiwi.png +0 -0
  342. package/src/interfaces/android/app/src/main/res/drawable-nodpi/mascot_laguna.png +0 -0
  343. package/src/interfaces/android/app/src/main/res/drawable-nodpi/mascot_lila.png +0 -0
  344. package/src/interfaces/android/app/src/main/res/drawable-nodpi/mascot_menta.png +0 -0
  345. package/src/interfaces/android/app/src/main/res/drawable-nodpi/mascot_nimbo.png +0 -0
  346. package/src/interfaces/android/app/src/main/res/drawable-nodpi/mascot_noche.png +0 -0
  347. package/src/interfaces/android/app/src/main/res/drawable-nodpi/mascot_onyx.png +0 -0
  348. package/src/interfaces/android/app/src/main/res/drawable-nodpi/mascot_orbita.png +0 -0
  349. package/src/interfaces/android/app/src/main/res/drawable-nodpi/mascot_ovni.png +0 -0
  350. package/src/interfaces/android/app/src/main/res/drawable-nodpi/mascot_papa.png +0 -0
  351. package/src/interfaces/android/app/src/main/res/drawable-nodpi/mascot_parche.png +0 -0
  352. package/src/interfaces/android/app/src/main/res/drawable-nodpi/mascot_peon.png +0 -0
  353. package/src/interfaces/android/app/src/main/res/drawable-nodpi/mascot_perla.png +0 -0
  354. package/src/interfaces/android/app/src/main/res/drawable-nodpi/mascot_pino.png +0 -0
  355. package/src/interfaces/android/app/src/main/res/drawable-nodpi/mascot_quad.png +0 -0
  356. package/src/interfaces/android/app/src/main/res/drawable-nodpi/mascot_rubi.png +0 -0
  357. package/src/interfaces/android/app/src/main/res/drawable-nodpi/mascot_saturno.png +0 -0
  358. package/src/interfaces/android/app/src/main/res/drawable-nodpi/mascot_trebol.png +0 -0
  359. package/src/interfaces/android/app/src/main/res/drawable-nodpi/mascot_trino.png +0 -0
  360. package/src/interfaces/android/app/src/main/res/drawable-nodpi/mascot_volcan.png +0 -0
  361. package/src/interfaces/android/app/src/main/res/drawable-nodpi/mascot_zafiro.png +0 -0
  362. package/src/interfaces/android/app/src/main/res/mipmap-anydpi-v26/ic_launcher.xml +5 -0
  363. package/src/interfaces/android/app/src/main/res/mipmap-anydpi-v26/ic_launcher_round.xml +5 -0
  364. package/src/interfaces/android/app/src/main/res/raw/apx_notification.mp3 +0 -0
  365. package/src/interfaces/android/app/src/main/res/values/colors.xml +4 -0
  366. package/src/interfaces/android/app/src/main/res/values/strings.xml +25 -0
  367. package/src/interfaces/android/app/src/main/res/values/styles.xml +10 -0
  368. package/src/interfaces/android/app/src/main/res/values-v31/styles.xml +14 -0
  369. package/src/interfaces/android/app/src/main/res/xml/automotive_app_desc.xml +9 -0
  370. package/src/interfaces/android/app/src/main/res/xml/network_security_config.xml +10 -0
  371. package/src/interfaces/android/app/src/test/java/dev/agentprojectcontext/apx/AndroidAutoDetectorTest.java +85 -0
  372. package/src/interfaces/android/app/src/test/java/dev/agentprojectcontext/apx/CarAlertStoreTest.java +104 -0
  373. package/src/interfaces/android/app/src/test/java/dev/agentprojectcontext/apx/DaemonAddressTest.java +23 -0
  374. package/src/interfaces/android/app/src/test/java/dev/agentprojectcontext/apx/MapsNavigationDetectorTest.java +69 -0
  375. package/src/interfaces/android/app/src/test/java/dev/agentprojectcontext/apx/MapsShareIntentParserTest.java +31 -0
  376. package/src/interfaces/android/app/src/test/java/dev/agentprojectcontext/apx/MessageFrameParserTest.java +180 -0
  377. package/src/interfaces/android/app/src/test/java/dev/agentprojectcontext/apx/TravelEventGateTest.java +64 -0
  378. package/src/interfaces/android/app/src/test/java/dev/agentprojectcontext/apx/TripPlacesSheetTest.java +66 -0
  379. package/src/interfaces/android/build.gradle +3 -0
  380. package/src/interfaces/android/gradle/wrapper/gradle-wrapper.jar +0 -0
  381. package/src/interfaces/android/gradle/wrapper/gradle-wrapper.properties +9 -0
  382. package/src/interfaces/android/gradle.properties +3 -0
  383. package/src/interfaces/android/gradlew +248 -0
  384. package/src/interfaces/android/gradlew.bat +82 -0
  385. package/src/interfaces/android/settings.gradle +18 -0
  386. package/src/interfaces/cli/commands/a2a.js +145 -4
  387. package/src/interfaces/cli/commands/agent.js +247 -22
  388. package/src/interfaces/cli/commands/code.js +1 -1
  389. package/src/interfaces/cli/commands/commitment.js +5 -0
  390. package/src/interfaces/cli/commands/config.js +85 -6
  391. package/src/interfaces/cli/commands/exec.js +90 -1
  392. package/src/interfaces/cli/commands/image.js +314 -0
  393. package/src/interfaces/cli/commands/mcp.js +87 -23
  394. package/src/interfaces/cli/commands/memory.js +35 -22
  395. package/src/interfaces/cli/commands/panel.js +94 -0
  396. package/src/interfaces/cli/commands/profile.js +14 -0
  397. package/src/interfaces/cli/commands/project.js +29 -0
  398. package/src/interfaces/cli/commands/routine.js +45 -10
  399. package/src/interfaces/cli/commands/runtime.js +30 -7
  400. package/src/interfaces/cli/commands/session.js +90 -38
  401. package/src/interfaces/cli/commands/sessions.js +35 -2
  402. package/src/interfaces/cli/commands/skills.js +15 -9
  403. package/src/interfaces/cli/commands/status.js +2 -3
  404. package/src/interfaces/cli/commands/task.js +54 -5
  405. package/src/interfaces/cli/commands/telegram.js +12 -4
  406. package/src/interfaces/cli/commands/transcribe.js +177 -0
  407. package/src/interfaces/cli/help/index.js +311 -72
  408. package/src/interfaces/cli/http.js +61 -13
  409. package/src/interfaces/cli/index.js +1 -1
  410. package/src/interfaces/cli/routes/agent.js +5 -4
  411. package/src/interfaces/cli/routes/commitment.js +3 -2
  412. package/src/interfaces/cli/routes/config.js +7 -2
  413. package/src/interfaces/cli/routes/image.js +11 -0
  414. package/src/interfaces/cli/routes/index.js +2 -0
  415. package/src/interfaces/cli/routes/log.js +1 -1
  416. package/src/interfaces/cli/routes/memory.js +3 -2
  417. package/src/interfaces/cli/routes/panel.js +15 -2
  418. package/src/interfaces/cli/routes/profile.js +3 -2
  419. package/src/interfaces/cli/routes/transcribe.js +10 -0
  420. package/src/interfaces/cli/stdin.js +29 -0
  421. package/src/interfaces/desktop/assets/blobs/amatista.png +0 -0
  422. package/src/interfaces/desktop/assets/blobs/aqua.png +0 -0
  423. package/src/interfaces/desktop/assets/blobs/brasa.png +0 -0
  424. package/src/interfaces/desktop/assets/blobs/campana.png +0 -0
  425. package/src/interfaces/desktop/assets/blobs/caracol.png +0 -0
  426. package/src/interfaces/desktop/assets/blobs/carbon.png +0 -0
  427. package/src/interfaces/desktop/assets/blobs/cobalto.png +0 -0
  428. package/src/interfaces/desktop/assets/blobs/cometa.png +0 -0
  429. package/src/interfaces/desktop/assets/blobs/coral.png +0 -0
  430. package/src/interfaces/desktop/assets/blobs/cubi.png +0 -0
  431. package/src/interfaces/desktop/assets/blobs/eclipse.png +0 -0
  432. package/src/interfaces/desktop/assets/blobs/faro.png +0 -0
  433. package/src/interfaces/desktop/assets/blobs/gajo.png +0 -0
  434. package/src/interfaces/desktop/assets/blobs/iris.png +0 -0
  435. package/src/interfaces/desktop/assets/blobs/kiwi.png +0 -0
  436. package/src/interfaces/desktop/assets/blobs/laguna.png +0 -0
  437. package/src/interfaces/desktop/assets/blobs/lila.png +0 -0
  438. package/src/interfaces/desktop/assets/blobs/menta.png +0 -0
  439. package/src/interfaces/desktop/assets/blobs/nimbo.png +0 -0
  440. package/src/interfaces/desktop/assets/blobs/noche.png +0 -0
  441. package/src/interfaces/desktop/assets/blobs/onyx.png +0 -0
  442. package/src/interfaces/desktop/assets/blobs/orbita.png +0 -0
  443. package/src/interfaces/desktop/assets/blobs/ovni.png +0 -0
  444. package/src/interfaces/desktop/assets/blobs/papa.png +0 -0
  445. package/src/interfaces/desktop/assets/blobs/parche.png +0 -0
  446. package/src/interfaces/desktop/assets/blobs/peon.png +0 -0
  447. package/src/interfaces/desktop/assets/blobs/perla.png +0 -0
  448. package/src/interfaces/desktop/assets/blobs/pino.png +0 -0
  449. package/src/interfaces/desktop/assets/blobs/quad.png +0 -0
  450. package/src/interfaces/desktop/assets/blobs/rubi.png +0 -0
  451. package/src/interfaces/desktop/assets/blobs/saturno.png +0 -0
  452. package/src/interfaces/desktop/assets/blobs/trebol.png +0 -0
  453. package/src/interfaces/desktop/assets/blobs/trino.png +0 -0
  454. package/src/interfaces/desktop/assets/blobs/volcan.png +0 -0
  455. package/src/interfaces/desktop/assets/blobs/zafiro.png +0 -0
  456. package/src/interfaces/desktop/assets/notification.mp3 +0 -0
  457. package/src/interfaces/desktop/main.js +473 -29
  458. package/src/interfaces/desktop/mascot-blobs.js +41 -0
  459. package/src/interfaces/desktop/mascot-preload.js +32 -0
  460. package/src/interfaces/desktop/mascot.css +186 -0
  461. package/src/interfaces/desktop/mascot.html +40 -0
  462. package/src/interfaces/desktop/mascot.js +163 -0
  463. package/src/interfaces/desktop/preload.js +10 -0
  464. package/src/interfaces/desktop/renderer.js +308 -48
  465. package/src/interfaces/desktop/style.css +34 -0
  466. package/src/interfaces/mcp-server/index.js +87 -0
  467. package/src/interfaces/tui/_shims/util-locale.ts +0 -2
  468. package/src/interfaces/tui/app.tsx +0 -6
  469. package/src/interfaces/tui/attach.ts +0 -1
  470. package/src/interfaces/tui/context/sdk-apx.tsx +0 -4
  471. package/src/interfaces/tui/plugin/api.tsx +0 -3
  472. package/src/interfaces/tui/plugin/runtime.ts +0 -3
  473. package/src/interfaces/tui/thread.ts +0 -16
  474. package/src/interfaces/web/README.md +22 -14
  475. package/src/interfaces/web/dist/assets/claude-XtpLmGtF.webp +0 -0
  476. package/src/interfaces/web/dist/assets/codex-DExPUgvh.webp +0 -0
  477. package/src/interfaces/web/dist/assets/index-BEoRgIqd.css +32 -0
  478. package/src/interfaces/web/dist/assets/index-BEoRgIqd.css.br +0 -0
  479. package/src/interfaces/web/dist/assets/index-BEoRgIqd.css.gz +0 -0
  480. package/src/interfaces/web/dist/assets/index-C6fXHc1p.js +1074 -0
  481. package/src/interfaces/web/dist/assets/index-C6fXHc1p.js.br +0 -0
  482. package/src/interfaces/web/dist/assets/index-C6fXHc1p.js.gz +0 -0
  483. package/src/interfaces/web/dist/assets/index-C6fXHc1p.js.map +1 -0
  484. package/src/interfaces/web/dist/assets/index-C6fXHc1p.js.map.br +0 -0
  485. package/src/interfaces/web/dist/assets/index-C6fXHc1p.js.map.gz +0 -0
  486. package/src/interfaces/web/dist/favicon/dark/site.webmanifest +12 -6
  487. package/src/interfaces/web/dist/favicon/white/site.webmanifest +12 -6
  488. package/src/interfaces/web/dist/index.html +22 -6
  489. package/src/interfaces/web/dist/index.html.br +0 -0
  490. package/src/interfaces/web/dist/index.html.gz +0 -0
  491. package/src/interfaces/web/dist/manifest.webmanifest +25 -0
  492. package/src/interfaces/web/dist/modules/blobs/amatista.png +0 -0
  493. package/src/interfaces/web/dist/modules/blobs/aqua.png +0 -0
  494. package/src/interfaces/web/dist/modules/blobs/brasa.png +0 -0
  495. package/src/interfaces/web/dist/modules/blobs/campana.png +0 -0
  496. package/src/interfaces/web/dist/modules/blobs/caracol.png +0 -0
  497. package/src/interfaces/web/dist/modules/blobs/carbon.png +0 -0
  498. package/src/interfaces/web/dist/modules/blobs/cobalto.png +0 -0
  499. package/src/interfaces/web/dist/modules/blobs/cometa.png +0 -0
  500. package/src/interfaces/web/dist/modules/blobs/coral.png +0 -0
  501. package/src/interfaces/web/dist/modules/blobs/cubi.png +0 -0
  502. package/src/interfaces/web/dist/modules/blobs/eclipse.png +0 -0
  503. package/src/interfaces/web/dist/modules/blobs/faro.png +0 -0
  504. package/src/interfaces/web/dist/modules/blobs/gajo.png +0 -0
  505. package/src/interfaces/web/dist/modules/blobs/iris.png +0 -0
  506. package/src/interfaces/web/dist/modules/blobs/kiwi.png +0 -0
  507. package/src/interfaces/web/dist/modules/blobs/laguna.png +0 -0
  508. package/src/interfaces/web/dist/modules/blobs/lila.png +0 -0
  509. package/src/interfaces/web/dist/modules/blobs/menta.png +0 -0
  510. package/src/interfaces/web/dist/modules/blobs/nimbo.png +0 -0
  511. package/src/interfaces/web/dist/modules/blobs/noche.png +0 -0
  512. package/src/interfaces/web/dist/modules/blobs/onyx.png +0 -0
  513. package/src/interfaces/web/dist/modules/blobs/orbita.png +0 -0
  514. package/src/interfaces/web/dist/modules/blobs/ovni.png +0 -0
  515. package/src/interfaces/web/dist/modules/blobs/papa.png +0 -0
  516. package/src/interfaces/web/dist/modules/blobs/parche.png +0 -0
  517. package/src/interfaces/web/dist/modules/blobs/peon.png +0 -0
  518. package/src/interfaces/web/dist/modules/blobs/perla.png +0 -0
  519. package/src/interfaces/web/dist/modules/blobs/pino.png +0 -0
  520. package/src/interfaces/web/dist/modules/blobs/quad.png +0 -0
  521. package/src/interfaces/web/dist/modules/blobs/rubi.png +0 -0
  522. package/src/interfaces/web/dist/modules/blobs/saturno.png +0 -0
  523. package/src/interfaces/web/dist/modules/blobs/trebol.png +0 -0
  524. package/src/interfaces/web/dist/modules/blobs/trino.png +0 -0
  525. package/src/interfaces/web/dist/modules/blobs/volcan.png +0 -0
  526. package/src/interfaces/web/dist/modules/blobs/zafiro.png +0 -0
  527. package/src/interfaces/web/dist/sw.js +106 -0
  528. package/src/interfaces/web/dist/sw.js.br +0 -0
  529. package/src/interfaces/web/dist/sw.js.gz +0 -0
  530. package/src/interfaces/web/eslint.config.js +83 -0
  531. package/src/interfaces/web/index.html +20 -4
  532. package/src/interfaces/web/package-lock.json +1651 -1280
  533. package/src/interfaces/web/package.json +9 -10
  534. package/src/interfaces/web/pnpm-lock.yaml +867 -869
  535. package/src/interfaces/web/public/favicon/dark/site.webmanifest +12 -6
  536. package/src/interfaces/web/public/favicon/white/site.webmanifest +12 -6
  537. package/src/interfaces/web/public/manifest.webmanifest +25 -0
  538. package/src/interfaces/web/public/modules/blobs/amatista.png +0 -0
  539. package/src/interfaces/web/public/modules/blobs/aqua.png +0 -0
  540. package/src/interfaces/web/public/modules/blobs/brasa.png +0 -0
  541. package/src/interfaces/web/public/modules/blobs/campana.png +0 -0
  542. package/src/interfaces/web/public/modules/blobs/caracol.png +0 -0
  543. package/src/interfaces/web/public/modules/blobs/carbon.png +0 -0
  544. package/src/interfaces/web/public/modules/blobs/cobalto.png +0 -0
  545. package/src/interfaces/web/public/modules/blobs/cometa.png +0 -0
  546. package/src/interfaces/web/public/modules/blobs/coral.png +0 -0
  547. package/src/interfaces/web/public/modules/blobs/cubi.png +0 -0
  548. package/src/interfaces/web/public/modules/blobs/eclipse.png +0 -0
  549. package/src/interfaces/web/public/modules/blobs/faro.png +0 -0
  550. package/src/interfaces/web/public/modules/blobs/gajo.png +0 -0
  551. package/src/interfaces/web/public/modules/blobs/iris.png +0 -0
  552. package/src/interfaces/web/public/modules/blobs/kiwi.png +0 -0
  553. package/src/interfaces/web/public/modules/blobs/laguna.png +0 -0
  554. package/src/interfaces/web/public/modules/blobs/lila.png +0 -0
  555. package/src/interfaces/web/public/modules/blobs/menta.png +0 -0
  556. package/src/interfaces/web/public/modules/blobs/nimbo.png +0 -0
  557. package/src/interfaces/web/public/modules/blobs/noche.png +0 -0
  558. package/src/interfaces/web/public/modules/blobs/onyx.png +0 -0
  559. package/src/interfaces/web/public/modules/blobs/orbita.png +0 -0
  560. package/src/interfaces/web/public/modules/blobs/ovni.png +0 -0
  561. package/src/interfaces/web/public/modules/blobs/papa.png +0 -0
  562. package/src/interfaces/web/public/modules/blobs/parche.png +0 -0
  563. package/src/interfaces/web/public/modules/blobs/peon.png +0 -0
  564. package/src/interfaces/web/public/modules/blobs/perla.png +0 -0
  565. package/src/interfaces/web/public/modules/blobs/pino.png +0 -0
  566. package/src/interfaces/web/public/modules/blobs/quad.png +0 -0
  567. package/src/interfaces/web/public/modules/blobs/rubi.png +0 -0
  568. package/src/interfaces/web/public/modules/blobs/saturno.png +0 -0
  569. package/src/interfaces/web/public/modules/blobs/trebol.png +0 -0
  570. package/src/interfaces/web/public/modules/blobs/trino.png +0 -0
  571. package/src/interfaces/web/public/modules/blobs/volcan.png +0 -0
  572. package/src/interfaces/web/public/modules/blobs/zafiro.png +0 -0
  573. package/src/interfaces/web/public/sw.js +106 -0
  574. package/src/interfaces/web/src/App.tsx +106 -10
  575. package/src/interfaces/web/src/assets/cli/claude.webp +0 -0
  576. package/src/interfaces/web/src/assets/cli/codex.webp +0 -0
  577. package/src/interfaces/web/src/assets/cli/cursor.svg +1 -0
  578. package/src/interfaces/web/src/assets/cli/opencode.png +0 -0
  579. package/src/interfaces/web/src/components/Combobox.tsx +201 -0
  580. package/src/interfaces/web/src/components/MobileHint.tsx +95 -0
  581. package/src/interfaces/web/src/components/MobileLinkDialog.tsx +156 -0
  582. package/src/interfaces/web/src/components/ModelCombobox.tsx +21 -113
  583. package/src/interfaces/web/src/components/{routines/ReadOnlyBlock.tsx → ReadOnlyBlock.tsx} +13 -4
  584. package/src/interfaces/web/src/components/Roby.tsx +5 -3
  585. package/src/interfaces/web/src/components/RobyBubble.tsx +23 -5
  586. package/src/interfaces/web/src/components/RowMenu.tsx +46 -0
  587. package/src/interfaces/web/src/components/TimezoneSelect.tsx +4 -1
  588. package/src/interfaces/web/src/components/Toast.tsx +50 -14
  589. package/src/interfaces/web/src/components/UiSelect.tsx +12 -5
  590. package/src/interfaces/web/src/components/agents/AgentAvatar.tsx +171 -0
  591. package/src/interfaces/web/src/components/agents/AgentFormFields.tsx +42 -11
  592. package/src/interfaces/web/src/components/agents/AgentModelBadge.tsx +157 -0
  593. package/src/interfaces/web/src/components/agents/AgentModelSelect.tsx +57 -0
  594. package/src/interfaces/web/src/components/agents/AgentSkillsPicker.tsx +115 -0
  595. package/src/interfaces/web/src/components/agents/BlobAvatar.tsx +50 -0
  596. package/src/interfaces/web/src/components/agents/blobPresets.ts +50 -0
  597. package/src/interfaces/web/src/components/agents/modelCatalog.ts +66 -0
  598. package/src/interfaces/web/src/components/chat/ActionGroup.tsx +162 -0
  599. package/src/interfaces/web/src/components/chat/AskAnswersCard.tsx +4 -3
  600. package/src/interfaces/web/src/components/chat/AskQuestionsCard.tsx +1 -1
  601. package/src/interfaces/web/src/components/chat/Attachment.tsx +220 -0
  602. package/src/interfaces/web/src/components/chat/ChatList.tsx +226 -51
  603. package/src/interfaces/web/src/components/chat/ChatRowActivity.tsx +45 -0
  604. package/src/interfaces/web/src/components/chat/Composer.tsx +672 -23
  605. package/src/interfaces/web/src/components/chat/ComposerCommands.tsx +175 -0
  606. package/src/interfaces/web/src/components/chat/ComposerSuggest.tsx +215 -0
  607. package/src/interfaces/web/src/components/chat/ContextBar.tsx +133 -65
  608. package/src/interfaces/web/src/components/chat/InlineAskPanel.tsx +107 -47
  609. package/src/interfaces/web/src/components/chat/MessageBubble.tsx +460 -119
  610. package/src/interfaces/web/src/components/chat/MessageList.tsx +165 -18
  611. package/src/interfaces/web/src/components/chat/ReasoningBlock.tsx +58 -0
  612. package/src/interfaces/web/src/components/chat/SessionPicker.tsx +182 -0
  613. package/src/interfaces/web/src/components/chat/SkillTrace.tsx +183 -0
  614. package/src/interfaces/web/src/components/chat/ToolCall.tsx +11 -11
  615. package/src/interfaces/web/src/components/code/CodeContextTab.tsx +87 -53
  616. package/src/interfaces/web/src/components/code/CodeFileTree.tsx +11 -52
  617. package/src/interfaces/web/src/components/code/CodeFileViewer.tsx +5 -4
  618. package/src/interfaces/web/src/components/code/CodeProjectPicker.tsx +31 -7
  619. package/src/interfaces/web/src/components/code/CodeSessionList.tsx +32 -11
  620. package/src/interfaces/web/src/components/code/CodeSidePanel.tsx +33 -3
  621. package/src/interfaces/web/src/components/code/CodeTerminal.tsx +5 -4
  622. package/src/interfaces/web/src/components/code/NewCodeSessionDialog.tsx +164 -0
  623. package/src/interfaces/web/src/components/commitments/CommitmentDetail.tsx +162 -0
  624. package/src/interfaces/web/src/components/commitments/CommitmentFormDialog.tsx +158 -0
  625. package/src/interfaces/web/src/components/commitments/CommitmentList.tsx +194 -0
  626. package/src/interfaces/web/src/components/commitments/commitmentState.tsx +46 -0
  627. package/src/interfaces/web/src/components/common/BulkActionBar.tsx +60 -0
  628. package/src/interfaces/web/src/components/common/ConfirmDialog.tsx +4 -1
  629. package/src/interfaces/web/src/components/common/SelectCheckbox.tsx +40 -0
  630. package/src/interfaces/web/src/components/common/TabNav.tsx +1 -1
  631. package/src/interfaces/web/src/components/cron/CronPicker.tsx +1 -1
  632. package/src/interfaces/web/src/components/files/FileBrowser.tsx +1 -1
  633. package/src/interfaces/web/src/components/files/FileTree.tsx +6 -4
  634. package/src/interfaces/web/src/components/files/FileViewer.tsx +9 -5
  635. package/src/interfaces/web/src/components/files/MarkdownPreview.tsx +45 -9
  636. package/src/interfaces/web/src/components/images/ImageDefaultsCard.tsx +93 -0
  637. package/src/interfaces/web/src/components/images/ImageProviderList.tsx +142 -0
  638. package/src/interfaces/web/src/components/images/ImageProviderModal.tsx +263 -0
  639. package/src/interfaces/web/src/components/images/ImageTestCard.tsx +142 -0
  640. package/src/interfaces/web/src/components/inbox/ChannelFilter.tsx +178 -0
  641. package/src/interfaces/web/src/components/inbox/InboxList.tsx +77 -81
  642. package/src/interfaces/web/src/components/inbox/InboxRowItem.tsx +140 -0
  643. package/src/interfaces/web/src/components/integrations/ComingSoonPlugin.tsx +2 -2
  644. package/src/interfaces/web/src/components/integrations/PluginConnect.tsx +208 -30
  645. package/src/interfaces/web/src/components/integrations/PluginToolsSection.tsx +1 -1
  646. package/src/interfaces/web/src/components/layout/ProjectAvatar.tsx +39 -24
  647. package/src/interfaces/web/src/components/layout/ProjectSidebar.tsx +253 -58
  648. package/src/interfaces/web/src/components/memory/MemoryBrowser.tsx +94 -47
  649. package/src/interfaces/web/src/components/routines/ExecutionsList.tsx +202 -90
  650. package/src/interfaces/web/src/components/routines/RoutineDetail.tsx +28 -6
  651. package/src/interfaces/web/src/components/routines/RoutineEditor.tsx +16 -5
  652. package/src/interfaces/web/src/components/routines/RoutineList.tsx +49 -9
  653. package/src/interfaces/web/src/components/routines/VarTextarea.tsx +1 -1
  654. package/src/interfaces/web/src/components/routines/runChat.ts +121 -0
  655. package/src/interfaces/web/src/components/sessions/SessionDetail.tsx +148 -0
  656. package/src/interfaces/web/src/components/sessions/SessionTerminal.tsx +98 -0
  657. package/src/interfaces/web/src/components/settings/AccessPanel.tsx +205 -0
  658. package/src/interfaces/web/src/components/settings/DefaultRouterCard.tsx +246 -101
  659. package/src/interfaces/web/src/components/settings/DesktopSettingsPanel.tsx +36 -2
  660. package/src/interfaces/web/src/components/settings/DevicesPanel.tsx +19 -6
  661. package/src/interfaces/web/src/components/settings/EmbedProviderList.tsx +274 -0
  662. package/src/interfaces/web/src/components/settings/EnginesPanel.tsx +26 -6
  663. package/src/interfaces/web/src/components/settings/MemoryPanel.tsx +118 -119
  664. package/src/interfaces/web/src/components/settings/NudgePanel.tsx +4 -3
  665. package/src/interfaces/web/src/components/settings/PairDeviceDialog.tsx +15 -4
  666. package/src/interfaces/web/src/components/settings/PanelPrefs.tsx +374 -0
  667. package/src/interfaces/web/src/components/settings/ProfilePanel.tsx +70 -2
  668. package/src/interfaces/web/src/components/settings/RoutingPanel.tsx +2 -1
  669. package/src/interfaces/web/src/components/settings/SkillsInspectorPanel.tsx +102 -43
  670. package/src/interfaces/web/src/components/settings/SkillsManager.tsx +76 -21
  671. package/src/interfaces/web/src/components/settings/SkillsSettings.tsx +10 -3
  672. package/src/interfaces/web/src/components/settings/SuperAgentPanel.tsx +8 -0
  673. package/src/interfaces/web/src/components/settings/TelegramChannelsPanel.tsx +11 -2
  674. package/src/interfaces/web/src/components/settings/TelegramContactsPanel.tsx +19 -8
  675. package/src/interfaces/web/src/components/settings/TelegramRolesPanel.tsx +12 -2
  676. package/src/interfaces/web/src/components/settings/WebPanel.tsx +22 -31
  677. package/src/interfaces/web/src/components/settings/providers/ProviderCard.tsx +15 -3
  678. package/src/interfaces/web/src/components/settings/providers/ProviderModal.tsx +97 -66
  679. package/src/interfaces/web/src/components/settings/providers/ProviderTestDialog.tsx +150 -0
  680. package/src/interfaces/web/src/components/settings/providers/typeStyles.ts +67 -25
  681. package/src/interfaces/web/src/components/settings/providers/types.ts +3 -0
  682. package/src/interfaces/web/src/components/tasks/TaskBoard.tsx +201 -0
  683. package/src/interfaces/web/src/components/tasks/TaskColumnsDialog.tsx +243 -0
  684. package/src/interfaces/web/src/components/tasks/TaskComments.tsx +167 -0
  685. package/src/interfaces/web/src/components/tasks/TaskDetail.tsx +335 -0
  686. package/src/interfaces/web/src/components/tasks/TaskFormDialog.tsx +406 -0
  687. package/src/interfaces/web/src/components/tasks/TaskList.tsx +258 -0
  688. package/src/interfaces/web/src/components/tasks/TaskSubtasks.tsx +126 -0
  689. package/src/interfaces/web/src/components/tasks/columns.ts +51 -0
  690. package/src/interfaces/web/src/components/tasks/taskStatus.tsx +159 -34
  691. package/src/interfaces/web/src/components/tasks/taskViewPrefs.ts +73 -0
  692. package/src/interfaces/web/src/components/tasks/useTaskColumns.ts +31 -0
  693. package/src/interfaces/web/src/components/ui/chat-input.tsx +136 -12
  694. package/src/interfaces/web/src/components/ui/context-menu.tsx +15 -198
  695. package/src/interfaces/web/src/components/ui/dialog.tsx +3 -2
  696. package/src/interfaces/web/src/components/ui/filter-chips.tsx +4 -0
  697. package/src/interfaces/web/src/components/ui/popover.tsx +14 -49
  698. package/src/interfaces/web/src/components/ui/sheet.tsx +2 -1
  699. package/src/interfaces/web/src/components/ui/spinner.tsx +2 -1
  700. package/src/interfaces/web/src/components/ui.tsx +62 -23
  701. package/src/interfaces/web/src/components/voice/VoiceProviderList.tsx +2 -1
  702. package/src/interfaces/web/src/components/voice/VoiceProviderModal.tsx +66 -8
  703. package/src/interfaces/web/src/components/voice/VoiceQvoxInstallCard.tsx +63 -0
  704. package/src/interfaces/web/src/components/voice/VoiceQvoxStatusCard.tsx +51 -0
  705. package/src/interfaces/web/src/components/voice/VoiceSttCard.tsx +4 -3
  706. package/src/interfaces/web/src/components/voice/VoiceTestCard.tsx +38 -4
  707. package/src/interfaces/web/src/constants/index.ts +1 -0
  708. package/src/interfaces/web/src/hooks/useChannelPrefs.ts +39 -0
  709. package/src/interfaces/web/src/hooks/useChat.ts +1092 -85
  710. package/src/interfaces/web/src/hooks/useChatActivity.ts +24 -0
  711. package/src/interfaces/web/src/hooks/useInbox.ts +26 -4
  712. package/src/interfaces/web/src/hooks/useLiveMessages.ts +16 -0
  713. package/src/interfaces/web/src/hooks/useOllamaModels.ts +79 -0
  714. package/src/interfaces/web/src/hooks/useRecorder.ts +198 -0
  715. package/src/interfaces/web/src/hooks/useTokenBootstrap.ts +23 -6
  716. package/src/interfaces/web/src/i18n/en.ts +832 -175
  717. package/src/interfaces/web/src/i18n/es.ts +841 -188
  718. package/src/interfaces/web/src/lib/api/agents.ts +23 -4
  719. package/src/interfaces/web/src/lib/api/code.ts +17 -0
  720. package/src/interfaces/web/src/lib/api/commitments.ts +7 -1
  721. package/src/interfaces/web/src/lib/api/conversations.ts +38 -11
  722. package/src/interfaces/web/src/lib/api/embeddings.ts +3 -0
  723. package/src/interfaces/web/src/lib/api/engines.ts +14 -0
  724. package/src/interfaces/web/src/lib/api/groups.ts +93 -0
  725. package/src/interfaces/web/src/lib/api/images.ts +193 -0
  726. package/src/interfaces/web/src/lib/api/inbox.ts +29 -5
  727. package/src/interfaces/web/src/lib/api/integrations.ts +9 -0
  728. package/src/interfaces/web/src/lib/api/media.ts +126 -0
  729. package/src/interfaces/web/src/lib/api/net.ts +44 -0
  730. package/src/interfaces/web/src/lib/api/profiles.ts +12 -0
  731. package/src/interfaces/web/src/lib/api/projects.ts +9 -1
  732. package/src/interfaces/web/src/lib/api/routines.ts +9 -1
  733. package/src/interfaces/web/src/lib/api/sessions.ts +18 -0
  734. package/src/interfaces/web/src/lib/api/skills.ts +8 -0
  735. package/src/interfaces/web/src/lib/api/super_agent.ts +3 -0
  736. package/src/interfaces/web/src/lib/api/tasks.ts +46 -6
  737. package/src/interfaces/web/src/lib/api/tools.ts +2 -0
  738. package/src/interfaces/web/src/lib/api/transcribe.ts +31 -0
  739. package/src/interfaces/web/src/lib/api/turns.ts +20 -0
  740. package/src/interfaces/web/src/lib/api/voice.ts +72 -2
  741. package/src/interfaces/web/src/lib/api.ts +3 -0
  742. package/src/interfaces/web/src/lib/channels.ts +214 -0
  743. package/src/interfaces/web/src/lib/chat-activity.ts +175 -0
  744. package/src/interfaces/web/src/lib/chat-prefs.ts +48 -0
  745. package/src/interfaces/web/src/lib/code-context.ts +0 -2
  746. package/src/interfaces/web/src/lib/http.ts +51 -17
  747. package/src/interfaces/web/src/lib/inbox-selection.ts +29 -0
  748. package/src/interfaces/web/src/lib/live.ts +252 -0
  749. package/src/interfaces/web/src/lib/net.ts +211 -0
  750. package/src/interfaces/web/src/lib/notify.ts +331 -0
  751. package/src/interfaces/web/src/lib/projectNav.ts +40 -0
  752. package/src/interfaces/web/src/lib/pwa.ts +115 -0
  753. package/src/interfaces/web/src/lib/qvox.ts +24 -0
  754. package/src/interfaces/web/src/lib/slug.ts +3 -0
  755. package/src/interfaces/web/src/lib/tone.ts +150 -0
  756. package/src/interfaces/web/src/main.tsx +15 -4
  757. package/src/interfaces/web/src/screens/ApxAdminScreen.tsx +33 -11
  758. package/src/interfaces/web/src/screens/InboxScreen.tsx +126 -71
  759. package/src/interfaces/web/src/screens/ProjectScreen.tsx +8 -4
  760. package/src/interfaces/web/src/screens/SettingsScreen.tsx +7 -4
  761. package/src/interfaces/web/src/screens/base/AgentDefaultsTab.tsx +30 -9
  762. package/src/interfaces/web/src/screens/base/CommitmentsTab.tsx +150 -168
  763. package/src/interfaces/web/src/screens/base/LogsTab.tsx +8 -7
  764. package/src/interfaces/web/src/screens/base/SessionsTab.tsx +99 -37
  765. package/src/interfaces/web/src/screens/base/WorkspacesTab.tsx +1 -1
  766. package/src/interfaces/web/src/screens/mobile/MobileChat.tsx +85 -0
  767. package/src/interfaces/web/src/screens/mobile/MobileChatList.tsx +244 -0
  768. package/src/interfaces/web/src/screens/mobile/MobileCommitments.tsx +350 -0
  769. package/src/interfaces/web/src/screens/mobile/MobileScreen.tsx +138 -0
  770. package/src/interfaces/web/src/screens/mobile/MobileTabBar.tsx +105 -0
  771. package/src/interfaces/web/src/screens/mobile/MobileTasks.tsx +407 -0
  772. package/src/interfaces/web/src/screens/mobile/NewChatSheet.tsx +313 -0
  773. package/src/interfaces/web/src/screens/mobile/mobileList.tsx +194 -0
  774. package/src/interfaces/web/src/screens/mobile/routes.ts +239 -0
  775. package/src/interfaces/web/src/screens/modules/CodeScreen.tsx +135 -64
  776. package/src/interfaces/web/src/screens/modules/DeckScreen.tsx +0 -1
  777. package/src/interfaces/web/src/screens/modules/ImagesScreen.tsx +172 -0
  778. package/src/interfaces/web/src/screens/modules/VoiceScreen.tsx +36 -4
  779. package/src/interfaces/web/src/screens/project/AgentBrainGraph.tsx +117 -30
  780. package/src/interfaces/web/src/screens/project/AgentDetailScreen.tsx +537 -92
  781. package/src/interfaces/web/src/screens/project/AgentsTab.tsx +344 -93
  782. package/src/interfaces/web/src/screens/project/ArtifactsTab.tsx +1 -1
  783. package/src/interfaces/web/src/screens/project/ChatTab.tsx +1160 -94
  784. package/src/interfaces/web/src/screens/project/IntegrationsTab.tsx +3 -2
  785. package/src/interfaces/web/src/screens/project/McpsTab.tsx +62 -14
  786. package/src/interfaces/web/src/screens/project/Overview.tsx +36 -15
  787. package/src/interfaces/web/src/screens/project/RoutinesTab.tsx +93 -8
  788. package/src/interfaces/web/src/screens/project/SkillsTab.tsx +4 -1
  789. package/src/interfaces/web/src/screens/project/StructureTab.tsx +5 -4
  790. package/src/interfaces/web/src/screens/project/TasksTab.tsx +351 -129
  791. package/src/interfaces/web/src/screens/project/VarsTab.tsx +17 -5
  792. package/src/interfaces/web/src/styles.css +106 -31
  793. package/src/interfaces/web/src/types/daemon.ts +246 -2
  794. package/src/interfaces/web/src/vite-env.d.ts +20 -0
  795. package/src/interfaces/tui/plugin/command-shim.ts +0 -109
  796. package/src/interfaces/web/components.json +0 -25
  797. package/src/interfaces/web/dist/assets/index-CvEoGtTf.js +0 -849
  798. package/src/interfaces/web/dist/assets/index-CvEoGtTf.js.map +0 -1
  799. package/src/interfaces/web/dist/assets/index-DzBBXFaO.css +0 -1
  800. package/src/interfaces/web/src/components/tasks/TaskDetailPanel.tsx +0 -142
  801. package/src/interfaces/web/src/components/ui/accordion.tsx +0 -72
  802. package/src/interfaces/web/src/components/ui/alert-dialog.tsx +0 -187
  803. package/src/interfaces/web/src/components/ui/alert.tsx +0 -76
  804. package/src/interfaces/web/src/components/ui/aspect-ratio.tsx +0 -22
  805. package/src/interfaces/web/src/components/ui/avatar.tsx +0 -107
  806. package/src/interfaces/web/src/components/ui/breadcrumb.tsx +0 -125
  807. package/src/interfaces/web/src/components/ui/button-group.tsx +0 -87
  808. package/src/interfaces/web/src/components/ui/calendar.tsx +0 -221
  809. package/src/interfaces/web/src/components/ui/card.tsx +0 -103
  810. package/src/interfaces/web/src/components/ui/carousel.tsx +0 -242
  811. package/src/interfaces/web/src/components/ui/chart.tsx +0 -371
  812. package/src/interfaces/web/src/components/ui/checkbox.tsx +0 -29
  813. package/src/interfaces/web/src/components/ui/collapsible.tsx +0 -19
  814. package/src/interfaces/web/src/components/ui/combobox.tsx +0 -295
  815. package/src/interfaces/web/src/components/ui/command.tsx +0 -196
  816. package/src/interfaces/web/src/components/ui/direction.tsx +0 -4
  817. package/src/interfaces/web/src/components/ui/drawer.tsx +0 -134
  818. package/src/interfaces/web/src/components/ui/empty.tsx +0 -104
  819. package/src/interfaces/web/src/components/ui/field.tsx +0 -236
  820. package/src/interfaces/web/src/components/ui/hover-card.tsx +0 -51
  821. package/src/interfaces/web/src/components/ui/input-otp.tsx +0 -85
  822. package/src/interfaces/web/src/components/ui/item.tsx +0 -201
  823. package/src/interfaces/web/src/components/ui/menubar.tsx +0 -280
  824. package/src/interfaces/web/src/components/ui/native-select.tsx +0 -61
  825. package/src/interfaces/web/src/components/ui/navigation-menu.tsx +0 -168
  826. package/src/interfaces/web/src/components/ui/pagination.tsx +0 -130
  827. package/src/interfaces/web/src/components/ui/progress.tsx +0 -83
  828. package/src/interfaces/web/src/components/ui/radio-group.tsx +0 -36
  829. package/src/interfaces/web/src/components/ui/resizable.tsx +0 -50
  830. package/src/interfaces/web/src/components/ui/scroll-area.tsx +0 -53
  831. package/src/interfaces/web/src/components/ui/sidebar.tsx +0 -726
  832. package/src/interfaces/web/src/components/ui/slider.tsx +0 -52
  833. package/src/interfaces/web/src/components/ui/sonner.tsx +0 -49
  834. package/src/interfaces/web/src/components/ui/table.tsx +0 -116
  835. package/src/interfaces/web/src/components/ui/toggle-group.tsx +0 -87
  836. package/src/interfaces/web/src/components/ui/toggle.tsx +0 -45
  837. package/src/interfaces/web/src/hooks/use-mobile.ts +0 -19
  838. package/src/interfaces/web/src/screens/base/GlobalTasksTab.tsx +0 -161
@@ -1,6 +1,6 @@
1
1
  ---
2
2
  name: apx-telegram
3
- description: APX Telegram plugin — channels, project pinning, master agents, media. Load BEFORE configuring a new bot or routing — multi-channel is the only mode, root bot_token/chat_id are legacy.
3
+ description: APX Telegram plugin — channels, project pinning, master agents, media. Load BEFORE configuring a new bot or routing — channels[] is the only place credentials live.
4
4
  ---
5
5
 
6
6
  # apx-telegram
@@ -21,7 +21,7 @@ APX polls `getUpdates` and routes messages. Config: `~/.apx/config.json → tele
21
21
  "name": "default",
22
22
  "bot_token": "<from BotFather>",
23
23
  "chat_id": "<numeric chat id>",
24
- "project": "iacrmar", // optional: pin to project
24
+ "project": "acme", // optional: pin to project
25
25
  "route_to_agent": "reviewer", // optional: per-channel agent
26
26
  "respond_with_engine": true, // optional: override global
27
27
  "owner_user_id": "123456789" // optional: via `apx telegram owner`
@@ -33,19 +33,19 @@ APX polls `getUpdates` and routes messages. Config: `~/.apx/config.json → tele
33
33
  }
34
34
  ```
35
35
 
36
- Root `telegram.bot_token` / `telegram.chat_id` are **legacy**. Don't write them. If a config still has them and `channels[]` is empty, APX migrates them into `channels[0]` automatically on first read.
36
+ Root `telegram.bot_token` / `telegram.chat_id` are **not read**. APX drops them on load, so a token written there silently does nothing — always use `channels[]`. With `channels[]` empty, APX polls one implicit `default` channel using `BOT_TELEGRAM_TOKEN` / `TELEGRAM_CHAT_ID` from the environment.
37
37
 
38
38
  ## Concrete CLI calls
39
39
 
40
40
  ```bash
41
- apx telegram setup # template (still emits legacy root fields — prefer channels[])
41
+ apx telegram setup # prints the config template (channels[] shape)
42
42
 
43
43
  # Channels CRUD
44
44
  apx telegram channel add # interactive
45
- apx telegram channel add clientes --bot-token <T> --chat-id <C> --project iacrmar --agent reviewer
45
+ apx telegram channel add clientes --bot-token <T> --chat-id <C> --project acme --agent reviewer
46
46
  apx telegram channel list # alias: ls
47
47
  apx telegram channel show clientes # alias: get
48
- apx telegram channel set clientes --project iacrmar
48
+ apx telegram channel set clientes --project acme
49
49
  apx telegram channel set clientes --agent reviewer
50
50
  apx telegram channel set clientes --respond-engine false
51
51
  apx telegram channel unset clientes --project --agent
@@ -85,20 +85,20 @@ Every `channel` CRUD write triggers `POST /api/admin/reload` so polling picks up
85
85
 
86
86
  ## What "pin to project" does
87
87
 
88
- On a message to a channel with `project: "iacrmar"`:
89
- 1. The super-agent invocation gets `channelMeta.projectId = <iacrmar's id>`.
88
+ On a message to a channel with `project: "acme"`:
89
+ 1. The super-agent invocation gets `channelMeta.projectId = <acme's id>`.
90
90
  2. The system prompt resolves project-scoped agents, MCPs, memory.
91
- 3. Tools (`list_agents`, `list_tasks`, `create_task`, …) default to that project — no need to repeat "in iacrmar" each message.
91
+ 3. Tools (`list_agents`, `list_tasks`, `create_task`, …) default to that project — no need to repeat "in acme" each message.
92
92
 
93
93
  ## What "master agent" does
94
94
 
95
- With `route_to_agent: "reviewer"`, messages go through `/api/projects/:pid/agents/reviewer/chat` instead of `/api/super-agent/chat`. The agent's `AGENT.md` + memory is used. No tools (project agents are `exec_agent`-shaped text in, text out). Single LLM call. Use this for persona channels (reviewer, sales, support) instead of the general assistant. Empty = super-agent (default).
95
+ With `route_to_agent: "reviewer"`, an incoming message is dispatched to that project agent instead of the super-agent. Routing is **in-process** — `src/core/channels/telegram/dispatch.js` reads the agent and makes a single `callEngine` with the agent's `AGENT.md` + memory (there is no per-request `agents/:slug/chat` HTTP route). No tools: text in, text out. Use this for persona channels (reviewer, sales, support) instead of the general assistant. Empty = super-agent (default).
96
96
 
97
97
  ## Anti-examples
98
98
 
99
99
  ```bash
100
- # DON'T write to legacy root fields.
101
- apx config set telegram.bot_token "<T>" # ← use channels[] via `apx telegram channel`
100
+ # DON'T write to the root fields — they are dropped on load.
101
+ apx config set --global telegram.bot_token "<T>" # ← use channels[] via `apx telegram channel`
102
102
 
103
103
  # DON'T expect routing magic from same project on two channels.
104
104
  # A channel pins messages TO a project, not vice-versa. Same project from multiple
@@ -0,0 +1,56 @@
1
+ ---
2
+ name: apx-transcribe
3
+ scope: optional
4
+ description: Transcribe audio and video files to text from the command line with `apx transcribe`, using the daemon's built-in Whisper. Load when asked to transcribe a voice note, an audio clip, or a video's speech, to batch-transcribe a folder, to pipe transcription into a script, or when choosing between the local, cloud, or a networked custom STT engine.
5
+ ---
6
+
7
+ # apx-transcribe
8
+
9
+ `apx transcribe` is a thin CLI over the daemon's speech-to-text engine — the same persistent `whisper-server.py` that powers the desktop overlay and Telegram voice notes (`core/voice/transcription.js`). The model is preloaded at daemon boot, so calls hit a warm server and stay fast. This is the fastest way to turn a file on disk into text without writing any HTTP.
10
+
11
+ ## Usage
12
+
13
+ ```bash
14
+ apx transcribe nota.oga # transcript to stdout, nothing else
15
+ apx transcribe reunion.mp4 # video: the audio track is extracted
16
+ apx transcribe a.wav b.m4a c.mp3 # bulk: one "── name ──" block per file
17
+ apx transcribe ./notas-de-voz/ # every audio/video file in a folder
18
+ apx transcribe voz.webm --lang es # pin the language (else auto-detect)
19
+ apx transcribe *.mp3 --json > out.json # machine-readable array
20
+ cat clip.wav | apx transcribe - # read audio from stdin
21
+ ```
22
+
23
+ ## Formats
24
+
25
+ Audio: `webm`, `ogg`/`oga`, `opus`, `m4a`, `aac`, `mp3`, `wav`, `flac`. Video: `mp4`, `mov`, `mkv`, `m4v`, `avi`, `3gp` and more. The daemon shells out to `ffmpeg`, which probes the real container from the bytes and pulls the audio track out of a video — so the extension is only a hint, and a mislabelled file still works.
26
+
27
+ ## Provider routing (`--provider`)
28
+
29
+ The `--provider` flag overrides the configured STT routing for one call:
30
+
31
+ | id | What it is |
32
+ |---|---|
33
+ | `local` | The embedded Whisper. On Apple Silicon it runs on `mlx` (Metal GPU), on NVIDIA on `faster-whisper` cuda, else CPU — picked automatically. |
34
+ | `openai` | Cloud Whisper (`whisper-1`). Needs `OPENAI_API_KEY` or `engines.openai.api_key`. |
35
+ | `custom` | Any OpenAI-compatible STT server reachable over the network — mlx-audio on this Mac, a Radeon/NVIDIA box on the LAN, or a remote endpoint. Configured under `transcription.custom.base_url`. |
36
+
37
+ Default routing lives in `~/.apx/config.json` under `transcription.provider` (`auto` tries local first, falls back to OpenAI if a key is set).
38
+
39
+ ## Output contract (why it is scriptable)
40
+
41
+ - **One file** → the bare transcript on **stdout**, one trailing newline. Pipe-friendly: `apx transcribe x.oga | pbcopy` copies clean text.
42
+ - **Many files / a folder** → a `── filename ──` header before each transcript.
43
+ - **`--json`** → the full result object (`text`, `language`, `backend`, `model`, …) for one file, or an array of `{file, ...}` in bulk.
44
+ - The `▸ APX CLI` banner always goes to **stderr**, never stdout.
45
+ - Bulk runs **sequentially** (the local model is single-instance) and keeps going past a failed file, exiting non-zero if any failed.
46
+
47
+ ## How it works
48
+
49
+ The CLI reads the file bytes and POSTs them to the daemon's `POST /api/transcribe/chunk` with `X-Audio-Format`, `X-Language`, and optional `X-Provider` headers. That endpoint is the shared "any external caller" entry point, so a routine's `pre_command`, a hook, or a plain shell script all get the same warm engine without spawning their own Whisper. Long media is allowed up to 20 minutes per request.
50
+
51
+ ## Don't
52
+
53
+ - Don't spin up a separate Whisper process or a Python script to transcribe — the daemon already runs a warm one; `apx transcribe` reuses it. A parallel instance just fights for the GPU.
54
+ - Don't restart the daemon to "load" the model before transcribing — it is preloaded at boot, and the endpoint lazily re-spawns it after the idle-shutdown anyway.
55
+ - Don't pre-extract audio from a video before transcribing it — pass the video directly; the daemon's ffmpeg handles the audio track.
56
+ - Don't parse the human transcript when you need fields — use `--json` and read `text`, never scrape stdout for the language or model.
@@ -35,9 +35,9 @@ When `base_url` is set, APX additionally forwards the non-OpenAI fields the serv
35
35
  Some backends (QVox/Qwen3-TTS, Gemini) accept inline `[tag]` markers and switch speaking emotion per segment while keeping the base voice. This is a **generic per-engine toggle**, not hardcoded to any adapter:
36
36
 
37
37
  ```bash
38
- apx config set voice.tts.custom.qvox.emotions.enabled true
38
+ apx config set --global voice.tts.custom.qvox.emotions.enabled true
39
39
  # optional: restrict the tag set (defaults to the canonical QVox set)
40
- apx config set voice.tts.custom.qvox.emotions.tags '["happy","sad","excited","calm","whisper","laugh","neutral"]'
40
+ apx config set --global voice.tts.custom.qvox.emotions.tags '["happy","sad","excited","calm","whisper","laugh","neutral"]'
41
41
  ```
42
42
 
43
43
  Default tags: `happy, sad, excited, angry, calm, whisper, shout, laugh, cry, narrator, neutral`. The voice-mode prompt learns the tag syntax **only when the engine that will actually speak has emotions enabled**. On any engine without tag support, stray `[tags]` are stripped from the displayed text and never read aloud (kept only for the speaking engine's audio).
@@ -57,6 +57,23 @@ apx voice listen --provider <id> # override STT provider
57
57
 
58
58
  Playback uses system binaries (`afplay`, `paplay`, `aplay`, `play`, `ffplay`). If none found, you get the file path and no playback.
59
59
 
60
+ ## Spoken replies while driving
61
+
62
+ When the daemon knows a trip is in progress (Android reports it — see
63
+ `rules/android.md`), every automatic Telegram reply goes out twice: a voice note
64
+ first, then the same words as text under a transcript header. The turn itself
65
+ runs in voice mode, so the reply is one or two spoken sentences rather than a
66
+ paragraph read aloud.
67
+
68
+ The audio is OGG/Opus — the only container Telegram renders as a voice note —
69
+ converted from whatever the engine returned via `ffmpeg`. A failing engine or a
70
+ missing `ffmpeg` costs the audio, never the message: it falls back to plain
71
+ text. The `mock` engine is silence, not speech, and is refused.
72
+
73
+ ```bash
74
+ apx config set --global voice.mobility_replies false # keep replies text-only in the car
75
+ ```
76
+
60
77
  ## Configuration
61
78
 
62
79
  `~/.apx/config.json → voice.tts.<engine>`:
@@ -85,7 +102,7 @@ Playback uses system binaries (`afplay`, `paplay`, `aplay`, `play`, `ffplay`). I
85
102
  }
86
103
  ```
87
104
 
88
- `apx config set voice.tts.provider <name>` to switch.
105
+ `apx config set --global voice.tts.provider <name>` to switch. Voice config is read from the global config, so `--global` is required — without it the value lands in a project's `.apc/config.json` and the voice stack never sees it.
89
106
 
90
107
  ## Quick setup: Piper local (recommended, no internet)
91
108
 
@@ -101,17 +118,17 @@ curl -LO https://huggingface.co/rhasspy/piper-voices/resolve/main/es/es_AR/danie
101
118
  curl -LO https://huggingface.co/rhasspy/piper-voices/resolve/main/es/es_AR/daniela/high/es_AR-daniela-high.onnx.json
102
119
 
103
120
  # 3. Configure + test
104
- apx config set voice.tts.provider piper
105
- apx config set voice.tts.piper.model "$HOME/.apx/voices/es_AR-daniela-high.onnx"
121
+ apx config set --global voice.tts.provider piper
122
+ apx config set --global voice.tts.piper.model "$HOME/.apx/voices/es_AR-daniela-high.onnx"
106
123
  apx voice say "hola, soy APX" --provider piper
107
124
  ```
108
125
 
109
126
  ## Quick setup: Gemini cloud
110
127
 
111
128
  ```bash
112
- apx config set voice.tts.provider gemini
113
- apx config set voice.tts.gemini.api_key '<GEMINI_KEY>'
114
- apx config set engines.gemini.api_key '<GEMINI_KEY>' # reuse for LLM router
129
+ apx config set --global voice.tts.provider gemini
130
+ apx config set --global voice.tts.gemini.api_key '<GEMINI_KEY>'
131
+ apx config set --global engines.gemini.api_key '<GEMINI_KEY>' # reuse for LLM router
115
132
  apx voice say "Hello from APX" --provider gemini
116
133
  ```
117
134
 
@@ -126,6 +143,8 @@ curl -X POST http://127.0.0.1:7430/api/voice/turn \
126
143
  -d '{"text":"Hello APX","channel":"voice"}'
127
144
  ```
128
145
 
146
+ `channel` names the surface the turn arrives on: `voice` (the deck's spoken mode), `deck`, `desktop`, `telegram`. Anything else — including omitting it — is treated as `api`, the bounded default: the route will not adopt another surface's behaviour just because a caller names it.
147
+
129
148
  Telegram voice messages and overlay mascot still have their own STT pipelines — they don't go through `/api/voice/turn` yet.
130
149
 
131
150
  ## Anti-examples
@@ -71,6 +71,14 @@ claude --continue # most recent session
71
71
  claude -p --resume <session-id> "..." # specific session, always with -p (print mode)
72
72
  ```
73
73
 
74
+ ## Not here: agent-to-agent (a2a) hand-off
75
+
76
+ Reaching an APX agent and being answered back (the a2a relay: `apx send … --deliver`,
77
+ `engine=… session=…` identity, `apx session resume … --msg`) is a **harness-side**
78
+ concern. It lives in the `apx` skill that every coding CLI loads, and on the agent
79
+ side in **apx-runtime**. This driver covers only how APX operates the Claude
80
+ engine — keep a2a out of it.
81
+
74
82
  ## APX runtime
75
83
 
76
84
  Run a project agent through Claude Code:
@@ -40,8 +40,14 @@ apx config --help
40
40
  apx status
41
41
  ```
42
42
 
43
- Then update only non-secret project-safe settings. Keep API keys in user config or environment, not
44
- in `.apc/` or git.
43
+ Then update only non-secret project-safe settings. Keep API keys in the global config or the
44
+ environment, never in `.apc/` or git — `apx config set` writes the project's committed
45
+ `.apc/config.json` unless you pass `--global`:
46
+
47
+ ```bash
48
+ apx config set --global engines.openrouter.api_key '<KEY>' # ~/.apx/config.json
49
+ apx config set engines.openrouter.model <model-id> # .apc/config.json (committed)
50
+ ```
45
51
 
46
52
  ## OpenCode guidance
47
53
 
@@ -6,9 +6,17 @@ const DEFAULT_TIMEOUT = 5 * 60 * 1000; // 5 minutes
6
6
 
7
7
  export function runProcess({ command, args = [], stdin = "", cwd, env, timeoutMs = DEFAULT_TIMEOUT }) {
8
8
  return new Promise((resolve) => {
9
+ // `cwd` moves the child's working directory but NOT its inherited `PWD`,
10
+ // which still names wherever the daemon was started. Tools that trust `PWD`
11
+ // over getcwd() — opencode does — then resolve the wrong project: an a2a
12
+ // coding session asked to write a file wrote it into the daemon's checkout
13
+ // instead of the caller's. Keep the two in agreement.
14
+ const childEnv = { ...process.env, ...(env || {}) };
15
+ if (cwd) childEnv.PWD = cwd;
16
+
9
17
  const child = spawn(command, args, {
10
18
  cwd,
11
- env: { ...process.env, ...(env || {}) },
19
+ env: childEnv,
12
20
  stdio: ["pipe", "pipe", "pipe"],
13
21
  });
14
22
 
@@ -1,5 +1,6 @@
1
1
  // Claude Code runtime adapter. Uses the headless `-p` mode:
2
2
  // claude -p "<prompt>" --append-system-prompt "<system>" --output-format json
3
+ // claude -p "<prompt>" --resume <session-id> continue that session
3
4
  // Returns one JSON line with the result and session_id.
4
5
  // Reference: https://docs.claude.com/en/docs/claude-code/headless
5
6
 
@@ -33,8 +34,15 @@ export default {
33
34
  binary: "claude",
34
35
  versionFlag: "--version",
35
36
 
36
- async run({ system, prompt, cwd, env, timeoutMs }) {
37
+ sessions: "capture",
38
+
39
+ async run({ system, prompt, cwd, env, timeoutMs, resumeSessionId = null, mode = "code" }) {
37
40
  const args = ["-p", prompt, "--output-format", "json"];
41
+ // `plan` is Claude Code's own read-only mode: it answers normally but will
42
+ // not edit. That is what a plain a2a message should get — a peer you talked
43
+ // to should not be able to rewrite your checkout because it was asked to.
44
+ if (mode === "chat") args.push("--permission-mode", "plan");
45
+ if (resumeSessionId) args.push("--resume", resumeSessionId);
38
46
  if (system) {
39
47
  args.push("--append-system-prompt", system);
40
48
  }
@@ -70,8 +78,9 @@ export default {
70
78
  exitCode: r.exitCode,
71
79
  output,
72
80
  stderr: r.stderr,
81
+ killed: r.killed,
73
82
  externalSessionPath,
74
- sessionId,
83
+ sessionId: sessionId || resumeSessionId || null,
75
84
  raw: parsed,
76
85
  };
77
86
  },
@@ -1,29 +1,63 @@
1
1
  // OpenAI Codex CLI runtime adapter.
2
- // codex exec --sandbox workspace-write --skip-git-repo-check "<prompt>"
2
+ // codex exec --sandbox workspace-write --skip-git-repo-check --json "<prompt>"
3
+ // codex exec resume <thread-id> --json "<prompt>" continue that thread
3
4
  // System prompt is prepended to the prompt body since Codex doesn't have a
4
5
  // dedicated --system flag in `exec` mode.
5
6
  // Reference: https://github.com/openai/codex
6
7
 
7
8
  import { runProcess } from "./_spawn.js";
8
9
 
10
+ // `--json` turns stdout into JSONL events. We ask for it because it is the only
11
+ // place codex names the thread it opened, and that id is what lets the NEXT
12
+ // turn resume this same conversation instead of starting a stranger. The prose
13
+ // we would otherwise have printed is in the agent_message items.
14
+ function parseCodexEvents(stdout) {
15
+ let threadId = null;
16
+ const messages = [];
17
+ for (const raw of String(stdout || "").split("\n")) {
18
+ const line = raw.trim();
19
+ if (!line.startsWith("{")) continue;
20
+ let event;
21
+ try { event = JSON.parse(line); } catch { continue; }
22
+ if (event.type === "thread.started" && event.thread_id) threadId = event.thread_id;
23
+ if (
24
+ event.type === "item.completed" &&
25
+ event.item?.type === "agent_message" &&
26
+ event.item.text
27
+ ) {
28
+ messages.push(String(event.item.text));
29
+ }
30
+ }
31
+ return { threadId, text: messages.join("\n\n").trim() };
32
+ }
33
+
9
34
  export default {
10
35
  id: "codex",
11
36
  binary: "codex",
12
37
  versionFlag: "--version",
38
+ sessions: "capture",
13
39
 
14
- async run({ system, prompt, cwd, env, timeoutMs }) {
40
+ async run({ system, prompt, cwd, env, timeoutMs, resumeSessionId = null, mode = "code" }) {
15
41
  const fullPrompt = system ? `${system}\n\n---\n\n${prompt}` : prompt;
16
- const r = await runProcess({
17
- command: "codex",
18
- args: ["exec", "--sandbox", "workspace-write", "--skip-git-repo-check", fullPrompt],
19
- cwd,
20
- env,
21
- timeoutMs,
22
- });
42
+ // `exec resume` takes no --sandbox: it inherits the sandbox the thread was
43
+ // opened with, and passing the flag is an error rather than a no-op. Which
44
+ // means the FIRST turn decides what the thread may touch for its whole life.
45
+ const sandbox = mode === "chat" ? "read-only" : "workspace-write";
46
+ const args = resumeSessionId
47
+ ? ["exec", "resume", resumeSessionId, "--skip-git-repo-check", "--json", fullPrompt]
48
+ : ["exec", "--sandbox", sandbox, "--skip-git-repo-check", "--json", fullPrompt];
49
+
50
+ const r = await runProcess({ command: "codex", args, cwd, env, timeoutMs });
51
+ const { threadId, text } = parseCodexEvents(r.stdout);
52
+
23
53
  return {
24
54
  exitCode: r.exitCode,
25
- output: r.stdout.trim(),
55
+ // A build that emitted no parsable event still said something on stdout;
56
+ // falling back to the raw text keeps this adapter working as before.
57
+ output: text || String(r.stdout || "").trim(),
26
58
  stderr: r.stderr,
59
+ killed: r.killed,
60
+ sessionId: threadId || resumeSessionId || null,
27
61
  externalSessionPath: null,
28
62
  };
29
63
  },
@@ -11,9 +11,24 @@
11
11
  // id,
12
12
  // binary, executable name to look for in PATH
13
13
  // versionFlag, flag to print the version
14
- // async run({ system, prompt, cwd, env, timeoutMs })
15
- // { exitCode, output, externalSessionPath?, raw? }
14
+ // sessions, "capture" when it can continue its own
15
+ // conversation; absent when every run
16
+ // starts cold
17
+ // async run({ system, prompt, cwd, env, timeoutMs,
18
+ // sessionKey, resumeSessionId })
19
+ // → { exitCode, output, sessionId?, externalSessionPath?, raw? }
16
20
  // }
21
+ //
22
+ // The session arguments are what turn a runtime from a one-shot into a real
23
+ // a2a peer: `resumeSessionId` continues the conversation the peer already has,
24
+ // and `sessionId` comes back so the caller can store it and resume again next
25
+ // turn. `sessionKey` is a stable name for the exchange, for CLIs that can only
26
+ // find their own session again by title (opencode); the ones that hand their id
27
+ // straight back (claude-code, codex) ignore it.
28
+ //
29
+ // A runtime WITHOUT sessions is not shut out of a2a — the caller flattens the
30
+ // thread history into the prompt instead. Sessions only make that unnecessary,
31
+ // which is the point: a resumed peer does not re-read what it already knows.
17
32
 
18
33
  import claudeCode from "./claude-code.js";
19
34
  import codex from "./codex.js";
@@ -1,27 +1,106 @@
1
1
  // OpenCode runtime adapter. Uses headless run:
2
2
  // opencode run "<prompt>"
3
+ // opencode run --session <id> "<prompt>" continue an earlier exchange
3
4
  // Reference: https://opencode.ai/docs/
4
5
 
6
+ import fs from "node:fs";
7
+ import path from "node:path";
5
8
  import { runProcess } from "./_spawn.js";
6
9
 
10
+ // opencode prints an "agent · model" banner and ANSI colour even when its stdout
11
+ // is a pipe. Neither is part of the answer, and an a2a reply is logged verbatim
12
+ // — so a banner would be filed as the peer's first sentence.
13
+ const ANSI = /\u001b\[[0-9;]*[A-Za-z]/g;
14
+ const BANNER = /^>\s+\S+\s+\S\s+\S+\s*$/;
15
+
16
+ function cleanOutput(stdout) {
17
+ const lines = String(stdout || "").replace(ANSI, "").split("\n");
18
+ while (lines.length && !lines[0].trim()) lines.shift();
19
+ // Exactly one banner, and only when it leads: a reply that legitimately
20
+ // opens with a quoted line has to survive intact.
21
+ if (lines.length && BANNER.test(lines[0])) lines.shift();
22
+ return lines.join("\n").trim();
23
+ }
24
+
25
+ // opencode mints its own session ids and refuses one it did not create
26
+ // ("Session not found"), so APX cannot dictate the id the way Claude Code
27
+ // allows. What it CAN do is name the session on the way in (--title) and read
28
+ // the id back out of `session list`, which speaks JSON. One extra call, only on
29
+ // a thread's first turn — after that the id is on the ledger.
30
+ async function findSessionByTitle({ title, cwd, env }) {
31
+ const r = await runProcess({
32
+ command: "opencode",
33
+ args: ["session", "list", "--format", "json", "-n", "40"],
34
+ cwd,
35
+ env,
36
+ timeoutMs: 20000,
37
+ });
38
+ if (r.exitCode !== 0) return null;
39
+ let rows;
40
+ try {
41
+ rows = JSON.parse(r.stdout);
42
+ } catch {
43
+ return null;
44
+ }
45
+ if (!Array.isArray(rows)) return null;
46
+ const named = rows.filter((s) => s && s.title === title);
47
+ // Sessions are listed across projects; prefer the one opened here.
48
+ const here = named.filter((s) => !cwd || !s.directory || s.directory === cwd);
49
+ const pick = (here.length ? here : named).sort((a, b) => (b.updated || 0) - (a.updated || 0))[0];
50
+ return pick?.id || null;
51
+ }
52
+
53
+ /**
54
+ * Why the session we just opened is not in opencode's own list.
55
+ *
56
+ * Observed: inside a git checkout `run --title X` is listed and resumable;
57
+ * in a plain directory the run succeeds but never appears, so there is no id to
58
+ * resume. Saying which case this is beats a silent null — the exchange still
59
+ * works (APX carries the thread in the prompt), it just costs a re-read a turn.
60
+ */
61
+ function missingSessionReason(cwd) {
62
+ let dir = cwd || process.cwd();
63
+ for (;;) {
64
+ if (fs.existsSync(path.join(dir, ".git"))) return "opencode did not list the session it just opened";
65
+ const up = path.dirname(dir);
66
+ if (up === dir) break;
67
+ dir = up;
68
+ }
69
+ return "opencode keeps no resumable session outside a git repo — the thread travels in the prompt instead";
70
+ }
71
+
7
72
  export default {
8
73
  id: "opencode",
9
74
  binary: "opencode",
10
75
  versionFlag: "--version",
76
+ sessions: "capture",
11
77
 
12
- async run({ system, prompt, cwd, env, timeoutMs }) {
78
+ async run({ system, prompt, cwd, env, timeoutMs, sessionKey = null, resumeSessionId = null, mode = "code" }) {
13
79
  const fullPrompt = system ? `${system}\n\n---\n\n${prompt}` : prompt;
14
- const r = await runProcess({
15
- command: "opencode",
16
- args: ["run", fullPrompt],
17
- cwd,
18
- env,
19
- timeoutMs,
20
- });
80
+ const args = ["run"];
81
+ // `plan` is opencode's own read-only primary agent; `build` (its default)
82
+ // may write. A plain a2a message gets the one that only talks.
83
+ if (mode === "chat") args.push("--agent", "plan");
84
+ if (resumeSessionId) args.push("--session", resumeSessionId);
85
+ else if (sessionKey) args.push("--title", sessionKey);
86
+ args.push(fullPrompt);
87
+
88
+ const r = await runProcess({ command: "opencode", args, cwd, env, timeoutMs });
89
+
90
+ let sessionId = resumeSessionId || null;
91
+ let sessionNote = null;
92
+ if (!sessionId && sessionKey && r.exitCode === 0) {
93
+ sessionId = await findSessionByTitle({ title: sessionKey, cwd, env });
94
+ if (!sessionId) sessionNote = missingSessionReason(cwd);
95
+ }
96
+
21
97
  return {
22
98
  exitCode: r.exitCode,
23
- output: r.stdout.trim(),
99
+ output: cleanOutput(r.stdout),
24
100
  stderr: r.stderr,
101
+ killed: r.killed,
102
+ sessionId,
103
+ sessionNote,
25
104
  externalSessionPath: null,
26
105
  };
27
106
  },
@@ -0,0 +1,119 @@
1
+ import { runProcess } from "./_spawn.js";
2
+ import { detectAll } from "./detect.js";
3
+
4
+ // Did the runtime actually do the work, and if not, what does the user need to
5
+ // hear? Shared by every caller that spawns a CLI — the super-agent's
6
+ // `call_runtime` tool and the a2a peer reply — because "exit 0 with nothing on
7
+ // stdout" has to mean the same thing on both paths. A second copy of this
8
+ // judgement is how one caller starts reporting a logged-out CLI as success.
9
+
10
+ // A CLI that refuses to work says why in one line — "Not logged in · Please run
11
+ // /login", "usage limit reached", "model requires a newer version". That line is
12
+ // the whole diagnosis, and an `exit 1` that drops it leaves the model, the
13
+ // session record and the daemon log all equally blind. Prefer stderr (where
14
+ // CLIs put refusals), fall back to stdout (claude -p puts them in .result).
15
+ // A machine-readable runtime answers in JSON; pasting the envelope would bury
16
+ // the sentence inside it, so unwrap the field that carries the message.
17
+ // Lines that carry a diagnosis rather than the machinery around it.
18
+ const STACK_FRAME = /^(at\s|\.\.\.\s|Node\.js v)/;
19
+ const DIAGNOSIS = /(error|failed|denied|invalid|expired|not logged|log ?in|usage limit|quota|unauthor|forbidden|not found|missing|required)/i;
20
+
21
+ export function diagnosticLine(r) {
22
+ const pick = String(r?.stderr || "").trim() || String(r?.output || "").trim();
23
+ if (!pick) return "";
24
+ // A crashing CLI ends on `at async main (…cli.js:539307:5)`, which says
25
+ // nothing. Prefer the last line that reads like a cause; a stack frame is
26
+ // never one, and blindly taking the last line reported a 401 as a file path.
27
+ const lines = pick.split("\n").map((l) => l.trim()).filter(Boolean);
28
+ const meaningful = lines.filter((l) => !STACK_FRAME.test(l));
29
+ const line =
30
+ meaningful.filter((l) => DIAGNOSIS.test(l)).pop() ||
31
+ meaningful.pop() ||
32
+ lines.pop() ||
33
+ "";
34
+ if (line.startsWith("{")) {
35
+ try {
36
+ const o = JSON.parse(line);
37
+ const msg = o.result || o.error?.message || o.error || o.message;
38
+ if (typeof msg === "string" && msg.trim()) return msg.trim().slice(0, 160);
39
+ } catch { /* not JSON after all — fall through to the raw line */ }
40
+ }
41
+ return line.slice(0, 160);
42
+ }
43
+
44
+ // Decide if the runtime actually did the work the caller asked for. A spawn
45
+ // failure (-1), a non-zero exit, or a clean exit with no captured output and
46
+ // no transcript path all point at "process didn't really run" — exactly the
47
+ // false-positive scenario this guard exists to catch.
48
+ export function runtimeLooksLikeFailure(r, { timedOut = false, timeoutS = 0 } = {}) {
49
+ if (!r) return { failed: true, reason: "no runtime result" };
50
+ if (r.exitCode === -1 || r.error) {
51
+ return { failed: true, reason: r.error || "spawn error" };
52
+ }
53
+ // Order matters: we SIGTERM'd it ourselves, so whatever it exits with is our
54
+ // own signal echoed back. Reading that as the CLI's verdict would report a
55
+ // timeout as a crash — or, when the exit code is null, as "empty output".
56
+ // `r.killed` only arrives from adapters that bother to forward it; the clock
57
+ // is what every runtime has in common, so it decides.
58
+ if (timedOut || r.killed) {
59
+ return { failed: true, reason: `killed (timeout after ${timeoutS}s)` };
60
+ }
61
+ if (typeof r.exitCode === "number" && r.exitCode !== 0) {
62
+ const why = diagnosticLine(r);
63
+ return { failed: true, reason: why ? `exit ${r.exitCode}: ${why}` : `exit ${r.exitCode}` };
64
+ }
65
+ const out = String(r.output || "").trim();
66
+ const stderr = String(r.stderr || "").trim();
67
+ if (!out && !r.externalSessionPath && !r.sessionId) {
68
+ return {
69
+ failed: true,
70
+ reason: stderr ? `empty output (stderr: ${stderr.slice(0, 120)})` : "empty output",
71
+ };
72
+ }
73
+ return { failed: false };
74
+ }
75
+
76
+ // How long we wait for `<binary> --version` before giving up on the answer.
77
+ // Not how long we wait for the runtime itself — that is the caller's timeout.
78
+ export const PROBE_TIMEOUT_MS = 3000;
79
+
80
+ /**
81
+ * Can this runtime run at all? Answered BEFORE spawning it for real, because
82
+ * "spawn error" is a useless thing to tell someone whose CLI is simply not
83
+ * installed. Shared with the super-agent's call_runtime tool so a missing
84
+ * binary reads the same however it was reached.
85
+ */
86
+ export async function runtimeAvailability(runtime, rt, { probeTimeoutMs = PROBE_TIMEOUT_MS } = {}) {
87
+ const probe = await runProcess({
88
+ command: rt.binary,
89
+ args: rt.versionFlag ? [rt.versionFlag] : ["--version"],
90
+ timeoutMs: probeTimeoutMs,
91
+ });
92
+ if (probe.exitCode === 0 || probe.stdout || probe.stderr) {
93
+ return { ok: true };
94
+ }
95
+ // A probe WE killed is not evidence of absence — it is evidence of presence.
96
+ // A binary that is not there fails at spawn (ENOENT, exitCode -1) and never
97
+ // gets far enough to be killed, so `killed` can only mean the binary exists,
98
+ // started, and was slower than our clock. Under load `--version` really does
99
+ // take longer than three seconds, and reading that as "not installed" refused
100
+ // to run a CLI sitting right there — then fell into detectAll() below, which
101
+ // spawns EVERY coding CLI on the machine to reach a verdict we already had.
102
+ if (probe.killed) {
103
+ return { ok: true };
104
+ }
105
+
106
+ const detected = await detectAll();
107
+ const current = detected.find((d) => d.id === runtime || d.binary === rt.binary);
108
+ if (current?.installed) {
109
+ return { ok: true, detected };
110
+ }
111
+ return {
112
+ ok: false,
113
+ reason: current?.reason || `${rt.binary} not found`,
114
+ detected,
115
+ installed: detected
116
+ .filter((d) => d.category === "runtime" && d.installed)
117
+ .map((d) => d.id),
118
+ };
119
+ }