@vellumai/assistant 0.8.4 → 0.8.6

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 (802) hide show
  1. package/AGENTS.md +33 -1
  2. package/ARCHITECTURE.md +3 -3
  3. package/bunfig.toml +6 -1
  4. package/docs/browser-use-architecture-phase2.md +1 -1
  5. package/docs/credential-execution-service.md +6 -6
  6. package/docs/plugins.md +4 -3
  7. package/knip.json +2 -1
  8. package/node_modules/@vellumai/skill-host-contracts/src/client.ts +12 -13
  9. package/node_modules/@vellumai/skill-host-contracts/src/skill-host.ts +4 -1
  10. package/node_modules/@vellumai/skill-host-contracts/src/tool-types.ts +16 -14
  11. package/openapi.yaml +2748 -216
  12. package/package.json +1 -1
  13. package/src/__tests__/actor-token-service.test.ts +3 -2
  14. package/src/__tests__/agent-loop-exit-reason.test.ts +102 -9
  15. package/src/__tests__/agent-loop-override-profile.test.ts +2 -1
  16. package/src/__tests__/agent-wake-disk-pressure-callsite.test.ts +1 -0
  17. package/src/__tests__/agent-wake-override-profile.test.ts +1 -0
  18. package/src/__tests__/always-loaded-tools-guard.test.ts +2 -2
  19. package/src/__tests__/annotate-risk-options.test.ts +1 -0
  20. package/src/__tests__/anthropic-provider.test.ts +34 -37
  21. package/src/__tests__/approval-cascade.test.ts +1 -0
  22. package/src/__tests__/approval-routes-http.test.ts +9 -13
  23. package/src/__tests__/assert-not-live-db.ts +79 -0
  24. package/src/__tests__/assistant-event-hub-self-exclusion.test.ts +293 -0
  25. package/src/__tests__/assistant-feature-flags-integration.test.ts +12 -28
  26. package/src/__tests__/audit-log-rotation.test.ts +72 -18
  27. package/src/__tests__/auto-analysis-end-to-end.test.ts +6 -6
  28. package/src/__tests__/background-workers-disk-pressure.test.ts +8 -11
  29. package/src/__tests__/browser-skill-endstate.test.ts +3 -3
  30. package/src/__tests__/btw-routes.test.ts +5 -5
  31. package/src/__tests__/call-controller.test.ts +3 -3
  32. package/src/__tests__/cancel-resolves-conversation-key.test.ts +1 -1
  33. package/src/__tests__/channel-approval-routes.test.ts +3 -2
  34. package/src/__tests__/channel-guardian.test.ts +6 -5
  35. package/src/__tests__/channel-readiness-slack-remote.test.ts +175 -0
  36. package/src/__tests__/channel-reply-delivery.test.ts +35 -0
  37. package/src/__tests__/channel-retry-sweep.test.ts +320 -3
  38. package/src/__tests__/checker.test.ts +18 -27
  39. package/src/__tests__/compaction-events.test.ts +2 -0
  40. package/src/__tests__/compaction-trail-store.test.ts +264 -0
  41. package/src/__tests__/compactor-call-site-logging.test.ts +215 -0
  42. package/src/__tests__/compactor-preserved-tail-count.test.ts +1 -0
  43. package/src/__tests__/computer-use-skill-manifest-regression.test.ts +12 -16
  44. package/src/__tests__/computer-use-tools.test.ts +14 -18
  45. package/src/__tests__/config-loader-backfill.test.ts +13 -28
  46. package/src/__tests__/config-loader-corrupt.test.ts +5 -5
  47. package/src/__tests__/config-loader-platform-defaults.test.ts +93 -26
  48. package/src/__tests__/config-loader-quarantine-bulletin.test.ts +3 -3
  49. package/src/__tests__/config-managed-gemini-defaults.test.ts +3 -4
  50. package/src/__tests__/config-schema.test.ts +10 -10
  51. package/src/__tests__/confirmation-request-guardian-bridge.test.ts +0 -1
  52. package/src/__tests__/connection-model-compat.test.ts +83 -0
  53. package/src/__tests__/contacts-tools.test.ts +3 -2
  54. package/src/__tests__/context-token-estimator.test.ts +22 -0
  55. package/src/__tests__/conversation-abort-tool-results.test.ts +5 -0
  56. package/src/__tests__/conversation-agent-loop-disk-pressure.test.ts +2 -1
  57. package/src/__tests__/conversation-agent-loop-handlers-max-tokens.test.ts +55 -0
  58. package/src/__tests__/conversation-agent-loop-inference-profile.test.ts +2 -1
  59. package/src/__tests__/conversation-agent-loop-overflow.test.ts +231 -2
  60. package/src/__tests__/conversation-agent-loop.test.ts +581 -54
  61. package/src/__tests__/conversation-analysis-routes.test.ts +1 -0
  62. package/src/__tests__/conversation-app-control-instantiation.test.ts +31 -24
  63. package/src/__tests__/conversation-app-control-lifecycle.test.ts +1 -0
  64. package/src/__tests__/conversation-attention-store.test.ts +101 -0
  65. package/src/__tests__/conversation-attention-telegram.test.ts +3 -2
  66. package/src/__tests__/conversation-clear-safety.test.ts +25 -25
  67. package/src/__tests__/conversation-confirmation-signals.test.ts +1 -0
  68. package/src/__tests__/conversation-delete-schedule-cleanup.test.ts +1 -1
  69. package/src/__tests__/conversation-disk-view-integration.test.ts +2 -2
  70. package/src/__tests__/conversation-error.test.ts +61 -0
  71. package/src/__tests__/conversation-fork-crud.test.ts +239 -15
  72. package/src/__tests__/conversation-fork-route.test.ts +3 -2
  73. package/src/__tests__/conversation-history-web-search.test.ts +1 -0
  74. package/src/__tests__/conversation-inference-profile-list.test.ts +3 -2
  75. package/src/__tests__/conversation-inference-profile-route.test.ts +3 -2
  76. package/src/__tests__/conversation-lifecycle.test.ts +53 -11
  77. package/src/__tests__/conversation-list-source.test.ts +3 -2
  78. package/src/__tests__/conversation-load-history-repair.test.ts +2 -1
  79. package/src/__tests__/{conversation-load-cleaned-at.test.ts → conversation-load-history-stripped.test.ts} +14 -13
  80. package/src/__tests__/conversation-pairing.test.ts +53 -0
  81. package/src/__tests__/conversation-process-app-control-preactivation.test.ts +26 -7
  82. package/src/__tests__/conversation-process-callsite.test.ts +1 -0
  83. package/src/__tests__/conversation-provider-retry-repair.test.ts +6 -0
  84. package/src/__tests__/conversation-queue.test.ts +333 -291
  85. package/src/__tests__/conversation-routes-disk-view.test.ts +112 -18
  86. package/src/__tests__/conversation-routes-guardian-reply.test.ts +33 -8
  87. package/src/__tests__/conversation-routes-slash-commands.test.ts +68 -2
  88. package/src/__tests__/conversation-runtime-assembly.test.ts +78 -0
  89. package/src/__tests__/conversation-skill-tools.test.ts +40 -147
  90. package/src/__tests__/conversation-slash-queue.test.ts +84 -32
  91. package/src/__tests__/conversation-slash-unknown.test.ts +5 -0
  92. package/src/__tests__/conversation-speed-override.test.ts +1 -0
  93. package/src/__tests__/conversation-store.test.ts +1 -1
  94. package/src/__tests__/conversation-surfaces-action-delivery.test.ts +46 -0
  95. package/src/__tests__/conversation-surfaces-data-persist.test.ts +1 -0
  96. package/src/__tests__/conversation-surfaces-standalone-payloads.test.ts +6 -3
  97. package/src/__tests__/conversation-surfaces-standalone.test.ts +6 -3
  98. package/src/__tests__/conversation-surfaces-state-update.test.ts +3 -3
  99. package/src/__tests__/conversation-surfaces-table-action.test.ts +7 -17
  100. package/src/__tests__/conversation-sync-tags.test.ts +218 -35
  101. package/src/__tests__/conversation-title-service.test.ts +1 -0
  102. package/src/__tests__/conversation-tool-setup-app-refresh.test.ts +30 -0
  103. package/src/__tests__/conversation-usage.test.ts +1 -0
  104. package/src/__tests__/conversation-workspace-cache-state.test.ts +2 -0
  105. package/src/__tests__/conversation-workspace-injection.test.ts +6 -1
  106. package/src/__tests__/conversation-workspace-tool-tracking.test.ts +6 -1
  107. package/src/__tests__/credential-broker-browser-fill.test.ts +3 -3
  108. package/src/__tests__/credential-broker-server-use.test.ts +5 -5
  109. package/src/__tests__/credential-execution-client.test.ts +72 -1
  110. package/src/__tests__/credential-execution-feature-gates.test.ts +19 -19
  111. package/src/__tests__/credential-execution-tools.test.ts +6 -6
  112. package/src/__tests__/credential-health-service.test.ts +252 -3
  113. package/src/__tests__/credential-security-invariants.test.ts +6 -5
  114. package/src/__tests__/credential-vault-unit.test.ts +21 -21
  115. package/src/__tests__/credential-vault.test.ts +5 -5
  116. package/src/__tests__/cross-provider-web-search.test.ts +56 -2
  117. package/src/__tests__/db-connection-isolation.test.ts +7 -6
  118. package/src/__tests__/db-conversation-fork-lineage-migration.test.ts +8 -10
  119. package/src/__tests__/db-conversation-inference-profile-migration.test.ts +7 -10
  120. package/src/__tests__/db-llm-request-log-provider-migration.test.ts +9 -15
  121. package/src/__tests__/db-test-helpers.ts +58 -0
  122. package/src/__tests__/disk-pressure-guard.test.ts +58 -41
  123. package/src/__tests__/disk-pressure-lifecycle.test.ts +13 -10
  124. package/src/__tests__/disk-pressure-routes.test.ts +0 -33
  125. package/src/__tests__/disk-pressure-tools.test.ts +0 -4
  126. package/src/__tests__/dm-persistence.test.ts +26 -40
  127. package/src/__tests__/document-create-dedupe.test.ts +189 -0
  128. package/src/__tests__/document-find-replace.test.ts +3 -2
  129. package/src/__tests__/document-tool-security.test.ts +81 -2
  130. package/src/__tests__/dynamic-page-surface.test.ts +2 -2
  131. package/src/__tests__/dynamic-skill-workflow-prompt.test.ts +5 -4
  132. package/src/__tests__/email-html-renderer.test.ts +12 -0
  133. package/src/__tests__/encrypted-store-test-helpers.ts +56 -0
  134. package/src/__tests__/encrypted-store.test.ts +11 -9
  135. package/src/__tests__/feature-flag-test-helpers.ts +53 -0
  136. package/src/__tests__/filing-service.test.ts +1 -0
  137. package/src/__tests__/first-greeting.test.ts +62 -12
  138. package/src/__tests__/gateway-flag-listener.test.ts +236 -0
  139. package/src/__tests__/gemini-provider.test.ts +104 -0
  140. package/src/__tests__/guardian-action-sweep.test.ts +3 -2
  141. package/src/__tests__/guardian-dispatch.test.ts +0 -1
  142. package/src/__tests__/guardian-outbound-http.test.ts +10 -7
  143. package/src/__tests__/handlers-skills-memory-v2-reseed.test.ts +48 -3
  144. package/src/__tests__/handlers-user-message-approval-consumption.test.ts +2 -1
  145. package/src/__tests__/heartbeat-disk-pressure.test.ts +5 -0
  146. package/src/__tests__/heartbeat-service.test.ts +5 -0
  147. package/src/__tests__/helpers/mock-logger.ts +26 -0
  148. package/src/__tests__/host-bash-routes.test.ts +1 -0
  149. package/src/__tests__/host-cu-routes-targeted.test.ts +1 -0
  150. package/src/__tests__/host-file-routes-targeted.test.ts +1 -0
  151. package/src/__tests__/host-shell-tool.test.ts +6 -5
  152. package/src/__tests__/host-transfer-routes-targeted.test.ts +1 -0
  153. package/src/__tests__/http-conversation-lineage.test.ts +3 -2
  154. package/src/__tests__/http-user-message-parity.test.ts +29 -7
  155. package/src/__tests__/identity-intro-cache.test.ts +133 -22
  156. package/src/__tests__/inbound-slack-persistence.test.ts +44 -72
  157. package/src/__tests__/inference-profile-reaper.test.ts +3 -2
  158. package/src/__tests__/inference-profile-session-ipc.test.ts +3 -2
  159. package/src/__tests__/init-feature-flag-overrides.test.ts +5 -6
  160. package/src/__tests__/injector-disk-pressure.test.ts +3 -17
  161. package/src/__tests__/inline-skill-load-permissions.test.ts +4 -4
  162. package/src/__tests__/list-messages-hidden-metadata.test.ts +80 -0
  163. package/src/__tests__/list-messages-tool-merge.test.ts +70 -11
  164. package/src/__tests__/llm-context-normalization.test.ts +42 -0
  165. package/src/__tests__/llm-request-log-call-site.test.ts +136 -0
  166. package/src/__tests__/llm-request-log-source-clickhouse.test.ts +26 -0
  167. package/src/__tests__/llm-resolver.test.ts +408 -9
  168. package/src/__tests__/llm-schema.test.ts +1 -1
  169. package/src/__tests__/llm-usage-store.test.ts +66 -0
  170. package/src/__tests__/logger.test.ts +89 -0
  171. package/src/__tests__/manual-token-reconciliation.test.ts +76 -1
  172. package/src/__tests__/mcp-abort-signal.test.ts +16 -2
  173. package/src/__tests__/mcp-client-auth.test.ts +14 -0
  174. package/src/__tests__/media-generate-image.test.ts +31 -0
  175. package/src/__tests__/memory-v2-static-injector.test.ts +7 -7
  176. package/src/__tests__/messaging-send-tool.test.ts +1 -0
  177. package/src/__tests__/migration-import-from-url.test.ts +3 -3
  178. package/src/__tests__/mock-gateway-ipc.ts +18 -2
  179. package/src/__tests__/model-intents.test.ts +4 -6
  180. package/src/__tests__/native-web-search.test.ts +30 -2
  181. package/src/__tests__/notification-deep-link.test.ts +62 -0
  182. package/src/__tests__/notification-guardian-path.test.ts +0 -1
  183. package/src/__tests__/oauth-commands-routes.test.ts +37 -0
  184. package/src/__tests__/oauth-provider-visibility.test.ts +8 -8
  185. package/src/__tests__/oauth-store.test.ts +3 -2
  186. package/src/__tests__/onboarding-template-contract.test.ts +4 -3
  187. package/src/__tests__/openai-provider.test.ts +54 -9
  188. package/src/__tests__/openai-responses-provider.test.ts +176 -14
  189. package/src/__tests__/openrouter-provider-only.test.ts +27 -5
  190. package/src/__tests__/outbound-slack-persistence.test.ts +46 -1
  191. package/src/__tests__/pending-interactions-resolved-event.test.ts +0 -1
  192. package/src/__tests__/persistence-pipeline.test.ts +139 -1
  193. package/src/__tests__/persistence-secret-redaction.test.ts +83 -12
  194. package/src/__tests__/platform-bash-auto-approve.test.ts +2 -2
  195. package/src/__tests__/platform.test.ts +2 -2
  196. package/src/__tests__/plugin-api-tool-definition.test.ts +92 -0
  197. package/src/__tests__/plugin-bootstrap.test.ts +11 -13
  198. package/src/__tests__/plugin-tool-contribution.test.ts +50 -40
  199. package/src/__tests__/plugin-types.test.ts +3 -2
  200. package/src/__tests__/prechat-onboarding-contract.test.ts +131 -98
  201. package/src/__tests__/pricing.test.ts +12 -0
  202. package/src/__tests__/process-message-background-slack.test.ts +21 -16
  203. package/src/__tests__/process-message-display-content.test.ts +19 -22
  204. package/src/__tests__/provider-catalog-visibility.test.ts +9 -9
  205. package/src/__tests__/provider-platform-proxy-integration.test.ts +216 -4
  206. package/src/__tests__/provider-registry-ollama.test.ts +45 -22
  207. package/src/__tests__/prune-jobs-changes-parser.test.ts +61 -0
  208. package/src/__tests__/recording-handler.test.ts +1 -0
  209. package/src/__tests__/regenerate-fire-and-forget-trace.test.ts +1 -0
  210. package/src/__tests__/registry.test.ts +84 -84
  211. package/src/__tests__/relay-server.test.ts +10 -10
  212. package/src/__tests__/require-fresh-approval.test.ts +2 -2
  213. package/src/__tests__/runtime-attachment-metadata.test.ts +3 -2
  214. package/src/__tests__/runtime-events-sse-bilingual.test.ts +154 -0
  215. package/src/__tests__/schedule-store.test.ts +16 -1
  216. package/src/__tests__/scheduler-reuse-conversation.test.ts +48 -3
  217. package/src/__tests__/secret-ingress-http.test.ts +5 -1
  218. package/src/__tests__/secure-keys.test.ts +3 -3
  219. package/src/__tests__/send-endpoint-busy.test.ts +81 -42
  220. package/src/__tests__/server-history-render.test.ts +4 -1
  221. package/src/__tests__/shell-tool-proxy-mode.test.ts +1 -1
  222. package/src/__tests__/skill-feature-flags-integration.test.ts +8 -10
  223. package/src/__tests__/skill-feature-flags.test.ts +16 -18
  224. package/src/__tests__/skill-load-feature-flag.test.ts +5 -5
  225. package/src/__tests__/skill-projection-feature-flag.test.ts +48 -37
  226. package/src/__tests__/skill-projection.benchmark.test.ts +7 -13
  227. package/src/__tests__/skill-tool-factory.test.ts +97 -96
  228. package/src/__tests__/slack-channel-config.test.ts +3 -3
  229. package/src/__tests__/subagent-call-site-routing.test.ts +11 -3
  230. package/src/__tests__/subagent-disposal.test.ts +27 -8
  231. package/src/__tests__/subagent-fork-notifications.test.ts +24 -9
  232. package/src/__tests__/subagent-fork-spawn.test.ts +13 -4
  233. package/src/__tests__/subagent-manager-notify.test.ts +20 -8
  234. package/src/__tests__/subagent-notify-parent.test.ts +6 -5
  235. package/src/__tests__/subagent-spawn-tool-fork.test.ts +58 -0
  236. package/src/__tests__/subagent-tools.test.ts +2 -1
  237. package/src/__tests__/suggestion-routes.test.ts +2 -0
  238. package/src/__tests__/sync-message-contract.test.ts +59 -0
  239. package/src/__tests__/system-prompt.test.ts +183 -131
  240. package/src/__tests__/terminal-tools.test.ts +1 -1
  241. package/src/__tests__/test-preload-verifier.ts +68 -0
  242. package/src/__tests__/test-preload.ts +32 -39
  243. package/src/__tests__/tool-approval-handler.test.ts +1 -5
  244. package/src/__tests__/tool-execute-pipeline.test.ts +2 -2
  245. package/src/__tests__/tool-execution-pipeline.benchmark.test.ts +2 -5
  246. package/src/__tests__/tool-executor-lifecycle-events.test.ts +35 -12
  247. package/src/__tests__/tool-executor.test.ts +64 -72
  248. package/src/__tests__/tool-grant-request-escalation.test.ts +1 -6
  249. package/src/__tests__/tool-preview-lifecycle.test.ts +1 -0
  250. package/src/__tests__/tool-result-metadata-plumbing.test.ts +1 -0
  251. package/src/__tests__/trusted-contact-approval-notifier.test.ts +0 -1
  252. package/src/__tests__/trusted-contact-inline-approval-integration.test.ts +1 -6
  253. package/src/__tests__/trusted-contact-multichannel.test.ts +0 -1
  254. package/src/__tests__/twilio-routes.test.ts +3 -2
  255. package/src/__tests__/ui-file-upload-surface.test.ts +2 -2
  256. package/src/__tests__/usage-routes.test.ts +3 -0
  257. package/src/__tests__/validate-input.test.ts +381 -0
  258. package/src/__tests__/verification-control-plane-policy.test.ts +3 -2
  259. package/src/__tests__/voice-scoped-grant-consumer.test.ts +2 -1
  260. package/src/__tests__/voice-session-bridge.test.ts +37 -28
  261. package/src/__tests__/workspace-git-service.test.ts +6 -5
  262. package/src/__tests__/workspace-migration-089-move-memory-tree-out-of-v3.test.ts +86 -0
  263. package/src/__tests__/workspace-migration-090-memory-router-cost-optimized-profile.test.ts +326 -0
  264. package/src/__tests__/workspace-migration-091-retighten-migration-onboarding-thread.test.ts +166 -0
  265. package/src/acp/__tests__/prepare-agent-env.test.ts +146 -0
  266. package/src/acp/prepare-agent-env.ts +78 -0
  267. package/src/acp/session-manager.ts +6 -7
  268. package/src/agent/loop.ts +88 -0
  269. package/src/api/README.md +127 -0
  270. package/src/api/constants/call-sites.ts +27 -0
  271. package/src/api/events/assistant-outbound-attachment.ts +51 -0
  272. package/src/api/events/assistant-text-delta.ts +32 -0
  273. package/src/api/events/assistant-turn-start.ts +33 -0
  274. package/src/api/events/document-comment-created.ts +48 -0
  275. package/src/api/events/document-comment-deleted.ts +24 -0
  276. package/src/api/events/document-comment-reopened.ts +25 -0
  277. package/src/api/events/document-comment-resolved.ts +27 -0
  278. package/src/api/events/generation-cancelled.ts +24 -0
  279. package/src/api/events/generation-handoff.ts +41 -0
  280. package/src/api/events/message-complete.ts +42 -0
  281. package/src/api/events/open-url.ts +30 -0
  282. package/src/api/events/relationship-state-updated.ts +25 -0
  283. package/src/api/events/tool-use-start.ts +32 -0
  284. package/src/api/index.ts +129 -0
  285. package/src/api/package.json +10 -0
  286. package/src/api/responses/llm-context-response.ts +39 -0
  287. package/src/api/responses/llm-request-log-entry.ts +93 -0
  288. package/src/api/responses/memory-recall-log.ts +65 -0
  289. package/src/api/responses/memory-v2-activation-log.ts +78 -0
  290. package/src/background-wake/background-wake-routes.test.ts +868 -0
  291. package/src/background-wake/platform-client.test.ts +308 -0
  292. package/src/background-wake/platform-client.ts +167 -0
  293. package/src/background-wake/publisher.ts +91 -0
  294. package/src/background-wake/runtime-registry.ts +24 -0
  295. package/src/background-wake/wake-intent-hooks.test.ts +282 -0
  296. package/src/calls/guardian-dispatch.ts +1 -0
  297. package/src/calls/voice-session-bridge.ts +4 -4
  298. package/src/cli/commands/__tests__/browser.test.ts +23 -5
  299. package/src/cli/commands/__tests__/conversations-slack.test.ts +16 -0
  300. package/src/cli/commands/__tests__/domain-register.test.ts +110 -0
  301. package/src/cli/commands/__tests__/domain-status.test.ts +33 -33
  302. package/src/cli/commands/__tests__/inference-send.test.ts +108 -5
  303. package/src/cli/commands/__tests__/memory-v2-compare-render.test.ts +98 -0
  304. package/src/cli/commands/__tests__/memory-v2.test.ts +1 -0
  305. package/src/cli/commands/__tests__/memory-v3-render.test.ts +340 -0
  306. package/src/cli/commands/__tests__/notifications.test.ts +184 -40
  307. package/src/cli/commands/browser.ts +247 -0
  308. package/src/cli/commands/channels/__tests__/channels.test.ts +143 -0
  309. package/src/cli/commands/channels/index.ts +229 -0
  310. package/src/cli/commands/domain.ts +91 -41
  311. package/src/cli/commands/inference.ts +93 -40
  312. package/src/cli/commands/memory-v2-compare-render.ts +115 -0
  313. package/src/cli/commands/memory-v2.ts +176 -1
  314. package/src/cli/commands/memory-v3-render.ts +491 -0
  315. package/src/cli/commands/memory-v3.ts +567 -0
  316. package/src/cli/commands/notifications.ts +365 -55
  317. package/src/cli/lib/open-browser.ts +7 -2
  318. package/src/cli/program.ts +4 -0
  319. package/src/config/assistant-feature-flags.ts +39 -46
  320. package/src/config/bundled-skills/document-editor/SKILL.md +16 -3
  321. package/src/config/bundled-skills/document-editor/TOOLS.json +18 -0
  322. package/src/config/bundled-skills/document-editor/tools/document-open.ts +12 -0
  323. package/src/config/bundled-skills/image-studio/SKILL.md +4 -0
  324. package/src/config/bundled-skills/image-studio/tools/media-generate-image.ts +2 -2
  325. package/src/config/bundled-skills/media-processing/tools/ingest-media.ts +13 -8
  326. package/src/config/bundled-skills/messaging/tools/messaging-analyze-style.ts +10 -3
  327. package/src/config/bundled-skills/phone-calls/references/TRANSCRIPTS.md +16 -14
  328. package/src/config/bundled-skills/playbooks/tools/playbook-create.ts +7 -2
  329. package/src/config/bundled-skills/playbooks/tools/playbook-update.ts +7 -2
  330. package/src/config/bundled-skills/schedule/SKILL.md +1 -1
  331. package/src/config/bundled-skills/schedule/TOOLS.json +2 -2
  332. package/src/config/bundled-skills/settings/tools/open-system-settings.ts +1 -0
  333. package/src/config/bundled-tool-registry.ts +2 -0
  334. package/src/config/call-site-defaults.ts +8 -7
  335. package/src/config/feature-flag-cache.ts +86 -0
  336. package/src/config/feature-flag-registry.json +33 -17
  337. package/src/config/llm-context-resolution.ts +10 -1
  338. package/src/config/llm-resolver.ts +121 -15
  339. package/src/config/loader.ts +4 -5
  340. package/src/config/schemas/__tests__/memory-v2.test.ts +228 -1
  341. package/src/config/schemas/call-site-catalog.ts +21 -7
  342. package/src/config/schemas/heartbeat.ts +1 -1
  343. package/src/config/schemas/llm.ts +102 -2
  344. package/src/config/schemas/memory-v2.ts +272 -0
  345. package/src/config/schemas/memory.ts +2 -1
  346. package/src/config/schemas/services.ts +6 -2
  347. package/src/config/seed-inference-profiles.ts +36 -16
  348. package/src/context/compactor.ts +52 -0
  349. package/src/context/token-estimator.ts +10 -5
  350. package/src/conversations/__tests__/message-consolidation.test.ts +350 -0
  351. package/src/conversations/message-consolidation.ts +404 -0
  352. package/src/credential-execution/executable-discovery.ts +40 -0
  353. package/src/credential-execution/process-manager.ts +6 -2
  354. package/src/credential-health/credential-health-service.ts +125 -40
  355. package/src/daemon/__tests__/conversation-lifecycle-auto-analyze.test.ts +3 -6
  356. package/src/daemon/__tests__/conversation-surfaces-launch.test.ts +13 -15
  357. package/src/daemon/__tests__/conversation-tool-setup-exclude.test.ts +2 -3
  358. package/src/daemon/__tests__/daemon-skill-host.test.ts +2 -0
  359. package/src/daemon/__tests__/meet-manifest-loader.test.ts +25 -12
  360. package/src/daemon/__tests__/native-web-search-metadata.test.ts +1 -0
  361. package/src/daemon/__tests__/switch-inference-profile-tool.test.ts +107 -0
  362. package/src/daemon/__tests__/web-search-status-text.test.ts +1 -0
  363. package/src/daemon/conversation-agent-loop-handlers.ts +390 -80
  364. package/src/daemon/conversation-agent-loop.ts +244 -90
  365. package/src/daemon/conversation-error.ts +64 -6
  366. package/src/daemon/conversation-lifecycle.ts +27 -22
  367. package/src/daemon/conversation-messaging.ts +84 -43
  368. package/src/daemon/conversation-process.ts +74 -37
  369. package/src/daemon/conversation-runtime-assembly.ts +38 -17
  370. package/src/daemon/conversation-skill-tools.ts +14 -30
  371. package/src/daemon/conversation-surfaces.ts +69 -34
  372. package/src/daemon/conversation-tool-setup.ts +77 -32
  373. package/src/daemon/conversation-usage.ts +2 -0
  374. package/src/daemon/conversation.ts +40 -75
  375. package/src/daemon/daemon-control.ts +1 -1
  376. package/src/daemon/daemon-skill-host.ts +9 -2
  377. package/src/daemon/disk-pressure-guard.ts +39 -29
  378. package/src/daemon/first-greeting.ts +31 -13
  379. package/src/daemon/handlers/config-model.test.ts +1 -0
  380. package/src/daemon/handlers/conversations.ts +11 -3
  381. package/src/daemon/handlers/shared.ts +6 -1
  382. package/src/daemon/host-browser-proxy.ts +5 -5
  383. package/src/daemon/host-cu-proxy.ts +4 -4
  384. package/src/daemon/host-file-proxy.ts +4 -4
  385. package/src/daemon/host-proxy-base.ts +4 -4
  386. package/src/daemon/host-transfer-proxy.ts +10 -10
  387. package/src/daemon/lifecycle.ts +29 -26
  388. package/src/daemon/mcp-reload-service.ts +1 -1
  389. package/src/daemon/meet-manifest-loader.ts +11 -24
  390. package/src/daemon/message-types/conversations.ts +22 -27
  391. package/src/daemon/message-types/document-comments.ts +8 -44
  392. package/src/daemon/message-types/home.ts +2 -14
  393. package/src/daemon/message-types/integrations.ts +2 -7
  394. package/src/daemon/message-types/messages.ts +25 -48
  395. package/src/daemon/message-types/subagents.ts +6 -0
  396. package/src/daemon/message-types/sync.ts +14 -0
  397. package/src/daemon/process-message.ts +9 -9
  398. package/src/daemon/providers-setup.ts +1 -1
  399. package/src/daemon/server.ts +16 -0
  400. package/src/daemon/shutdown-handlers.ts +24 -5
  401. package/src/daemon/switch-inference-profile-tool.ts +62 -0
  402. package/src/daemon/tool-setup-types.ts +7 -0
  403. package/src/daemon/wake-target-adapter.ts +10 -0
  404. package/src/documents/document-store.ts +38 -0
  405. package/src/export/__tests__/transcript-formatter.test.ts +1 -0
  406. package/src/heartbeat/__tests__/heartbeat-service.test.ts +30 -1
  407. package/src/heartbeat/heartbeat-service.ts +63 -0
  408. package/src/home/__tests__/feed-writer.test.ts +161 -0
  409. package/src/home/__tests__/post-connect-feed.test.ts +1 -0
  410. package/src/home/__tests__/suggested-prompts.test.ts +55 -59
  411. package/src/home/feed-writer.ts +146 -7
  412. package/src/home/home-greeting.ts +0 -9
  413. package/src/home/suggested-prompts.ts +27 -154
  414. package/src/ipc/__tests__/cli-ipc.test.ts +1 -0
  415. package/src/ipc/gateway-client.test.ts +4 -1
  416. package/src/ipc/gateway-flag-listener.ts +123 -0
  417. package/src/ipc/skill-routes/__tests__/memory.test.ts +1 -0
  418. package/src/ipc/skill-routes/__tests__/registries.test.ts +36 -7
  419. package/src/ipc/skill-routes/memory.ts +4 -3
  420. package/src/ipc/skill-routes/registries.ts +35 -40
  421. package/src/memory/__tests__/db-async-query.test.ts +165 -0
  422. package/src/memory/__tests__/db-maintenance.test.ts +115 -0
  423. package/src/memory/__tests__/jobs-store-enqueue-gate.test.ts +242 -0
  424. package/src/memory/__tests__/jobs-store-job-classes.test.ts +28 -1
  425. package/src/memory/__tests__/jobs-worker-v2-schedule.test.ts +26 -5
  426. package/src/memory/__tests__/memory-retrospective-enqueue.test.ts +1 -0
  427. package/src/memory/__tests__/memory-retrospective-job.test.ts +8 -0
  428. package/src/memory/__tests__/memory-retrospective-startup-cleanup.test.ts +1 -0
  429. package/src/memory/__tests__/memory-v2-activation-log-store.test.ts +31 -0
  430. package/src/memory/auto-analysis-enqueue.ts +5 -1
  431. package/src/memory/conversation-attention-store.ts +17 -3
  432. package/src/memory/conversation-crud.ts +423 -182
  433. package/src/memory/conversation-starters-cadence.ts +3 -1
  434. package/src/memory/conversation-title-service.ts +19 -3
  435. package/src/memory/db-async-query.ts +214 -0
  436. package/src/memory/db-connection.ts +29 -19
  437. package/src/memory/db-init.ts +14 -0
  438. package/src/memory/db-maintenance.ts +30 -21
  439. package/src/memory/db-singleton.ts +77 -0
  440. package/src/memory/delivery-channels.ts +82 -0
  441. package/src/memory/graph/__tests__/conversation-graph-memory-v2-routing.test.ts +2 -4
  442. package/src/memory/graph/bootstrap.ts +8 -1
  443. package/src/memory/graph/capability-seed.ts +7 -3
  444. package/src/memory/graph/conversation-graph-memory.ts +100 -17
  445. package/src/memory/graph/extraction.ts +1 -5
  446. package/src/memory/graph/graph-search.ts +7 -1
  447. package/src/memory/graph/retriever.test.ts +3 -3
  448. package/src/memory/indexer.ts +28 -18
  449. package/src/memory/job-handlers/cleanup.ts +76 -18
  450. package/src/memory/job-handlers/conversation-starters.ts +1 -4
  451. package/src/memory/job-handlers/embedding.test.ts +3 -2
  452. package/src/memory/jobs/__tests__/embed-concept-page.test.ts +5 -2
  453. package/src/memory/jobs/embed-pkb-file.ts +6 -1
  454. package/src/memory/jobs-store.ts +14 -0
  455. package/src/memory/jobs-worker.ts +66 -22
  456. package/src/memory/llm-request-log-source-clickhouse.ts +122 -2
  457. package/src/memory/llm-request-log-source-local.ts +31 -0
  458. package/src/memory/llm-request-log-source.ts +40 -2
  459. package/src/memory/llm-request-log-store.ts +228 -1
  460. package/src/memory/llm-usage-store.ts +24 -0
  461. package/src/memory/memory-retrospective-enqueue.ts +8 -1
  462. package/src/memory/memory-retrospective-job.ts +5 -0
  463. package/src/memory/memory-v2-activation-log-store.ts +110 -7
  464. package/src/memory/migrations/260-rename-cleaned-at.ts +44 -0
  465. package/src/memory/migrations/261-llm-usage-add-raw-usage.ts +36 -0
  466. package/src/memory/migrations/262-memory-v3-coactivation.ts +57 -0
  467. package/src/memory/migrations/263-memory-v3-auto-edges.ts +50 -0
  468. package/src/memory/migrations/264-llm-request-log-call-site.ts +29 -0
  469. package/src/memory/migrations/265-drop-provider-connection-status.ts +26 -0
  470. package/src/memory/migrations/266-messages-client-message-id.ts +43 -0
  471. package/src/memory/migrations/index.ts +19 -0
  472. package/src/memory/migrations/registry.ts +33 -0
  473. package/src/memory/schema/conversations.ts +10 -2
  474. package/src/memory/schema/inference.ts +0 -1
  475. package/src/memory/schema/infrastructure.ts +21 -0
  476. package/src/memory/tool-usage-store.ts +36 -8
  477. package/src/memory/v2/__tests__/backfill-jobs.test.ts +5 -2
  478. package/src/memory/v2/__tests__/consolidation-job.test.ts +1 -0
  479. package/src/memory/v2/__tests__/harness-compare.test.ts +186 -0
  480. package/src/memory/v2/__tests__/harness-metrics.test.ts +83 -0
  481. package/src/memory/v2/__tests__/harness-oracle.test.ts +257 -0
  482. package/src/memory/v2/__tests__/harness-replay-input.test.ts +230 -0
  483. package/src/memory/v2/__tests__/harness-runner.test.ts +135 -0
  484. package/src/memory/v2/__tests__/injection.test.ts +127 -98
  485. package/src/memory/v2/__tests__/qdrant.test.ts +36 -0
  486. package/src/memory/v2/__tests__/router.test.ts +171 -3
  487. package/src/memory/v2/__tests__/sweep-job.test.ts +6 -3
  488. package/src/memory/v2/harness/compare.ts +57 -0
  489. package/src/memory/v2/harness/metrics.ts +128 -0
  490. package/src/memory/v2/harness/oracle.ts +145 -0
  491. package/src/memory/v2/harness/replay-input.ts +240 -0
  492. package/src/memory/v2/harness/retriever.ts +74 -0
  493. package/src/memory/v2/harness/router-retriever.ts +43 -0
  494. package/src/memory/v2/harness/runner.ts +112 -0
  495. package/src/memory/v2/harness/trace.ts +64 -0
  496. package/src/memory/v2/injection.ts +21 -15
  497. package/src/memory/v2/prompts/router.ts +26 -1
  498. package/src/memory/v2/qdrant.ts +14 -2
  499. package/src/memory/v2/router.ts +171 -18
  500. package/src/memory/v3/__tests__/coactivation-store.test.ts +422 -0
  501. package/src/memory/v3/__tests__/consolidation-job.test.ts +466 -0
  502. package/src/memory/v3/__tests__/coretrieval-seed.test.ts +270 -0
  503. package/src/memory/v3/__tests__/edge-learning-job.test.ts +324 -0
  504. package/src/memory/v3/__tests__/edges.test.ts +706 -0
  505. package/src/memory/v3/__tests__/filter.test.ts +560 -0
  506. package/src/memory/v3/__tests__/gate.test.ts +637 -0
  507. package/src/memory/v3/__tests__/index-composition.test.ts +291 -0
  508. package/src/memory/v3/__tests__/loop.test.ts +775 -0
  509. package/src/memory/v3/__tests__/retriever.test.ts +226 -0
  510. package/src/memory/v3/__tests__/scouts.test.ts +489 -0
  511. package/src/memory/v3/__tests__/shadow-diff.test.ts +225 -0
  512. package/src/memory/v3/__tests__/shadow-middleware.test.ts +398 -0
  513. package/src/memory/v3/__tests__/system-prompts.test.ts +154 -0
  514. package/src/memory/v3/__tests__/traversal.test.ts +508 -0
  515. package/src/memory/v3/__tests__/tree-index.test.ts +280 -0
  516. package/src/memory/v3/__tests__/tree-store.test.ts +529 -0
  517. package/src/memory/v3/__tests__/tree-walk.test.ts +784 -0
  518. package/src/memory/v3/__tests__/validate.test.ts +277 -0
  519. package/src/memory/v3/auto-edges.ts +223 -0
  520. package/src/memory/v3/coactivation-store.ts +124 -0
  521. package/src/memory/v3/consolidation-job.ts +323 -0
  522. package/src/memory/v3/coretrieval-seed.ts +240 -0
  523. package/src/memory/v3/edge-learning-job.ts +160 -0
  524. package/src/memory/v3/edges.ts +286 -0
  525. package/src/memory/v3/filter.ts +286 -0
  526. package/src/memory/v3/gate.ts +349 -0
  527. package/src/memory/v3/index-composition.ts +126 -0
  528. package/src/memory/v3/llm-capture.ts +46 -0
  529. package/src/memory/v3/loop.ts +430 -0
  530. package/src/memory/v3/maintenance.ts +144 -0
  531. package/src/memory/v3/prompt-context.ts +33 -0
  532. package/src/memory/v3/prompts/consolidation.ts +458 -0
  533. package/src/memory/v3/prompts/system-prompts.ts +196 -0
  534. package/src/memory/v3/retriever.ts +33 -0
  535. package/src/memory/v3/scouts.ts +431 -0
  536. package/src/memory/v3/shadow-diff.ts +287 -0
  537. package/src/memory/v3/shadow-middleware.ts +347 -0
  538. package/src/memory/v3/traversal.ts +211 -0
  539. package/src/memory/v3/tree-index.ts +237 -0
  540. package/src/memory/v3/tree-store.ts +394 -0
  541. package/src/memory/v3/tree-walk.ts +356 -0
  542. package/src/memory/v3/types.ts +65 -0
  543. package/src/memory/v3/validate.ts +323 -0
  544. package/src/notifications/__tests__/emit-signal-home-feed.test.ts +1 -0
  545. package/src/notifications/__tests__/home-feed-side-effect.test.ts +1 -0
  546. package/src/notifications/adapters/macos.ts +18 -1
  547. package/src/notifications/adapters/platform.ts +1 -1
  548. package/src/notifications/adapters/slack.ts +45 -11
  549. package/src/notifications/broadcaster.ts +114 -63
  550. package/src/notifications/conversation-pairing.ts +23 -3
  551. package/src/notifications/decision-engine.ts +1 -4
  552. package/src/notifications/decisions-store.ts +32 -1
  553. package/src/notifications/deliveries-store.ts +45 -0
  554. package/src/notifications/edit-notification.ts +201 -0
  555. package/src/notifications/emit-signal.ts +40 -50
  556. package/src/notifications/signal.ts +10 -0
  557. package/src/notifications/types.ts +37 -0
  558. package/src/oauth/byo-connection.test.ts +67 -3
  559. package/src/oauth/byo-connection.ts +32 -5
  560. package/src/oauth/connect-orchestrator.ts +9 -0
  561. package/src/oauth/connection-resolver.test.ts +76 -0
  562. package/src/oauth/connection-resolver.ts +49 -10
  563. package/src/oauth/manual-token-connection.ts +51 -3
  564. package/src/oauth/seed-providers.ts +3 -0
  565. package/src/permissions/approval-policy.test.ts +19 -5
  566. package/src/permissions/approval-policy.ts +14 -3
  567. package/src/permissions/checker.ts +21 -8
  568. package/src/permissions/prompter.ts +3 -3
  569. package/src/permissions/question-prompter.ts +5 -2
  570. package/src/permissions/secret-prompter.ts +2 -2
  571. package/src/platform/client.test.ts +24 -1
  572. package/src/platform/client.ts +8 -0
  573. package/src/platform/feature-gate.ts +15 -0
  574. package/src/plugin-api/index.ts +4 -0
  575. package/src/plugin-api/types.ts +7 -33
  576. package/src/plugins/defaults/index.ts +6 -0
  577. package/src/plugins/defaults/injectors.ts +20 -19
  578. package/src/plugins/defaults/persistence.ts +25 -6
  579. package/src/plugins/external-plugin-loader.ts +5 -68
  580. package/src/plugins/types.ts +68 -29
  581. package/src/proactive-artifact/aux-message-injector.ts +17 -4
  582. package/src/proactive-artifact/job.test.ts +1 -0
  583. package/src/prompts/__tests__/system-prompt.test.ts +4 -4
  584. package/src/prompts/__tests__/task-progress-hint-section.test.ts +3 -9
  585. package/src/prompts/persona-resolver.ts +36 -21
  586. package/src/prompts/sections.ts +39 -7
  587. package/src/prompts/system-prompt.ts +84 -221
  588. package/src/prompts/template-detection.ts +10 -4
  589. package/src/prompts/templates/BOOTSTRAP.md +9 -13
  590. package/src/prompts/templates/IDENTITY.md +0 -2
  591. package/src/prompts/templates/system-sections.ts +230 -8
  592. package/src/providers/__tests__/connection-model-compat.test.ts +233 -0
  593. package/src/providers/__tests__/registry-native-web-search.test.ts +122 -0
  594. package/src/providers/__tests__/retry-callsite.test.ts +85 -5
  595. package/src/providers/anthropic/client.ts +32 -66
  596. package/src/providers/call-site-routing.ts +42 -6
  597. package/src/providers/connection-model-compat.ts +61 -0
  598. package/src/providers/connection-resolution.ts +47 -14
  599. package/src/providers/fireworks/client.ts +1 -0
  600. package/src/providers/gemini/client.ts +70 -6
  601. package/src/providers/inference/__tests__/adapter-factory-openai-compatible.test.ts +0 -2
  602. package/src/providers/inference/__tests__/base-url-security.test.ts +2 -3
  603. package/src/providers/inference/__tests__/{connections-status-label.test.ts → connections-label.test.ts} +12 -111
  604. package/src/providers/inference/adapter-factory.ts +3 -0
  605. package/src/providers/inference/auth.ts +0 -8
  606. package/src/providers/inference/connections.ts +3 -66
  607. package/src/providers/inference/resolve-auth.ts +2 -3
  608. package/src/providers/minimax/client.ts +106 -0
  609. package/src/providers/model-catalog.ts +78 -1
  610. package/src/providers/model-intents.ts +4 -4
  611. package/src/providers/openai/__tests__/api-error-detail.test.ts +120 -0
  612. package/src/providers/openai/__tests__/chat-completions-provider-reasoning.test.ts +157 -5
  613. package/src/providers/openai/chat-completions-provider.ts +116 -15
  614. package/src/providers/openai/codex-models.ts +20 -0
  615. package/src/providers/openai/responses-provider.ts +87 -30
  616. package/src/providers/openrouter/client.ts +13 -8
  617. package/src/providers/provider-send-message.ts +20 -5
  618. package/src/providers/registry.ts +48 -8
  619. package/src/providers/retry.ts +50 -7
  620. package/src/providers/search-provider-catalog.ts +17 -9
  621. package/src/providers/thinking-config.ts +26 -1
  622. package/src/providers/types.ts +9 -0
  623. package/src/providers/usage-tracking.ts +2 -0
  624. package/src/runtime/AGENTS.md +2 -2
  625. package/src/runtime/__tests__/agent-wake.test.ts +1 -0
  626. package/src/runtime/__tests__/background-job-runner.test.ts +1 -0
  627. package/src/runtime/access-request-helper.ts +1 -0
  628. package/src/runtime/agent-wake.ts +1 -0
  629. package/src/runtime/assistant-event-hub.ts +76 -6
  630. package/src/runtime/auth/route-policy.ts +46 -0
  631. package/src/runtime/btw-sidechain.ts +0 -6
  632. package/src/runtime/channel-readiness-service.ts +68 -0
  633. package/src/runtime/channel-reply-delivery.ts +23 -0
  634. package/src/runtime/channel-retry-sweep.ts +47 -14
  635. package/src/runtime/confirmation-request-guardian-bridge.ts +1 -1
  636. package/src/runtime/http-types.ts +0 -2
  637. package/src/runtime/migrations/vbundle-builder.ts +12 -4
  638. package/src/runtime/pending-interactions.ts +0 -1
  639. package/src/runtime/routes/__tests__/bookmark-routes.test.ts +1 -0
  640. package/src/runtime/routes/__tests__/conversation-compaction-routes.test.ts +406 -0
  641. package/src/runtime/routes/__tests__/conversation-query-routes.test.ts +204 -0
  642. package/src/runtime/routes/__tests__/heartbeat-routes.test.ts +1 -1
  643. package/src/runtime/routes/__tests__/home-feed-routes.test.ts +209 -1
  644. package/src/runtime/routes/__tests__/inference-provider-connection-routes.test.ts +13 -50
  645. package/src/runtime/routes/__tests__/memory-v2-simulate-route.test.ts +76 -9
  646. package/src/runtime/routes/__tests__/memory-v3-simulate-params.test.ts +35 -0
  647. package/src/runtime/routes/__tests__/plugins-routes.test.ts +512 -0
  648. package/src/runtime/routes/__tests__/slack-channel-routes.test.ts +3 -2
  649. package/src/runtime/routes/__tests__/surface-content-routes.test.ts +294 -0
  650. package/src/runtime/routes/__tests__/task-routes.test.ts +48 -3
  651. package/src/runtime/routes/acp-routes-list.test.ts +3 -0
  652. package/src/runtime/routes/acp-routes.test.ts +255 -6
  653. package/src/runtime/routes/acp-routes.ts +8 -1
  654. package/src/runtime/routes/app-management-routes.ts +111 -4
  655. package/src/runtime/routes/avatar-routes.ts +10 -10
  656. package/src/runtime/routes/background-wake-routes.ts +356 -0
  657. package/src/runtime/routes/browser-tabs-routes.ts +200 -0
  658. package/src/runtime/routes/btw-routes.ts +4 -10
  659. package/src/runtime/routes/conversation-analysis-routes.ts +6 -0
  660. package/src/runtime/routes/conversation-cli-routes.ts +1 -1
  661. package/src/runtime/routes/conversation-compaction-routes.ts +263 -0
  662. package/src/runtime/routes/conversation-list-routes.ts +159 -4
  663. package/src/runtime/routes/conversation-management-routes.ts +108 -26
  664. package/src/runtime/routes/conversation-query-routes.ts +200 -44
  665. package/src/runtime/routes/conversation-routes.ts +409 -521
  666. package/src/runtime/routes/conversation-starter-routes.ts +6 -3
  667. package/src/runtime/routes/conversations-import-routes.ts +19 -6
  668. package/src/runtime/routes/disk-pressure-routes.ts +1 -1
  669. package/src/runtime/routes/documents-routes.ts +10 -1
  670. package/src/runtime/routes/domain-routes.ts +60 -10
  671. package/src/runtime/routes/email-routes.ts +5 -2
  672. package/src/runtime/routes/events-routes.ts +54 -10
  673. package/src/runtime/routes/group-routes.ts +35 -8
  674. package/src/runtime/routes/home-feed-routes.ts +129 -0
  675. package/src/runtime/routes/host-browser-routes.ts +10 -2
  676. package/src/runtime/routes/host-cu-routes.ts +2 -2
  677. package/src/runtime/routes/identity-intro-cache.ts +61 -16
  678. package/src/runtime/routes/identity-routes.ts +30 -9
  679. package/src/runtime/routes/inbound-stages/acl-enforcement.ts +96 -3
  680. package/src/runtime/routes/inbound-stages/background-dispatch.test.ts +530 -6
  681. package/src/runtime/routes/inbound-stages/background-dispatch.ts +57 -8
  682. package/src/runtime/routes/index.ts +10 -0
  683. package/src/runtime/routes/inference-profile-session-handler.ts +22 -12
  684. package/src/runtime/routes/inference-profile-session-routes.ts +7 -1
  685. package/src/runtime/routes/inference-provider-connection-routes.ts +5 -26
  686. package/src/runtime/routes/integrations/vercel.ts +15 -0
  687. package/src/runtime/routes/llm-call-sites-routes.ts +32 -5
  688. package/src/runtime/routes/llm-context-normalization.ts +7 -2
  689. package/src/runtime/routes/memory-item-routes.ts +8 -3
  690. package/src/runtime/routes/memory-v2-routes.ts +215 -5
  691. package/src/runtime/routes/memory-v3-routes.ts +474 -0
  692. package/src/runtime/routes/migration-routes.ts +32 -28
  693. package/src/runtime/routes/notification-routes.ts +63 -1
  694. package/src/runtime/routes/oauth-commands-routes.ts +6 -1
  695. package/src/runtime/routes/plugins-routes.ts +337 -0
  696. package/src/runtime/routes/rename-conversation-routes.ts +6 -2
  697. package/src/runtime/routes/secret-routes.ts +25 -5
  698. package/src/runtime/routes/settings-routes.ts +12 -11
  699. package/src/runtime/routes/slack-channel-routes.ts +5 -4
  700. package/src/runtime/routes/surface-action-routes.ts +1 -38
  701. package/src/runtime/routes/surface-content-routes.ts +12 -5
  702. package/src/runtime/routes/surface-conversation-resolver.ts +65 -0
  703. package/src/runtime/routes/wipe-conversation-routes.ts +3 -0
  704. package/src/runtime/routes/workspace-routes.ts +25 -10
  705. package/src/runtime/services/__tests__/analyze-conversation.test.ts +2 -0
  706. package/src/runtime/slack-dm-text-delivery.ts +177 -0
  707. package/src/runtime/sync/resource-sync-events.ts +106 -38
  708. package/src/runtime/sync/sync-publisher.test.ts +49 -0
  709. package/src/runtime/sync/sync-publisher.ts +2 -1
  710. package/src/runtime/tool-grant-request-helper.ts +1 -0
  711. package/src/runtime/verification-outbound-actions.ts +73 -1
  712. package/src/schedule/schedule-store.ts +8 -1
  713. package/src/schedule/scheduler.ts +111 -15
  714. package/src/security/__tests__/provider-key-env-fallback.test.ts +3 -3
  715. package/src/security/encrypted-store.ts +7 -16
  716. package/src/security/store-path-override.ts +61 -0
  717. package/src/signals/user-message.ts +5 -8
  718. package/src/skills/validate-input.ts +177 -0
  719. package/src/subagent/manager.ts +13 -13
  720. package/src/subagent/types.ts +6 -0
  721. package/src/tasks/tool-sanitizer.ts +2 -2
  722. package/src/telemetry/types.ts +12 -0
  723. package/src/telemetry/usage-telemetry-reporter.test.ts +48 -0
  724. package/src/telemetry/usage-telemetry-reporter.ts +1 -0
  725. package/src/tools/acp/spawn.test.ts +119 -0
  726. package/src/tools/acp/spawn.ts +15 -2
  727. package/src/tools/apps/definitions.ts +36 -28
  728. package/src/tools/ask-question/ask-question-tool.test.ts +3 -3
  729. package/src/tools/ask-question/ask-question-tool.ts +38 -45
  730. package/src/tools/browser/__tests__/browser-execution-acquire.test.ts +2 -8
  731. package/src/tools/browser/__tests__/pinned-tabs.test.ts +70 -0
  732. package/src/tools/browser/browser-execution.ts +16 -3
  733. package/src/tools/browser/cdp-client/__tests__/browser-tabs-factory.test.ts +402 -0
  734. package/src/tools/browser/cdp-client/__tests__/types.test.ts +3 -0
  735. package/src/tools/browser/cdp-client/cdp-inspect-client.ts +12 -0
  736. package/src/tools/browser/cdp-client/extension-cdp-client.ts +27 -1
  737. package/src/tools/browser/cdp-client/factory.ts +100 -17
  738. package/src/tools/browser/cdp-client/local-cdp-client.ts +12 -0
  739. package/src/tools/browser/cdp-client/types.ts +65 -0
  740. package/src/tools/browser/pinned-tabs.ts +96 -40
  741. package/src/tools/computer-use/definitions.ts +282 -336
  742. package/src/tools/credential-execution/make-authenticated-request.ts +3 -9
  743. package/src/tools/credential-execution/manage-secure-command-tool.ts +3 -9
  744. package/src/tools/credential-execution/run-authenticated-command.ts +3 -9
  745. package/src/tools/credentials/vault.ts +3 -9
  746. package/src/tools/document/document-tool.ts +189 -7
  747. package/src/tools/execution-target.ts +18 -23
  748. package/src/tools/executor.ts +24 -56
  749. package/src/tools/filesystem/edit.ts +3 -9
  750. package/src/tools/filesystem/list.ts +3 -9
  751. package/src/tools/filesystem/read.ts +3 -9
  752. package/src/tools/filesystem/write.ts +3 -9
  753. package/src/tools/host-filesystem/edit.test.ts +1 -0
  754. package/src/tools/host-filesystem/edit.ts +3 -9
  755. package/src/tools/host-filesystem/read.test.ts +1 -0
  756. package/src/tools/host-filesystem/read.ts +3 -9
  757. package/src/tools/host-filesystem/transfer.test.ts +31 -6
  758. package/src/tools/host-filesystem/transfer.ts +3 -9
  759. package/src/tools/host-filesystem/write.test.ts +1 -0
  760. package/src/tools/host-filesystem/write.ts +3 -9
  761. package/src/tools/host-terminal/host-shell.ts +3 -9
  762. package/src/tools/mcp/mcp-tool-factory.ts +1 -10
  763. package/src/tools/memory/register.test.ts +1 -1
  764. package/src/tools/memory/register.ts +4 -9
  765. package/src/tools/network/__tests__/managed-search-proxy.test.ts +282 -0
  766. package/src/tools/network/__tests__/web-search.test.ts +211 -3
  767. package/src/tools/network/managed-search-proxy.ts +183 -0
  768. package/src/tools/network/web-fetch.ts +3 -9
  769. package/src/tools/network/web-search.ts +224 -76
  770. package/src/tools/policy-context.ts +3 -1
  771. package/src/tools/registry.ts +150 -123
  772. package/src/tools/schedule/create.ts +1 -1
  773. package/src/tools/schema-transforms.ts +1 -1
  774. package/src/tools/skills/execute.ts +3 -9
  775. package/src/tools/skills/load.ts +3 -9
  776. package/src/tools/skills/skill-tool-factory.ts +18 -44
  777. package/src/tools/subagent/notify-parent.ts +3 -9
  778. package/src/tools/subagent/spawn.ts +3 -0
  779. package/src/tools/system/request-permission.ts +3 -9
  780. package/src/tools/terminal/shell.ts +3 -9
  781. package/src/tools/tool-approval-handler.ts +10 -4
  782. package/src/tools/tool-defaults.ts +94 -0
  783. package/src/tools/tool-name-aliases.ts +72 -14
  784. package/src/tools/types.ts +32 -101
  785. package/src/tools/ui-surface/definitions.ts +104 -108
  786. package/src/types/onboarding-context.ts +6 -0
  787. package/src/usage/attribution.ts +32 -1
  788. package/src/usage/pricing.ts +23 -0
  789. package/src/usage/types.ts +12 -0
  790. package/src/util/browser.ts +7 -2
  791. package/src/util/logger.ts +16 -7
  792. package/src/util/platform.ts +7 -2
  793. package/src/util/sqlite3-runtime.ts +65 -0
  794. package/src/workspace/migrations/086-revert-stale-gemini-mis-rewrites.ts +1 -0
  795. package/src/workspace/migrations/089-move-memory-tree-out-of-v3.ts +86 -0
  796. package/src/workspace/migrations/090-memory-router-cost-optimized-profile.ts +109 -0
  797. package/src/workspace/migrations/091-retighten-migration-onboarding-thread.ts +41 -0
  798. package/src/workspace/migrations/registry.ts +6 -0
  799. package/src/__tests__/compaction-strip-metadata-clear.test.ts +0 -206
  800. package/src/__tests__/message-complete-display-id.test.ts +0 -175
  801. package/src/daemon/query-complexity-router.ts +0 -75
  802. package/src/prompts/cache-boundary.ts +0 -8
