@vellumai/assistant 0.6.4 → 0.6.5

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 (717) hide show
  1. package/.prettierignore +5 -0
  2. package/ARCHITECTURE.md +32 -36
  3. package/Dockerfile +12 -0
  4. package/README.md +3 -4
  5. package/bun.lock +8 -3
  6. package/docs/architecture/integrations.md +1 -20
  7. package/docs/architecture/security.md +16 -16
  8. package/docs/error-handling.md +111 -0
  9. package/docs/skills.md +10 -10
  10. package/docs/stt-provider-onboarding.md +2 -1
  11. package/knip.json +9 -2
  12. package/node_modules/@vellumai/ces-contracts/package.json +2 -1
  13. package/node_modules/@vellumai/ces-contracts/src/__tests__/trust-rules.test.ts +471 -0
  14. package/node_modules/@vellumai/ces-contracts/src/trust-rules.ts +398 -4
  15. package/node_modules/@vellumai/credential-storage/bun.lock +2 -2
  16. package/node_modules/@vellumai/credential-storage/package.json +2 -2
  17. package/node_modules/@vellumai/credential-storage/src/oauth-runtime.ts +20 -2
  18. package/node_modules/@vellumai/egress-proxy/bun.lock +2 -2
  19. package/node_modules/@vellumai/egress-proxy/package.json +2 -2
  20. package/openapi.yaml +123 -11
  21. package/package.json +6 -3
  22. package/scripts/generate-openapi.ts +50 -11
  23. package/src/__tests__/agent-loop-callsite-precedence.test.ts +318 -0
  24. package/src/__tests__/agent-loop-sentry-hygiene.test.ts +137 -0
  25. package/src/__tests__/agent-loop.test.ts +112 -1
  26. package/src/__tests__/anthropic-error-formatting.test.ts +98 -0
  27. package/src/__tests__/anthropic-provider.test.ts +171 -2
  28. package/src/__tests__/approval-cascade.test.ts +31 -10
  29. package/src/__tests__/approval-routes-http.test.ts +134 -10
  30. package/src/__tests__/assistant-attachments.test.ts +44 -0
  31. package/src/__tests__/assistant-feature-flags-integration.test.ts +29 -0
  32. package/src/__tests__/browser-fill-credential.test.ts +1 -1
  33. package/src/__tests__/browser-identifier-parity-guard.test.ts +53 -0
  34. package/src/__tests__/browser-skill-baseline-tool-payload.test.ts +23 -33
  35. package/src/__tests__/browser-skill-endstate.test.ts +51 -182
  36. package/src/__tests__/btw-routes.test.ts +47 -1
  37. package/src/__tests__/call-controller.test.ts +1 -2
  38. package/src/__tests__/call-site-routing-provider.test.ts +214 -0
  39. package/src/__tests__/catalog-cache.test.ts +27 -4
  40. package/src/__tests__/channel-approval-routes.test.ts +4 -4
  41. package/src/__tests__/channel-reply-delivery.test.ts +300 -2
  42. package/src/__tests__/checker.test.ts +428 -501
  43. package/src/__tests__/cli-command-risk-guard.test.ts +30 -33
  44. package/src/__tests__/compaction-circuit-breaker.test.ts +336 -0
  45. package/src/__tests__/compaction.benchmark.test.ts +1 -1
  46. package/src/__tests__/config-analysis.test.ts +11 -28
  47. package/src/__tests__/config-loader-backfill.test.ts +174 -0
  48. package/src/__tests__/config-loader-corrupt.test.ts +183 -0
  49. package/src/__tests__/config-loader-quarantine-bulletin.test.ts +202 -0
  50. package/src/__tests__/config-schema-cmd.test.ts +11 -5
  51. package/src/__tests__/config-schema.test.ts +427 -114
  52. package/src/__tests__/config-watcher.test.ts +2 -2
  53. package/src/__tests__/contact-store-user-file.test.ts +72 -73
  54. package/src/__tests__/contacts-write.test.ts +4 -4
  55. package/src/__tests__/context-token-estimator.test.ts +191 -1
  56. package/src/__tests__/context-window-manager.test.ts +530 -2
  57. package/src/__tests__/conversation-abort-tool-results.test.ts +30 -16
  58. package/src/__tests__/conversation-agent-loop-overflow.test.ts +61 -17
  59. package/src/__tests__/conversation-agent-loop.test.ts +412 -82
  60. package/src/__tests__/conversation-attachments.test.ts +1 -1
  61. package/src/__tests__/conversation-confirmation-signals.test.ts +30 -9
  62. package/src/__tests__/conversation-error.test.ts +37 -6
  63. package/src/__tests__/conversation-history-web-search.test.ts +6 -0
  64. package/src/__tests__/conversation-init.benchmark.test.ts +36 -0
  65. package/src/__tests__/conversation-lifecycle.test.ts +336 -0
  66. package/src/__tests__/conversation-load-history-repair.test.ts +27 -10
  67. package/src/__tests__/conversation-pre-run-repair.test.ts +30 -16
  68. package/src/__tests__/conversation-process-callsite.test.ts +306 -0
  69. package/src/__tests__/conversation-provider-retry-repair.test.ts +30 -16
  70. package/src/__tests__/conversation-queue.test.ts +41 -26
  71. package/src/__tests__/conversation-routes-disk-view.test.ts +29 -1
  72. package/src/__tests__/conversation-routes-slash-commands.test.ts +31 -3
  73. package/src/__tests__/conversation-runtime-assembly.test.ts +2735 -55
  74. package/src/__tests__/conversation-runtime-workspace.test.ts +12 -12
  75. package/src/__tests__/conversation-skill-tools.test.ts +12 -146
  76. package/src/__tests__/conversation-slash-queue.test.ts +34 -19
  77. package/src/__tests__/conversation-slash-unknown.test.ts +30 -16
  78. package/src/__tests__/conversation-speed-override.test.ts +30 -11
  79. package/src/__tests__/conversation-surfaces-standalone-payloads.test.ts +1035 -0
  80. package/src/__tests__/conversation-surfaces-standalone.test.ts +630 -0
  81. package/src/__tests__/conversation-title-service.test.ts +2 -2
  82. package/src/__tests__/conversation-tool-setup-batch-authorized.test.ts +1 -1
  83. package/src/__tests__/conversation-unread-route.test.ts +2 -2
  84. package/src/__tests__/conversation-usage.test.ts +3 -1
  85. package/src/__tests__/conversation-workspace-cache-state.test.ts +31 -10
  86. package/src/__tests__/conversation-workspace-injection.test.ts +43 -15
  87. package/src/__tests__/conversation-workspace-tool-tracking.test.ts +44 -16
  88. package/src/__tests__/credential-broker-browser-fill.test.ts +110 -0
  89. package/src/__tests__/credential-security-invariants.test.ts +3 -0
  90. package/src/__tests__/credential-storage-oauth-compat.test.ts +18 -0
  91. package/src/__tests__/credential-storage-static-compat.test.ts +28 -0
  92. package/src/__tests__/credential-vault-unit.test.ts +135 -19
  93. package/src/__tests__/credentials-cli.test.ts +1 -9
  94. package/src/__tests__/cross-provider-web-search.test.ts +84 -0
  95. package/src/__tests__/daemon-server-persist-and-process-callsite.test.ts +92 -0
  96. package/src/__tests__/delete-propagation.test.ts +437 -0
  97. package/src/__tests__/dm-backfill.test.ts +417 -0
  98. package/src/__tests__/dm-persistence.test.ts +227 -0
  99. package/src/__tests__/edit-propagation.test.ts +280 -0
  100. package/src/__tests__/ephemeral-permissions.test.ts +93 -3
  101. package/src/__tests__/estimator-calibration-integration.test.ts +208 -0
  102. package/src/__tests__/estimator-calibration.test.ts +213 -0
  103. package/src/__tests__/extension-id-sync-guard.test.ts +26 -7
  104. package/src/__tests__/file-write-tool.test.ts +151 -1
  105. package/src/__tests__/filing-service.test.ts +255 -0
  106. package/src/__tests__/gemini-provider.test.ts +0 -3
  107. package/src/__tests__/guardian-grant-minting.test.ts +8 -0
  108. package/src/__tests__/headless-browser-interactions.test.ts +1 -1
  109. package/src/__tests__/heartbeat-service.test.ts +96 -15
  110. package/src/__tests__/host-shell-tool.test.ts +124 -18
  111. package/src/__tests__/http-user-message-parity.test.ts +29 -1
  112. package/src/__tests__/inbound-slack-persistence.test.ts +340 -0
  113. package/src/__tests__/intent-routing.test.ts +1 -40
  114. package/src/__tests__/llm-catalog-parity.test.ts +174 -0
  115. package/src/__tests__/llm-context-normalization.test.ts +121 -0
  116. package/src/__tests__/llm-resolver.test.ts +214 -0
  117. package/src/__tests__/llm-schema.test.ts +223 -0
  118. package/src/__tests__/managed-proxy-context.test.ts +6 -2
  119. package/src/__tests__/messaging-skill-split.test.ts +3 -34
  120. package/src/__tests__/migration-import-from-url.test.ts +684 -0
  121. package/src/__tests__/model-intents.test.ts +9 -83
  122. package/src/__tests__/notification-decision-fallback.test.ts +0 -10
  123. package/src/__tests__/notification-decision-identity.test.ts +0 -9
  124. package/src/__tests__/notification-decision-recipient-context.test.ts +0 -9
  125. package/src/__tests__/oauth-store.test.ts +10 -7
  126. package/src/__tests__/oauth2-gateway-transport.test.ts +8 -3
  127. package/src/__tests__/oauth2-refresh-retry.test.ts +279 -0
  128. package/src/__tests__/openai-provider.test.ts +7 -0
  129. package/src/__tests__/openai-responses-provider.test.ts +396 -0
  130. package/src/__tests__/openrouter-provider-only.test.ts +135 -0
  131. package/src/__tests__/outbound-slack-persistence.test.ts +293 -0
  132. package/src/__tests__/permission-checker-host-gate.test.ts +1 -1
  133. package/src/__tests__/permission-mode.test.ts +16 -0
  134. package/src/__tests__/permission-types.test.ts +0 -1
  135. package/src/__tests__/persona-resolver.test.ts +13 -13
  136. package/src/__tests__/pkb-autoinject.test.ts +37 -1
  137. package/src/__tests__/platform-bash-auto-approve.test.ts +1 -1
  138. package/src/__tests__/pricing.test.ts +50 -3
  139. package/src/__tests__/profiler-routes.test.ts +1 -1
  140. package/src/__tests__/provider-commit-message-generator.test.ts +14 -84
  141. package/src/__tests__/provider-env-vars-scope.test.ts +52 -0
  142. package/src/__tests__/provider-error-scenarios.test.ts +135 -6
  143. package/src/__tests__/provider-managed-proxy-integration.test.ts +42 -11
  144. package/src/__tests__/provider-registry-ollama.test.ts +1 -2
  145. package/src/__tests__/proxy-approval-callback.test.ts +0 -1
  146. package/src/__tests__/reaction-persistence.test.ts +560 -0
  147. package/src/__tests__/relay-server.test.ts +1 -1
  148. package/src/__tests__/require-fresh-approval.test.ts +1 -1
  149. package/src/__tests__/retry-openrouter-only-normalization.test.ts +136 -0
  150. package/src/__tests__/retry-thinking-tool-choice.test.ts +226 -0
  151. package/src/__tests__/risk-classifier-parity.test.ts +230 -0
  152. package/src/__tests__/sanitize-config-for-transfer.test.ts +78 -1
  153. package/src/__tests__/secret-ingress-http.test.ts +28 -0
  154. package/src/__tests__/secret-prompter-channel-fallback.test.ts +125 -0
  155. package/src/__tests__/secret-routes-managed-proxy.test.ts +2 -3
  156. package/src/__tests__/secret-scanner-executor.test.ts +1 -1
  157. package/src/__tests__/send-endpoint-busy.test.ts +29 -1
  158. package/src/__tests__/server-history-render.test.ts +31 -0
  159. package/src/__tests__/shell-parser-property.test.ts +13 -13
  160. package/src/__tests__/skill-cache-store.test.ts +182 -0
  161. package/src/__tests__/skills.test.ts +19 -33
  162. package/src/__tests__/slack-app-setup-skill-regression.test.ts +3 -1
  163. package/src/__tests__/slack-skill.test.ts +3 -8
  164. package/src/__tests__/starter-bundle.test.ts +35 -0
  165. package/src/__tests__/subagent-call-site-routing.test.ts +280 -0
  166. package/src/__tests__/suggestion-routes.test.ts +160 -3
  167. package/src/__tests__/system-prompt.test.ts +22 -35
  168. package/src/__tests__/task-runner.test.ts +3 -1
  169. package/src/__tests__/tcc-sandbox-deny.test.ts +198 -0
  170. package/src/__tests__/terminal-tools.test.ts +8 -0
  171. package/src/__tests__/test-support/browser-skill-harness.ts +2 -52
  172. package/src/__tests__/thread-backfill.test.ts +941 -0
  173. package/src/__tests__/tool-execution-pipeline.benchmark.test.ts +2 -2
  174. package/src/__tests__/tool-executor-lifecycle-events.test.ts +2 -2
  175. package/src/__tests__/tool-executor.test.ts +60 -94
  176. package/src/__tests__/trust-store.test.ts +442 -109
  177. package/src/__tests__/update-bulletin-job.test.ts +389 -0
  178. package/src/__tests__/usage-cache-backfill-migration.test.ts +3 -1
  179. package/src/__tests__/verification-control-plane-policy.test.ts +1 -22
  180. package/src/__tests__/voice-session-bridge.test.ts +39 -0
  181. package/src/__tests__/volume-security-guard.test.ts +3 -2
  182. package/src/__tests__/web-search-history.test.ts +337 -0
  183. package/src/__tests__/workspace-migration-039-drop-legacy-llm-keys.test.ts +343 -0
  184. package/src/__tests__/workspace-migration-043-release-notes-latex-rendering.test.ts +202 -0
  185. package/src/__tests__/workspace-migration-045-release-notes-meet-avatar.test.ts +210 -0
  186. package/src/__tests__/workspace-migration-drop-user-md.test.ts +11 -11
  187. package/src/__tests__/workspace-migration-unify-llm-callsite-configs.test.ts +841 -0
  188. package/src/__tests__/workspace-policy.test.ts +1 -13
  189. package/src/acp/client-handler.ts +1 -2
  190. package/src/agent/loop.ts +209 -17
  191. package/src/avatar/resvg-lazy.test.ts +136 -0
  192. package/src/avatar/resvg-lazy.ts +82 -9
  193. package/src/avatar/traits-png-sync.ts +21 -1
  194. package/src/browser/__tests__/operations.test.ts +163 -0
  195. package/src/browser/identifiers.ts +51 -0
  196. package/src/browser/operations.ts +660 -0
  197. package/src/browser/types.ts +81 -0
  198. package/src/calls/guardian-question-copy.ts +2 -2
  199. package/src/calls/telephony-stt-routing.ts +1 -1
  200. package/src/calls/voice-session-bridge.ts +1 -0
  201. package/src/cli/AGENTS.md +1 -1
  202. package/src/cli/commands/__tests__/attachment.test.ts +438 -0
  203. package/src/cli/commands/__tests__/browser.test.ts +554 -0
  204. package/src/cli/commands/__tests__/cache.test.ts +623 -0
  205. package/src/cli/commands/__tests__/email-list.test.ts +6 -0
  206. package/src/cli/commands/__tests__/email-send.test.ts +93 -1
  207. package/src/cli/commands/__tests__/image-generation.test.ts +666 -0
  208. package/src/cli/commands/__tests__/inference-send.test.ts +451 -0
  209. package/src/cli/commands/__tests__/stt-transcribe.test.ts +454 -0
  210. package/src/cli/commands/__tests__/task.test.ts +913 -0
  211. package/src/cli/commands/__tests__/tts-synthesize.test.ts +594 -0
  212. package/src/cli/commands/__tests__/ui-confirm.test.ts +650 -0
  213. package/src/cli/commands/__tests__/ui.test.ts +1215 -0
  214. package/src/cli/commands/__tests__/watchers.test.ts +716 -0
  215. package/src/cli/commands/attachment.ts +182 -0
  216. package/src/cli/commands/browser.ts +350 -0
  217. package/src/cli/commands/cache.ts +341 -0
  218. package/src/cli/commands/completions.ts +0 -3
  219. package/src/cli/commands/config.ts +6 -6
  220. package/src/cli/commands/conversations-import.ts +347 -0
  221. package/src/cli/commands/conversations.ts +14 -1
  222. package/src/cli/commands/email.ts +234 -194
  223. package/src/cli/commands/image-generation.ts +300 -0
  224. package/src/cli/commands/inference.ts +200 -0
  225. package/src/cli/commands/memory.ts +127 -17
  226. package/src/cli/commands/platform/__tests__/callback-routes-list.test.ts +0 -1
  227. package/src/cli/commands/platform/__tests__/connect.test.ts +0 -1
  228. package/src/cli/commands/platform/__tests__/disconnect.test.ts +0 -1
  229. package/src/cli/commands/platform/__tests__/status.test.ts +0 -1
  230. package/src/cli/commands/stt.ts +339 -0
  231. package/src/cli/commands/task.ts +795 -0
  232. package/src/cli/commands/trust.ts +50 -19
  233. package/src/cli/commands/tts.ts +273 -0
  234. package/src/cli/commands/ui.ts +670 -0
  235. package/src/cli/commands/watchers.ts +509 -0
  236. package/src/cli/lib/daemon-credential-client.ts +0 -19
  237. package/src/cli/program.ts +23 -4
  238. package/src/cli.ts +0 -37
  239. package/src/config/bundled-skills/conversations/tools/rename-conversation.ts +23 -1
  240. package/src/config/bundled-skills/media-processing/services/reduce.ts +1 -1
  241. package/src/config/bundled-skills/messaging/SKILL.md +2 -2
  242. package/src/config/bundled-skills/messaging/TOOLS.json +4 -0
  243. package/src/config/bundled-skills/messaging/tools/messaging-archive-by-sender.ts +8 -1
  244. package/src/config/bundled-skills/messaging/tools/messaging-read.ts +15 -1
  245. package/src/config/bundled-skills/messaging/tools/messaging-search.ts +21 -1
  246. package/src/config/bundled-skills/messaging/tools/messaging-send.ts +11 -12
  247. package/src/config/bundled-skills/phone-calls/references/CONFIG.md +9 -8
  248. package/src/config/bundled-skills/settings/TOOLS.json +3 -3
  249. package/src/config/bundled-tool-registry.ts +0 -175
  250. package/src/config/env.ts +7 -2
  251. package/src/config/feature-flag-registry.json +25 -9
  252. package/src/config/llm-resolver.ts +128 -0
  253. package/src/config/loader.ts +194 -10
  254. package/src/config/raw-config-utils.ts +30 -2
  255. package/src/config/sanitize-for-transfer.ts +35 -0
  256. package/src/config/schema.ts +30 -41
  257. package/src/config/schemas/analysis.ts +3 -22
  258. package/src/config/schemas/calls.ts +0 -4
  259. package/src/config/schemas/filing.ts +2 -7
  260. package/src/config/schemas/heartbeat.ts +0 -5
  261. package/src/config/schemas/inference.ts +3 -23
  262. package/src/config/schemas/llm.ts +318 -0
  263. package/src/config/schemas/memory-processing.ts +1 -9
  264. package/src/config/schemas/notifications.ts +4 -11
  265. package/src/config/schemas/platform.ts +3 -9
  266. package/src/config/schemas/security.ts +33 -0
  267. package/src/config/schemas/services.ts +9 -4
  268. package/src/config/schemas/stt.ts +1 -0
  269. package/src/config/schemas/tts.ts +53 -0
  270. package/src/config/schemas/updates.ts +1 -1
  271. package/src/config/schemas/workspace-git.ts +3 -40
  272. package/src/config/skills.ts +2 -2
  273. package/src/context/__tests__/compact-prompt.test.ts +45 -0
  274. package/src/context/__tests__/microcompact.test.ts +805 -0
  275. package/src/context/estimator-calibration.ts +136 -0
  276. package/src/context/microcompact.ts +443 -0
  277. package/src/context/prompts/compact.md +12 -0
  278. package/src/context/token-estimator.ts +61 -3
  279. package/src/context/window-manager.ts +229 -25
  280. package/src/credential-execution/approval-bridge.ts +0 -1
  281. package/src/credential-execution/executable-discovery.ts +19 -8
  282. package/src/credential-execution/process-manager.test.ts +109 -0
  283. package/src/credential-execution/process-manager.ts +65 -2
  284. package/src/daemon/approval-generators.ts +29 -4
  285. package/src/daemon/assistant-attachments.ts +24 -13
  286. package/src/daemon/classifier.ts +2 -2
  287. package/src/daemon/config-watcher.ts +0 -1
  288. package/src/daemon/context-overflow-reducer.ts +4 -1
  289. package/src/daemon/conversation-agent-loop-handlers.ts +79 -12
  290. package/src/daemon/conversation-agent-loop.ts +462 -80
  291. package/src/daemon/conversation-attachments.ts +2 -6
  292. package/src/daemon/conversation-error.ts +36 -1
  293. package/src/daemon/conversation-lifecycle.ts +30 -6
  294. package/src/daemon/conversation-messaging.ts +73 -4
  295. package/src/daemon/conversation-process.ts +10 -4
  296. package/src/daemon/conversation-queue-manager.ts +3 -0
  297. package/src/daemon/conversation-runtime-assembly.ts +760 -29
  298. package/src/daemon/conversation-slash.ts +2 -2
  299. package/src/daemon/conversation-surfaces.ts +389 -1
  300. package/src/daemon/conversation-tool-setup.ts +10 -5
  301. package/src/daemon/conversation-usage.ts +1 -1
  302. package/src/daemon/conversation.ts +118 -30
  303. package/src/daemon/external-skills-bootstrap.ts +41 -0
  304. package/src/daemon/guardian-action-generators.ts +34 -14
  305. package/src/daemon/handlers/config-model.test.ts +86 -0
  306. package/src/daemon/handlers/config-model.ts +54 -12
  307. package/src/daemon/handlers/conversations.ts +9 -2
  308. package/src/daemon/handlers/shared.ts +39 -11
  309. package/src/daemon/handlers/skills.ts +2 -2
  310. package/src/daemon/handlers/slack-channel-oauth-install.ts +197 -0
  311. package/src/daemon/lifecycle.ts +76 -14
  312. package/src/daemon/message-types/conversations.ts +14 -0
  313. package/src/daemon/message-types/messages.ts +9 -1
  314. package/src/daemon/message-types/trust.ts +0 -2
  315. package/src/daemon/parse-actual-tokens-from-error.test.ts +57 -1
  316. package/src/daemon/parse-actual-tokens-from-error.ts +66 -0
  317. package/src/daemon/pkb-context-tracker.test.ts +169 -0
  318. package/src/daemon/pkb-context-tracker.ts +125 -0
  319. package/src/daemon/pkb-reminder-builder.test.ts +70 -0
  320. package/src/daemon/pkb-reminder-builder.ts +31 -0
  321. package/src/daemon/providers-setup.ts +6 -0
  322. package/src/daemon/server.ts +117 -9
  323. package/src/daemon/tool-side-effects.ts +0 -9
  324. package/src/daemon/watch-handler.ts +4 -4
  325. package/src/daemon/web-search-history.ts +126 -0
  326. package/src/events/domain-events.ts +0 -1
  327. package/src/filing/filing-service.ts +9 -10
  328. package/src/heartbeat/heartbeat-service.ts +76 -28
  329. package/src/home/__tests__/feed-scheduler.test.ts +39 -11
  330. package/src/home/__tests__/rollup-producer.test.ts +44 -0
  331. package/src/home/assistant-feed-authoring.ts +4 -0
  332. package/src/home/emit-feed-event.ts +4 -0
  333. package/src/home/feed-scheduler.ts +20 -4
  334. package/src/home/feed-types.ts +56 -2
  335. package/src/home/relationship-state-writer.ts +2 -2
  336. package/src/home/rollup-producer.ts +34 -5
  337. package/src/home/suggested-prompts.ts +101 -0
  338. package/src/ipc/__tests__/attachment-ipc.test.ts +213 -0
  339. package/src/ipc/__tests__/browser-ipc.test.ts +339 -0
  340. package/src/ipc/__tests__/cache-ipc.test.ts +266 -0
  341. package/src/ipc/__tests__/socket-path.test.ts +73 -0
  342. package/src/ipc/__tests__/task-ipc.test.ts +577 -0
  343. package/src/ipc/__tests__/ui-request-route.test.ts +495 -0
  344. package/src/ipc/__tests__/watcher-ipc.test.ts +295 -0
  345. package/src/ipc/cli-client.ts +2 -1
  346. package/src/ipc/cli-server.ts +26 -8
  347. package/src/ipc/gateway-client.ts +4 -4
  348. package/src/ipc/routes/attachment.ts +114 -0
  349. package/src/ipc/routes/browser-context.ts +61 -0
  350. package/src/ipc/routes/browser.ts +96 -0
  351. package/src/ipc/routes/cache.ts +96 -0
  352. package/src/ipc/routes/index.ts +17 -1
  353. package/src/ipc/routes/task-queue.ts +226 -0
  354. package/src/ipc/routes/task.ts +173 -0
  355. package/src/ipc/routes/ui-request.ts +50 -0
  356. package/src/ipc/routes/watcher.ts +203 -0
  357. package/src/ipc/socket-path.ts +100 -0
  358. package/src/memory/__tests__/conversation-analyze-job.test.ts +9 -8
  359. package/src/memory/__tests__/conversation-group-migration.test.ts +99 -0
  360. package/src/memory/admin.ts +18 -0
  361. package/src/memory/conversation-analyze-job.ts +14 -13
  362. package/src/memory/conversation-attention-store.ts +13 -6
  363. package/src/memory/conversation-crud.ts +103 -3
  364. package/src/memory/conversation-group-migration.ts +38 -6
  365. package/src/memory/conversation-title-service.ts +7 -4
  366. package/src/memory/db-init.ts +2 -0
  367. package/src/memory/embedding-backend.ts +1 -1
  368. package/src/memory/graph/compaction.ts +299 -0
  369. package/src/memory/graph/consolidation.ts +4 -4
  370. package/src/memory/graph/conversation-graph-memory.ts +89 -29
  371. package/src/memory/graph/extraction.test.ts +272 -2
  372. package/src/memory/graph/extraction.ts +173 -51
  373. package/src/memory/graph/graph-search.test.ts +92 -0
  374. package/src/memory/graph/graph-search.ts +4 -1
  375. package/src/memory/graph/narrative.ts +2 -2
  376. package/src/memory/graph/pattern-scan.ts +2 -2
  377. package/src/memory/graph/retriever.test.ts +459 -0
  378. package/src/memory/graph/retriever.ts +230 -48
  379. package/src/memory/graph/store.ts +41 -0
  380. package/src/memory/graph/tool-handlers.ts +27 -0
  381. package/src/memory/graph/tools.ts +6 -1
  382. package/src/memory/indexer.ts +5 -5
  383. package/src/memory/job-handlers/conversation-starters.ts +23 -20
  384. package/src/memory/job-handlers/summarization.ts +2 -2
  385. package/src/memory/job-utils.ts +7 -1
  386. package/src/memory/jobs/embed-pkb-file.test.ts +168 -0
  387. package/src/memory/jobs/embed-pkb-file.ts +54 -0
  388. package/src/memory/jobs-store.ts +44 -3
  389. package/src/memory/jobs-worker.ts +4 -0
  390. package/src/memory/migrations/140-backfill-usage-cache-accounting.ts +1 -1
  391. package/src/memory/migrations/220-normalize-user-file-by-principal.ts +2 -2
  392. package/src/memory/migrations/222-strip-placeholder-sentinels-from-messages.ts +82 -0
  393. package/src/memory/migrations/index.ts +1 -0
  394. package/src/memory/pkb/pkb-index.test.ts +368 -0
  395. package/src/memory/pkb/pkb-index.ts +255 -0
  396. package/src/memory/pkb/pkb-reconcile.test.ts +251 -0
  397. package/src/memory/pkb/pkb-reconcile.ts +148 -0
  398. package/src/memory/pkb/pkb-search.test.ts +438 -0
  399. package/src/memory/pkb/pkb-search.ts +137 -0
  400. package/src/memory/pkb/types.ts +53 -0
  401. package/src/memory/qdrant-client.ts +122 -1
  402. package/src/memory/slack-thread-store.ts +37 -0
  403. package/src/messaging/providers/gmail/adapter.ts +6 -16
  404. package/src/messaging/providers/gmail/client.ts +22 -0
  405. package/src/messaging/providers/gmail/types.ts +7 -0
  406. package/src/messaging/providers/slack/adapter.ts +14 -2
  407. package/src/messaging/providers/slack/backfill.test.ts +257 -0
  408. package/src/messaging/providers/slack/backfill.ts +101 -0
  409. package/src/messaging/providers/slack/message-metadata.test.ts +316 -0
  410. package/src/messaging/providers/slack/message-metadata.ts +123 -0
  411. package/src/messaging/providers/slack/render-transcript.test.ts +1373 -0
  412. package/src/messaging/providers/slack/render-transcript.ts +443 -0
  413. package/src/messaging/style-analyzer.ts +5 -2
  414. package/src/notifications/README.md +9 -5
  415. package/src/notifications/decision-engine.ts +3 -9
  416. package/src/notifications/preference-extractor.ts +2 -6
  417. package/src/oauth/oauth-store.ts +1 -0
  418. package/src/oauth/platform-connection.test.ts +47 -0
  419. package/src/oauth/platform-connection.ts +15 -5
  420. package/src/oauth/seed-providers.ts +4 -2
  421. package/src/permissions/approval-policy.test.ts +948 -0
  422. package/src/permissions/approval-policy.ts +257 -0
  423. package/src/permissions/bash-risk-classifier.test.ts +1208 -0
  424. package/src/permissions/bash-risk-classifier.ts +707 -0
  425. package/src/permissions/checker.ts +217 -708
  426. package/src/permissions/command-registry.test.ts +535 -0
  427. package/src/permissions/command-registry.ts +825 -0
  428. package/src/permissions/defaults.ts +26 -78
  429. package/src/permissions/file-risk-classifier.test.ts +535 -0
  430. package/src/permissions/file-risk-classifier.ts +274 -0
  431. package/src/permissions/risk-types.ts +205 -0
  432. package/src/permissions/secret-prompter.ts +53 -2
  433. package/src/permissions/skill-risk-classifier.test.ts +311 -0
  434. package/src/permissions/skill-risk-classifier.ts +214 -0
  435. package/src/permissions/trust-client.ts +52 -25
  436. package/src/permissions/trust-store-interface.ts +1 -6
  437. package/src/permissions/trust-store.ts +161 -62
  438. package/src/permissions/types.ts +23 -14
  439. package/src/permissions/web-risk-classifier.test.ts +170 -0
  440. package/src/permissions/web-risk-classifier.ts +89 -0
  441. package/src/permissions/workspace-policy.ts +1 -16
  442. package/src/platform/client.ts +19 -1
  443. package/src/prompts/persona-resolver.ts +3 -3
  444. package/src/prompts/system-prompt.ts +19 -20
  445. package/src/prompts/templates/SOUL.md +2 -2
  446. package/src/prompts/update-bulletin-job.ts +190 -0
  447. package/src/providers/__tests__/context-overflow-error.test.ts +328 -0
  448. package/src/providers/__tests__/provider-env-vars.test.ts +102 -0
  449. package/src/providers/__tests__/retry-callsite.test.ts +424 -0
  450. package/src/providers/anthropic/client.ts +183 -14
  451. package/src/providers/call-site-routing.ts +71 -0
  452. package/src/providers/gemini/client.ts +65 -2
  453. package/src/providers/managed-proxy/constants.ts +2 -1
  454. package/src/providers/model-catalog.ts +501 -33
  455. package/src/providers/model-intents.ts +4 -4
  456. package/src/providers/openai/chat-completions-provider.ts +57 -1
  457. package/src/providers/openai/responses-provider.ts +86 -9
  458. package/src/providers/openrouter/client.ts +76 -9
  459. package/src/providers/provider-env-vars.ts +56 -0
  460. package/src/providers/provider-send-message.ts +22 -5
  461. package/src/providers/ratelimit.ts +4 -0
  462. package/src/providers/registry.ts +19 -8
  463. package/src/providers/retry.ts +174 -39
  464. package/src/providers/speech-to-text/__tests__/resolve.test.ts +55 -0
  465. package/src/providers/speech-to-text/google-gemini-live-stream.ts +4 -4
  466. package/src/providers/speech-to-text/provider-catalog.ts +17 -0
  467. package/src/providers/speech-to-text/resolve.ts +7 -0
  468. package/src/providers/speech-to-text/xai-realtime.test.ts +578 -0
  469. package/src/providers/speech-to-text/xai-realtime.ts +796 -0
  470. package/src/providers/speech-to-text/xai.test.ts +155 -0
  471. package/src/providers/speech-to-text/xai.ts +97 -0
  472. package/src/providers/types.ts +93 -3
  473. package/src/runtime/AGENTS.md +2 -2
  474. package/src/runtime/__tests__/agent-wake.test.ts +43 -2
  475. package/src/runtime/__tests__/interactive-ui.test.ts +673 -0
  476. package/src/runtime/agent-wake.ts +63 -22
  477. package/src/runtime/auth/route-policy.ts +4 -0
  478. package/src/runtime/btw-sidechain.ts +13 -3
  479. package/src/runtime/channel-reply-delivery.ts +106 -2
  480. package/src/runtime/decision-token.ts +116 -0
  481. package/src/runtime/gateway-client.ts +2 -2
  482. package/src/runtime/http-router.ts +32 -0
  483. package/src/runtime/http-server.ts +52 -1
  484. package/src/runtime/http-types.ts +23 -1
  485. package/src/runtime/interactive-ui.ts +362 -0
  486. package/src/runtime/invite-instruction-generator.ts +2 -2
  487. package/src/runtime/migrations/__tests__/gcs-signed-url.test.ts +176 -0
  488. package/src/runtime/migrations/__tests__/vbundle-metadata-merge-integration.test.ts +390 -0
  489. package/src/runtime/migrations/__tests__/vbundle-metadata-merge.test.ts +221 -0
  490. package/src/runtime/migrations/__tests__/vbundle-streaming-importer.test.ts +1540 -0
  491. package/src/runtime/migrations/__tests__/vbundle-streaming-validator.test.ts +453 -0
  492. package/src/runtime/migrations/__tests__/vbundle-tar-stream.test.ts +222 -0
  493. package/src/runtime/migrations/gcs-signed-url.ts +162 -0
  494. package/src/runtime/migrations/vbundle-importer.ts +154 -9
  495. package/src/runtime/migrations/vbundle-metadata-merge.ts +124 -0
  496. package/src/runtime/migrations/vbundle-streaming-importer.ts +2522 -0
  497. package/src/runtime/migrations/vbundle-streaming-validator.ts +244 -0
  498. package/src/runtime/migrations/vbundle-tar-stream.ts +217 -0
  499. package/src/runtime/migrations/vbundle-validator.ts +15 -6
  500. package/src/runtime/routes/__tests__/home-feed-routes.test.ts +111 -0
  501. package/src/runtime/routes/__tests__/migration-import-credential-filter.test.ts +114 -75
  502. package/src/runtime/routes/__tests__/migration-vellum-metadata-reconcile.test.ts +246 -0
  503. package/src/runtime/routes/approval-prompt-ts-tracker.ts +58 -0
  504. package/src/runtime/routes/approval-routes.ts +12 -17
  505. package/src/runtime/routes/approval-strategies/guardian-callback-strategy.ts +9 -0
  506. package/src/runtime/routes/avatar-routes.ts +20 -4
  507. package/src/runtime/routes/btw-routes.ts +1 -4
  508. package/src/runtime/routes/conversation-management-routes.ts +20 -2
  509. package/src/runtime/routes/conversation-routes.ts +133 -27
  510. package/src/runtime/routes/debug-routes.ts +1 -1
  511. package/src/runtime/routes/diagnostics-routes.ts +6 -4
  512. package/src/runtime/routes/events-routes.ts +16 -0
  513. package/src/runtime/routes/guardian-approval-interception.ts +33 -3
  514. package/src/runtime/routes/guardian-approval-prompt.ts +13 -3
  515. package/src/runtime/routes/home-feed-routes.ts +120 -2
  516. package/src/runtime/routes/inbound-message-handler.ts +912 -2
  517. package/src/runtime/routes/inbound-stages/background-dispatch.test.ts +113 -2
  518. package/src/runtime/routes/inbound-stages/background-dispatch.ts +61 -3
  519. package/src/runtime/routes/inbound-stages/edit-intercept.ts +129 -6
  520. package/src/runtime/routes/integrations/slack/channel.ts +25 -3
  521. package/src/runtime/routes/llm-context-normalization.ts +23 -1
  522. package/src/runtime/routes/migration-routes.ts +720 -124
  523. package/src/runtime/routes/settings-routes.ts +4 -2
  524. package/src/runtime/routes/trust-rules-routes.ts +30 -14
  525. package/src/runtime/routes/work-items-routes.test.ts +1 -1
  526. package/src/runtime/routes/work-items-routes.ts +3 -2
  527. package/src/runtime/services/__tests__/analyze-conversation.test.ts +25 -43
  528. package/src/runtime/services/analyze-conversation.ts +12 -16
  529. package/src/runtime/skill-route-registry.ts +28 -6
  530. package/src/schedule/scheduler.ts +8 -0
  531. package/src/security/__tests__/provider-key-env-fallback.test.ts +119 -0
  532. package/src/security/__tests__/untrusted-content.test.ts +109 -0
  533. package/src/security/oauth2.ts +98 -35
  534. package/src/security/secure-keys.ts +7 -8
  535. package/src/security/token-manager.ts +27 -13
  536. package/src/security/untrusted-content.ts +102 -0
  537. package/src/skills/catalog-cache.ts +26 -7
  538. package/src/skills/catalog-install.ts +31 -3
  539. package/src/skills/skill-cache-store.ts +97 -0
  540. package/src/stt/__tests__/daemon-batch-transcriber.test.ts +76 -0
  541. package/src/stt/daemon-batch-transcriber.ts +33 -0
  542. package/src/stt/stt-stream-session.ts +8 -1
  543. package/src/stt/types.ts +5 -1
  544. package/src/subagent/manager.ts +41 -13
  545. package/src/tasks/ephemeral-permissions.ts +9 -4
  546. package/src/telemetry/usage-telemetry-reporter.ts +27 -5
  547. package/src/tools/browser/__tests__/browser-status.test.ts +45 -2
  548. package/src/tools/browser/browser-execution.ts +65 -38
  549. package/src/tools/browser/cdp-client/cdp-inspect/discovery.ts +22 -0
  550. package/src/tools/credentials/tool-policy.ts +39 -5
  551. package/src/tools/credentials/vault.ts +9 -4
  552. package/src/tools/executor.ts +4 -0
  553. package/src/tools/filesystem/write.ts +52 -0
  554. package/src/tools/host-terminal/host-shell.ts +45 -5
  555. package/src/tools/memory/register.test.ts +185 -0
  556. package/src/tools/memory/register.ts +3 -1
  557. package/src/tools/network/web-fetch.ts +20 -10
  558. package/src/tools/network/web-search.ts +19 -4
  559. package/src/tools/permission-checker.ts +36 -15
  560. package/src/tools/policy-context.ts +25 -8
  561. package/src/tools/registry.ts +55 -3
  562. package/src/tools/side-effects.ts +0 -11
  563. package/src/tools/skills/execute.ts +2 -2
  564. package/src/tools/skills/sandbox-runner.ts +5 -2
  565. package/src/tools/terminal/backends/native.ts +51 -2
  566. package/src/tools/terminal/safe-env.ts +3 -2
  567. package/src/tools/terminal/shell.ts +1 -0
  568. package/src/tools/tool-manifest.ts +6 -21
  569. package/src/tools/types.ts +12 -3
  570. package/src/tools/verification-control-plane-policy.ts +1 -1
  571. package/src/tts/__tests__/provider-adapters.test.ts +240 -13
  572. package/src/tts/provider-catalog.ts +18 -0
  573. package/src/tts/providers/index.ts +2 -0
  574. package/src/tts/providers/xai-provider.ts +224 -0
  575. package/src/tts/types.ts +46 -0
  576. package/src/types/tar-stream.d.ts +66 -0
  577. package/src/util/json.ts +17 -0
  578. package/src/util/platform.ts +2 -2
  579. package/src/util/pricing.ts +15 -5
  580. package/src/watcher/engine.ts +1 -1
  581. package/src/watcher/providers/google-calendar.ts +134 -8
  582. package/src/watcher/providers/outlook-calendar.ts +42 -2
  583. package/src/workspace/git-service.ts +23 -4
  584. package/src/workspace/migrations/038-unify-llm-callsite-configs.ts +516 -0
  585. package/src/workspace/migrations/039-drop-legacy-llm-keys.ts +171 -0
  586. package/src/workspace/migrations/040-seed-latency-callsite-defaults.ts +154 -0
  587. package/src/workspace/migrations/041-backfill-google-gmail-settings-scope.ts +57 -0
  588. package/src/workspace/migrations/042-fix-backfill-google-gmail-settings-scope.ts +70 -0
  589. package/src/workspace/migrations/043-release-notes-latex-rendering.ts +75 -0
  590. package/src/workspace/migrations/044-bump-stale-provider-stream-timeout.ts +51 -0
  591. package/src/workspace/migrations/045-release-notes-meet-avatar.ts +130 -0
  592. package/src/workspace/migrations/AGENTS.md +1 -1
  593. package/src/workspace/migrations/registry.ts +16 -0
  594. package/src/workspace/provider-commit-message-generator.ts +19 -38
  595. package/src/__tests__/gmail-archive-fallback.test.ts +0 -193
  596. package/src/__tests__/gmail-archive-gate.test.ts +0 -246
  597. package/src/__tests__/gmail-preferences.test.ts +0 -117
  598. package/src/__tests__/outlook-attachments.test.ts +0 -301
  599. package/src/__tests__/outlook-automation-tools.test.ts +0 -425
  600. package/src/__tests__/outlook-categories.test.ts +0 -212
  601. package/src/__tests__/outlook-compose-tools.test.ts +0 -325
  602. package/src/__tests__/outlook-declutter-tools.test.ts +0 -585
  603. package/src/__tests__/outlook-follow-up.test.ts +0 -196
  604. package/src/__tests__/outlook-trash.test.ts +0 -77
  605. package/src/__tests__/outlook-unsubscribe.test.ts +0 -279
  606. package/src/__tests__/update-bulletin-format.test.ts +0 -181
  607. package/src/__tests__/update-bulletin-state.test.ts +0 -135
  608. package/src/__tests__/update-bulletin.test.ts +0 -478
  609. package/src/__tests__/update-template-contract.test.ts +0 -29
  610. package/src/cli/commands/doctor.ts +0 -341
  611. package/src/config/bundled-skills/browser/SKILL.md +0 -88
  612. package/src/config/bundled-skills/browser/TOOLS.json +0 -516
  613. package/src/config/bundled-skills/browser/tools/browser-attach.ts +0 -12
  614. package/src/config/bundled-skills/browser/tools/browser-click.ts +0 -12
  615. package/src/config/bundled-skills/browser/tools/browser-close.ts +0 -12
  616. package/src/config/bundled-skills/browser/tools/browser-detach.ts +0 -12
  617. package/src/config/bundled-skills/browser/tools/browser-extract.ts +0 -12
  618. package/src/config/bundled-skills/browser/tools/browser-fill-credential.ts +0 -12
  619. package/src/config/bundled-skills/browser/tools/browser-hover.ts +0 -12
  620. package/src/config/bundled-skills/browser/tools/browser-navigate.ts +0 -12
  621. package/src/config/bundled-skills/browser/tools/browser-press-key.ts +0 -12
  622. package/src/config/bundled-skills/browser/tools/browser-screenshot.ts +0 -12
  623. package/src/config/bundled-skills/browser/tools/browser-scroll.ts +0 -12
  624. package/src/config/bundled-skills/browser/tools/browser-select-option.ts +0 -12
  625. package/src/config/bundled-skills/browser/tools/browser-snapshot.ts +0 -12
  626. package/src/config/bundled-skills/browser/tools/browser-status.ts +0 -12
  627. package/src/config/bundled-skills/browser/tools/browser-type.ts +0 -12
  628. package/src/config/bundled-skills/browser/tools/browser-wait-for-download.ts +0 -49
  629. package/src/config/bundled-skills/browser/tools/browser-wait-for.ts +0 -12
  630. package/src/config/bundled-skills/chatgpt-import/SKILL.md +0 -27
  631. package/src/config/bundled-skills/chatgpt-import/TOOLS.json +0 -27
  632. package/src/config/bundled-skills/chatgpt-import/tools/chatgpt-import.ts +0 -378
  633. package/src/config/bundled-skills/gmail/SKILL.md +0 -221
  634. package/src/config/bundled-skills/gmail/TOOLS.json +0 -588
  635. package/src/config/bundled-skills/gmail/tools/gmail-archive.ts +0 -256
  636. package/src/config/bundled-skills/gmail/tools/gmail-attachments.ts +0 -112
  637. package/src/config/bundled-skills/gmail/tools/gmail-draft.ts +0 -44
  638. package/src/config/bundled-skills/gmail/tools/gmail-filters.ts +0 -81
  639. package/src/config/bundled-skills/gmail/tools/gmail-follow-up.ts +0 -108
  640. package/src/config/bundled-skills/gmail/tools/gmail-forward.ts +0 -146
  641. package/src/config/bundled-skills/gmail/tools/gmail-label.ts +0 -53
  642. package/src/config/bundled-skills/gmail/tools/gmail-outreach-scan.ts +0 -347
  643. package/src/config/bundled-skills/gmail/tools/gmail-preferences-tool.ts +0 -59
  644. package/src/config/bundled-skills/gmail/tools/gmail-preferences.ts +0 -82
  645. package/src/config/bundled-skills/gmail/tools/gmail-send-draft.ts +0 -26
  646. package/src/config/bundled-skills/gmail/tools/gmail-sender-digest.ts +0 -347
  647. package/src/config/bundled-skills/gmail/tools/gmail-trash.ts +0 -29
  648. package/src/config/bundled-skills/gmail/tools/gmail-unsubscribe.ts +0 -122
  649. package/src/config/bundled-skills/gmail/tools/gmail-vacation.ts +0 -67
  650. package/src/config/bundled-skills/gmail/tools/scan-result-store.ts +0 -100
  651. package/src/config/bundled-skills/gmail/tools/shared.ts +0 -47
  652. package/src/config/bundled-skills/google-calendar/SKILL.md +0 -51
  653. package/src/config/bundled-skills/google-calendar/TOOLS.json +0 -226
  654. package/src/config/bundled-skills/google-calendar/calendar-client.ts +0 -223
  655. package/src/config/bundled-skills/google-calendar/tools/calendar-check-availability.ts +0 -27
  656. package/src/config/bundled-skills/google-calendar/tools/calendar-create-event.ts +0 -48
  657. package/src/config/bundled-skills/google-calendar/tools/calendar-get-event.ts +0 -19
  658. package/src/config/bundled-skills/google-calendar/tools/calendar-list-events.ts +0 -36
  659. package/src/config/bundled-skills/google-calendar/tools/calendar-rsvp.ts +0 -58
  660. package/src/config/bundled-skills/google-calendar/tools/shared.ts +0 -17
  661. package/src/config/bundled-skills/google-calendar/types.ts +0 -97
  662. package/src/config/bundled-skills/outlook/SKILL.md +0 -196
  663. package/src/config/bundled-skills/outlook/TOOLS.json +0 -530
  664. package/src/config/bundled-skills/outlook/tools/outlook-attachments.ts +0 -85
  665. package/src/config/bundled-skills/outlook/tools/outlook-categories.ts +0 -77
  666. package/src/config/bundled-skills/outlook/tools/outlook-draft.ts +0 -84
  667. package/src/config/bundled-skills/outlook/tools/outlook-follow-up.ts +0 -94
  668. package/src/config/bundled-skills/outlook/tools/outlook-forward.ts +0 -49
  669. package/src/config/bundled-skills/outlook/tools/outlook-outreach-scan.ts +0 -237
  670. package/src/config/bundled-skills/outlook/tools/outlook-rules.ts +0 -161
  671. package/src/config/bundled-skills/outlook/tools/outlook-send-draft.ts +0 -32
  672. package/src/config/bundled-skills/outlook/tools/outlook-sender-digest.ts +0 -272
  673. package/src/config/bundled-skills/outlook/tools/outlook-trash.ts +0 -29
  674. package/src/config/bundled-skills/outlook/tools/outlook-unsubscribe.ts +0 -129
  675. package/src/config/bundled-skills/outlook/tools/outlook-vacation.ts +0 -87
  676. package/src/config/bundled-skills/outlook/tools/shared.ts +0 -20
  677. package/src/config/bundled-skills/outlook-calendar/SKILL.md +0 -51
  678. package/src/config/bundled-skills/outlook-calendar/TOOLS.json +0 -221
  679. package/src/config/bundled-skills/outlook-calendar/calendar-client.ts +0 -252
  680. package/src/config/bundled-skills/outlook-calendar/tools/outlook-calendar-check-availability.ts +0 -53
  681. package/src/config/bundled-skills/outlook-calendar/tools/outlook-calendar-create-event.ts +0 -74
  682. package/src/config/bundled-skills/outlook-calendar/tools/outlook-calendar-get-event.ts +0 -18
  683. package/src/config/bundled-skills/outlook-calendar/tools/outlook-calendar-list-events.ts +0 -46
  684. package/src/config/bundled-skills/outlook-calendar/tools/outlook-calendar-rsvp.ts +0 -36
  685. package/src/config/bundled-skills/outlook-calendar/tools/shared.ts +0 -17
  686. package/src/config/bundled-skills/outlook-calendar/types.ts +0 -120
  687. package/src/config/bundled-skills/slack/SKILL.md +0 -108
  688. package/src/config/bundled-skills/tasks/SKILL.md +0 -37
  689. package/src/config/bundled-skills/tasks/TOOLS.json +0 -353
  690. package/src/config/bundled-skills/tasks/icon.svg +0 -34
  691. package/src/config/bundled-skills/tasks/tools/task-delete.ts +0 -12
  692. package/src/config/bundled-skills/tasks/tools/task-list-add.ts +0 -12
  693. package/src/config/bundled-skills/tasks/tools/task-list-remove.ts +0 -12
  694. package/src/config/bundled-skills/tasks/tools/task-list-show.ts +0 -12
  695. package/src/config/bundled-skills/tasks/tools/task-list-update.ts +0 -12
  696. package/src/config/bundled-skills/tasks/tools/task-list.ts +0 -12
  697. package/src/config/bundled-skills/tasks/tools/task-queue-run.ts +0 -12
  698. package/src/config/bundled-skills/tasks/tools/task-run.ts +0 -12
  699. package/src/config/bundled-skills/tasks/tools/task-save.ts +0 -12
  700. package/src/config/bundled-skills/watcher/SKILL.md +0 -31
  701. package/src/config/bundled-skills/watcher/TOOLS.json +0 -167
  702. package/src/config/bundled-skills/watcher/tools/watcher-create.ts +0 -12
  703. package/src/config/bundled-skills/watcher/tools/watcher-delete.ts +0 -12
  704. package/src/config/bundled-skills/watcher/tools/watcher-digest.ts +0 -12
  705. package/src/config/bundled-skills/watcher/tools/watcher-list.ts +0 -12
  706. package/src/config/bundled-skills/watcher/tools/watcher-update.ts +0 -12
  707. package/src/prompts/templates/UPDATES.md +0 -50
  708. package/src/prompts/update-bulletin-format.ts +0 -85
  709. package/src/prompts/update-bulletin-state.ts +0 -58
  710. package/src/prompts/update-bulletin-template-path.ts +0 -13
  711. package/src/prompts/update-bulletin.ts +0 -139
  712. package/src/shared/provider-env-vars.ts +0 -19
  713. package/src/tools/watcher/create.ts +0 -86
  714. package/src/tools/watcher/delete.ts +0 -36
  715. package/src/tools/watcher/digest.ts +0 -54
  716. package/src/tools/watcher/list.ts +0 -83
  717. package/src/tools/watcher/update.ts +0 -71
