@vellumai/assistant 0.8.3 → 0.8.4

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 (342) hide show
  1. package/docker-entrypoint.sh +0 -1
  2. package/node_modules/@vellumai/gateway-client/src/types.ts +2 -0
  3. package/openapi.yaml +610 -16
  4. package/package.json +1 -1
  5. package/src/__tests__/agent-loop-exit-reason.test.ts +4 -5
  6. package/src/__tests__/agent-loop-override-profile.test.ts +1 -1
  7. package/src/__tests__/agent-loop.test.ts +88 -3
  8. package/src/__tests__/anthropic-provider.test.ts +272 -0
  9. package/src/__tests__/approval-cascade.test.ts +1 -1
  10. package/src/__tests__/background-workers-disk-pressure.test.ts +2 -1
  11. package/src/__tests__/channel-delivery-store.test.ts +193 -0
  12. package/src/__tests__/channel-reply-delivery.test.ts +284 -5
  13. package/src/__tests__/channel-retry-sweep.test.ts +274 -1
  14. package/src/__tests__/compaction-events.test.ts +1 -1
  15. package/src/__tests__/compactor-preserved-tail-count.test.ts +110 -0
  16. package/src/__tests__/config-watcher.test.ts +1 -1
  17. package/src/__tests__/context-token-estimator.test.ts +91 -1
  18. package/src/__tests__/conversation-abort-tool-results.test.ts +1 -1
  19. package/src/__tests__/conversation-agent-loop-inference-profile.test.ts +54 -3
  20. package/src/__tests__/conversation-agent-loop-overflow.test.ts +31 -6
  21. package/src/__tests__/conversation-agent-loop.test.ts +25 -7
  22. package/src/__tests__/conversation-app-control-lifecycle.test.ts +1 -1
  23. package/src/__tests__/conversation-clean-command.test.ts +137 -0
  24. package/src/__tests__/conversation-confirmation-signals.test.ts +1 -1
  25. package/src/__tests__/conversation-fork-crud.test.ts +161 -0
  26. package/src/__tests__/conversation-lifecycle.test.ts +1 -1
  27. package/src/__tests__/conversation-load-cleaned-at.test.ts +279 -0
  28. package/src/__tests__/conversation-load-history-repair.test.ts +1 -1
  29. package/src/__tests__/conversation-pairing.test.ts +2 -2
  30. package/src/__tests__/conversation-process-callsite.test.ts +1 -1
  31. package/src/__tests__/conversation-provider-retry-repair.test.ts +1 -1
  32. package/src/__tests__/conversation-queue.test.ts +1 -1
  33. package/src/__tests__/conversation-runtime-assembly.test.ts +264 -81
  34. package/src/__tests__/conversation-seed-composer.test.ts +66 -4
  35. package/src/__tests__/conversation-slash-commands.test.ts +36 -8
  36. package/src/__tests__/conversation-slash-queue.test.ts +1 -1
  37. package/src/__tests__/conversation-slash-unknown.test.ts +1 -1
  38. package/src/__tests__/conversation-speed-override.test.ts +1 -1
  39. package/src/__tests__/conversation-surfaces-task-progress.test.ts +220 -0
  40. package/src/__tests__/conversation-workspace-cache-state.test.ts +1 -1
  41. package/src/__tests__/conversation-workspace-injection.test.ts +5 -1
  42. package/src/__tests__/conversation-workspace-tool-tracking.test.ts +5 -1
  43. package/src/__tests__/credential-security-invariants.test.ts +6 -0
  44. package/src/__tests__/cu-unified-flow.test.ts +10 -1
  45. package/src/__tests__/dm-backfill.test.ts +64 -0
  46. package/src/__tests__/dm-persistence.test.ts +33 -0
  47. package/src/__tests__/document-find-replace.test.ts +501 -0
  48. package/src/__tests__/first-greeting.test.ts +23 -2
  49. package/src/__tests__/headless-browser-navigate.test.ts +172 -0
  50. package/src/__tests__/host-bash-proxy.test.ts +6 -0
  51. package/src/__tests__/host-browser-proxy.test.ts +10 -0
  52. package/src/__tests__/host-cu-proxy.test.ts +8 -1
  53. package/src/__tests__/host-file-proxy.test.ts +8 -1
  54. package/src/__tests__/host-transfer-proxy.test.ts +8 -1
  55. package/src/__tests__/identity-routes.test.ts +57 -0
  56. package/src/__tests__/inbound-slack-persistence.test.ts +3 -0
  57. package/src/__tests__/injector-chain.test.ts +2 -0
  58. package/src/__tests__/injector-document-comments.test.ts +378 -0
  59. package/src/__tests__/injector-pkb-v2-silenced.test.ts +4 -25
  60. package/src/__tests__/list-messages-attachments.test.ts +21 -17
  61. package/src/__tests__/list-messages-hidden-metadata.test.ts +217 -0
  62. package/src/__tests__/list-messages-page-latest.test.ts +130 -14
  63. package/src/__tests__/list-messages-tool-merge.test.ts +17 -16
  64. package/src/__tests__/llm-context-normalization.test.ts +0 -2
  65. package/src/__tests__/llm-resolver.test.ts +85 -1
  66. package/src/__tests__/log-export-routes.test.ts +99 -2
  67. package/src/__tests__/message-queue-steer.test.ts +114 -0
  68. package/src/__tests__/openai-provider.test.ts +105 -0
  69. package/src/__tests__/openai-responses-provider.test.ts +4 -4
  70. package/src/__tests__/outbound-slack-persistence.test.ts +187 -20
  71. package/src/__tests__/pending-interactions-resolved-event.test.ts +190 -0
  72. package/src/__tests__/platform.test.ts +0 -3
  73. package/src/__tests__/plugin-source-watcher.test.ts +302 -0
  74. package/src/__tests__/process-message-background-slack.test.ts +1 -51
  75. package/src/__tests__/process-message-display-content.test.ts +21 -16
  76. package/src/__tests__/server-history-render.test.ts +83 -4
  77. package/src/__tests__/steer-tool-repair.test.ts +249 -0
  78. package/src/__tests__/system-prompt.test.ts +51 -28
  79. package/src/__tests__/terminal-tools.test.ts +11 -1
  80. package/src/__tests__/thinking-block-replay.test.ts +113 -0
  81. package/src/__tests__/thread-backfill.test.ts +370 -22
  82. package/src/__tests__/tool-executor.test.ts +90 -1
  83. package/src/__tests__/tool-result-metadata-plumbing.test.ts +167 -0
  84. package/src/__tests__/twilio-routes.test.ts +1 -1
  85. package/src/__tests__/web-fetch.test.ts +2 -2
  86. package/src/__tests__/workspace-git-service.test.ts +88 -5
  87. package/src/__tests__/workspace-migration-088-deprecate-background-conversation-override.test.ts +158 -0
  88. package/src/agent/attachments.ts +1 -0
  89. package/src/agent/loop.ts +57 -20
  90. package/src/background-wake/next-wake.test.ts +289 -0
  91. package/src/background-wake/next-wake.ts +172 -0
  92. package/src/browser/operations.ts +15 -0
  93. package/src/cli/commands/__tests__/conversations-slack.test.ts +572 -0
  94. package/src/cli/commands/__tests__/memory-v2.test.ts +9 -12
  95. package/src/cli/commands/conversations.ts +128 -1
  96. package/src/cli/commands/inference-providers.ts +147 -1
  97. package/src/cli/commands/memory-v2.ts +308 -0
  98. package/src/cli/commands/notifications.ts +24 -2
  99. package/src/cli/utils/conversation-id.ts +17 -5
  100. package/src/config/bundled-skills/app-builder/SKILL.md +2 -2
  101. package/src/config/bundled-skills/document-editor/SKILL.md +115 -0
  102. package/src/config/bundled-skills/document-editor/TOOLS.json +240 -0
  103. package/src/config/bundled-skills/document-editor/tools/comment-list.ts +12 -0
  104. package/src/config/bundled-skills/document-editor/tools/comment-reply.ts +12 -0
  105. package/src/config/bundled-skills/document-editor/tools/comment-resolve.ts +12 -0
  106. package/src/config/bundled-skills/document-editor/tools/document-find.ts +12 -0
  107. package/src/config/bundled-skills/document-editor/tools/document-replace-text.ts +12 -0
  108. package/src/config/bundled-skills/media-processing/SKILL.md +8 -0
  109. package/src/config/bundled-skills/schedule/SKILL.md +8 -0
  110. package/src/config/bundled-tool-registry.ts +22 -12
  111. package/src/config/call-site-defaults.ts +19 -0
  112. package/src/config/feature-flag-registry.json +99 -3
  113. package/src/config/llm-resolver.ts +16 -2
  114. package/src/config/schemas/__tests__/memory-v2.test.ts +4 -0
  115. package/src/config/schemas/call-site-catalog.ts +21 -0
  116. package/src/config/schemas/llm.ts +3 -0
  117. package/src/config/schemas/memory-v2.ts +48 -1
  118. package/src/context/compactor.ts +8 -1
  119. package/src/context/token-estimator.ts +47 -4
  120. package/src/context/window-manager.ts +25 -0
  121. package/src/credential-health/credential-health-service.ts +34 -19
  122. package/src/daemon/__tests__/conversation-tool-setup.test.ts +66 -6
  123. package/src/daemon/__tests__/native-web-search-metadata.test.ts +357 -0
  124. package/src/daemon/__tests__/web-search-status-text.test.ts +287 -0
  125. package/src/daemon/conversation-agent-loop-handlers.ts +153 -23
  126. package/src/daemon/conversation-agent-loop.ts +223 -54
  127. package/src/daemon/conversation-lifecycle.ts +142 -116
  128. package/src/daemon/conversation-messaging.ts +3 -0
  129. package/src/daemon/conversation-process.ts +273 -0
  130. package/src/daemon/conversation-queue-manager.ts +14 -0
  131. package/src/daemon/conversation-runtime-assembly.ts +135 -75
  132. package/src/daemon/conversation-slash.ts +37 -5
  133. package/src/daemon/conversation-surfaces.ts +45 -2
  134. package/src/daemon/conversation-tool-setup.ts +7 -0
  135. package/src/daemon/conversation.ts +42 -5
  136. package/src/daemon/first-greeting.ts +10 -0
  137. package/src/daemon/handlers/__tests__/config-a2a-accept.test.ts +498 -0
  138. package/src/daemon/handlers/config-a2a.ts +160 -0
  139. package/src/daemon/handlers/config-model.test.ts +1 -0
  140. package/src/daemon/handlers/conversations.ts +79 -0
  141. package/src/daemon/handlers/shared.ts +92 -29
  142. package/src/daemon/host-bash-proxy.ts +1 -1
  143. package/src/daemon/host-cu-proxy.ts +1 -1
  144. package/src/daemon/host-file-proxy.ts +1 -1
  145. package/src/daemon/host-transfer-proxy.ts +1 -1
  146. package/src/daemon/lifecycle.ts +18 -4
  147. package/src/daemon/message-protocol.ts +4 -0
  148. package/src/daemon/message-types/conversations.ts +8 -0
  149. package/src/daemon/message-types/document-comments.ts +50 -0
  150. package/src/daemon/message-types/messages.ts +68 -1
  151. package/src/daemon/message-types/surfaces.ts +3 -1
  152. package/src/daemon/message-types/web-activity.ts +57 -0
  153. package/src/daemon/plugin-source-watcher.ts +135 -3
  154. package/src/daemon/process-message.ts +69 -12
  155. package/src/daemon/query-complexity-router.ts +75 -0
  156. package/src/daemon/trust-context.ts +6 -0
  157. package/src/documents/document-comments-store.test.ts +338 -0
  158. package/src/documents/document-comments-store.ts +237 -0
  159. package/src/documents/document-store.ts +202 -0
  160. package/src/heartbeat/__tests__/heartbeat-service.test.ts +0 -1
  161. package/src/heartbeat/heartbeat-service.ts +1 -0
  162. package/src/home/__tests__/suggested-prompts.test.ts +33 -2
  163. package/src/home/feed-types.ts +6 -1
  164. package/src/home/home-content-refresh.ts +52 -0
  165. package/src/home/home-greeting-cache.ts +69 -0
  166. package/src/home/home-greeting.ts +94 -0
  167. package/src/home/suggested-prompts.ts +177 -9
  168. package/src/memory/__tests__/jobs-worker-v2-schedule.test.ts +135 -2
  169. package/src/memory/__tests__/memory-retrospective-job.test.ts +320 -6
  170. package/src/memory/conversation-crud.ts +133 -43
  171. package/src/memory/db-init.ts +16 -0
  172. package/src/memory/delivery-crud.ts +41 -0
  173. package/src/memory/delivery-status.ts +141 -15
  174. package/src/memory/external-conversation-store.ts +32 -1
  175. package/src/memory/jobs-worker.ts +21 -1
  176. package/src/memory/memory-retrospective-constants.ts +28 -0
  177. package/src/memory/memory-retrospective-enqueue.ts +3 -2
  178. package/src/memory/memory-retrospective-job.ts +408 -18
  179. package/src/memory/memory-retrospective-startup-cleanup.ts +3 -3
  180. package/src/memory/memory-v2-activation-log-store.ts +26 -8
  181. package/src/memory/migrations/100-core-tables.ts +1 -0
  182. package/src/memory/migrations/109-external-conversation-bindings.ts +1 -0
  183. package/src/memory/migrations/253-conversation-last-notified-profile.ts +15 -0
  184. package/src/memory/migrations/253-document-comments.ts +47 -0
  185. package/src/memory/migrations/254-external-conversation-binding-chat-name.ts +43 -0
  186. package/src/memory/migrations/255-channel-inbound-delivery-attempts.ts +24 -0
  187. package/src/memory/migrations/256-memory-v2-injection-events.ts +113 -0
  188. package/src/memory/migrations/257-strip-base-url-non-openai-compatible.ts +22 -0
  189. package/src/memory/migrations/258-onboarding-events-prior-assistants.ts +13 -0
  190. package/src/memory/migrations/259-conversation-cleaned-at.ts +33 -0
  191. package/src/memory/migrations/index.ts +17 -0
  192. package/src/memory/migrations/registry.ts +25 -0
  193. package/src/memory/onboarding-events-store.ts +7 -0
  194. package/src/memory/schema/calls.ts +1 -0
  195. package/src/memory/schema/conversations.ts +3 -0
  196. package/src/memory/schema/infrastructure.ts +1 -0
  197. package/src/memory/v2/__tests__/injection-events.test.ts +318 -0
  198. package/src/memory/v2/__tests__/injection.test.ts +31 -14
  199. package/src/memory/v2/__tests__/page-index.test.ts +365 -1
  200. package/src/memory/v2/__tests__/router.test.ts +489 -1
  201. package/src/memory/v2/consolidation-job.ts +14 -0
  202. package/src/memory/v2/injection-events.ts +101 -0
  203. package/src/memory/v2/injection.ts +21 -10
  204. package/src/memory/v2/page-index.ts +209 -7
  205. package/src/memory/v2/page-store.ts +18 -0
  206. package/src/memory/v2/router.ts +209 -55
  207. package/src/messaging/providers/index.ts +7 -1
  208. package/src/messaging/providers/slack/__tests__/adapter-mention-rendering.test.ts +329 -3
  209. package/src/messaging/providers/slack/__tests__/adapter-token-routing.test.ts +34 -1
  210. package/src/messaging/providers/slack/adapter.ts +178 -25
  211. package/src/messaging/providers/slack/api.test.ts +54 -0
  212. package/src/messaging/providers/slack/api.ts +119 -3
  213. package/src/messaging/providers/slack/client.ts +12 -0
  214. package/src/messaging/providers/slack/deep-link.ts +20 -1
  215. package/src/messaging/providers/slack/message-metadata.test.ts +48 -0
  216. package/src/messaging/providers/slack/message-metadata.ts +156 -0
  217. package/src/messaging/providers/slack/render-transcript.test.ts +107 -75
  218. package/src/messaging/providers/slack/render-transcript.ts +176 -49
  219. package/src/messaging/providers/slack/send.test.ts +77 -0
  220. package/src/messaging/providers/slack/send.ts +8 -2
  221. package/src/messaging/providers/slack/types.ts +14 -0
  222. package/src/notifications/__tests__/emit-signal-home-feed.test.ts +4 -1
  223. package/src/notifications/__tests__/home-feed-side-effect.test.ts +116 -54
  224. package/src/notifications/conversation-seed-composer.ts +14 -2
  225. package/src/notifications/deferred-emit.ts +135 -0
  226. package/src/notifications/emit-signal.ts +9 -1
  227. package/src/notifications/home-feed-side-effect.ts +60 -30
  228. package/src/oauth/connect-orchestrator.ts +3 -0
  229. package/src/oauth/credential-token-resolver.ts +2 -0
  230. package/src/oauth/manual-token-connection.ts +19 -0
  231. package/src/oauth/oauth-store.ts +12 -0
  232. package/src/oauth/seed-providers.ts +22 -0
  233. package/src/permissions/prompter.ts +5 -2
  234. package/src/permissions/secret-prompter.ts +4 -1
  235. package/src/plugins/defaults/injectors.ts +82 -9
  236. package/src/prompts/__tests__/system-prompt.test.ts +46 -2
  237. package/src/prompts/normalize-onboarding.ts +40 -0
  238. package/src/prompts/sections.ts +32 -14
  239. package/src/prompts/system-prompt.ts +105 -68
  240. package/src/prompts/template-detection.ts +37 -0
  241. package/src/prompts/templates/BOOTSTRAP-CONTENT-AUTOMATION.md +141 -0
  242. package/src/prompts/templates/BOOTSTRAP.md +8 -0
  243. package/src/prompts/templates/VOICE.md +3 -0
  244. package/src/prompts/templates/system-sections.ts +53 -3
  245. package/src/providers/anthropic/client.ts +132 -5
  246. package/src/providers/fireworks/client.ts +20 -2
  247. package/src/providers/inference/__tests__/base-url-route-validation.test.ts +342 -0
  248. package/src/providers/inference/__tests__/base-url-security.test.ts +189 -0
  249. package/src/providers/inference/__tests__/codex-token-refresh.test.ts +254 -0
  250. package/src/providers/inference/adapter-factory.ts +15 -1
  251. package/src/providers/inference/auth.ts +3 -3
  252. package/src/providers/inference/codex-token-refresh.ts +128 -0
  253. package/src/providers/inference/resolve-auth.ts +49 -6
  254. package/src/providers/model-catalog.ts +48 -1
  255. package/src/providers/openai/chat-completions-provider.ts +57 -20
  256. package/src/providers/openai/responses-provider.ts +9 -3
  257. package/src/providers/openrouter/client.ts +5 -1
  258. package/src/providers/types.ts +25 -0
  259. package/src/runtime/__tests__/agent-wake.test.ts +214 -0
  260. package/src/runtime/__tests__/background-job-runner.test.ts +128 -0
  261. package/src/runtime/agent-wake.ts +151 -56
  262. package/src/runtime/auth/route-policy.ts +7 -3
  263. package/src/runtime/background-job-runner.ts +26 -0
  264. package/src/runtime/channel-reply-delivery.ts +182 -47
  265. package/src/runtime/channel-retry-sweep.ts +141 -16
  266. package/src/runtime/http-types.ts +7 -4
  267. package/src/runtime/pending-interactions.ts +51 -8
  268. package/src/runtime/routes/__tests__/content-source-routes.test.ts +162 -0
  269. package/src/runtime/routes/__tests__/conversation-query-routes.test.ts +55 -1
  270. package/src/runtime/routes/__tests__/memory-v2-routes.test.ts +14 -0
  271. package/src/runtime/routes/__tests__/memory-v2-simulate-route.test.ts +271 -0
  272. package/src/runtime/routes/__tests__/sanity-routes.test.ts +280 -0
  273. package/src/runtime/routes/__tests__/slack-channel-routes.test.ts +266 -0
  274. package/src/runtime/routes/approval-routes.ts +4 -1
  275. package/src/runtime/routes/chatgpt-subscription-auth-routes.ts +246 -0
  276. package/src/runtime/routes/content-source-routes.ts +78 -0
  277. package/src/runtime/routes/conversation-cli-routes.ts +146 -1
  278. package/src/runtime/routes/conversation-query-routes.ts +60 -1
  279. package/src/runtime/routes/conversation-routes.ts +281 -76
  280. package/src/runtime/routes/document-comments-routes.ts +287 -0
  281. package/src/runtime/routes/documents-routes.ts +33 -0
  282. package/src/runtime/routes/home-feed-routes.ts +6 -3
  283. package/src/runtime/routes/host-app-control-routes.ts +1 -1
  284. package/src/runtime/routes/host-browser-routes.ts +8 -1
  285. package/src/runtime/routes/identity-routes.ts +21 -0
  286. package/src/runtime/routes/inbound-message-handler.ts +288 -58
  287. package/src/runtime/routes/inbound-stages/background-dispatch.test.ts +365 -6
  288. package/src/runtime/routes/inbound-stages/background-dispatch.ts +283 -82
  289. package/src/runtime/routes/index.ts +12 -4
  290. package/src/runtime/routes/inference-provider-connection-routes.ts +63 -7
  291. package/src/runtime/routes/integrations/a2a.ts +60 -1
  292. package/src/runtime/routes/log-export-routes.ts +39 -0
  293. package/src/runtime/routes/memory-v2-routes.ts +217 -0
  294. package/src/runtime/routes/notification-routes.ts +19 -2
  295. package/src/runtime/routes/question-routes.ts +4 -1
  296. package/src/runtime/routes/sanity-routes.ts +159 -0
  297. package/src/runtime/routes/slack-channel-routes.ts +187 -0
  298. package/src/runtime/services/conversation-serializer.ts +30 -4
  299. package/src/schedule/integration-status.ts +3 -1
  300. package/src/security/__tests__/oauth2-device-code.test.ts +479 -0
  301. package/src/security/oauth2-device-code.ts +307 -0
  302. package/src/security/oauth2.ts +26 -9
  303. package/src/security/secure-keys.ts +5 -0
  304. package/src/skills/catalog-install.ts +6 -2
  305. package/src/tools/browser/__tests__/pinned-tabs.test.ts +80 -0
  306. package/src/tools/browser/browser-execution.ts +93 -0
  307. package/src/tools/browser/cdp-client/__tests__/factory.test.ts +28 -0
  308. package/src/tools/browser/cdp-client/__tests__/types.test.ts +1 -0
  309. package/src/tools/browser/cdp-client/cdp-inspect-client.ts +10 -0
  310. package/src/tools/browser/cdp-client/extension-cdp-client.ts +15 -1
  311. package/src/tools/browser/cdp-client/factory.ts +87 -3
  312. package/src/tools/browser/cdp-client/local-cdp-client.ts +9 -0
  313. package/src/tools/browser/cdp-client/types.ts +36 -0
  314. package/src/tools/browser/pinned-tabs.ts +90 -0
  315. package/src/tools/document/document-comment-tool.test.ts +379 -0
  316. package/src/tools/document/document-comment-tool.ts +156 -0
  317. package/src/tools/document/document-tool.ts +128 -2
  318. package/src/tools/network/__tests__/web-fetch-metadata.test.ts +229 -0
  319. package/src/tools/network/__tests__/web-search-metadata.test.ts +346 -0
  320. package/src/tools/network/domain-normalize.ts +17 -0
  321. package/src/tools/network/web-fetch.ts +213 -64
  322. package/src/tools/network/web-search.ts +191 -66
  323. package/src/tools/terminal/safe-env.ts +3 -2
  324. package/src/tools/tool-approval-handler.ts +19 -12
  325. package/src/tools/types.ts +4 -0
  326. package/src/tools/ui-surface/definitions.ts +3 -1
  327. package/src/types/onboarding-context.ts +4 -0
  328. package/src/util/__tests__/favicon.test.ts +84 -0
  329. package/src/util/favicon.ts +40 -0
  330. package/src/util/platform.ts +0 -5
  331. package/src/workspace/git-service.ts +75 -4
  332. package/src/workspace/migrations/088-deprecate-background-conversation-override.ts +103 -0
  333. package/src/workspace/migrations/registry.ts +2 -0
  334. package/src/config/bundled-skills/document/SKILL.md +0 -54
  335. package/src/config/bundled-skills/document/TOOLS.json +0 -106
  336. package/src/daemon/seed-files.ts +0 -18
  337. package/src/runtime/routes/interface-routes.ts +0 -43
  338. /package/src/config/bundled-skills/{document → document-editor}/tools/document-create.ts +0 -0
  339. /package/src/config/bundled-skills/{document → document-editor}/tools/document-delete.ts +0 -0
  340. /package/src/config/bundled-skills/{document → document-editor}/tools/document-list.ts +0 -0
  341. /package/src/config/bundled-skills/{document → document-editor}/tools/document-read.ts +0 -0
  342. /package/src/config/bundled-skills/{document → document-editor}/tools/document-update.ts +0 -0
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@vellumai/assistant",
3
- "version": "0.8.3",
3
+ "version": "0.8.4",
4
4
  "license": "MIT",
