@agentprojectcontext/apx 1.81.0 → 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 +21 -11
  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
@@ -0,0 +1,218 @@
1
+ // Run one full group turn: persist the owner's line, walk the mention cascade
2
+ // (turn-resolver.js), and for each speaker call the SAME turn engine the 1:1
3
+ // chat uses (run-turn.js) — so agents run their real tools instead of narrating
4
+ // them — streaming tokens back tagged by speaker. Everything persists to the
5
+ // message ledger via the group helpers (stores/messages.js); there is no
6
+ // separate group store.
7
+ import { wasAbortedBySignal } from "#core/agent/abort.js";
8
+ import { resolveAgentModel } from "#core/agent/agent-model.js";
9
+ import { buildAgentSystem } from "#core/agent/build-agent-system.js";
10
+ import { groupToolIters } from "#core/agent/constants.js";
11
+ import { runAgentTurn } from "#core/agent/run-turn.js";
12
+ import { readAgents } from "#core/apc/parser.js";
13
+ import { CHANNELS } from "#core/constants/channels.js";
14
+ import {
15
+ appendGroupAgentMessage,
16
+ appendGroupOwnerMessage,
17
+ lastGroupOwnerMessage,
18
+ readProjectGroupThread,
19
+ } from "#core/stores/messages.js";
20
+ import { resolveGroupTurn } from "./turn-resolver.js";
21
+
22
+ const displayName = (a) => a.fields?.Name || a.slug;
23
+
24
+ // System addendum that turns a normal agent into a group participant. No "you
25
+ // have no tools" line — in a group the agent keeps its real toolset; this only
26
+ // frames the room and the @-mention protocol.
27
+ function groupSystemBlock({ me, ownerName, others }) {
28
+ const roster = others.length ? others.join(", ") : "(nadie más por ahora)";
29
+ return [
30
+ "## Group chat",
31
+ `You are in a group chat with **${ownerName}** (the owner) and these other agents: ${roster}.`,
32
+ "The conversation transcript is shown to you with each line prefixed by who said it.",
33
+ `Reply ONLY as yourself (**${me}**), in your own voice, concisely. Never write anyone else's lines, and never speak for the owner.`,
34
+ "**How to bring someone in:** the ONLY way another participant hears you and gets a turn is if you write their handle with an @ and their exact slug — e.g. `" + others.map((x) => x.match(/@[a-z0-9_-]+/)?.[0]).filter(Boolean).join("`, `") + "`. Writing just their NAME (without the @slug) does NOT reach them.",
35
+ "@-mention another agent with their exact @slug only if they actually need to reply. If you can close the turn yourself, don't cite anyone. A short acknowledgement is fine — don't pad.",
36
+ ].join("\n");
37
+ }
38
+
39
+ function reasonLine({ reason, byOwner, ownerName, nameFor, me }) {
40
+ if (byOwner) return `${ownerName} addressed the group and it's your turn, ${me}. Reply now.`;
41
+ return `${nameFor(reason)} tagged you (@${me}) into the conversation. Reply now.`;
42
+ }
43
+
44
+ /**
45
+ * @param {object} args
46
+ * @param {object} args.p resolved project (db entry: path, storagePath, config, logMessage)
47
+ * @param {string} args.gid group id
48
+ * @param {string} args.text the owner's message body
49
+ * @param {string} args.ownerName display name for the owner in the transcript
50
+ * @param {object} args.config global config (fallback for the project's)
51
+ * @param {object} args.projects projects registry (for runAgentTurn tool handlers)
52
+ * @param {object} [args.plugins]
53
+ * @param {object} [args.registries]
54
+ * @param {string} [args.from] regenerate: slug of the speaker to resume from
55
+ * @param {string|null} [args.reason] regenerate: who pulled that speaker in (null = owner)
56
+ * @param {AbortSignal} [args.signal] the owner pressed Stop: aborts the speaker
57
+ * mid-run and stops the cascade behind it (see the catch in runAgent)
58
+ * @param {(ev:object)=>void} [args.onEvent] stream sink: owner_message/speaker_start/speaker_delta/speaker_final/speaker_aborted/done
59
+ * @returns {Promise<{messages: object[]}>}
60
+ */
61
+ export async function runGroupTurn({ p, gid, text, attachments = [], media = null, rerun = false, from = null, reason = null, ownerName = "Owner", config, projects, plugins, registries, signal = null, onEvent = () => { } }) {
62
+ const thread = readProjectGroupThread(p.storagePath, gid);
63
+ if (!thread) throw new Error(`group ${gid} not found`);
64
+
65
+ // Regenerate: reuse the LAST owner turn already in the thread (the caller
66
+ // truncated from the target bubble onward), without appending a new owner
67
+ // line. If `from` is set, resume the cascade at that speaker and leave
68
+ // earlier replies this turn untouched.
69
+ let resume = null;
70
+ if (rerun) {
71
+ const seed = lastGroupOwnerMessage(p.storagePath, gid);
72
+ if (seed == null) throw new Error("nothing to regenerate: the group has no owner message yet");
73
+ text = seed;
74
+ if (from) {
75
+ resume = {
76
+ from,
77
+ reason: reason || "owner",
78
+ byOwner: !reason,
79
+ };
80
+ }
81
+ }
82
+
83
+ // Resolve each participant against its home project when the room was built
84
+ // cross-project (inbox / mobile). Same-project rooms keep the host roster.
85
+ const homes = thread.homes && typeof thread.homes === "object" ? thread.homes : null;
86
+ const resolveHome = (slug) => {
87
+ const homeId = homes?.[slug];
88
+ if (homeId == null || homeId === "" || String(homeId) === String(p.id)) return p;
89
+ try {
90
+ const home = projects?.get?.(homeId);
91
+ return home?.path ? home : p;
92
+ } catch {
93
+ return p;
94
+ }
95
+ };
96
+ const bySlug = new Map(); // slug -> { agent, project }
97
+ for (const slug of thread.participants || []) {
98
+ const home = resolveHome(slug);
99
+ const agent = readAgents(home.path).find((a) => a.slug === slug);
100
+ if (agent) bySlug.set(slug, { agent, project: home });
101
+ }
102
+ const agents = [...bySlug.values()].map((x) => x.agent);
103
+ if (!agents.length) throw new Error("group has no resolvable agents");
104
+ if (from && !bySlug.has(from))
105
+ throw new Error(`agent ${from} is not in this group`);
106
+
107
+ const nameFor = (author) =>
108
+ author === "owner" ? ownerName : (bySlug.get(author) ? displayName(bySlug.get(author).agent) : author);
109
+
110
+ const participants = [
111
+ { slug: "owner", name: ownerName, kind: "owner" },
112
+ ...[...bySlug.entries()].map(([slug, { agent }]) => ({ slug, name: displayName(agent), kind: "agent" })),
113
+ ];
114
+
115
+ // The owner's line first, so it's part of the transcript everyone reads.
116
+ // (A regenerate reuses the owner line already there — don't duplicate it.)
117
+ if (!rerun) {
118
+ appendGroupOwnerMessage(p.logMessage, gid, text, media);
119
+ onEvent({ type: "owner_message" });
120
+ }
121
+
122
+ const cfg = p.config || config;
123
+ const said = [];
124
+
125
+ const runAgent = async (slug, ctx) => {
126
+ const hit = bySlug.get(slug);
127
+ if (!hit) throw new Error(`agent ${slug} is not in this group`);
128
+ const { agent, project: agentProject } = hit;
129
+ const modelId = await resolveAgentModel({ agent, config: cfg });
130
+ if (!modelId) throw new Error(`no model for agent ${slug}`);
131
+
132
+ const me = displayName(agent);
133
+ const others = participants
134
+ .filter((x) => x.kind === "agent" && x.slug !== slug)
135
+ .map((x) => `${x.name} (@${x.slug})`);
136
+ const system = buildAgentSystem(agentProject, agent, {
137
+ invocation: "engine",
138
+ caller: ctx.byOwner ? "user" : ctx.reason,
139
+ globalConfig: cfg,
140
+ extraParts: [groupSystemBlock({ me, ownerName, others })],
141
+ });
142
+
143
+ // Fresh read each time: earlier speakers this turn are already persisted, so
144
+ // a later cascade speaker sees what was just said. Tool rows stay out of the
145
+ // transcript text — they are execution noise; the answer bubble is enough.
146
+ const current = readProjectGroupThread(p.storagePath, gid);
147
+ const transcript = current.messages
148
+ .filter((m) => m.role === "user" || (m.role === "assistant" && m.content))
149
+ .map((m) => `${m.role === "user" ? ownerName : (nameFor(m.agent) || "agent")}: ${m.content}`)
150
+ .join("\n");
151
+ const directive = reasonLine({ reason: ctx.reason, byOwner: ctx.byOwner, ownerName, nameFor, me });
152
+
153
+ onEvent({ type: "speaker_start", slug, reason: ctx.byOwner ? null : ctx.reason });
154
+ // What this speaker has produced so far, kept alongside the stream so an
155
+ // interrupted reply can still be written to the room. runAgentTurn throws on
156
+ // abort and takes its text and trace with it.
157
+ const partialTrace = [];
158
+ let partialText = "";
159
+ let result;
160
+ try {
161
+ result = await runAgentTurn({
162
+ p: agentProject, agent, modelId, system,
163
+ prompt: `${transcript}\n\n---\n${directive}`,
164
+ previousMessages: [],
165
+ // The owner's image rides on this turn for every speaker answering it, so
166
+ // a vision model actually sees what was sent (not just the "[image
167
+ // attached]" marker already folded into the transcript text).
168
+ attachments,
169
+ channel: CHANNELS.WEB,
170
+ // NOT the web channel's budget, even though the channel above says web:
171
+ // that string picks the channel PROMPT, and a room fans one owner message
172
+ // out into up to MAX_TURNS_PER_MESSAGE of these runs. See GROUP_TOOL_ITERS.
173
+ maxIters: groupToolIters(cfg),
174
+ tools: true,
175
+ projects, plugins, registries, config: cfg,
176
+ signal,
177
+ onEvent: (ev) => {
178
+ if (ev?.type === "tool_result" && ev.trace) partialTrace.push(ev.trace);
179
+ onEvent(ev);
180
+ },
181
+ onToken: (chunk) => { partialText += chunk; onEvent({ type: "speaker_delta", slug, delta: chunk }); },
182
+ });
183
+ } catch (e) {
184
+ if (!wasAbortedBySignal(e, signal)) throw e;
185
+ // The owner stopped the room mid-reply. Whatever streamed is real work they
186
+ // watched happen, so it stays in the transcript with the tool rows that
187
+ // really ran — the next owner message reads this as history, exactly as the
188
+ // 1:1 chat does with an interrupted turn. Returning "" parses no mentions,
189
+ // and the resolver's own signal check stops the queue behind us.
190
+ const partial = partialText.trim();
191
+ if (partial || partialTrace.length) {
192
+ appendGroupAgentMessage(p.logMessage, gid, {
193
+ slug, body: partial,
194
+ reason: ctx.byOwner ? null : ctx.reason,
195
+ model: modelId, trace: partialTrace,
196
+ });
197
+ }
198
+ onEvent({ type: "speaker_aborted", slug, text: partial });
199
+ return "";
200
+ }
201
+
202
+ const reply = (result.text || "").trim() || "…";
203
+ appendGroupAgentMessage(p.logMessage, gid, {
204
+ slug, body: reply,
205
+ reason: ctx.byOwner ? null : ctx.reason,
206
+ model: result.model, usage: result.usage,
207
+ trace: result.trace,
208
+ media: result.media,
209
+ });
210
+ said.push({ slug, text: reply });
211
+ onEvent({ type: "speaker_final", slug, model: result.model || modelId, usage: result.usage });
212
+ return reply;
213
+ };
214
+
215
+ await resolveGroupTurn({ text, participants, runAgent, resume, signal });
216
+ onEvent({ type: "done" });
217
+ return { messages: said };
218
+ }
@@ -0,0 +1,165 @@
1
+ // Group chat turn-taking (option C + cross-mentions).
2
+ //
3
+ // A group conversation is the owner plus N agents in one room. Who speaks on a
4
+ // given human message is decided by @mentions, and mentions CASCADE: if the
5
+ // owner writes "@naty …", Naty speaks; if Naty's reply names "@candela",
6
+ // Candela speaks next — even though the owner never addressed her. With no
7
+ // mention at all, the FIRST agent in the room takes the turn.
8
+ //
9
+ // This module is pure orchestration: it parses mentions and walks the cascade,
10
+ // delegating the actual model call to a `runAgent(slug, ctx)` callback the
11
+ // caller injects. That keeps the turn logic unit-testable without engines.
12
+
13
+ // Agents keep talking as long as they @-mention someone. The only loop guard
14
+ // is a ceiling: one human message can produce at most this many agent replies
15
+ // (A↔B ping-pong included). After that the cascade stops even if they still cite.
16
+ //
17
+ // Exported because it is half of the group tool budget: each of these replies is
18
+ // a full tool-loop run, so this number multiplies GROUP_TOOL_ITERS into what one
19
+ // owner message may actually cost (see agent/constants.js).
20
+ export const MAX_TURNS_PER_MESSAGE = 10;
21
+
22
+ // Strip diacritics + lowercase so "@Natalia", "@natalia" and "@natália" all
23
+ // resolve to the same participant.
24
+ function norm(s) {
25
+ return String(s || "")
26
+ .normalize("NFD")
27
+ .replace(/[\u0300-\u036f]/g, "")
28
+ .toLowerCase()
29
+ .trim();
30
+ }
31
+
32
+ /**
33
+ * Build the set of tokens that address a participant: its slug and every word
34
+ * of its display name (so "@naty" matches slug `naty` and "@Natalia" matches
35
+ * the agent whose Name is "Natalia"). Multi-word names also match on the full
36
+ * name joined without spaces ("@analytics-bot", "@AnaLucia").
37
+ */
38
+ function aliasesFor(participant) {
39
+ const out = new Set();
40
+ const add = (v) => { const n = norm(v); if (n) out.add(n); };
41
+ add(participant.slug);
42
+ if (participant.name) {
43
+ add(participant.name);
44
+ add(participant.name.replace(/\s+/g, ""));
45
+ for (const w of String(participant.name).split(/\s+/)) add(w);
46
+ }
47
+ return out;
48
+ }
49
+
50
+ /**
51
+ * Parse @mentions out of a message body and resolve them to participant slugs.
52
+ * Only AGENT participants can be addressed (mentioning the owner is a no-op —
53
+ * the owner speaks by typing, not by being summoned). The author never mentions
54
+ * themselves into another turn.
55
+ *
56
+ * @param {string} text
57
+ * @param {Array<{slug,name,kind}>} participants
58
+ * @param {string} [authorSlug] slug of who wrote `text`, excluded from the result
59
+ * @returns {string[]} ordered, de-duplicated slugs of mentioned agents
60
+ */
61
+ export function parseMentions(text, participants, authorSlug) {
62
+ const agents = participants.filter((p) => p.kind !== "owner");
63
+ // Longest alias first so "@ana-lucia" wins over a bare "@ana".
64
+ const table = agents
65
+ .map((p) => ({ slug: p.slug, aliases: [...aliasesFor(p)] }))
66
+ .flatMap((p) => p.aliases.map((a) => ({ slug: p.slug, alias: a })))
67
+ .sort((a, b) => b.alias.length - a.alias.length);
68
+
69
+ const found = [];
70
+ const seen = new Set();
71
+ // @token where token is a run of letters/digits/_/- (mentions never span
72
+ // spaces). We scan raw matches and resolve each against the alias table.
73
+ const re = /@([\p{L}\p{N}_-]+)/gu;
74
+ let m;
75
+ while ((m = re.exec(text)) !== null) {
76
+ const token = norm(m[1]);
77
+ const hit = table.find((t) => t.alias === token);
78
+ if (!hit) continue;
79
+ if (hit.slug === authorSlug) continue;
80
+ if (seen.has(hit.slug)) continue;
81
+ seen.add(hit.slug);
82
+ found.push(hit.slug);
83
+ }
84
+ return found;
85
+ }
86
+
87
+ /**
88
+ * Decide who speaks first for a human message: the agents it mentions, in
89
+ * order; or, if it mentions nobody, the first agent in the room.
90
+ *
91
+ * @returns {string[]} slugs to seed the cascade with
92
+ */
93
+ export function seedSpeakers(text, participants) {
94
+ const mentioned = parseMentions(text, participants, "owner");
95
+ if (mentioned.length) return mentioned;
96
+ const firstAgent = participants.find((p) => p.kind !== "owner");
97
+ return firstAgent ? [firstAgent.slug] : [];
98
+ }
99
+
100
+ /**
101
+ * Walk a full group turn. Starting from the human message, run each seeded
102
+ * speaker; scan every reply for @mentions and queue those agents — even if
103
+ * they already spoke this turn, so a back-and-forth keeps going until nobody
104
+ * cites anyone (or the ceiling is hit).
105
+ *
106
+ * @param {object} args
107
+ * @param {string} args.text the human message body
108
+ * @param {Array} args.participants [{slug,name,kind}], agents in room order
109
+ * @param {(slug:string, ctx:{reason:string, byOwner:boolean}) => Promise<string>} args.runAgent
110
+ * Runs one agent's turn against the current transcript and returns its
111
+ * reply text. The resolver appends it before scanning for mentions.
112
+ * @param {(slug:string) => void} [args.onSpeakerStart] fires before each run
113
+ * @param {number} [args.maxTurns]
114
+ * @param {AbortSignal} [args.signal]
115
+ * The owner stopped the room. Checked between speakers so an interrupted
116
+ * cascade does not start the NEXT agent's turn: the speaker that was
117
+ * mid-run is aborted through its own run's signal, and this stops the
118
+ * queue behind it. Without it "stop" only ever ended one reply of ten.
119
+ * @param {{from:string, reason?:string, byOwner?:boolean}} [args.resume]
120
+ * Regenerating one bubble: start from `from` instead of re-seeding the
121
+ * whole room from the owner line. Earlier replies this turn stay put;
122
+ * a new @mention can still pull those speakers in again.
123
+ * @returns {Promise<Array<{slug,text}>>} the replies in the order they were said
124
+ */
125
+ export async function resolveGroupTurn({
126
+ text,
127
+ participants,
128
+ runAgent,
129
+ onSpeakerStart,
130
+ maxTurns = MAX_TURNS_PER_MESSAGE,
131
+ resume = null,
132
+ signal = null,
133
+ }) {
134
+ const replies = [];
135
+ // Each queue entry remembers WHY the agent is speaking: addressed by the
136
+ // owner, or pulled in by another agent's mention. The reason is handed to
137
+ // runAgent so the prompt can frame it ("owner asked you" vs "naty tagged you").
138
+ // A regenerate of one bubble resumes from that speaker; a fresh turn seeds
139
+ // from the owner's @mentions (or the first agent in the room).
140
+ const queue = resume?.from
141
+ ? [{ slug: resume.from, reason: resume.reason || "owner", byOwner: resume.byOwner !== false }]
142
+ : seedSpeakers(text, participants).map((slug) => ({ slug, reason: "owner", byOwner: true }));
143
+
144
+ while (queue.length && replies.length < maxTurns) {
145
+ if (signal?.aborted) break;
146
+ const { slug, reason, byOwner } = queue.shift();
147
+ const participant = participants.find((p) => p.slug === slug && p.kind !== "owner");
148
+ if (!participant) continue;
149
+
150
+ onSpeakerStart?.(slug);
151
+ const reply = await runAgent(slug, { reason, byOwner });
152
+ const replyText = typeof reply === "string" ? reply : "";
153
+ replies.push({ slug, text: replyText });
154
+
155
+ // A reply can pull anyone in, including someone who already spoke — that's
156
+ // how the ping-pong continues. Skip only if they're already waiting.
157
+ for (const mentioned of parseMentions(replyText, participants, slug)) {
158
+ if (queue.some((q) => q.slug === mentioned)) continue;
159
+ queue.push({ slug: mentioned, reason: slug, byOwner: false });
160
+ }
161
+ }
162
+ return replies;
163
+ }
164
+
165
+ export const __test__ = { norm, aliasesFor, MAX_TURNS_PER_MESSAGE };
@@ -1,17 +1,39 @@
1
1
  // Goal-completion judge loop (OpenHands Critic / iterative-refinement
