@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
@@ -4,6 +4,11 @@
4
4
  * Persists non-secret metadata about credentials (policy, timestamps, IDs)
5
5
  * in a versioned JSON file under protected storage. Secret values remain
6
6
  * in the secure key backend only.
7
+ *
8
+ * OAuth-specific fields (expiresAt, grantedScopes, oauth2TokenUrl,
9
+ * oauth2ClientId, oauth2TokenEndpointAuthMethod, hasRefreshToken) are now
10
+ * exclusively managed by the SQLite oauth-store and have been removed
11
+ * from this interface as of v5.
7
12
  */
8
13
 
9
14
  import { randomUUID } from "node:crypto";
@@ -21,26 +26,16 @@ export interface CredentialMetadata {
21
26
  allowedTools: string[];
22
27
  allowedDomains: string[];
23
28
  usageDescription?: string;
24
- expiresAt?: number;
25
- grantedScopes?: string[];
26
- /** OAuth2 token endpoint — enables autonomous token refresh without an IntegrationDefinition. */
27
- oauth2TokenUrl?: string;
28
- /** OAuth2 client ID — paired with oauth2TokenUrl for refresh. */
29
- oauth2ClientId?: string;
30
- /** How the client authenticates at the token endpoint (client_secret_basic or client_secret_post). */
31
- oauth2TokenEndpointAuthMethod?: string;
32
29
  /** Human-friendly name for this credential (e.g. "fal-primary"). */
33
30
  alias?: string;
34
31
  /** Templates describing how to inject this credential into proxied requests. */
35
32
  injectionTemplates?: CredentialInjectionTemplate[];
36
- /** Whether a refresh token exists in the secure store for this service. */
37
- hasRefreshToken?: boolean;
38
33
  createdAt: number;
39
34
  updatedAt: number;
40
35
  }
41
36
 
42
37
  /** Current on-disk schema version. */
43
- const CURRENT_VERSION = 4;
38
+ const CURRENT_VERSION = 5;
44
39
 
