@vellumai/assistant 0.4.52 → 0.4.54

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 (380) hide show
  1. package/ARCHITECTURE.md +2 -2
  2. package/bun.lock +62 -349
  3. package/docs/architecture/integrations.md +1 -1
  4. package/docs/architecture/keychain-broker.md +91 -40
  5. package/docs/architecture/memory.md +3 -3
  6. package/docs/architecture/security.md +2 -2
  7. package/knip.json +7 -29
  8. package/package.json +2 -9
  9. package/src/__tests__/agent-loop.test.ts +1 -1
  10. package/src/__tests__/app-git-history.test.ts +0 -2
  11. package/src/__tests__/app-git-service.test.ts +1 -6
  12. package/src/__tests__/approval-cascade.test.ts +3 -2
  13. package/src/__tests__/approval-routes-http.test.ts +0 -1
  14. package/src/__tests__/asset-materialize-tool.test.ts +0 -1
  15. package/src/__tests__/asset-search-tool.test.ts +0 -1
  16. package/src/__tests__/assistant-events-sse-hardening.test.ts +0 -1
  17. package/src/__tests__/attachments-store.test.ts +0 -1
  18. package/src/__tests__/avatar-e2e.test.ts +5 -1
  19. package/src/__tests__/browser-fill-credential.test.ts +4 -6
  20. package/src/__tests__/btw-routes.test.ts +39 -0
  21. package/src/__tests__/call-controller.test.ts +0 -1
  22. package/src/__tests__/call-domain.test.ts +1 -1
  23. package/src/__tests__/call-routes-http.test.ts +1 -3
  24. package/src/__tests__/canonical-guardian-store.test.ts +33 -2
  25. package/src/__tests__/channel-guardian.test.ts +4 -4
  26. package/src/__tests__/channel-readiness-routes.test.ts +0 -1
  27. package/src/__tests__/channel-readiness-service.test.ts +1 -1
  28. package/src/__tests__/checker.test.ts +13 -11
  29. package/src/__tests__/claude-code-skill-regression.test.ts +5 -2
  30. package/src/__tests__/claude-code-tool-profiles.test.ts +7 -3
  31. package/src/__tests__/config-loader-backfill.test.ts +1 -5
  32. package/src/__tests__/config-schema.test.ts +9 -46
  33. package/src/__tests__/config-watcher.test.ts +11 -3
  34. package/src/__tests__/conversation-routes-slash-commands.test.ts +0 -1
  35. package/src/__tests__/credential-broker-browser-fill.test.ts +27 -24
  36. package/src/__tests__/credential-broker-server-use.test.ts +76 -40
  37. package/src/__tests__/credential-security-e2e.test.ts +1 -6
  38. package/src/__tests__/credential-security-invariants.test.ts +27 -8
  39. package/src/__tests__/credential-vault-unit.test.ts +32 -16
  40. package/src/__tests__/credential-vault.test.ts +40 -28
  41. package/src/__tests__/credentials-cli.test.ts +1 -21
  42. package/src/__tests__/email-invite-adapter.test.ts +0 -1
  43. package/src/__tests__/error-handler-friendly-messages.test.ts +4 -5
  44. package/src/__tests__/fixtures/credential-security-fixtures.ts +3 -3
  45. package/src/__tests__/fixtures/media-reuse-fixtures.ts +3 -79
  46. package/src/__tests__/gateway-only-enforcement.test.ts +1 -23
  47. package/src/__tests__/guardian-action-conversation-turn.test.ts +8 -8
  48. package/src/__tests__/guardian-action-late-reply.test.ts +13 -14
  49. package/src/__tests__/guardian-action-store.test.ts +0 -57
  50. package/src/__tests__/guardian-outbound-http.test.ts +1 -1
  51. package/src/__tests__/guardian-verification-voice-binding.test.ts +1 -3
  52. package/src/__tests__/hooks-blocking.test.ts +1 -1
  53. package/src/__tests__/hooks-config.test.ts +5 -29
  54. package/src/__tests__/hooks-discovery.test.ts +1 -1
  55. package/src/__tests__/hooks-integration.test.ts +1 -1
  56. package/src/__tests__/hooks-manager.test.ts +1 -1
  57. package/src/__tests__/hooks-runner.test.ts +1 -23
  58. package/src/__tests__/hooks-settings.test.ts +1 -1
  59. package/src/__tests__/hooks-templates.test.ts +1 -1
  60. package/src/__tests__/host-shell-tool.test.ts +0 -1
  61. package/src/__tests__/http-user-message-parity.test.ts +19 -0
  62. package/src/__tests__/integration-status.test.ts +0 -1
  63. package/src/__tests__/invite-routes-http.test.ts +0 -3
  64. package/src/__tests__/list-messages-attachments.test.ts +0 -1
  65. package/src/__tests__/llm-usage-store.test.ts +50 -0
  66. package/src/__tests__/log-export-workspace.test.ts +233 -0
  67. package/src/__tests__/managed-proxy-context.test.ts +41 -41
  68. package/src/__tests__/managed-skill-lifecycle.test.ts +0 -1
  69. package/src/__tests__/media-generate-image.test.ts +9 -4
  70. package/src/__tests__/media-reuse-story.e2e.test.ts +1 -7
  71. package/src/__tests__/memory-regressions.experimental.test.ts +4 -4
  72. package/src/__tests__/memory-regressions.test.ts +27 -28
  73. package/src/__tests__/memory-retrieval.benchmark.test.ts +1 -1
  74. package/src/__tests__/memory-upsert-concurrency.test.ts +4 -4
  75. package/src/__tests__/migration-cross-version-compatibility.test.ts +0 -1
  76. package/src/__tests__/migration-export-http.test.ts +0 -1
  77. package/src/__tests__/migration-import-commit-http.test.ts +0 -1
  78. package/src/__tests__/migration-import-preflight-http.test.ts +0 -1
  79. package/src/__tests__/migration-validate-http.test.ts +0 -1
  80. package/src/__tests__/notification-decision-fallback.test.ts +1 -1
  81. package/src/__tests__/notification-schedule-dedup.test.ts +237 -0
  82. package/src/__tests__/oauth-cli.test.ts +2 -14
  83. package/src/__tests__/oauth-store.test.ts +3 -7
  84. package/src/__tests__/oauth2-gateway-transport.test.ts +5 -4
  85. package/src/__tests__/onboarding-starter-tasks.test.ts +1 -1
  86. package/src/__tests__/onboarding-template-contract.test.ts +1 -2
  87. package/src/__tests__/openai-provider.test.ts +7 -7
  88. package/src/__tests__/platform.test.ts +14 -4
  89. package/src/__tests__/pricing.test.ts +0 -234
  90. package/src/__tests__/provider-commit-message-generator.test.ts +19 -15
  91. package/src/__tests__/provider-fail-open-selection.test.ts +67 -62
  92. package/src/__tests__/provider-managed-proxy-integration.test.ts +88 -85
  93. package/src/__tests__/provider-registry-ollama.test.ts +10 -4
  94. package/src/__tests__/public-ingress-urls.test.ts +1 -1
  95. package/src/__tests__/recording-handler.test.ts +0 -1
  96. package/src/__tests__/registry.test.ts +3 -103
  97. package/src/__tests__/relay-server.test.ts +0 -1
  98. package/src/__tests__/runtime-attachment-metadata.test.ts +0 -1
  99. package/src/__tests__/runtime-events-sse-parity.test.ts +0 -1
  100. package/src/__tests__/runtime-events-sse.test.ts +0 -1
  101. package/src/__tests__/script-proxy-injection-runtime.test.ts +2 -7
  102. package/src/__tests__/secret-onetime-send.test.ts +1 -6
  103. package/src/__tests__/secret-routes-managed-proxy.test.ts +6 -14
  104. package/src/__tests__/secret-scanner-executor.test.ts +0 -1
  105. package/src/__tests__/secure-keys.test.ts +241 -229
  106. package/src/__tests__/send-endpoint-busy.test.ts +0 -1
  107. package/src/__tests__/session-abort-tool-results.test.ts +3 -2
  108. package/src/__tests__/session-agent-loop-overflow.test.ts +1012 -838
  109. package/src/__tests__/session-agent-loop.test.ts +2 -2
  110. package/src/__tests__/session-confirmation-signals.test.ts +3 -2
  111. package/src/__tests__/session-error.test.ts +5 -4
  112. package/src/__tests__/session-history-web-search.test.ts +34 -9
  113. package/src/__tests__/session-messaging-secret-redirect.test.ts +1 -7
  114. package/src/__tests__/session-pre-run-repair.test.ts +3 -2
  115. package/src/__tests__/session-provider-retry-repair.test.ts +31 -27
  116. package/src/__tests__/session-queue.test.ts +5 -5
  117. package/src/__tests__/session-runtime-assembly.test.ts +118 -0
  118. package/src/__tests__/session-slash-known.test.ts +31 -14
  119. package/src/__tests__/session-slash-queue.test.ts +3 -2
  120. package/src/__tests__/session-slash-unknown.test.ts +3 -2
  121. package/src/__tests__/session-workspace-cache-state.test.ts +3 -1
  122. package/src/__tests__/session-workspace-injection.test.ts +3 -2
  123. package/src/__tests__/session-workspace-tool-tracking.test.ts +3 -2
  124. package/src/__tests__/shell-tool-proxy-mode.test.ts +0 -1
  125. package/src/__tests__/skill-projection-feature-flag.test.ts +0 -1
  126. package/src/__tests__/skill-script-runner-sandbox.test.ts +0 -1
  127. package/src/__tests__/skillssh-registry.test.ts +21 -0
  128. package/src/__tests__/slack-channel-config.test.ts +1 -7
  129. package/src/__tests__/slack-share-routes.test.ts +1 -1
  130. package/src/__tests__/swarm-recursion.test.ts +4 -1
  131. package/src/__tests__/swarm-session-integration.test.ts +24 -14
  132. package/src/__tests__/swarm-tool.test.ts +4 -2
  133. package/src/__tests__/task-compiler.test.ts +1 -1
  134. package/src/__tests__/telegram-bot-username-resolution.test.ts +2 -4
  135. package/src/__tests__/test-support/browser-skill-harness.ts +0 -18
  136. package/src/__tests__/test-support/computer-use-skill-harness.ts +0 -23
  137. package/src/__tests__/token-estimator-accuracy.benchmark.test.ts +1521 -0
  138. package/src/__tests__/tool-execution-abort-cleanup.test.ts +0 -1
  139. package/src/__tests__/tool-executor-lifecycle-events.test.ts +0 -1
  140. package/src/__tests__/tool-executor-shell-integration.test.ts +0 -1
  141. package/src/__tests__/tool-executor.test.ts +1 -2
  142. package/src/__tests__/trust-store.test.ts +8 -83
  143. package/src/__tests__/twilio-config.test.ts +0 -1
  144. package/src/__tests__/twilio-provider.test.ts +0 -5
  145. package/src/__tests__/twilio-routes.test.ts +2 -3
  146. package/src/__tests__/usage-cache-backfill-migration.test.ts +10 -10
  147. package/src/__tests__/verification-control-plane-policy.test.ts +0 -1
  148. package/src/__tests__/voice-quality.test.ts +2 -1
  149. package/src/__tests__/voice-scoped-grant-consumer.test.ts +0 -1
  150. package/src/__tests__/web-search.test.ts +1 -1
  151. package/src/agent/loop.ts +17 -1
  152. package/src/bundler/app-bundler.ts +40 -24
  153. package/src/calls/call-controller.ts +16 -0
  154. package/src/calls/guardian-question-copy.ts +1 -1
  155. package/src/calls/relay-server.ts +29 -13
  156. package/src/calls/voice-control-protocol.ts +1 -0
  157. package/src/calls/voice-quality.ts +1 -1
  158. package/src/calls/voice-session-bridge.ts +9 -3
  159. package/src/channels/types.ts +16 -0
  160. package/src/cli/commands/bash.ts +173 -0
  161. package/src/cli/commands/doctor.ts +15 -57
  162. package/src/cli/commands/memory.ts +3 -5
  163. package/src/cli/commands/oauth/connections.ts +4 -2
  164. package/src/cli/commands/oauth/providers.ts +1 -13
  165. package/src/cli/commands/sessions.ts +1 -1
  166. package/src/cli/commands/usage.ts +359 -0
  167. package/src/cli/http-client.ts +22 -12
  168. package/src/cli/program.ts +4 -0
  169. package/src/cli/reference.ts +2 -0
  170. package/src/cli.ts +251 -181
  171. package/src/config/assistant-feature-flags.ts +0 -7
  172. package/src/config/bundled-skills/chatgpt-import/tools/chatgpt-import.ts +1 -1
  173. package/src/config/bundled-skills/claude-code/SKILL.md +1 -1
  174. package/src/config/bundled-skills/claude-code/TOOLS.json +1 -1
  175. package/src/config/bundled-skills/gmail/SKILL.md +0 -1
  176. package/src/config/bundled-skills/image-studio/tools/media-generate-image.ts +4 -3
  177. package/src/config/bundled-skills/media-processing/services/reduce.ts +1 -1
  178. package/src/config/bundled-skills/media-processing/tools/analyze-keyframes.ts +3 -5
  179. package/src/config/bundled-skills/media-processing/tools/extract-keyframes.ts +2 -3
  180. package/src/config/bundled-skills/messaging/SKILL.md +0 -1
  181. package/src/config/bundled-skills/phone-calls/references/CONFIG.md +1 -1
  182. package/src/config/bundled-skills/sequences/SKILL.md +0 -1
  183. package/src/config/bundled-skills/transcribe/tools/transcribe-media.ts +5 -6
  184. package/src/config/env.ts +13 -0
  185. package/src/config/feature-flag-registry.json +15 -39
  186. package/src/config/loader.ts +7 -135
  187. package/src/config/schema.ts +0 -6
  188. package/src/config/schemas/channels.ts +1 -0
  189. package/src/config/schemas/elevenlabs.ts +2 -2
  190. package/src/config/schemas/security.ts +1 -2
  191. package/src/config/skills.ts +1 -1
  192. package/src/contacts/contact-store.ts +21 -75
  193. package/src/contacts/contacts-write.ts +6 -6
  194. package/src/contacts/types.ts +2 -0
  195. package/src/context/token-estimator.ts +35 -2
  196. package/src/context/window-manager.ts +16 -2
  197. package/src/daemon/approved-devices-store.ts +0 -44
  198. package/src/daemon/classifier.ts +1 -1
  199. package/src/daemon/config-watcher.ts +35 -11
  200. package/src/daemon/context-overflow-reducer.ts +13 -2
  201. package/src/daemon/handlers/config-ingress.ts +25 -8
  202. package/src/daemon/handlers/config-model.ts +22 -16
  203. package/src/daemon/handlers/config-telegram.ts +18 -6
  204. package/src/daemon/handlers/dictation.ts +0 -429
  205. package/src/daemon/handlers/sessions.ts +4 -116
  206. package/src/daemon/handlers/skills.ts +2 -201
  207. package/src/daemon/lifecycle.ts +21 -20
  208. package/src/daemon/message-types/contacts.ts +2 -0
  209. package/src/daemon/message-types/integrations.ts +1 -0
  210. package/src/daemon/message-types/sessions.ts +2 -0
  211. package/src/daemon/parse-actual-tokens-from-error.test.ts +75 -0
  212. package/src/daemon/providers-setup.ts +1 -1
  213. package/src/daemon/server.ts +42 -5
  214. package/src/daemon/session-agent-loop-handlers.ts +1 -1
  215. package/src/daemon/session-agent-loop.ts +27 -79
  216. package/src/daemon/session-error.ts +5 -4
  217. package/src/daemon/session-process.ts +17 -10
  218. package/src/daemon/session-runtime-assembly.ts +50 -0
  219. package/src/daemon/session-slash.ts +34 -22
  220. package/src/daemon/session.ts +1 -0
  221. package/src/daemon/shutdown-handlers.ts +15 -0
  222. package/src/daemon/watch-handler.ts +2 -2
  223. package/src/email/guardrails.ts +1 -1
  224. package/src/email/service.ts +0 -5
  225. package/src/events/domain-events.ts +1 -0
  226. package/src/hooks/templates.ts +1 -1
  227. package/src/media/app-icon-generator.ts +4 -3
  228. package/src/media/avatar-router.ts +5 -4
  229. package/src/media/gemini-image-service.ts +5 -5
  230. package/src/memory/admin.ts +2 -2
  231. package/src/memory/app-git-service.ts +0 -7
  232. package/src/memory/canonical-guardian-store.ts +25 -3
  233. package/src/memory/conversation-crud.ts +1 -1
  234. package/src/memory/conversation-title-service.ts +2 -2
  235. package/src/memory/db-init.ts +12 -0
  236. package/src/memory/embedding-backend.ts +46 -33
  237. package/src/memory/external-conversation-store.ts +0 -30
  238. package/src/memory/guardian-action-store.ts +0 -31
  239. package/src/memory/guardian-approvals.ts +1 -56
  240. package/src/memory/indexer.ts +4 -3
  241. package/src/memory/items-extractor.ts +1 -1
  242. package/src/memory/job-handlers/backfill.ts +5 -2
  243. package/src/memory/job-handlers/index-maintenance.ts +2 -2
  244. package/src/memory/job-handlers/media-processing.ts +2 -2
  245. package/src/memory/job-handlers/summarization.ts +1 -1
  246. package/src/memory/job-utils.ts +1 -2
  247. package/src/memory/jobs-worker.ts +2 -2
  248. package/src/memory/llm-usage-store.ts +57 -11
  249. package/src/memory/media-store.ts +4 -535
  250. package/src/memory/migrations/032-guardian-delivery-conversation-index.ts +2 -2
  251. package/src/memory/migrations/110-channel-guardian.ts +0 -1
  252. package/src/memory/migrations/158-channel-interaction-columns.ts +18 -0
  253. package/src/memory/migrations/159-drop-contact-interaction-columns.ts +16 -0
  254. package/src/memory/migrations/160-drop-loopback-port-column.ts +13 -0
  255. package/src/memory/migrations/index.ts +3 -0
  256. package/src/memory/published-pages-store.ts +0 -83
  257. package/src/memory/qdrant-circuit-breaker.ts +0 -8
  258. package/src/memory/retriever.test.ts +19 -12
  259. package/src/memory/retriever.ts +1 -1
  260. package/src/memory/schema/contacts.ts +2 -2
  261. package/src/memory/schema/oauth.ts +0 -1
  262. package/src/memory/search/semantic.ts +1 -8
  263. package/src/memory/shared-app-links-store.ts +0 -15
  264. package/src/messaging/registry.ts +0 -5
  265. package/src/messaging/style-analyzer.ts +1 -1
  266. package/src/notifications/copy-composer.ts +5 -13
  267. package/src/notifications/decision-engine.ts +2 -2
  268. package/src/notifications/deliveries-store.ts +0 -39
  269. package/src/notifications/guardian-question-mode.ts +6 -10
  270. package/src/notifications/preference-extractor.ts +1 -1
  271. package/src/oauth/byo-connection.test.ts +29 -20
  272. package/src/oauth/connect-orchestrator.ts +5 -3
  273. package/src/oauth/connect-types.ts +9 -2
  274. package/src/oauth/manual-token-connection.ts +9 -7
  275. package/src/oauth/oauth-store.ts +2 -8
  276. package/src/oauth/provider-behaviors.ts +11 -1
  277. package/src/oauth/seed-providers.ts +13 -5
  278. package/src/permissions/checker.ts +21 -2
  279. package/src/permissions/shell-identity.ts +0 -5
  280. package/src/permissions/trust-store.ts +0 -37
  281. package/src/prompts/__tests__/build-cli-reference-section.test.ts +1 -1
  282. package/src/prompts/system-prompt.ts +5 -14
  283. package/src/prompts/templates/BOOTSTRAP.md +1 -3
  284. package/src/providers/anthropic/client.ts +16 -8
  285. package/src/providers/managed-proxy/constants.ts +9 -11
  286. package/src/providers/managed-proxy/context.ts +14 -9
  287. package/src/providers/provider-send-message.ts +4 -52
  288. package/src/providers/registry.ts +29 -57
  289. package/src/providers/types.ts +1 -1
  290. package/src/runtime/actor-token-store.ts +0 -23
  291. package/src/runtime/auth/route-policy.ts +4 -0
  292. package/src/runtime/channel-invite-transports/telegram.ts +12 -6
  293. package/src/runtime/channel-retry-sweep.ts +6 -0
  294. package/src/runtime/http-router.ts +5 -1
  295. package/src/runtime/http-server.ts +101 -4
  296. package/src/runtime/http-types.ts +1 -0
  297. package/src/runtime/invite-instruction-generator.ts +25 -51
  298. package/src/runtime/invite-service.ts +0 -20
  299. package/src/runtime/middleware/error-handler.ts +1 -2
  300. package/src/runtime/routes/app-management-routes.ts +1 -0
  301. package/src/runtime/routes/attachment-routes.ts +1 -1
  302. package/src/runtime/routes/brain-graph-routes.ts +1 -1
  303. package/src/runtime/routes/btw-routes.ts +20 -1
  304. package/src/runtime/routes/call-routes.ts +1 -1
  305. package/src/runtime/routes/conversation-routes.ts +64 -24
  306. package/src/runtime/routes/debug-routes.ts +1 -1
  307. package/src/runtime/routes/diagnostics-routes.ts +2 -2
  308. package/src/runtime/routes/documents-routes.ts +3 -3
  309. package/src/runtime/routes/global-search-routes.ts +1 -1
  310. package/src/runtime/routes/guardian-bootstrap-routes.ts +0 -20
  311. package/src/runtime/routes/guardian-refresh-routes.ts +0 -20
  312. package/src/runtime/routes/inbound-message-handler.ts +10 -2
  313. package/src/runtime/routes/inbound-stages/background-dispatch.ts +4 -0
  314. package/src/runtime/routes/inbound-stages/edit-intercept.ts +5 -5
  315. package/src/runtime/routes/integrations/slack/share.ts +5 -5
  316. package/src/runtime/routes/log-export-routes.ts +122 -10
  317. package/src/runtime/routes/secret-routes.ts +4 -4
  318. package/src/runtime/routes/session-query-routes.ts +3 -3
  319. package/src/runtime/routes/settings-routes.ts +53 -0
  320. package/src/runtime/routes/trust-rules-routes.ts +1 -1
  321. package/src/runtime/routes/workspace-routes.ts +3 -0
  322. package/src/runtime/verification-templates.ts +1 -1
  323. package/src/security/credential-backend.ts +148 -0
  324. package/src/security/oauth2.ts +5 -5
  325. package/src/security/secret-allowlist.ts +1 -1
  326. package/src/security/secure-keys.ts +98 -160
  327. package/src/security/token-manager.ts +0 -7
  328. package/src/sequence/guardrails.ts +0 -4
  329. package/src/sequence/store.ts +1 -20
  330. package/src/sequence/types.ts +1 -36
  331. package/src/signals/bash.ts +157 -0
  332. package/src/signals/cancel.ts +69 -0
  333. package/src/signals/conversation-undo.ts +127 -0
  334. package/src/signals/trust-rule.ts +174 -0
  335. package/src/skills/clawhub.ts +5 -5
  336. package/src/skills/managed-store.ts +4 -4
  337. package/src/skills/skillssh-registry.ts +6 -1
  338. package/src/swarm/backend-claude-code.ts +6 -6
  339. package/src/swarm/worker-backend.ts +1 -1
  340. package/src/swarm/worker-runner.ts +1 -1
  341. package/src/telegram/bot-username.ts +11 -0
  342. package/src/telemetry/usage-telemetry-reporter.test.ts +366 -0
  343. package/src/telemetry/usage-telemetry-reporter.ts +181 -0
  344. package/src/tools/claude-code/claude-code.ts +6 -6
  345. package/src/tools/credentials/broker.ts +7 -5
  346. package/src/tools/credentials/vault.ts +11 -6
  347. package/src/tools/memory/handlers.test.ts +24 -26
  348. package/src/tools/memory/handlers.ts +1 -13
  349. package/src/tools/network/__tests__/web-search.test.ts +18 -86
  350. package/src/tools/network/web-search.ts +9 -15
  351. package/src/tools/registry.ts +5 -100
  352. package/src/tools/terminal/parser.ts +34 -4
  353. package/src/tools/tool-manifest.ts +0 -10
  354. package/src/usage/actors.ts +0 -12
  355. package/src/util/canonicalize-identity.ts +0 -9
  356. package/src/util/errors.ts +0 -3
  357. package/src/util/platform.ts +31 -8
  358. package/src/util/pricing.ts +0 -39
  359. package/src/watcher/constants.ts +0 -7
  360. package/src/watcher/providers/linear.ts +1 -1
  361. package/src/work-items/work-item-store.ts +4 -4
  362. package/src/workspace/commit-message-provider.ts +1 -1
  363. package/src/workspace/git-service.ts +44 -1
  364. package/src/workspace/provider-commit-message-generator.ts +11 -7
  365. package/src/__tests__/fixtures/proxy-fixtures.ts +0 -147
  366. package/src/browser-extension-relay/client.ts +0 -155
  367. package/src/contacts/index.ts +0 -18
  368. package/src/daemon/tls-certs.ts +0 -270
  369. package/src/errors.ts +0 -41
  370. package/src/events/index.ts +0 -18
  371. package/src/followups/index.ts +0 -10
  372. package/src/playbooks/index.ts +0 -10
  373. package/src/runtime/auth/index.ts +0 -44
  374. package/src/tasks/candidate-store.ts +0 -95
  375. package/src/tools/browser/api-map.ts +0 -313
  376. package/src/tools/browser/auto-navigate.ts +0 -469
  377. package/src/tools/browser/headless-browser.ts +0 -590
  378. package/src/tools/browser/recording-store.ts +0 -75
  379. package/src/tools/computer-use/registry.ts +0 -21
  380. package/src/tools/tasks/index.ts +0 -27
