@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
@@ -1,400 +0,0 @@
1
- /**
2
- * asset_search - cross-conversation attachment metadata search.
3
- *
4
- * Queries the attachments store for matching assets by MIME type,
5
- * filename, recency, or conversation scope. Returns metadata and
6
- * attachment IDs only - never base64 payloads. The IDs can be
7
- * passed to asset_materialize (PR 35) to retrieve actual content.
8
- */
9
-
10
- import { and, desc, eq, gte, like } from "drizzle-orm";
11
-
12
- import {
13
- type AttachmentContext,
14
- isAttachmentVisible,
15
- } from "../../daemon/media-visibility-policy.js";
16
- import type { StoredAttachment } from "../../memory/attachments-store.js";
17
- import { getConversationType } from "../../memory/conversation-crud.js";
18
- import { getDb, rawAll } from "../../memory/db.js";
19
- import {
20
- attachments,
21
- conversations,
22
- messageAttachments,
23
- messages,
24
- } from "../../memory/schema.js";
25
- import { RiskLevel } from "../../permissions/types.js";
26
-
27
- /** Escape SQL LIKE wildcard characters so a literal substring match is used. */
28
- function escapeLikeWildcards(s: string): string {
29
- return s.replace(/%/g, "").replace(/_/g, "");
30
- }
31
- import type { ToolDefinition } from "../../providers/types.js";
32
- import { registerTool } from "../registry.js";
33
- import type { Tool, ToolContext, ToolExecutionResult } from "../types.js";
34
-
35
- // ---------------------------------------------------------------------------
36
- // Recency presets - map human-readable labels to epoch-ms cutoff offsets
37
- // ---------------------------------------------------------------------------
38
-
39
- const RECENCY_MS: Record<string, number> = {
40
- last_hour: 60 * 60 * 1000,
41
- last_24_hours: 24 * 60 * 60 * 1000,
42
- last_7_days: 7 * 24 * 60 * 60 * 1000,
43
- last_30_days: 30 * 24 * 60 * 60 * 1000,
44
- last_90_days: 90 * 24 * 60 * 60 * 1000,
45
- };
46
-
47
- const VALID_RECENCY_VALUES = Object.keys(RECENCY_MS);
48
-
49
- // ---------------------------------------------------------------------------
50
- // Result formatting
51
- // ---------------------------------------------------------------------------
52
-
53
- function formatBytes(bytes: number): string {
54
- if (bytes < 1024) return `${bytes} B`;
55
- if (bytes < 1024 * 1024) return `${(bytes / 1024).toFixed(1)} KB`;
56
- return `${(bytes / (1024 * 1024)).toFixed(1)} MB`;
57
- }
58
-
59
- function formatAttachment(a: StoredAttachment): string {
60
- const date = new Date(a.createdAt).toISOString();
61
- return [
62
- `- **${a.originalFilename}** (ID: ${a.id})`,
63
- ` Type: ${a.mimeType} | Kind: ${a.kind} | Size: ${formatBytes(a.sizeBytes)}`,
64
- ` Created: ${date}`,
65
- ].join("\n");
66
- }
67
-
68
- // ---------------------------------------------------------------------------
69
- // Attachment source conversation lookup
70
- // ---------------------------------------------------------------------------
71
-
72
- /**
73
- * Look up which conversations an attachment belongs to, along with each
74
- * conversation's type. An attachment can be linked to multiple
75
- * messages across multiple conversations.
76
- */
77
- export function getAttachmentSourceConversations(
78
- attachmentId: string,
79
- ): Array<{ conversationId: string; conversationType: string }> {
80
- const db = getDb();
81
- return db
82
- .select({
83
- conversationId: messages.conversationId,
84
- conversationType: conversations.conversationType,
85
- })
86
- .from(messageAttachments)
87
- .innerJoin(messages, eq(messages.id, messageAttachments.messageId))
88
- .innerJoin(conversations, eq(conversations.id, messages.conversationId))
89
- .where(eq(messageAttachments.attachmentId, attachmentId))
90
- .all();
91
- }
92
-
93
- /**
94
- * Check whether an attachment is visible from the given context.
95
- * Returns true if visible, false if hidden.
96
- *
97
- * - Orphan attachments (no message linkage) are universally visible.
98
- * - Attachments with any standard-conversation source are universally visible.
99
- * - All-private attachments are visible only if the caller is in one of
100
- * the source private conversations.
101
- */
102
- function isAttachmentVisibleFromContext(
103
- attachmentId: string,
104
- currentContext: AttachmentContext,
105
- ): boolean {
106
- const sources = getAttachmentSourceConversations(attachmentId);
107
- if (sources.length === 0) {
108
- return true;
109
- }
110
-
111
- const hasStandard = sources.some((s) => s.conversationType !== "private");
112
- if (hasStandard) {
113
- return true;
114
- }
115
-
116
- // All sources are private - visible only if the caller is in one of those conversations
117
- return sources.some((s) =>
118
- isAttachmentVisible(
119
- { conversationId: s.conversationId, isPrivate: true },
120
- currentContext,
121
- ),
122
- );
123
- }
124
-
125
- // ---------------------------------------------------------------------------
126
- // Search logic
127
- // ---------------------------------------------------------------------------
128
-
129
- export interface AssetSearchParams {
130
- mime_type?: string;
131
- filename?: string;
132
- recency?: string;
133
- conversation_id?: string;
134
- limit?: number;
135
- }
136
-
137
- const MAX_RESULTS = 100;
138
- const DEFAULT_LIMIT = 20;
139
-
140
- export function searchAttachments(
141
- params: AssetSearchParams,
142
- ): StoredAttachment[] {
143
- const db = getDb();
144
- const conditions = [];
145
-
146
- // MIME type filter - supports wildcards like 'image/*' via LIKE
147
- if (params.mime_type) {
148
- const mimePattern = params.mime_type.replace(/\*/g, "%");
149
- conditions.push(like(attachments.mimeType, mimePattern));
150
- }
151
-
152
- // Filename filter - case-insensitive substring match (escape LIKE wildcards)
153
- if (params.filename) {
154
- conditions.push(
155
- like(
156
- attachments.originalFilename,
157
- `%${escapeLikeWildcards(params.filename)}%`,
158
- ),
159
- );
160
- }
161
-
162
- // Recency filter - computed cutoff timestamp
163
- if (params.recency) {
164
- const offsetMs = RECENCY_MS[params.recency];
165
- if (offsetMs) {
166
- const cutoff = Date.now() - offsetMs;
167
- conditions.push(gte(attachments.createdAt, cutoff));
168
- }
169
- }
170
-
171
- // Conversation scope - join through message_attachments + messages
172
- if (params.conversation_id) {
173
- const linkedIds = db
174
- .select({ attachmentId: messageAttachments.attachmentId })
175
- .from(messageAttachments)
176
- .innerJoin(messages, eq(messages.id, messageAttachments.messageId))
177
- .where(eq(messages.conversationId, params.conversation_id))
178
- .all()
179
- .map((r) => r.attachmentId)
180
- .filter((id): id is string => id !== undefined);
181
-
182
- if (linkedIds.length === 0) {
183
- return [];
184
- }
185
-
186
- const placeholders = linkedIds.map(() => "?").join(", ");
187
-
188
- // Build WHERE clauses for raw query (FTS5 virtual table not involved,
189
- // but dynamic IN-list with optional filters is simpler in raw SQL)
190
- const whereParts: string[] = [`a.id IN (${placeholders})`];
191
- const bindValues: (string | number)[] = [...linkedIds];
192
-
193
- if (params.mime_type) {
194
- const mimePattern = params.mime_type.replace(/\*/g, "%");
195
- whereParts.push(`a.mime_type LIKE ?`);
196
- bindValues.push(mimePattern);
197
- }
198
- if (params.filename) {
199
- whereParts.push(`a.original_filename LIKE ?`);
200
- bindValues.push(`%${escapeLikeWildcards(params.filename)}%`);
201
- }
202
- if (params.recency) {
203
- const offsetMs = RECENCY_MS[params.recency];
204
- if (offsetMs) {
205
- whereParts.push(`a.created_at >= ?`);
206
- bindValues.push(Date.now() - offsetMs);
207
- }
208
- }
209
- const limit = Math.min(params.limit ?? DEFAULT_LIMIT, MAX_RESULTS);
210
-
211
- interface AttachmentRow {
212
- id: string;
213
- original_filename: string;
214
- mime_type: string;
215
- size_bytes: number;
216
- kind: string;
217
- thumbnail_base64: string | null;
218
- created_at: number;
219
- }
220
-
221
- const rows = rawAll<AttachmentRow>(
222
- `SELECT a.id, a.original_filename, a.mime_type, a.size_bytes, a.kind, a.thumbnail_base64, a.created_at
223
- FROM attachments a
224
- WHERE ${whereParts.join(" AND ")}
225
- ORDER BY a.created_at DESC
226
- LIMIT ?`,
227
- ...bindValues,
228
- limit,
229
- );
230
-
231
- return rows.map((r) => ({
232
- id: r.id,
233
- originalFilename: r.original_filename,
234
- mimeType: r.mime_type,
235
- sizeBytes: r.size_bytes,
236
- kind: r.kind,
237
- thumbnailBase64: r.thumbnail_base64,
238
- createdAt: r.created_at,
239
- }));
240
- }
241
-
242
- // No conversation constraint - query attachments table directly
243
- const limit = Math.min(params.limit ?? DEFAULT_LIMIT, MAX_RESULTS);
244
- const where = conditions.length > 0 ? and(...conditions) : undefined;
245
-
246
- const query = db
247
- .select({
248
- id: attachments.id,
249
- originalFilename: attachments.originalFilename,
250
- mimeType: attachments.mimeType,
251
- sizeBytes: attachments.sizeBytes,
252
- kind: attachments.kind,
253
- thumbnailBase64: attachments.thumbnailBase64,
254
- createdAt: attachments.createdAt,
255
- })
256
- .from(attachments)
257
- .orderBy(desc(attachments.createdAt))
258
- .limit(limit);
259
-
260
- if (where) {
261
- return query.where(where).all();
262
- }
263
- return query.all();
264
- }
265
-
266
- // ---------------------------------------------------------------------------
267
- // Tool definition
268
- // ---------------------------------------------------------------------------
269
-
270
- const definition: ToolDefinition = {
271
- name: "asset_search",
272
- description:
273
- "Search for previously uploaded media assets (images, documents, etc.) by metadata. " +
274
- "Returns attachment IDs and metadata - not file content. Use the returned IDs with " +
275
- "asset_materialize to retrieve actual file data.",
276
- input_schema: {
277
- type: "object",
278
- properties: {
279
- mime_type: {
280
- type: "string",
281
- description:
282
- 'Filter by MIME type. Supports wildcards: "image/*" matches all images, ' +
283
- '"application/pdf" matches PDFs exactly.',
284
- },
285
- filename: {
286
- type: "string",
287
- description:
288
- "Search by original filename (case-insensitive substring match).",
289
- },
290
- recency: {
291
- type: "string",
292
- enum: VALID_RECENCY_VALUES,
293
- description:
294
- "Filter by recency. One of: last_hour, last_24_hours, last_7_days, last_30_days, last_90_days.",
295
- },
296
- conversation_id: {
297
- type: "string",
298
- description:
299
- "Constrain results to attachments linked to messages in a specific conversation.",
300
- },
301
- limit: {
302
- type: "number",
303
- description: `Maximum results to return (default ${DEFAULT_LIMIT}, max ${MAX_RESULTS}).`,
304
- },
305
- },
306
- required: [],
307
- },
308
- };
309
-
310
- // ---------------------------------------------------------------------------
311
- // Tool class
312
- // ---------------------------------------------------------------------------
313
-
314
- class AssetSearchTool implements Tool {
315
- name = "asset_search";
316
- description = definition.description;
317
- category = "assets";
318
- defaultRiskLevel = RiskLevel.Low;
319
-
320
- getDefinition(): ToolDefinition {
321
- return definition;
322
- }
323
-
324
- async execute(
325
- input: Record<string, unknown>,
326
- context: ToolContext,
327
- ): Promise<ToolExecutionResult> {
328
- const mimeType = input.mime_type as string | undefined;
329
- const filename = input.filename as string | undefined;
330
- const recency = input.recency as string | undefined;
331
- const conversationId = input.conversation_id as string | undefined;
332
- const limit = input.limit as number | undefined;
333
-
334
- // Validate recency if provided
335
- if (recency && !RECENCY_MS[recency]) {
336
- return {
337
- content: `Error: Invalid recency value "${recency}". Valid values: ${VALID_RECENCY_VALUES.join(", ")}`,
338
- isError: true,
339
- };
340
- }
341
-
342
- // Validate limit if provided
343
- if (limit !== undefined && (typeof limit !== "number" || limit < 1)) {
344
- return {
345
- content: "Error: limit must be a positive number.",
346
- isError: true,
347
- };
348
- }
349
-
350
- try {
351
- // Over-fetch with MAX_RESULTS so visibility filtering doesn't
352
- // under-fill the caller's requested limit.
353
- const results = searchAttachments({
354
- mime_type: mimeType,
355
- filename,
356
- recency,
357
- conversation_id: conversationId,
358
- limit: MAX_RESULTS,
359
- });
360
-
361
- // Enforce private-conversation visibility: filter out attachments that
362
- // belong exclusively to private conversations the caller cannot access.
363
- const currentConversationType = getConversationType(
364
- context.conversationId,
365
- );
366
- const currentContext: AttachmentContext = {
367
- conversationId: context.conversationId,
368
- isPrivate: currentConversationType === "private",
369
- };
370
-
371
- const effectiveLimit = Math.min(limit ?? DEFAULT_LIMIT, MAX_RESULTS);
372
- const visible = results
373
- .filter((attachment) =>
374
- isAttachmentVisibleFromContext(attachment.id, currentContext),
375
- )
376
- .slice(0, effectiveLimit);
377
-
378
- if (visible.length === 0) {
379
- return {
380
- content: "No assets found matching the search criteria.",
381
- isError: false,
382
- };
383
- }
384
-
385
- const lines = [`Found ${visible.length} asset(s):\n`];
386
- for (const attachment of visible) {
387
- lines.push(formatAttachment(attachment));
388
- }
389
-
390
- return { content: lines.join("\n"), isError: false };
391
- } catch (err) {
392
- const msg = err instanceof Error ? err.message : String(err);
393
- return { content: `Error: ${msg}`, isError: true };
394
- }
395
- }
396
- }
397
-
398
- export const assetSearchTool = new AssetSearchTool();
399
-
400
- registerTool(assetSearchTool);