@vellumai/assistant 0.5.1 → 0.5.3

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 (405) hide show
  1. package/ARCHITECTURE.md +163 -54
  2. package/docs/architecture/integrations.md +62 -67
  3. package/docs/credential-execution-service.md +3 -3
  4. package/docs/skills.md +100 -0
  5. package/package.json +1 -1
  6. package/src/__tests__/agent-loop.test.ts +111 -0
  7. package/src/__tests__/always-loaded-tools-guard.test.ts +3 -4
  8. package/src/__tests__/app-builder-tool-scripts.test.ts +13 -151
  9. package/src/__tests__/app-dir-path-guard.test.ts +78 -0
  10. package/src/__tests__/app-executors.test.ts +1 -291
  11. package/src/__tests__/app-git-history.test.ts +4 -4
  12. package/src/__tests__/app-routes-csp.test.ts +1 -0
  13. package/src/__tests__/app-store-dir-names.test.ts +426 -0
  14. package/src/__tests__/attachments-store.test.ts +169 -21
  15. package/src/__tests__/attachments.test.ts +115 -1
  16. package/src/__tests__/btw-routes.test.ts +1 -0
  17. package/src/__tests__/canonical-guardian-store.test.ts +38 -0
  18. package/src/__tests__/channel-reply-delivery.test.ts +55 -0
  19. package/src/__tests__/checker.test.ts +54 -0
  20. package/src/__tests__/claude-code-skill-regression.test.ts +2 -0
  21. package/src/__tests__/claude-code-tool-profiles.test.ts +2 -0
  22. package/src/__tests__/compaction.benchmark.test.ts +2 -1
  23. package/src/__tests__/config-schema-cmd.test.ts +68 -21
  24. package/src/__tests__/config-schema.test.ts +1 -1
  25. package/src/__tests__/conversation-agent-loop-overflow.test.ts +156 -5
  26. package/src/__tests__/conversation-agent-loop.test.ts +297 -2
  27. package/src/__tests__/conversation-attachments.test.ts +17 -19
  28. package/src/__tests__/conversation-disk-view-integration.test.ts +277 -0
  29. package/src/__tests__/conversation-disk-view.test.ts +810 -0
  30. package/src/__tests__/conversation-error.test.ts +1 -1
  31. package/src/__tests__/conversation-fork-crud.test.ts +551 -0
  32. package/src/__tests__/conversation-fork-route.test.ts +386 -0
  33. package/src/__tests__/conversation-history-web-search.test.ts +1 -1
  34. package/src/__tests__/conversation-key-store-disk-view.test.ts +130 -0
  35. package/src/__tests__/conversation-media-retry.test.ts +8 -2
  36. package/src/__tests__/conversation-memory-dirty-tail.test.ts +150 -0
  37. package/src/__tests__/conversation-provider-retry-repair.test.ts +7 -0
  38. package/src/__tests__/conversation-queue.test.ts +36 -1
  39. package/src/__tests__/conversation-routes-disk-view.test.ts +439 -0
  40. package/src/__tests__/conversation-routes-guardian-reply.test.ts +2 -2
  41. package/src/__tests__/conversation-routes-slash-commands.test.ts +2 -7
  42. package/src/__tests__/conversation-runtime-assembly.test.ts +17 -2
  43. package/src/__tests__/conversation-skill-tools.test.ts +4 -9
  44. package/src/__tests__/conversation-slash-commands.test.ts +149 -0
  45. package/src/__tests__/conversation-store.test.ts +24 -21
  46. package/src/__tests__/conversation-surfaces-state-update.test.ts +246 -0
  47. package/src/__tests__/conversation-surfaces-task-progress.test.ts +1 -0
  48. package/src/__tests__/conversation-title-service.test.ts +137 -0
  49. package/src/__tests__/conversation-tool-setup-app-refresh.test.ts +25 -315
  50. package/src/__tests__/conversation-tool-setup-memory-scope.test.ts +1 -0
  51. package/src/__tests__/conversation-tool-setup-side-effect-flag.test.ts +1 -0
  52. package/src/__tests__/conversation-wipe.test.ts +226 -0
  53. package/src/__tests__/conversation-workspace-cache-state.test.ts +44 -2
  54. package/src/__tests__/conversation-workspace-injection.test.ts +11 -0
  55. package/src/__tests__/credential-security-invariants.test.ts +3 -0
  56. package/src/__tests__/credential-vault-unit.test.ts +5 -10
  57. package/src/__tests__/cu-unified-flow.test.ts +1 -0
  58. package/src/__tests__/db-conversation-fork-lineage-migration.test.ts +241 -0
  59. package/src/__tests__/db-llm-request-log-provider-migration.test.ts +214 -0
  60. package/src/__tests__/db-memory-archive-migration.test.ts +372 -0
  61. package/src/__tests__/db-memory-brief-state-migration.test.ts +213 -0
  62. package/src/__tests__/db-memory-reducer-checkpoints.test.ts +273 -0
  63. package/src/__tests__/diagnostics-export.test.ts +70 -1
  64. package/src/__tests__/first-greeting.test.ts +80 -0
  65. package/src/__tests__/gateway-only-guard.test.ts +1 -0
  66. package/src/__tests__/handlers-user-message-approval-consumption.test.ts +3 -7
  67. package/src/__tests__/history-repair.test.ts +32 -10
  68. package/src/__tests__/http-conversation-lineage.test.ts +251 -0
  69. package/src/__tests__/image-source-path-reinject.test.ts +136 -0
  70. package/src/__tests__/inline-command-runner.test.ts +311 -0
  71. package/src/__tests__/inline-skill-authoring-guard.test.ts +220 -0
  72. package/src/__tests__/inline-skill-load-permissions.test.ts +435 -0
  73. package/src/__tests__/list-messages-attachments.test.ts +96 -0
  74. package/src/__tests__/llm-context-normalization.test.ts +1116 -0
  75. package/src/__tests__/llm-context-route-provider.test.ts +217 -0
  76. package/src/__tests__/llm-request-log-turn-query.test.ts +270 -0
  77. package/src/__tests__/media-generate-image.test.ts +47 -94
  78. package/src/__tests__/memory-brief-open-loops.test.ts +530 -0
  79. package/src/__tests__/memory-brief-time.test.ts +285 -0
  80. package/src/__tests__/memory-brief-wrapper.test.ts +311 -0
  81. package/src/__tests__/memory-chunk-archive.test.ts +400 -0
  82. package/src/__tests__/memory-chunk-dual-write.test.ts +453 -0
  83. package/src/__tests__/memory-episode-archive.test.ts +370 -0
  84. package/src/__tests__/memory-episode-dual-write.test.ts +626 -0
  85. package/src/__tests__/memory-lifecycle-e2e.test.ts +3 -1
  86. package/src/__tests__/memory-observation-archive.test.ts +375 -0
  87. package/src/__tests__/memory-observation-dual-write.test.ts +318 -0
  88. package/src/__tests__/memory-recall-quality.test.ts +7 -7
  89. package/src/__tests__/memory-reducer-store.test.ts +728 -0
  90. package/src/__tests__/memory-reducer-types.test.ts +699 -0
  91. package/src/__tests__/memory-reducer.test.ts +698 -0
  92. package/src/__tests__/memory-regressions.test.ts +6 -4
  93. package/src/__tests__/memory-simplified-config.test.ts +281 -0
  94. package/src/__tests__/migration-cross-version-compatibility.test.ts +4 -1
  95. package/src/__tests__/migration-export-http.test.ts +3 -1
  96. package/src/__tests__/migration-import-commit-http.test.ts +18 -4
  97. package/src/__tests__/migration-import-preflight-http.test.ts +1 -3
  98. package/src/__tests__/mime-builder.test.ts +3 -2
  99. package/src/__tests__/non-member-access-request.test.ts +12 -1
  100. package/src/__tests__/notification-decision-identity.test.ts +52 -0
  101. package/src/__tests__/oauth-apps-routes.test.ts +103 -0
  102. package/src/__tests__/oauth-store.test.ts +115 -0
  103. package/src/__tests__/parse-identity-fields.test.ts +129 -0
  104. package/src/__tests__/provider-error-scenarios.test.ts +1 -3
  105. package/src/__tests__/provider-failover-actual-provider.test.ts +66 -0
  106. package/src/__tests__/recording-handler.test.ts +17 -0
  107. package/src/__tests__/registry.test.ts +3 -8
  108. package/src/__tests__/relay-server.test.ts +1 -1
  109. package/src/__tests__/runtime-attachment-metadata.test.ts +7 -3
  110. package/src/__tests__/schema-transforms.test.ts +165 -5
  111. package/src/__tests__/server-history-render.test.ts +2 -2
  112. package/src/__tests__/skill-load-inline-command.test.ts +598 -0
  113. package/src/__tests__/skill-load-inline-includes.test.ts +644 -0
  114. package/src/__tests__/skills-inline-command-expansions.test.ts +301 -0
  115. package/src/__tests__/skills-transitive-hash.test.ts +333 -0
  116. package/src/__tests__/slack-app-setup-skill-regression.test.ts +3 -1
  117. package/src/__tests__/slack-inbound-verification.test.ts +2 -2
  118. package/src/__tests__/starter-task-flow.test.ts +1 -0
  119. package/src/__tests__/suggestion-routes.test.ts +443 -0
  120. package/src/__tests__/swarm-conversation-integration.test.ts +1 -0
  121. package/src/__tests__/swarm-recursion.test.ts +1 -0
  122. package/src/__tests__/swarm-tool.test.ts +1 -0
  123. package/src/__tests__/tool-execution-abort-cleanup.test.ts +1 -0
  124. package/src/__tests__/tool-preview-lifecycle.test.ts +32 -5
  125. package/src/__tests__/top-level-renderer.test.ts +22 -0
  126. package/src/__tests__/turn-boundary-resolution.test.ts +243 -0
  127. package/src/__tests__/vellum-self-knowledge-inline-command.test.ts +320 -0
  128. package/src/__tests__/web-fetch.test.ts +6 -2
  129. package/src/__tests__/workspace-migration-006-services-config.test.ts +335 -0
  130. package/src/__tests__/workspace-migration-007-web-search-provider-rename.test.ts +312 -0
  131. package/src/__tests__/workspace-migration-009-backfill-conversation-disk-view.test.ts +278 -0
  132. package/src/__tests__/workspace-migration-010-app-dir-rename.test.ts +275 -0
  133. package/src/__tests__/workspace-migration-012-rename-conversation-disk-view-dirs.test.ts +77 -0
  134. package/src/__tests__/workspace-migration-013-repair-conversation-disk-view.test.ts +401 -0
  135. package/src/__tests__/workspace-migration-backfill-installation-id.test.ts +328 -0
  136. package/src/__tests__/workspace-migration-seed-device-id.test.ts +6 -10
  137. package/src/agent/attachments.ts +27 -1
  138. package/src/agent/loop.ts +29 -1
  139. package/src/avatar/traits-png-sync.ts +80 -25
  140. package/src/bundler/app-bundler.ts +4 -4
  141. package/src/calls/call-domain.ts +1 -0
  142. package/src/calls/voice-session-bridge.ts +1 -0
  143. package/src/cli/commands/auth.ts +92 -0
  144. package/src/cli/commands/avatar.ts +7 -6
  145. package/src/cli/commands/config.ts +2 -0
  146. package/src/cli/commands/oauth/providers.ts +29 -0
  147. package/src/cli/program.ts +12 -0
  148. package/src/cli.ts +15 -48
  149. package/src/config/bundled-skills/app-builder/SKILL.md +103 -28
  150. package/src/config/bundled-skills/app-builder/TOOLS.json +5 -199
  151. package/src/config/bundled-skills/app-builder/tools/{app-query.ts → app-refresh.ts} +2 -2
  152. package/src/config/bundled-skills/contacts/tools/google-contacts.ts +2 -3
  153. package/src/config/bundled-skills/gmail/tools/gmail-archive.ts +6 -9
  154. package/src/config/bundled-skills/gmail/tools/gmail-attachments.ts +4 -6
  155. package/src/config/bundled-skills/gmail/tools/gmail-draft.ts +2 -3
  156. package/src/config/bundled-skills/gmail/tools/gmail-filters.ts +2 -3
  157. package/src/config/bundled-skills/gmail/tools/gmail-follow-up.ts +2 -3
  158. package/src/config/bundled-skills/gmail/tools/gmail-forward.ts +2 -3
  159. package/src/config/bundled-skills/gmail/tools/gmail-label.ts +4 -6
  160. package/src/config/bundled-skills/gmail/tools/gmail-outreach-scan.ts +2 -3
  161. package/src/config/bundled-skills/gmail/tools/gmail-send-draft.ts +2 -3
  162. package/src/config/bundled-skills/gmail/tools/gmail-sender-digest.ts +2 -3
  163. package/src/config/bundled-skills/gmail/tools/gmail-trash.ts +2 -3
  164. package/src/config/bundled-skills/gmail/tools/gmail-unsubscribe.ts +2 -3
  165. package/src/config/bundled-skills/gmail/tools/gmail-vacation.ts +2 -3
  166. package/src/config/bundled-skills/google-calendar/tools/shared.ts +1 -1
  167. package/src/config/bundled-skills/image-studio/SKILL.md +2 -2
  168. package/src/config/bundled-skills/image-studio/TOOLS.json +2 -2
  169. package/src/config/bundled-skills/image-studio/tools/media-generate-image.ts +45 -72
  170. package/src/config/bundled-skills/media-processing/tools/extract-keyframes.ts +2 -2
  171. package/src/config/bundled-skills/messaging/tools/shared.ts +1 -1
  172. package/src/config/bundled-skills/settings/tools/voice-config-update.ts +19 -3
  173. package/src/config/bundled-skills/skill-management/SKILL.md +1 -1
  174. package/src/config/bundled-skills/skill-management/TOOLS.json +2 -2
  175. package/src/config/bundled-skills/slack/tools/shared.ts +19 -4
  176. package/src/config/bundled-skills/slack/tools/slack-scan-digest.ts +2 -3
  177. package/src/config/bundled-skills/transcribe/SKILL.md +1 -1
  178. package/src/config/bundled-skills/transcribe/TOOLS.json +2 -6
  179. package/src/config/bundled-skills/transcribe/tools/transcribe-media.ts +19 -83
  180. package/src/config/bundled-tool-registry.ts +2 -14
  181. package/src/config/feature-flag-registry.json +24 -0
  182. package/src/config/loader.ts +65 -0
  183. package/src/config/raw-config-utils.ts +58 -0
  184. package/src/config/schema-utils.ts +28 -7
  185. package/src/config/schema.ts +20 -0
  186. package/src/config/schemas/elevenlabs.ts +18 -0
  187. package/src/config/schemas/memory-lifecycle.ts +4 -2
  188. package/src/config/schemas/memory-simplified.ts +101 -0
  189. package/src/config/schemas/memory-storage.ts +1 -1
  190. package/src/config/schemas/memory.ts +4 -0
  191. package/src/config/schemas/services.ts +8 -6
  192. package/src/config/skills.ts +50 -4
  193. package/src/contacts/contact-store.ts +13 -6
  194. package/src/contacts/contacts-write.ts +0 -1
  195. package/src/context/window-manager.ts +13 -2
  196. package/src/daemon/conversation-agent-loop-handlers.ts +54 -8
  197. package/src/daemon/conversation-agent-loop.ts +127 -20
  198. package/src/daemon/conversation-attachments.ts +18 -36
  199. package/src/daemon/conversation-error.ts +2 -1
  200. package/src/daemon/conversation-history.ts +18 -4
  201. package/src/daemon/conversation-lifecycle.ts +50 -16
  202. package/src/daemon/conversation-messaging.ts +70 -26
  203. package/src/daemon/conversation-process.ts +58 -34
  204. package/src/daemon/conversation-runtime-assembly.ts +22 -38
  205. package/src/daemon/conversation-slash.ts +121 -256
  206. package/src/daemon/conversation-surfaces.ts +170 -24
  207. package/src/daemon/conversation-tool-setup.ts +0 -6
  208. package/src/daemon/conversation-workspace.ts +21 -1
  209. package/src/daemon/conversation.ts +69 -30
  210. package/src/daemon/first-greeting.ts +35 -0
  211. package/src/daemon/handlers/config-embeddings.ts +156 -0
  212. package/src/daemon/handlers/config-model.ts +62 -26
  213. package/src/daemon/handlers/conversations.ts +0 -23
  214. package/src/daemon/handlers/identity.ts +12 -1
  215. package/src/daemon/handlers/recording.ts +26 -21
  216. package/src/daemon/host-cu-proxy.ts +2 -2
  217. package/src/daemon/lifecycle.ts +115 -65
  218. package/src/daemon/message-protocol.ts +3 -0
  219. package/src/daemon/message-types/conversations.ts +18 -0
  220. package/src/daemon/message-types/messages.ts +1 -0
  221. package/src/daemon/message-types/shared.ts +2 -0
  222. package/src/daemon/message-types/surfaces.ts +2 -0
  223. package/src/daemon/message-types/upgrades.ts +23 -0
  224. package/src/daemon/server.ts +83 -12
  225. package/src/daemon/shutdown-handlers.ts +8 -5
  226. package/src/daemon/startup-error.ts +9 -0
  227. package/src/daemon/tool-side-effects.ts +11 -28
  228. package/src/events/tool-permission-telemetry-listener.ts +1 -3
  229. package/src/followups/followup-store.ts +47 -1
  230. package/src/instrument.ts +0 -4
  231. package/src/media/app-icon-generator.ts +2 -2
  232. package/src/memory/app-git-service.ts +28 -16
  233. package/src/memory/app-store.ts +230 -41
  234. package/src/memory/archive-store.ts +400 -0
  235. package/src/memory/attachments-store.ts +558 -130
  236. package/src/memory/brief-formatting.ts +33 -0
  237. package/src/memory/brief-open-loops.ts +266 -0
  238. package/src/memory/brief-time.ts +161 -0
  239. package/src/memory/brief.ts +75 -0
  240. package/src/memory/conversation-attention-store.ts +70 -0
  241. package/src/memory/conversation-crud.ts +591 -8
  242. package/src/memory/conversation-directories.ts +125 -0
  243. package/src/memory/conversation-disk-view.ts +390 -0
  244. package/src/memory/conversation-key-store.ts +17 -5
  245. package/src/memory/conversation-queries.ts +5 -1
  246. package/src/memory/conversation-title-service.ts +21 -49
  247. package/src/memory/db-init.ts +40 -0
  248. package/src/memory/embedding-backend.ts +42 -53
  249. package/src/memory/embedding-gemini.test.ts +4 -4
  250. package/src/memory/embedding-local.ts +1 -3
  251. package/src/memory/embedding-ollama.ts +1 -3
  252. package/src/memory/embedding-openai.ts +1 -3
  253. package/src/memory/indexer.ts +114 -21
  254. package/src/memory/items-extractor.ts +42 -13
  255. package/src/memory/job-handlers/conversation-starters.ts +6 -1
  256. package/src/memory/job-handlers/embedding.test.ts +2 -4
  257. package/src/memory/job-handlers/embedding.ts +83 -0
  258. package/src/memory/job-utils.ts +1 -1
  259. package/src/memory/jobs-store.ts +6 -0
  260. package/src/memory/jobs-worker.ts +12 -0
  261. package/src/memory/llm-request-log-store.ts +100 -1
  262. package/src/memory/migrations/102-alter-table-columns.ts +5 -0
  263. package/src/memory/migrations/146-schedule-oneshot-routing.ts +3 -3
  264. package/src/memory/migrations/147-migrate-reminders-to-schedules.ts +66 -70
  265. package/src/memory/migrations/148-drop-reminders-table.ts +5 -9
  266. package/src/memory/migrations/160-drop-loopback-port-column.ts +1 -3
  267. package/src/memory/migrations/174-rename-thread-starters-table.ts +0 -7
  268. package/src/memory/migrations/178-oauth-providers-managed-service-config-key.ts +15 -0
  269. package/src/memory/migrations/179-llm-request-log-message-id.ts +16 -0
  270. package/src/memory/migrations/180-backfill-inline-attachments-to-disk.ts +66 -0
  271. package/src/memory/migrations/181-rename-thread-starters-checkpoints.ts +46 -0
  272. package/src/memory/migrations/182-oauth-providers-display-metadata.ts +20 -0
  273. package/src/memory/migrations/183-add-conversation-fork-lineage.ts +22 -0
  274. package/src/memory/migrations/184-llm-request-log-provider.ts +12 -0
  275. package/src/memory/migrations/185-memory-brief-state.ts +52 -0
  276. package/src/memory/migrations/186-memory-archive.ts +109 -0
  277. package/src/memory/migrations/187-memory-reducer-checkpoints.ts +19 -0
  278. package/src/memory/migrations/index.ts +10 -0
  279. package/src/memory/migrations/registry.ts +13 -0
  280. package/src/memory/qdrant-client.ts +23 -4
  281. package/src/memory/reducer-store.ts +271 -0
  282. package/src/memory/reducer-types.ts +99 -0
  283. package/src/memory/reducer.ts +453 -0
  284. package/src/memory/retriever.test.ts +601 -2
  285. package/src/memory/retriever.ts +85 -9
  286. package/src/memory/schema/conversations.ts +9 -0
  287. package/src/memory/schema/index.ts +2 -0
  288. package/src/memory/schema/infrastructure.ts +13 -7
  289. package/src/memory/schema/memory-archive.ts +121 -0
  290. package/src/memory/schema/memory-brief.ts +55 -0
  291. package/src/memory/schema/oauth.ts +6 -0
  292. package/src/memory/search/semantic.ts +17 -4
  293. package/src/messaging/providers/gmail/mime-builder.ts +3 -1
  294. package/src/notifications/copy-composer.ts +26 -0
  295. package/src/notifications/decision-engine.ts +14 -1
  296. package/src/notifications/emit-signal.ts +1 -1
  297. package/src/notifications/signal.ts +36 -0
  298. package/src/oauth/byo-connection.test.ts +1 -45
  299. package/src/oauth/byo-connection.ts +2 -8
  300. package/src/oauth/connect-orchestrator.ts +15 -11
  301. package/src/oauth/connection-resolver.test.ts +191 -0
  302. package/src/oauth/connection-resolver.ts +66 -38
  303. package/src/oauth/connection.ts +0 -1
  304. package/src/oauth/oauth-store.ts +99 -47
  305. package/src/oauth/platform-connection.test.ts +0 -1
  306. package/src/oauth/platform-connection.ts +11 -3
  307. package/src/oauth/seed-providers.ts +78 -3
  308. package/src/oauth/token-persistence.ts +16 -10
  309. package/src/permissions/checker.ts +160 -14
  310. package/src/permissions/defaults.ts +14 -0
  311. package/src/prompts/templates/BOOTSTRAP.md +2 -0
  312. package/src/providers/anthropic/client.ts +8 -1
  313. package/src/providers/failover.ts +4 -1
  314. package/src/providers/gemini/client.ts +50 -0
  315. package/src/providers/model-catalog.ts +92 -0
  316. package/src/providers/model-intents.ts +29 -20
  317. package/src/providers/openai/client.ts +49 -0
  318. package/src/providers/types.ts +2 -0
  319. package/src/runtime/access-request-helper.ts +16 -7
  320. package/src/runtime/auth/credential-service.ts +3 -1
  321. package/src/runtime/auth/route-policy.ts +14 -1
  322. package/src/runtime/btw-sidechain.ts +101 -0
  323. package/src/runtime/channel-reply-delivery.ts +17 -1
  324. package/src/runtime/http-router.ts +3 -1
  325. package/src/runtime/http-server.ts +196 -141
  326. package/src/runtime/http-types.ts +1 -0
  327. package/src/runtime/migrations/vbundle-builder.ts +5 -1
  328. package/src/runtime/routes/access-request-decision.ts +41 -0
  329. package/src/runtime/routes/app-management-routes.ts +6 -3
  330. package/src/runtime/routes/app-routes.ts +7 -3
  331. package/src/runtime/routes/approval-routes.ts +1 -0
  332. package/src/runtime/routes/approval-strategies/guardian-callback-strategy.ts +34 -2
  333. package/src/runtime/routes/attachment-routes.ts +45 -15
  334. package/src/runtime/routes/btw-routes.ts +21 -61
  335. package/src/runtime/routes/conversation-management-routes.ts +74 -0
  336. package/src/runtime/routes/conversation-query-routes.ts +187 -10
  337. package/src/runtime/routes/conversation-routes.ts +269 -28
  338. package/src/runtime/routes/conversation-starter-routes.ts +9 -11
  339. package/src/runtime/routes/diagnostics-routes.ts +1 -0
  340. package/src/runtime/routes/identity-routes.ts +2 -35
  341. package/src/runtime/routes/inbound-stages/acl-enforcement.ts +2 -2
  342. package/src/runtime/routes/llm-context-normalization.ts +1212 -0
  343. package/src/runtime/routes/log-export-routes.ts +3 -0
  344. package/src/runtime/routes/memory-item-routes.test.ts +34 -0
  345. package/src/runtime/routes/memory-item-routes.ts +94 -5
  346. package/src/runtime/routes/migration-routes.ts +4 -1
  347. package/src/runtime/routes/oauth-apps.ts +291 -0
  348. package/src/runtime/routes/secret-routes.ts +30 -1
  349. package/src/runtime/routes/settings-routes.ts +14 -0
  350. package/src/runtime/routes/surface-action-routes.ts +68 -1
  351. package/src/runtime/routes/trace-event-routes.ts +4 -1
  352. package/src/schedule/schedule-store.ts +30 -21
  353. package/src/security/secure-keys.ts +21 -0
  354. package/src/signals/bash.ts +1 -1
  355. package/src/skills/inline-command-expansions.ts +204 -0
  356. package/src/skills/inline-command-render.ts +127 -0
  357. package/src/skills/inline-command-runner.ts +242 -0
  358. package/src/skills/transitive-version-hash.ts +88 -0
  359. package/src/swarm/backend-claude-code.ts +3 -6
  360. package/src/tasks/task-store.ts +43 -1
  361. package/src/telemetry/usage-telemetry-reporter.test.ts +3 -2
  362. package/src/telemetry/usage-telemetry-reporter.ts +3 -1
  363. package/src/tools/AGENTS.md +6 -10
  364. package/src/tools/apps/executors.ts +17 -232
  365. package/src/tools/claude-code/claude-code.ts +2 -3
  366. package/src/tools/credentials/vault.ts +7 -12
  367. package/src/tools/host-filesystem/read.ts +13 -10
  368. package/src/tools/network/__tests__/web-search.test.ts +4 -2
  369. package/src/tools/permission-checker.ts +8 -1
  370. package/src/tools/schedule/list.ts +2 -7
  371. package/src/tools/schema-transforms.ts +5 -0
  372. package/src/tools/shared/filesystem/format-diff.ts +2 -7
  373. package/src/tools/skills/execute.ts +1 -1
  374. package/src/tools/skills/load.ts +140 -6
  375. package/src/tools/tool-manifest.ts +0 -6
  376. package/src/tools/ui-surface/definitions.ts +2 -2
  377. package/src/util/device-id.ts +28 -5
  378. package/src/util/platform.ts +24 -0
  379. package/src/util/pricing.ts +1 -0
  380. package/src/util/retry.ts +1 -3
  381. package/src/workspace/migrations/003-seed-device-id.ts +3 -4
  382. package/src/workspace/migrations/006-services-config.ts +5 -0
  383. package/src/workspace/migrations/008-voice-timeout-and-max-steps.ts +12 -0
  384. package/src/workspace/migrations/009-backfill-conversation-disk-view.ts +10 -0
  385. package/src/workspace/migrations/010-app-dir-rename.ts +223 -0
  386. package/src/workspace/migrations/{002-backfill-installation-id.ts → 011-backfill-installation-id.ts} +24 -13
  387. package/src/workspace/migrations/012-rename-conversation-disk-view-dirs.ts +64 -0
  388. package/src/workspace/migrations/013-repair-conversation-disk-view.ts +11 -0
  389. package/src/workspace/migrations/rebuild-conversation-disk-view.ts +186 -0
  390. package/src/workspace/migrations/registry.ts +11 -1
  391. package/src/workspace/top-level-renderer.ts +12 -0
  392. package/src/__tests__/asset-materialize-tool.test.ts +0 -523
  393. package/src/__tests__/asset-search-tool.test.ts +0 -536
  394. package/src/__tests__/fixtures/media-reuse-fixtures.ts +0 -56
  395. package/src/__tests__/media-reuse-story.e2e.test.ts +0 -762
  396. package/src/__tests__/media-visibility-policy.test.ts +0 -190
  397. package/src/config/bundled-skills/app-builder/tools/app-file-edit.ts +0 -14
  398. package/src/config/bundled-skills/app-builder/tools/app-file-list.ts +0 -13
  399. package/src/config/bundled-skills/app-builder/tools/app-file-read.ts +0 -21
  400. package/src/config/bundled-skills/app-builder/tools/app-file-write.ts +0 -14
  401. package/src/config/bundled-skills/app-builder/tools/app-list.ts +0 -13
  402. package/src/config/bundled-skills/app-builder/tools/app-update.ts +0 -23
  403. package/src/daemon/media-visibility-policy.ts +0 -59
  404. package/src/tools/assets/materialize.ts +0 -248
  405. package/src/tools/assets/search.ts +0 -400
