@vellumai/assistant 0.4.43 → 0.4.45

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 (713) hide show
  1. package/.prettierignore +4 -0
  2. package/ARCHITECTURE.md +46 -44
  3. package/README.md +15 -16
  4. package/bun.lock +10 -35
  5. package/docs/architecture/integrations.md +102 -215
  6. package/docs/architecture/keychain-broker.md +1 -1
  7. package/docs/architecture/memory.md +2 -2
  8. package/docs/architecture/scheduling.md +1 -1
  9. package/docs/architecture/security.md +11 -11
  10. package/docs/error-handling.md +1 -1
  11. package/docs/trusted-contact-access.md +3 -3
  12. package/drizzle/meta/0000_snapshot.json +34 -100
  13. package/drizzle/meta/_journal.json +1 -1
  14. package/drizzle.config.ts +4 -4
  15. package/package.json +3 -2
  16. package/scripts/capture-x-graphql.ts +237 -141
  17. package/scripts/generate-bundled-tool-registry.ts +223 -0
  18. package/src/__tests__/access-request-decision.test.ts +0 -1
  19. package/src/__tests__/actor-token-service.test.ts +23 -24
  20. package/src/__tests__/agent-loop.test.ts +0 -131
  21. package/src/__tests__/always-loaded-tools-guard.test.ts +71 -0
  22. package/src/__tests__/amazon-cdp-integration.test.ts +11 -9
  23. package/src/__tests__/approval-primitive.test.ts +0 -1
  24. package/src/__tests__/approval-routes-http.test.ts +11 -3
  25. package/src/__tests__/asset-materialize-tool.test.ts +0 -1
  26. package/src/__tests__/asset-search-tool.test.ts +0 -1
  27. package/src/__tests__/assistant-attachment-directive.test.ts +1 -1
  28. package/src/__tests__/assistant-events-sse-hardening.test.ts +0 -1
  29. package/src/__tests__/assistant-feature-flag-guardrails.test.ts +0 -2
  30. package/src/__tests__/assistant-feature-flags-integration.test.ts +70 -18
  31. package/src/__tests__/assistant-id-boundary-guard.test.ts +6 -6
  32. package/src/__tests__/attachments-store.test.ts +0 -1
  33. package/src/__tests__/avatar-e2e.test.ts +74 -115
  34. package/src/__tests__/avatar-router.test.ts +25 -62
  35. package/src/__tests__/browser-manager.test.ts +24 -0
  36. package/src/__tests__/browser-skill-baseline-tool-payload.test.ts +4 -3
  37. package/src/__tests__/browser-skill-endstate.test.ts +8 -11
  38. package/src/__tests__/btw-routes.test.ts +326 -0
  39. package/src/__tests__/bundled-asset.test.ts +1 -1
  40. package/src/__tests__/bundled-skill-retrieval-guard.test.ts +23 -9
  41. package/src/__tests__/call-controller.test.ts +0 -1
  42. package/src/__tests__/call-conversation-messages.test.ts +0 -1
  43. package/src/__tests__/call-domain.test.ts +0 -1
  44. package/src/__tests__/call-pointer-messages.test.ts +0 -1
  45. package/src/__tests__/call-recovery.test.ts +0 -1
  46. package/src/__tests__/call-routes-http.test.ts +0 -1
  47. package/src/__tests__/call-store.test.ts +0 -1
  48. package/src/__tests__/canonical-guardian-store.test.ts +0 -1
  49. package/src/__tests__/channel-approval-routes.test.ts +1 -1
  50. package/src/__tests__/channel-approvals.test.ts +1 -1
  51. package/src/__tests__/channel-delivery-store.test.ts +0 -1
  52. package/src/__tests__/channel-guardian.test.ts +5 -7
  53. package/src/__tests__/channel-retry-sweep.test.ts +0 -1
  54. package/src/__tests__/checker.test.ts +32 -36
  55. package/src/__tests__/compaction.benchmark.test.ts +16 -14
  56. package/src/__tests__/computer-use-session-lifecycle.test.ts +10 -11
  57. package/src/__tests__/computer-use-session-working-dir.test.ts +2 -6
  58. package/src/__tests__/computer-use-skill-lifecycle-cleanup.test.ts +2 -5
  59. package/src/__tests__/computer-use-tools.test.ts +35 -31
  60. package/src/__tests__/config-schema.test.ts +11 -15
  61. package/src/__tests__/config-watcher.test.ts +0 -1
  62. package/src/__tests__/confirmation-request-guardian-bridge.test.ts +0 -1
  63. package/src/__tests__/conflict-store.test.ts +0 -1
  64. package/src/__tests__/connection-policy.test.ts +4 -7
  65. package/src/__tests__/contacts-tools.test.ts +0 -1
  66. package/src/__tests__/context-memory-e2e.test.ts +2 -4
  67. package/src/__tests__/context-overflow-reducer.test.ts +2 -4
  68. package/src/__tests__/context-window-manager.test.ts +147 -60
  69. package/src/__tests__/contradiction-checker.test.ts +0 -1
  70. package/src/__tests__/conversation-attention-store.test.ts +0 -1
  71. package/src/__tests__/conversation-attention-telegram.test.ts +1 -1
  72. package/src/__tests__/conversation-pairing.test.ts +2 -2
  73. package/src/__tests__/conversation-routes-guardian-reply.test.ts +31 -7
  74. package/src/__tests__/conversation-routes-slash-commands.test.ts +381 -0
  75. package/src/__tests__/conversation-store.test.ts +0 -1
  76. package/src/__tests__/conversation-unread-route.test.ts +1 -2
  77. package/src/__tests__/credential-security-invariants.test.ts +8 -8
  78. package/src/__tests__/cross-provider-web-search.test.ts +353 -0
  79. package/src/__tests__/daemon-assistant-events.test.ts +6 -7
  80. package/src/__tests__/db-schedule-syntax-migration.test.ts +15 -3
  81. package/src/__tests__/delete-managed-skill-tool.test.ts +5 -9
  82. package/src/__tests__/deterministic-verification-control-plane.test.ts +0 -1
  83. package/src/__tests__/diagnostics-export.test.ts +189 -0
  84. package/src/__tests__/dynamic-skill-workflow-prompt.test.ts +0 -1
  85. package/src/__tests__/emit-signal-routing-intent.test.ts +3 -3
  86. package/src/__tests__/entity-extractor.test.ts +0 -1
  87. package/src/__tests__/entity-search.test.ts +0 -1
  88. package/src/__tests__/ephemeral-permissions.test.ts +2 -4
  89. package/src/__tests__/error-handler-friendly-messages.test.ts +46 -0
  90. package/src/__tests__/file-read-tool.test.ts +86 -0
  91. package/src/__tests__/followup-tools.test.ts +0 -1
  92. package/src/__tests__/frontmatter.test.ts +77 -34
  93. package/src/__tests__/gateway-only-enforcement.test.ts +0 -1
  94. package/src/__tests__/gateway-only-guard.test.ts +1 -1
  95. package/src/__tests__/guardian-action-conversation-turn.test.ts +0 -1
  96. package/src/__tests__/guardian-action-followup-executor.test.ts +0 -1
  97. package/src/__tests__/guardian-action-followup-store.test.ts +0 -1
  98. package/src/__tests__/guardian-action-grant-mint-consume.test.ts +0 -1
  99. package/src/__tests__/guardian-action-late-reply.test.ts +0 -1
  100. package/src/__tests__/guardian-action-store.test.ts +0 -1
  101. package/src/__tests__/guardian-action-sweep.test.ts +0 -1
  102. package/src/__tests__/guardian-decision-primitive-canonical.test.ts +0 -1
  103. package/src/__tests__/guardian-dispatch.test.ts +1 -2
  104. package/src/__tests__/guardian-grant-minting.test.ts +1 -1
  105. package/src/__tests__/guardian-outbound-http.test.ts +0 -1
  106. package/src/__tests__/guardian-principal-id-roundtrip.test.ts +0 -1
  107. package/src/__tests__/guardian-routing-invariants.test.ts +1 -1
  108. package/src/__tests__/guardian-routing-state.test.ts +0 -1
  109. package/src/__tests__/guardian-verification-voice-binding.test.ts +0 -1
  110. package/src/__tests__/guardian-verify-setup-skill-regression.test.ts +3 -5
  111. package/src/__tests__/handlers-user-message-approval-consumption.test.ts +28 -426
  112. package/src/__tests__/host-bash-proxy.test.ts +335 -0
  113. package/src/__tests__/host-file-proxy.test.ts +374 -0
  114. package/src/__tests__/host-shell-tool.test.ts +147 -1
  115. package/src/__tests__/http-user-message-parity.test.ts +361 -0
  116. package/src/__tests__/inbound-invite-redemption.test.ts +0 -1
  117. package/src/__tests__/integration-status.test.ts +3 -8
  118. package/src/__tests__/intent-routing.test.ts +7 -46
  119. package/src/__tests__/invite-redemption-service.test.ts +0 -1
  120. package/src/__tests__/invite-routes-http.test.ts +0 -1
  121. package/src/__tests__/llm-usage-store.test.ts +0 -1
  122. package/src/__tests__/managed-avatar-client.test.ts +101 -55
  123. package/src/__tests__/managed-skill-lifecycle.test.ts +9 -18
  124. package/src/__tests__/managed-store.test.ts +94 -21
  125. package/src/__tests__/media-reuse-story.e2e.test.ts +0 -1
  126. package/src/__tests__/memory-context-benchmark.benchmark.test.ts +2 -4
  127. package/src/__tests__/memory-lifecycle-e2e.test.ts +0 -1
  128. package/src/__tests__/memory-recall-quality.test.ts +0 -1
  129. package/src/__tests__/memory-regressions.experimental.test.ts +0 -1
  130. package/src/__tests__/memory-regressions.test.ts +0 -1
  131. package/src/__tests__/memory-retrieval.benchmark.test.ts +0 -1
  132. package/src/__tests__/memory-upsert-concurrency.test.ts +0 -1
  133. package/src/__tests__/messaging-send-tool.test.ts +35 -0
  134. package/src/__tests__/messaging-skill-split.test.ts +138 -0
  135. package/src/__tests__/migration-cross-version-compatibility.test.ts +0 -1
  136. package/src/__tests__/migration-export-http.test.ts +2 -3
  137. package/src/__tests__/migration-import-commit-http.test.ts +1 -2
  138. package/src/__tests__/migration-import-preflight-http.test.ts +1 -2
  139. package/src/__tests__/migration-validate-http.test.ts +1 -2
  140. package/src/__tests__/native-web-search.test.ts +475 -0
  141. package/src/__tests__/navigate-settings-tab.test.ts +84 -0
  142. package/src/__tests__/non-member-access-request.test.ts +0 -1
  143. package/src/__tests__/notification-broadcaster.test.ts +15 -15
  144. package/src/__tests__/notification-decision-strategy.test.ts +6 -6
  145. package/src/__tests__/notification-deep-link.test.ts +7 -7
  146. package/src/__tests__/notification-guardian-path.test.ts +2 -3
  147. package/src/__tests__/notification-telegram-adapter.test.ts +1 -1
  148. package/src/__tests__/notification-thread-candidates.test.ts +4 -4
  149. package/src/__tests__/onboarding-starter-tasks.test.ts +0 -1
  150. package/src/__tests__/onboarding-template-contract.test.ts +0 -10
  151. package/src/__tests__/playbook-execution.test.ts +0 -1
  152. package/src/__tests__/playbook-tools.test.ts +0 -1
  153. package/src/__tests__/profile-compiler.test.ts +0 -1
  154. package/src/__tests__/provider-fail-open-selection.test.ts +12 -2
  155. package/src/__tests__/provider-managed-proxy-integration.test.ts +25 -0
  156. package/src/__tests__/qdrant-collection-migration.test.ts +223 -0
  157. package/src/__tests__/recording-handler.test.ts +30 -94
  158. package/src/__tests__/registry.test.ts +28 -35
  159. package/src/__tests__/relay-server.test.ts +0 -1
  160. package/src/__tests__/ride-shotgun-handler.test.ts +4 -20
  161. package/src/__tests__/runtime-attachment-metadata.test.ts +0 -1
  162. package/src/__tests__/runtime-events-sse-parity.test.ts +3 -4
  163. package/src/__tests__/runtime-events-sse.test.ts +0 -1
  164. package/src/__tests__/sandbox-diagnostics.test.ts +0 -1
  165. package/src/__tests__/scaffold-managed-skill-tool.test.ts +30 -28
  166. package/src/__tests__/schedule-store.test.ts +441 -1
  167. package/src/__tests__/schedule-tools.test.ts +468 -7
  168. package/src/__tests__/scheduler-recurrence.test.ts +196 -23
  169. package/src/__tests__/scoped-approval-grants.test.ts +0 -1
  170. package/src/__tests__/scoped-grant-security-matrix.test.ts +0 -1
  171. package/src/__tests__/secret-prompt-log-hygiene.test.ts +6 -3
  172. package/src/__tests__/secret-response-routing.test.ts +4 -1
  173. package/src/__tests__/send-endpoint-busy.test.ts +14 -5
  174. package/src/__tests__/send-notification-tool.test.ts +0 -7
  175. package/src/__tests__/sequence-store.test.ts +0 -1
  176. package/src/__tests__/server-history-render.test.ts +1 -2
  177. package/src/__tests__/session-abort-tool-results.test.ts +0 -1
  178. package/src/__tests__/session-agent-loop.test.ts +46 -6
  179. package/src/__tests__/session-confirmation-signals.test.ts +7 -46
  180. package/src/__tests__/session-conflict-gate.test.ts +2 -6
  181. package/src/__tests__/session-error.test.ts +5 -14
  182. package/src/__tests__/session-init.benchmark.test.ts +3 -5
  183. package/src/__tests__/session-load-history-repair.test.ts +0 -1
  184. package/src/__tests__/session-media-retry.test.ts +12 -74
  185. package/src/__tests__/session-pre-run-repair.test.ts +0 -1
  186. package/src/__tests__/session-profile-injection.test.ts +2 -6
  187. package/src/__tests__/session-provider-retry-repair.test.ts +2 -6
  188. package/src/__tests__/session-queue.test.ts +94 -139
  189. package/src/__tests__/session-skill-tools.test.ts +115 -115
  190. package/src/__tests__/session-slash-known.test.ts +0 -1
  191. package/src/__tests__/session-slash-queue.test.ts +0 -1
  192. package/src/__tests__/session-slash-unknown.test.ts +0 -1
  193. package/src/__tests__/session-surfaces-task-progress.test.ts +34 -0
  194. package/src/__tests__/session-usage.test.ts +0 -1
  195. package/src/__tests__/session-workspace-cache-state.test.ts +2 -6
  196. package/src/__tests__/session-workspace-injection.test.ts +2 -6
  197. package/src/__tests__/session-workspace-tool-tracking.test.ts +2 -6
  198. package/src/__tests__/skill-feature-flags-integration.test.ts +180 -184
  199. package/src/__tests__/skill-feature-flags.test.ts +125 -18
  200. package/src/__tests__/skill-load-feature-flag.test.ts +1 -2
  201. package/src/__tests__/skill-load-tool.test.ts +194 -2
  202. package/src/__tests__/skill-projection-feature-flag.test.ts +27 -16
  203. package/src/__tests__/skill-projection.benchmark.test.ts +15 -14
  204. package/src/__tests__/skills.test.ts +14 -53
  205. package/src/__tests__/slack-channel-config.test.ts +0 -1
  206. package/src/__tests__/slack-inbound-verification.test.ts +0 -1
  207. package/src/__tests__/slack-skill.test.ts +1 -1
  208. package/src/__tests__/starter-task-flow.test.ts +9 -19
  209. package/src/__tests__/subagent-tools.test.ts +2 -2
  210. package/src/__tests__/system-prompt.test.ts +7 -7
  211. package/src/__tests__/task-compiler.test.ts +0 -1
  212. package/src/__tests__/task-management-tools.test.ts +0 -1
  213. package/src/__tests__/task-memory-cleanup.test.ts +0 -1
  214. package/src/__tests__/task-runner.test.ts +0 -1
  215. package/src/__tests__/task-scheduler.test.ts +0 -1
  216. package/src/__tests__/terminal-tools.test.ts +0 -1
  217. package/src/__tests__/test-support/computer-use-skill-harness.ts +2 -4
  218. package/src/__tests__/thread-seed-composer.test.ts +5 -5
  219. package/src/__tests__/tool-approval-handler.test.ts +0 -1
  220. package/src/__tests__/tool-execution-abort-cleanup.test.ts +0 -1
  221. package/src/__tests__/tool-execution-pipeline.benchmark.test.ts +0 -1
  222. package/src/__tests__/tool-executor.test.ts +8 -86
  223. package/src/__tests__/tool-grant-request-escalation.test.ts +0 -1
  224. package/src/__tests__/tool-notification-listener.test.ts +1 -1
  225. package/src/__tests__/tool-preview-lifecycle.test.ts +416 -0
  226. package/src/__tests__/trust-store.test.ts +84 -8
  227. package/src/__tests__/trusted-contact-approval-notifier.test.ts +0 -1
  228. package/src/__tests__/trusted-contact-inline-approval-integration.test.ts +0 -1
  229. package/src/__tests__/trusted-contact-lifecycle-notifications.test.ts +0 -1
  230. package/src/__tests__/trusted-contact-multichannel.test.ts +0 -1
  231. package/src/__tests__/trusted-contact-verification.test.ts +0 -1
  232. package/src/__tests__/twilio-provider.test.ts +0 -1
  233. package/src/__tests__/twilio-routes.test.ts +0 -1
  234. package/src/__tests__/{request-file-tool.test.ts → ui-file-upload-surface.test.ts} +11 -72
  235. package/src/__tests__/update-bulletin.test.ts +0 -1
  236. package/src/__tests__/usage-cache-backfill-migration.test.ts +0 -1
  237. package/src/__tests__/usage-routes.test.ts +0 -1
  238. package/src/__tests__/verification-control-plane-policy.test.ts +4 -4
  239. package/src/__tests__/voice-invite-redemption.test.ts +0 -1
  240. package/src/__tests__/voice-scoped-grant-consumer.test.ts +0 -1
  241. package/src/__tests__/voice-session-bridge.test.ts +9 -1
  242. package/src/__tests__/web-fetch.test.ts +57 -0
  243. package/src/__tests__/workspace-git-service.test.ts +5 -14
  244. package/src/__tests__/workspace-policy.test.ts +0 -1
  245. package/src/agent/loop.ts +22 -34
  246. package/src/bundler/bundle-signer.ts +4 -4
  247. package/src/calls/call-controller.ts +1 -1
  248. package/src/calls/relay-server.ts +1 -1
  249. package/src/calls/twilio-rest.ts +1 -1
  250. package/src/calls/voice-session-bridge.ts +3 -1
  251. package/src/cli/__tests__/notifications.test.ts +3 -4
  252. package/src/cli/commands/map.ts +2 -6
  253. package/src/cli/commands/mcp.ts +73 -15
  254. package/src/cli/commands/notifications.ts +4 -4
  255. package/src/cli/commands/sessions.ts +9 -1
  256. package/src/cli/commands/skills.ts +6 -10
  257. package/src/cli/http-client.ts +2 -3
  258. package/src/cli/main-screen.tsx +10 -10
  259. package/src/cli/program.ts +0 -4
  260. package/src/cli/reference.ts +0 -2
  261. package/src/cli.ts +15 -9
  262. package/src/config/__tests__/bundled-tool-registry-guard.test.ts +120 -0
  263. package/src/config/bundled-skills/_shared/CLI_RETRIEVAL_PATTERN.md +11 -0
  264. package/src/config/bundled-skills/app-builder/SKILL.md +6 -7
  265. package/src/config/bundled-skills/app-builder/TOOLS.json +0 -4
  266. package/src/config/bundled-skills/browser/SKILL.md +6 -1
  267. package/src/config/bundled-skills/chatgpt-import/SKILL.md +5 -1
  268. package/src/config/bundled-skills/claude-code/SKILL.md +5 -1
  269. package/src/config/bundled-skills/computer-use/SKILL.md +6 -1
  270. package/src/config/bundled-skills/computer-use/TOOLS.json +6 -69
  271. package/src/config/bundled-skills/computer-use/tools/computer-use-click.ts +10 -1
  272. package/src/config/bundled-skills/contacts/SKILL.md +10 -1
  273. package/src/config/bundled-skills/contacts/TOOLS.json +35 -0
  274. package/src/config/bundled-skills/{messaging → contacts}/tools/google-contacts.ts +9 -2
  275. package/src/config/bundled-skills/document/SKILL.md +4 -1
  276. package/src/config/bundled-skills/doordash/SKILL.md +8 -2
  277. package/src/config/bundled-skills/doordash/__tests__/doordash-session.test.ts +1 -82
  278. package/src/config/bundled-skills/doordash/doordash-cli.ts +17 -28
  279. package/src/config/bundled-skills/doordash/lib/session.ts +21 -17
  280. package/src/config/bundled-skills/doordash/lib/shared/platform.ts +4 -1
  281. package/src/config/bundled-skills/followups/SKILL.md +4 -1
  282. package/src/config/bundled-skills/gmail/SKILL.md +180 -0
  283. package/src/config/bundled-skills/gmail/TOOLS.json +506 -0
  284. package/src/config/bundled-skills/gmail/tools/gmail-archive.ts +149 -0
  285. package/src/config/bundled-skills/gmail/tools/gmail-attachments.ts +110 -0
  286. package/src/config/bundled-skills/{messaging → gmail}/tools/gmail-draft.ts +1 -1
  287. package/src/config/bundled-skills/{messaging → gmail}/tools/gmail-filters.ts +1 -1
  288. package/src/config/bundled-skills/{messaging → gmail}/tools/gmail-follow-up.ts +1 -1
  289. package/src/config/bundled-skills/{messaging → gmail}/tools/gmail-forward.ts +1 -1
  290. package/src/config/bundled-skills/gmail/tools/gmail-label.ts +50 -0
  291. package/src/config/bundled-skills/{messaging → gmail}/tools/gmail-outreach-scan.ts +8 -90
  292. package/src/config/bundled-skills/{messaging → gmail}/tools/gmail-send-draft.ts +1 -1
  293. package/src/config/bundled-skills/{messaging → gmail}/tools/gmail-sender-digest.ts +2 -2
  294. package/src/config/bundled-skills/{messaging → gmail}/tools/gmail-trash.ts +1 -1
  295. package/src/config/bundled-skills/{messaging → gmail}/tools/gmail-unsubscribe.ts +1 -1
  296. package/src/config/bundled-skills/{messaging → gmail}/tools/gmail-vacation.ts +1 -1
  297. package/src/config/bundled-skills/gmail/tools/shared.ts +47 -0
  298. package/src/config/bundled-skills/google-calendar/SKILL.md +5 -1
  299. package/src/config/bundled-skills/image-studio/SKILL.md +5 -1
  300. package/src/config/bundled-skills/knowledge-graph/SKILL.md +4 -1
  301. package/src/config/bundled-skills/media-processing/SKILL.md +7 -13
  302. package/src/config/bundled-skills/media-processing/TOOLS.json +0 -22
  303. package/src/config/bundled-skills/media-processing/tools/generate-clip.ts +12 -1
  304. package/src/config/bundled-skills/messaging/SKILL.md +23 -139
  305. package/src/config/bundled-skills/messaging/TOOLS.json +33 -1215
  306. package/src/config/bundled-skills/messaging/tools/gmail-mime-helpers.ts +42 -0
  307. package/src/config/bundled-skills/messaging/tools/messaging-send.ts +165 -2
  308. package/src/config/bundled-skills/messaging/tools/messaging-sender-digest.ts +1 -13
  309. package/src/config/bundled-skills/messaging/tools/shared.ts +81 -34
  310. package/src/config/bundled-skills/notifications/SKILL.md +5 -1
  311. package/src/config/bundled-skills/orchestration/SKILL.md +30 -0
  312. package/src/config/bundled-skills/orchestration/TOOLS.json +35 -0
  313. package/src/config/bundled-skills/{reminder/tools/reminder-cancel.ts → orchestration/tools/swarm-delegate.ts} +3 -3
  314. package/src/config/bundled-skills/phone-calls/SKILL.md +9 -1
  315. package/src/config/bundled-skills/playbooks/SKILL.md +4 -1
  316. package/src/config/bundled-skills/schedule/SKILL.md +70 -9
  317. package/src/config/bundled-skills/schedule/TOOLS.json +38 -6
  318. package/src/config/bundled-skills/screen-watch/SKILL.md +28 -0
  319. package/src/config/bundled-skills/screen-watch/TOOLS.json +35 -0
  320. package/src/config/bundled-skills/{reminder/tools/reminder-create.ts → screen-watch/tools/start-screen-watch.ts} +3 -3
  321. package/src/config/bundled-skills/sequences/SKILL.md +47 -0
  322. package/src/config/bundled-skills/sequences/TOOLS.json +340 -0
  323. package/src/config/bundled-skills/sequences/tools/sequence-update.ts +128 -0
  324. package/src/config/bundled-skills/sequences/tools/shared.ts +9 -0
  325. package/src/config/bundled-skills/settings/SKILL.md +12 -0
  326. package/src/config/bundled-skills/settings/TOOLS.json +112 -0
  327. package/src/config/bundled-skills/settings/tools/navigate-settings-tab.ts +43 -0
  328. package/src/config/bundled-skills/settings/tools/open-system-settings.ts +52 -0
  329. package/src/config/bundled-skills/{computer-use/tools/computer-use-right-click.ts → settings/tools/set-avatar.ts} +2 -6
  330. package/src/{tools/system/voice-config.ts → config/bundled-skills/settings/tools/voice-config-update.ts} +59 -96
  331. package/src/config/bundled-skills/skill-management/SKILL.md +18 -0
  332. package/src/config/bundled-skills/skill-management/TOOLS.json +90 -0
  333. package/src/config/bundled-skills/{computer-use/tools/computer-use-double-click.ts → skill-management/tools/delete-managed.ts} +2 -6
  334. package/src/config/bundled-skills/skill-management/tools/scaffold-managed.ts +12 -0
  335. package/src/config/bundled-skills/slack/SKILL.md +5 -1
  336. package/src/config/bundled-skills/subagent/SKILL.md +4 -1
  337. package/src/config/bundled-skills/tasks/SKILL.md +5 -2
  338. package/src/config/bundled-skills/transcribe/SKILL.md +4 -1
  339. package/src/config/bundled-skills/watcher/SKILL.md +4 -1
  340. package/src/config/bundled-tool-registry.ts +118 -107
  341. package/src/config/env.ts +5 -2
  342. package/src/config/feature-flag-registry.json +33 -9
  343. package/src/config/loader.ts +10 -2
  344. package/src/config/schema.ts +19 -16
  345. package/src/config/schemas/inference.ts +12 -22
  346. package/src/config/schemas/memory-storage.ts +19 -1
  347. package/src/config/schemas/platform.ts +0 -16
  348. package/src/config/skill-state.ts +11 -8
  349. package/src/config/skills.ts +83 -32
  350. package/src/context/token-estimator.ts +11 -0
  351. package/src/context/window-manager.ts +180 -151
  352. package/src/daemon/computer-use-session.ts +11 -43
  353. package/src/daemon/daemon-control.ts +4 -1
  354. package/src/daemon/handlers/config-channels.ts +5 -9
  355. package/src/daemon/handlers/config-ingress.ts +0 -4
  356. package/src/daemon/handlers/config-model.ts +7 -13
  357. package/src/daemon/handlers/config-telegram.ts +4 -8
  358. package/src/daemon/handlers/config-voice.ts +2 -5
  359. package/src/daemon/handlers/dictation.ts +2 -12
  360. package/src/daemon/handlers/identity.ts +0 -105
  361. package/src/daemon/handlers/recording.ts +3 -23
  362. package/src/daemon/handlers/session-history.ts +42 -10
  363. package/src/daemon/handlers/sessions.ts +53 -72
  364. package/src/daemon/handlers/shared.ts +7 -28
  365. package/src/daemon/handlers/skills.ts +31 -27
  366. package/src/daemon/host-bash-proxy.ts +148 -0
  367. package/src/daemon/host-file-proxy.ts +135 -0
  368. package/src/daemon/lifecycle.ts +53 -41
  369. package/src/daemon/mcp-reload-service.ts +123 -0
  370. package/src/daemon/message-protocol.ts +6 -0
  371. package/src/daemon/message-types/apps.ts +0 -25
  372. package/src/daemon/message-types/browser.ts +1 -1
  373. package/src/daemon/message-types/computer-use.ts +1 -4
  374. package/src/daemon/message-types/guardian-actions.ts +1 -1
  375. package/src/daemon/message-types/host-bash.ts +18 -0
  376. package/src/daemon/message-types/host-file.ts +44 -0
  377. package/src/daemon/message-types/integrations.ts +1 -73
  378. package/src/daemon/message-types/messages.ts +15 -0
  379. package/src/daemon/message-types/schedules.ts +11 -27
  380. package/src/daemon/message-types/sessions.ts +8 -2
  381. package/src/daemon/message-types/settings.ts +1 -1
  382. package/src/daemon/message-types/shared.ts +1 -1
  383. package/src/daemon/message-types/surfaces.ts +2 -0
  384. package/src/daemon/ride-shotgun-handler.ts +35 -43
  385. package/src/daemon/seed-files.ts +3 -27
  386. package/src/daemon/server.ts +45 -28
  387. package/src/daemon/session-agent-loop-handlers.ts +72 -9
  388. package/src/daemon/session-agent-loop.ts +97 -66
  389. package/src/daemon/session-attachments.ts +1 -1
  390. package/src/daemon/session-error.ts +17 -16
  391. package/src/daemon/session-lifecycle.ts +20 -1
  392. package/src/daemon/session-media-retry.ts +1 -15
  393. package/src/daemon/session-messaging.ts +14 -6
  394. package/src/daemon/session-process.ts +36 -7
  395. package/src/daemon/session-queue-manager.ts +62 -103
  396. package/src/daemon/session-runtime-assembly.ts +27 -7
  397. package/src/daemon/session-skill-tools.ts +12 -11
  398. package/src/daemon/session-slash.ts +7 -0
  399. package/src/daemon/session-surfaces.ts +192 -118
  400. package/src/daemon/session-tool-setup.ts +146 -6
  401. package/src/daemon/session.ts +75 -37
  402. package/src/errors.ts +0 -2
  403. package/src/export/formatter.ts +6 -0
  404. package/src/mcp/mcp-oauth-provider.ts +1 -3
  405. package/src/media/avatar-router.ts +20 -28
  406. package/src/media/avatar-types.ts +7 -14
  407. package/src/media/managed-avatar-client.ts +70 -34
  408. package/src/memory/app-store.ts +0 -18
  409. package/src/memory/conversation-title-service.ts +1 -2
  410. package/src/memory/db-init.ts +16 -0
  411. package/src/memory/embedding-backend.ts +129 -27
  412. package/src/memory/embedding-gemini.test.ts +256 -0
  413. package/src/memory/embedding-gemini.ts +47 -13
  414. package/src/memory/embedding-local.ts +14 -2
  415. package/src/memory/embedding-ollama.ts +15 -2
  416. package/src/memory/embedding-openai.ts +15 -2
  417. package/src/memory/embedding-types.test.ts +116 -0
  418. package/src/memory/embedding-types.ts +61 -0
  419. package/src/memory/fingerprint.ts +1 -1
  420. package/src/memory/indexer.ts +25 -1
  421. package/src/memory/job-handlers/embedding.test.ts +258 -0
  422. package/src/memory/job-handlers/embedding.ts +81 -1
  423. package/src/memory/job-handlers/index-maintenance.ts +35 -1
  424. package/src/memory/job-handlers/media-processing.ts +11 -1
  425. package/src/memory/job-utils.ts +21 -6
  426. package/src/memory/jobs-store.ts +5 -1
  427. package/src/memory/jobs-worker.ts +8 -0
  428. package/src/memory/message-content.ts +66 -0
  429. package/src/memory/migrations/100-core-tables.ts +1 -31
  430. package/src/memory/migrations/104-core-indexes.ts +0 -11
  431. package/src/memory/migrations/145-drop-accounts-table.ts +19 -0
  432. package/src/memory/migrations/146-schedule-oneshot-routing.ts +94 -0
  433. package/src/memory/migrations/147-migrate-reminders-to-schedules.ts +129 -0
  434. package/src/memory/migrations/148-drop-reminders-table.ts +18 -0
  435. package/src/memory/migrations/index.ts +4 -0
  436. package/src/memory/migrations/registry.ts +19 -0
  437. package/src/memory/qdrant-client.ts +158 -43
  438. package/src/memory/retriever.test.ts +0 -1
  439. package/src/memory/retriever.ts +12 -2
  440. package/src/memory/schema/infrastructure.ts +5 -37
  441. package/src/memory/search/formatting.ts +34 -9
  442. package/src/memory/search/semantic.ts +57 -2
  443. package/src/memory/search/types.ts +2 -1
  444. package/src/notifications/AGENTS.md +2 -2
  445. package/src/notifications/README.md +59 -58
  446. package/src/notifications/adapters/macos.ts +1 -1
  447. package/src/notifications/broadcaster.ts +5 -5
  448. package/src/notifications/copy-composer.ts +1 -1
  449. package/src/notifications/decision-engine.ts +2 -2
  450. package/src/notifications/destination-resolver.ts +2 -2
  451. package/src/notifications/emit-signal.ts +8 -8
  452. package/src/notifications/signal.ts +1 -1
  453. package/src/notifications/thread-seed-composer.ts +1 -1
  454. package/src/oauth/connect-orchestrator.ts +1 -1
  455. package/src/oauth/token-persistence.ts +1 -1
  456. package/src/permissions/checker.ts +12 -1
  457. package/src/permissions/defaults.ts +13 -17
  458. package/src/permissions/trust-store.ts +37 -0
  459. package/src/permissions/workspace-policy.ts +0 -1
  460. package/src/prompts/__tests__/build-cli-reference-section.test.ts +11 -0
  461. package/src/prompts/computer-use-prompt.ts +1 -1
  462. package/src/prompts/system-prompt.ts +33 -35
  463. package/src/prompts/templates/BOOTSTRAP.md +0 -3
  464. package/src/prompts/templates/SOUL.md +1 -2
  465. package/src/prompts/templates/UPDATES.md +16 -7
  466. package/src/providers/anthropic/client.ts +87 -33
  467. package/src/providers/gemini/client.ts +6 -0
  468. package/src/providers/managed-proxy/constants.ts +5 -0
  469. package/src/providers/openai/client.ts +15 -0
  470. package/src/providers/registry.ts +4 -6
  471. package/src/providers/types.ts +24 -2
  472. package/src/runtime/AGENTS.md +18 -0
  473. package/src/runtime/assistant-event-hub.ts +2 -3
  474. package/src/runtime/assistant-event.ts +4 -4
  475. package/src/runtime/auth/__tests__/context.test.ts +5 -5
  476. package/src/runtime/auth/__tests__/credential-service.test.ts +0 -1
  477. package/src/runtime/auth/__tests__/guard-tests.test.ts +3 -2
  478. package/src/runtime/auth/__tests__/{ipc-auth-context.test.ts → local-auth-context.test.ts} +21 -21
  479. package/src/runtime/auth/__tests__/route-policy.test.ts +2 -2
  480. package/src/runtime/auth/__tests__/scopes.test.ts +9 -8
  481. package/src/runtime/auth/__tests__/subject.test.ts +8 -8
  482. package/src/runtime/auth/__tests__/token-service.test.ts +0 -1
  483. package/src/runtime/auth/route-policy.ts +8 -8
  484. package/src/runtime/auth/scopes.ts +2 -1
  485. package/src/runtime/auth/subject.ts +4 -4
  486. package/src/runtime/auth/token-service.ts +1 -24
  487. package/src/runtime/auth/types.ts +3 -3
  488. package/src/runtime/guardian-action-followup-executor.ts +1 -1
  489. package/src/runtime/guardian-action-grant-minter.ts +1 -1
  490. package/src/runtime/guardian-action-service.ts +3 -3
  491. package/src/runtime/http-server.ts +15 -2
  492. package/src/runtime/http-types.ts +10 -0
  493. package/src/runtime/invite-service.ts +3 -3
  494. package/src/runtime/local-actor-identity.ts +17 -22
  495. package/src/runtime/middleware/error-handler.ts +14 -1
  496. package/src/runtime/pending-interactions.ts +21 -9
  497. package/src/runtime/routes/app-management-routes.ts +63 -67
  498. package/src/runtime/routes/approval-routes.ts +1 -3
  499. package/src/runtime/routes/brain-graph/brain-graph.html +1845 -0
  500. package/src/runtime/routes/brain-graph-routes.ts +4 -42
  501. package/src/runtime/routes/btw-routes.ts +155 -0
  502. package/src/runtime/routes/computer-use-routes.ts +77 -31
  503. package/src/runtime/routes/conversation-routes.ts +234 -47
  504. package/src/runtime/routes/diagnostics-routes.ts +154 -43
  505. package/src/runtime/routes/documents-routes.ts +2 -2
  506. package/src/runtime/routes/global-search-routes.ts +1 -1
  507. package/src/runtime/routes/host-bash-routes.ts +83 -0
  508. package/src/runtime/routes/host-file-routes.ts +79 -0
  509. package/src/runtime/routes/integrations/slack/share.ts +1 -1
  510. package/src/runtime/routes/log-export-routes.ts +120 -0
  511. package/src/runtime/routes/mcp-routes.ts +20 -0
  512. package/src/runtime/routes/migration-routes.ts +3 -3
  513. package/src/runtime/routes/pairing-routes.ts +1 -1
  514. package/src/runtime/routes/recording-routes.ts +6 -4
  515. package/src/runtime/routes/schedule-routes.ts +31 -5
  516. package/src/runtime/routes/session-management-routes.ts +2 -6
  517. package/src/runtime/routes/session-query-routes.ts +18 -15
  518. package/src/runtime/routes/settings-routes.ts +7 -351
  519. package/src/runtime/routes/skills-routes.ts +7 -6
  520. package/src/runtime/routes/subagents-routes.ts +4 -10
  521. package/src/runtime/routes/surface-action-routes.ts +3 -14
  522. package/src/runtime/routes/surface-content-routes.ts +22 -5
  523. package/src/runtime/routes/work-items-routes.ts +21 -25
  524. package/src/runtime/routes/workspace-routes.test.ts +3 -3
  525. package/src/runtime/routes/workspace-utils.ts +1 -1
  526. package/src/runtime/telegram-streaming-delivery.ts +3 -0
  527. package/src/runtime/verification-outbound-actions.ts +2 -2
  528. package/src/schedule/integration-status.ts +0 -6
  529. package/src/schedule/schedule-store.ts +234 -43
  530. package/src/schedule/scheduler.ts +73 -74
  531. package/src/security/oauth2.ts +1 -1
  532. package/src/sequence/store.ts +12 -2
  533. package/src/skills/frontmatter.ts +19 -77
  534. package/src/skills/managed-store.ts +11 -2
  535. package/src/subagent/manager.ts +5 -3
  536. package/src/tasks/ephemeral-permissions.ts +3 -5
  537. package/src/tools/AGENTS.md +37 -0
  538. package/src/tools/apps/executors.ts +0 -6
  539. package/src/tools/browser/browser-manager.ts +17 -11
  540. package/src/tools/browser/jit-auth.ts +4 -1
  541. package/src/tools/claude-code/claude-code.ts +1 -1
  542. package/src/tools/computer-use/definitions.ts +48 -60
  543. package/src/tools/document/document-tool.ts +6 -6
  544. package/src/tools/document/editor-template.ts +10 -8
  545. package/src/tools/filesystem/edit.ts +2 -1
  546. package/src/tools/filesystem/read.ts +20 -2
  547. package/src/tools/filesystem/write.ts +2 -1
  548. package/src/tools/host-filesystem/edit.ts +17 -1
  549. package/src/tools/host-filesystem/read.ts +16 -1
  550. package/src/tools/host-filesystem/write.ts +15 -1
  551. package/src/tools/host-terminal/host-shell.ts +24 -0
  552. package/src/tools/memory/definitions.ts +45 -81
  553. package/src/tools/memory/handlers.test.ts +0 -1
  554. package/src/tools/memory/handlers.ts +1 -1
  555. package/src/tools/memory/register.ts +26 -60
  556. package/src/tools/network/script-proxy/session-manager.ts +6 -8
  557. package/src/tools/network/web-fetch.ts +7 -1
  558. package/src/tools/network/web-search.ts +2 -1
  559. package/src/tools/registry.ts +23 -0
  560. package/src/tools/schedule/create.ts +113 -5
  561. package/src/tools/schedule/list.ts +57 -15
  562. package/src/tools/schedule/update.ts +73 -3
  563. package/src/tools/shared/filesystem/image-read.ts +192 -0
  564. package/src/tools/side-effects.ts +1 -7
  565. package/src/tools/skills/delete-managed.ts +27 -64
  566. package/src/tools/skills/execute.ts +54 -0
  567. package/src/tools/skills/load.ts +127 -5
  568. package/src/tools/skills/scaffold-managed.ts +93 -172
  569. package/src/tools/subagent/message.ts +0 -7
  570. package/src/tools/subagent/spawn.ts +1 -1
  571. package/src/tools/swarm/delegate.ts +0 -3
  572. package/src/tools/system/avatar-generator.ts +13 -19
  573. package/src/tools/system/request-permission.ts +2 -1
  574. package/src/tools/terminal/safe-env.ts +1 -0
  575. package/src/tools/tool-manifest.ts +41 -47
  576. package/src/tools/types.ts +6 -2
  577. package/src/tools/ui-surface/definitions.ts +0 -55
  578. package/src/util/errors.ts +12 -10
  579. package/src/workspace/git-service.ts +0 -2
  580. package/src/__tests__/account-registry.test.ts +0 -258
  581. package/src/__tests__/email-classifier.test.ts +0 -25
  582. package/src/__tests__/gmail-integration.test.ts +0 -97
  583. package/src/__tests__/handle-user-message-secret-resume.test.ts +0 -172
  584. package/src/__tests__/home-base-bootstrap.test.ts +0 -84
  585. package/src/__tests__/managed-twitter-guardrails.test.ts +0 -353
  586. package/src/__tests__/prebuilt-home-base-seed.test.ts +0 -79
  587. package/src/__tests__/recording-intent-fallback.test.ts +0 -199
  588. package/src/__tests__/recording-intent.test.ts +0 -985
  589. package/src/__tests__/recording-state-machine.test.ts +0 -1574
  590. package/src/__tests__/reminder-store.test.ts +0 -350
  591. package/src/__tests__/reminder.test.ts +0 -337
  592. package/src/__tests__/scan-result-store.test.ts +0 -121
  593. package/src/__tests__/twitter-platform-proxy-client.test.ts +0 -450
  594. package/src/__tests__/view-image-tool.test.ts +0 -241
  595. package/src/cli/commands/amazon/cart.ts +0 -513
  596. package/src/cli/commands/amazon/checkout.ts +0 -394
  597. package/src/cli/commands/amazon/client.ts +0 -513
  598. package/src/cli/commands/amazon/index.ts +0 -920
  599. package/src/cli/commands/amazon/product-details.ts +0 -145
  600. package/src/cli/commands/amazon/request-extractor.ts +0 -187
  601. package/src/cli/commands/amazon/search.ts +0 -76
  602. package/src/cli/commands/amazon/session.ts +0 -116
  603. package/src/cli/commands/twitter/__tests__/cli-error-shaping.test.ts +0 -265
  604. package/src/cli/commands/twitter/__tests__/cli-read-routing.test.ts +0 -483
  605. package/src/cli/commands/twitter/__tests__/cli-routing.test.ts +0 -412
  606. package/src/cli/commands/twitter/__tests__/oauth-client.test.ts +0 -197
  607. package/src/cli/commands/twitter/client.ts +0 -989
  608. package/src/cli/commands/twitter/index.ts +0 -1160
  609. package/src/cli/commands/twitter/oauth-client.ts +0 -94
  610. package/src/cli/commands/twitter/router.ts +0 -396
  611. package/src/cli/commands/twitter/session.ts +0 -121
  612. package/src/config/bundled-skills/agentmail/SKILL.md +0 -132
  613. package/src/config/bundled-skills/agentmail/icon.svg +0 -21
  614. package/src/config/bundled-skills/amazon/SKILL.md +0 -137
  615. package/src/config/bundled-skills/amazon/icon.svg +0 -13
  616. package/src/config/bundled-skills/api-mapping/SKILL.md +0 -78
  617. package/src/config/bundled-skills/api-mapping/icon.svg +0 -18
  618. package/src/config/bundled-skills/cli-discover/SKILL.md +0 -68
  619. package/src/config/bundled-skills/deploy-fullstack-vercel/SKILL.md +0 -179
  620. package/src/config/bundled-skills/document-writer/SKILL.md +0 -195
  621. package/src/config/bundled-skills/elevenlabs-voice/SKILL.md +0 -140
  622. package/src/config/bundled-skills/email-setup/SKILL.md +0 -68
  623. package/src/config/bundled-skills/frontend-design/SKILL.md +0 -44
  624. package/src/config/bundled-skills/frontend-design/icon.svg +0 -16
  625. package/src/config/bundled-skills/google-oauth-setup/SKILL.md +0 -452
  626. package/src/config/bundled-skills/guardian-verify-setup/SKILL.md +0 -203
  627. package/src/config/bundled-skills/influencer/SKILL.md +0 -144
  628. package/src/config/bundled-skills/influencer/scripts/client.ts +0 -1269
  629. package/src/config/bundled-skills/influencer/scripts/influencer.ts +0 -267
  630. package/src/config/bundled-skills/macos-automation/SKILL.md +0 -65
  631. package/src/config/bundled-skills/macos-automation/icon.svg +0 -12
  632. package/src/config/bundled-skills/mcp-setup/SKILL.md +0 -75
  633. package/src/config/bundled-skills/media-processing/tools/media-diagnostics.ts +0 -184
  634. package/src/config/bundled-skills/messaging/tools/gmail-archive-by-query.ts +0 -80
  635. package/src/config/bundled-skills/messaging/tools/gmail-archive.ts +0 -29
  636. package/src/config/bundled-skills/messaging/tools/gmail-batch-archive.ts +0 -56
  637. package/src/config/bundled-skills/messaging/tools/gmail-batch-label.ts +0 -34
  638. package/src/config/bundled-skills/messaging/tools/gmail-download-attachment.ts +0 -47
  639. package/src/config/bundled-skills/messaging/tools/gmail-label.ts +0 -31
  640. package/src/config/bundled-skills/messaging/tools/gmail-list-attachments.ts +0 -67
  641. package/src/config/bundled-skills/messaging/tools/gmail-send-with-attachments.ts +0 -97
  642. package/src/config/bundled-skills/messaging/tools/gmail-summarize-thread.ts +0 -87
  643. package/src/config/bundled-skills/messaging/tools/gmail-triage.ts +0 -135
  644. package/src/config/bundled-skills/messaging/tools/messaging-analyze-activity.ts +0 -24
  645. package/src/config/bundled-skills/messaging/tools/messaging-reply.ts +0 -201
  646. package/src/config/bundled-skills/messaging/tools/send-notification.ts +0 -1
  647. package/src/config/bundled-skills/messaging/tools/sequence-cancel.ts +0 -27
  648. package/src/config/bundled-skills/messaging/tools/sequence-pause.ts +0 -48
  649. package/src/config/bundled-skills/messaging/tools/sequence-resume.ts +0 -27
  650. package/src/config/bundled-skills/messaging/tools/sequence-update.ts +0 -56
  651. package/src/config/bundled-skills/notion/SKILL.md +0 -240
  652. package/src/config/bundled-skills/notion-oauth-setup/SKILL.md +0 -126
  653. package/src/config/bundled-skills/oauth-setup/SKILL.md +0 -143
  654. package/src/config/bundled-skills/public-ingress/SKILL.md +0 -258
  655. package/src/config/bundled-skills/reminder/SKILL.md +0 -79
  656. package/src/config/bundled-skills/reminder/TOOLS.json +0 -89
  657. package/src/config/bundled-skills/reminder/tools/reminder-list.ts +0 -12
  658. package/src/config/bundled-skills/restaurant-reservation/SKILL.md +0 -141
  659. package/src/config/bundled-skills/screen-recording/SKILL.md +0 -148
  660. package/src/config/bundled-skills/self-upgrade/SKILL.md +0 -69
  661. package/src/config/bundled-skills/skills-catalog/SKILL.md +0 -78
  662. package/src/config/bundled-skills/slack-app-setup/SKILL.md +0 -178
  663. package/src/config/bundled-skills/slack-digest-setup/SKILL.md +0 -163
  664. package/src/config/bundled-skills/slack-oauth-setup/SKILL.md +0 -157
  665. package/src/config/bundled-skills/start-the-day/SKILL.md +0 -70
  666. package/src/config/bundled-skills/start-the-day/icon.svg +0 -13
  667. package/src/config/bundled-skills/telegram-setup/SKILL.md +0 -105
  668. package/src/config/bundled-skills/time-based-actions/SKILL.md +0 -142
  669. package/src/config/bundled-skills/twilio-setup/SKILL.md +0 -232
  670. package/src/config/bundled-skills/twitter/SKILL.md +0 -319
  671. package/src/config/bundled-skills/twitter/icon.svg +0 -14
  672. package/src/config/bundled-skills/typescript-eval/SKILL.md +0 -60
  673. package/src/config/bundled-skills/vercel-token-setup/SKILL.md +0 -214
  674. package/src/config/bundled-skills/voice-setup/SKILL.md +0 -131
  675. package/src/config/bundled-skills/voice-setup/icon.svg +0 -20
  676. package/src/daemon/handlers/pairing.ts +0 -119
  677. package/src/daemon/handlers/session-user-message.ts +0 -961
  678. package/src/daemon/recording-executor.ts +0 -180
  679. package/src/daemon/recording-intent-fallback.ts +0 -162
  680. package/src/daemon/recording-intent.ts +0 -493
  681. package/src/home-base/app-link-store.ts +0 -78
  682. package/src/home-base/bootstrap.ts +0 -74
  683. package/src/home-base/prebuilt/brain-graph.html +0 -1483
  684. package/src/home-base/prebuilt/index.html +0 -702
  685. package/src/home-base/prebuilt/seed-metadata.json +0 -21
  686. package/src/home-base/prebuilt/seed.ts +0 -122
  687. package/src/home-base/prebuilt-home-base-updater.ts +0 -36
  688. package/src/memory/account-store.ts +0 -117
  689. package/src/messaging/activity-analyzer.ts +0 -76
  690. package/src/messaging/email-classifier.ts +0 -208
  691. package/src/messaging/index.ts +0 -2
  692. package/src/messaging/outreach-classifier.ts +0 -185
  693. package/src/messaging/thread-summarizer.ts +0 -346
  694. package/src/messaging/types.ts +0 -17
  695. package/src/tools/browser/x-auto-navigate.ts +0 -254
  696. package/src/tools/credentials/account-registry.ts +0 -144
  697. package/src/tools/filesystem/view-image.ts +0 -244
  698. package/src/tools/reminder/reminder-store.ts +0 -194
  699. package/src/tools/reminder/reminder.ts +0 -158
  700. package/src/tools/system/navigate-settings.ts +0 -74
  701. package/src/tools/system/open-system-settings.ts +0 -85
  702. package/src/tools/system/version.ts +0 -54
  703. package/src/twitter/platform-proxy-client.ts +0 -405
  704. package/src/util/cookie-session.ts +0 -98
  705. /package/src/config/bundled-skills/{messaging → gmail}/tools/scan-result-store.ts +0 -0
  706. /package/src/config/bundled-skills/{messaging → sequences}/tools/sequence-analytics.ts +0 -0
  707. /package/src/config/bundled-skills/{messaging → sequences}/tools/sequence-create.ts +0 -0
  708. /package/src/config/bundled-skills/{messaging → sequences}/tools/sequence-delete.ts +0 -0
  709. /package/src/config/bundled-skills/{messaging → sequences}/tools/sequence-enroll.ts +0 -0
  710. /package/src/config/bundled-skills/{messaging → sequences}/tools/sequence-enrollment-list.ts +0 -0
  711. /package/src/config/bundled-skills/{messaging → sequences}/tools/sequence-get.ts +0 -0
  712. /package/src/config/bundled-skills/{messaging → sequences}/tools/sequence-import.ts +0 -0
  713. /package/src/config/bundled-skills/{messaging → sequences}/tools/sequence-list.ts +0 -0
