@vellumai/assistant 0.5.13 → 0.5.15

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 (425) hide show
  1. package/.env.example +1 -6
  2. package/AGENTS.md +4 -0
  3. package/ARCHITECTURE.md +0 -1
  4. package/bunfig.toml +1 -0
  5. package/docs/architecture/memory.md +3 -3
  6. package/openapi.yaml +127 -22
  7. package/package.json +1 -1
  8. package/src/__tests__/access-request-decision.test.ts +2 -32
  9. package/src/__tests__/actor-token-service.test.ts +1 -31
  10. package/src/__tests__/anthropic-provider.test.ts +53 -40
  11. package/src/__tests__/app-git-history.test.ts +9 -17
  12. package/src/__tests__/app-git-service.test.ts +14 -20
  13. package/src/__tests__/app-store-dir-names.test.ts +10 -20
  14. package/src/__tests__/approval-cascade.test.ts +2 -19
  15. package/src/__tests__/approval-primitive.test.ts +2 -27
  16. package/src/__tests__/approval-routes-http.test.ts +2 -30
  17. package/src/__tests__/assistant-events-sse-hardening.test.ts +2 -28
  18. package/src/__tests__/assistant-feature-flags-integration.test.ts +2 -45
  19. package/src/__tests__/attachments-store.test.ts +5 -32
  20. package/src/__tests__/audit-log-rotation.test.ts +5 -36
  21. package/src/__tests__/avatar-e2e.test.ts +1 -9
  22. package/src/__tests__/avatar-generator.test.ts +1 -7
  23. package/src/__tests__/browser-fill-credential.test.ts +0 -4
  24. package/src/__tests__/browser-manager.test.ts +0 -6
  25. package/src/__tests__/call-controller.test.ts +1 -22
  26. package/src/__tests__/call-conversation-messages.test.ts +0 -21
  27. package/src/__tests__/call-domain.test.ts +0 -25
  28. package/src/__tests__/call-pointer-messages.test.ts +0 -21
  29. package/src/__tests__/call-recovery.test.ts +0 -22
  30. package/src/__tests__/call-routes-http.test.ts +0 -24
  31. package/src/__tests__/call-store.test.ts +0 -21
  32. package/src/__tests__/cancel-resolves-conversation-key.test.ts +0 -24
  33. package/src/__tests__/canonical-guardian-store.test.ts +48 -21
  34. package/src/__tests__/channel-approval-routes.test.ts +6 -26
  35. package/src/__tests__/channel-approvals.test.ts +1 -38
  36. package/src/__tests__/channel-delivery-store.test.ts +0 -21
  37. package/src/__tests__/channel-guardian.test.ts +0 -26
  38. package/src/__tests__/channel-reply-delivery.test.ts +5 -0
  39. package/src/__tests__/channel-retry-sweep.test.ts +0 -21
  40. package/src/__tests__/checker.test.ts +26 -61
  41. package/src/__tests__/clawhub.test.ts +9 -25
  42. package/src/__tests__/cli-command-risk-guard.test.ts +0 -18
  43. package/src/__tests__/config-loader-backfill.test.ts +9 -28
  44. package/src/__tests__/config-schema-cmd.test.ts +5 -25
  45. package/src/__tests__/config-schema.test.ts +21 -40
  46. package/src/__tests__/config-watcher.test.ts +4 -91
  47. package/src/__tests__/confirmation-request-guardian-bridge.test.ts +0 -21
  48. package/src/__tests__/contacts-tools.test.ts +0 -21
  49. package/src/__tests__/context-memory-e2e.test.ts +0 -21
  50. package/src/__tests__/context-window-manager.test.ts +130 -3
  51. package/src/__tests__/conversation-abort-tool-results.test.ts +0 -4
  52. package/src/__tests__/conversation-agent-loop-overflow.test.ts +0 -4
  53. package/src/__tests__/conversation-agent-loop.test.ts +0 -4
  54. package/src/__tests__/conversation-attachments.test.ts +1 -24
  55. package/src/__tests__/conversation-attention-store.test.ts +0 -21
  56. package/src/__tests__/conversation-attention-telegram.test.ts +0 -22
  57. package/src/__tests__/conversation-clear-safety.test.ts +0 -22
  58. package/src/__tests__/conversation-confirmation-signals.test.ts +2 -21
  59. package/src/__tests__/conversation-delete-schedule-cleanup.test.ts +0 -24
  60. package/src/__tests__/conversation-disk-view-integration.test.ts +1 -23
  61. package/src/__tests__/conversation-disk-view.test.ts +5 -27
  62. package/src/__tests__/conversation-error.test.ts +1 -1
  63. package/src/__tests__/conversation-fork-crud.test.ts +1 -33
  64. package/src/__tests__/conversation-fork-route.test.ts +0 -27
  65. package/src/__tests__/conversation-history-web-search.test.ts +23 -16
  66. package/src/__tests__/conversation-init.benchmark.test.ts +22 -43
  67. package/src/__tests__/conversation-key-store-disk-view.test.ts +8 -34
  68. package/src/__tests__/conversation-load-history-repair.test.ts +0 -4
  69. package/src/__tests__/conversation-pre-run-repair.test.ts +0 -4
  70. package/src/__tests__/conversation-provider-retry-repair.test.ts +0 -4
  71. package/src/__tests__/conversation-queue.test.ts +8 -8
  72. package/src/__tests__/conversation-routes-disk-view.test.ts +13 -51
  73. package/src/__tests__/conversation-runtime-assembly.test.ts +64 -38
  74. package/src/__tests__/conversation-slash-commands.test.ts +5 -0
  75. package/src/__tests__/conversation-slash-queue.test.ts +0 -4
  76. package/src/__tests__/conversation-slash-unknown.test.ts +0 -4
  77. package/src/__tests__/conversation-speed-override.test.ts +326 -0
  78. package/src/__tests__/conversation-starter-routes.test.ts +0 -23
  79. package/src/__tests__/conversation-store.test.ts +0 -21
  80. package/src/__tests__/conversation-unread-route.test.ts +0 -24
  81. package/src/__tests__/conversation-usage.test.ts +56 -21
  82. package/src/__tests__/conversation-wipe.test.ts +0 -21
  83. package/src/__tests__/conversation-workspace-cache-state.test.ts +0 -4
  84. package/src/__tests__/conversation-workspace-injection.test.ts +0 -4
  85. package/src/__tests__/conversation-workspace-tool-tracking.test.ts +0 -4
  86. package/src/__tests__/credential-execution-shell-lockdown.test.ts +8 -5
  87. package/src/__tests__/credential-vault-unit.test.ts +9 -428
  88. package/src/__tests__/credentials-cli.test.ts +10 -10
  89. package/src/__tests__/daemon-assistant-events.test.ts +0 -19
  90. package/src/__tests__/date-context.test.ts +77 -97
  91. package/src/__tests__/db-conversation-fork-lineage-migration.test.ts +7 -24
  92. package/src/__tests__/db-llm-request-log-provider-migration.test.ts +29 -42
  93. package/src/__tests__/delete-managed-skill-tool.test.ts +2 -10
  94. package/src/__tests__/deterministic-verification-control-plane.test.ts +1 -26
  95. package/src/__tests__/docker-signing-key-bootstrap.test.ts +61 -15
  96. package/src/__tests__/dynamic-skill-workflow-prompt.test.ts +2 -36
  97. package/src/__tests__/email-cli.test.ts +6 -6
  98. package/src/__tests__/ephemeral-permissions.test.ts +5 -17
  99. package/src/__tests__/first-greeting.test.ts +4 -32
  100. package/src/__tests__/followup-tools.test.ts +0 -21
  101. package/src/__tests__/gateway-only-enforcement.test.ts +0 -20
  102. package/src/__tests__/guardian-action-conversation-turn.test.ts +0 -23
  103. package/src/__tests__/guardian-action-followup-executor.test.ts +0 -23
  104. package/src/__tests__/guardian-action-followup-store.test.ts +0 -21
  105. package/src/__tests__/guardian-action-grant-mint-consume.test.ts +0 -21
  106. package/src/__tests__/guardian-action-late-reply.test.ts +0 -21
  107. package/src/__tests__/guardian-action-store.test.ts +0 -21
  108. package/src/__tests__/guardian-action-sweep.test.ts +0 -21
  109. package/src/__tests__/guardian-binding-drift-heal.test.ts +0 -23
  110. package/src/__tests__/guardian-decision-primitive-canonical.test.ts +172 -22
  111. package/src/__tests__/guardian-dispatch.test.ts +0 -21
  112. package/src/__tests__/guardian-grant-minting.test.ts +0 -22
  113. package/src/__tests__/guardian-outbound-http.test.ts +0 -22
  114. package/src/__tests__/guardian-principal-id-roundtrip.test.ts +0 -23
  115. package/src/__tests__/guardian-routing-invariants.test.ts +0 -22
  116. package/src/__tests__/guardian-routing-state.test.ts +0 -22
  117. package/src/__tests__/guardian-verification-voice-binding.test.ts +0 -24
  118. package/src/__tests__/headless-browser-interactions.test.ts +0 -4
  119. package/src/__tests__/headless-browser-navigate.test.ts +0 -4
  120. package/src/__tests__/headless-browser-read-tools.test.ts +0 -4
  121. package/src/__tests__/headless-browser-snapshot.test.ts +0 -4
  122. package/src/__tests__/heartbeat-service.test.ts +99 -26
  123. package/src/__tests__/hooks-blocking.test.ts +3 -3
  124. package/src/__tests__/hooks-config.test.ts +7 -7
  125. package/src/__tests__/hooks-discovery.test.ts +3 -3
  126. package/src/__tests__/hooks-integration.test.ts +5 -5
  127. package/src/__tests__/hooks-manager.test.ts +3 -3
  128. package/src/__tests__/hooks-runner.test.ts +5 -23
  129. package/src/__tests__/hooks-settings.test.ts +3 -3
  130. package/src/__tests__/hooks-templates.test.ts +3 -3
  131. package/src/__tests__/http-conversation-lineage.test.ts +0 -27
  132. package/src/__tests__/identity-intro-cache.test.ts +0 -4
  133. package/src/__tests__/inbound-invite-redemption.test.ts +0 -22
  134. package/src/__tests__/inline-skill-load-permissions.test.ts +5 -16
  135. package/src/__tests__/intent-routing.test.ts +2 -55
  136. package/src/__tests__/invite-redemption-service.test.ts +0 -21
  137. package/src/__tests__/invite-routes-http.test.ts +0 -21
  138. package/src/__tests__/jobs-store-qdrant-breaker.test.ts +0 -17
  139. package/src/__tests__/journal-context.test.ts +8 -75
  140. package/src/__tests__/list-messages-attachments.test.ts +0 -22
  141. package/src/__tests__/llm-context-route-provider.test.ts +0 -21
  142. package/src/__tests__/llm-request-log-turn-query.test.ts +46 -28
  143. package/src/__tests__/llm-usage-store.test.ts +0 -21
  144. package/src/__tests__/log-export-workspace.test.ts +1 -1
  145. package/src/__tests__/managed-skill-lifecycle.test.ts +1 -1
  146. package/src/__tests__/managed-store.test.ts +1 -1
  147. package/src/__tests__/mcp-cli.test.ts +7 -10
  148. package/src/__tests__/memory-context-benchmark.benchmark.test.ts +0 -21
  149. package/src/__tests__/memory-jobs-worker-backoff.test.ts +0 -11
  150. package/src/__tests__/memory-lifecycle-e2e.test.ts +0 -21
  151. package/src/__tests__/memory-recall-log-store.test.ts +0 -27
  152. package/src/__tests__/memory-recall-quality.test.ts +0 -21
  153. package/src/__tests__/memory-regressions.experimental.test.ts +31 -30
  154. package/src/__tests__/memory-regressions.test.ts +282 -70
  155. package/src/__tests__/memory-retrieval.benchmark.test.ts +0 -21
  156. package/src/__tests__/memory-upsert-concurrency.test.ts +0 -21
  157. package/src/__tests__/messaging-send-tool.test.ts +201 -0
  158. package/src/__tests__/migration-cross-version-compatibility.test.ts +18 -13
  159. package/src/__tests__/migration-export-http.test.ts +7 -1
  160. package/src/__tests__/migration-import-commit-http.test.ts +16 -14
  161. package/src/__tests__/migration-import-preflight-http.test.ts +27 -44
  162. package/src/__tests__/migration-validate-http.test.ts +1 -28
  163. package/src/__tests__/native-web-search.test.ts +25 -22
  164. package/src/__tests__/non-member-access-request.test.ts +0 -22
  165. package/src/__tests__/notification-guardian-path.test.ts +0 -21
  166. package/src/__tests__/notification-schedule-dedup.test.ts +1 -25
  167. package/src/__tests__/oauth-apps-routes.test.ts +103 -2
  168. package/src/__tests__/oauth-cli.test.ts +52 -0
  169. package/src/__tests__/oauth-provider-profiles.test.ts +0 -16
  170. package/src/__tests__/oauth-provider-serializer.test.ts +232 -0
  171. package/src/__tests__/oauth-providers-routes.test.ts +257 -0
  172. package/src/__tests__/oauth-store.test.ts +0 -21
  173. package/src/__tests__/onboarding-template-contract.test.ts +2 -2
  174. package/src/__tests__/openai-provider.test.ts +261 -0
  175. package/src/__tests__/pairing-concurrent.test.ts +6 -6
  176. package/src/__tests__/pairing-routes.test.ts +7 -1
  177. package/src/__tests__/path-policy.test.ts +1 -1
  178. package/src/__tests__/platform.test.ts +64 -88
  179. package/src/__tests__/playbook-execution.test.ts +0 -21
  180. package/src/__tests__/playbook-tools.test.ts +0 -21
  181. package/src/__tests__/pricing.test.ts +100 -0
  182. package/src/__tests__/relay-server.test.ts +1 -25
  183. package/src/__tests__/runtime-attachment-metadata.test.ts +0 -24
  184. package/src/__tests__/runtime-events-sse-parity.test.ts +2 -24
  185. package/src/__tests__/runtime-events-sse.test.ts +0 -24
  186. package/src/__tests__/sandbox-diagnostics.test.ts +2 -1
  187. package/src/__tests__/scaffold-managed-skill-tool.test.ts +1 -1
  188. package/src/__tests__/schedule-store.test.ts +0 -21
  189. package/src/__tests__/schedule-tools.test.ts +0 -21
  190. package/src/__tests__/scheduler-recurrence.test.ts +0 -21
  191. package/src/__tests__/scoped-approval-grants.test.ts +0 -21
  192. package/src/__tests__/scoped-grant-security-matrix.test.ts +0 -21
  193. package/src/__tests__/secret-allowlist.test.ts +1 -1
  194. package/src/__tests__/secret-ingress-channel.test.ts +0 -5
  195. package/src/__tests__/secret-ingress-cli.test.ts +0 -6
  196. package/src/__tests__/secret-ingress-http.test.ts +0 -5
  197. package/src/__tests__/secret-ingress.test.ts +0 -5
  198. package/src/__tests__/send-endpoint-busy.test.ts +0 -24
  199. package/src/__tests__/sequence-store.test.ts +0 -21
  200. package/src/__tests__/server-history-render.test.ts +0 -24
  201. package/src/__tests__/shell-tool-proxy-mode.test.ts +0 -4
  202. package/src/__tests__/skill-load-inline-command.test.ts +9 -0
  203. package/src/__tests__/skill-load-inline-includes.test.ts +9 -0
  204. package/src/__tests__/skill-load-tool.test.ts +11 -0
  205. package/src/__tests__/skills-uninstall.test.ts +10 -8
  206. package/src/__tests__/skills.test.ts +1 -1
  207. package/src/__tests__/slack-channel-config.test.ts +1 -1
  208. package/src/__tests__/slack-inbound-verification.test.ts +0 -22
  209. package/src/__tests__/starter-bundle.test.ts +4 -1
  210. package/src/__tests__/suggestion-routes.test.ts +2 -0
  211. package/src/__tests__/system-prompt.test.ts +1 -1
  212. package/src/__tests__/terminal-tools.test.ts +1 -1
  213. package/src/__tests__/test-preload.ts +31 -0
  214. package/src/__tests__/tool-execution-abort-cleanup.test.ts +1 -1
  215. package/src/__tests__/tool-execution-pipeline.benchmark.test.ts +1 -1
  216. package/src/__tests__/tool-executor.test.ts +0 -20
  217. package/src/__tests__/tool-input-summary.test.ts +124 -0
  218. package/src/__tests__/tool-preview-lifecycle.test.ts +2 -1
  219. package/src/__tests__/trust-store.test.ts +7 -1
  220. package/src/__tests__/trusted-contact-inline-approval-integration.test.ts +1 -1
  221. package/src/__tests__/trusted-contact-lifecycle-notifications.test.ts +1 -1
  222. package/src/__tests__/trusted-contact-multichannel.test.ts +1 -1
  223. package/src/__tests__/trusted-contact-verification.test.ts +1 -1
  224. package/src/__tests__/turn-boundary-resolution.test.ts +1 -1
  225. package/src/__tests__/twilio-routes.test.ts +1 -1
  226. package/src/__tests__/update-bulletin.test.ts +1 -1
  227. package/src/__tests__/vbundle-pax-and-symlink.test.ts +1 -1
  228. package/src/__tests__/vellum-self-knowledge-inline-command.test.ts +1 -0
  229. package/src/__tests__/voice-scoped-grant-consumer.test.ts +1 -1
  230. package/src/__tests__/voice-session-bridge.test.ts +1 -1
  231. package/src/__tests__/workspace-migration-009-backfill-conversation-disk-view.test.ts +4 -4
  232. package/src/__tests__/workspace-migration-013-repair-conversation-disk-view.test.ts +1 -1
  233. package/src/__tests__/workspace-migration-down-functions.test.ts +15 -3
  234. package/src/__tests__/workspace-migration-seed-device-id.test.ts +40 -4
  235. package/src/agent/loop.ts +6 -9
  236. package/src/approvals/guardian-decision-primitive.ts +46 -18
  237. package/src/approvals/guardian-request-resolvers.ts +19 -2
  238. package/src/calls/active-call-lease.ts +2 -2
  239. package/src/cli/AGENTS.md +1 -1
  240. package/src/cli/commands/doctor.ts +9 -9
  241. package/src/cli/commands/memory.ts +142 -0
  242. package/src/cli/commands/oauth/__tests__/connect.test.ts +13 -11
  243. package/src/cli/commands/oauth/__tests__/ping.test.ts +1 -1
  244. package/src/cli/commands/oauth/connect.ts +13 -12
  245. package/src/cli/commands/oauth/index.ts +1 -1
  246. package/src/cli/commands/oauth/providers.ts +47 -62
  247. package/src/cli/commands/platform/__tests__/connect.test.ts +72 -46
  248. package/src/cli/commands/platform/__tests__/disconnect.test.ts +54 -1
  249. package/src/cli/commands/platform/__tests__/status.test.ts +36 -0
  250. package/src/cli/commands/platform/connect.ts +17 -7
  251. package/src/cli/commands/platform/disconnect.ts +28 -3
  252. package/src/cli/commands/platform/index.ts +3 -3
  253. package/src/cli.ts +1 -299
  254. package/src/config/assistant-feature-flags.ts +23 -15
  255. package/src/config/bundled-skills/app-builder/TOOLS.json +16 -0
  256. package/src/config/bundled-skills/app-builder/tools/app-create.ts +4 -0
  257. package/src/config/bundled-skills/app-builder/tools/app-delete.ts +5 -1
  258. package/src/config/bundled-skills/app-builder/tools/app-generate-icon.ts +9 -1
  259. package/src/config/bundled-skills/app-builder/tools/app-refresh.ts +5 -1
  260. package/src/config/bundled-skills/contacts/TOOLS.json +8 -0
  261. package/src/config/bundled-skills/contacts/tools/contact-search.ts +10 -1
  262. package/src/config/bundled-skills/contacts/tools/contact-upsert.ts +16 -2
  263. package/src/config/bundled-skills/media-processing/tools/ingest-media.ts +1 -0
  264. package/src/config/bundled-skills/messaging/SKILL.md +7 -7
  265. package/src/config/bundled-skills/messaging/tools/messaging-send.ts +37 -0
  266. package/src/config/bundled-skills/slack/SKILL.md +18 -0
  267. package/src/config/env-registry.ts +15 -11
  268. package/src/config/env.ts +1 -11
  269. package/src/config/feature-flag-registry.json +16 -0
  270. package/src/config/schema.ts +4 -0
  271. package/src/config/schemas/heartbeat.ts +6 -1
  272. package/src/config/schemas/inference.ts +14 -3
  273. package/src/config/schemas/memory-processing.ts +16 -8
  274. package/src/config/schemas/memory-retrieval.ts +3 -3
  275. package/src/config/skills.ts +1 -1
  276. package/src/context/window-manager.ts +174 -51
  277. package/src/credential-execution/executable-discovery.ts +2 -2
  278. package/src/daemon/approved-devices-store.ts +2 -2
  279. package/src/daemon/assistant-attachments.ts +2 -0
  280. package/src/daemon/config-watcher.ts +4 -50
  281. package/src/daemon/conversation-agent-loop-handlers.ts +9 -1
  282. package/src/daemon/conversation-agent-loop.ts +12 -0
  283. package/src/daemon/conversation-error.ts +3 -5
  284. package/src/daemon/conversation-history.ts +7 -3
  285. package/src/daemon/conversation-lifecycle.ts +16 -0
  286. package/src/daemon/conversation-messaging.ts +1 -0
  287. package/src/daemon/conversation-notifiers.ts +67 -30
  288. package/src/daemon/conversation-process.ts +161 -2
  289. package/src/daemon/conversation-queue-manager.ts +2 -0
  290. package/src/daemon/conversation-runtime-assembly.ts +33 -11
  291. package/src/daemon/conversation-slash.ts +14 -3
  292. package/src/daemon/conversation-tool-setup.ts +2 -0
  293. package/src/daemon/conversation-usage.ts +32 -4
  294. package/src/daemon/conversation.ts +33 -1
  295. package/src/daemon/daemon-control.ts +32 -16
  296. package/src/daemon/date-context.ts +47 -45
  297. package/src/daemon/dictation-profile-store.ts +2 -2
  298. package/src/daemon/handlers/conversations.ts +19 -0
  299. package/src/daemon/handlers/shared.ts +14 -21
  300. package/src/daemon/lifecycle.ts +5 -7
  301. package/src/daemon/message-types/conversations.ts +2 -0
  302. package/src/daemon/message-types/guardian-actions.ts +3 -17
  303. package/src/daemon/message-types/integrations.ts +11 -1
  304. package/src/daemon/message-types/messages.ts +1 -0
  305. package/src/daemon/pairing-store.ts +2 -79
  306. package/src/daemon/server.ts +154 -8
  307. package/src/daemon/watch-handler.ts +65 -21
  308. package/src/email/guardrails.ts +3 -3
  309. package/src/heartbeat/heartbeat-service.ts +14 -7
  310. package/src/hooks/cli.ts +2 -2
  311. package/src/hooks/config.ts +2 -2
  312. package/src/hooks/discovery.ts +2 -2
  313. package/src/hooks/manager.ts +2 -2
  314. package/src/hooks/runner.ts +5 -2
  315. package/src/hooks/templates.ts +2 -2
  316. package/src/memory/admin.ts +181 -2
  317. package/src/memory/app-git-service.ts +61 -4
  318. package/src/memory/attachments-store.ts +2 -0
  319. package/src/memory/canonical-guardian-store.ts +16 -0
  320. package/src/memory/db-init.ts +8 -0
  321. package/src/memory/embedding-local.ts +5 -2
  322. package/src/memory/indexer.ts +44 -26
  323. package/src/memory/items-extractor.ts +34 -82
  324. package/src/memory/job-handlers/batch-extraction.ts +741 -0
  325. package/src/memory/job-handlers/journal-carry-forward.test.ts +383 -0
  326. package/src/memory/job-handlers/journal-carry-forward.ts +255 -0
  327. package/src/memory/jobs-store.ts +28 -0
  328. package/src/memory/jobs-worker.ts +56 -9
  329. package/src/memory/lifecycle-events-store.ts +4 -2
  330. package/src/memory/llm-request-log-store.ts +40 -2
  331. package/src/memory/llm-usage-store.ts +4 -3
  332. package/src/memory/migrations/199-guardian-request-enrichment-columns.ts +71 -0
  333. package/src/memory/migrations/200-usage-llm-call-count.ts +20 -0
  334. package/src/memory/migrations/index.ts +2 -0
  335. package/src/memory/query-expansion.ts +83 -0
  336. package/src/memory/retriever.test.ts +119 -0
  337. package/src/memory/retriever.ts +513 -105
  338. package/src/memory/schema/guardian.ts +4 -0
  339. package/src/memory/schema/infrastructure.ts +1 -0
  340. package/src/memory/search/formatting.test.ts +140 -0
  341. package/src/memory/search/formatting.ts +143 -198
  342. package/src/memory/search/mmr.ts +136 -0
  343. package/src/memory/search/staleness.ts +0 -15
  344. package/src/memory/search/tier-classifier.ts +10 -21
  345. package/src/memory/search/types.ts +17 -0
  346. package/src/messaging/providers/slack/adapter.ts +51 -5
  347. package/src/notifications/broadcaster.ts +13 -0
  348. package/src/notifications/copy-composer.ts +8 -0
  349. package/src/oauth/connect-orchestrator.ts +1 -1
  350. package/src/oauth/connection-resolver.ts +2 -2
  351. package/src/oauth/provider-serializer.ts +116 -0
  352. package/src/permissions/trust-store.ts +24 -7
  353. package/src/prompts/__tests__/build-cli-reference-section.test.ts +5 -0
  354. package/src/prompts/journal-context.ts +50 -35
  355. package/src/prompts/persona-resolver.ts +1 -1
  356. package/src/prompts/system-prompt.ts +27 -28
  357. package/src/prompts/templates/BOOTSTRAP.md +14 -1
  358. package/src/prompts/templates/HEARTBEAT.md +10 -0
  359. package/src/prompts/templates/NOW.md +19 -25
  360. package/src/prompts/templates/SOUL.md +13 -1
  361. package/src/prompts/templates/UPDATES.md +12 -0
  362. package/src/prompts/update-bulletin.ts +1 -1
  363. package/src/providers/anthropic/client.ts +89 -18
  364. package/src/providers/model-catalog.ts +22 -2
  365. package/src/providers/model-intents.ts +2 -2
  366. package/src/providers/openai/client.ts +40 -1
  367. package/src/providers/retry.ts +23 -4
  368. package/src/providers/types.ts +2 -0
  369. package/src/runtime/assistant-scope.ts +1 -1
  370. package/src/runtime/auth/__tests__/credential-service.test.ts +1 -0
  371. package/src/runtime/auth/route-policy.ts +1 -0
  372. package/src/runtime/auth/token-service.ts +51 -29
  373. package/src/runtime/confirmation-request-guardian-bridge.ts +3 -1
  374. package/src/runtime/guardian-decision-types.ts +16 -10
  375. package/src/runtime/http-server.ts +3 -14
  376. package/src/runtime/http-types.ts +1 -0
  377. package/src/runtime/migrations/vbundle-builder.ts +7 -4
  378. package/src/runtime/migrations/vbundle-import-analyzer.ts +0 -4
  379. package/src/runtime/migrations/vbundle-importer.ts +1 -1
  380. package/src/runtime/routes/conversation-query-routes.ts +40 -8
  381. package/src/runtime/routes/conversation-routes.ts +125 -3
  382. package/src/runtime/routes/guardian-action-routes.ts +9 -3
  383. package/src/runtime/routes/identity-routes.ts +25 -4
  384. package/src/runtime/routes/llm-context-normalization.ts +1 -0
  385. package/src/runtime/routes/log-export-routes.ts +34 -12
  386. package/src/runtime/routes/migration-routes.ts +6 -10
  387. package/src/runtime/routes/oauth-apps.ts +2 -9
  388. package/src/runtime/routes/oauth-providers.ts +60 -0
  389. package/src/runtime/routes/pairing-routes.ts +0 -8
  390. package/src/runtime/routes/settings-routes.ts +0 -1
  391. package/src/runtime/routes/telemetry-routes.ts +16 -4
  392. package/src/security/encrypted-store.ts +2 -2
  393. package/src/security/secret-allowlist.ts +3 -3
  394. package/src/signals/emit-event.ts +42 -0
  395. package/src/signals/user-message.ts +37 -0
  396. package/src/telemetry/usage-telemetry-reporter.test.ts +83 -19
  397. package/src/telemetry/usage-telemetry-reporter.ts +23 -17
  398. package/src/tools/browser/runtime-check.ts +2 -2
  399. package/src/tools/credentials/vault.ts +2 -249
  400. package/src/tools/memory/definitions.ts +1 -1
  401. package/src/tools/memory/handlers.test.ts +50 -8
  402. package/src/tools/memory/handlers.ts +3 -1
  403. package/src/tools/side-effects.ts +1 -6
  404. package/src/tools/terminal/safe-env.ts +3 -2
  405. package/src/tools/terminal/shell.ts +11 -14
  406. package/src/tools/tool-approval-handler.ts +20 -1
  407. package/src/tools/tool-input-summary.ts +66 -0
  408. package/src/tools/types.ts +4 -0
  409. package/src/usage/types.ts +4 -0
  410. package/src/util/device-id.ts +10 -10
  411. package/src/util/platform.ts +71 -33
  412. package/src/util/pricing.ts +19 -6
  413. package/src/util/strip-comment-lines.ts +28 -0
  414. package/src/workspace/git-service.ts +8 -18
  415. package/src/workspace/migrations/003-seed-device-id.ts +6 -4
  416. package/src/workspace/migrations/016-extract-feature-flags-to-protected.ts +7 -1
  417. package/src/workspace/migrations/017-seed-persona-dirs.ts +2 -4
  418. package/src/workspace/migrations/021-move-signals-to-workspace.ts +84 -0
  419. package/src/workspace/migrations/022-move-hooks-to-workspace.ts +94 -0
  420. package/src/workspace/migrations/023-move-config-files-to-workspace.ts +86 -0
  421. package/src/workspace/migrations/024-move-runtime-files-to-workspace.ts +126 -0
  422. package/src/workspace/migrations/migrate-to-workspace-volume.ts +3 -6
  423. package/src/workspace/migrations/registry.ts +8 -0
  424. package/src/signals/confirm.ts +0 -82
  425. package/src/signals/trust-rule.ts +0 -174