@@ -6,9 +6,11 @@
6
6
  *
7
7
  * - Registering a plugin with `tools: Tool[]`, running `bootstrapPlugins`,
8
8
  * and observing the contributed tool via `getAllTools()` / `getTool()`.
9
- * - Tool ownership metadata (`origin: "plugin"`, `ownerPluginId: <plugin>`)
10
- * stamped authoritatively by `registerPluginTools` regardless of what the
11
- * plugin author set on the incoming object.
9
+ * - Tool ownership (`owner: { kind: "plugin", id: <plugin> }`) recorded
10
+ * authoritatively by `registerPluginTools` into the registry's
11
+ * `ownersByName` map (queried via `getToolOwner(name)`), regardless of
12
+ * what the plugin author set on the incoming object. The `Tool` itself
13
+ * carries no ownership field — the bootstrap is the only writer.
12
14
  * - Shutdown hook unregistering the contributed tools so the registry is
13
15
  * clean again after teardown.
14
16
  * - Direct `registerPluginTools` / `unregisterPluginTools` semantics,
@@ -55,11 +57,12 @@ import {
55
57
  getAllTools,
56
58
  getPluginRefCount,
57
59
  getTool,
60
+ getToolOwner,
58
61
  registerPluginTools,
59
62
  unregisterPluginTools,
60
63
  } from "../tools/registry.js";
