@vellumai/assistant 0.6.2 → 0.6.4

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 (895) hide show
  1. package/ARCHITECTURE.md +273 -10
  2. package/Dockerfile +2 -3
  3. package/bun.lock +41 -49
  4. package/bunfig.toml +3 -0
  5. package/docs/architecture/memory.md +1 -1
  6. package/docs/backup-troubleshooting.md +52 -0
  7. package/docs/browser-use-architecture-phase2.md +174 -0
  8. package/docs/stt-provider-onboarding.md +120 -0
  9. package/knip.json +12 -2
  10. package/node_modules/@vellumai/ces-contracts/bun.lock +8 -6
  11. package/node_modules/@vellumai/ces-contracts/package.json +3 -3
  12. package/node_modules/@vellumai/ces-contracts/src/rpc.ts +42 -0
  13. package/openapi.yaml +1111 -86
  14. package/package.json +40 -42
  15. package/scripts/generate-openapi.ts +0 -2
  16. package/scripts/test.sh +73 -18
  17. package/src/__tests__/acp-session.test.ts +43 -0
  18. package/src/__tests__/agent-image-optimize.test.ts +28 -0
  19. package/src/__tests__/agent-loop.test.ts +123 -0
  20. package/src/__tests__/anthropic-provider.test.ts +263 -10
  21. package/src/__tests__/app-builder-tool-scripts.test.ts +1 -0
  22. package/src/__tests__/app-executors.test.ts +1 -0
  23. package/src/__tests__/app-source-watcher.test.ts +37 -11
  24. package/src/__tests__/approval-routes-http.test.ts +178 -1
  25. package/src/__tests__/auto-analysis-end-to-end.test.ts +550 -0
  26. package/src/__tests__/auto-analysis-prompt.test.ts +50 -0
  27. package/src/__tests__/browser-fill-credential.test.ts +240 -94
  28. package/src/__tests__/browser-manager.test.ts +40 -27
  29. package/src/__tests__/browser-skill-baseline-tool-payload.test.ts +2 -2
  30. package/src/__tests__/browser-skill-endstate.test.ts +31 -7
  31. package/src/__tests__/btw-routes.test.ts +7 -0
  32. package/src/__tests__/call-controller.test.ts +581 -20
  33. package/src/__tests__/catalog-files.test.ts +1000 -0
  34. package/src/__tests__/channel-approvals.test.ts +53 -0
  35. package/src/__tests__/channel-invite-transport.test.ts +2 -2
  36. package/src/__tests__/channel-readiness-routes.test.ts +16 -20
  37. package/src/__tests__/channel-readiness-service.test.ts +12 -7
  38. package/src/__tests__/checker.test.ts +157 -10
  39. package/src/__tests__/clawhub-files.test.ts +347 -0
  40. package/src/__tests__/commit-message-enrichment-service.test.ts +36 -19
  41. package/src/__tests__/config-analysis.test.ts +100 -0
  42. package/src/__tests__/config-managed-gemini-defaults.test.ts +326 -0
  43. package/src/__tests__/config-schema-cmd.test.ts +2 -2
  44. package/src/__tests__/config-schema.test.ts +1248 -224
  45. package/src/__tests__/config-watcher-cleanup-throttle.test.ts +339 -0
  46. package/src/__tests__/config-watcher.test.ts +43 -8
  47. package/src/__tests__/confirmation-request-guardian-bridge.test.ts +23 -0
  48. package/src/__tests__/contact-store-user-file.test.ts +512 -0
  49. package/src/__tests__/contacts-write.test.ts +197 -0
  50. package/src/__tests__/context-overflow-approval.test.ts +16 -1
  51. package/src/__tests__/context-window-manager.test.ts +88 -0
  52. package/src/__tests__/conversation-abort-tool-results.test.ts +2 -0
  53. package/src/__tests__/conversation-agent-loop-overflow.test.ts +2 -1
  54. package/src/__tests__/conversation-agent-loop.test.ts +99 -3
  55. package/src/__tests__/conversation-analysis-routes.test.ts +2 -2
  56. package/src/__tests__/conversation-attachments.test.ts +80 -4
  57. package/src/__tests__/conversation-confirmation-signals.test.ts +290 -0
  58. package/src/__tests__/conversation-error.test.ts +70 -0
  59. package/src/__tests__/conversation-fork-crud.test.ts +17 -0
  60. package/src/__tests__/conversation-history-web-search.test.ts +12 -4
  61. package/src/__tests__/conversation-host-access-routes.test.ts +229 -0
  62. package/src/__tests__/conversation-init.benchmark.test.ts +6 -1
  63. package/src/__tests__/conversation-inject-context.test.ts +103 -0
  64. package/src/__tests__/conversation-launcher-skill-regression.test.ts +51 -0
  65. package/src/__tests__/conversation-list-source.test.ts +145 -0
  66. package/src/__tests__/conversation-pre-run-repair.test.ts +2 -0
  67. package/src/__tests__/conversation-provider-retry-repair.test.ts +2 -0
  68. package/src/__tests__/conversation-queue.test.ts +946 -62
  69. package/src/__tests__/conversation-routes-disk-view.test.ts +275 -0
  70. package/src/__tests__/conversation-routes-guardian-reply.test.ts +16 -0
  71. package/src/__tests__/conversation-routes-slash-commands.test.ts +1 -0
  72. package/src/__tests__/conversation-runtime-assembly.test.ts +324 -46
  73. package/src/__tests__/conversation-skill-tools.test.ts +7 -4
  74. package/src/__tests__/conversation-slash-commands.test.ts +33 -0
  75. package/src/__tests__/conversation-slash-queue.test.ts +89 -18
  76. package/src/__tests__/conversation-slash-unknown.test.ts +2 -0
  77. package/src/__tests__/conversation-starter-routes.test.ts +126 -0
  78. package/src/__tests__/conversation-starters-cadence.test.ts +161 -0
  79. package/src/__tests__/conversation-store.test.ts +195 -0
  80. package/src/__tests__/conversation-tool-setup-batch-authorized.test.ts +226 -0
  81. package/src/__tests__/conversation-workspace-cache-state.test.ts +193 -0
  82. package/src/__tests__/conversation-workspace-injection.test.ts +2 -0
  83. package/src/__tests__/conversation-workspace-tool-tracking.test.ts +2 -0
  84. package/src/__tests__/credential-execution-approval-bridge.test.ts +32 -1
  85. package/src/__tests__/credential-health-service.test.ts +352 -0
  86. package/src/__tests__/credential-security-invariants.test.ts +6 -3
  87. package/src/__tests__/credential-vault-unit.test.ts +383 -7
  88. package/src/__tests__/credential-vault.test.ts +152 -13
  89. package/src/__tests__/credentials-cli.test.ts +42 -18
  90. package/src/__tests__/cross-provider-web-search.test.ts +146 -35
  91. package/src/__tests__/date-context.test.ts +4 -4
  92. package/src/__tests__/deterministic-verification-control-plane.test.ts +10 -1
  93. package/src/__tests__/device-id.test.ts +112 -0
  94. package/src/__tests__/docker-signing-key-bootstrap.test.ts +167 -4
  95. package/src/__tests__/dynamic-skill-workflow-prompt.test.ts +1 -3
  96. package/src/__tests__/email-html-renderer.test.ts +71 -0
  97. package/src/__tests__/email-invite-adapter.test.ts +36 -32
  98. package/src/__tests__/embedding-managed-proxy-selection.test.ts +256 -0
  99. package/src/__tests__/emit-event-signal.test.ts +71 -0
  100. package/src/__tests__/extension-id-sync-guard.test.ts +222 -0
  101. package/src/__tests__/fixtures/mock-chrome-extension.ts +386 -0
  102. package/src/__tests__/gateway-only-enforcement.test.ts +206 -1
  103. package/src/__tests__/gateway-only-guard.test.ts +2 -0
  104. package/src/__tests__/gemini-provider.test.ts +66 -2
  105. package/src/__tests__/get-skill-detail-audit.test.ts +325 -0
  106. package/src/__tests__/gmail-archive-fallback.test.ts +193 -0
  107. package/src/__tests__/gmail-archive-gate.test.ts +246 -0
  108. package/src/__tests__/gmail-preferences.test.ts +117 -0
  109. package/src/__tests__/guardian-routing-invariants.test.ts +70 -2
  110. package/src/__tests__/headless-browser-interactions.test.ts +738 -359
  111. package/src/__tests__/headless-browser-mode.test.ts +614 -0
  112. package/src/__tests__/headless-browser-navigate.test.ts +528 -49
  113. package/src/__tests__/headless-browser-read-tools.test.ts +274 -100
  114. package/src/__tests__/headless-browser-snapshot.test.ts +250 -77
  115. package/src/__tests__/heartbeat-service.test.ts +70 -17
  116. package/src/__tests__/home-state-routes.test.ts +162 -0
  117. package/src/__tests__/host-bash-proxy.test.ts +145 -1
  118. package/src/__tests__/host-browser-e2e-cloud.test.ts +596 -0
  119. package/src/__tests__/host-browser-e2e-self-hosted-capability.test.ts +286 -0
  120. package/src/__tests__/host-browser-e2e-self-hosted.test.ts +374 -0
  121. package/src/__tests__/host-browser-event-routes.test.ts +350 -0
  122. package/src/__tests__/host-browser-proxy.test.ts +444 -0
  123. package/src/__tests__/host-browser-routes.test.ts +198 -0
  124. package/src/__tests__/host-browser-ws-events-e2e.test.ts +423 -0
  125. package/src/__tests__/host-cu-proxy.test.ts +166 -1
  126. package/src/__tests__/host-file-proxy.test.ts +185 -1
  127. package/src/__tests__/host-file-read-tool.test.ts +52 -0
  128. package/src/__tests__/host-proxy-interface.test.ts +165 -0
  129. package/src/__tests__/host-shell-tool.test.ts +1 -11
  130. package/src/__tests__/http-user-message-parity.test.ts +1 -0
  131. package/src/__tests__/identity-intro-cache.test.ts +40 -10
  132. package/src/__tests__/init-feature-flag-overrides.test.ts +38 -112
  133. package/src/__tests__/integration-status.test.ts +6 -7
  134. package/src/__tests__/jobs-store-upsert-debounced.test.ts +141 -0
  135. package/src/__tests__/list-messages-tool-merge.test.ts +37 -12
  136. package/src/__tests__/llm-context-normalization.test.ts +488 -0
  137. package/src/__tests__/llm-context-route-provider.test.ts +86 -5
  138. package/src/__tests__/llm-usage-store.test.ts +363 -0
  139. package/src/__tests__/mcp-client-auth.test.ts +40 -4
  140. package/src/__tests__/mcp-health-check.test.ts +10 -3
  141. package/src/__tests__/media-stream-output.test.ts +555 -0
  142. package/src/__tests__/media-stream-parser.test.ts +374 -0
  143. package/src/__tests__/media-stream-server-integration.test.ts +1234 -0
  144. package/src/__tests__/media-stream-stt-session.test.ts +588 -0
  145. package/src/__tests__/media-turn-detector.test.ts +440 -0
  146. package/src/__tests__/message-queue.test.ts +125 -0
  147. package/src/__tests__/migration-cross-version-compatibility.test.ts +3 -1
  148. package/src/__tests__/migration-export-http.test.ts +67 -8
  149. package/src/__tests__/migration-export-streaming.test.ts +66 -0
  150. package/src/__tests__/migration-import-commit-http.test.ts +109 -7
  151. package/src/__tests__/migration-import-preflight-http.test.ts +6 -5
  152. package/src/__tests__/migration-validate-http.test.ts +3 -3
  153. package/src/__tests__/mock-gateway-ipc.ts +151 -0
  154. package/src/__tests__/model-intents.test.ts +2 -2
  155. package/src/__tests__/native-host-marker-sync-guard.test.ts +157 -0
  156. package/src/__tests__/oauth-apps-routes.test.ts +18 -12
  157. package/src/__tests__/oauth-cli.test.ts +709 -60
  158. package/src/__tests__/oauth-connect-orchestrator.test.ts +118 -24
  159. package/src/__tests__/oauth-provider-seed-logos.test.ts +23 -0
  160. package/src/__tests__/oauth-provider-serializer.test.ts +147 -10
  161. package/src/__tests__/oauth-provider-visibility.test.ts +19 -21
  162. package/src/__tests__/oauth-providers-routes.test.ts +52 -14
  163. package/src/__tests__/oauth-store.test.ts +1465 -176
  164. package/src/__tests__/oauth2-gateway-transport.test.ts +460 -26
  165. package/src/__tests__/onboarding-template-contract.test.ts +81 -70
  166. package/src/__tests__/openai-provider.test.ts +178 -2
  167. package/src/__tests__/openai-responses-cutover-guard.test.ts +184 -0
  168. package/src/__tests__/openai-responses-provider.test.ts +1105 -0
  169. package/src/__tests__/openrouter-token-estimation.test.ts +100 -0
  170. package/src/__tests__/outlook-categories.test.ts +1 -1
  171. package/src/__tests__/outlook-client-automation.test.ts +1 -1
  172. package/src/__tests__/outlook-compose-tools.test.ts +1 -1
  173. package/src/__tests__/outlook-email-watcher.test.ts +1 -1
  174. package/src/__tests__/outlook-follow-up.test.ts +1 -1
  175. package/src/__tests__/outlook-messaging-provider.test.ts +2 -2
  176. package/src/__tests__/outlook-trash.test.ts +1 -1
  177. package/src/__tests__/outlook-unsubscribe.test.ts +32 -3
  178. package/src/__tests__/permission-checker-host-gate.test.ts +74 -14
  179. package/src/__tests__/permission-mode.test.ts +28 -56
  180. package/src/__tests__/persona-resolver.test.ts +251 -0
  181. package/src/__tests__/platform-bash-auto-approve.test.ts +4 -0
  182. package/src/__tests__/platform-callback-registration.test.ts +19 -0
  183. package/src/__tests__/platform.test.ts +92 -1
  184. package/src/__tests__/post-turn-tool-result-truncation.test.ts +343 -0
  185. package/src/__tests__/prechat-onboarding-contract.test.ts +267 -0
  186. package/src/__tests__/pricing.test.ts +174 -0
  187. package/src/__tests__/proxy-approval-callback.test.ts +18 -0
  188. package/src/__tests__/qdrant-manager.test.ts +29 -8
  189. package/src/__tests__/regenerate-fire-and-forget-trace.test.ts +194 -0
  190. package/src/__tests__/relationship-state-contract.test.ts +175 -0
  191. package/src/__tests__/relay-server.test.ts +423 -5
  192. package/src/__tests__/require-fresh-approval.test.ts +40 -1
  193. package/src/__tests__/sanitize-config-for-transfer.test.ts +132 -0
  194. package/src/__tests__/schedule-routes.test.ts +162 -0
  195. package/src/__tests__/search-skills-unified.test.ts +118 -0
  196. package/src/__tests__/secret-detection-handler.test.ts +84 -0
  197. package/src/__tests__/secret-ingress-http.test.ts +1 -0
  198. package/src/__tests__/secret-scanner-executor.test.ts +4 -0
  199. package/src/__tests__/secure-keys.test.ts +107 -0
  200. package/src/__tests__/send-endpoint-busy.test.ts +8 -1
  201. package/src/__tests__/sequence-store.test.ts +1 -1
  202. package/src/__tests__/server-history-render.test.ts +49 -0
  203. package/src/__tests__/set-permission-mode.test.ts +13 -250
  204. package/src/__tests__/settings-routes.test.ts +201 -0
  205. package/src/__tests__/skill-load-feature-flag.test.ts +1 -0
  206. package/src/__tests__/skills-file-content-endpoint.test.ts +801 -0
  207. package/src/__tests__/skills-files-catalog-fallback.test.ts +738 -0
  208. package/src/__tests__/skills.test.ts +5 -2
  209. package/src/__tests__/skillssh-files.test.ts +446 -0
  210. package/src/__tests__/slack-block-formatting.test.ts +110 -0
  211. package/src/__tests__/slack-channel-config.test.ts +576 -16
  212. package/src/__tests__/stt-catalog-parity.test.ts +282 -0
  213. package/src/__tests__/stt-stream-session.test.ts +535 -0
  214. package/src/__tests__/subagent-detail.test.ts +44 -2
  215. package/src/__tests__/subagent-disposal.test.ts +1 -0
  216. package/src/__tests__/subagent-fork-notifications.test.ts +291 -0
  217. package/src/__tests__/subagent-fork-spawn.test.ts +384 -0
  218. package/src/__tests__/subagent-manager-notify.test.ts +1 -0
  219. package/src/__tests__/subagent-notify-parent.test.ts +1 -0
  220. package/src/__tests__/subagent-spawn-tool-fork.test.ts +411 -0
  221. package/src/__tests__/subagent-tools.test.ts +1 -0
  222. package/src/__tests__/subagent-types.test.ts +1 -0
  223. package/src/__tests__/system-prompt-ask-mode.test.ts +27 -71
  224. package/src/__tests__/system-prompt.test.ts +184 -27
  225. package/src/__tests__/task-scheduler.test.ts +32 -6
  226. package/src/__tests__/telegram-config.test.ts +10 -13
  227. package/src/__tests__/telephony-stt-routing.test.ts +329 -0
  228. package/src/__tests__/terminal-tools.test.ts +25 -5
  229. package/src/__tests__/test-preload.ts +18 -0
  230. package/src/__tests__/test-support/browser-skill-harness.ts +4 -1
  231. package/src/__tests__/tool-approval-handler.test.ts +73 -0
  232. package/src/__tests__/tool-executor-lifecycle-events.test.ts +9 -5
  233. package/src/__tests__/tool-executor-shell-integration.test.ts +4 -0
  234. package/src/__tests__/tool-executor.test.ts +33 -24
  235. package/src/__tests__/tool-result-truncation.test.ts +36 -0
  236. package/src/__tests__/tool-side-effects-slack-dm.test.ts +22 -0
  237. package/src/__tests__/top-level-renderer.test.ts +73 -1
  238. package/src/__tests__/transport-hints-queue.test.ts +14 -29
  239. package/src/__tests__/trust-store.test.ts +7 -1
  240. package/src/__tests__/trusted-contact-approval-notifier.test.ts +1 -1
  241. package/src/__tests__/trusted-contact-inline-approval-integration.test.ts +109 -0
  242. package/src/__tests__/tts-catalog-parity.test.ts +345 -0
  243. package/src/__tests__/twilio-routes-twiml.test.ts +512 -114
  244. package/src/__tests__/twilio-routes.test.ts +376 -0
  245. package/src/__tests__/unicode.test.ts +293 -0
  246. package/src/__tests__/update-bulletin-format.test.ts +59 -0
  247. package/src/__tests__/update-bulletin.test.ts +206 -5
  248. package/src/__tests__/usage-routes.test.ts +25 -4
  249. package/src/__tests__/user-reference.test.ts +46 -61
  250. package/src/__tests__/v2-consent-policy.test.ts +103 -0
  251. package/src/__tests__/verification-control-plane-policy.test.ts +4 -0
  252. package/src/__tests__/voice-config-update.test.ts +403 -0
  253. package/src/__tests__/voice-quality.test.ts +434 -19
  254. package/src/__tests__/workspace-heartbeat-service.test.ts +7 -0
  255. package/src/__tests__/workspace-migration-033-stt-service-explicit-config.test.ts +547 -0
  256. package/src/__tests__/workspace-migration-034-remove-calls-voice-transcription-provider.test.ts +596 -0
  257. package/src/__tests__/workspace-migration-drop-user-md.test.ts +368 -0
  258. package/src/__tests__/workspace-migration-meets.test.ts +244 -0
  259. package/src/__tests__/workspace-migration-seed-device-id.test.ts +14 -20
  260. package/src/__tests__/workspace-policy.test.ts +2 -0
  261. package/src/acp/client-handler.ts +30 -4
  262. package/src/agent/image-optimize.ts +24 -12
  263. package/src/agent/loop.ts +55 -9
  264. package/src/approvals/guardian-request-resolvers.ts +21 -15
  265. package/src/backup/__tests__/backup-key.test.ts +152 -0
  266. package/src/backup/__tests__/backup-worker.test.ts +767 -0
  267. package/src/backup/__tests__/list-snapshots.test.ts +87 -0
  268. package/src/backup/__tests__/local-writer.test.ts +218 -0
  269. package/src/backup/__tests__/offsite-writer.test.ts +641 -0
  270. package/src/backup/__tests__/paths.test.ts +300 -0
  271. package/src/backup/__tests__/restore.test.ts +498 -0
  272. package/src/backup/__tests__/snapshot-lock.test.ts +352 -0
  273. package/src/backup/__tests__/stream-crypt.test.ts +228 -0
  274. package/src/backup/backup-key.ts +137 -0
  275. package/src/backup/backup-worker.ts +459 -0
  276. package/src/backup/list-snapshots.ts +147 -0
  277. package/src/backup/local-writer.ts +133 -0
  278. package/src/backup/offsite-writer.ts +222 -0
  279. package/src/backup/paths.ts +226 -0
  280. package/src/backup/restore.ts +322 -0
  281. package/src/backup/snapshot-lock.ts +431 -0
  282. package/src/backup/stream-crypt.ts +263 -0
  283. package/src/browser-session/__tests__/manager.test.ts +297 -0
  284. package/src/browser-session/backends/cdp-inspect.ts +30 -0
  285. package/src/browser-session/backends/extension.ts +26 -0
  286. package/src/browser-session/backends/local.ts +24 -0
  287. package/src/browser-session/events.ts +164 -0
  288. package/src/browser-session/index.ts +27 -0
  289. package/src/browser-session/manager.ts +159 -0
  290. package/src/browser-session/types.ts +28 -0
  291. package/src/bundler/package-resolver.ts +4 -0
  292. package/src/calls/audio-store.ts +11 -5
  293. package/src/calls/call-controller.ts +226 -71
  294. package/src/calls/call-domain.ts +9 -0
  295. package/src/calls/call-speech-output.ts +190 -0
  296. package/src/calls/call-transport.ts +77 -0
  297. package/src/calls/media-stream-audio-transcode.ts +173 -0
  298. package/src/calls/media-stream-output.ts +660 -0
  299. package/src/calls/media-stream-parser.ts +300 -0
  300. package/src/calls/media-stream-protocol.ts +166 -0
  301. package/src/calls/media-stream-server.ts +592 -0
  302. package/src/calls/media-stream-stt-session.ts +460 -0
  303. package/src/calls/media-turn-detector.ts +230 -0
  304. package/src/calls/relay-server.ts +90 -75
  305. package/src/calls/resolve-call-tts-provider.ts +136 -0
  306. package/src/calls/telephony-stt-routing.ts +145 -0
  307. package/src/calls/tts-call-strategy.ts +161 -0
  308. package/src/calls/tts-text-sanitizer.ts +32 -16
  309. package/src/calls/twilio-routes.ts +281 -17
  310. package/src/calls/voice-quality.ts +78 -35
  311. package/src/calls/voice-session-bridge.ts +8 -1
  312. package/src/channels/__tests__/types.test.ts +134 -0
  313. package/src/channels/types.ts +69 -3
  314. package/src/cli/__tests__/run-assistant-command.ts +11 -1
  315. package/src/cli/commands/__tests__/backup.test.ts +1165 -0
  316. package/src/cli/commands/__tests__/domain-register.test.ts +234 -0
  317. package/src/cli/commands/__tests__/domain-status.test.ts +132 -0
  318. package/src/cli/commands/__tests__/email-attachment.test.ts +422 -0
  319. package/src/cli/commands/__tests__/email-download.test.ts +16 -1
  320. package/src/cli/commands/__tests__/email-list.test.ts +22 -4
  321. package/src/cli/commands/__tests__/email-register.test.ts +4 -4
  322. package/src/cli/commands/__tests__/email-send.test.ts +37 -4
  323. package/src/cli/commands/__tests__/email-status.test.ts +5 -1
  324. package/src/cli/commands/__tests__/email-unregister.test.ts +34 -5
  325. package/src/cli/commands/backup.ts +993 -0
  326. package/src/cli/commands/conversations.ts +77 -0
  327. package/src/cli/commands/credentials.ts +3 -4
  328. package/src/cli/commands/domain.ts +210 -0
  329. package/src/cli/commands/email.ts +273 -16
  330. package/src/cli/commands/mcp.ts +16 -4
  331. package/src/cli/commands/oauth/__tests__/connect.test.ts +56 -44
  332. package/src/cli/commands/oauth/__tests__/disconnect.test.ts +21 -21
  333. package/src/cli/commands/oauth/__tests__/mode.test.ts +17 -17
  334. package/src/cli/commands/oauth/__tests__/ping.test.ts +16 -16
  335. package/src/cli/commands/oauth/__tests__/providers-delete.test.ts +32 -33
  336. package/src/cli/commands/oauth/__tests__/providers-register.test.ts +330 -0
  337. package/src/cli/commands/oauth/__tests__/providers-update.test.ts +117 -12
  338. package/src/cli/commands/oauth/__tests__/status.test.ts +10 -10
  339. package/src/cli/commands/oauth/__tests__/token.test.ts +7 -7
  340. package/src/cli/commands/oauth/apps.ts +7 -4
  341. package/src/cli/commands/oauth/connect.ts +6 -3
  342. package/src/cli/commands/oauth/disconnect.ts +1 -1
  343. package/src/cli/commands/oauth/mode.ts +12 -3
  344. package/src/cli/commands/oauth/providers.ts +215 -36
  345. package/src/cli/commands/oauth/shared.ts +7 -6
  346. package/src/cli/commands/platform/__tests__/callback-routes-list.test.ts +254 -0
  347. package/src/cli/commands/platform/__tests__/connect.test.ts +6 -0
  348. package/src/cli/commands/platform/__tests__/disconnect.test.ts +7 -1
  349. package/src/cli/commands/platform/__tests__/status.test.ts +6 -0
  350. package/src/cli/commands/platform/index.ts +107 -10
  351. package/src/cli/commands/usage.ts +10 -9
  352. package/src/cli/lib/daemon-credential-client.ts +4 -0
  353. package/src/cli/program.ts +30 -4
  354. package/src/config/__tests__/backup-schema.test.ts +134 -0
  355. package/src/config/assistant-feature-flags.ts +61 -62
  356. package/src/config/bundled-skills/app-builder/SKILL.md +26 -249
  357. package/src/config/bundled-skills/app-builder/references/CUSTOM_ROUTES.md +141 -0
  358. package/src/config/bundled-skills/app-builder/references/INTERACTION_HOOKS.md +56 -0
  359. package/src/config/bundled-skills/app-builder/references/WIDGETS.md +125 -0
  360. package/src/config/bundled-skills/browser/SKILL.md +30 -5
  361. package/src/config/bundled-skills/browser/TOOLS.json +123 -0
  362. package/src/config/bundled-skills/browser/tools/browser-attach.ts +12 -0
  363. package/src/config/bundled-skills/browser/tools/browser-detach.ts +12 -0
  364. package/src/config/bundled-skills/browser/tools/browser-status.ts +12 -0
  365. package/src/config/bundled-skills/browser/tools/browser-wait-for-download.ts +17 -0
  366. package/src/config/bundled-skills/contacts/SKILL.md +5 -2
  367. package/src/config/bundled-skills/document/SKILL.md +4 -0
  368. package/src/config/bundled-skills/gmail/SKILL.md +54 -8
  369. package/src/config/bundled-skills/gmail/TOOLS.json +33 -3
  370. package/src/config/bundled-skills/gmail/tools/gmail-archive.ts +116 -9
  371. package/src/config/bundled-skills/gmail/tools/gmail-outreach-scan.ts +138 -11
  372. package/src/config/bundled-skills/gmail/tools/gmail-preferences-tool.ts +59 -0
  373. package/src/config/bundled-skills/gmail/tools/gmail-preferences.ts +82 -0
  374. package/src/config/bundled-skills/gmail/tools/gmail-sender-digest.ts +113 -17
  375. package/src/config/bundled-skills/gmail/tools/gmail-unsubscribe.ts +2 -2
  376. package/src/config/bundled-skills/media-processing/SKILL.md +3 -9
  377. package/src/config/bundled-skills/media-processing/TOOLS.json +1 -6
  378. package/src/config/bundled-skills/media-processing/__tests__/audio-transcribe.test.ts +125 -0
  379. package/src/config/bundled-skills/media-processing/__tests__/extract-keyframes.test.ts +181 -0
  380. package/src/config/bundled-skills/media-processing/__tests__/preprocess-audio.test.ts +141 -0
  381. package/src/config/bundled-skills/media-processing/services/audio-transcribe.ts +32 -87
  382. package/src/config/bundled-skills/media-processing/services/preprocess.ts +8 -4
  383. package/src/config/bundled-skills/media-processing/tools/extract-keyframes.ts +0 -10
  384. package/src/config/bundled-skills/messaging/SKILL.md +3 -3
  385. package/src/config/bundled-skills/messaging/tools/messaging-archive-by-sender.ts +2 -2
  386. package/src/config/bundled-skills/outlook/SKILL.md +9 -2
  387. package/src/config/bundled-skills/outlook/tools/outlook-unsubscribe.ts +2 -2
  388. package/src/config/bundled-skills/phone-calls/SKILL.md +2 -2
  389. package/src/config/bundled-skills/phone-calls/references/CONFIG.md +27 -18
  390. package/src/config/bundled-skills/phone-calls/references/TROUBLESHOOTING.md +3 -3
  391. package/src/config/bundled-skills/settings/TOOLS.json +3 -3
  392. package/src/config/bundled-skills/settings/tools/voice-config-update.ts +26 -22
  393. package/src/config/bundled-skills/slack/SKILL.md +1 -0
  394. package/src/config/bundled-skills/subagent/SKILL.md +21 -0
  395. package/src/config/bundled-skills/subagent/TOOLS.json +8 -4
  396. package/src/config/bundled-skills/tasks/SKILL.md +5 -0
  397. package/src/config/bundled-skills/transcribe/SKILL.md +9 -14
  398. package/src/config/bundled-skills/transcribe/TOOLS.json +2 -7
  399. package/src/config/bundled-skills/transcribe/tools/transcribe-media.test.ts +256 -0
  400. package/src/config/bundled-skills/transcribe/tools/transcribe-media.ts +38 -188
  401. package/src/config/bundled-tool-registry.ts +8 -0
  402. package/src/config/env-registry.ts +38 -0
  403. package/src/config/env.ts +49 -4
  404. package/src/config/feature-flag-registry.json +85 -14
  405. package/src/config/loader.ts +82 -13
  406. package/src/config/sanitize-for-transfer.ts +47 -0
  407. package/src/config/schema.ts +81 -15
  408. package/src/config/schemas/__tests__/stt.test.ts +43 -0
  409. package/src/config/schemas/analysis.ts +51 -0
  410. package/src/config/schemas/backup.ts +72 -0
  411. package/src/config/schemas/calls.ts +1 -26
  412. package/src/config/schemas/elevenlabs.ts +0 -59
  413. package/src/config/schemas/filing.ts +47 -7
  414. package/src/config/schemas/heartbeat.ts +27 -5
  415. package/src/config/schemas/host-browser.ts +112 -0
  416. package/src/config/schemas/inference.ts +1 -1
  417. package/src/config/schemas/memory-lifecycle.ts +14 -2
  418. package/src/config/schemas/memory-retrieval.ts +103 -0
  419. package/src/config/schemas/security.ts +0 -6
  420. package/src/config/schemas/services.ts +52 -0
  421. package/src/config/schemas/stt.ts +59 -0
  422. package/src/config/schemas/tts.ts +230 -0
  423. package/src/config/schemas/updates.ts +14 -0
  424. package/src/config/skills.ts +4 -0
  425. package/src/config/types.ts +4 -1
  426. package/src/contacts/contact-store.ts +56 -11
  427. package/src/contacts/contacts-write.ts +38 -1
  428. package/src/context/post-turn-tool-result-truncation.ts +177 -0
  429. package/src/context/tool-result-truncation.ts +2 -1
  430. package/src/context/window-manager.ts +61 -10
  431. package/src/credential-execution/approval-bridge.ts +49 -15
  432. package/src/credential-execution/executable-discovery.ts +12 -2
  433. package/src/credential-execution/process-manager.ts +33 -2
  434. package/src/credential-health/credential-health-service.ts +366 -0
  435. package/src/daemon/__tests__/conversation-lifecycle-auto-analyze.test.ts +324 -0
  436. package/src/daemon/__tests__/conversation-surfaces-launch.test.ts +497 -0
  437. package/src/daemon/__tests__/conversation-tool-setup.test.ts +195 -0
  438. package/src/daemon/__tests__/lifecycle-startup-ordering.test.ts +127 -0
  439. package/src/daemon/app-source-watcher.ts +35 -0
  440. package/src/daemon/config-watcher.ts +99 -5
  441. package/src/daemon/context-overflow-approval.ts +5 -0
  442. package/src/daemon/conversation-agent-loop-handlers.ts +23 -2
  443. package/src/daemon/conversation-agent-loop.ts +153 -42
  444. package/src/daemon/conversation-attachments.ts +40 -0
  445. package/src/daemon/conversation-error.ts +11 -0
  446. package/src/daemon/conversation-history.ts +40 -6
  447. package/src/daemon/conversation-launch.ts +220 -0
  448. package/src/daemon/conversation-lifecycle.ts +59 -9
  449. package/src/daemon/conversation-messaging.ts +37 -3
  450. package/src/daemon/conversation-notifiers.ts +5 -0
  451. package/src/daemon/conversation-process.ts +622 -13
  452. package/src/daemon/conversation-queue-manager.ts +24 -0
  453. package/src/daemon/conversation-runtime-assembly.ts +128 -36
  454. package/src/daemon/conversation-slash.ts +36 -0
  455. package/src/daemon/conversation-surfaces.ts +131 -40
  456. package/src/daemon/conversation-tool-setup.ts +99 -8
  457. package/src/daemon/conversation-usage.ts +7 -4
  458. package/src/daemon/conversation-workspace.ts +12 -0
  459. package/src/daemon/conversation.ts +292 -16
  460. package/src/daemon/date-context.ts +10 -10
  461. package/src/daemon/first-greeting.ts +3 -2
  462. package/src/daemon/handlers/config-slack-channel.ts +269 -94
  463. package/src/daemon/handlers/conversations.ts +13 -141
  464. package/src/daemon/handlers/shared.ts +80 -0
  465. package/src/daemon/handlers/skills.ts +483 -44
  466. package/src/daemon/host-bash-proxy.ts +48 -13
  467. package/src/daemon/host-browser-proxy.ts +192 -0
  468. package/src/daemon/host-cu-proxy.ts +36 -11
  469. package/src/daemon/host-file-proxy.ts +57 -9
  470. package/src/daemon/lifecycle.ts +179 -28
  471. package/src/daemon/message-protocol.ts +13 -0
  472. package/src/daemon/message-types/conversations.ts +89 -14
  473. package/src/daemon/message-types/home.ts +40 -0
  474. package/src/daemon/message-types/host-browser.ts +100 -0
  475. package/src/daemon/message-types/meet.ts +143 -0
  476. package/src/daemon/message-types/messages.ts +19 -5
  477. package/src/daemon/message-types/schedules.ts +34 -2
  478. package/src/daemon/message-types/skills.ts +26 -0
  479. package/src/daemon/message-types/subagents.ts +2 -0
  480. package/src/daemon/message-types/surfaces.ts +2 -0
  481. package/src/daemon/server.ts +439 -14
  482. package/src/daemon/shutdown-handlers.ts +32 -4
  483. package/src/daemon/shutdown-registry.ts +40 -0
  484. package/src/daemon/tool-side-effects.ts +15 -0
  485. package/src/daemon/transport-hints.ts +5 -24
  486. package/src/email/html-renderer.ts +76 -0
  487. package/src/heartbeat/heartbeat-service.ts +93 -7
  488. package/src/home/__tests__/assistant-feed-authoring.test.ts +156 -0
  489. package/src/home/__tests__/emit-feed-event.test.ts +169 -0
  490. package/src/home/__tests__/feed-scheduler.test.ts +194 -0
  491. package/src/home/__tests__/feed-types.test.ts +275 -0
  492. package/src/home/__tests__/feed-writer.test.ts +688 -0
  493. package/src/home/__tests__/phase5-exit-criteria.test.ts +212 -0
  494. package/src/home/__tests__/platform-gmail-digest.test.ts +222 -0
  495. package/src/home/__tests__/progress-formula.test.ts +213 -0
  496. package/src/home/__tests__/relationship-state-writer.test.ts +740 -0
  497. package/src/home/__tests__/rollup-producer.test.ts +398 -0
  498. package/src/home/assistant-feed-authoring.ts +124 -0
  499. package/src/home/emit-feed-event.ts +158 -0
  500. package/src/home/feed-scheduler.ts +247 -0
  501. package/src/home/feed-types.ts +181 -0
  502. package/src/home/feed-writer.ts +469 -0
  503. package/src/home/platform-gmail-digest.ts +163 -0
  504. package/src/home/progress-formula.ts +86 -0
  505. package/src/home/relationship-state-writer.ts +824 -0
  506. package/src/home/relationship-state.ts +143 -0
  507. package/src/home/rollup-producer.ts +384 -0
  508. package/src/hooks/runner.ts +7 -0
  509. package/src/inbound/platform-callback-registration.ts +30 -20
  510. package/src/inbound/public-ingress-urls.ts +12 -0
  511. package/src/instrument.ts +1 -1
  512. package/src/ipc/__tests__/cli-ipc.test.ts +200 -0
  513. package/src/ipc/cli-client.ts +151 -0
  514. package/src/ipc/cli-server.ts +234 -0
  515. package/src/ipc/gateway-client.ts +180 -0
  516. package/src/ipc/routes/index.ts +5 -0
  517. package/src/ipc/routes/wake-conversation.ts +19 -0
  518. package/src/mcp/client.ts +59 -24
  519. package/src/memory/__tests__/auto-analysis-enqueue.test.ts +356 -0
  520. package/src/memory/__tests__/auto-analysis-guard.test.ts +57 -0
  521. package/src/memory/__tests__/conversation-analyze-job.test.ts +232 -0
  522. package/src/memory/__tests__/find-analysis-conversation.test.ts +196 -0
  523. package/src/memory/app-store.ts +31 -1
  524. package/src/memory/attachments-store.ts +70 -0
  525. package/src/memory/auto-analysis-enqueue.ts +127 -0
  526. package/src/memory/auto-analysis-guard.ts +27 -0
  527. package/src/memory/cleanup-schedule-state.ts +37 -0
  528. package/src/memory/conversation-analyze-job.ts +73 -0
  529. package/src/memory/conversation-crud.ts +122 -0
  530. package/src/memory/conversation-disk-view.ts +7 -0
  531. package/src/memory/conversation-group-migration.ts +34 -2
  532. package/src/memory/conversation-queries.ts +6 -5
  533. package/src/memory/conversation-starters-cadence.ts +76 -0
  534. package/src/memory/conversation-title-service.ts +5 -2
  535. package/src/memory/db-init.ts +18 -0
  536. package/src/memory/db-maintenance.ts +108 -0
  537. package/src/memory/db.ts +1 -0
  538. package/src/memory/embedding-backend.test.ts +75 -0
  539. package/src/memory/embedding-backend.ts +131 -5
  540. package/src/memory/embedding-gemini.test.ts +54 -0
  541. package/src/memory/embedding-gemini.ts +20 -9
  542. package/src/memory/embedding-local.ts +176 -17
  543. package/src/memory/graph/consolidation.ts +10 -23
  544. package/src/memory/graph/conversation-graph-memory.ts +15 -0
  545. package/src/memory/graph/extraction-job.ts +15 -0
  546. package/src/memory/graph/extraction.test.ts +23 -0
  547. package/src/memory/graph/extraction.ts +8 -0
  548. package/src/memory/graph/retriever.ts +67 -40
  549. package/src/memory/graph/scoring.test.ts +186 -0
  550. package/src/memory/graph/scoring.ts +31 -1
  551. package/src/memory/graph/store.test.ts +7 -3
  552. package/src/memory/graph/store.ts +47 -12
  553. package/src/memory/graph/tools.ts +1 -1
  554. package/src/memory/group-crud.ts +6 -1
  555. package/src/memory/indexer.ts +95 -16
  556. package/src/memory/job-handlers/cleanup.ts +11 -8
  557. package/src/memory/job-handlers/conversation-starters.ts +16 -10
  558. package/src/memory/jobs-store.ts +64 -4
  559. package/src/memory/jobs-worker.ts +22 -9
  560. package/src/memory/llm-usage-store.ts +137 -60
  561. package/src/memory/migrations/213-oauth-providers-scope-separator.ts +13 -0
  562. package/src/memory/migrations/214-oauth-providers-refresh-url.ts +11 -0
  563. package/src/memory/migrations/215-oauth-providers-revoke.ts +14 -0
  564. package/src/memory/migrations/216-oauth-providers-token-auth-method.ts +30 -0
  565. package/src/memory/migrations/217-conversation-host-access.ts +40 -0
  566. package/src/memory/migrations/218-oauth-providers-logo-url.ts +11 -0
  567. package/src/memory/migrations/219-oauth-providers-token-exchange-body-format.ts +15 -0
  568. package/src/memory/migrations/220-normalize-user-file-by-principal.ts +190 -0
  569. package/src/memory/migrations/221-conversations-archived-at.ts +16 -0
  570. package/src/memory/migrations/index.ts +12 -0
  571. package/src/memory/migrations/registry.ts +16 -0
  572. package/src/memory/qdrant-manager.ts +43 -16
  573. package/src/memory/schema/conversations.ts +3 -0
  574. package/src/memory/schema/oauth.ts +21 -13
  575. package/src/memory/usage-buckets.ts +396 -0
  576. package/src/messaging/providers/gmail/client.ts +57 -6
  577. package/src/messaging/providers/slack/__tests__/adapter-token-routing.test.ts +282 -0
  578. package/src/messaging/providers/slack/adapter.ts +143 -38
  579. package/src/messaging/providers/slack/client.ts +16 -0
  580. package/src/messaging/providers/slack/types.ts +4 -0
  581. package/src/notifications/decision-engine.ts +3 -3
  582. package/src/notifications/signal.ts +5 -0
  583. package/src/oauth/AGENTS.md +76 -0
  584. package/src/oauth/__tests__/identity-verifier.test.ts +25 -19
  585. package/src/oauth/__tests__/seed-providers-managed.test.ts +32 -0
  586. package/src/oauth/byo-connection.test.ts +26 -9
  587. package/src/oauth/byo-connection.ts +10 -8
  588. package/src/oauth/connect-orchestrator.ts +25 -21
  589. package/src/oauth/connect-types.ts +3 -3
  590. package/src/oauth/connection-resolver.test.ts +17 -4
  591. package/src/oauth/connection-resolver.ts +22 -18
  592. package/src/oauth/connection.ts +3 -1
  593. package/src/oauth/manual-token-connection.ts +13 -13
  594. package/src/oauth/oauth-store.ts +223 -100
  595. package/src/oauth/platform-connection.test.ts +101 -3
  596. package/src/oauth/platform-connection.ts +56 -35
  597. package/src/oauth/provider-serializer.ts +31 -5
  598. package/src/oauth/revoke.ts +76 -0
  599. package/src/oauth/seed-providers.ts +133 -87
  600. package/src/oauth/token-persistence.ts +1 -1
  601. package/src/permissions/checker.ts +16 -6
  602. package/src/permissions/defaults.ts +49 -1
  603. package/src/permissions/permission-mode.ts +4 -11
  604. package/src/permissions/prompter.ts +13 -1
  605. package/src/permissions/trust-store.ts +3 -3
  606. package/src/permissions/v2-consent-policy.ts +87 -0
  607. package/src/permissions/workspace-policy.ts +3 -0
  608. package/src/platform/client.test.ts +10 -0
  609. package/src/platform/sync-identity.ts +129 -0
  610. package/src/prompts/persona-resolver.ts +126 -2
  611. package/src/prompts/system-prompt.ts +76 -38
  612. package/src/prompts/templates/BOOTSTRAP-REFERENCE.md +3 -65
  613. package/src/prompts/templates/BOOTSTRAP.md +59 -105
  614. package/src/prompts/templates/SOUL.md +3 -1
  615. package/src/prompts/templates/UPDATES.md +12 -0
  616. package/src/prompts/templates/channels/slack.md +20 -0
  617. package/src/prompts/update-bulletin-format.ts +26 -9
  618. package/src/prompts/update-bulletin.ts +34 -23
  619. package/src/prompts/user-reference.ts +20 -17
  620. package/src/providers/__tests__/provider-secret-catalog.test.ts +42 -0
  621. package/src/providers/anthropic/client.ts +157 -60
  622. package/src/providers/fireworks/client.ts +2 -2
  623. package/src/providers/gemini/client.ts +9 -1
  624. package/src/providers/model-catalog.ts +6 -0
  625. package/src/providers/model-intents.ts +4 -4
  626. package/src/providers/ollama/client.ts +2 -2
  627. package/src/providers/openai/chat-completions-provider.ts +474 -0
  628. package/src/providers/openai/client.ts +25 -440
  629. package/src/providers/openai/responses-provider.ts +502 -0
  630. package/src/providers/openrouter/client.ts +101 -4
  631. package/src/providers/provider-secret-catalog.ts +139 -0
  632. package/src/providers/registry.ts +2 -2
  633. package/src/providers/retry.ts +14 -3
  634. package/src/providers/speech-to-text/__tests__/provider-catalog.test.ts +251 -0
  635. package/src/providers/speech-to-text/__tests__/resolve.test.ts +828 -0
  636. package/src/providers/speech-to-text/deepgram-realtime.test.ts +980 -0
  637. package/src/providers/speech-to-text/deepgram-realtime.ts +767 -0
  638. package/src/providers/speech-to-text/deepgram.test.ts +332 -0
  639. package/src/providers/speech-to-text/deepgram.ts +115 -0
  640. package/src/providers/speech-to-text/google-gemini-live-stream.test.ts +743 -0
  641. package/src/providers/speech-to-text/google-gemini-live-stream.ts +625 -0
  642. package/src/providers/speech-to-text/google-gemini.test.ts +226 -0
  643. package/src/providers/speech-to-text/google-gemini.ts +101 -0
  644. package/src/providers/speech-to-text/openai-whisper-stream.test.ts +564 -0
  645. package/src/providers/speech-to-text/openai-whisper-stream.ts +381 -0
  646. package/src/providers/speech-to-text/openai-whisper.test.ts +1 -37
  647. package/src/providers/speech-to-text/openai-whisper.ts +63 -33
  648. package/src/providers/speech-to-text/provider-catalog.ts +306 -0
  649. package/src/providers/speech-to-text/resolve.ts +386 -6
  650. package/src/providers/types.ts +10 -1
  651. package/src/runtime/AGENTS.md +65 -0
  652. package/src/runtime/__tests__/agent-wake.test.ts +831 -0
  653. package/src/runtime/__tests__/browser-extension-pair-routes.test.ts +715 -0
  654. package/src/runtime/__tests__/capability-tokens.test.ts +258 -0
  655. package/src/runtime/__tests__/chrome-extension-registry.test.ts +518 -0
  656. package/src/runtime/__tests__/runtime-mode.test.ts +62 -0
  657. package/src/runtime/__tests__/slack-block-formatting.test.ts +481 -0
  658. package/src/runtime/agent-wake.ts +512 -0
  659. package/src/runtime/assistant-event-hub.ts +2 -2
  660. package/src/runtime/auth/__tests__/guard-tests.test.ts +1 -0
  661. package/src/runtime/auth/__tests__/middleware.test.ts +116 -1
  662. package/src/runtime/auth/__tests__/route-policy.test.ts +48 -0
  663. package/src/runtime/auth/middleware.ts +98 -0
  664. package/src/runtime/auth/route-policy.ts +33 -9
  665. package/src/runtime/auth/token-service.ts +56 -1
  666. package/src/runtime/btw-sidechain.ts +2 -0
  667. package/src/runtime/capability-tokens.ts +414 -0
  668. package/src/runtime/channel-approvals.ts +18 -5
  669. package/src/runtime/channel-invite-transport.ts +1 -1
  670. package/src/runtime/channel-invite-transports/email.ts +14 -6
  671. package/src/runtime/channel-readiness-service.ts +12 -22
  672. package/src/runtime/chrome-extension-registry.ts +368 -0
  673. package/src/runtime/confirmation-request-guardian-bridge.ts +6 -0
  674. package/src/runtime/guardian-decision-types.ts +7 -0
  675. package/src/runtime/http-server.ts +815 -75
  676. package/src/runtime/http-types.ts +6 -2
  677. package/src/runtime/migrations/__tests__/rebind-secrets-credentials.test.ts +172 -0
  678. package/src/runtime/migrations/__tests__/vbundle-builder-credentials.test.ts +276 -0
  679. package/src/runtime/migrations/__tests__/vbundle-import-credentials.test.ts +198 -0
  680. package/src/runtime/migrations/__tests__/vbundle-legacy-user-md.test.ts +360 -0
  681. package/src/runtime/migrations/migration-transport.ts +7 -0
  682. package/src/runtime/migrations/migration-wizard.ts +23 -2
  683. package/src/runtime/migrations/rebind-secrets-screen.ts +76 -15
  684. package/src/runtime/migrations/vbundle-builder.ts +145 -38
  685. package/src/runtime/migrations/vbundle-import-analyzer.ts +96 -1
  686. package/src/runtime/migrations/vbundle-importer.ts +89 -5
  687. package/src/runtime/pending-interactions.ts +18 -13
  688. package/src/runtime/routes/__tests__/backup-routes.test.ts +967 -0
  689. package/src/runtime/routes/__tests__/home-feed-routes.test.ts +507 -0
  690. package/src/runtime/routes/__tests__/migration-import-credential-filter.test.ts +208 -0
  691. package/src/runtime/routes/__tests__/stt-routes.test.ts +406 -0
  692. package/src/runtime/routes/__tests__/tts-routes.test.ts +474 -0
  693. package/src/runtime/routes/__tests__/user-route-dispatcher.test.ts +148 -17
  694. package/src/runtime/routes/app-management-routes.ts +12 -18
  695. package/src/runtime/routes/approval-routes.ts +90 -16
  696. package/src/runtime/routes/attachment-routes.test.ts +9 -3
  697. package/src/runtime/routes/attachment-routes.ts +216 -17
  698. package/src/runtime/routes/backup-routes.ts +519 -0
  699. package/src/runtime/routes/browser-extension-pair-routes.ts +556 -0
  700. package/src/runtime/routes/btw-routes.ts +8 -6
  701. package/src/runtime/routes/contact-routes.test.ts +298 -0
  702. package/src/runtime/routes/contact-routes.ts +132 -5
  703. package/src/runtime/routes/conversation-analysis-routes.ts +22 -141
  704. package/src/runtime/routes/conversation-management-routes.ts +223 -0
  705. package/src/runtime/routes/conversation-routes.ts +598 -103
  706. package/src/runtime/routes/conversation-starter-routes.ts +78 -16
  707. package/src/runtime/routes/filing-routes.ts +93 -0
  708. package/src/runtime/routes/guardian-action-routes.ts +24 -13
  709. package/src/runtime/routes/home-feed-routes.ts +334 -0
  710. package/src/runtime/routes/home-state-routes.ts +138 -0
  711. package/src/runtime/routes/host-browser-routes.ts +268 -0
  712. package/src/runtime/routes/host-file-routes.ts +9 -1
  713. package/src/runtime/routes/identity-intro-cache.ts +7 -3
  714. package/src/runtime/routes/identity-routes.ts +262 -33
  715. package/src/runtime/routes/inbound-stages/transcribe-audio.test.ts +46 -39
  716. package/src/runtime/routes/inbound-stages/transcribe-audio.ts +15 -15
  717. package/src/runtime/routes/integrations/slack/__tests__/channel.test.ts +137 -0
  718. package/src/runtime/routes/integrations/slack/__tests__/share.test.ts +179 -0
  719. package/src/runtime/routes/integrations/slack/channel.ts +11 -3
  720. package/src/runtime/routes/integrations/slack/share.ts +45 -7
  721. package/src/runtime/routes/llm-context-normalization.ts +303 -0
  722. package/src/runtime/routes/log-export-routes.ts +42 -22
  723. package/src/runtime/routes/memory-item-routes.test.ts +3 -2
  724. package/src/runtime/routes/memory-item-routes.ts +1 -7
  725. package/src/runtime/routes/migration-routes.ts +122 -2
  726. package/src/runtime/routes/oauth-apps.ts +15 -17
  727. package/src/runtime/routes/oauth-providers.ts +4 -0
  728. package/src/runtime/routes/schedule-routes.ts +24 -11
  729. package/src/runtime/routes/settings-routes.ts +31 -102
  730. package/src/runtime/routes/skills-routes.ts +128 -9
  731. package/src/runtime/routes/stt-routes.ts +233 -0
  732. package/src/runtime/routes/subagents-routes.ts +14 -10
  733. package/src/runtime/routes/surface-action-routes.ts +41 -2
  734. package/src/runtime/routes/tts-routes.ts +108 -24
  735. package/src/runtime/routes/usage-routes.ts +38 -9
  736. package/src/runtime/routes/user-route-dispatcher.ts +50 -5
  737. package/src/runtime/routes/user-routes.ts +13 -1
  738. package/src/runtime/routes/work-items-routes.ts +8 -1
  739. package/src/runtime/routes/workspace-routes.test.ts +22 -0
  740. package/src/runtime/routes/workspace-routes.ts +8 -1
  741. package/src/runtime/routes/workspace-utils.ts +2 -0
  742. package/src/runtime/runtime-mode.ts +33 -0
  743. package/src/runtime/services/__tests__/analyze-conversation.test.ts +444 -0
  744. package/src/runtime/services/__tests__/analyze-deps-singleton.test.ts +67 -0
  745. package/src/runtime/services/__tests__/auto-analysis-prompt.test.ts +53 -0
  746. package/src/runtime/services/__tests__/manual-analysis-prompt.test.ts +41 -0
  747. package/src/runtime/services/analyze-conversation.ts +344 -0
  748. package/src/runtime/services/analyze-deps-singleton.ts +32 -0
  749. package/src/runtime/services/auto-analysis-prompt.ts +55 -0
  750. package/src/runtime/skill-route-registry.ts +49 -0
  751. package/src/runtime/slack-block-formatting.ts +437 -10
  752. package/src/schedule/scheduler.ts +57 -5
  753. package/src/security/ces-credential-client.ts +20 -0
  754. package/src/security/ces-rpc-credential-backend.ts +17 -0
  755. package/src/security/credential-backend.ts +5 -0
  756. package/src/security/oauth2.ts +68 -29
  757. package/src/security/secure-keys.ts +143 -27
  758. package/src/security/token-manager.ts +31 -10
  759. package/src/sequence/engine.ts +23 -0
  760. package/src/sequence/types.ts +1 -1
  761. package/src/skills/catalog-files.ts +554 -0
  762. package/src/skills/category-inference.ts +122 -0
  763. package/src/skills/clawhub-files.ts +213 -0
  764. package/src/skills/clawhub.ts +84 -23
  765. package/src/skills/skill-file-provider.ts +40 -0
  766. package/src/skills/skillssh-files.ts +395 -0
  767. package/src/skills/skillssh-registry.ts +4 -4
  768. package/src/stt/__tests__/daemon-batch-transcriber.test.ts +392 -0
  769. package/src/stt/__tests__/types.test.ts +89 -0
  770. package/src/stt/daemon-batch-transcriber.ts +195 -0
  771. package/src/stt/stt-stream-session.ts +499 -0
  772. package/src/stt/types.ts +330 -0
  773. package/src/stt/wav-encoder.test.ts +373 -0
  774. package/src/stt/wav-encoder.ts +175 -0
  775. package/src/subagent/manager.ts +169 -40
  776. package/src/subagent/types.ts +19 -0
  777. package/src/tools/apps/executors.ts +11 -2
  778. package/src/tools/browser/__tests__/auth-detector.test.ts +202 -108
  779. package/src/tools/browser/__tests__/browser-mode.test.ts +119 -0
  780. package/src/tools/browser/__tests__/browser-status.test.ts +123 -0
  781. package/src/tools/browser/auth-detector.ts +43 -12
  782. package/src/tools/browser/browser-execution.ts +1787 -342
  783. package/src/tools/browser/browser-manager.ts +81 -12
  784. package/src/tools/browser/browser-mode-constants.ts +12 -0
  785. package/src/tools/browser/browser-mode.ts +92 -0
  786. package/src/tools/browser/browser-status-constants.ts +33 -0
  787. package/src/tools/browser/cdp-client/__tests__/accessibility-snapshot.test.ts +318 -0
  788. package/src/tools/browser/cdp-client/__tests__/cdp-dom-helpers.test.ts +1175 -0
  789. package/src/tools/browser/cdp-client/__tests__/cdp-inspect-client.test.ts +1263 -0
  790. package/src/tools/browser/cdp-client/__tests__/extension-cdp-client.test.ts +359 -0
  791. package/src/tools/browser/cdp-client/__tests__/factory.test.ts +1993 -0
  792. package/src/tools/browser/cdp-client/__tests__/fixtures/ax-tree-nested-frames.json +64 -0
  793. package/src/tools/browser/cdp-client/__tests__/fixtures/ax-tree-simple.json +69 -0
  794. package/src/tools/browser/cdp-client/__tests__/local-cdp-client.test.ts +310 -0
  795. package/src/tools/browser/cdp-client/__tests__/types.test.ts +96 -0
  796. package/src/tools/browser/cdp-client/accessibility-snapshot.ts +387 -0
  797. package/src/tools/browser/cdp-client/cdp-dom-helpers.ts +695 -0
  798. package/src/tools/browser/cdp-client/cdp-inspect/__tests__/discovery.test.ts +1007 -0
  799. package/src/tools/browser/cdp-client/cdp-inspect/__tests__/ws-transport.test.ts +580 -0
  800. package/src/tools/browser/cdp-client/cdp-inspect/discovery.ts +744 -0
  801. package/src/tools/browser/cdp-client/cdp-inspect/ws-transport.ts +579 -0
  802. package/src/tools/browser/cdp-client/cdp-inspect-client.ts +868 -0
  803. package/src/tools/browser/cdp-client/errors.ts +49 -0
  804. package/src/tools/browser/cdp-client/extension-cdp-client.ts +148 -0
  805. package/src/tools/browser/cdp-client/factory.ts +914 -0
  806. package/src/tools/browser/cdp-client/index.ts +28 -0
  807. package/src/tools/browser/cdp-client/local-cdp-client.ts +187 -0
  808. package/src/tools/browser/cdp-client/types.ts +120 -0
  809. package/src/tools/credentials/vault.ts +35 -6
  810. package/src/tools/filesystem/edit.ts +1 -1
  811. package/src/tools/filesystem/list.ts +1 -1
  812. package/src/tools/filesystem/read.ts +1 -1
  813. package/src/tools/filesystem/write.ts +2 -1
  814. package/src/tools/host-filesystem/edit.ts +1 -1
  815. package/src/tools/host-filesystem/read.ts +12 -15
  816. package/src/tools/host-filesystem/write.ts +1 -1
  817. package/src/tools/host-terminal/host-shell.ts +21 -16
  818. package/src/tools/network/web-fetch.ts +5 -2
  819. package/src/tools/network/web-search.ts +5 -2
  820. package/src/tools/permission-checker.ts +77 -82
  821. package/src/tools/registry.ts +0 -2
  822. package/src/tools/secret-detection-handler.ts +34 -0
  823. package/src/tools/shared/filesystem/image-read.ts +61 -40
  824. package/src/tools/shared/shell-output.ts +3 -1
  825. package/src/tools/side-effects.ts +2 -0
  826. package/src/tools/skills/sandbox-runner.ts +3 -2
  827. package/src/tools/subagent/spawn.ts +47 -3
  828. package/src/tools/subagent/status.ts +2 -0
  829. package/src/tools/system/register.ts +2 -16
  830. package/src/tools/terminal/safe-env.ts +15 -0
  831. package/src/tools/terminal/shell.ts +36 -20
  832. package/src/tools/tool-approval-handler.ts +48 -2
  833. package/src/tools/tool-manifest.ts +21 -0
  834. package/src/tools/types.ts +19 -0
  835. package/src/tools/ui-surface/definitions.ts +6 -1
  836. package/src/tts/__tests__/provider-adapters.test.ts +834 -0
  837. package/src/tts/__tests__/provider-catalog-consistency.test.ts +196 -0
  838. package/src/tts/__tests__/provider-catalog.test.ts +183 -0
  839. package/src/tts/__tests__/provider-registry.test.ts +90 -0
  840. package/src/tts/provider-catalog.ts +201 -0
  841. package/src/tts/provider-registry.ts +73 -0
  842. package/src/tts/providers/deepgram-provider.ts +219 -0
  843. package/src/tts/providers/elevenlabs-provider.ts +211 -0
  844. package/src/tts/providers/fish-audio-provider.ts +183 -0
  845. package/src/tts/providers/index.ts +42 -0
  846. package/src/tts/providers/register-builtins.ts +130 -0
  847. package/src/tts/synthesize-text.ts +110 -0
  848. package/src/tts/tts-config-resolver.ts +78 -0
  849. package/src/tts/types.ts +153 -0
  850. package/src/types/onboarding-context.ts +7 -0
  851. package/src/util/abort-reasons.ts +58 -0
  852. package/src/util/device-id.ts +32 -16
  853. package/src/util/errors.ts +9 -1
  854. package/src/util/platform.ts +63 -24
  855. package/src/util/pricing.ts +66 -3
  856. package/src/util/spawn.ts +1 -1
  857. package/src/util/truncate.ts +4 -2
  858. package/src/util/unicode.ts +201 -0
  859. package/src/version.ts +19 -24
  860. package/src/watcher/engine.ts +23 -0
  861. package/src/watcher/watcher-store.ts +31 -0
  862. package/src/workspace/migrations/003-seed-device-id.ts +9 -3
  863. package/src/workspace/migrations/017-seed-persona-dirs.ts +68 -4
  864. package/src/workspace/migrations/029-seed-pkb.ts +1 -1
  865. package/src/workspace/migrations/031-drop-user-md.ts +317 -0
  866. package/src/workspace/migrations/031-llm-log-retention-zero-to-null.ts +73 -0
  867. package/src/workspace/migrations/032-tts-provider-unification.ts +227 -0
  868. package/src/workspace/migrations/033-stt-service-explicit-config.ts +122 -0
  869. package/src/workspace/migrations/034-remove-calls-voice-transcription-provider.ts +215 -0
  870. package/src/workspace/migrations/035-seed-slack-channel-persona.ts +50 -0
  871. package/src/workspace/migrations/036-update-pkb-index-bar.ts +37 -0
  872. package/src/workspace/migrations/037-create-meets-dir.ts +61 -0
  873. package/src/workspace/migrations/registry.ts +16 -0
  874. package/src/workspace/top-level-renderer.ts +31 -1
  875. package/src/workspace/turn-commit.ts +31 -0
  876. package/src/__tests__/chrome-cdp.test.ts +0 -419
  877. package/src/__tests__/email-cli.test.ts +0 -297
  878. package/src/__tests__/email-service-config-fallback.test.ts +0 -102
  879. package/src/__tests__/permission-mode-sse.test.ts +0 -418
  880. package/src/__tests__/permission-mode-store.test.ts +0 -277
  881. package/src/browser-extension-relay/protocol.ts +0 -63
  882. package/src/browser-extension-relay/server.ts +0 -203
  883. package/src/cli/commands/browser-relay.ts +0 -536
  884. package/src/config/schemas/sandbox.ts +0 -14
  885. package/src/email/guardrails.ts +0 -221
  886. package/src/email/provider.ts +0 -117
  887. package/src/email/providers/agentmail.ts +0 -361
  888. package/src/email/providers/index.ts +0 -65
  889. package/src/email/service.ts +0 -384
  890. package/src/email/types.ts +0 -126
  891. package/src/permissions/permission-mode-store.ts +0 -180
  892. package/src/prompts/templates/USER.md +0 -13
  893. package/src/providers/speech-to-text/types.ts +0 -17
  894. package/src/tools/browser/chrome-cdp.ts +0 -239
  895. package/src/tools/system/set-permission-mode.ts +0 -103
