@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,11 +1,13 @@
1
1
  // YAML-ish frontmatter — one parser.
2
2
  //
3
- // Four copies existed, and they did not agree on which keys are legal:
3
+ // Six copies existed, and they did not agree on which keys are legal:
4
4
  //
5
5
  // apc/parser.js /^([a-zA-Z_-]+):/ dashes, no digits
6
6
  // agent/skills/loader /^([a-zA-Z_][a-zA-Z0-9_-]*)\s*:/ digits and dashes, strips quotes
7
7
  // core/sessions /^([a-zA-Z_]+):/ neither
8
8
  // cli/commands/session /^([a-zA-Z_]+):/ neither
9
+ // stores/sessions /^([a-zA-Z_]+):/ neither
10
+ // stores/conversations /^([a-zA-Z_]+):/ neither
9
11
  //
10
12
  // That is not cosmetic duplication: a key like `route_to_agent2` or
11
13
  // `agent-slug` parsed in some code paths and vanished in others, so the same
@@ -16,12 +18,44 @@
16
18
  // digits and dashes, quoted values are unquoted) and returns everything the
17
19
  // callers between them needed: the fields, the body, and where the body starts.
18
20
  //
19
- // Deliberately not a YAML library: the frontmatter APX writes is flat
21
+ // Still deliberately not a YAML library: the frontmatter APX *writes* is flat
20
22
  // `key: value` and staying strict about that keeps the format predictable for
21
- // the models that also read these files.
23
+ // the models that also read these files. But APX also *reads* files it did not
24
+ // write — every third-party skill dropped into ~/.apx/skills/ — and those come
25
+ // from an ecosystem where a multi-line description is written as a block
26
+ // scalar:
27
+ //
28
+ // description: |
29
+ // Rewrite text that sounds AI-generated while keeping the writer's
30
+ // facts, meaning, and voice.
31
+ //
32
+ // A flat parser reads that as the literal string "|" and drops the rest. The
33
+ // skill then lists and displays fine while the Skill Inspector embeds "|" as
34
+ // its description, so it can never be matched — a silent failure with no error
35
+ // anywhere, exactly the class of bug this file was created to end. So two
36
+ // shapes beyond flat `key: value` are understood on the way IN:
37
+ //
38
+ // • block scalars — `key: |` (literal, lines joined with \n) and `key: >`
39
+ // (folded, lines joined with a space, blank line = one \n).
40
+ // • nested maps — `metadata:` followed by indented `key: value` children,
41
+ // flattened to dotted keys (`metadata.version`).
42
+ //
43
+ // Flattening rather than nesting is deliberate: every caller (and the web's
44
+ // `frontmatter: Record<string, string>`) can keep assuming string values, so
45
+ // reading a nested map is purely additive — nothing that worked before sees a
46
+ // different shape. The parent key is still reported as "" exactly as it is
47
+ // today, so a caller that reads `fm.metadata` is unaffected.
48
+ //
49
+ // What APX writes is unchanged: `setFrontmatterField` emits flat `key: value`
50
+ // and only reaches for a block scalar when the value it is given contains a
51
+ // newline — which previously produced a corrupt file.
22
52
 
23
53
  const KEY_VALUE = /^([a-zA-Z_][a-zA-Z0-9_-]*)\s*:\s*(.*)$/;
24
54
 
