@vellumai/assistant 0.5.0 → 0.5.2

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 (347) hide show
  1. package/ARCHITECTURE.md +54 -54
  2. package/docs/architecture/integrations.md +62 -67
  3. package/docs/credential-execution-service.md +3 -3
  4. package/package.json +1 -1
  5. package/src/__tests__/agent-loop.test.ts +111 -0
  6. package/src/__tests__/always-loaded-tools-guard.test.ts +3 -4
  7. package/src/__tests__/app-builder-tool-scripts.test.ts +13 -151
  8. package/src/__tests__/app-dir-path-guard.test.ts +78 -0
  9. package/src/__tests__/app-executors.test.ts +1 -291
  10. package/src/__tests__/app-git-history.test.ts +4 -4
  11. package/src/__tests__/app-routes-csp.test.ts +1 -0
  12. package/src/__tests__/app-store-dir-names.test.ts +426 -0
  13. package/src/__tests__/assistant-feature-flags-integration.test.ts +7 -9
  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 +149 -5
  26. package/src/__tests__/conversation-agent-loop.test.ts +290 -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-queue.test.ts +36 -1
  37. package/src/__tests__/conversation-routes-disk-view.test.ts +439 -0
  38. package/src/__tests__/conversation-routes-guardian-reply.test.ts +2 -2
  39. package/src/__tests__/conversation-routes-slash-commands.test.ts +2 -7
  40. package/src/__tests__/conversation-runtime-assembly.test.ts +17 -2
  41. package/src/__tests__/conversation-skill-tools.test.ts +4 -9
  42. package/src/__tests__/conversation-slash-commands.test.ts +149 -0
  43. package/src/__tests__/conversation-store.test.ts +24 -21
  44. package/src/__tests__/conversation-surfaces-state-update.test.ts +246 -0
  45. package/src/__tests__/conversation-surfaces-task-progress.test.ts +1 -0
  46. package/src/__tests__/conversation-title-service.test.ts +137 -0
  47. package/src/__tests__/conversation-tool-setup-app-refresh.test.ts +25 -315
  48. package/src/__tests__/conversation-tool-setup-memory-scope.test.ts +1 -0
  49. package/src/__tests__/conversation-tool-setup-side-effect-flag.test.ts +1 -0
  50. package/src/__tests__/conversation-workspace-cache-state.test.ts +44 -2
  51. package/src/__tests__/conversation-workspace-injection.test.ts +11 -0
  52. package/src/__tests__/credential-execution-feature-gates.test.ts +3 -3
  53. package/src/__tests__/credential-security-invariants.test.ts +3 -0
  54. package/src/__tests__/credential-vault-unit.test.ts +5 -10
  55. package/src/__tests__/cu-unified-flow.test.ts +1 -0
  56. package/src/__tests__/db-conversation-fork-lineage-migration.test.ts +241 -0
  57. package/src/__tests__/db-llm-request-log-provider-migration.test.ts +214 -0
  58. package/src/__tests__/diagnostics-export.test.ts +70 -1
  59. package/src/__tests__/filesystem-tools.test.ts +4 -2
  60. package/src/__tests__/first-greeting.test.ts +80 -0
  61. package/src/__tests__/gateway-only-guard.test.ts +1 -0
  62. package/src/__tests__/handlers-user-message-approval-consumption.test.ts +3 -7
  63. package/src/__tests__/history-repair.test.ts +103 -10
  64. package/src/__tests__/http-conversation-lineage.test.ts +251 -0
  65. package/src/__tests__/image-source-path-reinject.test.ts +136 -0
  66. package/src/__tests__/llm-context-normalization.test.ts +1116 -0
  67. package/src/__tests__/llm-context-route-provider.test.ts +217 -0
  68. package/src/__tests__/llm-request-log-turn-query.test.ts +270 -0
  69. package/src/__tests__/media-generate-image.test.ts +47 -94
  70. package/src/__tests__/memory-lifecycle-e2e.test.ts +3 -1
  71. package/src/__tests__/memory-recall-quality.test.ts +5 -5
  72. package/src/__tests__/migration-cross-version-compatibility.test.ts +4 -1
  73. package/src/__tests__/migration-export-http.test.ts +3 -1
  74. package/src/__tests__/migration-import-commit-http.test.ts +18 -4
  75. package/src/__tests__/migration-import-preflight-http.test.ts +1 -3
  76. package/src/__tests__/mime-builder.test.ts +3 -2
  77. package/src/__tests__/non-member-access-request.test.ts +12 -1
  78. package/src/__tests__/notification-decision-identity.test.ts +52 -0
  79. package/src/__tests__/oauth-apps-routes.test.ts +103 -0
  80. package/src/__tests__/oauth-store.test.ts +115 -0
  81. package/src/__tests__/provider-error-scenarios.test.ts +1 -3
  82. package/src/__tests__/provider-failover-actual-provider.test.ts +66 -0
  83. package/src/__tests__/recording-handler.test.ts +17 -0
  84. package/src/__tests__/registry.test.ts +3 -8
  85. package/src/__tests__/relay-server.test.ts +1 -1
  86. package/src/__tests__/runtime-attachment-metadata.test.ts +7 -3
  87. package/src/__tests__/schema-transforms.test.ts +165 -5
  88. package/src/__tests__/server-history-render.test.ts +2 -2
  89. package/src/__tests__/skill-feature-flags-integration.test.ts +18 -17
  90. package/src/__tests__/skill-feature-flags.test.ts +13 -13
  91. package/src/__tests__/skill-load-feature-flag.test.ts +4 -4
  92. package/src/__tests__/slack-app-setup-skill-regression.test.ts +3 -1
  93. package/src/__tests__/slack-inbound-verification.test.ts +2 -2
  94. package/src/__tests__/starter-task-flow.test.ts +1 -0
  95. package/src/__tests__/suggestion-routes.test.ts +443 -0
  96. package/src/__tests__/swarm-conversation-integration.test.ts +1 -0
  97. package/src/__tests__/swarm-recursion.test.ts +1 -0
  98. package/src/__tests__/swarm-tool.test.ts +1 -0
  99. package/src/__tests__/system-prompt.test.ts +8 -0
  100. package/src/__tests__/tool-execution-abort-cleanup.test.ts +1 -0
  101. package/src/__tests__/tool-preview-lifecycle.test.ts +32 -5
  102. package/src/__tests__/top-level-renderer.test.ts +22 -0
  103. package/src/__tests__/turn-boundary-resolution.test.ts +243 -0
  104. package/src/__tests__/web-fetch.test.ts +6 -2
  105. package/src/__tests__/workspace-migration-006-services-config.test.ts +335 -0
  106. package/src/__tests__/workspace-migration-007-web-search-provider-rename.test.ts +312 -0
  107. package/src/__tests__/workspace-migration-009-backfill-conversation-disk-view.test.ts +278 -0
  108. package/src/__tests__/workspace-migration-010-app-dir-rename.test.ts +275 -0
  109. package/src/__tests__/workspace-migration-012-rename-conversation-disk-view-dirs.test.ts +77 -0
  110. package/src/__tests__/workspace-migration-013-repair-conversation-disk-view.test.ts +401 -0
  111. package/src/__tests__/workspace-migration-backfill-installation-id.test.ts +328 -0
  112. package/src/__tests__/workspace-migration-seed-device-id.test.ts +6 -10
  113. package/src/agent/attachments.ts +27 -1
  114. package/src/agent/loop.ts +29 -1
  115. package/src/avatar/traits-png-sync.ts +80 -25
  116. package/src/bundler/app-bundler.ts +4 -4
  117. package/src/calls/call-domain.ts +1 -0
  118. package/src/calls/voice-session-bridge.ts +1 -0
  119. package/src/cli/commands/auth.ts +92 -0
  120. package/src/cli/commands/avatar.ts +7 -6
  121. package/src/cli/commands/config.ts +2 -0
  122. package/src/cli/commands/oauth/providers.ts +29 -0
  123. package/src/cli/program.ts +12 -0
  124. package/src/cli.ts +15 -48
  125. package/src/config/bundled-skills/app-builder/SKILL.md +103 -28
  126. package/src/config/bundled-skills/app-builder/TOOLS.json +5 -199
  127. package/src/config/bundled-skills/app-builder/tools/{app-query.ts → app-refresh.ts} +2 -2
  128. package/src/config/bundled-skills/contacts/tools/google-contacts.ts +2 -3
  129. package/src/config/bundled-skills/gmail/tools/gmail-archive.ts +6 -9
  130. package/src/config/bundled-skills/gmail/tools/gmail-attachments.ts +4 -6
  131. package/src/config/bundled-skills/gmail/tools/gmail-draft.ts +2 -3
  132. package/src/config/bundled-skills/gmail/tools/gmail-filters.ts +2 -3
  133. package/src/config/bundled-skills/gmail/tools/gmail-follow-up.ts +2 -3
  134. package/src/config/bundled-skills/gmail/tools/gmail-forward.ts +2 -3
  135. package/src/config/bundled-skills/gmail/tools/gmail-label.ts +4 -6
  136. package/src/config/bundled-skills/gmail/tools/gmail-outreach-scan.ts +2 -3
  137. package/src/config/bundled-skills/gmail/tools/gmail-send-draft.ts +2 -3
  138. package/src/config/bundled-skills/gmail/tools/gmail-sender-digest.ts +2 -3
  139. package/src/config/bundled-skills/gmail/tools/gmail-trash.ts +2 -3
  140. package/src/config/bundled-skills/gmail/tools/gmail-unsubscribe.ts +2 -3
  141. package/src/config/bundled-skills/gmail/tools/gmail-vacation.ts +2 -3
  142. package/src/config/bundled-skills/google-calendar/tools/shared.ts +1 -1
  143. package/src/config/bundled-skills/image-studio/SKILL.md +2 -2
  144. package/src/config/bundled-skills/image-studio/TOOLS.json +2 -2
  145. package/src/config/bundled-skills/image-studio/tools/media-generate-image.ts +45 -72
  146. package/src/config/bundled-skills/media-processing/tools/extract-keyframes.ts +2 -2
  147. package/src/config/bundled-skills/messaging/tools/shared.ts +1 -1
  148. package/src/config/bundled-skills/settings/tools/voice-config-update.ts +19 -3
  149. package/src/config/bundled-skills/skill-management/TOOLS.json +2 -2
  150. package/src/config/bundled-skills/slack/tools/shared.ts +19 -4
  151. package/src/config/bundled-skills/slack/tools/slack-scan-digest.ts +2 -3
  152. package/src/config/bundled-skills/transcribe/SKILL.md +1 -1
  153. package/src/config/bundled-skills/transcribe/TOOLS.json +2 -6
  154. package/src/config/bundled-skills/transcribe/tools/transcribe-media.ts +19 -83
  155. package/src/config/bundled-tool-registry.ts +2 -14
  156. package/src/config/feature-flag-registry.json +16 -0
  157. package/src/config/loader.ts +64 -0
  158. package/src/config/raw-config-utils.ts +30 -0
  159. package/src/config/schema-utils.ts +28 -7
  160. package/src/config/schema.ts +8 -0
  161. package/src/config/schemas/elevenlabs.ts +18 -0
  162. package/src/config/schemas/memory-lifecycle.ts +4 -2
  163. package/src/config/schemas/memory-storage.ts +1 -1
  164. package/src/config/schemas/services.ts +8 -6
  165. package/src/contacts/contact-store.ts +13 -6
  166. package/src/contacts/contacts-write.ts +0 -1
  167. package/src/context/window-manager.ts +13 -2
  168. package/src/daemon/conversation-agent-loop-handlers.ts +46 -42
  169. package/src/daemon/conversation-agent-loop.ts +56 -19
  170. package/src/daemon/conversation-attachments.ts +18 -36
  171. package/src/daemon/conversation-error.ts +2 -1
  172. package/src/daemon/conversation-history.ts +18 -4
  173. package/src/daemon/conversation-lifecycle.ts +39 -15
  174. package/src/daemon/conversation-messaging.ts +70 -26
  175. package/src/daemon/conversation-process.ts +58 -34
  176. package/src/daemon/conversation-runtime-assembly.ts +21 -38
  177. package/src/daemon/conversation-slash.ts +121 -256
  178. package/src/daemon/conversation-surfaces.ts +143 -20
  179. package/src/daemon/conversation-tool-setup.ts +0 -6
  180. package/src/daemon/conversation-workspace.ts +21 -1
  181. package/src/daemon/conversation.ts +51 -29
  182. package/src/daemon/first-greeting.ts +35 -0
  183. package/src/daemon/handlers/config-embeddings.ts +148 -0
  184. package/src/daemon/handlers/config-model.ts +71 -26
  185. package/src/daemon/handlers/conversations.ts +0 -23
  186. package/src/daemon/handlers/recording.ts +26 -21
  187. package/src/daemon/history-repair.ts +28 -8
  188. package/src/daemon/host-cu-proxy.ts +2 -2
  189. package/src/daemon/lifecycle.ts +106 -64
  190. package/src/daemon/message-protocol.ts +3 -0
  191. package/src/daemon/message-types/conversations.ts +19 -0
  192. package/src/daemon/message-types/messages.ts +1 -0
  193. package/src/daemon/message-types/shared.ts +2 -0
  194. package/src/daemon/message-types/surfaces.ts +2 -0
  195. package/src/daemon/message-types/upgrades.ts +23 -0
  196. package/src/daemon/server.ts +83 -12
  197. package/src/daemon/shutdown-handlers.ts +8 -5
  198. package/src/daemon/startup-error.ts +9 -0
  199. package/src/daemon/tool-side-effects.ts +11 -28
  200. package/src/events/tool-permission-telemetry-listener.ts +1 -3
  201. package/src/instrument.ts +0 -4
  202. package/src/media/app-icon-generator.ts +2 -2
  203. package/src/memory/app-git-service.ts +28 -16
  204. package/src/memory/app-store.ts +230 -41
  205. package/src/memory/attachments-store.ts +558 -130
  206. package/src/memory/conversation-attention-store.ts +70 -0
  207. package/src/memory/conversation-crud.ts +442 -3
  208. package/src/memory/conversation-directories.ts +125 -0
  209. package/src/memory/conversation-disk-view.ts +390 -0
  210. package/src/memory/conversation-key-store.ts +17 -5
  211. package/src/memory/conversation-queries.ts +5 -1
  212. package/src/memory/conversation-title-service.ts +21 -49
  213. package/src/memory/db-init.ts +28 -0
  214. package/src/memory/embedding-backend.ts +42 -53
  215. package/src/memory/embedding-gemini.test.ts +4 -4
  216. package/src/memory/embedding-local.ts +1 -3
  217. package/src/memory/embedding-ollama.ts +1 -3
  218. package/src/memory/embedding-openai.ts +1 -3
  219. package/src/memory/indexer.ts +9 -7
  220. package/src/memory/items-extractor.ts +42 -13
  221. package/src/memory/job-handlers/conversation-starters.ts +6 -1
  222. package/src/memory/job-handlers/embedding.test.ts +1 -4
  223. package/src/memory/llm-request-log-store.ts +100 -1
  224. package/src/memory/migrations/102-alter-table-columns.ts +5 -0
  225. package/src/memory/migrations/146-schedule-oneshot-routing.ts +3 -3
  226. package/src/memory/migrations/147-migrate-reminders-to-schedules.ts +66 -70
  227. package/src/memory/migrations/148-drop-reminders-table.ts +5 -9
  228. package/src/memory/migrations/160-drop-loopback-port-column.ts +1 -3
  229. package/src/memory/migrations/174-rename-thread-starters-table.ts +0 -7
  230. package/src/memory/migrations/178-oauth-providers-managed-service-config-key.ts +15 -0
  231. package/src/memory/migrations/179-llm-request-log-message-id.ts +16 -0
  232. package/src/memory/migrations/180-backfill-inline-attachments-to-disk.ts +66 -0
  233. package/src/memory/migrations/181-rename-thread-starters-checkpoints.ts +46 -0
  234. package/src/memory/migrations/182-oauth-providers-display-metadata.ts +20 -0
  235. package/src/memory/migrations/183-add-conversation-fork-lineage.ts +22 -0
  236. package/src/memory/migrations/184-llm-request-log-provider.ts +12 -0
  237. package/src/memory/migrations/index.ts +7 -0
  238. package/src/memory/migrations/registry.ts +13 -0
  239. package/src/memory/retriever.test.ts +601 -2
  240. package/src/memory/retriever.ts +85 -9
  241. package/src/memory/schema/conversations.ts +6 -0
  242. package/src/memory/schema/infrastructure.ts +13 -7
  243. package/src/memory/schema/oauth.ts +6 -0
  244. package/src/messaging/providers/gmail/mime-builder.ts +3 -1
  245. package/src/notifications/copy-composer.ts +26 -0
  246. package/src/notifications/decision-engine.ts +14 -1
  247. package/src/notifications/emit-signal.ts +1 -1
  248. package/src/notifications/signal.ts +36 -0
  249. package/src/oauth/byo-connection.test.ts +1 -45
  250. package/src/oauth/byo-connection.ts +2 -8
  251. package/src/oauth/connect-orchestrator.ts +15 -11
  252. package/src/oauth/connection-resolver.test.ts +191 -0
  253. package/src/oauth/connection-resolver.ts +66 -38
  254. package/src/oauth/connection.ts +0 -1
  255. package/src/oauth/oauth-store.ts +97 -47
  256. package/src/oauth/platform-connection.test.ts +0 -1
  257. package/src/oauth/platform-connection.ts +11 -3
  258. package/src/oauth/seed-providers.ts +78 -3
  259. package/src/oauth/token-persistence.ts +16 -10
  260. package/src/permissions/checker.ts +62 -19
  261. package/src/prompts/system-prompt.ts +2 -0
  262. package/src/prompts/templates/BOOTSTRAP.md +2 -0
  263. package/src/providers/anthropic/client.ts +8 -1
  264. package/src/providers/failover.ts +4 -1
  265. package/src/providers/gemini/client.ts +50 -0
  266. package/src/providers/model-catalog.ts +92 -0
  267. package/src/providers/model-intents.ts +29 -20
  268. package/src/providers/openai/client.ts +49 -0
  269. package/src/providers/types.ts +2 -0
  270. package/src/runtime/access-request-helper.ts +16 -7
  271. package/src/runtime/auth/credential-service.ts +3 -1
  272. package/src/runtime/auth/route-policy.ts +14 -1
  273. package/src/runtime/btw-sidechain.ts +101 -0
  274. package/src/runtime/channel-reply-delivery.ts +17 -1
  275. package/src/runtime/http-router.ts +3 -1
  276. package/src/runtime/http-server.ts +196 -141
  277. package/src/runtime/http-types.ts +1 -0
  278. package/src/runtime/migrations/vbundle-builder.ts +5 -1
  279. package/src/runtime/routes/access-request-decision.ts +41 -0
  280. package/src/runtime/routes/app-management-routes.ts +6 -3
  281. package/src/runtime/routes/app-routes.ts +7 -3
  282. package/src/runtime/routes/approval-routes.ts +1 -0
  283. package/src/runtime/routes/approval-strategies/guardian-callback-strategy.ts +34 -2
  284. package/src/runtime/routes/attachment-routes.ts +45 -15
  285. package/src/runtime/routes/btw-routes.ts +21 -61
  286. package/src/runtime/routes/conversation-management-routes.ts +68 -0
  287. package/src/runtime/routes/conversation-query-routes.ts +180 -10
  288. package/src/runtime/routes/conversation-routes.ts +222 -28
  289. package/src/runtime/routes/conversation-starter-routes.ts +9 -11
  290. package/src/runtime/routes/diagnostics-routes.ts +1 -0
  291. package/src/runtime/routes/inbound-stages/acl-enforcement.ts +2 -2
  292. package/src/runtime/routes/llm-context-normalization.ts +1199 -0
  293. package/src/runtime/routes/log-export-routes.ts +3 -0
  294. package/src/runtime/routes/memory-item-routes.test.ts +34 -0
  295. package/src/runtime/routes/memory-item-routes.ts +4 -0
  296. package/src/runtime/routes/migration-routes.ts +4 -1
  297. package/src/runtime/routes/oauth-apps.ts +291 -0
  298. package/src/runtime/routes/secret-routes.ts +28 -1
  299. package/src/runtime/routes/settings-routes.ts +14 -0
  300. package/src/runtime/routes/trace-event-routes.ts +4 -1
  301. package/src/schedule/schedule-store.ts +9 -21
  302. package/src/security/secure-keys.ts +21 -0
  303. package/src/signals/bash.ts +1 -1
  304. package/src/swarm/backend-claude-code.ts +3 -6
  305. package/src/telemetry/usage-telemetry-reporter.test.ts +3 -2
  306. package/src/telemetry/usage-telemetry-reporter.ts +3 -1
  307. package/src/tools/AGENTS.md +6 -10
  308. package/src/tools/apps/executors.ts +17 -232
  309. package/src/tools/claude-code/claude-code.ts +2 -3
  310. package/src/tools/credentials/vault.ts +7 -12
  311. package/src/tools/host-filesystem/read.ts +13 -10
  312. package/src/tools/network/__tests__/web-search.test.ts +4 -2
  313. package/src/tools/schedule/list.ts +2 -7
  314. package/src/tools/schema-transforms.ts +5 -0
  315. package/src/tools/shared/filesystem/format-diff.ts +4 -21
  316. package/src/tools/skills/execute.ts +1 -1
  317. package/src/tools/tool-manifest.ts +0 -6
  318. package/src/tools/ui-surface/definitions.ts +2 -2
  319. package/src/util/device-id.ts +28 -5
  320. package/src/util/platform.ts +6 -0
  321. package/src/util/pricing.ts +1 -0
  322. package/src/util/retry.ts +1 -3
  323. package/src/workspace/migrations/002-backfill-installation-id.ts +23 -12
  324. package/src/workspace/migrations/003-seed-device-id.ts +3 -4
  325. package/src/workspace/migrations/006-services-config.ts +5 -0
  326. package/src/workspace/migrations/008-voice-timeout-and-max-steps.ts +12 -0
  327. package/src/workspace/migrations/009-backfill-conversation-disk-view.ts +10 -0
  328. package/src/workspace/migrations/010-app-dir-rename.ts +223 -0
  329. package/src/workspace/migrations/012-rename-conversation-disk-view-dirs.ts +64 -0
  330. package/src/workspace/migrations/013-repair-conversation-disk-view.ts +11 -0
  331. package/src/workspace/migrations/rebuild-conversation-disk-view.ts +186 -0
  332. package/src/workspace/migrations/registry.ts +10 -0
  333. package/src/workspace/top-level-renderer.ts +12 -0
  334. package/src/__tests__/asset-materialize-tool.test.ts +0 -523
  335. package/src/__tests__/asset-search-tool.test.ts +0 -536
  336. package/src/__tests__/fixtures/media-reuse-fixtures.ts +0 -56
  337. package/src/__tests__/media-reuse-story.e2e.test.ts +0 -762
  338. package/src/__tests__/media-visibility-policy.test.ts +0 -190
  339. package/src/config/bundled-skills/app-builder/tools/app-file-edit.ts +0 -14
  340. package/src/config/bundled-skills/app-builder/tools/app-file-list.ts +0 -13
  341. package/src/config/bundled-skills/app-builder/tools/app-file-read.ts +0 -21
  342. package/src/config/bundled-skills/app-builder/tools/app-file-write.ts +0 -14
  343. package/src/config/bundled-skills/app-builder/tools/app-list.ts +0 -13
  344. package/src/config/bundled-skills/app-builder/tools/app-update.ts +0 -23
  345. package/src/daemon/media-visibility-policy.ts +0 -59
  346. package/src/tools/assets/materialize.ts +0 -248
  347. package/src/tools/assets/search.ts +0 -400
