@agentprojectcontext/apx 1.81.0 → 1.89.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (838) hide show
  1. package/package.json +9 -8
  2. package/skills/apc-context/SKILL.md +14 -7
  3. package/skills/apx/SKILL.md +62 -2
  4. package/skills/apx-mcp/SKILL.md +42 -15
  5. package/src/core/agent/a2a/peers.js +161 -0
  6. package/src/core/agent/a2a/reply.js +379 -27
  7. package/src/core/agent/abort.js +25 -0
  8. package/src/core/agent/agent-model.js +58 -0
  9. package/src/core/agent/agent-tools.js +101 -0
  10. package/src/core/agent/author-line.js +110 -0
  11. package/src/core/agent/build-agent-system.js +52 -18
  12. package/src/core/agent/channels/voice-context.js +17 -2
  13. package/src/core/agent/closing-floor.js +117 -0
  14. package/src/core/agent/constants.js +119 -11
  15. package/src/core/agent/engine-call.js +56 -0
  16. package/src/core/agent/group/run-group-turn.js +218 -0
  17. package/src/core/agent/group/turn-resolver.js +165 -0
  18. package/src/core/agent/judge.js +138 -11
  19. package/src/core/agent/loop/side-effects.js +106 -3
  20. package/src/core/agent/memory.js +31 -18
  21. package/src/core/agent/model-capabilities.js +47 -0
  22. package/src/core/agent/model-router.js +11 -40
  23. package/src/core/agent/prompt-builder.js +47 -0
  24. package/src/core/agent/prompts/channels/a2a.md +12 -0
  25. package/src/core/agent/prompts/channels/code.md +3 -1
  26. package/src/core/agent/prompts/channels/telegram.md +2 -0
  27. package/src/core/agent/prompts/channels/web_code.md +1 -1
  28. package/src/core/agent/prompts/channels/whatsapp.md +37 -0
  29. package/src/core/agent/prompts/core/agent-base.md +2 -0
  30. package/src/core/agent/prompts/discipline/action.md +1 -0
  31. package/src/core/agent/prompts/discipline/two-segment.md +2 -1
  32. package/src/core/agent/prompts/modes/mobility.md +36 -0
  33. package/src/core/agent/retry.js +42 -0
  34. package/src/core/agent/run-agent.js +322 -25
  35. package/src/core/agent/run-turn.js +253 -0
  36. package/src/core/agent/self-memory.js +18 -52
  37. package/src/core/agent/skills/agent-skills.js +118 -0
  38. package/src/core/agent/skills/catalog.js +1 -1
  39. package/src/core/agent/skills/declared.js +13 -0
  40. package/src/core/agent/skills/index-store.js +8 -1
  41. package/src/core/agent/skills/inspector.js +20 -3
  42. package/src/core/agent/skills/loader.js +18 -3
  43. package/src/core/agent/skills/media.js +121 -0
  44. package/src/core/agent/skills/origin.js +61 -0
  45. package/src/core/agent/skills/sections.js +136 -0
  46. package/src/core/agent/super-agent.js +54 -14
  47. package/src/core/agent/tools/handlers/_calendar.js +50 -0
  48. package/src/core/agent/tools/handlers/add-mcp.js +103 -0
  49. package/src/core/agent/tools/handlers/asana-create-task.js +3 -1
  50. package/src/core/agent/tools/handlers/attach-media.js +56 -0
  51. package/src/core/agent/tools/handlers/calendar-create-event.js +38 -0
  52. package/src/core/agent/tools/handlers/calendar-find-slot.js +39 -0
  53. package/src/core/agent/tools/handlers/calendar-list-events.js +39 -0
  54. package/src/core/agent/tools/handlers/calendar-update-event.js +35 -0
  55. package/src/core/agent/tools/handlers/call-agent.js +14 -6
  56. package/src/core/agent/tools/handlers/call-runtime.js +27 -49
  57. package/src/core/agent/tools/handlers/comment-task.js +78 -0
  58. package/src/core/agent/tools/handlers/complete-task.js +60 -0
  59. package/src/core/agent/tools/handlers/configure-agent.js +70 -0
  60. package/src/core/agent/tools/handlers/create-agent.js +68 -0
  61. package/src/core/agent/tools/handlers/create-task.js +41 -3
  62. package/src/core/agent/tools/handlers/import-agent.js +5 -5
  63. package/src/core/agent/tools/handlers/list-mcp-tools.js +83 -0
  64. package/src/core/agent/tools/handlers/list-routines.js +46 -0
  65. package/src/core/agent/tools/handlers/list-tasks.js +8 -1
  66. package/src/core/agent/tools/handlers/mark-commitment.js +57 -0
  67. package/src/core/agent/tools/handlers/read-skill.js +64 -0
  68. package/src/core/agent/tools/handlers/remember-routine.js +2 -8
  69. package/src/core/agent/tools/handlers/remember.js +82 -6
  70. package/src/core/agent/tools/handlers/remove-agent.js +42 -0
  71. package/src/core/agent/tools/handlers/run-routine.js +94 -0
  72. package/src/core/agent/tools/handlers/run-shell.js +44 -2
  73. package/src/core/agent/tools/handlers/send-telegram.js +41 -19
  74. package/src/core/agent/tools/handlers/set-agent-prompt.js +44 -0
  75. package/src/core/agent/tools/handlers/view-media.js +69 -0
  76. package/src/core/agent/tools/handlers/write-agent-memory.js +52 -0
  77. package/src/core/agent/tools/helpers.js +36 -4
  78. package/src/core/agent/tools/names.js +64 -0
  79. package/src/core/agent/tools/registry-bridge.js +24 -1
  80. package/src/core/agent/tools/registry.js +79 -0
  81. package/src/core/agent/tools/tool-call-parser.js +136 -13
  82. package/src/core/agent/vision-bridge.js +69 -0
  83. package/src/core/apc/agent-identity.js +74 -0
  84. package/src/core/apc/agent-rename-refs.js +187 -0
  85. package/src/core/apc/agent-write.js +312 -0
  86. package/src/core/apc/agents-vault.js +1 -1
  87. package/src/core/apc/blob-keys.js +42 -0
  88. package/src/core/apc/frontmatter.js +166 -10
  89. package/src/core/apc/parser.js +33 -83
  90. package/src/core/apc/paths.js +4 -6
  91. package/src/core/apc/project-memory.js +44 -0
  92. package/src/core/apc/projects-helpers.js +33 -0
  93. package/src/core/apc/scaffold.js +36 -16
  94. package/src/core/channels/telegram/ask-callbacks.js +103 -0
  95. package/src/core/channels/telegram/dispatch.js +154 -30
  96. package/src/core/channels/telegram/helpers.js +59 -7
  97. package/src/core/channels/telegram/inbound/audio.js +26 -30
  98. package/src/core/channels/telegram/inbound/file.js +22 -32
  99. package/src/core/channels/telegram/inbound/photo.js +24 -28
  100. package/src/core/channels/telegram/progress-gate.js +76 -0
  101. package/src/core/channels/telegram/reply.js +151 -43
  102. package/src/core/channels/telegram/voice-note.js +150 -0
  103. package/src/core/config/index.js +53 -54
  104. package/src/core/config/paths.js +117 -31
  105. package/src/core/config/redact.js +89 -4
  106. package/src/core/config/secret-values.js +2 -4
  107. package/src/core/constants/actors.js +5 -0
  108. package/src/core/constants/channels.js +3 -1
  109. package/src/core/constants/task-categories.js +73 -0
  110. package/src/core/constants/task-fields.js +28 -0
  111. package/src/core/engines/_globs.js +33 -0
  112. package/src/core/engines/anthropic.js +19 -1
  113. package/src/core/engines/catalog.js +20 -0
  114. package/src/core/engines/gemini.js +84 -16
  115. package/src/core/engines/index.js +19 -3
  116. package/src/core/engines/mock.js +145 -1
  117. package/src/core/engines/openai-compatible.js +150 -15
  118. package/src/core/engines/presets.js +36 -9
  119. package/src/core/engines/zen.js +131 -0
  120. package/src/core/events/bus.js +140 -0
  121. package/src/core/events/mascot-notify.js +156 -0
  122. package/src/core/http-tools/browser.js +366 -36
  123. package/src/core/http-tools/catalog.js +206 -22
  124. package/src/core/http-tools/grep.js +62 -7
  125. package/src/core/http-tools/registry.js +3 -1
  126. package/src/core/i18n/en.js +34 -3
  127. package/src/core/i18n/es.js +36 -4
  128. package/src/core/i18n/index.js +5 -5
  129. package/src/core/i18n/pt.js +32 -3
  130. package/src/core/identity/self.js +14 -1
  131. package/src/core/images/engines/a1111.js +219 -0
  132. package/src/core/images/engines/index.js +187 -0
  133. package/src/core/images/engines/mock.js +74 -0
  134. package/src/core/images/engines/openai.js +130 -0
  135. package/src/core/images/engines/sdcpp.js +204 -0
  136. package/src/core/images/engines/shared.js +218 -0
  137. package/src/core/images/generate.js +260 -0
  138. package/src/core/integrations/catalog.js +8 -3
  139. package/src/core/integrations/plugins/_google-oauth.js +179 -0
  140. package/src/core/integrations/plugins/asana.js +7 -3
  141. package/src/core/integrations/plugins/calendar.js +404 -0
  142. package/src/core/integrations/store.js +2 -0
  143. package/src/core/memory/broker.js +16 -1
  144. package/src/core/memory/compactor.js +19 -3
  145. package/src/core/memory/consolidate.js +2 -2
  146. package/src/core/memory/dated-log.js +66 -0
  147. package/src/core/memory/embed-engines/custom.js +59 -0
  148. package/src/core/memory/embed-engines/gemini.js +9 -3
  149. package/src/core/memory/embed-engines/index.js +87 -15
  150. package/src/core/memory/embeddings.js +52 -24
  151. package/src/core/memory/index.js +13 -3
  152. package/src/core/memory/indexer.js +83 -27
  153. package/src/core/memory/prune.js +182 -0
  154. package/src/core/memory/store.js +22 -0
  155. package/src/core/memory/summarizer.js +72 -8
  156. package/src/core/mobility/answer.js +80 -0
  157. package/src/core/mobility/geofence.js +667 -0
  158. package/src/core/mobility/osm-route.js +282 -0
  159. package/src/core/mobility/preferences.js +91 -0
  160. package/src/core/mobility/state.js +245 -0
  161. package/src/core/mobility/trip-event.js +384 -0
  162. package/src/core/net/tailscale.js +168 -0
  163. package/src/core/profiles/bundled/secretary/PROFILE.md +32 -42
  164. package/src/core/profiles/bundled/secretary/config.schema.es.json +68 -0
  165. package/src/core/profiles/bundled/secretary/config.schema.json +30 -2
  166. package/src/core/profiles/bundled/secretary/profile.json +3 -1
  167. package/src/core/profiles/bundled/secretary/routines/a2a-sweep.json +20 -0
  168. package/src/core/profiles/bundled/secretary/routines/day-close.json +4 -1
  169. package/src/core/profiles/bundled/secretary/routines/day-open.json +7 -1
  170. package/src/core/profiles/bundled/secretary/routines/watch.json +13 -2
  171. package/src/core/profiles/lifecycle.js +243 -19
  172. package/src/core/profiles/paths.js +12 -0
  173. package/src/core/profiles/store.js +47 -0
  174. package/src/core/routines/active-runs.js +213 -0
  175. package/src/core/routines/delivery.js +612 -0
  176. package/src/core/routines/header.js +88 -0
  177. package/src/core/routines/index.js +26 -0
  178. package/src/core/routines/run-log.js +78 -0
  179. package/src/core/routines/runner.js +629 -66
  180. package/src/core/routines/signals.js +75 -0
  181. package/src/core/runtime-skills/apc-context/SKILL.md +14 -7
  182. package/src/core/runtime-skills/apx/SKILL.md +93 -1
  183. package/src/core/runtime-skills/apx-agency-agents/SKILL.md +2 -2
  184. package/src/core/runtime-skills/apx-agent/SKILL.md +134 -19
  185. package/src/core/runtime-skills/apx-commitment/SKILL.md +21 -11
  186. package/src/core/runtime-skills/apx-image/SKILL.md +60 -0
  187. package/src/core/runtime-skills/apx-integrations/SKILL.md +82 -0
  188. package/src/core/runtime-skills/apx-mcp/SKILL.md +45 -14
  189. package/src/core/runtime-skills/apx-mcp-builder/SKILL.md +4 -4
  190. package/src/core/runtime-skills/apx-profile/SKILL.md +27 -2
  191. package/src/core/runtime-skills/apx-project/SKILL.md +23 -2
  192. package/src/core/runtime-skills/apx-routine/SKILL.md +40 -17
  193. package/src/core/runtime-skills/apx-runtime/SKILL.md +124 -14
  194. package/src/core/runtime-skills/apx-sessions/SKILL.md +7 -6
  195. package/src/core/runtime-skills/apx-skill-builder/SKILL.md +15 -13
  196. package/src/core/runtime-skills/apx-task/SKILL.md +79 -26
  197. package/src/core/runtime-skills/apx-telegram/SKILL.md +12 -12
  198. package/src/core/runtime-skills/apx-transcribe/SKILL.md +56 -0
  199. package/src/core/runtime-skills/apx-voice/SKILL.md +27 -8
  200. package/src/core/runtime-skills/claude-code/SKILL.md +8 -0
  201. package/src/core/runtime-skills/openrouter/SKILL.md +8 -2
  202. package/src/core/runtimes/_spawn.js +9 -1
  203. package/src/core/runtimes/claude-code.js +11 -2
  204. package/src/core/runtimes/codex.js +44 -10
  205. package/src/core/runtimes/index.js +17 -2
  206. package/src/core/runtimes/opencode.js +88 -9
  207. package/src/core/runtimes/outcome.js +119 -0
  208. package/src/core/sessions/index.js +193 -1
  209. package/src/core/stores/agent-inbox.js +109 -23
  210. package/src/core/stores/code-sessions.js +21 -0
  211. package/src/core/stores/commitments.js +27 -3
  212. package/src/core/stores/conversations.js +220 -20
  213. package/src/core/stores/deliveries.js +177 -0
  214. package/src/core/stores/media-archive.js +228 -0
  215. package/src/core/stores/messages.js +1096 -112
  216. package/src/core/stores/organization.js +34 -0
  217. package/src/core/stores/project-memory.js +71 -0
  218. package/src/core/stores/routine-memory.js +16 -8
  219. package/src/core/stores/routines.js +27 -49
  220. package/src/core/stores/sessions.js +4 -8
  221. package/src/core/stores/tasks.js +212 -18
  222. package/src/core/stores/turn-record.js +209 -0
  223. package/src/core/tasks/columns.js +136 -0
  224. package/src/core/tasks/comment-turn.js +258 -0
  225. package/src/core/util/time.js +13 -0
  226. package/src/core/voice/engines/index.js +54 -1
  227. package/src/core/voice/engines/openai.js +50 -4
  228. package/src/core/voice/opus.js +67 -0
  229. package/src/core/voice/pronounceable.js +43 -0
  230. package/src/core/voice/transcription.js +4 -0
  231. package/src/core/voice/tts.js +114 -24
  232. package/src/host/daemon/active-turns.js +188 -0
  233. package/src/host/daemon/api/admin-config.js +9 -0
  234. package/src/host/daemon/api/agents.js +99 -90
  235. package/src/host/daemon/api/artifact-preview.js +7 -6
  236. package/src/host/daemon/api/artifacts.js +3 -2
  237. package/src/host/daemon/api/code.js +55 -9
  238. package/src/host/daemon/api/commitments.js +11 -0
  239. package/src/host/daemon/api/confirm.js +3 -2
  240. package/src/host/daemon/api/conversations.js +543 -35
  241. package/src/host/daemon/api/deck.js +9 -8
  242. package/src/host/daemon/api/deliveries.js +33 -0
  243. package/src/host/daemon/api/desktop.js +5 -4
  244. package/src/host/daemon/api/embeddings.js +15 -6
  245. package/src/host/daemon/api/engines.js +59 -8
  246. package/src/host/daemon/api/exec.js +437 -121
  247. package/src/host/daemon/api/groups.js +215 -0
  248. package/src/host/daemon/api/images.js +107 -0
  249. package/src/host/daemon/api/inbox.js +123 -2
  250. package/src/host/daemon/api/integrations.js +64 -2
  251. package/src/host/daemon/api/mcps.js +7 -6
  252. package/src/host/daemon/api/media.js +283 -0
  253. package/src/host/daemon/api/mobility.js +177 -0
  254. package/src/host/daemon/api/net.js +182 -0
  255. package/src/host/daemon/api/pairing.js +38 -5
  256. package/src/host/daemon/api/profiles.js +30 -2
  257. package/src/host/daemon/api/routines.js +36 -4
  258. package/src/host/daemon/api/runtimes.js +74 -39
  259. package/src/host/daemon/api/sessions-search.js +7 -2
  260. package/src/host/daemon/api/sessions.js +44 -2
  261. package/src/host/daemon/api/shared.js +127 -20
  262. package/src/host/daemon/api/skills.js +11 -4
  263. package/src/host/daemon/api/super-agent.js +384 -53
  264. package/src/host/daemon/api/tasks.js +180 -10
  265. package/src/host/daemon/api/telegram.js +11 -10
  266. package/src/host/daemon/api/thread-faces.js +159 -0
  267. package/src/host/daemon/api/top-level.js +3 -3
  268. package/src/host/daemon/api/transcribe.js +11 -10
  269. package/src/host/daemon/api/tts.js +97 -4
  270. package/src/host/daemon/api/turn-abort.js +23 -0
  271. package/src/host/daemon/api/turns.js +49 -0
  272. package/src/host/daemon/api/voice.js +5 -4
  273. package/src/host/daemon/api/web.js +98 -0
  274. package/src/host/daemon/api.js +39 -0
  275. package/src/host/daemon/delivery-sweep.js +58 -0
  276. package/src/host/daemon/desktop-ws.js +5 -23
  277. package/src/host/daemon/events-ws.js +273 -0
  278. package/src/host/daemon/index.js +59 -15
  279. package/src/host/daemon/plugins/desktop/index.js +17 -4
  280. package/src/host/daemon/plugins/telegram/index.js +78 -40
  281. package/src/host/daemon/pty-bridge.py +99 -0
  282. package/src/host/daemon/routines-scheduler.js +1 -0
  283. package/src/host/daemon/smoke.js +1 -2
  284. package/src/host/daemon/terminal-ws.js +132 -0
  285. package/src/host/daemon/tts-keepwarm.js +87 -0
  286. package/src/host/daemon/wakeup.js +11 -6
  287. package/src/host/daemon/whisper-server.js +44 -0
  288. package/src/host/daemon/whisper-server.py +70 -13
  289. package/src/host/daemon/ws-auth.js +28 -0
  290. package/src/interfaces/android/app/build.gradle +42 -0
  291. package/src/interfaces/android/app/proguard-rules.pro +4 -0
  292. package/src/interfaces/android/app/src/main/AndroidManifest.xml +139 -0
  293. package/src/interfaces/android/app/src/main/java/dev/agentprojectcontext/apx/AlertScreen.java +139 -0
  294. package/src/interfaces/android/app/src/main/java/dev/agentprojectcontext/apx/AndroidAutoDetector.java +106 -0
  295. package/src/interfaces/android/app/src/main/java/dev/agentprojectcontext/apx/ApxCarAppService.java +57 -0
  296. package/src/interfaces/android/app/src/main/java/dev/agentprojectcontext/apx/ApxPreferences.java +165 -0
  297. package/src/interfaces/android/app/src/main/java/dev/agentprojectcontext/apx/CarAlertStore.java +84 -0
  298. package/src/interfaces/android/app/src/main/java/dev/agentprojectcontext/apx/CarMessageActionReceiver.java +47 -0
  299. package/src/interfaces/android/app/src/main/java/dev/agentprojectcontext/apx/CarMessageNotification.java +152 -0
  300. package/src/interfaces/android/app/src/main/java/dev/agentprojectcontext/apx/DaemonAddress.java +35 -0
  301. package/src/interfaces/android/app/src/main/java/dev/agentprojectcontext/apx/DaemonClient.java +339 -0
  302. package/src/interfaces/android/app/src/main/java/dev/agentprojectcontext/apx/DeviceLocation.java +38 -0
  303. package/src/interfaces/android/app/src/main/java/dev/agentprojectcontext/apx/ErrandScreen.java +127 -0
  304. package/src/interfaces/android/app/src/main/java/dev/agentprojectcontext/apx/MainActivity.java +872 -0
  305. package/src/interfaces/android/app/src/main/java/dev/agentprojectcontext/apx/MapsNavigationDetector.java +63 -0
  306. package/src/interfaces/android/app/src/main/java/dev/agentprojectcontext/apx/MapsNavigationListenerService.java +453 -0
  307. package/src/interfaces/android/app/src/main/java/dev/agentprojectcontext/apx/MapsShareIntentParser.java +93 -0
  308. package/src/interfaces/android/app/src/main/java/dev/agentprojectcontext/apx/MascotBlobCatalog.java +66 -0
  309. package/src/interfaces/android/app/src/main/java/dev/agentprojectcontext/apx/MascotOverlayService.java +448 -0
  310. package/src/interfaces/android/app/src/main/java/dev/agentprojectcontext/apx/MascotView.java +249 -0
  311. package/src/interfaces/android/app/src/main/java/dev/agentprojectcontext/apx/MessageFrameParser.java +240 -0
  312. package/src/interfaces/android/app/src/main/java/dev/agentprojectcontext/apx/NotifyChannels.java +69 -0
  313. package/src/interfaces/android/app/src/main/java/dev/agentprojectcontext/apx/ProximityActionReceiver.java +78 -0
  314. package/src/interfaces/android/app/src/main/java/dev/agentprojectcontext/apx/ProximityNotification.java +161 -0
  315. package/src/interfaces/android/app/src/main/java/dev/agentprojectcontext/apx/StartupReceiver.java +57 -0
  316. package/src/interfaces/android/app/src/main/java/dev/agentprojectcontext/apx/TravelEventGate.java +62 -0
  317. package/src/interfaces/android/app/src/main/java/dev/agentprojectcontext/apx/TravelStatusBanner.java +116 -0
  318. package/src/interfaces/android/app/src/main/java/dev/agentprojectcontext/apx/TripLocationService.java +272 -0
  319. package/src/interfaces/android/app/src/main/java/dev/agentprojectcontext/apx/TripPlacesSheet.java +203 -0
  320. package/src/interfaces/android/app/src/main/java/dev/agentprojectcontext/apx/TripScreen.java +182 -0
  321. package/src/interfaces/android/app/src/main/res/drawable/app_background.xml +12 -0
  322. package/src/interfaces/android/app/src/main/res/drawable/ic_apx_app.xml +10 -0
  323. package/src/interfaces/android/app/src/main/res/drawable/ic_apx_launcher_foreground.xml +12 -0
  324. package/src/interfaces/android/app/src/main/res/drawable/ic_apx_notification.xml +22 -0
  325. package/src/interfaces/android/app/src/main/res/drawable/ic_trip_car.xml +37 -0
  326. package/src/interfaces/android/app/src/main/res/drawable-nodpi/apx_logo.png +0 -0
  327. package/src/interfaces/android/app/src/main/res/drawable-nodpi/mascot_amatista.png +0 -0
  328. package/src/interfaces/android/app/src/main/res/drawable-nodpi/mascot_aqua.png +0 -0
  329. package/src/interfaces/android/app/src/main/res/drawable-nodpi/mascot_brasa.png +0 -0
  330. package/src/interfaces/android/app/src/main/res/drawable-nodpi/mascot_campana.png +0 -0
  331. package/src/interfaces/android/app/src/main/res/drawable-nodpi/mascot_caracol.png +0 -0
  332. package/src/interfaces/android/app/src/main/res/drawable-nodpi/mascot_carbon.png +0 -0
  333. package/src/interfaces/android/app/src/main/res/drawable-nodpi/mascot_cobalto.png +0 -0
  334. package/src/interfaces/android/app/src/main/res/drawable-nodpi/mascot_cometa.png +0 -0
  335. package/src/interfaces/android/app/src/main/res/drawable-nodpi/mascot_coral.png +0 -0
  336. package/src/interfaces/android/app/src/main/res/drawable-nodpi/mascot_cubi.png +0 -0
  337. package/src/interfaces/android/app/src/main/res/drawable-nodpi/mascot_eclipse.png +0 -0
  338. package/src/interfaces/android/app/src/main/res/drawable-nodpi/mascot_faro.png +0 -0
  339. package/src/interfaces/android/app/src/main/res/drawable-nodpi/mascot_gajo.png +0 -0
  340. package/src/interfaces/android/app/src/main/res/drawable-nodpi/mascot_iris.png +0 -0
  341. package/src/interfaces/android/app/src/main/res/drawable-nodpi/mascot_kiwi.png +0 -0
  342. package/src/interfaces/android/app/src/main/res/drawable-nodpi/mascot_laguna.png +0 -0
  343. package/src/interfaces/android/app/src/main/res/drawable-nodpi/mascot_lila.png +0 -0
  344. package/src/interfaces/android/app/src/main/res/drawable-nodpi/mascot_menta.png +0 -0
  345. package/src/interfaces/android/app/src/main/res/drawable-nodpi/mascot_nimbo.png +0 -0
  346. package/src/interfaces/android/app/src/main/res/drawable-nodpi/mascot_noche.png +0 -0
  347. package/src/interfaces/android/app/src/main/res/drawable-nodpi/mascot_onyx.png +0 -0
  348. package/src/interfaces/android/app/src/main/res/drawable-nodpi/mascot_orbita.png +0 -0
  349. package/src/interfaces/android/app/src/main/res/drawable-nodpi/mascot_ovni.png +0 -0
  350. package/src/interfaces/android/app/src/main/res/drawable-nodpi/mascot_papa.png +0 -0
  351. package/src/interfaces/android/app/src/main/res/drawable-nodpi/mascot_parche.png +0 -0
  352. package/src/interfaces/android/app/src/main/res/drawable-nodpi/mascot_peon.png +0 -0
  353. package/src/interfaces/android/app/src/main/res/drawable-nodpi/mascot_perla.png +0 -0
  354. package/src/interfaces/android/app/src/main/res/drawable-nodpi/mascot_pino.png +0 -0
  355. package/src/interfaces/android/app/src/main/res/drawable-nodpi/mascot_quad.png +0 -0
  356. package/src/interfaces/android/app/src/main/res/drawable-nodpi/mascot_rubi.png +0 -0
  357. package/src/interfaces/android/app/src/main/res/drawable-nodpi/mascot_saturno.png +0 -0
  358. package/src/interfaces/android/app/src/main/res/drawable-nodpi/mascot_trebol.png +0 -0
  359. package/src/interfaces/android/app/src/main/res/drawable-nodpi/mascot_trino.png +0 -0
  360. package/src/interfaces/android/app/src/main/res/drawable-nodpi/mascot_volcan.png +0 -0
  361. package/src/interfaces/android/app/src/main/res/drawable-nodpi/mascot_zafiro.png +0 -0
  362. package/src/interfaces/android/app/src/main/res/mipmap-anydpi-v26/ic_launcher.xml +5 -0
  363. package/src/interfaces/android/app/src/main/res/mipmap-anydpi-v26/ic_launcher_round.xml +5 -0
  364. package/src/interfaces/android/app/src/main/res/raw/apx_notification.mp3 +0 -0
  365. package/src/interfaces/android/app/src/main/res/values/colors.xml +4 -0
  366. package/src/interfaces/android/app/src/main/res/values/strings.xml +25 -0
  367. package/src/interfaces/android/app/src/main/res/values/styles.xml +10 -0
  368. package/src/interfaces/android/app/src/main/res/values-v31/styles.xml +14 -0
  369. package/src/interfaces/android/app/src/main/res/xml/automotive_app_desc.xml +9 -0
  370. package/src/interfaces/android/app/src/main/res/xml/network_security_config.xml +10 -0
  371. package/src/interfaces/android/app/src/test/java/dev/agentprojectcontext/apx/AndroidAutoDetectorTest.java +85 -0
  372. package/src/interfaces/android/app/src/test/java/dev/agentprojectcontext/apx/CarAlertStoreTest.java +104 -0
  373. package/src/interfaces/android/app/src/test/java/dev/agentprojectcontext/apx/DaemonAddressTest.java +23 -0
  374. package/src/interfaces/android/app/src/test/java/dev/agentprojectcontext/apx/MapsNavigationDetectorTest.java +69 -0
  375. package/src/interfaces/android/app/src/test/java/dev/agentprojectcontext/apx/MapsShareIntentParserTest.java +31 -0
  376. package/src/interfaces/android/app/src/test/java/dev/agentprojectcontext/apx/MessageFrameParserTest.java +180 -0
  377. package/src/interfaces/android/app/src/test/java/dev/agentprojectcontext/apx/TravelEventGateTest.java +64 -0
  378. package/src/interfaces/android/app/src/test/java/dev/agentprojectcontext/apx/TripPlacesSheetTest.java +66 -0
  379. package/src/interfaces/android/build.gradle +3 -0
  380. package/src/interfaces/android/gradle/wrapper/gradle-wrapper.jar +0 -0
  381. package/src/interfaces/android/gradle/wrapper/gradle-wrapper.properties +9 -0
  382. package/src/interfaces/android/gradle.properties +3 -0
  383. package/src/interfaces/android/gradlew +248 -0
  384. package/src/interfaces/android/gradlew.bat +82 -0
  385. package/src/interfaces/android/settings.gradle +18 -0
  386. package/src/interfaces/cli/commands/a2a.js +145 -4
  387. package/src/interfaces/cli/commands/agent.js +247 -22
  388. package/src/interfaces/cli/commands/code.js +1 -1
  389. package/src/interfaces/cli/commands/commitment.js +5 -0
  390. package/src/interfaces/cli/commands/config.js +85 -6
  391. package/src/interfaces/cli/commands/exec.js +90 -1
  392. package/src/interfaces/cli/commands/image.js +314 -0
  393. package/src/interfaces/cli/commands/mcp.js +87 -23
  394. package/src/interfaces/cli/commands/memory.js +35 -22
  395. package/src/interfaces/cli/commands/panel.js +94 -0
  396. package/src/interfaces/cli/commands/profile.js +14 -0
  397. package/src/interfaces/cli/commands/project.js +29 -0
  398. package/src/interfaces/cli/commands/routine.js +45 -10
  399. package/src/interfaces/cli/commands/runtime.js +30 -7
  400. package/src/interfaces/cli/commands/session.js +90 -38
  401. package/src/interfaces/cli/commands/sessions.js +35 -2
  402. package/src/interfaces/cli/commands/skills.js +15 -9
  403. package/src/interfaces/cli/commands/status.js +2 -3
  404. package/src/interfaces/cli/commands/task.js +54 -5
  405. package/src/interfaces/cli/commands/telegram.js +12 -4
  406. package/src/interfaces/cli/commands/transcribe.js +177 -0
  407. package/src/interfaces/cli/help/index.js +311 -72
  408. package/src/interfaces/cli/http.js +61 -13
  409. package/src/interfaces/cli/index.js +1 -1
  410. package/src/interfaces/cli/routes/agent.js +5 -4
  411. package/src/interfaces/cli/routes/commitment.js +3 -2
  412. package/src/interfaces/cli/routes/config.js +7 -2
  413. package/src/interfaces/cli/routes/image.js +11 -0
  414. package/src/interfaces/cli/routes/index.js +2 -0
  415. package/src/interfaces/cli/routes/log.js +1 -1
  416. package/src/interfaces/cli/routes/memory.js +3 -2
  417. package/src/interfaces/cli/routes/panel.js +15 -2
  418. package/src/interfaces/cli/routes/profile.js +3 -2
  419. package/src/interfaces/cli/routes/transcribe.js +10 -0
  420. package/src/interfaces/cli/stdin.js +29 -0
  421. package/src/interfaces/desktop/assets/blobs/amatista.png +0 -0
  422. package/src/interfaces/desktop/assets/blobs/aqua.png +0 -0
  423. package/src/interfaces/desktop/assets/blobs/brasa.png +0 -0
  424. package/src/interfaces/desktop/assets/blobs/campana.png +0 -0
  425. package/src/interfaces/desktop/assets/blobs/caracol.png +0 -0
  426. package/src/interfaces/desktop/assets/blobs/carbon.png +0 -0
  427. package/src/interfaces/desktop/assets/blobs/cobalto.png +0 -0
  428. package/src/interfaces/desktop/assets/blobs/cometa.png +0 -0
  429. package/src/interfaces/desktop/assets/blobs/coral.png +0 -0
  430. package/src/interfaces/desktop/assets/blobs/cubi.png +0 -0
  431. package/src/interfaces/desktop/assets/blobs/eclipse.png +0 -0
  432. package/src/interfaces/desktop/assets/blobs/faro.png +0 -0
  433. package/src/interfaces/desktop/assets/blobs/gajo.png +0 -0
  434. package/src/interfaces/desktop/assets/blobs/iris.png +0 -0
  435. package/src/interfaces/desktop/assets/blobs/kiwi.png +0 -0
  436. package/src/interfaces/desktop/assets/blobs/laguna.png +0 -0
  437. package/src/interfaces/desktop/assets/blobs/lila.png +0 -0
  438. package/src/interfaces/desktop/assets/blobs/menta.png +0 -0
  439. package/src/interfaces/desktop/assets/blobs/nimbo.png +0 -0
  440. package/src/interfaces/desktop/assets/blobs/noche.png +0 -0
  441. package/src/interfaces/desktop/assets/blobs/onyx.png +0 -0
  442. package/src/interfaces/desktop/assets/blobs/orbita.png +0 -0
  443. package/src/interfaces/desktop/assets/blobs/ovni.png +0 -0
  444. package/src/interfaces/desktop/assets/blobs/papa.png +0 -0
  445. package/src/interfaces/desktop/assets/blobs/parche.png +0 -0
  446. package/src/interfaces/desktop/assets/blobs/peon.png +0 -0
  447. package/src/interfaces/desktop/assets/blobs/perla.png +0 -0
  448. package/src/interfaces/desktop/assets/blobs/pino.png +0 -0
  449. package/src/interfaces/desktop/assets/blobs/quad.png +0 -0
  450. package/src/interfaces/desktop/assets/blobs/rubi.png +0 -0
  451. package/src/interfaces/desktop/assets/blobs/saturno.png +0 -0
  452. package/src/interfaces/desktop/assets/blobs/trebol.png +0 -0
  453. package/src/interfaces/desktop/assets/blobs/trino.png +0 -0
  454. package/src/interfaces/desktop/assets/blobs/volcan.png +0 -0
  455. package/src/interfaces/desktop/assets/blobs/zafiro.png +0 -0
  456. package/src/interfaces/desktop/assets/notification.mp3 +0 -0
  457. package/src/interfaces/desktop/main.js +473 -29
  458. package/src/interfaces/desktop/mascot-blobs.js +41 -0
  459. package/src/interfaces/desktop/mascot-preload.js +32 -0
  460. package/src/interfaces/desktop/mascot.css +186 -0
  461. package/src/interfaces/desktop/mascot.html +40 -0
  462. package/src/interfaces/desktop/mascot.js +163 -0
  463. package/src/interfaces/desktop/preload.js +10 -0
  464. package/src/interfaces/desktop/renderer.js +308 -48
  465. package/src/interfaces/desktop/style.css +34 -0
  466. package/src/interfaces/mcp-server/index.js +87 -0
  467. package/src/interfaces/tui/_shims/util-locale.ts +0 -2
  468. package/src/interfaces/tui/app.tsx +0 -6
  469. package/src/interfaces/tui/attach.ts +0 -1
  470. package/src/interfaces/tui/context/sdk-apx.tsx +0 -4
  471. package/src/interfaces/tui/plugin/api.tsx +0 -3
  472. package/src/interfaces/tui/plugin/runtime.ts +0 -3
  473. package/src/interfaces/tui/thread.ts +0 -16
  474. package/src/interfaces/web/README.md +22 -14
  475. package/src/interfaces/web/dist/assets/claude-XtpLmGtF.webp +0 -0
  476. package/src/interfaces/web/dist/assets/codex-DExPUgvh.webp +0 -0
  477. package/src/interfaces/web/dist/assets/index-BEoRgIqd.css +32 -0
  478. package/src/interfaces/web/dist/assets/index-BEoRgIqd.css.br +0 -0
  479. package/src/interfaces/web/dist/assets/index-BEoRgIqd.css.gz +0 -0
  480. package/src/interfaces/web/dist/assets/index-C6fXHc1p.js +1074 -0
  481. package/src/interfaces/web/dist/assets/index-C6fXHc1p.js.br +0 -0
  482. package/src/interfaces/web/dist/assets/index-C6fXHc1p.js.gz +0 -0
  483. package/src/interfaces/web/dist/assets/index-C6fXHc1p.js.map +1 -0
  484. package/src/interfaces/web/dist/assets/index-C6fXHc1p.js.map.br +0 -0
  485. package/src/interfaces/web/dist/assets/index-C6fXHc1p.js.map.gz +0 -0
  486. package/src/interfaces/web/dist/favicon/dark/site.webmanifest +12 -6
  487. package/src/interfaces/web/dist/favicon/white/site.webmanifest +12 -6
  488. package/src/interfaces/web/dist/index.html +22 -6
  489. package/src/interfaces/web/dist/index.html.br +0 -0
  490. package/src/interfaces/web/dist/index.html.gz +0 -0
  491. package/src/interfaces/web/dist/manifest.webmanifest +25 -0
  492. package/src/interfaces/web/dist/modules/blobs/amatista.png +0 -0
  493. package/src/interfaces/web/dist/modules/blobs/aqua.png +0 -0
  494. package/src/interfaces/web/dist/modules/blobs/brasa.png +0 -0
  495. package/src/interfaces/web/dist/modules/blobs/campana.png +0 -0
  496. package/src/interfaces/web/dist/modules/blobs/caracol.png +0 -0
  497. package/src/interfaces/web/dist/modules/blobs/carbon.png +0 -0
  498. package/src/interfaces/web/dist/modules/blobs/cobalto.png +0 -0
  499. package/src/interfaces/web/dist/modules/blobs/cometa.png +0 -0
  500. package/src/interfaces/web/dist/modules/blobs/coral.png +0 -0
  501. package/src/interfaces/web/dist/modules/blobs/cubi.png +0 -0
  502. package/src/interfaces/web/dist/modules/blobs/eclipse.png +0 -0
  503. package/src/interfaces/web/dist/modules/blobs/faro.png +0 -0
  504. package/src/interfaces/web/dist/modules/blobs/gajo.png +0 -0
  505. package/src/interfaces/web/dist/modules/blobs/iris.png +0 -0
  506. package/src/interfaces/web/dist/modules/blobs/kiwi.png +0 -0
  507. package/src/interfaces/web/dist/modules/blobs/laguna.png +0 -0
  508. package/src/interfaces/web/dist/modules/blobs/lila.png +0 -0
  509. package/src/interfaces/web/dist/modules/blobs/menta.png +0 -0
  510. package/src/interfaces/web/dist/modules/blobs/nimbo.png +0 -0
  511. package/src/interfaces/web/dist/modules/blobs/noche.png +0 -0
  512. package/src/interfaces/web/dist/modules/blobs/onyx.png +0 -0
  513. package/src/interfaces/web/dist/modules/blobs/orbita.png +0 -0
  514. package/src/interfaces/web/dist/modules/blobs/ovni.png +0 -0
  515. package/src/interfaces/web/dist/modules/blobs/papa.png +0 -0
  516. package/src/interfaces/web/dist/modules/blobs/parche.png +0 -0
  517. package/src/interfaces/web/dist/modules/blobs/peon.png +0 -0
  518. package/src/interfaces/web/dist/modules/blobs/perla.png +0 -0
  519. package/src/interfaces/web/dist/modules/blobs/pino.png +0 -0
  520. package/src/interfaces/web/dist/modules/blobs/quad.png +0 -0
  521. package/src/interfaces/web/dist/modules/blobs/rubi.png +0 -0
  522. package/src/interfaces/web/dist/modules/blobs/saturno.png +0 -0
  523. package/src/interfaces/web/dist/modules/blobs/trebol.png +0 -0
  524. package/src/interfaces/web/dist/modules/blobs/trino.png +0 -0
  525. package/src/interfaces/web/dist/modules/blobs/volcan.png +0 -0
  526. package/src/interfaces/web/dist/modules/blobs/zafiro.png +0 -0
  527. package/src/interfaces/web/dist/sw.js +106 -0
  528. package/src/interfaces/web/dist/sw.js.br +0 -0
  529. package/src/interfaces/web/dist/sw.js.gz +0 -0
  530. package/src/interfaces/web/eslint.config.js +83 -0
  531. package/src/interfaces/web/index.html +20 -4
  532. package/src/interfaces/web/package-lock.json +1651 -1280
  533. package/src/interfaces/web/package.json +9 -10
  534. package/src/interfaces/web/pnpm-lock.yaml +867 -869
  535. package/src/interfaces/web/public/favicon/dark/site.webmanifest +12 -6
  536. package/src/interfaces/web/public/favicon/white/site.webmanifest +12 -6
  537. package/src/interfaces/web/public/manifest.webmanifest +25 -0
  538. package/src/interfaces/web/public/modules/blobs/amatista.png +0 -0
  539. package/src/interfaces/web/public/modules/blobs/aqua.png +0 -0
  540. package/src/interfaces/web/public/modules/blobs/brasa.png +0 -0
  541. package/src/interfaces/web/public/modules/blobs/campana.png +0 -0
  542. package/src/interfaces/web/public/modules/blobs/caracol.png +0 -0
  543. package/src/interfaces/web/public/modules/blobs/carbon.png +0 -0
  544. package/src/interfaces/web/public/modules/blobs/cobalto.png +0 -0
  545. package/src/interfaces/web/public/modules/blobs/cometa.png +0 -0
  546. package/src/interfaces/web/public/modules/blobs/coral.png +0 -0
  547. package/src/interfaces/web/public/modules/blobs/cubi.png +0 -0
  548. package/src/interfaces/web/public/modules/blobs/eclipse.png +0 -0
  549. package/src/interfaces/web/public/modules/blobs/faro.png +0 -0
  550. package/src/interfaces/web/public/modules/blobs/gajo.png +0 -0
  551. package/src/interfaces/web/public/modules/blobs/iris.png +0 -0
  552. package/src/interfaces/web/public/modules/blobs/kiwi.png +0 -0
  553. package/src/interfaces/web/public/modules/blobs/laguna.png +0 -0
  554. package/src/interfaces/web/public/modules/blobs/lila.png +0 -0
  555. package/src/interfaces/web/public/modules/blobs/menta.png +0 -0
  556. package/src/interfaces/web/public/modules/blobs/nimbo.png +0 -0
  557. package/src/interfaces/web/public/modules/blobs/noche.png +0 -0
  558. package/src/interfaces/web/public/modules/blobs/onyx.png +0 -0
  559. package/src/interfaces/web/public/modules/blobs/orbita.png +0 -0
  560. package/src/interfaces/web/public/modules/blobs/ovni.png +0 -0
  561. package/src/interfaces/web/public/modules/blobs/papa.png +0 -0
  562. package/src/interfaces/web/public/modules/blobs/parche.png +0 -0
  563. package/src/interfaces/web/public/modules/blobs/peon.png +0 -0
  564. package/src/interfaces/web/public/modules/blobs/perla.png +0 -0
  565. package/src/interfaces/web/public/modules/blobs/pino.png +0 -0
  566. package/src/interfaces/web/public/modules/blobs/quad.png +0 -0
  567. package/src/interfaces/web/public/modules/blobs/rubi.png +0 -0
  568. package/src/interfaces/web/public/modules/blobs/saturno.png +0 -0
  569. package/src/interfaces/web/public/modules/blobs/trebol.png +0 -0
  570. package/src/interfaces/web/public/modules/blobs/trino.png +0 -0
  571. package/src/interfaces/web/public/modules/blobs/volcan.png +0 -0
  572. package/src/interfaces/web/public/modules/blobs/zafiro.png +0 -0
  573. package/src/interfaces/web/public/sw.js +106 -0
  574. package/src/interfaces/web/src/App.tsx +106 -10
  575. package/src/interfaces/web/src/assets/cli/claude.webp +0 -0
  576. package/src/interfaces/web/src/assets/cli/codex.webp +0 -0
  577. package/src/interfaces/web/src/assets/cli/cursor.svg +1 -0
  578. package/src/interfaces/web/src/assets/cli/opencode.png +0 -0
  579. package/src/interfaces/web/src/components/Combobox.tsx +201 -0
  580. package/src/interfaces/web/src/components/MobileHint.tsx +95 -0
  581. package/src/interfaces/web/src/components/MobileLinkDialog.tsx +156 -0
  582. package/src/interfaces/web/src/components/ModelCombobox.tsx +21 -113
  583. package/src/interfaces/web/src/components/{routines/ReadOnlyBlock.tsx → ReadOnlyBlock.tsx} +13 -4
  584. package/src/interfaces/web/src/components/Roby.tsx +5 -3
  585. package/src/interfaces/web/src/components/RobyBubble.tsx +23 -5
  586. package/src/interfaces/web/src/components/RowMenu.tsx +46 -0
  587. package/src/interfaces/web/src/components/TimezoneSelect.tsx +4 -1
  588. package/src/interfaces/web/src/components/Toast.tsx +50 -14
  589. package/src/interfaces/web/src/components/UiSelect.tsx +12 -5
  590. package/src/interfaces/web/src/components/agents/AgentAvatar.tsx +171 -0
  591. package/src/interfaces/web/src/components/agents/AgentFormFields.tsx +42 -11
  592. package/src/interfaces/web/src/components/agents/AgentModelBadge.tsx +157 -0
  593. package/src/interfaces/web/src/components/agents/AgentModelSelect.tsx +57 -0
  594. package/src/interfaces/web/src/components/agents/AgentSkillsPicker.tsx +115 -0
  595. package/src/interfaces/web/src/components/agents/BlobAvatar.tsx +50 -0
  596. package/src/interfaces/web/src/components/agents/blobPresets.ts +50 -0
  597. package/src/interfaces/web/src/components/agents/modelCatalog.ts +66 -0
  598. package/src/interfaces/web/src/components/chat/ActionGroup.tsx +162 -0
  599. package/src/interfaces/web/src/components/chat/AskAnswersCard.tsx +4 -3
  600. package/src/interfaces/web/src/components/chat/AskQuestionsCard.tsx +1 -1
  601. package/src/interfaces/web/src/components/chat/Attachment.tsx +220 -0
  602. package/src/interfaces/web/src/components/chat/ChatList.tsx +226 -51
  603. package/src/interfaces/web/src/components/chat/ChatRowActivity.tsx +45 -0
  604. package/src/interfaces/web/src/components/chat/Composer.tsx +672 -23
  605. package/src/interfaces/web/src/components/chat/ComposerCommands.tsx +175 -0
  606. package/src/interfaces/web/src/components/chat/ComposerSuggest.tsx +215 -0
  607. package/src/interfaces/web/src/components/chat/ContextBar.tsx +133 -65
  608. package/src/interfaces/web/src/components/chat/InlineAskPanel.tsx +107 -47
  609. package/src/interfaces/web/src/components/chat/MessageBubble.tsx +460 -119
  610. package/src/interfaces/web/src/components/chat/MessageList.tsx +165 -18
  611. package/src/interfaces/web/src/components/chat/ReasoningBlock.tsx +58 -0
  612. package/src/interfaces/web/src/components/chat/SessionPicker.tsx +182 -0
  613. package/src/interfaces/web/src/components/chat/SkillTrace.tsx +183 -0
  614. package/src/interfaces/web/src/components/chat/ToolCall.tsx +11 -11
  615. package/src/interfaces/web/src/components/code/CodeContextTab.tsx +87 -53
  616. package/src/interfaces/web/src/components/code/CodeFileTree.tsx +11 -52
  617. package/src/interfaces/web/src/components/code/CodeFileViewer.tsx +5 -4
  618. package/src/interfaces/web/src/components/code/CodeProjectPicker.tsx +31 -7
  619. package/src/interfaces/web/src/components/code/CodeSessionList.tsx +32 -11
  620. package/src/interfaces/web/src/components/code/CodeSidePanel.tsx +33 -3
  621. package/src/interfaces/web/src/components/code/CodeTerminal.tsx +5 -4
  622. package/src/interfaces/web/src/components/code/NewCodeSessionDialog.tsx +164 -0
  623. package/src/interfaces/web/src/components/commitments/CommitmentDetail.tsx +162 -0
  624. package/src/interfaces/web/src/components/commitments/CommitmentFormDialog.tsx +158 -0
  625. package/src/interfaces/web/src/components/commitments/CommitmentList.tsx +194 -0
  626. package/src/interfaces/web/src/components/commitments/commitmentState.tsx +46 -0
  627. package/src/interfaces/web/src/components/common/BulkActionBar.tsx +60 -0
  628. package/src/interfaces/web/src/components/common/ConfirmDialog.tsx +4 -1
  629. package/src/interfaces/web/src/components/common/SelectCheckbox.tsx +40 -0
  630. package/src/interfaces/web/src/components/common/TabNav.tsx +1 -1
  631. package/src/interfaces/web/src/components/cron/CronPicker.tsx +1 -1
  632. package/src/interfaces/web/src/components/files/FileBrowser.tsx +1 -1
  633. package/src/interfaces/web/src/components/files/FileTree.tsx +6 -4
  634. package/src/interfaces/web/src/components/files/FileViewer.tsx +9 -5
  635. package/src/interfaces/web/src/components/files/MarkdownPreview.tsx +45 -9
  636. package/src/interfaces/web/src/components/images/ImageDefaultsCard.tsx +93 -0
  637. package/src/interfaces/web/src/components/images/ImageProviderList.tsx +142 -0
  638. package/src/interfaces/web/src/components/images/ImageProviderModal.tsx +263 -0
  639. package/src/interfaces/web/src/components/images/ImageTestCard.tsx +142 -0
  640. package/src/interfaces/web/src/components/inbox/ChannelFilter.tsx +178 -0
  641. package/src/interfaces/web/src/components/inbox/InboxList.tsx +77 -81
  642. package/src/interfaces/web/src/components/inbox/InboxRowItem.tsx +140 -0
  643. package/src/interfaces/web/src/components/integrations/ComingSoonPlugin.tsx +2 -2
  644. package/src/interfaces/web/src/components/integrations/PluginConnect.tsx +208 -30
  645. package/src/interfaces/web/src/components/integrations/PluginToolsSection.tsx +1 -1
  646. package/src/interfaces/web/src/components/layout/ProjectAvatar.tsx +39 -24
  647. package/src/interfaces/web/src/components/layout/ProjectSidebar.tsx +253 -58
  648. package/src/interfaces/web/src/components/memory/MemoryBrowser.tsx +94 -47
  649. package/src/interfaces/web/src/components/routines/ExecutionsList.tsx +202 -90
  650. package/src/interfaces/web/src/components/routines/RoutineDetail.tsx +28 -6
  651. package/src/interfaces/web/src/components/routines/RoutineEditor.tsx +16 -5
  652. package/src/interfaces/web/src/components/routines/RoutineList.tsx +49 -9
  653. package/src/interfaces/web/src/components/routines/VarTextarea.tsx +1 -1
  654. package/src/interfaces/web/src/components/routines/runChat.ts +121 -0
  655. package/src/interfaces/web/src/components/sessions/SessionDetail.tsx +148 -0
  656. package/src/interfaces/web/src/components/sessions/SessionTerminal.tsx +98 -0
  657. package/src/interfaces/web/src/components/settings/AccessPanel.tsx +205 -0
  658. package/src/interfaces/web/src/components/settings/DefaultRouterCard.tsx +246 -101
  659. package/src/interfaces/web/src/components/settings/DesktopSettingsPanel.tsx +36 -2
  660. package/src/interfaces/web/src/components/settings/DevicesPanel.tsx +19 -6
  661. package/src/interfaces/web/src/components/settings/EmbedProviderList.tsx +274 -0
  662. package/src/interfaces/web/src/components/settings/EnginesPanel.tsx +26 -6
  663. package/src/interfaces/web/src/components/settings/MemoryPanel.tsx +118 -119
  664. package/src/interfaces/web/src/components/settings/NudgePanel.tsx +4 -3
  665. package/src/interfaces/web/src/components/settings/PairDeviceDialog.tsx +15 -4
  666. package/src/interfaces/web/src/components/settings/PanelPrefs.tsx +374 -0
  667. package/src/interfaces/web/src/components/settings/ProfilePanel.tsx +70 -2
  668. package/src/interfaces/web/src/components/settings/RoutingPanel.tsx +2 -1
  669. package/src/interfaces/web/src/components/settings/SkillsInspectorPanel.tsx +102 -43
  670. package/src/interfaces/web/src/components/settings/SkillsManager.tsx +76 -21
  671. package/src/interfaces/web/src/components/settings/SkillsSettings.tsx +10 -3
  672. package/src/interfaces/web/src/components/settings/SuperAgentPanel.tsx +8 -0
  673. package/src/interfaces/web/src/components/settings/TelegramChannelsPanel.tsx +11 -2
  674. package/src/interfaces/web/src/components/settings/TelegramContactsPanel.tsx +19 -8
  675. package/src/interfaces/web/src/components/settings/TelegramRolesPanel.tsx +12 -2
  676. package/src/interfaces/web/src/components/settings/WebPanel.tsx +22 -31
  677. package/src/interfaces/web/src/components/settings/providers/ProviderCard.tsx +15 -3
  678. package/src/interfaces/web/src/components/settings/providers/ProviderModal.tsx +97 -66
  679. package/src/interfaces/web/src/components/settings/providers/ProviderTestDialog.tsx +150 -0
  680. package/src/interfaces/web/src/components/settings/providers/typeStyles.ts +67 -25
  681. package/src/interfaces/web/src/components/settings/providers/types.ts +3 -0
  682. package/src/interfaces/web/src/components/tasks/TaskBoard.tsx +201 -0
  683. package/src/interfaces/web/src/components/tasks/TaskColumnsDialog.tsx +243 -0
  684. package/src/interfaces/web/src/components/tasks/TaskComments.tsx +167 -0
  685. package/src/interfaces/web/src/components/tasks/TaskDetail.tsx +335 -0
  686. package/src/interfaces/web/src/components/tasks/TaskFormDialog.tsx +406 -0
  687. package/src/interfaces/web/src/components/tasks/TaskList.tsx +258 -0
  688. package/src/interfaces/web/src/components/tasks/TaskSubtasks.tsx +126 -0
  689. package/src/interfaces/web/src/components/tasks/columns.ts +51 -0
  690. package/src/interfaces/web/src/components/tasks/taskStatus.tsx +159 -34
  691. package/src/interfaces/web/src/components/tasks/taskViewPrefs.ts +73 -0
  692. package/src/interfaces/web/src/components/tasks/useTaskColumns.ts +31 -0
  693. package/src/interfaces/web/src/components/ui/chat-input.tsx +136 -12
  694. package/src/interfaces/web/src/components/ui/context-menu.tsx +15 -198
  695. package/src/interfaces/web/src/components/ui/dialog.tsx +3 -2
  696. package/src/interfaces/web/src/components/ui/filter-chips.tsx +4 -0
  697. package/src/interfaces/web/src/components/ui/popover.tsx +14 -49
  698. package/src/interfaces/web/src/components/ui/sheet.tsx +2 -1
  699. package/src/interfaces/web/src/components/ui/spinner.tsx +2 -1
  700. package/src/interfaces/web/src/components/ui.tsx +62 -23
  701. package/src/interfaces/web/src/components/voice/VoiceProviderList.tsx +2 -1
  702. package/src/interfaces/web/src/components/voice/VoiceProviderModal.tsx +66 -8
  703. package/src/interfaces/web/src/components/voice/VoiceQvoxInstallCard.tsx +63 -0
  704. package/src/interfaces/web/src/components/voice/VoiceQvoxStatusCard.tsx +51 -0
  705. package/src/interfaces/web/src/components/voice/VoiceSttCard.tsx +4 -3
  706. package/src/interfaces/web/src/components/voice/VoiceTestCard.tsx +38 -4
  707. package/src/interfaces/web/src/constants/index.ts +1 -0
  708. package/src/interfaces/web/src/hooks/useChannelPrefs.ts +39 -0
  709. package/src/interfaces/web/src/hooks/useChat.ts +1092 -85
  710. package/src/interfaces/web/src/hooks/useChatActivity.ts +24 -0
  711. package/src/interfaces/web/src/hooks/useInbox.ts +26 -4
  712. package/src/interfaces/web/src/hooks/useLiveMessages.ts +16 -0
  713. package/src/interfaces/web/src/hooks/useOllamaModels.ts +79 -0
  714. package/src/interfaces/web/src/hooks/useRecorder.ts +198 -0
  715. package/src/interfaces/web/src/hooks/useTokenBootstrap.ts +23 -6
  716. package/src/interfaces/web/src/i18n/en.ts +832 -175
  717. package/src/interfaces/web/src/i18n/es.ts +841 -188
  718. package/src/interfaces/web/src/lib/api/agents.ts +23 -4
  719. package/src/interfaces/web/src/lib/api/code.ts +17 -0
  720. package/src/interfaces/web/src/lib/api/commitments.ts +7 -1
  721. package/src/interfaces/web/src/lib/api/conversations.ts +38 -11
  722. package/src/interfaces/web/src/lib/api/embeddings.ts +3 -0
  723. package/src/interfaces/web/src/lib/api/engines.ts +14 -0
  724. package/src/interfaces/web/src/lib/api/groups.ts +93 -0
  725. package/src/interfaces/web/src/lib/api/images.ts +193 -0
  726. package/src/interfaces/web/src/lib/api/inbox.ts +29 -5
  727. package/src/interfaces/web/src/lib/api/integrations.ts +9 -0
  728. package/src/interfaces/web/src/lib/api/media.ts +126 -0
  729. package/src/interfaces/web/src/lib/api/net.ts +44 -0
  730. package/src/interfaces/web/src/lib/api/profiles.ts +12 -0
  731. package/src/interfaces/web/src/lib/api/projects.ts +9 -1
  732. package/src/interfaces/web/src/lib/api/routines.ts +9 -1
  733. package/src/interfaces/web/src/lib/api/sessions.ts +18 -0
  734. package/src/interfaces/web/src/lib/api/skills.ts +8 -0
  735. package/src/interfaces/web/src/lib/api/super_agent.ts +3 -0
  736. package/src/interfaces/web/src/lib/api/tasks.ts +46 -6
  737. package/src/interfaces/web/src/lib/api/tools.ts +2 -0
  738. package/src/interfaces/web/src/lib/api/transcribe.ts +31 -0
  739. package/src/interfaces/web/src/lib/api/turns.ts +20 -0
  740. package/src/interfaces/web/src/lib/api/voice.ts +72 -2
  741. package/src/interfaces/web/src/lib/api.ts +3 -0
  742. package/src/interfaces/web/src/lib/channels.ts +214 -0
  743. package/src/interfaces/web/src/lib/chat-activity.ts +175 -0
  744. package/src/interfaces/web/src/lib/chat-prefs.ts +48 -0
  745. package/src/interfaces/web/src/lib/code-context.ts +0 -2
  746. package/src/interfaces/web/src/lib/http.ts +51 -17
  747. package/src/interfaces/web/src/lib/inbox-selection.ts +29 -0
  748. package/src/interfaces/web/src/lib/live.ts +252 -0
  749. package/src/interfaces/web/src/lib/net.ts +211 -0
  750. package/src/interfaces/web/src/lib/notify.ts +331 -0
  751. package/src/interfaces/web/src/lib/projectNav.ts +40 -0
  752. package/src/interfaces/web/src/lib/pwa.ts +115 -0
  753. package/src/interfaces/web/src/lib/qvox.ts +24 -0
  754. package/src/interfaces/web/src/lib/slug.ts +3 -0
  755. package/src/interfaces/web/src/lib/tone.ts +150 -0
  756. package/src/interfaces/web/src/main.tsx +15 -4
  757. package/src/interfaces/web/src/screens/ApxAdminScreen.tsx +33 -11
  758. package/src/interfaces/web/src/screens/InboxScreen.tsx +126 -71
  759. package/src/interfaces/web/src/screens/ProjectScreen.tsx +8 -4
  760. package/src/interfaces/web/src/screens/SettingsScreen.tsx +7 -4
  761. package/src/interfaces/web/src/screens/base/AgentDefaultsTab.tsx +30 -9
  762. package/src/interfaces/web/src/screens/base/CommitmentsTab.tsx +150 -168
  763. package/src/interfaces/web/src/screens/base/LogsTab.tsx +8 -7
  764. package/src/interfaces/web/src/screens/base/SessionsTab.tsx +99 -37
  765. package/src/interfaces/web/src/screens/base/WorkspacesTab.tsx +1 -1
  766. package/src/interfaces/web/src/screens/mobile/MobileChat.tsx +85 -0
  767. package/src/interfaces/web/src/screens/mobile/MobileChatList.tsx +244 -0
  768. package/src/interfaces/web/src/screens/mobile/MobileCommitments.tsx +350 -0
  769. package/src/interfaces/web/src/screens/mobile/MobileScreen.tsx +138 -0
  770. package/src/interfaces/web/src/screens/mobile/MobileTabBar.tsx +105 -0
  771. package/src/interfaces/web/src/screens/mobile/MobileTasks.tsx +407 -0
  772. package/src/interfaces/web/src/screens/mobile/NewChatSheet.tsx +313 -0
  773. package/src/interfaces/web/src/screens/mobile/mobileList.tsx +194 -0
  774. package/src/interfaces/web/src/screens/mobile/routes.ts +239 -0
  775. package/src/interfaces/web/src/screens/modules/CodeScreen.tsx +135 -64
  776. package/src/interfaces/web/src/screens/modules/DeckScreen.tsx +0 -1
  777. package/src/interfaces/web/src/screens/modules/ImagesScreen.tsx +172 -0
  778. package/src/interfaces/web/src/screens/modules/VoiceScreen.tsx +36 -4
  779. package/src/interfaces/web/src/screens/project/AgentBrainGraph.tsx +117 -30
  780. package/src/interfaces/web/src/screens/project/AgentDetailScreen.tsx +537 -92
  781. package/src/interfaces/web/src/screens/project/AgentsTab.tsx +344 -93
  782. package/src/interfaces/web/src/screens/project/ArtifactsTab.tsx +1 -1
  783. package/src/interfaces/web/src/screens/project/ChatTab.tsx +1160 -94
  784. package/src/interfaces/web/src/screens/project/IntegrationsTab.tsx +3 -2
  785. package/src/interfaces/web/src/screens/project/McpsTab.tsx +62 -14
  786. package/src/interfaces/web/src/screens/project/Overview.tsx +36 -15
  787. package/src/interfaces/web/src/screens/project/RoutinesTab.tsx +93 -8
  788. package/src/interfaces/web/src/screens/project/SkillsTab.tsx +4 -1
  789. package/src/interfaces/web/src/screens/project/StructureTab.tsx +5 -4
  790. package/src/interfaces/web/src/screens/project/TasksTab.tsx +351 -129
  791. package/src/interfaces/web/src/screens/project/VarsTab.tsx +17 -5
  792. package/src/interfaces/web/src/styles.css +106 -31
  793. package/src/interfaces/web/src/types/daemon.ts +246 -2
  794. package/src/interfaces/web/src/vite-env.d.ts +20 -0
  795. package/src/interfaces/tui/plugin/command-shim.ts +0 -109
  796. package/src/interfaces/web/components.json +0 -25
  797. package/src/interfaces/web/dist/assets/index-CvEoGtTf.js +0 -849
  798. package/src/interfaces/web/dist/assets/index-CvEoGtTf.js.map +0 -1
  799. package/src/interfaces/web/dist/assets/index-DzBBXFaO.css +0 -1
  800. package/src/interfaces/web/src/components/tasks/TaskDetailPanel.tsx +0 -142
  801. package/src/interfaces/web/src/components/ui/accordion.tsx +0 -72
  802. package/src/interfaces/web/src/components/ui/alert-dialog.tsx +0 -187
  803. package/src/interfaces/web/src/components/ui/alert.tsx +0 -76
  804. package/src/interfaces/web/src/components/ui/aspect-ratio.tsx +0 -22
  805. package/src/interfaces/web/src/components/ui/avatar.tsx +0 -107
  806. package/src/interfaces/web/src/components/ui/breadcrumb.tsx +0 -125
  807. package/src/interfaces/web/src/components/ui/button-group.tsx +0 -87
  808. package/src/interfaces/web/src/components/ui/calendar.tsx +0 -221
  809. package/src/interfaces/web/src/components/ui/card.tsx +0 -103
  810. package/src/interfaces/web/src/components/ui/carousel.tsx +0 -242
  811. package/src/interfaces/web/src/components/ui/chart.tsx +0 -371
  812. package/src/interfaces/web/src/components/ui/checkbox.tsx +0 -29
  813. package/src/interfaces/web/src/components/ui/collapsible.tsx +0 -19
  814. package/src/interfaces/web/src/components/ui/combobox.tsx +0 -295
  815. package/src/interfaces/web/src/components/ui/command.tsx +0 -196
  816. package/src/interfaces/web/src/components/ui/direction.tsx +0 -4
  817. package/src/interfaces/web/src/components/ui/drawer.tsx +0 -134
  818. package/src/interfaces/web/src/components/ui/empty.tsx +0 -104
  819. package/src/interfaces/web/src/components/ui/field.tsx +0 -236
  820. package/src/interfaces/web/src/components/ui/hover-card.tsx +0 -51
  821. package/src/interfaces/web/src/components/ui/input-otp.tsx +0 -85
  822. package/src/interfaces/web/src/components/ui/item.tsx +0 -201
  823. package/src/interfaces/web/src/components/ui/menubar.tsx +0 -280
  824. package/src/interfaces/web/src/components/ui/native-select.tsx +0 -61
  825. package/src/interfaces/web/src/components/ui/navigation-menu.tsx +0 -168
  826. package/src/interfaces/web/src/components/ui/pagination.tsx +0 -130
  827. package/src/interfaces/web/src/components/ui/progress.tsx +0 -83
  828. package/src/interfaces/web/src/components/ui/radio-group.tsx +0 -36
  829. package/src/interfaces/web/src/components/ui/resizable.tsx +0 -50
  830. package/src/interfaces/web/src/components/ui/scroll-area.tsx +0 -53
  831. package/src/interfaces/web/src/components/ui/sidebar.tsx +0 -726
  832. package/src/interfaces/web/src/components/ui/slider.tsx +0 -52
  833. package/src/interfaces/web/src/components/ui/sonner.tsx +0 -49
  834. package/src/interfaces/web/src/components/ui/table.tsx +0 -116
  835. package/src/interfaces/web/src/components/ui/toggle-group.tsx +0 -87
  836. package/src/interfaces/web/src/components/ui/toggle.tsx +0 -45
  837. package/src/interfaces/web/src/hooks/use-mobile.ts +0 -19
  838. package/src/interfaces/web/src/screens/base/GlobalTasksTab.tsx +0 -161