@@ -129,8 +129,12 @@ mock.module("../permissions/checker.js", () => ({
129
129
  scopeOptionsOverride ?? [{ label: "/tmp", scope: "/tmp" }],
130
130
  }));
131
131
 
132
+ // Mock every export so downstream test files that dynamically import modules
133
+ // with a static `from "../memory/tool-usage-store.js"` still see all symbols.
132
134
  mock.module("../memory/tool-usage-store.js", () => ({
133
135
  recordToolInvocation: () => {},
136
+ getRecentInvocations: () => [],
137
+ rotateToolInvocations: () => 0,
134
138
  }));
135
139
 
136
140
  mock.module("../tools/registry.js", () => ({
@@ -1148,6 +1152,8 @@ describe("isSideEffectTool", () => {
1148
1152
  "browser_type",
1149
1153
  "browser_press_key",
1150
1154
  "browser_close",
1155
+ "browser_attach",
1156
+ "browser_detach",
1151
1157
  "browser_fill_credential",
1152
1158
  "document_create",
1153
1159
  "document_update",
@@ -1220,12 +1226,13 @@ describe("isSideEffectTool", () => {
1220
1226
  });
1221
1227
  });
1222
1228
 
1223
- // Baseline: allow rules can auto-allow file_edit for USER.md today (no forced prompting).
1224
- // The mock check() delegates to findHighestPriorityRule (via spy) so a regression
1225
- // in trust-rule matching would cause this test to fail instead of being masked by
1226
- // a blanket mock-allow.
1227
- describe("ToolExecutor baseline: allow rule auto-allows file_edit USER.md", () => {
1228
- const userMdPath = "/Users/sidd/.vellum/workspace/USER.md";
1229
+ // Baseline: allow rules can auto-allow file_edit for the guardian persona
1230
+ // today (no forced prompting). The mock check() delegates to
1231
+ // findHighestPriorityRule (via spy) so a regression in trust-rule matching
1232
+ // would cause this test to fail instead of being masked by a blanket
1233
+ // mock-allow.
1234
+ describe("ToolExecutor baseline: allow rule auto-allows file_edit guardian persona", () => {
1235
+ const guardianPersonaPath = "/Users/sidd/.vellum/workspace/users/sidd.md";
1229
1236
  let ruleSpy: ReturnType<typeof spyOn> | undefined;
1230
1237
 
1231
1238
  beforeEach(() => {
@@ -1239,18 +1246,19 @@ describe("ToolExecutor baseline: allow rule auto-allows file_edit USER.md", () =
1239
1246
  addRuleSpy = undefined;
1240
1247
  }
1241
1248
 
1242
- // Simulate a trust rule that allows file_edit on USER.md by stubbing
1243
- // findHighestPriorityRule. This mirrors the default allow rules that
1244
- // the trust-store creates for workspace prompt files.
1249
+ // Simulate a trust rule that allows file_edit on the guardian's per-user
1250
+ // persona file by stubbing findHighestPriorityRule. This mirrors the
1251
+ // default allow rules that the trust-store creates for the guardian
1252
+ // persona file (see permissions/defaults.ts).
1245
1253
  ruleSpy = spyOn(trustStore, "findHighestPriorityRule").mockImplementation(
1246
1254
  (tool: string, commands: string[], _scope: string) => {
1247
1255
  if (tool !== "file_edit") return null;
1248
1256
  for (const cmd of commands) {
1249
- if (cmd === `file_edit:${userMdPath}`) {
1257
+ if (cmd === `file_edit:${guardianPersonaPath}`) {
1250
1258
  return {
1251
- id: "default:allow-file_edit-user",
1259
+ id: "default:allow-file_edit-guardian-persona",
1252
1260
  tool: "file_edit",
1253
- pattern: `file_edit:${userMdPath}`,
1261
+ pattern: `file_edit:${guardianPersonaPath}`,
1254
1262
  scope: "everywhere",
1255
1263
  decision: "allow" as const,
1256
1264
  priority: 100,
@@ -1294,11 +1302,11 @@ describe("ToolExecutor baseline: allow rule auto-allows file_edit USER.md", () =
1294
1302
  }
1295
1303
  });
1296
1304
 
1297
- test("file_edit to USER.md is auto-allowed via trust rule", async () => {
1305
+ test("file_edit to guardian persona is auto-allowed via trust rule", async () => {
1298
1306
  const executor = new ToolExecutor(makePrompter());
1299
1307
  const result = await executor.execute(
1300
1308
  "file_edit",
1301
- { path: userMdPath, content: "hello" },
1309
+ { path: guardianPersonaPath, content: "hello" },
1302
1310
  makeContext(),
1303
1311
  );
1304
1312
  expect(result.isError).toBe(false);
@@ -1310,7 +1318,7 @@ describe("ToolExecutor baseline: allow rule auto-allows file_edit USER.md", () =
1310
1318
  expect(ruleSpy).toHaveBeenCalled();
1311
1319
  });
1312
1320
 
1313
- test("file_edit to a non-USER.md path is NOT auto-allowed without a matching rule", async () => {
1321
+ test("file_edit to a non-guardian-persona path is NOT auto-allowed without a matching rule", async () => {
1314
1322
  let promptCalled = false;
1315
1323
  const trackingPrompter = {
1316
1324
  prompt: async () => {
@@ -1530,22 +1538,23 @@ describe("ToolExecutor forcePromptSideEffects enforcement", () => {
1530
1538
  expect(promptCount).toBe(1);
1531
1539
  });
1532
1540
 
1533
- // ── USER.md security invariant (PR 31) ──────────
1541
+ // ── Guardian persona security invariant (PR 31) ──────────
1534
1542
 
1535
- test("file_edit to USER.md forces prompt in private conversation even with matching trust rule", async () => {
1536
- // This is a key security invariant: USER.md contains the user's persistent
1537
- // memory. In a private conversation (forcePromptSideEffects=true), edits to it
1538
- // must always require explicit approval, even when a trust rule matches.
1543
+ test("file_edit to guardian persona forces prompt in private conversation even with matching trust rule", async () => {
1544
+ // This is a key security invariant: the guardian persona file contains
1545
+ // the user's persistent memory. In a private conversation
1546
+ // (forcePromptSideEffects=true), edits to it must always require explicit
1547
+ // approval, even when a trust rule matches.
1539
1548
  checkResultOverride = {
1540
1549
  decision: "allow",
1541
- reason: "Matched trust rule: file_edit:*/USER.md",
1550
+ reason: "Matched trust rule: file_edit:*/users/*.md",
1542
1551
  };
1543
1552
 
1544
1553
  const executor = new ToolExecutor(makeTrackingPrompter());
1545
1554
  const result = await executor.execute(
1546
1555
  "file_edit",
1547
1556
  {
1548
- path: "/Users/sidd/.vellum/workspace/USER.md",
1557
+ path: "/Users/sidd/.vellum/workspace/users/sidd.md",
1549
1558
  old_string: "old pref",
1550
1559
  new_string: "new pref",
1551
1560
  },
@@ -1557,14 +1566,14 @@ describe("ToolExecutor forcePromptSideEffects enforcement", () => {
1557
1566
  expect(promptCalled).toBe(true);
1558
1567
  });
1559
1568
 
1560
- test("host_file_edit to USER.md forces prompt in private conversation", async () => {
1569
+ test("host_file_edit to guardian persona forces prompt in private conversation", async () => {
1561
1570
  checkResultOverride = { decision: "allow", reason: "Matched trust rule" };
1562
1571
 
1563
1572
  const executor = new ToolExecutor(makeTrackingPrompter());
1564
1573
  const result = await executor.execute(
1565
1574
  "host_file_edit",
1566
1575
  {
1567
- path: "/Users/sidd/.vellum/workspace/USER.md",
1576
+ path: "/Users/sidd/.vellum/workspace/users/sidd.md",
1568
1577
  old_string: "x",
1569
1578
  new_string: "y",
1570
1579
  },
@@ -11,6 +11,20 @@ import {
11
11
  } from "../context/tool-result-truncation.js";
12
12
  import type { ContentBlock, ToolResultContent } from "../providers/types.js";
13
13
 
14
+ function hasOrphanedSurrogate(str: string): boolean {
15
+ for (let i = 0; i < str.length; i++) {
16
+ const code = str.charCodeAt(i);
17
+ if (code >= 0xd800 && code <= 0xdbff) {
18
+ const next = i + 1 < str.length ? str.charCodeAt(i + 1) : 0;
19
+ if (next < 0xdc00 || next > 0xdfff) return true;
20
+ i++;
21
+ } else if (code >= 0xdc00 && code <= 0xdfff) {
22
+ return true;
23
+ }
24
+ }
25
+ return false;
26
+ }
27
+
14
28
  // ---------------------------------------------------------------------------
15
29
  // Helpers
16
30
  // ---------------------------------------------------------------------------
@@ -100,6 +114,28 @@ describe("truncateToolResultText", () => {
100
114
  expect(result).toBe(text);
101
115
  expect(result).not.toContain(TRUNCATION_SUFFIX);
102
116
  });
117
+
118
+ test("does not orphan a UTF-16 surrogate pair at the cut boundary", () => {
119
+ // Regression for the "no low surrogate in string" Anthropic 400 error.
120
+ // Build a string where the cut point lands inside a surrogate pair:
121
+ // 4999 padding chars, then an emoji (2 code units), then enough filler
122
+ // to push the cut inside the pair.
123
+ const EMOJI = "\uD83C\uDF89";
124
+ // maxChars = 5_000, so cutPoint = 5_000 - TRUNCATION_SUFFIX.length.
125
+ // Put the emoji so its high surrogate lands exactly at cutPoint - 1.
126
+ const maxChars = 5_000;
127
+ const cutPoint = maxChars - TRUNCATION_SUFFIX.length;
128
+ // Fill up to cutPoint - 1 with "a"s, then place the emoji so the high
129
+ // surrogate is the character at cutPoint - 1 and the low is at cutPoint.
130
+ const prefix = "a".repeat(cutPoint - 1);
131
+ const text = prefix + EMOJI + "b".repeat(100);
132
+ // Use a long filler with no newlines so lastIndexOf("\n", cutPoint) === -1
133
+ // and the function falls back to cutPoint itself.
134
+ const result = truncateToolResultText(text, maxChars);
135
+ expect(hasOrphanedSurrogate(result)).toBe(false);
136
+ // JSON.stringify must not throw on the result.
137
+ expect(() => JSON.stringify(result)).not.toThrow();
138
+ });
103
139
  });
104
140
 
105
141
  // ---------------------------------------------------------------------------
@@ -30,8 +30,30 @@ mock.module("../media/app-icon-generator.js", () => ({
30
30
  mock.module("../memory/app-store.js", () => ({
31
31
  getApp: mock(() => null),
32
32
  getAppDirPath: mock(() => ""),
33
+ getAppsDir: mock(() => ""),
33
34
  isMultifileApp: mock(() => false),
34
35
  resolveAppIdFromPath: mock(() => null),
36
+ resolveAppIdByDirName: mock(() => null),
37
+ resolveAppDir: mock(() => ({ dirName: "", dirPath: "" })),
38
+ slugify: mock((s: string) => s),
39
+ validateDirName: mock(() => {}),
40
+ generateAppDirName: mock(() => ""),
41
+ listApps: mock(() => []),
42
+ createApp: mock(() => ({})),
43
+ updateApp: mock(() => {}),
44
+ deleteApp: mock(() => {}),
45
+ getAppPreview: mock(() => null),
46
+ createAppRecord: mock(() => ({})),
47
+ getAppRecord: mock(() => null),
48
+ queryAppRecords: mock(() => []),
49
+ updateAppRecord: mock(() => {}),
50
+ deleteAppRecord: mock(() => {}),
51
+ listAppFiles: mock(() => []),
52
+ appFileExists: mock(() => false),
53
+ readAppFile: mock(() => ""),
54
+ writeAppFile: mock(() => {}),
55
+ editAppFile: mock(() => ({})),
56
+ inlineDistAssets: mock((_, html: string) => html),
35
57
  }));
36
58
  mock.module("../services/published-app-updater.js", () => ({
37
59
  updatePublishedAppDeployment: mock(() => Promise.resolve()),
@@ -1,10 +1,11 @@
1
+ import { homedir, userInfo } from "node:os";
1
2
  import { describe, expect, test } from "bun:test";
2
3
 
3
4
  import { renderWorkspaceTopLevelContext } from "../workspace/top-level-renderer.js";
4
5
  import type { TopLevelSnapshot } from "../workspace/top-level-scanner.js";
5
6
 
6
7
  describe("renderWorkspaceTopLevelContext", () => {
7
- test("renders basic snapshot with directories and files", () => {
8
+ test("renders basic snapshot with directories, files, and host env", () => {
8
9
  const snapshot: TopLevelSnapshot = {
9
10
  rootPath: "/sandbox",
10
11
  directories: ["lib", "src", "tests"],
@@ -19,6 +20,8 @@ describe("renderWorkspaceTopLevelContext", () => {
19
20
  "Root: /sandbox",
20
21
  "Directories: lib, src, tests",
21
22
  "Files: README.md, package.json",
23
+ `Host home directory: ${homedir()}`,
24
+ `Host username: ${userInfo().username}`,
22
25
  "</workspace>",
23
26
  ].join("\n"),
24
27
  );
@@ -65,6 +68,8 @@ describe("renderWorkspaceTopLevelContext", () => {
65
68
  "Root: /empty",
66
69
  "Directories: ",
67
70
  "Files: ",
71
+ `Host home directory: ${homedir()}`,
72
+ `Host username: ${userInfo().username}`,
68
73
  "</workspace>",
69
74
  ].join("\n"),
70
75
  );
@@ -142,4 +147,71 @@ describe("renderWorkspaceTopLevelContext", () => {
142
147
  );
143
148
  expect(result).not.toContain("Current conversation folder");
144
149
  });
150
+
151
+ test("prefers client-reported host env over daemon os.homedir()", () => {
152
+ const snapshot: TopLevelSnapshot = {
153
+ rootPath: "/sandbox",
154
+ directories: ["src"],
155
+ files: ["package.json"],
156
+ truncated: false,
157
+ };
158
+
159
+ const result = renderWorkspaceTopLevelContext(snapshot, {
160
+ hostHomeDir: "/Users/alice",
161
+ hostUsername: "alice",
162
+ });
163
+
164
+ expect(result).toContain("Host home directory: /Users/alice");
165
+ expect(result).toContain("Host username: alice");
166
+ // Fallback values must NOT appear when client values are provided.
167
+ expect(result).not.toContain(`Host home directory: ${homedir()}`);
168
+ expect(result).not.toContain(`Host username: ${userInfo().username}`);
169
+ });
170
+
171
+ test("falls back to daemon os info when host env options omitted", () => {
172
+ const snapshot: TopLevelSnapshot = {
173
+ rootPath: "/sandbox",
174
+ directories: ["src"],
175
+ files: ["package.json"],
176
+ truncated: false,
177
+ };
178
+
179
+ const result = renderWorkspaceTopLevelContext(snapshot, {});
180
+
181
+ expect(result).toContain(`Host home directory: ${homedir()}`);
182
+ expect(result).toContain(`Host username: ${userInfo().username}`);
183
+ });
184
+
185
+ test("falls back to daemon os info when host env options are undefined", () => {
186
+ const snapshot: TopLevelSnapshot = {
187
+ rootPath: "/sandbox",
188
+ directories: ["src"],
189
+ files: ["package.json"],
190
+ truncated: false,
191
+ };
192
+
193
+ const result = renderWorkspaceTopLevelContext(snapshot, {
194
+ hostHomeDir: undefined,
195
+ hostUsername: undefined,
196
+ });
197
+
198
+ expect(result).toContain(`Host home directory: ${homedir()}`);
199
+ expect(result).toContain(`Host username: ${userInfo().username}`);
200
+ });
201
+
202
+ test("uses client home dir but falls back to os username when only home is provided", () => {
203
+ const snapshot: TopLevelSnapshot = {
204
+ rootPath: "/sandbox",
205
+ directories: ["src"],
206
+ files: ["package.json"],
207
+ truncated: false,
208
+ };
209
+
210
+ const result = renderWorkspaceTopLevelContext(snapshot, {
211
+ hostHomeDir: "/Users/alice",
212
+ });
213
+
214
+ expect(result).toContain("Host home directory: /Users/alice");
215
+ expect(result).toContain(`Host username: ${userInfo().username}`);
216
+ });
145
217
  });
@@ -1,8 +1,8 @@
1
1
  import { describe, expect, test } from "bun:test";
2
2
 
3
3
  import type {
4
- MacosTransportMetadata,
5
- NonMacosTransportMetadata,
4
+ HostProxyTransportMetadata,
5
+ NonHostProxyTransportMetadata,
6
6
  } from "../daemon/message-types/conversations.js";
7
7
  import { buildTransportHints } from "../daemon/transport-hints.js";
8
8
 
@@ -11,8 +11,8 @@ import { buildTransportHints } from "../daemon/transport-hints.js";
11
11
  // ---------------------------------------------------------------------------
12
12
 
13
13
  describe("buildTransportHints", () => {
14
- test("produces correct hints for macOS transport", () => {
15
- const transport: MacosTransportMetadata = {
14
+ test("returns empty array for host-proxy transport without client hints", () => {
15
+ const transport: HostProxyTransportMetadata = {
16
16
  channelId: "vellum",
17
17
  interfaceId: "macos",
18
18
  hostHomeDir: "/Users/alice",
@@ -21,29 +21,22 @@ describe("buildTransportHints", () => {
21
21
 
22
22
  const hints = buildTransportHints(transport);
23
23
 
24
- expect(hints).toContain("User is messaging from interface: macos");
25
- expect(hints).toContain("Host home directory: /Users/alice");
26
- expect(hints).toContain("Host username: alice");
27
- expect(hints).toHaveLength(3);
24
+ expect(hints).toHaveLength(0);
28
25
  });
29
26
 
30
- test("produces correct hints for non-macOS transport", () => {
31
- const transport: NonMacosTransportMetadata = {
27
+ test("returns empty array for non-host-proxy transport without client hints", () => {
28
+ const transport: NonHostProxyTransportMetadata = {
32
29
  channelId: "vellum",
33
30
  interfaceId: "ios",
34
31
  };
35
32
 
36
33
  const hints = buildTransportHints(transport);
37
34
 
38
- expect(hints).toContain("User is messaging from interface: ios");
39
- expect(hints).toHaveLength(1);
40
- // Should not include host environment hints
41
- expect(hints.some((h) => h.includes("Host home directory"))).toBe(false);
42
- expect(hints.some((h) => h.includes("Host username"))).toBe(false);
35
+ expect(hints).toHaveLength(0);
43
36
  });
44
37
 
45
- test("includes client-provided hints", () => {
46
- const transport: MacosTransportMetadata = {
38
+ test("forwards client-provided hints", () => {
39
+ const transport: HostProxyTransportMetadata = {
47
40
  channelId: "vellum",
48
41
  interfaceId: "macos",
49
42
  hostHomeDir: "/Users/bob",
@@ -53,25 +46,17 @@ describe("buildTransportHints", () => {
53
46
 
54
47
  const hints = buildTransportHints(transport);
55
48
 
56
- expect(hints).toContain("User is messaging from interface: macos");
57
- expect(hints).toContain("Host home directory: /Users/bob");
58
- expect(hints).toContain("Host username: bob");
59
- expect(hints).toContain("custom hint");
60
- expect(hints).toHaveLength(4);
49
+ expect(hints).toEqual(["custom hint"]);
61
50
  });
62
51
 
63
- test("handles missing optional fields on macOS transport", () => {
64
- const transport: MacosTransportMetadata = {
52
+ test("returns empty array when no hints field present", () => {
53
+ const transport: HostProxyTransportMetadata = {
65
54
  channelId: "vellum",
66
55
  interfaceId: "macos",
67
56
  };
68
57
 
69
58
  const hints = buildTransportHints(transport);
70
59
 
71
- expect(hints).toContain("User is messaging from interface: macos");
72
- // Without hostHomeDir and hostUsername, only the interface hint is present
73
- expect(hints).toHaveLength(1);
74
- expect(hints.some((h) => h.includes("Host home directory"))).toBe(false);
75
- expect(hints.some((h) => h.includes("Host username"))).toBe(false);
60
+ expect(hints).toHaveLength(0);
76
61
  });
77
62
  });
@@ -740,8 +740,10 @@ describe("Trust Store", () => {
740
740
  ].sort();
741
741
  expect(defaultTools).toEqual([
742
742
  "bash",
743
+ "browser_attach",
743
744
  "browser_click",
744
745
  "browser_close",
746
+ "browser_detach",
745
747
  "browser_extract",
746
748
  "browser_fill_credential",
747
749
  "browser_hover",
@@ -751,6 +753,7 @@ describe("Trust Store", () => {
751
753
  "browser_scroll",
752
754
  "browser_select_option",
753
755
  "browser_snapshot",
756
+ "browser_status",
754
757
  "browser_type",
755
758
  "browser_wait_for",
756
759
  "browser_wait_for_download",
@@ -1078,13 +1081,15 @@ describe("Trust Store", () => {
1078
1081
 
1079
1082
  // ── default allow: browser tools ────────────────────────────
1080
1083
 
1081
- test("all 14 browser tools have default allow rules", () => {
1084
+ test("all browser tools have default allow rules", () => {
1082
1085
  const templates = getDefaultRuleTemplates();
1083
1086
  const browserTools = [
1084
1087
  "browser_navigate",
1085
1088
  "browser_snapshot",
1086
1089
  "browser_screenshot",
1087
1090
  "browser_close",
1091
+ "browser_attach",
1092
+ "browser_detach",
1088
1093
  "browser_click",
1089
1094
  "browser_type",
1090
1095
  "browser_press_key",
@@ -1095,6 +1100,7 @@ describe("Trust Store", () => {
1095
1100
  "browser_extract",
1096
1101
  "browser_wait_for_download",
1097
1102
  "browser_fill_credential",
1103
+ "browser_status",
1098
1104
  ];
1099
1105
 
1100
1106
  for (const tool of browserTools) {
@@ -117,7 +117,7 @@ mock.module("../prompts/user-reference.js", () => ({
117
117
  ...realUserReference,
118
118
  resolveUserReference: () => "my human",
119
119
  resolveGuardianName: (guardianDisplayName?: string | null): string => {
120
- // Mirror the real implementation: USER.md name > guardianDisplayName > default
120
+ // Mirror the real implementation: guardian persona name (from users/<slug>.md) > guardianDisplayName > default
121
121
  const userRef = "my human"; // In tests, resolveUserReference() returns this
122
122
  if (userRef !== "my human") return userRef;
123
123
  if (guardianDisplayName && guardianDisplayName.trim().length > 0) {
@@ -162,6 +162,7 @@ mock.module("../config/env.js", () => ({
162
162
  import { applyCanonicalGuardianDecision } from "../approvals/guardian-decision-primitive.js";
163
163
  import type { ActorContext } from "../approvals/guardian-request-resolvers.js";
164
164
  import { getResolver } from "../approvals/guardian-request-resolvers.js";
165
+ import { _setOverridesForTesting } from "../config/assistant-feature-flags.js";
165
166
  import type { TrustContext } from "../daemon/conversation-runtime-assembly.js";
166
167
  import {
167
168
  createCanonicalGuardianRequest,
@@ -169,6 +170,10 @@ import {
169
170
  listCanonicalGuardianRequests,
170
171
  updateCanonicalGuardianRequest,
171
172
  } from "../memory/canonical-guardian-store.js";
173
+ import {
174
+ createConversation,
175
+ updateConversationHostAccess,
176
+ } from "../memory/conversation-crud.js";
172
177
  import { getDb, initializeDb } from "../memory/db.js";
173
178
  import { scopedApprovalGrants } from "../memory/schema.js";
174
179
  import { bridgeConfirmationRequestToGuardian } from "../runtime/confirmation-request-guardian-bridge.js";
@@ -184,6 +189,8 @@ initializeDb();
184
189
  function resetTables(): void {
185
190
  const db = getDb();
186
191
  db.delete(scopedApprovalGrants).run();
192
+ db.run("DELETE FROM messages");
193
+ db.run("DELETE FROM conversations");
187
194
  db.run("DELETE FROM canonical_guardian_deliveries");
188
195
  db.run("DELETE FROM canonical_guardian_requests");
189
196
  }
@@ -246,6 +253,7 @@ describe("(a) target flow: trusted-contact inline guardian approval end-to-end",
246
253
  events.length = 0;
247
254
  emittedSignals.length = 0;
248
255
  deliveredReplies.length = 0;
256
+ _setOverridesForTesting({});
249
257
  mockGuardianBinding = {
250
258
  id: "binding-1",
251
259
  assistantId: "self",
@@ -1160,3 +1168,104 @@ describe("cross-milestone integration checks", () => {
1160
1168
  expect(freshReq?.followupState).toBeNull();
1161
1169
  });
1162
1170
  });
1171
+
1172
+ describe("(g) v2 trusted-contact flow: model-mediated guardian consent", () => {
1173
+ const handler = new ToolApprovalHandler({
1174
+ inlineGrantWait: { maxWaitMs: 100, intervalMs: 20 },
1175
+ });
1176
+
1177
+ beforeEach(() => {
1178
+ resetTables();
1179
+ events.length = 0;
1180
+ emittedSignals.length = 0;
1181
+ deliveredReplies.length = 0;
1182
+ _setOverridesForTesting({ "permission-controls-v2": true });
1183
+ mockGuardianBinding = {
1184
+ id: "binding-1",
1185
+ assistantId: "self",
1186
+ channel: "telegram",
1187
+ guardianExternalUserId: "guardian-1",
1188
+ guardianDeliveryChatId: "guardian-chat-1",
1189
+ guardianPrincipalId: "test-principal-id",
1190
+ status: "active",
1191
+ };
1192
+ });
1193
+
1194
+ test("trusted-contact host tools do not create tool_grant_request rows under v2", async () => {
1195
+ const conv = createConversation("trusted contact v2 host gate");
1196
+ const result = await handler.checkPreExecutionGates(
1197
+ "bash",
1198
+ { command: "ls" },
1199
+ makeToolContext({
1200
+ trustClass: "trusted_contact",
1201
+ conversationId: conv.id,
1202
+ }),
1203
+ "host",
1204
+ "high",
1205
+ Date.now(),
1206
+ emitLifecycleEvent,
1207
+ );
1208
+
1209
+ expect(result.allowed).toBe(false);
1210
+ if (result.allowed) return;
1211
+ expect(result.result.content).toContain(
1212
+ "computer access is not enabled for this conversation",
1213
+ );
1214
+
1215
+ const requests = listCanonicalGuardianRequests({
1216
+ kind: "tool_grant_request",
1217
+ status: "pending",
1218
+ });
1219
+ expect(requests).toHaveLength(0);
1220
+ expect(emittedSignals).toHaveLength(0);
1221
+ });
1222
+
1223
+ test("trusted-contact host tools run inline once the guardian has already enabled computer access for the conversation", async () => {
1224
+ const conv = createConversation("trusted contact v2 host access enabled");
1225
+ updateConversationHostAccess(conv.id, true);
1226
+
1227
+ const result = await handler.checkPreExecutionGates(
1228
+ "bash",
1229
+ { command: "ls" },
1230
+ makeToolContext({
1231
+ trustClass: "trusted_contact",
1232
+ conversationId: conv.id,
1233
+ }),
1234
+ "host",
1235
+ "high",
1236
+ Date.now(),
1237
+ emitLifecycleEvent,
1238
+ );
1239
+
1240
+ expect(result.allowed).toBe(true);
1241
+ });
1242
+
1243
+ test("confirmation_request guardian bridge is disabled for trusted contacts under v2", () => {
1244
+ const canonicalRequest = createCanonicalGuardianRequest({
1245
+ id: `req-v2-skip-${Date.now()}`,
1246
+ kind: "tool_approval",
1247
+ sourceType: "channel",
1248
+ sourceChannel: "telegram",
1249
+ conversationId: "conv-v2-skip",
1250
+ requesterExternalUserId: "requester-1",
1251
+ guardianExternalUserId: "guardian-1",
1252
+ guardianPrincipalId: "test-principal-id",
1253
+ toolName: "bash",
1254
+ status: "pending",
1255
+ expiresAt: Date.now() + 5 * 60_000,
1256
+ });
1257
+
1258
+ const result = bridgeConfirmationRequestToGuardian({
1259
+ canonicalRequest,
1260
+ trustContext: makeTrustedContactTrustContext(),
1261
+ conversationId: "conv-v2-skip",
1262
+ toolName: "bash",
1263
+ });
1264
+
1265
+ expect("skipped" in result && result.skipped).toBe(true);
1266
+ if ("skipped" in result) {
1267
+ expect(result.reason).toBe("v2_model_mediated");
1268
+ }
1269
+ expect(emittedSignals).toHaveLength(0);
1270
+ });
1271
+ });