@vellumai/assistant 0.8.3 → 0.8.5

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 (665) hide show
  1. package/ARCHITECTURE.md +2 -2
  2. package/docker-entrypoint.sh +0 -1
  3. package/docs/browser-use-architecture-phase2.md +1 -1
  4. package/knip.json +2 -1
  5. package/node_modules/@vellumai/gateway-client/src/types.ts +2 -0
  6. package/openapi.yaml +1492 -100
  7. package/package.json +1 -1
  8. package/src/__tests__/agent-loop-exit-reason.test.ts +4 -5
  9. package/src/__tests__/agent-loop-override-profile.test.ts +1 -1
  10. package/src/__tests__/agent-loop.test.ts +88 -3
  11. package/src/__tests__/anthropic-provider.test.ts +302 -33
  12. package/src/__tests__/approval-cascade.test.ts +1 -1
  13. package/src/__tests__/assistant-event-hub-self-exclusion.test.ts +293 -0
  14. package/src/__tests__/assistant-feature-flags-integration.test.ts +3 -3
  15. package/src/__tests__/audit-log-rotation.test.ts +70 -16
  16. package/src/__tests__/background-workers-disk-pressure.test.ts +4 -3
  17. package/src/__tests__/btw-routes.test.ts +2 -3
  18. package/src/__tests__/call-controller.test.ts +0 -1
  19. package/src/__tests__/cancel-resolves-conversation-key.test.ts +1 -1
  20. package/src/__tests__/channel-delivery-store.test.ts +193 -0
  21. package/src/__tests__/channel-guardian.test.ts +3 -3
  22. package/src/__tests__/channel-reply-delivery.test.ts +284 -5
  23. package/src/__tests__/channel-retry-sweep.test.ts +274 -1
  24. package/src/__tests__/checker.test.ts +6 -15
  25. package/src/__tests__/compaction-events.test.ts +2 -1
  26. package/src/__tests__/compactor-call-site-logging.test.ts +214 -0
  27. package/src/__tests__/compactor-preserved-tail-count.test.ts +110 -0
  28. package/src/__tests__/computer-use-skill-manifest-regression.test.ts +5 -11
  29. package/src/__tests__/computer-use-tools.test.ts +2 -4
  30. package/src/__tests__/config-watcher.test.ts +1 -1
  31. package/src/__tests__/confirmation-request-guardian-bridge.test.ts +0 -1
  32. package/src/__tests__/context-token-estimator.test.ts +91 -1
  33. package/src/__tests__/conversation-abort-tool-results.test.ts +1 -1
  34. package/src/__tests__/conversation-agent-loop-disk-pressure.test.ts +1 -1
  35. package/src/__tests__/conversation-agent-loop-inference-profile.test.ts +55 -4
  36. package/src/__tests__/conversation-agent-loop-overflow.test.ts +228 -8
  37. package/src/__tests__/conversation-agent-loop.test.ts +188 -129
  38. package/src/__tests__/conversation-app-control-instantiation.test.ts +2 -5
  39. package/src/__tests__/conversation-app-control-lifecycle.test.ts +1 -1
  40. package/src/__tests__/conversation-clean-command.test.ts +137 -0
  41. package/src/__tests__/conversation-clear-safety.test.ts +25 -25
  42. package/src/__tests__/conversation-confirmation-signals.test.ts +1 -1
  43. package/src/__tests__/conversation-delete-schedule-cleanup.test.ts +1 -1
  44. package/src/__tests__/conversation-disk-view-integration.test.ts +2 -2
  45. package/src/__tests__/conversation-error.test.ts +31 -0
  46. package/src/__tests__/conversation-fork-crud.test.ts +324 -0
  47. package/src/__tests__/conversation-lifecycle.test.ts +53 -12
  48. package/src/__tests__/conversation-load-history-repair.test.ts +1 -1
  49. package/src/__tests__/conversation-load-history-stripped.test.ts +279 -0
  50. package/src/__tests__/conversation-pairing.test.ts +2 -2
  51. package/src/__tests__/conversation-process-callsite.test.ts +1 -1
  52. package/src/__tests__/conversation-provider-retry-repair.test.ts +2 -1
  53. package/src/__tests__/conversation-queue.test.ts +1 -1
  54. package/src/__tests__/conversation-routes-disk-view.test.ts +109 -0
  55. package/src/__tests__/conversation-routes-slash-commands.test.ts +35 -0
  56. package/src/__tests__/conversation-runtime-assembly.test.ts +264 -81
  57. package/src/__tests__/conversation-seed-composer.test.ts +66 -4
  58. package/src/__tests__/conversation-skill-tools.test.ts +2 -5
  59. package/src/__tests__/conversation-slash-commands.test.ts +36 -8
  60. package/src/__tests__/conversation-slash-queue.test.ts +1 -1
  61. package/src/__tests__/conversation-slash-unknown.test.ts +1 -1
  62. package/src/__tests__/conversation-speed-override.test.ts +1 -1
  63. package/src/__tests__/conversation-store.test.ts +1 -1
  64. package/src/__tests__/conversation-surfaces-task-progress.test.ts +220 -0
  65. package/src/__tests__/conversation-sync-tags.test.ts +99 -32
  66. package/src/__tests__/conversation-workspace-cache-state.test.ts +2 -1
  67. package/src/__tests__/conversation-workspace-injection.test.ts +5 -1
  68. package/src/__tests__/conversation-workspace-tool-tracking.test.ts +5 -1
  69. package/src/__tests__/credential-execution-feature-gates.test.ts +9 -7
  70. package/src/__tests__/credential-execution-tools.test.ts +6 -6
  71. package/src/__tests__/credential-security-invariants.test.ts +7 -0
  72. package/src/__tests__/credential-vault-unit.test.ts +2 -2
  73. package/src/__tests__/cu-unified-flow.test.ts +10 -1
  74. package/src/__tests__/dm-backfill.test.ts +64 -0
  75. package/src/__tests__/dm-persistence.test.ts +33 -0
  76. package/src/__tests__/document-find-replace.test.ts +501 -0
  77. package/src/__tests__/dynamic-page-surface.test.ts +2 -2
  78. package/src/__tests__/email-html-renderer.test.ts +12 -0
  79. package/src/__tests__/first-greeting.test.ts +23 -2
  80. package/src/__tests__/gateway-flag-listener.test.ts +237 -0
  81. package/src/__tests__/gemini-provider.test.ts +78 -0
  82. package/src/__tests__/guardian-dispatch.test.ts +0 -1
  83. package/src/__tests__/guardian-outbound-http.test.ts +7 -5
  84. package/src/__tests__/handlers-user-message-approval-consumption.test.ts +1 -1
  85. package/src/__tests__/headless-browser-navigate.test.ts +172 -0
  86. package/src/__tests__/heartbeat-disk-pressure.test.ts +4 -0
  87. package/src/__tests__/heartbeat-service.test.ts +4 -0
  88. package/src/__tests__/host-bash-proxy.test.ts +6 -0
  89. package/src/__tests__/host-browser-proxy.test.ts +10 -0
  90. package/src/__tests__/host-cu-proxy.test.ts +8 -1
  91. package/src/__tests__/host-file-proxy.test.ts +8 -1
  92. package/src/__tests__/host-shell-tool.test.ts +1 -1
  93. package/src/__tests__/host-transfer-proxy.test.ts +8 -1
  94. package/src/__tests__/identity-routes.test.ts +57 -0
  95. package/src/__tests__/inbound-slack-persistence.test.ts +3 -0
  96. package/src/__tests__/init-feature-flag-overrides.test.ts +5 -6
  97. package/src/__tests__/injector-chain.test.ts +2 -0
  98. package/src/__tests__/injector-document-comments.test.ts +378 -0
  99. package/src/__tests__/injector-pkb-v2-silenced.test.ts +4 -25
  100. package/src/__tests__/list-messages-attachments.test.ts +21 -17
  101. package/src/__tests__/list-messages-hidden-metadata.test.ts +217 -0
  102. package/src/__tests__/list-messages-page-latest.test.ts +130 -14
  103. package/src/__tests__/list-messages-tool-merge.test.ts +77 -17
  104. package/src/__tests__/llm-context-normalization.test.ts +0 -2
  105. package/src/__tests__/llm-request-log-call-site.test.ts +136 -0
  106. package/src/__tests__/llm-request-log-source-clickhouse.test.ts +26 -0
  107. package/src/__tests__/llm-resolver.test.ts +161 -9
  108. package/src/__tests__/llm-usage-store.test.ts +66 -0
  109. package/src/__tests__/log-export-routes.test.ts +99 -2
  110. package/src/__tests__/logger.test.ts +89 -0
  111. package/src/__tests__/mcp-abort-signal.test.ts +2 -2
  112. package/src/__tests__/media-generate-image.test.ts +31 -0
  113. package/src/__tests__/memory-v2-static-injector.test.ts +7 -7
  114. package/src/__tests__/message-queue-steer.test.ts +114 -0
  115. package/src/__tests__/model-intents.test.ts +2 -4
  116. package/src/__tests__/notification-guardian-path.test.ts +0 -1
  117. package/src/__tests__/onboarding-template-contract.test.ts +1 -1
  118. package/src/__tests__/openai-provider.test.ts +151 -0
  119. package/src/__tests__/openai-responses-provider.test.ts +118 -16
  120. package/src/__tests__/outbound-slack-persistence.test.ts +187 -20
  121. package/src/__tests__/pending-interactions-resolved-event.test.ts +189 -0
  122. package/src/__tests__/platform-bash-auto-approve.test.ts +2 -2
  123. package/src/__tests__/platform.test.ts +2 -5
  124. package/src/__tests__/plugin-api-tool-definition.test.ts +92 -0
  125. package/src/__tests__/plugin-bootstrap.test.ts +2 -2
  126. package/src/__tests__/plugin-source-watcher.test.ts +302 -0
  127. package/src/__tests__/plugin-tool-contribution.test.ts +13 -6
  128. package/src/__tests__/plugin-types.test.ts +3 -2
  129. package/src/__tests__/prechat-onboarding-contract.test.ts +131 -98
  130. package/src/__tests__/pricing.test.ts +12 -0
  131. package/src/__tests__/process-message-background-slack.test.ts +1 -51
  132. package/src/__tests__/process-message-display-content.test.ts +21 -16
  133. package/src/__tests__/prune-jobs-changes-parser.test.ts +61 -0
  134. package/src/__tests__/registry.test.ts +2 -8
  135. package/src/__tests__/require-fresh-approval.test.ts +2 -2
  136. package/src/__tests__/runtime-events-sse-bilingual.test.ts +154 -0
  137. package/src/__tests__/server-history-render.test.ts +83 -4
  138. package/src/__tests__/shell-tool-proxy-mode.test.ts +1 -1
  139. package/src/__tests__/skill-feature-flags.test.ts +2 -2
  140. package/src/__tests__/skill-projection-feature-flag.test.ts +4 -7
  141. package/src/__tests__/skill-projection.benchmark.test.ts +2 -6
  142. package/src/__tests__/skill-tool-factory.test.ts +1 -1
  143. package/src/__tests__/steer-tool-repair.test.ts +249 -0
  144. package/src/__tests__/subagent-notify-parent.test.ts +1 -1
  145. package/src/__tests__/suggestion-routes.test.ts +1 -0
  146. package/src/__tests__/sync-message-contract.test.ts +59 -0
  147. package/src/__tests__/system-prompt.test.ts +161 -124
  148. package/src/__tests__/terminal-tools.test.ts +12 -2
  149. package/src/__tests__/thinking-block-replay.test.ts +113 -0
  150. package/src/__tests__/thread-backfill.test.ts +370 -22
  151. package/src/__tests__/tool-approval-handler.test.ts +1 -5
  152. package/src/__tests__/tool-execute-pipeline.test.ts +2 -2
  153. package/src/__tests__/tool-execution-pipeline.benchmark.test.ts +2 -5
  154. package/src/__tests__/tool-executor-lifecycle-events.test.ts +15 -5
  155. package/src/__tests__/tool-executor.test.ts +89 -53
  156. package/src/__tests__/tool-grant-request-escalation.test.ts +1 -6
  157. package/src/__tests__/tool-result-metadata-plumbing.test.ts +167 -0
  158. package/src/__tests__/trusted-contact-approval-notifier.test.ts +0 -1
  159. package/src/__tests__/trusted-contact-inline-approval-integration.test.ts +1 -6
  160. package/src/__tests__/trusted-contact-multichannel.test.ts +0 -1
  161. package/src/__tests__/twilio-routes.test.ts +1 -1
  162. package/src/__tests__/ui-file-upload-surface.test.ts +2 -2
  163. package/src/__tests__/usage-routes.test.ts +3 -0
  164. package/src/__tests__/verification-control-plane-policy.test.ts +2 -2
  165. package/src/__tests__/web-fetch.test.ts +2 -2
  166. package/src/__tests__/workspace-git-service.test.ts +94 -10
  167. package/src/__tests__/workspace-migration-088-deprecate-background-conversation-override.test.ts +158 -0
  168. package/src/__tests__/workspace-migration-089-move-memory-tree-out-of-v3.test.ts +86 -0
  169. package/src/acp/__tests__/prepare-agent-env.test.ts +146 -0
  170. package/src/acp/prepare-agent-env.ts +78 -0
  171. package/src/acp/session-manager.ts +1 -1
  172. package/src/agent/attachments.ts +1 -0
  173. package/src/agent/loop.ts +65 -20
  174. package/src/api/README.md +5 -0
  175. package/src/api/index.ts +4 -0
  176. package/src/api/package.json +10 -0
  177. package/src/background-wake/background-wake-routes.test.ts +233 -0
  178. package/src/background-wake/next-wake.test.ts +289 -0
  179. package/src/background-wake/next-wake.ts +172 -0
  180. package/src/background-wake/runtime-registry.ts +24 -0
  181. package/src/browser/operations.ts +15 -0
  182. package/src/cli/commands/__tests__/browser.test.ts +23 -5
  183. package/src/cli/commands/__tests__/conversations-slack.test.ts +572 -0
  184. package/src/cli/commands/__tests__/domain-register.test.ts +110 -0
  185. package/src/cli/commands/__tests__/domain-status.test.ts +33 -33
  186. package/src/cli/commands/__tests__/inference-send.test.ts +108 -5
  187. package/src/cli/commands/__tests__/memory-v2-compare-render.test.ts +98 -0
  188. package/src/cli/commands/__tests__/memory-v2.test.ts +10 -12
  189. package/src/cli/commands/__tests__/memory-v3-render.test.ts +340 -0
  190. package/src/cli/commands/browser.ts +247 -0
  191. package/src/cli/commands/conversations.ts +128 -1
  192. package/src/cli/commands/domain.ts +91 -41
  193. package/src/cli/commands/inference-providers.ts +147 -1
  194. package/src/cli/commands/inference.ts +93 -40
  195. package/src/cli/commands/memory-v2-compare-render.ts +115 -0
  196. package/src/cli/commands/memory-v2.ts +483 -0
  197. package/src/cli/commands/memory-v3-render.ts +344 -0
  198. package/src/cli/commands/memory-v3.ts +316 -0
  199. package/src/cli/commands/notifications.ts +24 -2
  200. package/src/cli/program.ts +2 -0
  201. package/src/cli/utils/conversation-id.ts +17 -5
  202. package/src/config/assistant-feature-flags.ts +21 -9
  203. package/src/config/bundled-skills/app-builder/SKILL.md +2 -2
  204. package/src/config/bundled-skills/document-editor/SKILL.md +124 -0
  205. package/src/config/bundled-skills/document-editor/TOOLS.json +258 -0
  206. package/src/config/bundled-skills/document-editor/tools/comment-list.ts +12 -0
  207. package/src/config/bundled-skills/document-editor/tools/comment-reply.ts +12 -0
  208. package/src/config/bundled-skills/document-editor/tools/comment-resolve.ts +12 -0
  209. package/src/config/bundled-skills/document-editor/tools/document-find.ts +12 -0
  210. package/src/config/bundled-skills/document-editor/tools/document-open.ts +12 -0
  211. package/src/config/bundled-skills/document-editor/tools/document-replace-text.ts +12 -0
  212. package/src/config/bundled-skills/image-studio/SKILL.md +4 -0
  213. package/src/config/bundled-skills/image-studio/tools/media-generate-image.ts +2 -2
  214. package/src/config/bundled-skills/media-processing/SKILL.md +8 -0
  215. package/src/config/bundled-skills/media-processing/tools/ingest-media.ts +13 -8
  216. package/src/config/bundled-skills/messaging/tools/messaging-analyze-style.ts +10 -3
  217. package/src/config/bundled-skills/phone-calls/references/TRANSCRIPTS.md +16 -14
  218. package/src/config/bundled-skills/playbooks/tools/playbook-create.ts +7 -2
  219. package/src/config/bundled-skills/playbooks/tools/playbook-update.ts +7 -2
  220. package/src/config/bundled-skills/schedule/SKILL.md +8 -0
  221. package/src/config/bundled-tool-registry.ts +24 -12
  222. package/src/config/call-site-defaults.ts +20 -0
  223. package/src/config/feature-flag-registry.json +115 -3
  224. package/src/config/llm-resolver.ts +16 -2
  225. package/src/config/schemas/__tests__/memory-v2.test.ts +217 -1
  226. package/src/config/schemas/call-site-catalog.ts +35 -0
  227. package/src/config/schemas/llm.ts +14 -0
  228. package/src/config/schemas/memory-v2.ts +294 -1
  229. package/src/config/schemas/memory.ts +2 -1
  230. package/src/context/compactor.ts +60 -1
  231. package/src/context/token-estimator.ts +47 -4
  232. package/src/context/window-manager.ts +25 -0
  233. package/src/conversations/__tests__/message-consolidation.test.ts +350 -0
  234. package/src/conversations/message-consolidation.ts +404 -0
  235. package/src/credential-health/credential-health-service.ts +34 -19
  236. package/src/daemon/__tests__/conversation-tool-setup-exclude.test.ts +1 -1
  237. package/src/daemon/__tests__/conversation-tool-setup.test.ts +66 -6
  238. package/src/daemon/__tests__/meet-manifest-loader.test.ts +1 -1
  239. package/src/daemon/__tests__/native-web-search-metadata.test.ts +357 -0
  240. package/src/daemon/__tests__/web-search-status-text.test.ts +287 -0
  241. package/src/daemon/conversation-agent-loop-handlers.ts +155 -36
  242. package/src/daemon/conversation-agent-loop.ts +307 -88
  243. package/src/daemon/conversation-error.ts +31 -1
  244. package/src/daemon/conversation-lifecycle.ts +149 -118
  245. package/src/daemon/conversation-messaging.ts +3 -0
  246. package/src/daemon/conversation-process.ts +273 -0
  247. package/src/daemon/conversation-queue-manager.ts +14 -0
  248. package/src/daemon/conversation-runtime-assembly.ts +145 -84
  249. package/src/daemon/conversation-slash.ts +37 -5
  250. package/src/daemon/conversation-surfaces.ts +45 -2
  251. package/src/daemon/conversation-tool-setup.ts +70 -3
  252. package/src/daemon/conversation-usage.ts +2 -0
  253. package/src/daemon/conversation.ts +54 -32
  254. package/src/daemon/disk-pressure-guard.ts +14 -2
  255. package/src/daemon/first-greeting.ts +10 -0
  256. package/src/daemon/handlers/__tests__/config-a2a-accept.test.ts +498 -0
  257. package/src/daemon/handlers/config-a2a.ts +160 -0
  258. package/src/daemon/handlers/config-model.test.ts +2 -0
  259. package/src/daemon/handlers/conversations.ts +90 -3
  260. package/src/daemon/handlers/shared.ts +92 -29
  261. package/src/daemon/host-bash-proxy.ts +1 -1
  262. package/src/daemon/host-browser-proxy.ts +5 -5
  263. package/src/daemon/host-cu-proxy.ts +5 -5
  264. package/src/daemon/host-file-proxy.ts +5 -5
  265. package/src/daemon/host-proxy-base.ts +4 -4
  266. package/src/daemon/host-transfer-proxy.ts +11 -11
  267. package/src/daemon/lifecycle.ts +40 -23
  268. package/src/daemon/meet-manifest-loader.ts +1 -7
  269. package/src/daemon/message-protocol.ts +4 -0
  270. package/src/daemon/message-types/conversations.ts +14 -9
  271. package/src/daemon/message-types/document-comments.ts +50 -0
  272. package/src/daemon/message-types/home.ts +1 -13
  273. package/src/daemon/message-types/messages.ts +66 -7
  274. package/src/daemon/message-types/surfaces.ts +3 -1
  275. package/src/daemon/message-types/sync.ts +14 -0
  276. package/src/daemon/message-types/web-activity.ts +57 -0
  277. package/src/daemon/plugin-source-watcher.ts +135 -3
  278. package/src/daemon/process-message.ts +69 -12
  279. package/src/daemon/shutdown-handlers.ts +24 -5
  280. package/src/daemon/switch-inference-profile-tool.ts +52 -0
  281. package/src/daemon/tool-setup-types.ts +13 -0
  282. package/src/daemon/trust-context.ts +6 -0
  283. package/src/documents/document-comments-store.test.ts +338 -0
  284. package/src/documents/document-comments-store.ts +237 -0
  285. package/src/documents/document-store.ts +202 -0
  286. package/src/events/relationship-state-updated.ts +25 -0
  287. package/src/heartbeat/__tests__/heartbeat-service.test.ts +1 -2
  288. package/src/heartbeat/heartbeat-service.ts +1 -0
  289. package/src/home/__tests__/suggested-prompts.test.ts +33 -2
  290. package/src/home/feed-types.ts +6 -1
  291. package/src/home/home-content-refresh.ts +52 -0
  292. package/src/home/home-greeting-cache.ts +69 -0
  293. package/src/home/home-greeting.ts +85 -0
  294. package/src/home/suggested-prompts.ts +168 -9
  295. package/src/ipc/gateway-flag-listener.ts +123 -0
  296. package/src/ipc/skill-routes/registries.ts +8 -12
  297. package/src/memory/__tests__/db-async-query.test.ts +165 -0
  298. package/src/memory/__tests__/db-maintenance.test.ts +115 -0
  299. package/src/memory/__tests__/jobs-store-enqueue-gate.test.ts +241 -0
  300. package/src/memory/__tests__/jobs-store-job-classes.test.ts +28 -1
  301. package/src/memory/__tests__/jobs-worker-v2-schedule.test.ts +135 -2
  302. package/src/memory/__tests__/memory-retrospective-job.test.ts +327 -6
  303. package/src/memory/auto-analysis-enqueue.ts +5 -1
  304. package/src/memory/conversation-crud.ts +191 -100
  305. package/src/memory/conversation-starters-cadence.ts +3 -1
  306. package/src/memory/conversation-title-service.ts +19 -3
  307. package/src/memory/db-async-query.ts +214 -0
  308. package/src/memory/db-init.ts +26 -0
  309. package/src/memory/db-maintenance.ts +30 -21
  310. package/src/memory/delivery-crud.ts +41 -0
  311. package/src/memory/delivery-status.ts +141 -15
  312. package/src/memory/external-conversation-store.ts +32 -1
  313. package/src/memory/graph/bootstrap.ts +8 -1
  314. package/src/memory/graph/capability-seed.ts +7 -3
  315. package/src/memory/graph/conversation-graph-memory.ts +100 -17
  316. package/src/memory/graph/extraction.ts +1 -5
  317. package/src/memory/graph/graph-search.ts +7 -1
  318. package/src/memory/indexer.ts +28 -18
  319. package/src/memory/job-handlers/cleanup.ts +76 -18
  320. package/src/memory/job-handlers/conversation-starters.ts +1 -4
  321. package/src/memory/jobs/embed-pkb-file.ts +6 -1
  322. package/src/memory/jobs-store.ts +14 -0
  323. package/src/memory/jobs-worker.ts +68 -15
  324. package/src/memory/llm-request-log-source-clickhouse.ts +42 -2
  325. package/src/memory/llm-request-log-source-local.ts +7 -0
  326. package/src/memory/llm-request-log-source.ts +9 -2
  327. package/src/memory/llm-request-log-store.ts +43 -1
  328. package/src/memory/llm-usage-store.ts +24 -0
  329. package/src/memory/memory-retrospective-constants.ts +28 -0
  330. package/src/memory/memory-retrospective-enqueue.ts +11 -3
  331. package/src/memory/memory-retrospective-job.ts +413 -18
  332. package/src/memory/memory-retrospective-startup-cleanup.ts +3 -3
  333. package/src/memory/memory-v2-activation-log-store.ts +41 -14
  334. package/src/memory/migrations/100-core-tables.ts +1 -0
  335. package/src/memory/migrations/109-external-conversation-bindings.ts +1 -0
  336. package/src/memory/migrations/253-conversation-last-notified-profile.ts +15 -0
  337. package/src/memory/migrations/253-document-comments.ts +47 -0
  338. package/src/memory/migrations/254-external-conversation-binding-chat-name.ts +43 -0
  339. package/src/memory/migrations/255-channel-inbound-delivery-attempts.ts +24 -0
  340. package/src/memory/migrations/256-memory-v2-injection-events.ts +113 -0
  341. package/src/memory/migrations/257-strip-base-url-non-openai-compatible.ts +22 -0
  342. package/src/memory/migrations/258-onboarding-events-prior-assistants.ts +13 -0
  343. package/src/memory/migrations/259-conversation-cleaned-at.ts +33 -0
  344. package/src/memory/migrations/260-rename-cleaned-at.ts +44 -0
  345. package/src/memory/migrations/261-llm-usage-add-raw-usage.ts +36 -0
  346. package/src/memory/migrations/262-memory-v3-coactivation.ts +57 -0
  347. package/src/memory/migrations/263-memory-v3-auto-edges.ts +50 -0
  348. package/src/memory/migrations/264-llm-request-log-call-site.ts +29 -0
  349. package/src/memory/migrations/index.ts +34 -0
  350. package/src/memory/migrations/registry.ts +58 -0
  351. package/src/memory/onboarding-events-store.ts +7 -0
  352. package/src/memory/schema/calls.ts +1 -0
  353. package/src/memory/schema/conversations.ts +3 -0
  354. package/src/memory/schema/infrastructure.ts +22 -0
  355. package/src/memory/tool-usage-store.ts +36 -8
  356. package/src/memory/v2/__tests__/consolidation-job.test.ts +1 -0
  357. package/src/memory/v2/__tests__/harness-compare.test.ts +186 -0
  358. package/src/memory/v2/__tests__/harness-metrics.test.ts +74 -0
  359. package/src/memory/v2/__tests__/harness-oracle.test.ts +257 -0
  360. package/src/memory/v2/__tests__/harness-replay-input.test.ts +225 -0
  361. package/src/memory/v2/__tests__/harness-runner.test.ts +109 -0
  362. package/src/memory/v2/__tests__/injection-events.test.ts +318 -0
  363. package/src/memory/v2/__tests__/injection.test.ts +158 -112
  364. package/src/memory/v2/__tests__/page-index.test.ts +365 -1
  365. package/src/memory/v2/__tests__/qdrant.test.ts +36 -0
  366. package/src/memory/v2/__tests__/router.test.ts +660 -4
  367. package/src/memory/v2/consolidation-job.ts +14 -0
  368. package/src/memory/v2/harness/compare.ts +57 -0
  369. package/src/memory/v2/harness/metrics.ts +124 -0
  370. package/src/memory/v2/harness/oracle.ts +145 -0
  371. package/src/memory/v2/harness/replay-input.ts +224 -0
  372. package/src/memory/v2/harness/retriever.ts +74 -0
  373. package/src/memory/v2/harness/router-retriever.ts +43 -0
  374. package/src/memory/v2/harness/runner.ts +106 -0
  375. package/src/memory/v2/harness/trace.ts +58 -0
  376. package/src/memory/v2/injection-events.ts +101 -0
  377. package/src/memory/v2/injection.ts +42 -25
  378. package/src/memory/v2/page-index.ts +209 -7
  379. package/src/memory/v2/page-store.ts +18 -0
  380. package/src/memory/v2/prompts/router.ts +26 -1
  381. package/src/memory/v2/qdrant.ts +14 -2
  382. package/src/memory/v2/router.ts +369 -62
  383. package/src/memory/v3/__tests__/coactivation-store.test.ts +422 -0
  384. package/src/memory/v3/__tests__/consolidation-job.test.ts +468 -0
  385. package/src/memory/v3/__tests__/edge-learning-job.test.ts +324 -0
  386. package/src/memory/v3/__tests__/edges.test.ts +563 -0
  387. package/src/memory/v3/__tests__/filter.test.ts +512 -0
  388. package/src/memory/v3/__tests__/gate.test.ts +574 -0
  389. package/src/memory/v3/__tests__/index-composition.test.ts +233 -0
  390. package/src/memory/v3/__tests__/loop.test.ts +530 -0
  391. package/src/memory/v3/__tests__/retriever.test.ts +226 -0
  392. package/src/memory/v3/__tests__/scouts.test.ts +440 -0
  393. package/src/memory/v3/__tests__/shadow-middleware.test.ts +312 -0
  394. package/src/memory/v3/__tests__/system-prompts.test.ts +154 -0
  395. package/src/memory/v3/__tests__/traversal.test.ts +469 -0
  396. package/src/memory/v3/__tests__/tree-index.test.ts +280 -0
  397. package/src/memory/v3/__tests__/tree-store.test.ts +529 -0
  398. package/src/memory/v3/__tests__/tree-walk.test.ts +707 -0
  399. package/src/memory/v3/__tests__/validate.test.ts +245 -0
  400. package/src/memory/v3/auto-edges.ts +223 -0
  401. package/src/memory/v3/coactivation-store.ts +124 -0
  402. package/src/memory/v3/consolidation-job.ts +323 -0
  403. package/src/memory/v3/edge-learning-job.ts +160 -0
  404. package/src/memory/v3/edges.ts +249 -0
  405. package/src/memory/v3/filter.ts +281 -0
  406. package/src/memory/v3/gate.ts +334 -0
  407. package/src/memory/v3/index-composition.ts +113 -0
  408. package/src/memory/v3/llm-capture.ts +46 -0
  409. package/src/memory/v3/loop.ts +382 -0
  410. package/src/memory/v3/maintenance.ts +144 -0
  411. package/src/memory/v3/prompt-context.ts +33 -0
  412. package/src/memory/v3/prompts/consolidation.ts +458 -0
  413. package/src/memory/v3/prompts/system-prompts.ts +196 -0
  414. package/src/memory/v3/retriever.ts +33 -0
  415. package/src/memory/v3/scouts.ts +420 -0
  416. package/src/memory/v3/shadow-middleware.ts +305 -0
  417. package/src/memory/v3/traversal.ts +206 -0
  418. package/src/memory/v3/tree-index.ts +237 -0
  419. package/src/memory/v3/tree-store.ts +394 -0
  420. package/src/memory/v3/tree-walk.ts +351 -0
  421. package/src/memory/v3/types.ts +65 -0
  422. package/src/memory/v3/validate.ts +300 -0
  423. package/src/messaging/providers/index.ts +7 -1
  424. package/src/messaging/providers/slack/__tests__/adapter-mention-rendering.test.ts +329 -3
  425. package/src/messaging/providers/slack/__tests__/adapter-token-routing.test.ts +34 -1
  426. package/src/messaging/providers/slack/adapter.ts +178 -25
  427. package/src/messaging/providers/slack/api.test.ts +54 -0
  428. package/src/messaging/providers/slack/api.ts +119 -3
  429. package/src/messaging/providers/slack/client.ts +12 -0
  430. package/src/messaging/providers/slack/deep-link.ts +20 -1
  431. package/src/messaging/providers/slack/message-metadata.test.ts +48 -0
  432. package/src/messaging/providers/slack/message-metadata.ts +156 -0
  433. package/src/messaging/providers/slack/render-transcript.test.ts +107 -75
  434. package/src/messaging/providers/slack/render-transcript.ts +176 -49
  435. package/src/messaging/providers/slack/send.test.ts +77 -0
  436. package/src/messaging/providers/slack/send.ts +8 -2
  437. package/src/messaging/providers/slack/types.ts +14 -0
  438. package/src/notifications/__tests__/emit-signal-home-feed.test.ts +4 -1
  439. package/src/notifications/__tests__/home-feed-side-effect.test.ts +116 -54
  440. package/src/notifications/adapters/macos.ts +18 -1
  441. package/src/notifications/adapters/platform.ts +1 -1
  442. package/src/notifications/conversation-seed-composer.ts +14 -2
  443. package/src/notifications/decision-engine.ts +1 -4
  444. package/src/notifications/deferred-emit.ts +135 -0
  445. package/src/notifications/emit-signal.ts +38 -50
  446. package/src/notifications/home-feed-side-effect.ts +60 -30
  447. package/src/oauth/connect-orchestrator.ts +3 -0
  448. package/src/oauth/credential-token-resolver.ts +2 -0
  449. package/src/oauth/manual-token-connection.ts +19 -0
  450. package/src/oauth/oauth-store.ts +12 -0
  451. package/src/oauth/seed-providers.ts +22 -0
  452. package/src/permissions/prompter.ts +8 -5
  453. package/src/permissions/question-prompter.ts +5 -2
  454. package/src/permissions/secret-prompter.ts +6 -3
  455. package/src/plugin-api/index.ts +4 -0
  456. package/src/plugin-api/types.ts +7 -33
  457. package/src/plugins/defaults/index.ts +6 -0
  458. package/src/plugins/defaults/injectors.ts +100 -20
  459. package/src/plugins/external-plugin-loader.ts +5 -68
  460. package/src/plugins/types.ts +11 -16
  461. package/src/proactive-artifact/aux-message-injector.ts +17 -4
  462. package/src/prompts/__tests__/system-prompt.test.ts +46 -2
  463. package/src/prompts/__tests__/task-progress-hint-section.test.ts +3 -9
  464. package/src/prompts/normalize-onboarding.ts +40 -0
  465. package/src/prompts/persona-resolver.ts +36 -21
  466. package/src/prompts/sections.ts +69 -19
  467. package/src/prompts/system-prompt.ts +118 -216
  468. package/src/prompts/template-detection.ts +37 -0
  469. package/src/prompts/templates/BOOTSTRAP-CONTENT-AUTOMATION.md +141 -0
  470. package/src/prompts/templates/BOOTSTRAP.md +10 -2
  471. package/src/prompts/templates/VOICE.md +3 -0
  472. package/src/prompts/templates/system-sections.ts +281 -9
  473. package/src/providers/__tests__/connection-model-compat.test.ts +234 -0
  474. package/src/providers/__tests__/retry-callsite.test.ts +85 -5
  475. package/src/providers/anthropic/client.ts +159 -66
  476. package/src/providers/call-site-routing.ts +14 -2
  477. package/src/providers/connection-model-compat.ts +38 -0
  478. package/src/providers/connection-resolution.ts +16 -2
  479. package/src/providers/fireworks/client.ts +20 -2
  480. package/src/providers/gemini/client.ts +49 -6
  481. package/src/providers/inference/__tests__/base-url-route-validation.test.ts +342 -0
  482. package/src/providers/inference/__tests__/base-url-security.test.ts +189 -0
  483. package/src/providers/inference/__tests__/codex-token-refresh.test.ts +254 -0
  484. package/src/providers/inference/adapter-factory.ts +18 -1
  485. package/src/providers/inference/auth.ts +3 -3
  486. package/src/providers/inference/codex-token-refresh.ts +128 -0
  487. package/src/providers/inference/resolve-auth.ts +49 -6
  488. package/src/providers/minimax/client.ts +106 -0
  489. package/src/providers/model-catalog.ts +91 -1
  490. package/src/providers/model-intents.ts +1 -1
  491. package/src/providers/openai/chat-completions-provider.ts +63 -23
  492. package/src/providers/openai/codex-models.ts +18 -0
  493. package/src/providers/openai/responses-provider.ts +86 -23
  494. package/src/providers/openrouter/client.ts +5 -1
  495. package/src/providers/provider-send-message.ts +7 -1
  496. package/src/providers/retry.ts +34 -3
  497. package/src/providers/thinking-config.ts +26 -1
  498. package/src/providers/types.ts +25 -0
  499. package/src/providers/usage-tracking.ts +2 -0
  500. package/src/runtime/AGENTS.md +2 -2
  501. package/src/runtime/__tests__/agent-wake.test.ts +214 -0
  502. package/src/runtime/__tests__/background-job-runner.test.ts +128 -0
  503. package/src/runtime/agent-wake.ts +152 -56
  504. package/src/runtime/assistant-event-hub.ts +76 -6
  505. package/src/runtime/auth/route-policy.ts +43 -3
  506. package/src/runtime/background-job-runner.ts +26 -0
  507. package/src/runtime/btw-sidechain.ts +0 -6
  508. package/src/runtime/channel-reply-delivery.ts +182 -47
  509. package/src/runtime/channel-retry-sweep.ts +141 -16
  510. package/src/runtime/http-types.ts +7 -6
  511. package/src/runtime/migrations/vbundle-builder.ts +10 -3
  512. package/src/runtime/pending-interactions.ts +50 -8
  513. package/src/runtime/routes/__tests__/content-source-routes.test.ts +162 -0
  514. package/src/runtime/routes/__tests__/conversation-query-routes.test.ts +161 -1
  515. package/src/runtime/routes/__tests__/memory-v2-routes.test.ts +14 -0
  516. package/src/runtime/routes/__tests__/memory-v2-simulate-route.test.ts +290 -0
  517. package/src/runtime/routes/__tests__/plugins-routes.test.ts +512 -0
  518. package/src/runtime/routes/__tests__/sanity-routes.test.ts +280 -0
  519. package/src/runtime/routes/__tests__/slack-channel-routes.test.ts +266 -0
  520. package/src/runtime/routes/acp-routes.test.ts +255 -6
  521. package/src/runtime/routes/acp-routes.ts +8 -1
  522. package/src/runtime/routes/approval-routes.ts +4 -1
  523. package/src/runtime/routes/avatar-routes.ts +10 -10
  524. package/src/runtime/routes/background-wake-routes.ts +188 -0
  525. package/src/runtime/routes/browser-tabs-routes.ts +200 -0
  526. package/src/runtime/routes/btw-routes.ts +0 -6
  527. package/src/runtime/routes/chatgpt-subscription-auth-routes.ts +246 -0
  528. package/src/runtime/routes/content-source-routes.ts +78 -0
  529. package/src/runtime/routes/conversation-cli-routes.ts +147 -2
  530. package/src/runtime/routes/conversation-list-routes.ts +12 -4
  531. package/src/runtime/routes/conversation-management-routes.ts +77 -20
  532. package/src/runtime/routes/conversation-query-routes.ts +196 -31
  533. package/src/runtime/routes/conversation-routes.ts +472 -425
  534. package/src/runtime/routes/conversation-starter-routes.ts +6 -3
  535. package/src/runtime/routes/disk-pressure-routes.ts +1 -1
  536. package/src/runtime/routes/document-comments-routes.ts +287 -0
  537. package/src/runtime/routes/documents-routes.ts +33 -0
  538. package/src/runtime/routes/domain-routes.ts +60 -10
  539. package/src/runtime/routes/email-routes.ts +5 -2
  540. package/src/runtime/routes/events-routes.ts +54 -10
  541. package/src/runtime/routes/group-routes.ts +24 -8
  542. package/src/runtime/routes/home-feed-routes.ts +6 -3
  543. package/src/runtime/routes/host-app-control-routes.ts +1 -1
  544. package/src/runtime/routes/host-browser-routes.ts +17 -2
  545. package/src/runtime/routes/host-cu-routes.ts +2 -2
  546. package/src/runtime/routes/identity-routes.ts +21 -0
  547. package/src/runtime/routes/inbound-message-handler.ts +288 -58
  548. package/src/runtime/routes/inbound-stages/acl-enforcement.ts +96 -3
  549. package/src/runtime/routes/inbound-stages/background-dispatch.test.ts +365 -6
  550. package/src/runtime/routes/inbound-stages/background-dispatch.ts +283 -82
  551. package/src/runtime/routes/index.ts +20 -4
  552. package/src/runtime/routes/inference-profile-session-handler.ts +22 -12
  553. package/src/runtime/routes/inference-profile-session-routes.ts +7 -1
  554. package/src/runtime/routes/inference-provider-connection-routes.ts +63 -7
  555. package/src/runtime/routes/integrations/a2a.ts +60 -1
  556. package/src/runtime/routes/llm-call-sites-routes.ts +32 -5
  557. package/src/runtime/routes/log-export-routes.ts +39 -0
  558. package/src/runtime/routes/memory-item-routes.ts +8 -3
  559. package/src/runtime/routes/memory-v2-routes.ts +427 -0
  560. package/src/runtime/routes/memory-v3-routes.ts +316 -0
  561. package/src/runtime/routes/migration-routes.ts +21 -24
  562. package/src/runtime/routes/notification-routes.ts +19 -2
  563. package/src/runtime/routes/plugins-routes.ts +337 -0
  564. package/src/runtime/routes/question-routes.ts +4 -1
  565. package/src/runtime/routes/rename-conversation-routes.ts +6 -2
  566. package/src/runtime/routes/sanity-routes.ts +159 -0
  567. package/src/runtime/routes/secret-routes.ts +25 -5
  568. package/src/runtime/routes/settings-routes.ts +12 -11
  569. package/src/runtime/routes/slack-channel-routes.ts +188 -0
  570. package/src/runtime/routes/workspace-routes.ts +25 -10
  571. package/src/runtime/services/conversation-serializer.ts +30 -4
  572. package/src/runtime/sync/resource-sync-events.ts +106 -38
  573. package/src/runtime/sync/sync-publisher.test.ts +49 -0
  574. package/src/runtime/sync/sync-publisher.ts +2 -1
  575. package/src/runtime/verification-outbound-actions.ts +73 -1
  576. package/src/schedule/integration-status.ts +3 -1
  577. package/src/security/__tests__/oauth2-device-code.test.ts +479 -0
  578. package/src/security/oauth2-device-code.ts +307 -0
  579. package/src/security/oauth2.ts +26 -9
  580. package/src/security/secure-keys.ts +5 -0
  581. package/src/skills/catalog-install.ts +6 -2
  582. package/src/telemetry/types.ts +12 -0
  583. package/src/telemetry/usage-telemetry-reporter.test.ts +48 -0
  584. package/src/telemetry/usage-telemetry-reporter.ts +1 -0
  585. package/src/tools/acp/spawn.test.ts +119 -0
  586. package/src/tools/acp/spawn.ts +15 -2
  587. package/src/tools/apps/definitions.ts +2 -8
  588. package/src/tools/ask-question/ask-question-tool.test.ts +3 -3
  589. package/src/tools/ask-question/ask-question-tool.ts +38 -45
  590. package/src/tools/browser/__tests__/pinned-tabs.test.ts +150 -0
  591. package/src/tools/browser/browser-execution.ts +106 -0
  592. package/src/tools/browser/cdp-client/__tests__/browser-tabs-factory.test.ts +402 -0
  593. package/src/tools/browser/cdp-client/__tests__/factory.test.ts +28 -0
  594. package/src/tools/browser/cdp-client/__tests__/types.test.ts +4 -0
  595. package/src/tools/browser/cdp-client/cdp-inspect-client.ts +22 -0
  596. package/src/tools/browser/cdp-client/extension-cdp-client.ts +42 -2
  597. package/src/tools/browser/cdp-client/factory.ts +171 -4
  598. package/src/tools/browser/cdp-client/local-cdp-client.ts +21 -0
  599. package/src/tools/browser/cdp-client/types.ts +101 -0
  600. package/src/tools/browser/pinned-tabs.ts +146 -0
  601. package/src/tools/computer-use/definitions.ts +22 -78
  602. package/src/tools/credential-execution/make-authenticated-request.ts +3 -9
  603. package/src/tools/credential-execution/manage-secure-command-tool.ts +3 -9
  604. package/src/tools/credential-execution/run-authenticated-command.ts +3 -9
  605. package/src/tools/credentials/vault.ts +3 -9
  606. package/src/tools/document/document-comment-tool.test.ts +379 -0
  607. package/src/tools/document/document-comment-tool.ts +156 -0
  608. package/src/tools/document/document-tool.ts +187 -2
  609. package/src/tools/execution-target.ts +21 -23
  610. package/src/tools/executor.ts +6 -1
  611. package/src/tools/filesystem/edit.ts +3 -9
  612. package/src/tools/filesystem/list.ts +3 -9
  613. package/src/tools/filesystem/read.ts +3 -9
  614. package/src/tools/filesystem/write.ts +3 -9
  615. package/src/tools/host-filesystem/edit.ts +3 -9
  616. package/src/tools/host-filesystem/read.ts +3 -9
  617. package/src/tools/host-filesystem/transfer.ts +3 -9
  618. package/src/tools/host-filesystem/write.ts +3 -9
  619. package/src/tools/host-terminal/host-shell.ts +3 -9
  620. package/src/tools/mcp/mcp-tool-factory.ts +1 -8
  621. package/src/tools/memory/register.test.ts +1 -1
  622. package/src/tools/memory/register.ts +4 -9
  623. package/src/tools/network/__tests__/web-fetch-metadata.test.ts +229 -0
  624. package/src/tools/network/__tests__/web-search-metadata.test.ts +346 -0
  625. package/src/tools/network/domain-normalize.ts +17 -0
  626. package/src/tools/network/web-fetch.ts +216 -73
  627. package/src/tools/network/web-search.ts +216 -98
  628. package/src/tools/registry.ts +7 -23
  629. package/src/tools/schema-transforms.ts +1 -1
  630. package/src/tools/skills/execute.ts +3 -9
  631. package/src/tools/skills/load.ts +3 -9
  632. package/src/tools/skills/skill-tool-factory.ts +1 -8
  633. package/src/tools/subagent/notify-parent.ts +3 -9
  634. package/src/tools/system/request-permission.ts +3 -9
  635. package/src/tools/terminal/safe-env.ts +3 -2
  636. package/src/tools/terminal/shell.ts +3 -9
  637. package/src/tools/tool-approval-handler.ts +19 -12
  638. package/src/tools/tool-defaults.ts +94 -0
  639. package/src/tools/types.ts +31 -98
  640. package/src/tools/ui-surface/definitions.ts +9 -23
  641. package/src/types/onboarding-context.ts +4 -0
  642. package/src/usage/pricing.ts +23 -0
  643. package/src/usage/types.ts +12 -0
  644. package/src/util/__tests__/favicon.test.ts +84 -0
  645. package/src/util/favicon.ts +40 -0
  646. package/src/util/logger.ts +16 -7
  647. package/src/util/platform.ts +7 -7
  648. package/src/util/sqlite3-runtime.ts +65 -0
  649. package/src/workspace/git-service.ts +75 -4
  650. package/src/workspace/migrations/086-revert-stale-gemini-mis-rewrites.ts +1 -0
  651. package/src/workspace/migrations/088-deprecate-background-conversation-override.ts +103 -0
  652. package/src/workspace/migrations/089-move-memory-tree-out-of-v3.ts +86 -0
  653. package/src/workspace/migrations/registry.ts +4 -0
  654. package/src/__tests__/compaction-strip-metadata-clear.test.ts +0 -206
  655. package/src/__tests__/message-complete-display-id.test.ts +0 -175
  656. package/src/config/bundled-skills/document/SKILL.md +0 -54
  657. package/src/config/bundled-skills/document/TOOLS.json +0 -106
  658. package/src/daemon/seed-files.ts +0 -18
  659. package/src/prompts/cache-boundary.ts +0 -8
  660. package/src/runtime/routes/interface-routes.ts +0 -43
  661. /package/src/config/bundled-skills/{document → document-editor}/tools/document-create.ts +0 -0
  662. /package/src/config/bundled-skills/{document → document-editor}/tools/document-delete.ts +0 -0
  663. /package/src/config/bundled-skills/{document → document-editor}/tools/document-list.ts +0 -0
  664. /package/src/config/bundled-skills/{document → document-editor}/tools/document-read.ts +0 -0
  665. /package/src/config/bundled-skills/{document → document-editor}/tools/document-update.ts +0 -0
