@vellumai/assistant 0.4.48 → 0.4.50

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 (423) hide show
  1. package/ARCHITECTURE.md +26 -35
  2. package/README.md +5 -26
  3. package/docs/architecture/integrations.md +45 -41
  4. package/docs/architecture/keychain-broker.md +3 -3
  5. package/docs/architecture/memory.md +180 -119
  6. package/docs/runbook-trusted-contacts.md +3 -8
  7. package/hook-templates/debug-prompt-logger/hook.json +1 -1
  8. package/hook-templates/debug-prompt-logger/run.sh +1 -3
  9. package/package.json +2 -2
  10. package/src/__tests__/actor-token-service.test.ts +0 -1
  11. package/src/__tests__/agent-loop.test.ts +3 -1
  12. package/src/__tests__/anthropic-provider.test.ts +249 -2
  13. package/src/__tests__/approval-cascade.test.ts +796 -0
  14. package/src/__tests__/approval-primitive.test.ts +0 -1
  15. package/src/__tests__/approval-routes-http.test.ts +4 -0
  16. package/src/__tests__/assistant-attachments.test.ts +12 -34
  17. package/src/__tests__/assistant-feature-flag-guard.test.ts +0 -23
  18. package/src/__tests__/assistant-feature-flag-guardrails.test.ts +76 -0
  19. package/src/__tests__/assistant-feature-flags-integration.test.ts +0 -1
  20. package/src/__tests__/browser-skill-baseline-tool-payload.test.ts +2 -2
  21. package/src/__tests__/canonical-guardian-store.test.ts +95 -0
  22. package/src/__tests__/channel-guardian.test.ts +0 -2
  23. package/src/__tests__/channel-readiness-routes.test.ts +15 -6
  24. package/src/__tests__/channel-readiness-service.test.ts +10 -9
  25. package/src/__tests__/checker.test.ts +13 -20
  26. package/src/__tests__/computer-use-skill-manifest-regression.test.ts +1 -1
  27. package/src/__tests__/computer-use-tools.test.ts +2 -19
  28. package/src/__tests__/config-schema.test.ts +1 -68
  29. package/src/__tests__/config-watcher.test.ts +0 -1
  30. package/src/__tests__/confirmation-request-guardian-bridge.test.ts +0 -1
  31. package/src/__tests__/context-image-dimensions.test.ts +332 -0
  32. package/src/__tests__/context-memory-e2e.test.ts +11 -100
  33. package/src/__tests__/context-token-estimator.test.ts +196 -13
  34. package/src/__tests__/conversation-attention-store.test.ts +0 -1
  35. package/src/__tests__/conversation-attention-telegram.test.ts +0 -1
  36. package/src/__tests__/conversation-routes-guardian-reply.test.ts +152 -0
  37. package/src/__tests__/conversation-routes-slash-commands.test.ts +2 -0
  38. package/src/__tests__/credential-metadata-store.test.ts +64 -73
  39. package/src/__tests__/credential-security-e2e.test.ts +1 -0
  40. package/src/__tests__/credential-security-invariants.test.ts +13 -7
  41. package/src/__tests__/credential-vault-unit.test.ts +284 -49
  42. package/src/__tests__/credential-vault.test.ts +150 -16
  43. package/src/__tests__/credentials-cli.test.ts +71 -0
  44. package/src/__tests__/cu-unified-flow.test.ts +532 -0
  45. package/src/__tests__/date-context.test.ts +93 -77
  46. package/src/__tests__/deterministic-verification-control-plane.test.ts +64 -0
  47. package/src/__tests__/dynamic-skill-workflow-prompt.test.ts +0 -1
  48. package/src/__tests__/ephemeral-permissions.test.ts +3 -3
  49. package/src/__tests__/gateway-only-guard.test.ts +0 -1
  50. package/src/__tests__/guardian-action-grant-mint-consume.test.ts +0 -1
  51. package/src/__tests__/guardian-decision-primitive-canonical.test.ts +0 -1
  52. package/src/__tests__/guardian-routing-invariants.test.ts +93 -1
  53. package/src/__tests__/guardian-verification-voice-binding.test.ts +0 -1
  54. package/src/__tests__/handlers-user-message-approval-consumption.test.ts +0 -39
  55. package/src/__tests__/heartbeat-service.test.ts +0 -1
  56. package/src/__tests__/history-repair.test.ts +245 -0
  57. package/src/__tests__/host-cu-proxy.test.ts +791 -0
  58. package/src/__tests__/host-shell-tool.test.ts +27 -15
  59. package/src/__tests__/http-user-message-parity.test.ts +2 -0
  60. package/src/__tests__/ingress-url-consistency.test.ts +14 -21
  61. package/src/__tests__/integration-status.test.ts +32 -51
  62. package/src/__tests__/intent-routing.test.ts +0 -1
  63. package/src/__tests__/invite-redemption-service.test.ts +65 -1
  64. package/src/__tests__/invite-routes-http.test.ts +10 -9
  65. package/src/__tests__/keychain-broker-client.test.ts +14 -46
  66. package/src/__tests__/memory-context-benchmark.benchmark.test.ts +56 -18
  67. package/src/__tests__/memory-lifecycle-e2e.test.ts +244 -387
  68. package/src/__tests__/memory-recall-quality.test.ts +244 -407
  69. package/src/__tests__/memory-regressions.experimental.test.ts +126 -101
  70. package/src/__tests__/memory-regressions.test.ts +477 -2841
  71. package/src/__tests__/memory-retrieval.benchmark.test.ts +33 -150
  72. package/src/__tests__/memory-upsert-concurrency.test.ts +5 -244
  73. package/src/__tests__/mime-builder.test.ts +28 -0
  74. package/src/__tests__/native-web-search.test.ts +1 -0
  75. package/src/__tests__/notification-routing-intent.test.ts +0 -1
  76. package/src/__tests__/oauth-cli.test.ts +941 -15
  77. package/src/__tests__/oauth-provider-profiles.test.ts +9 -9
  78. package/src/__tests__/oauth-scope-policy.test.ts +4 -6
  79. package/src/__tests__/oauth-store.test.ts +870 -0
  80. package/src/__tests__/onboarding-starter-tasks.test.ts +0 -1
  81. package/src/__tests__/provider-error-scenarios.test.ts +0 -1
  82. package/src/__tests__/provider-streaming.benchmark.test.ts +0 -1
  83. package/src/__tests__/public-ingress-urls.test.ts +15 -21
  84. package/src/__tests__/qdrant-collection-migration.test.ts +53 -8
  85. package/src/__tests__/recording-handler.test.ts +3 -4
  86. package/src/__tests__/registry.test.ts +2 -3
  87. package/src/__tests__/relay-server.test.ts +46 -1
  88. package/src/__tests__/runtime-events-sse.test.ts +55 -7
  89. package/src/__tests__/schedule-store.test.ts +0 -1
  90. package/src/__tests__/schedule-tools.test.ts +32 -0
  91. package/src/__tests__/scheduler-recurrence.test.ts +0 -1
  92. package/src/__tests__/scoped-approval-grants.test.ts +0 -1
  93. package/src/__tests__/scoped-grant-security-matrix.test.ts +0 -1
  94. package/src/__tests__/script-proxy-certs.test.ts +1 -1
  95. package/src/__tests__/secret-ingress-handler.test.ts +0 -1
  96. package/src/__tests__/secret-onetime-send.test.ts +1 -0
  97. package/src/__tests__/secure-keys.test.ts +7 -2
  98. package/src/__tests__/send-endpoint-busy.test.ts +24 -6
  99. package/src/__tests__/sequence-store.test.ts +0 -1
  100. package/src/__tests__/session-abort-tool-results.test.ts +1 -14
  101. package/src/__tests__/session-agent-loop-overflow.test.ts +1583 -0
  102. package/src/__tests__/session-agent-loop.test.ts +19 -15
  103. package/src/__tests__/session-confirmation-signals.test.ts +1 -15
  104. package/src/__tests__/session-error.test.ts +124 -2
  105. package/src/__tests__/session-history-web-search.test.ts +918 -0
  106. package/src/__tests__/session-init.benchmark.test.ts +4 -5
  107. package/src/__tests__/session-pre-run-repair.test.ts +1 -14
  108. package/src/__tests__/session-provider-retry-repair.test.ts +25 -28
  109. package/src/__tests__/session-queue.test.ts +37 -27
  110. package/src/__tests__/session-runtime-assembly.test.ts +54 -0
  111. package/src/__tests__/session-slash-known.test.ts +1 -15
  112. package/src/__tests__/session-slash-queue.test.ts +1 -15
  113. package/src/__tests__/session-slash-unknown.test.ts +1 -15
  114. package/src/__tests__/session-workspace-cache-state.test.ts +3 -33
  115. package/src/__tests__/session-workspace-injection.test.ts +3 -37
  116. package/src/__tests__/session-workspace-tool-tracking.test.ts +3 -37
  117. package/src/__tests__/skill-include-graph.test.ts +66 -0
  118. package/src/__tests__/skill-load-feature-flag.test.ts +0 -1
  119. package/src/__tests__/skill-load-tool.test.ts +149 -1
  120. package/src/__tests__/skill-projection-feature-flag.test.ts +0 -1
  121. package/src/__tests__/skills-install-extract.test.ts +93 -0
  122. package/src/__tests__/skills-uninstall.test.ts +1 -1
  123. package/src/__tests__/skills.test.ts +3 -3
  124. package/src/__tests__/skillssh-registry.test.ts +451 -0
  125. package/src/__tests__/slack-channel-config.test.ts +67 -3
  126. package/src/__tests__/slack-share-routes.test.ts +17 -19
  127. package/src/__tests__/system-prompt.test.ts +0 -1
  128. package/src/__tests__/telegram-invite-adapter.test.ts +18 -22
  129. package/src/__tests__/terminal-tools.test.ts +4 -3
  130. package/src/__tests__/test-support/computer-use-skill-harness.ts +3 -2
  131. package/src/__tests__/tool-approval-handler.test.ts +0 -1
  132. package/src/__tests__/tool-execution-pipeline.benchmark.test.ts +0 -1
  133. package/src/__tests__/tool-executor-lifecycle-events.test.ts +0 -1
  134. package/src/__tests__/tool-executor-shell-integration.test.ts +0 -1
  135. package/src/__tests__/tool-executor.test.ts +0 -1
  136. package/src/__tests__/tool-grant-request-escalation.test.ts +0 -1
  137. package/src/__tests__/trust-store-pattern-matches.test.ts +29 -0
  138. package/src/__tests__/trust-store.test.ts +7 -13
  139. package/src/__tests__/trusted-contact-approval-notifier.test.ts +0 -1
  140. package/src/__tests__/trusted-contact-inline-approval-integration.test.ts +0 -1
  141. package/src/__tests__/twilio-routes.test.ts +0 -16
  142. package/src/__tests__/verification-control-plane-policy.test.ts +0 -1
  143. package/src/__tests__/voice-invite-redemption.test.ts +32 -1
  144. package/src/__tests__/voice-scoped-grant-consumer.test.ts +0 -1
  145. package/src/agent/ax-tree-compaction.test.ts +286 -0
  146. package/src/agent/loop.ts +104 -131
  147. package/src/approvals/AGENTS.md +1 -1
  148. package/src/approvals/guardian-request-resolvers.ts +14 -2
  149. package/src/bundler/compiler-tools.ts +66 -2
  150. package/src/calls/call-domain.ts +133 -6
  151. package/src/calls/call-store.ts +6 -0
  152. package/src/calls/relay-server.ts +52 -18
  153. package/src/calls/relay-setup-router.ts +17 -1
  154. package/src/calls/twilio-config.ts +3 -8
  155. package/src/calls/twilio-routes.ts +1 -2
  156. package/src/calls/types.ts +3 -1
  157. package/src/calls/voice-ingress-preflight.ts +1 -1
  158. package/src/cli/commands/browser-relay.ts +18 -12
  159. package/src/cli/commands/completions.ts +0 -3
  160. package/src/cli/commands/credentials.ts +101 -15
  161. package/src/cli/commands/doctor.ts +4 -3
  162. package/src/cli/commands/mcp.ts +46 -59
  163. package/src/cli/commands/memory.ts +16 -165
  164. package/src/cli/commands/oauth/apps.ts +284 -0
  165. package/src/cli/commands/oauth/connections.ts +633 -0
  166. package/src/cli/commands/oauth/index.ts +52 -0
  167. package/src/cli/commands/oauth/providers.ts +256 -0
  168. package/src/cli/commands/sessions.ts +5 -2
  169. package/src/cli/commands/skills.ts +177 -339
  170. package/src/cli/http-client.ts +0 -20
  171. package/src/cli/main-screen.tsx +2 -2
  172. package/src/cli/program.ts +6 -11
  173. package/src/cli/reference.ts +1 -3
  174. package/src/cli.ts +4 -10
  175. package/src/config/assistant-feature-flags.ts +0 -3
  176. package/src/config/bundled-skills/_shared/CLI_RETRIEVAL_PATTERN.md +1 -1
  177. package/src/config/bundled-skills/computer-use/SKILL.md +3 -6
  178. package/src/config/bundled-skills/computer-use/TOOLS.json +23 -5
  179. package/src/config/bundled-skills/computer-use/tools/{computer-use-request-control.ts → computer-use-observe.ts} +1 -5
  180. package/src/config/bundled-skills/google-calendar/calendar-client.ts +21 -16
  181. package/src/config/bundled-skills/messaging/tools/shared.ts +1 -4
  182. package/src/config/bundled-skills/settings/SKILL.md +1 -1
  183. package/src/config/bundled-skills/settings/TOOLS.json +2 -8
  184. package/src/config/bundled-skills/settings/tools/voice-config-update.ts +5 -33
  185. package/src/config/bundled-tool-registry.ts +2 -5
  186. package/src/config/env-registry.ts +14 -83
  187. package/src/config/env.ts +11 -50
  188. package/src/config/feature-flag-registry.json +16 -16
  189. package/src/config/loader.ts +0 -6
  190. package/src/config/schema.ts +4 -13
  191. package/src/config/schemas/memory-lifecycle.ts +0 -9
  192. package/src/config/schemas/memory-processing.ts +0 -180
  193. package/src/config/schemas/memory-retrieval.ts +32 -104
  194. package/src/config/schemas/memory.ts +0 -10
  195. package/src/config/skills.ts +21 -2
  196. package/src/config/types.ts +0 -4
  197. package/src/context/image-dimensions.ts +229 -0
  198. package/src/context/token-estimator.ts +75 -12
  199. package/src/context/window-manager.ts +53 -11
  200. package/src/daemon/assistant-attachments.ts +1 -13
  201. package/src/daemon/config-watcher.ts +61 -3
  202. package/src/daemon/daemon-control.ts +1 -1
  203. package/src/daemon/date-context.ts +114 -31
  204. package/src/daemon/handlers/config-ingress.ts +8 -33
  205. package/src/daemon/handlers/config-slack-channel.ts +49 -46
  206. package/src/daemon/handlers/config-telegram.ts +32 -16
  207. package/src/daemon/handlers/sessions.ts +27 -36
  208. package/src/daemon/handlers/shared.ts +0 -130
  209. package/src/daemon/handlers/skills.ts +20 -1
  210. package/src/daemon/history-repair.ts +72 -8
  211. package/src/daemon/host-cu-proxy.ts +430 -0
  212. package/src/daemon/lifecycle.ts +67 -71
  213. package/src/daemon/mcp-reload-service.ts +2 -2
  214. package/src/daemon/message-protocol.ts +3 -0
  215. package/src/daemon/message-types/computer-use.ts +1 -129
  216. package/src/daemon/message-types/host-cu.ts +19 -0
  217. package/src/daemon/message-types/memory.ts +4 -16
  218. package/src/daemon/message-types/messages.ts +4 -0
  219. package/src/daemon/message-types/sessions.ts +4 -0
  220. package/src/daemon/server.ts +25 -21
  221. package/src/daemon/session-agent-loop-handlers.ts +40 -0
  222. package/src/daemon/session-agent-loop.ts +334 -48
  223. package/src/daemon/session-attachments.ts +1 -2
  224. package/src/daemon/session-error.ts +89 -6
  225. package/src/daemon/session-history.ts +17 -7
  226. package/src/daemon/session-media-retry.ts +6 -2
  227. package/src/daemon/session-memory.ts +69 -149
  228. package/src/daemon/session-process.ts +10 -1
  229. package/src/daemon/session-runtime-assembly.ts +49 -19
  230. package/src/daemon/session-slash.ts +1 -1
  231. package/src/daemon/session-surfaces.ts +43 -28
  232. package/src/daemon/session-tool-setup.ts +9 -10
  233. package/src/daemon/session.ts +150 -17
  234. package/src/daemon/tool-side-effects.ts +2 -8
  235. package/src/daemon/watch-handler.ts +2 -2
  236. package/src/events/tool-metrics-listener.ts +2 -2
  237. package/src/hooks/manager.ts +1 -4
  238. package/src/inbound/public-ingress-urls.ts +7 -7
  239. package/src/instrument.ts +61 -1
  240. package/src/logfire.ts +16 -5
  241. package/src/memory/admin.ts +2 -191
  242. package/src/memory/canonical-guardian-store.ts +38 -2
  243. package/src/memory/conversation-crud.ts +0 -33
  244. package/src/memory/conversation-key-store.ts +21 -0
  245. package/src/memory/conversation-queries.ts +22 -3
  246. package/src/memory/db-init.ts +32 -0
  247. package/src/memory/embedding-backend.ts +84 -8
  248. package/src/memory/embedding-types.ts +9 -1
  249. package/src/memory/indexer.ts +7 -46
  250. package/src/memory/items-extractor.ts +274 -76
  251. package/src/memory/job-handlers/backfill.ts +2 -127
  252. package/src/memory/job-handlers/cleanup.ts +2 -16
  253. package/src/memory/job-handlers/extraction.ts +2 -138
  254. package/src/memory/job-handlers/index-maintenance.ts +1 -6
  255. package/src/memory/job-handlers/summarization.ts +3 -148
  256. package/src/memory/job-utils.ts +21 -59
  257. package/src/memory/jobs-store.ts +1 -159
  258. package/src/memory/jobs-worker.ts +9 -52
  259. package/src/memory/migrations/104-core-indexes.ts +3 -3
  260. package/src/memory/migrations/149-oauth-tables.ts +62 -0
  261. package/src/memory/migrations/150-oauth-apps-client-secret-path.ts +98 -0
  262. package/src/memory/migrations/151-oauth-providers-ping-url.ts +11 -0
  263. package/src/memory/migrations/152-memory-item-supersession.ts +44 -0
  264. package/src/memory/migrations/153-drop-entity-tables.ts +15 -0
  265. package/src/memory/migrations/154-drop-fts.ts +20 -0
  266. package/src/memory/migrations/155-drop-conflicts.ts +7 -0
  267. package/src/memory/migrations/156-call-session-invite-metadata.ts +24 -0
  268. package/src/memory/migrations/index.ts +8 -0
  269. package/src/memory/qdrant-client.ts +148 -51
  270. package/src/memory/raw-query.ts +1 -1
  271. package/src/memory/retriever.test.ts +294 -273
  272. package/src/memory/retriever.ts +421 -645
  273. package/src/memory/schema/calls.ts +2 -0
  274. package/src/memory/schema/index.ts +1 -0
  275. package/src/memory/schema/memory-core.ts +3 -48
  276. package/src/memory/schema/oauth.ts +67 -0
  277. package/src/memory/search/formatting.ts +263 -176
  278. package/src/memory/search/lexical.ts +1 -254
  279. package/src/memory/search/ranking.ts +0 -455
  280. package/src/memory/search/semantic.ts +100 -14
  281. package/src/memory/search/staleness.ts +47 -0
  282. package/src/memory/search/tier-classifier.ts +21 -0
  283. package/src/memory/search/types.ts +15 -77
  284. package/src/memory/task-memory-cleanup.ts +4 -6
  285. package/src/messaging/provider.ts +4 -4
  286. package/src/messaging/providers/gmail/client.ts +82 -2
  287. package/src/messaging/providers/gmail/mime-builder.ts +17 -7
  288. package/src/messaging/providers/gmail/people-client.ts +10 -10
  289. package/src/messaging/providers/telegram-bot/adapter.ts +17 -17
  290. package/src/messaging/providers/whatsapp/adapter.ts +11 -8
  291. package/src/messaging/registry.ts +2 -32
  292. package/src/notifications/copy-composer.ts +0 -5
  293. package/src/notifications/signal.ts +4 -5
  294. package/src/oauth/byo-connection.test.ts +133 -25
  295. package/src/oauth/byo-connection.ts +22 -6
  296. package/src/oauth/connect-orchestrator.ts +113 -57
  297. package/src/oauth/connect-types.ts +17 -23
  298. package/src/oauth/connection-resolver.ts +35 -11
  299. package/src/oauth/connection.ts +1 -1
  300. package/src/oauth/manual-token-connection.ts +104 -0
  301. package/src/oauth/oauth-store.ts +582 -0
  302. package/src/oauth/platform-connection.test.ts +29 -0
  303. package/src/oauth/platform-connection.ts +6 -5
  304. package/src/oauth/provider-behaviors.ts +124 -0
  305. package/src/oauth/scope-policy.ts +9 -2
  306. package/src/oauth/seed-providers.ts +167 -0
  307. package/src/oauth/token-persistence.ts +81 -77
  308. package/src/permissions/checker.ts +3 -3
  309. package/src/permissions/defaults.ts +1 -1
  310. package/src/permissions/prompter.ts +10 -1
  311. package/src/permissions/trust-store.ts +36 -1
  312. package/src/playbooks/playbook-compiler.ts +1 -1
  313. package/src/prompts/__tests__/build-cli-reference-section.test.ts +3 -1
  314. package/src/prompts/system-prompt.ts +46 -42
  315. package/src/providers/anthropic/client.ts +59 -20
  316. package/src/providers/retry.ts +1 -27
  317. package/src/providers/types.ts +7 -1
  318. package/src/runtime/AGENTS.md +9 -0
  319. package/src/runtime/auth/route-policy.ts +6 -6
  320. package/src/runtime/channel-reply-delivery.ts +0 -40
  321. package/src/runtime/gateway-client.ts +0 -7
  322. package/src/runtime/guardian-reply-router.ts +24 -22
  323. package/src/runtime/http-server.ts +10 -8
  324. package/src/runtime/http-types.ts +2 -2
  325. package/src/runtime/invite-redemption-service.ts +19 -1
  326. package/src/runtime/invite-service.ts +25 -0
  327. package/src/runtime/middleware/twilio-validation.ts +1 -11
  328. package/src/runtime/pending-interactions.ts +14 -12
  329. package/src/runtime/routes/brain-graph-routes.ts +10 -90
  330. package/src/runtime/routes/channel-delivery-routes.ts +0 -1
  331. package/src/runtime/routes/conversation-routes.ts +81 -19
  332. package/src/runtime/routes/events-routes.ts +21 -11
  333. package/src/runtime/routes/host-cu-routes.ts +97 -0
  334. package/src/runtime/routes/inbound-stages/acl-enforcement.ts +21 -12
  335. package/src/runtime/routes/inbound-stages/background-dispatch.ts +12 -111
  336. package/src/runtime/routes/integrations/slack/share.ts +6 -7
  337. package/src/runtime/routes/log-export-routes.ts +126 -8
  338. package/src/runtime/routes/memory-item-routes.test.ts +754 -0
  339. package/src/runtime/routes/memory-item-routes.ts +503 -0
  340. package/src/runtime/routes/session-management-routes.ts +3 -3
  341. package/src/runtime/routes/settings-routes.ts +55 -48
  342. package/src/runtime/routes/surface-action-routes.ts +1 -1
  343. package/src/runtime/routes/trust-rules-routes.ts +14 -0
  344. package/src/runtime/routes/watch-routes.ts +128 -0
  345. package/src/runtime/routes/workspace-routes.ts +2 -1
  346. package/src/schedule/integration-status.ts +10 -9
  347. package/src/security/credential-key.ts +0 -156
  348. package/src/security/keychain-broker-client.ts +22 -10
  349. package/src/security/oauth2.ts +1 -1
  350. package/src/security/secure-keys.ts +25 -3
  351. package/src/security/token-manager.ts +137 -64
  352. package/src/skills/catalog-install.ts +414 -0
  353. package/src/skills/include-graph.ts +32 -0
  354. package/src/skills/skillssh-registry.ts +503 -0
  355. package/src/telegram/bot-username.ts +2 -3
  356. package/src/tools/assets/search.ts +5 -1
  357. package/src/tools/browser/network-recorder.ts +1 -1
  358. package/src/tools/browser/network-recording-types.ts +1 -1
  359. package/src/tools/computer-use/definitions.ts +36 -11
  360. package/src/tools/computer-use/registry.ts +5 -6
  361. package/src/tools/credentials/broker.ts +1 -2
  362. package/src/tools/credentials/metadata-store.ts +17 -121
  363. package/src/tools/credentials/vault.ts +92 -167
  364. package/src/tools/memory/definitions.ts +4 -13
  365. package/src/tools/memory/handlers.test.ts +83 -103
  366. package/src/tools/memory/handlers.ts +50 -85
  367. package/src/tools/registry.ts +2 -7
  368. package/src/tools/schedule/create.ts +8 -1
  369. package/src/tools/schedule/update.ts +8 -1
  370. package/src/tools/skills/load.ts +85 -3
  371. package/src/tools/watch/watch-state.ts +0 -12
  372. package/src/util/logger.ts +7 -41
  373. package/src/util/platform.ts +9 -28
  374. package/src/watcher/providers/google-calendar.ts +2 -1
  375. package/src/__tests__/clarification-resolver.test.ts +0 -193
  376. package/src/__tests__/computer-use-session-compaction.test.ts +0 -143
  377. package/src/__tests__/computer-use-session-lifecycle.test.ts +0 -322
  378. package/src/__tests__/computer-use-session-working-dir.test.ts +0 -166
  379. package/src/__tests__/computer-use-skill-baseline.test.ts +0 -78
  380. package/src/__tests__/computer-use-skill-endstate.test.ts +0 -105
  381. package/src/__tests__/computer-use-skill-lifecycle-cleanup.test.ts +0 -249
  382. package/src/__tests__/conflict-intent-tokenization.test.ts +0 -160
  383. package/src/__tests__/conflict-policy.test.ts +0 -269
  384. package/src/__tests__/conflict-store.test.ts +0 -372
  385. package/src/__tests__/contradiction-checker.test.ts +0 -361
  386. package/src/__tests__/entity-extractor.test.ts +0 -211
  387. package/src/__tests__/entity-search.test.ts +0 -1117
  388. package/src/__tests__/profile-compiler.test.ts +0 -392
  389. package/src/__tests__/ride-shotgun-handler.test.ts +0 -452
  390. package/src/__tests__/session-conflict-gate.test.ts +0 -1228
  391. package/src/__tests__/session-profile-injection.test.ts +0 -557
  392. package/src/cli/commands/dev.ts +0 -129
  393. package/src/cli/commands/map.ts +0 -391
  394. package/src/cli/commands/oauth.ts +0 -77
  395. package/src/config/bundled-skills/knowledge-graph/SKILL.md +0 -25
  396. package/src/config/bundled-skills/knowledge-graph/TOOLS.json +0 -66
  397. package/src/config/bundled-skills/knowledge-graph/tools/graph-query.ts +0 -211
  398. package/src/daemon/computer-use-session.ts +0 -1026
  399. package/src/daemon/ride-shotgun-handler.ts +0 -569
  400. package/src/daemon/session-conflict-gate.ts +0 -167
  401. package/src/daemon/session-dynamic-profile.ts +0 -77
  402. package/src/memory/clarification-resolver.ts +0 -417
  403. package/src/memory/conflict-intent.ts +0 -205
  404. package/src/memory/conflict-policy.ts +0 -127
  405. package/src/memory/conflict-store.ts +0 -410
  406. package/src/memory/contradiction-checker.ts +0 -508
  407. package/src/memory/entity-extractor.ts +0 -535
  408. package/src/memory/format-recall.ts +0 -47
  409. package/src/memory/fts-reconciler.ts +0 -165
  410. package/src/memory/job-handlers/conflict.ts +0 -200
  411. package/src/memory/profile-compiler.ts +0 -195
  412. package/src/memory/recall-cache.ts +0 -117
  413. package/src/memory/search/entity.ts +0 -535
  414. package/src/memory/search/query-expansion.test.ts +0 -70
  415. package/src/memory/search/query-expansion.ts +0 -118
  416. package/src/oauth/provider-base-urls.ts +0 -21
  417. package/src/oauth/provider-profiles.ts +0 -192
  418. package/src/prompts/computer-use-prompt.ts +0 -98
  419. package/src/runtime/routes/computer-use-routes.ts +0 -641
  420. package/src/runtime/routes/mcp-routes.ts +0 -20
  421. package/src/runtime/telegram-streaming-delivery.test.ts +0 -729
  422. package/src/runtime/telegram-streaming-delivery.ts +0 -393
  423. package/src/tools/computer-use/request-computer-control.ts +0 -56
