@vellumai/assistant 0.8.1 → 0.8.3

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 (630) hide show
  1. package/ARCHITECTURE.md +13 -19
  2. package/Dockerfile +75 -1
  3. package/bun.lock +11 -1
  4. package/docker-entrypoint.sh +17 -0
  5. package/docker-init-apt-root.sh +167 -0
  6. package/docker-kata-apt-env.sh +39 -0
  7. package/docs/plugins.md +88 -47
  8. package/docs/skills.md +9 -7
  9. package/examples/plugins/echo/README.md +27 -27
  10. package/examples/plugins/echo/package.json +3 -0
  11. package/examples/plugins/echo/register.ts +31 -31
  12. package/node_modules/@vellumai/slack-text/src/index.test.ts +114 -14
  13. package/node_modules/@vellumai/slack-text/src/index.ts +82 -18
  14. package/openapi.yaml +642 -5
  15. package/package.json +3 -1
  16. package/scripts/generate-openapi.ts +83 -10
  17. package/scripts/sync-llm-catalog.ts +2 -2
  18. package/scripts/sync-web-search-catalog.ts +47 -25
  19. package/src/__tests__/agent-image-optimize.test.ts +11 -3
  20. package/src/__tests__/agent-loop-exit-reason.test.ts +272 -0
  21. package/src/__tests__/agent-loop-provider-error-recording.test.ts +195 -0
  22. package/src/__tests__/agent-wake-disk-pressure-callsite.test.ts +131 -0
  23. package/src/__tests__/anthropic-provider.test.ts +45 -0
  24. package/src/__tests__/app-builder-tool-scripts.test.ts +9 -3
  25. package/src/__tests__/app-executors.test.ts +220 -4
  26. package/src/__tests__/auto-analysis-end-to-end.test.ts +35 -0
  27. package/src/__tests__/bundled-asset.test.ts +6 -6
  28. package/src/__tests__/channel-availability-routes.test.ts +206 -0
  29. package/src/__tests__/channel-delivery-store.test.ts +289 -1
  30. package/src/__tests__/circuit-breaker-pipeline.test.ts +0 -1
  31. package/src/__tests__/clawhub.test.ts +75 -16
  32. package/src/__tests__/compactor-tail-resolution.test.ts +147 -0
  33. package/src/__tests__/config-get-vision-flag.test.ts +136 -0
  34. package/src/__tests__/config-loader-backfill.test.ts +115 -18
  35. package/src/__tests__/config-schema.test.ts +21 -0
  36. package/src/__tests__/config-set-route.test.ts +80 -0
  37. package/src/__tests__/config-sounds-sync.test.ts +97 -0
  38. package/src/__tests__/config-watcher-skill-reseed.test.ts +453 -0
  39. package/src/__tests__/context-search-conversations-source.test.ts +117 -2
  40. package/src/__tests__/context-search-memory-v2-source.test.ts +0 -1
  41. package/src/__tests__/context-search-workspace-source.test.ts +7 -0
  42. package/src/__tests__/context-token-estimator.test.ts +31 -65
  43. package/src/__tests__/conversation-abort-tool-results.test.ts +4 -1
  44. package/src/__tests__/conversation-agent-loop-inference-profile.test.ts +1 -0
  45. package/src/__tests__/conversation-agent-loop-overflow.test.ts +92 -92
  46. package/src/__tests__/conversation-agent-loop.test.ts +59 -1
  47. package/src/__tests__/conversation-error.test.ts +42 -3
  48. package/src/__tests__/conversation-fork-crud.test.ts +82 -0
  49. package/src/__tests__/conversation-inference-profile-route.test.ts +40 -4
  50. package/src/__tests__/conversation-lifecycle.test.ts +173 -0
  51. package/src/__tests__/conversation-media-retry.test.ts +19 -8
  52. package/src/__tests__/conversation-message-sync-tags.test.ts +97 -0
  53. package/src/__tests__/conversation-pairing.test.ts +54 -0
  54. package/src/__tests__/conversation-process-callsite.test.ts +4 -1
  55. package/src/__tests__/conversation-provider-retry-repair.test.ts +5 -1
  56. package/src/__tests__/conversation-queue.test.ts +4 -1
  57. package/src/__tests__/conversation-runtime-assembly.test.ts +102 -13
  58. package/src/__tests__/conversation-slash-queue.test.ts +59 -1
  59. package/src/__tests__/conversation-slash-unknown.test.ts +4 -1
  60. package/src/__tests__/conversation-surfaces-table-action.test.ts +360 -0
  61. package/src/__tests__/conversation-sync-tags.test.ts +235 -0
  62. package/src/__tests__/conversation-workspace-injection.test.ts +5 -1
  63. package/src/__tests__/conversation-workspace-tool-tracking.test.ts +5 -1
  64. package/src/__tests__/credential-security-invariants.test.ts +3 -2
  65. package/src/__tests__/date-context.test.ts +45 -0
  66. package/src/__tests__/db-slack-external-content-normalization.test.ts +301 -0
  67. package/src/__tests__/delete-managed-skill-tool.test.ts +55 -13
  68. package/src/__tests__/disk-pressure-tools.test.ts +1 -0
  69. package/src/__tests__/dm-backfill.test.ts +121 -10
  70. package/src/__tests__/document-tool-security.test.ts +258 -0
  71. package/src/__tests__/dynamic-skill-workflow-prompt.test.ts +0 -1
  72. package/src/__tests__/edit-propagation.test.ts +33 -0
  73. package/src/__tests__/empty-response-pipeline.test.ts +0 -4
  74. package/src/__tests__/external-plugin-loader.test.ts +151 -55
  75. package/src/__tests__/filing-service.test.ts +140 -0
  76. package/src/__tests__/get-skill-detail-audit.test.ts +0 -4
  77. package/src/__tests__/guardian-action-no-hardcoded-copy.test.ts +0 -1
  78. package/src/__tests__/guardian-dispatch.test.ts +1 -0
  79. package/src/__tests__/handlers-skills-memory-v2-reseed.test.ts +43 -62
  80. package/src/__tests__/heartbeat-service.test.ts +24 -164
  81. package/src/__tests__/helpers/channel-test-adapter.ts +0 -2
  82. package/src/__tests__/helpers/tar-fixtures.ts +39 -0
  83. package/src/__tests__/helpers/wait-for.ts +21 -0
  84. package/src/__tests__/history-repair-pipeline.test.ts +0 -3
  85. package/src/__tests__/history-repair.test.ts +73 -0
  86. package/src/__tests__/host-app-control-proxy.test.ts +507 -10
  87. package/src/__tests__/host-proxy-preactivation.test.ts +200 -13
  88. package/src/__tests__/image-credentials.test.ts +1 -1
  89. package/src/__tests__/inbound-slack-persistence.test.ts +2 -0
  90. package/src/__tests__/inference-no-mode-boot-e2e.test.ts +1 -1
  91. package/src/__tests__/inference-profile-reaper.test.ts +4 -2
  92. package/src/__tests__/inference-profile-session-handler.test.ts +18 -6
  93. package/src/__tests__/inference-profile-session-ipc.test.ts +17 -5
  94. package/src/__tests__/injector-background-turn.test.ts +153 -0
  95. package/src/__tests__/injector-chain.test.ts +15 -8
  96. package/src/__tests__/install-skill-routing.test.ts +155 -37
  97. package/src/__tests__/lifecycle-memory-v2-seed.test.ts +99 -3
  98. package/src/__tests__/list-messages-page-latest.test.ts +55 -0
  99. package/src/__tests__/llm-call-pipeline.test.ts +0 -3
  100. package/src/__tests__/llm-callsite-catalog.test.ts +25 -0
  101. package/src/__tests__/llm-catalog-parity.test.ts +58 -13
  102. package/src/__tests__/llm-request-log-agent-loop-exit-reason.test.ts +116 -0
  103. package/src/__tests__/llm-request-log-error-payload.test.ts +138 -0
  104. package/src/__tests__/llm-request-log-source-clickhouse.test.ts +36 -0
  105. package/src/__tests__/llm-request-log-source-factory.test.ts +29 -53
  106. package/src/__tests__/llm-resolver.test.ts +255 -2
  107. package/src/__tests__/llm-usage-store.test.ts +114 -0
  108. package/src/__tests__/managed-profile-guard.test.ts +41 -29
  109. package/src/__tests__/managed-skill-lifecycle.test.ts +109 -18
  110. package/src/__tests__/managed-store.test.ts +84 -192
  111. package/src/__tests__/media-generate-image.test.ts +1 -1
  112. package/src/__tests__/memory-retrieval-pipeline.test.ts +0 -2
  113. package/src/__tests__/messages-after-tiebreaker.test.ts +122 -0
  114. package/src/__tests__/notification-decision-fallback.test.ts +0 -91
  115. package/src/__tests__/notification-decision-strategy.test.ts +14 -31
  116. package/src/__tests__/notification-deep-link.test.ts +15 -0
  117. package/src/__tests__/notification-guardian-path.test.ts +1 -2
  118. package/src/__tests__/notification-platform-adapter.test.ts +5 -4
  119. package/src/__tests__/notification-telegram-adapter.test.ts +1 -0
  120. package/src/__tests__/notification-vellum-adapter.test.ts +113 -0
  121. package/src/__tests__/oauth-commands-routes.test.ts +168 -16
  122. package/src/__tests__/oauth-provider-profiles.test.ts +9 -0
  123. package/src/__tests__/openai-provider.test.ts +242 -3
  124. package/src/__tests__/openai-responses-cutover-guard.test.ts +17 -9
  125. package/src/__tests__/openrouter-provider-only.test.ts +51 -3
  126. package/src/__tests__/openrouter-token-estimation.test.ts +34 -25
  127. package/src/__tests__/overflow-reduce-pipeline.test.ts +0 -2
  128. package/src/__tests__/persistence-pipeline.test.ts +0 -2
  129. package/src/__tests__/{managed-proxy-context.test.ts → platform-proxy-context.test.ts} +7 -2
  130. package/src/__tests__/platform.test.ts +2 -0
  131. package/src/__tests__/plugin-api-shim.test.ts +125 -0
  132. package/src/__tests__/plugin-bootstrap.test.ts +10 -36
  133. package/src/__tests__/plugin-external-api.test.ts +68 -0
  134. package/src/__tests__/plugin-registry.test.ts +0 -77
  135. package/src/__tests__/plugin-route-contribution.test.ts +0 -1
  136. package/src/__tests__/plugin-skill-contribution.test.ts +0 -2
  137. package/src/__tests__/plugin-tool-contribution.test.ts +16 -15
  138. package/src/__tests__/plugin-types.test.ts +3 -13
  139. package/src/__tests__/process-message-background-slack.test.ts +8 -1
  140. package/src/__tests__/process-message-display-content.test.ts +421 -0
  141. package/src/__tests__/provider-catalog-visibility.test.ts +158 -0
  142. package/src/__tests__/provider-error-scenarios.test.ts +111 -0
  143. package/src/__tests__/{provider-managed-proxy-integration.test.ts → provider-platform-proxy-integration.test.ts} +33 -31
  144. package/src/__tests__/scaffold-managed-skill-tool.test.ts +65 -13
  145. package/src/__tests__/schedule-routes.test.ts +50 -3
  146. package/src/__tests__/schedule-store.test.ts +94 -0
  147. package/src/__tests__/scheduler-reuse-conversation.test.ts +54 -7
  148. package/src/__tests__/schema-transforms.test.ts +20 -0
  149. package/src/__tests__/search-skills-unified.test.ts +0 -5
  150. package/src/__tests__/{secret-routes-managed-proxy.test.ts → secret-routes-platform-proxy.test.ts} +1 -1
  151. package/src/__tests__/server-history-render.test.ts +43 -0
  152. package/src/__tests__/skill-load-feature-flag.test.ts +0 -12
  153. package/src/__tests__/skill-load-tool.test.ts +27 -89
  154. package/src/__tests__/skill-memory.test.ts +23 -3
  155. package/src/__tests__/skills-file-content-endpoint.test.ts +9 -38
  156. package/src/__tests__/skills-files-catalog-fallback.test.ts +0 -3
  157. package/src/__tests__/skills-install-extract.test.ts +49 -38
  158. package/src/__tests__/skills-install-staging.test.ts +159 -0
  159. package/src/__tests__/skills-uninstall.test.ts +9 -41
  160. package/src/__tests__/skills.test.ts +51 -58
  161. package/src/__tests__/slack-channel-config.test.ts +9 -0
  162. package/src/__tests__/subagent-tool-filtering.test.ts +50 -0
  163. package/src/__tests__/system-prompt.test.ts +670 -63
  164. package/src/__tests__/terminal-tools.test.ts +28 -1
  165. package/src/__tests__/thread-backfill.test.ts +557 -27
  166. package/src/__tests__/title-generate-pipeline.test.ts +0 -13
  167. package/src/__tests__/token-estimate-pipeline.test.ts +0 -3
  168. package/src/__tests__/tool-error-pipeline.test.ts +0 -3
  169. package/src/__tests__/tool-execute-pipeline.test.ts +0 -5
  170. package/src/__tests__/tool-executor-lifecycle-events.test.ts +1 -1
  171. package/src/__tests__/tool-executor.test.ts +16 -4
  172. package/src/__tests__/tool-result-truncate-pipeline.test.ts +0 -12
  173. package/src/__tests__/turn-events-store.test.ts +256 -0
  174. package/src/__tests__/twilio-routes.test.ts +4 -0
  175. package/src/__tests__/user-plugin-loader.test.ts +0 -7
  176. package/src/__tests__/voice-session-bridge.test.ts +198 -0
  177. package/src/__tests__/web-search-catalog-parity.test.ts +32 -10
  178. package/src/__tests__/workspace-migration-057-repair-stale-gemini-model-ids.test.ts +115 -3
  179. package/src/__tests__/workspace-migration-072-seed-reply-suggestion-callsite.test.ts +50 -0
  180. package/src/__tests__/workspace-migration-073-repair-recall-callsite-empty-profile.test.ts +153 -0
  181. package/src/__tests__/workspace-migration-085-memory-v2-bm25-b-reembed-disabled-v2-pages.test.ts +220 -0
  182. package/src/__tests__/workspace-migration-086-revert-stale-gemini-mis-rewrites.test.ts +269 -0
  183. package/src/__tests__/workspace-migration-087-memory-router-balanced-profile.test.ts +228 -0
  184. package/src/__tests__/workspace-migration-remove-legacy-skills-index.test.ts +309 -0
  185. package/src/__tests__/workspace-migrations-runner.test.ts +111 -3
  186. package/src/a2a/__tests__/agent-card.test.ts +98 -0
  187. package/src/a2a/__tests__/e2e-a2a-channel.test.ts +597 -0
  188. package/src/a2a/__tests__/protocol-helpers.test.ts +113 -0
  189. package/src/a2a/__tests__/task-store.test.ts +246 -0
  190. package/src/a2a/agent-card.ts +58 -0
  191. package/src/a2a/feature-gate.ts +8 -0
  192. package/src/a2a/protocol-constants.ts +21 -0
  193. package/src/a2a/protocol-errors.ts +50 -0
  194. package/src/a2a/protocol-types.ts +162 -0
  195. package/src/a2a/task-store.ts +168 -0
  196. package/src/acp/resolve-agent.ts +1 -1
  197. package/src/agent/image-optimize.ts +13 -5
  198. package/src/agent/loop.ts +167 -18
  199. package/src/calls/voice-session-bridge.ts +61 -42
  200. package/src/channels/config.ts +9 -0
  201. package/src/channels/types.ts +122 -0
  202. package/src/cli/__tests__/unknown-command.test.ts +24 -0
  203. package/src/cli/commands/__tests__/changelog.test.ts +304 -319
  204. package/src/cli/{__tests__ → commands/__tests__}/notifications.test.ts +201 -28
  205. package/src/cli/commands/__tests__/schedules.test.ts +960 -0
  206. package/src/cli/commands/changelog.ts +106 -42
  207. package/src/cli/commands/conversations.ts +102 -17
  208. package/src/cli/commands/default-action.ts +10 -53
  209. package/src/cli/commands/notifications.ts +388 -346
  210. package/src/cli/commands/plugins.ts +252 -0
  211. package/src/cli/commands/schedules.ts +683 -0
  212. package/src/cli/commands/telemetry.ts +40 -0
  213. package/src/cli/lib/__tests__/cli-colors.test.ts +48 -0
  214. package/src/cli/lib/__tests__/confirm-prompt.test.ts +159 -0
  215. package/src/cli/lib/__tests__/install-from-github.test.ts +355 -0
  216. package/src/cli/lib/__tests__/list-installed-plugins.test.ts +154 -0
  217. package/src/cli/lib/__tests__/search-plugins.test.ts +261 -0
  218. package/src/cli/lib/__tests__/uninstall-plugin.test.ts +124 -0
  219. package/src/cli/lib/__tests__/unknown-command.test.ts +106 -0
  220. package/src/cli/lib/cli-colors.ts +12 -0
  221. package/src/cli/lib/confirm-prompt.ts +79 -0
  222. package/src/cli/lib/install-from-github.ts +303 -0
  223. package/src/cli/lib/list-installed-plugins.ts +137 -0
  224. package/src/cli/lib/search-plugins.ts +163 -0
  225. package/src/cli/lib/uninstall-plugin.ts +82 -0
  226. package/src/cli/lib/unknown-command.ts +111 -0
  227. package/src/cli/program.ts +52 -2
  228. package/src/config/assistant-feature-flags.ts +24 -54
  229. package/src/config/bundled-skills/app-builder/SKILL.md +140 -22
  230. package/src/config/bundled-skills/app-builder/TOOLS.json +7 -0
  231. package/src/config/bundled-skills/computer-use/TOOLS.json +15 -52
  232. package/src/config/bundled-skills/document/SKILL.md +23 -3
  233. package/src/config/bundled-skills/document/TOOLS.json +53 -0
  234. package/src/config/bundled-skills/document/tools/document-delete.ts +12 -0
  235. package/src/config/bundled-skills/document/tools/document-list.ts +12 -0
  236. package/src/config/bundled-skills/document/tools/document-read.ts +12 -0
  237. package/src/config/bundled-skills/phone-calls/SKILL.md +1 -1
  238. package/src/config/bundled-skills/skill-management/SKILL.md +2 -2
  239. package/src/config/bundled-skills/skill-management/TOOLS.json +7 -7
  240. package/src/config/bundled-tool-registry.ts +6 -0
  241. package/src/config/call-site-defaults.ts +105 -0
  242. package/src/config/feature-flag-registry.json +41 -9
  243. package/src/config/llm-resolver.ts +52 -1
  244. package/src/config/loader.ts +64 -38
  245. package/src/config/schema.ts +9 -10
  246. package/src/config/schemas/__tests__/llm-request-logs.test.ts +36 -0
  247. package/src/config/schemas/__tests__/memory-v2.test.ts +3 -3
  248. package/src/config/schemas/channels.ts +17 -0
  249. package/src/config/schemas/compaction.ts +28 -0
  250. package/src/config/schemas/conversations.ts +10 -0
  251. package/src/config/schemas/heartbeat.ts +23 -0
  252. package/src/config/schemas/llm-request-logs.ts +31 -7
  253. package/src/config/schemas/llm.ts +1 -0
  254. package/src/config/schemas/memory-retrieval.ts +18 -0
  255. package/src/config/schemas/memory-retrospective.ts +1 -1
  256. package/src/config/schemas/memory-v2.ts +4 -4
  257. package/src/config/schemas/memory.ts +3 -1
  258. package/src/config/schemas/tools.ts +14 -0
  259. package/src/config/seed-inference-profiles.ts +99 -29
  260. package/src/config/skills.ts +3 -96
  261. package/src/context/compactor.ts +1107 -0
  262. package/src/context/token-estimator.ts +34 -36
  263. package/src/context/window-manager.ts +197 -1520
  264. package/src/credential-execution/managed-catalog.ts +37 -0
  265. package/src/credential-health/credential-health-service.ts +280 -19
  266. package/src/daemon/__tests__/conversation-lifecycle-auto-analyze.test.ts +33 -18
  267. package/src/daemon/__tests__/conversation-tool-setup-exclude.test.ts +138 -0
  268. package/src/daemon/__tests__/conversation-tool-setup.test.ts +74 -0
  269. package/src/daemon/approval-generators.ts +8 -6
  270. package/src/daemon/config-watcher.ts +94 -31
  271. package/src/daemon/conversation-agent-loop-handlers.ts +78 -0
  272. package/src/daemon/conversation-agent-loop.ts +198 -11
  273. package/src/daemon/conversation-error.ts +171 -37
  274. package/src/daemon/conversation-lifecycle.ts +53 -40
  275. package/src/daemon/conversation-messaging.ts +25 -6
  276. package/src/daemon/conversation-process.ts +49 -12
  277. package/src/daemon/conversation-runtime-assembly.ts +25 -1
  278. package/src/daemon/conversation-slash.ts +12 -5
  279. package/src/daemon/conversation-store.ts +11 -4
  280. package/src/daemon/conversation-tool-setup.ts +39 -7
  281. package/src/daemon/conversation.ts +33 -8
  282. package/src/daemon/date-context.ts +40 -0
  283. package/src/daemon/external-plugins-bootstrap.ts +217 -181
  284. package/src/daemon/first-greeting.ts +22 -2
  285. package/src/daemon/guardian-action-generators.ts +1 -125
  286. package/src/daemon/handlers/__tests__/config-a2a-complete.test.ts +248 -0
  287. package/src/daemon/handlers/__tests__/config-a2a-invite.test.ts +154 -0
  288. package/src/daemon/handlers/__tests__/config-a2a-redeem.test.ts +133 -0
  289. package/src/daemon/handlers/__tests__/config-a2a.test.ts +95 -0
  290. package/src/daemon/handlers/config-a2a.ts +289 -0
  291. package/src/daemon/handlers/config-model.ts +6 -5
  292. package/src/daemon/handlers/config-slack-channel.ts +15 -3
  293. package/src/daemon/handlers/conversations.ts +1 -0
  294. package/src/daemon/handlers/shared.ts +14 -5
  295. package/src/daemon/handlers/skills.ts +111 -108
  296. package/src/daemon/history-repair.ts +28 -1
  297. package/src/daemon/host-app-control-proxy.ts +153 -27
  298. package/src/daemon/host-proxy-preactivation.ts +85 -18
  299. package/src/daemon/lifecycle.ts +89 -91
  300. package/src/daemon/meet-host-supervisor.ts +5 -4
  301. package/src/daemon/memory-v2-startup.ts +85 -0
  302. package/src/daemon/message-protocol.ts +1 -0
  303. package/src/daemon/message-types/conversations.ts +25 -0
  304. package/src/daemon/message-types/messages.ts +61 -0
  305. package/src/daemon/message-types/notifications.ts +21 -0
  306. package/src/daemon/message-types/subagents.ts +1 -0
  307. package/src/daemon/message-types/sync.ts +1 -0
  308. package/src/daemon/pkb-reminder-builder.test.ts +11 -54
  309. package/src/daemon/pkb-reminder-builder.ts +5 -20
  310. package/src/daemon/plugin-source-watcher.ts +146 -0
  311. package/src/daemon/process-message.ts +24 -3
  312. package/src/daemon/server.ts +11 -2
  313. package/src/daemon/skill-memory-refresh.ts +33 -0
  314. package/src/daemon/wake-target-adapter.ts +2 -0
  315. package/src/documents/document-store.ts +221 -3
  316. package/src/embedded/plugin-api.ts +40 -0
  317. package/src/export/__tests__/transcript-formatter.test.ts +121 -0
  318. package/src/export/transcript-formatter.ts +54 -20
  319. package/src/filing/filing-service.ts +39 -0
  320. package/src/heartbeat/__tests__/heartbeat-service.test.ts +135 -6
  321. package/src/heartbeat/heartbeat-run-store.ts +2 -1
  322. package/src/heartbeat/heartbeat-service.ts +73 -189
  323. package/src/home/__tests__/feed-types.test.ts +80 -0
  324. package/src/home/feed-types.ts +36 -2
  325. package/src/home/post-connect-feed.ts +1 -0
  326. package/src/index.ts +18 -1
  327. package/src/ipc/cli-client.ts +147 -45
  328. package/src/live-voice/__tests__/live-voice-stt.test.ts +57 -0
  329. package/src/mcp/client.ts +20 -4
  330. package/src/media/image-credentials.ts +3 -3
  331. package/src/memory/__tests__/bookmark-crud.test.ts +33 -27
  332. package/src/memory/__tests__/conversation-queries.test.ts +483 -0
  333. package/src/memory/__tests__/jobs-worker-v2-graph-trigger-embed.test.ts +113 -0
  334. package/src/memory/__tests__/memory-retrospective-enqueue.test.ts +2 -50
  335. package/src/memory/__tests__/memory-retrospective-job.test.ts +87 -4
  336. package/src/memory/__tests__/memory-retrospective-startup-cleanup.test.ts +119 -14
  337. package/src/memory/__tests__/message-content.test.ts +35 -0
  338. package/src/memory/bookmark-crud.ts +42 -10
  339. package/src/memory/context-search/sources/conversations.ts +62 -2
  340. package/src/memory/context-search/sources/workspace.ts +4 -0
  341. package/src/memory/conversation-crud.ts +63 -19
  342. package/src/memory/conversation-queries.ts +197 -11
  343. package/src/memory/conversation-title-service.ts +26 -4
  344. package/src/memory/db-init.ts +12 -0
  345. package/src/memory/delivery-crud.ts +152 -5
  346. package/src/memory/embedding-backend.ts +4 -4
  347. package/src/memory/external-conversation-store.ts +66 -5
  348. package/src/memory/graph/__tests__/conversation-graph-memory-v2-routing.test.ts +150 -12
  349. package/src/memory/graph/conversation-graph-memory.ts +49 -21
  350. package/src/memory/graph/tools.ts +9 -40
  351. package/src/memory/indexer.ts +34 -29
  352. package/src/memory/invite-store.ts +53 -0
  353. package/src/memory/jobs/__tests__/embed-concept-page.test.ts +73 -0
  354. package/src/memory/jobs/embed-concept-page.ts +20 -11
  355. package/src/memory/jobs-worker.ts +6 -1
  356. package/src/memory/llm-request-log-source-clickhouse.ts +24 -12
  357. package/src/memory/llm-request-log-source.ts +19 -52
  358. package/src/memory/llm-request-log-store.ts +92 -1
  359. package/src/memory/llm-usage-store.ts +125 -5
  360. package/src/memory/memory-retrospective-enqueue.ts +1 -20
  361. package/src/memory/memory-retrospective-job.ts +33 -6
  362. package/src/memory/memory-retrospective-startup-cleanup.ts +72 -5
  363. package/src/memory/message-content.ts +1 -1
  364. package/src/memory/migrations/109-external-conversation-bindings.ts +15 -4
  365. package/src/memory/migrations/229-delete-private-conversations.test.ts +38 -1
  366. package/src/memory/migrations/229-delete-private-conversations.ts +7 -0
  367. package/src/memory/migrations/247-external-conversation-binding-thread-id.ts +78 -0
  368. package/src/memory/migrations/248-create-onboarding-events.ts +21 -0
  369. package/src/memory/migrations/249-normalize-slack-external-content.ts +240 -0
  370. package/src/memory/migrations/250-provider-connection-base-url-and-models.ts +28 -0
  371. package/src/memory/migrations/251-a2a-tasks.ts +49 -0
  372. package/src/memory/migrations/252-llm-request-log-agent-loop-exit-reason.ts +32 -0
  373. package/src/memory/migrations/index.ts +9 -0
  374. package/src/memory/migrations/registry.ts +16 -0
  375. package/src/memory/onboarding-events-store.ts +106 -0
  376. package/src/memory/schema/a2a.ts +15 -0
  377. package/src/memory/schema/bookmarks.ts +0 -2
  378. package/src/memory/schema/calls.ts +1 -0
  379. package/src/memory/schema/index.ts +1 -0
  380. package/src/memory/schema/inference.ts +3 -3
  381. package/src/memory/schema/infrastructure.ts +13 -0
  382. package/src/memory/turn-events-store.ts +127 -2
  383. package/src/memory/v2/__tests__/activation-store.test.ts +25 -23
  384. package/src/memory/v2/__tests__/activation.test.ts +0 -8
  385. package/src/memory/v2/__tests__/cli-command-store.test.ts +404 -0
  386. package/src/memory/v2/__tests__/frontmatter-sweep.test.ts +25 -4
  387. package/src/memory/v2/__tests__/injection.test.ts +288 -11
  388. package/src/memory/v2/__tests__/migration.test.ts +87 -0
  389. package/src/memory/v2/__tests__/page-index.test.ts +83 -0
  390. package/src/memory/v2/__tests__/prompts-router.test.ts +58 -6
  391. package/src/memory/v2/__tests__/qdrant.test.ts +66 -3
  392. package/src/memory/v2/__tests__/router.test.ts +15 -0
  393. package/src/memory/v2/__tests__/skill-store.test.ts +387 -8
  394. package/src/memory/v2/__tests__/static-context.test.ts +12 -1
  395. package/src/memory/v2/activation-store.ts +14 -16
  396. package/src/memory/v2/cli-command-content.ts +19 -0
  397. package/src/memory/v2/cli-command-store.ts +304 -0
  398. package/src/memory/v2/frontmatter-sweep.ts +7 -1
  399. package/src/memory/v2/injection.ts +81 -26
  400. package/src/memory/v2/migration.ts +49 -19
  401. package/src/memory/v2/page-index.ts +63 -8
  402. package/src/memory/v2/prompts/router.ts +11 -8
  403. package/src/memory/v2/prompts/sweep.ts +2 -2
  404. package/src/memory/v2/qdrant.ts +135 -7
  405. package/src/memory/v2/router.ts +9 -8
  406. package/src/memory/v2/skill-store.ts +120 -35
  407. package/src/memory/v2/static-context.ts +4 -4
  408. package/src/memory/v2/types.ts +23 -0
  409. package/src/messaging/providers/a2a/__tests__/deliver.test.ts +274 -0
  410. package/src/messaging/providers/a2a/deliver.ts +156 -0
  411. package/src/messaging/providers/gmail/client.ts +9 -2
  412. package/src/messaging/providers/index.ts +11 -2
  413. package/src/messaging/providers/slack/__tests__/adapter-token-routing.test.ts +45 -5
  414. package/src/messaging/providers/slack/__tests__/download.test.ts +231 -0
  415. package/src/messaging/providers/slack/adapter.ts +43 -5
  416. package/src/messaging/providers/slack/client.ts +27 -0
  417. package/src/messaging/providers/slack/deep-link.ts +65 -0
  418. package/src/messaging/providers/slack/download.ts +104 -0
  419. package/src/messaging/providers/slack/message-metadata.test.ts +32 -0
  420. package/src/messaging/providers/slack/message-metadata.ts +27 -0
  421. package/src/messaging/providers/slack/render-transcript.test.ts +134 -0
  422. package/src/messaging/providers/slack/render-transcript.ts +69 -5
  423. package/src/messaging/providers/slack/types.ts +20 -1
  424. package/src/notifications/__tests__/broadcaster.test.ts +203 -0
  425. package/src/notifications/__tests__/decision-engine.test.ts +283 -0
  426. package/src/notifications/__tests__/deterministic-checks.test.ts +286 -0
  427. package/src/notifications/__tests__/emit-signal-home-feed.test.ts +1 -0
  428. package/src/notifications/__tests__/home-feed-side-effect.test.ts +430 -7
  429. package/src/notifications/adapters/macos.ts +12 -2
  430. package/src/notifications/broadcaster.ts +29 -4
  431. package/src/notifications/conversation-pairing.ts +2 -1
  432. package/src/notifications/copy-composer.ts +17 -64
  433. package/src/notifications/decision-engine.ts +113 -45
  434. package/src/notifications/deterministic-checks.ts +96 -0
  435. package/src/notifications/emit-signal.ts +21 -1
  436. package/src/notifications/home-feed-side-effect.ts +138 -5
  437. package/src/notifications/signal.ts +3 -5
  438. package/src/notifications/types.ts +8 -0
  439. package/src/oauth/connection-resolver.ts +8 -4
  440. package/src/oauth/platform-connection.test.ts +43 -3
  441. package/src/oauth/platform-connection.ts +19 -6
  442. package/src/oauth/seed-providers.ts +10 -1
  443. package/src/permissions/checker.ts +2 -0
  444. package/src/permissions/ipc-risk-types.ts +1 -0
  445. package/src/permissions/question-prompter.test.ts +416 -0
  446. package/src/permissions/question-prompter.ts +294 -0
  447. package/src/platform/client.test.ts +1 -1
  448. package/src/platform/client.ts +1 -1
  449. package/src/plugin-api/constants.ts +26 -0
  450. package/src/plugin-api/index.ts +34 -1
  451. package/src/plugin-api/types.ts +104 -22
  452. package/src/plugins/defaults/circuit-breaker.ts +0 -5
  453. package/src/plugins/defaults/compaction.ts +0 -4
  454. package/src/plugins/defaults/empty-response.ts +0 -2
  455. package/src/plugins/defaults/history-repair.ts +0 -2
  456. package/src/plugins/defaults/injectors.ts +74 -22
  457. package/src/plugins/defaults/llm-call.ts +0 -2
  458. package/src/plugins/defaults/memory-retrieval.ts +0 -1
  459. package/src/plugins/defaults/overflow-reduce.ts +0 -1
  460. package/src/plugins/defaults/persistence.ts +0 -2
  461. package/src/plugins/defaults/title-generate.ts +0 -5
  462. package/src/plugins/defaults/token-estimate.ts +0 -2
  463. package/src/plugins/defaults/tool-error.ts +0 -7
  464. package/src/plugins/defaults/tool-execute.ts +0 -2
  465. package/src/plugins/defaults/tool-result-truncate.ts +0 -4
  466. package/src/plugins/ensure-plugin-api-shim.ts +96 -0
  467. package/src/plugins/external-api.ts +104 -0
  468. package/src/plugins/external-plugin-loader.ts +187 -42
  469. package/src/plugins/feature-gate.ts +22 -0
  470. package/src/plugins/pipeline.ts +37 -0
  471. package/src/plugins/registry.ts +48 -80
  472. package/src/plugins/types.ts +40 -26
  473. package/src/plugins/user-loader.ts +21 -2
  474. package/src/proactive-artifact/aux-message-injector.ts +11 -0
  475. package/src/proactive-artifact/job.test.ts +37 -5
  476. package/src/prompts/__tests__/system-prompt.test.ts +10 -43
  477. package/src/prompts/__tests__/task-progress-hint-section.test.ts +95 -0
  478. package/src/prompts/normalize-onboarding.ts +27 -0
  479. package/src/prompts/sections.ts +302 -0
  480. package/src/prompts/system-prompt.ts +63 -174
  481. package/src/prompts/templates/BOOTSTRAP.md +17 -1
  482. package/src/prompts/templates/system-sections.ts +164 -0
  483. package/src/providers/__tests__/inference.test.ts +24 -7
  484. package/src/providers/anthropic/client.ts +28 -28
  485. package/src/providers/call-site-routing.ts +24 -6
  486. package/src/providers/connection-resolution.ts +68 -11
  487. package/src/providers/inference/__tests__/adapter-factory-openai-compatible.test.ts +74 -0
  488. package/src/providers/inference/__tests__/connections-openai-compatible.test.ts +175 -0
  489. package/src/providers/inference/__tests__/connections-status-label.test.ts +15 -0
  490. package/src/providers/inference/adapter-factory.ts +32 -6
  491. package/src/providers/inference/auth.ts +12 -0
  492. package/src/providers/inference/backfill.ts +14 -1
  493. package/src/providers/inference/connections.ts +159 -34
  494. package/src/providers/inference/resolve-auth.ts +14 -4
  495. package/src/providers/model-catalog.ts +249 -12
  496. package/src/providers/model-intents.ts +3 -3
  497. package/src/providers/openai/__tests__/chat-completions-provider-reasoning.test.ts +235 -0
  498. package/src/providers/openai/chat-completions-provider.ts +169 -8
  499. package/src/providers/openrouter/client.ts +49 -4
  500. package/src/providers/{managed-proxy → platform-proxy}/constants.ts +4 -2
  501. package/src/providers/{managed-proxy → platform-proxy}/context.ts +3 -3
  502. package/src/providers/provider-availability.ts +17 -2
  503. package/src/providers/provider-catalog-visibility.ts +38 -0
  504. package/src/providers/provider-send-message.ts +27 -12
  505. package/src/providers/registry.ts +52 -15
  506. package/src/providers/retry.ts +47 -1
  507. package/src/runtime/__tests__/agent-wake.test.ts +152 -0
  508. package/src/runtime/agent-wake.ts +103 -15
  509. package/src/runtime/auth/route-policy.ts +21 -1
  510. package/src/runtime/btw-sidechain.ts +2 -0
  511. package/src/runtime/http-server.ts +7 -16
  512. package/src/runtime/http-types.ts +19 -47
  513. package/src/runtime/migrations/origin-mode.ts +1 -1
  514. package/src/runtime/pending-interactions.ts +1 -0
  515. package/src/runtime/routes/__tests__/bookmark-routes.test.ts +17 -0
  516. package/src/runtime/routes/__tests__/consolidation-routes.test.ts +258 -0
  517. package/src/runtime/routes/__tests__/conversation-management-routes.test.ts +5 -1
  518. package/src/runtime/routes/__tests__/conversation-query-routes.test.ts +172 -23
  519. package/src/runtime/routes/__tests__/inference-provider-connection-routes.test.ts +275 -44
  520. package/src/runtime/routes/__tests__/llm-call-sites-routes.test.ts +12 -0
  521. package/src/runtime/routes/__tests__/question-routes.test.ts +395 -0
  522. package/src/runtime/routes/__tests__/tts-routes.test.ts +64 -1
  523. package/src/runtime/routes/acp-routes-list.test.ts +143 -0
  524. package/src/runtime/routes/acp-routes.ts +5 -3
  525. package/src/runtime/routes/auth-routes.ts +1 -1
  526. package/src/runtime/routes/bookmark-routes.ts +5 -3
  527. package/src/runtime/routes/btw-routes.ts +5 -1
  528. package/src/runtime/routes/channel-availability-routes.ts +126 -0
  529. package/src/runtime/routes/consolidation-routes.ts +100 -0
  530. package/src/runtime/routes/conversation-cli-routes.ts +44 -3
  531. package/src/runtime/routes/conversation-list-routes.ts +3 -20
  532. package/src/runtime/routes/conversation-management-routes.ts +17 -42
  533. package/src/runtime/routes/conversation-query-routes.ts +99 -35
  534. package/src/runtime/routes/conversation-routes.ts +97 -11
  535. package/src/runtime/routes/documents-routes.ts +25 -86
  536. package/src/runtime/routes/group-routes.ts +5 -0
  537. package/src/runtime/routes/inbound-conversation.ts +28 -8
  538. package/src/runtime/routes/inbound-message-handler.ts +236 -41
  539. package/src/runtime/routes/inbound-stages/background-dispatch.test.ts +111 -0
  540. package/src/runtime/routes/inbound-stages/background-dispatch.ts +32 -1
  541. package/src/runtime/routes/inbound-stages/edit-intercept.ts +17 -4
  542. package/src/runtime/routes/index.ts +8 -0
  543. package/src/runtime/routes/inference-profile-session-handler.ts +17 -44
  544. package/src/runtime/routes/inference-profile-session-reaper.ts +7 -21
  545. package/src/runtime/routes/inference-provider-connection-routes.ts +199 -22
  546. package/src/runtime/routes/integrations/a2a.ts +235 -0
  547. package/src/runtime/routes/integrations/slack/share.ts +4 -52
  548. package/src/runtime/routes/integrations/slack/token.ts +43 -0
  549. package/src/runtime/routes/integrations/twilio.ts +6 -13
  550. package/src/runtime/routes/llm-call-sites-routes.ts +11 -1
  551. package/src/runtime/routes/notification-routes.ts +1 -1
  552. package/src/runtime/routes/oauth-commands-routes.ts +105 -15
  553. package/src/runtime/routes/oauth-lifecycle-routes.ts +43 -0
  554. package/src/runtime/routes/question-routes.ts +259 -0
  555. package/src/runtime/routes/rename-conversation-routes.ts +2 -33
  556. package/src/runtime/routes/schedule-routes.ts +4 -7
  557. package/src/runtime/routes/subagents-routes.ts +98 -18
  558. package/src/runtime/routes/telemetry-routes.ts +27 -0
  559. package/src/runtime/routes/tts-routes.ts +27 -2
  560. package/src/runtime/routes/workspace-routes.test.ts +43 -0
  561. package/src/runtime/routes/workspace-routes.ts +28 -0
  562. package/src/runtime/services/conversation-serializer.ts +39 -7
  563. package/src/runtime/sync/resource-sync-events.ts +93 -1
  564. package/src/schedule/schedule-store.ts +27 -2
  565. package/src/schedule/scheduler.ts +9 -1
  566. package/src/security/__tests__/untrusted-content.test.ts +86 -0
  567. package/src/security/untrusted-content.ts +93 -8
  568. package/src/skills/catalog-files.ts +1 -1
  569. package/src/skills/catalog-install.ts +233 -116
  570. package/src/skills/clawhub.ts +70 -13
  571. package/src/skills/managed-store.ts +4 -119
  572. package/src/skills/skillssh-registry.ts +27 -48
  573. package/src/subagent/manager.ts +17 -7
  574. package/src/telemetry/types.ts +113 -1
  575. package/src/telemetry/usage-telemetry-reporter.test.ts +312 -5
  576. package/src/telemetry/usage-telemetry-reporter.ts +113 -7
  577. package/src/tools/apps/executors.ts +58 -7
  578. package/src/tools/ask-question/ask-question-tool.test.ts +509 -0
  579. package/src/tools/ask-question/ask-question-tool.ts +304 -0
  580. package/src/tools/browser/browser-execution.ts +15 -11
  581. package/src/tools/computer-use/definitions.ts +3 -3
  582. package/src/tools/credentials/vault.ts +1 -1
  583. package/src/tools/document/document-tool.ts +124 -1
  584. package/src/tools/filesystem/edit.ts +1 -1
  585. package/src/tools/filesystem/list.ts +1 -1
  586. package/src/tools/filesystem/read.ts +1 -1
  587. package/src/tools/filesystem/write.ts +5 -2
  588. package/src/tools/host-filesystem/transfer.ts +1 -1
  589. package/src/tools/host-terminal/host-shell.ts +1 -1
  590. package/src/tools/memory/register.ts +1 -9
  591. package/src/tools/permission-checker.ts +1 -1
  592. package/src/tools/registry.ts +17 -7
  593. package/src/tools/schedule/create.ts +2 -2
  594. package/src/tools/schema-transforms.ts +7 -2
  595. package/src/tools/side-effects.ts +1 -0
  596. package/src/tools/skills/delete-managed.ts +4 -4
  597. package/src/tools/skills/execute.ts +1 -1
  598. package/src/tools/skills/scaffold-managed.ts +3 -2
  599. package/src/tools/subagent/notify-parent.ts +1 -1
  600. package/src/tools/system/request-permission.ts +2 -2
  601. package/src/tools/terminal/safe-env.ts +60 -1
  602. package/src/tools/tool-manifest.ts +2 -0
  603. package/src/tools/types.ts +107 -21
  604. package/src/tools/ui-surface/definitions.ts +6 -5
  605. package/src/tts/__tests__/provider-adapters.test.ts +76 -2
  606. package/src/tts/providers/elevenlabs-provider.ts +75 -1
  607. package/src/types/onboarding-context.ts +2 -0
  608. package/src/util/errors.ts +17 -0
  609. package/src/util/platform.ts +10 -0
  610. package/src/watcher/__tests__/engine.test.ts +22 -0
  611. package/src/watcher/engine.ts +6 -2
  612. package/src/workspace/migrations/057-repair-stale-gemini-model-ids.ts +80 -15
  613. package/src/workspace/migrations/072-seed-reply-suggestion-callsite.ts +35 -22
  614. package/src/workspace/migrations/073-repair-recall-callsite-empty-profile.ts +3 -1
  615. package/src/workspace/migrations/083-system-prompt-prefix-to-file.ts +191 -0
  616. package/src/workspace/migrations/084-remove-legacy-skills-index.ts +276 -0
  617. package/src/workspace/migrations/085-memory-v2-bm25-b-reembed-disabled-v2-pages.ts +137 -0
  618. package/src/workspace/migrations/086-revert-stale-gemini-mis-rewrites.ts +198 -0
  619. package/src/workspace/migrations/087-memory-router-balanced-profile.ts +91 -0
  620. package/src/workspace/migrations/registry.ts +10 -0
  621. package/src/workspace/migrations/runner.ts +39 -9
  622. package/src/workspace/migrations/types.ts +4 -0
  623. package/examples/plugins/echo/bun.lock +0 -25
  624. package/src/__tests__/context-window-manager.test.ts +0 -2481
  625. package/src/__tests__/guardian-action-conversation-turn.test.ts +0 -441
  626. package/src/context/__tests__/compact-prompt.test.ts +0 -63
  627. package/src/context/prompts/compact.md +0 -26
  628. package/src/memory/graph/__tests__/remember-description.test.ts +0 -55
  629. package/src/prompts/__tests__/build-cli-reference-section.test.ts +0 -37
  630. package/src/runtime/guardian-action-conversation-turn.ts +0 -99
