@agentprojectcontext/apx 1.80.2 → 1.89.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (838) hide show
  1. package/package.json +9 -8
  2. package/skills/apc-context/SKILL.md +14 -7
  3. package/skills/apx/SKILL.md +62 -2
  4. package/skills/apx-mcp/SKILL.md +42 -15
  5. package/src/core/agent/a2a/peers.js +161 -0
  6. package/src/core/agent/a2a/reply.js +379 -27
  7. package/src/core/agent/abort.js +25 -0
  8. package/src/core/agent/agent-model.js +58 -0
  9. package/src/core/agent/agent-tools.js +101 -0
  10. package/src/core/agent/author-line.js +110 -0
  11. package/src/core/agent/build-agent-system.js +52 -18
  12. package/src/core/agent/channels/voice-context.js +17 -2
  13. package/src/core/agent/closing-floor.js +117 -0
  14. package/src/core/agent/constants.js +119 -11
  15. package/src/core/agent/engine-call.js +56 -0
  16. package/src/core/agent/group/run-group-turn.js +218 -0
  17. package/src/core/agent/group/turn-resolver.js +165 -0
  18. package/src/core/agent/judge.js +138 -11
  19. package/src/core/agent/loop/side-effects.js +106 -3
  20. package/src/core/agent/memory.js +31 -18
  21. package/src/core/agent/model-capabilities.js +47 -0
  22. package/src/core/agent/model-router.js +11 -40
  23. package/src/core/agent/prompt-builder.js +47 -0
  24. package/src/core/agent/prompts/channels/a2a.md +12 -0
  25. package/src/core/agent/prompts/channels/code.md +3 -1
  26. package/src/core/agent/prompts/channels/telegram.md +2 -0
  27. package/src/core/agent/prompts/channels/web_code.md +1 -1
  28. package/src/core/agent/prompts/channels/whatsapp.md +37 -0
  29. package/src/core/agent/prompts/core/agent-base.md +2 -0
  30. package/src/core/agent/prompts/discipline/action.md +1 -0
  31. package/src/core/agent/prompts/discipline/two-segment.md +2 -1
  32. package/src/core/agent/prompts/modes/mobility.md +36 -0
  33. package/src/core/agent/retry.js +42 -0
  34. package/src/core/agent/run-agent.js +322 -25
  35. package/src/core/agent/run-turn.js +253 -0
  36. package/src/core/agent/self-memory.js +18 -52
  37. package/src/core/agent/skills/agent-skills.js +118 -0
  38. package/src/core/agent/skills/catalog.js +1 -1
  39. package/src/core/agent/skills/declared.js +13 -0
  40. package/src/core/agent/skills/index-store.js +8 -1
  41. package/src/core/agent/skills/inspector.js +20 -3
  42. package/src/core/agent/skills/loader.js +18 -3
  43. package/src/core/agent/skills/media.js +121 -0
  44. package/src/core/agent/skills/origin.js +61 -0
  45. package/src/core/agent/skills/sections.js +136 -0
  46. package/src/core/agent/super-agent.js +54 -14
  47. package/src/core/agent/tools/handlers/_calendar.js +50 -0
  48. package/src/core/agent/tools/handlers/add-mcp.js +103 -0
  49. package/src/core/agent/tools/handlers/asana-create-task.js +3 -1
  50. package/src/core/agent/tools/handlers/attach-media.js +56 -0
  51. package/src/core/agent/tools/handlers/calendar-create-event.js +38 -0
  52. package/src/core/agent/tools/handlers/calendar-find-slot.js +39 -0
  53. package/src/core/agent/tools/handlers/calendar-list-events.js +39 -0
  54. package/src/core/agent/tools/handlers/calendar-update-event.js +35 -0
  55. package/src/core/agent/tools/handlers/call-agent.js +14 -6
  56. package/src/core/agent/tools/handlers/call-runtime.js +27 -49
  57. package/src/core/agent/tools/handlers/comment-task.js +78 -0
  58. package/src/core/agent/tools/handlers/complete-task.js +60 -0
  59. package/src/core/agent/tools/handlers/configure-agent.js +70 -0
  60. package/src/core/agent/tools/handlers/create-agent.js +68 -0
  61. package/src/core/agent/tools/handlers/create-task.js +41 -3
  62. package/src/core/agent/tools/handlers/import-agent.js +5 -5
  63. package/src/core/agent/tools/handlers/list-mcp-tools.js +83 -0
  64. package/src/core/agent/tools/handlers/list-routines.js +46 -0
  65. package/src/core/agent/tools/handlers/list-tasks.js +8 -1
  66. package/src/core/agent/tools/handlers/mark-commitment.js +57 -0
  67. package/src/core/agent/tools/handlers/read-skill.js +64 -0
  68. package/src/core/agent/tools/handlers/remember-routine.js +2 -8
  69. package/src/core/agent/tools/handlers/remember.js +82 -6
  70. package/src/core/agent/tools/handlers/remove-agent.js +42 -0
  71. package/src/core/agent/tools/handlers/run-routine.js +94 -0
  72. package/src/core/agent/tools/handlers/run-shell.js +44 -2
  73. package/src/core/agent/tools/handlers/send-telegram.js +41 -19
  74. package/src/core/agent/tools/handlers/set-agent-prompt.js +44 -0
  75. package/src/core/agent/tools/handlers/view-media.js +69 -0
  76. package/src/core/agent/tools/handlers/write-agent-memory.js +52 -0
  77. package/src/core/agent/tools/helpers.js +36 -4
  78. package/src/core/agent/tools/names.js +64 -0
  79. package/src/core/agent/tools/registry-bridge.js +24 -1
  80. package/src/core/agent/tools/registry.js +79 -0
  81. package/src/core/agent/tools/tool-call-parser.js +136 -13
  82. package/src/core/agent/vision-bridge.js +69 -0
  83. package/src/core/apc/agent-identity.js +74 -0
  84. package/src/core/apc/agent-rename-refs.js +187 -0
  85. package/src/core/apc/agent-write.js +312 -0
  86. package/src/core/apc/agents-vault.js +1 -1
  87. package/src/core/apc/blob-keys.js +42 -0
  88. package/src/core/apc/frontmatter.js +166 -10
  89. package/src/core/apc/parser.js +33 -83
  90. package/src/core/apc/paths.js +4 -6
  91. package/src/core/apc/project-memory.js +44 -0
  92. package/src/core/apc/projects-helpers.js +33 -0
  93. package/src/core/apc/scaffold.js +36 -16
  94. package/src/core/channels/telegram/ask-callbacks.js +103 -0
  95. package/src/core/channels/telegram/dispatch.js +154 -30
  96. package/src/core/channels/telegram/helpers.js +59 -7
  97. package/src/core/channels/telegram/inbound/audio.js +26 -30
  98. package/src/core/channels/telegram/inbound/file.js +22 -32
  99. package/src/core/channels/telegram/inbound/photo.js +24 -28
  100. package/src/core/channels/telegram/progress-gate.js +76 -0
  101. package/src/core/channels/telegram/reply.js +151 -43
  102. package/src/core/channels/telegram/voice-note.js +150 -0
  103. package/src/core/config/index.js +53 -54
  104. package/src/core/config/paths.js +117 -31
  105. package/src/core/config/redact.js +89 -4
  106. package/src/core/config/secret-values.js +2 -4
  107. package/src/core/constants/actors.js +5 -0
  108. package/src/core/constants/channels.js +3 -1
  109. package/src/core/constants/task-categories.js +73 -0
  110. package/src/core/constants/task-fields.js +28 -0
  111. package/src/core/engines/_globs.js +33 -0
  112. package/src/core/engines/anthropic.js +19 -1
  113. package/src/core/engines/catalog.js +20 -0
  114. package/src/core/engines/gemini.js +84 -16
  115. package/src/core/engines/index.js +19 -3
  116. package/src/core/engines/mock.js +145 -1
  117. package/src/core/engines/openai-compatible.js +150 -15
  118. package/src/core/engines/presets.js +36 -9
  119. package/src/core/engines/zen.js +131 -0
  120. package/src/core/events/bus.js +140 -0
  121. package/src/core/events/mascot-notify.js +156 -0
  122. package/src/core/http-tools/browser.js +366 -36
  123. package/src/core/http-tools/catalog.js +206 -22
  124. package/src/core/http-tools/grep.js +62 -7
  125. package/src/core/http-tools/registry.js +3 -1
  126. package/src/core/i18n/en.js +34 -3
  127. package/src/core/i18n/es.js +36 -4
  128. package/src/core/i18n/index.js +5 -5
  129. package/src/core/i18n/pt.js +32 -3
  130. package/src/core/identity/self.js +14 -1
  131. package/src/core/images/engines/a1111.js +219 -0
  132. package/src/core/images/engines/index.js +187 -0
  133. package/src/core/images/engines/mock.js +74 -0
  134. package/src/core/images/engines/openai.js +130 -0
  135. package/src/core/images/engines/sdcpp.js +204 -0
  136. package/src/core/images/engines/shared.js +218 -0
  137. package/src/core/images/generate.js +260 -0
  138. package/src/core/integrations/catalog.js +8 -3
  139. package/src/core/integrations/plugins/_google-oauth.js +179 -0
  140. package/src/core/integrations/plugins/asana.js +7 -3
  141. package/src/core/integrations/plugins/calendar.js +404 -0
  142. package/src/core/integrations/store.js +2 -0
  143. package/src/core/memory/broker.js +16 -1
  144. package/src/core/memory/compactor.js +19 -3
  145. package/src/core/memory/consolidate.js +2 -2
  146. package/src/core/memory/dated-log.js +66 -0
  147. package/src/core/memory/embed-engines/custom.js +59 -0
  148. package/src/core/memory/embed-engines/gemini.js +9 -3
  149. package/src/core/memory/embed-engines/index.js +87 -15
  150. package/src/core/memory/embeddings.js +52 -24
  151. package/src/core/memory/index.js +13 -3
  152. package/src/core/memory/indexer.js +83 -27
  153. package/src/core/memory/prune.js +182 -0
  154. package/src/core/memory/store.js +22 -0
  155. package/src/core/memory/summarizer.js +72 -8
  156. package/src/core/mobility/answer.js +80 -0
  157. package/src/core/mobility/geofence.js +667 -0
  158. package/src/core/mobility/osm-route.js +282 -0
  159. package/src/core/mobility/preferences.js +91 -0
  160. package/src/core/mobility/state.js +245 -0
  161. package/src/core/mobility/trip-event.js +384 -0
  162. package/src/core/net/tailscale.js +168 -0
  163. package/src/core/profiles/bundled/secretary/PROFILE.md +32 -42
  164. package/src/core/profiles/bundled/secretary/config.schema.es.json +68 -0
  165. package/src/core/profiles/bundled/secretary/config.schema.json +30 -2
  166. package/src/core/profiles/bundled/secretary/profile.json +3 -1
  167. package/src/core/profiles/bundled/secretary/routines/a2a-sweep.json +20 -0
  168. package/src/core/profiles/bundled/secretary/routines/day-close.json +4 -1
  169. package/src/core/profiles/bundled/secretary/routines/day-open.json +7 -1
  170. package/src/core/profiles/bundled/secretary/routines/watch.json +13 -2
  171. package/src/core/profiles/lifecycle.js +243 -19
  172. package/src/core/profiles/paths.js +12 -0
  173. package/src/core/profiles/store.js +47 -0
  174. package/src/core/routines/active-runs.js +213 -0
  175. package/src/core/routines/delivery.js +612 -0
  176. package/src/core/routines/header.js +88 -0
  177. package/src/core/routines/index.js +26 -0
  178. package/src/core/routines/run-log.js +78 -0
  179. package/src/core/routines/runner.js +629 -66
  180. package/src/core/routines/signals.js +75 -0
  181. package/src/core/runtime-skills/apc-context/SKILL.md +14 -7
  182. package/src/core/runtime-skills/apx/SKILL.md +93 -1
  183. package/src/core/runtime-skills/apx-agency-agents/SKILL.md +2 -2
  184. package/src/core/runtime-skills/apx-agent/SKILL.md +134 -19
  185. package/src/core/runtime-skills/apx-commitment/SKILL.md +134 -0
  186. package/src/core/runtime-skills/apx-image/SKILL.md +60 -0
  187. package/src/core/runtime-skills/apx-integrations/SKILL.md +82 -0
  188. package/src/core/runtime-skills/apx-mcp/SKILL.md +45 -14
  189. package/src/core/runtime-skills/apx-mcp-builder/SKILL.md +4 -4
  190. package/src/core/runtime-skills/apx-profile/SKILL.md +27 -2
  191. package/src/core/runtime-skills/apx-project/SKILL.md +23 -2
  192. package/src/core/runtime-skills/apx-routine/SKILL.md +40 -17
  193. package/src/core/runtime-skills/apx-runtime/SKILL.md +124 -14
  194. package/src/core/runtime-skills/apx-sessions/SKILL.md +7 -6
  195. package/src/core/runtime-skills/apx-skill-builder/SKILL.md +15 -13
  196. package/src/core/runtime-skills/apx-task/SKILL.md +79 -26
  197. package/src/core/runtime-skills/apx-telegram/SKILL.md +12 -12
  198. package/src/core/runtime-skills/apx-transcribe/SKILL.md +56 -0
  199. package/src/core/runtime-skills/apx-voice/SKILL.md +27 -8
  200. package/src/core/runtime-skills/claude-code/SKILL.md +8 -0
  201. package/src/core/runtime-skills/openrouter/SKILL.md +8 -2
  202. package/src/core/runtimes/_spawn.js +9 -1
  203. package/src/core/runtimes/claude-code.js +11 -2
  204. package/src/core/runtimes/codex.js +44 -10
  205. package/src/core/runtimes/index.js +17 -2
  206. package/src/core/runtimes/opencode.js +88 -9
  207. package/src/core/runtimes/outcome.js +119 -0
  208. package/src/core/sessions/index.js +193 -1
  209. package/src/core/stores/agent-inbox.js +109 -23
  210. package/src/core/stores/code-sessions.js +21 -0
  211. package/src/core/stores/commitments.js +27 -3
  212. package/src/core/stores/conversations.js +220 -20
  213. package/src/core/stores/deliveries.js +177 -0
  214. package/src/core/stores/media-archive.js +228 -0
  215. package/src/core/stores/messages.js +1096 -112
  216. package/src/core/stores/organization.js +34 -0
  217. package/src/core/stores/project-memory.js +71 -0
  218. package/src/core/stores/routine-memory.js +16 -8
  219. package/src/core/stores/routines.js +27 -49
  220. package/src/core/stores/sessions.js +4 -8
  221. package/src/core/stores/tasks.js +212 -18
  222. package/src/core/stores/turn-record.js +209 -0
  223. package/src/core/tasks/columns.js +136 -0
  224. package/src/core/tasks/comment-turn.js +258 -0
  225. package/src/core/util/time.js +13 -0
  226. package/src/core/voice/engines/index.js +54 -1
  227. package/src/core/voice/engines/openai.js +50 -4
  228. package/src/core/voice/opus.js +67 -0
  229. package/src/core/voice/pronounceable.js +43 -0
  230. package/src/core/voice/transcription.js +4 -0
  231. package/src/core/voice/tts.js +114 -24
  232. package/src/host/daemon/active-turns.js +188 -0
  233. package/src/host/daemon/api/admin-config.js +9 -0
  234. package/src/host/daemon/api/agents.js +99 -90
  235. package/src/host/daemon/api/artifact-preview.js +7 -6
  236. package/src/host/daemon/api/artifacts.js +3 -2
  237. package/src/host/daemon/api/code.js +55 -9
  238. package/src/host/daemon/api/commitments.js +11 -0
  239. package/src/host/daemon/api/confirm.js +3 -2
  240. package/src/host/daemon/api/conversations.js +543 -35
  241. package/src/host/daemon/api/deck.js +9 -8
  242. package/src/host/daemon/api/deliveries.js +33 -0
  243. package/src/host/daemon/api/desktop.js +5 -4
  244. package/src/host/daemon/api/embeddings.js +15 -6
  245. package/src/host/daemon/api/engines.js +59 -8
  246. package/src/host/daemon/api/exec.js +437 -121
  247. package/src/host/daemon/api/groups.js +215 -0
  248. package/src/host/daemon/api/images.js +107 -0
  249. package/src/host/daemon/api/inbox.js +123 -2
  250. package/src/host/daemon/api/integrations.js +64 -2
  251. package/src/host/daemon/api/mcps.js +7 -6
  252. package/src/host/daemon/api/media.js +283 -0
  253. package/src/host/daemon/api/mobility.js +177 -0
  254. package/src/host/daemon/api/net.js +182 -0
  255. package/src/host/daemon/api/pairing.js +38 -5
  256. package/src/host/daemon/api/profiles.js +30 -2
  257. package/src/host/daemon/api/routines.js +36 -4
  258. package/src/host/daemon/api/runtimes.js +74 -39
  259. package/src/host/daemon/api/sessions-search.js +7 -2
  260. package/src/host/daemon/api/sessions.js +44 -2
  261. package/src/host/daemon/api/shared.js +127 -20
  262. package/src/host/daemon/api/skills.js +11 -4
  263. package/src/host/daemon/api/super-agent.js +384 -53
  264. package/src/host/daemon/api/tasks.js +180 -10
  265. package/src/host/daemon/api/telegram.js +11 -10
  266. package/src/host/daemon/api/thread-faces.js +159 -0
  267. package/src/host/daemon/api/top-level.js +3 -3
  268. package/src/host/daemon/api/transcribe.js +11 -10
  269. package/src/host/daemon/api/tts.js +97 -4
  270. package/src/host/daemon/api/turn-abort.js +23 -0
  271. package/src/host/daemon/api/turns.js +49 -0
  272. package/src/host/daemon/api/voice.js +5 -4
  273. package/src/host/daemon/api/web.js +98 -0
  274. package/src/host/daemon/api.js +39 -0
  275. package/src/host/daemon/delivery-sweep.js +58 -0
  276. package/src/host/daemon/desktop-ws.js +5 -23
  277. package/src/host/daemon/events-ws.js +273 -0
  278. package/src/host/daemon/index.js +59 -15
  279. package/src/host/daemon/plugins/desktop/index.js +17 -4
  280. package/src/host/daemon/plugins/telegram/index.js +78 -40
  281. package/src/host/daemon/pty-bridge.py +99 -0
  282. package/src/host/daemon/routines-scheduler.js +1 -0
  283. package/src/host/daemon/smoke.js +1 -2
  284. package/src/host/daemon/terminal-ws.js +132 -0
  285. package/src/host/daemon/tts-keepwarm.js +87 -0
  286. package/src/host/daemon/wakeup.js +11 -6
  287. package/src/host/daemon/whisper-server.js +44 -0
  288. package/src/host/daemon/whisper-server.py +70 -13
  289. package/src/host/daemon/ws-auth.js +28 -0
  290. package/src/interfaces/android/app/build.gradle +42 -0
  291. package/src/interfaces/android/app/proguard-rules.pro +4 -0
  292. package/src/interfaces/android/app/src/main/AndroidManifest.xml +139 -0
  293. package/src/interfaces/android/app/src/main/java/dev/agentprojectcontext/apx/AlertScreen.java +139 -0
  294. package/src/interfaces/android/app/src/main/java/dev/agentprojectcontext/apx/AndroidAutoDetector.java +106 -0
  295. package/src/interfaces/android/app/src/main/java/dev/agentprojectcontext/apx/ApxCarAppService.java +57 -0
  296. package/src/interfaces/android/app/src/main/java/dev/agentprojectcontext/apx/ApxPreferences.java +165 -0
  297. package/src/interfaces/android/app/src/main/java/dev/agentprojectcontext/apx/CarAlertStore.java +84 -0
  298. package/src/interfaces/android/app/src/main/java/dev/agentprojectcontext/apx/CarMessageActionReceiver.java +47 -0
  299. package/src/interfaces/android/app/src/main/java/dev/agentprojectcontext/apx/CarMessageNotification.java +152 -0
  300. package/src/interfaces/android/app/src/main/java/dev/agentprojectcontext/apx/DaemonAddress.java +35 -0
  301. package/src/interfaces/android/app/src/main/java/dev/agentprojectcontext/apx/DaemonClient.java +339 -0
  302. package/src/interfaces/android/app/src/main/java/dev/agentprojectcontext/apx/DeviceLocation.java +38 -0
  303. package/src/interfaces/android/app/src/main/java/dev/agentprojectcontext/apx/ErrandScreen.java +127 -0
  304. package/src/interfaces/android/app/src/main/java/dev/agentprojectcontext/apx/MainActivity.java +872 -0
  305. package/src/interfaces/android/app/src/main/java/dev/agentprojectcontext/apx/MapsNavigationDetector.java +63 -0
  306. package/src/interfaces/android/app/src/main/java/dev/agentprojectcontext/apx/MapsNavigationListenerService.java +453 -0
  307. package/src/interfaces/android/app/src/main/java/dev/agentprojectcontext/apx/MapsShareIntentParser.java +93 -0
  308. package/src/interfaces/android/app/src/main/java/dev/agentprojectcontext/apx/MascotBlobCatalog.java +66 -0
  309. package/src/interfaces/android/app/src/main/java/dev/agentprojectcontext/apx/MascotOverlayService.java +448 -0
  310. package/src/interfaces/android/app/src/main/java/dev/agentprojectcontext/apx/MascotView.java +249 -0
  311. package/src/interfaces/android/app/src/main/java/dev/agentprojectcontext/apx/MessageFrameParser.java +240 -0
  312. package/src/interfaces/android/app/src/main/java/dev/agentprojectcontext/apx/NotifyChannels.java +69 -0
  313. package/src/interfaces/android/app/src/main/java/dev/agentprojectcontext/apx/ProximityActionReceiver.java +78 -0
  314. package/src/interfaces/android/app/src/main/java/dev/agentprojectcontext/apx/ProximityNotification.java +161 -0
  315. package/src/interfaces/android/app/src/main/java/dev/agentprojectcontext/apx/StartupReceiver.java +57 -0
  316. package/src/interfaces/android/app/src/main/java/dev/agentprojectcontext/apx/TravelEventGate.java +62 -0
  317. package/src/interfaces/android/app/src/main/java/dev/agentprojectcontext/apx/TravelStatusBanner.java +116 -0
  318. package/src/interfaces/android/app/src/main/java/dev/agentprojectcontext/apx/TripLocationService.java +272 -0
  319. package/src/interfaces/android/app/src/main/java/dev/agentprojectcontext/apx/TripPlacesSheet.java +203 -0
  320. package/src/interfaces/android/app/src/main/java/dev/agentprojectcontext/apx/TripScreen.java +182 -0
  321. package/src/interfaces/android/app/src/main/res/drawable/app_background.xml +12 -0
  322. package/src/interfaces/android/app/src/main/res/drawable/ic_apx_app.xml +10 -0
  323. package/src/interfaces/android/app/src/main/res/drawable/ic_apx_launcher_foreground.xml +12 -0
  324. package/src/interfaces/android/app/src/main/res/drawable/ic_apx_notification.xml +22 -0
  325. package/src/interfaces/android/app/src/main/res/drawable/ic_trip_car.xml +37 -0
  326. package/src/interfaces/android/app/src/main/res/drawable-nodpi/apx_logo.png +0 -0
  327. package/src/interfaces/android/app/src/main/res/drawable-nodpi/mascot_amatista.png +0 -0
  328. package/src/interfaces/android/app/src/main/res/drawable-nodpi/mascot_aqua.png +0 -0
  329. package/src/interfaces/android/app/src/main/res/drawable-nodpi/mascot_brasa.png +0 -0
  330. package/src/interfaces/android/app/src/main/res/drawable-nodpi/mascot_campana.png +0 -0
  331. package/src/interfaces/android/app/src/main/res/drawable-nodpi/mascot_caracol.png +0 -0
  332. package/src/interfaces/android/app/src/main/res/drawable-nodpi/mascot_carbon.png +0 -0
  333. package/src/interfaces/android/app/src/main/res/drawable-nodpi/mascot_cobalto.png +0 -0
  334. package/src/interfaces/android/app/src/main/res/drawable-nodpi/mascot_cometa.png +0 -0
  335. package/src/interfaces/android/app/src/main/res/drawable-nodpi/mascot_coral.png +0 -0
  336. package/src/interfaces/android/app/src/main/res/drawable-nodpi/mascot_cubi.png +0 -0
  337. package/src/interfaces/android/app/src/main/res/drawable-nodpi/mascot_eclipse.png +0 -0
  338. package/src/interfaces/android/app/src/main/res/drawable-nodpi/mascot_faro.png +0 -0
  339. package/src/interfaces/android/app/src/main/res/drawable-nodpi/mascot_gajo.png +0 -0
  340. package/src/interfaces/android/app/src/main/res/drawable-nodpi/mascot_iris.png +0 -0
  341. package/src/interfaces/android/app/src/main/res/drawable-nodpi/mascot_kiwi.png +0 -0
  342. package/src/interfaces/android/app/src/main/res/drawable-nodpi/mascot_laguna.png +0 -0
  343. package/src/interfaces/android/app/src/main/res/drawable-nodpi/mascot_lila.png +0 -0
  344. package/src/interfaces/android/app/src/main/res/drawable-nodpi/mascot_menta.png +0 -0
  345. package/src/interfaces/android/app/src/main/res/drawable-nodpi/mascot_nimbo.png +0 -0
  346. package/src/interfaces/android/app/src/main/res/drawable-nodpi/mascot_noche.png +0 -0
  347. package/src/interfaces/android/app/src/main/res/drawable-nodpi/mascot_onyx.png +0 -0
  348. package/src/interfaces/android/app/src/main/res/drawable-nodpi/mascot_orbita.png +0 -0
  349. package/src/interfaces/android/app/src/main/res/drawable-nodpi/mascot_ovni.png +0 -0
  350. package/src/interfaces/android/app/src/main/res/drawable-nodpi/mascot_papa.png +0 -0
  351. package/src/interfaces/android/app/src/main/res/drawable-nodpi/mascot_parche.png +0 -0
  352. package/src/interfaces/android/app/src/main/res/drawable-nodpi/mascot_peon.png +0 -0
  353. package/src/interfaces/android/app/src/main/res/drawable-nodpi/mascot_perla.png +0 -0
  354. package/src/interfaces/android/app/src/main/res/drawable-nodpi/mascot_pino.png +0 -0
  355. package/src/interfaces/android/app/src/main/res/drawable-nodpi/mascot_quad.png +0 -0
  356. package/src/interfaces/android/app/src/main/res/drawable-nodpi/mascot_rubi.png +0 -0
  357. package/src/interfaces/android/app/src/main/res/drawable-nodpi/mascot_saturno.png +0 -0
  358. package/src/interfaces/android/app/src/main/res/drawable-nodpi/mascot_trebol.png +0 -0
  359. package/src/interfaces/android/app/src/main/res/drawable-nodpi/mascot_trino.png +0 -0
  360. package/src/interfaces/android/app/src/main/res/drawable-nodpi/mascot_volcan.png +0 -0
  361. package/src/interfaces/android/app/src/main/res/drawable-nodpi/mascot_zafiro.png +0 -0
  362. package/src/interfaces/android/app/src/main/res/mipmap-anydpi-v26/ic_launcher.xml +5 -0
  363. package/src/interfaces/android/app/src/main/res/mipmap-anydpi-v26/ic_launcher_round.xml +5 -0
  364. package/src/interfaces/android/app/src/main/res/raw/apx_notification.mp3 +0 -0
  365. package/src/interfaces/android/app/src/main/res/values/colors.xml +4 -0
  366. package/src/interfaces/android/app/src/main/res/values/strings.xml +25 -0
  367. package/src/interfaces/android/app/src/main/res/values/styles.xml +10 -0
  368. package/src/interfaces/android/app/src/main/res/values-v31/styles.xml +14 -0
  369. package/src/interfaces/android/app/src/main/res/xml/automotive_app_desc.xml +9 -0
  370. package/src/interfaces/android/app/src/main/res/xml/network_security_config.xml +10 -0
  371. package/src/interfaces/android/app/src/test/java/dev/agentprojectcontext/apx/AndroidAutoDetectorTest.java +85 -0
  372. package/src/interfaces/android/app/src/test/java/dev/agentprojectcontext/apx/CarAlertStoreTest.java +104 -0
  373. package/src/interfaces/android/app/src/test/java/dev/agentprojectcontext/apx/DaemonAddressTest.java +23 -0
  374. package/src/interfaces/android/app/src/test/java/dev/agentprojectcontext/apx/MapsNavigationDetectorTest.java +69 -0
  375. package/src/interfaces/android/app/src/test/java/dev/agentprojectcontext/apx/MapsShareIntentParserTest.java +31 -0
  376. package/src/interfaces/android/app/src/test/java/dev/agentprojectcontext/apx/MessageFrameParserTest.java +180 -0
  377. package/src/interfaces/android/app/src/test/java/dev/agentprojectcontext/apx/TravelEventGateTest.java +64 -0
  378. package/src/interfaces/android/app/src/test/java/dev/agentprojectcontext/apx/TripPlacesSheetTest.java +66 -0
  379. package/src/interfaces/android/build.gradle +3 -0
  380. package/src/interfaces/android/gradle/wrapper/gradle-wrapper.jar +0 -0
  381. package/src/interfaces/android/gradle/wrapper/gradle-wrapper.properties +9 -0
  382. package/src/interfaces/android/gradle.properties +3 -0
  383. package/src/interfaces/android/gradlew +248 -0
  384. package/src/interfaces/android/gradlew.bat +82 -0
  385. package/src/interfaces/android/settings.gradle +18 -0
  386. package/src/interfaces/cli/commands/a2a.js +145 -4
  387. package/src/interfaces/cli/commands/agent.js +247 -22
  388. package/src/interfaces/cli/commands/code.js +1 -1
  389. package/src/interfaces/cli/commands/commitment.js +5 -0
  390. package/src/interfaces/cli/commands/config.js +85 -6
  391. package/src/interfaces/cli/commands/exec.js +90 -1
  392. package/src/interfaces/cli/commands/image.js +314 -0
  393. package/src/interfaces/cli/commands/mcp.js +87 -23
  394. package/src/interfaces/cli/commands/memory.js +35 -22
  395. package/src/interfaces/cli/commands/panel.js +94 -0
  396. package/src/interfaces/cli/commands/profile.js +14 -0
  397. package/src/interfaces/cli/commands/project.js +29 -0
  398. package/src/interfaces/cli/commands/routine.js +45 -10
  399. package/src/interfaces/cli/commands/runtime.js +30 -7
  400. package/src/interfaces/cli/commands/session.js +90 -38
  401. package/src/interfaces/cli/commands/sessions.js +35 -2
  402. package/src/interfaces/cli/commands/skills.js +15 -9
  403. package/src/interfaces/cli/commands/status.js +2 -3
  404. package/src/interfaces/cli/commands/task.js +54 -5
  405. package/src/interfaces/cli/commands/telegram.js +12 -4
  406. package/src/interfaces/cli/commands/transcribe.js +177 -0
  407. package/src/interfaces/cli/help/index.js +311 -72
  408. package/src/interfaces/cli/http.js +61 -13
  409. package/src/interfaces/cli/index.js +1 -1
  410. package/src/interfaces/cli/routes/agent.js +5 -4
  411. package/src/interfaces/cli/routes/commitment.js +3 -2
  412. package/src/interfaces/cli/routes/config.js +7 -2
  413. package/src/interfaces/cli/routes/image.js +11 -0
  414. package/src/interfaces/cli/routes/index.js +2 -0
  415. package/src/interfaces/cli/routes/log.js +1 -1
  416. package/src/interfaces/cli/routes/memory.js +3 -2
  417. package/src/interfaces/cli/routes/panel.js +15 -2
  418. package/src/interfaces/cli/routes/profile.js +3 -2
  419. package/src/interfaces/cli/routes/transcribe.js +10 -0
  420. package/src/interfaces/cli/stdin.js +29 -0
  421. package/src/interfaces/desktop/assets/blobs/amatista.png +0 -0
  422. package/src/interfaces/desktop/assets/blobs/aqua.png +0 -0
  423. package/src/interfaces/desktop/assets/blobs/brasa.png +0 -0
  424. package/src/interfaces/desktop/assets/blobs/campana.png +0 -0
  425. package/src/interfaces/desktop/assets/blobs/caracol.png +0 -0
  426. package/src/interfaces/desktop/assets/blobs/carbon.png +0 -0
  427. package/src/interfaces/desktop/assets/blobs/cobalto.png +0 -0
  428. package/src/interfaces/desktop/assets/blobs/cometa.png +0 -0
  429. package/src/interfaces/desktop/assets/blobs/coral.png +0 -0
  430. package/src/interfaces/desktop/assets/blobs/cubi.png +0 -0
  431. package/src/interfaces/desktop/assets/blobs/eclipse.png +0 -0
  432. package/src/interfaces/desktop/assets/blobs/faro.png +0 -0
  433. package/src/interfaces/desktop/assets/blobs/gajo.png +0 -0
  434. package/src/interfaces/desktop/assets/blobs/iris.png +0 -0
  435. package/src/interfaces/desktop/assets/blobs/kiwi.png +0 -0
  436. package/src/interfaces/desktop/assets/blobs/laguna.png +0 -0
  437. package/src/interfaces/desktop/assets/blobs/lila.png +0 -0
  438. package/src/interfaces/desktop/assets/blobs/menta.png +0 -0
  439. package/src/interfaces/desktop/assets/blobs/nimbo.png +0 -0
  440. package/src/interfaces/desktop/assets/blobs/noche.png +0 -0
  441. package/src/interfaces/desktop/assets/blobs/onyx.png +0 -0
  442. package/src/interfaces/desktop/assets/blobs/orbita.png +0 -0
  443. package/src/interfaces/desktop/assets/blobs/ovni.png +0 -0
  444. package/src/interfaces/desktop/assets/blobs/papa.png +0 -0
  445. package/src/interfaces/desktop/assets/blobs/parche.png +0 -0
  446. package/src/interfaces/desktop/assets/blobs/peon.png +0 -0
  447. package/src/interfaces/desktop/assets/blobs/perla.png +0 -0
  448. package/src/interfaces/desktop/assets/blobs/pino.png +0 -0
  449. package/src/interfaces/desktop/assets/blobs/quad.png +0 -0
  450. package/src/interfaces/desktop/assets/blobs/rubi.png +0 -0
  451. package/src/interfaces/desktop/assets/blobs/saturno.png +0 -0
  452. package/src/interfaces/desktop/assets/blobs/trebol.png +0 -0
  453. package/src/interfaces/desktop/assets/blobs/trino.png +0 -0
  454. package/src/interfaces/desktop/assets/blobs/volcan.png +0 -0
  455. package/src/interfaces/desktop/assets/blobs/zafiro.png +0 -0
  456. package/src/interfaces/desktop/assets/notification.mp3 +0 -0
  457. package/src/interfaces/desktop/main.js +473 -29
  458. package/src/interfaces/desktop/mascot-blobs.js +41 -0
  459. package/src/interfaces/desktop/mascot-preload.js +32 -0
  460. package/src/interfaces/desktop/mascot.css +186 -0
  461. package/src/interfaces/desktop/mascot.html +40 -0
  462. package/src/interfaces/desktop/mascot.js +163 -0
  463. package/src/interfaces/desktop/preload.js +10 -0
  464. package/src/interfaces/desktop/renderer.js +308 -48
  465. package/src/interfaces/desktop/style.css +34 -0
  466. package/src/interfaces/mcp-server/index.js +87 -0
  467. package/src/interfaces/tui/_shims/util-locale.ts +0 -2
  468. package/src/interfaces/tui/app.tsx +0 -6
  469. package/src/interfaces/tui/attach.ts +0 -1
  470. package/src/interfaces/tui/context/sdk-apx.tsx +0 -4
  471. package/src/interfaces/tui/plugin/api.tsx +0 -3
  472. package/src/interfaces/tui/plugin/runtime.ts +0 -3
  473. package/src/interfaces/tui/thread.ts +0 -16
  474. package/src/interfaces/web/README.md +22 -14
  475. package/src/interfaces/web/dist/assets/claude-XtpLmGtF.webp +0 -0
  476. package/src/interfaces/web/dist/assets/codex-DExPUgvh.webp +0 -0
  477. package/src/interfaces/web/dist/assets/index-BEoRgIqd.css +32 -0
  478. package/src/interfaces/web/dist/assets/index-BEoRgIqd.css.br +0 -0
  479. package/src/interfaces/web/dist/assets/index-BEoRgIqd.css.gz +0 -0
  480. package/src/interfaces/web/dist/assets/index-C6fXHc1p.js +1074 -0
  481. package/src/interfaces/web/dist/assets/index-C6fXHc1p.js.br +0 -0
  482. package/src/interfaces/web/dist/assets/index-C6fXHc1p.js.gz +0 -0
  483. package/src/interfaces/web/dist/assets/index-C6fXHc1p.js.map +1 -0
  484. package/src/interfaces/web/dist/assets/index-C6fXHc1p.js.map.br +0 -0
  485. package/src/interfaces/web/dist/assets/index-C6fXHc1p.js.map.gz +0 -0
  486. package/src/interfaces/web/dist/favicon/dark/site.webmanifest +12 -6
  487. package/src/interfaces/web/dist/favicon/white/site.webmanifest +12 -6
  488. package/src/interfaces/web/dist/index.html +22 -6
  489. package/src/interfaces/web/dist/index.html.br +0 -0
  490. package/src/interfaces/web/dist/index.html.gz +0 -0
  491. package/src/interfaces/web/dist/manifest.webmanifest +25 -0
  492. package/src/interfaces/web/dist/modules/blobs/amatista.png +0 -0
  493. package/src/interfaces/web/dist/modules/blobs/aqua.png +0 -0
  494. package/src/interfaces/web/dist/modules/blobs/brasa.png +0 -0
  495. package/src/interfaces/web/dist/modules/blobs/campana.png +0 -0
  496. package/src/interfaces/web/dist/modules/blobs/caracol.png +0 -0
  497. package/src/interfaces/web/dist/modules/blobs/carbon.png +0 -0
  498. package/src/interfaces/web/dist/modules/blobs/cobalto.png +0 -0
  499. package/src/interfaces/web/dist/modules/blobs/cometa.png +0 -0
  500. package/src/interfaces/web/dist/modules/blobs/coral.png +0 -0
  501. package/src/interfaces/web/dist/modules/blobs/cubi.png +0 -0
  502. package/src/interfaces/web/dist/modules/blobs/eclipse.png +0 -0
  503. package/src/interfaces/web/dist/modules/blobs/faro.png +0 -0
  504. package/src/interfaces/web/dist/modules/blobs/gajo.png +0 -0
  505. package/src/interfaces/web/dist/modules/blobs/iris.png +0 -0
  506. package/src/interfaces/web/dist/modules/blobs/kiwi.png +0 -0
  507. package/src/interfaces/web/dist/modules/blobs/laguna.png +0 -0
  508. package/src/interfaces/web/dist/modules/blobs/lila.png +0 -0
  509. package/src/interfaces/web/dist/modules/blobs/menta.png +0 -0
  510. package/src/interfaces/web/dist/modules/blobs/nimbo.png +0 -0
  511. package/src/interfaces/web/dist/modules/blobs/noche.png +0 -0
  512. package/src/interfaces/web/dist/modules/blobs/onyx.png +0 -0
  513. package/src/interfaces/web/dist/modules/blobs/orbita.png +0 -0
  514. package/src/interfaces/web/dist/modules/blobs/ovni.png +0 -0
  515. package/src/interfaces/web/dist/modules/blobs/papa.png +0 -0
  516. package/src/interfaces/web/dist/modules/blobs/parche.png +0 -0
  517. package/src/interfaces/web/dist/modules/blobs/peon.png +0 -0
  518. package/src/interfaces/web/dist/modules/blobs/perla.png +0 -0
  519. package/src/interfaces/web/dist/modules/blobs/pino.png +0 -0
  520. package/src/interfaces/web/dist/modules/blobs/quad.png +0 -0
  521. package/src/interfaces/web/dist/modules/blobs/rubi.png +0 -0
  522. package/src/interfaces/web/dist/modules/blobs/saturno.png +0 -0
  523. package/src/interfaces/web/dist/modules/blobs/trebol.png +0 -0
  524. package/src/interfaces/web/dist/modules/blobs/trino.png +0 -0
  525. package/src/interfaces/web/dist/modules/blobs/volcan.png +0 -0
  526. package/src/interfaces/web/dist/modules/blobs/zafiro.png +0 -0
  527. package/src/interfaces/web/dist/sw.js +106 -0
  528. package/src/interfaces/web/dist/sw.js.br +0 -0
  529. package/src/interfaces/web/dist/sw.js.gz +0 -0
  530. package/src/interfaces/web/eslint.config.js +83 -0
  531. package/src/interfaces/web/index.html +20 -4
  532. package/src/interfaces/web/package-lock.json +1651 -1280
  533. package/src/interfaces/web/package.json +9 -10
  534. package/src/interfaces/web/pnpm-lock.yaml +867 -869
  535. package/src/interfaces/web/public/favicon/dark/site.webmanifest +12 -6
  536. package/src/interfaces/web/public/favicon/white/site.webmanifest +12 -6
  537. package/src/interfaces/web/public/manifest.webmanifest +25 -0
  538. package/src/interfaces/web/public/modules/blobs/amatista.png +0 -0
  539. package/src/interfaces/web/public/modules/blobs/aqua.png +0 -0
  540. package/src/interfaces/web/public/modules/blobs/brasa.png +0 -0
  541. package/src/interfaces/web/public/modules/blobs/campana.png +0 -0
  542. package/src/interfaces/web/public/modules/blobs/caracol.png +0 -0
  543. package/src/interfaces/web/public/modules/blobs/carbon.png +0 -0
  544. package/src/interfaces/web/public/modules/blobs/cobalto.png +0 -0
  545. package/src/interfaces/web/public/modules/blobs/cometa.png +0 -0
  546. package/src/interfaces/web/public/modules/blobs/coral.png +0 -0
  547. package/src/interfaces/web/public/modules/blobs/cubi.png +0 -0
  548. package/src/interfaces/web/public/modules/blobs/eclipse.png +0 -0
  549. package/src/interfaces/web/public/modules/blobs/faro.png +0 -0
  550. package/src/interfaces/web/public/modules/blobs/gajo.png +0 -0
  551. package/src/interfaces/web/public/modules/blobs/iris.png +0 -0
  552. package/src/interfaces/web/public/modules/blobs/kiwi.png +0 -0
  553. package/src/interfaces/web/public/modules/blobs/laguna.png +0 -0
  554. package/src/interfaces/web/public/modules/blobs/lila.png +0 -0
  555. package/src/interfaces/web/public/modules/blobs/menta.png +0 -0
  556. package/src/interfaces/web/public/modules/blobs/nimbo.png +0 -0
  557. package/src/interfaces/web/public/modules/blobs/noche.png +0 -0
  558. package/src/interfaces/web/public/modules/blobs/onyx.png +0 -0
  559. package/src/interfaces/web/public/modules/blobs/orbita.png +0 -0
  560. package/src/interfaces/web/public/modules/blobs/ovni.png +0 -0
  561. package/src/interfaces/web/public/modules/blobs/papa.png +0 -0
  562. package/src/interfaces/web/public/modules/blobs/parche.png +0 -0
  563. package/src/interfaces/web/public/modules/blobs/peon.png +0 -0
  564. package/src/interfaces/web/public/modules/blobs/perla.png +0 -0
  565. package/src/interfaces/web/public/modules/blobs/pino.png +0 -0
  566. package/src/interfaces/web/public/modules/blobs/quad.png +0 -0
  567. package/src/interfaces/web/public/modules/blobs/rubi.png +0 -0
  568. package/src/interfaces/web/public/modules/blobs/saturno.png +0 -0
  569. package/src/interfaces/web/public/modules/blobs/trebol.png +0 -0
  570. package/src/interfaces/web/public/modules/blobs/trino.png +0 -0
  571. package/src/interfaces/web/public/modules/blobs/volcan.png +0 -0
  572. package/src/interfaces/web/public/modules/blobs/zafiro.png +0 -0
  573. package/src/interfaces/web/public/sw.js +106 -0
  574. package/src/interfaces/web/src/App.tsx +106 -10
  575. package/src/interfaces/web/src/assets/cli/claude.webp +0 -0
  576. package/src/interfaces/web/src/assets/cli/codex.webp +0 -0
  577. package/src/interfaces/web/src/assets/cli/cursor.svg +1 -0
  578. package/src/interfaces/web/src/assets/cli/opencode.png +0 -0
  579. package/src/interfaces/web/src/components/Combobox.tsx +201 -0
  580. package/src/interfaces/web/src/components/MobileHint.tsx +95 -0
  581. package/src/interfaces/web/src/components/MobileLinkDialog.tsx +156 -0
  582. package/src/interfaces/web/src/components/ModelCombobox.tsx +21 -113
  583. package/src/interfaces/web/src/components/{routines/ReadOnlyBlock.tsx → ReadOnlyBlock.tsx} +13 -4
  584. package/src/interfaces/web/src/components/Roby.tsx +5 -3
  585. package/src/interfaces/web/src/components/RobyBubble.tsx +23 -5
  586. package/src/interfaces/web/src/components/RowMenu.tsx +46 -0
  587. package/src/interfaces/web/src/components/TimezoneSelect.tsx +4 -1
  588. package/src/interfaces/web/src/components/Toast.tsx +50 -14
  589. package/src/interfaces/web/src/components/UiSelect.tsx +12 -5
  590. package/src/interfaces/web/src/components/agents/AgentAvatar.tsx +171 -0
  591. package/src/interfaces/web/src/components/agents/AgentFormFields.tsx +42 -11
  592. package/src/interfaces/web/src/components/agents/AgentModelBadge.tsx +157 -0
  593. package/src/interfaces/web/src/components/agents/AgentModelSelect.tsx +57 -0
  594. package/src/interfaces/web/src/components/agents/AgentSkillsPicker.tsx +115 -0
  595. package/src/interfaces/web/src/components/agents/BlobAvatar.tsx +50 -0
  596. package/src/interfaces/web/src/components/agents/blobPresets.ts +50 -0
  597. package/src/interfaces/web/src/components/agents/modelCatalog.ts +66 -0
  598. package/src/interfaces/web/src/components/chat/ActionGroup.tsx +162 -0
  599. package/src/interfaces/web/src/components/chat/AskAnswersCard.tsx +4 -3
  600. package/src/interfaces/web/src/components/chat/AskQuestionsCard.tsx +1 -1
  601. package/src/interfaces/web/src/components/chat/Attachment.tsx +220 -0
  602. package/src/interfaces/web/src/components/chat/ChatList.tsx +226 -51
  603. package/src/interfaces/web/src/components/chat/ChatRowActivity.tsx +45 -0
  604. package/src/interfaces/web/src/components/chat/Composer.tsx +672 -23
  605. package/src/interfaces/web/src/components/chat/ComposerCommands.tsx +175 -0
  606. package/src/interfaces/web/src/components/chat/ComposerSuggest.tsx +215 -0
  607. package/src/interfaces/web/src/components/chat/ContextBar.tsx +133 -65
  608. package/src/interfaces/web/src/components/chat/InlineAskPanel.tsx +107 -47
  609. package/src/interfaces/web/src/components/chat/MessageBubble.tsx +460 -119
  610. package/src/interfaces/web/src/components/chat/MessageList.tsx +165 -18
  611. package/src/interfaces/web/src/components/chat/ReasoningBlock.tsx +58 -0
  612. package/src/interfaces/web/src/components/chat/SessionPicker.tsx +182 -0
  613. package/src/interfaces/web/src/components/chat/SkillTrace.tsx +183 -0
  614. package/src/interfaces/web/src/components/chat/ToolCall.tsx +11 -11
  615. package/src/interfaces/web/src/components/code/CodeContextTab.tsx +87 -53
  616. package/src/interfaces/web/src/components/code/CodeFileTree.tsx +11 -52
  617. package/src/interfaces/web/src/components/code/CodeFileViewer.tsx +5 -4
  618. package/src/interfaces/web/src/components/code/CodeProjectPicker.tsx +31 -7
  619. package/src/interfaces/web/src/components/code/CodeSessionList.tsx +32 -11
  620. package/src/interfaces/web/src/components/code/CodeSidePanel.tsx +33 -3
  621. package/src/interfaces/web/src/components/code/CodeTerminal.tsx +5 -4
  622. package/src/interfaces/web/src/components/code/NewCodeSessionDialog.tsx +164 -0
  623. package/src/interfaces/web/src/components/commitments/CommitmentDetail.tsx +162 -0
  624. package/src/interfaces/web/src/components/commitments/CommitmentFormDialog.tsx +158 -0
  625. package/src/interfaces/web/src/components/commitments/CommitmentList.tsx +194 -0
  626. package/src/interfaces/web/src/components/commitments/commitmentState.tsx +46 -0
  627. package/src/interfaces/web/src/components/common/BulkActionBar.tsx +60 -0
  628. package/src/interfaces/web/src/components/common/ConfirmDialog.tsx +4 -1
  629. package/src/interfaces/web/src/components/common/SelectCheckbox.tsx +40 -0
  630. package/src/interfaces/web/src/components/common/TabNav.tsx +1 -1
  631. package/src/interfaces/web/src/components/cron/CronPicker.tsx +1 -1
  632. package/src/interfaces/web/src/components/files/FileBrowser.tsx +1 -1
  633. package/src/interfaces/web/src/components/files/FileTree.tsx +6 -4
  634. package/src/interfaces/web/src/components/files/FileViewer.tsx +9 -5
  635. package/src/interfaces/web/src/components/files/MarkdownPreview.tsx +45 -9
  636. package/src/interfaces/web/src/components/images/ImageDefaultsCard.tsx +93 -0
  637. package/src/interfaces/web/src/components/images/ImageProviderList.tsx +142 -0
  638. package/src/interfaces/web/src/components/images/ImageProviderModal.tsx +263 -0
  639. package/src/interfaces/web/src/components/images/ImageTestCard.tsx +142 -0
  640. package/src/interfaces/web/src/components/inbox/ChannelFilter.tsx +178 -0
  641. package/src/interfaces/web/src/components/inbox/InboxList.tsx +77 -81
  642. package/src/interfaces/web/src/components/inbox/InboxRowItem.tsx +140 -0
  643. package/src/interfaces/web/src/components/integrations/ComingSoonPlugin.tsx +2 -2
  644. package/src/interfaces/web/src/components/integrations/PluginConnect.tsx +208 -30
  645. package/src/interfaces/web/src/components/integrations/PluginToolsSection.tsx +1 -1
  646. package/src/interfaces/web/src/components/layout/ProjectAvatar.tsx +39 -24
  647. package/src/interfaces/web/src/components/layout/ProjectSidebar.tsx +253 -58
  648. package/src/interfaces/web/src/components/memory/MemoryBrowser.tsx +94 -47
  649. package/src/interfaces/web/src/components/routines/ExecutionsList.tsx +202 -90
  650. package/src/interfaces/web/src/components/routines/RoutineDetail.tsx +28 -6
  651. package/src/interfaces/web/src/components/routines/RoutineEditor.tsx +16 -5
  652. package/src/interfaces/web/src/components/routines/RoutineList.tsx +49 -9
  653. package/src/interfaces/web/src/components/routines/VarTextarea.tsx +1 -1
  654. package/src/interfaces/web/src/components/routines/runChat.ts +121 -0
  655. package/src/interfaces/web/src/components/sessions/SessionDetail.tsx +148 -0
  656. package/src/interfaces/web/src/components/sessions/SessionTerminal.tsx +98 -0
  657. package/src/interfaces/web/src/components/settings/AccessPanel.tsx +205 -0
  658. package/src/interfaces/web/src/components/settings/DefaultRouterCard.tsx +246 -101
  659. package/src/interfaces/web/src/components/settings/DesktopSettingsPanel.tsx +36 -2
  660. package/src/interfaces/web/src/components/settings/DevicesPanel.tsx +19 -6
  661. package/src/interfaces/web/src/components/settings/EmbedProviderList.tsx +274 -0
  662. package/src/interfaces/web/src/components/settings/EnginesPanel.tsx +26 -6
  663. package/src/interfaces/web/src/components/settings/MemoryPanel.tsx +118 -119
  664. package/src/interfaces/web/src/components/settings/NudgePanel.tsx +4 -3
  665. package/src/interfaces/web/src/components/settings/PairDeviceDialog.tsx +15 -4
  666. package/src/interfaces/web/src/components/settings/PanelPrefs.tsx +374 -0
  667. package/src/interfaces/web/src/components/settings/ProfilePanel.tsx +70 -2
  668. package/src/interfaces/web/src/components/settings/RoutingPanel.tsx +2 -1
  669. package/src/interfaces/web/src/components/settings/SkillsInspectorPanel.tsx +102 -43
  670. package/src/interfaces/web/src/components/settings/SkillsManager.tsx +76 -21
  671. package/src/interfaces/web/src/components/settings/SkillsSettings.tsx +10 -3
  672. package/src/interfaces/web/src/components/settings/SuperAgentPanel.tsx +8 -0
  673. package/src/interfaces/web/src/components/settings/TelegramChannelsPanel.tsx +11 -2
  674. package/src/interfaces/web/src/components/settings/TelegramContactsPanel.tsx +19 -8
  675. package/src/interfaces/web/src/components/settings/TelegramRolesPanel.tsx +12 -2
  676. package/src/interfaces/web/src/components/settings/WebPanel.tsx +22 -31
  677. package/src/interfaces/web/src/components/settings/providers/ProviderCard.tsx +15 -3
  678. package/src/interfaces/web/src/components/settings/providers/ProviderModal.tsx +97 -66
  679. package/src/interfaces/web/src/components/settings/providers/ProviderTestDialog.tsx +150 -0
  680. package/src/interfaces/web/src/components/settings/providers/typeStyles.ts +67 -25
  681. package/src/interfaces/web/src/components/settings/providers/types.ts +3 -0
  682. package/src/interfaces/web/src/components/tasks/TaskBoard.tsx +201 -0
  683. package/src/interfaces/web/src/components/tasks/TaskColumnsDialog.tsx +243 -0
  684. package/src/interfaces/web/src/components/tasks/TaskComments.tsx +167 -0
  685. package/src/interfaces/web/src/components/tasks/TaskDetail.tsx +335 -0
  686. package/src/interfaces/web/src/components/tasks/TaskFormDialog.tsx +406 -0
  687. package/src/interfaces/web/src/components/tasks/TaskList.tsx +258 -0
  688. package/src/interfaces/web/src/components/tasks/TaskSubtasks.tsx +126 -0
  689. package/src/interfaces/web/src/components/tasks/columns.ts +51 -0
  690. package/src/interfaces/web/src/components/tasks/taskStatus.tsx +159 -34
  691. package/src/interfaces/web/src/components/tasks/taskViewPrefs.ts +73 -0
  692. package/src/interfaces/web/src/components/tasks/useTaskColumns.ts +31 -0
  693. package/src/interfaces/web/src/components/ui/chat-input.tsx +136 -12
  694. package/src/interfaces/web/src/components/ui/context-menu.tsx +15 -198
  695. package/src/interfaces/web/src/components/ui/dialog.tsx +3 -2
  696. package/src/interfaces/web/src/components/ui/filter-chips.tsx +4 -0
  697. package/src/interfaces/web/src/components/ui/popover.tsx +14 -49
  698. package/src/interfaces/web/src/components/ui/sheet.tsx +2 -1
  699. package/src/interfaces/web/src/components/ui/spinner.tsx +2 -1
  700. package/src/interfaces/web/src/components/ui.tsx +62 -23
  701. package/src/interfaces/web/src/components/voice/VoiceProviderList.tsx +2 -1
  702. package/src/interfaces/web/src/components/voice/VoiceProviderModal.tsx +66 -8
  703. package/src/interfaces/web/src/components/voice/VoiceQvoxInstallCard.tsx +63 -0
  704. package/src/interfaces/web/src/components/voice/VoiceQvoxStatusCard.tsx +51 -0
  705. package/src/interfaces/web/src/components/voice/VoiceSttCard.tsx +4 -3
  706. package/src/interfaces/web/src/components/voice/VoiceTestCard.tsx +38 -4
  707. package/src/interfaces/web/src/constants/index.ts +1 -0
  708. package/src/interfaces/web/src/hooks/useChannelPrefs.ts +39 -0
  709. package/src/interfaces/web/src/hooks/useChat.ts +1092 -85
  710. package/src/interfaces/web/src/hooks/useChatActivity.ts +24 -0
  711. package/src/interfaces/web/src/hooks/useInbox.ts +26 -4
  712. package/src/interfaces/web/src/hooks/useLiveMessages.ts +16 -0
  713. package/src/interfaces/web/src/hooks/useOllamaModels.ts +79 -0
  714. package/src/interfaces/web/src/hooks/useRecorder.ts +198 -0
  715. package/src/interfaces/web/src/hooks/useTokenBootstrap.ts +23 -6
  716. package/src/interfaces/web/src/i18n/en.ts +832 -175
  717. package/src/interfaces/web/src/i18n/es.ts +841 -188
  718. package/src/interfaces/web/src/lib/api/agents.ts +23 -4
  719. package/src/interfaces/web/src/lib/api/code.ts +17 -0
  720. package/src/interfaces/web/src/lib/api/commitments.ts +7 -1
  721. package/src/interfaces/web/src/lib/api/conversations.ts +38 -11
  722. package/src/interfaces/web/src/lib/api/embeddings.ts +3 -0
  723. package/src/interfaces/web/src/lib/api/engines.ts +14 -0
  724. package/src/interfaces/web/src/lib/api/groups.ts +93 -0
  725. package/src/interfaces/web/src/lib/api/images.ts +193 -0
  726. package/src/interfaces/web/src/lib/api/inbox.ts +29 -5
  727. package/src/interfaces/web/src/lib/api/integrations.ts +9 -0
  728. package/src/interfaces/web/src/lib/api/media.ts +126 -0
  729. package/src/interfaces/web/src/lib/api/net.ts +44 -0
  730. package/src/interfaces/web/src/lib/api/profiles.ts +12 -0
  731. package/src/interfaces/web/src/lib/api/projects.ts +9 -1
  732. package/src/interfaces/web/src/lib/api/routines.ts +9 -1
  733. package/src/interfaces/web/src/lib/api/sessions.ts +18 -0
  734. package/src/interfaces/web/src/lib/api/skills.ts +8 -0
  735. package/src/interfaces/web/src/lib/api/super_agent.ts +3 -0
  736. package/src/interfaces/web/src/lib/api/tasks.ts +46 -6
  737. package/src/interfaces/web/src/lib/api/tools.ts +2 -0
  738. package/src/interfaces/web/src/lib/api/transcribe.ts +31 -0
  739. package/src/interfaces/web/src/lib/api/turns.ts +20 -0
  740. package/src/interfaces/web/src/lib/api/voice.ts +72 -2
  741. package/src/interfaces/web/src/lib/api.ts +3 -0
  742. package/src/interfaces/web/src/lib/channels.ts +214 -0
  743. package/src/interfaces/web/src/lib/chat-activity.ts +175 -0
  744. package/src/interfaces/web/src/lib/chat-prefs.ts +48 -0
  745. package/src/interfaces/web/src/lib/code-context.ts +0 -2
  746. package/src/interfaces/web/src/lib/http.ts +51 -17
  747. package/src/interfaces/web/src/lib/inbox-selection.ts +29 -0
  748. package/src/interfaces/web/src/lib/live.ts +252 -0
  749. package/src/interfaces/web/src/lib/net.ts +211 -0
  750. package/src/interfaces/web/src/lib/notify.ts +331 -0
  751. package/src/interfaces/web/src/lib/projectNav.ts +40 -0
  752. package/src/interfaces/web/src/lib/pwa.ts +115 -0
  753. package/src/interfaces/web/src/lib/qvox.ts +24 -0
  754. package/src/interfaces/web/src/lib/slug.ts +3 -0
  755. package/src/interfaces/web/src/lib/tone.ts +150 -0
  756. package/src/interfaces/web/src/main.tsx +15 -4
  757. package/src/interfaces/web/src/screens/ApxAdminScreen.tsx +33 -11
  758. package/src/interfaces/web/src/screens/InboxScreen.tsx +126 -71
  759. package/src/interfaces/web/src/screens/ProjectScreen.tsx +8 -4
  760. package/src/interfaces/web/src/screens/SettingsScreen.tsx +7 -4
  761. package/src/interfaces/web/src/screens/base/AgentDefaultsTab.tsx +30 -9
  762. package/src/interfaces/web/src/screens/base/CommitmentsTab.tsx +150 -168
  763. package/src/interfaces/web/src/screens/base/LogsTab.tsx +8 -7
  764. package/src/interfaces/web/src/screens/base/SessionsTab.tsx +99 -37
  765. package/src/interfaces/web/src/screens/base/WorkspacesTab.tsx +1 -1
  766. package/src/interfaces/web/src/screens/mobile/MobileChat.tsx +85 -0
  767. package/src/interfaces/web/src/screens/mobile/MobileChatList.tsx +244 -0
  768. package/src/interfaces/web/src/screens/mobile/MobileCommitments.tsx +350 -0
  769. package/src/interfaces/web/src/screens/mobile/MobileScreen.tsx +138 -0
  770. package/src/interfaces/web/src/screens/mobile/MobileTabBar.tsx +105 -0
  771. package/src/interfaces/web/src/screens/mobile/MobileTasks.tsx +407 -0
  772. package/src/interfaces/web/src/screens/mobile/NewChatSheet.tsx +313 -0
  773. package/src/interfaces/web/src/screens/mobile/mobileList.tsx +194 -0
  774. package/src/interfaces/web/src/screens/mobile/routes.ts +239 -0
  775. package/src/interfaces/web/src/screens/modules/CodeScreen.tsx +135 -64
  776. package/src/interfaces/web/src/screens/modules/DeckScreen.tsx +0 -1
  777. package/src/interfaces/web/src/screens/modules/ImagesScreen.tsx +172 -0
  778. package/src/interfaces/web/src/screens/modules/VoiceScreen.tsx +36 -4
  779. package/src/interfaces/web/src/screens/project/AgentBrainGraph.tsx +117 -30
  780. package/src/interfaces/web/src/screens/project/AgentDetailScreen.tsx +537 -92
  781. package/src/interfaces/web/src/screens/project/AgentsTab.tsx +344 -93
  782. package/src/interfaces/web/src/screens/project/ArtifactsTab.tsx +1 -1
  783. package/src/interfaces/web/src/screens/project/ChatTab.tsx +1160 -94
  784. package/src/interfaces/web/src/screens/project/IntegrationsTab.tsx +3 -2
  785. package/src/interfaces/web/src/screens/project/McpsTab.tsx +62 -14
  786. package/src/interfaces/web/src/screens/project/Overview.tsx +36 -15
  787. package/src/interfaces/web/src/screens/project/RoutinesTab.tsx +93 -8
  788. package/src/interfaces/web/src/screens/project/SkillsTab.tsx +4 -1
  789. package/src/interfaces/web/src/screens/project/StructureTab.tsx +5 -4
  790. package/src/interfaces/web/src/screens/project/TasksTab.tsx +351 -129
  791. package/src/interfaces/web/src/screens/project/VarsTab.tsx +17 -5
  792. package/src/interfaces/web/src/styles.css +106 -31
  793. package/src/interfaces/web/src/types/daemon.ts +246 -2
  794. package/src/interfaces/web/src/vite-env.d.ts +20 -0
  795. package/src/interfaces/tui/plugin/command-shim.ts +0 -109
  796. package/src/interfaces/web/components.json +0 -25
  797. package/src/interfaces/web/dist/assets/index-CvEoGtTf.js +0 -849
  798. package/src/interfaces/web/dist/assets/index-CvEoGtTf.js.map +0 -1
  799. package/src/interfaces/web/dist/assets/index-DzBBXFaO.css +0 -1
  800. package/src/interfaces/web/src/components/tasks/TaskDetailPanel.tsx +0 -142
  801. package/src/interfaces/web/src/components/ui/accordion.tsx +0 -72
  802. package/src/interfaces/web/src/components/ui/alert-dialog.tsx +0 -187
  803. package/src/interfaces/web/src/components/ui/alert.tsx +0 -76
  804. package/src/interfaces/web/src/components/ui/aspect-ratio.tsx +0 -22
  805. package/src/interfaces/web/src/components/ui/avatar.tsx +0 -107
  806. package/src/interfaces/web/src/components/ui/breadcrumb.tsx +0 -125
  807. package/src/interfaces/web/src/components/ui/button-group.tsx +0 -87
  808. package/src/interfaces/web/src/components/ui/calendar.tsx +0 -221
  809. package/src/interfaces/web/src/components/ui/card.tsx +0 -103
  810. package/src/interfaces/web/src/components/ui/carousel.tsx +0 -242
  811. package/src/interfaces/web/src/components/ui/chart.tsx +0 -371
  812. package/src/interfaces/web/src/components/ui/checkbox.tsx +0 -29
  813. package/src/interfaces/web/src/components/ui/collapsible.tsx +0 -19
  814. package/src/interfaces/web/src/components/ui/combobox.tsx +0 -295
  815. package/src/interfaces/web/src/components/ui/command.tsx +0 -196
  816. package/src/interfaces/web/src/components/ui/direction.tsx +0 -4
  817. package/src/interfaces/web/src/components/ui/drawer.tsx +0 -134
  818. package/src/interfaces/web/src/components/ui/empty.tsx +0 -104
  819. package/src/interfaces/web/src/components/ui/field.tsx +0 -236
  820. package/src/interfaces/web/src/components/ui/hover-card.tsx +0 -51
  821. package/src/interfaces/web/src/components/ui/input-otp.tsx +0 -85
  822. package/src/interfaces/web/src/components/ui/item.tsx +0 -201
  823. package/src/interfaces/web/src/components/ui/menubar.tsx +0 -280
  824. package/src/interfaces/web/src/components/ui/native-select.tsx +0 -61
  825. package/src/interfaces/web/src/components/ui/navigation-menu.tsx +0 -168
  826. package/src/interfaces/web/src/components/ui/pagination.tsx +0 -130
  827. package/src/interfaces/web/src/components/ui/progress.tsx +0 -83
  828. package/src/interfaces/web/src/components/ui/radio-group.tsx +0 -36
  829. package/src/interfaces/web/src/components/ui/resizable.tsx +0 -50
  830. package/src/interfaces/web/src/components/ui/scroll-area.tsx +0 -53
  831. package/src/interfaces/web/src/components/ui/sidebar.tsx +0 -726
  832. package/src/interfaces/web/src/components/ui/slider.tsx +0 -52
  833. package/src/interfaces/web/src/components/ui/sonner.tsx +0 -49
  834. package/src/interfaces/web/src/components/ui/table.tsx +0 -116
  835. package/src/interfaces/web/src/components/ui/toggle-group.tsx +0 -87
  836. package/src/interfaces/web/src/components/ui/toggle.tsx +0 -45
  837. package/src/interfaces/web/src/hooks/use-mobile.ts +0 -19
  838. package/src/interfaces/web/src/screens/base/GlobalTasksTab.tsx +0 -161