2
- // pattern). After a completion-contract run declares done, an LLM judge scores
3
- // how likely the ORIGINAL goal is actually met (0..1). Below the threshold,
4
- // the agent gets a follow-up verification note and continues bounded by
5
- // max_iterations so a harsh judge can't spin forever. Opt-in and scoped to
6
- // completion-contract surfaces (coding turns), where "done" is checkable.
2
+ // pattern). An LLM judge scores how likely the ORIGINAL goal is actually met
3
+ // (0..1); below the threshold the agent gets a follow-up verification note and
4
+ // continues bounded by max_iterations so a harsh judge can't spin forever.
5
+ //
6
+ // Two bounds, and only one of them is a count of rounds. `max_iterations` caps
7
+ // how many times we RE-ASK; the turn's tool budget caps how much the asking may
8
+ // cost, and the rounds share that budget with the run that came before them
9
+ // (applyJudgeLoop's `maxIters`). They used to be independent, which quietly made
10
+ // the real ceiling max_iterations × the budget — see constants.js.
11
+ //
12
+ // It serves two different failures, through the same loop:
13
+ //
14
+ // - Completion-contract turns (coding surfaces) declare "done" themselves,
15
+ // and the judge checks that claim. Opt-in: `judge.enabled`.
16
+ // - Conversational turns (Telegram, web chat) end whenever the model stops
17
+ // calling tools — which it also does when it merely ANNOUNCES the next step
18
+ // ("ahora genero el SRT en inglés") and writes no call. Nothing declared
19
+ // anything; the task just stopped halfway and waited to be poked. Here the
20
+ // judge IS the poke, and it is on by default (`judge.continue_unfinished`).
7
21
  import { callEngine } from "../engines/index.js";
