@vellumai/assistant 0.5.5 → 0.5.7

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 (382) hide show
  1. package/.env.example +16 -2
  2. package/ARCHITECTURE.md +6 -75
  3. package/Dockerfile +4 -5
  4. package/README.md +0 -2
  5. package/bun.lock +0 -414
  6. package/docs/architecture/keychain-broker.md +45 -240
  7. package/docs/architecture/security.md +0 -17
  8. package/docs/credential-execution-service.md +2 -2
  9. package/node_modules/@vellumai/ces-contracts/package.json +1 -0
  10. package/node_modules/@vellumai/ces-contracts/src/rpc.ts +119 -0
  11. package/node_modules/@vellumai/credential-storage/package.json +1 -0
  12. package/node_modules/@vellumai/egress-proxy/package.json +1 -0
  13. package/package.json +2 -3
  14. package/src/__tests__/actor-token-service.test.ts +1 -2
  15. package/src/__tests__/assistant-feature-flags-integration.test.ts +30 -29
  16. package/src/__tests__/browser-skill-endstate.test.ts +6 -5
  17. package/src/__tests__/btw-routes.test.ts +0 -39
  18. package/src/__tests__/call-domain.test.ts +0 -128
  19. package/src/__tests__/ces-rpc-credential-backend.test.ts +199 -0
  20. package/src/__tests__/channel-approval-routes.test.ts +0 -5
  21. package/src/__tests__/channel-readiness-service.test.ts +1 -60
  22. package/src/__tests__/checker.test.ts +4 -2
  23. package/src/__tests__/cli-command-risk-guard.test.ts +112 -0
  24. package/src/__tests__/config-schema-cmd.test.ts +0 -1
  25. package/src/__tests__/config-schema.test.ts +3 -3
  26. package/src/__tests__/context-window-manager.test.ts +78 -0
  27. package/src/__tests__/conversation-attention-telegram.test.ts +0 -5
  28. package/src/__tests__/conversation-init.benchmark.test.ts +0 -2
  29. package/src/__tests__/conversation-skill-tools.test.ts +0 -54
  30. package/src/__tests__/conversation-title-service.test.ts +117 -1
  31. package/src/__tests__/credential-execution-feature-gates.test.ts +28 -14
  32. package/src/__tests__/credential-execution-managed-contract.test.ts +33 -18
  33. package/src/__tests__/credential-security-e2e.test.ts +0 -66
  34. package/src/__tests__/credential-security-invariants.test.ts +4 -45
  35. package/src/__tests__/credentials-cli.test.ts +78 -0
  36. package/src/__tests__/db-migration-rollback.test.ts +2015 -1
  37. package/src/__tests__/docker-signing-key-bootstrap.test.ts +98 -0
  38. package/src/__tests__/dynamic-skill-workflow-prompt.test.ts +6 -4
  39. package/src/__tests__/guardian-routing-state.test.ts +0 -5
  40. package/src/__tests__/host-shell-tool.test.ts +6 -7
  41. package/src/__tests__/http-user-message-parity.test.ts +3 -103
  42. package/src/__tests__/inbound-invite-redemption.test.ts +0 -4
  43. package/src/__tests__/inline-skill-load-permissions.test.ts +6 -8
  44. package/src/__tests__/intent-routing.test.ts +0 -13
  45. package/src/__tests__/jobs-store-qdrant-breaker.test.ts +178 -0
  46. package/src/__tests__/keychain-broker-client.test.ts +161 -22
  47. package/src/__tests__/memory-jobs-worker-backoff.test.ts +150 -0
  48. package/src/__tests__/memory-regressions.test.ts +8 -30
  49. package/src/__tests__/migration-export-http.test.ts +2 -2
  50. package/src/__tests__/migration-import-commit-http.test.ts +2 -2
  51. package/src/__tests__/migration-import-preflight-http.test.ts +2 -2
  52. package/src/__tests__/migration-validate-http.test.ts +2 -2
  53. package/src/__tests__/non-member-access-request.test.ts +0 -5
  54. package/src/__tests__/notification-decision-fallback.test.ts +4 -0
  55. package/src/__tests__/notification-decision-identity.test.ts +4 -0
  56. package/src/__tests__/permission-types.test.ts +1 -0
  57. package/src/__tests__/provider-managed-proxy-integration.test.ts +5 -6
  58. package/src/__tests__/qdrant-manager.test.ts +28 -2
  59. package/src/__tests__/registry.test.ts +0 -6
  60. package/src/__tests__/require-fresh-approval.test.ts +4 -0
  61. package/src/__tests__/runtime-attachment-metadata.test.ts +0 -4
  62. package/src/__tests__/secret-routes-managed-proxy.test.ts +0 -4
  63. package/src/__tests__/secure-keys.test.ts +83 -263
  64. package/src/__tests__/shell-identity.test.ts +96 -6
  65. package/src/__tests__/skill-feature-flags-integration.test.ts +22 -14
  66. package/src/__tests__/skill-feature-flags.test.ts +46 -45
  67. package/src/__tests__/skill-load-feature-flag.test.ts +7 -10
  68. package/src/__tests__/skill-load-inline-command.test.ts +8 -12
  69. package/src/__tests__/skill-load-inline-includes.test.ts +6 -10
  70. package/src/__tests__/skill-load-tool.test.ts +0 -2
  71. package/src/__tests__/skill-projection-feature-flag.test.ts +33 -29
  72. package/src/__tests__/skills.test.ts +0 -2
  73. package/src/__tests__/slack-inbound-verification.test.ts +0 -4
  74. package/src/__tests__/suggestion-routes.test.ts +1 -32
  75. package/src/__tests__/system-prompt.test.ts +0 -1
  76. package/src/__tests__/tool-executor-lifecycle-events.test.ts +4 -0
  77. package/src/__tests__/tool-executor-shell-integration.test.ts +5 -3
  78. package/src/__tests__/tool-executor.test.ts +4 -0
  79. package/src/__tests__/trusted-contact-lifecycle-notifications.test.ts +0 -5
  80. package/src/__tests__/trusted-contact-multichannel.test.ts +0 -4
  81. package/src/__tests__/update-bulletin.test.ts +0 -2
  82. package/src/__tests__/vellum-self-knowledge-inline-command.test.ts +6 -9
  83. package/src/__tests__/voice-scoped-grant-consumer.test.ts +0 -6
  84. package/src/__tests__/workspace-migration-015-migrate-credentials-to-keychain.test.ts +252 -0
  85. package/src/__tests__/workspace-migration-016-migrate-credentials-from-keychain.test.ts +218 -0
  86. package/src/__tests__/workspace-migration-down-functions.test.ts +1009 -0
  87. package/src/__tests__/workspace-migrations-runner.test.ts +114 -0
  88. package/src/calls/audio-store.test.ts +97 -0
  89. package/src/calls/audio-store.ts +205 -0
  90. package/src/calls/call-controller.ts +85 -7
  91. package/src/calls/call-domain.ts +3 -0
  92. package/src/calls/call-store.ts +10 -3
  93. package/src/calls/fish-audio-client.ts +117 -0
  94. package/src/calls/relay-server.ts +27 -0
  95. package/src/calls/twilio-routes.ts +2 -1
  96. package/src/calls/types.ts +1 -0
  97. package/src/calls/voice-ingress-preflight.ts +0 -42
  98. package/src/calls/voice-quality.ts +26 -5
  99. package/src/calls/voice-session-bridge.ts +6 -12
  100. package/src/cli/commands/config.ts +1 -4
  101. package/src/cli/commands/conversations.ts +0 -18
  102. package/src/cli/commands/credentials.ts +34 -4
  103. package/src/cli/commands/oauth/index.ts +7 -0
  104. package/src/cli/commands/oauth/platform.ts +179 -0
  105. package/src/cli/commands/platform.ts +3 -3
  106. package/src/config/assistant-feature-flags.ts +186 -5
  107. package/src/config/bundled-skills/messaging/SKILL.md +5 -5
  108. package/src/config/bundled-skills/phone-calls/TOOLS.json +4 -0
  109. package/src/config/bundled-skills/settings/TOOLS.json +2 -2
  110. package/src/config/bundled-skills/settings/tools/voice-config-update.ts +42 -0
  111. package/src/config/bundled-tool-registry.ts +1 -11
  112. package/src/config/env-registry.ts +1 -1
  113. package/src/config/env.ts +16 -16
  114. package/src/config/feature-flag-registry.json +48 -16
  115. package/src/config/loader.ts +98 -31
  116. package/src/config/schema.ts +4 -25
  117. package/src/config/schemas/calls.ts +13 -0
  118. package/src/config/schemas/fish-audio.ts +39 -0
  119. package/src/config/schemas/memory.ts +0 -4
  120. package/src/config/schemas/platform.ts +1 -1
  121. package/src/config/schemas/security.ts +4 -4
  122. package/src/config/types.ts +0 -1
  123. package/src/contacts/contact-store.ts +39 -0
  124. package/src/contacts/types.ts +2 -0
  125. package/src/context/window-manager.ts +53 -2
  126. package/src/credential-execution/approval-bridge.ts +1 -0
  127. package/src/credential-execution/executable-discovery.ts +28 -4
  128. package/src/credential-execution/feature-gates.ts +16 -0
  129. package/src/credential-execution/process-manager.ts +38 -0
  130. package/src/daemon/assistant-attachments.ts +9 -0
  131. package/src/daemon/config-watcher.ts +6 -4
  132. package/src/daemon/conversation-agent-loop.ts +0 -60
  133. package/src/daemon/conversation-memory.ts +0 -117
  134. package/src/daemon/conversation-runtime-assembly.ts +0 -2
  135. package/src/daemon/conversation-tool-setup.ts +0 -105
  136. package/src/daemon/conversation.ts +10 -1
  137. package/src/daemon/handlers/config-vercel.ts +92 -0
  138. package/src/daemon/handlers/conversations.ts +0 -11
  139. package/src/daemon/handlers/skills.ts +2 -15
  140. package/src/daemon/install-symlink.ts +195 -0
  141. package/src/daemon/lifecycle.ts +229 -96
  142. package/src/daemon/message-types/conversations.ts +3 -4
  143. package/src/daemon/message-types/diagnostics.ts +3 -22
  144. package/src/daemon/message-types/messages.ts +0 -2
  145. package/src/daemon/message-types/upgrades.ts +8 -0
  146. package/src/daemon/server.ts +30 -92
  147. package/src/events/domain-events.ts +2 -1
  148. package/src/followups/followup-store.ts +5 -2
  149. package/src/inbound/platform-callback-registration.ts +3 -3
  150. package/src/instrument.ts +8 -5
  151. package/src/memory/conversation-crud.ts +0 -236
  152. package/src/memory/conversation-title-service.ts +76 -11
  153. package/src/memory/db-init.ts +15 -11
  154. package/src/memory/indexer.ts +15 -106
  155. package/src/memory/items-extractor.ts +15 -1
  156. package/src/memory/job-handlers/conversation-starters.ts +4 -1
  157. package/src/memory/job-handlers/embedding.ts +0 -79
  158. package/src/memory/job-utils.ts +1 -1
  159. package/src/memory/jobs-store.ts +30 -13
  160. package/src/memory/jobs-worker.ts +31 -27
  161. package/src/memory/migrations/001-job-deferrals.ts +19 -0
  162. package/src/memory/migrations/004-entity-relation-dedup.ts +10 -0
  163. package/src/memory/migrations/005-fingerprint-scope-unique.ts +76 -0
  164. package/src/memory/migrations/006-scope-salted-fingerprints.ts +50 -0
  165. package/src/memory/migrations/007-assistant-id-to-self.ts +10 -0
  166. package/src/memory/migrations/008-remove-assistant-id-columns.ts +34 -0
  167. package/src/memory/migrations/009-llm-usage-events-drop-assistant-id.ts +26 -0
  168. package/src/memory/migrations/014-backfill-inbox-thread-state.ts +10 -0
  169. package/src/memory/migrations/015-drop-active-search-index.ts +17 -0
  170. package/src/memory/migrations/019-notification-tables-schema-migration.ts +12 -0
  171. package/src/memory/migrations/020-rename-macos-ios-channel-to-vellum.ts +121 -0
  172. package/src/memory/migrations/024-embedding-vector-blob.ts +74 -0
  173. package/src/memory/migrations/026a-embeddings-nullable-vector-json.ts +82 -0
  174. package/src/memory/migrations/036-normalize-phone-identities.ts +11 -0
  175. package/src/memory/migrations/116-messages-fts.ts +106 -1
  176. package/src/memory/migrations/126-backfill-guardian-principal-id.ts +52 -0
  177. package/src/memory/migrations/127-guardian-principal-id-not-null.ts +77 -0
  178. package/src/memory/migrations/134-contacts-notes-column.ts +13 -0
  179. package/src/memory/migrations/135-backfill-contact-interaction-stats.ts +20 -0
  180. package/src/memory/migrations/136-drop-assistant-id-columns.ts +52 -0
  181. package/src/memory/migrations/140-backfill-usage-cache-accounting.ts +13 -0
  182. package/src/memory/migrations/141-rename-verification-table.ts +54 -0
  183. package/src/memory/migrations/142-rename-verification-session-id-column.ts +25 -0
  184. package/src/memory/migrations/143-rename-guardian-verification-values.ts +35 -0
  185. package/src/memory/migrations/144-rename-voice-to-phone.ts +136 -0
  186. package/src/memory/migrations/145-drop-accounts-table.ts +32 -0
  187. package/src/memory/migrations/147-migrate-reminders-to-schedules.ts +14 -1
  188. package/src/memory/migrations/148-drop-reminders-table.ts +35 -1
  189. package/src/memory/migrations/150-oauth-apps-client-secret-path.ts +69 -1
  190. package/src/memory/migrations/162-guardian-timestamps-epoch-ms.ts +290 -0
  191. package/src/memory/migrations/169-rename-gmail-provider-key-to-google.ts +51 -1
  192. package/src/memory/migrations/174-rename-thread-starters-table.ts +47 -1
  193. package/src/memory/migrations/176-drop-capability-card-state.ts +13 -0
  194. package/src/memory/migrations/180-backfill-inline-attachments-to-disk.ts +16 -0
  195. package/src/memory/migrations/181-rename-thread-starters-checkpoints.ts +28 -1
  196. package/src/memory/migrations/189-drop-simplified-memory.ts +42 -0
  197. package/src/memory/migrations/190-call-session-skip-disclosure.ts +15 -0
  198. package/src/memory/migrations/191-backfill-audio-attachment-mime-types.ts +64 -0
  199. package/src/memory/migrations/192-contacts-user-file-column.ts +15 -0
  200. package/src/memory/migrations/index.ts +5 -3
  201. package/src/memory/migrations/registry.ts +90 -0
  202. package/src/memory/migrations/validate-migration-state.ts +137 -11
  203. package/src/memory/qdrant-circuit-breaker.ts +9 -0
  204. package/src/memory/qdrant-client.ts +4 -6
  205. package/src/memory/qdrant-manager.ts +64 -7
  206. package/src/memory/schema/calls.ts +1 -0
  207. package/src/memory/schema/contacts.ts +1 -0
  208. package/src/memory/schema/conversations.ts +0 -3
  209. package/src/memory/schema/index.ts +0 -2
  210. package/src/messaging/draft-store.ts +2 -2
  211. package/src/notifications/decision-engine.ts +4 -1
  212. package/src/oauth/connection-resolver.ts +6 -4
  213. package/src/permissions/checker.ts +0 -38
  214. package/src/permissions/defaults.ts +3 -3
  215. package/src/permissions/shell-identity.ts +76 -22
  216. package/src/permissions/trust-client.ts +2 -13
  217. package/src/permissions/trust-store.ts +8 -3
  218. package/src/permissions/types.ts +4 -2
  219. package/src/platform/client.ts +35 -7
  220. package/src/prompts/persona-resolver.ts +138 -0
  221. package/src/prompts/system-prompt.ts +36 -4
  222. package/src/prompts/templates/users/default.md +1 -0
  223. package/src/providers/registry.ts +27 -40
  224. package/src/runtime/auth/__tests__/credential-service.test.ts +0 -1
  225. package/src/runtime/auth/__tests__/external-assistant-id.test.ts +13 -68
  226. package/src/runtime/auth/external-assistant-id.ts +13 -59
  227. package/src/runtime/auth/route-policy.ts +29 -1
  228. package/src/runtime/auth/token-service.ts +53 -15
  229. package/src/runtime/channel-readiness-service.ts +1 -16
  230. package/src/runtime/http-server.ts +29 -2
  231. package/src/runtime/middleware/error-handler.ts +1 -9
  232. package/src/runtime/routes/audio-routes.ts +40 -0
  233. package/src/runtime/routes/btw-routes.ts +0 -17
  234. package/src/runtime/routes/conversation-management-routes.ts +0 -36
  235. package/src/runtime/routes/conversation-query-routes.ts +106 -2
  236. package/src/runtime/routes/conversation-routes.ts +4 -43
  237. package/src/runtime/routes/diagnostics-routes.ts +1 -477
  238. package/src/runtime/routes/identity-routes.ts +18 -29
  239. package/src/runtime/routes/inbound-stages/secret-ingress-check.ts +4 -33
  240. package/src/runtime/routes/inbound-stages/transcribe-audio.test.ts +1 -1
  241. package/src/runtime/routes/integrations/vercel.ts +89 -0
  242. package/src/runtime/routes/log-export-routes.ts +5 -0
  243. package/src/runtime/routes/memory-item-routes.test.ts +221 -3
  244. package/src/runtime/routes/memory-item-routes.ts +144 -4
  245. package/src/runtime/routes/migration-rollback-routes.ts +209 -0
  246. package/src/runtime/routes/migration-routes.ts +17 -1
  247. package/src/runtime/routes/notification-routes.ts +58 -0
  248. package/src/runtime/routes/schedule-routes.ts +65 -0
  249. package/src/runtime/routes/settings-routes.ts +41 -1
  250. package/src/runtime/routes/tts-routes.ts +86 -0
  251. package/src/runtime/routes/upgrade-broadcast-routes.ts +175 -0
  252. package/src/runtime/routes/workspace-commit-routes.ts +62 -0
  253. package/src/runtime/routes/workspace-routes.test.ts +22 -1
  254. package/src/runtime/routes/workspace-routes.ts +1 -1
  255. package/src/runtime/routes/workspace-utils.ts +86 -2
  256. package/src/schedule/schedule-store.ts +0 -21
  257. package/src/security/ces-credential-client.ts +59 -22
  258. package/src/security/ces-rpc-credential-backend.ts +85 -0
  259. package/src/security/credential-backend.ts +12 -88
  260. package/src/security/keychain-broker-client.ts +10 -2
  261. package/src/security/secure-keys.ts +94 -113
  262. package/src/skills/catalog-install.ts +13 -7
  263. package/src/skills/inline-command-render.ts +5 -1
  264. package/src/skills/inline-command-runner.ts +30 -2
  265. package/src/telemetry/usage-telemetry-reporter.ts +4 -2
  266. package/src/tools/calls/call-start.ts +1 -0
  267. package/src/tools/executor.ts +0 -4
  268. package/src/tools/memory/handlers.ts +1 -129
  269. package/src/tools/network/script-proxy/session-manager.ts +19 -4
  270. package/src/tools/network/web-fetch.ts +3 -1
  271. package/src/tools/permission-checker.ts +18 -0
  272. package/src/tools/skills/execute.ts +1 -1
  273. package/src/tools/skills/load.ts +9 -2
  274. package/src/tools/types.ts +0 -8
  275. package/src/util/errors.ts +0 -12
  276. package/src/util/platform.ts +8 -55
  277. package/src/util/xml.ts +8 -0
  278. package/src/workspace/git-service.ts +5 -2
  279. package/src/workspace/heartbeat-service.ts +5 -24
  280. package/src/workspace/migrations/001-avatar-rename.ts +15 -0
  281. package/src/workspace/migrations/003-seed-device-id.ts +17 -1
  282. package/src/workspace/migrations/004-extract-collect-usage-data.ts +33 -0
  283. package/src/workspace/migrations/005-add-send-diagnostics.ts +3 -0
  284. package/src/workspace/migrations/006-services-config.ts +49 -0
  285. package/src/workspace/migrations/007-web-search-provider-rename.ts +27 -0
  286. package/src/workspace/migrations/008-voice-timeout-and-max-steps.ts +3 -0
  287. package/src/workspace/migrations/009-backfill-conversation-disk-view.ts +4 -0
  288. package/src/workspace/migrations/010-app-dir-rename.ts +78 -0
  289. package/src/workspace/migrations/011-backfill-installation-id.ts +11 -0
  290. package/src/workspace/migrations/012-rename-conversation-disk-view-dirs.ts +44 -0
  291. package/src/workspace/migrations/013-repair-conversation-disk-view.ts +5 -0
  292. package/src/workspace/migrations/015-migrate-credentials-to-keychain.ts +153 -0
  293. package/src/workspace/migrations/016-extract-feature-flags-to-protected.ts +156 -0
  294. package/src/workspace/migrations/016-migrate-credentials-from-keychain.ts +150 -0
  295. package/src/workspace/migrations/017-seed-persona-dirs.ts +95 -0
  296. package/src/workspace/migrations/migrate-to-workspace-volume.ts +23 -1
  297. package/src/workspace/migrations/registry.ts +8 -0
  298. package/src/workspace/migrations/runner.ts +106 -2
  299. package/src/workspace/migrations/types.ts +4 -0
  300. package/src/__tests__/archive-recall.test.ts +0 -560
  301. package/src/__tests__/claude-code-skill-regression.test.ts +0 -206
  302. package/src/__tests__/claude-code-tool-profiles.test.ts +0 -99
  303. package/src/__tests__/conversation-memory-dirty-tail.test.ts +0 -150
  304. package/src/__tests__/conversation-switch-memory-reduction.test.ts +0 -474
  305. package/src/__tests__/db-memory-archive-migration.test.ts +0 -372
  306. package/src/__tests__/db-memory-brief-state-migration.test.ts +0 -213
  307. package/src/__tests__/db-memory-reducer-checkpoints.test.ts +0 -273
  308. package/src/__tests__/diagnostics-export.test.ts +0 -288
  309. package/src/__tests__/local-gateway-health.test.ts +0 -209
  310. package/src/__tests__/memory-brief-open-loops.test.ts +0 -530
  311. package/src/__tests__/memory-brief-time.test.ts +0 -285
  312. package/src/__tests__/memory-brief-wrapper.test.ts +0 -311
  313. package/src/__tests__/memory-chunk-archive.test.ts +0 -400
  314. package/src/__tests__/memory-chunk-dual-write.test.ts +0 -453
  315. package/src/__tests__/memory-episode-archive.test.ts +0 -370
  316. package/src/__tests__/memory-episode-dual-write.test.ts +0 -626
  317. package/src/__tests__/memory-observation-archive.test.ts +0 -375
  318. package/src/__tests__/memory-observation-dual-write.test.ts +0 -318
  319. package/src/__tests__/memory-reducer-job.test.ts +0 -538
  320. package/src/__tests__/memory-reducer-scheduling.test.ts +0 -473
  321. package/src/__tests__/memory-reducer-store.test.ts +0 -728
  322. package/src/__tests__/memory-reducer-types.test.ts +0 -707
  323. package/src/__tests__/memory-reducer.test.ts +0 -704
  324. package/src/__tests__/memory-simplified-config.test.ts +0 -281
  325. package/src/__tests__/secret-ingress-handler.test.ts +0 -120
  326. package/src/__tests__/simplified-memory-e2e.test.ts +0 -666
  327. package/src/__tests__/simplified-memory-runtime.test.ts +0 -616
  328. package/src/__tests__/swarm-conversation-integration.test.ts +0 -358
  329. package/src/__tests__/swarm-dag-pathological.test.ts +0 -547
  330. package/src/__tests__/swarm-orchestrator.test.ts +0 -463
  331. package/src/__tests__/swarm-plan-validator.test.ts +0 -384
  332. package/src/__tests__/swarm-recursion.test.ts +0 -197
  333. package/src/__tests__/swarm-router-planner.test.ts +0 -234
  334. package/src/__tests__/swarm-tool.test.ts +0 -185
  335. package/src/__tests__/swarm-worker-backend.test.ts +0 -144
  336. package/src/__tests__/swarm-worker-runner.test.ts +0 -288
  337. package/src/commands/__tests__/cc-command-registry.test.ts +0 -396
  338. package/src/commands/cc-command-registry.ts +0 -248
  339. package/src/config/bundled-skills/claude-code/SKILL.md +0 -53
  340. package/src/config/bundled-skills/claude-code/TOOLS.json +0 -47
  341. package/src/config/bundled-skills/claude-code/tools/claude-code.ts +0 -12
  342. package/src/config/bundled-skills/orchestration/SKILL.md +0 -33
  343. package/src/config/bundled-skills/orchestration/TOOLS.json +0 -35
  344. package/src/config/bundled-skills/orchestration/tools/swarm-delegate.ts +0 -12
  345. package/src/config/schemas/memory-simplified.ts +0 -101
  346. package/src/config/schemas/swarm.ts +0 -82
  347. package/src/logfire.ts +0 -135
  348. package/src/memory/archive-recall.ts +0 -516
  349. package/src/memory/archive-store.ts +0 -400
  350. package/src/memory/brief-formatting.ts +0 -33
  351. package/src/memory/brief-open-loops.ts +0 -266
  352. package/src/memory/brief-time.ts +0 -162
  353. package/src/memory/brief.ts +0 -75
  354. package/src/memory/job-handlers/backfill-simplified-memory.ts +0 -462
  355. package/src/memory/job-handlers/reduce-conversation-memory.ts +0 -229
  356. package/src/memory/migrations/185-memory-brief-state.ts +0 -52
  357. package/src/memory/migrations/186-memory-archive.ts +0 -109
  358. package/src/memory/migrations/187-memory-reducer-checkpoints.ts +0 -19
  359. package/src/memory/reducer-scheduler.ts +0 -242
  360. package/src/memory/reducer-store.ts +0 -271
  361. package/src/memory/reducer-types.ts +0 -106
  362. package/src/memory/reducer.ts +0 -467
  363. package/src/memory/schema/memory-archive.ts +0 -121
  364. package/src/memory/schema/memory-brief.ts +0 -55
  365. package/src/runtime/local-gateway-health.ts +0 -275
  366. package/src/security/secret-ingress.ts +0 -68
  367. package/src/swarm/backend-claude-code.ts +0 -225
  368. package/src/swarm/checkpoint.ts +0 -137
  369. package/src/swarm/graph-utils.ts +0 -53
  370. package/src/swarm/index.ts +0 -55
  371. package/src/swarm/limits.ts +0 -66
  372. package/src/swarm/orchestrator.ts +0 -424
  373. package/src/swarm/plan-validator.ts +0 -117
  374. package/src/swarm/router-planner.ts +0 -162
  375. package/src/swarm/router-prompts.ts +0 -39
  376. package/src/swarm/synthesizer.ts +0 -81
  377. package/src/swarm/types.ts +0 -72
  378. package/src/swarm/worker-backend.ts +0 -131
  379. package/src/swarm/worker-prompts.ts +0 -80
  380. package/src/swarm/worker-runner.ts +0 -170
  381. package/src/tools/claude-code/claude-code.ts +0 -610
  382. package/src/tools/swarm/delegate.ts +0 -205
