@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
@@ -12,10 +12,12 @@ export const CHANNELS = Object.freeze({
12
12
  API: "api",
13
13
  WEB: "web", // Web admin big chat
14
14
  WEB_SIDEBAR: "web_sidebar", // Web admin docked sidebar
15
- WEB_CODE: "web_code", // Web admin `/m/code` (OpenCode-style)
15
+ WEB_CODE: "web_code", // Web admin `/code` (OpenCode-style)
16
16
  DECK: "deck", // Mobile cockpit dashboard
17
17
  DESKTOP: "desktop", // Electron capsule (always voice mode)
18
18
  CODE: "code", // `apx code` — terminal coding session
19
+ A2A: "a2a", // Agent-to-agent relay (project-scoped ledger)
20
+ LOG: "log", // Readable, never delivered (routine abstentions)
19
21
  DIRECT: "direct", // Planned: 1:1 channel that isn't a chat platform
20
22
  WHATSAPP: "whatsapp", // Planned: WhatsApp bot integration
21
23
  });
@@ -0,0 +1,73 @@
1
+ // What KIND of thing a task is — orthogonal to `state` (open/done/dropped),
2
+ // to `status` (pending/running/…), and to `tags`.
3
+ //
4
+ // Tags stay exactly what they were: free-form labels the owner invents. A
5
+ // category is a closed set the SYSTEM can act on, which is the whole point:
6
+ // "this is an errand, at this place" is a fact the daemon can route on without
7
+ // asking a model to read the title and guess. That guess is what a category
8
+ // replaces — a mobility reminder for a categorised task costs no geocoding,
9
+ // no place search and no LLM call.
10
+ //
11
+ // Registry pattern (AGENTS.md): adding a category is one entry here plus its
12
+ // two i18n keys. Nothing else switches on the id.
13
+ export const TASK_CATEGORIES = Object.freeze({
14
+ // The default. A task that is just a task.
15
+ general: Object.freeze({ id: "general", icon: "circle-dot", locatable: false }),
16
+ // Something to do while out — an errand with a place. `locatable` is what
17
+ // makes the mobility geofence consider it, and what makes the web offer the
18
+ // place fields.
19
+ trip: Object.freeze({ id: "trip", icon: "car", locatable: true }),
20
+ });
21
+
22
+ export const TASK_CATEGORY_IDS = Object.freeze(Object.keys(TASK_CATEGORIES));
23
+ export const DEFAULT_TASK_CATEGORY = "general";
24
+
25
+ /** Unknown or missing → the default. Never throws: this reads stored data. */
26
+ export function normalizeTaskCategory(value) {
27
+ const id = String(value || "").trim().toLowerCase();
28
+ return TASK_CATEGORY_IDS.includes(id) ? id : DEFAULT_TASK_CATEGORY;
29
+ }
30
+
31
+ /** Can a task of this category carry a place? */
32
+ export function categoryIsLocatable(value) {
33
+ return TASK_CATEGORIES[normalizeTaskCategory(value)].locatable === true;
34
+ }
35
+
36
+ function finite(value) {
37
+ const number = Number(value);
38
+ return Number.isFinite(number) ? number : null;
39
+ }
40
+
41
+ function text(value, max) {
42
+ return typeof value === "string" ? value.trim().slice(0, max) : "";
43
+ }
44
+
45
+ /**
46
+ * A task's place, normalized. Returns null when there is nothing usable —
47
+ * a half-filled location is worse than none, because everything downstream
48
+ * would treat it as an answer.
49
+ *
50
+ * `place` alone is valid: it names somewhere without pinning it, which is
51
+ * still enough for a reminder to be worth reading. Coordinates are only kept
52
+ * as a pair, and only when both are in range.
53
+ */
54
+ export function normalizeTaskLocation(value) {
55
+ if (!value || typeof value !== "object") return null;
56
+ const place = text(value.place ?? value.name, 200);
57
+ const address = text(value.address, 300);
58
+ const latitude = finite(value.latitude ?? value.lat);
59
+ const longitude = finite(value.longitude ?? value.lon ?? value.lng);
60
+ const pinned =
61
+ latitude != null && longitude != null &&
62
+ latitude >= -90 && latitude <= 90 &&
63
+ longitude >= -180 && longitude <= 180;
64
+ if (!place && !address && !pinned) return null;
65
+ return {
66
+ ...(place ? { place } : {}),
67
+ ...(address ? { address } : {}),
68
+ ...(pinned ? { latitude, longitude } : {}),
69
+ // How close counts as "there". Absent means the caller had no opinion and
70
+ // the mobility default applies.
71
+ ...(finite(value.radius_m) != null ? { radius_m: finite(value.radius_m) } : {}),
72
+ };
73
+ }
@@ -0,0 +1,28 @@
1
+ import { OWNER_ACTOR_ID } from "./actors.js";
2
+
3
+ export const TASK_PRIORITIES = Object.freeze(["low", "normal", "high", "urgent"]);
4
+ export const DEFAULT_TASK_PRIORITY = "normal";
5
+
6
+ export const TASK_REMINDER_FREQUENCIES = Object.freeze(["none", "once", "daily", "weekly"]);
7
+ export const DEFAULT_TASK_REMINDER_FREQUENCY = "none";
8
+
9
+ /** `human` is accepted at every write boundary; storage stays canonical. */
10
+ export function normalizeTaskAssignee(value) {
11
+ const assignee = typeof value === "string" ? value.trim() : "";
12
+ if (!assignee) return null;
13
+ return ["human", OWNER_ACTOR_ID].includes(assignee.toLowerCase())
14
+ ? OWNER_ACTOR_ID
15
+ : assignee;
16
+ }
17
+
18
+ export function normalizeTaskPriority(value) {
19
+ const priority = String(value || "").trim().toLowerCase();
20
+ return TASK_PRIORITIES.includes(priority) ? priority : DEFAULT_TASK_PRIORITY;
21
+ }
22
+
23
+ export function normalizeTaskReminderFrequency(value) {
24
+ const frequency = String(value || "").trim().toLowerCase();
25
+ return TASK_REMINDER_FREQUENCIES.includes(frequency)
26
+ ? frequency
27
+ : DEFAULT_TASK_REMINDER_FREQUENCY;
28
+ }
@@ -0,0 +1,33 @@
1
+ // Shell-style glob matching for model ids.
2
+ //
3
+ // Several adapters gate a wire-format quirk on WHICH model is answering rather
4
+ // than on which provider it came from: Gemini's thought signatures, DeepSeek's
5
+ // reasoning replay. Declaring those as glob patterns keeps "which models need
6
+ // this" a list an operator can read and a config key can override, instead of
7
+ // a branch buried in the serialiser.
8
+ //
9
+ // Patterns match the bare model id (no `<provider>:` prefix): `*` is any run of
10
+ // characters, `?` a single one. Matching is case-insensitive.
11
+
12
+ function globToRegExp(pattern) {
13
+ const escaped = String(pattern).replace(/[.+^${}()|[\]\\]/g, "\\$&");
14
+ return new RegExp(`^${escaped.replace(/\*/g, ".*").replace(/\?/g, ".")}$`, "i");
15
+ }
16
+
17
+ /** Does `model` match any of `patterns`? An empty list matches nothing. */
18
+ export function matchesModelGlob(model, patterns) {
19
+ if (!Array.isArray(patterns) || patterns.length === 0) return false;
20
+ const id = String(model || "");
21
+ return patterns.some((p) => globToRegExp(p).test(id));
22
+ }
23
+
24
+ /**
25
+ * Resolve "which models use this mechanism" from config, falling back to the
26
+ * adapter's built-in list.
27
+ *
28
+ * A configured array REPLACES the default — it is the whole answer to the
29
+ * question, so an install can also opt out entirely with an explicit `[]`.
30
+ */
31
+ export function modelListFromConfig(configured, builtIn) {
32
+ return Array.isArray(configured) ? configured : builtIn;
33
+ }
@@ -9,6 +9,24 @@ function getKey(config) {
9
9
  return config.api_key || process.env.ANTHROPIC_API_KEY || "";
10
10
  }