@@ -6,6 +6,20 @@ import { getLogger } from "../util/logger.js";
6
6
  import { GeminiEmbeddingBackend } from "./embedding-gemini.js";
7
7
  import { OllamaEmbeddingBackend } from "./embedding-ollama.js";
8
8
  import { OpenAIEmbeddingBackend } from "./embedding-openai.js";
9
+ import {
10
+ type EmbeddingInput,
11
+ embeddingInputContentHash,
12
+ type MultimodalEmbeddingInput,
13
+ normalizeEmbeddingInput,
14
+ type TextEmbeddingInput,
15
+ } from "./embedding-types.js";
16
+
17
+ export type {
18
+ EmbeddingInput,
19
+ MultimodalEmbeddingInput,
20
+ TextEmbeddingInput,
21
+ };
22
+ export { embeddingInputContentHash, normalizeEmbeddingInput };
9
23
 
10
24
  const log = getLogger("memory-embeddings");
11
25
 
@@ -34,12 +48,12 @@ class LazyLocalEmbeddingBackend implements EmbeddingBackend {
34
48
  }
35
49
 
36
50
  async embed(
37
- texts: string[],
51
+ inputs: EmbeddingInput[],
38
52
  options?: EmbeddingRequestOptions,
39
53
  ): Promise<number[][]> {
40
54
  const backend = await this.getDelegate();
41
55
  try {
42
- return await backend.embed(texts, options);
56
+ return await backend.embed(inputs, options);
43
57
  } catch (err) {
44
58
  // The onnxruntime-node failure surfaces here during the first embed() call
45
59
  // (via LocalEmbeddingBackend.initialize()). Mark broken so auto mode stops
@@ -103,18 +117,26 @@ function estimateEntryBytes(key: string, vector: number[]): number {
103
117
  return key.length * 2 + vector.length * 8;
104
118
  }
105
119
 
106
- function vectorCacheKey(provider: string, model: string, text: string): string {
120
+ function vectorCacheKey(
121
+ provider: string,
122
+ model: string,
123
+ input: EmbeddingInput,
124
+ extras?: string[],
125
+ ): string {
126
+ const contentHash = embeddingInputContentHash(input);
127
+ const suffix = extras && extras.length > 0 ? `\0${extras.join("\0")}` : "";
107
128
  return createHash("sha256")
108
- .update(`${provider}\0${model}\0${text}`)
129
+ .update(`${provider}\0${model}\0${contentHash}${suffix}`)
109
130
  .digest("hex");
110
131
  }
111
132
 
112
133
  function getFromVectorCache(
113
134
  provider: string,
114
135
  model: string,
115
- text: string,
136
+ input: EmbeddingInput,
137
+ extras?: string[],
116
138
  ): number[] | undefined {
117
- const key = vectorCacheKey(provider, model, text);
139
+ const key = vectorCacheKey(provider, model, input, extras);
118
140
  const v = vectorCache.get(key);
119
141
  if (v !== undefined) {
120
142
  // LRU refresh: move to end of insertion order
@@ -127,10 +149,11 @@ function getFromVectorCache(
127
149
  function putInVectorCache(
128
150
  provider: string,
129
151
  model: string,
130
- text: string,
152
+ input: EmbeddingInput,
131
153
  vector: number[],
154
+ extras?: string[],
132
155
  ): void {
133
- const key = vectorCacheKey(provider, model, text);
156
+ const key = vectorCacheKey(provider, model, input, extras);
134
157
  // If replacing an existing entry, subtract its old cost first
135
158
  const existing = vectorCache.get(key);
136
159
  if (existing !== undefined) {
@@ -161,7 +184,10 @@ export function clearEmbeddingBackendCache(): void {
161
184
  localBackendBroken = false;
162
185
  }
163
186
 
164
- function cacheKey(provider: string, model: string): string {
187
+ function cacheKey(provider: string, model: string, extras?: string[]): string {
188
+ if (extras && extras.length > 0) {
189
+ return `${provider}:${model}:${extras.join(":")}`;
190
+ }
165
191
  return `${provider}:${model}`;
166
192
  }
167
193
 
@@ -169,8 +195,9 @@ function getCachedOrCreate<T extends EmbeddingBackend>(
169
195
  provider: string,
170
196
  model: string,
171
197
  create: () => T,
198
+ extras?: string[],
172
199
  ): T {
173
- const key = cacheKey(provider, model);
200
+ const key = cacheKey(provider, model, extras);
174
201
  const existing = backendCache.get(key);
175
202
  if (existing) return existing as T;
176
203
  const instance = create();
@@ -178,6 +205,17 @@ function getCachedOrCreate<T extends EmbeddingBackend>(
178
205
  return instance;
179
206
  }
180
207
 
208
+ function geminiCacheExtras(config: AssistantConfig): string[] {
209
+ const extras: string[] = [];
210
+ if (config.memory.embeddings.geminiTaskType) {
211
+ extras.push(`task=${config.memory.embeddings.geminiTaskType}`);
212
+ }
213
+ if (config.memory.embeddings.geminiDimensions != null) {
214
+ extras.push(`dim=${config.memory.embeddings.geminiDimensions}`);
215
+ }
216
+ return extras;
217
+ }
218
+
181
219
  export type EmbeddingProviderName = "local" | "openai" | "gemini" | "ollama";
182
220
 
183
221
  export interface EmbeddingRequestOptions {
@@ -188,7 +226,7 @@ export interface EmbeddingBackend {
188
226
  readonly provider: EmbeddingProviderName;
189
227
  readonly model: string;
190
228
  embed(
191
- texts: string[],
229
+ inputs: EmbeddingInput[],
192
230
  options?: EmbeddingRequestOptions,
193
231
  ): Promise<number[][]>;
194
232
  }
@@ -272,7 +310,12 @@ export function selectEmbeddingBackend(
272
310
  new GeminiEmbeddingBackend(
273
311
  config.apiKeys.gemini,
274
312
  config.memory.embeddings.geminiModel,
313
+ {
314
+ taskType: config.memory.embeddings.geminiTaskType,
315
+ dimensions: config.memory.embeddings.geminiDimensions,
316
+ },
275
317
  ),
318
+ geminiCacheExtras(config),
276
319
  ),
277
320
  reason: null,
278
321
  };
@@ -336,7 +379,7 @@ export function getMemoryBackendStatus(config: AssistantConfig): {
336
379
 
337
380
  export async function embedWithBackend(
338
381
  config: AssistantConfig,
339
- texts: string[],
382
+ inputs: EmbeddingInput[],
340
383
  options?: EmbeddingRequestOptions,
341
384
  ): Promise<{
342
385
  provider: EmbeddingProviderName;
@@ -354,15 +397,22 @@ export async function embedWithBackend(
354
397
  const { provider: primaryProvider, model: primaryModel } = selection.backend;
355
398
 
356
399
  // ── Build fallback backends list (needed for embed fallback) ──
400
+ // In auto mode, build a fallback chain from all configured backends
401
+ // (excluding the primary). This lets multimodal inputs fall through
402
+ // to Gemini even when the primary is local or openai.
357
403
  const fallbacks: EmbeddingBackend[] =
358
404
  config.memory.embeddings.provider === "auto" &&
359
- selection.backend.provider === "local"
360
- ? selectFallbackBackends(config, "local")
405
+ selection.backend.provider !== "gemini"
406
+ ? selectFallbackBackends(config, selection.backend.provider)
361
407
  : [];
362
408
 
409
+ // ── Compute provider-specific vector cache extras ───────────────
410
+ const vectorExtras =
411
+ primaryProvider === "gemini" ? geminiCacheExtras(config) : undefined;
412
+
363
413
  // ── In-memory cache check (primary provider only) ──────────────
364
- const cached: (number[] | null)[] = texts.map((t) => {
365
- const v = getFromVectorCache(primaryProvider, primaryModel, t);
414
+ const cached: (number[] | null)[] = inputs.map((input) => {
415
+ const v = getFromVectorCache(primaryProvider, primaryModel, input, vectorExtras);
366
416
  if (v && v.length === expectedDim) return v;
367
417
  return null;
368
418
  });
@@ -378,23 +428,33 @@ export async function embedWithBackend(
378
428
  };
379
429
  }
380
430
 
381
- // ── Embed uncached texts ────────────────────────────────────────
431
+ // ── Embed uncached inputs ───────────────────────────────────────
382
432
  const backends: EmbeddingBackend[] = [selection.backend, ...fallbacks];
383
433
 
384
434
  let lastErr: unknown;
435
+ let anyBackendAttempted = false;
385
436
  for (const backend of backends) {
386
437
  const isPrimary = backend === selection.backend;
387
- // For the primary backend, only embed uncached texts and merge with cached.
388
- // For fallback backends, embed ALL texts since the cache was keyed to the primary.
389
- const textsToEmbed = isPrimary
390
- ? uncachedIndices.map((i) => texts[i])
391
- : texts;
438
+ // For the primary backend, only embed uncached inputs and merge with cached.
439
+ // For fallback backends, embed ALL inputs since the cache was keyed to the primary.
440
+ const inputsToEmbed = isPrimary
441
+ ? uncachedIndices.map((i) => inputs[i])
442
+ : inputs;
443
+
444
+ // Skip text-only backends for multimodal inputs
445
+ const hasNonText = inputsToEmbed.some(
446
+ (i) => typeof i !== "string" && normalizeEmbeddingInput(i).type !== "text",
447
+ );
448
+ if (backend.provider !== "gemini" && hasNonText) {
449
+ continue;
450
+ }
392
451
 
393
452
  try {
394
- const vectors = await backend.embed(textsToEmbed, options);
395
- if (vectors.length !== textsToEmbed.length) {
453
+ anyBackendAttempted = true;
454
+ const vectors = await backend.embed(inputsToEmbed, options);
455
+ if (vectors.length !== inputsToEmbed.length) {
396
456
  throw new Error(
397
- `Embedding backend returned ${vectors.length} vectors for ${textsToEmbed.length} texts`,
457
+ `Embedding backend returned ${vectors.length} vectors for ${inputsToEmbed.length} inputs`,
398
458
  );
399
459
  }
400
460
  for (const vec of vectors) {
@@ -406,12 +466,15 @@ export async function embedWithBackend(
406
466
  }
407
467
 
408
468
  // Populate cache with freshly embedded vectors
409
- for (let i = 0; i < textsToEmbed.length; i++) {
469
+ const backendExtras =
470
+ backend.provider === "gemini" ? geminiCacheExtras(config) : undefined;
471
+ for (let i = 0; i < inputsToEmbed.length; i++) {
410
472
  putInVectorCache(
411
473
  backend.provider,
412
474
  backend.model,
413
- textsToEmbed[i],
475
+ inputsToEmbed[i],
414
476
  vectors[i],
477
+ backendExtras,
415
478
  );
416
479
  }
417
480
 
@@ -437,6 +500,16 @@ export async function embedWithBackend(
437
500
  }
438
501
  }
439
502
  }
503
+ if (!anyBackendAttempted) {
504
+ const hasMultimodal = inputs.some(
505
+ (i) => typeof i !== "string" && normalizeEmbeddingInput(i).type !== "text",
506
+ );
507
+ if (hasMultimodal) {
508
+ throw new Error(
509
+ "No available embedding backend supports multimodal inputs. Gemini API key is required for image/audio/video embeddings.",
510
+ );
511
+ }
512
+ }
440
513
  throw lastErr;
441
514
  }
442
515
 
@@ -478,7 +551,12 @@ function selectFallbackBackends(
478
551
  new GeminiEmbeddingBackend(
479
552
  config.apiKeys.gemini,
480
553
  config.memory.embeddings.geminiModel,
554
+ {
555
+ taskType: config.memory.embeddings.geminiTaskType,
556
+ dimensions: config.memory.embeddings.geminiDimensions,
557
+ },
481
558
  ),
559
+ geminiCacheExtras(config),
482
560
  ),
483
561
  );
484
562
  }
@@ -505,6 +583,30 @@ function selectFallbackBackends(
505
583
  return backends;
506
584
  }
507
585
 
586
+ /**
587
+ * Returns true when the embedding pipeline can handle multimodal inputs
588
+ * (images, audio, video). Today only Gemini supports multimodal.
589
+ *
590
+ * In auto mode, the primary backend is usually local or OpenAI, but
591
+ * embedWithBackend builds a fallback chain that includes Gemini when
592
+ * available. We check both the primary and fallback backends so that
593
+ * multimodal jobs are still enqueued when Gemini is reachable via fallback.
594
+ */
595
+ export function selectedBackendSupportsMultimodal(
596
+ config: AssistantConfig,
597
+ ): boolean {
598
+ const { backend } = selectEmbeddingBackend(config);
599
+ if (!backend) return false;
600
+ if (backend.provider === "gemini") return true;
601
+
602
+ // In auto mode, check if Gemini is available as a fallback backend.
603
+ if (config.memory.embeddings.provider === "auto") {
604
+ const fallbacks = selectFallbackBackends(config, backend.provider);
605
+ return fallbacks.some((fb) => fb.provider === "gemini");
606
+ }
607
+ return false;
608
+ }
609
+
508
610
  function isOllamaConfigured(config: AssistantConfig): boolean {
509
611
  return (
510
612
  config.provider === "ollama" ||
@@ -0,0 +1,256 @@
1
+ import { afterEach, beforeEach, describe, expect, mock, test } from "bun:test";
2
+
3
+ import { GeminiEmbeddingBackend } from "./embedding-gemini.js";
4
+
5
+ function makeSuccessResponse(values: number[]) {
6
+ return new Response(JSON.stringify({ embedding: { values } }), {
7
+ status: 200,
8
+ headers: { "Content-Type": "application/json" },
9
+ });
10
+ }
11
+
12
+ describe("GeminiEmbeddingBackend", () => {
13
+ const originalFetch = globalThis.fetch;
14
+ let mockFetch: ReturnType<typeof mock>;
15
+
16
+ beforeEach(() => {
17
+ mockFetch = mock(() => Promise.resolve(makeSuccessResponse([0.1, 0.2, 0.3])));
18
+ globalThis.fetch = mockFetch as unknown as typeof fetch;
19
+ });
20
+
21
+ afterEach(() => {
22
+ globalThis.fetch = originalFetch;
23
+ });
24
+
25
+ describe("text inputs", () => {
26
+ test("sends text as parts: [{ text }]", async () => {
27
+ const backend = new GeminiEmbeddingBackend("test-key", "test-model");
28
+ await backend.embed(["hello world"]);
29
+
30
+ expect(mockFetch).toHaveBeenCalledTimes(1);
31
+ const [url, init] = mockFetch.mock.calls[0] as [string, RequestInit];
32
+ expect(url).toContain("models/test-model:embedContent");
33
+ expect(url).toContain("key=test-key");
34
+
35
+ const body = JSON.parse(init.body as string);
36
+ expect(body.model).toBe("models/test-model");
37
+ expect(body.content).toEqual({ parts: [{ text: "hello world" }] });
38
+ });
39
+
40
+ test("handles TextEmbeddingInput objects", async () => {
41
+ const backend = new GeminiEmbeddingBackend("test-key", "test-model");
42
+ await backend.embed([{ type: "text", text: "structured text" }]);
43
+
44
+ const [, init] = mockFetch.mock.calls[0] as [string, RequestInit];
45
+ const body = JSON.parse(init.body as string);
46
+ expect(body.content).toEqual({ parts: [{ text: "structured text" }] });
47
+ });
48
+ });
49
+
50
+ describe("image inputs", () => {
51
+ test("sends image as inline_data with base64", async () => {
52
+ const imageData = Buffer.from("fake-png-data");
53
+ const backend = new GeminiEmbeddingBackend("test-key", "test-model");
54
+ await backend.embed([
55
+ { type: "image", data: imageData, mimeType: "image/png" },
56
+ ]);
57
+
58
+ expect(mockFetch).toHaveBeenCalledTimes(1);
59
+ const [, init] = mockFetch.mock.calls[0] as [string, RequestInit];
60
+ const body = JSON.parse(init.body as string);
61
+ expect(body.content).toEqual({
62
+ parts: [
63
+ {
64
+ inline_data: {
65
+ mime_type: "image/png",
66
+ data: imageData.toString("base64"),
67
+ },
68
+ },
69
+ ],
70
+ });
71
+ });
72
+ });
73
+
74
+ describe("audio inputs", () => {
75
+ test("sends audio as inline_data with base64", async () => {
76
+ const audioData = Buffer.from("fake-audio-data");
77
+ const backend = new GeminiEmbeddingBackend("test-key", "test-model");
78
+ await backend.embed([
79
+ { type: "audio", data: audioData, mimeType: "audio/mp3" },
80
+ ]);
81
+
82
+ const [, init] = mockFetch.mock.calls[0] as [string, RequestInit];
83
+ const body = JSON.parse(init.body as string);
84
+ expect(body.content).toEqual({
85
+ parts: [
86
+ {
87
+ inline_data: {
88
+ mime_type: "audio/mp3",
89
+ data: audioData.toString("base64"),
90
+ },
91
+ },
92
+ ],
93
+ });
94
+ });
95
+ });
96
+
97
+ describe("video inputs", () => {
98
+ test("sends video as inline_data with base64", async () => {
99
+ const videoData = Buffer.from("fake-video-data");
100
+ const backend = new GeminiEmbeddingBackend("test-key", "test-model");
101
+ await backend.embed([
102
+ { type: "video", data: videoData, mimeType: "video/mp4" },
103
+ ]);
104
+
105
+ const [, init] = mockFetch.mock.calls[0] as [string, RequestInit];
106
+ const body = JSON.parse(init.body as string);
107
+ expect(body.content).toEqual({
108
+ parts: [
109
+ {
110
+ inline_data: {
111
+ mime_type: "video/mp4",
112
+ data: videoData.toString("base64"),
113
+ },
114
+ },
115
+ ],
116
+ });
117
+ });
118
+ });
119
+
120
+ describe("taskType and outputDimensionality", () => {
121
+ test("includes taskType in request body when configured", async () => {
122
+ const backend = new GeminiEmbeddingBackend("test-key", "test-model", {
123
+ taskType: "RETRIEVAL_DOCUMENT",
124
+ });
125
+ await backend.embed(["hello"]);
126
+
127
+ const [, init] = mockFetch.mock.calls[0] as [string, RequestInit];
128
+ const body = JSON.parse(init.body as string);
129
+ expect(body.taskType).toBe("RETRIEVAL_DOCUMENT");
130
+ });
131
+
132
+ test("includes outputDimensionality in request body when dimensions configured", async () => {
133
+ const backend = new GeminiEmbeddingBackend("test-key", "test-model", {
134
+ dimensions: 256,
135
+ });
136
+ await backend.embed(["hello"]);
137
+
138
+ const [, init] = mockFetch.mock.calls[0] as [string, RequestInit];
139
+ const body = JSON.parse(init.body as string);
140
+ expect(body.outputDimensionality).toBe(256);
141
+ });
142
+
143
+ test("includes both taskType and outputDimensionality when both configured", async () => {
144
+ const backend = new GeminiEmbeddingBackend("test-key", "test-model", {
145
+ taskType: "SEMANTIC_SIMILARITY",
146
+ dimensions: 512,
147
+ });
148
+ await backend.embed(["hello"]);
149
+
150
+ const [, init] = mockFetch.mock.calls[0] as [string, RequestInit];
151
+ const body = JSON.parse(init.body as string);
152
+ expect(body.taskType).toBe("SEMANTIC_SIMILARITY");
153
+ expect(body.outputDimensionality).toBe(512);
154
+ });
155
+
156
+ test("omits taskType when not configured", async () => {
157
+ const backend = new GeminiEmbeddingBackend("test-key", "test-model");
158
+ await backend.embed(["hello"]);
159
+
160
+ const [, init] = mockFetch.mock.calls[0] as [string, RequestInit];
161
+ const body = JSON.parse(init.body as string);
162
+ expect(body.taskType).toBeUndefined();
163
+ });
164
+
165
+ test("omits outputDimensionality when not configured", async () => {
166
+ const backend = new GeminiEmbeddingBackend("test-key", "test-model");
167
+ await backend.embed(["hello"]);
168
+
169
+ const [, init] = mockFetch.mock.calls[0] as [string, RequestInit];
170
+ const body = JSON.parse(init.body as string);
171
+ expect(body.outputDimensionality).toBeUndefined();
172
+ });
173
+
174
+ test("omits both when options is undefined", async () => {
175
+ const backend = new GeminiEmbeddingBackend("test-key", "test-model");
176
+ await backend.embed(["hello"]);
177
+
178
+ const [, init] = mockFetch.mock.calls[0] as [string, RequestInit];
179
+ const body = JSON.parse(init.body as string);
180
+ expect(body.taskType).toBeUndefined();
181
+ expect(body.outputDimensionality).toBeUndefined();
182
+ expect(Object.keys(body)).toEqual(["model", "content"]);
183
+ });
184
+ });
185
+
186
+ describe("error handling", () => {
187
+ test("throws on non-OK response", async () => {
188
+ mockFetch = mock(() =>
189
+ Promise.resolve(
190
+ new Response("Internal Server Error", { status: 500 }),
191
+ ),
192
+ );
193
+ globalThis.fetch = mockFetch as unknown as typeof fetch;
194
+
195
+ const backend = new GeminiEmbeddingBackend("test-key", "test-model");
196
+ await expect(backend.embed(["hello"])).rejects.toThrow(
197
+ "Gemini embeddings request failed (500): Internal Server Error",
198
+ );
199
+ });
200
+
201
+ test("throws when response is missing embedding values", async () => {
202
+ mockFetch = mock(() =>
203
+ Promise.resolve(
204
+ new Response(JSON.stringify({}), {
205
+ status: 200,
206
+ headers: { "Content-Type": "application/json" },
207
+ }),
208
+ ),
209
+ );
210
+ globalThis.fetch = mockFetch as unknown as typeof fetch;
211
+
212
+ const backend = new GeminiEmbeddingBackend("test-key", "test-model");
213
+ await expect(backend.embed(["hello"])).rejects.toThrow(
214
+ "Gemini embeddings response missing vector values",
215
+ );
216
+ });
217
+
218
+ test("throws when embedding values array is empty", async () => {
219
+ mockFetch = mock(() =>
220
+ Promise.resolve(
221
+ new Response(JSON.stringify({ embedding: { values: [] } }), {
222
+ status: 200,
223
+ headers: { "Content-Type": "application/json" },
224
+ }),
225
+ ),
226
+ );
227
+ globalThis.fetch = mockFetch as unknown as typeof fetch;
228
+
229
+ const backend = new GeminiEmbeddingBackend("test-key", "test-model");
230
+ await expect(backend.embed(["hello"])).rejects.toThrow(
231
+ "Gemini embeddings response missing vector values",
232
+ );
233
+ });
234
+ });
235
+
236
+ describe("multiple inputs", () => {
237
+ test("embeds multiple inputs sequentially", async () => {
238
+ let callCount = 0;
239
+ mockFetch = mock(() => {
240
+ callCount++;
241
+ return Promise.resolve(
242
+ makeSuccessResponse([0.1 * callCount, 0.2 * callCount]),
243
+ );
244
+ });
245
+ globalThis.fetch = mockFetch as unknown as typeof fetch;
246
+
247
+ const backend = new GeminiEmbeddingBackend("test-key", "test-model");
248
+ const result = await backend.embed(["hello", "world"]);
249
+
250
+ expect(mockFetch).toHaveBeenCalledTimes(2);
251
+ expect(result).toHaveLength(2);
252
+ expect(result[0]).toEqual([0.1, 0.2]);
253
+ expect(result[1]).toEqual([0.2, 0.4]);
254
+ });
255
+ });
256
+ });
@@ -1,7 +1,13 @@
1
1
  import type {
2
2
  EmbeddingBackend,
3
+ EmbeddingInput,
3
4
  EmbeddingRequestOptions,
4
5
  } from "./embedding-backend.js";
6
+ import type {
7
+ EmbeddingTaskType,
8
+ MultimodalEmbeddingInput,
9
+ } from "./embedding-types.js";
10
+ import { normalizeEmbeddingInput } from "./embedding-types.js";
5
11
 
6
12
  interface GeminiEmbedResponse {
7
13
  embedding?: {
@@ -13,46 +19,59 @@ export class GeminiEmbeddingBackend implements EmbeddingBackend {
13
19
  readonly provider = "gemini" as const;
14
20
  readonly model: string;
15
21
  private readonly apiKey: string;
22
+ private readonly taskType?: EmbeddingTaskType;
23
+ private readonly dimensions?: number;
16
24
 
17
- constructor(apiKey: string, model: string) {
25
+ constructor(
26
+ apiKey: string,
27
+ model: string,
28
+ options?: { taskType?: EmbeddingTaskType; dimensions?: number },
29
+ ) {
18
30
  this.apiKey = apiKey;
19
31
  this.model = model;
32
+ this.taskType = options?.taskType;
33
+ this.dimensions = options?.dimensions;
20
34
  }
21
35
 
22
36
  async embed(
23
- texts: string[],
37
+ inputs: EmbeddingInput[],
24
38
  options?: EmbeddingRequestOptions,
25
39
  ): Promise<number[][]> {
26
40
  const vectors: number[][] = [];
27
- for (const text of texts) {
28
- const values = await this.embedSingle(text, options);
41
+ for (const input of inputs) {
42
+ const values = await this.embedSingle(input, options);
29
43
  vectors.push(values);
30
44
  }
31
45
  return vectors;
32
46
  }
33
47
 
34
48
  private async embedSingle(
35
- text: string,
49
+ input: EmbeddingInput,
36
50
  options?: EmbeddingRequestOptions,
37
51
  ): Promise<number[]> {
52
+ const normalized = normalizeEmbeddingInput(input);
53
+ const parts = this.buildParts(normalized);
54
+
55
+ const body: Record<string, unknown> = {
56
+ model: `models/${this.model}`,
57
+ content: { parts },
58
+ };
59
+ if (this.taskType) body.taskType = this.taskType;
60
+ if (this.dimensions) body.outputDimensionality = this.dimensions;
61
+
38
62
  const url = `https://generativelanguage.googleapis.com/v1beta/models/${encodeURIComponent(
39
63
  this.model,
40
64
  )}:embedContent?key=${encodeURIComponent(this.apiKey)}`;
41
65
  const response = await fetch(url, {
42
66
  method: "POST",
43
67
  headers: { "Content-Type": "application/json" },
44
- body: JSON.stringify({
45
- model: `models/${this.model}`,
46
- content: {
47
- parts: [{ text }],
48
- },
49
- }),
68
+ body: JSON.stringify(body),
50
69
  signal: options?.signal,
51
70
  });
52
71
  if (!response.ok) {
53
- const body = await response.text();
72
+ const responseBody = await response.text();
54
73
  throw new Error(
55
- `Gemini embeddings request failed (${response.status}): ${body}`,
74
+ `Gemini embeddings request failed (${response.status}): ${responseBody}`,
56
75
  );
57
76
  }
58
77
  const payload = (await response.json()) as GeminiEmbedResponse;
@@ -62,4 +81,19 @@ export class GeminiEmbeddingBackend implements EmbeddingBackend {
62
81
  }
63
82
  return values;
64
83
  }
84
+
85
+ private buildParts(input: MultimodalEmbeddingInput): unknown[] {
86
+ if (input.type === "text") {
87
+ return [{ text: input.text }];
88
+ }
89
+ // Image, audio, video: use inline_data with base64
90
+ return [
91
+ {
92
+ inline_data: {
93
+ mime_type: input.mimeType,
94
+ data: input.data.toString("base64"),
95
+ },
96
+ },
97
+ ];
98
+ }
65
99
  }
@@ -6,9 +6,11 @@ import { getEmbeddingModelsDir, getRootDir } from "../util/platform.js";
6
6
  import { PromiseGuard } from "../util/promise-guard.js";
7
7
  import type {
8
8
  EmbeddingBackend,
9
+ EmbeddingInput,
9
10
  EmbeddingRequestOptions,
10
11
  } from "./embedding-backend.js";
11
12
  import { EmbeddingRuntimeManager } from "./embedding-runtime-manager.js";
13
+ import { normalizeEmbeddingInput } from "./embedding-types.js";
12
14
 
13
15
  const log = getLogger("memory-embedding-local");
14
16
 
@@ -56,10 +58,20 @@ export class LocalEmbeddingBackend implements EmbeddingBackend {
56
58
  }
57
59
 
58
60
  async embed(
59
- texts: string[],
61
+ inputs: EmbeddingInput[],
60
62
  options?: EmbeddingRequestOptions,
61
63
  ): Promise<number[][]> {
62
- if (texts.length === 0) return [];
64
+ if (inputs.length === 0) return [];
65
+
66
+ const texts = inputs.map((i) => {
67
+ const n = normalizeEmbeddingInput(i);
68
+ if (n.type !== "text") {
69
+ throw new Error(
70
+ "Local embedding backend only supports text inputs",
71
+ );
72
+ }
73
+ return n.text;
74
+ });
63
75
  if (options?.signal?.aborted)
64
76
  throw new DOMException("Aborted", "AbortError");
65
77