@@ -0,0 +1,89 @@
1
+ /**
2
+ * Route handlers for Vercel integration config endpoints.
3
+ *
4
+ * GET /v1/integrations/vercel/config — check if a Vercel API token is stored
5
+ * POST /v1/integrations/vercel/config — set or delete token (dispatched via action field)
6
+ * DELETE /v1/integrations/vercel/config — delete the stored Vercel API token
7
+ *
8
+ * The Swift client sends all mutations as POST with an `action` field
9
+ * ("set" or "delete") rather than using HTTP verbs directly.
10
+ */
11
+
12
+ import {
13
+ deleteVercelConfig,
14
+ getVercelConfig,
15
+ setVercelConfig,
16
+ } from "../../../daemon/handlers/config-vercel.js";
17
+ import type { RouteDefinition } from "../../http-router.js";
18
+
19
+ /**
20
+ * GET /v1/integrations/vercel/config
21
+ */
22
+ export async function handleGetVercelConfig(): Promise<Response> {
23
+ const result = await getVercelConfig();
24
+ return Response.json(result);
25
+ }
26
+
27
+ /**
28
+ * POST /v1/integrations/vercel/config
29
+ *
30
+ * Body: { action: "set" | "delete"; apiToken?: string }
31
+ *
32
+ * The Swift client uses POST for both set and delete operations,
33
+ * distinguished by the `action` field.
34
+ */
35
+ export async function handlePostVercelConfig(req: Request): Promise<Response> {
36
+ const body = (await req.json()) as {
37
+ action?: "get" | "set" | "delete";
38
+ apiToken?: string;
39
+ };
40
+
41
+ switch (body.action) {
42
+ case "delete": {
43
+ const result = await deleteVercelConfig();
44
+ return Response.json(result);
45
+ }
46
+ case "get": {
47
+ const result = await getVercelConfig();
48
+ return Response.json(result);
49
+ }
50
+ case "set":
51
+ default: {
52
+ const result = await setVercelConfig(body.apiToken);
53
+ const status = result.success ? 200 : 400;
54
+ return Response.json(result, { status });
55
+ }
56
+ }
57
+ }
58
+
59
+ /**
60
+ * DELETE /v1/integrations/vercel/config
61
+ */
62
+ export async function handleDeleteVercelConfig(): Promise<Response> {
63
+ const result = await deleteVercelConfig();
64
+ return Response.json(result);
65
+ }
66
+
67
+ // ---------------------------------------------------------------------------
68
+ // Route definitions
69
+ // ---------------------------------------------------------------------------
70
+
71
+ export function vercelRouteDefinitions(): RouteDefinition[] {
72
+ return [
73
+ {
74
+ endpoint: "integrations/vercel/config",
75
+ method: "GET",
76
+ handler: () => handleGetVercelConfig(),
77
+ },
78
+ {
79
+ endpoint: "integrations/vercel/config",
80
+ method: "POST",
81
+ handler: async ({ req }) => handlePostVercelConfig(req),
82
+ },
83
+ {
84
+ endpoint: "integrations/vercel/config",
85
+ method: "DELETE",
86
+ handler: async () => handleDeleteVercelConfig(),
87
+ },
88
+ ];
89
+ }
@@ -37,6 +37,7 @@ import {
37
37
  getWorkspaceConfigPath,
38
38
  getWorkspaceDir,
39
39
  } from "../../util/platform.js";