22
+ import { TURN_ENDING_TOOLS } from "./tools/names.js";
23
+ import { MIN_JUDGE_ROUND_ITERS } from "./constants.js";
8
24
 
9
25
  export function judgeConfig(globalConfig) {
10
26
  const raw = globalConfig?.super_agent?.judge || {};
11
27
  const threshold = Number(raw.success_threshold);
12
28
  const iters = parseInt(raw.max_iterations, 10);
13
29
  return {
30
+ // Verify a contract turn's own "done". Opt-in — the coding surfaces pay a
31
+ // judge call per finish, and not every deployment wants that.
14
32
  enabled: raw.enabled === true,
33
+ // Continue a conversational turn that stopped mid-task. On unless switched
34
+ // off: a turn that quits after announcing its next step reads as a bug, and
35
+ // the alternative is the user typing "seguí" to restart it by hand.
36
+ continue_unfinished: raw.continue_unfinished !== false,
15
37
  success_threshold:
16
38
  Number.isFinite(threshold) && threshold > 0 && threshold <= 1 ? threshold : 0.6,
17
39
  max_iterations: Number.isFinite(iters) && iters > 0 ? Math.min(iters, 5) : 2,
@@ -91,10 +113,17 @@ export function parseVerdict(text) {
91
113
  * Score a finished run against its goal. Returns {score, reasoning, missing}
92
114
  * or null when the judge is unusable (engine down, unparseable reply) — the
93
115
  * caller treats null as "accept the result", never as a failure.
116
+ *
117
+ * `fallbackModel` is the last resort for the model that does the scoring, and
118
+ * exists for project agents: they run on installs that never configured a
119
+ * super-agent, and resolving to "" there would switch the judge off silently —
120
+ * shipped, on by default, and doing nothing. The caller passes the model that
121
+ * ran the turn. The explicit knobs still win, in order: `judge.model`, then
122
+ * `super_agent.model`.
94
123
  */
95
- export async function judgeCompletion({ goal, result, globalConfig, callEngineFn = callEngine }) {
124
+ export async function judgeCompletion({ goal, result, globalConfig, fallbackModel = "", callEngineFn = callEngine }) {
96
125
  const cfg = judgeConfig(globalConfig);
97
- const modelId = cfg.model || globalConfig?.super_agent?.model || "";
126
+ const modelId = cfg.model || globalConfig?.super_agent?.model || fallbackModel || "";
98
127
  if (!modelId) return null;
99
128
  try {
100
129
  const r = await callEngineFn({
@@ -136,15 +165,89 @@ export function buildJudgeFollowup(verdict, iteration) {
136
165
  .join("\n");
137
166
  }
138
167
 
168
+ /**
169
+ * Is this conversational turn one worth checking — and continuing if unfinished?
170
+ *
171
+ * Two exclusions, both about not spending a call to learn nothing:
172
+ * - a turn that ran no tools is chat, and chat has no half-done work; judging
173
+ * it would be one model call per "hola".
174
+ * - a turn that ended by ASKING the user is not unfinished, it is waiting. A
175
+ * verdict of "not complete" there would push the agent to answer its own
176
+ * question instead of letting the person answer it. That covers both ways a
177
+ * turn can ask: the ask_questions tool, and run-agent's reserved wrap-up
178
+ * step (`endedAwaitingUser`), whose whole job is to recap and ask "want me
179
+ * to keep going?" when the tool budget runs out.
180
+ *
181
+ * The wrap-up case is the one that bit us (2026-08-30, web chat): the budget
182
+ * ran out at 9 actions, the wrap-up asked whether to continue, the judge read
183
+ * "worked and then stopped" and re-ran the turn — which spent another 9 actions
184
+ * and hit the same wall, so the user got the same recap and the same question
185
+ * three times in a row, never once getting to answer it. Extending a budget the
186
+ * system itself set is what maxIters is for; the judge's job is to poke a turn
187
+ * that quit on its own.
188
+ *
189
+ * @param {{trace?: {tool?: string}[], endedAwaitingUser?: boolean}} result a runAgent result
190
+ */
191
+ export function continuableTurn(result) {
192
+ const trace = Array.isArray(result?.trace) ? result.trace : [];
193
+ if (trace.length === 0) return false;
194
+ return !awaitingUser(result);
195
+ }
196
+
197
+ /**
198
+ * Did this turn close by putting a question to the user? Two ways it can:
199
+ * the ask_questions tool, or run-agent's reserved wrap-up step, which recaps
200
+ * and asks "want me to keep going?" when the tool budget runs out
201
+ * (`endedAwaitingUser`). Either way the next move belongs to a person.
202
+ *
203
+ * @param {{trace?: {tool?: string}[], endedAwaitingUser?: boolean}} result a runAgent result
204
+ */
205
+ export function awaitingUser(result) {
206
+ if (result?.endedAwaitingUser) return true;
207
+ const trace = Array.isArray(result?.trace) ? result.trace : [];
208
+ return trace.some((t) => TURN_ENDING_TOOLS.has(String(t?.tool || "")));
209
+ }
210
+
211
+ /**
212
+ * Iterations of the tool budget a run consumed. runAgent reports it directly;
213
+ * an injected runner (tests, a surface with its own loop) may not, and for
214
+ * those we fall back to a LOWER BOUND — a tool result cannot exist without an
215
+ * iteration that produced it, and a round that ran at all cost at least one.
216
+ * Under-counting means one extra round in a synthetic case; not counting at all
217
+ * would mean no ceiling, which is the bug this whole file's budget arithmetic
218
+ * exists to close.
219
+ *
220
+ * @param {{iterations?: number, trace?: unknown[]}} result a runAgent result
221
+ */
222
+ export function itersSpent(result) {
223
+ const n = Number(result?.iterations);
224
+ if (Number.isFinite(n) && n >= 0) return n;
225
+ const trace = Array.isArray(result?.trace) ? result.trace : [];
226
+ return Math.max(1, trace.length);
227
+ }
228
+
139
229
  /**
140
230
  * Refinement driver, dependency-injected so surfaces and tests supply their
141
231
  * own judge/runner. `judgeFn(result)` → verdict|null; `runFollowup(followupPrompt,
142
- * result)` → next run result. Merges usage and traces across rounds and
143
- * attaches the verdict trail as `result.judge`.
232
+ * result, {maxIters})` → next run result. Merges usage, traces and iteration
233
+ * spend across rounds and attaches the verdict trail as `result.judge`.
234
+ *
235
+ * `maxIters` is the budget for the WHOLE TURN — the run that produced
236
+ * `initialResult` plus every round this loop adds — not a per-round allowance.
237
+ * Each round is handed what the rounds before it left, and once too little is
238
+ * left to be worth a round (MIN_JUDGE_ROUND_ITERS) the loop stops. See the
239
+ * "one turn, one budget" note in constants.js for why the total is shared
240
+ * rather than the rounds getting a budget of their own.
241
+ *
242
+ * Omit it (or pass 0) and there is no arithmetic to do: rounds run on whatever
243
+ * budget the runner picks, bounded only by cfg.max_iterations. That is the
244
+ * shape an injected runner without a tool loop wants.
144
245
  */
145
- export async function applyJudgeLoop({ initialResult, cfg, judgeFn, runFollowup, onEvent = null }) {
246
+ export async function applyJudgeLoop({ initialResult, cfg, judgeFn, runFollowup, onEvent = null, maxIters = 0 }) {
146
247
  let result = initialResult;
147
248
  const trail = [];
249
+ const budget = Number.isFinite(Number(maxIters)) && Number(maxIters) > 0 ? Number(maxIters) : 0;
250
+ let spent = itersSpent(initialResult);
148
251
  for (let i = 1; i <= cfg.max_iterations; i++) {
149
252
  const verdict = await judgeFn(result);
150
253
  if (verdict) {
@@ -160,7 +263,23 @@ export async function applyJudgeLoop({ initialResult, cfg, judgeFn, runFollowup,
160
263
  }
161
264
  }
162
265
  if (!verdict || verdict.score >= cfg.success_threshold) break;
163
- const next = await runFollowup(buildJudgeFollowup(verdict, i), result);
266
+ // The verdict is worth recording even when we cannot act on it — it says
267
+ // the turn ended unverified, and why. Acting on it is what the budget
268
+ // decides. We judge first and check the budget here, rather than the other
269
+ // way round, because a completion-contract turn is judged FOR the verdict.
270
+ const remaining = budget ? budget - spent : 0;
271
+ if (budget && remaining < MIN_JUDGE_ROUND_ITERS) {
272
+ if (typeof onEvent === "function") {
273
+ await onEvent({ type: "judge_budget_exhausted", iteration: i, spent, budget });
274
+ }
275
+ break;
276
+ }
277
+ const next = await runFollowup(
278
+ buildJudgeFollowup(verdict, i),
279
+ result,
280
+ budget ? { maxIters: remaining } : {},
281
+ );
282
+ spent += itersSpent(next);
164
283
  result = {
165
284
  ...next,
166
285
  usage: {
@@ -168,7 +287,15 @@ export async function applyJudgeLoop({ initialResult, cfg, judgeFn, runFollowup,
168
287
  output_tokens: (result.usage?.output_tokens || 0) + (next.usage?.output_tokens || 0),
169
288
  },
170
289
  trace: [...(result.trace || []), ...(next.trace || [])],
290
+ // The turn's total, not this round's — same rule as usage and trace. A
291
+ // caller that logs "spent N of maxIters" must see one number for the turn.
292
+ iterations: spent,
171
293
  };
294
+ // The round we just ran closed by asking the user something — it exhausted
295
+ // its budget and wrapped up, or it called ask_questions. Same rule as the
296
+ // gate that let us in here: another round would answer over their head and
297
+ // re-ask the identical question.
298
+ if (awaitingUser(result)) break;
172
299
  }
173
300
  return trail.length ? { ...result, judge: trail } : result;
174
301
  }