5
5
  "type": "module",
6
6
  "exports": {
@@ -7,8 +7,8 @@
7
7
  * throw → catch-block fallback case).
8
8
  * 2. **Reason matches break site** — for each reachable break site, the
9
9
  * emitted reason is the one documented in `AgentLoopExitReason`.
10
- * 3. **Always the last AgentEvent of the run** — consumers can rely on
11
- * positional ordering to find it.
10
+ * 3. **Always the last AgentEvent of terminal runs** — consumers can rely on
11
+ * positional ordering to find it when a run reaches a terminal state.
12
12
  *
13
13
  * Sites not exercised here (`empty_response_exhausted`, `aborted_via_error`)
14
14
  * require deeper provider fakery and are best covered by integration tests
@@ -172,7 +172,7 @@ describe("AgentLoop exit-reason instrumentation", () => {
172
172
  expect(lastExitEvent(events)?.reason).toBe("yield_to_user");
173
173
  });
174
174
 
175
- test("emits 'checkpoint_yield' when onCheckpoint returns 'yield'", async () => {
175
+ test("does not emit agent_loop_exit when onCheckpoint yields control", async () => {
176
176
  const { provider } = createMockProvider([
177
177
  toolUseResponse("t1", "read_file", { path: "/a.txt" }),
178
178
  textResponse("never reached"),
@@ -198,8 +198,7 @@ describe("AgentLoop exit-reason instrumentation", () => {
198
198
  onCheckpoint,
199
199
  );
200
200
 
201
- expect(countExitEvents(events)).toBe(1);
202
- expect(lastExitEvent(events)?.reason).toBe("checkpoint_yield");
201
+ expect(countExitEvents(events)).toBe(0);
203
202
  });
204
203
 
205
204
  test("emits 'error' when provider throws an unhandled error", async () => {
@@ -257,7 +257,7 @@ const anthropicStub = { name: "anthropic" };
257
257
  mock.module("../providers/registry.js", () => ({
258
258
  getProvider: () => anthropicStub,
259
259
  listProviders: () => ["anthropic"],
260
- initializeProviders: () => {},
260
+ initializeProviders: async () => {},
261
261
  resolveProviderFromConnection: async () => anthropicStub,
262
262
  }));
263
263
 
@@ -181,6 +181,88 @@ describe("AgentLoop", () => {
181
181
  ]);
182
182
  });
183
183
 
184
+ test("re-resolves override profile before each provider call", async () => {
185
+ const toolCallId = "tool-1";
186
+ const { provider, calls } = createMockProvider([
187
+ toolUseResponse(toolCallId, "read_file", { path: "/tmp/test.txt" }),
188
+ textResponse("File contents received."),
189
+ ]);
190
+
191
+ let overrideProfile: string | undefined;
192
+ const toolExecutor = async () => {
193
+ overrideProfile = "quality-optimized";
194
+ return { content: "ok", isError: false };
195
+ };
196
+ const loop = new AgentLoop(
197
+ provider,
198
+ "system",
199
+ {},
200
+ dummyTools,
201
+ toolExecutor,
202
+ );
203
+
204
+ await loop.run(
205
+ [userMessage],
206
+ collectEvents([]),
207
+ undefined,
208
+ "req-1",
209
+ undefined,
210
+ "mainAgent",
211
+ undefined,
212
+ undefined,
213
+ undefined,
214
+ () => overrideProfile,
215
+ );
216
+
217
+ expect(calls).toHaveLength(2);
218
+ expect(calls[0].options?.config?.overrideProfile).toBeUndefined();
219
+ expect(calls[1].options?.config?.overrideProfile).toBe("quality-optimized");
220
+ });
221
+
222
+ test("re-resolves max input tokens before truncating tool results", async () => {
223
+ const toolCallId = "tool-1";
224
+ const toolOutput = "x".repeat(2_500);
225
+ const { provider, calls } = createMockProvider([
226
+ toolUseResponse(toolCallId, "read_file", { path: "/tmp/test.txt" }),
227
+ textResponse("File contents received."),
228
+ ]);
229
+
230
+ let maxInputTokens = 1_000;
231
+ const toolExecutor = async () => {
232
+ maxInputTokens = 10_000;
233
+ return { content: toolOutput, isError: false };
234
+ };
235
+ const loop = new AgentLoop(
236
+ provider,
237
+ "system",
238
+ {},
239
+ dummyTools,
240
+ toolExecutor,
241
+ );
242
+
243
+ await loop.run(
244
+ [userMessage],
245
+ collectEvents([]),
246
+ undefined,
247
+ "req-1",
248
+ undefined,
249
+ "mainAgent",
250
+ undefined,
251
+ undefined,
252
+ 1_000,
253
+ undefined,
254
+ () => maxInputTokens,
255
+ );
256
+
257
+ const secondCallMessages = calls[1].messages;
258
+ const lastMsg = secondCallMessages[secondCallMessages.length - 1];
259
+ const toolResultBlock = lastMsg.content.find(
260
+ (b): b is Extract<ContentBlock, { type: "tool_result" }> =>
261
+ b.type === "tool_result",
262
+ );
263
+ expect(toolResultBlock?.content).toBe(toolOutput);
264
+ });
265
+
184
266
  // 3. Multi-turn tool loop
185
267
  test("supports multi-turn tool execution", async () => {
186
268
  const { provider, calls } = createMockProvider([
@@ -470,7 +552,6 @@ describe("AgentLoop", () => {
470
552
  ).toBe(false);
471
553
  });
472
554
 
473
-
474
555
  // 9. Tool executor error results are forwarded correctly
475
556
  test("forwards tool error results to provider", async () => {
476
557
  const { provider, calls } = createMockProvider([
@@ -1767,7 +1848,9 @@ describe("AgentLoop", () => {
1767
1848
  ]);
1768
1849
 
1769
1850
  // message_complete emitted for tool_use response + retry text response (not the empty one)
1770
- const messageCompletes = events.filter((e) => e.type === "message_complete");
1851
+ const messageCompletes = events.filter(
1852
+ (e) => e.type === "message_complete",
1853
+ );
1771
1854
  expect(messageCompletes).toHaveLength(2);
1772
1855
  });
1773
1856
 
@@ -1883,7 +1966,9 @@ describe("AgentLoop", () => {
1883
1966
  expect(calls).toHaveLength(3);
1884
1967
 
1885
1968
  // message_complete: tool_use response + final empty response (retry exhausted)
1886
- const messageCompletes = events.filter((e) => e.type === "message_complete");
1969
+ const messageCompletes = events.filter(
1970
+ (e) => e.type === "message_complete",
1971
+ );
1887
1972
  expect(messageCompletes).toHaveLength(2);
1888
1973
 
1889
1974
  // The last assistant message in history is the empty one
@@ -1,5 +1,7 @@
1
1
  import { beforeEach, describe, expect, mock, test } from "bun:test";
2
2
 
3
+ import type { Anthropic } from "@anthropic-ai/sdk";
4
+
3
5
  import type { Message, ToolDefinition } from "../providers/types.js";
4
6
 
5
7
  // ---------------------------------------------------------------------------
@@ -204,6 +206,28 @@ describe("AnthropicProvider — Cache-Control Characterization", () => {
204
206
  expect(lastStreamParams!.thinking).toEqual({ type: "disabled" });
205
207
  });
206
208
 
209
+ test("drops unsigned thinking blocks from prior assistant messages", async () => {
210
+ await provider.sendMessage([
211
+ userMsg("Hi"),
212
+ {
213
+ role: "assistant",
214
+ content: [
215
+ { type: "thinking", thinking: "non-native reasoning", signature: "" },
216
+ { type: "text", text: "I can help." },
217
+ ],
218
+ },
219
+ userMsg("Continue"),
220
+ ]);
221
+
222
+ const messages = lastStreamParams!.messages as Array<{
223
+ role: string;
224
+ content: Array<{ type: string; text?: string; thinking?: string }>;
225
+ }>;
226
+ const assistant = messages.find((message) => message.role === "assistant");
227
+
228
+ expect(assistant?.content).toEqual([{ type: "text", text: "I can help." }]);
229
+ });
230
+
207
231
  test("splits system prompt into two cache blocks on boundary marker", async () => {
208
232
  const staticBlock = "You are a helpful assistant.";
209
233
  const dynamicBlock = "User workspace files here.";
@@ -2405,3 +2429,251 @@ describe("OpenRouterProvider — Anthropic dispatch", () => {
2405
2429
  expect(lastStreamParams!.model).toBe("anthropic/claude-haiku-4.5");
2406
2430
  });
2407
2431
  });
2432
+
2433
+ // ---------------------------------------------------------------------------
2434
+ // Thinking block send-time filtering
2435
+ // ---------------------------------------------------------------------------
2436
+
2437
+ describe("AnthropicProvider — thinking block send-time filtering", () => {
2438
+ let provider: AnthropicProvider;
2439
+
2440
+ beforeEach(() => {
2441
+ lastStreamParams = null;
2442
+ _lastStreamOptions = null;
2443
+ lastConstructorArgs = null;
2444
+ scriptedStream = null;
2445
+ provider = new AnthropicProvider("sk-ant-test", "claude-sonnet-4-6");
2446
+ });
2447
+
2448
+ function assistantThinkingMsg(
2449
+ thinking: string,
2450
+ signature: string,
2451
+ text: string,
2452
+ ): Message {
2453
+ return {
2454
+ role: "assistant",
2455
+ content: [
2456
+ { type: "thinking", thinking, signature },
2457
+ { type: "text", text },
2458
+ ],
2459
+ };
2460
+ }
2461
+
2462
+ function assistantThinkingToolUseMsg(
2463
+ thinking: string,
2464
+ signature: string,
2465
+ toolUseId: string,
2466
+ toolName: string,
2467
+ ): Message {
2468
+ return {
2469
+ role: "assistant",
2470
+ content: [
2471
+ { type: "thinking", thinking, signature },
2472
+ { type: "tool_use", id: toolUseId, name: toolName, input: {} },
2473
+ ],
2474
+ };
2475
+ }
2476
+
2477
+ function assistantRedactedThinkingMsg(data: string, text: string): Message {
2478
+ return {
2479
+ role: "assistant",
2480
+ content: [
2481
+ { type: "redacted_thinking", data },
2482
+ { type: "text", text },
2483
+ ],
2484
+ };
2485
+ }
2486
+
2487
+ test("strips thinking blocks from completed historical assistant turns", async () => {
2488
+ const messages: Message[] = [
2489
+ userMsg("What is 2+2?"),
2490
+ assistantThinkingMsg("let me think...", "sig-abc-old", "4"),
2491
+ userMsg("And what is 3+3?"),
2492
+ ];
2493
+
2494
+ await provider.sendMessage(messages, sampleTools, "system");
2495
+ expect(lastStreamParams).toBeTruthy();
2496
+
2497
+ const sent = lastStreamParams!.messages as Anthropic.MessageParam[];
2498
+ const assistantTurn = sent.find((m) => m.role === "assistant");
2499
+ expect(assistantTurn).toBeTruthy();
2500
+
2501
+ const blocks = assistantTurn!.content as Anthropic.ContentBlockParam[];
2502
+ const thinkingBlocks = blocks.filter(
2503
+ (b) => typeof b !== "string" && b.type === "thinking",
2504
+ );
2505
+ expect(thinkingBlocks).toHaveLength(0);
2506
+
2507
+ const textBlocks = blocks.filter(
2508
+ (b) => typeof b !== "string" && b.type === "text",
2509
+ );
2510
+ expect(textBlocks).toHaveLength(1);
2511
+ });
2512
+
2513
+ test("strips redacted_thinking blocks from completed historical turns", async () => {
2514
+ const messages: Message[] = [
2515
+ userMsg("What is 2+2?"),
2516
+ assistantRedactedThinkingMsg("encrypted-data-xyz", "4"),
2517
+ userMsg("And what is 3+3?"),
2518
+ ];
2519
+
2520
+ await provider.sendMessage(messages, sampleTools, "system");
2521
+ expect(lastStreamParams).toBeTruthy();
2522
+
2523
+ const sent = lastStreamParams!.messages as Anthropic.MessageParam[];
2524
+ const assistantTurn = sent.find((m) => m.role === "assistant");
2525
+ expect(assistantTurn).toBeTruthy();
2526
+
2527
+ const blocks = assistantTurn!.content as Anthropic.ContentBlockParam[];
2528
+ const redactedBlocks = blocks.filter(
2529
+ (b) => typeof b !== "string" && b.type === "redacted_thinking",
2530
+ );
2531
+ expect(redactedBlocks).toHaveLength(0);
2532
+ });
2533
+
2534
+ test("preserves thinking blocks in active tool-use continuation span", async () => {
2535
+ const messages: Message[] = [
2536
+ userMsg("Read the file"),
2537
+ assistantThinkingToolUseMsg(
2538
+ "I should read the file",
2539
+ "sig-valid-123",
2540
+ "tu-1",
2541
+ "file_read",
2542
+ ),
2543
+ toolResultMsg("tu-1", "file contents here"),
2544
+ ];
2545
+
2546
+ await provider.sendMessage(messages, sampleTools, "system");
2547
+ expect(lastStreamParams).toBeTruthy();
2548
+
2549
+ const sent = lastStreamParams!.messages as Anthropic.MessageParam[];
2550
+ const assistantTurn = sent.find((m) => m.role === "assistant");
2551
+ expect(assistantTurn).toBeTruthy();
2552
+
2553
+ const blocks = assistantTurn!.content as Anthropic.ContentBlockParam[];
2554
+ const thinkingBlocks = blocks.filter(
2555
+ (b) => typeof b !== "string" && b.type === "thinking",
2556
+ );
2557
+ expect(thinkingBlocks).toHaveLength(1);
2558
+ expect((thinkingBlocks[0] as { signature: string }).signature).toBe(
2559
+ "sig-valid-123",
2560
+ );
2561
+ });
2562
+
2563
+ test("strips historical thinking but preserves active continuation in same conversation", async () => {
2564
+ const messages: Message[] = [
2565
+ // Completed historical turn
2566
+ userMsg("What is 2+2?"),
2567
+ assistantThinkingMsg("old thinking", "sig-old-stale", "4"),
2568
+ // Active tool-use continuation
2569
+ userMsg("Now read the file"),
2570
+ assistantThinkingToolUseMsg(
2571
+ "current thinking",
2572
+ "sig-current-valid",
2573
+ "tu-2",
2574
+ "file_read",
2575
+ ),
2576
+ toolResultMsg("tu-2", "file contents"),
2577
+ ];
2578
+
2579
+ await provider.sendMessage(messages, sampleTools, "system");
2580
+ expect(lastStreamParams).toBeTruthy();
2581
+
2582
+ const sent = lastStreamParams!.messages as Anthropic.MessageParam[];
2583
+ const assistantTurns = sent.filter((m) => m.role === "assistant");
2584
+ expect(assistantTurns.length).toBeGreaterThanOrEqual(2);
2585
+
2586
+ // Historical turn: thinking stripped
2587
+ const historicalBlocks = assistantTurns[0]
2588
+ .content as Anthropic.ContentBlockParam[];
2589
+ const historicalThinking = historicalBlocks.filter(
2590
+ (b) => typeof b !== "string" && b.type === "thinking",
2591
+ );
2592
+ expect(historicalThinking).toHaveLength(0);
2593
+
2594
+ // Active turn: thinking preserved
2595
+ const activeBlocks = assistantTurns[1]
2596
+ .content as Anthropic.ContentBlockParam[];
2597
+ const activeThinking = activeBlocks.filter(
2598
+ (b) => typeof b !== "string" && b.type === "thinking",
2599
+ );
2600
+ expect(activeThinking).toHaveLength(1);
2601
+ expect((activeThinking[0] as { signature: string }).signature).toBe(
2602
+ "sig-current-valid",
2603
+ );
2604
+ });
2605
+
2606
+ test("uses placeholder when stripping thinking leaves assistant message empty", async () => {
2607
+ const messages: Message[] = [
2608
+ userMsg("Think about this"),
2609
+ {
2610
+ role: "assistant",
2611
+ content: [{ type: "thinking", thinking: "hmm...", signature: "sig-x" }],
2612
+ },
2613
+ userMsg("What did you conclude?"),
2614
+ ];
2615
+
2616
+ await provider.sendMessage(messages, sampleTools, "system");
2617
+ expect(lastStreamParams).toBeTruthy();
2618
+
2619
+ const sent = lastStreamParams!.messages as Anthropic.MessageParam[];
2620
+ const assistantTurn = sent.find((m) => m.role === "assistant");
2621
+ expect(assistantTurn).toBeTruthy();
2622
+
2623
+ const blocks = assistantTurn!.content as Anthropic.ContentBlockParam[];
2624
+ expect(blocks).toHaveLength(1);
2625
+ expect((blocks[0] as { type: string; text: string }).type).toBe("text");
2626
+ expect(
2627
+ isPlaceholderSentinelText((blocks[0] as { text: string }).text),
2628
+ ).toBe(true);
2629
+ });
2630
+
2631
+ test("multi-step tool-use chain preserves all thinking in the active span", async () => {
2632
+ const messages: Message[] = [
2633
+ // Completed historical turn
2634
+ userMsg("Hello"),
2635
+ assistantThinkingMsg("old thinking", "sig-old", "Hi there"),
2636
+ // Multi-step active tool-use chain
2637
+ userMsg("Do two things"),
2638
+ assistantThinkingToolUseMsg(
2639
+ "step 1 thinking",
2640
+ "sig-step1",
2641
+ "tu-a",
2642
+ "file_read",
2643
+ ),
2644
+ toolResultMsg("tu-a", "result a"),
2645
+ assistantThinkingToolUseMsg(
2646
+ "step 2 thinking",
2647
+ "sig-step2",
2648
+ "tu-b",
2649
+ "file_write",
2650
+ ),
2651
+ toolResultMsg("tu-b", "result b"),
2652
+ ];
2653
+
2654
+ await provider.sendMessage(messages, sampleTools, "system");
2655
+ expect(lastStreamParams).toBeTruthy();
2656
+
2657
+ const sent = lastStreamParams!.messages as Anthropic.MessageParam[];
2658
+
2659
+ // Collect all thinking blocks across all assistant messages
2660
+ const allThinking: Anthropic.ContentBlockParam[] = [];
2661
+ for (const m of sent) {
2662
+ if (m.role !== "assistant") continue;
2663
+ const blocks = m.content as Anthropic.ContentBlockParam[];
2664
+ for (const b of blocks) {
2665
+ if (typeof b !== "string" && b.type === "thinking") {
2666
+ allThinking.push(b);
2667
+ }
2668
+ }
2669
+ }
2670
+
2671
+ // Only the active span's thinking blocks should remain
2672
+ const signatures = allThinking.map(
2673
+ (b) => (b as { signature: string }).signature,
2674
+ );
2675
+ expect(signatures).not.toContain("sig-old");
2676
+ expect(signatures).toContain("sig-step1");
2677
+ expect(signatures).toContain("sig-step2");
2678
+ });
2679
+ });
@@ -50,7 +50,7 @@ mock.module("../memory/guardian-action-store.js", () => ({
50
50
 
51
51
  mock.module("../providers/registry.js", () => ({
52
52
  getProvider: () => ({ name: "mock-provider" }),
53
- initializeProviders: () => {},
53
+ initializeProviders: async () => {},
54
54
  }));
55
55
 
56
56
  mock.module("../config/loader.js", () => ({
@@ -131,7 +131,6 @@ mock.module("../memory/conversation-crud.js", () => ({
131
131
  getConversationSource: () => null,
132
132
  getAssistantMessageIdsInTurn: () => [],
133
133
  getDisplayMetaForConversations: () => new Map(),
134
- getLastAssistantTimestampBefore: () => null,
135
134
  getLastUserTimestampBefore: () => null,
136
135
  getMessageById: () => null,
137
136
  getMessages: () => [],
@@ -156,6 +155,8 @@ mock.module("../memory/conversation-crud.js", () => ({
156
155
  updateConversationSlackContextWatermark: mock(() => {}),
157
156
  updateConversationTitle: mock(() => {}),
158
157
  updateConversationUsage: mock(() => {}),
158
+ setLastNotifiedInferenceProfile: mock(() => {}),
159
+ setConversationCleanedAt: mock(() => {}),
159
160
  wipeConversation: mock(() => ({ memoryIds: [] })),
160
161
  }));
161
162