40
+ import { APP_VERSION, COMMIT_SHA } from "../../version.js";
40
41
  import { httpError } from "../http-errors.js";
41
42
  import type { RouteDefinition } from "../http-router.js";
42
43
 
@@ -264,12 +265,16 @@ async function handleExport(body: ExportRequestBody): Promise<Response> {
264
265
  ? {
265
266
  type: "conversation-export" as const,
266
267
  conversationId,
268
+ assistantVersion: APP_VERSION,
269
+ commitSha: COMMIT_SHA,
267
270
  ...(startTime !== undefined ? { startTime } : {}),
268
271
  ...(endTime !== undefined ? { endTime } : {}),
269
272
  exportedAt: new Date().toISOString(),
270
273
  }
271
274
  : {
272
275
  type: "global-export" as const,
276
+ assistantVersion: APP_VERSION,
277
+ commitSha: COMMIT_SHA,
273
278
  exportedAt: new Date().toISOString(),
274
279
  };
275
280
  writeFileSync(
@@ -37,13 +37,55 @@ mock.module("../../util/logger.js", () => ({
37
37
  }),
38
38
  }));
39
39
 
40
- // Stub config loader
40
+ // Stub config loader — returns a config with memory enabled by default
41
41
  mock.module("../../config/loader.js", () => ({
42
- loadConfig: () => ({}),
43
- getConfig: () => ({}),
42
+ loadConfig: () => mockConfig,
43
+ getConfig: () => mockConfig,
44
44
  invalidateConfigCache: () => {},
45
45
  }));