11
11
 
12
+ /** Anthropic multimodal content blocks. Images ride on `m.images` the same
13
+ * way Gemini/OpenAI adapters read them — without this, Claude never saw
14
+ * photos attached to a turn. */
15
+ function contentForAnthropic(m) {
16
+ const text = typeof m.content === "string" ? m.content : JSON.stringify(m.content ?? "");
17
+ const imgs = Array.isArray(m.images)
18
+ ? m.images.filter((im) => im && im.data && im.mime)
19
+ : [];
20
+ if (!imgs.length) return text;
21
+ return [
22
+ ...(text ? [{ type: "text", text }] : []),
23
+ ...imgs.map((im) => ({
24
+ type: "image",
25
+ source: { type: "base64", media_type: im.mime, data: im.data },
26
+ })),
27
+ ];
28
+ }
29
+
12
30
  export default {
13
31
  id: "anthropic",
14
32
  needsApiKey: true,
@@ -39,7 +57,7 @@ export default {
39
57
  temperature,
40
58
  messages: messages.map((m) => ({
41
59
  role: m.role === "assistant" ? "assistant" : "user",
42
- content: typeof m.content === "string" ? m.content : JSON.stringify(m.content),
60
+ content: contentForAnthropic(m),
43
61
  })),
44
62
  };
45
63
  if (system) body.system = system;
@@ -3,6 +3,7 @@
3
3
  // { error }. Pure transport — no daemon dependencies. Both the daemon HTTP
4
4
  // adapter and CLI commands can reuse this.
5
5
  import { fetchJsonWithTimeout } from "./_health.js";
6
+ import { ZEN_HEADERS } from "./zen.js";
6
7
 
7
8
  export const DEFAULT_BASE = {
8
9
  openai: "https://api.openai.com/v1",
@@ -11,6 +12,7 @@ export const DEFAULT_BASE = {
11
12
  gemini: "https://generativelanguage.googleapis.com/v1beta/openai",
12
13
  anthropic: "https://api.anthropic.com/v1",
13
14
  ollama: "http://localhost:11434",
15
+ zen: "https://opencode.ai/zen/v1",
14
16
  };
15
17
 
16
18
  // Gemini's native models endpoint returns a much richer catalog than the
@@ -66,6 +68,24 @@ export async function listModels(engine, baseUrl, apiKey) {
66
68
  return { models };
67
69
  }
68
70
 
71
+ // Zen publishes its catalog without a key, so the model picker can be filled
72
+ // before the user has one — useful, since choosing a model is how you decide
73
+ // whether the provider is worth signing up for.
74
+ if (engine === "zen") {
75
+ const r = await fetchJsonWithTimeout(`${base || DEFAULT_BASE.zen}/models`, {
76
+ timeoutMs: 5000,
77
+ headers: { ...ZEN_HEADERS, ...(apiKey ? { authorization: `Bearer ${apiKey}` } : {}) },
78
+ });
79
+ if (!r.ok) return { error: r.reason || `HTTP ${r.status}` };
80
+ const list = Array.isArray(r.json?.data) ? r.json.data : [];
81
+ const ids = list.map((m) => m?.id).filter(Boolean);
82
+ // Free-tier ids first. The catalog mixes models that bill at zero with
83
+ // Claude/GPT/Gemini ones that very much do not, under names that don't say
84
+ // which is which — so the cheap ones are the ones you scroll to first.
85
+ const free = (id) => /-free$/.test(id) || id === "big-pickle";
86
+ return { models: [...ids.filter(free).sort(), ...ids.filter((id) => !free(id)).sort()] };
87
+ }
88
+
69
89
  // openai-compatible family: openai, groq, openrouter, azure, custom
70
90
  if (!apiKey) return { error: "falta api_key" };
71
91
  if (!base) return { error: "falta base_url" };
@@ -2,6 +2,8 @@
2
2
  // Direct fetch, no SDK. Supports function calling (Gemini's name for tool
3
3
  // use) so it can drive the super-agent loop on parity with Groq / OpenAI.
4
4
  import { randomUUID } from "node:crypto";
5
+ import { matchesModelGlob, modelListFromConfig } from "./_globs.js";
6
+ import { streamSseDataEvents } from "./_streaming.js";
5
7
 
6
8
  const API_BASE = "https://generativelanguage.googleapis.com/v1beta/models";
7
9
 
@@ -71,6 +73,55 @@ function markExhausted(model, key, now = Date.now()) {
71
73
  exhausted.set(cooldownKey(model, key), reset.getTime());
72
74
  }
73
75
 
76
+ /**
77
+ * Read a `streamGenerateContent?alt=sse` response and rebuild the single
78
+ * response object the non-streaming path returns, so everything downstream —
79
+ * thought filtering, functionCall extraction, thought-signature replay — runs
80
+ * on one shape and stays unaware that streaming happened.
81
+ *
82
+ * Visible text deltas are handed to `onToken` as they arrive. Thought parts are
83
+ * NOT: they are the model's internal reasoning, and the desktop speaks what it
84
+ * streams.
85
+ */
86
+ async function readGeminiStream(response, onToken) {
87
+ const parts = [];
88
+ let finishReason = null;
89
+ let usageMetadata = null;
90
+
91
+ const isTextPart = (p) => typeof p?.text === "string" && !(p.functionCall || p.function_call);
92
+
93
+ for await (const evt of streamSseDataEvents(response)) {
94
+ const cand = evt?.candidates?.[0];
95
+ if (evt?.usageMetadata) usageMetadata = evt.usageMetadata;
96
+ if (cand?.finishReason) finishReason = cand.finishReason;
97
+
98
+ for (const p of cand?.content?.parts || []) {
99
+ if (isTextPart(p) && !p.thought && p.text) {
100
+ try { onToken(p.text); } catch { /* a consumer throwing must not kill the turn */ }
101
+ }
102
+ // Text arrives in fragments; fold consecutive same-kind text parts back
103
+ // into one so the replayed model turn matches what a single-shot call
104
+ // would have produced. functionCall parts always arrive whole.
105
+ const last = parts[parts.length - 1];
106
+ if (
107
+ isTextPart(p) && last && isTextPart(last) &&
108
+ Boolean(last.thought) === Boolean(p.thought)
109
+ ) {
110
+ last.text += p.text || "";
111
+ const sig = p.thoughtSignature || p.thought_signature;
112
+ if (sig) last.thoughtSignature = sig;
113
+ continue;
114
+ }
115
+ parts.push({ ...p });
116
+ }
117
+ }
118
+
119
+ return {
120
+ candidates: [{ content: { parts }, finishReason }],
121
+ ...(usageMetadata ? { usageMetadata } : {}),
122
+ };
123
+ }
124
+
74
125
  /** Did this response mean "this key has no quota left", as opposed to a real error? */
75
126
  function isQuotaError(status, json) {
76
127
  if (status === 429) return true;
@@ -150,21 +201,13 @@ export const THOUGHT_SIGNATURE_MODELS = [
150
201
  "gemini-5*",
151
202
  ];
152
203
 
153
- function globToRegExp(pattern) {
154
- const escaped = String(pattern).replace(/[.+^${}()|[\]\\]/g, "\\$&");
155
- return new RegExp(`^${escaped.replace(/\*/g, ".*").replace(/\?/g, ".")}$`, "i");
156
- }
157
-
158
204
  // Per-install override, no code change required:
159
205
  // engines.gemini.thought_signature_models: ["gemini-3*", "my-tuned-model*"]
160
- // A configured list REPLACES the built-in default — it is the whole answer to
161
- // "which models use this mechanism", so an install can also opt out entirely
162
- // with an explicit empty list.
163
206
  export function modelUsesThoughtSignatures(model, config = {}) {
164
- const configured = config?.thought_signature_models;
165
- const patterns = Array.isArray(configured) ? configured : THOUGHT_SIGNATURE_MODELS;
166
- const id = String(model || "");
167
- return patterns.some((p) => globToRegExp(p).test(id));
207
+ return matchesModelGlob(
208
+ model,
209
+ modelListFromConfig(config?.thought_signature_models, THOUGHT_SIGNATURE_MODELS)
210
+ );
168
211
  }
169
212
 
170
213
  function historyHasSignature(messages) {
@@ -193,7 +236,7 @@ function signaturesRequired(model, messages, config) {
193
236
  // their thoughtSignature) that the signing families require in every
194
237
  // subsequent turn. Falling back to reconstruction handles messages that came
195
238
  // from a non-Gemini engine or were serialised before this field was added.
196
- function toGeminiContents(messages, { model = "", config = {} } = {}) {
239
+ export function toGeminiContents(messages, { model = "", config = {} } = {}) {
197
240
  const requireSignatures = signaturesRequired(model, messages, config);
198
241
  const out = [];
199
242
  // tool_call ids whose functionCall part we could not replay with a valid
@@ -231,6 +274,16 @@ function toGeminiContents(messages, { model = "", config = {} } = {}) {
231
274
  } else {
232
275
  out.push({ role: "user", parts: [part] });
233
276
  }
277
+ // A multimodal tool result (view_media) carries images the model should
278
+ // SEE. A functionResponse can't hold pixels, so the image rides on a
279
+ // following user turn with a short cue, right after the result.
280
+ if (Array.isArray(m.images) && m.images.length) {
281
+ const imgParts = [{ text: `(imagen de ${name})` }];
282
+ for (const img of m.images) {
283
+ if (img?.data && img?.mime) imgParts.push({ inlineData: { mimeType: img.mime, data: img.data } });
284
+ }
285
+ if (imgParts.length > 1) out.push({ role: "user", parts: imgParts });
286
+ }
234
287
  continue;
235
288
  }
236
289
 
@@ -334,6 +387,7 @@ export default {
334
387
  toolChoice,
335
388
  config = {},
336
389
  signal,
390
+ onToken,
337
391
  }) {
338
392
  const keys = getKeys(config);
339
393
  if (!keys.length) throw new Error("gemini: no api_key (set GEMINI_API_KEY or engines.gemini.api_key)");
@@ -366,20 +420,34 @@ export default {
366
420
  // request, not the turn.
367
421
  const order = fresh.length ? fresh : keys;
368
422
 
423
+ // Streaming is opt-in per call: the caller wants tokens as they land, and
424
+ // the turn isn't forcing a function call (mode ANY produces a call, not
425
+ // prose — there'd be nothing to stream). Same request body either way; only
426
+ // the endpoint and how the response is read differ, so the key rotation and
427
+ // error handling below stay shared.
428
+ const wantsStream =
429
+ typeof onToken === "function" && toolChoice !== "required" && toolChoice !== "any";
430
+
369
431
  let json;
370
432
  let lastError = null;
371
433
  for (let i = 0; i < order.length; i++) {
372
434
  const key = order[i];
373
- const url = `${API_BASE}/${encodeURIComponent(model)}:generateContent?key=${key}`;
435
+ const verb = wantsStream ? "streamGenerateContent?alt=sse&" : "generateContent?";
436
+ const url = `${API_BASE}/${encodeURIComponent(model)}:${verb}key=${key}`;
374
437
  const res = await fetch(url, {
375
438
  method: "POST",
376
439
  headers: { "content-type": "application/json" },
377
440
  body: JSON.stringify(body),
378
441
  signal,
379
442
  });
380
- const payload = await res.json();
381
443
 
382
- if (res.ok) { json = payload; break; }
444
+ // An SSE response body must not be read as JSON, so settle the ok/error
445
+ // question on the status first and only then choose how to read it.
446
+ if (res.ok) {
447
+ json = wantsStream ? await readGeminiStream(res, onToken) : await res.json();
448
+ break;
449
+ }
450
+ const payload = await res.json().catch(() => ({}));
383
451
 
384
452
  if (isQuotaError(res.status, payload)) {
385
453
  markExhausted(model, key);
@@ -17,9 +17,10 @@ import groq from "./groq.js";
17
17
  import openrouter from "./openrouter.js";
18
18
  import ollama from "./ollama.js";
19
19
  import gemini from "./gemini.js";
20
+ import zen from "./zen.js";
20
21
  import mock from "./mock.js";
21
22
 
22
- const ADAPTERS = { anthropic, openai, groq, openrouter, ollama, gemini, mock };
23
+ const ADAPTERS = { anthropic, openai, groq, openrouter, ollama, gemini, zen, mock };
23
24
 
24
25
  export function resolveProvider(modelId) {
25
26
  if (typeof modelId !== "string" || !modelId) {
@@ -38,6 +39,18 @@ export function resolveProvider(modelId) {
38
39
  );
39
40
  }
40
41
 
42
+ /**
43
+ * The adapter behind a provider *slug*. A slug is not always an adapter id:
44
+ * a provider named "carlos" running on Ollama is stored as
45
+ * `engines.carlos = { engine: "ollama", … }`, and "carlos:llama3.2" has to
46
+ * reach the ollama adapter. Falls back to the slug itself, which is the case
47
+ * for the stock providers whose slug already is the engine id.
48
+ */
49
+ export function adapterForSlug(slug, config) {
50
+ const cfg = (config && config.engines && config.engines[slug]) || {};
51
+ return getAdapter(cfg.engine || slug);
52
+ }
53
+
41
54
  export function getAdapter(provider) {
42
55
  const a = ADAPTERS[provider];
43
56
  if (!a) {
@@ -48,10 +61,12 @@ export function getAdapter(provider) {
48
61
  return a;
49
62
  }
50
63
 
51
- export async function callEngine({ modelId, system, messages, config, temperature, maxTokens, tools, toolChoice, signal, onToken }) {
64
+ export async function callEngine({ modelId, system, messages, config, temperature, maxTokens, tools, toolChoice, signal, onToken, onReasoningToken }) {
52
65
  const { provider, model } = resolveProvider(modelId);
53
- const adapter = getAdapter(provider);
54
66
  const providerCfg = (config && config.engines && config.engines[provider]) || {};
67
+ // `provider` here is the slug the user configured, which only coincides with
68
+ // the adapter id for the stock providers.
69
+ const adapter = getAdapter(providerCfg.engine || provider);
55
70
  // The per-provider `default_max_tokens` set in the web admin (Provider modal
56
71
  // slider) acts as a floor: callers may ask for more, but never less. This
57
72
  // matters for "thinking" models (e.g. Gemini 3.x) whose internal reasoning
@@ -73,6 +88,7 @@ export async function callEngine({ modelId, system, messages, config, temperatur
73
88
  config: providerCfg,
74
89
  signal,
75
90
  onToken,
91
+ onReasoningToken,
76
92
  });
77
93
  }
78
94
 
@@ -10,9 +10,26 @@ export default {
10
10
  return { ok: true, soft: true };
11
11
  },
12
12
 
13
- async chat({ system, messages, model = "mock", tools }) {
13
+ async chat({ system, messages, model = "mock", tools, signal }) {
14
+ const forcedStatus = String(model).match(/^fail-(\d{3})$/)?.[1];
15
+ if (forcedStatus) throw new Error(`mock ${forcedStatus}: forced test failure`);
14
16
  const last = [...messages].reverse().find((m) => m.role === "user");
15
17
  const userText = last?.content || "";
18
+ // `[mock:slow:<ms>]` → hold each step for <ms> before answering, and honor
19
+ // the abort signal while holding. A real engine call takes time, and
20
+ // anything about what happens DURING a turn — cancelling it, interrupting
21
+ // it, watching it stream — cannot be tested against a mock that finishes a
22
+ // 400-step loop in under a second. Capped so a typo cannot hang a suite.
23
+ const slowMs = Math.min(parseInt(userText.match(/\[mock:slow:(\d+)\]/)?.[1] ?? "0", 10) || 0, 5000);
24
+ if (slowMs) {
25
+ await new Promise((resolve, reject) => {
26
+ const t = setTimeout(resolve, slowMs);
27
+ signal?.addEventListener?.("abort", () => {
28
+ clearTimeout(t);
29
+ reject(Object.assign(new Error("aborted"), { name: "AbortError" }));
30
+ }, { once: true });
31
+ });
32
+ }
16
33
  // Mirror real engines: tool calls are only possible when the caller offers
17
34
  // tools. The loop withholds them on its tool-free wrap-up step, and we must
18
35
  // honor that here — otherwise the mock would keep "calling" tools the model
@@ -22,6 +39,16 @@ export default {
22
39
  const loopTool = userText.match(/\[mock:loop:([a-z_]+)\]/)?.[1];
23
40
  const finishSummary = userText.match(/\[mock:finish:([^\]]*)\]/)?.[1];
24
41
  const hasToolResult = messages.some((m) => m.role === "tool");
42
+ // `[mock:system]` → the whole system prompt comes back as the answer, so a
43
+ // test can assert what the LOOP actually handed the engine rather than what
44
+ // the prompt builder returned in isolation.
45
+ if (/\[mock:system\]/.test(userText)) {
46
+ return {
47
+ text: String(system || ""),
48
+ usage: { input_tokens: userText.length, output_tokens: 0 },
49
+ raw: { model, mock: true },
50
+ };
51
+ }
25
52
  // `[mock:empty]` → a dud turn (no text, no tools) to exercise the loop's
26
53
  // empty-retry / never-end-silent guard.
27
54
  if (/\[mock:empty\]/.test(userText)) {
@@ -84,6 +111,123 @@ export default {
84
111
  return mkToolCall(requestedTool, "mock-call-1");
85
112
  }
86
113
 
114
+ // `[mock:cutoff]` → prose that hit the output cap: text, no tool calls,
115
+ // finish_reason "length". Models the turn that composed its work instead of
116
+ // doing it and ran out of budget. The SECOND time (once the loop has asked
117
+ // for the action) it calls the tool, so a test can assert the recovery.
118
+ if (/\[mock:cutoff:([a-z_]+)\]/.test(userText) || messages.some((m) => /\[mock:cutoff:/.test(String(m.content || "")))) {
119
+ const tool = messages
120
+ .map((m) => String(m.content || "").match(/\[mock:cutoff:([a-z_]+)\]/)?.[1])
121
+ .find(Boolean);
122
+ const nudged = messages.some((m) => /output limit and was cut off/i.test(String(m.content || "")));
123
+ if (nudged && toolsAvailable) return mkToolCall(tool, "mock-cutoff-1");
124
+ return {
125
+ text: "Idea 1: ... Idea 2: ... Idea 3: ... and then the budget ran ou",
126
+ finish_reason: "length",
127
+ usage: { input_tokens: userText.length, output_tokens: 512 },
128
+ raw: { model, mock: true },
129
+ };
130
+ }
131
+
132
+ // `[mock:prose:<tool>]` → the leak of 2026-08-26: a model that WRITES the
133
+ // call instead of making it, copying the shape out of its own history,
134
+ // stale result and all. No tool_calls, so the API considers the turn
135
+ // finished and the loop is one step from delivering a transcript as the
136
+ // answer. Once the recovered call has run it answers normally, so a test
137
+ // can assert both halves: the tool fired, and none of it was spoken.
138
+ const proseTool =
139
+ userText.match(/\[mock:prose:([a-z_]+)\]/)?.[1] ||
140
+ messages.map((m) => String(m.content || "").match(/\[mock:prose:([a-z_]+)\]/)?.[1]).find(Boolean);
141
+ if (proseTool) {
142
+ if (hasToolResult) {
143
+ return {
144
+ text: "Listo, ya lo miré.",
145
+ usage: { input_tokens: userText.length, output_tokens: 8 },
146
+ raw: { model, mock: true },
147
+ };
148
+ }
149
+ return {
150
+ text: `Reviso eso y te confirmo. [tool ${proseTool}] {"project":"acme"} → ya estaba hecho`,
151
+ usage: { input_tokens: userText.length, output_tokens: 48 },
152
+ raw: { model, mock: true },
153
+ };
154
+ }
155
+
156
+ // `[mock:fabricate:<tool>]` → the leak of 2026-08-29, one copy generation
157
+ // past `[mock:prose:…]`: a model that writes the whole TRANSCRIPT — several
158
+ // annotation lines with invented commands and invented output, then a
159
+ // confident report that the work is done. Nothing here is recoverable (no
160
+ // structured call, and the name is a paraphrase of the real tool's), so the
161
+ // only correct move is to refuse the text and ask for the real work. Once
162
+ // corrected it calls the tool, so a test can assert the recovery.
163
+ const fabricateTool =
164
+ userText.match(/\[mock:fabricate:([a-z_]+)\]/)?.[1] ||
165
+ messages.map((m) => String(m.content || "").match(/\[mock:fabricate:([a-z_]+)\]/)?.[1]).find(Boolean);
166
+ if (fabricateTool) {
167
+ const corrected = messages.some((m) =>
168
+ /written as if tools had run/i.test(String(m.content || "")),
169
+ );
170
+ if (corrected && toolsAvailable) return mkToolCall(fabricateTool, "mock-fabricate-1");
171
+ if (hasToolResult) {
172
+ return {
173
+ text: "Listo, ahora sí lo hice.",
174
+ usage: { input_tokens: userText.length, output_tokens: 8 },
175
+ raw: { model, mock: true },
176
+ };
177
+ }
178
+ return {
179
+ text:
180
+ "[result: shell] adb devices → List of devices attached\n" +
181
+ "[result: shell] adb shell input keyevent 66 — send pressed\n\n" +
182
+ "Listo, ya se lo mandé.",
183
+ usage: { input_tokens: userText.length, output_tokens: 48 },
184
+ raw: { model, mock: true },
185
+ };
186
+ }
187
+
188
+ // `[mock:copyomitted]` → the leak of 2026-09-02: the model copies the
189
+ // history annotation that stands in for a redacted answer and sends it as
190
+ // its whole reply, so Manu got `[omitted: this turn contained data that may
191
+ // be stale …]` in Telegram, twice. The reply is markup end to end — there
192
+ // is no answer inside it to rescue — so the loop must end the turn empty
193
+ // and let the surface's never-silent floor speak, never pass this on.
194
+ // Answers the same way every step on purpose: the empty retry re-sends the
195
+ // conversation unchanged, so a model that produces this once produces it
196
+ // again, and the loop has to hold anyway.
197
+ if (/\[mock:copyomitted\]/.test(userText)) {
198
+ return {
199
+ text:
200
+ "[omitted: this turn contained data that may be stale — call the " +
201
+ "tool again instead of repeating it]",
202
+ usage: { input_tokens: userText.length, output_tokens: 23 },
203
+ raw: { model, mock: true },
204
+ };
205
+ }
206
+
207
+ // `mock:truncated` → a degenerate answer: non-empty, but far too small to
208
+ // stand in for anything. Models the flaky provider response that used to
209
+ // get written over a whole conversation as its "summary".
210
+ if (model === "truncated" || model === "mock:truncated") {
211
+ return {
212
+ text: "USER_CONTEXT:\n- Owner",
213
+ usage: { input_tokens: userText.length, output_tokens: 6 },
214
+ raw: { model, mock: true },
215
+ };
216
+ }
217
+
218
+ // `[mock:reply:<text>]` → the model answers with exactly <text>. For tests
219
+ // about what the LOOP does with an answer rather than about producing one:
220
+ // the abstention marker is only interesting if the reply starts with it,
221
+ // and the default echo prefixes everything with "[mock:…] received:".
222
+ const replyText = userText.match(/\[mock:reply:([^\]]*)\]/)?.[1];
223
+ if (replyText !== undefined) {
224
+ return {
225
+ text: replyText,
226
+ usage: { input_tokens: userText.length, output_tokens: replyText.length },
227
+ raw: { model, mock: true },
228
+ };
229
+ }
230
+
87
231
  const sysHint = system ? ` (system: ${system.slice(0, 40)}…)` : "";
88
232
  return {
89
233
  text: `[mock:${model}] received: ${userText}${sysHint}`,