@vellumai/assistant 0.7.0 → 0.7.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (666) hide show
  1. package/ARCHITECTURE.md +6 -7
  2. package/Dockerfile +1 -0
  3. package/README.md +2 -2
  4. package/__tests__/permissions/gateway-threshold-reader.test.ts +79 -139
  5. package/bun.lock +3 -0
  6. package/docs/architecture/security.md +18 -16
  7. package/knip.json +1 -0
  8. package/node_modules/@vellumai/skill-host-contracts/__tests__/client.test.ts +1 -5
  9. package/node_modules/@vellumai/skill-host-contracts/src/assistant-event.ts +0 -5
  10. package/node_modules/@vellumai/skill-host-contracts/src/client.ts +10 -16
  11. package/node_modules/@vellumai/skill-host-contracts/src/skill-host.ts +1 -9
  12. package/node_modules/@vellumai/skill-host-contracts/src/tool-types.ts +12 -12
  13. package/node_modules/@vellumai/slack-text/bun.lock +24 -0
  14. package/node_modules/@vellumai/slack-text/package.json +18 -0
  15. package/node_modules/@vellumai/slack-text/src/index.test.ts +153 -0
  16. package/node_modules/@vellumai/slack-text/src/index.ts +235 -0
  17. package/node_modules/@vellumai/slack-text/tsconfig.json +20 -0
  18. package/openapi.yaml +294 -107
  19. package/package.json +4 -2
  20. package/scripts/generate-openapi.ts +16 -111
  21. package/src/__tests__/agent-wake-override-profile.test.ts +23 -1
  22. package/src/__tests__/anthropic-provider.test.ts +56 -13
  23. package/src/__tests__/app-conversation-ids-backfill.test.ts +278 -0
  24. package/src/__tests__/app-conversation-ids.test.ts +151 -0
  25. package/src/__tests__/approval-cascade.test.ts +0 -15
  26. package/src/__tests__/approval-routes-http.test.ts +6 -17
  27. package/src/__tests__/assistant-event-hub.test.ts +126 -77
  28. package/src/__tests__/assistant-event.test.ts +0 -5
  29. package/src/__tests__/assistant-events-sse-hardening.test.ts +37 -15
  30. package/src/__tests__/assistant-feature-flags-integration.test.ts +0 -29
  31. package/src/__tests__/background-shell-host-bash.test.ts +34 -43
  32. package/src/__tests__/call-controller.test.ts +1 -1
  33. package/src/__tests__/call-site-routing-provider.test.ts +193 -0
  34. package/src/__tests__/channel-approval-routes.test.ts +10 -296
  35. package/src/__tests__/channel-approvals.test.ts +25 -17
  36. package/src/__tests__/channel-guardian.test.ts +100 -146
  37. package/src/__tests__/checker.test.ts +20 -34
  38. package/src/__tests__/compact-event-conversation-id-guard.test.ts +50 -0
  39. package/src/__tests__/compaction-events.test.ts +2 -0
  40. package/src/__tests__/config-schema.test.ts +6 -48
  41. package/src/__tests__/config-watcher.test.ts +12 -0
  42. package/src/__tests__/connection-policy.test.ts +1 -52
  43. package/src/__tests__/contacts-write.test.ts +2 -64
  44. package/src/__tests__/context-image-dimensions.test.ts +1 -1
  45. package/src/__tests__/context-search-memory-source.test.ts +120 -1
  46. package/src/__tests__/context-search-memory-v2-source.test.ts +383 -0
  47. package/src/__tests__/context-search-pkb-source.test.ts +49 -0
  48. package/src/__tests__/context-search-workspace-source.test.ts +9 -22
  49. package/src/__tests__/context-window-manager.test.ts +46 -0
  50. package/src/__tests__/conversation-agent-loop-inference-profile.test.ts +2 -0
  51. package/src/__tests__/conversation-agent-loop-overflow.test.ts +102 -29
  52. package/src/__tests__/conversation-agent-loop.test.ts +980 -13
  53. package/src/__tests__/conversation-analysis-routes.test.ts +12 -10
  54. package/src/__tests__/conversation-attention-telegram.test.ts +11 -3
  55. package/src/__tests__/conversation-confirmation-signals.test.ts +0 -291
  56. package/src/__tests__/conversation-history-web-search.test.ts +4 -3
  57. package/src/__tests__/conversation-inference-profile-route.test.ts +12 -23
  58. package/src/__tests__/conversation-lifecycle.test.ts +4 -4
  59. package/src/__tests__/conversation-process-callsite.test.ts +79 -2
  60. package/src/__tests__/conversation-queue.test.ts +3 -8
  61. package/src/__tests__/conversation-routes-disk-view.test.ts +1 -161
  62. package/src/__tests__/conversation-routes-guardian-reply.test.ts +0 -32
  63. package/src/__tests__/conversation-routes-slash-commands.test.ts +75 -66
  64. package/src/__tests__/conversation-runtime-assembly.test.ts +257 -3
  65. package/src/__tests__/conversation-slash-commands.test.ts +24 -4
  66. package/src/__tests__/conversation-slash-queue.test.ts +2 -0
  67. package/src/__tests__/conversation-speed-override.test.ts +0 -3
  68. package/src/__tests__/conversation-starter-routes.test.ts +79 -2
  69. package/src/__tests__/conversation-surfaces-standalone-payloads.test.ts +12 -5
  70. package/src/__tests__/conversation-surfaces-standalone.test.ts +18 -14
  71. package/src/__tests__/conversation-surfaces-state-update.test.ts +3 -2
  72. package/src/__tests__/conversation-tool-setup-app-refresh.test.ts +8 -46
  73. package/src/__tests__/conversation-usage.test.ts +253 -3
  74. package/src/__tests__/credential-execution-shell-lockdown.test.ts +0 -39
  75. package/src/__tests__/credential-health-service.test.ts +68 -0
  76. package/src/__tests__/credential-security-e2e.test.ts +4 -3
  77. package/src/__tests__/credential-security-invariants.test.ts +1 -5
  78. package/src/__tests__/credential-token-resolver.test.ts +180 -0
  79. package/src/__tests__/cu-unified-flow.test.ts +33 -16
  80. package/src/__tests__/daemon-assistant-events.test.ts +34 -21
  81. package/src/__tests__/daemon-credential-client.test.ts +4 -1
  82. package/src/__tests__/db-connection-isolation.test.ts +125 -0
  83. package/src/__tests__/db-migration-rollback.test.ts +101 -0
  84. package/src/__tests__/db-slack-compaction-watermark-migration.test.ts +169 -0
  85. package/src/__tests__/deterministic-verification-control-plane.test.ts +7 -80
  86. package/src/__tests__/document-conversations.test.ts +332 -0
  87. package/src/__tests__/embedding-managed-proxy-selection.test.ts +2 -2
  88. package/src/__tests__/emit-event-signal.test.ts +4 -6
  89. package/src/__tests__/events-client-registration.test.ts +193 -49
  90. package/src/__tests__/filing-service.test.ts +58 -7
  91. package/src/__tests__/first-greeting.test.ts +156 -150
  92. package/src/__tests__/fixtures/mock-chrome-extension.ts +108 -66
  93. package/src/__tests__/get-skill-detail-audit.test.ts +3 -8
  94. package/src/__tests__/guardian-binding-drift-heal.test.ts +1 -1
  95. package/src/__tests__/guardian-dispatch.test.ts +1 -1
  96. package/src/__tests__/guardian-grant-minting.test.ts +7 -2
  97. package/src/__tests__/guardian-routing-invariants.test.ts +7 -2
  98. package/src/__tests__/guardian-routing-state.test.ts +1 -1
  99. package/src/__tests__/handlers-skills-memory-v2-reseed.test.ts +32 -11
  100. package/src/__tests__/handlers-user-message-approval-consumption.test.ts +2 -83
  101. package/src/__tests__/headless-browser-mode.test.ts +4 -9
  102. package/src/__tests__/headless-browser-navigate.test.ts +21 -20
  103. package/src/__tests__/heartbeat-service.test.ts +289 -7
  104. package/src/__tests__/helpers/channel-test-adapter.ts +2 -2
  105. package/src/__tests__/helpers/create-guardian-binding.ts +91 -0
  106. package/src/__tests__/host-bash-proxy.test.ts +46 -122
  107. package/src/__tests__/host-browser-e2e-cloud.test.ts +36 -497
  108. package/src/__tests__/host-browser-e2e-self-hosted-capability.test.ts +26 -96
  109. package/src/__tests__/host-browser-proxy.test.ts +111 -185
  110. package/src/__tests__/host-browser-routes.test.ts +45 -75
  111. package/src/__tests__/host-browser-ws-events-e2e.test.ts +26 -30
  112. package/src/__tests__/host-cu-proxy.test.ts +56 -111
  113. package/src/__tests__/host-file-proxy.test.ts +44 -98
  114. package/src/__tests__/host-file-read-tool.test.ts +42 -21
  115. package/src/__tests__/host-shell-tool.test.ts +33 -68
  116. package/src/__tests__/host-transfer-pending-interactions.test.ts +2 -18
  117. package/src/__tests__/host-transfer-proxy.test.ts +43 -53
  118. package/src/__tests__/http-user-message-parity.test.ts +0 -6
  119. package/src/__tests__/inbound-slack-persistence.test.ts +31 -0
  120. package/src/__tests__/injector-chain.test.ts +10 -5
  121. package/src/__tests__/injector-pkb-v2-silenced.test.ts +124 -0
  122. package/src/__tests__/inline-command-runner.test.ts +0 -66
  123. package/src/__tests__/inline-skill-load-permissions.test.ts +0 -2
  124. package/src/__tests__/install-skill-routing.test.ts +1 -13
  125. package/src/__tests__/llm-callsite-catalog.test.ts +34 -0
  126. package/src/__tests__/llm-catalog-parity.test.ts +90 -0
  127. package/src/__tests__/llm-context-resolution.test.ts +180 -0
  128. package/src/__tests__/llm-resolver.test.ts +80 -12
  129. package/src/__tests__/llm-usage-store.test.ts +269 -4
  130. package/src/__tests__/log-export-routes.test.ts +89 -0
  131. package/src/__tests__/managed-profile-guard.test.ts +225 -0
  132. package/src/__tests__/managed-skill-lifecycle.test.ts +0 -10
  133. package/src/__tests__/manual-token-reconciliation.test.ts +334 -0
  134. package/src/__tests__/memory-v2-static-injector.test.ts +95 -0
  135. package/src/__tests__/migration-cross-version-compatibility.test.ts +197 -291
  136. package/src/__tests__/migration-export-http.test.ts +33 -26
  137. package/src/__tests__/migration-export-streaming.test.ts +18 -10
  138. package/src/__tests__/migration-export-to-gcs.test.ts +49 -9
  139. package/src/__tests__/migration-import-commit-http.test.ts +66 -21
  140. package/src/__tests__/migration-import-from-gcs.test.ts +50 -9
  141. package/src/__tests__/migration-import-from-url.test.ts +20 -6
  142. package/src/__tests__/migration-import-preflight-http.test.ts +95 -95
  143. package/src/__tests__/migration-parity-persistence.test.ts +62 -25
  144. package/src/__tests__/migration-transport.test.ts +115 -23
  145. package/src/__tests__/migration-validate-http.test.ts +105 -80
  146. package/src/__tests__/migration-wizard.test.ts +133 -27
  147. package/src/__tests__/non-member-access-request.test.ts +1 -1
  148. package/src/__tests__/notification-guardian-path.test.ts +1 -1
  149. package/src/__tests__/oauth-store.test.ts +19 -0
  150. package/src/__tests__/platform-bash-auto-approve.test.ts +21 -12
  151. package/src/__tests__/prechat-onboarding-contract.test.ts +31 -7
  152. package/src/__tests__/pricing.test.ts +68 -4
  153. package/src/__tests__/process-message-background-slack.test.ts +331 -0
  154. package/src/__tests__/provider-managed-proxy-integration.test.ts +153 -17
  155. package/src/__tests__/provider-send-message-override-profile.test.ts +50 -0
  156. package/src/__tests__/provider-usage-tracking.test.ts +208 -0
  157. package/src/__tests__/reaction-persistence.test.ts +9 -6
  158. package/src/__tests__/rebind-secrets-screen.test.ts +53 -16
  159. package/src/__tests__/recording-handler.test.ts +64 -81
  160. package/src/__tests__/regenerate-fire-and-forget-trace.test.ts +4 -3
  161. package/src/__tests__/relay-server.test.ts +18 -13
  162. package/src/__tests__/require-fresh-approval.test.ts +13 -22
  163. package/src/__tests__/runtime-attachment-metadata.test.ts +1 -1
  164. package/src/__tests__/runtime-events-sse-parity.test.ts +3 -4
  165. package/src/__tests__/runtime-events-sse.test.ts +3 -12
  166. package/src/__tests__/search-skills-unified.test.ts +9 -15
  167. package/src/__tests__/secret-ingress-cli.test.ts +2 -5
  168. package/src/__tests__/secret-ingress-http.test.ts +0 -4
  169. package/src/__tests__/secret-onetime-send.test.ts +4 -2
  170. package/src/__tests__/secret-prompt-log-hygiene.test.ts +24 -7
  171. package/src/__tests__/secret-prompter-channel-fallback.test.ts +42 -47
  172. package/src/__tests__/secret-response-routing.test.ts +29 -15
  173. package/src/__tests__/secret-routes-managed-proxy.test.ts +5 -1
  174. package/src/__tests__/secret-scanner.test.ts +2 -545
  175. package/src/__tests__/send-endpoint-busy.test.ts +9 -24
  176. package/src/__tests__/settings-routes.test.ts +1 -1
  177. package/src/__tests__/shell-credential-ref.test.ts +0 -8
  178. package/src/__tests__/shell-tool-proxy-mode.test.ts +0 -56
  179. package/src/__tests__/skill-script-runner-sandbox.test.ts +0 -11
  180. package/src/__tests__/skill-tool-factory.test.ts +97 -0
  181. package/src/__tests__/skills-file-content-endpoint.test.ts +9 -30
  182. package/src/__tests__/skills-files-catalog-fallback.test.ts +11 -17
  183. package/src/__tests__/slack-inbound-verification.test.ts +1 -62
  184. package/src/__tests__/subagent-fork-notifications.test.ts +57 -47
  185. package/src/__tests__/subagent-manager-notify.test.ts +70 -70
  186. package/src/__tests__/subagent-notify-parent.test.ts +80 -83
  187. package/src/__tests__/system-prompt.test.ts +115 -13
  188. package/src/__tests__/terminal-tools.test.ts +0 -89
  189. package/src/__tests__/thread-backfill.test.ts +945 -31
  190. package/src/__tests__/tool-domain-event-publisher.test.ts +0 -36
  191. package/src/__tests__/tool-execute-pipeline.test.ts +0 -6
  192. package/src/__tests__/tool-execution-abort-cleanup.test.ts +0 -16
  193. package/src/__tests__/tool-execution-pipeline.benchmark.test.ts +9 -19
  194. package/src/__tests__/tool-executor-lifecycle-events.test.ts +4 -7
  195. package/src/__tests__/tool-executor.test.ts +12 -19
  196. package/src/__tests__/tool-metrics-listener.test.ts +0 -35
  197. package/src/__tests__/tool-side-effects-slack-dm.test.ts +1 -0
  198. package/src/__tests__/tool-trace-listener.test.ts +0 -17
  199. package/src/__tests__/transfer-progress-screen.test.ts +63 -26
  200. package/src/__tests__/trusted-contact-lifecycle-notifications.test.ts +2 -149
  201. package/src/__tests__/trusted-contact-multichannel.test.ts +2 -4
  202. package/src/__tests__/trusted-contact-verification.test.ts +1 -1
  203. package/src/__tests__/tts-catalog-parity.test.ts +16 -5
  204. package/src/__tests__/usage-attribution.test.ts +247 -0
  205. package/src/__tests__/usage-cli.test.ts +143 -0
  206. package/src/__tests__/usage-grouped-buckets.test.ts +155 -0
  207. package/src/__tests__/usage-routes.test.ts +150 -0
  208. package/src/__tests__/validation-results-screen.test.ts +39 -16
  209. package/src/__tests__/vbundle-pax-and-symlink.test.ts +12 -3
  210. package/src/__tests__/vellum-self-knowledge-inline-command.test.ts +49 -137
  211. package/src/__tests__/verification-control-plane-policy.test.ts +4 -7
  212. package/src/__tests__/voice-session-bridge.test.ts +5 -5
  213. package/src/__tests__/workspace-migration-062-drop-memory-v2-edges-json.test.ts +103 -0
  214. package/src/__tests__/workspace-migration-063-release-notes-dynamic-model-context.test.ts +77 -0
  215. package/src/__tests__/workspace-migration-064-unwind-main-agent-opus-seed.test.ts +225 -0
  216. package/src/__tests__/workspace-migration-memory-v2-init.test.ts +8 -30
  217. package/src/acp/index.ts +0 -15
  218. package/src/acp/session-manager.ts +37 -34
  219. package/src/agent/loop.ts +16 -1
  220. package/src/approvals/AGENTS.md +4 -0
  221. package/src/approvals/__tests__/guardian-feed-event.test.ts +10 -3
  222. package/src/approvals/guardian-request-resolvers.ts +10 -2
  223. package/src/backup/__tests__/backup-worker.test.ts +36 -8
  224. package/src/backup/__tests__/paths.test.ts +2 -2
  225. package/src/backup/__tests__/restore.test.ts +45 -28
  226. package/src/backup/backup-worker.ts +36 -2
  227. package/src/backup/paths.ts +9 -6
  228. package/src/browser-session/events.ts +0 -9
  229. package/src/calls/call-store.ts +1 -34
  230. package/src/calls/guardian-question-copy.ts +0 -108
  231. package/src/calls/relay-server.ts +0 -24
  232. package/src/calls/twilio-rest.ts +0 -38
  233. package/src/calls/twilio-routes.ts +1 -1
  234. package/src/calls/voice-session-bridge.ts +7 -38
  235. package/src/channels/types.ts +1 -36
  236. package/src/cli/commands/__tests__/cache.test.ts +152 -5
  237. package/src/cli/commands/__tests__/memory-v2.test.ts +14 -28
  238. package/src/cli/commands/__tests__/trust.test.ts +21 -387
  239. package/src/cli/commands/backup.ts +4 -4
  240. package/src/cli/commands/cache-fs.ts +8 -0
  241. package/src/cli/commands/cache.ts +153 -82
  242. package/src/cli/commands/clients.ts +63 -5
  243. package/src/cli/commands/completions.ts +3 -3
  244. package/src/cli/commands/contacts.ts +231 -76
  245. package/src/cli/commands/keys.ts +4 -1
  246. package/src/cli/commands/memory-v2.ts +24 -52
  247. package/src/cli/commands/oauth/shared.ts +2 -29
  248. package/src/cli/commands/pending.ts +102 -0
  249. package/src/cli/commands/skills.ts +77 -35
  250. package/src/cli/commands/trust.ts +70 -430
  251. package/src/cli/commands/usage.ts +25 -16
  252. package/src/cli/lib/daemon-credential-client.ts +14 -0
  253. package/src/cli/program.ts +2 -0
  254. package/src/cli.ts +0 -21
  255. package/src/config/__tests__/feature-flag-registry-guard.test.ts +2 -2
  256. package/src/config/bundled-skills/messaging/TOOLS.json +14 -4
  257. package/src/config/env-registry.ts +12 -2
  258. package/src/config/env.ts +3 -14
  259. package/src/config/feature-flag-registry.json +30 -30
  260. package/src/config/llm-callsite-catalog.ts +12 -0
  261. package/src/config/llm-context-resolution.ts +80 -0
  262. package/src/config/llm-resolver.ts +58 -22
  263. package/src/config/loader.ts +3 -3
  264. package/src/config/schema.ts +2 -158
  265. package/src/config/schemas/__tests__/memory-v2.test.ts +1 -0
  266. package/src/config/schemas/call-site-catalog.ts +271 -0
  267. package/src/config/schemas/calls.ts +5 -5
  268. package/src/config/schemas/inference.ts +1 -1
  269. package/src/config/schemas/ingress.ts +1 -1
  270. package/src/config/schemas/llm.ts +31 -3
  271. package/src/config/schemas/memory-retrieval.ts +2 -2
  272. package/src/config/schemas/memory-v2.ts +9 -0
  273. package/src/config/schemas/security.ts +1 -42
  274. package/src/config/schemas/services.ts +6 -6
  275. package/src/config/schemas/skills.ts +5 -5
  276. package/src/config/schemas/tts.ts +1 -1
  277. package/src/config/seed-inference-profiles.ts +117 -0
  278. package/src/config/skills.ts +0 -90
  279. package/src/config/types.ts +3 -6
  280. package/src/contacts/contact-store.ts +0 -17
  281. package/src/contacts/contacts-write.ts +1 -105
  282. package/src/context/window-manager.ts +44 -5
  283. package/src/credential-execution/process-manager.ts +34 -10
  284. package/src/credential-health/credential-health-service.ts +21 -16
  285. package/src/daemon/__tests__/conversation-surfaces-launch.test.ts +75 -82
  286. package/src/daemon/__tests__/daemon-skill-host.test.ts +2 -9
  287. package/src/daemon/connection-policy.ts +1 -26
  288. package/src/daemon/conversation-agent-loop-handlers.ts +53 -4
  289. package/src/daemon/conversation-agent-loop.ts +277 -36
  290. package/src/daemon/conversation-history.ts +8 -8
  291. package/src/daemon/conversation-launch.ts +20 -135
  292. package/src/daemon/conversation-lifecycle.ts +1 -1
  293. package/src/daemon/conversation-messaging.ts +1 -0
  294. package/src/daemon/conversation-process.ts +83 -163
  295. package/src/daemon/conversation-runtime-assembly.ts +219 -76
  296. package/src/daemon/conversation-slash.ts +47 -5
  297. package/src/daemon/conversation-store.ts +7 -31
  298. package/src/daemon/conversation-surfaces.ts +22 -28
  299. package/src/daemon/conversation-tool-setup.ts +3 -33
  300. package/src/daemon/conversation-usage.ts +36 -0
  301. package/src/daemon/conversation.ts +117 -233
  302. package/src/daemon/daemon-control.ts +3 -71
  303. package/src/daemon/daemon-skill-host.ts +8 -11
  304. package/src/daemon/dictation-profile-store.ts +2 -26
  305. package/src/daemon/first-greeting.ts +44 -156
  306. package/src/daemon/handlers/config-channels.ts +12 -12
  307. package/src/daemon/handlers/config-ingress.ts +4 -165
  308. package/src/daemon/handlers/config-model.ts +1 -1
  309. package/src/daemon/handlers/config-voice.ts +0 -42
  310. package/src/daemon/handlers/conversations.ts +11 -190
  311. package/src/daemon/handlers/recording.ts +26 -158
  312. package/src/daemon/handlers/shared.ts +23 -71
  313. package/src/daemon/handlers/skills.ts +42 -93
  314. package/src/daemon/host-bash-proxy.ts +67 -45
  315. package/src/daemon/host-browser-proxy.ts +65 -27
  316. package/src/daemon/host-cu-proxy.ts +40 -39
  317. package/src/daemon/host-file-proxy.ts +58 -37
  318. package/src/daemon/host-transfer-proxy.ts +84 -46
  319. package/src/daemon/lifecycle.ts +49 -15
  320. package/src/daemon/message-types/conversations.ts +7 -0
  321. package/src/daemon/message-types/host-bash.ts +1 -0
  322. package/src/daemon/message-types/host-cu.ts +1 -0
  323. package/src/daemon/message-types/host-file.ts +1 -0
  324. package/src/daemon/message-types/host-transfer.ts +1 -0
  325. package/src/daemon/message-types/messages.ts +10 -9
  326. package/src/daemon/message-types/workspace.ts +1 -1
  327. package/src/daemon/process-message.ts +102 -239
  328. package/src/daemon/server.ts +13 -462
  329. package/src/daemon/shutdown-handlers.ts +2 -2
  330. package/src/daemon/tool-side-effects.ts +125 -107
  331. package/src/daemon/trust-context.ts +13 -0
  332. package/src/daemon/wake-target-adapter.ts +4 -9
  333. package/src/events/domain-events.ts +0 -8
  334. package/src/events/tool-audit-listener.ts +3 -1
  335. package/src/events/tool-domain-event-publisher.ts +0 -10
  336. package/src/events/tool-metrics-listener.ts +0 -17
  337. package/src/events/tool-trace-listener.ts +0 -14
  338. package/src/filing/filing-service.ts +13 -1
  339. package/src/heartbeat/__tests__/heartbeat-feed-event.test.ts +6 -2
  340. package/src/heartbeat/heartbeat-service.ts +23 -5
  341. package/src/home/__tests__/feed-writer.test.ts +0 -4
  342. package/src/home/__tests__/relationship-state-writer.test.ts +30 -0
  343. package/src/home/feed-writer.ts +1 -2
  344. package/src/home/relationship-state-writer.ts +16 -3
  345. package/src/ipc/__tests__/browser-ipc.test.ts +2 -12
  346. package/src/ipc/__tests__/skill-server-bidirectional.test.ts +0 -1
  347. package/src/ipc/assistant-server.ts +3 -10
  348. package/src/ipc/routes/__tests__/memory-v2-backfill.test.ts +39 -20
  349. package/src/ipc/routes/route-adapter.ts +1 -1
  350. package/src/ipc/routes/trust-rules.test.ts +0 -95
  351. package/src/ipc/skill-ipc-types.ts +41 -0
  352. package/src/ipc/skill-routes/__tests__/events-ipc.test.ts +13 -27
  353. package/src/ipc/skill-routes/__tests__/identity.test.ts +4 -23
  354. package/src/ipc/skill-routes/events.ts +12 -23
  355. package/src/ipc/skill-routes/identity.ts +4 -17
  356. package/src/ipc/skill-routes/index.ts +1 -1
  357. package/src/ipc/skill-server.ts +6 -39
  358. package/src/live-voice/__tests__/runtime-websocket-shell.test.ts +0 -8
  359. package/src/live-voice/protocol.ts +4 -13
  360. package/src/mcp/manager.ts +0 -5
  361. package/src/memory/__tests__/fixtures/memory-v2-activation-fixtures.ts +55 -0
  362. package/src/memory/__tests__/memory-v2-activation-log-store.test.ts +127 -0
  363. package/src/memory/app-git-service.ts +0 -32
  364. package/src/memory/app-store.ts +154 -0
  365. package/src/memory/attachments-store.ts +6 -0
  366. package/src/memory/context-search/sources/memory-v2.ts +578 -0
  367. package/src/memory/context-search/sources/memory.ts +5 -0
  368. package/src/memory/context-search/sources/pkb.ts +10 -1
  369. package/src/memory/context-search/sources/workspace.ts +3 -2
  370. package/src/memory/conversation-crud.ts +29 -4
  371. package/src/memory/conversation-disk-view.ts +1 -5
  372. package/src/memory/conversation-starter-checkpoints.ts +63 -0
  373. package/src/memory/db-connection.ts +62 -0
  374. package/src/memory/db-init.ts +14 -0
  375. package/src/memory/embedding-backend.ts +3 -21
  376. package/src/memory/embedding-gemini.ts +0 -2
  377. package/src/memory/embedding-local.ts +6 -6
  378. package/src/memory/embedding-ollama.ts +6 -6
  379. package/src/memory/embedding-openai.ts +6 -6
  380. package/src/memory/embedding-types.ts +21 -0
  381. package/src/memory/graph/__tests__/conversation-graph-memory-v2-routing.test.ts +3 -7
  382. package/src/memory/graph/conversation-graph-memory.ts +35 -13
  383. package/src/memory/graph/injection.test.ts +2 -2
  384. package/src/memory/graph/injection.ts +1 -1
  385. package/src/memory/guardian-action-store.ts +0 -83
  386. package/src/memory/guardian-approvals.ts +0 -48
  387. package/src/memory/indexer.ts +1 -15
  388. package/src/memory/job-handlers/conversation-starters.ts +36 -53
  389. package/src/memory/job-utils.ts +0 -6
  390. package/src/memory/jobs-store.ts +0 -1
  391. package/src/memory/jobs-worker.ts +2 -16
  392. package/src/memory/llm-request-log-store.ts +0 -41
  393. package/src/memory/llm-usage-store.ts +129 -43
  394. package/src/memory/memory-v2-activation-log-store.ts +115 -0
  395. package/src/memory/migrations/233-document-conversations.ts +54 -0
  396. package/src/memory/migrations/234-memory-v2-activation-logs.ts +55 -0
  397. package/src/memory/migrations/235-llm-usage-attribution.ts +31 -0
  398. package/src/memory/migrations/235-slack-compaction-watermark.ts +44 -0
  399. package/src/memory/migrations/236-tool-invocations-matched-rule-id.ts +26 -0
  400. package/src/memory/migrations/__tests__/234-memory-v2-activation-logs.test.ts +182 -0
  401. package/src/memory/migrations/index.ts +14 -0
  402. package/src/memory/migrations/registry.ts +24 -0
  403. package/src/memory/raw-query.ts +2 -68
  404. package/src/memory/schema/conversations.ts +7 -0
  405. package/src/memory/schema/infrastructure.ts +25 -0
  406. package/src/memory/search/semantic.ts +5 -16
  407. package/src/memory/tool-usage-store.ts +2 -0
  408. package/src/memory/usage-buckets.ts +40 -1
  409. package/src/memory/usage-grouped-buckets.ts +127 -0
  410. package/src/memory/v2/__tests__/activation.test.ts +289 -90
  411. package/src/memory/v2/__tests__/backfill-jobs.test.ts +2 -129
  412. package/src/memory/v2/__tests__/consolidation-job.test.ts +28 -11
  413. package/src/memory/v2/__tests__/edge-index.test.ts +278 -0
  414. package/src/memory/v2/__tests__/injection.test.ts +384 -15
  415. package/src/memory/v2/__tests__/migration.test.ts +64 -36
  416. package/src/memory/v2/__tests__/page-store.test.ts +191 -8
  417. package/src/memory/v2/__tests__/prompts-consolidation.test.ts +181 -0
  418. package/src/memory/v2/__tests__/skill-store.test.ts +115 -3
  419. package/src/memory/v2/__tests__/static-context.test.ts +153 -0
  420. package/src/memory/v2/activation.ts +168 -97
  421. package/src/memory/v2/backfill-jobs.ts +15 -100
  422. package/src/memory/v2/consolidation-job.ts +14 -12
  423. package/src/memory/v2/edge-index.ts +191 -0
  424. package/src/memory/v2/injection.ts +182 -58
  425. package/src/memory/v2/migration.ts +57 -64
  426. package/src/memory/v2/now-text.ts +2 -3
  427. package/src/memory/v2/page-store.ts +168 -31
  428. package/src/memory/v2/prompts/consolidation.ts +118 -42
  429. package/src/memory/v2/prompts/sweep.ts +3 -3
  430. package/src/memory/v2/skill-store.ts +55 -7
  431. package/src/memory/v2/static-context.ts +62 -0
  432. package/src/memory/v2/types.ts +10 -20
  433. package/src/memory/validation.ts +0 -11
  434. package/src/messaging/draft-store.ts +0 -6
  435. package/src/messaging/provider-types.ts +8 -0
  436. package/src/messaging/provider.ts +7 -0
  437. package/src/messaging/providers/gmail/client.ts +1 -121
  438. package/src/messaging/providers/outlook/client.ts +0 -73
  439. package/src/messaging/providers/slack/__tests__/adapter-mention-rendering.test.ts +226 -0
  440. package/src/messaging/providers/slack/adapter.ts +122 -21
  441. package/src/messaging/providers/slack/backfill.test.ts +95 -6
  442. package/src/messaging/providers/slack/backfill.ts +89 -11
  443. package/src/messaging/providers/slack/client.ts +10 -124
  444. package/src/messaging/providers/slack/message-metadata.ts +12 -2
  445. package/src/messaging/providers/slack/render-transcript.test.ts +56 -0
  446. package/src/messaging/providers/slack/render-transcript.ts +126 -25
  447. package/src/messaging/providers/slack/types.ts +1 -0
  448. package/src/oauth/connection-resolver.test.ts +8 -0
  449. package/src/oauth/connection-resolver.ts +8 -16
  450. package/src/oauth/credential-token-resolver.ts +97 -0
  451. package/src/oauth/manual-token-connection.ts +30 -34
  452. package/src/oauth/oauth-store.ts +6 -4
  453. package/src/outbound-proxy/certs.ts +0 -7
  454. package/src/outbound-proxy/config.ts +0 -74
  455. package/src/outbound-proxy/health.ts +0 -44
  456. package/src/outbound-proxy/index.ts +0 -22
  457. package/src/permissions/approval-provenance.test.ts +184 -0
  458. package/src/permissions/approval-provenance.ts +70 -0
  459. package/src/permissions/checker.ts +4 -1
  460. package/src/permissions/gateway-threshold-reader.ts +4 -1
  461. package/src/permissions/prompter.ts +9 -2
  462. package/src/permissions/secret-prompter.ts +21 -48
  463. package/src/permissions/types.ts +33 -0
  464. package/src/permissions/workspace-policy.ts +0 -5
  465. package/src/platform/sync-identity.ts +0 -8
  466. package/src/plugins/defaults/injectors.ts +69 -2
  467. package/src/plugins/defaults/overflow-reduce.ts +3 -2
  468. package/src/plugins/types.ts +8 -0
  469. package/src/prompts/system-prompt.ts +34 -70
  470. package/src/prompts/templates/BOOTSTRAP.md +52 -6
  471. package/src/prompts/update-bulletin-job.ts +2 -0
  472. package/src/providers/__tests__/retry-callsite.test.ts +138 -1
  473. package/src/providers/anthropic/client.ts +72 -33
  474. package/src/providers/call-site-routing.ts +42 -3
  475. package/src/providers/gemini/client.ts +18 -2
  476. package/src/providers/managed-proxy/context.ts +0 -5
  477. package/src/providers/model-catalog.ts +105 -19
  478. package/src/providers/openai/chat-completions-provider.ts +6 -0
  479. package/src/providers/openai/responses-provider.ts +7 -1
  480. package/src/providers/provider-send-message.ts +45 -2
  481. package/src/providers/ratelimit.ts +7 -2
  482. package/src/providers/registry.ts +14 -9
  483. package/src/providers/retry.ts +96 -8
  484. package/src/providers/types.ts +13 -0
  485. package/src/providers/usage-tracking.ts +96 -0
  486. package/src/runtime/AGENTS.md +10 -6
  487. package/src/runtime/__tests__/agent-wake.test.ts +89 -0
  488. package/src/runtime/agent-wake.ts +39 -2
  489. package/src/runtime/assistant-event-hub.ts +541 -45
  490. package/src/runtime/assistant-event.ts +1 -6
  491. package/src/runtime/auth/context.ts +0 -9
  492. package/src/runtime/auth/middleware.ts +1 -1
  493. package/src/runtime/auth/route-policy.ts +11 -9
  494. package/src/runtime/auth/token-service.ts +0 -11
  495. package/src/runtime/channel-approvals.ts +6 -2
  496. package/src/runtime/channel-verification-service.ts +3 -5
  497. package/src/runtime/http-errors.ts +0 -34
  498. package/src/runtime/http-router.ts +6 -3
  499. package/src/runtime/http-server.ts +22 -82
  500. package/src/runtime/http-types.ts +5 -0
  501. package/src/runtime/interactive-ui.ts +0 -1
  502. package/src/runtime/middleware/auth.ts +0 -20
  503. package/src/runtime/migrations/__tests__/v1-test-helpers.ts +112 -0
  504. package/src/runtime/migrations/__tests__/vbundle-builder-credentials.test.ts +11 -4
  505. package/src/runtime/migrations/__tests__/vbundle-builder-v1-shape.test.ts +253 -0
  506. package/src/runtime/migrations/__tests__/vbundle-import-credentials.test.ts +19 -6
  507. package/src/runtime/migrations/__tests__/vbundle-legacy-user-md.test.ts +71 -27
  508. package/src/runtime/migrations/__tests__/vbundle-metadata-merge-integration.test.ts +41 -2
  509. package/src/runtime/migrations/__tests__/vbundle-streaming-importer.test.ts +143 -79
  510. package/src/runtime/migrations/__tests__/vbundle-streaming-validator.test.ts +143 -23
  511. package/src/runtime/migrations/__tests__/vbundle-tar-stream.test.ts +2 -2
  512. package/src/runtime/migrations/__tests__/vbundle-validator-v1-schema.test.ts +371 -0
  513. package/src/runtime/migrations/migration-transport.ts +46 -13
  514. package/src/runtime/migrations/migration-wizard.ts +2 -2
  515. package/src/runtime/migrations/origin-mode.ts +40 -0
  516. package/src/runtime/migrations/vbundle-builder.ts +133 -79
  517. package/src/runtime/migrations/vbundle-import-analyzer.ts +9 -7
  518. package/src/runtime/migrations/vbundle-importer.ts +7 -7
  519. package/src/runtime/migrations/vbundle-metadata-merge.ts +1 -1
  520. package/src/runtime/migrations/vbundle-streaming-importer.ts +3 -3
  521. package/src/runtime/migrations/vbundle-streaming-validator.ts +48 -26
  522. package/src/runtime/migrations/vbundle-validator.ts +214 -41
  523. package/src/runtime/pending-interactions.ts +13 -4
  524. package/src/runtime/routes/__tests__/acp-routes.test.ts +0 -1
  525. package/src/runtime/routes/__tests__/backup-routes.test.ts +28 -19
  526. package/src/runtime/routes/__tests__/conversation-query-routes.test.ts +235 -0
  527. package/src/runtime/routes/__tests__/llm-call-sites-routes.test.ts +58 -0
  528. package/src/runtime/routes/__tests__/migration-export-secrets-redacted.test.ts +54 -0
  529. package/src/runtime/routes/__tests__/migration-import-credential-filter.test.ts +19 -6
  530. package/src/runtime/routes/__tests__/user-route-dispatcher.test.ts +7 -7
  531. package/src/runtime/routes/acp-routes.test.ts +0 -3
  532. package/src/runtime/routes/acp-routes.ts +3 -7
  533. package/src/runtime/routes/app-management-routes.ts +18 -9
  534. package/src/runtime/routes/approval-routes.ts +55 -14
  535. package/src/runtime/routes/avatar-routes.ts +3 -5
  536. package/src/runtime/routes/browser-routes.ts +1 -15
  537. package/src/runtime/routes/channel-guardian-routes.ts +1 -5
  538. package/src/runtime/routes/channel-readiness-routes.ts +3 -7
  539. package/src/runtime/routes/channel-route-shared.ts +2 -28
  540. package/src/runtime/routes/client-routes.ts +45 -12
  541. package/src/runtime/routes/consolidation-routes.ts +115 -0
  542. package/src/runtime/routes/conversation-list-routes.ts +12 -29
  543. package/src/runtime/routes/conversation-management-routes.ts +14 -51
  544. package/src/runtime/routes/conversation-query-routes.ts +120 -8
  545. package/src/runtime/routes/conversation-routes.ts +44 -528
  546. package/src/runtime/routes/conversation-starter-routes.ts +19 -40
  547. package/src/runtime/routes/documents-routes.ts +53 -18
  548. package/src/runtime/routes/events-routes.ts +59 -91
  549. package/src/runtime/routes/filing-routes.ts +18 -1
  550. package/src/runtime/routes/guardian-action-routes.ts +4 -9
  551. package/src/runtime/routes/host-bash-routes.ts +3 -2
  552. package/src/runtime/routes/host-browser-routes.ts +9 -33
  553. package/src/runtime/routes/host-cu-routes.ts +6 -1
  554. package/src/runtime/routes/host-file-routes.ts +3 -2
  555. package/src/runtime/routes/host-transfer-routes.ts +11 -15
  556. package/src/runtime/routes/identity-routes.ts +78 -6
  557. package/src/runtime/routes/inbound-message-handler.ts +580 -137
  558. package/src/runtime/routes/inbound-stages/acl-enforcement.ts +2 -88
  559. package/src/runtime/routes/inbound-stages/background-dispatch.ts +3 -0
  560. package/src/runtime/routes/index.ts +4 -0
  561. package/src/runtime/routes/integrations/slack/channel.ts +0 -24
  562. package/src/runtime/routes/llm-call-sites-routes.ts +22 -0
  563. package/src/runtime/routes/memory-v2-routes.ts +10 -15
  564. package/src/runtime/routes/migration-routes.ts +188 -31
  565. package/src/runtime/routes/playground/guard.ts +1 -1
  566. package/src/runtime/routes/playground/index.ts +0 -2
  567. package/src/runtime/routes/recording-routes.ts +4 -24
  568. package/src/runtime/routes/rename-conversation-routes.ts +2 -6
  569. package/src/runtime/routes/schedule-routes.ts +3 -6
  570. package/src/runtime/routes/secret-routes.ts +87 -18
  571. package/src/runtime/routes/settings-routes.ts +29 -28
  572. package/src/runtime/routes/skills-routes.ts +12 -31
  573. package/src/runtime/routes/suggest-trust-rule-routes.ts +32 -1
  574. package/src/runtime/routes/task-routes.ts +6 -6
  575. package/src/runtime/routes/trust-rules-routes.ts +3 -94
  576. package/src/runtime/routes/types.ts +4 -4
  577. package/src/runtime/routes/upgrade-broadcast-routes.ts +3 -10
  578. package/src/runtime/routes/usage-routes.ts +87 -10
  579. package/src/runtime/routes/user-routes.ts +17 -31
  580. package/src/runtime/routes/work-items-routes.ts +1 -4
  581. package/src/runtime/services/__tests__/analyze-conversation.test.ts +2 -2
  582. package/src/runtime/services/analyze-conversation.ts +7 -17
  583. package/src/runtime/services/conversation-serializer.ts +2 -4
  584. package/src/runtime/verification-outbound-actions.ts +1 -1
  585. package/src/runtime/verification-rate-limiter.ts +1 -1
  586. package/src/schedule/schedule-store.ts +0 -16
  587. package/src/security/secret-scanner.ts +14 -547
  588. package/src/security/secure-keys.ts +31 -11
  589. package/src/security/token-manager.ts +7 -3
  590. package/src/signals/cancel.ts +16 -25
  591. package/src/signals/conversation-undo.ts +2 -27
  592. package/src/signals/emit-event.ts +1 -2
  593. package/src/signals/user-message.ts +108 -22
  594. package/src/skills/catalog-install.ts +1 -0
  595. package/src/skills/clawhub.ts +2 -2
  596. package/src/skills/inline-command-runner.ts +1 -7
  597. package/src/subagent/manager.ts +67 -84
  598. package/src/tasks/task-store.ts +1 -28
  599. package/src/telemetry/types.ts +6 -0
  600. package/src/telemetry/usage-telemetry-reporter.test.ts +38 -15
  601. package/src/telemetry/usage-telemetry-reporter.ts +3 -5
  602. package/src/tools/acp/spawn.test.ts +1 -2
  603. package/src/tools/acp/steer.test.ts +1 -2
  604. package/src/tools/browser/__tests__/browser-status.test.ts +44 -127
  605. package/src/tools/browser/browser-execution.ts +31 -147
  606. package/src/tools/browser/cdp-client/__tests__/factory.test.ts +92 -68
  607. package/src/tools/browser/cdp-client/factory.ts +48 -76
  608. package/src/tools/browser/cdp-client/index.ts +1 -14
  609. package/src/tools/executor.ts +44 -31
  610. package/src/tools/host-filesystem/edit.ts +3 -2
  611. package/src/tools/host-filesystem/read.ts +3 -2
  612. package/src/tools/host-filesystem/transfer.test.ts +45 -42
  613. package/src/tools/host-filesystem/transfer.ts +4 -3
  614. package/src/tools/host-filesystem/write.ts +3 -2
  615. package/src/tools/host-terminal/host-shell.ts +4 -3
  616. package/src/tools/network/script-proxy/index.ts +1 -10
  617. package/src/tools/permission-checker.ts +66 -1
  618. package/src/tools/skills/sandbox-runner.ts +1 -6
  619. package/src/tools/skills/skill-tool-factory.ts +32 -0
  620. package/src/tools/terminal/safe-env.ts +1 -0
  621. package/src/tools/terminal/shell.ts +2 -78
  622. package/src/tools/types.ts +12 -39
  623. package/src/tts/__tests__/provider-catalog.test.ts +2 -2
  624. package/src/tts/provider-catalog.ts +1 -1
  625. package/src/usage/actors.ts +2 -1
  626. package/src/usage/attribution.ts +185 -0
  627. package/src/usage/pricing.ts +166 -0
  628. package/src/usage/types.ts +14 -0
  629. package/src/util/json.ts +13 -0
  630. package/src/util/logger.ts +3 -3
  631. package/src/util/pricing.ts +50 -3
  632. package/src/work-items/work-item-runner.ts +15 -42
  633. package/src/workspace/migrations/050-seed-main-agent-opus-callsite.ts +4 -3
  634. package/src/workspace/migrations/052-seed-default-inference-profiles.ts +3 -3
  635. package/src/workspace/migrations/060-memory-v2-init.ts +2 -18
  636. package/src/workspace/migrations/061-move-backup-key-to-workspace.ts +59 -0
  637. package/src/workspace/migrations/062-drop-memory-v2-edges-json.ts +27 -0
  638. package/src/workspace/migrations/063-release-notes-dynamic-model-context.ts +70 -0
  639. package/src/workspace/migrations/064-unwind-main-agent-opus-seed.ts +64 -0
  640. package/src/workspace/migrations/registry.ts +8 -0
  641. package/src/workspace/provider-commit-message-generator.ts +3 -3
  642. package/src/__tests__/sandbox-diagnostics.test.ts +0 -138
  643. package/src/__tests__/sandbox-host-parity.test.ts +0 -1024
  644. package/src/__tests__/secret-detection-handler.test.ts +0 -67
  645. package/src/__tests__/secret-scanner-executor.test.ts +0 -450
  646. package/src/__tests__/tcc-sandbox-deny.test.ts +0 -198
  647. package/src/__tests__/terminal-sandbox.test.ts +0 -374
  648. package/src/__tests__/tool-notification-listener.test.ts +0 -65
  649. package/src/context/__tests__/microcompact.test.ts +0 -805
  650. package/src/context/microcompact.ts +0 -443
  651. package/src/daemon/handlers/slack-channel-oauth-install.ts +0 -197
  652. package/src/events/tool-notification-listener.ts +0 -17
  653. package/src/ipc/routes/__tests__/memory-v2-validate.test.ts +0 -219
  654. package/src/memory/v2/__tests__/edges.test.ts +0 -435
  655. package/src/memory/v2/edges.ts +0 -217
  656. package/src/prompts/__tests__/system-prompt-memory-v2.test.ts +0 -197
  657. package/src/runtime/__tests__/chrome-extension-registry.test.ts +0 -518
  658. package/src/runtime/__tests__/client-registry.test.ts +0 -271
  659. package/src/runtime/chrome-extension-registry.ts +0 -368
  660. package/src/runtime/client-registry.ts +0 -254
  661. package/src/runtime/routes/inbound-stages/verification-intercept.ts +0 -329
  662. package/src/tools/secret-detection-handler.ts +0 -269
  663. package/src/tools/terminal/backends/native.ts +0 -327
  664. package/src/tools/terminal/backends/types.ts +0 -37
  665. package/src/tools/terminal/sandbox-diagnostics.ts +0 -87
  666. package/src/tools/terminal/sandbox.ts +0 -40