@@ -2,32 +2,24 @@ import { describe, expect, test } from "bun:test";
2
2
 
3
3
  import { buildPkbReminder } from "./pkb-reminder-builder.js";
4
4
 
5
- // Byte-for-byte fixture of the default (non-relaxed) PKB reminder. Asserted
6
- // verbatim so that any future edit to the BODY text is caught by tests.
7
- const BASE_REMINDER_DEFAULT =
5
+ // Byte-for-byte fixture of the PKB reminder. Asserted verbatim so that any
6
+ // future edit to the BODY text is caught by tests.
7
+ const BASE_REMINDER =
8
8
  "<system_reminder>" +
9
- "\n**CRITICAL:** Call `remember` this turn for anything concrete the user said facts, preferences, plans, names, dates, decisions, corrections, felt moments. Default to remembering; skip only obvious noise. This should be your most frequently used tool." +
9
+ "\nStay present in this conversation. Use `remember` when something feels worth pausing to markcorrections (highest priority), plans, decisions, felt moments. You don't have to capture everything in the moment a retrospective pass reviews this conversation in the background and saves what you didn't capture." +
10
10
  "\nIf you're unsure about something that may live in the workspace — past decisions, prior conversations, files — use `recall` before asking or guessing." +
11
11
  "\n</system_reminder>";