46
46
 
47
+ // ── Controllable mocks for semantic search ─────────────────────────────
48
+ const mockConfig: unknown = {};
49
+
50
+ let mockBackendStatus: {
51
+ enabled: boolean;
52
+ provider: string | null;
53
+ model: string | null;
54
+ } = { enabled: false, provider: null, model: null };
55
+
56
+ const mockEmbedResult: {
57
+ provider: string;
58
+ model: string;
59
+ vectors: number[][];
60
+ } = { provider: "local", model: "test", vectors: [[0.1, 0.2, 0.3]] };
61
+
62
+ let mockHybridSearchResults: Array<{
63
+ id: string;
64
+ score: number;
65
+ payload: Record<string, unknown>;
66
+ }> = [];
67
+
68
+ mock.module("../../memory/embedding-backend.js", () => ({
69
+ getMemoryBackendStatus: async () => mockBackendStatus,
70
+ embedWithBackend: async () => mockEmbedResult,
71
+ generateSparseEmbedding: () => ({
72
+ indices: [0, 1, 2],
73
+ values: [0.5, 0.3, 0.2],
74
+ }),
75
+ }));
76
+
77
+ mock.module("../../memory/qdrant-client.js", () => ({
78
+ getQdrantClient: () => ({
79
+ hybridSearch: async () => [...mockHybridSearchResults],
80
+ searchWithFilter: async () => [...mockHybridSearchResults],
81
+ }),
82
+ initQdrantClient: () => {},
83
+ }));
84
+
85
+ mock.module("../../memory/qdrant-circuit-breaker.js", () => ({
86
+ withQdrantBreaker: async (fn: () => Promise<unknown>) => fn(),
87
+ }));
88
+
47
89
  import { and, eq } from "drizzle-orm";