@@ -4,10 +4,9 @@
4
4
  * HTTP route definitions.
5
5
  *
6
6
  * Pipeline:
7
- * 1. Programmatically import and invoke all *RouteDefinitions() exports
8
- * from src/runtime/routes/ — no regex, no source-text parsing.
9
- * 2. Combine with inline routes (defined in buildRouteTable()) and
10
- * pre-auth / non-v1 routes.
7
+ * 1. Programmatically import every route module under src/runtime/routes/
8
+ * and collect all exported ROUTES arrays — no regex, no source-text parsing.
9
+ * 2. Combine with pre-auth / non-v1 routes.
11
10
  * 3. Convert to OpenAPI path items.
12
11
  * 4. Write to openapi.yaml.
13
12
  *
@@ -132,40 +131,12 @@ function toJSONSchemaObject(schema: unknown): JSONSchemaObject {
132
131
  // ---------------------------------------------------------------------------
133
132
 
134
133
  /**
135
- * Create a recursive proxy that stands in for any dependency object.
134
+ * Dynamically import every route module under `src/runtime/routes/`
135
+ * and collect all exported `ROUTES` arrays.
136
136
  *
137
- * Route definition functions capture deps in handler closures but never
138
- * access them during array construction, so this stub is never actually
139
- * invoked at runtime — it just needs to be truthy and not throw when
140
- * properties are read or the value is called as a function.
141
- */
142
- function createDeepStub(): unknown {
143
- // eslint-disable-next-line @typescript-eslint/no-explicit-any
144
- const stub: any = new Proxy(function () {}, {
145
- get(_target, prop) {
146
- // Prevent the stub from being treated as a Promise (await-able).
147
- if (prop === "then") return undefined;
148
- // Prevent infinite iteration.
149
- if (prop === Symbol.iterator) return undefined;
150
- // String coercion.
151
- if (prop === Symbol.toPrimitive) return () => "";
152
- return createDeepStub();
153
- },
154
- apply() {
155
- return createDeepStub();
156
- },
157
- });
158
- return stub;
159
- }
160
-
161
- /**
162
- * Dynamically import every route module under `src/runtime/routes/`,
163
- * find all exported functions whose names end with `RouteDefinitions`,
164
- * invoke each with a deep stub as its first argument, and collect the
165
- * `{ endpoint, method }` pairs from the returned arrays.
166
- *
167
- * This replaces the previous regex + balanced-brace scanning approach
168
- * and automatically picks up new route modules without manual updates.
137
+ * Each route module is expected to export a `ROUTES: RouteDefinition[]`
138
+ * constant. The function automatically picks up new route modules
139
+ * without manual updates.
169
140
  */
170
141
  async function collectRoutesFromModules(): Promise<RouteEntry[]> {
171
142
  const routes: RouteEntry[] = [];
@@ -191,41 +162,13 @@ async function collectRoutesFromModules(): Promise<RouteEntry[]> {
191
162
  continue;
192
163
  }
193
164
 
194
- for (const [exportName, exportValue] of Object.entries(mod)) {
195
- if (exportName === "ROUTES" && Array.isArray(exportValue)) {
196
- for (const raw of exportValue) {
197
- const result = RouteEntrySchema.safeParse({
198
- ...(typeof raw === "object" && raw !== null ? raw : {}),
199
- sourceModule: file,
200
- });
201
- if (result.success) routes.push(result.data);
202
- }
203
- continue;
204
- }
205
-
206
- if (
207
- !exportName.endsWith("RouteDefinitions") ||
208
- typeof exportValue !== "function"
209
- ) {
210
- continue;
211
- }
212
-
213
- try {
214
- const rawDefs = exportValue(createDeepStub());
215
- if (!Array.isArray(rawDefs)) continue;
216
- for (const raw of rawDefs) {
217
- const result = RouteEntrySchema.safeParse({
218
- ...(typeof raw === "object" && raw !== null ? raw : {}),
219
- sourceModule: file,
220
- });
221
- if (result.success) {
222
- routes.push(result.data);
223
- }
224
- }
225
- } catch (err) {
226
- console.warn(
227
- `Warning: ${exportName}() in ${file} threw: ${err instanceof Error ? err.message : err}`,
228
- );
165
+ if ("ROUTES" in mod && Array.isArray(mod.ROUTES)) {
166
+ for (const raw of mod.ROUTES) {
167
+ const result = RouteEntrySchema.safeParse({
168
+ ...(typeof raw === "object" && raw !== null ? raw : {}),
169
+ sourceModule: file,
170
+ });
171
+ if (result.success) routes.push(result.data);
229
172
  }
230
173
  }
231
174
  }
@@ -233,40 +176,6 @@ async function collectRoutesFromModules(): Promise<RouteEntry[]> {
233
176
  return routes;
234
177
  }
235
178
 
236
- /**
237
- * Routes defined inline in RuntimeHttpServer.buildRouteTable() that are
238
- * not exported from any route module. These are kept here because they
239
- * depend on cross-cutting concerns specific to the RuntimeHttpServer
240
- * instance (see B2 in the improvement plan for the recommendation to
241
- * extract these into modules).
242
- *
243
- * Whenever buildRouteTable() gains or loses an inline route, this list
244
- * must be updated manually. Note: `--check` only compares the generated
245
- * YAML against the committed YAML, so it will NOT catch a missing entry
246
- * here if openapi.yaml is also stale. Plan items B2/C2 address this gap.
247
- */
248
- const INLINE_ROUTES: RouteEntry[] = [
249
- { endpoint: "conversations", method: "GET" },
250
- { endpoint: "conversations/seen", method: "POST" },
251
- { endpoint: "conversations/unread", method: "POST" },
252
- { endpoint: "conversations/:id", method: "GET" },
253
- { endpoint: "interfaces/:path*", method: "GET" },
254
- { endpoint: "internal/twilio/voice-webhook", method: "POST" },
255
- { endpoint: "internal/twilio/status", method: "POST" },
256
- { endpoint: "internal/twilio/connect-action", method: "POST" },
257
- { endpoint: "internal/oauth/callback", method: "POST" },
258
- ];
259
-
260
- /**
261
- * Pre-auth routes handled directly in routeRequest() before the router.
262
- * These are a small, stable set that bypass JWT authentication and are
263
- * not part of the declarative route table.
264
- */
265
- const PRE_AUTH_ROUTES: RouteEntry[] = [
266
- { method: "POST", endpoint: "pairing/request" },
267
- { method: "GET", endpoint: "pairing/status" },
268
- ];
269
-
270
179
  /**
271
180
  * Top-level routes outside the /v1/ namespace.
272
181
  * These are added to the spec separately.
@@ -551,11 +460,7 @@ async function main() {
551
460
  const moduleRoutes = await collectRoutesFromModules();
552
461
 
553
462
  // Combine all route sources
554
- const allRoutes: RouteEntry[] = [
555
- ...PRE_AUTH_ROUTES,
556
- ...INLINE_ROUTES,
557
- ...moduleRoutes,
558
- ];
463
+ const allRoutes: RouteEntry[] = moduleRoutes;
559
464
 
560
465
  // Build the spec
561
466
  const spec = buildSpec(allRoutes, version);
@@ -20,7 +20,8 @@
20
20
  * asserts that:
21
21
  * 1. The wake forwards `overrideProfile` to `agentLoop.run`.
22
22
  * 2. The wake forwards `callSite: "mainAgent"` to `agentLoop.run`.
23
- * 3. With both set, `RetryProvider.normalizeSendMessageOptions` actually
23
+ * 3. The wake resolves and forwards the effective max input token budget.
24
+ * 4. With both routing keys set, `RetryProvider.normalizeSendMessageOptions` actually
24
25
  * invokes the resolver and replaces workspace defaults with the
25
26
  * pinned-profile values.
26
27
  */
@@ -69,6 +70,7 @@ interface RunArgs {
69
70
  callSite: unknown;
70
71
  turnContext: unknown;
71
72
  overrideProfile: string | undefined;
73
+ effectiveMaxInputTokens: number | undefined;
72
74
  }
73
75
 
74
76
  function makeTarget(): {
@@ -93,6 +95,7 @@ function makeTarget(): {
93
95
  callSite?: unknown,
94
96
  turnContext?: unknown,
95
97
  overrideProfile?: string,
98
+ effectiveMaxInputTokens?: number,
96
99
  ) => {
97
100
  runArgs.push({
98
101
  messages: [...messages],
@@ -102,6 +105,7 @@ function makeTarget(): {
102
105
  callSite,
103
106
  turnContext,
104
107
  overrideProfile,
108
+ effectiveMaxInputTokens,
105
109
  });
106
110
  // Return the input verbatim → silent no-op (no assistant tail).
107
111
  return messages;
@@ -133,6 +137,22 @@ afterEach(() => {
133
137
  describe("wakeAgentForOpportunity — overrideProfile forwarding", () => {
134
138
  test("forwards the conversation's pinned overrideProfile + mainAgent callSite to agentLoop.run", async () => {
135
139
  mockOverrideProfile = "frontier";
140
+ mockLlmConfig = LLMSchema.parse({
141
+ default: {
142
+ provider: "anthropic",
143
+ model: "claude-sonnet-4-6",
144
+ maxTokens: 64000,
145
+ contextWindow: { maxInputTokens: 200000 },
146
+ },
147
+ profiles: {
148
+ frontier: {
149
+ contextWindow: { maxInputTokens: 150000 },
150
+ },
151
+ },
152
+ callSites: {
153
+ mainAgent: {},
154
+ },
155
+ }) as Record<string, unknown>;
136
156
  const { target, runArgs } = makeTarget();
137
157
 
138
158
  const result = await wakeAgentForOpportunity(
@@ -155,6 +175,7 @@ describe("wakeAgentForOpportunity — overrideProfile forwarding", () => {
155
175
  // short-circuit and silently drop both the call-site config and the
156
176
  // pinned override profile.
157
177
  expect(runArgs[0]!.callSite).toBe("mainAgent");
178
+ expect(runArgs[0]!.effectiveMaxInputTokens).toBe(150000);
158
179
  // Sanity: the wake-source tag still propagates as requestId.
159
180
  expect(runArgs[0]!.requestId).toBe("wake:scheduler");
160
181
  });
@@ -179,6 +200,7 @@ describe("wakeAgentForOpportunity — overrideProfile forwarding", () => {
179
200
  // maxTokens, effort, etc.). Otherwise the wake silently runs under
180
201
  // workspace defaults regardless of any per-call-site configuration.
181
202
  expect(runArgs[0]!.callSite).toBe("mainAgent");
203
+ expect(runArgs[0]!.effectiveMaxInputTokens).toBeGreaterThan(0);
182
204
  });
183
205
  });
184
206
 
@@ -374,17 +374,53 @@ describe("AnthropicProvider — Cache-Control Characterization", () => {
374
374
  }>;
375
375
 
376
376
  const userMessages = sent.filter((m) => m.role === "user");
377
- // Only the last user message (turn-starting) gets cache_control
378
- for (const user of userMessages.slice(0, -1)) {
379
- for (const block of user.content) {
380
- expect(block.cache_control).toBeUndefined();
381
- }
377
+ // Oldest user message (Turn 1) has no cache_control
378
+ for (const block of userMessages[0].content) {
379
+ expect(block.cache_control).toBeUndefined();
382
380
  }
381
+ // Previous-turn anchor (Turn 2) gets 1h cache on its last block to
382
+ // preserve the cached prefix across turn transitions
383
+ const prevTurn = userMessages[userMessages.length - 2];
384
+ const prevTurnLast = prevTurn.content[prevTurn.content.length - 1];
385
+ expect(prevTurnLast.cache_control).toEqual({
386
+ type: "ephemeral",
387
+ ttl: "1h",
388
+ });
389
+ // Current-turn anchor (Turn 3) gets 1h cache on its last block
383
390
  const lastUser = userMessages[userMessages.length - 1];
384
391
  const lastBlock = lastUser.content[lastUser.content.length - 1];
385
392
  expect(lastBlock.cache_control).toEqual({ type: "ephemeral", ttl: "1h" });
386
393
  });
387
394
 
395
+ test("previous-turn anchor is NOT applied during a tool-use loop", async () => {
396
+ // When the request is mid tool-use (last msg is a tool_result), the
397
+ // turn-start anchor already covers the long prefix, so we must not
398
+ // place a second anchor on the prior turn — that would push us over
399
+ // the 4-breakpoint budget without adding cache value.
400
+ const messages: Message[] = [
401
+ userMsg("Turn 1"),
402
+ assistantMsg("Response 1"),
403
+ userMsg("Turn 2"),
404
+ toolUseMsg("tu_1", "bash"),
405
+ toolResultMsg("tu_1", "output"),
406
+ ];
407
+ await provider.sendMessage(messages);
408
+
409
+ const sent = lastStreamParams!.messages as Array<{
410
+ role: string;
411
+ content: Array<{
412
+ type: string;
413
+ cache_control?: { type: string; ttl?: string };
414
+ }>;
415
+ }>;
416
+ // Turn 1 user message must have no cache_control (would be the
417
+ // prev-turn-anchor if we applied it, which we shouldn't here)
418
+ const turn1 = sent[0];
419
+ for (const block of turn1.content) {
420
+ expect(block.cache_control).toBeUndefined();
421
+ }
422
+ });
423
+
388
424
  // -----------------------------------------------------------------------
389
425
  // Negative: assistant messages never get cache_control
390
426
  // -----------------------------------------------------------------------
@@ -1621,7 +1657,7 @@ describe("AnthropicProvider — Cache-Control Characterization", () => {
1621
1657
  expect(sent[4].content[0].text).toBe("Follow-up question");
1622
1658
  });
1623
1659
 
1624
- test("multi-turn with workspace injection: only last user message gets 1h cache", async () => {
1660
+ test("multi-turn with workspace injection: prev-turn + last user message get 1h cache", async () => {
1625
1661
  const messages: Message[] = [
1626
1662
  {
1627
1663
  role: "user",
@@ -1669,14 +1705,21 @@ describe("AnthropicProvider — Cache-Control Characterization", () => {
1669
1705
  const userMsgs = sent.filter((m) => m.role === "user");
1670
1706
  expect(userMsgs).toHaveLength(3);
1671
1707
 
1672
- // Earlier user messages: no cache_control
1673
- for (const user of userMsgs.slice(0, -1)) {
1674
- for (const block of user.content) {
1675
- expect(block.cache_control).toBeUndefined();
1676
- }
1708
+ // Oldest user message (turn 1): no cache_control
1709
+ for (const block of userMsgs[0].content) {
1710
+ expect(block.cache_control).toBeUndefined();
1677
1711
  }
1678
1712
 
1679
- // Last user message (turn 3): 1h cache on last block only
1713
+ // Previous-turn anchor (turn 2): 1h cache on last block to preserve the
1714
+ // cached prefix across turn transitions
1715
+ const prevTurn = userMsgs[userMsgs.length - 2];
1716
+ expect(prevTurn.content[0].cache_control).toBeUndefined();
1717
+ expect(prevTurn.content[1].cache_control).toEqual({
1718
+ type: "ephemeral",
1719
+ ttl: "1h",
1720
+ });
1721
+
1722
+ // Current-turn anchor (turn 3): 1h cache on last block
1680
1723
  const lastUser = userMsgs[userMsgs.length - 1];
1681
1724
  expect(lastUser.content[0].cache_control).toBeUndefined();
1682
1725
  expect(lastUser.content[1].cache_control).toEqual({
@@ -2100,7 +2143,7 @@ describe("AnthropicProvider — Haiku Model Gating", () => {
2100
2143
  expect(system[0].cache_control).not.toHaveProperty("ttl");
2101
2144
  });
2102
2145
 
2103
- test("betas array is empty for Haiku (no extended cache TTL or 1M context)", async () => {
2146
+ test("betas array is empty for Haiku (no extended cache TTL)", async () => {
2104
2147
  await provider.sendMessage([userMsg("Hi")], undefined, "You are helpful.");
2105
2148
 
2106
2149
  // When betas is empty, the non-beta stream path is used, so no betas
@@ -0,0 +1,278 @@
1
+ import { existsSync, rmSync } from "node:fs";
2
+ import { tmpdir } from "node:os";
3
+ import { join } from "node:path";
4
+ import { afterEach, beforeEach, describe, expect, mock, test } from "bun:test";
5
+
6
+ mock.module("../util/logger.js", () => ({
7
+ getLogger: () =>
8
+ new Proxy({} as Record<string, unknown>, {
9
+ get: () => () => {},
10
+ }),
11
+ }));
12
+
13
+ import {
14
+ addAppConversationId,
15
+ backfillAppConversationIds,
16
+ createApp,
17
+ getApp,
18
+ } from "../memory/app-store.js";
19
+ import { getDb } from "../memory/db-connection.js";
20
+ import { initializeDb } from "../memory/db-init.js";
21
+ import { rawRun } from "../memory/raw-query.js";
22
+
23
+ // Initialize db once for all tests
24
+ initializeDb();
25
+
26
+ // ---------------------------------------------------------------------------
27
+ // Helpers
28
+ // ---------------------------------------------------------------------------
29
+
30
+ let testDataDir: string;
31
+
32
+ function freshTempDir(): string {
33
+ return join(
34
+ tmpdir(),
35
+ `vellum-app-backfill-test-${Date.now()}-${Math.random().toString(36).slice(2)}`,
36
+ );
37
+ }
38
+
39
+ function makeAppParams(name: string) {
40
+ return {
41
+ name,
42
+ schemaJson: "{}",
43
+ htmlDefinition: "<h1>Hello</h1>",
44
+ };
45
+ }
46
+
47
+ /** Insert a message row with the given conversation_id and content JSON. */
48
+ function insertMessage(
49
+ conversationId: string,
50
+ content: unknown[],
51
+ role = "assistant",
52
+ ): void {
53
+ const id = `msg-${Date.now()}-${Math.random().toString(36).slice(2)}`;
54
+ const contentStr = JSON.stringify(content);
55
+ rawRun(
56
+ `INSERT INTO messages (id, conversation_id, role, content, created_at) VALUES (?, ?, ?, ?, ?)`,
57
+ id,
58
+ conversationId,
59
+ role,
60
+ contentStr,
61
+ Date.now(),
62
+ );
63
+ }
64
+
65
+ /** Insert a conversation row so FK constraints are satisfied. */
66
+ function insertConversation(id: string): void {
67
+ const now = Date.now();
68
+ rawRun(
69
+ `INSERT OR IGNORE INTO conversations (id, title, created_at, updated_at) VALUES (?, ?, ?, ?)`,
70
+ id,
71
+ "test",
72
+ now,
73
+ now,
74
+ );
75
+ }
76
+
77
+ // ---------------------------------------------------------------------------
78
+ // Setup / teardown
79
+ // ---------------------------------------------------------------------------
80
+
81
+ beforeEach(() => {
82
+ // Clean database tables between tests
83
+ const db = getDb();
84
+ db.run(`DELETE FROM messages`);
85
+ db.run(`DELETE FROM conversations`);
86
+
87
+ // Fresh temp dir for app-store filesystem operations
88
+ testDataDir = freshTempDir();
89
+ process.env.VELLUM_WORKSPACE_DIR = testDataDir;
90
+ });
91
+
92
+ afterEach(() => {
93
+ if (existsSync(testDataDir)) {
94
+ rmSync(testDataDir, { recursive: true, force: true });
95
+ }
96
+ });
97
+
98
+ // ---------------------------------------------------------------------------
99
+ // backfillAppConversationIds
100
+ // ---------------------------------------------------------------------------
101
+
102
+ describe("backfillAppConversationIds", () => {
103
+ test("populates conversationIds from ui_surface blocks in messages", () => {
104
+ const app = createApp(makeAppParams("My App"));
105
+ const convId = "conv-backfill-1";
106
+ insertConversation(convId);
107
+
108
+ // Insert a message with a ui_surface block referencing the app
109
+ insertMessage(convId, [
110
+ { type: "text", text: "Here is your app" },
111
+ {
112
+ type: "ui_surface",
113
+ surfaceType: "dynamic_page",
114
+ data: { appId: app.id, html: "<h1>App</h1>" },
115
+ },
116
+ ]);
117
+
118
+ backfillAppConversationIds();
119
+
120
+ const loaded = getApp(app.id);
121
+ expect(loaded?.conversationIds).toEqual([convId]);
122
+ });
123
+
124
+ test("handles multiple apps and conversations", () => {
125
+ const app1 = createApp(makeAppParams("App One"));
126
+ const app2 = createApp(makeAppParams("App Two"));
127
+ const conv1 = "conv-multi-1";
128
+ const conv2 = "conv-multi-2";
129
+ insertConversation(conv1);
130
+ insertConversation(conv2);
131
+
132
+ // app1 referenced in conv1 and conv2
133
+ insertMessage(conv1, [
134
+ {
135
+ type: "ui_surface",
136
+ surfaceType: "dynamic_page",
137
+ data: { appId: app1.id, html: "<h1>A1</h1>" },
138
+ },
139
+ ]);
140
+ insertMessage(conv2, [
141
+ {
142
+ type: "ui_surface",
143
+ surfaceType: "dynamic_page",
144
+ data: { appId: app1.id, html: "<h1>A1</h1>" },
145
+ },
146
+ ]);
147
+
148
+ // app2 referenced only in conv2
149
+ insertMessage(conv2, [
150
+ {
151
+ type: "ui_surface",
152
+ surfaceType: "dynamic_page",
153
+ data: { appId: app2.id, html: "<h1>A2</h1>" },
154
+ },
155
+ ]);
156
+
157
+ backfillAppConversationIds();
158
+
159
+ const loaded1 = getApp(app1.id);
160
+ expect(loaded1?.conversationIds?.sort()).toEqual([conv1, conv2].sort());
161
+
162
+ const loaded2 = getApp(app2.id);
163
+ expect(loaded2?.conversationIds).toEqual([conv2]);
164
+ });
165
+
166
+ test("is idempotent — running twice does not duplicate associations", () => {
167
+ const app = createApp(makeAppParams("Idempotent App"));
168
+ const convId = "conv-idemp-1";
169
+ insertConversation(convId);
170
+
171
+ insertMessage(convId, [
172
+ {
173
+ type: "ui_surface",
174
+ surfaceType: "dynamic_page",
175
+ data: { appId: app.id, html: "<h1>App</h1>" },
176
+ },
177
+ ]);
178
+
179
+ backfillAppConversationIds();
180
+ backfillAppConversationIds();
181
+
182
+ const loaded = getApp(app.id);
183
+ expect(loaded?.conversationIds).toEqual([convId]);
184
+ });
185
+
186
+ test("apps with no message references remain unchanged", () => {
187
+ const app = createApp(makeAppParams("Untouched App"));
188
+ const convId = "conv-unrelated";
189
+ insertConversation(convId);
190
+
191
+ // Insert a message with no ui_surface blocks
192
+ insertMessage(convId, [{ type: "text", text: "Hello world" }]);
193
+
194
+ backfillAppConversationIds();
195
+
196
+ const loaded = getApp(app.id);
197
+ expect(loaded?.conversationIds).toBeUndefined();
198
+ });
199
+
200
+ test("skips malformed message rows without error", () => {
201
+ const app = createApp(makeAppParams("Robust App"));
202
+ const convId = "conv-malformed";
203
+ insertConversation(convId);
204
+
205
+ // Insert a message with invalid JSON that happens to match the LIKE filter
206
+ const msgId = `msg-malformed-${Date.now()}`;
207
+ rawRun(
208
+ `INSERT INTO messages (id, conversation_id, role, content, created_at) VALUES (?, ?, ?, ?, ?)`,
209
+ msgId,
210
+ convId,
211
+ "assistant",
212
+ 'not valid json but has "type":"ui_surface" in it',
213
+ Date.now(),
214
+ );
215
+
216
+ // Also insert a valid message referencing the app
217
+ const convId2 = "conv-valid";
218
+ insertConversation(convId2);
219
+ insertMessage(convId2, [
220
+ {
221
+ type: "ui_surface",
222
+ surfaceType: "dynamic_page",
223
+ data: { appId: app.id, html: "<h1>App</h1>" },
224
+ },
225
+ ]);
226
+
227
+ // Should not throw, and should still process the valid message
228
+ backfillAppConversationIds();
229
+
230
+ const loaded = getApp(app.id);
231
+ expect(loaded?.conversationIds).toEqual([convId2]);
232
+ });
233
+
234
+ test("skips ui_surface blocks without data.appId", () => {
235
+ const app = createApp(makeAppParams("No AppId App"));
236
+ const convId = "conv-no-appid";
237
+ insertConversation(convId);
238
+
239
+ // ui_surface block without appId in data
240
+ insertMessage(convId, [
241
+ {
242
+ type: "ui_surface",
243
+ surfaceType: "card",
244
+ data: { title: "Hello", body: "World" },
245
+ },
246
+ ]);
247
+
248
+ backfillAppConversationIds();
249
+
250
+ const loaded = getApp(app.id);
251
+ expect(loaded?.conversationIds).toBeUndefined();
252
+ });
253
+
254
+ test("preserves existing conversationIds added before backfill", () => {
255
+ const app = createApp(makeAppParams("Pre-existing App"));
256
+ const existingConvId = "conv-existing";
257
+ const backfillConvId = "conv-from-backfill";
258
+ insertConversation(existingConvId);
259
+ insertConversation(backfillConvId);
260
+
261
+ // Manually add a conversationId before backfill
262
+ addAppConversationId(app.id, existingConvId);
263
+
264
+ // Insert a message referencing the app from a different conversation
265
+ insertMessage(backfillConvId, [
266
+ {
267
+ type: "ui_surface",
268
+ surfaceType: "dynamic_page",
269
+ data: { appId: app.id, html: "<h1>App</h1>" },
270
+ },
271
+ ]);
272
+
273
+ backfillAppConversationIds();
274
+
275
+ const loaded = getApp(app.id);
276
+ expect(loaded?.conversationIds).toEqual([existingConvId, backfillConvId]);
277
+ });
278
+ });