@@ -1,9 +1,9 @@
1
1
  import { useMemo, useState } from "react";
2
- import { useNavigate, useParams } from "react-router-dom";
2
+ import { Link, useNavigate, useParams, useSearchParams } from "react-router-dom";
3
3
  import useSWR from "swr";
4
4
  import {
5
- ArrowDownLeft, ArrowLeft, ArrowUpRight, Bot, Brain, Crown, Gauge,
6
- Heart, MessagesSquare, Save, Send, Settings, Sparkles, Trash2, Wrench, Activity,
5
+ ArrowDownLeft, ArrowLeft, ArrowUpRight, Bot, Brain, Copy, Crown, FileText, Gauge,
6
+ Heart, MessagesSquare, Pencil, Save, Send, Settings, Sparkles, Trash2, Wrench, Activity,
7
7
  } from "lucide-react";
8
8
  import { Agents, Conversations, Messages, Routines, Tasks, Tools } from "../../lib/api";
9
9
  import type { AgentDetail, AgentEntry, FileContent, MessageEntry, RoutineEntry } from "../../types/daemon";
@@ -13,14 +13,22 @@ import { Tip } from "../../components/ui/tip";
13
13
  import { UiSelect } from "../../components/UiSelect";
14
14
  import { useToast } from "../../components/Toast";