@@ -1,6 +1,6 @@
1
1
  import { useMemo, useState } from "react";
2
2
  import useSWR from "swr";
3
- import { Brain, Bot, Crown, NotebookPen, RefreshCw } from "lucide-react";
3
+ import { Brain, BrainCircuit, Bot, Crown, NotebookPen, RefreshCw } from "lucide-react";
4
4
  import { Agents, Projects } from "../../lib/api";
5
5
  import { Notebook } from "../../lib/api/notebook";
6
6
  import type { AgentEntry, FileContent } from "../../types/daemon";
@@ -8,15 +8,22 @@ import { cn } from "../../lib/cn";
8
8
  import { Spinner, Empty } from "../ui";
9
9
  import { useToast } from "../Toast";
10
10
  import { t } from "../../i18n";
11
+ import { toneText } from "../../lib/tone";
11
12
  import { usePersonaName } from "../../hooks/usePersonaName";
12
13
  import { FileViewer } from "../files/FileViewer";
13
14
 
14
- // Which memory is open in the right pane.
15
- type Sel = { kind: "notebook" } | { kind: "project" } | { kind: "agent"; slug: string };
15
+ // Which memory is open in the right pane. A project has TWO: "project" is the
16
+ // curated `.apc/memory.md` that git carries, "local" is the never-committed file
17
+ // the agent writes. Keeping them separate rows is the point — the boundary is
18
+ // what stops an automatic note putting a pasted token in someone's repo.
19
+ type Sel =
20
+ | { kind: "notebook" }
21
+ | { kind: "project" }
22
+ | { kind: "local" }
23
+ | { kind: "agent"; slug: string };
16
24
 