@@ -0,0 +1,307 @@
1
+ /**
2
+ * OAuth2 Device Authorization Grant (RFC 8628).
3
+ *
4
+ * Implements the device-code flow for environments where a browser redirect
5
+ * is impractical (CLI, headless). The user visits a verification URI and
6
+ * enters a short code; meanwhile, the client polls the token endpoint until
7
+ * authorization completes.
8
+ *
9
+ * This is intentionally separate from the PKCE authorization code flow in
10
+ * oauth2.ts — different grant type, different UX (no localhost server), and
11
+ * different polling lifecycle.
12
+ */
13
+
14
+ import { getLogger } from "../util/logger.js";
15
+
16
+ const log = getLogger("oauth2-device-code");
17
+
18
+ // ---------------------------------------------------------------------------
19
+ // Types
20
+ // ---------------------------------------------------------------------------
21
+
22
+ export interface DeviceCodeConfig {
23
+ deviceCodeUrl: string;
24
+ tokenUrl: string;
25
+ clientId: string;
26
+ scopes: string[];
27
+ audience?: string;
28
+ }
29
+
30
+ export interface DeviceCodeInitResult {
31
+ deviceCode: string;
32
+ userCode: string;
33
+ verificationUri: string;
34
+ verificationUriComplete?: string;
35
+ expiresIn: number;
36
+ interval: number;
37
+ }
38
+
39
+ export interface DeviceCodeTokenResult {
40
+ accessToken: string;
41
+ refreshToken?: string;
42
+ expiresIn?: number;
43
+ tokenType?: string;
44
+ scope?: string;
45
+ }
46
+
47
+ export class DeviceCodeError extends Error {
48
+ constructor(
49
+ message: string,
50
+ public readonly code:
51
+ | "expired_token"
52
+ | "access_denied"
53
+ | "request_failed"
54
+ | "aborted",
55
+ ) {
56
+ super(message);
57
+ this.name = "DeviceCodeError";
58
+ }
59
+ }
60
+
61
+ // ---------------------------------------------------------------------------
62
+ // Well-known provider configs
63
+ // ---------------------------------------------------------------------------
64
+
65
+ export const OPENAI_DEVICE_CODE_CONFIG: DeviceCodeConfig = {
66
+ deviceCodeUrl: "https://auth.openai.com/oauth/device/code",
67
+ tokenUrl: "https://auth.openai.com/oauth/token",
68
+ clientId: "app_EMoamEEZ73f0CkXaXp7hrann",
69
+ scopes: ["openid", "profile", "email", "offline_access"],
70
+ audience: "https://chatgpt.com",
71
+ };
72
+
73
+ // ---------------------------------------------------------------------------
74
+ // Device code request
75
+ // ---------------------------------------------------------------------------
76
+
77
+ export async function requestDeviceCode(
78
+ config: DeviceCodeConfig,
79
+ ): Promise<DeviceCodeInitResult> {
80
+ const body: Record<string, string> = {
81
+ client_id: config.clientId,
82
+ scope: config.scopes.join(" "),
83
+ };
84
+ if (config.audience) {
85
+ body.audience = config.audience;
86
+ }
87
+
88
+ const resp = await fetch(config.deviceCodeUrl, {
89
+ method: "POST",
90
+ headers: {
91
+ "Content-Type": "application/x-www-form-urlencoded",
92
+ Accept: "application/json",
93
+ },
94
+ body: new URLSearchParams(body),
95
+ });
96
+
97
+ if (!resp.ok) {
98
+ const rawBody = await resp.text().catch(() => "");
99
+ log.error(
100
+ { status: resp.status, body: rawBody },
101
+ "Device code request failed",
102
+ );
103
+ throw new DeviceCodeError(
104
+ `Device code request failed (HTTP ${resp.status})`,
105
+ "request_failed",
106
+ );
107
+ }
108
+
109
+ const data = (await resp.json()) as Record<string, unknown>;
110
+
111
+ return {
112
+ deviceCode: data.device_code as string,
113
+ userCode: data.user_code as string,
114
+ verificationUri: data.verification_uri as string,
115
+ verificationUriComplete: data.verification_uri_complete as
116
+ | string
117
+ | undefined,
118
+ expiresIn: data.expires_in as number,
119
+ interval: (data.interval as number | undefined) ?? 5,
120
+ };
121
+ }
122
+
123
+ // ---------------------------------------------------------------------------
124
+ // Token polling
125
+ // ---------------------------------------------------------------------------
126
+
127
+ /**
128
+ * Poll the token endpoint until the user completes authorization or the
129
+ * device code expires.
130
+ *
131
+ * Handles RFC 8628 error codes:
132
+ * - `authorization_pending` — keep polling
133
+ * - `slow_down` — increase interval by 5 seconds (per spec)
134
+ * - `expired_token` — abort with error
135
+ * - `access_denied` — abort with error
136
+ */
137
+ export async function pollForToken(
138
+ config: DeviceCodeConfig,
139
+ deviceCode: string,
140
+ intervalSeconds: number,
141
+ expiresIn: number,
142
+ signal?: AbortSignal,
143
+ /** @internal Test-only: override the sleep function to avoid real delays. */
144
+ _sleepFn?: (ms: number, signal?: AbortSignal) => Promise<void>,
145
+ ): Promise<DeviceCodeTokenResult> {
146
+ const doSleep = _sleepFn ?? sleep;
147
+ let interval = intervalSeconds;
148
+ const deadline = Date.now() + expiresIn * 1000;
149
+
150
+ while (Date.now() < deadline) {
151
+ if (signal?.aborted) {
152
+ throw new DeviceCodeError("Device code flow aborted", "aborted");
153
+ }
154
+
155
+ await doSleep(interval * 1000, signal);
156
+
157
+ if (signal?.aborted) {
158
+ throw new DeviceCodeError("Device code flow aborted", "aborted");
159
+ }
160
+
161
+ const body = new URLSearchParams({
162
+ grant_type: "urn:ietf:params:oauth:grant-type:device_code",
163
+ device_code: deviceCode,
164
+ client_id: config.clientId,
165
+ });
166
+
167
+ let resp: Response;
168
+ try {
169
+ resp = await fetch(config.tokenUrl, {
170
+ method: "POST",
171
+ headers: {
172
+ "Content-Type": "application/x-www-form-urlencoded",
173
+ Accept: "application/json",
174
+ },
175
+ body,
176
+ signal,
177
+ });
178
+ } catch (err) {
179
+ if (signal?.aborted) {
180
+ throw new DeviceCodeError("Device code flow aborted", "aborted");
181
+ }
182
+ log.warn({ err }, "Token poll request failed, will retry");
183
+ continue;
184
+ }
185
+
186
+ const data = (await resp.json()) as Record<string, unknown>;
187
+
188
+ if (resp.ok) {
189
+ log.info("Device code authorization completed");
190
+ return {
191
+ accessToken: data.access_token as string,
192
+ refreshToken: data.refresh_token as string | undefined,
193
+ expiresIn: data.expires_in as number | undefined,
194
+ tokenType: data.token_type as string | undefined,
195
+ scope: data.scope as string | undefined,
196
+ };
197
+ }
198
+
199
+ const errorCode = data.error as string | undefined;
200
+
201
+ if (errorCode === "authorization_pending") {
202
+ log.debug("Authorization pending, continuing to poll");
203
+ continue;
204
+ }
205
+
206
+ if (errorCode === "slow_down") {
207
+ interval += 5;
208
+ log.info({ newInterval: interval }, "Received slow_down, increasing poll interval");
209
+ continue;
210
+ }
211
+
212
+ if (errorCode === "expired_token") {
213
+ throw new DeviceCodeError(
214
+ "Device code expired before user completed authorization",
215
+ "expired_token",
216
+ );
217
+ }
218
+
219
+ if (errorCode === "access_denied") {
220
+ throw new DeviceCodeError(
221
+ "User denied the authorization request",
222
+ "access_denied",
223
+ );
224
+ }
225
+
226
+ log.error(
227
+ { status: resp.status, error: errorCode },
228
+ "Unexpected token poll error",
229
+ );
230
+ throw new DeviceCodeError(
231
+ `Token poll failed: ${errorCode ?? `HTTP ${resp.status}`}`,
232
+ "request_failed",
233
+ );
234
+ }
235
+
236
+ throw new DeviceCodeError(
237
+ "Device code expired before user completed authorization",
238
+ "expired_token",
239
+ );
240
+ }
241
+
242
+ // ---------------------------------------------------------------------------
243
+ // Combined flow
244
+ // ---------------------------------------------------------------------------
245
+
246
+ export interface DeviceCodeFlowResult {
247
+ tokens: DeviceCodeTokenResult;
248
+ init: DeviceCodeInitResult;
249
+ }
250
+
251
+ /**
252
+ * Run the full device-code flow:
253
+ * 1. Request a device code + user code
254
+ * 2. Return the user code and verification URI (caller shows these to the user)
255
+ * 3. Poll for the token
256
+ *
257
+ * The returned `init` contains the user code and verification URI that the
258
+ * caller should present to the user before awaiting `tokens`.
259
+ */
260
+ export async function startDeviceCodeFlow(
261
+ config: DeviceCodeConfig,
262
+ signal?: AbortSignal,
263
+ ): Promise<DeviceCodeFlowResult> {
264
+ const init = await requestDeviceCode(config);
265
+
266
+ log.info(
267
+ {
268
+ verificationUri: init.verificationUri,
269
+ expiresIn: init.expiresIn,
270
+ interval: init.interval,
271
+ },
272
+ "Device code flow started",
273
+ );
274
+
275
+ const tokens = await pollForToken(
276
+ config,
277
+ init.deviceCode,
278
+ init.interval,
279
+ init.expiresIn,
280
+ signal,
281
+ );
282
+
283
+ return { tokens, init };
284
+ }
285
+
286
+ // ---------------------------------------------------------------------------
287
+ // Helpers
288
+ // ---------------------------------------------------------------------------
289
+
290
+ function sleep(ms: number, signal?: AbortSignal): Promise<void> {
291
+ return new Promise((resolve, reject) => {
292
+ if (signal?.aborted) {
293
+ reject(new DeviceCodeError("Device code flow aborted", "aborted"));
294
+ return;
295
+ }
296
+ const timer = setTimeout(resolve, ms);
297
+ if (typeof timer === "object" && "unref" in timer) timer.unref();
298
+ signal?.addEventListener(
299
+ "abort",
300
+ () => {
301
+ clearTimeout(timer);
302
+ reject(new DeviceCodeError("Device code flow aborted", "aborted"));
303
+ },
304
+ { once: true },
305
+ );
306
+ });
307
+ }
@@ -86,6 +86,10 @@ export interface OAuth2FlowOptions {
86
86
  * instead of an OS-assigned random port. Required for providers like Slack that
87
87
  * need pre-registered redirect URIs. */
88
88
  loopbackPort?: number;
89
+ /** Override the loopback callback path. Defaults to `/oauth/callback`.
90
+ * Required for providers with pre-registered redirect URIs that use a
91
+ * different path (e.g. OpenAI Codex uses `/auth/callback`). */
92
+ loopbackCallbackPath?: string;
89
93
  }