@@ -25,31 +25,25 @@ export interface BYOOAuthConnectionOptions {
25
25
  providerKey: string;
26
26
  baseUrl: string;
27
27
  accountInfo: string | null;
28
- grantedScopes: string[];
29
- credentialService: string;
30
28
  }
31
29
 
32
30
  export class BYOOAuthConnection implements OAuthConnection {
33
31
  readonly id: string;
34
32
  readonly providerKey: string;
35
33
  readonly accountInfo: string | null;
36
- readonly grantedScopes: string[];
37
34
 
38
35
  private readonly baseUrl: string;
39
- private readonly credentialService: string;
40
36
 
41
37
  constructor(opts: BYOOAuthConnectionOptions) {
42
38
  this.id = opts.id;
43
39
  this.providerKey = opts.providerKey;
44
40
  this.baseUrl = opts.baseUrl;
45
41
  this.accountInfo = opts.accountInfo;
46
- this.grantedScopes = opts.grantedScopes;
47
- this.credentialService = opts.credentialService;
48
42
  }
49
43
 
50
44
  async request(req: OAuthConnectionRequest): Promise<OAuthConnectionResponse> {
51
45
  return withValidToken(
52
- this.credentialService,
46
+ this.providerKey,
53
47
  async (token) => {
54
48
  const effectiveBaseUrl = req.baseUrl ?? this.baseUrl;
55
49
  let fullUrl = `${effectiveBaseUrl}${req.path}`;
@@ -106,7 +100,7 @@ export class BYOOAuthConnection implements OAuthConnection {
106
100
  }
107
101
 
108
102
  async withToken<T>(fn: (token: string) => Promise<T>): Promise<T> {
109
- return withValidToken(this.credentialService, fn, {
103
+ return withValidToken(this.providerKey, fn, {
110
104
  connectionId: this.id,
111
105
  });
112
106
  }
@@ -252,12 +252,13 @@ export async function orchestrateOAuthConnect(
252
252
  prepared.completion
253
253
  .then(async (result) => {
254
254
  try {
255
- let accountInfo: string | undefined;
255
+ let parsedAccountIdentifier: string | undefined;
256
256
 
257
- // Run identity verifier if available (code-side behavior)
257
+ // Parse account identifier from the provider's identity endpoint.
258
+ // Best-effort — format varies by provider and may fail.
258
259
  if (behavior.identityVerifier) {
259
260
  try {
260
- accountInfo = await behavior.identityVerifier(
261
+ parsedAccountIdentifier = await behavior.identityVerifier(
261
262
  result.tokens.accessToken,
262
263
  );
263
264
  } catch {
@@ -270,19 +271,19 @@ export async function orchestrateOAuthConnect(
270
271
  tokens: result.tokens,
271
272
  grantedScopes: result.grantedScopes,
272
273
  rawTokenResponse: result.rawTokenResponse,
273
- identityAccountInfo: accountInfo,
274
+ parsedAccountIdentifier,
274
275
  });
275
276
  log.info(
276
277
  {
277
278
  service: resolvedService,
278
- accountInfo: stored.accountInfo ?? accountInfo,
279
+ accountInfo: stored.accountInfo ?? parsedAccountIdentifier,
279
280
  },
280
281
  "Deferred OAuth2 flow completed — tokens stored",
281
282
  );
282
283
  options.onDeferredComplete?.({
283
284
  success: true,
284
285
  service: resolvedService,
285
- accountInfo: stored.accountInfo ?? accountInfo,
286
+ accountInfo: stored.accountInfo ?? parsedAccountIdentifier,
286
287
  });
287
288
  } catch (err) {
288
289
  log.error(
@@ -353,11 +354,14 @@ export async function orchestrateOAuthConnect(
353
354
  : undefined,
354
355
  );
355
356
 
356
- // Run identity verifier if available (code-side behavior)
357
- let verifiedIdentity: string | undefined;
357
+ // Parse account identifier from the provider's identity endpoint.
358
+ // Best-effort format varies by provider and may fail.
359
+ let parsedAccountIdentifier: string | undefined;
358
360
  if (behavior.identityVerifier) {
359
361
  try {
360
- verifiedIdentity = await behavior.identityVerifier(tokens.accessToken);
362
+ parsedAccountIdentifier = await behavior.identityVerifier(
363
+ tokens.accessToken,
364
+ );
361
365
  } catch {
362
366
  // Non-fatal
363
367
  }
@@ -368,14 +372,14 @@ export async function orchestrateOAuthConnect(
368
372
  tokens,
369
373
  grantedScopes,
370
374
  rawTokenResponse,
371
- identityAccountInfo: verifiedIdentity,
375
+ parsedAccountIdentifier,
372
376
  });
373
377
 
374
378
  return {
375
379
  success: true,
376
380
  deferred: false,
377
381
  grantedScopes,
378
- accountInfo: accountInfo ?? verifiedIdentity,
382
+ accountInfo: accountInfo ?? parsedAccountIdentifier,
379
383
  };
380
384
  } catch (err: unknown) {
381
385
  const message =
@@ -0,0 +1,191 @@
1
+ import { beforeEach, describe, expect, mock, test } from "bun:test";
2
+
3
+ // ---------------------------------------------------------------------------
4
+ // Mutable mock state
5
+ // ---------------------------------------------------------------------------
6
+
7
+ let mockProvider: Record<string, unknown> | undefined;
8
+ let mockConnection: Record<string, unknown> | undefined;
9
+ let mockAccessToken: string | undefined;
10
+ let mockConfig: Record<string, unknown> = {};
11
+ let mockManagedProxyCtx = {
12
+ enabled: false,
13
+ platformBaseUrl: "",
14
+ assistantApiKey: "",
15
+ };
16
+ let mockAssistantId = "";
17
+
18
+ // ---------------------------------------------------------------------------
19
+ // Module mocks (must precede imports of the module under test)
20
+ // ---------------------------------------------------------------------------
21
+
22
+ mock.module("../util/logger.js", () => ({
23
+ getLogger: () =>
24
+ new Proxy({} as Record<string, unknown>, {
25
+ get: () => () => {},
26
+ }),
27
+ }));
28
+
29
+ mock.module("./oauth-store.js", () => ({
30
+ getProvider: () => mockProvider,
31
+ getActiveConnection: (
32
+ _pk: string,
33
+ opts?: { clientId?: string; account?: string },
34
+ ) => {
35
+ if (opts?.clientId && mockConnection?.clientId !== opts.clientId)
36
+ return undefined;
37
+ if (opts?.account && mockConnection?.accountInfo !== opts.account)
38
+ return undefined;
39
+ return mockConnection;
40
+ },
41
+ }));
42
+
43
+ mock.module("../security/secure-keys.js", () => ({
44
+ getSecureKeyAsync: async () => mockAccessToken,
45
+ }));
46
+
47
+ mock.module("../config/loader.js", () => ({
48
+ getConfig: () => mockConfig,
49
+ }));
50
+
51
+ mock.module("../config/env.js", () => ({
52
+ getPlatformAssistantId: () => mockAssistantId,
53
+ }));
54
+
55
+ mock.module("../providers/managed-proxy/context.js", () => ({
56
+ resolveManagedProxyContext: async () => mockManagedProxyCtx,
57
+ }));
58
+
59
+ // ---------------------------------------------------------------------------
60
+ // Import the module under test (after all mocks are registered)
61
+ // ---------------------------------------------------------------------------
62
+
63
+ import { BYOOAuthConnection } from "./byo-connection.js";
64
+ import { resolveOAuthConnection } from "./connection-resolver.js";
65
+ import { PlatformOAuthConnection } from "./platform-connection.js";
66
+
67
+ // ---------------------------------------------------------------------------
68
+ // Helpers
69
+ // ---------------------------------------------------------------------------
70
+
71
+ function setupDefaults(): void {
72
+ mockProvider = {
73
+ providerKey: "integration:google",
74
+ baseUrl: "https://gmail.googleapis.com/gmail/v1/users/me",
75
+ managedServiceConfigKey: null,
76
+ };
77
+ mockConnection = {
78
+ id: "conn-1",
79
+ providerKey: "integration:google",
80
+ oauthAppId: "app-1",
81
+ accountInfo: "user@example.com",
82
+ grantedScopes: JSON.stringify(["scope-a", "scope-b"]),
83
+ status: "active",
84
+ clientId: "client-1",
85
+ };
86
+ mockAccessToken = "tok-valid";
87
+ mockConfig = {
88
+ services: {
89
+ inference: {
90
+ mode: "your-own",
91
+ provider: "anthropic",
92
+ model: "claude-opus-4-6",
93
+ },
94
+ "image-generation": {
95
+ mode: "your-own",
96
+ provider: "gemini",
97
+ model: "gemini-3.1-flash-image-preview",
98
+ },
99
+ "web-search": { mode: "your-own", provider: "inference-provider-native" },
100
+ "google-oauth": { mode: "managed" },
101
+ },
102
+ };
103
+ mockManagedProxyCtx = {
104
+ enabled: true,
105
+ platformBaseUrl: "https://platform.example.com",
106
+ assistantApiKey: "sk-test-key",
107
+ };
108
+ mockAssistantId = "asst-123";
109
+ }
110
+
111
+ // ---------------------------------------------------------------------------
112
+ // Tests
113
+ // ---------------------------------------------------------------------------
114
+
115
+ describe("resolveOAuthConnection", () => {
116
+ beforeEach(() => {
117
+ setupDefaults();
118
+ });
119
+
120
+ test("returns BYOOAuthConnection when provider has no managedServiceConfigKey", async () => {
121
+ const result = await resolveOAuthConnection("integration:google");
122
+ expect(result).toBeInstanceOf(BYOOAuthConnection);
123
+ expect(result.id).toBe("conn-1");
124
+ expect(result.providerKey).toBe("integration:google");
125
+ });
126
+
127
+ test("returns PlatformOAuthConnection when managed mode is active", async () => {
128
+ mockProvider!.managedServiceConfigKey = "google-oauth";
129
+
130
+ const result = await resolveOAuthConnection("integration:google");
131
+ expect(result).toBeInstanceOf(PlatformOAuthConnection);
132
+ expect(result.id).toBe("integration:google");
133
+ expect(result.providerKey).toBe("integration:google");
134
+ expect(result.accountInfo).toBeNull();
135
+ });
136
+
137
+ test("passes account through to PlatformOAuthConnection", async () => {
138
+ mockProvider!.managedServiceConfigKey = "google-oauth";
139
+
140
+ const result = await resolveOAuthConnection("integration:google", {
141
+ account: "user@example.com",
142
+ });
143
+ expect(result).toBeInstanceOf(PlatformOAuthConnection);
144
+ expect(result.accountInfo).toBe("user@example.com");
145
+ });
146
+
147
+ test("returns BYOOAuthConnection when service config mode is your-own", async () => {
148
+ mockProvider!.managedServiceConfigKey = "google-oauth";
149
+ (mockConfig.services as Record<string, unknown>)["google-oauth"] = {
150
+ mode: "your-own",
151
+ };
152
+
153
+ const result = await resolveOAuthConnection("integration:google");
154
+ expect(result).toBeInstanceOf(BYOOAuthConnection);
155
+ expect(result.id).toBe("conn-1");
156
+ });
157
+
158
+ test("managed path does not require a local connection row", async () => {
159
+ mockProvider!.managedServiceConfigKey = "google-oauth";
160
+ mockConnection = undefined;
161
+ mockAccessToken = undefined;
162
+
163
+ const result = await resolveOAuthConnection("integration:google");
164
+ expect(result).toBeInstanceOf(PlatformOAuthConnection);
165
+ });
166
+
167
+ test("managed path ignores clientId option", async () => {
168
+ mockProvider!.managedServiceConfigKey = "google-oauth";
169
+
170
+ const result = await resolveOAuthConnection("integration:google", {
171
+ clientId: "some-client-id",
172
+ });
173
+ expect(result).toBeInstanceOf(PlatformOAuthConnection);
174
+ });
175
+
176
+ test("BYO path narrows by clientId when provided", async () => {
177
+ const result = await resolveOAuthConnection("integration:google", {
178
+ clientId: "client-1",
179
+ });
180
+ expect(result).toBeInstanceOf(BYOOAuthConnection);
181
+ expect(result.id).toBe("conn-1");
182
+ });
183
+
184
+ test("BYO path returns no credential when clientId does not match", async () => {
185
+ await expect(
186
+ resolveOAuthConnection("integration:google", {
187
+ clientId: "wrong-client",
188
+ }),
189
+ ).rejects.toThrow(/No active OAuth connection found/);
190
+ });
191
+ });
@@ -1,72 +1,100 @@
1
+ import { getPlatformAssistantId } from "../config/env.js";
2
+ import { getConfig } from "../config/loader.js";
3
+ import { type Services, ServicesSchema } from "../config/schemas/services.js";
4
+ import { resolveManagedProxyContext } from "../providers/managed-proxy/context.js";
1
5
  import { getSecureKeyAsync } from "../security/secure-keys.js";
2
6
  import { BYOOAuthConnection } from "./byo-connection.js";
3
7
  import type { OAuthConnection } from "./connection.js";
4
- import {
5
- getApp,
6
- getConnectionByProvider,
7
- getConnectionByProviderAndAccount,
8
- getProvider,
9
- } from "./oauth-store.js";
8
+ import { getActiveConnection, getProvider } from "./oauth-store.js";
9
+ import { PlatformOAuthConnection } from "./platform-connection.js";
10
+
11
+ export interface ResolveOAuthConnectionOptions {
12
+ /** OAuth app client ID — narrows to a specific app when multiple BYO apps
13
+ * exist for the same provider. */
14
+ clientId?: string;
15
+ /** Account identifier (e.g. email, username) — disambiguates when multiple
16
+ * accounts are connected for the same provider. Best-effort: not guaranteed
17
+ * to be present on all connections. */
18
+ account?: string;
19
+ }
10
20
 
11
21
  /**
12
- * Resolve an OAuthConnection for a given credential service.
22
+ * Resolve an OAuthConnection for a given provider.
23
+ *
24
+ * Managed providers (where the service config `mode` is `"managed"`) are
25
+ * routed through the platform proxy with no local state required.
13
26
  *
14
- * When `accountInfo` is provided, resolves the connection for that specific
15
- * account (e.g. "user@gmail.com"). Otherwise falls back to the most recent
16
- * active connection.
27
+ * BYO providers resolve from the local SQLite oauth-store and require an
28
+ * active connection row and a stored access token.
17
29
  *
18
- * Reads exclusively from the SQLite oauth-store. Throws if no connection
19
- * exists (authorization required).
30
+ * @param providerKey - Provider identifier (e.g. "integration:google").
31
+ * Maps to the `provider_key` primary key in the `oauth_providers` table.
32
+ * @param options.clientId - Optional OAuth app client ID. When multiple BYO
33
+ * apps exist for the same provider, narrows the connection lookup to the
34
+ * app matching this client ID. Ignored for managed providers.
35
+ * @param options.account - Optional account identifier to disambiguate
36
+ * multi-account connections.
20
37
  */
21
38
  export async function resolveOAuthConnection(
22
- credentialService: string,
23
- accountInfo?: string,
39
+ providerKey: string,
40
+ options?: ResolveOAuthConnectionOptions,
24
41
  ): Promise<OAuthConnection> {
25
- const conn = accountInfo
26
- ? getConnectionByProviderAndAccount(credentialService, accountInfo)
27
- : getConnectionByProvider(credentialService);
42
+ const { clientId, account } = options ?? {};
43
+ const provider = getProvider(providerKey);
44
+ const managedKey = provider?.managedServiceConfigKey;
45
+
46
+ if (managedKey && managedKey in ServicesSchema.shape) {
47
+ const services: Services = getConfig().services;
48
+ if (services[managedKey as keyof Services].mode === "managed") {
49
+ const ctx = await resolveManagedProxyContext();
50
+ const assistantId = getPlatformAssistantId();
51
+ return new PlatformOAuthConnection({
52
+ id: providerKey,
53
+ providerKey,
54
+ externalId: providerKey,
55
+ accountInfo: account ?? null,
56
+ assistantId,
57
+ platformBaseUrl: ctx.platformBaseUrl,
58
+ apiKey: ctx.assistantApiKey,
59
+ });
60
+ }
61
+ }
62
+
63
+ // BYO path — requires a local connection row, access token, and base URL.
64
+ const conn = getActiveConnection(providerKey, { clientId, account });
28
65
  if (!conn) {
66
+ const filters = [
67
+ account && `account "${account}"`,
68
+ clientId && `client ID "${clientId}"`,
69
+ ].filter(Boolean);
70
+ const qualifier = filters.length
71
+ ? ` matching ${filters.join(" and ")}`
72
+ : "";
29
73
  throw new Error(
30
- `No credential found for "${credentialService}". Authorization required.`,
74
+ `No active OAuth connection found for "${providerKey}"${qualifier}. Connect the service first with oauth2_connect.`,
31
75
  );
32
76
  }
33
77
 
34
78
  const accessToken = await getSecureKeyAsync(
35
79
  `oauth_connection/${conn.id}/access_token`,
36
80
  );
37
-
38
81
  if (!accessToken) {
39
82
  throw new Error(
40
- `No access token found for "${credentialService}". Authorization required.`,
83
+ `OAuth connection for "${providerKey}" exists but has no access token. Re-authorize with oauth2_connect.`,
41
84
  );
42
85
  }
43
86
 
44
- // Look up the provider by credentialService first; fall back to the
45
- // connection's app's canonical providerKey so custom credential_service
46
- // overrides (e.g. "integration:github-work") still resolve to the well-known
47
- // provider's base URL. We traverse conn -> oauthApp -> providerKey because
48
- // conn.providerKey equals credentialService (getConnectionByProvider queries
49
- // WHERE providerKey = credentialService), whereas the app's providerKey is a
50
- // foreign key to the oauthProviders table.
51
- const provider =
52
- getProvider(credentialService) ??
53
- getProvider(getApp(conn.oauthAppId)?.providerKey ?? "");
54
87
  const baseUrl = provider?.baseUrl;
55
-
56
88
  if (!baseUrl) {
57
- throw new Error(`No base URL configured for "${credentialService}".`);
89
+ throw new Error(
90
+ `OAuth provider "${providerKey}" has no base URL configured. Check provider setup.`,
91
+ );
58
92
  }
59
93
 
60
- const grantedScopes: string[] = conn.grantedScopes
61
- ? JSON.parse(conn.grantedScopes)
62
- : [];
63
-
64
94
  return new BYOOAuthConnection({
65
95
  id: conn.id,
66
96
  providerKey: conn.providerKey,
67
97
  baseUrl,
68
98
  accountInfo: conn.accountInfo,
69
- grantedScopes,
70
- credentialService,
71
99
  });
72
100
  }
@@ -34,5 +34,4 @@ export interface OAuthConnection {
34
34
  readonly id: string;
35
35
  readonly providerKey: string;
36
36
  readonly accountInfo: string | null;
37
- readonly grantedScopes: string[];
38
37
  }