@@ -5,19 +5,11 @@
5
5
  * Uses content-hash deduplication (same pattern as attachments-store.ts).
6
6
  */
7
7
 
8
- import { and, asc, desc, eq, gte, inArray } from "drizzle-orm";
8
+ import { eq } from "drizzle-orm";
9
9
  import { v4 as uuid } from "uuid";
10
10
 
11
11
  import { getDb } from "./db.js";
12
- import {
13
- mediaAssets,
14
- mediaEvents,
15
- mediaKeyframes,
16
- mediaTimelines,
17
- mediaTrackingProfiles,
18
- mediaVisionOutputs,
19
- processingStages,
20
- } from "./schema.js";
12
+ import { mediaAssets, mediaKeyframes, processingStages } from "./schema.js";
21
13
 
22
14
  // ---------------------------------------------------------------------------
23
15
  // Types
@@ -62,19 +54,8 @@ export interface ProcessingStage {
62
54
  // ---------------------------------------------------------------------------
63
55
 
64
56
  /**
65
- * Compute a content hash for deduplication. Uses SHA-256 hex encoding for
66
- * consistency with the streaming variant.
67
- */
68
- export function computeFileHash(data: Buffer | Uint8Array): string {
69
- const hasher = new Bun.CryptoHasher("sha256");
70
- hasher.update(data);
71
- return hasher.digest("hex");
72
- }
73
-
74
- /**
75
- * Streaming variant of content hashing that avoids loading the entire file
76
- * into memory. Uses SHA-256 via Bun.CryptoHasher so multi-GB files won't OOM.
77
- * Produces the same hash format as `computeFileHash`.
57
+ * Streaming content hashing that avoids loading the entire file into memory.
58
+ * Uses SHA-256 via Bun.CryptoHasher so multi-GB files won't OOM.
78
59
  */
79
60
  export async function computeFileHashStreaming(
80
61
  filePath: string,
@@ -291,26 +272,6 @@ export interface MediaKeyframe {
291
272
  createdAt: number;
292
273
  }
293
274
 
294
- export function insertKeyframe(params: {
295
- assetId: string;
296
- timestamp: number;
297
- filePath: string;
298
- metadata?: Record<string, unknown>;
299
- }): MediaKeyframe {
300
- const db = getDb();
301
- const now = Date.now();
302
- const record = {
303
- id: uuid(),
304
- assetId: params.assetId,
305
- timestamp: params.timestamp,
306
- filePath: params.filePath,
307
- metadata: params.metadata ? JSON.stringify(params.metadata) : null,
308
- createdAt: now,
309
- };
310
- db.insert(mediaKeyframes).values(record).run();
311
- return { ...record, metadata: params.metadata ?? null };
312
- }
313
-
314
275
  export function insertKeyframesBatch(
315
276
  rows: Array<{
316
277
  assetId: string;
@@ -353,16 +314,6 @@ export function deleteKeyframesForAsset(assetId: string): void {
353
314
  db.delete(mediaKeyframes).where(eq(mediaKeyframes.assetId, assetId)).run();
354
315
  }
355
316
 
356
- export function getKeyframeById(id: string): MediaKeyframe | null {
357
- const db = getDb();
358
- const row = db
359
- .select()
360
- .from(mediaKeyframes)
361
- .where(eq(mediaKeyframes.id, id))
362
- .get();
363
- return row ? parseKeyframeRow(row) : null;
364
- }
365
-
366
317
  function parseKeyframeRow(
367
318
  row: typeof mediaKeyframes.$inferSelect,
368
319
  ): MediaKeyframe {
@@ -383,485 +334,3 @@ function parseKeyframeRow(
383
334
  createdAt: row.createdAt,
384
335
  };
385
336
  }
386
-
387
- // ---------------------------------------------------------------------------
388
- // Vision output types & CRUD
389
- // ---------------------------------------------------------------------------
390
-
391
- export interface MediaVisionOutput {
392
- id: string;
393
- assetId: string;
394
- keyframeId: string;
395
- analysisType: string;
396
- output: Record<string, unknown>;
397
- confidence: number | null;
398
- createdAt: number;
399
- }
400
-
401
- export function insertVisionOutput(params: {
402
- assetId: string;
403
- keyframeId: string;
404
- analysisType: string;
405
- output: Record<string, unknown>;
406
- confidence?: number;
407
- }): MediaVisionOutput {
408
- const db = getDb();
409
- const now = Date.now();
410
- const record = {
411
- id: uuid(),
412
- assetId: params.assetId,
413
- keyframeId: params.keyframeId,
414
- analysisType: params.analysisType,
415
- output: JSON.stringify(params.output),
416
- confidence: params.confidence ?? null,
417
- createdAt: now,
418
- };
419
- db.insert(mediaVisionOutputs).values(record).run();
420
- return { ...record, output: params.output };
421
- }
422
-
423
- export function insertVisionOutputsBatch(
424
- rows: Array<{
425
- assetId: string;
426
- keyframeId: string;
427
- analysisType: string;
428
- output: Record<string, unknown>;
429
- confidence?: number;
430
- }>,
431
- ): MediaVisionOutput[] {
432
- const db = getDb();
433
- const now = Date.now();
434
- const records = rows.map((r) => ({
435
- id: uuid(),
436
- assetId: r.assetId,
437
- keyframeId: r.keyframeId,
438
- analysisType: r.analysisType,
439
- output: JSON.stringify(r.output),
440
- confidence: r.confidence ?? null,
441
- createdAt: now,
442
- }));
443
- if (records.length > 0) {
444
- db.insert(mediaVisionOutputs).values(records).run();
445
- }
446
- return records.map((rec, i) => ({
447
- ...rec,
448
- output: rows[i].output,
449
- }));
450
- }
451
-
452
- export function getVisionOutputsForAsset(
453
- assetId: string,
454
- analysisType?: string,
455
- ): MediaVisionOutput[] {
456
- const db = getDb();
457
- const conditions = [eq(mediaVisionOutputs.assetId, assetId)];
458
- if (analysisType) {
459
- conditions.push(eq(mediaVisionOutputs.analysisType, analysisType));
460
- }
461
- const rows = db
462
- .select()
463
- .from(mediaVisionOutputs)
464
- .where(and(...conditions))
465
- .all();
466
- return rows.map(parseVisionOutputRow);
467
- }
468
-
469
- export function getVisionOutputsByKeyframeIds(
470
- keyframeIds: string[],
471
- ): MediaVisionOutput[] {
472
- if (keyframeIds.length === 0) return [];
473
- const db = getDb();
474
- const rows = db
475
- .select()
476
- .from(mediaVisionOutputs)
477
- .where(inArray(mediaVisionOutputs.keyframeId, keyframeIds))
478
- .all();
479
- return rows.map(parseVisionOutputRow);
480
- }
481
-
482
- function parseVisionOutputRow(
483
- row: typeof mediaVisionOutputs.$inferSelect,
484
- ): MediaVisionOutput {
485
- let output: Record<string, unknown> = {};
486
- try {
487
- output = JSON.parse(row.output) as Record<string, unknown>;
488
- } catch {
489
- output = {};
490
- }
491
- return {
492
- id: row.id,
493
- assetId: row.assetId,
494
- keyframeId: row.keyframeId,
495
- analysisType: row.analysisType,
496
- output,
497
- confidence: row.confidence,
498
- createdAt: row.createdAt,
499
- };
500
- }
501
-
502
- // ---------------------------------------------------------------------------
503
- // Timeline types & CRUD
504
- // ---------------------------------------------------------------------------
505
-
506
- export interface MediaTimeline {
507
- id: string;
508
- assetId: string;
509
- startTime: number;
510
- endTime: number;
511
- segmentType: string;
512
- attributes: Record<string, unknown> | null;
513
- confidence: number | null;
514
- createdAt: number;
515
- }
516
-
517
- export function insertTimelineSegment(params: {
518
- assetId: string;
519
- startTime: number;
520
- endTime: number;
521
- segmentType: string;
522
- attributes?: Record<string, unknown>;
523
- confidence?: number;
524
- }): MediaTimeline {
525
- const db = getDb();
526
- const now = Date.now();
527
- const record = {
528
- id: uuid(),
529
- assetId: params.assetId,
530
- startTime: params.startTime,
531
- endTime: params.endTime,
532
- segmentType: params.segmentType,
533
- attributes: params.attributes ? JSON.stringify(params.attributes) : null,
534
- confidence: params.confidence ?? null,
535
- createdAt: now,
536
- };
537
- db.insert(mediaTimelines).values(record).run();
538
- return { ...record, attributes: params.attributes ?? null };
539
- }
540
-
541
- export function insertTimelineSegmentsBatch(
542
- rows: Array<{
543
- assetId: string;
544
- startTime: number;
545
- endTime: number;
546
- segmentType: string;
547
- attributes?: Record<string, unknown>;
548
- confidence?: number;
549
- }>,
550
- ): MediaTimeline[] {
551
- const db = getDb();
552
- const now = Date.now();
553
- const records = rows.map((r) => ({
554
- id: uuid(),
555
- assetId: r.assetId,
556
- startTime: r.startTime,
557
- endTime: r.endTime,
558
- segmentType: r.segmentType,
559
- attributes: r.attributes ? JSON.stringify(r.attributes) : null,
560
- confidence: r.confidence ?? null,
561
- createdAt: now,
562
- }));
563
- if (records.length > 0) {
564
- db.insert(mediaTimelines).values(records).run();
565
- }
566
- return records.map((rec, i) => ({
567
- ...rec,
568
- attributes: rows[i].attributes ?? null,
569
- }));
570
- }
571
-
572
- export function getTimelineForAsset(assetId: string): MediaTimeline[] {
573
- const db = getDb();
574
- const rows = db
575
- .select()
576
- .from(mediaTimelines)
577
- .where(eq(mediaTimelines.assetId, assetId))
578
- .all();
579
- return rows.map(parseTimelineRow);
580
- }
581
-
582
- export function deleteTimelineForAsset(assetId: string): void {
583
- const db = getDb();
584
- db.delete(mediaTimelines).where(eq(mediaTimelines.assetId, assetId)).run();
585
- }
586
-
587
- function parseTimelineRow(
588
- row: typeof mediaTimelines.$inferSelect,
589
- ): MediaTimeline {
590
- let attributes: Record<string, unknown> | null = null;
591
- if (row.attributes) {
592
- try {
593
- attributes = JSON.parse(row.attributes) as Record<string, unknown>;
594
- } catch {
595
- attributes = null;
596
- }
597
- }
598
- return {
599
- id: row.id,
600
- assetId: row.assetId,
601
- startTime: row.startTime,
602
- endTime: row.endTime,
603
- segmentType: row.segmentType,
604
- attributes,
605
- confidence: row.confidence,
606
- createdAt: row.createdAt,
607
- };
608
- }
609
-
610
- // ---------------------------------------------------------------------------
611
- // Media event types & CRUD
612
- // ---------------------------------------------------------------------------
613
-
614
- export interface MediaEvent {
615
- id: string;
616
- assetId: string;
617
- eventType: string;
618
- startTime: number;
619
- endTime: number;
620
- confidence: number;
621
- reasons: string[];
622
- metadata: Record<string, unknown> | null;
623
- createdAt: number;
624
- }
625
-
626
- export function insertEvent(params: {
627
- assetId: string;
628
- eventType: string;
629
- startTime: number;
630
- endTime: number;
631
- confidence: number;
632
- reasons: string[];
633
- metadata?: Record<string, unknown>;
634
- }): MediaEvent {
635
- const db = getDb();
636
- const now = Date.now();
637
- const record = {
638
- id: uuid(),
639
- assetId: params.assetId,
640
- eventType: params.eventType,
641
- startTime: params.startTime,
642
- endTime: params.endTime,
643
- confidence: params.confidence,
644
- reasons: JSON.stringify(params.reasons),
645
- metadata: params.metadata ? JSON.stringify(params.metadata) : null,
646
- createdAt: now,
647
- };
648
- db.insert(mediaEvents).values(record).run();
649
- return {
650
- ...record,
651
- reasons: params.reasons,
652
- metadata: params.metadata ?? null,
653
- };
654
- }
655
-
656
- export function insertEventsBatch(
657
- rows: Array<{
658
- assetId: string;
659
- eventType: string;
660
- startTime: number;
661
- endTime: number;
662
- confidence: number;
663
- reasons: string[];
664
- metadata?: Record<string, unknown>;
665
- }>,
666
- ): MediaEvent[] {
667
- const db = getDb();
668
- const now = Date.now();
669
- const records = rows.map((r) => ({
670
- id: uuid(),
671
- assetId: r.assetId,
672
- eventType: r.eventType,
673
- startTime: r.startTime,
674
- endTime: r.endTime,
675
- confidence: r.confidence,
676
- reasons: JSON.stringify(r.reasons),
677
- metadata: r.metadata ? JSON.stringify(r.metadata) : null,
678
- createdAt: now,
679
- }));
680
- if (records.length > 0) {
681
- db.insert(mediaEvents).values(records).run();
682
- }
683
- return records.map((rec, i) => ({
684
- ...rec,
685
- reasons: rows[i].reasons,
686
- metadata: rows[i].metadata ?? null,
687
- }));
688
- }
689
-
690
- export function getEventsForAsset(
691
- assetId: string,
692
- filters?: {
693
- eventType?: string;
694
- minConfidence?: number;
695
- limit?: number;
696
- sortBy?: "confidence" | "startTime";
697
- },
698
- ): MediaEvent[] {
699
- const db = getDb();
700
- const conditions = [eq(mediaEvents.assetId, assetId)];
701
- if (filters?.eventType) {
702
- conditions.push(eq(mediaEvents.eventType, filters.eventType));
703
- }
704
- if (filters?.minConfidence !== undefined) {
705
- conditions.push(gte(mediaEvents.confidence, filters.minConfidence));
706
- }
707
-
708
- let query = db
709
- .select()
710
- .from(mediaEvents)
711
- .where(and(...conditions))
712
- .$dynamic();
713
-
714
- if (filters?.sortBy === "confidence") {
715
- query = query.orderBy(desc(mediaEvents.confidence));
716
- } else {
717
- query = query.orderBy(asc(mediaEvents.startTime));
718
- }
719
-
720
- if (filters?.limit) {
721
- query = query.limit(filters.limit);
722
- }
723
-
724
- const rows = query.all();
725
- return rows.map(parseEventRow);
726
- }
727
-
728
- export function getEventById(id: string): MediaEvent | null {
729
- const db = getDb();
730
- const row = db.select().from(mediaEvents).where(eq(mediaEvents.id, id)).get();
731
- return row ? parseEventRow(row) : null;
732
- }
733
-
734
- export function deleteEventsForAsset(assetId: string): void {
735
- const db = getDb();
736
- db.delete(mediaEvents).where(eq(mediaEvents.assetId, assetId)).run();
737
- }
738
-
739
- export function deleteEventsForAssetByType(
740
- assetId: string,
741
- eventType: string,
742
- ): void {
743
- const db = getDb();
744
- db.delete(mediaEvents)
745
- .where(
746
- and(
747
- eq(mediaEvents.assetId, assetId),
748
- eq(mediaEvents.eventType, eventType),
749
- ),
750
- )
751
- .run();
752
- }
753
-
754
- function parseEventRow(row: typeof mediaEvents.$inferSelect): MediaEvent {
755
- let reasons: string[] = [];
756
- try {
757
- reasons = JSON.parse(row.reasons) as string[];
758
- } catch {
759
- reasons = [];
760
- }
761
- let metadata: Record<string, unknown> | null = null;
762
- if (row.metadata) {
763
- try {
764
- metadata = JSON.parse(row.metadata) as Record<string, unknown>;
765
- } catch {
766
- metadata = null;
767
- }
768
- }
769
- return {
770
- id: row.id,
771
- assetId: row.assetId,
772
- eventType: row.eventType,
773
- startTime: row.startTime,
774
- endTime: row.endTime,
775
- confidence: row.confidence,
776
- reasons,
777
- metadata,
778
- createdAt: row.createdAt,
779
- };
780
- }
781
-
782
- // ---------------------------------------------------------------------------
783
- // Tracking profile types & CRUD
784
- // ---------------------------------------------------------------------------
785
-
786
- export type CapabilityTier = "ready" | "beta" | "experimental";
787
-
788
- export interface CapabilityProfileEntry {
789
- enabled: boolean;
790
- tier: CapabilityTier;
791
- }
792
-
793
- export type CapabilityProfile = Record<string, CapabilityProfileEntry>;
794
-
795
- export interface TrackingProfile {
796
- id: string;
797
- assetId: string;
798
- capabilities: CapabilityProfile;
799
- createdAt: number;
800
- }
801
-
802
- /**
803
- * Upsert a tracking profile for a media asset. If a profile already exists
804
- * for the given assetId, it is replaced.
805
- */
806
- export function setTrackingProfile(
807
- assetId: string,
808
- capabilities: CapabilityProfile,
809
- ): TrackingProfile {
810
- const db = getDb();
811
- const now = Date.now();
812
-
813
- // Check for existing profile by assetId
814
- const existing = db
815
- .select()
816
- .from(mediaTrackingProfiles)
817
- .where(eq(mediaTrackingProfiles.assetId, assetId))
818
- .get();
819
-
820
- if (existing) {
821
- db.update(mediaTrackingProfiles)
822
- .set({ capabilities: JSON.stringify(capabilities), createdAt: now })
823
- .where(eq(mediaTrackingProfiles.id, existing.id))
824
- .run();
825
- return { id: existing.id, assetId, capabilities, createdAt: now };
826
- }
827
-
828
- const id = uuid();
829
- db.insert(mediaTrackingProfiles)
830
- .values({
831
- id,
832
- assetId,
833
- capabilities: JSON.stringify(capabilities),
834
- createdAt: now,
835
- })
836
- .run();
837
-
838
- return { id, assetId, capabilities, createdAt: now };
839
- }
840
-
841
- /**
842
- * Get the current tracking profile for a media asset, if one exists.
843
- */
844
- export function getTrackingProfile(assetId: string): TrackingProfile | null {
845
- const db = getDb();
846
- const row = db
847
- .select()
848
- .from(mediaTrackingProfiles)
849
- .where(eq(mediaTrackingProfiles.assetId, assetId))
850
- .get();
851
-
852
- if (!row) return null;
853
-
854
- let capabilities: CapabilityProfile = {};
855
- try {
856
- capabilities = JSON.parse(row.capabilities) as CapabilityProfile;
857
- } catch {
858
- capabilities = {};
859
- }
860
-
861
- return {
862
- id: row.id,
863
- assetId: row.assetId,
864
- capabilities,
865
- createdAt: row.createdAt,
866
- };
867
- }
@@ -3,8 +3,8 @@ import type { DrizzleDb } from "../db-connection.js";
3
3
  /**
4
4
  * Add index on guardian_action_deliveries.destination_conversation_id.
5
5
  *
6
- * Several lookup paths (getPendingDeliveryByConversation,
7
- * getExpiredDeliveryByConversation, getFollowupDeliveryByConversation)
6
+ * Several lookup paths (getPendingDeliveriesByConversation,
7
+ * getExpiredDeliveriesByConversation, getFollowupDeliveriesByConversation)
8
8
  * filter deliveries by destination_conversation_id. Without an index
9
9
  * these degrade to full table scans as delivery history grows.
10
10
  */
@@ -89,7 +89,6 @@ export function createChannelGuardianTables(database: DrizzleDb): void {
89
89
  );
90
90
 
91
91
  // Migration: add assistant_id column to scope approval requests by assistant.
92
- // Existing rows default to 'self' for backward compatibility.
93
92
  try {
94
93
  database.run(
95
94
  /*sql*/ `ALTER TABLE channel_guardian_approval_requests ADD COLUMN assistant_id TEXT NOT NULL DEFAULT 'self'`,
@@ -0,0 +1,18 @@
1
+ import type { DrizzleDb } from "../db-connection.js";
2
+
3
+ export function migrateChannelInteractionColumns(database: DrizzleDb): void {
4
+ try {
5
+ database.run(
6
+ /*sql*/ `ALTER TABLE contact_channels ADD COLUMN interaction_count INTEGER NOT NULL DEFAULT 0`,
7
+ );
8
+ } catch {
9
+ /* already exists */
10
+ }
11
+ try {
12
+ database.run(
13
+ /*sql*/ `ALTER TABLE contact_channels ADD COLUMN last_interaction INTEGER`,
14
+ );
15
+ } catch {
16
+ /* already exists */
17
+ }
18
+ }
@@ -0,0 +1,16 @@
1
+ import type { DrizzleDb } from "../db-connection.js";
2
+
3
+ export function migrateDropContactInteractionColumns(
4
+ database: DrizzleDb,
5
+ ): void {
6
+ try {
7
+ database.run(/*sql*/ `ALTER TABLE contacts DROP COLUMN interaction_count`);
8
+ } catch {
9
+ /* already dropped or doesn't exist */
10
+ }
11
+ try {
12
+ database.run(/*sql*/ `ALTER TABLE contacts DROP COLUMN last_interaction`);
13
+ } catch {
14
+ /* already dropped or doesn't exist */
15
+ }
16
+ }
@@ -0,0 +1,13 @@
1
+ import type { DrizzleDb } from "../db-connection.js";
2
+ import { getSqliteFrom } from "../db-connection.js";
3
+
4
+ export function migrateDropLoopbackPortColumn(database: DrizzleDb): void {
5
+ const raw = getSqliteFrom(database);
6
+ try {
7
+ raw.exec(
8
+ /*sql*/ `ALTER TABLE oauth_providers DROP COLUMN loopback_port`,
9
+ );
10
+ } catch {
11
+ // Column already dropped or doesn't exist — nothing to do.
12
+ }
13
+ }
@@ -99,6 +99,9 @@ export { migrateDropMemorySegmentFts } from "./154-drop-fts.js";
99
99
  export { migrateDropConflicts } from "./155-drop-conflicts.js";
100
100
  export { migrateCallSessionInviteMetadata } from "./156-call-session-invite-metadata.js";
101
101
  export { migrateInviteContactId } from "./157-invite-contact-id.js";
102
+ export { migrateChannelInteractionColumns } from "./158-channel-interaction-columns.js";
103
+ export { migrateDropContactInteractionColumns } from "./159-drop-contact-interaction-columns.js";
104
+ export { migrateDropLoopbackPortColumn } from "./160-drop-loopback-port-column.js";
102
105
  export {
103
106
  MIGRATION_REGISTRY,
104
107
  type MigrationRegistryEntry,