@@ -70,21 +70,53 @@ describe("injectActivityField", () => {
70
70
  expect("activity" in props0).toBe(false);
71
71
  });
72
72
 
73
- test("skips tools that already have activity in properties", () => {
73
+ test("returns unchanged when activity is in top-level properties but not required", () => {
74
74
  const defs = [
75
75
  makeDef("my_tool", {
76
76
  type: "object",
77
77
  properties: { activity: { type: "number" } },
78
- required: [],
78
+ required: ["foo"],
79
79
  }),
80
80
  ];
81
81
  const result = injectActivityField(defs);
82
- // Should be the exact same object reference (no clone needed)
82
+ // Should be the exact same object reference (no modification)
83
83
  expect(Object.is(result[0], defs[0])).toBe(true);
84
84
  const schema = result[0].input_schema as Record<string, unknown>;
85
85
  const props = schema.properties as Record<string, unknown>;
86
86
  // Original activity type preserved
87
87
  expect(props.activity).toEqual({ type: "number" });
88
+ // required NOT modified — don't promote server-defined optional activity
89
+ expect(schema.required).toEqual(["foo"]);
90
+ });
91
+
92
+ test("returns unchanged when activity is in both top-level properties AND required", () => {
93
+ const defs = [
94
+ makeDef("my_tool", {
95
+ type: "object",
96
+ properties: { activity: { type: "string" } },
97
+ required: ["activity"],
98
+ }),
99
+ ];
100
+ const result = injectActivityField(defs);
101
+ const schema = result[0].input_schema as Record<string, unknown>;
102
+ const props = schema.properties as Record<string, unknown>;
103
+ // Original activity type preserved
104
+ expect(props.activity).toEqual({ type: "string" });
105
+ // activity must be in required even though it was already in properties
106
+ expect(schema.required).toEqual(["activity"]);
107
+ });
108
+
109
+ test("skips tools that already have activity in both properties and required", () => {
110
+ const defs = [
111
+ makeDef("my_tool", {
112
+ type: "object",
113
+ properties: { activity: { type: "number" } },
114
+ required: ["activity"],
115
+ }),
116
+ ];
117
+ const result = injectActivityField(defs);
118
+ // Should be the exact same object reference (no clone needed)
119
+ expect(Object.is(result[0], defs[0])).toBe(true);
88
120
  });
89
121
 
90
122
  test("does NOT mutate original definition objects", () => {
@@ -125,6 +157,60 @@ describe("injectActivityField", () => {
125
157
  expect(Object.is(result[0], defs[0])).toBe(true);
126
158
  });
127
159
 
160
+ test("does NOT add activity to top-level required when only in oneOf branch", () => {
161
+ const defs = [
162
+ makeDef("my_tool", {
163
+ type: "object",
164
+ properties: { shared: { type: "string" } },
165
+ oneOf: [
166
+ {
167
+ properties: {
168
+ activity: { type: "string" },
169
+ branch_a: { type: "number" },
170
+ },
171
+ },
172
+ {
173
+ properties: { branch_b: { type: "boolean" } },
174
+ },
175
+ ],
176
+ required: ["shared"],
177
+ }),
178
+ ];
179
+ const result = injectActivityField(defs);
180
+ // Should be the exact same object reference (no modification)
181
+ expect(Object.is(result[0], defs[0])).toBe(true);
182
+ const schema = result[0].input_schema as Record<string, unknown>;
183
+ // Top-level required should NOT include activity
184
+ expect(schema.required).toEqual(["shared"]);
185
+ // Top-level properties should NOT have activity injected
186
+ const props = schema.properties as Record<string, unknown>;
187
+ expect("activity" in props).toBe(false);
188
+ });
189
+
190
+ test("does NOT add activity to top-level required when only in allOf sub-schema with additionalProperties: false", () => {
191
+ const defs = [
192
+ makeDef("my_tool", {
193
+ type: "object",
194
+ properties: { foo: { type: "string" } },
195
+ additionalProperties: false,
196
+ allOf: [
197
+ {
198
+ properties: { activity: { type: "string" } },
199
+ },
200
+ ],
201
+ required: ["foo"],
202
+ }),
203
+ ];
204
+ const result = injectActivityField(defs);
205
+ // Should be the exact same object reference (no modification)
206
+ expect(Object.is(result[0], defs[0])).toBe(true);
207
+ const schema = result[0].input_schema as Record<string, unknown>;
208
+ // Top-level required should NOT include activity
209
+ expect(schema.required).toEqual(["foo"]);
210
+ const props = schema.properties as Record<string, unknown>;
211
+ expect("activity" in props).toBe(false);
212
+ });
213
+
128
214
  test("skips tools with activity defined inside allOf member (composite schema)", () => {
129
215
  const defs = [
130
216
  makeDef("my_tool", {
@@ -139,18 +225,92 @@ describe("injectActivityField", () => {
139
225
  }),
140
226
  ];
141
227
  const result = injectActivityField(defs);
142
- // Should be the exact same object reference (no injection)
228
+ // Should be the exact same object reference (no modification)
143
229
  expect(Object.is(result[0], defs[0])).toBe(true);
144
230
  const schema = result[0].input_schema as Record<string, unknown>;
145
231
  const props = schema.properties as Record<string, unknown>;
146
- // Top-level properties should NOT have activity injected
232
+ // Top-level properties should NOT have activity injected (it's in allOf)
147
233
  expect("activity" in props).toBe(false);
234
+ // Top-level required should NOT include activity (it's only in composite sub-schemas)
235
+ expect(schema.required).toEqual([]);
236
+ });
237
+
238
+ test("skips allOf composite schema where activity is already required", () => {
239
+ const defs = [
240
+ makeDef("my_tool", {
241
+ type: "object",
242
+ properties: { foo: { type: "string" } },
243
+ allOf: [
244
+ {
245
+ properties: { activity: { type: "string" } },
246
+ },
247
+ ],
248
+ required: ["activity"],
249
+ }),
250
+ ];
251
+ const result = injectActivityField(defs);
252
+ // Should be the exact same object reference (no change needed)
253
+ expect(Object.is(result[0], defs[0])).toBe(true);
148
254
  });
149
255
 
150
256
  test("handles empty definitions array", () => {
151
257
  const result = injectActivityField([]);
152
258
  expect(result).toEqual([]);
153
259
  });
260
+
261
+ test("injects activity only on tools that don't define it at all", () => {
262
+ const defs = [
263
+ // Normal tool without activity — should get it injected
264
+ makeDef("tool_a", {
265
+ type: "object",
266
+ properties: { foo: { type: "string" } },
267
+ required: ["foo"],
268
+ }),
269
+ // Tool defines activity in properties but NOT in required — left unchanged
270
+ makeDef("tool_b", {
271
+ type: "object",
272
+ properties: {
273
+ bar: { type: "string" },
274
+ activity: { type: "string", description: "custom activity" },
275
+ },
276
+ required: ["bar"],
277
+ }),
278
+ // Tool that defines activity in both properties AND required — left unchanged
279
+ makeDef("tool_c", {
280
+ type: "object",
281
+ properties: {
282
+ baz: { type: "number" },
283
+ activity: { type: "string", description: "custom activity" },
284
+ },
285
+ required: ["baz", "activity"],
286
+ }),
287
+ // Non-object schema — should be left alone
288
+ makeDef("tool_d", { type: "string" }),
289
+ // Object schema without properties — should be left alone
290
+ makeDef("tool_e", { type: "object" }),
291
+ ];
292
+
293
+ const result = injectActivityField(defs);
294
+
295
+ // tool_a: activity injected and required
296
+ const schemaA = result[0].input_schema as Record<string, unknown>;
297
+ expect(
298
+ (schemaA.properties as Record<string, unknown>).activity,
299
+ ).toBeDefined();
300
+ expect(schemaA.required).toEqual(["foo", "activity"]);
301
+
302
+ // tool_b: unchanged (activity optional, not promoted)
303
+ expect(Object.is(result[1], defs[1])).toBe(true);
304
+ const schemaB = result[1].input_schema as Record<string, unknown>;
305
+ expect(schemaB.required).toEqual(["bar"]);
306
+
307
+ // tool_c: unchanged (activity already present and required)
308
+ expect(Object.is(result[2], defs[2])).toBe(true);
309
+
310
+ // tool_d, tool_e: unchanged
311
+ expect(Object.is(result[3], defs[3])).toBe(true);
312
+ expect(Object.is(result[4], defs[4])).toBe(true);
313
+ });
154
314
  });
155
315
 
156
316
  describe("schemaDefinesProperty", () => {
@@ -330,7 +330,7 @@ describe("getAttachmentsForMessage", () => {
330
330
 
331
331
  test("returns attachments linked to a message", async () => {
332
332
  const msgId = await createMessage("assistant", "Here is a chart");
333
- const stored = uploadAttachment("chart.png", "image/png", "iVBOR");
333
+ const stored = uploadAttachment("chart.png", "image/png", "iVBORw==");
334
334
  linkAttachmentToMessage(msgId, stored.id, 0);
335
335
 
336
336
  const result = getAttachmentsForMessage(msgId);
@@ -338,7 +338,7 @@ describe("getAttachmentsForMessage", () => {
338
338
  expect(result[0].id).toBe(stored.id);
339
339
  expect(result[0].originalFilename).toBe("chart.png");
340
340
  expect(result[0].mimeType).toBe("image/png");
341
- expect(result[0].dataBase64).toBe("iVBOR");
341
+ expect(result[0].dataBase64).toBe("iVBORw==");
342
342
  });
343
343
 
344
344
  test("returns empty array when no attachments are linked", () => {
@@ -138,14 +138,15 @@ describe("frontmatter feature-flag integration", () => {
138
138
  expect(key).toBeUndefined();
139
139
  });
140
140
 
141
- test("resolveSkillStates gates skill with featureFlag when flag is OFF", () => {
141
+ test("resolveSkillStates includes skill with featureFlag when flag defaults to ON", () => {
142
142
  const skill = buildSkillSummary("contacts", SKILL_MD_WITH_FLAG)!;
143
- // "contacts" is in the registry with defaultEnabled: false
143
+ // "contacts" is in the registry with defaultEnabled: true
144
144
  const config = makeConfig();
145
145
 
146
146
  const resolved = resolveSkillStates([skill], config);
147
- // Flag defaults to false → skill is filtered out
148
- expect(resolved.length).toBe(0);
147
+ // Flag defaults to true → skill passes through
148
+ expect(resolved.length).toBe(1);
149
+ expect(resolved[0].summary.id).toBe("contacts");
149
150
  });
150
151
 
151
152
  test("resolveSkillStates includes skill with featureFlag when flag is ON", () => {
@@ -192,22 +193,22 @@ describe("frontmatter feature-flag integration", () => {
192
193
  const key = skillFlagKey(skill);
193
194
  expect(key).toBe("feature_flags.contacts.enabled");
194
195
 
195
- // Step 4: Check flag state — "contacts" has defaultEnabled: false in registry
196
- const configOff = makeConfig();
197
- expect(isAssistantFeatureFlagEnabled(key!, configOff)).toBe(false);
196
+ // Step 4: Check flag state — "contacts" has defaultEnabled: true in registry
197
+ const configDefault = makeConfig();
198
+ expect(isAssistantFeatureFlagEnabled(key!, configDefault)).toBe(true);
198
199
 
199
- // Step 5: resolveSkillStates correctly filters it out
200
- const resolvedOff = resolveSkillStates([skill], configOff);
201
- expect(resolvedOff.length).toBe(0);
200
+ // Step 5: resolveSkillStates includes it by default
201
+ const resolvedDefault = resolveSkillStates([skill], configDefault);
202
+ expect(resolvedDefault.length).toBe(1);
203
+ expect(resolvedDefault[0].summary.id).toBe("contacts");
202
204
 
203
- // Step 6: With override enabled, skill passes through
204
- const configOn = makeConfig({
205
- assistantFeatureFlagValues: { [key!]: true },
205
+ // Step 6: With override disabled, skill is filtered out
206
+ const configOff = makeConfig({
207
+ assistantFeatureFlagValues: { [key!]: false },
206
208
  });
207
- expect(isAssistantFeatureFlagEnabled(key!, configOn)).toBe(true);
209
+ expect(isAssistantFeatureFlagEnabled(key!, configOff)).toBe(false);
208
210
 
209
- const resolvedOn = resolveSkillStates([skill], configOn);
210
- expect(resolvedOn.length).toBe(1);
211
- expect(resolvedOn[0].summary.id).toBe("contacts");
211
+ const resolvedOff = resolveSkillStates([skill], configOff);
212
+ expect(resolvedOff.length).toBe(0);
212
213
  });
213
214
  });
@@ -81,14 +81,14 @@ describe("skillFlagKey", () => {
81
81
  // ---------------------------------------------------------------------------
82
82
 
83
83
  describe("isAssistantFeatureFlagEnabled with skillFlagKey", () => {
84
- test("returns false when no flag overrides (registry default is false)", () => {
84
+ test("returns true when no flag overrides (registry default is true)", () => {
85
85
  const config = makeConfig();
86
86
  expect(
87
87
  isAssistantFeatureFlagEnabled(
88
88
  skillFlagKey({ featureFlag: DECLARED_FLAG_ID })!,
89
89
  config,
90
90
  ),
91
- ).toBe(false);
91
+ ).toBe(true);
92
92
  });
93
93
 
94
94
  test("returns true when skill key is explicitly true", () => {
@@ -140,10 +140,8 @@ describe("isAssistantFeatureFlagEnabled", () => {
140
140
 
141
141
  test("falls back to registry default when no override", () => {
142
142
  const config = makeConfig();
143
- // contacts defaults to false in the registry
144
- expect(isAssistantFeatureFlagEnabled(DECLARED_FLAG_KEY, config)).toBe(
145
- false,
146
- );
143
+ // contacts defaults to true in the registry
144
+ expect(isAssistantFeatureFlagEnabled(DECLARED_FLAG_KEY, config)).toBe(true);
147
145
  });
148
146
 
149
147
  test("respects persisted overrides for undeclared keys", () => {
@@ -207,13 +205,14 @@ describe("resolveSkillStates with feature flags", () => {
207
205
  expect(ids).toContain("browser");
208
206
  });
209
207
 
210
- test("declared flag key defaults to registry value (false)", () => {
208
+ test("declared flag key defaults to registry value (true)", () => {
211
209
  const catalog = [makeSkill(DECLARED_SKILL_ID, "bundled", DECLARED_FLAG_ID)];
212
210
  const config = makeConfig();
213
211
 
214
212
  const resolved = resolveSkillStates(catalog, config);
215
- // contacts registry default is false, so it's filtered out
216
- expect(resolved.length).toBe(0);
213
+ // contacts registry default is true, so it passes through
214
+ expect(resolved.length).toBe(1);
215
+ expect(resolved[0].summary.id).toBe(DECLARED_SKILL_ID);
217
216
  });
218
217
 
219
218
  test("skill without featureFlag is never flag-gated", () => {
@@ -280,14 +279,15 @@ describe("resolveSkillStates with feature flags", () => {
280
279
  // ---------------------------------------------------------------------------
281
280
 
282
281
  describe("resolveSkillStates with frontmatter featureFlag", () => {
283
- test("skill with featureFlag (defaultEnabled: false) is filtered when no config override", () => {
284
- // contacts has defaultEnabled: false in the registry
282
+ test("skill with featureFlag (defaultEnabled: true) is included when no config override", () => {
283
+ // contacts has defaultEnabled: true in the registry
285
284
  const catalog = [makeSkill(DECLARED_SKILL_ID, "bundled", DECLARED_FLAG_ID)];
286
285
  const config = makeConfig();
287
286
 
288
287
  const resolved = resolveSkillStates(catalog, config);
289
- // No override, registry default is falsefiltered out
290
- expect(resolved.length).toBe(0);
288
+ // No override, registry default is truepasses through
289
+ expect(resolved.length).toBe(1);
290
+ expect(resolved[0].summary.id).toBe(DECLARED_SKILL_ID);
291
291
  });
292
292
 
293
293
  test("skill with featureFlag is included when config override enables it", () => {
@@ -166,7 +166,7 @@ describe("skill_load feature flag enforcement", () => {
166
166
  expect(result.content).toContain("Skill: Contacts");
167
167
  });
168
168
 
169
- test("rejects skill when flag key is absent (registry defaults to disabled)", async () => {
169
+ test("loads skill when flag key is absent (registry defaults to enabled)", async () => {
170
170
  writeSkill(
171
171
  DECLARED_SKILL_ID,
172
172
  "Contacts",
@@ -184,8 +184,8 @@ describe("skill_load feature flag enforcement", () => {
184
184
 
185
185
  const result = await executeSkillLoad({ skill: DECLARED_SKILL_ID });
186
186
 
187
- // contacts is declared in the registry with defaultEnabled: false
188
- expect(result.isError).toBe(true);
189
- expect(result.content).toContain("disabled by feature flag");
187
+ // contacts is declared in the registry with defaultEnabled: true
188
+ expect(result.isError).toBe(false);
189
+ expect(result.content).toContain("Skill: Contacts");
190
190
  });
191
191
  });
@@ -9,7 +9,9 @@ const skillContent = readFileSync(SKILL_PATH, "utf-8");
9
9
 
10
10
  describe("slack-app-setup skill regression", () => {
11
11
  test("keeps Slack token collection on the secure credential prompt path", () => {
12
- expect(skillContent).toContain('`credential_store` with `action: "prompt"`');
12
+ expect(skillContent).toContain(
13
+ '`credential_store` with `action: "prompt"`',
14
+ );
13
15
  expect(skillContent).toContain(
14
16
  "same Slack settings handler used by Settings",
15
17
  );
@@ -163,11 +163,11 @@ describe("Slack inbound trusted contact verification", () => {
163
163
  // Verification code is NOT sent to the requester — only the guardian
164
164
  // receives it via the access request notification flow
165
165
 
166
- // Channel reply tells user the owner has been notified
166
+ // Channel reply tells user they're not recognized yet
167
167
  expect(deliverReplyCalls.length).toBe(1);
168
168
  expect(
169
169
  (deliverReplyCalls[0].payload as Record<string, unknown>).text,
170
- ).toContain("notified the owner");
170
+ ).toContain("I don't recognize you yet");
171
171
  });
172
172
 
173
173
  test("verification session is identity-bound to the Slack user", async () => {
@@ -39,6 +39,7 @@ function makeContext(): SurfaceConversationContext {
39
39
  >(),
40
40
  surfaceState: new Map(),
41
41
  surfaceUndoStacks: new Map(),
42
+ accumulatedSurfaceState: new Map(),
42
43
  surfaceActionRequestIds: new Set<string>(),
43
44
  currentTurnSurfaces: [],
44
45
  isProcessing: () => false,