@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
@@ -72,6 +72,40 @@ const RETRYABLE_STREAM_PATTERNS = [
72
72
  */
73
73
  const RETRYABLE_PROVIDER_MESSAGE_PATTERNS = [/overloaded/i];
74
74
 
75
+ /**
76
+ * Patterns that indicate the Anthropic provider SDK reported a transport-level
77
+ * abort (TCP close mid-stream, edge LB idle cutoff, Bun fetch deadline) rather
78
+ * than a caller-initiated cancellation or inner-timeout deadline. The SDK
79
+ * surfaces all three cases as ``Request was aborted`` with ``error.status ===
80
+ * undefined``; the catch-site in ``providers/anthropic/client.ts`` separates
81
+ * them by:
82
+ * - tagging caller cancellations with ``abortReason`` (short-circuits in
83
+ * {@link isRetryableError} before reaching this predicate)
84
+ * - rewriting the inner-timeout message to ``"Anthropic stream timed out
85
+ * after Xs (inner streamTimeoutMs)"`` (doesn't start with ``Anthropic API
86
+ * error:`` so it falls through to network-error classification)
87
+ * - leaving the transport-abort message verbatim as
88
+ * ``"Anthropic API error: Request was aborted."``
89
+ *
90
+ * Pattern is intentionally anchored to the Anthropic-specific message prefix.
91
+ * The OpenAI / Gemini / OpenRouter catch-sites format their errors as
92
+ * ``"<Provider> API error (undefined): Request was aborted."`` (note the
93
+ * ``(undefined)`` parenthetical) and — crucially — do **not** rewrite
94
+ * inner-timeout failures, so a provider-agnostic ``/request was aborted/i``
95
+ * predicate would erroneously retry their 30-minute deadline failures three
96
+ * additional times. Once those catch-sites grow the same
97
+ * ``innerTimeoutFired`` distinction the Anthropic one has, the pattern set
98
+ * here can be expanded to cover them too.
99
+ *
100
+ * This is the daemon-side counterpart to the vembda graceful-close behavior
101
+ * for upstream disconnects (LUM-1536) — together they collapse the 45 s
102
+ * silent-stall window the web client used to observe whenever Anthropic's
103
+ * stream was cut mid-token.
104
+ */
105
+ const RETRYABLE_TRANSPORT_ABORT_PATTERNS = [
106
+ /^anthropic api error:\s*request was aborted/i,
107
+ ];
108
+
75
109
  function isRetryableStreamError(error: unknown): boolean {
76
110
  if (!(error instanceof ProviderError)) return false;
77
111
  if (error.statusCode !== undefined) return false; // has a real HTTP status — not a stream error
@@ -84,6 +118,15 @@ function isRetryableProviderMessage(error: unknown): boolean {
84
118
  return RETRYABLE_PROVIDER_MESSAGE_PATTERNS.some((p) => p.test(error.message));
85
119
  }
86
120
 
121
+ function isRetryableTransportAbort(error: unknown): boolean {
122
+ if (!(error instanceof ProviderError)) return false;
123
+ // Transport aborts surface with ``status === undefined`` (the SDK never
124
+ // saw an HTTP response). A real HTTP status here means a server error,
125
+ // which is handled by the status check.
126
+ if (error.statusCode !== undefined) return false;
127
+ return RETRYABLE_TRANSPORT_ABORT_PATTERNS.some((p) => p.test(error.message));
128
+ }
129
+
87
130
  function isRetryableError(error: unknown): boolean {
88
131
  // Context overflow is deterministic — retrying the same oversized prompt
89
132
  // will never succeed. Short-circuit before the generic 429/5xx check so
@@ -103,6 +146,7 @@ function isRetryableError(error: unknown): boolean {
103
146
  }
104
147
  if (isRetryableProviderMessage(error)) return true;
105
148
  if (isRetryableStreamError(error)) return true;
149
+ if (isRetryableTransportAbort(error)) return true;
106
150
  return isRetryableNetworkError(error);
107
151
  }
108
152
 
@@ -482,7 +526,9 @@ export class RetryProvider implements Provider {
482
526
  ? "provider_overloaded"
483
527
  : isRetryableStreamError(error)
484
528
  ? "stream_corruption"
485
- : "network_error";
529
+ : isRetryableTransportAbort(error)
530
+ ? "transport_abort"
531
+ : "network_error";
486
532
  log.warn(
487
533
  {
488
534
  attempt: attempt + 1,
@@ -68,6 +68,33 @@ mock.module("../../daemon/disk-pressure-guard.js", () => ({
68
68
  getDiskPressureStatus: () => mockDiskPressureStatus,
69
69
  }));
70
70
 
71
+ const recordRequestLogCalls: Array<{
72
+ conversationId: string;
73
+ requestPayload: string;
74
+ responsePayload: string;
75
+ messageId?: string;
76
+ provider?: string;
77
+ }> = [];
78
+ mock.module("../../memory/llm-request-log-store.js", () => ({
79
+ recordRequestLog: (
80
+ conversationId: string,
81
+ requestPayload: string,
82
+ responsePayload: string,
83
+ messageId?: string,
84
+ provider?: string,
85
+ ) => {
86
+ recordRequestLogCalls.push({
87
+ conversationId,
88
+ requestPayload,
89
+ responsePayload,
90
+ messageId,
91
+ provider,
92
+ });
93
+ return "log-id-test";
94
+ },
95
+ backfillMessageIdOnLogs: () => {},
96
+ }));
97
+
71
98
  import type { AgentEvent } from "../../agent/loop.js";
72
99
  import type { Message } from "../../providers/types.js";
73
100
  import {
@@ -220,6 +247,7 @@ function makeTarget(options: {
220
247
 
221
248
  beforeEach(() => {
222
249
  __resetWakeChainForTests();
250
+ recordRequestLogCalls.length = 0;
223
251
  mockDiskPressureStatus = {
224
252
  enabled: false,
225
253
  state: "disabled",
@@ -1435,4 +1463,128 @@ describe("wakeAgentForOpportunity", () => {
1435
1463
  expect(uiBlock!.surfaceId).toBe(wakeProducedOutputCalls[0]);
1436
1464
  },
1437
1465
  );
1466
+
1467
+ test(
1468
+ "silent no-op wake drops LLM request logs so a future backfillMessageIdOnLogs " +
1469
+ "sweep cannot misattach them to an unrelated assistant reply",
1470
+ async () => {
1471
+ const usageEvent: AgentEvent = {
1472
+ type: "usage",
1473
+ inputTokens: 100,
1474
+ outputTokens: 5,
1475
+ model: "test-model",
1476
+ actualProvider: "test-provider",
1477
+ providerDurationMs: 10,
1478
+ rawRequest: { request: "no-op wake" },
1479
+ rawResponse: { response: "no output" },
1480
+ };
1481
+ const target = makeTarget({
1482
+ baseline: [{ role: "user", content: [{ type: "text", text: "hi" }] }],
1483
+ scriptedEvents: [usageEvent],
1484
+ // Empty assistant text → silent no-op.
1485
+ scriptedAssistant: {
1486
+ role: "assistant",
1487
+ content: [{ type: "text", text: "" }],
1488
+ },
1489
+ });
1490
+
1491
+ const result = await wakeAgentForOpportunity(
1492
+ {
1493
+ conversationId: target.conversationId,
1494
+ hint: "consider doing nothing",
1495
+ source: "unit-test",
1496
+ },
1497
+ { resolveTarget: async () => target },
1498
+ );
1499
+
1500
+ expect(result).toEqual({ invoked: true, producedToolCalls: false });
1501
+ // Nothing emitted, nothing persisted to the conversation.
1502
+ expect(target.emittedEvents).toHaveLength(0);
1503
+ expect(target.persistedTailCalls).toHaveLength(0);
1504
+ // Critical: the LLM request log must NOT be inserted with messageId=NULL,
1505
+ // otherwise the next user turn's backfillMessageIdOnLogs sweep would
1506
+ // misattach this row to an unrelated future assistant reply.
1507
+ expect(recordRequestLogCalls).toHaveLength(0);
1508
+ },
1509
+ );
1510
+
1511
+ test("wake that produces output persists buffered LLM request logs", async () => {
1512
+ const usageEvent: AgentEvent = {
1513
+ type: "usage",
1514
+ inputTokens: 100,
1515
+ outputTokens: 5,
1516
+ model: "test-model",
1517
+ actualProvider: "test-provider",
1518
+ providerDurationMs: 10,
1519
+ rawRequest: { request: "produced wake" },
1520
+ rawResponse: { response: "real reply" },
1521
+ };
1522
+ const target = makeTarget({
1523
+ baseline: [{ role: "user", content: [{ type: "text", text: "hi" }] }],
1524
+ scriptedEvents: [usageEvent],
1525
+ scriptedAssistant: {
1526
+ role: "assistant",
1527
+ content: [{ type: "text", text: "real reply" }],
1528
+ },
1529
+ });
1530
+
1531
+ const result = await wakeAgentForOpportunity(
1532
+ {
1533
+ conversationId: target.conversationId,
1534
+ hint: "do reply",
1535
+ source: "unit-test",
1536
+ },
1537
+ { resolveTarget: async () => target },
1538
+ );
1539
+
1540
+ expect(result).toEqual({ invoked: true, producedToolCalls: false });
1541
+ expect(recordRequestLogCalls).toHaveLength(1);
1542
+ expect(recordRequestLogCalls[0]).toMatchObject({
1543
+ conversationId: target.conversationId,
1544
+ provider: "test-provider",
1545
+ messageId: undefined,
1546
+ });
1547
+ });
1548
+
1549
+ test("non-serializable usage payload does not abort the wake", async () => {
1550
+ // Circular reference in rawRequest — JSON.stringify throws on this.
1551
+ // Serialization must happen inside persistLog's try/catch so the
1552
+ // failure is swallowed as a non-fatal log warning rather than
1553
+ // escaping and aborting the wake.
1554
+ const circular: Record<string, unknown> = { request: "produced wake" };
1555
+ circular.self = circular;
1556
+ const usageEvent: AgentEvent = {
1557
+ type: "usage",
1558
+ inputTokens: 100,
1559
+ outputTokens: 5,
1560
+ model: "test-model",
1561
+ actualProvider: "test-provider",
1562
+ providerDurationMs: 10,
1563
+ rawRequest: circular,
1564
+ rawResponse: { response: "real reply" },
1565
+ };
1566
+ const target = makeTarget({
1567
+ baseline: [{ role: "user", content: [{ type: "text", text: "hi" }] }],
1568
+ scriptedEvents: [usageEvent],
1569
+ scriptedAssistant: {
1570
+ role: "assistant",
1571
+ content: [{ type: "text", text: "real reply" }],
1572
+ },
1573
+ });
1574
+
1575
+ const result = await wakeAgentForOpportunity(
1576
+ {
1577
+ conversationId: target.conversationId,
1578
+ hint: "do reply",
1579
+ source: "unit-test",
1580
+ },
1581
+ { resolveTarget: async () => target },
1582
+ );
1583
+
1584
+ expect(result).toEqual({ invoked: true, producedToolCalls: false });
1585
+ // Wake still produced output even though logging failed.
1586
+ expect(target.persistedTailCalls).toHaveLength(1);
1587
+ // No log row was inserted because JSON.stringify threw.
1588
+ expect(recordRequestLogCalls).toHaveLength(0);
1589
+ });
1438
1590
  });
@@ -330,7 +330,7 @@ function classifyWakeDiskPressurePolicy(opts: WakeOptions): {
330
330
  const status = getDiskPressureStatus();
331
331
  const decision = classifyDiskPressureTurnPolicy(status, {
332
332
  conversationSource: opts.source,
333
- callSite: "mainAgent",
333
+ callSite: opts.callSite ?? "mainAgent",
334
334
  isDirectWake: true,
335
335
  sourceChannel: opts.sourceChannel ?? opts.trustContext?.sourceChannel,
336
336
  sourceInterface: opts.sourceInterface,
@@ -537,6 +537,33 @@ export async function wakeAgentForOpportunity(
537
537
  // only after `agentLoop.run()` returns.
538
538
  let mode: "buffering" | "live" = "buffering";
539
539
  const buffered: AgentEvent[] = [];
540
+ // LLM request logs accumulated while buffering. Persisted only if the
541
+ // wake transitions to live (i.e. produced output). A silent no-op wake
542
+ // drops them — otherwise the next user-turn's `backfillMessageIdOnLogs`
543
+ // sweep would misattach these NULL-messageId rows to an unrelated
544
+ // future assistant message, contaminating inspector context.
545
+ type PendingLog = {
546
+ rawRequest: unknown;
547
+ rawResponse: unknown;
548
+ provider?: string;
549
+ };
550
+ const pendingLogs: PendingLog[] = [];
551
+ const persistLog = (record: PendingLog): void => {
552
+ try {
553
+ recordRequestLog(
554
+ conversationId,
555
+ JSON.stringify(record.rawRequest),
556
+ JSON.stringify(record.rawResponse),
557
+ undefined,
558
+ record.provider,
559
+ );
560
+ } catch (err) {
561
+ log.warn(
562
+ { err, conversationId, source },
563
+ "agent-wake: failed to persist LLM request log (non-fatal)",
564
+ );
565
+ }
566
+ };
540
567
  const safeEmit = (event: AgentEvent): void => {
541
568
  try {
542
569
  target.emitAgentEvent(event);
@@ -550,20 +577,17 @@ export async function wakeAgentForOpportunity(
550
577
  const onEvent = (event: AgentEvent): void => {
551
578
  // Replicates the recordRequestLog side-effect in `handleUsage` because
552
579
  // wakes own their own onEvent and never reach `dispatchAgentEvent`.
580
+ // Defer persistence while buffering — see `pendingLogs` above.
553
581
  if (event.type === "usage" && event.rawRequest && event.rawResponse) {
554
- try {
555
- recordRequestLog(
556
- conversationId,
557
- JSON.stringify(event.rawRequest),
558
- JSON.stringify(event.rawResponse),
559
- undefined,
560
- event.actualProvider,
561
- );
562
- } catch (err) {
563
- log.warn(
564
- { err, conversationId, source },
565
- "agent-wake: failed to persist LLM request log (non-fatal)",
566
- );
582
+ const record = {
583
+ rawRequest: event.rawRequest,
584
+ rawResponse: event.rawResponse,
585
+ provider: event.actualProvider,
586
+ };
587
+ if (mode === "buffering") {
588
+ pendingLogs.push(record);
589
+ } else {
590
+ persistLog(record);
567
591
  }
568
592
  }
569
593
  if (mode === "buffering") {
@@ -620,6 +644,10 @@ export async function wakeAgentForOpportunity(
620
644
  safeEmit(event);
621
645
  }
622
646
  buffered.length = 0;
647
+ for (const record of pendingLogs) {
648
+ persistLog(record);
649
+ }
650
+ pendingLogs.length = 0;
623
651
  mode = "live";
624
652
  };
625
653
 
@@ -164,6 +164,7 @@ const ACTOR_ENDPOINTS: Array<{ endpoint: string; scopes: Scope[] }> = [
164
164
  { endpoint: "confirm", scopes: ["approval.write"] },
165
165
  { endpoint: "secret", scopes: ["approval.write"] },
166
166
  { endpoint: "trust-rules", scopes: ["approval.write"] },
167
+ { endpoint: "question-response", scopes: ["approval.write"] },
167
168
  { endpoint: "host-app-control-result", scopes: ["approval.write"] },
168
169
  { endpoint: "host-bash-result", scopes: ["approval.write"] },
169
170
  { endpoint: "host-browser-result", scopes: ["approval.write"] },
@@ -285,7 +286,8 @@ const ACTOR_ENDPOINTS: Array<{ endpoint: string; scopes: Scope[] }> = [
285
286
  { endpoint: "slack/channels", scopes: ["settings.read"] },
286
287
  { endpoint: "slack/share", scopes: ["settings.write"] },
287
288
 
288
- // Channel readiness
289
+ // Channel availability + readiness
290
+ { endpoint: "channels/available", scopes: ["settings.read"] },
289
291
  { endpoint: "channels/readiness", scopes: ["settings.read"] },
290
292
  { endpoint: "channels/readiness/refresh", scopes: ["settings.write"] },
291
293
 
@@ -342,6 +344,7 @@ const ACTOR_ENDPOINTS: Array<{ endpoint: string; scopes: Scope[] }> = [
342
344
 
343
345
  // Lifecycle telemetry
344
346
  { endpoint: "telemetry/lifecycle", scopes: ["settings.write"] },
347
+ { endpoint: "telemetry/flush", scopes: ["settings.write"] },
345
348
 
346
349
  // Debug / introspection
347
350
  { endpoint: "clients", scopes: ["settings.read"] },
@@ -1079,6 +1082,10 @@ registerPolicy("oauth/mode.set", {
1079
1082
  requiredScopes: ["settings.write"],
1080
1083
  allowedPrincipalTypes: ["local"],
1081
1084
  });
1085
+ registerPolicy("oauth/connection-changed", {
1086
+ requiredScopes: ["settings.write"],
1087
+ allowedPrincipalTypes: ["local"],
1088
+ });
1082
1089
  registerPolicy("oauth/status", {
1083
1090
  requiredScopes: ["settings.read"],
1084
1091
  allowedPrincipalTypes: ["local"],
@@ -70,6 +70,8 @@ export async function runBtwSidechain(
70
70
  const tools = params.tools;
71
71
  const history = params.messages ?? params.conversation?.getMessages() ?? [];
72
72
  const messages = [...history, userMessage(trimmedContent)];
73
+ // Side-chains force `tool_choice: { type: "none" }` below, so tool usage
74
+ // guidance must stay in tool descriptions rather than this system prompt.
73
75
  const systemPrompt =
74
76
  params.systemPrompt ??
75
77
  (params.conversation?.hasSystemPromptOverride
@@ -115,6 +115,11 @@ export interface RuntimeMessageConversationOptions {
115
115
  commandIntent?: { type: string; payload?: string; languageCode?: string };
116
116
  /** Slack-only non-persisted notice injected into the active model turn. */
117
117
  slackRuntimeContextNotice?: string;
118
+ /**
119
+ * Persisted user-facing content. When present, storage/UI use this value
120
+ * while the model-facing turn continues to use `content`.
121
+ */
122
+ displayContent?: string;
118
123
  /** Optional callback to receive real-time agent loop events (text deltas, tool starts, etc.). */
119
124
  onEvent?: (msg: ServerMessage) => void;
120
125
  /**
@@ -227,5 +232,19 @@ export interface RuntimeMessagePayload {
227
232
  status: string;
228
233
  error?: string;
229
234
  conversationId?: string;
235
+ objective?: string;
236
+ };
237
+ slackMessage?: {
238
+ channelId: string;
239
+ channelTs: string;
240
+ threadTs?: string;
241
+ messageLink?: {
242
+ appUrl?: string;
243
+ webUrl?: string;
244
+ };
245
+ threadLink?: {
246
+ appUrl?: string;
247
+ webUrl?: string;
248
+ };
230
249
  };
231
250
  }
@@ -14,7 +14,7 @@
14
14
  * combination logic.
15
15
  */
16
16
 
17
- import { hasManagedProxyPrereqs } from "../../providers/managed-proxy/context.js";
17
+ import { hasManagedProxyPrereqs } from "../../providers/platform-proxy/context.js";
18
18
  import { getDaemonRuntimeMode } from "../runtime-mode.js";
19
19
 
20
20
  export type VBundleOriginMode =
@@ -47,6 +47,7 @@ export interface PendingInteraction {
47
47
  kind:
48
48
  | "confirmation"
49
49
  | "secret"
50
+ | "question"
50
51
  | "host_bash"
51
52
  | "host_file"
52
53
  | "host_cu"
@@ -241,6 +241,23 @@ describe("bookmark routes", () => {
241
241
  ).toBe("msg-6");
242
242
  });
243
243
 
244
+ test("duplicate POSTs only broadcast one bookmark.created event", async () => {
245
+ seedConversationAndMessage({
246
+ conversationId: "conv-dup",
247
+ messageId: "msg-dup",
248
+ });
249
+
250
+ await call(createHandler, {
251
+ body: { messageId: "msg-dup", conversationId: "conv-dup" },
252
+ });
253
+ await call(createHandler, {
254
+ body: { messageId: "msg-dup", conversationId: "conv-dup" },
255
+ });
256
+ await new Promise((r) => setTimeout(r, 0));
257
+
258
+ expect(publishedTypes()).toEqual(["bookmark.created"]);
259
+ });
260
+
244
261
  test("DELETE on a non-existent messageId does not publish", async () => {
245
262
  await call(deleteByMessageHandler, {
246
263
  pathParams: { messageId: "does-not-exist" },
@@ -23,6 +23,7 @@ mock.module("../../assistant-event-hub.js", () => ({
23
23
  publish: async () => {},
24
24
  subscribe: () => () => {},
25
25
  },
26
+ broadcastMessage: () => {},
26
27
  }));
27
28
 
28
29
  import { getDb } from "../../../memory/db-connection.js";
@@ -114,7 +115,10 @@ function seedConversation(id: string): void {
114
115
  describe("PUT /v1/conversations/:id/inference-profile", () => {
115
116
  beforeEach(() => {
116
117
  clearConversations();
117
- configLlmProfiles = { fast: { model: "model-a" }, slow: { model: "model-b" } };
118
+ configLlmProfiles = {
119
+ fast: { model: "model-a" },
120
+ slow: { model: "model-b" },
121
+ };
118
122
  });
119
123
 
120
124
  test("PUT with ttlSeconds=600 → response includes sessionId (UUID), expiresAt, ttlSeconds=600", async () => {