@@ -119,9 +119,19 @@ export interface WakeOptions {
119
119
  source: string;
120
120
  }
121
121
 
122
+ /**
123
+ * Reason a wake returned `invoked: false`. Callers (CLI, update-bulletin
124
+ * job) need to distinguish "conversation doesn't exist" from "conversation
125
+ * exists but stayed busy past the wait-until-idle timeout" — the former is
126
+ * a user-visible error, the latter is an expected transient condition.
127
+ */
128
+ export type WakeSkipReason = "not_found" | "timeout" | "no_resolver";
129
+
122
130
  export interface WakeResult {
123
131
  invoked: boolean;
124
132
  producedToolCalls: boolean;
133
+ /** Present only when `invoked: false`; identifies why the wake was skipped. */
134
+ reason?: WakeSkipReason;
125
135
  }
126
136
 
127
137
  /**
@@ -223,13 +233,12 @@ async function waitUntilIdle(
223
233
  target: WakeTarget,
224
234
  nowFn: () => number,
225
235
  timeoutMs = 30_000,
226
- ): Promise<void> {
236
+ ): Promise<boolean> {
227
237
  const deadline = nowFn() + timeoutMs;
228
- // 50ms backoff is fine — wakes are not latency-critical and a user turn
229
- // typically completes on the order of seconds.
230
238
  while (target.isProcessing() && nowFn() < deadline) {
231
239
  await new Promise((resolve) => setTimeout(resolve, 50));
232
240
  }
241
+ return !target.isProcessing();
233
242
  }
234
243
 
235
244
  /**
@@ -300,7 +309,7 @@ export async function wakeAgentForOpportunity(
300
309
  { conversationId, source },
301
310
  "agent-wake: no resolver available (default resolver not registered and no deps passed); skipping",
302
311
  );
303
- return { invoked: false, producedToolCalls: false };
312
+ return { invoked: false, producedToolCalls: false, reason: "no_resolver" };
304
313
  }
305
314
  const nowFn = deps?.now ?? Date.now;
306
315
  const startedAt = nowFn();
@@ -312,10 +321,17 @@ export async function wakeAgentForOpportunity(
312
321
  { conversationId, source },
313
322
  "agent-wake: conversation not found; skipping",
314
323
  );
315
- return { invoked: false, producedToolCalls: false };
324
+ return { invoked: false, producedToolCalls: false, reason: "not_found" };
316
325
  }
317
326
 
318
- await waitUntilIdle(target, nowFn);
327
+ const idle = await waitUntilIdle(target, nowFn);
328
+ if (!idle) {
329
+ log.warn(
330
+ { conversationId, source },
331
+ "agent-wake: conversation still processing after timeout; skipping",
332
+ );
333
+ return { invoked: false, producedToolCalls: false, reason: "timeout" };
334
+ }
319
335
 
320
336
  const baseline = target.getMessages();
321
337
  const hintContent = `[opportunity:${source}] ${hint}`;
@@ -346,6 +362,7 @@ export async function wakeAgentForOpportunity(
346
362
  let producedToolCalls = false;
347
363
  let toolUseNames: string[] = [];
348
364
  let tailMessageCount = 0;
365
+ let drainedInTry = false;
349
366
  try {
350
367
  let updatedHistory: Message[];
351
368
  try {
@@ -375,8 +392,11 @@ export async function wakeAgentForOpportunity(
375
392
  // `drainSingleMessage` reads `ctx.messages` mid-tail and writes a
376
393
  // DB row that lands out of chronological order (queued user msg
377
394
  // before the wake's just-produced assistant outputs).
378
- const { tailMessages, hasVisibleText, toolUseNames: names } =
379
- inspectWakeOutput(baseline.length, updatedHistory);
395
+ const {
396
+ tailMessages,
397
+ hasVisibleText,
398
+ toolUseNames: names,
399
+ } = inspectWakeOutput(baseline.length, updatedHistory);
380
400
  toolUseNames = names;
381
401
  producedToolCalls = names.length > 0;
382
402
  const producedOutput = producedToolCalls || hasVisibleText;
@@ -431,11 +451,12 @@ export async function wakeAgentForOpportunity(
431
451
  }
432
452
  }
433
453
 
434
- return { invoked: true, producedToolCalls };
435
- } finally {
436
- // Release the processing marker regardless of success/failure so
437
- // the next user turn (or wake) isn't blocked waiting on a stale
438
- // flag.
454
+ // Drain queued messages AFTER tail is pushed + persisted so the
455
+ // next dequeued user message sees the complete, up-to-date
456
+ // history. markProcessing(false) must come first (the queue only
457
+ // accepts entries while processing === true, and drain expects
458
+ // processing to already be false). The finally block handles the
459
+ // error/early-return paths where no tail was produced.
439
460
  try {
440
461
  target.markProcessing(false);
441
462
  } catch (err) {
@@ -444,15 +465,6 @@ export async function wakeAgentForOpportunity(
444
465
  "agent-wake: markProcessing(false) threw; continuing",
445
466
  );
446
467
  }
447
- // Drain any messages queued during the wake. Order matters:
448
- // `enqueueMessage()` only queues when `processing === true`, so
449
- // late sends arriving while the wake was running landed on the
450
- // queue. The canonical user-turn finally calls drain after
451
- // resetting `processing = false` AND after `ctx.messages` has
452
- // been updated with the new tail; mirror that here so a queued
453
- // message is picked up against an updated history rather than
454
- // stranded behind an out-of-order DB row. Wrapped in try/catch
455
- // so a drain failure can't propagate out of the wake.
456
468
  if (target.drainQueue) {
457
469
  try {
458
470
  await target.drainQueue();
@@ -463,6 +475,35 @@ export async function wakeAgentForOpportunity(
463
475
  );
464
476
  }
465
477
  }
478
+ drainedInTry = true;
479
+
480
+ return { invoked: true, producedToolCalls };
481
+ } finally {
482
+ // The success path (above) already called markProcessing(false)
483
+ // + drainQueue after tail persist. This catch-all handles the
484
+ // error and early-return paths where no tail was produced — those
485
+ // exit the try body before reaching the drain block, so
486
+ // `drainedInTry` is still false.
487
+ if (!drainedInTry) {
488
+ try {
489
+ target.markProcessing(false);
490
+ } catch (err) {
491
+ log.warn(
492
+ { conversationId, source, err },
493
+ "agent-wake: markProcessing(false) threw; continuing",
494
+ );
495
+ }
496
+ if (target.drainQueue) {
497
+ try {
498
+ await target.drainQueue();
499
+ } catch (err) {
500
+ log.warn(
501
+ { conversationId, source, err },
502
+ "agent-wake: drainQueue threw; continuing",
503
+ );
504
+ }
505
+ }
506
+ }
466
507
 
467
508
  const durationMs = nowFn() - startedAt;
468
509
  if (runError) {
@@ -214,6 +214,10 @@ const ACTOR_ENDPOINTS: Array<{ endpoint: string; scopes: Scope[] }> = [
214
214
  endpoint: "integrations/slack/channel/config:DELETE",
215
215
  scopes: ["settings.write"],
216
216
  },
217
+ {
218
+ endpoint: "integrations/slack/channel/oauth-install:POST",
219
+ scopes: ["settings.write"],
220
+ },
217
221
  { endpoint: "channel-verification-sessions", scopes: ["settings.write"] },
218
222
  {
219
223
  endpoint: "channel-verification-sessions:DELETE",
@@ -1,3 +1,4 @@
1
+ import type { LLMCallSite } from "../config/schemas/llm.js";
1
2
  import { buildToolDefinitions } from "../daemon/conversation-tool-setup.js";
2
3
  import { buildSystemPrompt } from "../prompts/system-prompt.js";
3
4
  import {
@@ -7,7 +8,6 @@ import {
7
8
  } from "../providers/provider-send-message.js";
8
9
  import type {
9
10
  Message,
10
- ModelIntent,
11
11
  Provider,
12
12
  ProviderEvent,
13
13
  ProviderResponse,
@@ -29,7 +29,15 @@ export interface RunBtwSidechainParams {
29
29
  systemPrompt?: string;
30
30
  tools?: ToolDefinition[];
31
31
  maxTokens?: number;
32
- modelIntent?: ModelIntent;
32
+ /**
33
+ * Unified call-site identifier. The provider layer resolves
34
+ * provider/model/maxTokens/effort/speed/temperature/thinking/contextWindow
35
+ * via `resolveCallSiteConfig(callSite, config.llm)`. Defaults to
36
+ * `'identityIntro'` since this side-chain runner was originally introduced
37
+ * for the identity intro generation path; callers (greeting, title, etc.)
38
+ * override it with their own call-site ID.
39
+ */
40
+ callSite?: LLMCallSite;
33
41
  signal?: AbortSignal;
