@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
@@ -0,0 +1,400 @@
1
+ import { createHash } from "node:crypto";
2
+
3
+ import { eq } from "drizzle-orm";
4
+ import { v4 as uuid } from "uuid";
5
+
6
+ import { estimateTextTokens } from "../context/token-estimator.js";
7
+ import { getLogger } from "../util/logger.js";
8
+ import { getDb, rawChanges } from "./db.js";
9
+ import { enqueueMemoryJob, type MemoryJobType } from "./jobs-store.js";
10
+ import {
11
+ memoryChunks,
12
+ memoryEpisodes,
13
+ memoryObservations,
14
+ } from "./schema.js";
15
+
16
+ const log = getLogger("memory-archive-store");
17
+
18
+ // ── Content hashing ─────────────────────────────────────────────────
19
+
20
+ /**
21
+ * Compute a SHA-256 content hash for a chunk's content, scoped by scopeId.
22
+ * Used for idempotent upserts — if the hash already exists within the same
23
+ * scope, the chunk is skipped.
24
+ */
25
+ export function computeChunkContentHash(
26
+ scopeId: string,
27
+ content: string,
28
+ ): string {
29
+ return createHash("sha256").update(`${scopeId}|${content}`).digest("hex");
30
+ }
31
+
32
+ /**
33
+ * Compute a SHA-256 hash of the observation content, scoped by scopeId.
34
+ * Used for idempotent chunk deduplication.
35
+ */
36
+ export function computeObservationContentHash(
37
+ scopeId: string,
38
+ content: string,
39
+ ): string {
40
+ return createHash("sha256").update(`${scopeId}|${content}`).digest("hex");
41
+ }
42
+
43
+ // ── Token estimation ────────────────────────────────────────────────
44
+
45
+ /**
46
+ * Rough token count estimate based on character length.
47
+ * Uses the common ~4 chars/token heuristic for English text.
48
+ */
49
+ export function estimateTokens(text: string): number {
50
+ return Math.max(1, Math.ceil(text.length / 4));
51
+ }
52
+
53
+ // ── Chunk upsert ────────────────────────────────────────────────────
54
+
55
+ export interface UpsertChunkInput {
56
+ /** Scope for memory isolation. Defaults to "default". */
57
+ scopeId?: string;
58
+ /** FK to the parent observation. */
59
+ observationId: string;
60
+ /** The chunk text to embed and recall. */
61
+ content: string;
62
+ /** Optional pre-computed token estimate. If omitted, estimated from content length. */
63
+ tokenEstimate?: number;
64
+ }
65
+
66
+ export interface UpsertChunkResult {
67
+ chunkId: string;
68
+ /** True if a new row was inserted; false if an existing row matched the content hash. */
69
+ inserted: boolean;
70
+ }
71
+
72
+ /**
73
+ * Idempotently upsert a chunk into the archive. If a chunk with the same
74
+ * (scopeId, contentHash) already exists, the insert is skipped and the
75
+ * existing row's id is returned. Otherwise a new row is inserted and an
76
+ * `embed_chunk` job is enqueued.
77
+ */
78
+ export function upsertChunk(input: UpsertChunkInput): UpsertChunkResult {
79
+ const scopeId = input.scopeId ?? "default";
80
+ const contentHash = computeChunkContentHash(scopeId, input.content);
81
+ const tokenEstimate = input.tokenEstimate ?? estimateTokens(input.content);
82
+ const db = getDb();
83
+
84
+ // Check for an existing chunk with the same content hash in this scope
85
+ const existing = db
86
+ .select({ id: memoryChunks.id })
87
+ .from(memoryChunks)
88
+ .where(eq(memoryChunks.contentHash, contentHash))
89
+ .get();
90
+
91
+ if (existing) {
92
+ log.debug(
93
+ { scopeId, contentHash, existingId: existing.id },
94
+ "Chunk already exists, skipping insert",
95
+ );
96
+ return { chunkId: existing.id, inserted: false };
97
+ }
98
+
99
+ const chunkId = uuid();
100
+ const now = Date.now();
101
+
102
+ db.insert(memoryChunks)
103
+ .values({
104
+ id: chunkId,
105
+ scopeId,
106
+ observationId: input.observationId,
107
+ content: input.content,
108
+ tokenEstimate,
109
+ contentHash,
110
+ createdAt: now,
111
+ })
112
+ .run();
113
+
114
+ // Enqueue an embedding job for the new chunk
115
+ enqueueMemoryJob("embed_chunk", {
116
+ chunkId,
117
+ scopeId,
118
+ });
119
+
120
+ log.debug(
121
+ { chunkId, scopeId, contentHash },
122
+ "Inserted new chunk and enqueued embed_chunk job",
123
+ );
124
+
125
+ return { chunkId, inserted: true };
126
+ }
127
+
128
+ /**
129
+ * Upsert multiple chunks for a single observation. Returns results for
130
+ * each input in the same order.
131
+ */
132
+ export function upsertChunks(inputs: UpsertChunkInput[]): UpsertChunkResult[] {
133
+ return inputs.map((input) => upsertChunk(input));
134
+ }
135
+
136
+ // ── Chunk queries ───────────────────────────────────────────────────
137
+
138
+ /**
139
+ * Get a chunk by its ID.
140
+ */
141
+ export function getChunkById(
142
+ chunkId: string,
143
+ ): typeof memoryChunks.$inferSelect | undefined {
144
+ const db = getDb();
145
+ return db
146
+ .select()
147
+ .from(memoryChunks)
148
+ .where(eq(memoryChunks.id, chunkId))
149
+ .get();
150
+ }
151
+
152
+ /**
153
+ * Get all chunks for a given observation.
154
+ */
155
+ export function getChunksByObservationId(
156
+ observationId: string,
157
+ ): Array<typeof memoryChunks.$inferSelect> {
158
+ const db = getDb();
159
+ return db
160
+ .select()
161
+ .from(memoryChunks)
162
+ .where(eq(memoryChunks.observationId, observationId))
163
+ .all();
164
+ }
165
+
166
+ // ── Episode insertion helpers ───────────────────────────────────────
167
+
168
+ export interface InsertEpisodeParams {
169
+ scopeId?: string;
170
+ conversationId: string;
171
+ title: string;
172
+ summary: string;
173
+ tokenEstimate: number;
174
+ source?: string;
175
+ startAt: number;
176
+ endAt: number;
177
+ }
178
+
179
+ /**
180
+ * Insert an episode row produced by conversation compaction.
181
+ * Compaction episodes summarize a contiguous block of turns that was
182
+ * compressed to free context-window space.
183
+ *
184
+ * An `embed_episode` job is enqueued automatically so the episode
185
+ * becomes searchable via vector recall.
186
+ */
187
+ export function insertCompactionEpisode(params: InsertEpisodeParams): {
188
+ episodeId: string;
189
+ jobId: string;
190
+ } {
191
+ return insertEpisodeAndEnqueue(params);
192
+ }
193
+
194
+ /**
195
+ * Insert an episode row produced by resolution (end-of-conversation)
196
+ * summarization. Resolution episodes capture the full narrative arc
197
+ * of a completed conversation.
198
+ *
199
+ * An `embed_episode` job is enqueued automatically so the episode
200
+ * becomes searchable via vector recall.
201
+ */
202
+ export function insertResolutionEpisode(params: InsertEpisodeParams): {
203
+ episodeId: string;
204
+ jobId: string;
205
+ } {
206
+ return insertEpisodeAndEnqueue(params);
207
+ }
208
+
209
+ // ── Internal (episode) ──────────────────────────────────────────────
210
+
211
+ function insertEpisodeAndEnqueue(params: InsertEpisodeParams): {
212
+ episodeId: string;
213
+ jobId: string;
214
+ } {
215
+ const db = getDb();
216
+ const episodeId = uuid();
217
+ const now = Date.now();
218
+
219
+ db.insert(memoryEpisodes)
220
+ .values({
221
+ id: episodeId,
222
+ scopeId: params.scopeId ?? "default",
223
+ conversationId: params.conversationId,
224
+ title: params.title,
225
+ summary: params.summary,
226
+ tokenEstimate: params.tokenEstimate,
227
+ source: params.source ?? null,
228
+ startAt: params.startAt,
229
+ endAt: params.endAt,
230
+ createdAt: now,
231
+ updatedAt: now,
232
+ })
233
+ .run();
234
+
235
+ const jobId = enqueueMemoryJob("embed_episode" satisfies MemoryJobType, {
236
+ episodeId,
237
+ });
238
+
239
+ log.debug(
240
+ { episodeId, jobId, conversationId: params.conversationId },
241
+ "Inserted episode and enqueued embed job",
242
+ );
243
+
244
+ return { episodeId, jobId };
245
+ }
246
+
247
+ // ── Observation types ───────────────────────────────────────────────
248
+
249
+ export interface InsertObservationParams {
250
+ conversationId: string;
251
+ messageId?: string | null;
252
+ role: string;
253
+ content: string;
254
+ scopeId?: string;
255
+ modality?: string;
256
+ source?: string | null;
257
+ }
258
+
259
+ export interface InsertedObservation {
260
+ observationId: string;
261
+ chunkId: string | null;
262
+ contentHash: string;
263
+ embeddingJobId: string | null;
264
+ }
265
+
266
+ // ── Observation insert helpers ──────────────────────────────────────
267
+
268
+ /**
269
+ * Insert a raw observation row and its associated chunk. If a chunk with the
270
+ * same content hash already exists in the scope, the chunk insert is skipped
271
+ * (idempotent dual-write safety). An `embed_observation` job is enqueued when
272
+ * a new chunk is created.
273
+ *
274
+ * Returns the observation ID, chunk ID (null if deduplicated), content hash,
275
+ * and embedding job ID (null if no new chunk was created).
276
+ */
277
+ export function insertObservation(
278
+ params: InsertObservationParams,
279
+ ): InsertedObservation {
280
+ const db = getDb();
281
+ const now = Date.now();
282
+ const scopeId = params.scopeId ?? "default";
283
+ const modality = params.modality ?? "text";
284
+
285
+ const observationId = uuid();
286
+ const contentHash = computeObservationContentHash(scopeId, params.content);
287
+
288
+ // Insert the observation row
289
+ db.insert(memoryObservations)
290
+ .values({
291
+ id: observationId,
292
+ scopeId,
293
+ conversationId: params.conversationId,
294
+ messageId: params.messageId ?? null,
295
+ role: params.role,
296
+ content: params.content,
297
+ modality,
298
+ source: params.source ?? null,
299
+ createdAt: now,
300
+ })
301
+ .run();
302
+
303
+ // Attempt to insert the chunk — the unique index on (scope_id, content_hash)
304
+ // will cause a conflict if this content was already chunked. We use
305
+ // onConflictDoNothing to silently skip the duplicate.
306
+ const chunkId = uuid();
307
+ const tokenEstimate = estimateTextTokens(params.content);
308
+
309
+ db.insert(memoryChunks)
310
+ .values({
311
+ id: chunkId,
312
+ scopeId,
313
+ observationId,
314
+ content: params.content,
315
+ tokenEstimate,
316
+ contentHash,
317
+ createdAt: now,
318
+ })
319
+ .onConflictDoNothing({
320
+ target: [memoryChunks.scopeId, memoryChunks.contentHash],
321
+ })
322
+ .run();
323
+
324
+ // Drizzle bun:sqlite .run() returns void; use rawChanges() to detect no-ops
325
+ const chunkInserted = rawChanges() > 0;
326
+
327
+ let embeddingJobId: string | null = null;
328
+ if (chunkInserted) {
329
+ embeddingJobId = enqueueMemoryJob("embed_observation", {
330
+ observationId,
331
+ chunkId,
332
+ });
333
+ log.debug(
334
+ { observationId, chunkId, contentHash, embeddingJobId },
335
+ "Inserted observation with new chunk, enqueued embed job",
336
+ );
337
+ } else {
338
+ log.debug(
339
+ { observationId, contentHash },
340
+ "Inserted observation, chunk deduplicated by content hash",
341
+ );
342
+ }
343
+
344
+ return {
345
+ observationId,
346
+ chunkId: chunkInserted ? chunkId : null,
347
+ contentHash,
348
+ embeddingJobId,
349
+ };
350
+ }
351
+
352
+ /**
353
+ * Insert multiple observations in a single transaction.
354
+ * Returns the results for each insertion.
355
+ */
356
+ export function insertObservations(
357
+ observations: InsertObservationParams[],
358
+ ): InsertedObservation[] {
359
+ const db = getDb();
360
+ const results: InsertedObservation[] = [];
361
+ db.transaction((tx) => {
362
+ // We don't use `tx` directly for individual inserts because
363
+ // insertObservation uses getDb() internally. Instead, the transaction
364
+ // wrapper ensures atomicity at the SQLite level.
365
+ void tx;
366
+ for (const obs of observations) {
367
+ results.push(insertObservation(obs));
368
+ }
369
+ });
370
+ return results;
371
+ }
372
+
373
+ /**
374
+ * Look up an observation by ID.
375
+ */
376
+ export function getObservation(
377
+ observationId: string,
378
+ ): typeof memoryObservations.$inferSelect | undefined {
379
+ const db = getDb();
380
+ return db
381
+ .select()
382
+ .from(memoryObservations)
383
+ .where(eq(memoryObservations.id, observationId))
384
+ .get();
385
+ }
386
+
387
+ /**
388
+ * Look up a chunk by observation ID. Returns the first chunk linked to the
389
+ * given observation, or undefined if none exists.
390
+ */
391
+ export function getChunkByObservationId(
392
+ observationId: string,
393
+ ): typeof memoryChunks.$inferSelect | undefined {
394
+ const db = getDb();
395
+ return db
396
+ .select()
397
+ .from(memoryChunks)
398
+ .where(eq(memoryChunks.observationId, observationId))
399
+ .get();
400
+ }