15
15
  import { ConfirmDialog } from "../../components/common/ConfirmDialog";
16
- import { EmojiInput, AutonomyPicker, AreaRoleFields } from "../../components/agents/AgentFormFields";
16
+ import { AutonomyPicker, AreaRoleFields, AgentIconPicker } from "../../components/agents/AgentFormFields";
17
+ import { AgentSkillsPicker } from "../../components/agents/AgentSkillsPicker";
18
+ import { AgentModelSelect } from "../../components/agents/AgentModelSelect";
19
+ import { INHERIT_MODEL, isInheritedModel } from "../../components/agents/modelCatalog";
20
+ import { useProject } from "../../hooks/useProjects";
21
+ import { BlobAvatar } from "../../components/agents/BlobAvatar";
22
+ import { isBlobKey } from "../../components/agents/blobPresets";
17
23
  import { FileViewer } from "../../components/files/FileViewer";
18
24
  import { cn } from "../../lib/cn";
25
+ import { slugify } from "../../lib/slug";
19
26
  import { t } from "../../i18n";
27
+ import { toneOutline, toneText } from "../../lib/tone";
20
28
  import type { AgentAutonomy } from "../../types/daemon";
21
- import { BrainGraph, type BrainNode, type BrainEdge } from "./AgentBrainGraph";
29
+ import { BrainGraph, type BrainNode, type BrainEdge, agentPreview, routinePreview, clipPreview } from "./AgentBrainGraph";
22
30
 
