@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
@@ -0,0 +1,110 @@
1
+ // One short line, written by the model instead of written for it.
2
+ //
3
+ // A few messages are the host's to TRIGGER but not to word: the ack after a
4
+ // /reset, the closing of a turn that came back empty. They lived in the i18n
5
+ // dicts as one canned string per case per language — copy that ages in place
6
+ // while the agent's voice moves on, and that has to be re-translated by hand
7
+ // every time a language is added. This asks the model for the line instead.
8
+ //
9
+ // Deliberately NOT a turn: no tools, no history, no persistence, no streaming.
10
+ // One directive in, one line out. It never throws and never blocks for long —
11
+ // an unusable engine, a timeout or an empty answer all come back as "", and the
12
+ // caller falls through to its own floor. That floor is the reason this can be
13
+ // best-effort: nothing here is allowed to be the difference between a reply and
14
+ // silence.
15
+ import { callEngine } from "../engines/index.js";
16
+ import { stripReasoning } from "../util/thinking.js";
17
+
18
+ /** How long the caller waits for a line it could also do without. */
19
+ export const AUTHOR_LINE_TIMEOUT_MS = 8000;
20
+
21
+ // The only fixed text left: an instruction to the model, not copy for the user.
22
+ // It says how to write, never what to say — the what is the caller's
23
+ // `instruction`, and the words are the model's.
24
+ const SYSTEM = [
25
+ "You are the assistant, writing ONE short line to the user in a chat you are already in.",
26
+ "Write it in the user's language and in your own voice — natural, specific, never a template.",
27
+ "Plain text only: no markdown, no quotes around it, no preamble, no sign-off.",
28
+ "Output the line and nothing else.",
29
+ ].join("\n");
30
+
31
+ /**
32
+ * The most specific language tag the config has. `user.locale` before
33
+ * `user.language` on purpose: "es" comes back as neutral Spanish, "es-AR" comes
34
+ * back in voseo — the difference between a line that sounds like the agent and
35
+ * one that sounds like a translation of it.
36
+ */
37
+ function languageTag(globalConfig, override) {
38
+ return String(override || globalConfig?.user?.locale || globalConfig?.user?.language || "").trim();
39
+ }
40
+
41
+ /** Strip the wrapper a model puts around a line it was asked to produce. */
42
+ function cleanLine(raw) {
43
+ let s = stripReasoning(String(raw || "")).answer.trim();
44
+ if (!s) return "";
45
+ // A fenced block around a one-liner is packaging, not content.
46
+ s = s.replace(/^```[a-z]*\s*/i, "").replace(/\s*```$/, "").trim();
47
+ // Same for quotes the model wrapped the whole line in.
48
+ if (s.length > 1 && /^["'“”«](.|\n)*["'“”»]$/.test(s)) s = s.slice(1, -1).trim();
49
+ // It was asked for one line; blank lines mean it wrote a note instead.
50
+ return s.replace(/\n{2,}/g, "\n").trim();
51
+ }
52
+
53
+ /**
54
+ * Ask the super-agent's model for a single line.
55
+ *
56
+ * @param {object} o
57
+ * @param {object} o.globalConfig config snapshot (names the model + language)
58
+ * @param {string} o.instruction what the line has to do, addressed to the model
59
+ * @param {string} [o.model] write with this model instead of the super-agent's.
60
+ * A project agent's line is its own to word — it is
61
+ * the one whose voice the thread is in.
62
+ * @param {string} [o.context] what just happened, so the line can be specific
63
+ * @param {string} [o.lang] override the tag to write in; defaults to the config's locale
64
+ * @param {number} [o.maxTokens]
65
+ * @param {number} [o.timeoutMs]
66
+ * @param {AbortSignal} [o.signal] caller's own abort (combined with the timeout)
67
+ * @param {Function} [o.callEngineFn] injectable for tests
68
+ * @returns {Promise<string>} the line, or "" when the caller should use its floor
69
+ */
70
+ export async function authorLine({
71
+ globalConfig,
72
+ instruction,
73
+ model = "",
74
+ context = "",
75
+ lang = "",
76
+ maxTokens = 160,
77
+ timeoutMs = AUTHOR_LINE_TIMEOUT_MS,
78
+ signal = null,
79
+ callEngineFn = callEngine,
80
+ }) {
81
+ const modelId = model || globalConfig?.super_agent?.model || "";
82
+ if (!modelId || !instruction) return "";
83
+
84
+ const parts = [instruction];
85
+ if (context) parts.push(context);
86
+ // A language hint, not a phrasing one: /reset carries no user prose to mirror,
87
+ // so without this the model answers a bare command in whatever it defaults to.
88
+ const tag = languageTag(globalConfig, lang);
89
+ if (tag) parts.push(`Write in this language (BCP-47 tag): ${tag}.`);
90
+
91
+ // A line nobody is waiting on must not hold the turn open. The caller's own
92
+ // abort still wins when it fires first.
93
+ const timeout = AbortSignal.timeout(Math.max(1000, timeoutMs));
94
+ const combined = signal ? AbortSignal.any([signal, timeout]) : timeout;
95
+
96
+ try {
97
+ const r = await callEngineFn({
98
+ modelId,
99
+ system: SYSTEM,
100
+ messages: [{ role: "user", content: parts.join("\n\n") }],
101
+ config: globalConfig,
102
+ maxTokens,
103
+ signal: combined,
104
+ });
105
+ return cleanLine(r?.text);
106
+ } catch {
107
+ // Engine down, model unknown, timed out, aborted: all the same answer.
108
+ return "";
109
+ }
110
+ }
@@ -9,25 +9,24 @@
9
9
  import fs from "node:fs";
10
10
  import { readAgentMemory } from "./memory.js";
11
11
  import { apcProjectFile, apcSkillFile } from "../apc/paths.js";
12
+ import { listField, agentSkills } from "./skills/declared.js";
13
+ import { loadAgentSkills, renderAgentSkillsBlock } from "./skills/agent-skills.js";
12
14
  import {
13
15
  PROMPTS,
14
16
  buildChannelContextBlock,
15
17
  buildVoiceModeBlock,
18
+ buildMobilityModeBlock,
16
19
  buildRelationshipBlock,
17
20
  buildUserContextBlock,
18
21
  buildSegmentDiscipline,
19
22
  } from "./prompt-builder.js";
20
23
  import { readJson } from "#core/util/json-file.js";
24
+ import { resolveAgentName } from "../identity/self.js";
21
25
 
22
26
  // Cap the injected agent body so an over-long authored file can't blow the
23
27
  // token budget. Mirrors PROJECT_AGENTS_MAX_CHARS for AGENTS.md.
24
28
  const AGENT_BODY_MAX_CHARS = 6000;
25
29
 
26
- function listField(value) {
27
- if (Array.isArray(value)) return value.map(String).map((s) => s.trim()).filter(Boolean);
28
- return String(value || "").split(",").map((s) => s.trim()).filter(Boolean);
29
- }
30
-
31
30
  function projectName(project) {
32
31
  if (project?.name) return project.name;
33
32
  try {
@@ -38,9 +37,7 @@ function projectName(project) {
38
37
  }
39
38
  }
40
39
 
41
- export function agentSkills(agent) {
42
- return listField(agent?.fields?.Skills);
43
- }
40
+ export { agentSkills };
44
41
 
45
42
  /**
46
43
  * Build the system prompt for a project agent.
@@ -103,25 +100,28 @@ export function buildAgentSystem(project, agent, {
103
100
  // agents talk through the same surfaces; they need the same formatting rules.
104
101
  const channelBlock = buildChannelContextBlock(channel, channelMeta);
105
102
  const voiceBlock = buildVoiceModeBlock(voice);
103
+ const mobilityBlock = buildMobilityModeBlock(!!channelMeta?.mobility);
106
104
  const segmentDiscipline = buildSegmentDiscipline({ channel: channelLow, voice });
107
105
 
108
106
  // Relationship block — "you're talking to <owner>" / "<contact>" / "<guest>".
109
107
  const relationship = buildRelationshipBlock(sender);
110
108
 
111
- // Declared tool hints (informational actual callables come from runtime).
109
+ // Declared tool allowlist. The names here are what this agent may call;
110
+ // the runtime maps catalog aliases (glob, memory_get, …) to native tools.
112
111
  const declaredTools = listField(fields.Tools);
113
112
  const toolHints = declaredTools.length
114
113
  ? [
115
- "## Declared tool hints (agent-level expectations)",
114
+ "## Tools you may call this turn",
116
115
  declaredTools.join(", "),
117
- "Actual callable tools depend on the invocation surface use whatever the runtime sends this turn.",
116
+ "Do not invent tools outside this list. If a needed tool is missing, say so instead of faking the call.",
118
117
  ].join("\n")
119
118
  : "";
120
119
 
121
120
  // Invocation context (who called me, through what, for what).
122
121
  const invocationCtx = buildInvocationContext({ invocation, runtime, caller, routine });
123
122
 
124
- // Per-agent memory (lives under <project>/.apc/agents/<slug>/memory.md).
123
+ // Per-agent memory ~/.apx/projects/<apx_id>/agents/<slug>/memory.md,
124
+ // never inside the repo (core/agent/memory.js).
125
125
  const memory = readAgentMemory(project, agent.slug);
126
126
  const memoryBlock = memory ? "# Memory\n" + memory : "";
127
127
 
@@ -129,6 +129,10 @@ export function buildAgentSystem(project, agent, {
129
129
  // small and specific to this agent).
130
130
  const projectSkills = buildProjectSkills(project, agent);
131
131
 
132
+ // How to reach the owner with something that happens outside this chat. Every
133
+ // project agent gets it (the super-agent, which IS Roby, never does).
134
+ const ownerNotice = buildOwnerNoticeProtocol(agent.slug, projectName(project));
135
+
132
136
  return [
133
137
  roleBlock,
134
138
  profileLines.join("\n"),
@@ -139,9 +143,11 @@ export function buildAgentSystem(project, agent, {
139
143
  channelBlock,
140
144
  toolHints,
141
145
  invocationCtx,
146
+ ownerNotice,
142
147
  projectSkills,
143
148
  ...extraParts.filter(Boolean),
144
149
  voiceBlock,
150
+ mobilityBlock,
145
151
  PROMPTS.ACTION_DISCIPLINE,
146
152
  segmentDiscipline,
147
153
  ]
@@ -149,6 +155,35 @@ export function buildAgentSystem(project, agent, {
149
155
  .join("\n\n");
150
156
  }
151
157
 
158
+ /**
159
+ * The owner-notice protocol. A project agent is NOT the orchestrator: when
160
+ * something the owner should know happens outside the conversation it is in, it
161
+ * does not ping the owner's phone itself — it relays to Roby, tagged with an
162
+ * urgency the owner chose the meaning of. `blocker` reaches them in the act;
163
+ * `status`/`fyi` wait for the end-of-day digest. This is the same split the
164
+ * a2a severity contract enforces (core/routines/signals.js).
165
+ */
166
+ function buildOwnerNoticeProtocol(slug, project) {
167
+ const proj = project || "<project>";
168
+ const superName = resolveAgentName() || "Roby";
169
+ return [
170
+ "# Reaching the owner",
171
+ `You are not ${superName} (the super-agent / orchestrator). When something the owner needs to know happens outside`,
172
+ "the conversation you are in — a routine result, a problem you hit — do NOT message their phone",
173
+ `yourself. Relay it to ${superName} and let ${superName} decide how and when to tell them:`,
174
+ "```",
175
+ `apx send ${slug} default "<one clear line>" --deliver --project ${proj}`,
176
+ "```",
177
+ `Tag how urgent it is, so ${superName} knows how fast to surface it:`,
178
+ "- `--severity blocker` — a critical problem the owner must see NOW. Alerts them in the act,",
179
+ " crossing quiet hours and the interruption budget. Use it only for what truly cannot wait.",
180
+ "- `--severity status` — routine progress or an FYI. Folded into the end-of-day digest, never an",
181
+ " interruption. (`fyi` is the same, lowest priority.)",
182
+ "Always also leave the full detail in your own web chat: the relay is the heads-up, your chat is",
183
+ "where the owner reads the whole thing and replies.",
184
+ ].join("\n");
185
+ }
186
+
152
187
  function buildInvocationContext({ invocation, runtime, caller, routine }) {
153
188
  const lines = [`## Invocation`, `invocation: ${invocation}`];
154
189
  if (runtime) lines.push(`runtime: ${runtime}`);
@@ -177,11 +212,10 @@ function buildProjectSkills(project, agent) {
177
212
  if (fs.existsSync(apxSkill)) {
178
213
  parts.push("## APX\n" + fs.readFileSync(apxSkill, "utf8").trim());
179
214
  }
180
- for (const skill of agentSkills(agent)) {
181
- const skillPath = apcSkillFile(project.path, skill);
182
- if (fs.existsSync(skillPath)) {
183
- parts.push(`## Skill: ${skill}\n` + fs.readFileSync(skillPath, "utf8").trim());
184
- }
185
- }
215
+ // The agent's declared skills, with progressive disclosure: a small skill is
216
+ // injected whole, a large one (or one with images) as a card the agent pages
217
+ // with read_skill / attach_media / view_media. See skills/agent-skills.js.
218
+ const declared = renderAgentSkillsBlock(loadAgentSkills(project, agent));
219
+ if (declared) parts.push(declared);
186
220
  return parts.join("\n\n");
187
221
  }
@@ -14,7 +14,9 @@
14
14
  // wantsSuggestions — whether the surface can render the trailing
15
15
  // `suggestions` JSON block (deck/desktop UI can; raw
16
16
  // Telegram cannot)
17
- // channel — resolved surface ("deck"/"desktop"/"telegram"/…)
17
+ // channel — resolved surface ("deck"/"desktop"/"telegram"). A channel
18
+ // this file does not recognise resolves to "api", not to
19
+ // itself — see the `default` branch for why
18
20
  // channelMeta — surface metadata (e.g. `{ voice: true }` flags spoken mode)
19
21
  import { CHANNELS } from "../../constants/channels.js";
20
22
 
@@ -93,6 +95,19 @@ export function buildVoiceChannelContext(channel, { projectId, language = "es" }
93
95
  case CHANNELS.TELEGRAM:
94
96
  return { ...base, contextNote: dynamicNote, channel: CHANNELS.TELEGRAM, channelMeta: {} };
95
97
  default:
96
- return { ...base, contextNote: dynamicNote, channel: channel || CHANNELS.API, channelMeta: {} };
98
+ // An unrecognised channel does NOT pass through. The cases above ARE the
99
+ // surfaces this pre-processor knows how to shape; a string it does not
100
+ // recognise is by definition one it can make no claim about, and trusting
101
+ // it let the CALLER pick a surface's behaviour by naming it. That is a
102
+ // budget decision, not a label: `channelToolIters` (agent/constants.js)
103
+ // hands `web`/`web_sidebar` a run-to-completion ceiling because those are
104
+ // the surfaces a human WATCHES, so POST /voice/turn with
105
+ // `channel: "web"` would have run a SPOKEN turn uncapped — the opposite
106
+ // of what a voice answer wants, which is short and fast.
107
+ //
108
+ // So an unknown channel falls back to `api`, the bounded default, exactly
109
+ // as an absent one already did. This keeps the budget keyed on the real
110
+ // surface: a new one here is one more `case`, added deliberately.
111
+ return { ...base, contextNote: dynamicNote, channel: CHANNELS.API, channelMeta: {} };
97
112
  }
98
113
  }
@@ -0,0 +1,117 @@
1
+ // The never-silent floor: what a surface says when a turn's closing came back
2
+ // empty.
3
+ //
4
+ // runAgent re-prompts a dud turn (MAX_EMPTY_RETRIES) and then gives up, and the
5
+ // comment where it gives up hands the problem on: "the surface's last-resort
6
+ // floor sends a non-silent reply". Telegram had one. The web did not —
7
+ // `result.text` went out verbatim, so an empty turn rendered as an empty bubble
8
+ // and was written to the thread as an empty assistant row, which is what the
9
+ // NEXT turn reads back as the answer it gave.
10
+ //
11
+ // Two layers, and the order is the whole point:
12
+ //
13
+ // 1. the model writes the closing itself, from what the turn actually did;
14
+ // 2. the canned i18n line goes out ONLY when the model cannot answer either —
15
+ // usually the same outage that emptied the turn in the first place.
16
+ //
17
+ // Never silent beats never canned, in that order. A turn that DID answer never
18
+ // reaches the floor: it costs a model call, and it must never speak over a real
19
+ // reply.
20
+ import { authorLine } from "./author-line.js";
21
+ import { summarizeToolTrace, formatToolSummary } from "./tool-summary.js";
22
+ import { t, resolveLang } from "#core/i18n/index.js";
23
+
24
+ // Addressed to the model, not to the user: what the line has to DO. The words
25
+ // are the model's — see author-line.js.
26
+ const INSTRUCTION_WORKED =
27
+ "You worked on the user's request but the closing message never got written. " +
28
+ "Write it now: where the work got to, and whether you should keep going if something is left.";
29
+ const INSTRUCTION_NOTHING =
30
+ "Your reply came back empty. Write the one line that should have gone out — " +
31
+ "acknowledge them without claiming a result you do not have.";
32
+
33
+ /**
34
+ * The line to send when there is no closing text. Callers decide WHEN they are
35
+ * in that situation (the rules differ per surface — Telegram also treats a
36
+ * closing that merely repeats the last streamed piece as nothing to send) and
37
+ * what counts as having worked; this owns what gets said.
38
+ *
39
+ * @param {object} o
40
+ * @param {object} o.globalConfig config snapshot — names the model and the language
41
+ * @param {string} [o.model] write with this model instead of the super-agent's
42
+ * (a project agent's line is its own to word)
43
+ * @param {boolean} [o.worked] did the turn do anything the user saw? Decides
44
+ * between "here's where it got to" and a bare ack
45
+ * @param {string} [o.lastText] the last thing the turn actually said
46
+ * @param {object} [o.toolSummary] summarizeToolTrace() output, for what it did
47
+ * @param {Function}[o.authorLineFn] injectable for tests
48
+ * @returns {Promise<{text: string, authored: boolean}>} `authored` is false when the
49
+ * canned floor spoke — worth logging, because it means two model calls
50
+ * in a row came back with nothing.
51
+ */
52
+ export async function closingFloorLine({
53
+ globalConfig,
54
+ model = "",
55
+ worked = false,
56
+ lastText = "",
57
+ toolSummary = null,
58
+ authorLineFn = authorLine,
59
+ }) {
60
+ const authored = await authorLineFn({
61
+ globalConfig,
62
+ ...(model ? { model } : {}),
63
+ instruction: worked ? INSTRUCTION_WORKED : INSTRUCTION_NOTHING,
64
+ context: [
65
+ lastText ? `The last thing you said to them was: ${lastText}` : "",
66
+ toolSummary ? `What you did this turn: ${formatToolSummary(toolSummary)}` : "",
67
+ ].filter(Boolean).join("\n"),
68
+ });
69
+ const lang = resolveLang(globalConfig);
70
+ return {
71
+ text: authored || t(worked ? "reply.fallback_continue" : "reply.fallback_done", { lang }),
72
+ authored: Boolean(authored),
73
+ };
74
+ }
75
+
76
+ /**
77
+ * The floor as a request/response surface needs it: hand it the turn's reply and
78
+ * get back the text to send, persist and render.
79
+ *
80
+ * A non-empty reply comes back untouched and costs nothing — no model call, no
81
+ * canned sentence written over an answer the model did give. Only an empty one
82
+ * is floored, and `floored` says so for the log.
83
+ *
84
+ * NOT for an aborted turn. An interruption that wrote nothing is meant to leave
85
+ * no bubble at all; flooring it would answer a question the user withdrew.
86
+ *
87
+ * @param {object} o
88
+ * @param {object} o.globalConfig
89
+ * @param {string} [o.model] the model to write with (a project agent's own)
90
+ * @param {string} [o.text] the turn's reply, as it came back
91
+ * @param {string} [o.streamedText] the last text the turn streamed, if any
92
+ * @param {object[]}[o.trace] the turn's tool calls
93
+ * @param {Function}[o.authorLineFn] injectable for tests
94
+ * @returns {Promise<{text: string, authored: boolean, floored: boolean}>}
95
+ */
96
+ export async function floorReplyText({
97
+ globalConfig,
98
+ model = "",
99
+ text = "",
100
+ streamedText = "",
101
+ trace = [],
102
+ authorLineFn = authorLine,
103
+ }) {
104
+ if (String(text || "").trim()) return { text, authored: false, floored: false };
105
+ const toolSummary = summarizeToolTrace(trace);
106
+ const { text: line, authored } = await closingFloorLine({
107
+ globalConfig,
108
+ model,
109
+ // On the web the mid-turn prose was already rendered, so "worked" is not a
110
+ // guess: either the user watched text arrive or a tool ran.
111
+ worked: Boolean(String(streamedText || "").trim()) || Boolean(toolSummary),
112
+ lastText: String(streamedText || "").trim(),
113
+ toolSummary,
114
+ authorLineFn,
115
+ });
116
+ return { text: line, authored, floored: true };
117
+ }
@@ -1,3 +1,4 @@
1
+ import { CHANNELS } from "#core/constants/channels.js";
1
2
  // Per-turn tool-loop budget for conversational surfaces (telegram/desktop/voice
2
3
  // /deck). The LAST of these iterations is reserved by run-agent.js for a
3
4
  // tool-free, model-authored wrap-up — so a multi-step task gets ~N-1 action
@@ -5,16 +6,124 @@
5
6
  // Coding surfaces (web Code / terminal Build) raise this via maxIters and use
6
7
  // the finish-tool completionContract instead.
7
8
  export const MAX_TOOL_ITERS = 10;
8
- // Telegram is the "do real work for me" conversational surface (the super-agent
9
- // Roby): it needs to chain explore→edit→verify→close autonomously, not stop
10
- // after ~9 actions and ask "want me to continue?". A budget of 10 left only one
11
- // usable action step before the reserved wrap-up, so multi-step tasks routinely
12
- // cut off mid-job. We give it a real autonomy budget (mirroring the TUI Code
13
- // surface's maxIters:40) while keeping it below the coding surfaces. The
14
- // reserved final-step wrap-up still applies, but now only fires when a task
15
- // genuinely exhausts this budget a rare safety floor, not the default close.
16
- // Overridable per-deployment via config.super_agent.telegram_max_iters.
17
- export const TELEGRAM_TOOL_ITERS = 24;
9
+ // Telegram is an owner-controlled work surface too. Its live action notices
10
+ // make long turns observable, so stopping after a small count and asking
11
+ // "should I continue?" is friction rather than a guardrail. This is a runaway
12
+ // backstop: the loop normally ends when work is done, while stuck detection
13
+ // still aborts repeats. Overridable via config.super_agent.telegram_max_iters.
14
+ export const TELEGRAM_TOOL_ITERS = 1000;
15
+ // A background routine that does NOT report to Telegram has no human waiting on
16
+ // a bounded chat turn: nobody is going to read a "want me to keep going?"
17
+ // wrap-up, let alone answer it. Capping such a run at the conversational budget
18
+ // just filed a half-finished record — Magui hitting ~23 steps and stopping
19
+ // mid-backlog. So a non-Telegram routine runs until the work is actually done:
20
+ // the loop already ends on its own the moment the model stops calling tools
21
+ // (run-agent.js), and this high finite ceiling stays only as a runaway backstop.
22
+ // Overridable per-deployment via config.super_agent.routine_max_iters.
23
+ export const ROUTINE_UNCAPPED_TOOL_ITERS = 1000;
24
+ // The web chat — big chat and docked sidebar — is the surface you WATCH: every
25
+ // tool call renders live, streaming survives a refresh, and a person is one
26
+ // click from stopping the turn. The bounded budget exists for the surface where
27
+ // none of that is true. On Telegram a turn scrolls past on a phone with no way
28
+ // to see it going wrong, so stopping to ask IS the guardrail. On web the human
29
+ // is the guardrail, and being asked "want me to keep going?" every 9 actions is
30
+ // pure friction — the whole point of the surface is that it finishes the job.
31
+ //
32
+ // So web runs like a non-Telegram routine: until the work is actually done. The
33
+ // loop already ends on its own the moment the model stops calling tools, stuck
34
+ // detection aborts the repeat-loops, and this ceiling is only the runaway
35
+ // backstop — not a normal stopping point.
36
+ // Overridable per-deployment via config.super_agent.web_max_iters.
37
+ export const WEB_TOOL_ITERS = ROUTINE_UNCAPPED_TOOL_ITERS;
38
+ // A GROUP speaker gets its own number, and this is the one place that says why.
39
+ // A group turn runs the same loop on the same watched surface as the web chat —
40
+ // it streams live and, since the cascade registers in active-turns, Stop reaches
41
+ // it — so by the surface rule above it would inherit WEB_TOOL_ITERS. It used to,
42
+ // by accident: run-group-turn.js passes `channel: WEB` (for the channel PROMPT)
43
+ // and the budget fell out of that string.
44
+ //
45
+ // What the surface rule does not model is the CASCADE. One owner line can
46
+ // produce up to MAX_TURNS_PER_MESSAGE (10, group/turn-resolver.js) agent
47
+ // replies, each a full loop run, so handing every speaker the 1:1 ceiling makes
48
+ // one message worth ten of them — 10x whatever number is written down, which is
49
+ // not a ceiling anybody chose. Same failure the judge rounds had, and the same
50
+ // answer: the budget belongs to the OWNER'S turn, and the runs it fans out into
51
+ // have to fit inside it.
52
+ //
53
+ // So: generous enough for genuine multi-step work (5x the conversational
54
+ // default — a speaker asked to go look something up has real room), small
55
+ // enough that ten of them is still a number picked on purpose. The invariant
56
+ // that keeps it honest, asserted in tests/web-iter-budget.test.js:
57
+ //
58
+ // GROUP_TOOL_ITERS * MAX_TURNS_PER_MESSAGE <= WEB_TOOL_ITERS
59
+ //
60
+ // — one owner message in a room can never cost more than one owner message in a
61
+ // 1:1 web chat. Raise either factor and that test says so.
62
+ //
63
+ // Exhausting it is not a dead end: the last iteration is the tool-free wrap-up,
64
+ // so the speaker closes with how far it got and the room carries on. A group is
65
+ // a conversation; solo work that genuinely needs hundreds of steps belongs in
66
+ // that agent's own chat, which has the ceiling for it.
67
+ // Overridable per-deployment via config.super_agent.group_max_iters.
68
+ export const GROUP_TOOL_ITERS = 50;
69
+ // ONE TURN, ONE BUDGET. Every number above is the budget for a TURN, not for
70
+ // one pass of the tool loop — and a turn can run the loop more than once, when
71
+ // the completion judge sends it back to finish something (agent/judge.js). Those
72
+ // rounds SHARE the number: each gets what the rounds before it left. Before
73
+ // this, every round was handed the full budget again and nothing summed, so the
74
+ // real ceiling was (1 + judge.max_iterations) × the number written here — 3×1000
75
+ // on web from a single message. That ceiling was never a decision anyone made;
76
+ // it was the product of two settings that didn't know about each other.
77
+ //
78
+ // The alternative was a separate, smaller budget for verification rounds. It was
79
+ // rejected for the reason this comment exists: a second number does not tell you
80
+ // what one turn may spend, it just makes you multiply two numbers instead of
81
+ // one. The budget answers "how many tool steps before we stop and ask the
82
+ // human", and that question is about the turn.
83
+ //
84
+ // The floor below is what a round needs to be worth running: one action step,
85
+ // plus the tool-free closing step run-agent.js reserves. With less than that a
86
+ // round can only produce a "ran out of room" recap — over the top of an answer
87
+ // we already have — so the judge loop stops instead of starting one.
88
+ export const MIN_JUDGE_ROUND_ITERS = 2;
89
+ // The channels WEB_TOOL_ITERS applies to. Coding surfaces (web_code, code) are
90
+ // deliberately absent: they set their own budget alongside the completion
91
+ // contract, and that pairing is what makes them stop on `finish` rather than on
92
+ // a count.
93
+ const RUN_TO_COMPLETION_CHANNELS = new Set([CHANNELS.WEB, CHANNELS.WEB_SIDEBAR]);
94
+
95
+ /**
96
+ * Default tool-loop budget for a turn on `channel`, or null when the channel
97
+ * has no opinion and runAgent's own default should stand. An explicit
98
+ * `maxIters` from the caller always wins over this.
99
+ *
100
+ * Keyed on the SURFACE, not on who is answering: the budget is about whether a
101
+ * human can watch the turn work, which is just as true of a project agent as it
102
+ * is of the super-agent. Both reach it — runSuperAgent for Roby, runAgentTurn
103
+ * for everyone else — because a chat that stops every 9 actions to ask is the
104
+ * same friction whichever agent is in it.
105
+ *
106
+ * Telegram resolves its budget at its own call site (channels/telegram/reply.js)
107
+ * and routines at theirs (routines/runner.js); this covers the surfaces that
108
+ * reach the loop through the plain daemon chat routes.
109
+ */
110
+ export function channelToolIters(config, channel) {
111
+ if (!RUN_TO_COMPLETION_CHANNELS.has(channel)) return null;
112
+ const raw = Number(config?.super_agent?.web_max_iters);
113
+ return Number.isFinite(raw) && raw > 0 ? raw : WEB_TOOL_ITERS;
114
+ }
115
+
116
+ /**
117
+ * Tool-loop budget for ONE speaker in a group cascade. Passed as an explicit
118
+ * `maxIters` by run-group-turn.js rather than resolved from the channel: the
119
+ * group turn runs on `channel: WEB` so the agent gets the web channel prompt,
120
+ * and `channelToolIters` must keep meaning what it means for a 1:1 web chat.
121
+ * See GROUP_TOOL_ITERS for why a room is not simply a watched chat.
122
+ */
123
+ export function groupToolIters(config) {
124
+ const raw = Number(config?.super_agent?.group_max_iters);
125
+ return Number.isFinite(raw) && raw > 0 ? raw : GROUP_TOOL_ITERS;
126
+ }
18
127
  // Defined in tools/names.js, next to the names they reference.
19
128
  export { ACK_ONLY_TOOLS, TURN_ENDING_TOOLS } from "./tools/names.js";
20
129
  export const MAX_CONSECUTIVE_ACKS = 2;
@@ -22,4 +131,3 @@ export const MAX_CONSECUTIVE_ACKS = 2;
22
131
  // tool runs we break the loop — even under completionContract — because the
23
132
  // task literally cannot advance without a human reply. Without this, models
24
133
  // under forced toolChoice spam the same question across iterations.
25
-
@@ -0,0 +1,56 @@
1
+ // One-shot engine calls that survive a bad minute.
2
+ //
3
+ // The agent loop has always walked a fallback chain: a 429 or a 5xx rotates to
4
+ // the next model and the turn continues. Every OTHER caller went straight to
5
+ // callEngine with a single model id and no chain, so the same rate limit that
6
+ // the super-agent shrugged off ended a delegated call outright — "how can it
7
+ // rate-limit her if it doesn't rate-limit him" has a boring answer, and this is
8
+ // it. `call_agent` was the one that showed: Roby delegates to a project agent,
9
+ // Zen answers 429, and the sub-call dies while Roby's own turn would have moved
10
+ // to Gemini without saying a word.
11
+ //
12
+ // Same classifier as the loop (retry.js), same chain (model-router.js), so the
13
+ // two agree about what "retryable" means and which model comes next.
14
+ import { callEngine } from "../engines/index.js";
15
+ import { fallbackModels, isFallbackEnabled } from "./model-router.js";
16
+ import { messagesForModel } from "./model-capabilities.js";
17
+ import { isRetryableEngineError, shortRetryReason } from "./retry.js";
18
+
19
+ /**
20
+ * callEngine, walking the configured fallback chain on retryable failures.
21
+ *
22
+ * @param {object} params forwarded to callEngine (minus modelId)
23
+ * @param {string} params.modelId the model to try first
24
+ * @param {object} params.config global/project config; supplies the chain
25
+ * @param {(ev:{model:string,reason:string,retry_with:string})=>void} [onRotate]
26
+ * called before each rotation, so a caller can log why the model changed
27
+ * @returns {Promise<object>} the engine result, plus `model` — the one that
28
+ * actually answered, which is not always the one that was asked.
29
+ */
30
+ export async function callEngineWithFallback({ modelId, config, ...rest }, { onRotate } = {}) {
31
+ const chain = isFallbackEnabled(config)
32
+ ? fallbackModels(config).filter((m) => m && m !== modelId)
33
+ : [];
34
+ let active = modelId;
35
+ for (;;) {
36
+ try {
37
+ const out = await callEngine({
38
+ ...rest,
39
+ messages: messagesForModel(rest.messages, active, config),
40
+ config,
41
+ modelId: active,
42
+ });
43
+ return { ...out, model: active };
44
+ } catch (e) {
45
+ if (e?.name === "AbortError" || rest.signal?.aborted) throw e;
46
+ if (!chain.length || !isRetryableEngineError(e)) throw e;
47
+ const next = chain.shift();
48
+ try {
49
+ onRotate?.({ model: active, reason: shortRetryReason(e), retry_with: next });
50
+ } catch {
51
+ /* logging must not break the call */
52
+ }
53
+ active = next;
54
+ }
55
+ }
56
+ }