@vellumai/assistant 0.7.0 → 0.7.1

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 (666) hide show
  1. package/ARCHITECTURE.md +6 -7
  2. package/Dockerfile +1 -0
  3. package/README.md +2 -2
  4. package/__tests__/permissions/gateway-threshold-reader.test.ts +79 -139
  5. package/bun.lock +3 -0
  6. package/docs/architecture/security.md +18 -16
  7. package/knip.json +1 -0
  8. package/node_modules/@vellumai/skill-host-contracts/__tests__/client.test.ts +1 -5
  9. package/node_modules/@vellumai/skill-host-contracts/src/assistant-event.ts +0 -5
  10. package/node_modules/@vellumai/skill-host-contracts/src/client.ts +10 -16
  11. package/node_modules/@vellumai/skill-host-contracts/src/skill-host.ts +1 -9
  12. package/node_modules/@vellumai/skill-host-contracts/src/tool-types.ts +12 -12
  13. package/node_modules/@vellumai/slack-text/bun.lock +24 -0
  14. package/node_modules/@vellumai/slack-text/package.json +18 -0
  15. package/node_modules/@vellumai/slack-text/src/index.test.ts +153 -0
  16. package/node_modules/@vellumai/slack-text/src/index.ts +235 -0
  17. package/node_modules/@vellumai/slack-text/tsconfig.json +20 -0
  18. package/openapi.yaml +294 -107
  19. package/package.json +4 -2
  20. package/scripts/generate-openapi.ts +16 -111
  21. package/src/__tests__/agent-wake-override-profile.test.ts +23 -1
  22. package/src/__tests__/anthropic-provider.test.ts +56 -13
  23. package/src/__tests__/app-conversation-ids-backfill.test.ts +278 -0
  24. package/src/__tests__/app-conversation-ids.test.ts +151 -0
  25. package/src/__tests__/approval-cascade.test.ts +0 -15
  26. package/src/__tests__/approval-routes-http.test.ts +6 -17
  27. package/src/__tests__/assistant-event-hub.test.ts +126 -77
  28. package/src/__tests__/assistant-event.test.ts +0 -5
  29. package/src/__tests__/assistant-events-sse-hardening.test.ts +37 -15
  30. package/src/__tests__/assistant-feature-flags-integration.test.ts +0 -29
  31. package/src/__tests__/background-shell-host-bash.test.ts +34 -43
  32. package/src/__tests__/call-controller.test.ts +1 -1
  33. package/src/__tests__/call-site-routing-provider.test.ts +193 -0
  34. package/src/__tests__/channel-approval-routes.test.ts +10 -296
  35. package/src/__tests__/channel-approvals.test.ts +25 -17
  36. package/src/__tests__/channel-guardian.test.ts +100 -146
  37. package/src/__tests__/checker.test.ts +20 -34
  38. package/src/__tests__/compact-event-conversation-id-guard.test.ts +50 -0
  39. package/src/__tests__/compaction-events.test.ts +2 -0
  40. package/src/__tests__/config-schema.test.ts +6 -48
  41. package/src/__tests__/config-watcher.test.ts +12 -0
  42. package/src/__tests__/connection-policy.test.ts +1 -52
  43. package/src/__tests__/contacts-write.test.ts +2 -64
  44. package/src/__tests__/context-image-dimensions.test.ts +1 -1
  45. package/src/__tests__/context-search-memory-source.test.ts +120 -1
  46. package/src/__tests__/context-search-memory-v2-source.test.ts +383 -0
  47. package/src/__tests__/context-search-pkb-source.test.ts +49 -0
  48. package/src/__tests__/context-search-workspace-source.test.ts +9 -22
  49. package/src/__tests__/context-window-manager.test.ts +46 -0
  50. package/src/__tests__/conversation-agent-loop-inference-profile.test.ts +2 -0
  51. package/src/__tests__/conversation-agent-loop-overflow.test.ts +102 -29
  52. package/src/__tests__/conversation-agent-loop.test.ts +980 -13
  53. package/src/__tests__/conversation-analysis-routes.test.ts +12 -10
  54. package/src/__tests__/conversation-attention-telegram.test.ts +11 -3
  55. package/src/__tests__/conversation-confirmation-signals.test.ts +0 -291
  56. package/src/__tests__/conversation-history-web-search.test.ts +4 -3
  57. package/src/__tests__/conversation-inference-profile-route.test.ts +12 -23
  58. package/src/__tests__/conversation-lifecycle.test.ts +4 -4
  59. package/src/__tests__/conversation-process-callsite.test.ts +79 -2
  60. package/src/__tests__/conversation-queue.test.ts +3 -8
  61. package/src/__tests__/conversation-routes-disk-view.test.ts +1 -161
  62. package/src/__tests__/conversation-routes-guardian-reply.test.ts +0 -32
  63. package/src/__tests__/conversation-routes-slash-commands.test.ts +75 -66
  64. package/src/__tests__/conversation-runtime-assembly.test.ts +257 -3
  65. package/src/__tests__/conversation-slash-commands.test.ts +24 -4
  66. package/src/__tests__/conversation-slash-queue.test.ts +2 -0
  67. package/src/__tests__/conversation-speed-override.test.ts +0 -3
  68. package/src/__tests__/conversation-starter-routes.test.ts +79 -2
  69. package/src/__tests__/conversation-surfaces-standalone-payloads.test.ts +12 -5
  70. package/src/__tests__/conversation-surfaces-standalone.test.ts +18 -14
  71. package/src/__tests__/conversation-surfaces-state-update.test.ts +3 -2
  72. package/src/__tests__/conversation-tool-setup-app-refresh.test.ts +8 -46
  73. package/src/__tests__/conversation-usage.test.ts +253 -3
  74. package/src/__tests__/credential-execution-shell-lockdown.test.ts +0 -39
  75. package/src/__tests__/credential-health-service.test.ts +68 -0
  76. package/src/__tests__/credential-security-e2e.test.ts +4 -3
  77. package/src/__tests__/credential-security-invariants.test.ts +1 -5
  78. package/src/__tests__/credential-token-resolver.test.ts +180 -0
  79. package/src/__tests__/cu-unified-flow.test.ts +33 -16
  80. package/src/__tests__/daemon-assistant-events.test.ts +34 -21
  81. package/src/__tests__/daemon-credential-client.test.ts +4 -1
  82. package/src/__tests__/db-connection-isolation.test.ts +125 -0
  83. package/src/__tests__/db-migration-rollback.test.ts +101 -0
  84. package/src/__tests__/db-slack-compaction-watermark-migration.test.ts +169 -0
  85. package/src/__tests__/deterministic-verification-control-plane.test.ts +7 -80
  86. package/src/__tests__/document-conversations.test.ts +332 -0
  87. package/src/__tests__/embedding-managed-proxy-selection.test.ts +2 -2
  88. package/src/__tests__/emit-event-signal.test.ts +4 -6
  89. package/src/__tests__/events-client-registration.test.ts +193 -49
  90. package/src/__tests__/filing-service.test.ts +58 -7
  91. package/src/__tests__/first-greeting.test.ts +156 -150
  92. package/src/__tests__/fixtures/mock-chrome-extension.ts +108 -66
  93. package/src/__tests__/get-skill-detail-audit.test.ts +3 -8
  94. package/src/__tests__/guardian-binding-drift-heal.test.ts +1 -1
  95. package/src/__tests__/guardian-dispatch.test.ts +1 -1
  96. package/src/__tests__/guardian-grant-minting.test.ts +7 -2
  97. package/src/__tests__/guardian-routing-invariants.test.ts +7 -2
  98. package/src/__tests__/guardian-routing-state.test.ts +1 -1
  99. package/src/__tests__/handlers-skills-memory-v2-reseed.test.ts +32 -11
  100. package/src/__tests__/handlers-user-message-approval-consumption.test.ts +2 -83
  101. package/src/__tests__/headless-browser-mode.test.ts +4 -9
  102. package/src/__tests__/headless-browser-navigate.test.ts +21 -20
  103. package/src/__tests__/heartbeat-service.test.ts +289 -7
  104. package/src/__tests__/helpers/channel-test-adapter.ts +2 -2
  105. package/src/__tests__/helpers/create-guardian-binding.ts +91 -0
  106. package/src/__tests__/host-bash-proxy.test.ts +46 -122
  107. package/src/__tests__/host-browser-e2e-cloud.test.ts +36 -497
  108. package/src/__tests__/host-browser-e2e-self-hosted-capability.test.ts +26 -96
  109. package/src/__tests__/host-browser-proxy.test.ts +111 -185
  110. package/src/__tests__/host-browser-routes.test.ts +45 -75
  111. package/src/__tests__/host-browser-ws-events-e2e.test.ts +26 -30
  112. package/src/__tests__/host-cu-proxy.test.ts +56 -111
  113. package/src/__tests__/host-file-proxy.test.ts +44 -98
  114. package/src/__tests__/host-file-read-tool.test.ts +42 -21
  115. package/src/__tests__/host-shell-tool.test.ts +33 -68
  116. package/src/__tests__/host-transfer-pending-interactions.test.ts +2 -18
  117. package/src/__tests__/host-transfer-proxy.test.ts +43 -53
  118. package/src/__tests__/http-user-message-parity.test.ts +0 -6
  119. package/src/__tests__/inbound-slack-persistence.test.ts +31 -0
  120. package/src/__tests__/injector-chain.test.ts +10 -5
  121. package/src/__tests__/injector-pkb-v2-silenced.test.ts +124 -0
  122. package/src/__tests__/inline-command-runner.test.ts +0 -66
  123. package/src/__tests__/inline-skill-load-permissions.test.ts +0 -2
  124. package/src/__tests__/install-skill-routing.test.ts +1 -13
  125. package/src/__tests__/llm-callsite-catalog.test.ts +34 -0
  126. package/src/__tests__/llm-catalog-parity.test.ts +90 -0
  127. package/src/__tests__/llm-context-resolution.test.ts +180 -0
  128. package/src/__tests__/llm-resolver.test.ts +80 -12
  129. package/src/__tests__/llm-usage-store.test.ts +269 -4
  130. package/src/__tests__/log-export-routes.test.ts +89 -0
  131. package/src/__tests__/managed-profile-guard.test.ts +225 -0
  132. package/src/__tests__/managed-skill-lifecycle.test.ts +0 -10
  133. package/src/__tests__/manual-token-reconciliation.test.ts +334 -0
  134. package/src/__tests__/memory-v2-static-injector.test.ts +95 -0
  135. package/src/__tests__/migration-cross-version-compatibility.test.ts +197 -291
  136. package/src/__tests__/migration-export-http.test.ts +33 -26
  137. package/src/__tests__/migration-export-streaming.test.ts +18 -10
  138. package/src/__tests__/migration-export-to-gcs.test.ts +49 -9
  139. package/src/__tests__/migration-import-commit-http.test.ts +66 -21
  140. package/src/__tests__/migration-import-from-gcs.test.ts +50 -9
  141. package/src/__tests__/migration-import-from-url.test.ts +20 -6
  142. package/src/__tests__/migration-import-preflight-http.test.ts +95 -95
  143. package/src/__tests__/migration-parity-persistence.test.ts +62 -25
  144. package/src/__tests__/migration-transport.test.ts +115 -23
  145. package/src/__tests__/migration-validate-http.test.ts +105 -80
  146. package/src/__tests__/migration-wizard.test.ts +133 -27
  147. package/src/__tests__/non-member-access-request.test.ts +1 -1
  148. package/src/__tests__/notification-guardian-path.test.ts +1 -1
  149. package/src/__tests__/oauth-store.test.ts +19 -0
  150. package/src/__tests__/platform-bash-auto-approve.test.ts +21 -12
  151. package/src/__tests__/prechat-onboarding-contract.test.ts +31 -7
  152. package/src/__tests__/pricing.test.ts +68 -4
  153. package/src/__tests__/process-message-background-slack.test.ts +331 -0
  154. package/src/__tests__/provider-managed-proxy-integration.test.ts +153 -17
  155. package/src/__tests__/provider-send-message-override-profile.test.ts +50 -0
  156. package/src/__tests__/provider-usage-tracking.test.ts +208 -0
  157. package/src/__tests__/reaction-persistence.test.ts +9 -6
  158. package/src/__tests__/rebind-secrets-screen.test.ts +53 -16
  159. package/src/__tests__/recording-handler.test.ts +64 -81
  160. package/src/__tests__/regenerate-fire-and-forget-trace.test.ts +4 -3
  161. package/src/__tests__/relay-server.test.ts +18 -13
  162. package/src/__tests__/require-fresh-approval.test.ts +13 -22
  163. package/src/__tests__/runtime-attachment-metadata.test.ts +1 -1
  164. package/src/__tests__/runtime-events-sse-parity.test.ts +3 -4
  165. package/src/__tests__/runtime-events-sse.test.ts +3 -12
  166. package/src/__tests__/search-skills-unified.test.ts +9 -15
  167. package/src/__tests__/secret-ingress-cli.test.ts +2 -5
  168. package/src/__tests__/secret-ingress-http.test.ts +0 -4
  169. package/src/__tests__/secret-onetime-send.test.ts +4 -2
  170. package/src/__tests__/secret-prompt-log-hygiene.test.ts +24 -7
  171. package/src/__tests__/secret-prompter-channel-fallback.test.ts +42 -47
  172. package/src/__tests__/secret-response-routing.test.ts +29 -15
  173. package/src/__tests__/secret-routes-managed-proxy.test.ts +5 -1
  174. package/src/__tests__/secret-scanner.test.ts +2 -545
  175. package/src/__tests__/send-endpoint-busy.test.ts +9 -24
  176. package/src/__tests__/settings-routes.test.ts +1 -1
  177. package/src/__tests__/shell-credential-ref.test.ts +0 -8
  178. package/src/__tests__/shell-tool-proxy-mode.test.ts +0 -56
  179. package/src/__tests__/skill-script-runner-sandbox.test.ts +0 -11
  180. package/src/__tests__/skill-tool-factory.test.ts +97 -0
  181. package/src/__tests__/skills-file-content-endpoint.test.ts +9 -30
  182. package/src/__tests__/skills-files-catalog-fallback.test.ts +11 -17
  183. package/src/__tests__/slack-inbound-verification.test.ts +1 -62
  184. package/src/__tests__/subagent-fork-notifications.test.ts +57 -47
  185. package/src/__tests__/subagent-manager-notify.test.ts +70 -70
  186. package/src/__tests__/subagent-notify-parent.test.ts +80 -83
  187. package/src/__tests__/system-prompt.test.ts +115 -13
  188. package/src/__tests__/terminal-tools.test.ts +0 -89
  189. package/src/__tests__/thread-backfill.test.ts +945 -31
  190. package/src/__tests__/tool-domain-event-publisher.test.ts +0 -36
  191. package/src/__tests__/tool-execute-pipeline.test.ts +0 -6
  192. package/src/__tests__/tool-execution-abort-cleanup.test.ts +0 -16
  193. package/src/__tests__/tool-execution-pipeline.benchmark.test.ts +9 -19
  194. package/src/__tests__/tool-executor-lifecycle-events.test.ts +4 -7
  195. package/src/__tests__/tool-executor.test.ts +12 -19
  196. package/src/__tests__/tool-metrics-listener.test.ts +0 -35
  197. package/src/__tests__/tool-side-effects-slack-dm.test.ts +1 -0
  198. package/src/__tests__/tool-trace-listener.test.ts +0 -17
  199. package/src/__tests__/transfer-progress-screen.test.ts +63 -26
  200. package/src/__tests__/trusted-contact-lifecycle-notifications.test.ts +2 -149
  201. package/src/__tests__/trusted-contact-multichannel.test.ts +2 -4
  202. package/src/__tests__/trusted-contact-verification.test.ts +1 -1
  203. package/src/__tests__/tts-catalog-parity.test.ts +16 -5
  204. package/src/__tests__/usage-attribution.test.ts +247 -0
  205. package/src/__tests__/usage-cli.test.ts +143 -0
  206. package/src/__tests__/usage-grouped-buckets.test.ts +155 -0
  207. package/src/__tests__/usage-routes.test.ts +150 -0
  208. package/src/__tests__/validation-results-screen.test.ts +39 -16
  209. package/src/__tests__/vbundle-pax-and-symlink.test.ts +12 -3
  210. package/src/__tests__/vellum-self-knowledge-inline-command.test.ts +49 -137
  211. package/src/__tests__/verification-control-plane-policy.test.ts +4 -7
  212. package/src/__tests__/voice-session-bridge.test.ts +5 -5
  213. package/src/__tests__/workspace-migration-062-drop-memory-v2-edges-json.test.ts +103 -0
  214. package/src/__tests__/workspace-migration-063-release-notes-dynamic-model-context.test.ts +77 -0
  215. package/src/__tests__/workspace-migration-064-unwind-main-agent-opus-seed.test.ts +225 -0
  216. package/src/__tests__/workspace-migration-memory-v2-init.test.ts +8 -30
  217. package/src/acp/index.ts +0 -15
  218. package/src/acp/session-manager.ts +37 -34
  219. package/src/agent/loop.ts +16 -1
  220. package/src/approvals/AGENTS.md +4 -0
  221. package/src/approvals/__tests__/guardian-feed-event.test.ts +10 -3
  222. package/src/approvals/guardian-request-resolvers.ts +10 -2
  223. package/src/backup/__tests__/backup-worker.test.ts +36 -8
  224. package/src/backup/__tests__/paths.test.ts +2 -2
  225. package/src/backup/__tests__/restore.test.ts +45 -28
  226. package/src/backup/backup-worker.ts +36 -2
  227. package/src/backup/paths.ts +9 -6
  228. package/src/browser-session/events.ts +0 -9
  229. package/src/calls/call-store.ts +1 -34
  230. package/src/calls/guardian-question-copy.ts +0 -108
  231. package/src/calls/relay-server.ts +0 -24
  232. package/src/calls/twilio-rest.ts +0 -38
  233. package/src/calls/twilio-routes.ts +1 -1
  234. package/src/calls/voice-session-bridge.ts +7 -38
  235. package/src/channels/types.ts +1 -36
  236. package/src/cli/commands/__tests__/cache.test.ts +152 -5
  237. package/src/cli/commands/__tests__/memory-v2.test.ts +14 -28
  238. package/src/cli/commands/__tests__/trust.test.ts +21 -387
  239. package/src/cli/commands/backup.ts +4 -4
  240. package/src/cli/commands/cache-fs.ts +8 -0
  241. package/src/cli/commands/cache.ts +153 -82
  242. package/src/cli/commands/clients.ts +63 -5
  243. package/src/cli/commands/completions.ts +3 -3
  244. package/src/cli/commands/contacts.ts +231 -76
  245. package/src/cli/commands/keys.ts +4 -1
  246. package/src/cli/commands/memory-v2.ts +24 -52
  247. package/src/cli/commands/oauth/shared.ts +2 -29
  248. package/src/cli/commands/pending.ts +102 -0
  249. package/src/cli/commands/skills.ts +77 -35
  250. package/src/cli/commands/trust.ts +70 -430
  251. package/src/cli/commands/usage.ts +25 -16
  252. package/src/cli/lib/daemon-credential-client.ts +14 -0
  253. package/src/cli/program.ts +2 -0
  254. package/src/cli.ts +0 -21
  255. package/src/config/__tests__/feature-flag-registry-guard.test.ts +2 -2
  256. package/src/config/bundled-skills/messaging/TOOLS.json +14 -4
  257. package/src/config/env-registry.ts +12 -2
  258. package/src/config/env.ts +3 -14
  259. package/src/config/feature-flag-registry.json +30 -30
  260. package/src/config/llm-callsite-catalog.ts +12 -0
  261. package/src/config/llm-context-resolution.ts +80 -0
  262. package/src/config/llm-resolver.ts +58 -22
  263. package/src/config/loader.ts +3 -3
  264. package/src/config/schema.ts +2 -158
  265. package/src/config/schemas/__tests__/memory-v2.test.ts +1 -0
  266. package/src/config/schemas/call-site-catalog.ts +271 -0
  267. package/src/config/schemas/calls.ts +5 -5
  268. package/src/config/schemas/inference.ts +1 -1
  269. package/src/config/schemas/ingress.ts +1 -1
  270. package/src/config/schemas/llm.ts +31 -3
  271. package/src/config/schemas/memory-retrieval.ts +2 -2
  272. package/src/config/schemas/memory-v2.ts +9 -0
  273. package/src/config/schemas/security.ts +1 -42
  274. package/src/config/schemas/services.ts +6 -6
  275. package/src/config/schemas/skills.ts +5 -5
  276. package/src/config/schemas/tts.ts +1 -1
  277. package/src/config/seed-inference-profiles.ts +117 -0
  278. package/src/config/skills.ts +0 -90
  279. package/src/config/types.ts +3 -6
  280. package/src/contacts/contact-store.ts +0 -17
  281. package/src/contacts/contacts-write.ts +1 -105
  282. package/src/context/window-manager.ts +44 -5
  283. package/src/credential-execution/process-manager.ts +34 -10
  284. package/src/credential-health/credential-health-service.ts +21 -16
  285. package/src/daemon/__tests__/conversation-surfaces-launch.test.ts +75 -82
  286. package/src/daemon/__tests__/daemon-skill-host.test.ts +2 -9
  287. package/src/daemon/connection-policy.ts +1 -26
  288. package/src/daemon/conversation-agent-loop-handlers.ts +53 -4
  289. package/src/daemon/conversation-agent-loop.ts +277 -36
  290. package/src/daemon/conversation-history.ts +8 -8
  291. package/src/daemon/conversation-launch.ts +20 -135
  292. package/src/daemon/conversation-lifecycle.ts +1 -1
  293. package/src/daemon/conversation-messaging.ts +1 -0
  294. package/src/daemon/conversation-process.ts +83 -163
  295. package/src/daemon/conversation-runtime-assembly.ts +219 -76
  296. package/src/daemon/conversation-slash.ts +47 -5
  297. package/src/daemon/conversation-store.ts +7 -31
  298. package/src/daemon/conversation-surfaces.ts +22 -28
  299. package/src/daemon/conversation-tool-setup.ts +3 -33
  300. package/src/daemon/conversation-usage.ts +36 -0
  301. package/src/daemon/conversation.ts +117 -233
  302. package/src/daemon/daemon-control.ts +3 -71
  303. package/src/daemon/daemon-skill-host.ts +8 -11
  304. package/src/daemon/dictation-profile-store.ts +2 -26
  305. package/src/daemon/first-greeting.ts +44 -156
  306. package/src/daemon/handlers/config-channels.ts +12 -12
  307. package/src/daemon/handlers/config-ingress.ts +4 -165
  308. package/src/daemon/handlers/config-model.ts +1 -1
  309. package/src/daemon/handlers/config-voice.ts +0 -42
  310. package/src/daemon/handlers/conversations.ts +11 -190
  311. package/src/daemon/handlers/recording.ts +26 -158
  312. package/src/daemon/handlers/shared.ts +23 -71
  313. package/src/daemon/handlers/skills.ts +42 -93
  314. package/src/daemon/host-bash-proxy.ts +67 -45
  315. package/src/daemon/host-browser-proxy.ts +65 -27
  316. package/src/daemon/host-cu-proxy.ts +40 -39
  317. package/src/daemon/host-file-proxy.ts +58 -37
  318. package/src/daemon/host-transfer-proxy.ts +84 -46
  319. package/src/daemon/lifecycle.ts +49 -15
  320. package/src/daemon/message-types/conversations.ts +7 -0
  321. package/src/daemon/message-types/host-bash.ts +1 -0
  322. package/src/daemon/message-types/host-cu.ts +1 -0
  323. package/src/daemon/message-types/host-file.ts +1 -0
  324. package/src/daemon/message-types/host-transfer.ts +1 -0
  325. package/src/daemon/message-types/messages.ts +10 -9
  326. package/src/daemon/message-types/workspace.ts +1 -1
  327. package/src/daemon/process-message.ts +102 -239
  328. package/src/daemon/server.ts +13 -462
  329. package/src/daemon/shutdown-handlers.ts +2 -2
  330. package/src/daemon/tool-side-effects.ts +125 -107
  331. package/src/daemon/trust-context.ts +13 -0
  332. package/src/daemon/wake-target-adapter.ts +4 -9
  333. package/src/events/domain-events.ts +0 -8
  334. package/src/events/tool-audit-listener.ts +3 -1
  335. package/src/events/tool-domain-event-publisher.ts +0 -10
  336. package/src/events/tool-metrics-listener.ts +0 -17
  337. package/src/events/tool-trace-listener.ts +0 -14
  338. package/src/filing/filing-service.ts +13 -1
  339. package/src/heartbeat/__tests__/heartbeat-feed-event.test.ts +6 -2
  340. package/src/heartbeat/heartbeat-service.ts +23 -5
  341. package/src/home/__tests__/feed-writer.test.ts +0 -4
  342. package/src/home/__tests__/relationship-state-writer.test.ts +30 -0
  343. package/src/home/feed-writer.ts +1 -2
  344. package/src/home/relationship-state-writer.ts +16 -3
  345. package/src/ipc/__tests__/browser-ipc.test.ts +2 -12
  346. package/src/ipc/__tests__/skill-server-bidirectional.test.ts +0 -1
  347. package/src/ipc/assistant-server.ts +3 -10
  348. package/src/ipc/routes/__tests__/memory-v2-backfill.test.ts +39 -20
  349. package/src/ipc/routes/route-adapter.ts +1 -1
  350. package/src/ipc/routes/trust-rules.test.ts +0 -95
  351. package/src/ipc/skill-ipc-types.ts +41 -0
  352. package/src/ipc/skill-routes/__tests__/events-ipc.test.ts +13 -27
  353. package/src/ipc/skill-routes/__tests__/identity.test.ts +4 -23
  354. package/src/ipc/skill-routes/events.ts +12 -23
  355. package/src/ipc/skill-routes/identity.ts +4 -17
  356. package/src/ipc/skill-routes/index.ts +1 -1
  357. package/src/ipc/skill-server.ts +6 -39
  358. package/src/live-voice/__tests__/runtime-websocket-shell.test.ts +0 -8
  359. package/src/live-voice/protocol.ts +4 -13
  360. package/src/mcp/manager.ts +0 -5
  361. package/src/memory/__tests__/fixtures/memory-v2-activation-fixtures.ts +55 -0
  362. package/src/memory/__tests__/memory-v2-activation-log-store.test.ts +127 -0
  363. package/src/memory/app-git-service.ts +0 -32
  364. package/src/memory/app-store.ts +154 -0
  365. package/src/memory/attachments-store.ts +6 -0
  366. package/src/memory/context-search/sources/memory-v2.ts +578 -0
  367. package/src/memory/context-search/sources/memory.ts +5 -0
  368. package/src/memory/context-search/sources/pkb.ts +10 -1
  369. package/src/memory/context-search/sources/workspace.ts +3 -2
  370. package/src/memory/conversation-crud.ts +29 -4
  371. package/src/memory/conversation-disk-view.ts +1 -5
  372. package/src/memory/conversation-starter-checkpoints.ts +63 -0
  373. package/src/memory/db-connection.ts +62 -0
  374. package/src/memory/db-init.ts +14 -0
  375. package/src/memory/embedding-backend.ts +3 -21
  376. package/src/memory/embedding-gemini.ts +0 -2
  377. package/src/memory/embedding-local.ts +6 -6
  378. package/src/memory/embedding-ollama.ts +6 -6
  379. package/src/memory/embedding-openai.ts +6 -6
  380. package/src/memory/embedding-types.ts +21 -0
  381. package/src/memory/graph/__tests__/conversation-graph-memory-v2-routing.test.ts +3 -7
  382. package/src/memory/graph/conversation-graph-memory.ts +35 -13
  383. package/src/memory/graph/injection.test.ts +2 -2
  384. package/src/memory/graph/injection.ts +1 -1
  385. package/src/memory/guardian-action-store.ts +0 -83
  386. package/src/memory/guardian-approvals.ts +0 -48
  387. package/src/memory/indexer.ts +1 -15
  388. package/src/memory/job-handlers/conversation-starters.ts +36 -53
  389. package/src/memory/job-utils.ts +0 -6
  390. package/src/memory/jobs-store.ts +0 -1
  391. package/src/memory/jobs-worker.ts +2 -16
  392. package/src/memory/llm-request-log-store.ts +0 -41
  393. package/src/memory/llm-usage-store.ts +129 -43
  394. package/src/memory/memory-v2-activation-log-store.ts +115 -0
  395. package/src/memory/migrations/233-document-conversations.ts +54 -0
  396. package/src/memory/migrations/234-memory-v2-activation-logs.ts +55 -0
  397. package/src/memory/migrations/235-llm-usage-attribution.ts +31 -0
  398. package/src/memory/migrations/235-slack-compaction-watermark.ts +44 -0
  399. package/src/memory/migrations/236-tool-invocations-matched-rule-id.ts +26 -0
  400. package/src/memory/migrations/__tests__/234-memory-v2-activation-logs.test.ts +182 -0
  401. package/src/memory/migrations/index.ts +14 -0
  402. package/src/memory/migrations/registry.ts +24 -0
  403. package/src/memory/raw-query.ts +2 -68
  404. package/src/memory/schema/conversations.ts +7 -0
  405. package/src/memory/schema/infrastructure.ts +25 -0
  406. package/src/memory/search/semantic.ts +5 -16
  407. package/src/memory/tool-usage-store.ts +2 -0
  408. package/src/memory/usage-buckets.ts +40 -1
  409. package/src/memory/usage-grouped-buckets.ts +127 -0
  410. package/src/memory/v2/__tests__/activation.test.ts +289 -90
  411. package/src/memory/v2/__tests__/backfill-jobs.test.ts +2 -129
  412. package/src/memory/v2/__tests__/consolidation-job.test.ts +28 -11
  413. package/src/memory/v2/__tests__/edge-index.test.ts +278 -0
  414. package/src/memory/v2/__tests__/injection.test.ts +384 -15
  415. package/src/memory/v2/__tests__/migration.test.ts +64 -36
  416. package/src/memory/v2/__tests__/page-store.test.ts +191 -8
  417. package/src/memory/v2/__tests__/prompts-consolidation.test.ts +181 -0
  418. package/src/memory/v2/__tests__/skill-store.test.ts +115 -3
  419. package/src/memory/v2/__tests__/static-context.test.ts +153 -0
  420. package/src/memory/v2/activation.ts +168 -97
  421. package/src/memory/v2/backfill-jobs.ts +15 -100
  422. package/src/memory/v2/consolidation-job.ts +14 -12
  423. package/src/memory/v2/edge-index.ts +191 -0
  424. package/src/memory/v2/injection.ts +182 -58
  425. package/src/memory/v2/migration.ts +57 -64
  426. package/src/memory/v2/now-text.ts +2 -3
  427. package/src/memory/v2/page-store.ts +168 -31
  428. package/src/memory/v2/prompts/consolidation.ts +118 -42
  429. package/src/memory/v2/prompts/sweep.ts +3 -3
  430. package/src/memory/v2/skill-store.ts +55 -7
  431. package/src/memory/v2/static-context.ts +62 -0
  432. package/src/memory/v2/types.ts +10 -20
  433. package/src/memory/validation.ts +0 -11
  434. package/src/messaging/draft-store.ts +0 -6
  435. package/src/messaging/provider-types.ts +8 -0
  436. package/src/messaging/provider.ts +7 -0
  437. package/src/messaging/providers/gmail/client.ts +1 -121
  438. package/src/messaging/providers/outlook/client.ts +0 -73
  439. package/src/messaging/providers/slack/__tests__/adapter-mention-rendering.test.ts +226 -0
  440. package/src/messaging/providers/slack/adapter.ts +122 -21
  441. package/src/messaging/providers/slack/backfill.test.ts +95 -6
  442. package/src/messaging/providers/slack/backfill.ts +89 -11
  443. package/src/messaging/providers/slack/client.ts +10 -124
  444. package/src/messaging/providers/slack/message-metadata.ts +12 -2
  445. package/src/messaging/providers/slack/render-transcript.test.ts +56 -0
  446. package/src/messaging/providers/slack/render-transcript.ts +126 -25
  447. package/src/messaging/providers/slack/types.ts +1 -0
  448. package/src/oauth/connection-resolver.test.ts +8 -0
  449. package/src/oauth/connection-resolver.ts +8 -16
  450. package/src/oauth/credential-token-resolver.ts +97 -0
  451. package/src/oauth/manual-token-connection.ts +30 -34
  452. package/src/oauth/oauth-store.ts +6 -4
  453. package/src/outbound-proxy/certs.ts +0 -7
  454. package/src/outbound-proxy/config.ts +0 -74
  455. package/src/outbound-proxy/health.ts +0 -44
  456. package/src/outbound-proxy/index.ts +0 -22
  457. package/src/permissions/approval-provenance.test.ts +184 -0
  458. package/src/permissions/approval-provenance.ts +70 -0
  459. package/src/permissions/checker.ts +4 -1
  460. package/src/permissions/gateway-threshold-reader.ts +4 -1
  461. package/src/permissions/prompter.ts +9 -2
  462. package/src/permissions/secret-prompter.ts +21 -48
  463. package/src/permissions/types.ts +33 -0
  464. package/src/permissions/workspace-policy.ts +0 -5
  465. package/src/platform/sync-identity.ts +0 -8
  466. package/src/plugins/defaults/injectors.ts +69 -2
  467. package/src/plugins/defaults/overflow-reduce.ts +3 -2
  468. package/src/plugins/types.ts +8 -0
  469. package/src/prompts/system-prompt.ts +34 -70
  470. package/src/prompts/templates/BOOTSTRAP.md +52 -6
  471. package/src/prompts/update-bulletin-job.ts +2 -0
  472. package/src/providers/__tests__/retry-callsite.test.ts +138 -1
  473. package/src/providers/anthropic/client.ts +72 -33
  474. package/src/providers/call-site-routing.ts +42 -3
  475. package/src/providers/gemini/client.ts +18 -2
  476. package/src/providers/managed-proxy/context.ts +0 -5
  477. package/src/providers/model-catalog.ts +105 -19
  478. package/src/providers/openai/chat-completions-provider.ts +6 -0
  479. package/src/providers/openai/responses-provider.ts +7 -1
  480. package/src/providers/provider-send-message.ts +45 -2
  481. package/src/providers/ratelimit.ts +7 -2
  482. package/src/providers/registry.ts +14 -9
  483. package/src/providers/retry.ts +96 -8
  484. package/src/providers/types.ts +13 -0
  485. package/src/providers/usage-tracking.ts +96 -0
  486. package/src/runtime/AGENTS.md +10 -6
  487. package/src/runtime/__tests__/agent-wake.test.ts +89 -0
  488. package/src/runtime/agent-wake.ts +39 -2
  489. package/src/runtime/assistant-event-hub.ts +541 -45
  490. package/src/runtime/assistant-event.ts +1 -6
  491. package/src/runtime/auth/context.ts +0 -9
  492. package/src/runtime/auth/middleware.ts +1 -1
  493. package/src/runtime/auth/route-policy.ts +11 -9
  494. package/src/runtime/auth/token-service.ts +0 -11
  495. package/src/runtime/channel-approvals.ts +6 -2
  496. package/src/runtime/channel-verification-service.ts +3 -5
  497. package/src/runtime/http-errors.ts +0 -34
  498. package/src/runtime/http-router.ts +6 -3
  499. package/src/runtime/http-server.ts +22 -82
  500. package/src/runtime/http-types.ts +5 -0
  501. package/src/runtime/interactive-ui.ts +0 -1
  502. package/src/runtime/middleware/auth.ts +0 -20
  503. package/src/runtime/migrations/__tests__/v1-test-helpers.ts +112 -0
  504. package/src/runtime/migrations/__tests__/vbundle-builder-credentials.test.ts +11 -4
  505. package/src/runtime/migrations/__tests__/vbundle-builder-v1-shape.test.ts +253 -0
  506. package/src/runtime/migrations/__tests__/vbundle-import-credentials.test.ts +19 -6
  507. package/src/runtime/migrations/__tests__/vbundle-legacy-user-md.test.ts +71 -27
  508. package/src/runtime/migrations/__tests__/vbundle-metadata-merge-integration.test.ts +41 -2
  509. package/src/runtime/migrations/__tests__/vbundle-streaming-importer.test.ts +143 -79
  510. package/src/runtime/migrations/__tests__/vbundle-streaming-validator.test.ts +143 -23
  511. package/src/runtime/migrations/__tests__/vbundle-tar-stream.test.ts +2 -2
  512. package/src/runtime/migrations/__tests__/vbundle-validator-v1-schema.test.ts +371 -0
  513. package/src/runtime/migrations/migration-transport.ts +46 -13
  514. package/src/runtime/migrations/migration-wizard.ts +2 -2
  515. package/src/runtime/migrations/origin-mode.ts +40 -0
  516. package/src/runtime/migrations/vbundle-builder.ts +133 -79
  517. package/src/runtime/migrations/vbundle-import-analyzer.ts +9 -7
  518. package/src/runtime/migrations/vbundle-importer.ts +7 -7
  519. package/src/runtime/migrations/vbundle-metadata-merge.ts +1 -1
  520. package/src/runtime/migrations/vbundle-streaming-importer.ts +3 -3
  521. package/src/runtime/migrations/vbundle-streaming-validator.ts +48 -26
  522. package/src/runtime/migrations/vbundle-validator.ts +214 -41
  523. package/src/runtime/pending-interactions.ts +13 -4
  524. package/src/runtime/routes/__tests__/acp-routes.test.ts +0 -1
  525. package/src/runtime/routes/__tests__/backup-routes.test.ts +28 -19
  526. package/src/runtime/routes/__tests__/conversation-query-routes.test.ts +235 -0
  527. package/src/runtime/routes/__tests__/llm-call-sites-routes.test.ts +58 -0
  528. package/src/runtime/routes/__tests__/migration-export-secrets-redacted.test.ts +54 -0
  529. package/src/runtime/routes/__tests__/migration-import-credential-filter.test.ts +19 -6
  530. package/src/runtime/routes/__tests__/user-route-dispatcher.test.ts +7 -7
  531. package/src/runtime/routes/acp-routes.test.ts +0 -3
  532. package/src/runtime/routes/acp-routes.ts +3 -7
  533. package/src/runtime/routes/app-management-routes.ts +18 -9
  534. package/src/runtime/routes/approval-routes.ts +55 -14
  535. package/src/runtime/routes/avatar-routes.ts +3 -5
  536. package/src/runtime/routes/browser-routes.ts +1 -15
  537. package/src/runtime/routes/channel-guardian-routes.ts +1 -5
  538. package/src/runtime/routes/channel-readiness-routes.ts +3 -7
  539. package/src/runtime/routes/channel-route-shared.ts +2 -28
  540. package/src/runtime/routes/client-routes.ts +45 -12
  541. package/src/runtime/routes/consolidation-routes.ts +115 -0
  542. package/src/runtime/routes/conversation-list-routes.ts +12 -29
  543. package/src/runtime/routes/conversation-management-routes.ts +14 -51
  544. package/src/runtime/routes/conversation-query-routes.ts +120 -8
  545. package/src/runtime/routes/conversation-routes.ts +44 -528
  546. package/src/runtime/routes/conversation-starter-routes.ts +19 -40
  547. package/src/runtime/routes/documents-routes.ts +53 -18
  548. package/src/runtime/routes/events-routes.ts +59 -91
  549. package/src/runtime/routes/filing-routes.ts +18 -1
  550. package/src/runtime/routes/guardian-action-routes.ts +4 -9
  551. package/src/runtime/routes/host-bash-routes.ts +3 -2
  552. package/src/runtime/routes/host-browser-routes.ts +9 -33
  553. package/src/runtime/routes/host-cu-routes.ts +6 -1
  554. package/src/runtime/routes/host-file-routes.ts +3 -2
  555. package/src/runtime/routes/host-transfer-routes.ts +11 -15
  556. package/src/runtime/routes/identity-routes.ts +78 -6
  557. package/src/runtime/routes/inbound-message-handler.ts +580 -137
  558. package/src/runtime/routes/inbound-stages/acl-enforcement.ts +2 -88
  559. package/src/runtime/routes/inbound-stages/background-dispatch.ts +3 -0
  560. package/src/runtime/routes/index.ts +4 -0
  561. package/src/runtime/routes/integrations/slack/channel.ts +0 -24
  562. package/src/runtime/routes/llm-call-sites-routes.ts +22 -0
  563. package/src/runtime/routes/memory-v2-routes.ts +10 -15
  564. package/src/runtime/routes/migration-routes.ts +188 -31
  565. package/src/runtime/routes/playground/guard.ts +1 -1
  566. package/src/runtime/routes/playground/index.ts +0 -2
  567. package/src/runtime/routes/recording-routes.ts +4 -24
  568. package/src/runtime/routes/rename-conversation-routes.ts +2 -6
  569. package/src/runtime/routes/schedule-routes.ts +3 -6
  570. package/src/runtime/routes/secret-routes.ts +87 -18
  571. package/src/runtime/routes/settings-routes.ts +29 -28
  572. package/src/runtime/routes/skills-routes.ts +12 -31
  573. package/src/runtime/routes/suggest-trust-rule-routes.ts +32 -1
  574. package/src/runtime/routes/task-routes.ts +6 -6
  575. package/src/runtime/routes/trust-rules-routes.ts +3 -94
  576. package/src/runtime/routes/types.ts +4 -4
  577. package/src/runtime/routes/upgrade-broadcast-routes.ts +3 -10
  578. package/src/runtime/routes/usage-routes.ts +87 -10
  579. package/src/runtime/routes/user-routes.ts +17 -31
  580. package/src/runtime/routes/work-items-routes.ts +1 -4
  581. package/src/runtime/services/__tests__/analyze-conversation.test.ts +2 -2
  582. package/src/runtime/services/analyze-conversation.ts +7 -17
  583. package/src/runtime/services/conversation-serializer.ts +2 -4
  584. package/src/runtime/verification-outbound-actions.ts +1 -1
  585. package/src/runtime/verification-rate-limiter.ts +1 -1
  586. package/src/schedule/schedule-store.ts +0 -16
  587. package/src/security/secret-scanner.ts +14 -547
  588. package/src/security/secure-keys.ts +31 -11
  589. package/src/security/token-manager.ts +7 -3
  590. package/src/signals/cancel.ts +16 -25
  591. package/src/signals/conversation-undo.ts +2 -27
  592. package/src/signals/emit-event.ts +1 -2
  593. package/src/signals/user-message.ts +108 -22
  594. package/src/skills/catalog-install.ts +1 -0
  595. package/src/skills/clawhub.ts +2 -2
  596. package/src/skills/inline-command-runner.ts +1 -7
  597. package/src/subagent/manager.ts +67 -84
  598. package/src/tasks/task-store.ts +1 -28
  599. package/src/telemetry/types.ts +6 -0
  600. package/src/telemetry/usage-telemetry-reporter.test.ts +38 -15
  601. package/src/telemetry/usage-telemetry-reporter.ts +3 -5
  602. package/src/tools/acp/spawn.test.ts +1 -2
  603. package/src/tools/acp/steer.test.ts +1 -2
  604. package/src/tools/browser/__tests__/browser-status.test.ts +44 -127
  605. package/src/tools/browser/browser-execution.ts +31 -147
  606. package/src/tools/browser/cdp-client/__tests__/factory.test.ts +92 -68
  607. package/src/tools/browser/cdp-client/factory.ts +48 -76
  608. package/src/tools/browser/cdp-client/index.ts +1 -14
  609. package/src/tools/executor.ts +44 -31
  610. package/src/tools/host-filesystem/edit.ts +3 -2
  611. package/src/tools/host-filesystem/read.ts +3 -2
  612. package/src/tools/host-filesystem/transfer.test.ts +45 -42
  613. package/src/tools/host-filesystem/transfer.ts +4 -3
  614. package/src/tools/host-filesystem/write.ts +3 -2
  615. package/src/tools/host-terminal/host-shell.ts +4 -3
  616. package/src/tools/network/script-proxy/index.ts +1 -10
  617. package/src/tools/permission-checker.ts +66 -1
  618. package/src/tools/skills/sandbox-runner.ts +1 -6
  619. package/src/tools/skills/skill-tool-factory.ts +32 -0
  620. package/src/tools/terminal/safe-env.ts +1 -0
  621. package/src/tools/terminal/shell.ts +2 -78
  622. package/src/tools/types.ts +12 -39
  623. package/src/tts/__tests__/provider-catalog.test.ts +2 -2
  624. package/src/tts/provider-catalog.ts +1 -1
  625. package/src/usage/actors.ts +2 -1
  626. package/src/usage/attribution.ts +185 -0
  627. package/src/usage/pricing.ts +166 -0
  628. package/src/usage/types.ts +14 -0
  629. package/src/util/json.ts +13 -0
  630. package/src/util/logger.ts +3 -3
  631. package/src/util/pricing.ts +50 -3
  632. package/src/work-items/work-item-runner.ts +15 -42
  633. package/src/workspace/migrations/050-seed-main-agent-opus-callsite.ts +4 -3
  634. package/src/workspace/migrations/052-seed-default-inference-profiles.ts +3 -3
  635. package/src/workspace/migrations/060-memory-v2-init.ts +2 -18
  636. package/src/workspace/migrations/061-move-backup-key-to-workspace.ts +59 -0
  637. package/src/workspace/migrations/062-drop-memory-v2-edges-json.ts +27 -0
  638. package/src/workspace/migrations/063-release-notes-dynamic-model-context.ts +70 -0
  639. package/src/workspace/migrations/064-unwind-main-agent-opus-seed.ts +64 -0
  640. package/src/workspace/migrations/registry.ts +8 -0
  641. package/src/workspace/provider-commit-message-generator.ts +3 -3
  642. package/src/__tests__/sandbox-diagnostics.test.ts +0 -138
  643. package/src/__tests__/sandbox-host-parity.test.ts +0 -1024
  644. package/src/__tests__/secret-detection-handler.test.ts +0 -67
  645. package/src/__tests__/secret-scanner-executor.test.ts +0 -450
  646. package/src/__tests__/tcc-sandbox-deny.test.ts +0 -198
  647. package/src/__tests__/terminal-sandbox.test.ts +0 -374
  648. package/src/__tests__/tool-notification-listener.test.ts +0 -65
  649. package/src/context/__tests__/microcompact.test.ts +0 -805
  650. package/src/context/microcompact.ts +0 -443
  651. package/src/daemon/handlers/slack-channel-oauth-install.ts +0 -197
  652. package/src/events/tool-notification-listener.ts +0 -17
  653. package/src/ipc/routes/__tests__/memory-v2-validate.test.ts +0 -219
  654. package/src/memory/v2/__tests__/edges.test.ts +0 -435
  655. package/src/memory/v2/edges.ts +0 -217
  656. package/src/prompts/__tests__/system-prompt-memory-v2.test.ts +0 -197
  657. package/src/runtime/__tests__/chrome-extension-registry.test.ts +0 -518
  658. package/src/runtime/__tests__/client-registry.test.ts +0 -271
  659. package/src/runtime/chrome-extension-registry.ts +0 -368
  660. package/src/runtime/client-registry.ts +0 -254
  661. package/src/runtime/routes/inbound-stages/verification-intercept.ts +0 -329
  662. package/src/tools/secret-detection-handler.ts +0 -269
  663. package/src/tools/terminal/backends/native.ts +0 -327
  664. package/src/tools/terminal/backends/types.ts +0 -37
  665. package/src/tools/terminal/sandbox-diagnostics.ts +0 -87
  666. package/src/tools/terminal/sandbox.ts +0 -40