34
42
  timeoutMs?: number;
35
43
  onEvent?: (event: ProviderEvent) => void;
@@ -89,7 +97,9 @@ export async function runBtwSidechain(
89
97
  config: {
90
98
  max_tokens: params.maxTokens ?? 1024,
91
99
  tool_choice: { type: "none" },
92
- modelIntent: params.modelIntent ?? "latency-optimized",
100
+ // Default call site is "identityIntro" — the original purpose of
101
+ // this side-chain runner. Callers may override per invocation.
102
+ callSite: params.callSite ?? ("identityIntro" as LLMCallSite),
93
103
  },
94
104
  onEvent: (event) => {
95
105
  if (event.type === "text_delta") {
@@ -1,6 +1,12 @@
1
1
  import { renderHistoryContent } from "../daemon/handlers/shared.js";
2
2
  import * as attachmentsStore from "../memory/attachments-store.js";
3
- import { getMessages } from "../memory/conversation-crud.js";
3
+ import {
4
+ getMessageById,
5
+ getMessages,
6
+ updateMessageMetadata,
7
+ } from "../memory/conversation-crud.js";
8
+ import { readSlackMetadata } from "../messaging/providers/slack/message-metadata.js";
9
+ import { getLogger } from "../util/logger.js";
4
10
  import type { ChannelDeliveryResult } from "./gateway-client.js";
5
11
  import { deliverChannelReply } from "./gateway-client.js";
6
12
  import type { RuntimeAttachmentMetadata } from "./http-types.js";
@@ -9,6 +15,8 @@ import {
9
15
  textToSlackBlocks,
10
16
  } from "./slack-block-formatting.js";
11
17
 
18
+ const log = getLogger("channel-reply-delivery");
19
+
12
20
  const INTER_SEGMENT_DELAY_MS = 150;
13
21
 
14
22
  type DeliverRenderedReplyParams = {
@@ -206,6 +214,22 @@ export async function deliverReplyViaCallback(
206
214
  kind: a.kind,
207
215
  }));
208
216
 
217
+ // Compose an `onMessageTs` that reconciles `slackMeta.channelTs` on the
218
+ // persisted assistant row once Slack returns the authoritative ts. The
219
+ // assistant row was written BEFORE the gateway POST in
220
+ // `handleMessageComplete`, so the partial `slackMeta` it carries is
221
+ // missing `channelTs` and would otherwise be rejected by
222
+ // `readSlackMetadata`, dropping the row out of chronological/thread-tag
223
+ // rendering. We only act on the FIRST ts (top-level segment); any
224
+ // subsequent split segments become independent Slack messages with
225
+ // their own ts and are not represented as separate DB rows.
226
+ const reconcileOnMessageTs = makeChannelTsReconciler(msgs[i].id);
227
+ const callerOnMessageTs = options?.onMessageTs;
228
+ const composedOnMessageTs = (ts: string): void => {
229
+ reconcileOnMessageTs(ts);
230
+ callerOnMessageTs?.(ts);
231
+ };
232
+
209
233
  await deliverRenderedReplyViaCallback({
210
234
  callbackUrl,
211
235
  chatId: externalChatId,
@@ -219,8 +243,88 @@ export async function deliverReplyViaCallback(
219
243
  ephemeral: options?.ephemeral,
220
244
  user: options?.user,
221
245
  messageTs: options?.messageTs,
222
- onMessageTs: options?.onMessageTs,
246
+ onMessageTs: composedOnMessageTs,
223
247
  });
224
248
  break;
225
249
  }
226
250
  }
251
+
252
+ /**
253
+ * Build a one-shot `onMessageTs` handler that reconciles the persisted
254
+ * assistant message's `slackMeta.channelTs` from Slack's authoritative `ts`.
255
+ *
256
+ * Behavior:
257
+ * - Acts only on the first invocation per delivery (subsequent segments
258
+ * correspond to independent Slack messages with their own ts and are not
259
+ * represented as separate DB rows).
260
+ * - No-op when the row was not persisted with a `slackMeta` envelope (the
261
+ * channel was not Slack at write-time, e.g. vellum/telegram outbound).
262
+ * - No-op when the row's existing `slackMeta` already parses cleanly via
263
+ * `readSlackMetadata` (channelTs already present, e.g. from a prior
264
+ * reconciliation).
265
+ * - Failures are logged and swallowed so a transient DB error cannot break
266
+ * the outbound delivery itself.
267
+ */
268
+ function makeChannelTsReconciler(messageId: string): (ts: string) => void {
269
+ let applied = false;
270
+ return (ts: string): void => {
271
+ if (applied) return;
272
+ applied = true;
273
+ if (!ts) return;
274
+ try {
275
+ // Re-read the row's current metadata so a concurrent edit-propagation
276
+ // write (e.g. `editedAt`) is not clobbered. `updateMessageMetadata`
277
+ // shallow-merges into the top-level envelope, and the slackMeta
278
+ // sub-object is merged manually below so we can preserve fields on
279
+ // the partial pre-send envelope (`mergeSlackMetadata` would call
280
+ // `readSlackMetadata` which rejects the partial form for lacking
281
+ // channelTs — exactly the state we are reconciling).
282
+ const row = getMessageById(messageId);
283
+ if (row === null || row.metadata === null) return;
284
+ let envelope: Record<string, unknown>;
285
+ try {
286
+ envelope = JSON.parse(row.metadata) as Record<string, unknown>;
287
+ } catch {
288
+ return;
289
+ }
290
+ const slackMetaRaw =
291
+ typeof envelope.slackMeta === "string" ? envelope.slackMeta : null;
292
+ if (slackMetaRaw === null) return;
293
+ // If the existing slackMeta already parses cleanly via the strict
294
+ // reader, channelTs is already present (a prior reconciliation ran,
295
+ // or backfill stamped the field) — nothing to do.
296
+ if (readSlackMetadata(slackMetaRaw) !== null) return;
297
+ // Lenient parse of the partial slackMeta so we can preserve every
298
+ // field already written by `handleMessageComplete` (source,
299
+ // eventKind, channelId, threadTs, ...) while patching channelTs in.
300
+ let existingSlackMeta: Record<string, unknown>;
301
+ try {
302
+ const parsed = JSON.parse(slackMetaRaw) as unknown;
303
+ if (
304
+ parsed === null ||
305
+ typeof parsed !== "object" ||
306
+ Array.isArray(parsed)
307
+ ) {
308
+ return;
309
+ }
310
+ existingSlackMeta = parsed as Record<string, unknown>;
311
+ } catch {
312
+ return;
313
+ }
314
+ const mergedSlackMeta = JSON.stringify({
315
+ ...existingSlackMeta,
316
+ channelTs: ts,
317
+ // Force `source: "slack"` for parity with `mergeSlackMetadata`'s
318
+ // invariant — the reader rejects anything else and we never want a
319
+ // reconciled row to slip through with a stale source.
320
+ source: "slack",
321
+ });
322
+ updateMessageMetadata(messageId, { slackMeta: mergedSlackMeta });
323
+ } catch (err) {
324
+ log.warn(
325
+ { err, messageId },
326
+ "Failed to reconcile slackMeta.channelTs on outbound assistant row",
327
+ );
328
+ }
329
+ };
330
+ }
@@ -0,0 +1,116 @@
1
+ /**
2
+ * Lightweight informational decision token for interactive UI outcomes.
3
+ *
4
+ * Minted when a confirmation-style surface is `submitted`. The token is
5
+ * **non-authoritative** — it carries metadata about the decision for
6
+ * audit and correlation purposes only. It does not grant any capability
7
+ * and must not be used for enforcement or replay protection (that is
8
+ * explicitly out of scope for v1).
9
+ *
10
+ * Format: base64url-encoded JSON payload + `.` + random nonce.
11
+ * The nonce makes tokens unique even for identical payloads; the
12
+ * payload is readable by any consumer without a secret.
13
+ *
14
+ * This module is intentionally decoupled from the existing auth/token
15
+ * infrastructure in `runtime/auth/` — it serves a different purpose
16
+ * and should remain independent.
17
+ */
18
+
19
+ import { randomBytes } from "node:crypto";
20
+
21
+ // ── Token shape ──────────────────────────────────────────────────────
22
+
23
+ export interface DecisionTokenPayload {
24
+ /** Conversation the decision belongs to. */
25
+ conversationId: string;
26
+ /** Surface identifier that was displayed. */
27
+ surfaceId: string;
28
+ /** The action ID the user selected (e.g. "confirm"). Only present on affirmative confirmation. */
29
+ action: string;
30
+ /** ISO-8601 timestamp when the decision was recorded. */
31
+ issuedAt: string;
32
+ /** ISO-8601 timestamp after which the token should be considered stale. */
33
+ expiresAt: string;
34
+ }
35
+
36
+ /** Default token lifetime: 5 minutes. */
37
+ const DEFAULT_TTL_MS = 5 * 60 * 1000;
38
+
39
+ // ── Minting ──────────────────────────────────────────────────────────
40
+
41
+ /**
42
+ * Mint an informational decision token.
43
+ *
44
+ * The returned string is `<base64url-payload>.<random-nonce>`. It is
45
+ * short-lived (default 5 minutes) and non-authoritative.
46
+ *
47
+ * @param opts - Decision metadata.
48
+ * @param opts.conversationId - Conversation scope.
49
+ * @param opts.surfaceId - Surface that was displayed.
50
+ * @param opts.action - Terminal action taken by the user.
51
+ * @param opts.ttlMs - Token lifetime in milliseconds (default 5 min).
52
+ * @returns The minted token string.
53
+ */
54
+ export function mintDecisionToken(opts: {
55
+ conversationId: string;
56
+ surfaceId: string;
57
+ action: string;
58
+ ttlMs?: number;
59
+ }): string {
60
+ const now = new Date();
61
+ const ttl = opts.ttlMs ?? DEFAULT_TTL_MS;
62
+ const expiresAt = new Date(now.getTime() + ttl);
63
+
64
+ const payload: DecisionTokenPayload = {
65
+ conversationId: opts.conversationId,
66
+ surfaceId: opts.surfaceId,
67
+ action: opts.action,
68
+ issuedAt: now.toISOString(),
69
+ expiresAt: expiresAt.toISOString(),
70
+ };
71
+
72
+ const encoded = Buffer.from(JSON.stringify(payload)).toString("base64url");
73
+ const nonce = randomBytes(12).toString("hex");
74
+
75
+ return `${encoded}.${nonce}`;
76
+ }
77
+
78
+ // ── Decoding (informational only) ────────────────────────────────────
79
+
80
+ /**
81
+ * Decode a decision token's payload.
82
+ *
83
+ * This is a pure decoding step — there is no signature verification
84
+ * because the token is non-authoritative. Consumers should treat the
85
+ * payload as informational metadata, not a trust assertion.
86
+ *
87
+ * @param token - The token string produced by {@link mintDecisionToken}.
88
+ * @returns The decoded payload, or `null` if the token is malformed.
89
+ */
90
+ export function decodeDecisionToken(
91
+ token: string,
92
+ ): DecisionTokenPayload | null {
93
+ const dotIdx = token.indexOf(".");
94
+ if (dotIdx < 0) return null;
95
+
96
+ const encodedPayload = token.slice(0, dotIdx);
97
+ try {
98
+ const json = Buffer.from(encodedPayload, "base64url").toString("utf-8");
99
+ const parsed = JSON.parse(json) as Record<string, unknown>;
100
+
101
+ // Minimal structural validation
102
+ if (
103
+ typeof parsed.conversationId !== "string" ||
104
+ typeof parsed.surfaceId !== "string" ||
105
+ typeof parsed.action !== "string" ||
106
+ typeof parsed.issuedAt !== "string" ||
107
+ typeof parsed.expiresAt !== "string"
108
+ ) {
109
+ return null;
110
+ }
111
+
112
+ return parsed as unknown as DecisionTokenPayload;
113
+ } catch {
114
+ return null;
115
+ }
116
+ }
@@ -397,8 +397,8 @@ export async function deliverApprovalPrompt(
397
397
  approval: ApprovalUIMetadata,
398
398
  assistantId?: string,
399
399
  bearerToken?: string,
400
- ): Promise<void> {
401
- await deliverChannelReply(
400
+ ): Promise<ChannelDeliveryResult> {
401
+ return deliverChannelReply(
402
402
  callbackUrl,
403
403
  { chatId, text, approval, assistantId },
404
404
  bearerToken,
@@ -48,6 +48,29 @@ export interface RouteQueryParam {
48
48
  * The generate-openapi script converts these to JSON Schema via z.toJSONSchema(). */
49
49
  export type RouteBodySchema = z.ZodType;
50
50
 
51
+ /**
52
+ * Description for a non-200 response variant. Used when an endpoint has
53
+ * meaningful alternate response shapes that clients should handle (e.g.
54
+ * 502 `fetch_failed` on POST /v1/migrations/import when the URL body path
55
+ * can't reach the upstream bundle host).
56
+ */
57
+ export interface RouteAdditionalResponse {
58
+ description: string;
59
+ /** Zod schema or plain JSON Schema fragment. */
60
+ schema?: RouteBodySchema | Record<string, unknown>;
61
+ }
62
+
63
+ /**
64
+ * Request-body variant keyed by Content-Type. Use this when an endpoint
65
+ * accepts multiple body shapes (e.g. `application/octet-stream` OR
66
+ * `application/json`). For the common single-JSON case, use `requestBody`.
67
+ */
68
+ export interface RouteRequestBodyVariant {
69
+ contentType: string;
70
+ /** Zod schema or plain JSON Schema fragment. Plain objects are embedded verbatim. */
71
+ schema: RouteBodySchema | Record<string, unknown>;
72
+ }
73
+
51
74
  /**
52
75
  * A single route entry in the declarative table.
53
76
  *
@@ -76,8 +99,17 @@ export interface RouteDefinition {
76
99
  queryParams?: RouteQueryParam[];
77
100
  /** Zod schema for the request body (POST/PUT/PATCH/DELETE). */
78
101
  requestBody?: RouteBodySchema;
102
+ /**
103
+ * Alternate request-body variants keyed by Content-Type. When set,
104
+ * overrides `requestBody` in the generated OpenAPI spec — use this for
105
+ * endpoints that accept multiple body shapes on the same URL (e.g.
106
+ * raw bytes OR JSON URL).
107
+ */
108
+ requestBodies?: RouteRequestBodyVariant[];
79
109
  /** Zod schema for the 200 response body. */
80
110
  responseBody?: RouteBodySchema;
111
+ /** Additional non-200 responses documented in the generated OpenAPI spec. */
112
+ additionalResponses?: Record<string, RouteAdditionalResponse>;
81
113
  }
82
114
 
83
115
  // ---------------------------------------------------------------------------
@@ -1066,6 +1066,12 @@ export class RuntimeHttpServer {
1066
1066
  // tokens minted by a session manager).
1067
1067
  const skillMatch = matchSkillRoute(path, req.method);
1068
1068
  if (skillMatch) {
1069
+ if (skillMatch.kind === "methodMismatch") {
1070
+ return new Response("Method Not Allowed", {
1071
+ status: 405,
1072
+ headers: { Allow: skillMatch.allow.join(", ") },
1073
+ });
1074
+ }
1069
1075
  return await skillMatch.route.handler(req, skillMatch.match);
1070
1076
  }
1071
1077
 
@@ -1851,6 +1857,21 @@ export class RuntimeHttpServer {
1851
1857
  404,
1852
1858
  );
1853
1859
  try {
1860
+ // Snapshot current state to detect whether the seen cursor
1861
+ // actually advances (avoids emitting on no-op signals).
1862
+ // Only consider a conversation "unseen" when a latest assistant
1863
+ // message exists and the seen cursor is behind it — matching
1864
+ // the hasUnseenLatestAssistantMessage logic in buildAssistantAttention.
1865
+ const priorState = getAttentionStateByConversationIds([
1866
+ conversationId,
1867
+ ]).get(conversationId);
1868
+ const wasUnseen =
1869
+ priorState != null &&
1870
+ priorState.latestAssistantMessageAt != null &&
1871
+ (priorState.lastSeenAssistantMessageAt == null ||
1872
+ priorState.lastSeenAssistantMessageAt <
1873
+ priorState.latestAssistantMessageAt);
1874
+
1854
1875
  recordConversationSeenSignal({
1855
1876
  conversationId,
1856
1877
  sourceChannel: (body.sourceChannel as string) ?? "vellum",
@@ -1863,6 +1884,21 @@ export class RuntimeHttpServer {
1863
1884
  metadata: body.metadata as Record<string, unknown> | undefined,
1864
1885
  observedAt: body.observedAt as number | undefined,
1865
1886
  });
1887
+ if (wasUnseen) {
1888
+ assistantEventHub
1889
+ .publish(
1890
+ buildAssistantEvent(DAEMON_INTERNAL_ASSISTANT_ID, {
1891
+ type: "conversation_list_invalidated",
1892
+ reason: "seen_changed",
1893
+ }),
1894
+ )
1895
+ .catch((err) => {
1896
+ log.warn(
1897
+ { err },
1898
+ "Failed to publish conversation_list_invalidated (seen_changed)",
1899
+ );
1900
+ });
1901
+ }
1866
1902
  return Response.json({ ok: true });
1867
1903
  } catch (err) {
1868
1904
  log.error(
@@ -1894,7 +1930,22 @@ export class RuntimeHttpServer {
1894
1930
  404,
1895
1931
  );
1896
1932
  try {
1897
- markConversationUnread(conversationId);
1933
+ const changed = markConversationUnread(conversationId);
1934
+ if (changed) {
1935
+ assistantEventHub
1936
+ .publish(
1937
+ buildAssistantEvent(DAEMON_INTERNAL_ASSISTANT_ID, {
1938
+ type: "conversation_list_invalidated",
1939
+ reason: "seen_changed",
1940
+ }),
1941
+ )
1942
+ .catch((err) => {
1943
+ log.warn(
1944
+ { err },
1945
+ "Failed to publish conversation_list_invalidated (seen_changed)",
1946
+ );
1947
+ });
1948
+ }
1898
1949
  return Response.json({ ok: true });
1899
1950
  } catch (err) {
1900
1951
  if (err instanceof UserError) {
@@ -2,10 +2,18 @@
2
2
  * Shared types for the runtime HTTP server and its route handlers.
3
3
  */
4
4
  import type { ChannelId, InterfaceId } from "../channels/types.js";
5
+ import type { LLMCallSite } from "../config/schemas/llm.js";
5
6
  import type { CesClient } from "../credential-execution/client.js";
6
7
  import type { Conversation } from "../daemon/conversation.js";
7
8
  import type { TrustContext } from "../daemon/conversation-runtime-assembly.js";
8
- import type { ConversationCreateOptions } from "../daemon/handlers/shared.js";
9
+ import type {
10
+ ConversationCreateOptions,
11
+ SlackInboundMessageMetadata,
12
+ } from "../daemon/handlers/shared.js";
13
+
14
+ // Re-export so route modules (background-dispatch, etc.) can pull the type
15
+ // from the runtime barrel without reaching into daemon internals.
16
+ export type { SlackInboundMessageMetadata };
9
17
  import type { SkillOperationContext } from "../daemon/handlers/skills.js";
10
18
  import type { ServerMessage } from "../daemon/message-protocol.js";
11
19
  import type {
@@ -132,6 +140,20 @@ export interface RuntimeMessageConversationOptions {
132
140
  commandIntent?: { type: string; payload?: string; languageCode?: string };
133
141
  /** Optional callback to receive real-time agent loop events (text deltas, tool starts, etc.). */
134
142
  onEvent?: (msg: ServerMessage) => void;
143
+ /**
144
+ * Optional LLM call-site identifier. Channel ingress and other inbound paths
145
+ * may pass this so the daemon's per-call provider config picks up the right
146
+ * profile via `resolveCallSiteConfig`. PRs 7-11 wire individual call-site
147
+ * literals into specific call paths.
148
+ */
149
+ callSite?: LLMCallSite;
150
+ /**
151
+ * Slack inbound metadata captured at the channel ingress boundary. When
152
+ * present (and the turn channel resolves to Slack), persistence writes a
153
+ * `slackMeta` sub-object into the message's `metadata` JSON for the
154
+ * chronological renderer to consume.
155
+ */
156
+ slackInbound?: SlackInboundMessageMetadata;
135
157
  }
136
158
 
137
159
  export type MessageProcessor = (