48
90
 
49
91
  import { getDb, initializeDb, resetDb } from "../../memory/db.js";
@@ -392,6 +434,182 @@ describe("Memory Item Routes", () => {
392
434
  const res = await handler(ctx);
393
435
  expect(res.status).toBe(400);
394
436
  });
437
+
438
+ // ── Semantic / hybrid search ──────────────────────────────────────
439
+
440
+ test("uses semantic search when embedding backend is available", async () => {
441
+ insertItem({
442
+ id: "i1",
443
+ kind: "preference",
444
+ subject: "dark mode",
445
+ statement: "User prefers dark mode",
446
+ });
447
+ insertItem({
448
+ id: "i2",
449
+ kind: "identity",
450
+ subject: "name",
451
+ statement: "User name is Alice",
452
+ });
453
+
454
+ // Enable semantic search
455
+ mockBackendStatus = {
456
+ enabled: true,
457
+ provider: "local",
458
+ model: "test",
459
+ };
460
+ // Qdrant returns i2 first (higher relevance), then i1
461
+ mockHybridSearchResults = [
462
+ {
463
+ id: "pt-2",
464
+ score: 0.95,
465
+ payload: { target_type: "item", target_id: "i2" },
466
+ },
467
+ {
468
+ id: "pt-1",
469
+ score: 0.7,
470
+ payload: { target_type: "item", target_id: "i1" },
471
+ },
472
+ ];
473
+
474
+ const ctx = makeCtx({ search: "alice" });
475
+ const res = await handler(ctx);
476
+ const body = (await res.json()) as {
477
+ items: Array<{ id: string }>;
478
+ total: number;
479
+ };
480
+
481
+ // Results in Qdrant relevance order (i2 first)
482
+ expect(body.items.length).toBe(2);
483
+ expect(body.items[0].id).toBe("i2");
484
+ expect(body.items[1].id).toBe("i1");
485
+ expect(body.total).toBe(2);
486
+
487
+ // Reset
488
+ mockBackendStatus = { enabled: false, provider: null, model: null };
489
+ mockHybridSearchResults = [];
490
+ });
491
+
492
+ test("falls back to SQL LIKE when backend is unavailable", async () => {
493
+ insertItem({
494
+ id: "i1",
495
+ kind: "preference",
496
+ subject: "dark mode",
497
+ statement: "User prefers dark mode",
498
+ });
499
+ insertItem({
500
+ id: "i2",
501
+ kind: "identity",
502
+ subject: "name",
503
+ statement: "User name is Alice",
504
+ });
505
+
506
+ // Backend unavailable
507
+ mockBackendStatus = { enabled: false, provider: null, model: null };
508
+ mockHybridSearchResults = [];
509
+
510
+ const ctx = makeCtx({ search: "dark" });
511
+ const res = await handler(ctx);
512
+ const body = (await res.json()) as {
513
+ items: Array<{ id: string }>;
514
+ total: number;
515
+ };
516
+
517
+ // SQL LIKE fallback finds "dark" in subject/statement
518
+ expect(body.total).toBe(1);
519
+ expect(body.items[0].id).toBe("i1");
520
+ });
521
+
522
+ test("semantic search respects pagination", async () => {
523
+ insertItem({
524
+ id: "i1",
525
+ kind: "preference",
526
+ subject: "s1",
527
+ statement: "first item",
528
+ });
529
+ insertItem({
530
+ id: "i2",
531
+ kind: "preference",
532
+ subject: "s2",
533
+ statement: "second item",
534
+ });
535
+ insertItem({
536
+ id: "i3",
537
+ kind: "preference",
538
+ subject: "s3",
539
+ statement: "third item",
540
+ });
541
+
542
+ mockBackendStatus = {
543
+ enabled: true,
544
+ provider: "local",
545
+ model: "test",
546
+ };
547
+ mockHybridSearchResults = [
548
+ {
549
+ id: "pt-1",
550
+ score: 0.9,
551
+ payload: { target_type: "item", target_id: "i1" },
552
+ },
553
+ {
554
+ id: "pt-2",
555
+ score: 0.8,
556
+ payload: { target_type: "item", target_id: "i2" },
557
+ },
558
+ {
559
+ id: "pt-3",
560
+ score: 0.7,
561
+ payload: { target_type: "item", target_id: "i3" },
562
+ },
563
+ ];
564
+
565
+ // Request page 2 (offset=1, limit=1)
566
+ const ctx = makeCtx({ search: "item", limit: "1", offset: "1" });
567
+ const res = await handler(ctx);
568
+ const body = (await res.json()) as {
569
+ items: Array<{ id: string }>;
570
+ total: number;
571
+ };
572
+
573
+ expect(body.items.length).toBe(1);
574
+ expect(body.items[0].id).toBe("i2"); // second by relevance
575
+ expect(body.total).toBe(3);
576
+
577
+ // Reset
578
+ mockBackendStatus = { enabled: false, provider: null, model: null };
579
+ mockHybridSearchResults = [];
580
+ });
581
+
582
+ test("falls back to SQL when semantic returns empty results", async () => {
583
+ insertItem({
584
+ id: "i1",
585
+ kind: "preference",
586
+ subject: "dark mode",
587
+ statement: "User prefers dark mode",
588
+ });
589
+
590
+ mockBackendStatus = {
591
+ enabled: true,
592
+ provider: "local",
593
+ model: "test",
594
+ };
595
+ // Qdrant returns nothing
596
+ mockHybridSearchResults = [];
597
+
598
+ const ctx = makeCtx({ search: "dark" });
599
+ const res = await handler(ctx);
600
+ const body = (await res.json()) as {
601
+ items: Array<{ id: string }>;
602
+ total: number;
603
+ };
604
+
605
+ // Falls through to SQL LIKE
606
+ expect(body.total).toBe(1);
607
+ expect(body.items[0].id).toBe("i1");
608
+
609
+ // Reset
610
+ mockBackendStatus = { enabled: false, provider: null, model: null };
611
+ mockHybridSearchResults = [];
612
+ });
395
613
  });