@@ -7,6 +7,8 @@ const updateConversationUsageCalls: Array<{
7
7
  estimatedCost: number;
8
8
  }> = [];
9
9
 
10
+ let mockLlmConfig = createMockLlmConfig();
11
+
10
12
  mock.module("../util/logger.js", () => ({
11
13
  getLogger: () =>
12
14
  new Proxy({} as Record<string, unknown>, {
@@ -16,9 +18,7 @@ mock.module("../util/logger.js", () => ({
16
18
 
17
19
  mock.module("../config/loader.js", () => ({
18
20
  getConfig: () => ({
19
- llm: {
20
- pricingOverrides: [],
21
- },
21
+ llm: mockLlmConfig,
22
22
  }),
23
23
  }));
24
24
 
@@ -42,16 +42,67 @@ import { recordUsage } from "../daemon/conversation-usage.js";
42
42
  import { getDb } from "../memory/db-connection.js";
43
43
  import { initializeDb } from "../memory/db-init.js";
44
44
  import { listUsageEvents } from "../memory/llm-usage-store.js";
45
+ import type { Provider, ProviderResponse } from "../providers/types.js";
46
+ import { UsageTrackingProvider } from "../providers/usage-tracking.js";
45
47
  import type { PricingUsage } from "../usage/types.js";
46
48
  import { resolvePricingForUsageWithOverrides } from "../util/pricing.js";
47
49
 
48
50
  initializeDb();
49
51
 
52
+ function createMockLlmConfig() {
53
+ return {
54
+ default: {
55
+ provider: "anthropic" as const,
56
+ model: "claude-opus-4-6",
57
+ maxTokens: 64_000,
58
+ effort: "max" as const,
59
+ speed: "standard" as const,
60
+ verbosity: "medium" as const,
61
+ temperature: null,
62
+ thinking: { enabled: true, streamThinking: true },
63
+ contextWindow: {
64
+ enabled: true,
65
+ maxInputTokens: 200_000,
66
+ targetBudgetRatio: 0.3,
67
+ compactThreshold: 0.8,
68
+ summaryBudgetRatio: 0.05,
69
+ overflowRecovery: {
70
+ enabled: true,
71
+ safetyMarginRatio: 0.05,
72
+ maxAttempts: 3,
73
+ interactiveLatestTurnCompression: "summarize" as const,
74
+ nonInteractiveLatestTurnCompression: "truncate" as const,
75
+ },
76
+ },
77
+ openrouter: { only: [] },
78
+ },
79
+ profiles: {
80
+ conversationProfile: {
81
+ provider: "openai" as const,
82
+ model: "gpt-4o",
83
+ },
84
+ summaryProfile: {
85
+ provider: "anthropic" as const,
86
+ model: "claude-haiku-3",
87
+ },
88
+ },
89
+ profileOrder: [],
90
+ callSites: {
91
+ conversationSummarization: {
92
+ profile: "summaryProfile",
93
+ },
94
+ },
95
+ activeProfile: undefined,
96
+ pricingOverrides: [],
97
+ };
98
+ }
99
+
50
100
  describe("recordUsage", () => {
51
101
  beforeEach(() => {
52
102
  const db = getDb();
53
103
  db.run(`DELETE FROM llm_usage_events`);
54
104
  updateConversationUsageCalls.length = 0;
105
+ mockLlmConfig = createMockLlmConfig();
55
106
  });
56
107
 
57
108
  test("applies fast mode pricing when any response has speed: fast", () => {
@@ -211,4 +262,203 @@ describe("recordUsage", () => {
211
262
  },
212
263
  ]);
213
264
  });
265
+
266
+ test("manual provider usage tracking leaves conversation aggregate recording as the only ledger row", async () => {
267
+ const response: ProviderResponse = {
268
+ content: [{ type: "text", text: "ok" }],
269
+ model: "gpt-5.4-mini",
270
+ usage: {
271
+ inputTokens: 1_000,
272
+ outputTokens: 2_000,
273
+ },
274
+ stopReason: "end_turn",
275
+ };
276
+ const provider: Provider = {
277
+ name: "openai",
278
+ async sendMessage() {
279
+ return response;
280
+ },
281
+ };
282
+ const wrapped = new UsageTrackingProvider(provider);
283
+
284
+ await wrapped.sendMessage(
285
+ [{ role: "user", content: [{ type: "text", text: "Hello" }] }],
286
+ undefined,
287
+ undefined,
288
+ {
289
+ config: {
290
+ callSite: "mainAgent",
291
+ usageTracking: "manual",
292
+ },
293
+ },
294
+ );
295
+ expect(listUsageEvents()).toHaveLength(0);
296
+
297
+ const usageStats = {
298
+ inputTokens: 0,
299
+ outputTokens: 0,
300
+ estimatedCost: 0,
301
+ };
302
+
303
+ recordUsage(
304
+ {
305
+ conversationId: "conv-manual-1",
306
+ providerName: "openai",
307
+ usageStats,
308
+ },
309
+ response.usage.inputTokens,
310
+ response.usage.outputTokens,
311
+ response.model,
312
+ () => {},
313
+ "main_agent",
314
+ "req-manual-1",
315
+ );
316
+
317
+ const events = listUsageEvents();
318
+ expect(events).toHaveLength(1);
319
+ expect(events[0]).toMatchObject({
320
+ actor: "main_agent",
321
+ conversationId: "conv-manual-1",
322
+ requestId: "req-manual-1",
323
+ provider: "openai",
324
+ model: "gpt-5.4-mini",
325
+ inputTokens: 1_000,
326
+ outputTokens: 2_000,
327
+ });
328
+ });
329
+
330
+ test("persists resolved main-agent attribution from input without changing totals", () => {
331
+ const usageStats = {
332
+ inputTokens: 0,
333
+ outputTokens: 0,
334
+ estimatedCost: 0,
335
+ };
336
+
337
+ recordUsage(
338
+ {
339
+ conversationId: "conv-attrib-1",
340
+ providerName: "openai",
341
+ usageStats,
342
+ },
343
+ 100,
344
+ 20,
345
+ "gpt-4o",
346
+ () => {},
347
+ "main_agent",
348
+ "req-attrib-1",
349
+ 0,
350
+ 0,
351
+ undefined,
352
+ 1,
353
+ undefined,
354
+ {
355
+ callSite: "mainAgent",
356
+ overrideProfile: "conversationProfile",
357
+ },
358
+ );
359
+
360
+ const events = listUsageEvents();
361
+ expect(events).toHaveLength(1);
362
+ expect(events[0]).toMatchObject({
363
+ actor: "main_agent",
364
+ provider: "openai",
365
+ model: "gpt-4o",
366
+ inputTokens: 100,
367
+ outputTokens: 20,
368
+ callSite: "mainAgent",
369
+ inferenceProfile: "conversationProfile",
370
+ inferenceProfileSource: "conversation",
371
+ });
372
+ expect(usageStats.inputTokens).toBe(100);
373
+ expect(usageStats.outputTokens).toBe(20);
374
+ });
375
+
376
+ test("persists compaction attribution using the summary call-site profile", () => {
377
+ const usageStats = {
378
+ inputTokens: 0,
379
+ outputTokens: 0,
380
+ estimatedCost: 0,
381
+ };
382
+
383
+ recordUsage(
384
+ {
385
+ conversationId: "conv-attrib-2",
386
+ providerName: "anthropic",
387
+ usageStats,
388
+ },
389
+ 500,
390
+ 80,
391
+ "claude-haiku-3",
392
+ () => {},
393
+ "context_compactor",
394
+ "req-attrib-2",
395
+ 0,
396
+ 0,
397
+ undefined,
398
+ 1,
399
+ undefined,
400
+ {
401
+ callSite: "conversationSummarization",
402
+ overrideProfile: "conversationProfile",
403
+ },
404
+ );
405
+
406
+ const events = listUsageEvents();
407
+ expect(events).toHaveLength(1);
408
+ expect(events[0]).toMatchObject({
409
+ actor: "context_compactor",
410
+ provider: "anthropic",
411
+ model: "claude-haiku-3",
412
+ inputTokens: 500,
413
+ outputTokens: 80,
414
+ callSite: "conversationSummarization",
415
+ inferenceProfile: "summaryProfile",
416
+ inferenceProfileSource: "call_site",
417
+ });
418
+ });
419
+
420
+ test("persists a pre-resolved attribution snapshot", () => {
421
+ const usageStats = {
422
+ inputTokens: 0,
423
+ outputTokens: 0,
424
+ estimatedCost: 0,
425
+ };
426
+
427
+ recordUsage(
428
+ {
429
+ conversationId: "conv-attrib-3",
430
+ providerName: "anthropic",
431
+ usageStats,
432
+ },
433
+ 25,
434
+ 5,
435
+ "claude-opus-4-6",
436
+ () => {},
437
+ "main_agent",
438
+ "req-attrib-3",
439
+ 0,
440
+ 0,
441
+ undefined,
442
+ 1,
443
+ undefined,
444
+ {
445
+ callSite: "mainAgent",
446
+ activeProfile: null,
447
+ overrideProfile: null,
448
+ callSiteProfile: null,
449
+ appliedProfile: null,
450
+ profileSource: "default",
451
+ resolvedProvider: "anthropic",
452
+ resolvedModel: "claude-opus-4-6",
453
+ },
454
+ );
455
+
456
+ const events = listUsageEvents();
457
+ expect(events).toHaveLength(1);
458
+ expect(events[0]).toMatchObject({
459
+ callSite: "mainAgent",
460
+ inferenceProfile: null,
461
+ inferenceProfileSource: "default",
462
+ });
463
+ });
214
464
  });
@@ -6,15 +6,12 @@
6
6
  * - Untrusted bash rejects non-empty credential-ref mode when lockdown is active.
7
7
  * - VELLUM_UNTRUSTED_SHELL env flag is injected for untrusted actors.
8
8
  * - host_bash sets forcePromptSideEffects for untrusted actors under lockdown.
9
- * - Protected paths are passed to the sandbox when lockdown is active.
10
9
  * - CLI commands deny raw secret/token reveal when VELLUM_UNTRUSTED_SHELL=1.
11
10
  */
12
11
 
13
- import { join } from "node:path";
14
12
  import { describe, expect, test } from "bun:test";
15
13
 
16
14
  import { isUntrustedTrustClass } from "../runtime/actor-trust-resolver.js";
17
- import { getProtectedDir, getWorkspaceDir } from "../util/platform.js";
18
15
 
19
16
  // ---------------------------------------------------------------------------
20
17
  // Trust class categorization (foundational for lockdown decisions)
@@ -114,39 +111,3 @@ describe("CES shell lockdown activation", () => {
114
111
  }
115
112
  });
116
113
  });
117
-
118
- // ---------------------------------------------------------------------------
119
- // Sandbox deny-read paths
120
- // ---------------------------------------------------------------------------
121
-
122
- describe("CES protected paths for sandbox deny-read", () => {
123
- test("protected paths include the protected dir and db dir", () => {
124
- // The buildCesProtectedPaths function constructs paths from getProtectedDir()
125
- // and getWorkspaceDir(). We verify the pattern: paths should be absolute and clean.
126
- const expectedPaths = [
127
- getProtectedDir(),
128
- join(getWorkspaceDir(), "data", "db"),
129
- ];
130
-
131
- // Each expected path should be a valid absolute path pattern
132
- for (const p of expectedPaths) {
133
- expect(p.startsWith("/") || p.match(/^[A-Z]:\\/)).toBeTruthy();
134
- expect(p.includes("..")).toBe(false);
135
- }
136
- });
137
- });
138
-
139
- // ---------------------------------------------------------------------------
140
- // Native sandbox backend deny-read integration
141
- // ---------------------------------------------------------------------------
142
-
143
- describe("NativeBackend deny-read paths", () => {
144
- test("WrapOptions accepts denyReadPaths", () => {
145
- // Type-level check: ensure the WrapOptions interface includes denyReadPaths.
146
- const opts: import("../tools/terminal/backends/types.js").WrapOptions = {
147
- networkMode: "off",
148
- denyReadPaths: ["/home/test/.vellum/protected"],
149
- };
150
- expect(opts.denyReadPaths).toHaveLength(1);
151
- });
152
- });
@@ -3,6 +3,7 @@ import { beforeEach, describe, expect, mock, test } from "bun:test";
3
3
  // ── Mutable state for mocks ──────────────────────────────────────────
4
4
 
5
5
  const secureKeyValues = new Map<string, string>();
6
+ const unreachableKeys = new Set<string>();
6
7
 
7
8
  let mockProviders: Array<{
8
9
  provider: string;
@@ -36,6 +37,10 @@ let mockFetchThrows = false;
36
37
 
37
38
  mock.module("../security/secure-keys.js", () => ({
38
39
  getSecureKeyAsync: async (account: string) => secureKeyValues.get(account),
40
+ getSecureKeyResultAsync: async (account: string) => ({
41
+ value: secureKeyValues.get(account),
42
+ unreachable: unreachableKeys.has(account),
43
+ }),
39
44
  setSecureKeyAsync: async () => {},
40
45
  deleteSecureKeyAsync: async () => "deleted",
41
46
  listSecureKeysAsync: async () => [],
@@ -140,11 +145,16 @@ function setToken(connectionId: string, token = "mock-token") {
140
145
  secureKeyValues.set(`oauth_connection/${connectionId}/access_token`, token);
141
146
  }
142
147
 
148
+ function markUnreachable(key: string) {
149
+ unreachableKeys.add(key);
150
+ }
151
+
143
152
  // ── Tests ────────────────────────────────────────────────────────────
144
153
 
145
154
  describe("credential-health-service", () => {
146
155
  beforeEach(() => {
147
156
  secureKeyValues.clear();
157
+ unreachableKeys.clear();
148
158
  mockProviders = [];
149
159
  mockConnections = new Map();
150
160
  mockFetchResponse = { ok: true, status: 200 };
@@ -191,6 +201,30 @@ describe("credential-health-service", () => {
191
201
  expect(report.unhealthy).toHaveLength(1);
192
202
  });
193
203
 
204
+ test("returns unreachable when credential backend is unreachable", async () => {
205
+ addProvider("google");
206
+ addConnection("google", "conn-1");
207
+ // Don't set token, but mark the path as unreachable
208
+ markUnreachable("oauth_connection/conn-1/access_token");
209
+
210
+ const report = await checkAllCredentials();
211
+ expect(report.results).toHaveLength(1);
212
+ expect(report.results[0]!.status).toBe("unreachable");
213
+ expect(report.results[0]!.canAutoRecover).toBe(true);
214
+ expect(report.unhealthy).toHaveLength(1);
215
+ });
216
+
217
+ test("returns missing_token (not unreachable) when backend is reachable but token absent", async () => {
218
+ addProvider("google");
219
+ addConnection("google", "conn-1");
220
+ // Don't set token, don't mark unreachable — genuinely missing
221
+
222
+ const report = await checkAllCredentials();
223
+ expect(report.results).toHaveLength(1);
224
+ expect(report.results[0]!.status).toBe("missing_token");
225
+ expect(report.results[0]!.canAutoRecover).toBe(false);
226
+ });
227
+
194
228
  test("returns expired when token is past expiresAt without refresh token", async () => {
195
229
  addProvider("google");
196
230
  addConnection("google", "conn-1", {
@@ -389,6 +423,40 @@ describe("credential-health-service", () => {
389
423
  const report = await checkAllCredentials();
390
424
  expect(report.results[0]!.status).toBe("healthy");
391
425
  });
426
+
427
+ test("slack_channel returns unreachable when credential backend is down", async () => {
428
+ addProvider("slack_channel", {
429
+ pingUrl: "https://slack.com/api/auth.test",
430
+ });
431
+ addConnection("slack_channel", "conn-slack", {
432
+ expiresAt: null,
433
+ hasRefreshToken: false,
434
+ grantedScopes: [],
435
+ });
436
+ // Don't set token, mark the manual-token path as unreachable
437
+ markUnreachable("credential/slack_channel/bot_token");
438
+
439
+ const report = await checkAllCredentials();
440
+ expect(report.results).toHaveLength(1);
441
+ expect(report.results[0]!.status).toBe("unreachable");
442
+ expect(report.results[0]!.canAutoRecover).toBe(true);
443
+ });
444
+
445
+ test("telegram returns unreachable when credential backend is down", async () => {
446
+ addProvider("telegram");
447
+ addConnection("telegram", "conn-tg", {
448
+ expiresAt: null,
449
+ hasRefreshToken: false,
450
+ grantedScopes: [],
451
+ });
452
+ // Don't set token, mark the manual-token path as unreachable
453
+ markUnreachable("credential/telegram/bot_token");
454
+
455
+ const report = await checkAllCredentials();
456
+ expect(report.results).toHaveLength(1);
457
+ expect(report.results[0]!.status).toBe("unreachable");
458
+ expect(report.results[0]!.canAutoRecover).toBe(true);
459
+ });
392
460
  });
393
461
 
394
462
  describe("checkCredentialForProvider", () => {
@@ -7,8 +7,6 @@ import { beforeEach, describe, expect, mock, test } from "bun:test";
7
7
  const mockConfig = {
8
8
  secretDetection: {
9
9
  enabled: true,
10
- action: "block" as "redact" | "warn" | "block",
11
- entropyThreshold: 4.0,
12
10
  allowOneTimeSend: false,
13
11
  },
14
12
  timeouts: { permissionTimeoutSec: 300 },
@@ -63,6 +61,10 @@ mock.module("../security/secure-keys.js", () => {
63
61
  };
64
62
  return {
65
63
  getSecureKeyAsync: async (key: string) => storedKeys.get(key) ?? undefined,
64
+ getSecureKeyResultAsync: async (account: string) => ({
65
+ value: storedKeys.get(account),
66
+ unreachable: false,
67
+ }),
66
68
  setSecureKeyAsync: async (key: string, value: string) =>
67
69
  syncSet(key, value),
68
70
  deleteSecureKeyAsync: async (key: string) => syncDelete(key),
@@ -330,7 +332,6 @@ describe("E2E: cross-cutting secret leak prevention", () => {
330
332
  beforeEach(() => {
331
333
  storedKeys.clear();
332
334
  mockConfig.secretDetection.enabled = true;
333
- mockConfig.secretDetection.action = "block";
334
335
  mockConfig.secretDetection.allowOneTimeSend = false;
335
336
  });
336
337
 
@@ -189,13 +189,13 @@ describe("Invariant 2: no generic plaintext secret read API", () => {
189
189
  "messaging/providers/slack/adapter.ts", // Slack bot token lookup for Socket Mode connectivity check
190
190
  "credential-health/credential-health-service.ts", // proactive credential health monitoring
191
191
  "daemon/handlers/config-slack-channel.ts", // Slack channel config credential management
192
- "daemon/handlers/slack-channel-oauth-install.ts", // Slack OAuth loopback reads client credentials for token exchange
193
192
  "providers/managed-proxy/context.ts", // managed proxy API key lookup for provider initialization
194
193
  "platform/client.ts", // platform client credential store fallback for standalone CLI auth
195
194
  "mcp/mcp-oauth-provider.ts", // MCP OAuth token/client/discovery persistence
196
195
  "runtime/routes/integrations/slack/share.ts", // Slack share routes credential lookup
197
196
  "mcp/client.ts", // MCP client cached-token lookup
198
197
  "oauth/token-persistence.ts", // OAuth token persistence (set/delete tokens)
198
+ "oauth/credential-token-resolver.ts", // centralized access-token key resolution for OAuth and manual-token providers
199
199
  "oauth/connection-resolver.ts", // resolve OAuthConnection from oauth-store (access_token lookup)
200
200
  "runtime/routes/secret-routes.ts", // HTTP secret management routes (set/delete secrets)
201
201
  "runtime/routes/migration-routes.ts", // migration import credential restore
@@ -583,10 +583,6 @@ describe("One-time send override", () => {
583
583
  test("allowOneTimeSend defaults to false in config", () => {
584
584
  expect(DEFAULT_CONFIG.secretDetection.allowOneTimeSend).toBe(false);
585
585
  });
586
-
587
- test("default secretDetection.action is redact", () => {
588
- expect(DEFAULT_CONFIG.secretDetection.action).toBe("redact");
589
- });
590
586
  });
591
587
 
592
588
  // ---------------------------------------------------------------------------
@@ -0,0 +1,180 @@
1
+ import { beforeEach, describe, expect, mock, test } from "bun:test";
2
+
3
+ // ── Mutable state for mocks ──────────────────────────────────────────
4
+
5
+ const secureKeyValues = new Map<string, string>();
6
+ const unreachableKeys = new Set<string>();
7
+
8
+ // ── Module mocks ─────────────────────────────────────────────────────
9
+
10
+ mock.module("../security/secure-keys.js", () => ({
11
+ getSecureKeyAsync: async (account: string) => secureKeyValues.get(account),
12
+ getSecureKeyResultAsync: async (account: string) => ({
13
+ value: secureKeyValues.get(account),
14
+ unreachable: unreachableKeys.has(account),
15
+ }),
16
+ setSecureKeyAsync: async () => {},
17
+ deleteSecureKeyAsync: async () => "deleted",
18
+ listSecureKeysAsync: async () => [],
19
+ getProviderKeyAsync: async () => undefined,
20
+ getMaskedProviderKey: () => undefined,
21
+ }));
22
+
23
+ mock.module("../util/logger.js", () => ({
24
+ getLogger: () => ({
25
+ info: () => {},
26
+ warn: () => {},
27
+ debug: () => {},
28
+ error: () => {},
29
+ }),
30
+ }));
31
+
32
+ // ── Import under test ────────────────────────────────────────────────
33
+
34
+ const { resolveAccessTokenKey, getConnectionAccessTokenResult } =
35
+ await import("../oauth/credential-token-resolver.js");
36
+
37
+ // ── Tests ────────────────────────────────────────────────────────────
38
+
39
+ describe("credential-token-resolver", () => {
40
+ beforeEach(() => {
41
+ secureKeyValues.clear();
42
+ unreachableKeys.clear();
43
+ });
44
+
45
+ describe("resolveAccessTokenKey", () => {
46
+ test("slack_channel resolves to credential/slack_channel/bot_token", () => {
47
+ expect(resolveAccessTokenKey("slack_channel", "conn-123")).toBe(
48
+ "credential/slack_channel/bot_token",
49
+ );
50
+ });
51
+
52
+ test("telegram resolves to credential/telegram/bot_token", () => {
53
+ expect(resolveAccessTokenKey("telegram", "conn-456")).toBe(
54
+ "credential/telegram/bot_token",
55
+ );
56
+ });
57
+
58
+ test("standard OAuth provider resolves to oauth_connection/<id>/access_token", () => {
59
+ expect(resolveAccessTokenKey("google", "conn-789")).toBe(
60
+ "oauth_connection/conn-789/access_token",
61
+ );
62
+ });
63
+
64
+ test("unknown provider resolves to oauth_connection/<id>/access_token", () => {
65
+ expect(resolveAccessTokenKey("github", "conn-abc")).toBe(
66
+ "oauth_connection/conn-abc/access_token",
67
+ );
68
+ });
69
+ });
70
+
71
+ describe("getConnectionAccessTokenResult", () => {
72
+ test("returns token value and key for slack_channel using bot_token path", async () => {
73
+ secureKeyValues.set("credential/slack_channel/bot_token", "xoxb-valid");
74
+
75
+ const result = await getConnectionAccessTokenResult({
76
+ provider: "slack_channel",
77
+ connectionId: "conn-slack",
78
+ });
79
+
80
+ expect(result.value).toBe("xoxb-valid");
81
+ expect(result.unreachable).toBe(false);
82
+ expect(result.key).toBe("credential/slack_channel/bot_token");
83
+ });
84
+
85
+ test("returns undefined for slack_channel when bot_token is absent even if oauth path is set", async () => {
86
+ // Simulate the bug scenario: OAuth access-token path is populated but
87
+ // the manual-token path is not. The resolver must NOT fall through to
88
+ // the OAuth path for manual-token providers.
89
+ secureKeyValues.set(
90
+ "oauth_connection/conn-slack/access_token",
91
+ "should-be-ignored",
92
+ );
93
+
94
+ const result = await getConnectionAccessTokenResult({
95
+ provider: "slack_channel",
96
+ connectionId: "conn-slack",
97
+ });
98
+
99
+ expect(result.value).toBeUndefined();
100
+ expect(result.key).toBe("credential/slack_channel/bot_token");
101
+ });
102
+
103
+ test("returns token for standard OAuth provider via connection path", async () => {
104
+ secureKeyValues.set(
105
+ "oauth_connection/conn-google/access_token",
106
+ "ya29.token",
107
+ );
108
+
109
+ const result = await getConnectionAccessTokenResult({
110
+ provider: "google",
111
+ connectionId: "conn-google",
112
+ });
113
+
114
+ expect(result.value).toBe("ya29.token");
115
+ expect(result.unreachable).toBe(false);
116
+ expect(result.key).toBe("oauth_connection/conn-google/access_token");
117
+ });
118
+
119
+ test("returns unreachable when credential backend is down", async () => {
120
+ unreachableKeys.add("credential/telegram/bot_token");
121
+
122
+ const result = await getConnectionAccessTokenResult({
123
+ provider: "telegram",
124
+ connectionId: "conn-tg",
125
+ });
126
+
127
+ expect(result.value).toBeUndefined();
128
+ expect(result.unreachable).toBe(true);
129
+ expect(result.key).toBe("credential/telegram/bot_token");
130
+ });
131
+
132
+ test("returns undefined (not unreachable) when token is genuinely missing", async () => {
133
+ const result = await getConnectionAccessTokenResult({
134
+ provider: "google",
135
+ connectionId: "conn-missing",
136
+ });
137
+
138
+ expect(result.value).toBeUndefined();
139
+ expect(result.unreachable).toBe(false);
140
+ expect(result.key).toBe("oauth_connection/conn-missing/access_token");
141
+ });
142
+ });
143
+
144
+ describe("regression: oauth ping slack_channel uses bot_token", () => {
145
+ // The root cause of false credential health alerts was that some code paths
146
+ // looked up tokens at oauth_connection/<id>/access_token for ALL providers,
147
+ // while manual-token providers (slack_channel, telegram) actually store
148
+ // their tokens at credential/<provider>/bot_token. The centralized resolver
149
+ // ensures ALL consumers agree on the path.
150
+
151
+ test("slack_channel token lookup goes to credential/slack_channel/bot_token, not oauth path", async () => {
152
+ secureKeyValues.set("credential/slack_channel/bot_token", "xoxb-real");
153
+
154
+ const result = await getConnectionAccessTokenResult({
155
+ provider: "slack_channel",
156
+ connectionId: "any-connection-id",
157
+ });
158
+
159
+ // Must find the token at the manual-token path
160
+ expect(result.value).toBe("xoxb-real");
161
+ // Must report the correct key
162
+ expect(result.key).toBe("credential/slack_channel/bot_token");
163
+ // Connection ID must be irrelevant for manual-token providers
164
+ expect(result.key).not.toContain("any-connection-id");
165
+ });
166
+
167
+ test("telegram token lookup goes to credential/telegram/bot_token, not oauth path", async () => {
168
+ secureKeyValues.set("credential/telegram/bot_token", "tg-token");
169
+
170
+ const result = await getConnectionAccessTokenResult({
171
+ provider: "telegram",
172
+ connectionId: "any-connection-id",
173
+ });
174
+
175
+ expect(result.value).toBe("tg-token");
176
+ expect(result.key).toBe("credential/telegram/bot_token");
177
+ expect(result.key).not.toContain("any-connection-id");
178
+ });
179
+ });
180
+ });