@@ -1,4 +1,4 @@
1
- import { mkdtempSync } from "node:fs";
1
+ import { existsSync, mkdtempSync, readFileSync, rmSync } from "node:fs";
2
2
  import { tmpdir } from "node:os";
3
3
  import { join } from "node:path";
4
4
  import { beforeEach, describe, expect, mock, test } from "bun:test";
@@ -21,7 +21,7 @@ mock.module("../../../lib/daemon-credential-client.js", () => ({
21
21
  getSecureKeyViaDaemon: (account: string) =>
22
22
  mockGetSecureKeyViaDaemon(account),
23
23
  deleteSecureKeyViaDaemon: async () => "not-found" as const,
24
- setSecureKeyViaDaemon: async () => false,
24
+ setSecureKeyViaDaemon: async () => true,
25
25
  getProviderKeyViaDaemon: async () => undefined,
26
26
  getSecureKeyResultViaDaemon: async () => ({
27
27
  value: undefined,
@@ -97,6 +97,14 @@ mock.module("../../../../util/platform.js", () => ({
97
97
  getLogPath: () => join(testDir, "test.log"),
98
98
  getWorkspaceDirDisplay: () => testDir,
99
99
  getWorkspacePromptPath: (file: string) => join(testDir, file),
100
+ getProtectedDir: () => join(testDir, "protected"),
101
+ getDeprecatedDir: () => join(testDir, "workspace", "deprecated"),
102
+ getExternalDir: () => join(testDir, "external"),
103
+ getBinDir: () => join(testDir, "bin"),
104
+ getDotEnvPath: () => join(testDir, ".env"),
105
+ getDaemonStderrLogPath: () => join(testDir, "daemon-stderr.log"),
106
+ getDaemonStartupLockPath: () => join(testDir, "daemon-startup.lock"),
107
+ getEmbedWorkerPidPath: () => join(testDir, "embed-worker.pid"),
100
108
  ensureDataDir: () => {},
101
109
  }));
102
110
 
@@ -175,50 +183,68 @@ describe("assistant platform connect", () => {
175
183
  beforeEach(() => {
176
184
  mockGetSecureKeyViaDaemon = async () => undefined;
177
185
  process.exitCode = 0;
186
+ // Remove any signal file left by previous tests
187
+ try {
188
+ rmSync(join(testDir, "signals"), { recursive: true, force: true });
189
+ } catch {
190
+ // ignore
191
+ }
178
192
  });
179
193
 
180
- test.todo(
181
- "already connected returns success with existing base URL",
182
- async () => {
183
- /**
184
- * When the assistant already has stored platform credentials (base
185
- * URL and API key), the connect command should short-circuit and
186
- * report that it is already connected, returning the existing base
187
- * URL.
188
- *
189
- * NOTE: The connect command is currently stubbed — the full
190
- * credential-collection flow via a secure UI component is not yet
191
- * implemented. This test validates the already-connected early-exit
192
- * path, which IS implemented. It is skipped because the stub path
193
- * still sets a non-zero exit code before reaching this branch
194
- * under certain conditions. Unskip once the full connect flow
195
- * lands.
196
- */
197
-
198
- // GIVEN stored platform credentials already exist
199
- mockGetSecureKeyViaDaemon = async (account: string) => {
200
- if (account === "credential/vellum/platform_base_url")
201
- return "https://platform.vellum.ai";
202
- if (account === "credential/vellum/assistant_api_key")
203
- return "sk-existing-key";
204
- return undefined;
205
- };
206
-
207
- // WHEN the connect command is run with --json
208
- const { exitCode, stdout } = await runCommand([
209
- "platform",
210
- "connect",
211
- "--json",
212
- ]);
213
-
214
- // THEN the command succeeds
215
- expect(exitCode).toBe(0);
216
-
217
- // AND the output indicates already connected with the base URL
218
- const parsed = JSON.parse(stdout);
219
- expect(parsed.ok).toBe(true);
220
- expect(parsed.alreadyConnected).toBe(true);
221
- expect(parsed.baseUrl).toBe("https://platform.vellum.ai");
222
- },
223
- );
194
+ test("writes emit-event signal file and reports success", async () => {
195
+ // GIVEN no existing platform credentials
196
+ mockGetSecureKeyViaDaemon = async () => undefined;
197
+
198
+ // WHEN the connect command is run with --json
199
+ const { exitCode, stdout } = await runCommand([
200
+ "platform",
201
+ "connect",
202
+ "--json",
203
+ ]);
204
+
205
+ // THEN the command succeeds
206
+ expect(exitCode).toBe(0);
207
+
208
+ // AND the output confirms the login UI was triggered
209
+ const parsed = JSON.parse(stdout);
210
+ expect(parsed.ok).toBe(true);
211
+ expect(parsed.showPlatformLogin).toBe(true);
212
+
213
+ // AND a show_platform_login emit-event signal file was written
214
+ const signalPath = join(testDir, "signals", "emit-event");
215
+ expect(existsSync(signalPath)).toBe(true);
216
+ const payload = JSON.parse(readFileSync(signalPath, "utf-8"));
217
+ expect(payload).toEqual({ type: "show_platform_login" });
218
+ });
219
+
220
+ test("already connected returns success with existing base URL", async () => {
221
+ // GIVEN stored platform credentials already exist
222
+ mockGetSecureKeyViaDaemon = async (account: string) => {
223
+ if (account === "credential/vellum/platform_base_url")
224
+ return "https://platform.vellum.ai";
225
+ if (account === "credential/vellum/assistant_api_key")
226
+ return "sk-existing-key";
227
+ return undefined;
228
+ };
229
+
230
+ // WHEN the connect command is run with --json
231
+ const { exitCode, stdout } = await runCommand([
232
+ "platform",
233
+ "connect",
234
+ "--json",
235
+ ]);
236
+
237
+ // THEN the command succeeds
238
+ expect(exitCode).toBe(0);
239
+
240
+ // AND the output indicates already connected with the base URL
241
+ const parsed = JSON.parse(stdout);
242
+ expect(parsed.ok).toBe(true);
243
+ expect(parsed.alreadyConnected).toBe(true);
244
+ expect(parsed.baseUrl).toBe("https://platform.vellum.ai");
245
+
246
+ // AND no emit-event signal file was written
247
+ const signalPath = join(testDir, "signals", "emit-event");
248
+ expect(existsSync(signalPath)).toBe(false);
249
+ });
224
250
  });
@@ -1,4 +1,4 @@
1
- import { mkdtempSync } from "node:fs";
1
+ import { existsSync, mkdtempSync, readFileSync } from "node:fs";
2
2
  import { tmpdir } from "node:os";
3
3
  import { join } from "node:path";
4
4
  import { beforeEach, describe, expect, mock, test } from "bun:test";
@@ -21,10 +21,20 @@ let mockDeleteSecureKeyViaDaemonCalls: Array<{
21
21
  let mockDeleteSecureKeyViaDaemonResult: "deleted" | "not-found" | "error" =
22
22
  "deleted";
23
23
 
24
+ let mockIsPlatformRemote = false;
25
+
24
26
  // ---------------------------------------------------------------------------
25
27
  // Mocks
26
28
  // ---------------------------------------------------------------------------
27
29
 
30
+ mock.module("../../../../config/env-registry.js", () => ({
31
+ getIsContainerized: () => false,
32
+ isPlatformRemote: () => mockIsPlatformRemote,
33
+ getDebugStdoutLogs: () => false,
34
+ getWorkspaceDirOverride: () => undefined,
35
+ checkUnrecognizedEnvVars: () => [],
36
+ }));
37
+
28
38
  mock.module("../../../../inbound/platform-callback-registration.js", () => ({
29
39
  resolvePlatformCallbackRegistrationContext: async () => ({
30
40
  containerized: false,
@@ -82,7 +92,15 @@ mock.module("../../../../util/platform.js", () => ({
82
92
  getWorkspaceHooksDir: () => join(testDir, "workspace", "hooks"),
83
93
  getWorkspaceConfigPath: () => join(testDir, "workspace", "config.json"),
84
94
  getHooksDir: () => join(testDir, "hooks"),
95
+ getProtectedDir: () => join(testDir, "protected"),
96
+ getDeprecatedDir: () => join(testDir, "workspace", "deprecated"),
85
97
  getSignalsDir: () => join(testDir, "signals"),
98
+ getDaemonStderrLogPath: () => join(testDir, "daemon-stderr.log"),
99
+ getDaemonStartupLockPath: () => join(testDir, "daemon-startup.lock"),
100
+ getExternalDir: () => join(testDir, "external"),
101
+ getBinDir: () => join(testDir, "bin"),
102
+ getDotEnvPath: () => join(testDir, ".env"),
103
+ getEmbedWorkerPidPath: () => join(testDir, "embed-worker.pid"),
86
104
  getConversationsDir: () => join(testDir, "conversations"),
87
105
  getEmbeddingModelsDir: () => join(testDir, "models"),
88
106
  getSandboxRootDir: () => join(testDir, "sandbox"),
@@ -187,6 +205,7 @@ describe("assistant platform disconnect", () => {
187
205
  mockGetSecureKeyViaDaemon = async () => undefined;
188
206
  mockDeleteSecureKeyViaDaemonCalls = [];
189
207
  mockDeleteSecureKeyViaDaemonResult = "deleted";
208
+ mockIsPlatformRemote = false;
190
209
  process.exitCode = 0;
191
210
  });
192
211
 
@@ -233,5 +252,39 @@ describe("assistant platform disconnect", () => {
233
252
  expect(deletedNames).toContain("vellum:platform_assistant_id");
234
253
  expect(deletedNames).toContain("vellum:platform_organization_id");
235
254
  expect(deletedNames).toContain("vellum:platform_user_id");
255
+
256
+ // AND a platform_disconnected signal was emitted for connected clients
257
+ const signalPath = join(testDir, "signals", "emit-event");
258
+ expect(existsSync(signalPath)).toBe(true);
259
+ const signal = JSON.parse(readFileSync(signalPath, "utf-8"));
260
+ expect(signal).toEqual({ type: "platform_disconnected" });
261
+ });
262
+
263
+ test("rejects with error when running on a platform-hosted assistant", async () => {
264
+ /**
265
+ * Platform-hosted (containerized) assistants are managed by the platform
266
+ * and should not allow manual disconnect via the CLI.
267
+ */
268
+
269
+ // GIVEN the assistant is running inside a platform host
270
+ mockIsPlatformRemote = true;
271
+
272
+ // WHEN the disconnect command is run with --json
273
+ const { exitCode, stdout } = await runCommand([
274
+ "platform",
275
+ "disconnect",
276
+ "--json",
277
+ ]);
278
+
279
+ // THEN the command fails
280
+ expect(exitCode).toBe(1);
281
+
282
+ // AND the error message explains why
283
+ const parsed = JSON.parse(stdout);
284
+ expect(parsed.ok).toBe(false);
285
+ expect(parsed.error).toContain("platform-hosted");
286
+
287
+ // AND no credentials were deleted
288
+ expect(mockDeleteSecureKeyViaDaemonCalls).toHaveLength(0);
236
289
  });
237
290
  });
@@ -102,6 +102,14 @@ mock.module("../../../../util/platform.js", () => ({
102
102
  getLogPath: () => join(testDir, "test.log"),
103
103
  getWorkspaceDirDisplay: () => testDir,
104
104
  getWorkspacePromptPath: (file: string) => join(testDir, file),
105
+ getProtectedDir: () => join(testDir, "protected"),
106
+ getDeprecatedDir: () => join(testDir, "workspace", "deprecated"),
107
+ getExternalDir: () => join(testDir, "external"),
108
+ getBinDir: () => join(testDir, "bin"),
109
+ getDotEnvPath: () => join(testDir, ".env"),
110
+ getDaemonStderrLogPath: () => join(testDir, "daemon-stderr.log"),
111
+ getDaemonStartupLockPath: () => join(testDir, "daemon-startup.lock"),
112
+ getEmbedWorkerPidPath: () => join(testDir, "embed-worker.pid"),
105
113
  ensureDataDir: () => {},
106
114
  }));
107
115
 
@@ -243,4 +251,32 @@ describe("assistant platform status", () => {
243
251
  expect(parsed.organizationId).toBe("org-456");
244
252
  expect(parsed.userId).toBe("user-789");
245
253
  });
254
+
255
+ test("plain text mode does not emit JSON to stdout", async () => {
256
+ /**
257
+ * Without --json, the status command should only produce log output
258
+ * (via the CLI logger) and NOT write JSON to stdout. Previously both
259
+ * JSON and plain text were emitted, duplicating the information.
260
+ */
261
+
262
+ // GIVEN a disconnected environment with no stored credentials
263
+ mockResolvePlatformCallbackRegistrationContext = async () => ({
264
+ containerized: false,
265
+ platformBaseUrl: "",
266
+ assistantId: "",
267
+ hasInternalApiKey: false,
268
+ hasAssistantApiKey: false,
269
+ authHeader: null,
270
+ enabled: false,
271
+ });
272
+
273
+ // WHEN the status command is run without --json
274
+ const { exitCode, stdout } = await runCommand(["platform", "status"]);
275
+
276
+ // THEN the command succeeds
277
+ expect(exitCode).toBe(0);
278
+
279
+ // AND stdout contains no JSON (writeOutput is skipped in plain text mode)
280
+ expect(stdout.trim()).toBe("");
281
+ });
246
282
  });
@@ -1,6 +1,10 @@
1
+ import { mkdirSync, writeFileSync } from "node:fs";
2
+ import { join } from "node:path";
3
+
1
4
  import type { Command } from "commander";
2
5
 
3
6
  import { credentialKey } from "../../../security/credential-key.js";
7
+ import { getSignalsDir } from "../../../util/platform.js";
4
8
  import { getSecureKeyViaDaemon } from "../../lib/daemon-credential-client.js";
5
9
  import { getCliLogger } from "../../logger.js";
6
10
  import { shouldOutputJson, writeOutput } from "../../output.js";
@@ -32,8 +36,8 @@ export function registerPlatformConnectCommand(platform: Command): void {
32
36
  .addHelpText(
33
37
  "after",
34
38
  `
35
- Initiates a platform connection flow. Credentials are collected via a secure
36
- UI component rendered by the assistant client.
39
+ Initiates a platform connection flow. Emits a signal for connected clients
40
+ to show a platform login UI where the user can sign in and store credentials.
37
41
 
38
42
  Use 'assistant platform status' to check the current connection state and
39
43
  'assistant platform disconnect' to remove stored credentials.
@@ -83,15 +87,21 @@ Examples:
83
87
  return;
84
88
  }
85
89
 
86
- // TODO: Send a UI component to collect credentials from the user
87
- writeError(
88
- "Platform connect UI component not yet implemented. " +
89
- "Credentials will be collected via a secure client-side flow.",
90
+ // Emit a signal for the daemon to show the platform login UI
91
+ // on connected clients.
92
+ const signalsDir = getSignalsDir();
93
+ mkdirSync(signalsDir, { recursive: true });
94
+ writeFileSync(
95
+ join(signalsDir, "emit-event"),
96
+ JSON.stringify({ type: "show_platform_login" }),
90
97
  );
91
98
 
99
+ writeOutput(cmd, { ok: true, showPlatformLogin: true });
100
+
92
101
  if (!jsonMode) {
93
102
  log.info(
94
- "Platform connect will be available once the client-side credential flow is implemented.",
103
+ "Showing the platform login screen on connected clients. " +
104
+ "Please complete the sign-in flow in the app.",
95
105
  );
96
106
  }
97
107
  } catch (err) {
@@ -1,6 +1,11 @@
1
+ import { mkdirSync, writeFileSync } from "node:fs";
2
+ import { join } from "node:path";
3
+
1
4
  import type { Command } from "commander";
2
5
 
6
+ import { isPlatformRemote } from "../../../config/env-registry.js";
3
7
  import { credentialKey } from "../../../security/credential-key.js";
8
+ import { getSignalsDir } from "../../../util/platform.js";
4
9
  import {
5
10
  deleteSecureKeyViaDaemon,
6
11
  getSecureKeyViaDaemon,
@@ -46,7 +51,17 @@ Examples:
46
51
 
47
52
  try {
48
53
  // ---------------------------------------------------------------
49
- // 1. Check if connected
54
+ // 1. Reject if running inside a platform host
55
+ // ---------------------------------------------------------------
56
+ if (isPlatformRemote()) {
57
+ writeError(
58
+ "Cannot disconnect from the platform on a platform-hosted assistant.",
59
+ );
60
+ return;
61
+ }
62
+
63
+ // ---------------------------------------------------------------
64
+ // 2. Check if connected
50
65
  // ---------------------------------------------------------------
51
66
  const baseUrl = await getSecureKeyViaDaemon(
52
67
  credentialKey(
@@ -70,7 +85,7 @@ Examples:
70
85
  }
71
86
 
72
87
  // ---------------------------------------------------------------
73
- // 2. Delete all platform credentials
88
+ // 3. Delete all platform credentials
74
89
  // ---------------------------------------------------------------
75
90
  const keysToDelete = [
76
91
  CREDENTIAL_KEYS.baseUrl,
@@ -97,7 +112,17 @@ Examples:
97
112
  }
98
113
 
99
114
  // ---------------------------------------------------------------
100
- // 3. Output result
115
+ // 4. Notify connected clients
116
+ // ---------------------------------------------------------------
117
+ const signalsDir = getSignalsDir();
118
+ mkdirSync(signalsDir, { recursive: true });
119
+ writeFileSync(
120
+ join(signalsDir, "emit-event"),
121
+ JSON.stringify({ type: "platform_disconnected" }),
122
+ );
123
+
124
+ // ---------------------------------------------------------------
125
+ // 5. Output result
101
126
  // ---------------------------------------------------------------
102
127
  writeOutput(cmd, {
103
128
  ok: true,
@@ -123,9 +123,9 @@ Examples:
123
123
  userId: userId || null,
124
124
  };
125
125
 
126
- writeOutput(cmd, result);
127
-
128
- if (!shouldOutputJson(cmd)) {
126
+ if (shouldOutputJson(cmd)) {
127
+ writeOutput(cmd, result);
128
+ } else {
129
129
  log.info(`Containerized: ${result.containerized}`);
130
130
  log.info(`Base URL: ${result.baseUrl || "(not set)"}`);
131
131
  log.info(`Assistant ID: ${result.assistantId || "(not set)"}`);