@vellumai/assistant 0.6.3 → 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 (667) hide show
  1. package/ARCHITECTURE.md +273 -10
  2. package/Dockerfile +2 -3
  3. package/bun.lock +5 -13
  4. package/docs/backup-troubleshooting.md +52 -0
  5. package/docs/browser-use-architecture-phase2.md +174 -0
  6. package/docs/stt-provider-onboarding.md +120 -0
  7. package/knip.json +12 -2
  8. package/node_modules/@vellumai/ces-contracts/bun.lock +8 -6
  9. package/node_modules/@vellumai/ces-contracts/package.json +3 -3
  10. package/openapi.yaml +982 -72
  11. package/package.json +4 -6
  12. package/scripts/generate-openapi.ts +0 -1
  13. package/scripts/test.sh +73 -18
  14. package/src/__tests__/agent-image-optimize.test.ts +28 -0
  15. package/src/__tests__/agent-loop.test.ts +123 -0
  16. package/src/__tests__/anthropic-provider.test.ts +263 -10
  17. package/src/__tests__/auto-analysis-end-to-end.test.ts +550 -0
  18. package/src/__tests__/auto-analysis-prompt.test.ts +50 -0
  19. package/src/__tests__/browser-fill-credential.test.ts +11 -0
  20. package/src/__tests__/browser-skill-baseline-tool-payload.test.ts +2 -2
  21. package/src/__tests__/browser-skill-endstate.test.ts +31 -7
  22. package/src/__tests__/btw-routes.test.ts +7 -0
  23. package/src/__tests__/call-controller.test.ts +581 -20
  24. package/src/__tests__/catalog-files.test.ts +138 -0
  25. package/src/__tests__/channel-invite-transport.test.ts +2 -2
  26. package/src/__tests__/channel-readiness-routes.test.ts +16 -20
  27. package/src/__tests__/channel-readiness-service.test.ts +12 -7
  28. package/src/__tests__/checker.test.ts +157 -10
  29. package/src/__tests__/clawhub-files.test.ts +347 -0
  30. package/src/__tests__/commit-message-enrichment-service.test.ts +36 -19
  31. package/src/__tests__/config-analysis.test.ts +100 -0
  32. package/src/__tests__/config-schema.test.ts +1013 -66
  33. package/src/__tests__/config-watcher-cleanup-throttle.test.ts +339 -0
  34. package/src/__tests__/config-watcher.test.ts +43 -8
  35. package/src/__tests__/contact-store-user-file.test.ts +512 -0
  36. package/src/__tests__/contacts-write.test.ts +197 -0
  37. package/src/__tests__/context-window-manager.test.ts +88 -0
  38. package/src/__tests__/conversation-abort-tool-results.test.ts +2 -0
  39. package/src/__tests__/conversation-agent-loop-overflow.test.ts +1 -0
  40. package/src/__tests__/conversation-agent-loop.test.ts +98 -2
  41. package/src/__tests__/conversation-confirmation-signals.test.ts +135 -0
  42. package/src/__tests__/conversation-error.test.ts +70 -0
  43. package/src/__tests__/conversation-history-web-search.test.ts +11 -4
  44. package/src/__tests__/conversation-init.benchmark.test.ts +6 -1
  45. package/src/__tests__/conversation-launcher-skill-regression.test.ts +51 -0
  46. package/src/__tests__/conversation-list-source.test.ts +145 -0
  47. package/src/__tests__/conversation-pre-run-repair.test.ts +2 -0
  48. package/src/__tests__/conversation-provider-retry-repair.test.ts +2 -0
  49. package/src/__tests__/conversation-queue.test.ts +901 -60
  50. package/src/__tests__/conversation-routes-disk-view.test.ts +270 -0
  51. package/src/__tests__/conversation-runtime-assembly.test.ts +55 -0
  52. package/src/__tests__/conversation-skill-tools.test.ts +7 -4
  53. package/src/__tests__/conversation-slash-commands.test.ts +33 -0
  54. package/src/__tests__/conversation-slash-queue.test.ts +89 -18
  55. package/src/__tests__/conversation-slash-unknown.test.ts +2 -0
  56. package/src/__tests__/conversation-tool-setup-batch-authorized.test.ts +226 -0
  57. package/src/__tests__/conversation-workspace-injection.test.ts +2 -0
  58. package/src/__tests__/conversation-workspace-tool-tracking.test.ts +2 -0
  59. package/src/__tests__/credential-health-service.test.ts +352 -0
  60. package/src/__tests__/credential-security-invariants.test.ts +5 -3
  61. package/src/__tests__/credential-vault-unit.test.ts +379 -3
  62. package/src/__tests__/credentials-cli.test.ts +40 -16
  63. package/src/__tests__/cross-provider-web-search.test.ts +146 -35
  64. package/src/__tests__/deterministic-verification-control-plane.test.ts +10 -1
  65. package/src/__tests__/device-id.test.ts +112 -0
  66. package/src/__tests__/docker-signing-key-bootstrap.test.ts +167 -4
  67. package/src/__tests__/dynamic-skill-workflow-prompt.test.ts +1 -3
  68. package/src/__tests__/email-html-renderer.test.ts +71 -0
  69. package/src/__tests__/email-invite-adapter.test.ts +36 -32
  70. package/src/__tests__/emit-event-signal.test.ts +71 -0
  71. package/src/__tests__/extension-id-sync-guard.test.ts +75 -8
  72. package/src/__tests__/fixtures/mock-chrome-extension.ts +11 -0
  73. package/src/__tests__/gateway-only-enforcement.test.ts +206 -1
  74. package/src/__tests__/gateway-only-guard.test.ts +0 -1
  75. package/src/__tests__/gemini-provider.test.ts +64 -0
  76. package/src/__tests__/get-skill-detail-audit.test.ts +325 -0
  77. package/src/__tests__/gmail-archive-fallback.test.ts +193 -0
  78. package/src/__tests__/gmail-archive-gate.test.ts +246 -0
  79. package/src/__tests__/gmail-preferences.test.ts +117 -0
  80. package/src/__tests__/headless-browser-interactions.test.ts +43 -0
  81. package/src/__tests__/headless-browser-mode.test.ts +614 -0
  82. package/src/__tests__/headless-browser-navigate.test.ts +142 -5
  83. package/src/__tests__/headless-browser-read-tools.test.ts +11 -0
  84. package/src/__tests__/headless-browser-snapshot.test.ts +10 -0
  85. package/src/__tests__/heartbeat-service.test.ts +70 -17
  86. package/src/__tests__/home-state-routes.test.ts +162 -0
  87. package/src/__tests__/host-bash-proxy.test.ts +0 -5
  88. package/src/__tests__/host-browser-e2e-cloud.test.ts +138 -4
  89. package/src/__tests__/host-browser-e2e-self-hosted.test.ts +4 -4
  90. package/src/__tests__/host-browser-ws-events-e2e.test.ts +103 -0
  91. package/src/__tests__/host-cu-proxy.test.ts +0 -5
  92. package/src/__tests__/identity-intro-cache.test.ts +40 -10
  93. package/src/__tests__/init-feature-flag-overrides.test.ts +38 -112
  94. package/src/__tests__/jobs-store-upsert-debounced.test.ts +141 -0
  95. package/src/__tests__/llm-context-normalization.test.ts +488 -0
  96. package/src/__tests__/llm-context-route-provider.test.ts +86 -5
  97. package/src/__tests__/llm-usage-store.test.ts +363 -0
  98. package/src/__tests__/media-stream-output.test.ts +555 -0
  99. package/src/__tests__/media-stream-parser.test.ts +374 -0
  100. package/src/__tests__/media-stream-server-integration.test.ts +1234 -0
  101. package/src/__tests__/media-stream-stt-session.test.ts +588 -0
  102. package/src/__tests__/media-turn-detector.test.ts +440 -0
  103. package/src/__tests__/message-queue.test.ts +125 -0
  104. package/src/__tests__/migration-export-http.test.ts +6 -6
  105. package/src/__tests__/migration-import-commit-http.test.ts +8 -6
  106. package/src/__tests__/migration-import-preflight-http.test.ts +6 -5
  107. package/src/__tests__/migration-validate-http.test.ts +3 -3
  108. package/src/__tests__/mock-gateway-ipc.ts +151 -0
  109. package/src/__tests__/model-intents.test.ts +2 -2
  110. package/src/__tests__/oauth-apps-routes.test.ts +1 -0
  111. package/src/__tests__/oauth-cli.test.ts +2 -0
  112. package/src/__tests__/oauth-connect-orchestrator.test.ts +2 -0
  113. package/src/__tests__/oauth-provider-serializer.test.ts +1 -0
  114. package/src/__tests__/oauth-providers-routes.test.ts +2 -0
  115. package/src/__tests__/oauth-store.test.ts +85 -0
  116. package/src/__tests__/oauth2-gateway-transport.test.ts +249 -6
  117. package/src/__tests__/onboarding-template-contract.test.ts +6 -13
  118. package/src/__tests__/openai-provider.test.ts +176 -0
  119. package/src/__tests__/openai-responses-cutover-guard.test.ts +184 -0
  120. package/src/__tests__/openai-responses-provider.test.ts +1105 -0
  121. package/src/__tests__/openrouter-token-estimation.test.ts +100 -0
  122. package/src/__tests__/outlook-unsubscribe.test.ts +31 -2
  123. package/src/__tests__/persona-resolver.test.ts +251 -0
  124. package/src/__tests__/platform-bash-auto-approve.test.ts +4 -0
  125. package/src/__tests__/platform.test.ts +92 -1
  126. package/src/__tests__/post-turn-tool-result-truncation.test.ts +47 -0
  127. package/src/__tests__/prechat-onboarding-contract.test.ts +267 -0
  128. package/src/__tests__/pricing.test.ts +174 -0
  129. package/src/__tests__/qdrant-manager.test.ts +29 -8
  130. package/src/__tests__/regenerate-fire-and-forget-trace.test.ts +194 -0
  131. package/src/__tests__/relationship-state-contract.test.ts +175 -0
  132. package/src/__tests__/relay-server.test.ts +423 -5
  133. package/src/__tests__/search-skills-unified.test.ts +118 -0
  134. package/src/__tests__/secret-scanner-executor.test.ts +4 -0
  135. package/src/__tests__/secure-keys.test.ts +107 -0
  136. package/src/__tests__/send-endpoint-busy.test.ts +5 -1
  137. package/src/__tests__/sequence-store.test.ts +1 -1
  138. package/src/__tests__/server-history-render.test.ts +49 -0
  139. package/src/__tests__/settings-routes.test.ts +201 -0
  140. package/src/__tests__/skill-load-feature-flag.test.ts +1 -0
  141. package/src/__tests__/skills-file-content-endpoint.test.ts +276 -145
  142. package/src/__tests__/skills-files-catalog-fallback.test.ts +381 -93
  143. package/src/__tests__/skills.test.ts +5 -2
  144. package/src/__tests__/skillssh-files.test.ts +446 -0
  145. package/src/__tests__/slack-block-formatting.test.ts +110 -0
  146. package/src/__tests__/slack-channel-config.test.ts +564 -1
  147. package/src/__tests__/stt-catalog-parity.test.ts +282 -0
  148. package/src/__tests__/stt-stream-session.test.ts +535 -0
  149. package/src/__tests__/system-prompt.test.ts +112 -26
  150. package/src/__tests__/telephony-stt-routing.test.ts +329 -0
  151. package/src/__tests__/terminal-tools.test.ts +18 -7
  152. package/src/__tests__/test-preload.ts +18 -0
  153. package/src/__tests__/test-support/browser-skill-harness.ts +4 -1
  154. package/src/__tests__/tool-executor-lifecycle-events.test.ts +9 -5
  155. package/src/__tests__/tool-executor-shell-integration.test.ts +4 -0
  156. package/src/__tests__/tool-executor.test.ts +33 -24
  157. package/src/__tests__/tool-result-truncation.test.ts +36 -0
  158. package/src/__tests__/trust-store.test.ts +7 -1
  159. package/src/__tests__/trusted-contact-approval-notifier.test.ts +1 -1
  160. package/src/__tests__/tts-catalog-parity.test.ts +345 -0
  161. package/src/__tests__/twilio-routes-twiml.test.ts +512 -114
  162. package/src/__tests__/twilio-routes.test.ts +376 -0
  163. package/src/__tests__/unicode.test.ts +293 -0
  164. package/src/__tests__/update-bulletin-format.test.ts +59 -0
  165. package/src/__tests__/update-bulletin.test.ts +206 -5
  166. package/src/__tests__/usage-routes.test.ts +25 -4
  167. package/src/__tests__/user-reference.test.ts +46 -61
  168. package/src/__tests__/verification-control-plane-policy.test.ts +4 -0
  169. package/src/__tests__/voice-config-update.test.ts +403 -0
  170. package/src/__tests__/voice-quality.test.ts +434 -19
  171. package/src/__tests__/workspace-heartbeat-service.test.ts +7 -0
  172. package/src/__tests__/workspace-migration-033-stt-service-explicit-config.test.ts +547 -0
  173. package/src/__tests__/workspace-migration-034-remove-calls-voice-transcription-provider.test.ts +596 -0
  174. package/src/__tests__/workspace-migration-drop-user-md.test.ts +368 -0
  175. package/src/__tests__/workspace-migration-meets.test.ts +244 -0
  176. package/src/__tests__/workspace-migration-seed-device-id.test.ts +14 -20
  177. package/src/__tests__/workspace-policy.test.ts +2 -0
  178. package/src/agent/image-optimize.ts +24 -12
  179. package/src/agent/loop.ts +43 -3
  180. package/src/backup/__tests__/backup-key.test.ts +152 -0
  181. package/src/backup/__tests__/backup-worker.test.ts +767 -0
  182. package/src/backup/__tests__/list-snapshots.test.ts +87 -0
  183. package/src/backup/__tests__/local-writer.test.ts +218 -0
  184. package/src/backup/__tests__/offsite-writer.test.ts +641 -0
  185. package/src/backup/__tests__/paths.test.ts +300 -0
  186. package/src/backup/__tests__/restore.test.ts +498 -0
  187. package/src/backup/__tests__/snapshot-lock.test.ts +352 -0
  188. package/src/backup/__tests__/stream-crypt.test.ts +228 -0
  189. package/src/backup/backup-key.ts +137 -0
  190. package/src/backup/backup-worker.ts +459 -0
  191. package/src/backup/list-snapshots.ts +147 -0
  192. package/src/backup/local-writer.ts +133 -0
  193. package/src/backup/offsite-writer.ts +222 -0
  194. package/src/backup/paths.ts +226 -0
  195. package/src/backup/restore.ts +322 -0
  196. package/src/backup/snapshot-lock.ts +431 -0
  197. package/src/backup/stream-crypt.ts +263 -0
  198. package/src/bundler/package-resolver.ts +4 -0
  199. package/src/calls/audio-store.ts +11 -5
  200. package/src/calls/call-controller.ts +226 -71
  201. package/src/calls/call-domain.ts +9 -0
  202. package/src/calls/call-speech-output.ts +190 -0
  203. package/src/calls/call-transport.ts +77 -0
  204. package/src/calls/media-stream-audio-transcode.ts +173 -0
  205. package/src/calls/media-stream-output.ts +660 -0
  206. package/src/calls/media-stream-parser.ts +300 -0
  207. package/src/calls/media-stream-protocol.ts +166 -0
  208. package/src/calls/media-stream-server.ts +592 -0
  209. package/src/calls/media-stream-stt-session.ts +460 -0
  210. package/src/calls/media-turn-detector.ts +230 -0
  211. package/src/calls/relay-server.ts +90 -75
  212. package/src/calls/resolve-call-tts-provider.ts +136 -0
  213. package/src/calls/telephony-stt-routing.ts +145 -0
  214. package/src/calls/tts-call-strategy.ts +161 -0
  215. package/src/calls/tts-text-sanitizer.ts +32 -16
  216. package/src/calls/twilio-routes.ts +281 -17
  217. package/src/calls/voice-quality.ts +78 -35
  218. package/src/calls/voice-session-bridge.ts +8 -1
  219. package/src/channels/types.ts +16 -0
  220. package/src/cli/__tests__/run-assistant-command.ts +11 -1
  221. package/src/cli/commands/__tests__/backup.test.ts +1165 -0
  222. package/src/cli/commands/__tests__/domain-register.test.ts +234 -0
  223. package/src/cli/commands/__tests__/domain-status.test.ts +132 -0
  224. package/src/cli/commands/__tests__/email-attachment.test.ts +422 -0
  225. package/src/cli/commands/__tests__/email-download.test.ts +16 -1
  226. package/src/cli/commands/__tests__/email-list.test.ts +22 -4
  227. package/src/cli/commands/__tests__/email-register.test.ts +4 -4
  228. package/src/cli/commands/__tests__/email-send.test.ts +37 -4
  229. package/src/cli/commands/__tests__/email-status.test.ts +5 -1
  230. package/src/cli/commands/__tests__/email-unregister.test.ts +34 -5
  231. package/src/cli/commands/backup.ts +993 -0
  232. package/src/cli/commands/conversations.ts +77 -0
  233. package/src/cli/commands/credentials.ts +0 -1
  234. package/src/cli/commands/domain.ts +210 -0
  235. package/src/cli/commands/email.ts +255 -3
  236. package/src/cli/commands/oauth/__tests__/connect.test.ts +12 -0
  237. package/src/cli/commands/oauth/__tests__/providers-delete.test.ts +1 -0
  238. package/src/cli/commands/oauth/__tests__/providers-register.test.ts +1 -0
  239. package/src/cli/commands/oauth/__tests__/providers-update.test.ts +1 -0
  240. package/src/cli/commands/oauth/mode.ts +12 -3
  241. package/src/cli/commands/oauth/providers.ts +15 -0
  242. package/src/cli/commands/oauth/shared.ts +2 -1
  243. package/src/cli/commands/platform/__tests__/callback-routes-list.test.ts +4 -9
  244. package/src/cli/commands/platform/__tests__/connect.test.ts +6 -0
  245. package/src/cli/commands/platform/__tests__/disconnect.test.ts +7 -1
  246. package/src/cli/commands/platform/__tests__/status.test.ts +6 -0
  247. package/src/cli/program.ts +30 -4
  248. package/src/config/__tests__/backup-schema.test.ts +134 -0
  249. package/src/config/assistant-feature-flags.ts +61 -62
  250. package/src/config/bundled-skills/app-builder/references/CUSTOM_ROUTES.md +37 -1
  251. package/src/config/bundled-skills/browser/SKILL.md +30 -5
  252. package/src/config/bundled-skills/browser/TOOLS.json +123 -0
  253. package/src/config/bundled-skills/browser/tools/browser-attach.ts +12 -0
  254. package/src/config/bundled-skills/browser/tools/browser-detach.ts +12 -0
  255. package/src/config/bundled-skills/browser/tools/browser-status.ts +12 -0
  256. package/src/config/bundled-skills/browser/tools/browser-wait-for-download.ts +17 -0
  257. package/src/config/bundled-skills/contacts/SKILL.md +2 -2
  258. package/src/config/bundled-skills/gmail/SKILL.md +53 -7
  259. package/src/config/bundled-skills/gmail/TOOLS.json +33 -3
  260. package/src/config/bundled-skills/gmail/tools/gmail-archive.ts +116 -9
  261. package/src/config/bundled-skills/gmail/tools/gmail-outreach-scan.ts +138 -11
  262. package/src/config/bundled-skills/gmail/tools/gmail-preferences-tool.ts +59 -0
  263. package/src/config/bundled-skills/gmail/tools/gmail-preferences.ts +82 -0
  264. package/src/config/bundled-skills/gmail/tools/gmail-sender-digest.ts +113 -17
  265. package/src/config/bundled-skills/gmail/tools/gmail-unsubscribe.ts +2 -2
  266. package/src/config/bundled-skills/media-processing/SKILL.md +3 -9
  267. package/src/config/bundled-skills/media-processing/TOOLS.json +1 -6
  268. package/src/config/bundled-skills/media-processing/__tests__/audio-transcribe.test.ts +125 -0
  269. package/src/config/bundled-skills/media-processing/__tests__/extract-keyframes.test.ts +181 -0
  270. package/src/config/bundled-skills/media-processing/__tests__/preprocess-audio.test.ts +141 -0
  271. package/src/config/bundled-skills/media-processing/services/audio-transcribe.ts +32 -87
  272. package/src/config/bundled-skills/media-processing/services/preprocess.ts +8 -4
  273. package/src/config/bundled-skills/media-processing/tools/extract-keyframes.ts +0 -10
  274. package/src/config/bundled-skills/messaging/SKILL.md +3 -3
  275. package/src/config/bundled-skills/messaging/tools/messaging-archive-by-sender.ts +2 -2
  276. package/src/config/bundled-skills/outlook/SKILL.md +2 -2
  277. package/src/config/bundled-skills/outlook/tools/outlook-unsubscribe.ts +2 -2
  278. package/src/config/bundled-skills/phone-calls/SKILL.md +2 -2
  279. package/src/config/bundled-skills/phone-calls/references/CONFIG.md +27 -18
  280. package/src/config/bundled-skills/phone-calls/references/TROUBLESHOOTING.md +3 -3
  281. package/src/config/bundled-skills/settings/TOOLS.json +3 -3
  282. package/src/config/bundled-skills/settings/tools/voice-config-update.ts +26 -22
  283. package/src/config/bundled-skills/slack/SKILL.md +1 -0
  284. package/src/config/bundled-skills/transcribe/SKILL.md +9 -14
  285. package/src/config/bundled-skills/transcribe/TOOLS.json +2 -7
  286. package/src/config/bundled-skills/transcribe/tools/transcribe-media.test.ts +256 -0
  287. package/src/config/bundled-skills/transcribe/tools/transcribe-media.ts +38 -188
  288. package/src/config/bundled-tool-registry.ts +8 -0
  289. package/src/config/env-registry.ts +24 -0
  290. package/src/config/env.ts +34 -10
  291. package/src/config/feature-flag-registry.json +46 -14
  292. package/src/config/loader.ts +26 -12
  293. package/src/config/schema.ts +35 -10
  294. package/src/config/schemas/__tests__/stt.test.ts +43 -0
  295. package/src/config/schemas/analysis.ts +51 -0
  296. package/src/config/schemas/backup.ts +72 -0
  297. package/src/config/schemas/calls.ts +1 -26
  298. package/src/config/schemas/elevenlabs.ts +0 -59
  299. package/src/config/schemas/filing.ts +47 -7
  300. package/src/config/schemas/heartbeat.ts +27 -5
  301. package/src/config/schemas/host-browser.ts +47 -1
  302. package/src/config/schemas/inference.ts +1 -1
  303. package/src/config/schemas/memory-lifecycle.ts +14 -2
  304. package/src/config/schemas/services.ts +44 -0
  305. package/src/config/schemas/stt.ts +59 -0
  306. package/src/config/schemas/tts.ts +230 -0
  307. package/src/config/schemas/updates.ts +14 -0
  308. package/src/config/skills.ts +4 -0
  309. package/src/config/types.ts +4 -0
  310. package/src/contacts/contact-store.ts +56 -11
  311. package/src/contacts/contacts-write.ts +38 -1
  312. package/src/context/post-turn-tool-result-truncation.ts +3 -2
  313. package/src/context/tool-result-truncation.ts +2 -1
  314. package/src/context/window-manager.ts +45 -12
  315. package/src/credential-execution/executable-discovery.ts +12 -2
  316. package/src/credential-execution/process-manager.ts +33 -2
  317. package/src/credential-health/credential-health-service.ts +366 -0
  318. package/src/daemon/__tests__/conversation-lifecycle-auto-analyze.test.ts +324 -0
  319. package/src/daemon/__tests__/conversation-surfaces-launch.test.ts +497 -0
  320. package/src/daemon/__tests__/conversation-tool-setup.test.ts +17 -8
  321. package/src/daemon/__tests__/lifecycle-startup-ordering.test.ts +127 -0
  322. package/src/daemon/config-watcher.ts +99 -5
  323. package/src/daemon/conversation-agent-loop-handlers.ts +6 -0
  324. package/src/daemon/conversation-agent-loop.ts +101 -24
  325. package/src/daemon/conversation-error.ts +11 -0
  326. package/src/daemon/conversation-history.ts +40 -6
  327. package/src/daemon/conversation-launch.ts +220 -0
  328. package/src/daemon/conversation-lifecycle.ts +59 -9
  329. package/src/daemon/conversation-messaging.ts +37 -3
  330. package/src/daemon/conversation-notifiers.ts +5 -0
  331. package/src/daemon/conversation-process.ts +581 -19
  332. package/src/daemon/conversation-queue-manager.ts +24 -0
  333. package/src/daemon/conversation-runtime-assembly.ts +11 -1
  334. package/src/daemon/conversation-slash.ts +36 -0
  335. package/src/daemon/conversation-surfaces.ts +94 -4
  336. package/src/daemon/conversation-tool-setup.ts +25 -0
  337. package/src/daemon/conversation-usage.ts +7 -4
  338. package/src/daemon/conversation.ts +86 -28
  339. package/src/daemon/handlers/config-slack-channel.ts +269 -94
  340. package/src/daemon/handlers/conversations.ts +4 -1
  341. package/src/daemon/handlers/shared.ts +22 -0
  342. package/src/daemon/handlers/skills.ts +321 -77
  343. package/src/daemon/host-browser-proxy.ts +2 -1
  344. package/src/daemon/lifecycle.ts +122 -25
  345. package/src/daemon/message-protocol.ts +6 -0
  346. package/src/daemon/message-types/conversations.ts +34 -1
  347. package/src/daemon/message-types/home.ts +40 -0
  348. package/src/daemon/message-types/meet.ts +143 -0
  349. package/src/daemon/message-types/messages.ts +14 -0
  350. package/src/daemon/message-types/schedules.ts +34 -2
  351. package/src/daemon/message-types/skills.ts +16 -0
  352. package/src/daemon/message-types/surfaces.ts +2 -0
  353. package/src/daemon/server.ts +347 -2
  354. package/src/daemon/shutdown-handlers.ts +32 -4
  355. package/src/daemon/shutdown-registry.ts +40 -0
  356. package/src/daemon/tool-side-effects.ts +9 -0
  357. package/src/email/html-renderer.ts +76 -0
  358. package/src/heartbeat/heartbeat-service.ts +93 -7
  359. package/src/home/__tests__/assistant-feed-authoring.test.ts +156 -0
  360. package/src/home/__tests__/emit-feed-event.test.ts +169 -0
  361. package/src/home/__tests__/feed-scheduler.test.ts +194 -0
  362. package/src/home/__tests__/feed-types.test.ts +275 -0
  363. package/src/home/__tests__/feed-writer.test.ts +688 -0
  364. package/src/home/__tests__/phase5-exit-criteria.test.ts +212 -0
  365. package/src/home/__tests__/platform-gmail-digest.test.ts +222 -0
  366. package/src/home/__tests__/progress-formula.test.ts +213 -0
  367. package/src/home/__tests__/relationship-state-writer.test.ts +740 -0
  368. package/src/home/__tests__/rollup-producer.test.ts +398 -0
  369. package/src/home/assistant-feed-authoring.ts +124 -0
  370. package/src/home/emit-feed-event.ts +158 -0
  371. package/src/home/feed-scheduler.ts +247 -0
  372. package/src/home/feed-types.ts +181 -0
  373. package/src/home/feed-writer.ts +469 -0
  374. package/src/home/platform-gmail-digest.ts +163 -0
  375. package/src/home/progress-formula.ts +86 -0
  376. package/src/home/relationship-state-writer.ts +824 -0
  377. package/src/home/relationship-state.ts +143 -0
  378. package/src/home/rollup-producer.ts +384 -0
  379. package/src/hooks/runner.ts +7 -0
  380. package/src/inbound/platform-callback-registration.ts +12 -3
  381. package/src/inbound/public-ingress-urls.ts +12 -0
  382. package/src/instrument.ts +1 -1
  383. package/src/ipc/__tests__/cli-ipc.test.ts +200 -0
  384. package/src/ipc/cli-client.ts +151 -0
  385. package/src/ipc/cli-server.ts +234 -0
  386. package/src/ipc/gateway-client.ts +180 -0
  387. package/src/ipc/routes/index.ts +5 -0
  388. package/src/ipc/routes/wake-conversation.ts +19 -0
  389. package/src/memory/__tests__/auto-analysis-enqueue.test.ts +356 -0
  390. package/src/memory/__tests__/auto-analysis-guard.test.ts +57 -0
  391. package/src/memory/__tests__/conversation-analyze-job.test.ts +232 -0
  392. package/src/memory/__tests__/find-analysis-conversation.test.ts +196 -0
  393. package/src/memory/app-store.ts +1 -1
  394. package/src/memory/attachments-store.ts +70 -0
  395. package/src/memory/auto-analysis-enqueue.ts +127 -0
  396. package/src/memory/auto-analysis-guard.ts +27 -0
  397. package/src/memory/cleanup-schedule-state.ts +37 -0
  398. package/src/memory/conversation-analyze-job.ts +73 -0
  399. package/src/memory/conversation-crud.ts +99 -0
  400. package/src/memory/conversation-disk-view.ts +7 -0
  401. package/src/memory/conversation-group-migration.ts +34 -2
  402. package/src/memory/conversation-queries.ts +6 -5
  403. package/src/memory/db-init.ts +6 -0
  404. package/src/memory/db-maintenance.ts +108 -0
  405. package/src/memory/db.ts +1 -0
  406. package/src/memory/graph/conversation-graph-memory.ts +15 -0
  407. package/src/memory/graph/extraction.test.ts +23 -0
  408. package/src/memory/graph/extraction.ts +8 -0
  409. package/src/memory/graph/retriever.ts +27 -18
  410. package/src/memory/graph/scoring.test.ts +186 -0
  411. package/src/memory/graph/scoring.ts +31 -1
  412. package/src/memory/graph/tools.ts +1 -1
  413. package/src/memory/group-crud.ts +6 -1
  414. package/src/memory/indexer.ts +95 -16
  415. package/src/memory/job-handlers/cleanup.ts +11 -8
  416. package/src/memory/job-handlers/conversation-starters.ts +16 -10
  417. package/src/memory/jobs-store.ts +64 -4
  418. package/src/memory/jobs-worker.ts +22 -9
  419. package/src/memory/llm-usage-store.ts +92 -56
  420. package/src/memory/migrations/219-oauth-providers-token-exchange-body-format.ts +15 -0
  421. package/src/memory/migrations/220-normalize-user-file-by-principal.ts +190 -0
  422. package/src/memory/migrations/221-conversations-archived-at.ts +16 -0
  423. package/src/memory/migrations/index.ts +6 -0
  424. package/src/memory/migrations/registry.ts +8 -0
  425. package/src/memory/qdrant-manager.ts +43 -16
  426. package/src/memory/schema/conversations.ts +2 -0
  427. package/src/memory/schema/oauth.ts +3 -0
  428. package/src/memory/usage-buckets.ts +396 -0
  429. package/src/messaging/providers/gmail/client.ts +57 -6
  430. package/src/messaging/providers/slack/__tests__/adapter-token-routing.test.ts +282 -0
  431. package/src/messaging/providers/slack/adapter.ts +143 -38
  432. package/src/messaging/providers/slack/client.ts +16 -0
  433. package/src/messaging/providers/slack/types.ts +4 -0
  434. package/src/notifications/decision-engine.ts +3 -3
  435. package/src/notifications/signal.ts +5 -0
  436. package/src/oauth/__tests__/identity-verifier.test.ts +1 -0
  437. package/src/oauth/byo-connection.test.ts +18 -1
  438. package/src/oauth/byo-connection.ts +3 -1
  439. package/src/oauth/connect-orchestrator.ts +2 -0
  440. package/src/oauth/connection-resolver.ts +6 -2
  441. package/src/oauth/connection.ts +2 -0
  442. package/src/oauth/oauth-store.ts +9 -0
  443. package/src/oauth/platform-connection.test.ts +98 -0
  444. package/src/oauth/platform-connection.ts +52 -31
  445. package/src/oauth/seed-providers.ts +7 -0
  446. package/src/permissions/checker.ts +16 -6
  447. package/src/permissions/defaults.ts +49 -1
  448. package/src/permissions/trust-store.ts +3 -3
  449. package/src/permissions/workspace-policy.ts +3 -0
  450. package/src/platform/client.test.ts +10 -0
  451. package/src/platform/sync-identity.ts +129 -0
  452. package/src/prompts/persona-resolver.ts +126 -2
  453. package/src/prompts/system-prompt.ts +59 -18
  454. package/src/prompts/templates/BOOTSTRAP.md +5 -5
  455. package/src/prompts/templates/SOUL.md +3 -1
  456. package/src/prompts/templates/UPDATES.md +12 -0
  457. package/src/prompts/templates/channels/slack.md +20 -0
  458. package/src/prompts/update-bulletin-format.ts +26 -9
  459. package/src/prompts/update-bulletin.ts +34 -23
  460. package/src/prompts/user-reference.ts +20 -17
  461. package/src/providers/__tests__/provider-secret-catalog.test.ts +42 -0
  462. package/src/providers/anthropic/client.ts +157 -61
  463. package/src/providers/fireworks/client.ts +2 -2
  464. package/src/providers/gemini/client.ts +9 -1
  465. package/src/providers/model-catalog.ts +6 -0
  466. package/src/providers/model-intents.ts +4 -4
  467. package/src/providers/ollama/client.ts +2 -2
  468. package/src/providers/openai/chat-completions-provider.ts +474 -0
  469. package/src/providers/openai/client.ts +25 -440
  470. package/src/providers/openai/responses-provider.ts +502 -0
  471. package/src/providers/openrouter/client.ts +101 -4
  472. package/src/providers/provider-secret-catalog.ts +139 -0
  473. package/src/providers/registry.ts +2 -2
  474. package/src/providers/retry.ts +14 -3
  475. package/src/providers/speech-to-text/__tests__/provider-catalog.test.ts +251 -0
  476. package/src/providers/speech-to-text/__tests__/resolve.test.ts +828 -0
  477. package/src/providers/speech-to-text/deepgram-realtime.test.ts +980 -0
  478. package/src/providers/speech-to-text/deepgram-realtime.ts +767 -0
  479. package/src/providers/speech-to-text/deepgram.test.ts +332 -0
  480. package/src/providers/speech-to-text/deepgram.ts +115 -0
  481. package/src/providers/speech-to-text/google-gemini-live-stream.test.ts +743 -0
  482. package/src/providers/speech-to-text/google-gemini-live-stream.ts +625 -0
  483. package/src/providers/speech-to-text/google-gemini.test.ts +226 -0
  484. package/src/providers/speech-to-text/google-gemini.ts +101 -0
  485. package/src/providers/speech-to-text/openai-whisper-stream.test.ts +564 -0
  486. package/src/providers/speech-to-text/openai-whisper-stream.ts +381 -0
  487. package/src/providers/speech-to-text/openai-whisper.test.ts +1 -37
  488. package/src/providers/speech-to-text/openai-whisper.ts +63 -33
  489. package/src/providers/speech-to-text/provider-catalog.ts +306 -0
  490. package/src/providers/speech-to-text/resolve.ts +386 -6
  491. package/src/providers/types.ts +9 -0
  492. package/src/runtime/AGENTS.md +43 -1
  493. package/src/runtime/__tests__/agent-wake.test.ts +831 -0
  494. package/src/runtime/__tests__/runtime-mode.test.ts +62 -0
  495. package/src/runtime/__tests__/slack-block-formatting.test.ts +481 -0
  496. package/src/runtime/agent-wake.ts +512 -0
  497. package/src/runtime/auth/__tests__/route-policy.test.ts +40 -0
  498. package/src/runtime/auth/route-policy.ts +30 -5
  499. package/src/runtime/auth/token-service.ts +56 -1
  500. package/src/runtime/btw-sidechain.ts +2 -0
  501. package/src/runtime/capability-tokens.ts +10 -10
  502. package/src/runtime/channel-invite-transport.ts +1 -1
  503. package/src/runtime/channel-invite-transports/email.ts +14 -6
  504. package/src/runtime/channel-readiness-service.ts +12 -22
  505. package/src/runtime/chrome-extension-registry.ts +38 -2
  506. package/src/runtime/http-server.ts +395 -10
  507. package/src/runtime/http-types.ts +6 -2
  508. package/src/runtime/migrations/__tests__/vbundle-import-credentials.test.ts +36 -0
  509. package/src/runtime/migrations/__tests__/vbundle-legacy-user-md.test.ts +360 -0
  510. package/src/runtime/migrations/migration-transport.ts +1 -0
  511. package/src/runtime/migrations/migration-wizard.ts +1 -0
  512. package/src/runtime/migrations/vbundle-import-analyzer.ts +77 -1
  513. package/src/runtime/migrations/vbundle-importer.ts +34 -0
  514. package/src/runtime/pending-interactions.ts +0 -11
  515. package/src/runtime/routes/__tests__/backup-routes.test.ts +967 -0
  516. package/src/runtime/routes/__tests__/home-feed-routes.test.ts +507 -0
  517. package/src/runtime/routes/__tests__/migration-import-credential-filter.test.ts +208 -0
  518. package/src/runtime/routes/__tests__/stt-routes.test.ts +406 -0
  519. package/src/runtime/routes/__tests__/tts-routes.test.ts +474 -0
  520. package/src/runtime/routes/__tests__/user-route-dispatcher.test.ts +148 -17
  521. package/src/runtime/routes/app-management-routes.ts +12 -18
  522. package/src/runtime/routes/attachment-routes.test.ts +9 -3
  523. package/src/runtime/routes/attachment-routes.ts +216 -17
  524. package/src/runtime/routes/backup-routes.ts +519 -0
  525. package/src/runtime/routes/browser-extension-pair-routes.ts +82 -23
  526. package/src/runtime/routes/btw-routes.ts +8 -6
  527. package/src/runtime/routes/contact-routes.test.ts +298 -0
  528. package/src/runtime/routes/contact-routes.ts +132 -5
  529. package/src/runtime/routes/conversation-analysis-routes.ts +22 -142
  530. package/src/runtime/routes/conversation-management-routes.ts +115 -0
  531. package/src/runtime/routes/conversation-routes.ts +367 -146
  532. package/src/runtime/routes/filing-routes.ts +93 -0
  533. package/src/runtime/routes/home-feed-routes.ts +334 -0
  534. package/src/runtime/routes/home-state-routes.ts +138 -0
  535. package/src/runtime/routes/host-browser-routes.ts +3 -14
  536. package/src/runtime/routes/identity-intro-cache.ts +7 -3
  537. package/src/runtime/routes/identity-routes.ts +3 -17
  538. package/src/runtime/routes/inbound-stages/transcribe-audio.test.ts +46 -39
  539. package/src/runtime/routes/inbound-stages/transcribe-audio.ts +15 -15
  540. package/src/runtime/routes/integrations/slack/__tests__/channel.test.ts +137 -0
  541. package/src/runtime/routes/integrations/slack/__tests__/share.test.ts +179 -0
  542. package/src/runtime/routes/integrations/slack/channel.ts +11 -3
  543. package/src/runtime/routes/integrations/slack/share.ts +45 -7
  544. package/src/runtime/routes/llm-context-normalization.ts +303 -0
  545. package/src/runtime/routes/memory-item-routes.test.ts +3 -2
  546. package/src/runtime/routes/migration-routes.ts +40 -5
  547. package/src/runtime/routes/settings-routes.ts +22 -5
  548. package/src/runtime/routes/skills-routes.ts +76 -7
  549. package/src/runtime/routes/stt-routes.ts +233 -0
  550. package/src/runtime/routes/surface-action-routes.ts +41 -2
  551. package/src/runtime/routes/tts-routes.ts +108 -24
  552. package/src/runtime/routes/usage-routes.ts +30 -2
  553. package/src/runtime/routes/user-route-dispatcher.ts +50 -5
  554. package/src/runtime/routes/user-routes.ts +13 -1
  555. package/src/runtime/routes/work-items-routes.ts +8 -1
  556. package/src/runtime/runtime-mode.ts +33 -0
  557. package/src/runtime/services/__tests__/analyze-conversation.test.ts +444 -0
  558. package/src/runtime/services/__tests__/analyze-deps-singleton.test.ts +67 -0
  559. package/src/runtime/services/__tests__/auto-analysis-prompt.test.ts +53 -0
  560. package/src/runtime/services/__tests__/manual-analysis-prompt.test.ts +41 -0
  561. package/src/runtime/services/analyze-conversation.ts +344 -0
  562. package/src/runtime/services/analyze-deps-singleton.ts +32 -0
  563. package/src/runtime/services/auto-analysis-prompt.ts +55 -0
  564. package/src/runtime/skill-route-registry.ts +49 -0
  565. package/src/runtime/slack-block-formatting.ts +437 -10
  566. package/src/schedule/scheduler.ts +50 -0
  567. package/src/security/oauth2.ts +26 -4
  568. package/src/security/secure-keys.ts +25 -2
  569. package/src/security/token-manager.ts +8 -0
  570. package/src/sequence/engine.ts +23 -0
  571. package/src/sequence/types.ts +1 -1
  572. package/src/skills/catalog-files.ts +64 -2
  573. package/src/skills/category-inference.ts +122 -0
  574. package/src/skills/clawhub-files.ts +213 -0
  575. package/src/skills/clawhub.ts +84 -23
  576. package/src/skills/skill-file-provider.ts +40 -0
  577. package/src/skills/skillssh-files.ts +395 -0
  578. package/src/skills/skillssh-registry.ts +4 -4
  579. package/src/stt/__tests__/daemon-batch-transcriber.test.ts +392 -0
  580. package/src/stt/__tests__/types.test.ts +89 -0
  581. package/src/stt/daemon-batch-transcriber.ts +195 -0
  582. package/src/stt/stt-stream-session.ts +499 -0
  583. package/src/stt/types.ts +330 -0
  584. package/src/stt/wav-encoder.test.ts +373 -0
  585. package/src/stt/wav-encoder.ts +175 -0
  586. package/src/subagent/manager.ts +38 -14
  587. package/src/tools/browser/__tests__/browser-mode.test.ts +119 -0
  588. package/src/tools/browser/__tests__/browser-status.test.ts +123 -0
  589. package/src/tools/browser/browser-execution.ts +1163 -23
  590. package/src/tools/browser/browser-manager.ts +45 -0
  591. package/src/tools/browser/browser-mode-constants.ts +12 -0
  592. package/src/tools/browser/browser-mode.ts +92 -0
  593. package/src/tools/browser/browser-status-constants.ts +33 -0
  594. package/src/tools/browser/cdp-client/__tests__/cdp-inspect-client.test.ts +393 -0
  595. package/src/tools/browser/cdp-client/__tests__/extension-cdp-client.test.ts +29 -0
  596. package/src/tools/browser/cdp-client/__tests__/factory.test.ts +1648 -32
  597. package/src/tools/browser/cdp-client/cdp-inspect/__tests__/discovery.test.ts +264 -0
  598. package/src/tools/browser/cdp-client/cdp-inspect/discovery.ts +183 -17
  599. package/src/tools/browser/cdp-client/cdp-inspect-client.ts +254 -21
  600. package/src/tools/browser/cdp-client/errors.ts +15 -0
  601. package/src/tools/browser/cdp-client/extension-cdp-client.ts +39 -16
  602. package/src/tools/browser/cdp-client/factory.ts +797 -87
  603. package/src/tools/browser/cdp-client/index.ts +16 -2
  604. package/src/tools/browser/cdp-client/types.ts +68 -0
  605. package/src/tools/credentials/vault.ts +35 -6
  606. package/src/tools/network/web-fetch.ts +5 -2
  607. package/src/tools/network/web-search.ts +5 -2
  608. package/src/tools/shared/shell-output.ts +3 -1
  609. package/src/tools/side-effects.ts +2 -0
  610. package/src/tools/skills/sandbox-runner.ts +3 -2
  611. package/src/tools/terminal/safe-env.ts +10 -2
  612. package/src/tools/terminal/shell.ts +15 -4
  613. package/src/tools/tool-manifest.ts +21 -0
  614. package/src/tools/types.ts +17 -0
  615. package/src/tools/ui-surface/definitions.ts +6 -1
  616. package/src/tts/__tests__/provider-adapters.test.ts +834 -0
  617. package/src/tts/__tests__/provider-catalog-consistency.test.ts +196 -0
  618. package/src/tts/__tests__/provider-catalog.test.ts +183 -0
  619. package/src/tts/__tests__/provider-registry.test.ts +90 -0
  620. package/src/tts/provider-catalog.ts +201 -0
  621. package/src/tts/provider-registry.ts +73 -0
  622. package/src/tts/providers/deepgram-provider.ts +219 -0
  623. package/src/tts/providers/elevenlabs-provider.ts +211 -0
  624. package/src/tts/providers/fish-audio-provider.ts +183 -0
  625. package/src/tts/providers/index.ts +42 -0
  626. package/src/tts/providers/register-builtins.ts +130 -0
  627. package/src/tts/synthesize-text.ts +110 -0
  628. package/src/tts/tts-config-resolver.ts +78 -0
  629. package/src/tts/types.ts +153 -0
  630. package/src/types/onboarding-context.ts +7 -0
  631. package/src/util/abort-reasons.ts +58 -0
  632. package/src/util/device-id.ts +32 -16
  633. package/src/util/errors.ts +9 -1
  634. package/src/util/platform.ts +54 -10
  635. package/src/util/pricing.ts +66 -3
  636. package/src/util/spawn.ts +1 -1
  637. package/src/util/truncate.ts +4 -2
  638. package/src/util/unicode.ts +201 -0
  639. package/src/version.ts +19 -24
  640. package/src/watcher/engine.ts +23 -0
  641. package/src/watcher/watcher-store.ts +31 -0
  642. package/src/workspace/migrations/003-seed-device-id.ts +9 -3
  643. package/src/workspace/migrations/017-seed-persona-dirs.ts +68 -4
  644. package/src/workspace/migrations/029-seed-pkb.ts +1 -1
  645. package/src/workspace/migrations/031-drop-user-md.ts +317 -0
  646. package/src/workspace/migrations/031-llm-log-retention-zero-to-null.ts +73 -0
  647. package/src/workspace/migrations/032-tts-provider-unification.ts +227 -0
  648. package/src/workspace/migrations/033-stt-service-explicit-config.ts +122 -0
  649. package/src/workspace/migrations/034-remove-calls-voice-transcription-provider.ts +215 -0
  650. package/src/workspace/migrations/035-seed-slack-channel-persona.ts +50 -0
  651. package/src/workspace/migrations/036-update-pkb-index-bar.ts +37 -0
  652. package/src/workspace/migrations/037-create-meets-dir.ts +61 -0
  653. package/src/workspace/migrations/registry.ts +16 -0
  654. package/src/workspace/top-level-renderer.ts +13 -1
  655. package/src/workspace/turn-commit.ts +31 -0
  656. package/src/__tests__/email-cli.test.ts +0 -297
  657. package/src/__tests__/email-service-config-fallback.test.ts +0 -102
  658. package/src/cli/commands/browser-relay.ts +0 -466
  659. package/src/email/guardrails.ts +0 -221
  660. package/src/email/provider.ts +0 -117
  661. package/src/email/providers/agentmail.ts +0 -361
  662. package/src/email/providers/index.ts +0 -65
  663. package/src/email/service.ts +0 -384
  664. package/src/email/types.ts +0 -126
  665. package/src/prompts/templates/USER.md +0 -13
  666. package/src/providers/speech-to-text/types.ts +0 -17
  667. package/src/runtime/routes/browser-cdp-routes.ts +0 -229