@@ -104,7 +104,7 @@ describe("token estimator", () => {
104
104
  expect(largeFileTokens - smallFileTokens).toBeGreaterThan(1000);
105
105
  });
106
106
 
107
- test("does not count file base64 payload for OpenAI/Anthropic-style file fallback", () => {
107
+ test("does not count file base64 payload for OpenAI-style file fallback", () => {
108
108
  const sharedSource = {
109
109
  type: "base64" as const,
110
110
  filename: "report.pdf",
@@ -130,6 +130,47 @@ describe("token estimator", () => {
130
130
  expect(largeFileTokens).toBe(smallFileTokens);
131
131
  });
132
132
 
133
+ test("estimates Anthropic PDF tokens from file size", () => {
134
+ // ~14.8 MB PDF => ~20M base64 chars
135
+ const base64Length = 20_000_000;
136
+ const tokens = estimateContentBlockTokens(
137
+ {
138
+ type: "file",
139
+ source: {
140
+ type: "base64",
141
+ filename: "large-report.pdf",
142
+ media_type: "application/pdf",
143
+ data: "a".repeat(base64Length),
144
+ },
145
+ extracted_text: "",
146
+ },
147
+ { providerName: "anthropic" },
148
+ );
149
+
150
+ // Raw bytes = 20_000_000 * 3/4 = 15_000_000
151
+ // Estimated tokens = 15_000_000 * 0.016 = 240_000 (plus overhead)
152
+ expect(tokens).toBeGreaterThan(200_000);
153
+ });
154
+
155
+ test("Anthropic PDF minimum is one page", () => {
156
+ const tokens = estimateContentBlockTokens(
157
+ {
158
+ type: "file",
159
+ source: {
160
+ type: "base64",
161
+ filename: "tiny.pdf",
162
+ media_type: "application/pdf",
163
+ data: "a".repeat(16),
164
+ },
165
+ extracted_text: "",
166
+ },
167
+ { providerName: "anthropic" },
168
+ );
169
+
170
+ // Should be at least ANTHROPIC_PDF_MIN_TOKENS (1600) plus overhead
171
+ expect(tokens).toBeGreaterThanOrEqual(1600);
172
+ });
173
+
133
174
  test("does not count non-inline file base64 payload for Gemini", () => {
134
175
  const sharedSource = {
135
176
  type: "base64" as const,
@@ -156,21 +197,163 @@ describe("token estimator", () => {
156
197
  expect(largeFileTokens).toBe(smallFileTokens);
157
198
  });
158
199
 
159
- test("scales image token estimate with base64 payload size", () => {
160
- const smallImageTokens = estimateContentBlockTokens({
161
- type: "image",
162
- source: { type: "base64", media_type: "image/png", data: "a".repeat(64) },
163
- });
164
- const largeImageTokens = estimateContentBlockTokens({
165
- type: "image",
166
- source: {
167
- type: "base64",
168
- media_type: "image/png",
169
- data: "a".repeat(60_000),
200
+ // Non-Anthropic providers use base64 payload size for image estimation
201
+ test("scales image token estimate with base64 payload size (non-Anthropic)", () => {
202
+ const smallImageTokens = estimateContentBlockTokens(
203
+ {
204
+ type: "image",
205
+ source: {
206
+ type: "base64",
207
+ media_type: "image/png",
208
+ data: "a".repeat(64),
209
+ },
170
210
  },
171
- });
211
+ { providerName: "openai" },
212
+ );
213
+ const largeImageTokens = estimateContentBlockTokens(
214
+ {
215
+ type: "image",
216
+ source: {
217
+ type: "base64",
218
+ media_type: "image/png",
219
+ data: "a".repeat(60_000),
220
+ },
221
+ },
222
+ { providerName: "openai" },
223
+ );
172
224
 
173
225
  expect(largeImageTokens).toBeGreaterThan(smallImageTokens);
174
226
  expect(largeImageTokens - smallImageTokens).toBeGreaterThan(1000);
175
227
  });
228
+
229
+ test("estimates Anthropic image tokens from dimensions, not base64 size", () => {
230
+ // Build a minimal valid PNG header encoding 1920x1080 dimensions.
231
+ // PNG header: 8-byte signature + 4-byte IHDR length + 4-byte "IHDR" + 4-byte width + 4-byte height = 24 bytes minimum
232
+ const pngHeader = Buffer.alloc(24);
233
+ // PNG signature: 89 50 4E 47 0D 0A 1A 0A
234
+ pngHeader[0] = 0x89;
235
+ pngHeader[1] = 0x50;
236
+ pngHeader[2] = 0x4e;
237
+ pngHeader[3] = 0x47;
238
+ pngHeader[4] = 0x0d;
239
+ pngHeader[5] = 0x0a;
240
+ pngHeader[6] = 0x1a;
241
+ pngHeader[7] = 0x0a;
242
+ // IHDR chunk length (13 bytes)
243
+ pngHeader.writeUInt32BE(13, 8);
244
+ // "IHDR"
245
+ pngHeader[12] = 0x49;
246
+ pngHeader[13] = 0x48;
247
+ pngHeader[14] = 0x44;
248
+ pngHeader[15] = 0x52;
249
+ // Width: 1920
250
+ pngHeader.writeUInt32BE(1920, 16);
251
+ // Height: 1080
252
+ pngHeader.writeUInt32BE(1080, 20);
253
+
254
+ // Pad with ~200 KB of data to simulate a real screenshot payload
255
+ const padding = Buffer.alloc(200_000, 0x42);
256
+ const fullPayload = Buffer.concat([pngHeader, padding]);
257
+ const base64Data = fullPayload.toString("base64");
258
+
259
+ const anthropicTokens = estimateContentBlockTokens(
260
+ {
261
+ type: "image",
262
+ source: { type: "base64", media_type: "image/png", data: base64Data },
263
+ },
264
+ { providerName: "anthropic" },
265
+ );
266
+
267
+ // 1920x1080 scaled to fit 1568x1568: scale = 1568/1920 = 0.8167
268
+ // scaledWidth = round(1920 * 0.8167) = 1568, scaledHeight = round(1080 * 0.8167) = 882
269
+ // tokens = ceil(1568 * 882 / 750) = ceil(1843.968) = ~1844
270
+ // With IMAGE_BLOCK_OVERHEAD_TOKENS and media_type overhead, still well under 5000
271
+ expect(anthropicTokens).toBeLessThan(5_000);
272
+
273
+ // Verify it's NOT using base64 size (which would be ~50,000+ tokens)
274
+ const nonAnthropicTokens = estimateContentBlockTokens(
275
+ {
276
+ type: "image",
277
+ source: { type: "base64", media_type: "image/png", data: base64Data },
278
+ },
279
+ { providerName: "openai" },
280
+ );
281
+ expect(nonAnthropicTokens).toBeGreaterThan(50_000);
282
+ });
283
+
284
+ test("falls back to max tokens when Anthropic image dimensions can't be parsed", () => {
285
+ // Corrupted base64 that won't parse as a valid image header
286
+ const corruptedData = Buffer.from(
287
+ "not-a-valid-image-header-at-all",
288
+ ).toString("base64");
289
+
290
+ const tokens = estimateContentBlockTokens(
291
+ {
292
+ type: "image",
293
+ source: {
294
+ type: "base64",
295
+ media_type: "image/png",
296
+ data: corruptedData,
297
+ },
298
+ },
299
+ { providerName: "anthropic" },
300
+ );
301
+
302
+ // Should fall back to ANTHROPIC_IMAGE_MAX_TOKENS (~3,277)
303
+ // The total will include IMAGE_BLOCK_OVERHEAD_TOKENS + media_type overhead,
304
+ // but the max is applied at the outer Math.max(IMAGE_BLOCK_TOKENS, ...) level
305
+ // ANTHROPIC_IMAGE_MAX_TOKENS = ceil(1568*1568/750) = 3277
306
+ // Total = max(1024, 16 + ceil(9/4) + 3277) = max(1024, 3296) = 3296
307
+ expect(tokens).toBeGreaterThanOrEqual(3_277);
308
+ expect(tokens).toBeLessThan(4_000);
309
+ });
310
+
311
+ test("Anthropic image tokens are the same for same-dimension images regardless of payload size", () => {
312
+ // Build two PNG headers with the same dimensions (800x600) but different payload sizes
313
+ function makePng(
314
+ width: number,
315
+ height: number,
316
+ paddingSize: number,
317
+ ): string {
318
+ const header = Buffer.alloc(24);
319
+ header[0] = 0x89;
320
+ header[1] = 0x50;
321
+ header[2] = 0x4e;
322
+ header[3] = 0x47;
323
+ header[4] = 0x0d;
324
+ header[5] = 0x0a;
325
+ header[6] = 0x1a;
326
+ header[7] = 0x0a;
327
+ header.writeUInt32BE(13, 8);
328
+ header[12] = 0x49;
329
+ header[13] = 0x48;
330
+ header[14] = 0x44;
331
+ header[15] = 0x52;
332
+ header.writeUInt32BE(width, 16);
333
+ header.writeUInt32BE(height, 20);
334
+ const padding = Buffer.alloc(paddingSize, 0x42);
335
+ return Buffer.concat([header, padding]).toString("base64");
336
+ }
337
+
338
+ const smallPayload = makePng(800, 600, 1_000);
339
+ const largePayload = makePng(800, 600, 200_000);
340
+
341
+ const smallTokens = estimateContentBlockTokens(
342
+ {
343
+ type: "image",
344
+ source: { type: "base64", media_type: "image/png", data: smallPayload },
345
+ },
346
+ { providerName: "anthropic" },
347
+ );
348
+ const largeTokens = estimateContentBlockTokens(
349
+ {
350
+ type: "image",
351
+ source: { type: "base64", media_type: "image/png", data: largePayload },
352
+ },
353
+ { providerName: "anthropic" },
354
+ );
355
+
356
+ // For Anthropic, same dimensions should produce the same estimate
357
+ expect(largeTokens).toBe(smallTokens);
358
+ });
176
359
  });
@@ -21,7 +21,6 @@ mock.module("../util/logger.js", () => ({
21
21
  new Proxy({} as Record<string, unknown>, {
22
22
  get: () => () => {},
23
23
  }),
24
- isDebug: () => false,
25
24
  truncateForLog: (value: string) => value,
26
25
  }));
27
26
 
@@ -28,7 +28,6 @@ mock.module("../util/logger.js", () => ({
28
28
  new Proxy({} as Record<string, unknown>, {
29
29
  get: () => () => {},
30
30
  }),
31
- isDebug: () => false,
32
31
  truncateForLog: (value: string) => value,
33
32
  }));
34
33
 
@@ -171,6 +171,8 @@ describe("handleSendMessage canonical guardian reply interception", () => {
171
171
  hasPendingConfirmation: () => false,
172
172
  setHostBashProxy: () => {},
173
173
  setHostFileProxy: () => {},
174
+ setHostCuProxy: () => {},
175
+ addPreactivatedSkillId: () => {},
174
176
  } as unknown as import("../daemon/session.js").Session;
175
177
 
176
178
  const req = new Request("http://localhost/v1/messages", {
@@ -246,6 +248,8 @@ describe("handleSendMessage canonical guardian reply interception", () => {
246
248
  hasPendingConfirmation: () => false,
247
249
  setHostBashProxy: () => {},
248
250
  setHostFileProxy: () => {},
251
+ setHostCuProxy: () => {},
252
+ addPreactivatedSkillId: () => {},
249
253
  } as unknown as import("../daemon/session.js").Session;
250
254
 
251
255
  const req = new Request("http://localhost/v1/messages", {
@@ -317,6 +321,8 @@ describe("handleSendMessage canonical guardian reply interception", () => {
317
321
  requestId === "tool-approval-live",
318
322
  setHostBashProxy: () => {},
319
323
  setHostFileProxy: () => {},
324
+ setHostCuProxy: () => {},
325
+ addPreactivatedSkillId: () => {},
320
326
  } as unknown as import("../daemon/session.js").Session;
321
327
 
322
328
  const req = new Request("http://localhost/v1/messages", {
@@ -392,6 +398,8 @@ describe("handleSendMessage canonical guardian reply interception", () => {
392
398
  hasPendingConfirmation: (id: string) => id === "tool-req-code-1",
393
399
  setHostBashProxy: () => {},
394
400
  setHostFileProxy: () => {},
401
+ setHostCuProxy: () => {},
402
+ addPreactivatedSkillId: () => {},
395
403
  } as unknown as import("../daemon/session.js").Session;
396
404
 
397
405
  const req = new Request("http://localhost/v1/messages", {
@@ -463,6 +471,8 @@ describe("handleSendMessage canonical guardian reply interception", () => {
463
471
  hasPendingConfirmation: (id: string) => id === "pending-reject-1",
464
472
  setHostBashProxy: () => {},
465
473
  setHostFileProxy: () => {},
474
+ setHostCuProxy: () => {},
475
+ addPreactivatedSkillId: () => {},
466
476
  } as unknown as import("../daemon/session.js").Session;
467
477
 
468
478
  const req = new Request("http://localhost/v1/messages", {
@@ -528,6 +538,8 @@ describe("handleSendMessage canonical guardian reply interception", () => {
528
538
  hasPendingConfirmation: (id: string) => id === "pending-1",
529
539
  setHostBashProxy: () => {},
530
540
  setHostFileProxy: () => {},
541
+ setHostCuProxy: () => {},
542
+ addPreactivatedSkillId: () => {},
531
543
  } as unknown as import("../daemon/session.js").Session;
532
544
 
533
545
  const req = new Request("http://localhost/v1/messages", {
@@ -559,4 +571,144 @@ describe("handleSendMessage canonical guardian reply interception", () => {
559
571
  expect(persistUserMessage).toHaveBeenCalledTimes(1);
560
572
  expect(runAgentLoop).toHaveBeenCalledTimes(1);
561
573
  });
574
+
575
+ test("desktop sessions do not pass approvalConversationGenerator to routeGuardianReply", async () => {
576
+ listPendingByDestinationMock.mockReturnValue([
577
+ { id: "pending-1", kind: "access_request" },
578
+ ]);
579
+ listCanonicalMock.mockReturnValue([]);
580
+ routeGuardianReplyMock.mockResolvedValue({
581
+ consumed: false,
582
+ decisionApplied: false,
583
+ type: "not_consumed",
584
+ });
585
+
586
+ const mockGenerator = mock(async () => ({}));
587
+ const persistUserMessage = mock(async () => "persisted-user-id");
588
+ const runAgentLoop = mock(async () => undefined);
589
+ const session = {
590
+ setTrustContext: () => {},
591
+ updateClient: () => {},
592
+ emitConfirmationStateChanged: () => {},
593
+ emitActivityState: () => {},
594
+ setTurnChannelContext: () => {},
595
+ setTurnInterfaceContext: () => {},
596
+ ensureActorScopedHistory: async () => {},
597
+ usageStats: { inputTokens: 0, outputTokens: 0, estimatedCost: 0 },
598
+ isProcessing: () => false,
599
+ hasAnyPendingConfirmation: () => false,
600
+ denyAllPendingConfirmations: () => {},
601
+ enqueueMessage: () => ({ queued: true, requestId: "queued-id" }),
602
+ persistUserMessage,
603
+ runAgentLoop,
604
+ getMessages: () => [] as unknown[],
605
+ assistantId: "self",
606
+ trustContext: undefined,
607
+ hasPendingConfirmation: () => false,
608
+ setHostBashProxy: () => {},
609
+ setHostFileProxy: () => {},
610
+ setHostCuProxy: () => {},
611
+ addPreactivatedSkillId: () => {},
612
+ } as unknown as import("../daemon/session.js").Session;
613
+
614
+ const req = new Request("http://localhost/v1/messages", {
615
+ method: "POST",
616
+ headers: { "Content-Type": "application/json" },
617
+ body: JSON.stringify({
618
+ conversationKey: "guardian-thread-key",
619
+ content: "no sorry, beats 0 and 3 should be new threads",
620
+ sourceChannel: "vellum",
621
+ interface: "macos",
622
+ }),
623
+ });
624
+
625
+ await handleSendMessage(
626
+ req,
627
+ {
628
+ sendMessageDeps: {
629
+ getOrCreateSession: async () => session,
630
+ assistantEventHub: { publish: async () => {} } as any,
631
+ resolveAttachments: () => [],
632
+ },
633
+ approvalConversationGenerator: mockGenerator as any,
634
+ },
635
+ testAuthContext,
636
+ );
637
+
638
+ expect(routeGuardianReplyMock).toHaveBeenCalledTimes(1);
639
+ const routerCall = (routeGuardianReplyMock as any).mock
640
+ .calls[0][0] as Record<string, unknown>;
641
+ // Desktop (vellum) should suppress the NL engine
642
+ expect(routerCall.approvalConversationGenerator).toBeUndefined();
643
+ });
644
+
645
+ test("channel sessions pass approvalConversationGenerator to routeGuardianReply", async () => {
646
+ listPendingByDestinationMock.mockReturnValue([
647
+ { id: "pending-1", kind: "access_request" },
648
+ ]);
649
+ listCanonicalMock.mockReturnValue([]);
650
+ routeGuardianReplyMock.mockResolvedValue({
651
+ consumed: false,
652
+ decisionApplied: false,
653
+ type: "not_consumed",
654
+ });
655
+
656
+ const mockGenerator = mock(async () => ({}));
657
+ const persistUserMessage = mock(async () => "persisted-user-id");
658
+ const runAgentLoop = mock(async () => undefined);
659
+ const session = {
660
+ setTrustContext: () => {},
661
+ updateClient: () => {},
662
+ emitConfirmationStateChanged: () => {},
663
+ emitActivityState: () => {},
664
+ setTurnChannelContext: () => {},
665
+ setTurnInterfaceContext: () => {},
666
+ ensureActorScopedHistory: async () => {},
667
+ usageStats: { inputTokens: 0, outputTokens: 0, estimatedCost: 0 },
668
+ isProcessing: () => false,
669
+ hasAnyPendingConfirmation: () => false,
670
+ denyAllPendingConfirmations: () => {},
671
+ enqueueMessage: () => ({ queued: true, requestId: "queued-id" }),
672
+ persistUserMessage,
673
+ runAgentLoop,
674
+ getMessages: () => [] as unknown[],
675
+ assistantId: "self",
676
+ trustContext: undefined,
677
+ hasPendingConfirmation: () => false,
678
+ setHostBashProxy: () => {},
679
+ setHostFileProxy: () => {},
680
+ setHostCuProxy: () => {},
681
+ addPreactivatedSkillId: () => {},
682
+ } as unknown as import("../daemon/session.js").Session;
683
+
684
+ const req = new Request("http://localhost/v1/messages", {
685
+ method: "POST",
686
+ headers: { "Content-Type": "application/json" },
687
+ body: JSON.stringify({
688
+ conversationKey: "guardian-thread-key",
689
+ content: "no sorry, beats 0 and 3 should be new threads",
690
+ sourceChannel: "telegram",
691
+ interface: "telegram",
692
+ }),
693
+ });
694
+
695
+ await handleSendMessage(
696
+ req,
697
+ {
698
+ sendMessageDeps: {
699
+ getOrCreateSession: async () => session,
700
+ assistantEventHub: { publish: async () => {} } as any,
701
+ resolveAttachments: () => [],
702
+ },
703
+ approvalConversationGenerator: mockGenerator as any,
704
+ },
705
+ testAuthContext,
706
+ );
707
+
708
+ expect(routeGuardianReplyMock).toHaveBeenCalledTimes(1);
709
+ const routerCall = (routeGuardianReplyMock as any).mock
710
+ .calls[0][0] as Record<string, unknown>;
711
+ // Channel sessions should receive the NL engine
712
+ expect(routerCall.approvalConversationGenerator).toBe(mockGenerator);
713
+ });
562
714
  });
@@ -203,6 +203,8 @@ function makeSession() {
203
203
  hasPendingConfirmation: () => false,
204
204
  setHostBashProxy: () => {},
205
205
  setHostFileProxy: () => {},
206
+ setHostCuProxy: () => {},
207
+ addPreactivatedSkillId: () => {},
206
208
  usageStats: {
207
209
  inputTokens: 1000,
208
210
  outputTokens: 500,