23
- type TabKey = "overview" | "memories" | "records" | "sleep" | "brain" | "config";
31
+ type TabKey = "overview" | "memories" | "records" | "sleep" | "brain" | "prompt" | "config";
24
32
  function buildTabs(): { key: TabKey; label: string; icon: typeof Bot }[] {
25
33
  return [
26
34
  { key: "overview", label: t("agents_ui.tab_explorer"), icon: Gauge },
@@ -28,7 +36,8 @@ function buildTabs(): { key: TabKey; label: string; icon: typeof Bot }[] {
28
36
  { key: "records", label: t("project.agent_detail.records_title"), icon: Activity },
29
37
  { key: "sleep", label: t("project.agent_detail.sleep_title"), icon: Heart },
30
38
  { key: "brain", label: t("project.agent_detail.brain_title"), icon: Sparkles },
31
- { key: "config", label: t("settings.tabs.advanced"), icon: Settings },
39
+ { key: "prompt", label: t("project.agent_detail.tab_prompt"), icon: FileText },
40
+ { key: "config", label: t("project.agent_detail.tab_config"), icon: Settings },
32
41
  ];
33
42
  }
34
43
 
@@ -44,6 +53,10 @@ export function typeOptions() {
44
53
  }
45
54
  const csv = (s: string) => s.split(",").map((x) => x.trim()).filter(Boolean);
46
55
 
56
+ // Height cap for the skills scroller, chosen to sit level with the tools card
57
+ // beside it rather than stretching the row to the full skill catalog.
58
+ const SKILLS_SCROLLER_MAX = 260;
59
+
47
60
  const routinesForAgent = (rs: RoutineEntry[], slug: string) =>
48
61
  rs.filter((r) => (r.spec as any)?.agent === slug || (slug === "super-agent" && r.kind === "super_agent"));
49
62
 
@@ -58,9 +71,13 @@ function memoryFacts(text: string): string[] {
58
71
  export function AgentDetailScreen({ pid }: { pid: string }) {
59
72
  const { slug = "" } = useParams();
60
73
  const navigate = useNavigate();
61
- const [tab, setTab] = useState<TabKey>("overview");
74
+ const [searchParams] = useSearchParams();
62
75
  const TABS = buildTabs();
76
+ // Tab lives in the URL (?tab=…) so views are linkable and survive reloads.
77
+ const raw = searchParams.get("tab");
78
+ const tab: TabKey = TABS.some((x) => x.key === raw) ? (raw as TabKey) : "overview";
63
79
 
80
+ const { project } = useProject(pid);
64
81
  const detail = useSWR(`/api/projects/${pid}/agents/${slug}`, () => Agents.get(pid, slug));
65
82
  const agents = useSWR(`/api/projects/${pid}/agents`, () => Agents.list(pid));
66
83
  const routines = useSWR(`/api/projects/${pid}/routines`, () => Routines.list(pid));
@@ -86,17 +103,27 @@ export function AgentDetailScreen({ pid }: { pid: string }) {
86
103
  <button onClick={() => navigate(`/p/${pid}/agents`)} className="mt-1 text-muted-fg hover:text-foreground">
87
104
  <ArrowLeft size={16} />
88
105
  </button>
89
- <div className={cn("flex size-11 items-center justify-center rounded-xl bg-gradient-to-br", a.is_master ? "from-violet-600 to-indigo-600" : "from-slate-600 to-gray-600")}>
90
- <Icon className="size-5 text-white" />
91
- </div>
106
+ {isBlobKey(a.icon) ? (
107
+ <BlobAvatar preset={a.icon} size={44} seed={a.slug} className="shrink-0" />
108
+ ) : (
109
+ <div className={cn("flex size-11 items-center justify-center rounded-xl bg-gradient-to-br", a.is_master ? "from-violet-600 to-indigo-600" : "from-slate-600 to-gray-600")}>
110
+ {a.emoji ? <span className="text-xl leading-none">{a.emoji}</span> : <Icon className="size-5 text-white" />}
111
+ </div>
112
+ )}
92
113
  <div>
93
114
  <div className="flex flex-wrap items-center gap-2">
94
- <h1 className="text-lg font-semibold">{a.slug}</h1>
115
+ <AgentNameHeading
116
+ pid={pid}
117
+ slug={a.slug}
118
+ name={a.name || ""}
119
+ onSaved={() => { void detail.mutate(); void agents.mutate(); }}
120
+ onRenamed={(newSlug) => { void agents.mutate(); navigate(`/p/${pid}/agents/${newSlug}`); }}
121
+ />
95
122
  {a.is_master && <Badge tone="success"><Crown size={10} /> {t("project.agents.orchestrator")}</Badge>}
96
123
  {a.role && <Badge>{a.role}</Badge>}
97
124
  {a.model && <Badge tone="info">{a.model}</Badge>}
98
125
  {a.parent && (
99
- <button onClick={() => navigate(`/p/${pid}/agents/${a.parent}`)} className="text-[11px] text-violet-400 hover:underline">
126
+ <button onClick={() => navigate(`/p/${pid}/agents/${a.parent}`)} className={`text-[11px] hover:underline ${toneText.violet}`}>
100
127
  {t("project.agent_detail.reports_to")} {a.parent}
101
128
  </button>
102
129
  )}
@@ -104,24 +131,34 @@ export function AgentDetailScreen({ pid }: { pid: string }) {
104
131
  {a.description && <p className="mt-0.5 max-w-2xl text-xs text-muted-fg">{a.description}</p>}
105
132
  </div>
106
133
  </div>
107
- <Button size="sm" variant="primary" onClick={() => navigate(`/p/${pid}/chat?agent=${slug}`)}>
108
- <Send size={13} /> {t("project.agent_detail.chat_btn", { slug: a.slug })}
109
- </Button>
134
+ <div className="flex shrink-0 items-center gap-2">
135
+ <CloneAgentButton
136
+ pid={pid}
137
+ slug={a.slug}
138
+ onCloned={(newSlug) => {
139
+ void agents.mutate();
140
+ navigate(`/p/${pid}/agents/${newSlug}`);
141
+ }}
142
+ />
143
+ <Button size="sm" variant="primary" onClick={() => navigate(`/p/${pid}/chat?agent=${slug}`)}>
144
+ <Send size={13} /> {t("project.agent_detail.chat_btn", { slug: a.slug })}
145
+ </Button>
146
+ </div>
110
147
  </div>
111
148
 
112
- {/* Tabs */}
149
+ {/* Tabs — real links (?tab=…) so each view has a shareable href */}
113
150
  <div className="flex flex-wrap gap-1 border-b border-border">
114
151
  {TABS.map(({ key, label, icon: TI }) => (
115
- <button
152
+ <Link
116
153
  key={key}
117
- onClick={() => setTab(key)}
154
+ to={`?tab=${key}`}
118
155
  className={cn(
119
156
  "flex items-center gap-1.5 border-b-2 px-3 py-2 text-sm transition-colors -mb-px",
120
157
  tab === key ? "border-foreground text-foreground" : "border-transparent text-muted-fg hover:text-foreground",
121
158
  )}
122
159
  >
123
160
  <TI size={14} /> {label}
124
- </button>
161
+ </Link>
125
162
  ))}
126
163
  </div>
127
164
 
@@ -176,41 +213,182 @@ export function AgentDetailScreen({ pid }: { pid: string }) {
176
213
 
177
214
  {tab === "brain" && (
178
215
  <BrainTab
216
+ pid={pid}
179
217
  slug={slug}
180
218
  emoji={a.emoji || undefined}
219
+ icon={a.icon || undefined}
220
+ description={a.description || undefined}
221
+ role={a.role || undefined}
222
+ type={a.type || undefined}
181
223
  memory={a.memory || ""}
182
224
  threads={(threads.data || []).map((t) => ({ id: t.id, label: t.title || t.filename }))}
183
225
  tasks={myTasks.map((t) => ({ id: t.id, label: t.title, detail: t.body || undefined }))}
184
226
  routines={myRoutines}
185
- parent={a.parent || null}
186
- children={children.map((c) => c.slug)}
227
+ parent={a.parent
228
+ ? ((agents.data || []).find((x) => x.slug === a.parent) ?? { slug: a.parent })
229
+ : null}
230
+ children={children}
187
231
  />
188
232
  )}
189
233
 
234
+ {tab === "prompt" && (
235
+ <SystemPromptEditor pid={pid} slug={slug} system={a.system || ""} onSaved={() => void detail.mutate()} />
236
+ )}
237
+
190
238
  {tab === "config" && (
191
239
  <AgentConfigForm
192
240
  pid={pid}
193
241
  agent={a}
194
242
  agents={agents.data || []}
243
+ projectPath={project?.path}
195
244
  onSaved={() => { detail.mutate(); agents.mutate(); }}
196
245
  onDeleted={() => { agents.mutate(); navigate(`/p/${pid}/agents`); }}
246
+ onRenamed={(newSlug) => { void agents.mutate(); navigate(`/p/${pid}/agents/${newSlug}?tab=config`); }}
197
247
  />
198
248
  )}
199
249
  </div>
200
250
  );
201
251
  }
202
252
 
253
+ // Heading that doubles as an inline rename. Click the pencil (or the name) to
254
+ // swap the h1 for an input; Enter/blur saves, Escape cancels. Only the display
255
+ // Name changes — the slug is the agent's identity (filename, parent links,
256
+ // delegation targets) and stays put.
257
+ function AgentNameHeading({
258
+ pid, slug, name, onSaved, onRenamed,
259
+ }: { pid: string; slug: string; name: string; onSaved: () => void; onRenamed: (s: string) => void }) {
260
+ const toast = useToast();
261
+ const [editing, setEditing] = useState(false);
262
+ const [draft, setDraft] = useState(name);
263
+ const [busy, setBusy] = useState(false);
264
+ // After a name change, if the slug would follow, we offer to rename it too —
265
+ // but renaming moves the agent's file/dir and changes the URL, so it's an
266
+ // explicit confirm rather than a silent side effect of editing the name.
267
+ const [renameTo, setRenameTo] = useState<string | null>(null);
268
+
269
+ const start = () => { setDraft(name); setEditing(true); };
270
+
271
+ const commit = async () => {
272
+ const next = draft.trim();
273
+ setEditing(false);
274
+ if (next === name) return;
275
+ setBusy(true);
276
+ try {
277
+ await Agents.update(pid, slug, { name: next || null });
278
+ onSaved();
279
+ // Suggest matching the slug to the new name, but only when it's a real,
280
+ // valid change (never for the super-agent or an unchanged slug).
281
+ const suggested = slugify(next);
282
+ if (
283
+ slug !== "super-agent" &&
284
+ suggested &&
285
+ suggested !== slug &&
286
+ /^[a-z][a-z0-9_-]*$/.test(suggested)
287
+ ) {
288
+ setRenameTo(suggested);
289
+ }
290
+ } catch (e) { toast.error((e as Error).message); }
291
+ finally { setBusy(false); }
292
+ };
293
+
294
+ const rename = async () => {
295
+ if (!renameTo) return;
296
+ setBusy(true);
297
+ try {
298
+ const updated = await Agents.rename(pid, slug, renameTo);
299
+ toast.success(t("project.agent_detail.rename_success", { slug: updated.slug }));
300
+ onRenamed(updated.slug);
301
+ } catch (e) { toast.error((e as Error).message); }
302
+ finally { setBusy(false); setRenameTo(null); }
303
+ };
304
+
305
+ if (editing) {
306
+ return (
307
+ <input
308
+ autoFocus
309
+ value={draft}
310
+ disabled={busy}
311
+ onChange={(e) => setDraft(e.target.value)}
312
+ onBlur={commit}
313
+ onKeyDown={(e) => {
314
+ if (e.key === "Enter") { e.preventDefault(); void commit(); }
315
+ if (e.key === "Escape") { setDraft(name); setEditing(false); }
316
+ }}
317
+ placeholder={slug}
318
+ aria-label={t("agents_form.name")}
319
+ className="rounded-md border border-border bg-card px-2 py-0.5 text-lg font-semibold outline-none focus:border-muted-fg"
320
+ />
321
+ );
322
+ }
323
+
324
+ return (
325
+ <span className="group flex items-center gap-1.5">
326
+ <h1 className="cursor-text text-lg font-semibold" onClick={start}>{name || slug}</h1>
327
+ {name && <span className="font-mono text-[11px] text-muted-fg">{slug}</span>}
328
+ <Tip content={t("common.edit")}>
329
+ <button
330
+ type="button"
331
+ onClick={start}
332
+ aria-label={t("common.edit")}
333
+ className="text-muted-fg opacity-0 transition-opacity hover:text-foreground group-hover:opacity-100"
334
+ >
335
+ <Pencil size={13} />
336
+ </button>
337
+ </Tip>
338
+ <ConfirmDialog
339
+ open={!!renameTo}
340
+ onClose={() => setRenameTo(null)}
341
+ onConfirm={rename}
342
+ title={t("project.agent_detail.rename_btn")}
343
+ description={t("project.agent_detail.rename_confirm", { from: slug, to: renameTo || "" })}
344
+ confirmLabel={t("project.agent_detail.rename_btn")}
345
+ />
346
+ </span>
347
+ );
348
+ }
349
+
350
+ // Duplicate this agent and jump to the copy. The heavy lifting (unique slug,
351
+ // " (n)" naming, prompt + memory copy) is server-side; here we only fire it,
352
+ // surface the toast, and let the parent navigate to the fresh agent.
353
+ function CloneAgentButton({
354
+ pid, slug, onCloned,
355
+ }: { pid: string; slug: string; onCloned: (newSlug: string) => void }) {
356
+ const toast = useToast();
357
+ const [busy, setBusy] = useState(false);
358
+
359
+ const clone = async () => {
360
+ setBusy(true);
361
+ try {
362
+ const created = await Agents.clone(pid, slug);
363
+ toast.success(t("project.agent_detail.clone_success", { slug: created.slug }));
364
+ onCloned(created.slug);
365
+ } catch (e) { toast.error((e as Error).message); }
366
+ finally { setBusy(false); }
367
+ };
368
+
369
+ return (
370
+ <Tip content={t("project.agent_detail.clone_hint")}>
371
+ <Button size="sm" variant="secondary" loading={busy} onClick={clone}>
372
+ <Copy size={13} /> {t("project.agent_detail.clone_btn")}
373
+ </Button>
374
+ </Tip>
375
+ );
376
+ }
377
+
203
378
  function AgentConfigForm({
204
- pid, agent, agents, onSaved, onDeleted,
379
+ pid, agent, agents, projectPath, onSaved, onDeleted, onRenamed,
205
380
  }: {
206
381
  pid: string;
207
382
  agent: AgentDetail;
208
383
  agents: AgentEntry[];
384
+ projectPath?: string;
209
385
  onSaved: () => void;
210
386
  onDeleted: () => void;
387
+ onRenamed: (newSlug: string) => void;
211
388
  }) {
212
389
  const toast = useToast();
213
- const [emoji, setEmoji] = useState(agent.emoji || "");
390
+ const [icon, setIcon] = useState(agent.icon || "");
391
+ const [name, setName] = useState(agent.name || "");
214
392
  const [type, setType] = useState(agent.type || "");
215
393
  const [area, setArea] = useState(agent.area || "");
216
394
  const [role, setRole] = useState(agent.role || "");
@@ -218,29 +396,32 @@ function AgentConfigForm({
218
396
  const [model, setModel] = useState(agent.model || "");
219
397
  const [parent, setParent] = useState(agent.parent || "");
220
398
  const [isMaster, setIsMaster] = useState(!!agent.is_master);
221
- const [skills, setSkills] = useState((agent.skills || []).join(", "));
399
+ const [skills, setSkills] = useState<string[]>(agent.skills || []);
400
+ // No declared skills ⇒ the agent inherits whatever the project enables.
401
+ const [skillDefaults, setSkillDefaults] = useState((agent.skills || []).length === 0);
222
402
  const [tools, setTools] = useState((agent.tools || []).join(", "));
223
403
  const [description, setDescription] = useState(agent.description || "");
224
- const [system, setSystem] = useState(agent.system || "");
225
404
  const [busy, setBusy] = useState(false);
226
405
  const [confirmDelete, setConfirmDelete] = useState(false);
406
+ // The prompt body is edited in its own tab; here we only report its size.
407
+ const promptLines = (agent.system || "").trim() ? (agent.system || "").trim().split("\n").length : 0;
227
408
 
228
409
  const save = async () => {
229
410
  setBusy(true);
230
411
  try {
231
412
  await Agents.update(pid, agent.slug, {
232
- emoji: emoji || null,
413
+ name: name || null,
414
+ icon: icon || null,
233
415
  type: type || null,
234
416
  area: area || null,
235
417
  role: role || null,
236
418
  autonomy: autonomy || null,
237
- model: model || null,
419
+ model: isInheritedModel(model) ? INHERIT_MODEL : model,
238
420
  parent: parent || null,
239
421
  is_master: isMaster || type === "orchestrator",
240
- skills: csv(skills),
422
+ skills: skillDefaults ? [] : skills,
241
423
  tools: csv(tools),
242
424
  description: description || null,
243
- system,
244
425
  });
245
426
  toast.success(t("project.agent_detail.update_success"));
246
427
  onSaved();
@@ -255,43 +436,96 @@ function AgentConfigForm({
255
436
  };
256
437
 
257
438
  return (
258
- <Section title={t("project.agent_detail.config_title")} description={`.apc/agents/${agent.slug}.md — ${t("agents_ui.config_def_desc")}`}>
259
- <div className="space-y-3">
260
- <div className="grid grid-cols-[80px_1fr] gap-3">
261
- <Field label={t("agents_form.emoji")}><EmojiInput value={emoji} onChange={setEmoji} /></Field>
262
- <Field label={t("project.agent_detail.type_label")}><UiSelect value={type} onChange={setType} options={typeOptions()} /></Field>
263
- </div>
264
- <AreaRoleFields pid={pid} area={area} role={role} onArea={setArea} onRole={setRole} />
265
- <Field label={t("agents_form.autonomy")} hint={t("agents_form.autonomy_hint")}>
266
- <AutonomyPicker value={autonomy} onChange={setAutonomy} />
267
- </Field>
268
- <div className="grid grid-cols-2 gap-3">
269
- <Field label={t("project.agent_detail.parent_label")}>
270
- <UiSelect
271
- value={parent}
272
- onChange={setParent}
273
- placeholder={t("project.agent_detail.none_parent")}
274
- options={[{ value: "", label: t("project.agent_detail.none_parent") }, ...agents.filter((x) => x.slug !== agent.slug).map((x) => ({ value: x.slug, label: x.slug }))]}
275
- />
276
- </Field>
277
- <Field label={t("project.agent_detail.model_label")} hint={t("project.agent_detail.model_hint")}>
278
- <Input value={model} onChange={(e) => setModel(e.target.value)} placeholder={t("project.agent_detail.model_ph")} />
279
- </Field>
280
- </div>
281
- <Field label={t("project.agent_detail.skills_label")}><Input value={skills} onChange={(e) => setSkills(e.target.value)} placeholder="skill-a, skill-b" /></Field>
282
- <ToolsPicker value={tools} onChange={setTools} />
283
- <Field label={t("project.agent_detail.bio_label")}><Textarea rows={2} value={description} onChange={(e) => setDescription(e.target.value)} /></Field>
284
- <Field label={t("project.agent_detail.system_label")} hint={t("project.agent_detail.system_hint")}>
285
- <Textarea rows={10} className="font-mono text-xs" value={system} onChange={(e) => setSystem(e.target.value)} placeholder="You are…" />
286
- </Field>
287
- <Switch checked={isMaster} onChange={setIsMaster} label={t("project.agent_detail.master_label")} />
288
-
289
- <div className="flex items-center justify-between border-t border-border pt-3">
290
- <Button variant="destructive" onClick={() => setConfirmDelete(true)}><Trash2 size={13} /> {t("project.agent_detail.delete_btn")}</Button>
291
- <Button variant="primary" loading={busy} onClick={save}><Save size={13} /> {t("project.agent_detail.save_btn")}</Button>
439
+ <div className="space-y-4">
440
+ {/* Actions sit at the top of the form so Save/Delete are reachable
441
+ without scrolling past the whole config. */}
442
+ <div className="flex items-center justify-between rounded-xl border border-border bg-card p-4">
443
+ <Button variant="destructive" onClick={() => setConfirmDelete(true)}><Trash2 size={13} /> {t("project.agent_detail.delete_btn")}</Button>
444
+ <Button variant="primary" loading={busy} onClick={save}><Save size={13} /> {t("project.agent_detail.save_btn")}</Button>
445
+ </div>
446
+
447
+ {/* Identity | behavior side by side, capabilities last. The system
448
+ prompt used to hold the right column, but it always dwarfed the rest
449
+ of the form — it moved to its own tab (?tab=prompt) with the markdown
450
+ editor, and behavior moved up into the space it left. */}
451
+ <div className="grid gap-4 lg:grid-cols-2">
452
+ <Section title={t("project.agent_detail.config_identity")} description={`.apc/agents/${agent.slug}.md — ${t("agents_ui.config_def_desc")}`}>
453
+ <div className="space-y-3">
454
+ <div className="grid grid-cols-2 gap-3">
455
+ <Field label={t("agents_form.name")} hint={t("agents_form.name_hint")}>
456
+ <Input value={name} onChange={(e) => setName(e.target.value)} placeholder={agent.slug} />
457
+ </Field>
458
+ <Field label={t("project.agent_detail.type_label")}><UiSelect value={type} onChange={setType} options={typeOptions()} /></Field>
459
+ </div>
460
+ {agent.slug !== "super-agent" && (
461
+ <SlugRenameField pid={pid} currentSlug={agent.slug} nameDraft={name} onRenamed={onRenamed} />
462
+ )}
463
+ <Field label={t("agents_form.icon")}>
464
+ <AgentIconPicker icon={icon} onIcon={setIcon} />
465
+ </Field>
466
+ <AreaRoleFields pid={pid} area={area} role={role} onArea={setArea} onRole={setRole} />
467
+ <Field label={t("project.agent_detail.bio_label")}>
468
+ <Textarea rows={3} value={description} onChange={(e) => setDescription(e.target.value)} />
469
+ </Field>
470
+ </div>
471
+ </Section>
472
+
473
+ <div className="space-y-4">
474
+ <Section title={t("project.agent_detail.config_behavior")} description={t("project.agent_detail.config_behavior_desc")}>
475
+ <div className="space-y-3">
476
+ <Field label={t("agents_form.autonomy")} hint={t("agents_form.autonomy_hint")}>
477
+ <AutonomyPicker value={autonomy} onChange={setAutonomy} />
478
+ </Field>
479
+ <Field label={t("project.agent_detail.parent_label")}>
480
+ <UiSelect
481
+ value={parent}
482
+ onChange={setParent}
483
+ placeholder={t("project.agent_detail.none_parent")}
484
+ options={[{ value: "", label: t("project.agent_detail.none_parent") }, ...agents.filter((x) => x.slug !== agent.slug).map((x) => ({ value: x.slug, label: x.slug }))]}
485
+ />
486
+ </Field>
487
+ <Field label={t("project.agent_detail.model_label")} hint={t("project.agent_detail.model_hint")}>
488
+ <AgentModelSelect value={model} onChange={setModel} />
489
+ </Field>
490
+ <Switch checked={isMaster} onChange={setIsMaster} label={t("project.agent_detail.master_label")} />
491
+ </div>
492
+ </Section>
493
+
494
+ {/* The prompt left this form for its own tab — this keeps the trail
495
+ visible from where people used to look for it. */}
496
+ <Link
497
+ to="?tab=prompt"
498
+ className="flex items-center justify-between gap-3 rounded-xl border border-border bg-card px-4 py-3 hover:border-muted-fg/50"
499
+ >
500
+ <span className="flex min-w-0 items-center gap-2">
501
+ <FileText size={14} className="shrink-0 text-muted-fg" />
502
+ <span className="truncate text-sm font-medium">{t("project.agent_detail.system_label")}</span>
503
+ <span className="shrink-0 text-xs text-muted-fg">
504
+ {promptLines ? t("project.agent_detail.prompt_lines", { n: promptLines }) : t("project.agent_detail.prompt_empty")}
505
+ </span>
506
+ </span>
507
+ <span className={`shrink-0 text-xs ${toneText.violet}`}>{t("common.open")} →</span>
508
+ </Link>
292
509
  </div>
293
510
  </div>
294
511
 
512
+ <div className="grid gap-4 lg:grid-cols-2">
513
+ <Section title={t("agents_form.skills_title")} description={t("agents_form.skills_desc")}>
514
+ <AgentSkillsPicker
515
+ value={skills}
516
+ onChange={setSkills}
517
+ projectPath={projectPath}
518
+ useDefaults={skillDefaults}
519
+ onUseDefaults={setSkillDefaults}
520
+ matchHeight={SKILLS_SCROLLER_MAX}
521
+ />
522
+ </Section>
523
+
524
+ <Section title={t("agents_ui.tools_label")} description={t("project.agent_detail.tools_hint")}>
525
+ <ToolsPicker value={tools} onChange={setTools} />
526
+ </Section>
527
+ </div>
528
+
295
529
  <ConfirmDialog
296
530
  open={confirmDelete}
297
531
  onClose={() => setConfirmDelete(false)}
@@ -300,7 +534,76 @@ function AgentConfigForm({
300
534
  description={t("project.agent_detail.delete_confirm", { slug: agent.slug })}
301
535
  confirmLabel={t("project.agent_detail.delete_btn")}
302
536
  />
303
- </Section>
537
+ </div>
538
+ );
539
+ }
540
+
541
+ // Renaming the slug is deliberately its own action, apart from "Save": the slug
542
+ // is the agent's physical key (its .apc/agents/<slug>.md, its runtime dir, the
543
+ // Parent refs and routines that point at it, and this page's URL). The server
544
+ // moves the file + dir and repoints references atomically; here we only collect
545
+ // the new slug (suggested from the name, editable), confirm — because it's an
546
+ // irreversible move — and let the parent navigate to the new URL.
547
+ function SlugRenameField({
548
+ pid, currentSlug, nameDraft, onRenamed,
549
+ }: { pid: string; currentSlug: string; nameDraft: string; onRenamed: (s: string) => void }) {
550
+ const toast = useToast();
551
+ const [draft, setDraft] = useState(currentSlug);
552
+ const [busy, setBusy] = useState(false);
553
+ const [confirm, setConfirm] = useState(false);
554
+
555
+ const suggestion = slugify(nameDraft);
556
+ const next = slugify(draft);
557
+ const invalid = !/^[a-z][a-z0-9_-]*$/.test(next);
558
+ const unchanged = next === currentSlug;
559
+
560
+ const rename = async () => {
561
+ setBusy(true);
562
+ try {
563
+ const updated = await Agents.rename(pid, currentSlug, next);
564
+ toast.success(t("project.agent_detail.rename_success", { slug: updated.slug }));
565
+ onRenamed(updated.slug);
566
+ } catch (e) { toast.error((e as Error).message); }
567
+ finally { setBusy(false); setConfirm(false); }
568
+ };
569
+
570
+ return (
571
+ <Field label={t("project.agent_detail.slug_label")} hint={t("project.agent_detail.slug_hint")}>
572
+ <div className="flex items-center gap-2">
573
+ <Input
574
+ value={draft}
575
+ onChange={(e) => setDraft(e.target.value)}
576
+ onBlur={() => setDraft(next)}
577
+ placeholder={currentSlug}
578
+ className="font-mono"
579
+ />
580
+ <Button
581
+ size="sm"
582
+ variant="secondary"
583
+ disabled={busy || invalid || unchanged}
584
+ onClick={() => setConfirm(true)}
585
+ >
586
+ <Pencil size={13} /> {t("project.agent_detail.rename_btn")}
587
+ </Button>
588
+ </div>
589
+ {suggestion && suggestion !== next && (
590
+ <button
591
+ type="button"
592
+ onClick={() => setDraft(suggestion)}
593
+ className={`mt-1 text-[11px] hover:underline ${toneText.violet}`}
594
+ >
595
+ {t("project.agent_detail.rename_from_name", { slug: suggestion })}
596
+ </button>
597
+ )}
598
+ <ConfirmDialog
599
+ open={confirm}
600
+ onClose={() => setConfirm(false)}
601
+ onConfirm={rename}
602
+ title={t("project.agent_detail.rename_btn")}
603
+ description={t("project.agent_detail.rename_confirm", { from: currentSlug, to: next })}
604
+ confirmLabel={t("project.agent_detail.rename_btn")}
605
+ />
606
+ </Field>
304
607
  );
305
608
  }
306
609
 
@@ -324,7 +627,7 @@ function MemoryEditor({ pid, slug, onSaved }: { pid: string; slug: string; onSav
324
627
  if (body.data === undefined) return null;
325
628
  const content = body.data ?? "";
326
629
  return {
327
- path: `agents/${slug}/memory.md`,
630
+ path: `~/.apx/projects/<id>/agents/${slug}/memory.md`,
328
631
  name: "memory.md",
329
632
  kind: "markdown",
330
633
  size: content.length,
@@ -348,6 +651,45 @@ function MemoryEditor({ pid, slug, onSaved }: { pid: string; slug: string; onSav
348
651
  );
349
652
  }
350
653
 
654
+ // The system prompt is the body of .apc/agents/<slug>.md, and real prompts run
655
+ // hundreds of lines — far past what a form textarea beside the identity fields
656
+ // can show. It gets its own tab and the same markdown editor as memory/docs:
657
+ // rendered preview by default, split editing, ⌘S to save.
658
+ function SystemPromptEditor({
659
+ pid, slug, system, onSaved,
660
+ }: { pid: string; slug: string; system: string; onSaved: () => void }) {
661
+ const toast = useToast();
662
+
663
+ const file = useMemo<FileContent>(() => ({
664
+ path: `.apc/agents/${slug}.md`,
665
+ name: `${slug}.md`,
666
+ kind: "markdown",
667
+ size: system.length,
668
+ modified: "",
669
+ encoding: "utf8",
670
+ content: system,
671
+ }), [slug, system]);
672
+
673
+ const onSave = async (content: string) => {
674
+ await Agents.update(pid, slug, { system: content });
675
+ toast.success(t("project.agent_detail.update_success"));
676
+ onSaved();
677
+ };
678
+
679
+ return (
680
+ <Section
681
+ title={t("project.agent_detail.system_label")}
682
+ description={t("project.agent_detail.system_hint")}
683
+ fullHeight
684
+ className="h-[70vh] min-h-[460px]"
685
+ >
686
+ <div className="flex min-h-0 flex-1 flex-col overflow-hidden rounded-lg border border-border">
687
+ <FileViewer file={file} onSave={onSave} />
688
+ </div>
689
+ </Section>
690
+ );
691
+ }
692
+
351
693
  function RecordsList({ records, loading }: { records: MessageEntry[]; loading: boolean }) {
352
694
  const sorted = useMemo(() => [...records].sort((a, b) => (b.ts || "").localeCompare(a.ts || "")), [records]);
353
695
  return (
@@ -358,7 +700,7 @@ function RecordsList({ records, loading }: { records: MessageEntry[]; loading: b
358
700
  {sorted.map((m, i) => (
359
701
  <li key={`${m.ts}-${i}`} className="flex items-start gap-2 rounded-md border border-border bg-muted/30 px-3 py-2">
360
702
  <span className="mt-0.5 shrink-0">
361
- {m.direction === "in" ? <ArrowDownLeft size={13} className="text-blue-400" /> : <ArrowUpRight size={13} className="text-emerald-400" />}
703
+ {m.direction === "in" ? <ArrowDownLeft size={13} className={toneText.blue} /> : <ArrowUpRight size={13} className={toneText.emerald} />}
362
704
  </span>
363
705
  <div className="min-w-0 flex-1">
364
706
  <div className="flex flex-wrap items-center gap-2 text-[11px] text-muted-fg">
@@ -380,7 +722,7 @@ function SleepView({ routines }: { routines: RoutineEntry[] }) {
380
722
  return (
381
723
  <Section title={t("project.agent_detail.sleep_title")} description={t("project.agent_detail.sleep_desc")}>
382
724
  <div className="rounded-lg border border-amber-500/30 bg-amber-500/5 p-4 text-sm">
383
- <div className="font-medium text-amber-400">{t("project.agent_detail.sleep_deep")}</div>
725
+ <div className={`font-medium ${toneText.amber}`}>{t("project.agent_detail.sleep_deep")}</div>
384
726
  <p className="mt-1 text-xs text-muted-fg">{t("project.agent_detail.sleep_deep_desc")}</p>
385
727
  </div>
386
728
  </Section>
@@ -426,6 +768,7 @@ function Field2({ label, value }: { label: string; value: string }) {
426
768
 
427
769
  function ToolsPicker({ value, onChange }: { value: string; onChange: (v: string) => void }) {
428
770
  const cat = useSWR("/api/tools", () => Tools.list());
771
+ const [draft, setDraft] = useState("");
429
772
  const selected = csv(value);
430
773
  const catalog = cat.data || [];
431
774
  const toggle = (name: string) => {
@@ -433,17 +776,25 @@ function ToolsPicker({ value, onChange }: { value: string; onChange: (v: string)
433
776
  if (set.has(name)) set.delete(name); else set.add(name);
434
777
  onChange([...set].join(", "));
435
778
  };
779
+ const addDraft = () => {
780
+ const name = draft.trim();
781
+ if (!name) return;
782
+ if (!selected.includes(name)) onChange([...selected, name].join(", "));
783
+ setDraft("");
784
+ };
436
785
  const custom = selected.filter((s) => !catalog.some((tool) => tool.name === s));
786
+ // The chips ARE the editor (tap to toggle) — no redundant CSV text field.
787
+ // Custom tools not in the catalog are added via the small inline input.
437
788
  return (
438
- <Field label={t("agents_ui.tools_label")} hint={t("project.agent_detail.tools_hint")}>
439
- <div className="flex flex-wrap gap-1.5">
789
+ <Field label={t("agents_ui.tools_label")}>
790
+ <div className="flex flex-wrap items-center gap-1.5">
440
791
  {catalog.map((tool) => {
441
792
  const on = selected.includes(tool.name);
442
793
  return (
443
794
  <Tip key={tool.name} content={tool.description || tool.name}>
444
795
  <button type="button" onClick={() => toggle(tool.name)}
445
796
  className={cn("rounded-md border px-2 py-0.5 font-mono text-[11px] transition-colors",
446
- on ? "border-emerald-500/50 bg-emerald-500/10 text-emerald-400" : "border-border text-muted-fg hover:text-foreground")}>
797
+ on ? toneOutline.emerald : "border-border text-muted-fg hover:text-foreground")}>
447
798
  {tool.name}
448
799
  </button>
449
800
  </Tip>
@@ -451,12 +802,39 @@ function ToolsPicker({ value, onChange }: { value: string; onChange: (v: string)
451
802
  })}
452
803
  {custom.map((s) => (
453
804
  <button key={s} type="button" onClick={() => toggle(s)}
454
- className="rounded-md border border-sky-500/50 bg-sky-500/10 px-2 py-0.5 font-mono text-[11px] text-sky-400">
805
+ className={cn("rounded-md px-2 py-0.5 font-mono text-[11px]", toneOutline.sky)}>
455
806
  {s} ✕
456
807
  </button>
457
808
  ))}
809
+ <input
810
+ value={draft}
811
+ onChange={(e) => setDraft(e.target.value)}
812
+ onKeyDown={(e) => { if (e.key === "Enter") { e.preventDefault(); addDraft(); } }}
813
+ onBlur={addDraft}
814
+ placeholder={t("project.agent_detail.tools_custom_ph")}
815
+ className="h-[23px] w-36 rounded-md border border-dashed border-border bg-transparent px-2 font-mono text-[11px] text-foreground outline-none placeholder:text-muted-fg/60 focus:border-muted-fg"
816
+ />
817
+ </div>
818
+ {/* Chip selection mirrored as CSV text so the list can be copied,
819
+ pasted or bulk-edited; both stay in sync. */}
820
+ <div className="mt-2 flex items-center gap-1.5">
821
+ <input
822
+ value={value}
823
+ onChange={(e) => onChange(e.target.value)}
824
+ placeholder={t("project.agent_detail.tools_csv_ph")}
825
+ className="h-7 flex-1 rounded-md border border-border bg-muted/30 px-2 font-mono text-[11px] text-muted-fg outline-none focus:border-muted-fg focus:text-foreground"
826
+ />
827
+ <Tip content={t("common.copy")}>
828
+ <button
829
+ type="button"
830
+ onClick={() => { void navigator.clipboard.writeText(csv(value).join(", ")); }}
831
+ aria-label={t("common.copy")}
832
+ className="flex h-7 w-7 shrink-0 items-center justify-center rounded-md border border-border text-muted-fg hover:text-foreground"
833
+ >
834
+ <Copy size={12} />
835
+ </button>
836
+ </Tip>
458
837
  </div>
459
- <Input className="mt-2" value={value} onChange={(e) => onChange(e.target.value)} placeholder={t("project.agent_detail.tools_custom_ph")} />
460
838
  </Field>
461
839
  );
462
840
  }
@@ -478,28 +856,64 @@ function shareKeyword(a: Set<string>, b: Set<string>): boolean {
478
856
  return false;
479
857
  }
480
858
 
859
+ type BrainAgentFace = {
860
+ slug: string;
861
+ emoji?: string | null;
862
+ icon?: string | null;
863
+ description?: string | null;
864
+ role?: string | null;
865
+ type?: string | null;
866
+ };
867
+
868
+ function brainAgentNode(pid: string, id: string, agent: BrainAgentFace, relation: string): BrainNode {
869
+ return {
870
+ id,
871
+ label: agent.slug,
872
+ kind: "agentlink",
873
+ role: "hub",
874
+ relation,
875
+ slug: agent.slug,
876
+ emoji: agent.emoji || undefined,
877
+ icon: agent.icon || undefined,
878
+ detail: agentPreview(agent),
879
+ href: `/p/${pid}/agents/${agent.slug}`,
880
+ editHref: `/p/${pid}/agents/${agent.slug}?tab=config`,
881
+ };
882
+ }
883
+
481
884
  function BrainTab({
482
- slug, emoji, memory, threads, tasks, routines, parent, children,
885
+ pid, slug, emoji, icon, description, role, type, memory, threads, tasks, routines, parent, children,
483
886
  }: {
887
+ pid: string;
484
888
  slug: string;
485
889
  emoji?: string;
890
+ icon?: string;
891
+ description?: string;
892
+ role?: string;
893
+ type?: string;
486
894
  memory: string;
487
895
  threads: { id: string; label: string }[];
488
896
  tasks: { id: string; label: string; detail?: string }[];
489
897
  routines: RoutineEntry[];
490
- parent: string | null;
491
- children: string[];
898
+ parent: BrainAgentFace | null;
899
+ children: BrainAgentFace[];
492
900
  }) {
493
901
  const { nodes, edges } = useMemo(() => {
494
902
  const nodes: BrainNode[] = [];
495
903
  const edges: BrainEdge[] = [];
496
904
  const CORE = "__core";
497
- nodes.push({ id: CORE, label: slug, kind: "agent", role: "core", emoji, relation: "self" });
905
+ const agentHref = `/p/${pid}/agents/${slug}`;
906
+ nodes.push({
907
+ id: CORE, label: slug, kind: "agent", role: "core", emoji, icon, relation: "self", slug,
908
+ detail: agentPreview({ description, role, type }),
909
+ href: agentHref,
910
+ editHref: `${agentHref}?tab=config`,
911
+ });
498
912
 
499
913
  // A category hub groups its items so items hang off the hub (a two-level
500
914
  // tree) instead of all wiring straight to the core.
501
- const hub = (id: string, label: string, kind: BrainNode["kind"]) => {
502
- nodes.push({ id, label, kind, role: "hub", relation: "cluster" });
915
+ const hub = (id: string, label: string, kind: BrainNode["kind"], href?: string) => {
916
+ nodes.push({ id, label, kind, role: "hub", relation: "cluster", href });
503
917
  edges.push({ source: CORE, target: id });
504
918
  };
505
919
 
@@ -508,28 +922,59 @@ function BrainTab({
508
922
  const ts = tasks.slice(0, 8);
509
923
 
510
924
  if (mem.length) {
511
- hub("hub-mem", t("agents_ui.kind_memory"), "memory");
512
- mem.forEach((f, i) => { nodes.push({ id: `m${i}`, label: f, kind: "memory", relation: "knows", detail: f }); edges.push({ source: "hub-mem", target: `m${i}` }); });
925
+ hub("hub-mem", t("agents_ui.kind_memory"), "memory", `${agentHref}?tab=memories`);
926
+ mem.forEach((f, i) => {
927
+ nodes.push({
928
+ id: `m${i}`, label: f, kind: "memory", relation: "knows", detail: f,
929
+ href: `${agentHref}?tab=memories`,
930
+ });
931
+ edges.push({ source: "hub-mem", target: `m${i}` });
932
+ });
513
933
  }
514
934
  if (th.length) {
515
- hub("hub-thread", t("agents_ui.kind_thread"), "thread");
516
- th.forEach((x) => { nodes.push({ id: `th-${x.id}`, label: x.label, kind: "thread", relation: "in_thread" }); edges.push({ source: "hub-thread", target: `th-${x.id}` }); });
935
+ hub("hub-thread", t("agents_ui.kind_thread"), "thread", `/p/${pid}/chat?agent=${slug}`);
936
+ th.forEach((x) => {
937
+ nodes.push({
938
+ id: `th-${x.id}`, label: x.label, kind: "thread", relation: "in_thread",
939
+ href: `/p/${pid}/chat?agent=${slug}&conv=${x.id}`,
940
+ });
941
+ edges.push({ source: "hub-thread", target: `th-${x.id}` });
942
+ });
517
943
  }
518
944
  if (ts.length) {
519
- hub("hub-task", t("agents_ui.kind_task"), "task");
520
- ts.forEach((x) => { nodes.push({ id: `ts-${x.id}`, label: x.label, kind: "task", relation: "handles_task", detail: x.detail }); edges.push({ source: "hub-task", target: `ts-${x.id}` }); });
945
+ hub("hub-task", t("agents_ui.kind_task"), "task", `/p/${pid}/tasks`);
946
+ ts.forEach((x) => {
947
+ nodes.push({
948
+ id: `ts-${x.id}`, label: x.label, kind: "task", relation: "handles_task",
949
+ detail: clipPreview(x.detail),
950
+ href: `/p/${pid}/tasks?task=${x.id}`,
951
+ editHref: `/p/${pid}/tasks?task=${x.id}&edit=1`,
952
+ });
953
+ edges.push({ source: "hub-task", target: `ts-${x.id}` });
954
+ });
521
955
  }
522
956
  if (routines.length) {
523
- hub("hub-routine", t("agents_ui.kind_routine"), "routine");
524
- routines.forEach((r) => { nodes.push({ id: `rt-${r.name}`, label: r.name, kind: "routine", relation: "ticks", detail: `schedule: ${r.schedule}` }); edges.push({ source: "hub-routine", target: `rt-${r.name}` }); });
957
+ hub("hub-routine", t("agents_ui.kind_routine"), "routine", `/p/${pid}/routines`);
958
+ routines.forEach((r) => {
959
+ nodes.push({
960
+ id: `rt-${r.name}`, label: r.name, kind: "routine", relation: "ticks",
961
+ detail: routinePreview(r),
962
+ href: `/p/${pid}/routines?r_id=${encodeURIComponent(r.name)}`,
963
+ editHref: `/p/${pid}/routines?r_id=${encodeURIComponent(r.name)}&edit=1`,
964
+ });
965
+ edges.push({ source: "hub-routine", target: `rt-${r.name}` });
966
+ });
525
967
  }
526
968
  if (children.length) {
527
- hub("hub-team", t("agents_ui.kind_hierarchy"), "agentlink");
528
- children.forEach((c) => { nodes.push({ id: `c-${c}`, label: c, kind: "agentlink", role: "hub", relation: "orchestrates", slug: c }); edges.push({ source: "hub-team", target: `c-${c}` }); });
969
+ hub("hub-team", t("agents_ui.kind_hierarchy"), "agentlink", `/p/${pid}/agents`);
970
+ children.forEach((c) => {
971
+ nodes.push(brainAgentNode(pid, `c-${c.slug}`, c, "orchestrates"));
972
+ edges.push({ source: "hub-team", target: `c-${c.slug}` });
973
+ });
529
974
  }
530
975
  if (parent) {
531
- nodes.push({ id: `p-${parent}`, label: parent, kind: "agentlink", role: "hub", relation: "reports_to", slug: parent });
532
- edges.push({ source: `p-${parent}`, target: CORE });
976
+ nodes.push(brainAgentNode(pid, `p-${parent.slug}`, parent, "reports_to"));
977
+ edges.push({ source: `p-${parent.slug}`, target: CORE });
533
978
  }
534
979
 
535
980
  // Cross-links: wire a task to a thread that shares a keyword (first match).
@@ -541,7 +986,7 @@ function BrainTab({
541
986
  });
542
987
 
543
988
  return { nodes, edges };
544
- }, [slug, emoji, memory, threads, tasks, routines, parent, children]);
989
+ }, [pid, slug, emoji, icon, description, role, type, memory, threads, tasks, routines, parent, children]);
545
990
 
546
991
  return (
547
992
  <Section title={t("project.agent_detail.brain_title")} description={t("project.agent_detail.brain_desc")}>