@@ -112,6 +112,168 @@ export function normalizeLlmContextPayloads(
112
112
  function normalizeOpenAiRequestPayload(
113
113
  requestPayload: unknown,
114
114
  allowPlainText = false,
115
+ ): NormalizedPayloadCandidate | null {
116
+ // Try Responses API shape first, then fall back to chat-completions.
117
+ return (
118
+ normalizeOpenAiResponsesRequestPayload(requestPayload, allowPlainText) ??
119
+ normalizeOpenAiChatCompletionsRequestPayload(requestPayload, allowPlainText)
120
+ );
121
+ }
122
+
123
+ /**
124
+ * Detect and normalize OpenAI Responses API request payloads.
125
+ *
126
+ * Responses requests use `input` (array) instead of `messages`, may have a
127
+ * top-level `instructions` string, and tools have `type: "function"` at the
128
+ * top level with the function fields inlined (no nested `function` wrapper).
129
+ */
130
+ function normalizeOpenAiResponsesRequestPayload(
131
+ requestPayload: unknown,
132
+ allowPlainText = false,
133
+ ): NormalizedPayloadCandidate | null {
134
+ const request = asRecord(requestPayload);
135
+ if (!request) {
136
+ return null;
137
+ }
138
+
139
+ const input = asRecordArray(request.input);
140
+ if (!input) {
141
+ return null;
142
+ }
143
+
144
+ // Require at least one Responses-specific signal to avoid matching generic
145
+ // arrays. `instructions` is the strongest signal; otherwise look for
146
+ // Responses-shaped input items or tool objects.
147
+ const hasResponsesSignal =
148
+ typeof request.instructions === "string" ||
149
+ hasOpenAiModelPrefix(asString(request.model)) ||
150
+ input.some(
151
+ (item) =>
152
+ asString(item.type) === "function_call" ||
153
+ asString(item.type) === "function_call_output",
154
+ ) ||
155
+ extractOpenAiResponsesRequestToolNames(request.tools).length > 0;
156
+
157
+ if (!allowPlainText && !hasResponsesSignal) {
158
+ return null;
159
+ }
160
+
161
+ const requestSections: LlmContextSection[] = [];
162
+
163
+ // System-level instructions
164
+ const instructions = asString(request.instructions);
165
+ if (instructions && hasMeaningfulText(instructions)) {
166
+ requestSections.push({
167
+ kind: "system",
168
+ label: "System prompt",
169
+ role: "system",
170
+ text: instructions,
171
+ });
172
+ }
173
+
174
+ // Input items
175
+ let messageIndex = 0;
176
+ for (const item of input) {
177
+ const itemType = asString(item.type);
178
+
179
+ if (itemType === "message") {
180
+ messageIndex++;
181
+ const role = asString(item.role) ?? "unknown";
182
+ const messageText = extractOpenAiContentText(item.content);
183
+ if (messageText !== undefined) {
184
+ requestSections.push({
185
+ kind: "message",
186
+ label: buildMessageLabel(role, messageIndex),
187
+ role,
188
+ text: messageText,
189
+ });
190
+ }
191
+ continue;
192
+ }
193
+
194
+ if (itemType === "function_call") {
195
+ const name = asString(item.name);
196
+ const args = parseJsonValue(asString(item.arguments));
197
+ requestSections.push({
198
+ kind: "function_call",
199
+ label: `Request tool call${name ? ` (${name})` : ""}`,
200
+ role: "assistant",
201
+ toolName: name,
202
+ data: args,
203
+ text: previewStructuredValue(args),
204
+ });
205
+ continue;
206
+ }
207
+
208
+ if (itemType === "function_call_output") {
209
+ const output = asString(item.output);
210
+ requestSections.push({
211
+ kind: "tool_result",
212
+ label: `Tool result${asString(item.call_id) ? ` (${asString(item.call_id)})` : ""}`,
213
+ role: "tool",
214
+ toolName: asString(item.call_id),
215
+ text: output,
216
+ });
217
+ }
218
+ }
219
+
220
+ // Tool definitions (Responses shape: top-level type/name/parameters)
221
+ const requestToolNames = extractOpenAiResponsesRequestToolNames(
222
+ request.tools,
223
+ );
224
+ if (requestToolNames.length > 0) {
225
+ requestSections.push({
226
+ kind: "tool_definitions",
227
+ label: "Available tools",
228
+ data: {
229
+ tools: asRecordArray(request.tools) ?? request.tools,
230
+ },
231
+ language: "json",
232
+ });
233
+ }
234
+
235
+ const requestSettings = omitRecordKeys(request, [
236
+ "instructions",
237
+ "input",
238
+ "tools",
239
+ ]);
240
+ if (hasMeaningfulRequestSettings(requestSettings)) {
241
+ requestSections.push(
242
+ structuredJsonSection("settings", "Request settings", requestSettings),
243
+ );
244
+ }
245
+
246
+ // Count all input items for the message count (includes messages, function
247
+ // calls, and function call outputs — mirrors how chat-completions counts
248
+ // all messages regardless of role).
249
+ return {
250
+ provider: "openai",
251
+ summary: {
252
+ provider: "openai",
253
+ model: asString(request.model),
254
+ inputTokens: undefined,
255
+ outputTokens: undefined,
256
+ cacheCreationInputTokens: undefined,
257
+ cacheReadInputTokens: undefined,
258
+ stopReason: undefined,
259
+ requestMessageCount: input.length,
260
+ requestToolCount: requestToolNames.length,
261
+ responseMessageCount: undefined,
262
+ responseToolCallCount: undefined,
263
+ responsePreview: undefined,
264
+ toolCallNames: undefined,
265
+ },
266
+ requestSections: requestSections.length > 0 ? requestSections : undefined,
267
+ };
268
+ }
269
+
270
+ /**
271
+ * Normalize a legacy OpenAI Chat Completions request payload.
272
+ * Requires `messages` array in the request.
273
+ */
274
+ function normalizeOpenAiChatCompletionsRequestPayload(
275
+ requestPayload: unknown,
276
+ allowPlainText = false,
115
277
  ): NormalizedPayloadCandidate | null {
116
278
  const request = asRecord(requestPayload);
117
279
  if (!request) {
@@ -202,6 +364,130 @@ function normalizeOpenAiRequestPayload(
202
364
 
203
365
  function normalizeOpenAiResponsePayload(
204
366
  responsePayload: unknown,
367
+ ): NormalizedPayloadCandidate | null {
368
+ // Try Responses API shape first, then fall back to chat-completions.
369
+ return (
370
+ normalizeOpenAiResponsesResponsePayload(responsePayload) ??
371
+ normalizeOpenAiChatCompletionsResponsePayload(responsePayload)
372
+ );
373
+ }
374
+
375
+ /**
376
+ * Detect and normalize OpenAI Responses API response payloads.
377
+ *
378
+ * Responses responses have an `output` array of items instead of `choices`.
379
+ * Tool calls are top-level items with `type: "function_call"`.
380
+ * Usage uses `input_tokens`/`output_tokens` (not `prompt_tokens`/`completion_tokens`).
381
+ * `status` replaces `choices[0].finish_reason`.
382
+ */
383
+ function normalizeOpenAiResponsesResponsePayload(
384
+ responsePayload: unknown,
385
+ ): NormalizedPayloadCandidate | null {
386
+ const response = asRecord(responsePayload);
387
+ if (!response) {
388
+ return null;
389
+ }
390
+
391
+ const output = asRecordArray(response.output);
392
+ if (!output) {
393
+ return null;
394
+ }
395
+
396
+ // Require at least one Responses-specific signal
397
+ const hasResponsesSignal =
398
+ typeof response.status === "string" ||
399
+ hasOpenAiModelPrefix(asString(response.model)) ||
400
+ output.some(
401
+ (item) =>
402
+ asString(item.type) === "message" ||
403
+ asString(item.type) === "function_call",
404
+ );
405
+ if (!hasResponsesSignal) {
406
+ return null;
407
+ }
408
+
409
+ const responseSections: LlmContextSection[] = [];
410
+ let responseText: string | undefined;
411
+ const toolCallSections: LlmContextSection[] = [];
412
+ let toolCallIndex = 0;
413
+
414
+ for (const item of output) {
415
+ const itemType = asString(item.type);
416
+
417
+ if (itemType === "message") {
418
+ const role = asString(item.role) ?? "assistant";
419
+ const content = asRecordArray(item.content);
420
+ const text = content ? extractOpenAiContentText(content) : undefined;
421
+ if (text !== undefined) {
422
+ responseText = text;
423
+ responseSections.push({
424
+ kind: "message",
425
+ label: "Assistant response",
426
+ role,
427
+ text,
428
+ });
429
+ }
430
+ continue;
431
+ }
432
+
433
+ if (itemType === "function_call") {
434
+ toolCallIndex++;
435
+ const name = asString(item.name);
436
+ const args = parseJsonValue(asString(item.arguments));
437
+ const section: LlmContextSection = {
438
+ kind: "function_call",
439
+ label: `Response tool call ${toolCallIndex}`,
440
+ role: "assistant",
441
+ toolName: name,
442
+ data: args,
443
+ text: previewStructuredValue(args),
444
+ };
445
+ toolCallSections.push(section);
446
+ responseSections.push(section);
447
+ }
448
+ }
449
+
450
+ const usage = asRecord(response.usage);
451
+ const toolCallNames = toolCallSections
452
+ .map((section) => section.toolName)
453
+ .filter((name): name is string => typeof name === "string");
454
+
455
+ // Map Responses API status to a stop reason string.
456
+ const status = asString(response.status);
457
+ const stopReason = status === "completed" ? "stop" : status;
458
+
459
+ return {
460
+ provider: "openai",
461
+ summary: {
462
+ provider: "openai",
463
+ model: asString(response.model),
464
+ inputTokens: asNumber(usage?.input_tokens),
465
+ outputTokens: asNumber(usage?.output_tokens),
466
+ cacheCreationInputTokens: undefined,
467
+ cacheReadInputTokens: undefined,
468
+ stopReason,
469
+ requestMessageCount: undefined,
470
+ requestToolCount: undefined,
471
+ responseMessageCount:
472
+ responseText !== undefined || toolCallSections.length > 0
473
+ ? 1
474
+ : undefined,
475
+ responseToolCallCount:
476
+ toolCallSections.length > 0 ? toolCallSections.length : undefined,
477
+ responsePreview: responseText ? truncateText(responseText) : undefined,
478
+ toolCallNames: toolCallNames.length > 0 ? toolCallNames : undefined,
479
+ },
480
+ responseSections:
481
+ responseSections.length > 0 ? responseSections : undefined,
482
+ };
483
+ }
484
+
485
+ /**
486
+ * Normalize a legacy OpenAI Chat Completions response payload.
487
+ * Requires `choices` array in the response.
488
+ */
489
+ function normalizeOpenAiChatCompletionsResponsePayload(
490
+ responsePayload: unknown,
205
491
  ): NormalizedPayloadCandidate | null {
206
492
  const response = asRecord(responsePayload);
207
493
  if (!response) {
@@ -739,6 +1025,23 @@ function extractOpenAiRequestToolNames(tools: unknown): string[] {
739
1025
  .filter((name): name is string => typeof name === "string");
740
1026
  }
741
1027
 
1028
+ /**
1029
+ * Extract tool names from Responses API tool definitions.
1030
+ * Responses tools have `type: "function"` at the top level with `name`
1031
+ * directly on the tool object (no nested `function` wrapper).
1032
+ */
1033
+ function extractOpenAiResponsesRequestToolNames(tools: unknown): string[] {
1034
+ return (asRecordArray(tools) ?? [])
1035
+ .map((tool) => {
1036
+ // Responses shape: { type: "function", name: "...", ... }
1037
+ if (asString(tool.type) === "function" && asString(tool.name)) {
1038
+ return asString(tool.name);
1039
+ }
1040
+ return undefined;
1041
+ })
1042
+ .filter((name): name is string => typeof name === "string");
1043
+ }
1044
+
742
1045
  function extractAnthropicToolNames(tools: unknown): string[] {
743
1046
  return (asRecordArray(tools) ?? [])
744
1047
  .map((tool) => asString(tool.name))
@@ -868,14 +868,15 @@ describe("Memory Item Routes", () => {
868
868
  const res = await handler(ctx);
869
869
  expect(res.status).toBe(204);
870
870
 
871
- // Verify the node is gone
871
+ // Verify the node is soft-deleted (fidelity='gone')
872
872
  const db = getDb();
873
873
  const node = db
874
874
  .select()
875
875
  .from(memoryGraphNodes)
876
876
  .where(eq(memoryGraphNodes.id, "i1"))
877
877
  .get();
878
- expect(node).toBeUndefined();
878
+ expect(node).toBeDefined();
879
+ expect(node?.fidelity).toBe("gone");
879
880
  });
880
881
 
881
882
  test("returns 404 for non-existent item", async () => {
@@ -45,6 +45,9 @@ import {
45
45
  } from "../migrations/vbundle-importer.js";
46
46
  import { validateVBundle } from "../migrations/vbundle-validator.js";
47
47
 
48
+ /** Credentials with this prefix are platform-identity keys and must not be imported. */
49
+ const PLATFORM_CREDENTIAL_PREFIX = "vellum:";
50
+
48
51
  const log = getLogger("migration-routes");
49
52
 
50
53
  /**
@@ -483,6 +486,7 @@ export async function handleMigrationImport(req: Request): Promise<Response> {
483
486
  succeeded: number;
484
487
  failed: number;
485
488
  failedAccounts: string[];
489
+ skippedPlatform: number;
486
490
  }
487
491
  | undefined;
488
492
 
@@ -491,9 +495,22 @@ export async function handleMigrationImport(req: Request): Promise<Response> {
491
495
  validation.entries,
492
496
  validation.manifest!,
493
497
  );
494
- if (bundleCredentials.length > 0) {
498
+
499
+ // Filter out platform-identity credentials (vellum:*) — these are
500
+ // environment-specific and must not overwrite the target's own identity.
501
+ const userCredentials = bundleCredentials.filter(
502
+ (c) => !c.account.startsWith(PLATFORM_CREDENTIAL_PREFIX),
503
+ );
504
+ const skippedPlatform = bundleCredentials.length - userCredentials.length;
505
+ if (skippedPlatform > 0) {
506
+ log.info(
507
+ `Skipped ${skippedPlatform} platform credential(s) from import`,
508
+ );
509
+ }
510
+
511
+ if (userCredentials.length > 0) {
495
512
  try {
496
- const credResults = await bulkSetSecureKeysAsync(bundleCredentials);
513
+ const credResults = await bulkSetSecureKeysAsync(userCredentials);
497
514
  const failedResults = credResults.filter((r) => !r.ok);
498
515
  if (failedResults.length > 0) {
499
516
  log.warn(
@@ -502,15 +519,16 @@ export async function handleMigrationImport(req: Request): Promise<Response> {
502
519
  );
503
520
  }
504
521
  log.info(
505
- { total: bundleCredentials.length, failed: failedResults.length },
522
+ { total: userCredentials.length, failed: failedResults.length },
506
523
  "Credential import complete",
507
524
  );
508
- const succeeded = bundleCredentials.length - failedResults.length;
525
+ const succeeded = userCredentials.length - failedResults.length;
509
526
  credentialsImported = {
510
- total: bundleCredentials.length,
527
+ total: userCredentials.length,
511
528
  succeeded,
512
529
  failed: failedResults.length,
513
530
  failedAccounts: failedResults.map((f) => f.account),
531
+ skippedPlatform,
514
532
  };
515
533
  if (failedResults.length > 0) {
516
534
  result.report.warnings.push(
@@ -522,7 +540,24 @@ export async function handleMigrationImport(req: Request): Promise<Response> {
522
540
  result.report.warnings.push(
523
541
  `Credential import failed: ${err instanceof Error ? err.message : String(err)}`,
524
542
  );
543
+ credentialsImported = {
544
+ total: userCredentials.length,
545
+ succeeded: 0,
546
+ failed: userCredentials.length,
547
+ failedAccounts: userCredentials.map((c) => c.account),
548
+ skippedPlatform,
549
+ };
525
550
  }
551
+ } else if (skippedPlatform > 0) {
552
+ // All credentials in the bundle were platform credentials — report
553
+ // the skip count even though nothing was sent to CES.
554
+ credentialsImported = {
555
+ total: userCredentials.length,
556
+ succeeded: 0,
557
+ failed: 0,
558
+ failedAccounts: [],
559
+ skippedPlatform,
560
+ };
526
561
  }
527
562
  }
528
563
 
@@ -8,7 +8,7 @@
8
8
  */
9
9
 
10
10
  import { readFileSync } from "node:fs";
11
- import { join } from "node:path";
11
+ import { basename, join } from "node:path";
12
12
 
13
13
  import { z } from "zod";
14
14
 
@@ -36,6 +36,8 @@ import {
36
36
  generateAllowlistOptions,
37
37
  generateScopeOptions,
38
38
  } from "../../permissions/checker.js";
39
+ import { resolveGuardianPersonaPath } from "../../prompts/persona-resolver.js";
40
+ import type { ToolDefinition } from "../../providers/types.js";
39
41
  import { getSecureKeyAsync } from "../../security/secure-keys.js";
40
42
  import { parseToolManifestFile } from "../../skills/tool-manifest.js";
41
43
  import {
@@ -314,16 +316,31 @@ async function handleOAuthConnectStart(body: {
314
316
  // Workspace files (list/read)
315
317
  // ---------------------------------------------------------------------------
316
318
 
317
- const WORKSPACE_FILES = ["IDENTITY.md", "SOUL.md", "USER.md", "skills/"];
319
+ /**
320
+ * Build the list of workspace files exposed via the workspace-files endpoint.
321
+ *
322
+ * Returns the static identity/soul files and skills directory plus the
323
+ * guardian's resolved per-user persona file at `users/<slug>.md` when a
324
+ * guardian exists. Callers should invoke this per-request instead of
325
+ * caching, since the guardian can change over the lifetime of the daemon.
326
+ */
327
+ function getWorkspaceFiles(): string[] {
328
+ const files = ["IDENTITY.md", "SOUL.md", "skills/"];
329
+ const guardianPath = resolveGuardianPersonaPath();
330
+ if (guardianPath) {
331
+ files.push(`users/${basename(guardianPath)}`);
332
+ }
333
+ return files;
334
+ }
318
335
 
319
336
  function handleWorkspaceFilesList(): Response {
320
337
  const base = getWorkspaceDir();
321
- const files = WORKSPACE_FILES.map((name) => ({
338
+ const files = getWorkspaceFiles().map((name) => ({
322
339
  path: name,
323
340
  name,
324
341
  exists: pathExists(join(base, name)),
325
342
  }));
326
- return Response.json({ files });
343
+ return Response.json({ type: "workspace_files_list_response", files });
327
344
  }
328
345
 
329
346
  function handleWorkspaceFileRead(requestedPath: string): Response {
@@ -389,7 +406,7 @@ function handleToolNamesList(): Response {
389
406
  const schemas: Record<string, SchemaShape> = {};
390
407
 
391
408
  // Collect raw definitions from the registry so we can transform them.
392
- const rawDefs: import("../../providers/types.js").ToolDefinition[] = [];
409
+ const rawDefs: ToolDefinition[] = [];
393
410
  for (const tool of tools) {
394
411
  try {
395
412
  rawDefs.push(tool.getDefinition());
@@ -24,7 +24,7 @@ import {
24
24
  inspectSkill,
25
25
  installSkill,
26
26
  listSkills,
27
- listSkillsWithCatalog,
27
+ listSkillsFiltered,
28
28
  searchSkills,
29
29
  uninstallSkill,
30
30
  updateSkill,
@@ -40,6 +40,13 @@ export interface SkillRouteDeps {
40
40
  getSkillContext: () => SkillOperationContext;
41
41
  }
42
42
 
43
+ const partnerAuditSchema = z.object({
44
+ risk: z.enum(["safe", "low", "medium", "high", "critical", "unknown"]),
45
+ alerts: z.number().optional(),
46
+ score: z.number().optional(),
47
+ analyzedAt: z.string(),
48
+ });
49
+
43
50
  const slimSkillBase = {
44
51
  id: z.string(),
45
52
  name: z.string(),
@@ -60,6 +67,7 @@ const slimSkillSchema = z.discriminatedUnion("origin", [
60
67
  installs: z.number(),
61
68
  reports: z.number(),
62
69
  publishedAt: z.string().optional(),
70
+ version: z.string(),
63
71
  }),
64
72
  z.object({
65
73
  ...slimSkillBase,
@@ -67,6 +75,7 @@ const slimSkillSchema = z.discriminatedUnion("origin", [
67
75
  slug: z.string(),
68
76
  sourceRepo: z.string(),
69
77
  installs: z.number(),
78
+ audit: z.record(z.string(), partnerAuditSchema).optional(),
70
79
  }),
71
80
  z.object({ ...slimSkillBase, origin: z.literal("custom") }),
72
81
  ]);
@@ -82,6 +91,7 @@ const skillDetailSchema = z.discriminatedUnion("origin", [
82
91
  installs: z.number(),
83
92
  reports: z.number(),
84
93
  publishedAt: z.string().optional(),
94
+ version: z.string(),
85
95
  owner: z
86
96
  .object({
87
97
  handle: z.string(),
@@ -115,6 +125,7 @@ const skillDetailSchema = z.discriminatedUnion("origin", [
115
125
  slug: z.string(),
116
126
  sourceRepo: z.string(),
117
127
  installs: z.number(),
128
+ audit: z.record(z.string(), partnerAuditSchema).optional(),
118
129
  }),
119
130
  z.object({ ...slimSkillBase, origin: z.literal("custom") }),
120
131
  ]);
@@ -129,7 +140,7 @@ export function skillRouteDefinitions(deps: SkillRouteDeps): RouteDefinition[] {
129
140
  policyKey: "skills",
130
141
  summary: "List all skills",
131
142
  description:
132
- "Return all installed skills. Pass ?include=catalog to also include available catalog skills.",
143
+ "Return all installed skills. Pass ?include=catalog to also include available catalog skills. Supports optional filter params: origin, kind, q, category.",
133
144
  tags: ["skills"],
134
145
  queryParams: [
135
146
  {
@@ -138,16 +149,73 @@ export function skillRouteDefinitions(deps: SkillRouteDeps): RouteDefinition[] {
138
149
  description:
139
150
  "Optional inclusion flag. Use 'catalog' to merge available Vellum catalog skills into the response.",
140
151
  },
152
+ {
153
+ name: "origin",
154
+ schema: { type: "string" },
155
+ description:
156
+ "Filter by skill origin (e.g. 'vellum', 'clawhub', 'skillssh', 'custom').",
157
+ },
158
+ {
159
+ name: "kind",
160
+ schema: { type: "string" },
161
+ description:
162
+ "Filter by kind: 'installed' (includes bundled), 'available', or pass through as skill.kind.",
163
+ },
164
+ {
165
+ name: "q",
166
+ schema: { type: "string" },
167
+ description:
168
+ "Text search across skill name, description, id, and origin label.",
169
+ },
170
+ {
171
+ name: "category",
172
+ schema: { type: "string" },
173
+ description:
174
+ "Filter by inferred category (e.g. 'communication', 'productivity').",
175
+ },
141
176
  ],
142
177
  responseBody: z.object({
143
178
  skills: z.array(slimSkillSchema).describe("Skill objects"),
179
+ categoryCounts: z
180
+ .record(z.string(), z.number())
181
+ .optional()
182
+ .describe(
183
+ "Count of skills per category (before category filter is applied)",
184
+ ),
185
+ totalCount: z
186
+ .number()
187
+ .optional()
188
+ .describe("Total number of skills matching non-category filters"),
144
189
  }),
145
190
  handler: async ({ url }) => {
146
191
  const include = url.searchParams.get("include");
147
- const skills =
148
- include === "catalog"
149
- ? await listSkillsWithCatalog(ctx())
150
- : listSkills(ctx());
192
+ const origin = url.searchParams.get("origin");
193
+ const kind = url.searchParams.get("kind");
194
+ const q = url.searchParams.get("q");
195
+ const category = url.searchParams.get("category");
196
+
197
+ const hasFilter = !!(origin || kind || q || category);
198
+
199
+ if (hasFilter || include === "catalog") {
200
+ const result = await listSkillsFiltered(
201
+ {
202
+ ...(origin ? { origin } : {}),
203
+ ...(kind ? { kind } : {}),
204
+ ...(q ? { q } : {}),
205
+ ...(category ? { category } : {}),
206
+ includeCatalog: include === "catalog",
207
+ },
208
+ ctx(),
209
+ );
210
+ return Response.json({
211
+ skills: result.skills,
212
+ categoryCounts: result.categoryCounts,
213
+ totalCount: result.totalCount,
214
+ });
215
+ }
216
+
217
+ // No filter params and include !== catalog: preserve existing behavior
218
+ const skills = listSkills(ctx());
151
219
  return Response.json({ skills });
152
220
  },
153
221
  },
@@ -312,6 +380,7 @@ export function skillRouteDefinitions(deps: SkillRouteDeps): RouteDefinition[] {
312
380
  }),
313
381
  responseBody: z.object({
314
382
  ok: z.boolean(),
383
+ skillId: z.string().optional(),
315
384
  }),
316
385
  handler: async ({ req, authContext }) => {
317
386
  const body = (await req.json()) as {
@@ -337,7 +406,7 @@ export function skillRouteDefinitions(deps: SkillRouteDeps): RouteDefinition[] {
337
406
  if (!result.success) {
338
407
  return httpError("INTERNAL_ERROR", result.error, 500);
339
408
  }
340
- return Response.json({ ok: true });
409
+ return Response.json({ ok: true, skillId: result.skillId });
341
410
  },
342
411
  },
343
412