17
25
  function selId(s: Sel): string {
18
- if (s.kind === "notebook") return "notebook";
19
- return s.kind === "project" ? "project" : `agent:${s.slug}`;
26
+ return s.kind === "agent" ? `agent:${s.slug}` : s.kind;
20
27
  }
21
28
 
22
29
  // On-disk-ish path shown in the viewer header (mirrors the real memory.md
@@ -24,23 +31,32 @@ function selId(s: Sel): string {
24
31
  function selPath(s: Sel): string {
25
32
  // The notebook is NOT under the project — it is global to the super-agent.
26
33
  // Showing its real absolute-ish path is the whole point: the confusion this
27
- // entry fixes was not knowing where it lived.
28
- if (s.kind === "notebook") return "~/.apx/memory.md";
29
- return s.kind === "project" ? ".apc/memory.md" : `agents/${s.slug}/memory.md`;
34
+ // entry fixes was not knowing where it lived. Same reasoning for the local
35
+ // file: "not in the repo" is a property you have to be able to SEE.
36
+ switch (s.kind) {
37
+ case "notebook": return "~/.apx/memory.md";
38
+ case "project": return ".apc/memory.md";
39
+ case "local": return "~/.apx/projects/<id>/memory.md";
40
+ default: return `~/.apx/projects/<id>/agents/${s.slug}/memory.md`;
41
+ }
30
42
  }
31
43
 
32
44
  function loadBody(pid: string, s: Sel): Promise<string> {
33
- if (s.kind === "notebook") return Notebook.get().then((r) => r.body);
34
- return s.kind === "project"
35
- ? Projects.memory.get(pid).then((r) => r.body)
36
- : Agents.memory.get(pid, s.slug).then((r) => r.body);
45
+ switch (s.kind) {
46
+ case "notebook": return Notebook.get().then((r) => r.body);
47
+ case "project": return Projects.memory.get(pid).then((r) => r.body);
48
+ case "local": return Projects.memory.local.get(pid).then((r) => r.body);
49
+ default: return Agents.memory.get(pid, s.slug).then((r) => r.body);
50
+ }
37
51
  }
38
52
 
39
53
  function saveBody(pid: string, s: Sel, body: string): Promise<void> {
40
- if (s.kind === "notebook") return Notebook.put(body).then(() => {});
41
- return s.kind === "project"
42
- ? Projects.memory.put(pid, body).then(() => {})
43
- : Agents.memory.put(pid, s.slug, body).then(() => {});
54
+ switch (s.kind) {
55
+ case "notebook": return Notebook.put(body).then(() => {});
56
+ case "project": return Projects.memory.put(pid, body).then(() => {});
57
+ case "local": return Projects.memory.local.put(pid, body).then(() => {});
58
+ default: return Agents.memory.put(pid, s.slug, body).then(() => {});
59
+ }
44
60
  }
45
61
 
46
62
  function SidebarItem({
@@ -74,24 +90,38 @@ function SidebarItem({
74
90
  // right for markdown edit / split-preview / save — the same surface as /docs.
75
91
  export function MemoryBrowser({ pid }: { pid: string }) {
76
92
  const toast = useToast();
77
- // Opens on the notebook. It is the memory that ships in every prompt on
78
- // every channel, so it is the one most worth seeing first.
79
- const [sel, setSel] = useState<Sel>({ kind: "notebook" });
80
- const notebook = useSWR("/api/notebook", () => Notebook.get());
93
+ // The notebook belongs to Base (id 0) and to nowhere else. It is ONE global
94
+ // file (~/.apx/memory.md) that used to head the sidebar of every project, so
95
+ // twelve projects each looked like they owned a copy of the super-agent's
96
+ // memory and editing it "in Postbeam" silently edited the global one.
97
+ const isBase = String(pid) === "0";
98
+ // What opens first is what is most likely to have something in it. On Base
99
+ // that is the notebook (the memory that ships in every prompt on every
100
+ // channel); on a project it is the internal memory, because that is where
101
+ // everything the agent has learned lands — opening on the curated file meant
102
+ // opening on an empty pane and having to go looking, which is the exact
103
+ // feeling this screen exists to remove.
104
+ const fallback: Sel = isBase ? { kind: "notebook" } : { kind: "local" };
105
+ const [sel, setSel] = useState<Sel | null>(null);
106
+ // Switching projects from the rail re-renders this component without
107
+ // remounting it, so a notebook selection can outlive Base. Derive rather than
108
+ // reset: off Base there is simply no such row to be on.
109
+ const open: Sel = !sel || (!isBase && sel.kind === "notebook") ? fallback : sel;
110
+ const notebook = useSWR(isBase ? "/api/notebook" : null, () => Notebook.get());
81
111
  // Never hardcode the agent's name (AGENTS.md rule 13) — it is the user's to set.
82
112
  const persona = usePersonaName();
83
113
 
84
114
  const agents = useSWR(`/api/projects/${pid}/agents`, () => Agents.list(pid));
85
115
 
86
- const bodyKey = `/api/memory/${pid}/${selId(sel)}`;
87
- const body = useSWR(bodyKey, () => loadBody(pid, sel));
116
+ const bodyKey = `/api/memory/${pid}/${selId(open)}`;
117
+ const body = useSWR(bodyKey, () => loadBody(pid, open));
88
118
 
89
119
  // Adapt the raw memory body into the FileContent shape FileViewer expects.
90
120
  const file = useMemo<FileContent | null>(() => {
91
121
  if (body.data === undefined) return null;
92
122
  const content = body.data ?? "";
93
123
  return {
94
- path: selPath(sel),
124
+ path: selPath(open),
95
125
  name: "memory.md",
96
126
  kind: "markdown",
97
127
  size: content.length,
@@ -99,10 +129,10 @@ export function MemoryBrowser({ pid }: { pid: string }) {
99
129
  encoding: "utf8",
100
130
  content,
101
131
  };
102
- }, [body.data, sel]);
132
+ }, [body.data, open]);
103
133
 
104
134
  const onSave = async (content: string) => {
105
- await saveBody(pid, sel, content);
135
+ await saveBody(pid, open, content);
106
136
  toast.success(t("project.memories.saved"));
107
137
  void body.mutate(content, { revalidate: false });
108
138
  };
@@ -129,52 +159,69 @@ export function MemoryBrowser({ pid }: { pid: string }) {
129
159
  </div>
130
160
 
131
161
  <div className="min-h-0 flex-1 overflow-y-auto p-1.5">
132
- {/* The super-agent's own notebook. First, and in its own group,
133
- because it is global not a property of this project — and its
134
- absence from this list is what made "where is Roby's memory?" an
135
- unanswerable question. */}
136
- <p className="px-1.5 pb-1 pt-1 text-[10px] font-semibold uppercase tracking-wide text-muted-foreground/60">
137
- {t("project.memories.super_agent_group")}
138
- </p>
139
- <SidebarItem
140
- active={sel.kind === "notebook"}
141
- onClick={() => setSel({ kind: "notebook" })}
142
- icon={NotebookPen}
143
- iconClass="text-emerald-400"
144
- label={t("project.memories.notebook_item", { persona })}
145
- sub={notebook.data ? t("project.memories.tokens", { n: notebook.data.approx_tokens }) : undefined}
146
- />
162
+ {/* The super-agent's own notebook — Base only. First, and in its own
163
+ group, because it is global rather than a property of a project,
164
+ and its absence from every list is what made "where is the
165
+ super-agent's memory?" an unanswerable question. */}
166
+ {isBase && (
167
+ <>
168
+ <p className="px-1.5 pb-1 pt-1 text-[10px] font-semibold uppercase tracking-wide text-muted-foreground">
169
+ {t("project.memories.super_agent_group")}
170
+ </p>
171
+ <SidebarItem
172
+ active={open.kind === "notebook"}
173
+ onClick={() => setSel({ kind: "notebook" })}
174
+ icon={NotebookPen}
175
+ iconClass={toneText.emerald}
176
+ label={t("project.memories.notebook_item", { persona })}
177
+ sub={notebook.data ? t("project.memories.tokens", { n: notebook.data.approx_tokens }) : undefined}
178
+ />
179
+ </>
180
+ )}
147
181
 
148
182
  {/* General / project memory */}
149
- <p className="px-1.5 pb-1 pt-3 text-[10px] font-semibold uppercase tracking-wide text-muted-foreground/60">
183
+ <p className={`px-1.5 pb-1 ${isBase ? "pt-3" : "pt-1"} text-[10px] font-semibold uppercase tracking-wide text-muted-foreground`}>
150
184
  {t("project.memories.general_group")}
151
185
  </p>
186
+ {/* The agent's half, first because it is the one that fills up: what
187
+ `remember` writes lands here, so a fact picked up mid-chat cannot
188
+ put a pasted credential into the repo's history. Promotion to
189
+ .apc/memory.md is a person copying a line they have read. */}
190
+ <SidebarItem
191
+ active={open.kind === "local"}
192
+ onClick={() => setSel({ kind: "local" })}
193
+ icon={BrainCircuit}
194
+ iconClass={toneText.amber}
195
+ label={t("project.memories.local_item")}
196
+ sub={t("project.memories.not_committed")}
197
+ />
152
198
  <SidebarItem
153
- active={sel.kind === "project"}
199
+ active={open.kind === "project"}
154
200
  onClick={() => setSel({ kind: "project" })}
155
201
  icon={Brain}
156
- iconClass="text-sky-500"
202
+ iconClass={toneText.sky}
157
203
  label={t("project.memories.general_item")}
204
+ sub={t("project.memories.committed")}
158
205
  />
159
206
 
160
207
  {/* Agent memories */}
161
- <p className="px-1.5 pb-1 pt-3 text-[10px] font-semibold uppercase tracking-wide text-muted-foreground/60">
208
+ <p className="px-1.5 pb-1 pt-3 text-[10px] font-semibold uppercase tracking-wide text-muted-foreground">
162
209
  {t("project.memories.agents_title")}
163
210
  </p>
164
211
  {agents.isLoading ? (
165
212
  <div className="flex justify-center py-4"><Spinner size={14} /></div>
166
213
  ) : list.length === 0 ? (
167
214
  <div className="px-1.5 py-2">
168
- <Empty>{t("project.memories.no_agents")}</Empty>
215
+ <Empty icon={Brain}>{t("project.memories.no_agents")}</Empty>
169
216
  </div>
170
217
  ) : (
171
218
  list.map((a) => (
172
219
  <SidebarItem
173
220
  key={a.slug}
174
- active={sel.kind === "agent" && sel.slug === a.slug}
221
+ active={open.kind === "agent" && open.slug === a.slug}
175
222
  onClick={() => setSel({ kind: "agent", slug: a.slug })}
176
223
  icon={a.is_master ? Crown : Bot}
177
- iconClass={a.is_master ? "text-violet-400" : "text-muted-foreground"}
224
+ iconClass={a.is_master ? toneText.violet : "text-muted-foreground"}
178
225
  label={a.slug}
179
226
  sub={a.role || undefined}
180
227
  />
@@ -1,25 +1,42 @@
1
- import { useState, type ReactNode } from "react";
2
- import useSWR from "swr";
3
- import { Ban, Check, X } from "lucide-react";
4
- import { Messages } from "../../lib/api";
5
- import type { MessageEntry } from "../../types/daemon";
6
- import { Loading, Spinner } from "../ui";
1
+ import { useEffect, useState, type ReactNode } from "react";
2
+ import { Link } from "react-router-dom";
3
+ import useSWR, { mutate as globalMutate } from "swr";
4
+ import { Ban, Check, MessageSquare, X } from "lucide-react";
5
+ import { Routines } from "../../lib/api";
6
+ import type { LiveRoutineRun, RoutineRun } from "../../types/daemon";
7
+ import { subscribeRoutineRuns } from "../../lib/live";
8
+ import { Loading, Spinner, Tip } from "../ui";
7
9
  import { cn } from "../../lib/cn";
10
+ import { toneText } from "../../lib/tone";
8
11
  import { t } from "../../i18n";
12
+ import { MessageList } from "../chat/MessageList";
13
+ import { liveRunToChatMsgs, routineRunToChatMsgs } from "./runChat";
9
14
 
10
- // Execution history is derived from the ROUTINE-channel messages the runner
11
- // logs at the end of each run (src/core/routines/runner.js) — there is no
12
- // dedicated runs table. One system message per run carries meta.routine +
13
- // meta.status + meta.skipped + meta.result.
15
+ // A routine's runs: the one happening now, and the ones already made.
16
+ //
17
+ // Both used to be guesswork here. The history was the ROUTINE-channel ledger
18
+ // filtered client-side on `meta.routine` + a system actor — which is also what
19
+ // a "routine updated" row looks like, so editing a routine added a run to its
20
+ // own history, drawn green because an edit carries no status. That reading now
21
+ // lives in core/routines/run-log.js and arrives shaped.
22
+ //
23
+ // The run in flight came from nowhere at all: it was a boolean in the tab that
24
+ // pressed Play, so a refresh erased a routine that was still working. It now
25
+ // comes from the daemon (GET .../run) and follows the live feed, which means it
26
+ // also shows up when the SCHEDULER started it, on every open panel.
14
27
 
15
- type RunSt = "ok" | "error" | "skipped";
28
+ const RUN_PHASE_LABELS: Record<string, () => string> = {
29
+ pre: () => t("project.routines.phase_pre"),
30
+ agent: () => t("project.routines.phase_agent"),
31
+ delivery: () => t("project.routines.phase_delivery"),
32
+ post: () => t("project.routines.phase_post"),
33
+ };
16
34
 
17
- function runStatus(m: MessageEntry): RunSt {
18
- const meta = (m.meta || {}) as Record<string, unknown>;
19
- if (meta.skipped) return "skipped";
20
- if (meta.status === "error") return "error";
21
- return "ok";
22
- }
35
+ const TRIGGER_LABELS: Record<string, () => string> = {
36
+ manual: () => t("project.routines.trigger_manual"),
37
+ schedule: () => t("project.routines.trigger_schedule"),
38
+ agent: () => t("project.routines.trigger_agent"),
39
+ };
23
40
 
24
41
  function fmtTs(ts: string): string {
25
42
  const d = new Date(ts);
@@ -29,14 +46,42 @@ function fmtTs(ts: string): string {
29
46
  });
30
47
  }
31
48
 
32
- function StatusIcon({ st }: { st: RunSt }) {
33
- if (st === "ok") return <Check size={13} className="shrink-0 text-emerald-500" />;
49
+ function StatusIcon({ st }: { st: RoutineRun["status"] }) {
50
+ if (st === "ok") return <Check size={13} className={cn("shrink-0", toneText.emerald)} />;
34
51
  if (st === "error") return <X size={13} className="shrink-0 text-destructive" />;
35
- return <Ban size={13} className="shrink-0 text-amber-500" />;
52
+ return <Ban size={13} className={cn("shrink-0", toneText.amber)} />;
53
+ }
54
+
55
+ function statusLabel(st: RoutineRun["status"]): string {
56
+ return st === "ok" ? t("project.routines.status_ok")
57
+ : st === "error" ? t("project.routines.status_error")
58
+ : t("project.routines.status_skipped");
59
+ }
60
+
61
+ /** Where a run's own chat lives. Every run that went through an agent filed one
62
+ * — this is the link that was buried one click deep inside the detail panel. */
63
+ function chatHrefOf(pid: string, run: { conversation_id: string | null; agent_slug: string | null }): string | null {
64
+ if (!run.conversation_id || !run.agent_slug) return null;
65
+ return `/p/${pid}/chat?agent=${encodeURIComponent(run.agent_slug)}&conv=${encodeURIComponent(run.conversation_id)}`;
36
66
  }
37
67
 
38
- function statusLabel(st: RunSt): string {
39
- return st === "ok" ? t("project.routines.status_ok") : st === "error" ? t("project.routines.status_error") : t("project.routines.status_skipped");
68
+ /** The chat link as it appears on a row: an anchor, so it opens in a new tab
69
+ * with the usual gestures, and stops the click from also selecting the row. */
70
+ function ChatLink({ href, compact = false }: { href: string; compact?: boolean }) {
71
+ return (
72
+ <Tip content={t("project.routines.open_chat")}>
73
+ <Link
74
+ to={href}
75
+ onClick={(e) => e.stopPropagation()}
76
+ aria-label={t("project.routines.open_chat")}
77
+ data-testid="routine-open-chat"
78
+ className="inline-flex shrink-0 items-center gap-1 rounded-md px-1.5 py-1 text-[11px] text-muted-fg hover:bg-muted hover:text-foreground"
79
+ >
80
+ <MessageSquare size={13} />
81
+ {!compact && t("project.routines.open_chat")}
82
+ </Link>
83
+ </Tip>
84
+ );
40
85
  }
41
86
 
42
87
  function FlowBlock({ title, children }: { title: string; children: ReactNode }) {
@@ -48,61 +93,59 @@ function FlowBlock({ title, children }: { title: string; children: ReactNode })
48
93
  );
49
94
  }
50
95
 
51
- type RunFlow = {
52
- pre?: { output?: string; exit?: number } | null;
53
- post?: Array<{ cmd: string; exit: number; stdout: string; stderr: string }> | null;
54
- };
55
-
56
96
  const PRE_CLS = "whitespace-pre-wrap break-words rounded-lg border border-border bg-muted/20 px-3 py-2 font-mono text-[11px]";
57
97
 
58
98
  /** Side panel: the full flow of the clicked run — pre → action → post. Phases
59
99
  * that did not run are hidden; older runs (no saved flow) show just the output. */
60
- function RunDetailPanel({ m, onClose }: { m: MessageEntry; onClose: () => void }) {
61
- const st = runStatus(m);
62
- const meta = (m.meta || {}) as Record<string, any>;
63
- const result = (meta.result || {}) as Record<string, any>;
64
- const flow = (meta.flow || null) as RunFlow | null;
100
+ function RunDetailPanel({ pid, run, onClose }: { pid: string; run: RoutineRun; onClose: () => void }) {
101
+ const result = run.result || {};
65
102
  const output = String(result.reply ?? result.text ?? result.stdout ?? "");
66
103
  const err = String(result.error ?? result.stderr ?? "");
67
104
  const note = String(result.note ?? "");
68
105
  const empty = <span className="text-muted-fg">{t("project.routines.block_empty")}</span>;
106
+ const chatMsgs = routineRunToChatMsgs(result, run.ts);
107
+ const href = chatHrefOf(pid, run);
69
108
 
70
109
  return (
71
110
  <div className="flex min-h-0 flex-col border-l border-border">
72
111
  <div className="flex shrink-0 items-center justify-between gap-2 px-4 py-2">
73
112
  <div className="flex items-center gap-2 text-xs">
74
- <StatusIcon st={st} />
75
- <span className={cn("font-medium", st === "ok" && "text-emerald-500", st === "error" && "text-destructive", st === "skipped" && "text-amber-500")}>{statusLabel(st)}</span>
76
- <span className="font-mono text-muted-fg">{fmtTs(m.ts)}</span>
113
+ <StatusIcon st={run.status} />
114
+ <span className={cn("font-medium", run.status === "ok" && toneText.emerald, run.status === "error" && "text-destructive", run.status === "skipped" && toneText.amber)}>{statusLabel(run.status)}</span>
115
+ <span className="font-mono text-muted-fg">{fmtTs(run.ts)}</span>
116
+ </div>
117
+ <div className="flex items-center gap-1">
118
+ {href && <ChatLink href={href} />}
119
+ <button type="button" onClick={onClose} aria-label={t("project.routines.runs_close")}
120
+ className="rounded-md p-1 text-muted-fg hover:bg-muted hover:text-foreground">
121
+ <X size={14} />
122
+ </button>
77
123
  </div>
78
- <button type="button" onClick={onClose} aria-label={t("project.routines.runs_close")}
79
- className="rounded-md p-1 text-muted-fg hover:bg-muted hover:text-foreground">
80
- <X size={14} />
81
- </button>
82
124
  </div>
83
125
  <div className="min-h-0 flex-1 space-y-3 overflow-y-auto px-4 pb-4 text-xs">
84
- {m.body && <div className="text-muted-fg">{m.body}</div>}
126
+ {run.body && <div className="text-muted-fg">{run.body}</div>}
85
127
 
86
- {/* Pre-commands */}
87
- {flow?.pre && (
128
+ {run.flow?.pre && (
88
129
  <FlowBlock title={t("project.routines.block_pre")}>
89
- {flow.pre.output?.trim() ? <pre className={PRE_CLS}>{flow.pre.output}</pre> : empty}
130
+ {run.flow.pre.output?.trim() ? <pre className={PRE_CLS}>{run.flow.pre.output}</pre> : empty}
90
131
  </FlowBlock>
91
132
  )}
92
133
 
93
- {/* Action output (agent reply / telegram message / shell stdout) */}
94
- <FlowBlock title={t("project.routines.runs_output")}>
95
- {output ? <pre className={PRE_CLS}>{output}</pre>
134
+ <FlowBlock title={chatMsgs.length ? t("project.routines.runs_chat") : t("project.routines.runs_output")}>
135
+ {chatMsgs.length ? (
136
+ <div data-testid="routine-run-chat" className="-mx-1">
137
+ <MessageList msgs={chatMsgs} onCopy={() => {}} autoscroll={false} />
138
+ </div>
139
+ ) : output ? <pre className={PRE_CLS}>{output}</pre>
96
140
  : err ? <pre className="whitespace-pre-wrap break-words rounded-lg bg-destructive/10 px-3 py-2 font-mono text-[11px] text-destructive">{err}</pre>
97
141
  : note ? <div className="text-muted-fg">{note}</div>
98
142
  : empty}
99
143
  </FlowBlock>
100
144
 
101
- {/* Post-commands */}
102
- {flow?.post && flow.post.length > 0 && (
145
+ {run.flow?.post && run.flow.post.length > 0 && (
103
146
  <FlowBlock title={t("project.routines.block_post")}>
104
147
  <div className="space-y-1.5">
105
- {flow.post.map((p, i) => (
148
+ {run.flow.post.map((p, i) => (
106
149
  <div key={i} className="space-y-1">
107
150
  <div className="font-mono text-[10px] text-muted-fg">$ {p.cmd} <span className="opacity-70">· exit {p.exit}</span></div>
108
151
  {(p.stdout || p.stderr) && <pre className={PRE_CLS}>{p.stdout || p.stderr}</pre>}
@@ -116,65 +159,133 @@ function RunDetailPanel({ m, onClose }: { m: MessageEntry; onClose: () => void }
116
159
  );
117
160
  }
118
161
 
119
- /** Bottom pane of the detail view: scrollable list of past runs; clicking one
120
- * opens a side grid column with that run's details. */
121
- export function ExecutionsList({ pid, name, running }: { pid: string; name: string; running?: boolean }) {
122
- const runs = useSWR(
123
- `/api/projects/${pid}/routines/${name}/runs`,
124
- async () => {
125
- const msgs = await Messages.project(pid, { channel: "routine", limit: 200 });
126
- // Keep one row per run: the runner's end-of-run system summary.
127
- return msgs.filter((m) =>
128
- (m.meta as Record<string, unknown>)?.routine === name &&
129
- (m.actor_id === "apx:routine" || m.type === "system"),
130
- );
131
- },
162
+ /** Same panel, for the run happening right now: the steps as they arrive. This
163
+ * is the answer to "it says running running WHAT?", which before this had no
164
+ * answer anywhere, not even in the tab that started it. */
165
+ function LiveRunPanel({ pid, run, onClose }: { pid: string; run: LiveRoutineRun; onClose: () => void }) {
166
+ const msgs = liveRunToChatMsgs(run);
167
+ const href = chatHrefOf(pid, { conversation_id: run.conversation_id ?? null, agent_slug: run.agent_slug });
168
+ return (
169
+ <div className="flex min-h-0 flex-col border-l border-border" data-testid="routine-live-panel">
170
+ <div className="flex shrink-0 items-center justify-between gap-2 px-4 py-2">
171
+ <div className="flex items-center gap-2 text-xs">
172
+ <Spinner size={12} />
173
+ <span className="font-medium text-primary">{RUN_PHASE_LABELS[run.phase]?.() || run.phase}</span>
174
+ <span className="font-mono text-muted-fg">{fmtTs(run.started_at)}</span>
175
+ </div>
176
+ <div className="flex items-center gap-1">
177
+ {href && <ChatLink href={href} />}
178
+ <button type="button" onClick={onClose} aria-label={t("project.routines.runs_close")}
179
+ className="rounded-md p-1 text-muted-fg hover:bg-muted hover:text-foreground">
180
+ <X size={14} />
181
+ </button>
182
+ </div>
183
+ </div>
184
+ <div className="min-h-0 flex-1 space-y-3 overflow-y-auto px-4 pb-4 text-xs">
185
+ <FlowBlock title={t("project.routines.runs_chat")}>
186
+ {msgs.length ? (
187
+ <div data-testid="routine-run-chat" className="-mx-1">
188
+ <MessageList msgs={msgs} onCopy={() => {}} autoscroll={false} />
189
+ </div>
190
+ ) : (
191
+ <div className="text-muted-fg">{t("project.routines.live_waiting")}</div>
192
+ )}
193
+ </FlowBlock>
194
+ </div>
195
+ </div>
132
196
  );
133
- const rows = (runs.data || []).slice(0, 50);
197
+ }
198
+
199
+ /** Bottom pane of the detail view: the run in flight (if any) above the runs
200
+ * already made. Clicking one opens it in a side grid column. */
201
+ export function ExecutionsList({ pid, name }: { pid: string; name: string }) {
202
+ const runsKey = `/api/projects/${pid}/routines/${name}/runs`;
203
+ const liveKey = `/api/projects/${pid}/routines/${name}/run`;
204
+ const runs = useSWR(runsKey, () => Routines.runs(pid, name));
205
+ // Seeded from the daemon rather than from a click, which is what makes a run
206
+ // survive a refresh and show up on a panel that never started it.
207
+ const seed = useSWR(liveKey, () => Routines.activeRun(pid, name).then((r) => r.run));
208
+ const [live, setLive] = useState<LiveRoutineRun | null>(null);
134
209
  const [selTs, setSelTs] = useState<string | null>(null);
135
- const selected = selTs ? rows.find((m) => m.ts === selTs) || null : null;
210
+
211
+ useEffect(() => { setLive(seed.data ?? null); }, [seed.data]);
212
+
213
+ useEffect(() => subscribeRoutineRuns((frame) => {
214
+ if (frame.routine !== name || String(frame.project_id) !== String(pid)) return;
215
+ if (frame.phase === "end") {
216
+ setLive(null);
217
+ // The run only exists in the ledger now that it is over — and the routine
218
+ // header's "last run / last status" moved with it.
219
+ globalMutate(runsKey);
220
+ globalMutate(`/api/projects/${pid}/routines`);
221
+ } else {
222
+ setLive(frame.run);
223
+ }
224
+ }), [pid, name, runsKey]);
225
+
226
+ const rows = runs.data || [];
227
+ const selected = selTs && selTs !== "live" ? rows.find((r) => r.ts === selTs) || null : null;
228
+ const liveSelected = selTs === "live" && live ? live : null;
136
229
 
137
230
  return (
138
231
  <div className="flex min-h-0 flex-1 flex-col border-t border-border">
139
232
  <div className="shrink-0 px-4 pb-1.5 pt-3 text-[11px] font-semibold uppercase tracking-wide text-muted-fg">
140
233
  {t("project.routines.runs_title")}
141
234
  </div>
142
- <div className={cn("grid min-h-0 flex-1 overflow-hidden", selected ? "grid-cols-[minmax(0,1fr)_minmax(0,1.1fr)]" : "grid-cols-1")}>
235
+ <div className={cn("grid min-h-0 flex-1 overflow-hidden", selected || liveSelected ? "grid-cols-[minmax(0,1fr)_minmax(0,1.1fr)]" : "grid-cols-1")}>
143
236
  {/* list */}
144
237
  <div className="min-h-0 overflow-y-auto px-4 pb-4">
145
238
  {runs.isLoading && <Loading />}
146
- {!runs.isLoading && rows.length === 0 && (
239
+ {!runs.isLoading && rows.length === 0 && !live && (
147
240
  <div className="text-xs text-muted-fg">{t("project.routines.runs_empty")}</div>
148
241
  )}
149
242
  <ul className="space-y-1">
150
- {running && (
243
+ {live && (
151
244
  <li>
152
- <div className="flex w-full items-center gap-2 rounded-md border border-primary/40 bg-primary/5 px-3 py-1.5 text-xs">
245
+ <button
246
+ type="button"
247
+ onClick={() => setSelTs(selTs === "live" ? null : "live")}
248
+ aria-current={selTs === "live"}
249
+ data-testid="routine-live-row"
250
+ className={cn(
251
+ "flex w-full items-center gap-2 rounded-md border px-3 py-1.5 text-left text-xs transition-colors",
252
+ selTs === "live" ? "border-primary/60 bg-primary/10" : "border-primary/40 bg-primary/5 hover:border-primary/60",
253
+ )}
254
+ >
153
255
  <Spinner size={12} />
154
- <span className="text-muted-fg">{t("project.routines.running")}</span>
155
- </div>
256
+ <span className="font-medium text-primary">{RUN_PHASE_LABELS[live.phase]?.() || t("project.routines.running")}</span>
257
+ <span className="truncate text-muted-fg">
258
+ {TRIGGER_LABELS[live.trigger]?.() || live.trigger}
259
+ </span>
260
+ <span className="ml-auto shrink-0 font-mono text-muted-fg">{fmtTs(live.started_at)}</span>
261
+ </button>
156
262
  </li>
157
263
  )}
158
- {rows.map((m, i) => {
159
- const st = runStatus(m);
160
- const active = selTs === m.ts;
264
+ {rows.map((run, i) => {
265
+ const active = selTs === run.ts;
266
+ const href = chatHrefOf(pid, run);
161
267
  return (
162
- <li key={`${m.ts}-${i}`}>
163
- <button
164
- type="button"
165
- onClick={() => setSelTs(active ? null : m.ts)}
166
- aria-current={active}
167
- className={cn(
168
- "flex w-full items-center gap-2 rounded-md border px-3 py-1.5 text-left text-xs transition-colors",
169
- active ? "border-primary/50 bg-primary/10" : "border-border bg-muted/30 hover:border-muted-fg/40",
170
- )}
171
- >
172
- <StatusIcon st={st} />
173
- <span className="font-mono text-muted-fg">{fmtTs(m.ts)}</span>
174
- <span className={cn("font-medium", st === "ok" && "text-emerald-500", st === "error" && "text-destructive", st === "skipped" && "text-amber-500")}>
175
- {statusLabel(st)}
176
- </span>
177
- </button>
268
+ <li key={`${run.ts}-${i}`}>
269
+ {/* The link is a sibling of the row button, not inside it: a
270
+ button in a button is invalid and swallows the click. */}
271
+ <div className={cn(
272
+ "flex items-center gap-1 rounded-md border pr-1 transition-colors",
273
+ active ? "border-primary/50 bg-primary/10" : "border-border bg-muted/30 hover:border-muted-fg/40",
274
+ )}>
275
+ <button
276
+ type="button"
277
+ onClick={() => setSelTs(active ? null : run.ts)}
278
+ aria-current={active}
279
+ className="flex min-w-0 flex-1 items-center gap-2 px-3 py-1.5 text-left text-xs"
280
+ >
281
+ <StatusIcon st={run.status} />
282
+ <span className="font-mono text-muted-fg">{fmtTs(run.ts)}</span>
283
+ <span className={cn("font-medium", run.status === "ok" && toneText.emerald, run.status === "error" && "text-destructive", run.status === "skipped" && toneText.amber)}>
284
+ {statusLabel(run.status)}
285
+ </span>
286
+ </button>
287
+ {href && <ChatLink href={href} compact />}
288
+ </div>
178
289
  </li>
179
290
  );
180
291
  })}
@@ -182,7 +293,8 @@ export function ExecutionsList({ pid, name, running }: { pid: string; name: stri
182
293
  </div>
183
294
 
184
295
  {/* run detail (opens as a side grid column) */}
185
- {selected && <RunDetailPanel m={selected} onClose={() => setSelTs(null)} />}
296
+ {liveSelected && <LiveRunPanel pid={pid} run={liveSelected} onClose={() => setSelTs(null)} />}
297
+ {!liveSelected && selected && <RunDetailPanel pid={pid} run={selected} onClose={() => setSelTs(null)} />}
186
298
  </div>
187
299
  </div>
188
300
  );