55
+ // `|`, `>`, and their chomping/indent variants (`|-`, `>+`, `|2`). The
56
+ // indicators are accepted but not honoured — see readBlockScalar.
57
+ const BLOCK_SCALAR = /^([|>])[+-]?\d*$/;
58
+
25
59
  function unquote(value) {
26
60
  const v = value.trim();
27
61
  if (v.length >= 2 && ((v.startsWith('"') && v.endsWith('"')) || (v.startsWith("'") && v.endsWith("'")))) {
@@ -30,6 +64,112 @@ function unquote(value) {
30
64
  return v;
31
65
  }
32
66
 
67
+ /** Leading-whitespace width. Tabs count as one — indentation only has to be
68
+ * comparable within a single file, not universally correct. */
69
+ function indentOf(line) {
70
+ const m = line.match(/^[ \t]*/);
71
+ return m ? m[0].length : 0;
72
+ }
73
+
74
+ /**
75
+ * How far the entry that starts at `start` reaches: itself plus every
76
+ * following line indented deeper than it. A blank line belongs to the entry
77
+ * only when a deeper-indented line follows it — that keeps a paragraph break
78
+ * inside a block scalar, without swallowing the blank line an author left
79
+ * between two flat fields.
80
+ *
81
+ * @returns {number} exclusive end index; always > start.
82
+ */
83
+ function entryExtent(lines, start, end, indent) {
84
+ let last = start;
85
+ for (let i = start + 1; i < end; i++) {
86
+ const line = lines[i];
87
+ if (line.trim() === "") continue; // tentative — only kept if more follows
88
+ if (indentOf(line) <= indent) break;
89
+ last = i;
90
+ }
91
+ return last + 1;
92
+ }
93
+
94
+ /**
95
+ * Body of a block scalar: the lines in [start, end), stripped of the common
96
+ * indent established by the first non-blank one.
97
+ *
98
+ * Deviates from YAML in two places, both deliberate and both invisible for the
99
+ * frontmatter this parses: chomping indicators are ignored (trailing blank
100
+ * lines are always stripped — a trailing newline on a description would only
101
+ * surprise callers), and an explicit indent indicator (`|2`) is ignored in
102
+ * favour of the observed indent.
103
+ */
104
+ function readBlockScalar(lines, start, end, style) {
105
+ const content = [];
106
+ let blockIndent = null;
107
+ for (let i = start; i < end; i++) {
108
+ const line = lines[i];
109
+ if (line.trim() === "") { content.push(""); continue; }
110
+ const ind = indentOf(line);
111
+ if (blockIndent === null) blockIndent = ind;
112
+ content.push(line.slice(Math.min(ind, blockIndent)));
113
+ }
114
+ while (content.length && content[content.length - 1] === "") content.pop();
115
+
116
+ if (style === "|") return content.join("\n");
117
+
118
+ // Folded: a run of lines becomes one space-joined line, a blank line ends
119
+ // the run and contributes the single newline between them.
120
+ const paragraphs = [];
121
+ let run = [];
122
+ for (const line of content) {
123
+ if (line.trim() === "") {
124
+ if (run.length) { paragraphs.push(run.join(" ")); run = []; }
125
+ continue;
126
+ }
127
+ run.push(line.trim());
128
+ }
129
+ if (run.length) paragraphs.push(run.join(" "));
130
+ return paragraphs.join("\n");
131
+ }
132
+
133
+ /**
134
+ * Parse the lines of one indentation level into `fm`, recursing into nested
135
+ * maps with dotted key prefixes.
136
+ *
137
+ * `levelIndent` is fixed by the caller for the top level (0, so a stray
138
+ * indented line stays skipped exactly as it always was) and observed from the
139
+ * first child for nested levels.
140
+ */
141
+ function parseLevel(lines, start, end, prefix, levelIndent, fm) {
142
+ let indent = levelIndent;
143
+ let i = start;
144
+ while (i < end) {
145
+ const line = lines[i];
146
+ if (line.trim() === "") { i++; continue; }
147
+ const ind = indentOf(line);
148
+ if (indent === null) indent = ind;
149
+ if (ind < indent) break; // dedent — belongs to an outer level
150
+ if (ind > indent) { i++; continue; } // deeper than this level and not claimed
151
+ const m = line.slice(ind).match(KEY_VALUE);
152
+ if (!m) { i++; continue; } // not `key: value` — skipped, never fatal
153
+
154
+ const key = prefix + m[1];
155
+ const rawValue = m[2].trim();
156
+ const stop = entryExtent(lines, i, end, ind);
157
+ const block = rawValue.match(BLOCK_SCALAR);
158
+
159
+ if (block) {
160
+ fm[key] = readBlockScalar(lines, i + 1, stop, block[1]);
161
+ } else if (rawValue === "" && stop > i + 1) {
162
+ // A bare `key:` with indented lines under it: a nested map. The parent
163
+ // keeps the "" it has always had; the children arrive as dotted keys.
164
+ fm[key] = "";
165
+ parseLevel(lines, i + 1, stop, `${key}.`, null, fm);
166
+ } else {
167
+ fm[key] = unquote(m[2]);
168
+ }
169
+ i = stop;
170
+ }
171
+ }
172
+
33
173
  /**
34
174
  * Parse leading `---` frontmatter.
35
175
  *
@@ -49,10 +189,8 @@ export function parseFrontmatter(text) {
49
189
  if (end === -1) return { fm: {}, body: raw, bodyStart: 0 };
50
190
 
51
191
  const fm = {};
52
- for (const line of raw.slice(openLen, end).split("\n")) {
53
- const m = line.match(KEY_VALUE);
54
- if (m) fm[m[1]] = unquote(m[2]);
55
- }
192
+ const lines = raw.slice(openLen, end).split("\n");
193
+ parseLevel(lines, 0, lines.length, "", 0, fm);
56
194
 
57
195
  // The closing fence is followed by a newline, and authors conventionally
58
196
  // leave a blank line after it — consume both so `body` starts at content.
@@ -65,9 +203,27 @@ export function parseFrontmatterFields(text) {
65
203
  return parseFrontmatter(text).fm;
66
204
  }
67
205
 
206
+ /**
207
+ * Render one `key: value` frontmatter entry as the line(s) it occupies.
208
+ * Single-line values are emitted exactly as they always were; a value that
209
+ * contains a newline becomes a literal block scalar, because writing it flat
210
+ * produces a file that no longer parses back to the same value.
211
+ *
212
+ * @returns {string[]} one entry, one line per element.
213
+ */
214
+ export function formatFrontmatterEntry(key, value) {
215
+ const text = `${value}`;
216
+ if (!text.includes("\n")) return [`${key}: ${text}`];
217
+ return [`${key}: |`, ...text.split("\n").map((l) => (l ? ` ${l}` : ""))];
218
+ }
219
+
68
220
  /**
69
221
  * Set or replace one field in place, preserving the rest of the file byte for
70
222
  * byte. Returns the text unchanged when there is no frontmatter to edit.
223
+ *
224
+ * Replacing a field that spans several lines (a block scalar, a nested map)
225
+ * replaces the whole entry — otherwise its continuation lines would be left
226
+ * orphaned under the new value.
71
227
  */
72
228
  export function setFrontmatterField(text, field, value) {
73
229
  const raw = String(text ?? "");
@@ -77,9 +233,9 @@ export function setFrontmatterField(text, field, value) {
77
233
 
78
234
  const lines = raw.slice(4, end).split("\n");
79
235
  const idx = lines.findIndex((l) => l.match(KEY_VALUE)?.[1] === field);
80
- const entry = `${field}: ${value}`;
81
- if (idx >= 0) lines[idx] = entry;
82
- else lines.push(entry);
236
+ const entry = formatFrontmatterEntry(field, value);
237
+ if (idx >= 0) lines.splice(idx, entryExtent(lines, idx, lines.length, indentOf(lines[idx])) - idx, ...entry);
238
+ else lines.push(...entry);
83
239
 
84
240
  return `---\n${lines.join("\n")}${raw.slice(end)}`;
85
241
  }
@@ -6,66 +6,12 @@ import {
6
6
  apcAgentsDir,
7
7
  apcAgentFile,
8
8
  apcProjectFile,
9
- agentsMdFile,
10
9
  isApcProject,
11
10
  } from "./paths.js";
12
11
 
13
12
  export const SLUG_RE = /^[a-z][a-z0-9_-]*$/;
14
- const H1_RE = /^#\s+Agents\s*$/i;
15
- const H2_RE = /^##\s+(\S.*?)\s*$/;
16
- const FIELD_RE = /^-\s+\*\*([^*]+?)\*\*\s*:\s*(.*)$/;
17
- const INDENT_CONT_RE = /^\s{2,}\S/;
18
13
  const LIST_FIELDS = new Set(["Skills", "Tools"]);
19
14
 
20
- // ---------------------------------------------------------------------------
21
- // AGENTS.md parser (legacy / Codex compat source)
22
- // ---------------------------------------------------------------------------
23
-
24
- export function parseAgentsMd(text) {
25
- const stripped = text.replace(/<!--[\s\S]*?-->/g, "");
26
- const lines = stripped.split(/\r?\n/);
27
- const agents = [];
28
- let current = null;
29
- let pendingField = null;
30
- let seenH1 = false;
31
-
32
- for (const raw of lines) {
33
- const line = raw.replace(/\s+$/, "");
34
- if (H1_RE.test(line)) { seenH1 = true; continue; }
35
- const mH2 = line.match(H2_RE);
36
- if (mH2 && seenH1) {
37
- const slug = mH2[1].trim();
38
- if (SLUG_RE.test(slug)) {
39
- current = { slug, fields: {} };
40
- agents.push(current);
41
- pendingField = null;
42
- } else {
43
- current = null; pendingField = null;
44
- }
45
- continue;
46
- }
47
- if (!current) continue;
48
- const mField = line.match(FIELD_RE);
49
- if (mField) {
50
- const name = mField[1].trim();
51
- const value = mField[2].trim();
52
- current.fields[name] = LIST_FIELDS.has(name)
53
- ? value.split(",").map((s) => s.trim()).filter(Boolean)
54
- : value;
55
- pendingField = name;
56
- continue;
57
- }
58
- if (pendingField && INDENT_CONT_RE.test(raw)) {
59
- const existing = current.fields[pendingField];
60
- if (!Array.isArray(existing)) {
61
- current.fields[pendingField] = existing ? `${existing} ${raw.trim()}` : raw.trim();
62
- }
63
- continue;
64
- }
65
- if (line.trim() === "") pendingField = null;
66
- }
67
- return agents;
68
- }
69
15
 
70
16
  // ---------------------------------------------------------------------------
71
17
  // Per-agent file parser (.apc/agents/<slug>.md)
@@ -176,24 +122,39 @@ export function readVaultAgents({ includeRemoved = false } = {}) {
176
122
  return [...bySlug.values()].sort((a, b) => a.slug.localeCompare(b.slug));
177
123
  }
178
124
 
179
- // Resolve a single vault agent honoring the layered model. Returns null when
180
- // the slug is missing or tombstoned (unless includeRemoved is true).
181
- function readVaultAgent(slug, { includeRemoved = false } = {}) {
125
+ // WHERE a vault slug's definition actually lives, honoring the layered model:
126
+ // user file wins, bundled default is the fallback, a tombstoned slug resolves
127
+ // to nothing. Returns null when the slug is unusable or absent.
128
+ //
129
+ // Every caller that needs the FILE — the import tool, `apx agent import`,
130
+ // readAgents() resolving an imported slug — must come through here. Each of
131
+ // them used to build `path.join(VAULT_DIR, slug + ".md")` by hand, which sees
132
+ // ONLY the user layer: on a machine where ~/.apx/agents holds nothing (the
133
+ // normal state — the bundle is the vault most people ever use), every bundled
134
+ // agent looked missing while list_vault_agents listed it happily. Importing
135
+ // one failed with "not found in vault. Available: <the very slug you asked
136
+ // for>", and an already-imported one silently vanished from its project.
137
+ export function vaultAgentFile(slug, { includeRemoved = false } = {}) {
138
+ if (!slug || !SLUG_RE.test(slug)) return null;
182
139
  if (!includeRemoved && readVaultTombstones().has(slug)) return null;
183
140
  const userPath = path.join(VAULT_DIR, `${slug}.md`);
184
- if (fs.existsSync(userPath)) {
185
- const agent = parseAgentFile(slug, fs.readFileSync(userPath, "utf8"));
186
- const overrides = fs.existsSync(path.join(BUNDLED_VAULT_DIR, `${slug}.md`));
187
- return { ...agent, source: overrides ? "user-override" : "user" };
188
- }
141
+ if (fs.existsSync(userPath)) return userPath;
189
142
  const bundledPath = path.join(BUNDLED_VAULT_DIR, `${slug}.md`);
190
- if (fs.existsSync(bundledPath)) {
191
- const agent = parseAgentFile(slug, fs.readFileSync(bundledPath, "utf8"));
192
- return { ...agent, source: "bundled" };
193
- }
143
+ if (fs.existsSync(bundledPath)) return bundledPath;
194
144
  return null;
195
145
  }
196
146
 
147
+ // Resolve a single vault agent honoring the layered model. Returns null when
148
+ // the slug is missing or tombstoned (unless includeRemoved is true).
149
+ function readVaultAgent(slug, { includeRemoved = false } = {}) {
150
+ const file = vaultAgentFile(slug, { includeRemoved });
151
+ if (!file) return null;
152
+ const agent = parseAgentFile(slug, fs.readFileSync(file, "utf8"));
153
+ if (path.dirname(file) !== VAULT_DIR) return { ...agent, source: "bundled" };
154
+ const overrides = fs.existsSync(path.join(BUNDLED_VAULT_DIR, `${slug}.md`));
155
+ return { ...agent, source: overrides ? "user-override" : "user" };
156
+ }
157
+
197
158
  // Resolve a single agent for a project: local file → vault (layered) → null.
198
159
  export function resolveAgent(root, slug) {
199
160
  const localPath = apcAgentFile(root, slug);
@@ -219,7 +180,7 @@ export function importedVaultSlugs(root) {
219
180
  // Resolution order:
220
181
  // 1. .apc/agents/<slug>.md (local — overrides everything)
221
182
  // 2. ~/.apx/agents/<slug>.md (vault — for imported slugs)
222
- // 3. Legacy hand-written AGENTS.md (not auto-generated)
183
+ // AGENTS.md is the project's startup-rules file, never an agent registry.
223
184
  export function readAgents(root) {
224
185
  const fromFiles = readAgentsFromDir(root).map((a) => ({ ...a, source: "local" }));
225
186
  const localSlugs = new Set(fromFiles.map((a) => a.slug));
@@ -229,27 +190,16 @@ export function readAgents(root) {
229
190
  const vaultAgents = imported
230
191
  .filter((slug) => !localSlugs.has(slug))
231
192
  .map((slug) => {
232
- const vaultPath = path.join(VAULT_DIR, `${slug}.md`);
233
- if (!fs.existsSync(vaultPath)) return null;
193
+ // includeRemoved: hiding a template from the vault listing must not
194
+ // delete the agent out of a project that already imported it.
195
+ const vaultPath = vaultAgentFile(slug, { includeRemoved: true });
196
+ if (!vaultPath) return null;
234
197
  const agent = parseAgentFile(slug, fs.readFileSync(vaultPath, "utf8"));
235
198
  return { ...agent, source: "vault" };
236
199
  })
237
200
  .filter(Boolean);
238
201
 
239
- const all = [...fromFiles, ...vaultAgents];
240
- const allSlugs = new Set(all.map((a) => a.slug));
241
-
242
- const agentsMdPath = agentsMdFile(root);
243
- if (!fs.existsSync(agentsMdPath)) return all;
244
-
245
- const mdText = fs.readFileSync(agentsMdPath, "utf8");
246
- if (mdText.includes("Auto-generated from .apc/agents/")) return all;
247
-
248
- // Legacy hand-written AGENTS.md
249
- const legacy = parseAgentsMd(mdText)
250
- .filter((a) => !allSlugs.has(a.slug))
251
- .map((a) => ({ ...a, source: "legacy" }));
252
- return [...all, ...legacy];
202
+ return [...fromFiles, ...vaultAgents];
253
203
  }
254
204
 
255
205
  // ---------------------------------------------------------------------------
@@ -44,10 +44,6 @@ export function apcAgentFile(root, slug) {
44
44
  return path.join(root, APC_DIR, APC_AGENTS_DIR, `${slug}.md`);
45
45
  }
46
46
 
47
- export function apcAgentMemoryFile(root, slug) {
48
- return path.join(root, APC_DIR, APC_AGENTS_DIR, slug, "memory.md");
49
- }
50
-
51
47
  export function apcRemovedFile(root) {
52
48
  return path.join(root, APC_DIR, APC_AGENTS_DIR, APC_REMOVED_FILE);
53
49
  }
@@ -68,8 +64,10 @@ export function apcNotesDir(root) {
68
64
  return path.join(root, APC_DIR, APC_NOTES_DIR);
69
65
  }
70
66
 
71
- // Project-level memory (super-agent / project-wide), distinct from the
72
- // per-agent memory.md that lives under .apc/agents/<slug>/.
67
+ // Project-level memory: curated, committed, written by a person. This is the
68
+ // ONLY memory.md that belongs inside a repo. A single agent's memory is runtime
69
+ // state and lives in ~/.apx/projects/<apx_id>/agents/<slug>/memory.md — see
70
+ // core/agent/memory.js. There is deliberately no builder for it here.
73
71
  export function apcMemoryFile(root) {
74
72
  return path.join(root, APC_DIR, APC_PROJECT_MEMORY_FILE);
75
73
  }
@@ -0,0 +1,44 @@
1
+ // A project's CURATED memory — `<repo>/.apc/memory.md`. Committed.
2
+ //
3
+ // What the PROJECT knows and the team may read: what this repo is, who owns it,
4
+ // the decisions that outlive a session. Distinct from what one agent knows
5
+ // (per-agent memory.md), from what the super-agent knows everywhere
6
+ // (~/.apx/memory.md), and — the distinction that matters most here — from the
7
+ // project's LOCAL memory (core/stores/project-memory.js), which is never
8
+ // committed and is where the agent actually writes.
9
+ //
10
+ // NOTHING AUTOMATIC WRITES THIS FILE. That is the rule, and it is APC's:
11
+ // `.apc/` memory is "only for curated project facts safe for the team", while
12
+ // private runtime memory belongs in the runtime's own store because it "often
13
+ // contains sensitive prompts, credentials pasted by mistake, customer data".
14
+ // A file that git will carry forever is written by a person who read it first.
15
+ // The writer here is the Memories editor (a human pressing Save) and the
16
+ // dangerous-gated file tools, which ask before they touch a repo.
17
+ //
18
+ // It still has an automatic READER: the RAG indexer scopes it to `project:<id>`,
19
+ // so curated facts come back as context without being re-typed.
20
+ import fs from "node:fs";
21
+ import { apcDir, apcMemoryFile } from "./paths.js";
22
+
23
+ export { apcMemoryFile as projectMemoryPath };
24
+
25
+ /** Read the memory body. "" when the file doesn't exist. Never throws. */
26
+ export function readProjectMemory(root) {
27
+ try {
28
+ return fs.readFileSync(apcMemoryFile(root), "utf8");
29
+ } catch {
30
+ return "";
31
+ }
32
+ }
33
+
34
+ /**
35
+ * Replace the whole body — the Memories editor's Save, and the only writer.
36
+ * There is deliberately no append helper here: an appender is what an automatic
37
+ * caller reaches for, and this file is not written automatically.
38
+ */
39
+ export function writeProjectMemory(root, body) {
40
+ const file = apcMemoryFile(root);
41
+ fs.mkdirSync(apcDir(root), { recursive: true });
42
+ fs.writeFileSync(file, body);
43
+ return { path: file, bytes: Buffer.byteLength(body, "utf8") };
44
+ }
@@ -12,9 +12,42 @@ export function projectMeta(projects, entry) {
12
12
  };
13
13
  }
14
14
 
15
+ /**
16
+ * The registry, scoped to the project a turn BELONGS to.
17
+ *
18
+ * `resolveProject` used to read an omitted `project` argument as "the default
19
+ * project", which is right for the super-agent (it orchestrates across all of
20
+ * them) and wrong for anyone who lives in one. A routine run by Magui in Appsi
21
+ * called `run_shell tail work/marketing/magui/brain.md` and got
22
+ * `~/.apx/projects/default` — her own notes, one directory over, reported as
23
+ * "No such file or directory". Every scheduled run since had been working from
24
+ * an empty memory and writing its entry where nobody reads it.
25
+ *
26
+ * Scoping at the registry — rather than threading a project through all 30-odd
27
+ * handlers — means a tool that takes an optional `project` keeps its exact
28
+ * signature and simply defaults to the right one. An EXPLICIT argument still
29
+ * wins, `project: "default"` still means the default project, and an unscoped
30
+ * registry behaves exactly as before.
31
+ *
32
+ * The wrapper delegates through the prototype chain: the registry keeps one set
33
+ * of entries and one cache, and a scope is a view of it, never a copy.
34
+ */
35
+ export function scopeProjects(projects, projectId) {
36
+ if (!projects || projectId === undefined || projectId === null) return projects;
37
+ const self = projects.get?.(projectId);
38
+ if (!self) return projects;
39
+ return Object.assign(Object.create(projects), { current: () => self });
40
+ }
41
+
15
42
  export function resolveProject(projects, target, { allowMulti = false } = {}) {
16
43
  if (target === undefined || target === null || target === "") {
17
44
  if (allowMulti) return null;
45
+ // Whose turn this is, when the caller said (see `scopeProjects`). Ahead of
46
+ // the default project, because "the project I belong to" is what an agent
47
+ // means by an unqualified path — and behind an explicit argument, which is
48
+ // handled below and still addresses any project by id, name or path.
49
+ const scoped = projects.current?.();
50
+ if (scoped) return scoped;
18
51
  const defaultProject = projects.get(0);
19
52
  if (defaultProject) return defaultProject;
20
53
  const all = projects.list();
@@ -10,6 +10,7 @@ import {
10
10
  writeVaultTombstones,
11
11
  } from "./parser.js";
12
12
  import { readApcContextSkill } from "./skill-sync.js";
13
+ import { formatFrontmatterEntry } from "./frontmatter.js";
13
14
  import { nowIso } from "../util/time.js";
14
15
  import {
15
16
  apcDir,
@@ -137,7 +138,7 @@ export const IDE_TARGETS = [
137
138
  // Global targets (absolute paths, use ~/<dir>/skills/<slug>/SKILL.md format).
138
139
  // These dirs are read by Claude Code, Cursor (compat), and tools adopting the skills.sh spec.
139
140
  const GLOBAL_SKILL_DIRS = [
140
- path.join(os.homedir(), ".claude", "skills"), // Claude Code + Cursor legacy compat
141
+ path.join(os.homedir(), ".claude", "skills"), // Claude Code (Cursor reads it too)
141
142
  path.join(os.homedir(), ".cursor", "skills"), // Cursor primary global path
142
143
  path.join(os.homedir(), ".codex", "skills"), // Codex (OpenAI)
143
144
  path.join(os.homedir(), ".agents", "skills"), // Antigravity/other skills.sh adopters
@@ -215,10 +216,11 @@ export function listEngineSkills() {
215
216
  return listBundledSkills();
216
217
  }
217
218
 
218
- // Legacy slugs APX used to ship to global dirs but no longer does — exposed so
219
- // the CLI can report what `installGlobalSkills` will prune.
220
- export function listLegacyPruneSlugs() {
221
- return [...PRUNE_LEGACY_SLUGS];
219
+ // Slugs APX used to ship to global dirs but no longer does — exposed so the
220
+ // CLI can report what `installGlobalSkills` will prune. Add to this list every
221
+ // time a slug leaves the published set, or stale copies linger forever.
222
+ export function listRetiredSkillSlugs() {
223
+ return [...RETIRED_SKILL_SLUGS];
222
224
  }
223
225
 
224
226
  function discoverBundledSkills() {
@@ -248,12 +250,12 @@ function discoverBundledSkills() {
248
250
  // compatibility with `apx skills sync --include-…`; the slim set has no tiers.
249
251
  //
250
252
  // Pruning: removes stale APX-shipped slugs that are no longer in the engine
251
- // set (the catalog of slugs APX has ever published, see PRUNE_LEGACY_SLUGS).
253
+ // set (the catalog of slugs APX has ever published, see RETIRED_SKILL_SLUGS).
252
254
  // Skills the user installed themselves are NOT touched.
253
255
  //
254
256
  // Returns an array of { dir, skill, file, status, scope }.
255
257
  // status ∈ {created, updated, unchanged, pruned}
256
- const PRUNE_LEGACY_SLUGS = [
258
+ const RETIRED_SKILL_SLUGS = [
257
259
  "apx-agency-agents",
258
260
  "apx-agent",
259
261
  "apx-mcp-builder",
@@ -298,13 +300,13 @@ export function installGlobalSkills({
298
300
  results.push({ dir: base, skill: slug, file: dest, status: existed ? "updated" : "created", scope: "engine" });
299
301
  }
300
302
  if (prune) {
301
- for (const slug of PRUNE_LEGACY_SLUGS) {
303
+ for (const slug of RETIRED_SKILL_SLUGS) {
302
304
  if (wantedSlugs.has(slug)) continue;
303
305
  const dest = path.join(base, slug, "SKILL.md");
304
306
  if (!fs.existsSync(dest)) continue;
305
307
  fs.unlinkSync(dest);
306
308
  try { fs.rmdirSync(path.dirname(dest)); } catch {}
307
- results.push({ dir: base, skill: slug, file: dest, status: "pruned", scope: "legacy" });
309
+ results.push({ dir: base, skill: slug, file: dest, status: "pruned", scope: "retired" });
308
310
  }
309
311
  }
310
312
  }
@@ -339,7 +341,7 @@ const AGENTS_MD_TEMPLATE = `# AGENTS.md
339
341
  const APC_GITIGNORE = `# APC repository-safe context only.
340
342
  # Runtime state belongs in ~/.apx/projects/<id>/, not in .apc/.
341
343
 
342
- # Legacy per-agent runtime dirs (agent definitions are flat: agents/<slug>.md)
344
+ # Per-agent runtime dirs (agent definitions are flat: agents/<slug>.md)
343
345
  agents/*/
344
346
 
345
347
  # Runtime sessions / conversations / messages
@@ -500,14 +502,14 @@ export function ensureAgentDir(root, _slug) {
500
502
  export function writeAgentFile(root, slug, fields, body = "") {
501
503
  const dest = apcAgentFile(root, slug);
502
504
  const lines = ["---"];
503
- const order = ["role", "model", "language", "description", "skills", "tools"];
505
+ const order = ["name", "role", "model", "language", "description", "skills", "tools"];
504
506
  const written = new Set();
505
507
  for (const key of order) {
506
508
  const titleKey = key.charAt(0).toUpperCase() + key.slice(1);
507
509
  const v = fields[titleKey] ?? fields[key];
508
510
  if (v === undefined || v === null || v === "") continue;
509
511
  const value = Array.isArray(v) ? v.join(", ") : v;
510
- lines.push(`${key}: ${value}`);
512
+ lines.push(...formatFrontmatterEntry(key, value));
511
513
  written.add(titleKey);
512
514
  }
513
515
  // Any extra fields not in the ordered list
@@ -515,7 +517,7 @@ export function writeAgentFile(root, slug, fields, body = "") {
515
517
  const titleKey = k.charAt(0).toUpperCase() + k.slice(1);
516
518
  if (written.has(titleKey) || v === undefined || v === null || v === "") continue;
517
519
  const value = Array.isArray(v) ? v.join(", ") : v;
518
- lines.push(`${k.toLowerCase()}: ${value}`);
520
+ lines.push(...formatFrontmatterEntry(k.toLowerCase(), value));
519
521
  }
520
522
  lines.push("---");
521
523
  if (body) lines.push("", body);
@@ -527,19 +529,19 @@ export function writeVaultAgentFile(slug, fields, body = "") {
527
529
  fs.mkdirSync(VAULT_DIR, { recursive: true });
528
530
  const dest = path.join(VAULT_DIR, `${slug}.md`);
529
531
  const lines = ["---"];
530
- const order = ["role", "model", "language", "description", "skills", "tools"];
532
+ const order = ["name", "role", "model", "language", "description", "skills", "tools"];
531
533
  const written = new Set();
532
534
  for (const key of order) {
533
535
  const titleKey = key.charAt(0).toUpperCase() + key.slice(1);
534
536
  const v = fields[titleKey] ?? fields[key];
535
537
  if (v === undefined || v === null || v === "") continue;
536
- lines.push(`${key}: ${Array.isArray(v) ? v.join(", ") : v}`);
538
+ lines.push(...formatFrontmatterEntry(key, Array.isArray(v) ? v.join(", ") : v));
537
539
  written.add(titleKey);
538
540
  }
539
541
  for (const [k, v] of Object.entries(fields)) {
540
542
  const titleKey = k.charAt(0).toUpperCase() + k.slice(1);
541
543
  if (written.has(titleKey) || v === undefined || v === null || v === "") continue;
542
- lines.push(`${k.toLowerCase()}: ${Array.isArray(v) ? v.join(", ") : v}`);
544
+ lines.push(...formatFrontmatterEntry(k.toLowerCase(), Array.isArray(v) ? v.join(", ") : v));
543
545
  }
544
546
  lines.push("---");
545
547
  if (body) lines.push("", body);
@@ -595,6 +597,24 @@ export function addImportedAgent(root, slug) {
595
597
  fs.writeFileSync(p, JSON.stringify(cfg, null, 2) + "\n");
596
598
  }
597
599
 
600
+ // Drop a slug from the project's agents.imported list. The counterpart of
601
+ // addImportedAgent, and the reason a rename does not leave a ghost: an imported
602
+ // agent has NO local file (readAgents resolves it from the vault by that list),
603
+ // so renaming it writes the new slug locally and the old one keeps resolving
604
+ // from the vault — the same agent showing up twice in the roster, one card with
605
+ // the chats and one with the history. Returns whether anything was removed;
606
+ // a project with no project.json or no list is a no-op, not an error.
607
+ export function removeImportedAgent(root, slug) {
608
+ const p = apcProjectFile(root);
609
+ if (!fs.existsSync(p)) return false;
610
+ const cfg = readJson(p, null);
611
+ const imported = cfg?.agents?.imported;
612
+ if (!Array.isArray(imported) || !imported.includes(slug)) return false;
613
+ cfg.agents.imported = imported.filter((s) => s !== slug);
614
+ fs.writeFileSync(p, JSON.stringify(cfg, null, 2) + "\n");
615
+ return true;
616
+ }
617
+
598
618
  // NOTE: AGENTS.md is created once at `apx init` (see AGENTS_MD_TEMPLATE) and is
599
619
  // thereafter owned by the user — APX never regenerates it. Agents live in
600
620
  // `.apc/agents/<slug>.md` (read by parser.js readAgents); they are NOT listed