45
40
  interface MetadataFile {
46
41
  version: typeof CURRENT_VERSION;
@@ -88,9 +83,10 @@ function isValidCredentialRecord(
88
83
  }
89
84
 
90
85
  /**
91
- * Migrate a v1 record to v2 by backfilling new optional fields with defaults.
86
+ * Migrate any record to v5 by stripping OAuth-specific fields that are
87
+ * now exclusively managed by the SQLite oauth-store.
92
88
  */
93
- function migrateRecordV1toV2(
89
+ function migrateRecordToV5(
94
90
  record: Record<string, unknown>,
95
91
  ): CredentialMetadata {
96
92
  return {
@@ -107,73 +103,15 @@ function migrateRecordV1toV2(
107
103
  typeof record.usageDescription === "string"
108
104
  ? record.usageDescription
109
105
  : undefined,
110
- expiresAt:
111
- typeof record.expiresAt === "number" ? record.expiresAt : undefined,
112
- grantedScopes: Array.isArray(record.grantedScopes)
113
- ? (record.grantedScopes as string[])
114
- : undefined,
115
- oauth2TokenUrl:
116
- typeof record.oauth2TokenUrl === "string"
117
- ? record.oauth2TokenUrl
118
- : undefined,
119
- oauth2ClientId:
120
- typeof record.oauth2ClientId === "string"
121
- ? record.oauth2ClientId
122
- : undefined,
123
- oauth2TokenEndpointAuthMethod:
124
- typeof record.oauth2TokenEndpointAuthMethod === "string"
125
- ? record.oauth2TokenEndpointAuthMethod
126
- : undefined,
127
106
  alias: typeof record.alias === "string" ? record.alias : undefined,
128
107
  injectionTemplates: Array.isArray(record.injectionTemplates)
129
108
  ? (record.injectionTemplates as CredentialInjectionTemplate[])
130
109
  : undefined,
131
- hasRefreshToken:
132
- typeof record.hasRefreshToken === "boolean"
133
- ? record.hasRefreshToken
134
- : undefined,
135
110
  createdAt: record.createdAt as number,
136
111
  updatedAt: record.updatedAt as number,
137
112
  };
138
113
  }
139
114
 
140
- /**
141
- * Migrate a v2 record to v3 by stripping the oauth2ClientSecret field.
142
- * Client secrets are now read exclusively from the secure key store.
143
- */
144
- function migrateRecordV2toV3(record: CredentialMetadata): CredentialMetadata {
145
- const { oauth2ClientSecret: _removed, ...rest } =
146
- record as CredentialMetadata & { oauth2ClientSecret?: string };
147
- return rest;
148
- }
149
-
150
- /**
151
- * Migrate v3 credentials to v4:
152
- * - Delete ghost `refresh_token` metadata records
153
- * - Set `hasRefreshToken: true` on corresponding `access_token` records
154
- */
155
- function migrateV3toV4(
156
- credentials: CredentialMetadata[],
157
- ): CredentialMetadata[] {
158
- // Collect services that had refresh_token ghost records
159
- const servicesWithRefresh = new Set<string>();
160
- for (const c of credentials) {
161
- if (c.field === "refresh_token") {
162
- servicesWithRefresh.add(c.service);
163
- }
164
- }
165
-
166
- // Remove all refresh_token records and set hasRefreshToken on access_token records
167
- const filtered = credentials.filter((c) => c.field !== "refresh_token");
168
- for (const c of filtered) {
169
- if (c.field === "access_token" && servicesWithRefresh.has(c.service)) {
170
- c.hasRefreshToken = true;
171
- }
172
- }
173
-
174
- return filtered;
175
- }
176
-
177
115
  function loadFile(): LoadResult {
178
116
  const raw = readTextFileSync(getMetadataPath());
179
117
  if (raw == null) {
@@ -189,7 +127,8 @@ function loadFile(): LoadResult {
189
127
  fileVersion !== 1 &&
190
128
  fileVersion !== 2 &&
191
129
  fileVersion !== 3 &&
192
- fileVersion !== 4
130
+ fileVersion !== 4 &&
131
+ fileVersion !== 5
193
132
  ) {
194
133
  // Unrecognized version (future, fractional, negative, zero) — refuse to touch it
195
134
  return { unknownVersion: true };
@@ -201,24 +140,12 @@ function loadFile(): LoadResult {
201
140
  const validRecords = rawCredentials.filter(isValidCredentialRecord);
202
141
 
203
142
  if (fileVersion < CURRENT_VERSION) {
204
- // Apply migrations in sequence: v1→v2→v3→v4
205
- let credentials: CredentialMetadata[];
206
- if (fileVersion === 1) {
207
- credentials = migrateV3toV4(
208
- validRecords.map(migrateRecordV1toV2).map(migrateRecordV2toV3),
209
- );
210
- } else if (fileVersion === 2) {
211
- credentials = migrateV3toV4(
212
- (validRecords as unknown as CredentialMetadata[]).map(
213
- migrateRecordV2toV3,
214
- ),
215
- );
216
- } else {
217
- // fileVersion === 3
218
- credentials = migrateV3toV4(
219
- validRecords as unknown as CredentialMetadata[],
220
- );
221
- }
143
+ // Migrate all older versions to v5 by stripping OAuth-specific fields
144
+ // and removing ghost refresh_token records
145
+ const filtered = validRecords.filter(
146
+ (r) => (r as Record<string, unknown>).field !== "refresh_token",
147
+ );
148
+ const credentials = filtered.map(migrateRecordToV5);
222
149
  const migrated: MetadataFile = { version: CURRENT_VERSION, credentials };
223
150
  try {
224
151
  saveFile(migrated);
@@ -272,17 +199,10 @@ export function upsertCredentialMetadata(
272
199
  allowedTools?: string[];
273
200
  allowedDomains?: string[];
274
201
  usageDescription?: string;
275
- /** Pass `null` to explicitly clear a previously-set expiry. */
276
- expiresAt?: number | null;
277
- grantedScopes?: string[];
278
- oauth2TokenUrl?: string;
279
- oauth2ClientId?: string;
280
- oauth2TokenEndpointAuthMethod?: string;
281
202
  /** Pass `null` to explicitly clear a previously-set alias. */
282
203
  alias?: string | null;
283
204
  /** Pass `null` to explicitly clear injection templates. */
284
205
  injectionTemplates?: CredentialInjectionTemplate[] | null;
285
- hasRefreshToken?: boolean;
286
206
  },
287
207
  ): CredentialMetadata {
288
208
  const result = loadFile();
@@ -305,22 +225,6 @@ export function upsertCredentialMetadata(
305
225
  existing.allowedDomains = policy.allowedDomains;
306
226
  if (policy?.usageDescription !== undefined)
307
227
  existing.usageDescription = policy.usageDescription;
308
- if (policy?.expiresAt !== undefined) {
309
- if (policy.expiresAt == null) {
310
- delete existing.expiresAt;
311
- } else {
312
- existing.expiresAt = policy.expiresAt;
313
- }
314
- }
315
- if (policy?.grantedScopes !== undefined)
316
- existing.grantedScopes = policy.grantedScopes;
317
- if (policy?.oauth2TokenUrl !== undefined)
318
- existing.oauth2TokenUrl = policy.oauth2TokenUrl;
319
- if (policy?.oauth2ClientId !== undefined)
320
- existing.oauth2ClientId = policy.oauth2ClientId;
321
- if (policy?.oauth2TokenEndpointAuthMethod !== undefined)
322
- existing.oauth2TokenEndpointAuthMethod =
323
- policy.oauth2TokenEndpointAuthMethod;
324
228
  if (policy?.alias !== undefined) {
325
229
  if (policy.alias == null) {
326
230
  delete existing.alias;
@@ -335,8 +239,6 @@ export function upsertCredentialMetadata(
335
239
  existing.injectionTemplates = policy.injectionTemplates;
336
240
  }
337
241
  }
338
- if (policy?.hasRefreshToken !== undefined)
339
- existing.hasRefreshToken = policy.hasRefreshToken;
340
242
  existing.updatedAt = now;
341
243
  saveFile(data);
342
244
  return existing;
@@ -349,14 +251,8 @@ export function upsertCredentialMetadata(
349
251
  allowedTools: policy?.allowedTools ?? [],
350
252
  allowedDomains: policy?.allowedDomains ?? [],
351
253
  usageDescription: policy?.usageDescription,
352
- expiresAt: policy?.expiresAt ?? undefined,
353
- grantedScopes: policy?.grantedScopes,
354
- oauth2TokenUrl: policy?.oauth2TokenUrl,
355
- oauth2ClientId: policy?.oauth2ClientId,
356
- oauth2TokenEndpointAuthMethod: policy?.oauth2TokenEndpointAuthMethod,
357
254
  alias: policy?.alias ?? undefined,
358
255
  injectionTemplates: policy?.injectionTemplates ?? undefined,
359
- hasRefreshToken: policy?.hasRefreshToken,
360
256
  createdAt: now,
361
257
  updatedAt: now,
362
258
  };
@@ -1,17 +1,22 @@
1
1
  import { getConfig } from "../../config/loader.js";
2
2
  import { orchestrateOAuthConnect } from "../../oauth/connect-orchestrator.js";
3
3
  import {
4
- getProviderProfile,
4
+ disconnectOAuthProvider,
5
+ getAppByProviderAndClientId,
6
+ getMostRecentAppByProvider,
7
+ getProvider,
8
+ } from "../../oauth/oauth-store.js";
9
+ import {
10
+ getProviderBehavior,
5
11
  resolveService,
6
12
  SERVICE_ALIASES,
7
- } from "../../oauth/provider-profiles.js";
13
+ } from "../../oauth/provider-behaviors.js";
8
14
  import { RiskLevel } from "../../permissions/types.js";
9
15
  import type { ToolDefinition } from "../../providers/types.js";
10
16
  import { buildAssistantEvent } from "../../runtime/assistant-event.js";
11
17
  import { assistantEventHub } from "../../runtime/assistant-event-hub.js";
12
18
  import { DAEMON_INTERNAL_ASSISTANT_ID } from "../../runtime/assistant-scope.js";
13
- import { credentialKey, migrateKeys } from "../../security/credential-key.js";
14
- import type { TokenEndpointAuthMethod } from "../../security/oauth2.js";
19
+ import { credentialKey } from "../../security/credential-key.js";
15
20
  import {
16
21
  deleteSecureKeyAsync,
17
22
  getSecureKey,
@@ -36,50 +41,6 @@ import { toPolicyFromInput, validatePolicyInput } from "./policy-validate.js";
36
41
 
37
42
  const log = getLogger("credential-vault");
38
43
 
39
- /**
40
- * Look up a stored OAuth secret (e.g. client_secret) for a service from the
41
- * secure store. Checks both the canonical and alias service names.
42
- */
43
- function findStoredOAuthSecret(
44
- service: string,
45
- field: string,
46
- ): string | undefined {
47
- const servicesToCheck = [service];
48
- // Also check the alias if the input is the canonical name, or vice versa
49
- for (const [alias, canonical] of Object.entries(SERVICE_ALIASES)) {
50
- if (canonical === service) servicesToCheck.push(alias);
51
- if (alias === service) servicesToCheck.push(canonical);
52
- }
53
- for (const svc of servicesToCheck) {
54
- const value = getSecureKey(credentialKey(svc, field));
55
- if (value) return value;
56
- }
57
- return undefined;
58
- }
59
-
60
- /**
61
- * Look up the stored OAuth client_id for a service from credential metadata.
62
- * Checks both the canonical and alias service names.
63
- */
64
- function findStoredOAuthClientId(service: string): string | undefined {
65
- const servicesToCheck = [service];
66
- for (const [alias, canonical] of Object.entries(SERVICE_ALIASES)) {
67
- if (canonical === service) servicesToCheck.push(alias);
68
- if (alias === service) servicesToCheck.push(canonical);
69
- }
70
- // Check metadata first (written by oauth2_connect after successful auth)
71
- for (const svc of servicesToCheck) {
72
- const meta = getCredentialMetadata(svc, "access_token");
73
- if (meta?.oauth2ClientId) return meta.oauth2ClientId;
74
- }
75
- // Fall back to secure key store (written by credential_store prompt action)
76
- for (const svc of servicesToCheck) {
77
- const value = getSecureKey(credentialKey(svc, "client_id"));
78
- if (value) return value;
79
- }
80
- return undefined;
81
- }
82
-
83
44
  class CredentialStoreTool implements Tool {
84
45
  name = "credential_store";
85
46
  description =
@@ -151,16 +112,6 @@ class CredentialStoreTool implements Tool {
151
112
  description:
152
113
  'Human-readable description of intended usage (for store/prompt actions), e.g. "GitHub login for pushing changes"',
153
114
  },
154
- auth_url: {
155
- type: "string",
156
- description:
157
- "OAuth2 authorization endpoint (only for oauth2_connect action). Auto-filled for well-known services (gmail, slack).",
158
- },
159
- token_url: {
160
- type: "string",
161
- description:
162
- "OAuth2 token endpoint (only for oauth2_connect action). Auto-filled for well-known services (gmail, slack).",
163
- },
164
115
  scopes: {
165
116
  type: "array",
166
117
  items: { type: "string" },
@@ -172,27 +123,11 @@ class CredentialStoreTool implements Tool {
172
123
  description:
173
124
  "OAuth2 client ID (only for oauth2_connect action). If omitted, looked up from previously stored credentials.",
174
125
  },
175
- extra_params: {
176
- type: "object",
177
- description:
178
- "Extra query params for OAuth2 auth URL (only for oauth2_connect action)",
179
- },
180
- userinfo_url: {
181
- type: "string",
182
- description:
183
- "Endpoint to fetch account info after OAuth2 auth (only for oauth2_connect action)",
184
- },
185
126
  client_secret: {
186
127
  type: "string",
187
128
  description:
188
129
  "OAuth2 client secret for providers that require it (e.g. Google, Slack). If omitted, looked up from previously stored credentials; if still absent, PKCE-only is used (only for oauth2_connect action)",
189
130
  },
190
- token_endpoint_auth_method: {
191
- type: "string",
192
- enum: ["client_secret_basic", "client_secret_post"],
193
- description:
194
- 'How to send client credentials at the token endpoint: "client_secret_post" (default, in POST body) or "client_secret_basic" (HTTP Basic Auth header). Only for oauth2_connect action.',
195
- },
196
131
  alias: {
197
132
  type: "string",
198
133
  description:
@@ -243,7 +178,6 @@ class CredentialStoreTool implements Tool {
243
178
  input: Record<string, unknown>,
244
179
  context: ToolContext,
245
180
  ): Promise<ToolExecutionResult> {
246
- migrateKeys();
247
181
  const action = input.action as string;
248
182
 
249
183
  switch (action) {
@@ -517,6 +451,21 @@ class CredentialStoreTool implements Tool {
517
451
  "metadata delete failed after removing credential",
518
452
  );
519
453
  }
454
+ // Also clean up any OAuth connection for this service (best-effort)
455
+ try {
456
+ const oauthResult = await disconnectOAuthProvider(service);
457
+ if (oauthResult === "error") {
458
+ log.warn(
459
+ { service },
460
+ "OAuth disconnect failed after removing credential — secure key deletion error",
461
+ );
462
+ }
463
+ } catch (err) {
464
+ log.warn(
465
+ { service, err },
466
+ "OAuth disconnect failed after removing credential",
467
+ );
468
+ }
520
469
  return {
521
470
  content: `Deleted credential for ${service}/${field}.`,
522
471
  isError: false,
@@ -777,51 +726,42 @@ class CredentialStoreTool implements Tool {
777
726
  // Resolve aliases (e.g. "gmail" → "integration:gmail")
778
727
  const service = resolveService(rawService);
779
728
 
780
- // Fill missing params from provider profile
781
- const profile = getProviderProfile(service);
782
-
783
- // Look up client_id from metadata and client_secret from secure store
784
- const clientId =
785
- (input.client_id as string | undefined) ??
786
- findStoredOAuthClientId(service);
787
- const clientSecret =
788
- (input.client_secret as string | undefined) ??
789
- findStoredOAuthSecret(service, "client_secret");
729
+ // Code-side behavioral fields (identityVerifier, setup, etc.)
730
+ const behavior = getProviderBehavior(service);
731
+ // Protocol-level config from the DB (authUrl, tokenUrl, scopes, etc.)
732
+ const providerRow = getProvider(service);
733
+
734
+ // Resolve client_id and client_secret.
735
+ // Priority:
736
+ // 1. Explicit input from the caller
737
+ // 2. oauth-store DB when clientId is already known, look up the
738
+ // matching app so the secret comes from the same app. Only fall
739
+ // back to the most-recent-app heuristic when clientId is unknown.
740
+ let clientId = input.client_id as string | undefined;
741
+ let clientSecret = input.client_secret as string | undefined;
742
+
743
+ if (!clientId || !clientSecret) {
744
+ const dbApp = clientId
745
+ ? getAppByProviderAndClientId(service, clientId)
746
+ : getMostRecentAppByProvider(service);
747
+ if (dbApp) {
748
+ if (!clientId) clientId = dbApp.clientId;
749
+ if (!clientSecret) {
750
+ clientSecret = getSecureKey(dbApp.clientSecretCredentialPath);
751
+ }
752
+ }
753
+ }
790
754
 
791
755
  // Early guardrails that stay in vault.ts (credential resolution is vault-specific)
792
756
  const inputScopes = input.scopes as string[] | undefined;
793
757
 
794
- if (profile) {
795
- // Profile-based provider (well-known like gmail, slack, twitter):
796
- // Don't pass authUrl/tokenUrl the orchestrator resolves those from the profile.
797
- // Pass user-provided scopes as requestedScopes so the scope policy engine is invoked.
798
- // If no scopes provided, pass neither — let the orchestrator use profile defaults via scope policy.
799
- } else {
800
- // Custom/unknown provider: require authUrl, tokenUrl, scopes from input
801
- if (!input.auth_url)
802
- return {
803
- content:
804
- "Error: auth_url is required for oauth2_connect action (no well-known config for this service)",
805
- isError: true,
806
- };
807
- if (!input.token_url)
808
- return {
809
- content:
810
- "Error: token_url is required for oauth2_connect action (no well-known config for this service)",
811
- isError: true,
812
- };
813
- if (!inputScopes)
814
- return {
815
- content:
816
- "Error: scopes is required for oauth2_connect action (no well-known config for this service)",
817
- isError: true,
818
- };
758
+ if (!providerRow) {
759
+ return {
760
+ content: `Error: no OAuth provider registered for "${service}". Ensure the provider is seeded in the database.`,
761
+ isError: true,
762
+ };
819
763
  }
820
764
 
821
- const authUrl =
822
- (input.auth_url as string | undefined) ?? profile?.authUrl;
823
- const tokenUrl =
824
- (input.token_url as string | undefined) ?? profile?.tokenUrl;
825
765
  if (!clientId)
826
766
  return {
827
767
  content:
@@ -833,10 +773,10 @@ class CredentialStoreTool implements Tool {
833
773
  // agent to collect it from the user rather than letting it improvise
834
774
  // browser-automation workarounds that inevitably fail.
835
775
  const requiresSecret =
836
- profile?.setup?.requiresClientSecret ??
837
- !!(profile?.tokenEndpointAuthMethod || profile?.extraParams);
776
+ behavior?.setup?.requiresClientSecret ??
777
+ !!(providerRow.tokenEndpointAuthMethod || providerRow.extraParams);
838
778
  if (requiresSecret && !clientSecret) {
839
- const skillId = profile?.setupSkillId;
779
+ const skillId = behavior?.setupSkillId;
840
780
  const skillHint = skillId
841
781
  ? `\n\nLoad the "${skillId}" skill for provider-specific instructions on obtaining the client secret.`
842
782
  : '\n\nUse credential_store with action "prompt" to securely collect the client_secret from the user before calling oauth2_connect again.';
@@ -846,25 +786,8 @@ class CredentialStoreTool implements Tool {
846
786
  };
847
787
  }
848
788
 
849
- try {
850
- assertMetadataWritable();
851
- } catch {
852
- return {
853
- content:
854
- "Error: credential metadata file has an unrecognized version; cannot store credentials",
855
- isError: true,
856
- };
857
- }
858
-
859
- const tokenEndpointAuthMethod =
860
- (input.token_endpoint_auth_method as
861
- | TokenEndpointAuthMethod
862
- | undefined) ?? profile?.tokenEndpointAuthMethod;
863
-
864
- // Delegate to the shared orchestrator.
865
- // For profile-based providers, pass user scopes as requestedScopes so the
866
- // scope policy engine (resolveScopes) is invoked. For custom providers,
867
- // pass scopes directly as an explicit override.
789
+ // Delegate to the shared orchestrator — it resolves authUrl, tokenUrl,
790
+ // extraParams, userinfoUrl, and tokenEndpointAuthMethod from the DB.
868
791
  const result = await orchestrateOAuthConnect({
869
792
  service: rawService,
870
793
  clientId,
@@ -872,24 +795,7 @@ class CredentialStoreTool implements Tool {
872
795
  isInteractive: !!context.isInteractive,
873
796
  sendToClient: context.sendToClient,
874
797
  allowedTools: input.allowed_tools as string[] | undefined,
875
- authUrl,
876
- tokenUrl,
877
- ...(profile
878
- ? {
879
- // Profile-based: let orchestrator resolve scopes via policy engine.
880
- // Only pass requestedScopes if the user explicitly provided scopes.
881
- ...(inputScopes ? { requestedScopes: inputScopes } : {}),
882
- }
883
- : {
884
- // Custom provider: explicit scopes override (bypasses policy engine)
885
- scopes: inputScopes,
886
- }),
887
- extraParams:
888
- (input.extra_params as Record<string, string> | undefined) ??
889
- profile?.extraParams,
890
- userinfoUrl:
891
- (input.userinfo_url as string | undefined) ?? profile?.userinfoUrl,
892
- tokenEndpointAuthMethod,
798
+ ...(inputScopes ? { requestedScopes: inputScopes } : {}),
893
799
  onDeferredComplete: (deferredResult) => {
894
800
  // Emit oauth_connect_result to all connected SSE clients so the
895
801
  // UI can update immediately when the deferred browser flow completes.
@@ -958,8 +864,8 @@ class CredentialStoreTool implements Tool {
958
864
  };
959
865
  }
960
866
  const resolvedService = resolveService(rawService);
961
- const profile = getProviderProfile(resolvedService);
962
- if (!profile) {
867
+ const descProviderRow = getProvider(resolvedService);
868
+ if (!descProviderRow) {
963
869
  return {
964
870
  content: `No well-known OAuth config found for "${rawService}". Available services: ${Object.keys(
965
871
  SERVICE_ALIASES,
@@ -968,11 +874,17 @@ class CredentialStoreTool implements Tool {
968
874
  };
969
875
  }
970
876
 
877
+ const descBehavior = getProviderBehavior(resolvedService);
878
+
971
879
  // Compute the redirect URI based on callback transport
972
880
  let redirectUri: string;
973
- const transport = profile.callbackTransport ?? "gateway";
974
- if (transport === "loopback" && profile.loopbackPort) {
975
- redirectUri = `http://127.0.0.1:${profile.loopbackPort}/oauth/callback`;
881
+ const transport =
882
+ (descProviderRow.callbackTransport as
883
+ | "loopback"
884
+ | "gateway"
885
+ | null) ?? "gateway";
886
+ if (transport === "loopback" && descProviderRow.loopbackPort) {
887
+ redirectUri = `http://127.0.0.1:${descProviderRow.loopbackPort}/oauth/callback`;
976
888
  } else if (transport === "loopback") {
977
889
  redirectUri =
978
890
  "(automatic — no redirect URI needed, uses random localhost port)";
@@ -986,26 +898,39 @@ class CredentialStoreTool implements Tool {
986
898
  redirectUri = `${baseUrl}/webhooks/oauth/callback`;
987
899
  } catch {
988
900
  redirectUri =
989
- "(requires INGRESS_PUBLIC_BASE_URL — not currently configured)";
901
+ "(requires ingress.publicBaseUrl — not currently configured)";
990
902
  }
991
903
  }
992
904
 
993
905
  // Prefer explicit setup metadata, fall back to heuristic
994
906
  const requiresClientSecret =
995
- profile.setup?.requiresClientSecret ??
996
- !!(profile.tokenEndpointAuthMethod || profile.extraParams);
907
+ descBehavior?.setup?.requiresClientSecret ??
908
+ !!(
909
+ descProviderRow.tokenEndpointAuthMethod ||
910
+ descProviderRow.extraParams
911
+ );
912
+
913
+ const descDefaultScopes: string[] = descProviderRow.defaultScopes
914
+ ? JSON.parse(descProviderRow.defaultScopes)
915
+ : [];
997
916
 
998
917
  const info: Record<string, unknown> = {
999
918
  service: resolvedService,
1000
- authUrl: profile.authUrl,
1001
- tokenUrl: profile.tokenUrl,
1002
- scopes: profile.defaultScopes,
919
+ authUrl: descProviderRow.authUrl,
920
+ tokenUrl: descProviderRow.tokenUrl,
921
+ scopes: descDefaultScopes,
1003
922
  callbackTransport: transport,
1004
923
  redirectUri,
1005
924
  requiresClientSecret,
1006
925
  };
1007
- if (profile.setup) info.setup = profile.setup;
1008
- if (profile.extraParams) info.extraParams = profile.extraParams;
926
+ if (descBehavior?.setup) info.setup = descBehavior.setup;
927
+ if (descProviderRow.extraParams) {
928
+ try {
929
+ info.extraParams = JSON.parse(descProviderRow.extraParams);
930
+ } catch {
931
+ // Non-fatal
932
+ }
933
+ }
1009
934
 
1010
935
  return { content: JSON.stringify(info, null, 2), isError: false };
1011
936
  }
@@ -3,7 +3,7 @@ import type { ToolDefinition } from "../../providers/types.js";
3
3
  export const memoryRecallDefinition: ToolDefinition = {
4
4
  name: "memory_recall",
5
5
  description:
6
- "Deep search across all memory sources (semantic, lexical, entity graph, recency) for specific information. Use this when you need to recall details about past conversations, decisions, preferences, project context, or any prior knowledge. Returns formatted memory context with item IDs for use with memory_manage.",
6
+ "Hybrid search across memory (semantic and recency) for specific information. Use this when you need to recall details about past conversations, decisions, preferences, project context, or any prior knowledge. Returns formatted memory context with item IDs for use with memory_manage.",
7
7
  input_schema: {
8
8
  type: "object",
9
9
  properties: {
@@ -11,10 +11,6 @@ export const memoryRecallDefinition: ToolDefinition = {
11
11
  type: "string",
12
12
  description: "The search query — be specific and descriptive",
13
13
  },
14
- max_results: {
15
- type: "number",
16
- description: "Maximum number of memory items to return (default: 10)",
17
- },
18
14
  scope: {
19
15
  type: "string",
20
16
  enum: ["default", "conversation"],
@@ -44,17 +40,12 @@ const memoryManageProperties = {
44
40
  kind: {
45
41
  type: "string" as const,
46
42
  enum: [
43
+ "identity",
47
44
  "preference",
48
- "fact",
45
+ "project",
49
46
  "decision",
50
- "profile",
51
- "relationship",
47
+ "constraint",
52
48
  "event",
53
- "opinion",
54
- "instruction",
55
- "style",
56
- "playbook",
57
- "learning",
58
49
  ],
59
50
  description: "Category of the memory item (required for save)",
60
51
  },