396
614
 
397
615
  // =========================================================================
@@ -11,18 +11,29 @@
11
11
  import { and, asc, count, desc, eq, inArray, like, ne, or } from "drizzle-orm";
12
12
  import { v4 as uuid } from "uuid";
13
13
 
14
+ import { getConfig } from "../../config/loader.js";
14
15
  import { getDb } from "../../memory/db.js";
16
+ import {
17
+ embedWithBackend,
18
+ generateSparseEmbedding,
19
+ getMemoryBackendStatus,
20
+ } from "../../memory/embedding-backend.js";
15
21
  import { computeMemoryFingerprint } from "../../memory/fingerprint.js";
16
22
  import { enqueueMemoryJob } from "../../memory/jobs-store.js";
23
+ import { withQdrantBreaker } from "../../memory/qdrant-circuit-breaker.js";
24
+ import { getQdrantClient } from "../../memory/qdrant-client.js";
17
25
  import {
18
26
  conversations,
19
27
  memoryEmbeddings,
20
28
  memoryItems,
21
29
  } from "../../memory/schema.js";
30
+ import { getLogger } from "../../util/logger.js";
22
31
  import { truncate } from "../../util/truncate.js";
23
32
  import { httpError } from "../http-errors.js";
24
33
  import type { RouteContext, RouteDefinition } from "../http-router.js";