90
94
 
91
95
  export interface OAuth2FlowResult {
@@ -98,15 +102,15 @@ export interface OAuth2FlowResult {
98
102
  // PKCE helpers
99
103
  // ---------------------------------------------------------------------------
100
104
 
101
- function generateCodeVerifier(): string {
105
+ export function generateCodeVerifier(): string {
102
106
  return randomBytes(32).toString("base64url");
103
107
  }
104
108
 
105
- function generateCodeChallenge(verifier: string): string {
109
+ export function generateCodeChallenge(verifier: string): string {
106
110
  return createHash("sha256").update(verifier).digest("base64url");
107
111
  }
108
112
 
109
- function generateState(): string {
113
+ export function generateState(): string {
110
114
  return randomBytes(16).toString("hex");
111
115
  }
112
116
 
@@ -114,7 +118,7 @@ function generateState(): string {
114
118
  // Token exchange (shared between transports)
115
119
  // ---------------------------------------------------------------------------
116
120
 
117
- async function exchangeCodeForTokens(
121
+ export async function exchangeCodeForTokens(
118
122
  config: OAuth2Config,
119
123
  code: string,
120
124
  redirectUri: string,
@@ -293,6 +297,7 @@ async function runLoopbackFlow(
293
297
  codeChallenge: string,
294
298
  state: string,
295
299
  loopbackPort?: number,
300
+ callbackPath?: string,
296
301
  ): Promise<OAuth2FlowResult> {
297
302
  const { code, redirectUri } = await startLoopbackServerAndWaitForCode(
298
303
  config,
@@ -300,6 +305,7 @@ async function runLoopbackFlow(
300
305
  codeChallenge,
301
306
  state,
302
307
  loopbackPort,
308
+ callbackPath,
303
309
  );
304
310
 
305
311
  return await exchangeCodeForTokens(config, code, redirectUri, codeVerifier);
@@ -317,7 +323,9 @@ function startLoopbackServerAndWaitForCode(
317
323
  codeChallenge: string,
318
324
  state: string,
319
325
  loopbackPort?: number,
326
+ callbackPath?: string,
320
327
  ): Promise<{ code: string; redirectUri: string }> {
328
+ const effectiveCallbackPath = callbackPath ?? LOOPBACK_CALLBACK_PATH;
321
329
  return new Promise((resolve, reject) => {
322
330
  let settled = false;
323
331
  let boundRedirectUri = "";
@@ -340,7 +348,7 @@ function startLoopbackServerAndWaitForCode(
340
348
 
341
349
  const url = new URL(req.url ?? "/", `http://127.0.0.1`);
342
350
 
343
- if (url.pathname !== LOOPBACK_CALLBACK_PATH) {
351
+ if (url.pathname !== effectiveCallbackPath) {
344
352
  log.info(
345
353
  { pathname: url.pathname },
346
354
  "oauth2 loopback: non-callback path, returning 404",
@@ -426,7 +434,7 @@ function startLoopbackServerAndWaitForCode(
426
434
 
427
435
  server.listen(loopbackPort ?? 0, "localhost", () => {
428
436
  const addr = server.address() as { port: number };
429
- boundRedirectUri = `http://localhost:${addr.port}${LOOPBACK_CALLBACK_PATH}`;
437
+ boundRedirectUri = `http://localhost:${addr.port}${effectiveCallbackPath}`;
430
438
 
431
439
  log.info(
432
440
  { port: addr.port, redirectUri: boundRedirectUri },
@@ -497,7 +505,11 @@ export async function prepareOAuth2Flow(
497
505
  const transport = options?.callbackTransport ?? "loopback";
498
506
 
499
507
  if (transport === "loopback") {
500
- return prepareLoopbackFlow(config, options?.loopbackPort);
508
+ return prepareLoopbackFlow(
509
+ config,
510
+ options?.loopbackPort,
511
+ options?.loopbackCallbackPath,
512
+ );
501
513
  }
502
514
 
503
515
  // Dynamic imports required here to avoid circular dependencies with
@@ -555,6 +567,7 @@ export async function prepareOAuth2Flow(
555
567
  async function prepareLoopbackFlow(
556
568
  config: OAuth2Config,
557
569
  loopbackPort?: number,
570
+ callbackPath?: string,
558
571
  ): Promise<OAuth2PreparedFlow> {
559
572
  const codeVerifier = generateCodeVerifier();
560
573
  const codeChallenge = generateCodeChallenge(codeVerifier);
@@ -563,6 +576,7 @@ async function prepareLoopbackFlow(
563
576
  const { redirectUri, codePromise } = await startLoopbackServerForPreparedFlow(
564
577
  state,
565
578
  loopbackPort,
579
+ callbackPath,
566
580
  );
567
581
 
568
582
  const authParams = new URLSearchParams({
@@ -599,7 +613,9 @@ async function prepareLoopbackFlow(
599
613
  function startLoopbackServerForPreparedFlow(
600
614
  state: string,
601
615
  loopbackPort?: number,
616
+ callbackPath?: string,
602
617
  ): Promise<{ redirectUri: string; codePromise: Promise<string> }> {
618
+ const effectiveCallbackPath = callbackPath ?? LOOPBACK_CALLBACK_PATH;
603
619
  return new Promise((resolveSetup, rejectSetup) => {
604
620
  let settled = false;
605
621
  let listening = false;
@@ -619,7 +635,7 @@ function startLoopbackServerForPreparedFlow(
619
635
 
620
636
  const url = new URL(req.url ?? "/", `http://127.0.0.1`);
621
637
 
622
- if (url.pathname !== LOOPBACK_CALLBACK_PATH) {
638
+ if (url.pathname !== effectiveCallbackPath) {
623
639
  res.writeHead(404, { "Content-Type": "text/plain" });
624
640
  res.end("Not found");
625
641
  return;
@@ -683,7 +699,7 @@ function startLoopbackServerForPreparedFlow(
683
699
 
684
700
  server.listen(loopbackPort ?? 0, "localhost", () => {
685
701
  const addr = server.address() as { port: number };
686
- const redirectUri = `http://localhost:${addr.port}${LOOPBACK_CALLBACK_PATH}`;
702
+ const redirectUri = `http://localhost:${addr.port}${effectiveCallbackPath}`;
687
703
  listening = true;
688
704
  resolveSetup({ redirectUri, codePromise });
689
705
  });
@@ -784,6 +800,7 @@ export async function startOAuth2Flow(
784
800
  codeChallenge,
785
801
  state,
786
802
  options?.loopbackPort,
803
+ options?.loopbackCallbackPath,
787
804
  );
788
805
  }
789
806
 
@@ -113,6 +113,11 @@ const RECONNECT_COOLDOWN_MS = 3_000;
113
113
  */
114
114
  const CREDENTIAL_OP_TIMEOUT_MS = 45_000;
115
115
 
116
+ /** Returns the current CES RPC client if one has been injected. */
117
+ export function getCesClient(): CesClient | undefined {
118
+ return _cesClient;
119
+ }
120
+
116
121
  /** Inject a CES RPC client for credential routing. Resets the resolved backend. */
117
122
  export function setCesClient(client: CesClient | undefined): void {
118
123
  _cesClient = client;
@@ -111,7 +111,9 @@ export async function fetchCatalog(): Promise<CatalogSkill[]> {
111
111
  if (!Array.isArray(manifest.skills)) {
112
112
  throw new Error("Platform catalog has invalid skills array");
113
113
  }
114
- return manifest.skills;
114
+ return manifest.skills.filter(
115
+ (s): s is CatalogSkill => !!s && typeof s.id === "string",
116
+ );
115
117
  }
116
118
 
117
119
  export function readLocalCatalog(repoSkillsDir: string): CatalogSkill[] {
@@ -119,7 +121,9 @@ export function readLocalCatalog(repoSkillsDir: string): CatalogSkill[] {
119
121
  const raw = readFileSync(join(repoSkillsDir, "catalog.json"), "utf-8");
120
122
  const manifest = JSON.parse(raw) as CatalogManifest;
121
123
  if (!Array.isArray(manifest.skills)) return [];
122
- return manifest.skills;
124
+ return manifest.skills.filter(
125
+ (s): s is CatalogSkill => !!s && typeof s.id === "string",
126
+ );
123
127
  } catch {
124
128
  return [];
125
129
  }
@@ -38,6 +38,18 @@ export interface LlmUsageTelemetryEvent extends TelemetryEventBase {
38
38
  output_tokens: number;
39
39
  cache_creation_input_tokens: number | null;
40
40
  cache_read_input_tokens: number | null;
41
+ /**
42
+ * The provider's untouched `usage` block. Anthropic surfaces a TTL
43
+ * breakdown under `cache_creation.ephemeral_{5m,1h}_input_tokens`;
44
+ * OpenAI surfaces cached-read counts under
45
+ * `prompt_tokens_details.cached_tokens` (and reasoning tokens under
46
+ * `completion_tokens_details`). Both shapes are forwarded verbatim so
47
+ * downstream consumers (admin charts, dbt models) can extract any
48
+ * provider-specific detail without requiring a schema change here.
49
+ * Null when the provider did not return a usage payload, and for
50
+ * daemons that predate `260-llm-usage-add-raw-usage`.
51
+ */
52
+ raw_usage: Record<string, unknown> | null;
41
53
  actor: string;
42
54
  llm_call_site: LLMCallSite | null;
43
55
  inference_profile: string | null;
@@ -159,6 +159,7 @@ function makeUsageEvent(
159
159
  outputTokens: 50,
160
160
  cacheCreationInputTokens: 10,
161
161
  cacheReadInputTokens: 5,
162
+ rawUsage: null,
162
163
  actor: "main_agent",
163
164
  callSite: null,
164
165
  inferenceProfile: null,
@@ -435,6 +436,53 @@ describe("UsageTelemetryReporter", () => {
435
436
  expect(e.inference_profile_source).toBe("conversation");
436
437
  expect(e.cost).toBe(0.001);
437
438
  expect(e.recorded_at).toBe(1700000099000);
439
+ // raw_usage defaults to null on this fixture (the makeUsageEvent default),
440
+ // confirming the wire shape carries the key as `null` rather than
441
+ // dropping it for legacy rows or providers that did not return a
442
+ // usage block.
443
+ expect(e.raw_usage).toBeNull();
444
+ });
445
+
446
+ test("payload forwards the provider's raw_usage block verbatim", async () => {
447
+ // The reporter must surface the literal usage object the provider
448
+ // returned (Anthropic nests TTL breakdown under `cache_creation`,
449
+ // OpenAI nests cached-read counts under `prompt_tokens_details`,
450
+ // etc.) so downstream consumers can extract any provider-specific
451
+ // detail without a wire-level schema change. Anything that
452
+ // transforms, summarises, or strips fields here destroys data the
453
+ // admin charts and dbt models depend on.
454
+ const rawUsage = {
455
+ input_tokens: 200,
456
+ output_tokens: 100,
457
+ cache_creation_input_tokens: 750,
458
+ cache_creation: {
459
+ ephemeral_5m_input_tokens: 250,
460
+ ephemeral_1h_input_tokens: 500,
461
+ },
462
+ cache_read_input_tokens: 15,
463
+ service_tier: "standard",
464
+ };
465
+ const event = makeUsageEvent({
466
+ id: "evt-raw-usage",
467
+ provider: "anthropic",
468
+ model: "claude-sonnet-4-20250514",
469
+ cacheCreationInputTokens: 750,
470
+ rawUsage,
471
+ });
472
+ mockQueryUnreportedUsageEvents.mockReturnValue([event]);
473
+ mockFetch.mockImplementation(() =>
474
+ Promise.resolve(new Response('{"accepted":1}', { status: 200 })),
475
+ );
476
+
477
+ const reporter = new UsageTelemetryReporter();
478
+ await reporter.flush();
479
+
480
+ const body = JSON.parse(
481
+ (mockFetch.mock.calls[0] as [string, RequestInit])[1].body as string,
482
+ );
483
+ const e = body.events[0];
484
+ expect(e.cache_creation_input_tokens).toBe(750);
485
+ expect(e.raw_usage).toEqual(rawUsage);
438
486
  });
439
487
 
440
488
  test("payload preserves null attribution for historical usage rows", async () => {
@@ -234,6 +234,7 @@ export class UsageTelemetryReporter {
234
234
  output_tokens: e.outputTokens,
235
235
  cache_creation_input_tokens: e.cacheCreationInputTokens ?? null,
236
236
  cache_read_input_tokens: e.cacheReadInputTokens ?? null,
237
+ raw_usage: e.rawUsage,
237
238
  actor: e.actor,
238
239
  llm_call_site: e.callSite,
239
240
  inference_profile: e.inferenceProfile,