61
64
  import type {
62
- LoadedPluginTool,
65
+ LoadedTool,
63
66
  ToolContext,
64
67
  ToolExecutionResult,
65
68
  } from "../tools/types.js";
@@ -81,12 +84,13 @@ const fakeCtx: DaemonContext = {
81
84
 
82
85
  function makeFakeTool(
83
86
  name: string,
84
- extras: Partial<LoadedPluginTool> = {},
85
- ): LoadedPluginTool {
87
+ extras: Partial<LoadedTool> = {},
88
+ ): LoadedTool {
86
89
  return {
87
90
  name,
88
91
  description: `Fake ${name}`,
89
92
  defaultRiskLevel: RiskLevel.Low,
93
+ executionTarget: "sandbox",
90
94
  input_schema: { type: "object", properties: {}, required: [] },
91
95
  async execute(
92
96
  _input: Record<string, unknown>,
@@ -163,13 +167,17 @@ describe("plugin tool contributions", () => {
163
167
 
164
168
  const retrieved = getTool("plugin-contrib-tool");
165
169
  expect(retrieved).toBeDefined();
166
- // Ownership metadata must be stamped authoritatively by the bootstrap
167
- // the registry uses it to drive ref-counting and conflict detection when
168
- // the plugin shuts down or is hot-reloaded. Plugin tools live in their
169
- // own `origin: "plugin"` namespace, disjoint from real skills, so a
170
- // plugin name that happens to match a skill id cannot collide.
171
- expect(retrieved?.origin).toBe("plugin");
172
- expect(retrieved?.ownerPluginId).toBe("alpha-contributor");
170
+ // Ownership is recorded authoritatively by the bootstrap into the
171
+ // registry's `ownersByName` map (keyed by tool name, accessed via
172
+ // `getToolOwner(name)`) — the registry uses it to drive ref-counting
173
+ // and conflict detection when the plugin shuts down or is hot-reloaded.
174
+ // Plugin tools live in their own namespace, disjoint from real skills,
175
+ // so a plugin name that happens to match a skill id cannot collide.
176
+ // Ownership is not stamped on the `Tool` object itself.
177
+ expect(getToolOwner("plugin-contrib-tool")).toEqual({
178
+ kind: "plugin",
179
+ id: "alpha-contributor",
180
+ });
173
181
 
174
182
  // The tool surfaces in the global `getAllTools()` snapshot, which is
175
183
  // what downstream consumers (tool-manifest, session projection) read.
@@ -247,22 +255,23 @@ describe("registerPluginTools / unregisterPluginTools helpers", () => {
247
255
  __resetRegistryForTesting();
248
256
  });
249
257
 
250
- test("registerPluginTools stamps category, origin, and ownerPluginId from the plugin name", () => {
251
- // Even if the plugin author hands in a tool with no category or ownership
252
- // metadata, the helper fills it in so the tool can be registered and
253
- // unregistered consistently.
258
+ test("registerPluginTools stamps category and records ownership in the registry", () => {
259
+ // Even if the plugin author hands in a tool with no category, the
260
+ // helper fills it in and records ownership in the registry's
261
+ // `ownersByName` map — the tool itself never carries an `owner` field,
262
+ // so plugin authors can't spoof ownership by forging one.
254
263
  const accepted = registerPluginTools("my-plugin", [
255
264
  makeFakeTool("pt_stamped"),
256
265
  ]);
257
266
  expect(accepted).toHaveLength(1);
258
267
  expect(accepted[0]?.category).toBe("plugin");
259
- expect(accepted[0]?.origin).toBe("plugin");
260
- expect(accepted[0]?.ownerPluginId).toBe("my-plugin");
268
+ expect(getToolOwner("pt_stamped")).toEqual({
269
+ kind: "plugin",
270
+ id: "my-plugin",
271
+ });
261
272
 
262
273
  const retrieved = getTool("pt_stamped");
263
274
  expect(retrieved?.category).toBe("plugin");
264
- expect(retrieved?.origin).toBe("plugin");
265
- expect(retrieved?.ownerPluginId).toBe("my-plugin");
266
275
  });
267
276
 
268
277
  test("registerPluginTools exposes provider-safe aliases for unsafe plugin tool names", async () => {
@@ -281,7 +290,7 @@ describe("registerPluginTools / unregisterPluginTools helpers", () => {
281
290
  expect(alias).toMatch(/^[a-zA-Z0-9_-]{1,64}$/);
282
291
  expect(alias.startsWith("Stripe_Link_CLI__")).toBe(true);
283
292
  expect(getTool(alias)).toBeDefined();
284
- expect(accepted[0]!.getDefinition().name).toBe(alias);
293
+ expect(accepted[0]!.name).toBe(alias);
285
294
 
286
295
  await accepted[0]!.execute(
287
296
  {},
@@ -312,27 +321,28 @@ describe("registerPluginTools / unregisterPluginTools helpers", () => {
312
321
  expect(getTool(paddedAlias!)).toBeDefined();
313
322
  });
314
323
 
315
- test("registerPluginTools overwrites any pre-existing ownership metadata", () => {
324
+ test("registerPluginTools ignores forged ownership fields on the incoming tool", () => {
316
325
  // A plugin author could (maliciously or mistakenly) hand in a tool
317
- // pre-tagged with another skill's or plugin's ID. The helper must
318
- // overwrite it so the bootstrap is always the source of truth for
319
- // ownership and it must clear cross-origin fields (ownerSkillId /
320
- // ownerMcpServerId / ownerSkillBundled / ownerSkillVersionHash) so the
321
- // stamped tool cannot leak across namespaces or spoof bundled-skill
322
- // auto-allow.
323
- const spoofed = makeFakeTool("pt_spoof", {
326
+ // pre-tagged with another skill's or plugin's ID. The `Tool` type now
327
+ // carries no ownership field at all, so any such forgery is purely
328
+ // inert extra data the registry only populates `ownersByName` from
329
+ // the first argument to `register*Tools`, which is the single source
330
+ // of truth for ownership and cannot be spoofed by forging fields on
331
+ // the manifest.
332
+ //
333
+ // Cast through `unknown` to simulate a hostile or transpiled artifact
334
+ // arriving with extra fields baked in.
335
+ const spoofed = {
336
+ ...makeFakeTool("pt_spoof"),
324
337
  origin: "skill",
325
- ownerSkillId: "some-other-skill",
326
- ownerSkillBundled: true,
327
- ownerSkillVersionHash: "deadbeef",
328
- });
338
+ owner: { kind: "skill", id: "some-other-skill" },
339
+ } as unknown as LoadedTool;
329
340
  registerPluginTools("my-plugin", [spoofed]);
330
- const retrieved = getTool("pt_spoof");
331
- expect(retrieved?.origin).toBe("plugin");
332
- expect(retrieved?.ownerPluginId).toBe("my-plugin");
333
- expect(retrieved?.ownerSkillId).toBeUndefined();
334
- expect(retrieved?.ownerSkillBundled).toBeUndefined();
335
- expect(retrieved?.ownerSkillVersionHash).toBeUndefined();
341
+ expect(getTool("pt_spoof")).toBeDefined();
342
+ expect(getToolOwner("pt_spoof")).toEqual({
343
+ kind: "plugin",
344
+ id: "my-plugin",
345
+ });
336
346
  });
337
347
 
338
348
  test("unregisterPluginTools removes the plugin's tools", () => {
@@ -46,7 +46,7 @@ import {
46
46
  type ToolResultTruncateResult,
47
47
  type TurnContext,
48
48
  } from "../plugins/types.js";
49
- import type { LoadedPluginTool } from "../tools/types.js";
49
+ import type { LoadedTool } from "../tools/types.js";
50
50
 
51
51
  const sampleTrust: TrustContext = {
52
52
  sourceChannel: "vellum",
@@ -207,10 +207,11 @@ describe("plugin core types", () => {
207
207
  },
208
208
  };
209
209
 
210
- const sampleTool: LoadedPluginTool = {
210
+ const sampleTool: LoadedTool = {
211
211
  name: "sample-tool",
212
212
  description: "Sample plugin tool",
213
213
  defaultRiskLevel: RiskLevel.Low,
214
+ executionTarget: "sandbox",
214
215
  input_schema: { type: "object", properties: {}, required: [] },
215
216
  async execute() {
216
217
  return { content: "ok", isError: false };
@@ -61,22 +61,43 @@ mock.module("../prompts/user-reference.js", () => ({
61
61
  resolveUserPronouns: () => null,
62
62
  }));
63
63
 
64
- const { buildSystemPrompt, SYSTEM_PROMPT_CACHE_BOUNDARY } =
65
- await import("../prompts/system-prompt.js");
64
+ // Stub persona-resolver so tests can dictate the slug `buildSystemPrompt`
65
+ // sees without writing contact rows to the test DB. User and channel
66
+ // persona content now flows through bundled sections that read files
67
+ // directly, so tests write the persona file under TEST_DIR rather than
68
+ // stubbing the content here.
69
+ const mockPersona: {
70
+ userSlug: string | null;
71
+ guardianPersona: string | null;
72
+ } = { userSlug: null, guardianPersona: null };
73
+ // eslint-disable-next-line @typescript-eslint/no-require-imports
74
+ const realPersonaResolver = require("../prompts/persona-resolver.js");
75
+ mock.module("../prompts/persona-resolver.js", () => ({
76
+ ...realPersonaResolver,
77
+ resolveUserSlug: () => mockPersona.userSlug,
78
+ resolveGuardianPersona: () => mockPersona.guardianPersona,
79
+ }));
80
+
81
+ const { buildSystemPrompt } = await import("../prompts/system-prompt.js");
66
82
 
67
83
  /**
68
- * Extract the dynamic block (workspace-file content) from the full system prompt.
84
+ * Slice the assembled system prompt from the `# First-Run Ritual`
85
+ * marker through the end of the prompt, returning just the
86
+ * `13-bootstrap` section's rendered payload. Returns "" when the
87
+ * section isn't rendered (no BOOTSTRAP.md, `excludeBootstrap: true`,
88
+ * etc.).
69
89
  */
70
- function dynamicBlock(result: string): string {
71
- const boundaryIdx = result.indexOf(SYSTEM_PROMPT_CACHE_BOUNDARY);
72
- return boundaryIdx >= 0
73
- ? result.slice(boundaryIdx + SYSTEM_PROMPT_CACHE_BOUNDARY.length)
74
- : result;
90
+ function bootstrapBlock(result: string): string {
91
+ const ritualIdx = result.indexOf("# First-Run Ritual");
92
+ if (ritualIdx < 0) return "";
93
+ return result.slice(ritualIdx);
75
94
  }
76
95
 
77
96
  describe("pre-chat onboarding contract", () => {
78
97
  beforeEach(() => {
79
98
  mkdirSync(TEST_DIR, { recursive: true });
99
+ mockPersona.userSlug = null;
100
+ mockPersona.guardianPersona = null;
80
101
  });
81
102
 
82
103
  afterEach(() => {
@@ -87,6 +108,8 @@ describe("pre-chat onboarding contract", () => {
87
108
  "BOOTSTRAP.md",
88
109
  "BOOTSTRAP-REFERENCE.md",
89
110
  "UPDATES.md",
111
+ "users",
112
+ "channels",
90
113
  ]) {
91
114
  const p = join(TEST_DIR, name);
92
115
  if (existsSync(p)) rmSync(p, { recursive: true, force: true });
@@ -151,20 +174,20 @@ describe("pre-chat onboarding contract", () => {
151
174
  };
152
175
 
153
176
  const result = buildSystemPrompt({ onboardingContext: context });
154
- const dynamic = dynamicBlock(result);
177
+ const bootstrap = bootstrapBlock(result);
155
178
 
156
- expect(dynamic).toContain("## First-Run User Context");
157
- expect(dynamic).toContain(
179
+ expect(bootstrap).toContain("## First-Run User Context");
180
+ expect(bootstrap).toContain(
158
181
  "The user completed setup before this conversation.",
159
182
  );
160
- expect(dynamic).toContain("- Daily tools: Slack, Linear");
161
- expect(dynamic).toContain("- Common work: builds code, apps, or tools");
162
- expect(dynamic).toContain("- Name: Alex");
163
- expect(dynamic).toContain("- Chosen assistant name: Nova");
164
- expect(dynamic).toContain("Apply this context quietly.");
183
+ expect(bootstrap).toContain("- Daily tools: Slack, Linear");
184
+ expect(bootstrap).toContain("- Common work: builds code, apps, or tools");
185
+ expect(bootstrap).toContain("- Name: Alex");
186
+ expect(bootstrap).toContain("- Chosen assistant name: Nova");
187
+ expect(bootstrap).toContain("Apply this context quietly.");
165
188
 
166
189
  // Raw JSON must NOT be present
167
- expect(dynamic).not.toContain("```json");
190
+ expect(bootstrap).not.toContain("```json");
168
191
  });
169
192
 
170
193
  test("does NOT inject onboarding context when BOOTSTRAP.md does not exist", () => {
@@ -177,11 +200,11 @@ describe("pre-chat onboarding contract", () => {
177
200
  };
178
201
 
179
202
  const result = buildSystemPrompt({ onboardingContext: context });
180
- const dynamic = dynamicBlock(result);
203
+ const bootstrap = bootstrapBlock(result);
181
204
 
182
- expect(dynamic).not.toContain("## First-Run User Context");
183
- expect(dynamic).not.toContain("First-Run User Context");
184
- expect(dynamic).not.toContain("- Daily tools:");
205
+ expect(bootstrap).not.toContain("## First-Run User Context");
206
+ expect(bootstrap).not.toContain("First-Run User Context");
207
+ expect(bootstrap).not.toContain("- Daily tools:");
185
208
  });
186
209
 
187
210
  test("does NOT inject onboarding context when excludeBootstrap is true", () => {
@@ -200,10 +223,10 @@ describe("pre-chat onboarding contract", () => {
200
223
  onboardingContext: context,
201
224
  excludeBootstrap: true,
202
225
  });
203
- const dynamic = dynamicBlock(result);
226
+ const bootstrap = bootstrapBlock(result);
204
227
 
205
- expect(dynamic).not.toContain("## First-Run User Context");
206
- expect(dynamic).not.toContain("First-Run Ritual");
228
+ expect(bootstrap).not.toContain("## First-Run User Context");
229
+ expect(bootstrap).not.toContain("First-Run Ritual");
207
230
  });
208
231
 
209
232
  test("omits onboarding section when context is undefined", () => {
@@ -213,12 +236,12 @@ describe("pre-chat onboarding contract", () => {
213
236
  );
214
237
 
215
238
  const result = buildSystemPrompt({ onboardingContext: undefined });
216
- const dynamic = dynamicBlock(result);
239
+ const bootstrap = bootstrapBlock(result);
217
240
 
218
241
  // Bootstrap should still be present
219
- expect(dynamic).toContain("First-Run Ritual");
242
+ expect(bootstrap).toContain("First-Run Ritual");
220
243
  // But no onboarding context section
221
- expect(dynamic).not.toContain("## First-Run User Context");
244
+ expect(bootstrap).not.toContain("## First-Run User Context");
222
245
  });
223
246
 
224
247
  test("accepts all four personality tones", () => {
@@ -238,10 +261,10 @@ describe("pre-chat onboarding contract", () => {
238
261
  };
239
262
 
240
263
  const result = buildSystemPrompt({ onboardingContext: context });
241
- const dynamic = dynamicBlock(result);
264
+ const bootstrap = bootstrapBlock(result);
242
265
 
243
- expect(dynamic).toContain("## First-Run User Context");
244
- expect(dynamic).toContain(`- Preferred initial voice: ${tone}`);
266
+ expect(bootstrap).toContain("## First-Run User Context");
267
+ expect(bootstrap).toContain(`- Preferred initial voice: ${tone}`);
245
268
  }
246
269
  });
247
270
 
@@ -260,20 +283,20 @@ describe("pre-chat onboarding contract", () => {
260
283
  };
261
284
 
262
285
  const result = buildSystemPrompt({ onboardingContext: context });
263
- const dynamic = dynamicBlock(result);
286
+ const bootstrap = bootstrapBlock(result);
264
287
 
265
288
  // Should contain compact markdown lines
266
- expect(dynamic).toContain("## First-Run User Context");
267
- expect(dynamic).toContain("- Name: Jane");
268
- expect(dynamic).toContain("- Common work: plans and coordinates work");
269
- expect(dynamic).toContain("- Daily tools: Notion");
270
- expect(dynamic).toContain("- Chosen assistant name: Kit");
271
- expect(dynamic).toContain("- Preferred initial voice: warm");
289
+ expect(bootstrap).toContain("## First-Run User Context");
290
+ expect(bootstrap).toContain("- Name: Jane");
291
+ expect(bootstrap).toContain("- Common work: plans and coordinates work");
292
+ expect(bootstrap).toContain("- Daily tools: Notion");
293
+ expect(bootstrap).toContain("- Chosen assistant name: Kit");
294
+ expect(bootstrap).toContain("- Preferred initial voice: warm");
272
295
 
273
296
  // Must NOT contain JSON output
274
- expect(dynamic).not.toContain("```json");
297
+ expect(bootstrap).not.toContain("```json");
275
298
  const expectedJson = JSON.stringify(context, null, 2);
276
- expect(dynamic).not.toContain(expectedJson);
299
+ expect(bootstrap).not.toContain(expectedJson);
277
300
  });
278
301
 
279
302
  test("empty tools/tasks arrays result in no Daily tools / Common work lines", () => {
@@ -290,12 +313,12 @@ describe("pre-chat onboarding contract", () => {
290
313
  };
291
314
 
292
315
  const result = buildSystemPrompt({ onboardingContext: context });
293
- const dynamic = dynamicBlock(result);
316
+ const bootstrap = bootstrapBlock(result);
294
317
 
295
- expect(dynamic).toContain("## First-Run User Context");
296
- expect(dynamic).toContain("- Name: Alex");
297
- expect(dynamic).not.toContain("- Daily tools:");
298
- expect(dynamic).not.toContain("- Common work:");
318
+ expect(bootstrap).toContain("## First-Run User Context");
319
+ expect(bootstrap).toContain("- Name: Alex");
320
+ expect(bootstrap).not.toContain("- Daily tools:");
321
+ expect(bootstrap).not.toContain("- Common work:");
299
322
  });
300
323
 
301
324
  test("absent userName results in no Name line", () => {
@@ -311,16 +334,16 @@ describe("pre-chat onboarding contract", () => {
311
334
  };
312
335
 
313
336
  const result = buildSystemPrompt({ onboardingContext: context });
314
- const dynamic = dynamicBlock(result);
337
+ const bootstrap = bootstrapBlock(result);
315
338
 
316
- expect(dynamic).toContain("## First-Run User Context");
317
- expect(dynamic).not.toContain("- Name:");
339
+ expect(bootstrap).toContain("## First-Run User Context");
340
+ expect(bootstrap).not.toContain("- Name:");
318
341
  // Other fields should still be present
319
- expect(dynamic).toContain("- Daily tools: Slack");
320
- expect(dynamic).toContain(
342
+ expect(bootstrap).toContain("- Daily tools: Slack");
343
+ expect(bootstrap).toContain(
321
344
  "- Common work: writes docs, emails, or content",
322
345
  );
323
- expect(dynamic).toContain("- Preferred initial voice: warm");
346
+ expect(bootstrap).toContain("- Preferred initial voice: warm");
324
347
  });
325
348
  });
326
349
 
@@ -356,26 +379,26 @@ describe("pre-chat onboarding contract", () => {
356
379
  };
357
380
 
358
381
  const result = buildSystemPrompt({ onboardingContext: context });
359
- const dynamic = dynamicBlock(result);
382
+ const bootstrap = bootstrapBlock(result);
360
383
 
361
384
  // Heading is present
362
- expect(dynamic).toContain("## First-Run User Context");
385
+ expect(bootstrap).toContain("## First-Run User Context");
363
386
 
364
387
  // Normalized labels appear (capitalised tool names, human-readable task descriptions)
365
- expect(dynamic).toContain("- Daily tools: Slack, Notion, Linear");
366
- expect(dynamic).toContain("- Name: Alice");
367
- expect(dynamic).toContain("- Chosen assistant name: Pax");
368
- expect(dynamic).toContain("- Preferred initial voice: grounded");
388
+ expect(bootstrap).toContain("- Daily tools: Slack, Notion, Linear");
389
+ expect(bootstrap).toContain("- Name: Alice");
390
+ expect(bootstrap).toContain("- Chosen assistant name: Pax");
391
+ expect(bootstrap).toContain("- Preferred initial voice: grounded");
369
392
  // Common work descriptions are normalised from task IDs
370
- expect(dynamic).toContain("- Common work:");
371
-
372
- // No raw JSON anywhere in the dynamic block
373
- expect(dynamic).not.toContain("```json");
374
- expect(dynamic).not.toContain('"tools"');
375
- expect(dynamic).not.toContain('"tasks"');
376
- expect(dynamic).not.toContain('"tone"');
377
- expect(dynamic).not.toContain('"userName"');
378
- expect(dynamic).not.toContain('"assistantName"');
393
+ expect(bootstrap).toContain("- Common work:");
394
+
395
+ // No raw JSON anywhere in the bootstrap block
396
+ expect(bootstrap).not.toContain("```json");
397
+ expect(bootstrap).not.toContain('"tools"');
398
+ expect(bootstrap).not.toContain('"tasks"');
399
+ expect(bootstrap).not.toContain('"tone"');
400
+ expect(bootstrap).not.toContain('"userName"');
401
+ expect(bootstrap).not.toContain('"assistantName"');
379
402
  });
380
403
 
381
404
  test("without BOOTSTRAP.md, onboarding context does NOT appear in system prompt", () => {
@@ -389,15 +412,15 @@ describe("pre-chat onboarding contract", () => {
389
412
  };
390
413
 
391
414
  const result = buildSystemPrompt({ onboardingContext: context });
392
- const dynamic = dynamicBlock(result);
415
+ const bootstrap = bootstrapBlock(result);
393
416
 
394
417
  // Onboarding section must be absent
395
- expect(dynamic).not.toContain("## First-Run User Context");
396
- expect(dynamic).not.toContain("First-Run Ritual");
397
- expect(dynamic).not.toContain("- Daily tools:");
398
- expect(dynamic).not.toContain("- Name: Bob");
399
- expect(dynamic).not.toContain("- Chosen assistant name:");
400
- expect(dynamic).not.toContain("Apply this context quietly.");
418
+ expect(bootstrap).not.toContain("## First-Run User Context");
419
+ expect(bootstrap).not.toContain("First-Run Ritual");
420
+ expect(bootstrap).not.toContain("- Daily tools:");
421
+ expect(bootstrap).not.toContain("- Name: Bob");
422
+ expect(bootstrap).not.toContain("- Chosen assistant name:");
423
+ expect(bootstrap).not.toContain("Apply this context quietly.");
401
424
  });
402
425
 
403
426
  test("excludeBootstrap suppresses both bootstrap and onboarding sections", () => {
@@ -418,34 +441,38 @@ describe("pre-chat onboarding contract", () => {
418
441
  onboardingContext: context,
419
442
  excludeBootstrap: true,
420
443
  });
421
- const dynamic = dynamicBlock(result);
444
+ const bootstrap = bootstrapBlock(result);
422
445
 
423
446
  // Both bootstrap and onboarding must be suppressed
424
- expect(dynamic).not.toContain("First-Run Ritual");
425
- expect(dynamic).not.toContain("## First-Run User Context");
426
- expect(dynamic).not.toContain("- Daily tools:");
427
- expect(dynamic).not.toContain("- Name: Charlie");
428
- expect(dynamic).not.toContain("Apply this context quietly.");
447
+ expect(bootstrap).not.toContain("First-Run Ritual");
448
+ expect(bootstrap).not.toContain("## First-Run User Context");
449
+ expect(bootstrap).not.toContain("- Daily tools:");
450
+ expect(bootstrap).not.toContain("- Name: Charlie");
451
+ expect(bootstrap).not.toContain("Apply this context quietly.");
429
452
  });
430
453
 
431
454
  test("userPersona is included independently of onboarding context", () => {
432
- // No BOOTSTRAP.md — the durable persona path after bootstrap is deleted
433
- const personaContent =
434
- "# User Persona\n\nPrefers concise answers. Works in fintech.";
455
+ // No BOOTSTRAP.md — the durable persona path after bootstrap is deleted.
456
+ // User persona content now lives in `users/<slug>.md` and renders
457
+ // via the `10-user-persona` bundled section in the static prefix.
458
+ mkdirSync(join(TEST_DIR, "users"), { recursive: true });
459
+ writeFileSync(
460
+ join(TEST_DIR, "users", "default.md"),
461
+ "# User Persona\n\nPrefers concise answers. Works in fintech.",
462
+ );
435
463
 
436
464
  const result = buildSystemPrompt({
437
- userPersona: personaContent,
438
465
  // No onboardingContext — simulates post-onboarding conversation
439
466
  });
440
- const dynamic = dynamicBlock(result);
441
467
 
442
468
  // Persona content appears in prompt even without bootstrap or onboarding
443
- expect(dynamic).toContain("# User Persona");
444
- expect(dynamic).toContain("Prefers concise answers. Works in fintech.");
469
+ expect(result).toContain("# User Persona");
470
+ expect(result).toContain("Prefers concise answers. Works in fintech.");
445
471
 
446
472
  // No onboarding section should be present
447
- expect(dynamic).not.toContain("## First-Run User Context");
448
- expect(dynamic).not.toContain("First-Run Ritual");
473
+ const bootstrap = bootstrapBlock(result);
474
+ expect(bootstrap).not.toContain("## First-Run User Context");
475
+ expect(bootstrap).not.toContain("First-Run Ritual");
449
476
  });
450
477
 
451
478
  test("userPersona appears alongside onboarding context during first run", () => {
@@ -454,8 +481,14 @@ describe("pre-chat onboarding contract", () => {
454
481
  "# Bootstrap\n\nOnboarding flow.",
455
482
  );
456
483
 
457
- const personaContent =
458
- "# User Persona\n\nEarly-stage startup founder. Likes bullet points.";
484
+ // User persona file renders via the `10-user-persona` section
485
+ // and the First-Run Ritual + onboarding context render via the
486
+ // `13-bootstrap` section — both in the static prefix.
487
+ mkdirSync(join(TEST_DIR, "users"), { recursive: true });
488
+ writeFileSync(
489
+ join(TEST_DIR, "users", "default.md"),
490
+ "# User Persona\n\nEarly-stage startup founder. Likes bullet points.",
491
+ );
459
492
  const context: OnboardingContext = {
460
493
  tools: ["slack"],
461
494
  tasks: ["writing"],
@@ -464,17 +497,17 @@ describe("pre-chat onboarding contract", () => {
464
497
  };
465
498
 
466
499
  const result = buildSystemPrompt({
467
- userPersona: personaContent,
468
500
  onboardingContext: context,
469
501
  });
470
- const dynamic = dynamicBlock(result);
471
-
472
- // Both persona and onboarding context appear
473
- expect(dynamic).toContain("# User Persona");
474
- expect(dynamic).toContain("Likes bullet points.");
475
- expect(dynamic).toContain("## First-Run User Context");
476
- expect(dynamic).toContain("- Name: Dana");
477
- expect(dynamic).toContain("- Daily tools: Slack");
502
+ const bootstrap = bootstrapBlock(result);
503
+
504
+ // Both persona and onboarding context appear in the static prefix
505
+ // (`10-user-persona` and `13-bootstrap` respectively)
506
+ expect(result).toContain("# User Persona");
507
+ expect(result).toContain("Likes bullet points.");
508
+ expect(bootstrap).toContain("## First-Run User Context");
509
+ expect(bootstrap).toContain("- Name: Dana");
510
+ expect(bootstrap).toContain("- Daily tools: Slack");
478
511
  });
479
512
  });
480
513
  });
@@ -216,6 +216,17 @@ describe("resolvePricing", () => {
216
216
  expect(result.estimatedCostUsd).toBe(0.25 + 1.5);
217
217
  });
218
218
 
219
+ test("returns priced for gemini-3.1-flash-lite", () => {
220
+ const result = resolvePricing(
221
+ "gemini",
222
+ "gemini-3.1-flash-lite",
223
+ 1_000_000,
224
+ 1_000_000,
225
+ );
226
+ expect(result.pricingStatus).toBe("priced");
227
+ expect(result.estimatedCostUsd).toBe(0.25 + 1.5);
228
+ });
229
+
219
230
  test("prices gemini-2.5-pro at the low-context tier through 200k input tokens", () => {
220
231
  const result = resolvePricing(
221
232
  "gemini",
@@ -489,6 +500,7 @@ describe("resolvePricingForUsage", () => {
489
500
  const cases = [
490
501
  ["gemini-3-flash-preview", 0.05],
491
502
  ["gemini-3.1-flash-lite-preview", 0.025],
503
+ ["gemini-3.1-flash-lite", 0.025],
492
504
  ["gemini-2.5-flash", 0.03],
493
505
  ["gemini-2.5-flash-lite", 0.01],
494
506
  ["gemini-2.5-pro", 0.625],