25
34
 
35
+ const log = getLogger("memory-item-routes");
36
+
26
37
  // ---------------------------------------------------------------------------
27
38
  // Constants
28
39
  // ---------------------------------------------------------------------------
@@ -34,6 +45,7 @@ const VALID_KINDS = [
34
45
  "decision",
35
46
  "constraint",
36
47
  "event",
48
+ "capability",
37
49
  ] as const;
38
50
 
39
51
  type MemoryItemKind = (typeof VALID_KINDS)[number];
@@ -116,11 +128,80 @@ function buildConversationTitleMap(
116
128
  return map;
117
129
  }
118
130
 
131
+ // ---------------------------------------------------------------------------
132
+ // Semantic search helper
133
+ // ---------------------------------------------------------------------------
134
+
135
+ /**
136
+ * Attempt hybrid semantic search for memory items via Qdrant.
137
+ * Returns ordered item IDs + total count on success, or `null` when
138
+ * the embedding backend / Qdrant is unavailable (caller falls back to SQL).
139
+ */
140
+ async function searchItemsSemantic(
141
+ query: string,
142
+ fetchLimit: number,
143
+ kindFilter: string | null,
144
+ statusFilter: string,
145
+ ): Promise<{ ids: string[]; total: number } | null> {
146
+ try {
147
+ const config = getConfig();
148
+ const backendStatus = await getMemoryBackendStatus(config);
149
+ if (!backendStatus.provider) return null;
150
+
151
+ const embedded = await embedWithBackend(config, [query]);
152
+ const queryVector = embedded.vectors[0];
153
+ if (!queryVector) return null;
154
+
155
+ const sparse = generateSparseEmbedding(query);
156
+ const sparseVector = { indices: sparse.indices, values: sparse.values };
157
+
158
+ // Build Qdrant filter — items only, exclude sentinel
159
+ const mustConditions: Array<Record<string, unknown>> = [
160
+ { key: "target_type", match: { value: "item" } },
161
+ ];
162
+ if (statusFilter && statusFilter !== "all") {
163
+ mustConditions.push({ key: "status", match: { value: statusFilter } });
164
+ }
165
+ if (kindFilter) {
166
+ mustConditions.push({ key: "kind", match: { value: kindFilter } });
167
+ }
168
+
169
+ const filter = {
170
+ must: mustConditions,
171
+ must_not: [
172
+ { key: "_meta", match: { value: true } },
173
+ ],
174
+ };
175
+
176
+ const qdrant = getQdrantClient();
177
+ const results = await withQdrantBreaker(() =>
178
+ qdrant.hybridSearch({
179
+ denseVector: queryVector,
180
+ sparseVector,
181
+ filter,
182
+ limit: fetchLimit,
183
+ prefetchLimit: fetchLimit,
184
+ }),
185
+ );
186
+
187
+ const ids = results.map((r) => r.payload.target_id);
188
+
189
+ // Use the vector search result count as the pagination total.
190
+ // A DB-wide COUNT would include items with no embedding yet (lagging) and
191
+ // items irrelevant to the search query, inflating the total and causing
192
+ // clients to paginate into empty pages.
193
+ return { ids, total: ids.length };
194
+ } catch (err) {
195
+ log.warn({ err }, "Semantic memory search failed, falling back to SQL");
196
+ return null;
197
+ }
198
+ }
199
+
119
200
  // ---------------------------------------------------------------------------
