@vellumai/assistant 0.8.1 → 0.8.2

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 (506) hide show
  1. package/ARCHITECTURE.md +2 -7
  2. package/Dockerfile +75 -1
  3. package/bun.lock +11 -1
  4. package/docker-entrypoint.sh +5 -0
  5. package/docker-init-apt-root.sh +94 -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 +325 -3
  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-wake-disk-pressure-callsite.test.ts +131 -0
  21. package/src/__tests__/anthropic-provider.test.ts +45 -0
  22. package/src/__tests__/app-builder-tool-scripts.test.ts +9 -3
  23. package/src/__tests__/app-executors.test.ts +220 -4
  24. package/src/__tests__/auto-analysis-end-to-end.test.ts +35 -0
  25. package/src/__tests__/bundled-asset.test.ts +6 -6
  26. package/src/__tests__/channel-availability-routes.test.ts +206 -0
  27. package/src/__tests__/channel-delivery-store.test.ts +289 -1
  28. package/src/__tests__/circuit-breaker-pipeline.test.ts +0 -1
  29. package/src/__tests__/clawhub.test.ts +75 -16
  30. package/src/__tests__/compactor-tail-resolution.test.ts +41 -0
  31. package/src/__tests__/config-schema.test.ts +21 -0
  32. package/src/__tests__/config-set-route.test.ts +80 -0
  33. package/src/__tests__/config-sounds-sync.test.ts +97 -0
  34. package/src/__tests__/config-watcher-skill-reseed.test.ts +453 -0
  35. package/src/__tests__/context-search-conversations-source.test.ts +117 -2
  36. package/src/__tests__/context-search-memory-v2-source.test.ts +0 -1
  37. package/src/__tests__/context-search-workspace-source.test.ts +7 -0
  38. package/src/__tests__/context-token-estimator.test.ts +1 -0
  39. package/src/__tests__/conversation-abort-tool-results.test.ts +4 -1
  40. package/src/__tests__/conversation-agent-loop-inference-profile.test.ts +1 -0
  41. package/src/__tests__/conversation-agent-loop-overflow.test.ts +92 -92
  42. package/src/__tests__/conversation-agent-loop.test.ts +2 -0
  43. package/src/__tests__/conversation-error.test.ts +42 -3
  44. package/src/__tests__/conversation-fork-crud.test.ts +82 -0
  45. package/src/__tests__/conversation-inference-profile-route.test.ts +40 -4
  46. package/src/__tests__/conversation-lifecycle.test.ts +173 -0
  47. package/src/__tests__/conversation-message-sync-tags.test.ts +97 -0
  48. package/src/__tests__/conversation-pairing.test.ts +54 -0
  49. package/src/__tests__/conversation-process-callsite.test.ts +4 -1
  50. package/src/__tests__/conversation-provider-retry-repair.test.ts +5 -1
  51. package/src/__tests__/conversation-queue.test.ts +4 -1
  52. package/src/__tests__/conversation-runtime-assembly.test.ts +76 -9
  53. package/src/__tests__/conversation-slash-queue.test.ts +59 -1
  54. package/src/__tests__/conversation-slash-unknown.test.ts +4 -1
  55. package/src/__tests__/conversation-surfaces-table-action.test.ts +360 -0
  56. package/src/__tests__/conversation-sync-tags.test.ts +235 -0
  57. package/src/__tests__/conversation-workspace-injection.test.ts +5 -1
  58. package/src/__tests__/conversation-workspace-tool-tracking.test.ts +5 -1
  59. package/src/__tests__/credential-security-invariants.test.ts +3 -2
  60. package/src/__tests__/db-slack-external-content-normalization.test.ts +301 -0
  61. package/src/__tests__/delete-managed-skill-tool.test.ts +55 -13
  62. package/src/__tests__/disk-pressure-tools.test.ts +1 -0
  63. package/src/__tests__/dm-backfill.test.ts +121 -10
  64. package/src/__tests__/document-tool-security.test.ts +258 -0
  65. package/src/__tests__/dynamic-skill-workflow-prompt.test.ts +0 -1
  66. package/src/__tests__/edit-propagation.test.ts +33 -0
  67. package/src/__tests__/empty-response-pipeline.test.ts +0 -4
  68. package/src/__tests__/external-plugin-loader.test.ts +60 -36
  69. package/src/__tests__/filing-service.test.ts +140 -0
  70. package/src/__tests__/get-skill-detail-audit.test.ts +0 -4
  71. package/src/__tests__/handlers-skills-memory-v2-reseed.test.ts +43 -62
  72. package/src/__tests__/helpers/tar-fixtures.ts +39 -0
  73. package/src/__tests__/helpers/wait-for.ts +21 -0
  74. package/src/__tests__/history-repair-pipeline.test.ts +0 -3
  75. package/src/__tests__/history-repair.test.ts +73 -0
  76. package/src/__tests__/host-app-control-proxy.test.ts +266 -10
  77. package/src/__tests__/image-credentials.test.ts +1 -1
  78. package/src/__tests__/inbound-slack-persistence.test.ts +2 -0
  79. package/src/__tests__/inference-no-mode-boot-e2e.test.ts +1 -1
  80. package/src/__tests__/inference-profile-reaper.test.ts +4 -2
  81. package/src/__tests__/inference-profile-session-handler.test.ts +18 -6
  82. package/src/__tests__/inference-profile-session-ipc.test.ts +17 -5
  83. package/src/__tests__/injector-chain.test.ts +10 -8
  84. package/src/__tests__/install-skill-routing.test.ts +155 -37
  85. package/src/__tests__/lifecycle-memory-v2-seed.test.ts +92 -3
  86. package/src/__tests__/list-messages-page-latest.test.ts +55 -0
  87. package/src/__tests__/llm-call-pipeline.test.ts +0 -3
  88. package/src/__tests__/llm-catalog-parity.test.ts +55 -13
  89. package/src/__tests__/llm-request-log-source-clickhouse.test.ts +34 -0
  90. package/src/__tests__/llm-request-log-source-factory.test.ts +29 -53
  91. package/src/__tests__/llm-usage-store.test.ts +114 -0
  92. package/src/__tests__/managed-profile-guard.test.ts +31 -29
  93. package/src/__tests__/managed-skill-lifecycle.test.ts +109 -18
  94. package/src/__tests__/managed-store.test.ts +84 -192
  95. package/src/__tests__/media-generate-image.test.ts +1 -1
  96. package/src/__tests__/memory-retrieval-pipeline.test.ts +0 -2
  97. package/src/__tests__/messages-after-tiebreaker.test.ts +122 -0
  98. package/src/__tests__/oauth-commands-routes.test.ts +168 -16
  99. package/src/__tests__/oauth-provider-profiles.test.ts +9 -0
  100. package/src/__tests__/openai-provider.test.ts +24 -0
  101. package/src/__tests__/openai-responses-cutover-guard.test.ts +17 -9
  102. package/src/__tests__/overflow-reduce-pipeline.test.ts +0 -2
  103. package/src/__tests__/persistence-pipeline.test.ts +0 -2
  104. package/src/__tests__/{managed-proxy-context.test.ts → platform-proxy-context.test.ts} +1 -1
  105. package/src/__tests__/platform.test.ts +2 -0
  106. package/src/__tests__/plugin-api-shim.test.ts +125 -0
  107. package/src/__tests__/plugin-bootstrap.test.ts +10 -36
  108. package/src/__tests__/plugin-external-api.test.ts +68 -0
  109. package/src/__tests__/plugin-registry.test.ts +0 -77
  110. package/src/__tests__/plugin-route-contribution.test.ts +0 -1
  111. package/src/__tests__/plugin-skill-contribution.test.ts +0 -2
  112. package/src/__tests__/plugin-tool-contribution.test.ts +16 -15
  113. package/src/__tests__/plugin-types.test.ts +3 -13
  114. package/src/__tests__/process-message-background-slack.test.ts +8 -1
  115. package/src/__tests__/process-message-display-content.test.ts +421 -0
  116. package/src/__tests__/provider-catalog-visibility.test.ts +142 -0
  117. package/src/__tests__/provider-error-scenarios.test.ts +111 -0
  118. package/src/__tests__/{provider-managed-proxy-integration.test.ts → provider-platform-proxy-integration.test.ts} +8 -8
  119. package/src/__tests__/scaffold-managed-skill-tool.test.ts +65 -13
  120. package/src/__tests__/schedule-routes.test.ts +50 -3
  121. package/src/__tests__/schedule-store.test.ts +94 -0
  122. package/src/__tests__/scheduler-reuse-conversation.test.ts +54 -7
  123. package/src/__tests__/schema-transforms.test.ts +20 -0
  124. package/src/__tests__/search-skills-unified.test.ts +0 -5
  125. package/src/__tests__/server-history-render.test.ts +43 -0
  126. package/src/__tests__/skill-load-feature-flag.test.ts +0 -12
  127. package/src/__tests__/skill-load-tool.test.ts +27 -89
  128. package/src/__tests__/skill-memory.test.ts +23 -3
  129. package/src/__tests__/skills-file-content-endpoint.test.ts +9 -38
  130. package/src/__tests__/skills-files-catalog-fallback.test.ts +0 -3
  131. package/src/__tests__/skills-install-extract.test.ts +49 -38
  132. package/src/__tests__/skills-install-staging.test.ts +159 -0
  133. package/src/__tests__/skills-uninstall.test.ts +9 -41
  134. package/src/__tests__/skills.test.ts +51 -58
  135. package/src/__tests__/slack-channel-config.test.ts +9 -0
  136. package/src/__tests__/subagent-tool-filtering.test.ts +50 -0
  137. package/src/__tests__/system-prompt.test.ts +737 -63
  138. package/src/__tests__/terminal-tools.test.ts +28 -1
  139. package/src/__tests__/thread-backfill.test.ts +557 -27
  140. package/src/__tests__/title-generate-pipeline.test.ts +0 -13
  141. package/src/__tests__/token-estimate-pipeline.test.ts +0 -3
  142. package/src/__tests__/tool-error-pipeline.test.ts +0 -3
  143. package/src/__tests__/tool-execute-pipeline.test.ts +0 -5
  144. package/src/__tests__/tool-executor-lifecycle-events.test.ts +1 -1
  145. package/src/__tests__/tool-executor.test.ts +16 -4
  146. package/src/__tests__/tool-result-truncate-pipeline.test.ts +0 -12
  147. package/src/__tests__/turn-events-store.test.ts +256 -0
  148. package/src/__tests__/twilio-routes.test.ts +4 -0
  149. package/src/__tests__/user-plugin-loader.test.ts +0 -7
  150. package/src/__tests__/voice-session-bridge.test.ts +198 -0
  151. package/src/__tests__/web-search-catalog-parity.test.ts +32 -10
  152. package/src/__tests__/workspace-migration-057-repair-stale-gemini-model-ids.test.ts +115 -3
  153. package/src/__tests__/workspace-migration-072-seed-reply-suggestion-callsite.test.ts +50 -0
  154. package/src/__tests__/workspace-migration-073-repair-recall-callsite-empty-profile.test.ts +153 -0
  155. package/src/__tests__/workspace-migration-085-memory-v2-bm25-b-reembed-disabled-v2-pages.test.ts +220 -0
  156. package/src/__tests__/workspace-migration-086-revert-stale-gemini-mis-rewrites.test.ts +269 -0
  157. package/src/__tests__/workspace-migration-remove-legacy-skills-index.test.ts +309 -0
  158. package/src/__tests__/workspace-migrations-runner.test.ts +111 -3
  159. package/src/acp/resolve-agent.ts +1 -1
  160. package/src/agent/image-optimize.ts +13 -5
  161. package/src/calls/voice-session-bridge.ts +61 -42
  162. package/src/channels/types.ts +108 -0
  163. package/src/cli/__tests__/unknown-command.test.ts +24 -0
  164. package/src/cli/commands/__tests__/changelog.test.ts +304 -319
  165. package/src/cli/commands/__tests__/schedules.test.ts +491 -0
  166. package/src/cli/commands/changelog.ts +106 -42
  167. package/src/cli/commands/conversations.ts +102 -17
  168. package/src/cli/commands/default-action.ts +10 -53
  169. package/src/cli/commands/notifications.ts +329 -317
  170. package/src/cli/commands/plugins.ts +185 -0
  171. package/src/cli/commands/schedules.ts +391 -0
  172. package/src/cli/commands/telemetry.ts +40 -0
  173. package/src/cli/lib/__tests__/cli-colors.test.ts +48 -0
  174. package/src/cli/lib/__tests__/confirm-prompt.test.ts +159 -0
  175. package/src/cli/lib/__tests__/install-from-github.test.ts +355 -0
  176. package/src/cli/lib/__tests__/list-installed-plugins.test.ts +154 -0
  177. package/src/cli/lib/__tests__/uninstall-plugin.test.ts +124 -0
  178. package/src/cli/lib/__tests__/unknown-command.test.ts +106 -0
  179. package/src/cli/lib/cli-colors.ts +12 -0
  180. package/src/cli/lib/confirm-prompt.ts +79 -0
  181. package/src/cli/lib/install-from-github.ts +304 -0
  182. package/src/cli/lib/list-installed-plugins.ts +137 -0
  183. package/src/cli/lib/uninstall-plugin.ts +82 -0
  184. package/src/cli/lib/unknown-command.ts +111 -0
  185. package/src/cli/program.ts +38 -2
  186. package/src/config/bundled-skills/app-builder/SKILL.md +23 -21
  187. package/src/config/bundled-skills/app-builder/TOOLS.json +7 -0
  188. package/src/config/bundled-skills/computer-use/TOOLS.json +15 -52
  189. package/src/config/bundled-skills/document/SKILL.md +23 -3
  190. package/src/config/bundled-skills/document/TOOLS.json +53 -0
  191. package/src/config/bundled-skills/document/tools/document-delete.ts +12 -0
  192. package/src/config/bundled-skills/document/tools/document-list.ts +12 -0
  193. package/src/config/bundled-skills/document/tools/document-read.ts +12 -0
  194. package/src/config/bundled-skills/skill-management/SKILL.md +2 -2
  195. package/src/config/bundled-skills/skill-management/TOOLS.json +7 -7
  196. package/src/config/bundled-tool-registry.ts +6 -0
  197. package/src/config/feature-flag-registry.json +41 -1
  198. package/src/config/loader.ts +64 -38
  199. package/src/config/schema.ts +7 -10
  200. package/src/config/schemas/__tests__/llm-request-logs.test.ts +36 -0
  201. package/src/config/schemas/channels.ts +8 -0
  202. package/src/config/schemas/compaction.ts +28 -0
  203. package/src/config/schemas/heartbeat.ts +9 -0
  204. package/src/config/schemas/llm-request-logs.ts +31 -7
  205. package/src/config/schemas/llm.ts +3 -0
  206. package/src/config/schemas/memory-retrieval.ts +18 -0
  207. package/src/config/schemas/tools.ts +14 -0
  208. package/src/config/skills.ts +3 -96
  209. package/src/context/compactor.ts +1047 -0
  210. package/src/context/token-estimator.ts +2 -2
  211. package/src/context/window-manager.ts +197 -1520
  212. package/src/credential-execution/managed-catalog.ts +37 -0
  213. package/src/credential-health/credential-health-service.ts +280 -19
  214. package/src/daemon/__tests__/conversation-lifecycle-auto-analyze.test.ts +34 -0
  215. package/src/daemon/__tests__/conversation-tool-setup-exclude.test.ts +138 -0
  216. package/src/daemon/__tests__/conversation-tool-setup.test.ts +74 -0
  217. package/src/daemon/approval-generators.ts +8 -6
  218. package/src/daemon/config-watcher.ts +94 -31
  219. package/src/daemon/conversation-agent-loop.ts +169 -9
  220. package/src/daemon/conversation-error.ts +171 -37
  221. package/src/daemon/conversation-lifecycle.ts +53 -40
  222. package/src/daemon/conversation-messaging.ts +25 -6
  223. package/src/daemon/conversation-process.ts +49 -12
  224. package/src/daemon/conversation-runtime-assembly.ts +16 -1
  225. package/src/daemon/conversation-slash.ts +12 -5
  226. package/src/daemon/conversation-store.ts +11 -4
  227. package/src/daemon/conversation-tool-setup.ts +39 -7
  228. package/src/daemon/conversation.ts +33 -1
  229. package/src/daemon/external-plugins-bootstrap.ts +217 -181
  230. package/src/daemon/first-greeting.ts +22 -2
  231. package/src/daemon/handlers/config-model.ts +6 -5
  232. package/src/daemon/handlers/config-slack-channel.ts +15 -3
  233. package/src/daemon/handlers/shared.ts +14 -5
  234. package/src/daemon/handlers/skills.ts +111 -108
  235. package/src/daemon/history-repair.ts +28 -1
  236. package/src/daemon/host-app-control-proxy.ts +98 -23
  237. package/src/daemon/lifecycle.ts +45 -35
  238. package/src/daemon/meet-host-supervisor.ts +5 -4
  239. package/src/daemon/memory-v2-startup.ts +49 -0
  240. package/src/daemon/message-protocol.ts +1 -0
  241. package/src/daemon/message-types/conversations.ts +25 -0
  242. package/src/daemon/message-types/messages.ts +61 -0
  243. package/src/daemon/message-types/subagents.ts +1 -0
  244. package/src/daemon/message-types/sync.ts +1 -0
  245. package/src/daemon/pkb-reminder-builder.test.ts +1 -1
  246. package/src/daemon/pkb-reminder-builder.ts +1 -1
  247. package/src/daemon/plugin-source-watcher.ts +146 -0
  248. package/src/daemon/process-message.ts +21 -3
  249. package/src/daemon/server.ts +11 -2
  250. package/src/daemon/skill-memory-refresh.ts +29 -0
  251. package/src/documents/document-store.ts +221 -3
  252. package/src/embedded/plugin-api.ts +40 -0
  253. package/src/filing/filing-service.ts +39 -0
  254. package/src/heartbeat/__tests__/heartbeat-service.test.ts +91 -6
  255. package/src/heartbeat/heartbeat-run-store.ts +2 -1
  256. package/src/heartbeat/heartbeat-service.ts +41 -0
  257. package/src/home/__tests__/feed-types.test.ts +40 -0
  258. package/src/home/feed-types.ts +22 -0
  259. package/src/home/post-connect-feed.ts +1 -0
  260. package/src/index.ts +18 -1
  261. package/src/live-voice/__tests__/live-voice-stt.test.ts +57 -0
  262. package/src/mcp/client.ts +20 -4
  263. package/src/media/image-credentials.ts +3 -3
  264. package/src/memory/__tests__/bookmark-crud.test.ts +33 -27
  265. package/src/memory/__tests__/conversation-queries.test.ts +263 -0
  266. package/src/memory/__tests__/jobs-worker-v2-graph-trigger-embed.test.ts +113 -0
  267. package/src/memory/__tests__/memory-retrospective-startup-cleanup.test.ts +119 -14
  268. package/src/memory/__tests__/message-content.test.ts +35 -0
  269. package/src/memory/bookmark-crud.ts +42 -10
  270. package/src/memory/context-search/sources/conversations.ts +62 -2
  271. package/src/memory/context-search/sources/workspace.ts +4 -0
  272. package/src/memory/conversation-crud.ts +63 -19
  273. package/src/memory/conversation-queries.ts +110 -10
  274. package/src/memory/db-init.ts +6 -0
  275. package/src/memory/delivery-crud.ts +152 -5
  276. package/src/memory/embedding-backend.ts +4 -4
  277. package/src/memory/external-conversation-store.ts +66 -5
  278. package/src/memory/graph/__tests__/conversation-graph-memory-v2-routing.test.ts +66 -9
  279. package/src/memory/graph/conversation-graph-memory.ts +31 -15
  280. package/src/memory/graph/tools.ts +3 -3
  281. package/src/memory/indexer.ts +34 -29
  282. package/src/memory/jobs/__tests__/embed-concept-page.test.ts +73 -0
  283. package/src/memory/jobs/embed-concept-page.ts +20 -11
  284. package/src/memory/jobs-worker.ts +6 -1
  285. package/src/memory/llm-request-log-source-clickhouse.ts +17 -10
  286. package/src/memory/llm-request-log-source.ts +19 -52
  287. package/src/memory/llm-usage-store.ts +125 -5
  288. package/src/memory/memory-retrospective-startup-cleanup.ts +72 -5
  289. package/src/memory/message-content.ts +1 -1
  290. package/src/memory/migrations/109-external-conversation-bindings.ts +15 -4
  291. package/src/memory/migrations/229-delete-private-conversations.test.ts +38 -1
  292. package/src/memory/migrations/229-delete-private-conversations.ts +7 -0
  293. package/src/memory/migrations/247-external-conversation-binding-thread-id.ts +78 -0
  294. package/src/memory/migrations/248-create-onboarding-events.ts +21 -0
  295. package/src/memory/migrations/249-normalize-slack-external-content.ts +240 -0
  296. package/src/memory/migrations/index.ts +6 -0
  297. package/src/memory/migrations/registry.ts +8 -0
  298. package/src/memory/onboarding-events-store.ts +106 -0
  299. package/src/memory/schema/bookmarks.ts +0 -2
  300. package/src/memory/schema/calls.ts +1 -0
  301. package/src/memory/schema/inference.ts +1 -3
  302. package/src/memory/schema/infrastructure.ts +12 -0
  303. package/src/memory/turn-events-store.ts +127 -2
  304. package/src/memory/v2/__tests__/activation.test.ts +0 -8
  305. package/src/memory/v2/__tests__/injection.test.ts +98 -8
  306. package/src/memory/v2/__tests__/migration.test.ts +87 -0
  307. package/src/memory/v2/__tests__/page-index.test.ts +83 -0
  308. package/src/memory/v2/__tests__/prompts-router.test.ts +58 -6
  309. package/src/memory/v2/__tests__/qdrant.test.ts +66 -3
  310. package/src/memory/v2/__tests__/router.test.ts +15 -0
  311. package/src/memory/v2/__tests__/skill-store.test.ts +387 -8
  312. package/src/memory/v2/injection.ts +32 -6
  313. package/src/memory/v2/migration.ts +49 -19
  314. package/src/memory/v2/page-index.ts +35 -5
  315. package/src/memory/v2/prompts/router.ts +11 -8
  316. package/src/memory/v2/prompts/sweep.ts +2 -2
  317. package/src/memory/v2/qdrant.ts +135 -7
  318. package/src/memory/v2/router.ts +9 -8
  319. package/src/memory/v2/skill-store.ts +120 -35
  320. package/src/messaging/providers/slack/__tests__/adapter-token-routing.test.ts +45 -5
  321. package/src/messaging/providers/slack/__tests__/download.test.ts +231 -0
  322. package/src/messaging/providers/slack/adapter.ts +43 -5
  323. package/src/messaging/providers/slack/client.ts +27 -0
  324. package/src/messaging/providers/slack/deep-link.ts +65 -0
  325. package/src/messaging/providers/slack/download.ts +104 -0
  326. package/src/messaging/providers/slack/message-metadata.test.ts +32 -0
  327. package/src/messaging/providers/slack/message-metadata.ts +27 -0
  328. package/src/messaging/providers/slack/render-transcript.test.ts +134 -0
  329. package/src/messaging/providers/slack/render-transcript.ts +69 -5
  330. package/src/messaging/providers/slack/types.ts +20 -1
  331. package/src/notifications/conversation-pairing.ts +2 -1
  332. package/src/notifications/decision-engine.ts +2 -1
  333. package/src/notifications/emit-signal.ts +20 -1
  334. package/src/notifications/home-feed-side-effect.ts +54 -0
  335. package/src/notifications/signal.ts +3 -1
  336. package/src/oauth/connection-resolver.ts +8 -4
  337. package/src/oauth/platform-connection.ts +6 -2
  338. package/src/oauth/seed-providers.ts +10 -1
  339. package/src/permissions/checker.ts +2 -0
  340. package/src/permissions/ipc-risk-types.ts +1 -0
  341. package/src/permissions/question-prompter.test.ts +416 -0
  342. package/src/permissions/question-prompter.ts +294 -0
  343. package/src/platform/client.test.ts +1 -1
  344. package/src/platform/client.ts +1 -1
  345. package/src/plugin-api/constants.ts +26 -0
  346. package/src/plugin-api/index.ts +34 -1
  347. package/src/plugin-api/types.ts +104 -22
  348. package/src/plugins/defaults/circuit-breaker.ts +0 -5
  349. package/src/plugins/defaults/compaction.ts +0 -4
  350. package/src/plugins/defaults/empty-response.ts +0 -2
  351. package/src/plugins/defaults/history-repair.ts +0 -2
  352. package/src/plugins/defaults/injectors.ts +36 -3
  353. package/src/plugins/defaults/llm-call.ts +0 -2
  354. package/src/plugins/defaults/memory-retrieval.ts +0 -1
  355. package/src/plugins/defaults/overflow-reduce.ts +0 -1
  356. package/src/plugins/defaults/persistence.ts +0 -2
  357. package/src/plugins/defaults/title-generate.ts +0 -5
  358. package/src/plugins/defaults/token-estimate.ts +0 -2
  359. package/src/plugins/defaults/tool-error.ts +0 -7
  360. package/src/plugins/defaults/tool-execute.ts +0 -2
  361. package/src/plugins/defaults/tool-result-truncate.ts +0 -4
  362. package/src/plugins/ensure-plugin-api-shim.ts +96 -0
  363. package/src/plugins/external-api.ts +104 -0
  364. package/src/plugins/external-plugin-loader.ts +105 -32
  365. package/src/plugins/feature-gate.ts +22 -0
  366. package/src/plugins/pipeline.ts +37 -0
  367. package/src/plugins/registry.ts +48 -80
  368. package/src/plugins/types.ts +31 -26
  369. package/src/plugins/user-loader.ts +21 -2
  370. package/src/proactive-artifact/aux-message-injector.ts +11 -0
  371. package/src/proactive-artifact/job.test.ts +37 -5
  372. package/src/prompts/__tests__/system-prompt.test.ts +12 -0
  373. package/src/prompts/__tests__/task-progress-hint-section.test.ts +99 -0
  374. package/src/prompts/normalize-onboarding.ts +27 -0
  375. package/src/prompts/sections.ts +302 -0
  376. package/src/prompts/system-prompt.ts +63 -166
  377. package/src/prompts/templates/BOOTSTRAP.md +17 -1
  378. package/src/prompts/templates/system-sections.ts +173 -0
  379. package/src/providers/__tests__/inference.test.ts +22 -7
  380. package/src/providers/anthropic/client.ts +28 -28
  381. package/src/providers/connection-resolution.ts +7 -0
  382. package/src/providers/inference/adapter-factory.ts +41 -4
  383. package/src/providers/inference/connections.ts +74 -29
  384. package/src/providers/inference/resolve-auth.ts +12 -4
  385. package/src/providers/model-catalog.ts +294 -12
  386. package/src/providers/openai/chat-completions-provider.ts +10 -2
  387. package/src/providers/openrouter/client.ts +7 -0
  388. package/src/providers/{managed-proxy → platform-proxy}/constants.ts +4 -1
  389. package/src/providers/{managed-proxy → platform-proxy}/context.ts +3 -3
  390. package/src/providers/provider-availability.ts +17 -2
  391. package/src/providers/provider-catalog-visibility.ts +36 -0
  392. package/src/providers/registry.ts +22 -14
  393. package/src/providers/retry.ts +47 -1
  394. package/src/runtime/__tests__/agent-wake.test.ts +152 -0
  395. package/src/runtime/agent-wake.ts +42 -14
  396. package/src/runtime/auth/route-policy.ts +8 -1
  397. package/src/runtime/btw-sidechain.ts +2 -0
  398. package/src/runtime/http-types.ts +19 -0
  399. package/src/runtime/migrations/origin-mode.ts +1 -1
  400. package/src/runtime/pending-interactions.ts +1 -0
  401. package/src/runtime/routes/__tests__/bookmark-routes.test.ts +17 -0
  402. package/src/runtime/routes/__tests__/conversation-management-routes.test.ts +5 -1
  403. package/src/runtime/routes/__tests__/conversation-query-routes.test.ts +107 -20
  404. package/src/runtime/routes/__tests__/question-routes.test.ts +395 -0
  405. package/src/runtime/routes/__tests__/tts-routes.test.ts +64 -1
  406. package/src/runtime/routes/acp-routes-list.test.ts +143 -0
  407. package/src/runtime/routes/acp-routes.ts +5 -3
  408. package/src/runtime/routes/auth-routes.ts +1 -1
  409. package/src/runtime/routes/bookmark-routes.ts +5 -3
  410. package/src/runtime/routes/btw-routes.ts +5 -1
  411. package/src/runtime/routes/channel-availability-routes.ts +121 -0
  412. package/src/runtime/routes/conversation-cli-routes.ts +44 -3
  413. package/src/runtime/routes/conversation-list-routes.ts +3 -20
  414. package/src/runtime/routes/conversation-management-routes.ts +17 -42
  415. package/src/runtime/routes/conversation-query-routes.ts +40 -35
  416. package/src/runtime/routes/conversation-routes.ts +90 -11
  417. package/src/runtime/routes/documents-routes.ts +25 -86
  418. package/src/runtime/routes/group-routes.ts +5 -0
  419. package/src/runtime/routes/inbound-conversation.ts +28 -8
  420. package/src/runtime/routes/inbound-message-handler.ts +236 -41
  421. package/src/runtime/routes/inbound-stages/background-dispatch.test.ts +111 -0
  422. package/src/runtime/routes/inbound-stages/background-dispatch.ts +32 -1
  423. package/src/runtime/routes/inbound-stages/edit-intercept.ts +17 -4
  424. package/src/runtime/routes/index.ts +6 -0
  425. package/src/runtime/routes/inference-profile-session-handler.ts +17 -44
  426. package/src/runtime/routes/inference-profile-session-reaper.ts +7 -21
  427. package/src/runtime/routes/inference-provider-connection-routes.ts +65 -21
  428. package/src/runtime/routes/integrations/slack/share.ts +4 -52
  429. package/src/runtime/routes/integrations/slack/token.ts +43 -0
  430. package/src/runtime/routes/integrations/twilio.ts +6 -13
  431. package/src/runtime/routes/notification-routes.ts +1 -1
  432. package/src/runtime/routes/oauth-commands-routes.ts +105 -15
  433. package/src/runtime/routes/oauth-lifecycle-routes.ts +43 -0
  434. package/src/runtime/routes/question-routes.ts +259 -0
  435. package/src/runtime/routes/rename-conversation-routes.ts +2 -33
  436. package/src/runtime/routes/schedule-routes.ts +4 -7
  437. package/src/runtime/routes/subagents-routes.ts +57 -18
  438. package/src/runtime/routes/telemetry-routes.ts +27 -0
  439. package/src/runtime/routes/tts-routes.ts +27 -2
  440. package/src/runtime/routes/workspace-routes.test.ts +43 -0
  441. package/src/runtime/routes/workspace-routes.ts +28 -0
  442. package/src/runtime/services/conversation-serializer.ts +39 -7
  443. package/src/runtime/sync/resource-sync-events.ts +93 -1
  444. package/src/schedule/schedule-store.ts +27 -2
  445. package/src/schedule/scheduler.ts +9 -1
  446. package/src/security/__tests__/untrusted-content.test.ts +86 -0
  447. package/src/security/untrusted-content.ts +93 -8
  448. package/src/skills/catalog-files.ts +1 -1
  449. package/src/skills/catalog-install.ts +233 -116
  450. package/src/skills/clawhub.ts +70 -13
  451. package/src/skills/managed-store.ts +4 -119
  452. package/src/skills/skillssh-registry.ts +27 -48
  453. package/src/subagent/manager.ts +15 -7
  454. package/src/telemetry/types.ts +113 -1
  455. package/src/telemetry/usage-telemetry-reporter.test.ts +312 -5
  456. package/src/telemetry/usage-telemetry-reporter.ts +113 -7
  457. package/src/tools/apps/executors.ts +58 -7
  458. package/src/tools/ask-question/ask-question-tool.test.ts +509 -0
  459. package/src/tools/ask-question/ask-question-tool.ts +304 -0
  460. package/src/tools/browser/browser-execution.ts +15 -11
  461. package/src/tools/computer-use/definitions.ts +3 -3
  462. package/src/tools/credentials/vault.ts +1 -1
  463. package/src/tools/document/document-tool.ts +124 -1
  464. package/src/tools/filesystem/edit.ts +1 -1
  465. package/src/tools/filesystem/list.ts +1 -1
  466. package/src/tools/filesystem/read.ts +1 -1
  467. package/src/tools/filesystem/write.ts +5 -2
  468. package/src/tools/host-filesystem/transfer.ts +1 -1
  469. package/src/tools/host-terminal/host-shell.ts +1 -1
  470. package/src/tools/permission-checker.ts +1 -1
  471. package/src/tools/registry.ts +17 -7
  472. package/src/tools/schedule/create.ts +2 -2
  473. package/src/tools/schema-transforms.ts +7 -2
  474. package/src/tools/side-effects.ts +1 -0
  475. package/src/tools/skills/delete-managed.ts +4 -4
  476. package/src/tools/skills/execute.ts +1 -1
  477. package/src/tools/skills/scaffold-managed.ts +3 -2
  478. package/src/tools/subagent/notify-parent.ts +1 -1
  479. package/src/tools/system/request-permission.ts +2 -2
  480. package/src/tools/terminal/safe-env.ts +60 -1
  481. package/src/tools/tool-manifest.ts +2 -0
  482. package/src/tools/types.ts +72 -21
  483. package/src/tools/ui-surface/definitions.ts +6 -5
  484. package/src/tts/__tests__/provider-adapters.test.ts +76 -2
  485. package/src/tts/providers/elevenlabs-provider.ts +75 -1
  486. package/src/types/onboarding-context.ts +2 -0
  487. package/src/util/errors.ts +17 -0
  488. package/src/util/platform.ts +10 -0
  489. package/src/watcher/__tests__/engine.test.ts +22 -0
  490. package/src/watcher/engine.ts +6 -2
  491. package/src/workspace/migrations/057-repair-stale-gemini-model-ids.ts +80 -15
  492. package/src/workspace/migrations/072-seed-reply-suggestion-callsite.ts +35 -22
  493. package/src/workspace/migrations/073-repair-recall-callsite-empty-profile.ts +3 -1
  494. package/src/workspace/migrations/083-system-prompt-prefix-to-file.ts +191 -0
  495. package/src/workspace/migrations/084-remove-legacy-skills-index.ts +276 -0
  496. package/src/workspace/migrations/085-memory-v2-bm25-b-reembed-disabled-v2-pages.ts +137 -0
  497. package/src/workspace/migrations/086-revert-stale-gemini-mis-rewrites.ts +198 -0
  498. package/src/workspace/migrations/registry.ts +8 -0
  499. package/src/workspace/migrations/runner.ts +39 -9
  500. package/src/workspace/migrations/types.ts +4 -0
  501. package/examples/plugins/echo/bun.lock +0 -25
  502. package/src/__tests__/context-window-manager.test.ts +0 -2481
  503. package/src/context/__tests__/compact-prompt.test.ts +0 -63
  504. package/src/context/prompts/compact.md +0 -26
  505. package/src/prompts/__tests__/build-cli-reference-section.test.ts +0 -37
  506. /package/src/__tests__/{secret-routes-managed-proxy.test.ts → secret-routes-platform-proxy.test.ts} +0 -0