12
12
 
13
- // Byte-for-byte fixture of the relaxed PKB reminder used when the
14
- // `memory-retrospective` feature flag is on.
15
- const BASE_REMINDER_RELAXED =
16
- "<system_reminder>" +
17
- "\nStay present in this conversation. Use `remember` when something feels worth pausing to mark — corrections (highest priority), plans, decisions, felt moments, things the user asks you to hold onto. You don't have to capture everything in the moment — a retrospective pass reviews this conversation in the background and saves what you didn't capture." +
18
- "\nIf you're unsure about something that may live in the workspace — past decisions, prior conversations, files — use `recall` before asking or guessing." +
19
- "\n</system_reminder>";
20
-
21
- describe("buildPkbReminder — default body (relaxed=false)", () => {
13
+ describe("buildPkbReminder", () => {
22
14
  test("empty hints returns exact base reminder byte-for-byte", () => {
23
- expect(buildPkbReminder([], false)).toBe(BASE_REMINDER_DEFAULT);
15
+ expect(buildPkbReminder([])).toBe(BASE_REMINDER);
24
16
  });
25
17
 
26
18
  test("single hint renders one bullet with no duplicates or trailing blank line", () => {
27
- const out = buildPkbReminder(["projects/alpha.md"], false);
19
+ const out = buildPkbReminder(["projects/alpha.md"]);
28
20
  const expected =
29
21
  "<system_reminder>" +
30
- "\n**CRITICAL:** Call `remember` this turn for anything concrete the user said facts, preferences, plans, names, dates, decisions, corrections, felt moments. Default to remembering; skip only obvious noise. This should be your most frequently used tool." +
22
+ "\nStay present in this conversation. Use `remember` when something feels worth pausing to markcorrections (highest priority), plans, decisions, felt moments. You don't have to capture everything in the moment a retrospective pass reviews this conversation in the background and saves what you didn't capture." +
31
23
  "\nIf you're unsure about something that may live in the workspace — past decisions, prior conversations, files — use `recall` before asking or guessing." +
32
24
  "\nBased on the current context, these files look especially relevant:" +
33
25
  "\n- projects/alpha.md" +
@@ -44,10 +36,10 @@ describe("buildPkbReminder — default body (relaxed=false)", () => {
44
36
 
45
37
  test("three hints render all three in order", () => {
46
38
  const hints = ["a.md", "sub/b.md", "c/d/e.md"];
47
- const out = buildPkbReminder(hints, false);
39
+ const out = buildPkbReminder(hints);
48
40
  const expected =
49
41
  "<system_reminder>" +
50
- "\n**CRITICAL:** Call `remember` this turn for anything concrete the user said facts, preferences, plans, names, dates, decisions, corrections, felt moments. Default to remembering; skip only obvious noise. This should be your most frequently used tool." +
42
+ "\nStay present in this conversation. Use `remember` when something feels worth pausing to markcorrections (highest priority), plans, decisions, felt moments. You don't have to capture everything in the moment a retrospective pass reviews this conversation in the background and saves what you didn't capture." +
51
43
  "\nIf you're unsure about something that may live in the workspace — past decisions, prior conversations, files — use `recall` before asking or guessing." +
52
44
  "\nBased on the current context, these files look especially relevant:" +
53
45
  "\n- a.md" +
@@ -67,7 +59,7 @@ describe("buildPkbReminder — default body (relaxed=false)", () => {
67
59
 
68
60
  test("hints with special chars (< and &) are emitted verbatim (no escaping)", () => {
69
61
  const hints = ["weird<name>.md", "foo&bar.md"];
70
- const out = buildPkbReminder(hints, false);
62
+ const out = buildPkbReminder(hints);
71
63
  expect(out).toContain("- weird<name>.md");
72
64
  expect(out).toContain("- foo&bar.md");
73
65
  // Ensure no HTML-style escaping happened.
@@ -75,38 +67,3 @@ describe("buildPkbReminder — default body (relaxed=false)", () => {
75
67
  expect(out).not.toContain("&amp;");
76
68
  });
77
69
  });
78
-
79
- describe("buildPkbReminder — relaxed body (relaxed=true)", () => {
80
- test("empty hints returns the relaxed base reminder byte-for-byte", () => {
81
- expect(buildPkbReminder([], true)).toBe(BASE_REMINDER_RELAXED);
82
- });
83
-
84
- test("relaxed BODY does NOT contain the default high-pressure phrasing", () => {
85
- const out = buildPkbReminder([], true);
86
- expect(out).not.toContain("**CRITICAL:**");
87
- expect(out).not.toContain("most frequently used tool");
88
- expect(out).not.toContain("Default to remembering");
89
- });
90
-
91
- test("relaxed BODY mentions the retrospective backstop framing", () => {
92
- const out = buildPkbReminder([], true);
93
- expect(out).toContain("Stay present");
94
- expect(out).toContain("retrospective pass");
95
- });
96
-
97
- test("hints render below the relaxed body in the same shape as default", () => {
98
- const out = buildPkbReminder(["projects/alpha.md"], true);
99
- expect(out).toContain("- projects/alpha.md");
100
- expect(out).toContain(
101
- "Based on the current context, these files look especially relevant:",
102
- );
103
- // Should still close cleanly with no double newline before the tag.
104
- expect(out.includes("\n\n</system_reminder>")).toBe(false);
105
- });
106
- });
107
-
108
- describe("buildPkbReminder — relaxed vs default differ", () => {
109
- test("the two BODY variants are NOT byte-identical", () => {
110
- expect(buildPkbReminder([], false)).not.toBe(buildPkbReminder([], true));
111
- });
112
- });
@@ -1,9 +1,5 @@
1
- const BODY_DEFAULT =
2
- "\n**CRITICAL:** Call `remember` this turn for anything concrete the user said facts, preferences, plans, names, dates, decisions, corrections, felt moments. Default to remembering; skip only obvious noise. This should be your most frequently used tool." +
3
- "\nIf you're unsure about something that may live in the workspace — past decisions, prior conversations, files — use `recall` before asking or guessing.";
4
-
5
- const BODY_RELAXED =
6
- "\nStay present in this conversation. Use `remember` when something feels worth pausing to mark — corrections (highest priority), plans, decisions, felt moments, things the user asks you to hold onto. You don't have to capture everything in the moment — a retrospective pass reviews this conversation in the background and saves what you didn't capture." +
1
+ const BODY =
2
+ "\nStay present in this conversation. Use `remember` when something feels worth pausing to markcorrections (highest priority), plans, decisions, felt moments. You don't have to capture everything in the moment a retrospective pass reviews this conversation in the background and saves what you didn't capture." +
7
3
  "\nIf you're unsure about something that may live in the workspace — past decisions, prior conversations, files — use `recall` before asking or guessing.";
8
4
 
9
5
  /**
@@ -15,23 +11,12 @@ const BODY_RELAXED =
15
11
  * hint. Hints are emitted verbatim — they are trusted internal paths, not
16
12
  * user input, so no escaping is performed.
17
13
  *
18
- * The `relaxed` flag selects between the default high-pressure body and the
19
- * relaxed "judgment framing" body used when the `memory-retrospective`
20
- * feature flag is on. With the flag on, the in-conversation remember pressure
21
- * eases because the retrospective is the backstop. Callers must pass
22
- * `relaxed` explicitly — no default — so the contract is visible at every
23
- * call site.
24
- *
25
14
  * Caller is responsible for capping the hints array at 3 entries.
26
15
  */
27
- export function buildPkbReminder(
28
- hints: ReadonlyArray<string>,
29
- relaxed: boolean,
30
- ): string {
31
- const body = relaxed ? BODY_RELAXED : BODY_DEFAULT;
16
+ export function buildPkbReminder(hints: ReadonlyArray<string>): string {
32
17
  if (hints.length === 0) {
33
- return `<system_reminder>${body}\n</system_reminder>`;
18
+ return `<system_reminder>${BODY}\n</system_reminder>`;
34
19
  }
35
20
  const bullets = hints.map((h) => `- ${h}`).join("\n");
36
- return `<system_reminder>${body}\nBased on the current context, these files look especially relevant:\n${bullets}\n</system_reminder>`;
21
+ return `<system_reminder>${BODY}\nBased on the current context, these files look especially relevant:\n${bullets}\n</system_reminder>`;
37
22
  }
@@ -0,0 +1,146 @@
1
+ /**
2
+ * Filesystem watcher for the external plugins directory.
3
+ *
4
+ * Watches `<workspaceDir>/plugins/` recursively using fs.watch (FSEvents on
5
+ * macOS). When a plugin directory is created or modified, debounces per
6
+ * top-level directory name (= the plugin name) and dispatches to the
7
+ * watcher's internal change handler so the daemon can register or reload
8
+ * the plugin without a restart.
9
+ *
10
+ * Mirrors `app-source-watcher.ts` (same DebouncerMap shape, same start/stop
11
+ * lifecycle, same ensureStarted late-create hook), but exposes its lifecycle
12
+ * through a static singleton so tool side-effects can call
13
+ * `PluginSourceWatcher.getInstance().ensureStarted()` directly without an
14
+ * intermediate module-level injection.
15
+ */
16
+
17
+ import { type FSWatcher, mkdirSync, watch } from "node:fs";
18
+
19
+ import { DebouncerMap } from "../util/debounce.js";
20
+ import { getLogger } from "../util/logger.js";
21
+ import { getWorkspacePluginsDir } from "../util/platform.js";
22
+ import { reregisterExternalPlugin } from "./external-plugins-bootstrap.js";
23
+
24
+ const log = getLogger("plugin-source-watcher");
25
+
26
+ const PLUGIN_SOURCE_DEBOUNCE_MS = 500;
27
+
28
+ /**
29
+ * Extract the plugin's top-level directory name from a relative path within
30
+ * the plugins root. Returns null for a stray file directly in `plugins/`
31
+ * (not a plugin dir).
32
+ */
33
+ function resolvePluginNameFromRelPath(relPath: string): string | null {
34
+ const slashIdx = relPath.indexOf("/");
35
+ if (slashIdx === -1) {
36
+ // Bare entry under plugins/ — fs.watch reports these when a new
37
+ // directory is first created. We treat the name as the plugin name and
38
+ // let the install path decide whether it's a real plugin.
39
+ return relPath.length > 0 ? relPath : null;
40
+ }
41
+ const dirName = relPath.slice(0, slashIdx);
42
+ return dirName.length > 0 ? dirName : null;
43
+ }
44
+
45
+ export class PluginSourceWatcher {
46
+ /**
47
+ * Process-wide singleton. Callers reach the watcher via
48
+ * {@link PluginSourceWatcher.getInstance} rather than instantiating
49
+ * directly so tool side-effects (`assistant plugins install`) can call
50
+ * `ensureStarted()` on the same watcher the daemon `start()`/`stop()`
51
+ * lifecycle owns, without threading an instance through a registered
52
+ * module-level callback.
53
+ */
54
+ private static singleton: PluginSourceWatcher | null = null;
55
+
56
+ static getInstance(): PluginSourceWatcher {
57
+ PluginSourceWatcher.singleton ??= new PluginSourceWatcher();
58
+ return PluginSourceWatcher.singleton;
59
+ }
60
+
61
+ /** Test-only — drops the singleton so the next `getInstance()` rebuilds. */
62
+ static resetForTests(): void {
63
+ PluginSourceWatcher.singleton?.stop();
64
+ PluginSourceWatcher.singleton = null;
65
+ }
66
+
67
+ private watcher: FSWatcher | null = null;
68
+ private started = false;
69
+ private debouncer = new DebouncerMap({
70
+ defaultDelayMs: PLUGIN_SOURCE_DEBOUNCE_MS,
71
+ maxEntries: 50,
72
+ });
73
+
74
+ start(): void {
75
+ this.started = true;
76
+ this.tryWatch();
77
+ }
78
+
79
+ /**
80
+ * Ensure the watcher is running. Idempotent — safe to call after a tool
81
+ * side-effect that may have just created the plugins directory.
82
+ * No-op if `start()` has not been called yet.
83
+ */
84
+ ensureStarted(): void {
85
+ if (!this.started || this.watcher) return;
86
+ this.tryWatch();
87
+ }
88
+
89
+ stop(): void {
90
+ this.started = false;
91
+ this.debouncer.cancelAll();
92
+ if (this.watcher) {
93
+ this.watcher.close();
94
+ this.watcher = null;
95
+ }
96
+ }
97
+
98
+ private onChange(pluginName: string): Promise<void> {
99
+ return reregisterExternalPlugin(pluginName);
100
+ }
101
+
102
+ private tryWatch(): void {
103
+ if (this.watcher) return;
104
+
105
+ let pluginsDir: string;
106
+ try {
107
+ pluginsDir = getWorkspacePluginsDir();
108
+ } catch {
109
+ log.warn(
110
+ "Could not resolve plugins directory; plugin source watching disabled",
111
+ );
112
+ return;
113
+ }
114
+
115
+ try {
116
+ mkdirSync(pluginsDir, { recursive: true });
117
+ } catch (err) {
118
+ log.warn(
119
+ { err, pluginsDir },
120
+ "Could not create plugins directory; source watching disabled",
121
+ );
122
+ return;
123
+ }
124
+
125
+ try {
126
+ this.watcher = watch(
127
+ pluginsDir,
128
+ { recursive: true },
129
+ (_eventType, filename) => {
130
+ if (!filename) return;
131
+ const pluginName = resolvePluginNameFromRelPath(filename);
132
+ if (!pluginName) return;
133
+ this.debouncer.schedule(`plugin:${pluginName}`, () => {
134
+ void this.onChange(pluginName);
135
+ });
136
+ },
137
+ );
138
+ log.info({ pluginsDir }, "Plugin source watcher started");
139
+ } catch (err) {
140
+ log.warn(
141
+ { err },
142
+ "Failed to watch plugins directory; source watching disabled",
143
+ );
144
+ }
145
+ }
146
+ }
@@ -30,9 +30,14 @@ import {
30
30
  import { updateMetaFile } from "../memory/conversation-disk-view.js";
31
31
  import { broadcastMessage } from "../runtime/assistant-event-hub.js";
32
32
  import { DAEMON_INTERNAL_ASSISTANT_ID } from "../runtime/assistant-scope.js";
33
+ import { publishConversationMessagesChanged } from "../runtime/sync/resource-sync-events.js";
34
+ import { getSubagentManager } from "../subagent/index.js";
33
35
  import { getLogger } from "../util/logger.js";
34
36
  import type { Conversation } from "./conversation.js";
35
- import { buildSlackMetaForPersistence } from "./conversation-messaging.js";
37
+ import {
38
+ buildSlackMetaForPersistence,
39
+ serializePersistedUserMessageContent,
40
+ } from "./conversation-messaging.js";
36
41
  import { formatCompactResult } from "./conversation-process.js";
37
42
  import { resolveChannelCapabilities } from "./conversation-runtime-assembly.js";
38
43
  import {
@@ -314,7 +319,11 @@ export async function processMessage(
314
319
  const persisted = await addMessage(
315
320
  conversationId,
316
321
  "user",
317
- JSON.stringify(cleanMsg.content),
322
+ serializePersistedUserMessageContent(
323
+ content,
324
+ attachments,
325
+ options?.displayContent,
326
+ ),
318
327
  userMetaWithSlack,
319
328
  );
320
329
  conversation.getMessages().push(llmMsg);
@@ -368,6 +377,7 @@ export async function processMessage(
368
377
  serverChannelMeta,
369
378
  );
370
379
  conversation.getMessages().push(assistantMsg);
380
+ publishConversationMessagesChanged(conversationId);
371
381
  return { messageId: persisted.id };
372
382
  }
373
383
 
@@ -399,7 +409,11 @@ export async function processMessage(
399
409
  const persisted = await addMessage(
400
410
  conversationId,
401
411
  "user",
402
- JSON.stringify(cleanMsg.content),
412
+ serializePersistedUserMessageContent(
413
+ content,
414
+ attachments,
415
+ options?.displayContent,
416
+ ),
403
417
  compactUserMeta,
404
418
  );
405
419
  conversation.getMessages().push(cleanMsg);
@@ -421,6 +435,7 @@ export async function processMessage(
421
435
  compactChannelMeta,
422
436
  );
423
437
  conversation.getMessages().push(assistantMsg);
438
+ publishConversationMessagesChanged(conversationId);
424
439
  return { messageId: persisted.id };
425
440
  }
426
441
 
@@ -435,10 +450,13 @@ export async function processMessage(
435
450
  attachments,
436
451
  requestId,
437
452
  persistMetadata,
453
+ options?.displayContent,
438
454
  );
455
+ publishConversationMessagesChanged(conversationId);
439
456
 
440
457
  if (options?.isInteractive === true) {
441
458
  conversation.updateClient(broadcastMessage, false);
459
+ getSubagentManager().updateParentSender(conversationId, broadcastMessage);
442
460
  }
443
461
 
444
462
  try {
@@ -499,10 +517,13 @@ export async function processMessageInBackground(
499
517
  attachments,
500
518
  requestId,
501
519
  persistMetadata,
520
+ options?.displayContent,
502
521
  );
522
+ publishConversationMessagesChanged(conversationId);
503
523
 
504
524
  if (options?.isInteractive === true) {
505
525
  conversation.updateClient(broadcastMessage, false);
526
+ getSubagentManager().updateParentSender(conversationId, broadcastMessage);
506
527
  }
507
528
 
508
529
  conversation.setSlackRuntimeContextNotice(options?.slackRuntimeContextNotice);
@@ -16,7 +16,9 @@ import { broadcastMessage } from "../runtime/assistant-event-hub.js";
16
16
  import { getSigningKeyFingerprint } from "../runtime/auth/token-service.js";
17
17
  import {
18
18
  publishAvatarChanged,
19
+ publishConfigChanged,
19
20
  publishIdentityChanged,
21
+ publishSoundsConfigUpdated,
20
22
  } from "../runtime/sync/resource-sync-events.js";
21
23
  import { updatePublishedAppDeployment } from "../services/published-app-updater.js";
22
24
  import { getSubagentManager } from "../subagent/index.js";
@@ -43,6 +45,8 @@ import { refreshSurfacesForApp } from "./conversation-surfaces.js";
43
45
  import { parseIdentityFields } from "./handlers/identity.js";
44
46
  import type { ConversationCreateOptions } from "./handlers/shared.js";
45
47
  import { setGlobalSkillIpcSender } from "./meet-host-supervisor.js";
48
+ import { PluginSourceWatcher } from "./plugin-source-watcher.js";
49
+ import { refreshSkillCapabilityMemories } from "./skill-memory-refresh.js";
46
50
 
47
51
  const log = getLogger("server");
48
52
 
@@ -68,6 +72,7 @@ export class DaemonServer {
68
72
  // Composed subsystems
69
73
  private configWatcher = getConfigWatcher();
70
74
  private appSourceWatcher = new AppSourceWatcher();
75
+ private pluginSourceWatcher = PluginSourceWatcher.getInstance();
71
76
  private cliIpc = new AssistantIpcServer();
72
77
  private skillIpc = new SkillIpcServer();
73
78
 
@@ -193,11 +198,11 @@ export class DaemonServer {
193
198
  }
194
199
 
195
200
  private broadcastConfigChanged(): void {
196
- broadcastMessage({ type: "config_changed" });
201
+ publishConfigChanged();
197
202
  }
198
203
 
199
204
  private broadcastSoundsConfigUpdated(): void {
200
- broadcastMessage({ type: "sounds_config_updated" });
205
+ publishSoundsConfigUpdated();
201
206
  }
202
207
 
203
208
  private broadcastAvatarUpdated(): void {
@@ -279,12 +284,15 @@ export class DaemonServer {
279
284
  () => this.broadcastSoundsConfigUpdated(),
280
285
  () => this.broadcastAvatarUpdated(),
281
286
  () => this.broadcastConfigChanged(),
287
+ () => refreshSkillCapabilityMemories(getConfig()),
282
288
  );
283
289
 
284
290
  this.syncIdentityToPlatform();
285
291
 
286
292
  this.appSourceWatcher.start((appId) => this.handleAppSourceChange(appId));
287
293
 
294
+ this.pluginSourceWatcher.start();
295
+
288
296
  // Broadcast contacts_changed to all clients when any contact mutation occurs.
289
297
  this.unsubscribeContactChange = onContactChange(() => {
290
298
  broadcastMessage({ type: "contacts_changed" });
@@ -299,6 +307,7 @@ export class DaemonServer {
299
307
  this.evictor.stop();
300
308
  this.configWatcher.stop();
301
309
  this.appSourceWatcher.stop();
310
+ this.pluginSourceWatcher.stop();
302
311
  this.cliIpc.stop();
303
312
  this.skillIpc.stop();
304
313
  if (this.unsubscribeContactChange) {
@@ -0,0 +1,33 @@
1
+ import { getConfig } from "../config/loader.js";
2
+ import type { AssistantConfig } from "../config/schema.js";
3
+ import {
4
+ seedSkillGraphNodes,
5
+ seedUninstalledCatalogSkillMemories,
6
+ } from "../memory/graph/capability-seed.js";
7
+ import { getLogger } from "../util/logger.js";
8
+ import {
9
+ maybeSeedMemoryV2CliCommands,
10
+ maybeSeedMemoryV2Skills,
11
+ } from "./memory-v2-startup.js";
12
+
13
+ const log = getLogger("skill-memory-refresh");
14
+
15
+ export function refreshSkillCapabilityMemories(
16
+ config: AssistantConfig = getConfig(),
17
+ ): void {
18
+ seedSkillGraphNodes();
19
+ maybeSeedMemoryV2Skills(config);
20
+ maybeSeedMemoryV2CliCommands(config);
21
+ void seedUninstalledCatalogSkillMemories()
22
+ .then(() => {
23
+ // Re-run after the async catalog fetch populates the cache so stale
24
+ // installed-skill nodes can be pruned without deleting catalog-only nodes.
25
+ seedSkillGraphNodes();
26
+ })
27
+ .catch((err) =>
28
+ log.warn(
29
+ { err },
30
+ "Uninstalled catalog skill memory seeding failed — continuing",
31
+ ),
32
+ );
33
+ }
@@ -135,6 +135,8 @@ function translateAgentEventToServerMessage(
135
135
  case "input_json_delta":
136
136
  case "usage":
137
137
  case "error":
138
+ case "provider_error":
139
+ case "agent_loop_exit":
138
140
  return null;
139
141
  }
140
142
  }