120
201
  // GET /v1/memory-items
121
202
  // ---------------------------------------------------------------------------
122
203
 
123
- export function handleListMemoryItems(url: URL): Response {
204
+ export async function handleListMemoryItems(url: URL): Promise<Response> {
124
205
  const kindParam = url.searchParams.get("kind");
125
206
  const statusParam = url.searchParams.get("status") ?? "active";
126
207
  const searchParam = url.searchParams.get("search");
@@ -155,10 +236,69 @@ export function handleListMemoryItems(url: URL): Response {
155
236
 
156
237
  const db = getDb();
157
238
 
158
- // Build WHERE conditions
239
+ // ── Semantic search path ────────────────────────────────────────────
240
+ // When a search query is present, try Qdrant hybrid search first.
241
+ // Falls back to SQL LIKE when embeddings / Qdrant are unavailable.
242
+ if (searchParam) {
243
+ const semanticResult = await searchItemsSemantic(
244
+ searchParam,
245
+ limitParam + offsetParam,
246
+ kindParam,
247
+ statusParam,
248
+ );
249
+
250
+ if (semanticResult && semanticResult.ids.length > 0) {
251
+ // Slice for pagination
252
+ const pageIds = semanticResult.ids.slice(
253
+ offsetParam,
254
+ offsetParam + limitParam,
255
+ );
256
+
257
+ if (pageIds.length === 0) {
258
+ return Response.json({ items: [], total: semanticResult.total });
259
+ }
260
+
261
+ // Re-apply the same DB-side filters used in the SQL path as defense-
262
+ // in-depth against stale Qdrant payloads leaking deleted/mismatched rows.
263
+ const hydrationConditions = [
264
+ inArray(memoryItems.id, pageIds),
265
+ ];
266
+ if (statusParam && statusParam !== "all") {
267
+ hydrationConditions.push(eq(memoryItems.status, statusParam));
268
+ }
269
+ if (kindParam) {
270
+ hydrationConditions.push(eq(memoryItems.kind, kindParam));
271
+ }
272
+
273
+ const rows = db
274
+ .select()
275
+ .from(memoryItems)
276
+ .where(and(...hydrationConditions))
277
+ .all();
278
+
279
+ // Preserve Qdrant relevance ordering
280
+ const idOrder = new Map(pageIds.map((id, i) => [id, i]));
281
+ rows.sort((a, b) => (idOrder.get(a.id) ?? 0) - (idOrder.get(b.id) ?? 0));
282
+
283
+ const titleMap = buildConversationTitleMap(
284
+ db,
285
+ rows.map((i) => i.scopeId),
286
+ );
287
+ const enrichedItems = rows.map((item) => ({
288
+ ...item,
289
+ scopeLabel: resolveScopeLabel(item.scopeId, titleMap),
290
+ }));
291
+
292
+ return Response.json({
293
+ items: enrichedItems,
294
+ total: semanticResult.total,
295
+ });
296
+ }
297
+ // semanticResult was null (Qdrant unavailable) or empty — fall through to SQL
298
+ }
299
+
300
+ // ── SQL path (default or fallback) ──────────────────────────────────
159
301
  const conditions = [];
160
- // Hide system-managed capability memories (skill announcements) from the UI
161
- conditions.push(ne(memoryItems.kind, "capability"));
162
302
  if (statusParam && statusParam !== "all") {
163
303
  conditions.push(eq(memoryItems.status, statusParam));
164
304
  }