@@ -31,8 +31,12 @@ import { extractPreferences } from "../notifications/preference-extractor.js";
31
31
  import { createPreference } from "../notifications/preferences-store.js";
32
32
  import type { Message } from "../providers/types.js";
33
33
  import { routeGuardianReply } from "../runtime/guardian-reply-router.js";
34
+ import { publishConversationMessagesChanged } from "../runtime/sync/resource-sync-events.js";
34
35
  import { getLogger } from "../util/logger.js";
35
- import { persistQueuedMessageBody } from "./conversation-messaging.js";
36
+ import {
37
+ persistQueuedMessageBody,
38
+ serializePersistedUserMessageContent,
39
+ } from "./conversation-messaging.js";
36
40
  import type {
37
41
  MessageQueue,
38
42
  QueuedMessage,
@@ -513,11 +517,11 @@ async function drainSingleMessage(
513
517
  // When displayContent is provided (e.g. original text before recording
514
518
  // intent stripping), persist that to DB so users see the full message.
515
519
  // The in-memory userMessage (sent to the LLM) still uses the stripped content.
516
- const contentToPersist = next.displayContent
517
- ? JSON.stringify(
518
- createUserMessage(next.displayContent, next.attachments).content,
519
- )
520
- : JSON.stringify(cleanUserMsg.content);
520
+ const contentToPersist = serializePersistedUserMessageContent(
521
+ next.content,
522
+ next.attachments,
523
+ next.displayContent,
524
+ );
521
525
  await addMessage(
522
526
  conversation.conversationId,
523
527
  "user",
@@ -570,6 +574,7 @@ async function drainSingleMessage(
570
574
  type: "message_complete",
571
575
  conversationId: conversation.conversationId,
572
576
  });
577
+ publishConversationMessagesChanged(conversation.conversationId);
573
578
  } catch (err) {
574
579
  const message = err instanceof Error ? err.message : String(err);
575
580
  log.error(
@@ -602,6 +607,7 @@ async function drainSingleMessage(
602
607
 
603
608
  // /compact — force context compaction, persist exchange, continue draining.
604
609
  if (slashResult.kind === "compact") {
610
+ let persistedCompactMessage = false;
605
611
  try {
606
612
  const drainProvenance = provenanceFromTrustContext(
607
613
  conversation.trustContext,
@@ -627,9 +633,14 @@ async function drainSingleMessage(
627
633
  await addMessage(
628
634
  conversation.conversationId,
629
635
  "user",
630
- JSON.stringify(cleanUserMsg.content),
636
+ serializePersistedUserMessageContent(
637
+ next.content,
638
+ next.attachments,
639
+ next.displayContent,
640
+ ),
631
641
  drainChannelMeta,
632
642
  );
643
+ persistedCompactMessage = true;
633
644
  conversation.messages.push(cleanUserMsg);
634
645
 
635
646
  conversation.emitActivityState(
@@ -666,7 +677,11 @@ async function drainSingleMessage(
666
677
  type: "message_complete",
667
678
  conversationId: conversation.conversationId,
668
679
  });
680
+ publishConversationMessagesChanged(conversation.conversationId);
669
681
  } catch (err) {
682
+ if (persistedCompactMessage) {
683
+ publishConversationMessagesChanged(conversation.conversationId);
684
+ }
670
685
  const message = err instanceof Error ? err.message : String(err);
671
686
  log.error(
672
687
  {
@@ -762,6 +777,7 @@ async function drainSingleMessage(
762
777
  requestId: next.requestId,
763
778
  clientMessageId: next.clientMessageId,
764
779
  });
780
+ publishConversationMessagesChanged(conversation.conversationId);
765
781
 
766
782
  // Set the active surface for the dequeued message so runAgentLoop can inject context
767
783
  conversation.currentActiveSurfaceId = next.activeSurfaceId;
@@ -1087,6 +1103,7 @@ async function drainBatch(
1087
1103
  requestId: qm.requestId,
1088
1104
  clientMessageId: qm.clientMessageId,
1089
1105
  });
1106
+ publishConversationMessagesChanged(conversation.conversationId);
1090
1107
 
1091
1108
  // Persist succeeded. Update last-successful markers so a later tail
1092
1109
  // failure won't overwrite them.
@@ -1306,7 +1323,11 @@ export async function processMessage(
1306
1323
  const persisted = await addMessage(
1307
1324
  conversation.conversationId,
1308
1325
  "user",
1309
- JSON.stringify(cleanUserMsg.content),
1326
+ serializePersistedUserMessageContent(
1327
+ content,
1328
+ attachments,
1329
+ displayContent,
1330
+ ),
1310
1331
  routerChannelMeta,
1311
1332
  );
1312
1333
  conversation.messages.push(llmUserMsg);
@@ -1391,9 +1412,11 @@ export async function processMessage(
1391
1412
  // When displayContent is provided (e.g. original text before recording
1392
1413
  // intent stripping), persist that to DB so users see the full message.
1393
1414
  // The in-memory userMessage (sent to the LLM) still uses the stripped content.
1394
- const contentToPersist = displayContent
1395
- ? JSON.stringify(createUserMessage(displayContent, attachments).content)
1396
- : JSON.stringify(cleanUserMsg.content);
1415
+ const contentToPersist = serializePersistedUserMessageContent(
1416
+ content,
1417
+ attachments,
1418
+ displayContent,
1419
+ );
1397
1420
  const persisted = await addMessage(
1398
1421
  conversation.conversationId,
1399
1422
  "user",
@@ -1446,12 +1469,14 @@ export async function processMessage(
1446
1469
  type: "message_complete",
1447
1470
  conversationId: conversation.conversationId,
1448
1471
  });
1472
+ publishConversationMessagesChanged(conversation.conversationId);
1449
1473
  return persisted.id;
1450
1474
  }
1451
1475
 
1452
1476
  // /compact — force context compaction, persist exchange, return message ID.
1453
1477
  if (slashResult.kind === "compact") {
1454
1478
  conversation.processing = true;
1479
+ let persistedCompactMessage = false;
1455
1480
  try {
1456
1481
  const pmTurnCtx = conversation.getTurnChannelContext();
1457
1482
  const pmInterfaceCtx = conversation.getTurnInterfaceContext();
@@ -1478,9 +1503,14 @@ export async function processMessage(
1478
1503
  const persisted = await addMessage(
1479
1504
  conversation.conversationId,
1480
1505
  "user",
1481
- JSON.stringify(cleanUserMsg.content),
1506
+ serializePersistedUserMessageContent(
1507
+ content,
1508
+ attachments,
1509
+ displayContent,
1510
+ ),
1482
1511
  pmChannelMeta,
1483
1512
  );
1513
+ persistedCompactMessage = true;
1484
1514
  conversation.messages.push(cleanUserMsg);
1485
1515
 
1486
1516
  conversation.emitActivityState(
@@ -1517,7 +1547,13 @@ export async function processMessage(
1517
1547
  type: "message_complete",
1518
1548
  conversationId: conversation.conversationId,
1519
1549
  });
1550
+ publishConversationMessagesChanged(conversation.conversationId);
1520
1551
  return persisted.id;
1552
+ } catch (err) {
1553
+ if (persistedCompactMessage) {
1554
+ publishConversationMessagesChanged(conversation.conversationId);
1555
+ }
1556
+ throw err;
1521
1557
  } finally {
1522
1558
  conversation.processing = false;
1523
1559
  await drainQueue(conversation);
@@ -1557,6 +1593,7 @@ export async function processMessage(
1557
1593
  undefined,
1558
1594
  displayContent,
1559
1595
  );
1596
+ publishConversationMessagesChanged(conversation.conversationId);
1560
1597
  } catch (err) {
1561
1598
  const message = err instanceof Error ? err.message : String(err);
1562
1599
  onEvent({
@@ -1182,12 +1182,23 @@ function placeholderForBlockType(type: ContentBlock["type"]): string | null {
1182
1182
  */
1183
1183
  function rowToRenderable(row: SlackTranscriptInputRow): RenderableSlackMessage {
1184
1184
  let slackMeta: ReturnType<typeof readSlackMetadata> = null;
1185
+ let provenanceTrustClass: TrustClass | undefined;
1185
1186
  if (row.metadata) {
1186
1187
  try {
1187
- const outer = JSON.parse(row.metadata) as { slackMeta?: unknown };
1188
+ const outer = JSON.parse(row.metadata) as {
1189
+ slackMeta?: unknown;
1190
+ provenanceTrustClass?: unknown;
1191
+ };
1188
1192
  if (typeof outer.slackMeta === "string") {
1189
1193
  slackMeta = readSlackMetadata(outer.slackMeta);
1190
1194
  }
1195
+ if (
1196
+ outer.provenanceTrustClass === "guardian" ||
1197
+ outer.provenanceTrustClass === "trusted_contact" ||
1198
+ outer.provenanceTrustClass === "unknown"
1199
+ ) {
1200
+ provenanceTrustClass = outer.provenanceTrustClass;
1201
+ }
1191
1202
  } catch {
1192
1203
  // Malformed metadata — fall through to legacy/null treatment.
1193
1204
  }
@@ -1252,6 +1263,8 @@ function rowToRenderable(row: SlackTranscriptInputRow): RenderableSlackMessage {
1252
1263
  senderLabel,
1253
1264
  createdAt: row.createdAt,
1254
1265
  contentBlocks,
1266
+ wrapContentForModel:
1267
+ row.role === "user" && !isReaction && provenanceTrustClass !== "guardian",
1255
1268
  };
1256
1269
  }
1257
1270
 
@@ -1989,6 +2002,7 @@ export interface RuntimeInjectionOptions {
1989
2002
  * `undefined` when the inbound is a top-level (non-thread) post.
1990
2003
  */
1991
2004
  slackActiveThreadFocusBlock?: string | null;
2005
+ activeDocuments?: TurnInjectionInputs["activeDocuments"];
1992
2006
  mode?: InjectionMode;
1993
2007
  /**
1994
2008
  * Per-turn {@link TurnContext} forwarded to plugin-registered
@@ -2042,6 +2056,7 @@ function buildTurnInjectionInputs(
2042
2056
  voiceCallControlPrompt: options.voiceCallControlPrompt,
2043
2057
  transportHints: options.transportHints,
2044
2058
  isNonInteractive: options.isNonInteractive,
2059
+ activeDocuments: options.activeDocuments,
2045
2060
  };
2046
2061
  }
2047
2062
 
@@ -8,8 +8,8 @@ import {
8
8
  saveRawConfig,
9
9
  } from "../config/loader.js";
10
10
  import { getConversationOverrideProfile } from "../memory/conversation-crud.js";
11
- import { PROVIDER_CATALOG } from "../providers/model-catalog.js";
12
11
  import { getConfiguredProviders } from "../providers/provider-availability.js";
12
+ import { getVisibleProviderCatalog } from "../providers/provider-catalog-visibility.js";
13
13
 
14
14
  export type SlashResolution =
15
15
  | { kind: "passthrough"; content: string }
@@ -132,7 +132,10 @@ function parseModelCommand(trimmed: string): ModelCommandParse | null {
132
132
  }
133
133
 
134
134
  function orderedProfileNames(
135
- profiles: Record<string, { label?: string; description?: string; status?: "active" | "disabled" }>,
135
+ profiles: Record<
136
+ string,
137
+ { label?: string; description?: string; status?: "active" | "disabled" }
138
+ >,
136
139
  profileOrder: readonly string[] | undefined,
137
140
  ): string[] {
138
141
  const order = profileOrder ?? [];
@@ -177,8 +180,12 @@ async function resolveModelCommand(
177
180
  const isDisabled = profile.status === "disabled";
178
181
  const marker = isCurrent ? " **[current]**" : "";
179
182
  const disabled = isDisabled ? " *(disabled)*" : "";
180
- const description = profile.description ? ` — ${profile.description}` : "";
181
- lines.push(` - \`${name}\` (${label})${marker}${disabled}${description}`);
183
+ const description = profile.description
184
+ ? ` ${profile.description}`
185
+ : "";
186
+ lines.push(
187
+ ` - \`${name}\` (${label})${marker}${disabled}${description}`,
188
+ );
182
189
  }
183
190
  lines.push("\nSwitch with `/model <name>`.");
184
191
  return { kind: "unknown", message: lines.join("\n") };
@@ -240,7 +247,7 @@ async function resolveModelList(): Promise<SlashResolution> {
240
247
  id: provider,
241
248
  displayName: providerName,
242
249
  models,
243
- } of PROVIDER_CATALOG) {
250
+ } of getVisibleProviderCatalog(config)) {
244
251
  const hasKey = configuredProviders.has(provider);
245
252
  const status = hasKey ? "✓" : "✗";
246
253
  lines.push(`**${providerName}** ${status}`);
@@ -21,7 +21,9 @@ import { buildSystemPrompt } from "../prompts/system-prompt.js";
21
21
  import { wrapWithCallSiteRouting } from "../providers/call-site-routing.js";
22
22
  import { resolveDefaultProvider } from "../providers/connection-resolution.js";
23
23
  import { RateLimitProvider } from "../providers/ratelimit.js";
24
+ import { listProviders } from "../providers/registry.js";
24
25
  import { getSubagentManager } from "../subagent/index.js";
26
+ import { ProviderNotConfiguredError } from "../util/errors.js";
25
27
  import { getSandboxWorkingDir } from "../util/platform.js";
26
28
  import { Conversation } from "./conversation.js";
27
29
  import type { ConversationEvictor } from "./conversation-evictor.js";
@@ -226,12 +228,17 @@ export async function getOrCreateConversation(
226
228
  // Connection-aware default-provider resolution. Throws
227
229
  // `ConnectionResolutionError` when the default profile's
228
230
  // `provider_connection` is unset / unknown / mismatched (config
229
- // bugs). Returns null on soft credential failures (handled below
230
- // as "default provider not registered").
231
+ // bugs). Returns null on soft credential failures (missing
232
+ // credential, platform auth unavailable).
231
233
  const baseProvider = await resolveDefaultProvider(config);
232
234
  if (!baseProvider) {
233
- throw new Error(
234
- `Conversation: default provider '${resolveCallSiteConfig("mainAgent", config.llm).provider}' is not registered`,
235
+ const resolved = resolveCallSiteConfig("mainAgent", config.llm);
236
+ throw new ProviderNotConfiguredError(
237
+ resolved.provider,
238
+ listProviders(),
239
+ {
240
+ connectionName: resolved.provider_connection,
241
+ },
235
242
  );
236
243
  }
237
244
  // Per-call `callSite` routing layered on top, with connection-awareness
@@ -13,6 +13,7 @@ import {
13
13
  } from "../channels/types.js";
14
14
  import { isHttpAuthDisabled } from "../config/env.js";
15
15
  import { getIsPlatform } from "../config/env-registry.js";
16
+ import { getConfig } from "../config/loader.js";
16
17
  import { getBindingByConversation } from "../memory/external-conversation-store.js";
17
18
  import type { PermissionPrompter } from "../permissions/prompter.js";
18
19
  import type { SecretPrompter } from "../permissions/secret-prompter.js";
@@ -392,7 +393,8 @@ const CROSS_CLIENT_EXPOSED_CAPABILITIES = new Set<HostProxyCapability>([
392
393
  "host_file",
393
394
  "host_browser",
394
395
  ]);
395
- const CLIENT_CAPABILITY_TOOL_NAMES = new Set(["app_open"]);
396
+ // Tools that require a connected client but no specific host proxy capability.
397
+ const CLIENT_CAPABILITY_TOOL_NAMES = new Set(["app_open", "ask_question"]);
396
398
  const PLATFORM_TOOL_NAMES = new Set(["request_system_permission"]);
397
399
 
398
400
  /**
@@ -406,16 +408,34 @@ export const SUBAGENT_ONLY_TOOL_NAMES = new Set<string>([
406
408
  ]);
407
409
 
408
410
  /**
409
- * Determine whether a tool should be included in the LLM tool definitions
410
- * for the current turn based on conversation context. Tools not active for the
411
- * current context are omitted from the definitions sent to the provider,
412
- * reducing noise and preventing the model from attempting calls that would
413
- * fail.
411
+ * Determine whether a tool is part of the final exposed tool set for the
412
+ * current turn. This helper mirrors the filtering applied by
413
+ * `createResolveToolsCallback` including the subagent allowlist,
414
+ * `toolsDisabledDepth`, and disk-pressure cleanup restrictions.
414
415
  */
415
416
  export function isToolActiveForContext(
416
417
  name: string,
417
418
  ctx: SkillProjectionContext,
418
419
  ): boolean {
420
+ // When the conversation is acting as a subagent, the parent orchestrator
421
+ // restricts the tool list. A tool that isn't on the allowlist is not
422
+ // available for this turn, so short-circuit before any capability checks.
423
+ if (ctx.subagentAllowedTools && !ctx.subagentAllowedTools.has(name)) {
424
+ return false;
425
+ }
426
+ // `createResolveToolsCallback` returns an empty tool list when tools are
427
+ // disabled (e.g. pointer-generation turns) and restricts to cleanup-safe
428
+ // tools under disk pressure. Mirror both here so this helper reports the
429
+ // same final tool set the LLM receives.
430
+ if (ctx.toolsDisabledDepth > 0) {
431
+ return false;
432
+ }
433
+ if (
434
+ ctx.diskPressureCleanupModeActive === true &&
435
+ !isDiskPressureCleanupToolName(name)
436
+ ) {
437
+ return false;
438
+ }
419
439
  if (UI_SURFACE_TOOL_NAMES.has(name)) {
420
440
  return ctx.channelCapabilities?.supportsDynamicUi ?? !ctx.hasNoClient;
421
441
  }
@@ -463,6 +483,14 @@ export function isToolActiveForContext(
463
483
  return !ctx.hasNoClient;
464
484
  }
465
485
  if (CLIENT_CAPABILITY_TOOL_NAMES.has(name)) {
486
+ if (
487
+ name === "ask_question" &&
488
+ ctx.channelCapabilities?.clientOS === "macos"
489
+ ) {
490
+ // macOS has no UI handler for question_request yet; hiding the tool
491
+ // avoids a 5-minute prompter timeout when the LLM would otherwise call it.
492
+ return false;
493
+ }
466
494
  return !ctx.hasNoClient;
467
495
  }
468
496
  if (PLATFORM_TOOL_NAMES.has(name)) {
@@ -544,7 +572,10 @@ export function createResolveToolsCallback(
544
572
  const scopedMcpDefs = ctx.subagentAllowedTools
545
573
  ? currentMcpDefs.filter((d) => ctx.subagentAllowedTools!.has(d.name))
546
574
  : currentMcpDefs;
547
- const allBaseDefs = [...scopedCoreDefs, ...scopedMcpDefs];
575
+ const excluded = new Set(getConfig().tools.exclude);
576
+ const allBaseDefs = [...scopedCoreDefs, ...scopedMcpDefs].filter(
577
+ (d) => !excluded.has(d.name),
578
+ );
548
579
 
549
580
  const effectivePreactivated = [
550
581
  ...DEFAULT_PREACTIVATED_SKILL_IDS,
@@ -561,6 +592,7 @@ export function createResolveToolsCallback(
561
592
  if (ctx.subagentAllowedTools && !ctx.subagentAllowedTools.has(name)) {
562
593
  continue;
563
594
  }
595
+ if (excluded.has(name)) continue;
564
596
  turnAllowed.add(name);
565
597
  }
566
598
  if (ctx.diskPressureCleanupModeActive === true) {
@@ -56,6 +56,7 @@ import {
56
56
  } from "../memory/conversation-crud.js";
57
57
  import { isBackgroundConversationType } from "../memory/conversation-types.js";
58
58
  import { ConversationGraphMemory } from "../memory/graph/conversation-graph-memory.js";
59
+ import { shouldExposePersonalMemory } from "../memory/v2/static-context.js";
59
60
  import { PermissionPrompter } from "../permissions/prompter.js";
60
61
  import { SecretPrompter } from "../permissions/secret-prompter.js";
61
62
  import type { UserDecision } from "../permissions/types.js";
@@ -118,6 +119,7 @@ import {
118
119
  buildToolDefinitions,
119
120
  createResolveToolsCallback,
120
121
  createToolExecutor,
122
+ resolveTrustClass,
121
123
  } from "./conversation-tool-setup.js";
122
124
  import { refreshWorkspaceTopLevelContextIfNeeded as refreshWorkspaceImpl } from "./conversation-workspace.js";
123
125
  import { canonicalizeTimeZone } from "./date-context.js";
@@ -180,6 +182,17 @@ export class Conversation {
180
182
  /** @internal */ contextWindowManager: ContextWindowManager;
181
183
  /** @internal */ contextCompactedMessageCount = 0;
182
184
  /** @internal */ contextCompactedAt: number | null = null;
185
+ /**
186
+ * Set true by `applyCompactionResult` when compaction strips runtime
187
+ * injections from the tail. The next agent loop turn reads this flag at
188
+ * entry, treats it as a `compactedThisTurn` trigger (re-injecting NOW.md,
189
+ * PKB, and the v2 essentials/threads/recent/buffer block), and clears it.
190
+ *
191
+ * Required because `/compact` runs outside the agent loop — without this
192
+ * signal, the next turn cannot tell that the static blocks were just
193
+ * stripped and never re-emits them.
194
+ */
195
+ /** @internal */ pendingPostCompactReinject = false;
183
196
  /**
184
197
  * Tracks consecutive compaction failures (summary LLM call threw). In-memory
185
198
  * only — resets to 0 on process restart, which is the intended "one free
@@ -225,6 +238,7 @@ export class Conversation {
225
238
  /** @internal */ currentTurnOverrideProfile?: string;
226
239
  /** @internal */ authContext?: AuthContext;
227
240
  /** @internal */ loadedHistoryTrustClass?: TrustClass;
241
+ /** @internal */ loadedHistoryPersonalMemoryAllowed?: boolean;
228
242
  /** @internal */ voiceCallControlPrompt?: string;
229
243
  /** @internal */ transportHints?: string[];
230
244
  /** @internal */ slackRuntimeContextNotice?: string;
@@ -527,6 +541,10 @@ export class Conversation {
527
541
  systemPrompt: () => resolveSystemPromptCallback([]).systemPrompt,
528
542
  config: initialContextWindowConfig,
529
543
  toolTokenBudget: this.agentLoop.getToolTokenBudget(),
544
+ conversationId: this.conversationId,
545
+ resolveTools: resolveTools
546
+ ? () => resolveTools(this.messages)
547
+ : undefined,
530
548
  });
531
549
  }
532
550
 
@@ -647,7 +665,21 @@ export class Conversation {
647
665
 
648
666
  async ensureActorScopedHistory(): Promise<void> {
649
667
  const currentTrustClass = this.trustContext?.trustClass;
650
- if (this.loadedHistoryTrustClass === currentTrustClass) return;
668
+ // `loadFromDb` gates personal-memory rehydration on `sourceChannel` too
669
+ // (via `shouldExposePersonalMemory`), so a same-trust-class reuse from a
670
+ // different channel (e.g. internal `vellum` → remote channel) must also
671
+ // trigger a reload. Otherwise stale personal-memory blocks can leak to
672
+ // an untrusted remote turn, or be hidden when they should be present.
673
+ const currentPersonalMemoryAllowed = shouldExposePersonalMemory({
674
+ sourceChannel: this.trustContext?.sourceChannel,
675
+ isTrustedActor: resolveTrustClass(this.trustContext) === "guardian",
676
+ });
677
+ if (
678
+ this.loadedHistoryTrustClass === currentTrustClass &&
679
+ this.loadedHistoryPersonalMemoryAllowed === currentPersonalMemoryAllowed
680
+ ) {
681
+ return;
682
+ }
651
683
  await this.loadFromDb();
652
684
  }
653
685