@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
@@ -13,6 +13,7 @@ import type {
13
13
  TurnChannelContext,
14
14
  TurnInterfaceContext,
15
15
  } from "../channels/types.js";
16
+ import { getConfig } from "../config/loader.js";
16
17
  import { recordEstimate } from "../context/estimator-calibration.js";
17
18
  import { getCalibrationProviderKey } from "../context/token-estimator.js";
18
19
  import {
@@ -31,6 +32,7 @@ import { backfillMemoryRecallLogMessageId } from "../memory/memory-recall-log-st
31
32
  import { backfillMemoryV2ActivationMessageId } from "../memory/memory-v2-activation-log-store.js";
32
33
  import { getThreadTs } from "../memory/slack-thread-store.js";
33
34
  import {
35
+ formatSlackTimezoneLabel,
34
36
  type SlackMessageMetadata,
35
37
  writeSlackMetadata,
36
38
  } from "../messaging/providers/slack/message-metadata.js";
@@ -46,7 +48,9 @@ import type {
46
48
  import type { ContentBlock, ImageContent } from "../providers/types.js";
47
49
  import { isContextOverflowError } from "../providers/types.js";
48
50
  import { redactSecrets } from "../security/secret-scanner.js";
51
+ import { extractDomain } from "../tools/network/domain-normalize.js";
49
52
  import { ProviderError } from "../util/errors.js";
53
+ import { faviconUrlForDomain } from "../util/favicon.js";
50
54
  import { getLogger } from "../util/logger.js";
51
55
  import type { DirectiveRequest } from "./assistant-attachments.js";
52
56
  import {
@@ -60,7 +64,12 @@ import {
60
64
  isContextTooLarge,
61
65
  } from "./conversation-error.js";
62
66
  import { isProviderOrderingError } from "./conversation-slash.js";
67
+ import { resolveTurnTimezoneContext } from "./date-context.js";
63
68
  import type { ServerMessage } from "./message-protocol.js";
69
+ import type {
70
+ WebSearchMetadata,
71
+ WebSearchResultItem,
72
+ } from "./message-types/web-activity.js";
64
73
 
65
74
  const log = getLogger("agent-loop-handlers");
66
75
 
@@ -199,6 +208,10 @@ export interface EventHandlerState {
199
208
  currentTurnToolUseIds: string[];
200
209
  /** Wall-clock time (ms since epoch) when the agent loop turn started, used as the display timestamp for assistant messages. */
201
210
  turnStartedAt: number;
211
+ /** Wall-clock start time of native server tool calls, keyed by tool_use_id. */
212
+ readonly serverToolStartedAt: Map<string, number>;
213
+ /** Original input from server_tool_start, keyed by tool_use_id, so the complete handler can read the query. */
214
+ readonly serverToolInputs: Map<string, Record<string, unknown>>;
202
215
  }
203
216
 
204
217
  /** Immutable context shared across event handlers within a single agent loop run. */
@@ -257,6 +270,8 @@ export function createEventHandlerState(): EventHandlerState {
257
270
  toolRiskOutcomes: new Map(),
258
271
  currentTurnToolUseIds: [],
259
272
  turnStartedAt: Date.now(),
273
+ serverToolStartedAt: new Map(),
274
+ serverToolInputs: new Map(),
260
275
  };
261
276
  }
262
277
 
@@ -324,6 +339,68 @@ function friendlyToolName(name: string): string {
324
339
  return TOOL_FRIENDLY_NAMES[name] ?? name.replace(/_/g, " ");
325
340
  }
326
341
 
342
+ /**
343
+ * Status text shown to the client while a web search is in flight.
344
+ * Surfaces the actual query so the loading state is meaningful instead of
345
+ * a generic "Searching the web". Used for both Anthropic native server-tool
346
+ * starts and non-native `web_search` tool starts.
347
+ */
348
+ export function formatSearchStatusText(
349
+ toolName: string,
350
+ query: string,
351
+ ): string {
352
+ if (toolName !== "web_search") return `Running ${toolName}`;
353
+ const trimmed = query.trim();
354
+ if (!trimmed) return "Searching the web";
355
+ const truncated =
356
+ trimmed.length > 60 ? trimmed.slice(0, 57) + "..." : trimmed;
357
+ return `Searching "${truncated}"`;
358
+ }
359
+
360
+ /**
361
+ * Status text shown to the client while a web fetch is in flight.
362
+ * Surfaces the domain so users can tell what page is being read.
363
+ */
364
+ export function formatFetchStatusText(url: unknown): string {
365
+ if (typeof url !== "string") return "Reading a page";
366
+ const domain = extractDomain(url);
367
+ if (!domain) return "Reading a page";
368
+ return `Reading ${domain}`;
369
+ }
370
+
371
+ function computeToolUseStatusText(
372
+ name: string,
373
+ input: Record<string, unknown>,
374
+ ): string {
375
+ if (name === "web_search") {
376
+ const query = typeof input.query === "string" ? input.query : "";
377
+ return formatSearchStatusText("web_search", query);
378
+ }
379
+ if (name === "web_fetch") {
380
+ return formatFetchStatusText(input.url);
381
+ }
382
+ if (
383
+ name === "skill_execute" &&
384
+ typeof input.activity === "string" &&
385
+ input.activity.length > 0
386
+ ) {
387
+ return input.activity;
388
+ }
389
+ return `Running ${friendlyToolName(name)}`;
390
+ }
391
+
392
+ function resolveAssistantReplyTimestampTimezone(
393
+ ctx: AgentLoopConversationContext,
394
+ ): string {
395
+ const config = getConfig();
396
+ return resolveTurnTimezoneContext({
397
+ configuredUserTimeZone: config.ui?.userTimezone ?? null,
398
+ clientTimezone: ctx.clientTimezone ?? null,
399
+ detectedTimezone: config.ui?.detectedTimezone ?? null,
400
+ hostTimeZone: Intl.DateTimeFormat().resolvedOptions().timeZone,
401
+ }).effectiveTimezone;
402
+ }
403
+
327
404
  // ── Individual Handlers ──────────────────────────────────────────────
328
405
 
329
406
  function handleTextDelta(
@@ -405,12 +482,7 @@ export function handleToolUse(
405
482
  state.toolCallTimestamps.set(event.id, { startedAt: Date.now() });
406
483
  state.currentToolUseId = event.id;
407
484
  state.currentTurnToolUseIds.push(event.id);
408
- const statusText =
409
- event.name === "skill_execute" &&
410
- typeof event.input.activity === "string" &&
411
- event.input.activity.length > 0
412
- ? event.input.activity
413
- : `Running ${friendlyToolName(event.name)}`;
485
+ const statusText = computeToolUseStatusText(event.name, event.input);
414
486
  deps.ctx.emitActivityState(
415
487
  "tool_running",
416
488
  "tool_use_start",
@@ -677,6 +749,7 @@ export function handleToolResult(
677
749
  approvalMode: event.approvalMode,
678
750
  approvalReason: event.approvalReason,
679
751
  riskThreshold: event.riskThreshold,
752
+ activityMetadata: event.activityMetadata,
680
753
  });
681
754
  }
682
755
 
@@ -985,11 +1058,20 @@ export async function handleMessageComplete(
985
1058
  const channelId = deps.ctx.trustContext?.requesterChatId;
986
1059
  if (channelId) {
987
1060
  const threadTs = getThreadTs(deps.ctx.conversationId);
1061
+ const timestampTimezone = resolveAssistantReplyTimestampTimezone(
1062
+ deps.ctx,
1063
+ );
1064
+ const timestampTimezoneLabel = formatSlackTimezoneLabel(
1065
+ timestampTimezone,
1066
+ { nowMs: state.turnStartedAt },
1067
+ );
988
1068
  const partialSlackMeta: Partial<SlackMessageMetadata> = {
989
1069
  source: "slack",
990
1070
  eventKind: "message",
991
1071
  channelId,
992
1072
  ...(threadTs ? { threadTs } : {}),
1073
+ timestampTimezone,
1074
+ ...(timestampTimezoneLabel ? { timestampTimezoneLabel } : {}),
993
1075
  };
994
1076
  assistantChannelMetadata.slackMeta = writeSlackMetadata(
995
1077
  // `channelTs` is filled in by the post-send reconciliation step in
@@ -1246,10 +1328,9 @@ export async function dispatchAgentEvent(
1246
1328
  handleToolResult(state, deps, event);
1247
1329
  break;
1248
1330
  case "server_tool_start": {
1249
- const friendlyNames: Record<string, string> = {
1250
- web_search: "Searching the web",
1251
- };
1252
- const statusText = friendlyNames[event.name] ?? `Running ${event.name}`;
1331
+ const query =
1332
+ typeof event.input.query === "string" ? event.input.query : "";
1333
+ const statusText = formatSearchStatusText(event.name, query);
1253
1334
  deps.ctx.emitActivityState(
1254
1335
  "tool_running",
1255
1336
  "tool_use_start",
@@ -1257,6 +1338,8 @@ export async function dispatchAgentEvent(
1257
1338
  deps.reqId,
1258
1339
  statusText,
1259
1340
  );
1341
+ state.serverToolStartedAt.set(event.toolUseId, Date.now());
1342
+ state.serverToolInputs.set(event.toolUseId, event.input);
1260
1343
  deps.onEvent({
1261
1344
  type: "tool_use_start",
1262
1345
  toolName: event.name,
@@ -1275,19 +1358,65 @@ export async function dispatchAgentEvent(
1275
1358
  "Thinking",
1276
1359
  );
1277
1360
 
1278
- // Format web search results into a human-readable string for the client.
1279
- let resultText = "";
1280
- if (Array.isArray(event.content) && event.content.length > 0) {
1281
- resultText = (event.content as unknown[])
1282
- .filter(
1283
- (r): r is { type: string; title: string; url: string } =>
1284
- typeof r === "object" &&
1285
- r != null &&
1286
- (r as { type?: string }).type === "web_search_result",
1287
- )
1288
- .map((r) => `${r.title}\n${r.url}`)
1289
- .join("\n\n");
1290
- }
1361
+ // Prefer `resolvedInput` (Anthropic's accumulated server-tool input,
1362
+ // populated on content_block_stop) over the input captured at
1363
+ // server_tool_start, which is `{}` on Anthropic until the deltas land.
1364
+ const inputForCall =
1365
+ event.resolvedInput ?? state.serverToolInputs.get(event.toolUseId);
1366
+ const query =
1367
+ typeof inputForCall?.query === "string" ? inputForCall.query : "";
1368
+ const startedAt =
1369
+ state.serverToolStartedAt.get(event.toolUseId) ?? Date.now();
1370
+ const durationMs = Date.now() - startedAt;
1371
+ state.serverToolStartedAt.delete(event.toolUseId);
1372
+ state.serverToolInputs.delete(event.toolUseId);
1373
+
1374
+ const rawBlocks = Array.isArray(event.content) ? event.content : [];
1375
+ const results: WebSearchResultItem[] = rawBlocks
1376
+ .filter(
1377
+ (r): r is { type: string; title: string; url: string } =>
1378
+ typeof r === "object" &&
1379
+ r != null &&
1380
+ (r as { type?: string }).type === "web_search_result",
1381
+ )
1382
+ .map((r, i) => {
1383
+ const domain = extractDomain(r.url);
1384
+ return {
1385
+ rank: i + 1,
1386
+ title: r.title,
1387
+ url: r.url,
1388
+ domain,
1389
+ faviconUrl: faviconUrlForDomain(domain),
1390
+ // snippet intentionally absent — Anthropic native content is encrypted/opaque
1391
+ };
1392
+ });
1393
+
1394
+ // Only Anthropic produces structured `web_search_tool_result` blocks
1395
+ // that map cleanly onto `WebSearchMetadata` (provider-tagged
1396
+ // "anthropic-native"). Other providers (e.g. OpenAI's responses
1397
+ // `web_search_call`) share this event channel but their results are
1398
+ // woven into the text stream — emitting "anthropic-native" metadata
1399
+ // for them would mis-label the provider and ship empty results.
1400
+ const isAnthropicNative = deps.ctx.provider.name === "anthropic";
1401
+
1402
+ const errorMessage = event.isError
1403
+ ? (event.errorMessage ?? event.errorCode ?? "Search failed")
1404
+ : undefined;
1405
+
1406
+ const metadata: WebSearchMetadata | undefined = isAnthropicNative
1407
+ ? {
1408
+ query,
1409
+ provider: "anthropic-native",
1410
+ resultCount: results.length,
1411
+ durationMs,
1412
+ results,
1413
+ ...(errorMessage ? { errorMessage } : {}),
1414
+ }
1415
+ : undefined;
1416
+
1417
+ const resultText = results
1418
+ .map((r) => `${r.title}\n${r.url}`)
1419
+ .join("\n\n");
1291
1420
 
1292
1421
  deps.onEvent({
1293
1422
  type: "tool_result",
@@ -1296,6 +1425,7 @@ export async function dispatchAgentEvent(
1296
1425
  isError: event.isError,
1297
1426
  conversationId: deps.ctx.conversationId,
1298
1427
  toolUseId: event.toolUseId,
1428
+ ...(metadata ? { activityMetadata: { webSearch: metadata } } : {}),
1299
1429
  });
1300
1430
  break;
1301
1431
  }