@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
@@ -0,0 +1,287 @@
1
+ /**
2
+ * Route handlers for document comment CRUD operations.
3
+ *
4
+ * Exposes comment management over HTTP, delegating to the store layer in
5
+ * `documents/document-comments-store.ts`.
6
+ */
7
+ import { z } from "zod";
8
+
9
+ import {
10
+ createComment,
11
+ deleteComment,
12
+ getComment,
13
+ listComments,
14
+ reopenComment,
15
+ resolveComment,
16
+ updateCommentContent,
17
+ } from "../../documents/document-comments-store.js";
18
+ import { getLogger } from "../../util/logger.js";
19
+ import { broadcastMessage } from "../assistant-event-hub.js";
20
+ import { BadRequestError, NotFoundError } from "./errors.js";
21
+ import type { RouteDefinition } from "./types.js";
22
+
23
+ const log = getLogger("document-comments-routes");
24
+
25
+ // ---------------------------------------------------------------------------
26
+ // Request schemas
27
+ // ---------------------------------------------------------------------------
28
+
29
+ const listQuerySchema = z.object({
30
+ status: z
31
+ .enum(["open", "resolved", "all"])
32
+ .default("all")
33
+ .describe("Filter by comment status"),
34
+ });
35
+
36
+ const createBodySchema = z.object({
37
+ content: z.string().min(1).describe("Comment text content"),
38
+ author: z.literal("user").optional().default("user").describe("Comment author"),
39
+ anchorStart: z
40
+ .number()
41
+ .nullable()
42
+ .optional()
43
+ .describe("Selection start offset"),
44
+ anchorEnd: z.number().nullable().optional().describe("Selection end offset"),
45
+ anchorText: z
46
+ .string()
47
+ .nullable()
48
+ .optional()
49
+ .describe("Anchored text snippet"),
50
+ parentCommentId: z
51
+ .string()
52
+ .nullable()
53
+ .optional()
54
+ .describe("Parent comment ID for replies"),
55
+ conversationId: z.string().describe("Owning conversation ID"),
56
+ });
57
+
58
+ const updateBodySchema = z
59
+ .object({
60
+ status: z
61
+ .enum(["open", "resolved"])
62
+ .optional()
63
+ .describe("New comment status"),
64
+ content: z.string().min(1).optional().describe("Updated comment text"),
65
+ resolvedBy: z.string().optional().describe("Who resolved the comment"),
66
+ })
67
+ .refine((data) => data.status !== undefined || data.content !== undefined, {
68
+ message: "At least one of status or content must be provided",
69
+ });
70
+
71
+ // ---------------------------------------------------------------------------
72
+ // Route definitions
73
+ // ---------------------------------------------------------------------------
74
+
75
+ export const ROUTES: RouteDefinition[] = [
76
+ {
77
+ operationId: "listDocumentComments",
78
+ endpoint: "documents/:id/comments",
79
+ method: "GET",
80
+ policyKey: "documents",
81
+ requirePolicyEnforcement: true,
82
+ summary: "List comments for a document",
83
+ description:
84
+ "Return comments for a document, optionally filtered by status.",
85
+ tags: ["documents"],
86
+ queryParams: [
87
+ {
88
+ name: "status",
89
+ schema: { type: "string", enum: ["open", "resolved", "all"] },
90
+ description: "Filter by comment status (default: all)",
91
+ },
92
+ ],
93
+ responseBody: z.object({
94
+ comments: z.array(z.unknown()).describe("Comment records"),
95
+ }),
96
+ handler: ({ pathParams, queryParams }) => {
97
+ const parsed = listQuerySchema.safeParse(queryParams ?? {});
98
+ if (!parsed.success) {
99
+ throw new BadRequestError(parsed.error.issues[0].message);
100
+ }
101
+ const { status } = parsed.data;
102
+ const comments = listComments(pathParams!.id, { status });
103
+ return { comments };
104
+ },
105
+ },
106
+
107
+ {
108
+ operationId: "createDocumentComment",
109
+ endpoint: "documents/:id/comments",
110
+ method: "POST",
111
+ policyKey: "documents",
112
+ requirePolicyEnforcement: true,
113
+ summary: "Create a comment on a document",
114
+ description: "Add a new comment to a document.",
115
+ tags: ["documents"],
116
+ requestBody: createBodySchema,
117
+ responseBody: z.object({
118
+ id: z.string(),
119
+ surfaceId: z.string(),
120
+ conversationId: z.string(),
121
+ author: z.string(),
122
+ content: z.string(),
123
+ status: z.string(),
124
+ createdAt: z.number(),
125
+ updatedAt: z.number(),
126
+ }),
127
+ handler: ({ pathParams, body }) => {
128
+ const parsed = createBodySchema.safeParse(body ?? {});
129
+ if (!parsed.success) {
130
+ throw new BadRequestError(parsed.error.issues[0].message);
131
+ }
132
+ const {
133
+ content,
134
+ author,
135
+ anchorStart,
136
+ anchorEnd,
137
+ anchorText,
138
+ parentCommentId,
139
+ conversationId,
140
+ } = parsed.data;
141
+ const comment = createComment({
142
+ surfaceId: pathParams!.id,
143
+ conversationId,
144
+ author,
145
+ content,
146
+ anchorStart,
147
+ anchorEnd,
148
+ anchorText,
149
+ parentCommentId,
150
+ });
151
+ broadcastMessage(
152
+ {
153
+ type: "document_comment_created",
154
+ conversationId,
155
+ surfaceId: pathParams!.id,
156
+ comment: {
157
+ id: comment.id,
158
+ surfaceId: comment.surfaceId,
159
+ author: comment.author,
160
+ content: comment.content,
161
+ anchorStart: comment.anchorStart ?? undefined,
162
+ anchorEnd: comment.anchorEnd ?? undefined,
163
+ anchorText: comment.anchorText ?? undefined,
164
+ parentCommentId: comment.parentCommentId ?? undefined,
165
+ status: comment.status,
166
+ createdAt: comment.createdAt,
167
+ updatedAt: comment.updatedAt,
168
+ },
169
+ },
170
+ conversationId,
171
+ );
172
+ log.info(
173
+ { id: comment.id, surfaceId: pathParams!.id },
174
+ "Created document comment via HTTP",
175
+ );
176
+ return comment;
177
+ },
178
+ },
179
+
180
+ {
181
+ operationId: "updateDocumentComment",
182
+ endpoint: "documents/:id/comments/:commentId",
183
+ method: "PATCH",
184
+ policyKey: "documents",
185
+ requirePolicyEnforcement: true,
186
+ summary: "Update a document comment",
187
+ description: "Update the status or content of a comment.",
188
+ tags: ["documents"],
189
+ requestBody: updateBodySchema,
190
+ responseBody: z.object({
191
+ id: z.string(),
192
+ surfaceId: z.string(),
193
+ content: z.string(),
194
+ status: z.string(),
195
+ updatedAt: z.number(),
196
+ }),
197
+ handler: ({ pathParams, body }) => {
198
+ const parsed = updateBodySchema.safeParse(body ?? {});
199
+ if (!parsed.success) {
200
+ throw new BadRequestError(parsed.error.issues[0].message);
201
+ }
202
+ const { status, content, resolvedBy } = parsed.data;
203
+ const commentId = pathParams!.commentId;
204
+
205
+ const existing = getComment(commentId);
206
+ if (!existing || existing.surfaceId !== pathParams!.id) {
207
+ throw new NotFoundError("Comment not found");
208
+ }
209
+
210
+ if (status === "resolved") {
211
+ resolveComment(commentId, resolvedBy ?? "user");
212
+ broadcastMessage(
213
+ {
214
+ type: "document_comment_resolved",
215
+ conversationId: existing.conversationId,
216
+ surfaceId: pathParams!.id,
217
+ commentId,
218
+ resolvedBy: resolvedBy ?? "user",
219
+ },
220
+ existing.conversationId,
221
+ );
222
+ } else if (status === "open") {
223
+ reopenComment(commentId);
224
+ broadcastMessage(
225
+ {
226
+ type: "document_comment_reopened",
227
+ conversationId: existing.conversationId,
228
+ surfaceId: pathParams!.id,
229
+ commentId,
230
+ },
231
+ existing.conversationId,
232
+ );
233
+ }
234
+
235
+ if (content !== undefined) {
236
+ updateCommentContent(commentId, content);
237
+ }
238
+
239
+ const updated = getComment(commentId);
240
+ if (!updated) {
241
+ throw new NotFoundError("Comment not found after update");
242
+ }
243
+
244
+ log.info(
245
+ { id: commentId, surfaceId: pathParams!.id },
246
+ "Updated document comment via HTTP",
247
+ );
248
+ return updated;
249
+ },
250
+ },
251
+
252
+ {
253
+ operationId: "deleteDocumentComment",
254
+ endpoint: "documents/:id/comments/:commentId",
255
+ method: "DELETE",
256
+ policyKey: "documents",
257
+ requirePolicyEnforcement: true,
258
+ summary: "Delete a document comment",
259
+ description: "Permanently delete a comment.",
260
+ tags: ["documents"],
261
+ responseBody: z.object({
262
+ success: z.literal(true),
263
+ }),
264
+ handler: ({ pathParams }) => {
265
+ const commentId = pathParams!.commentId;
266
+ const existing = getComment(commentId);
267
+ if (!existing || existing.surfaceId !== pathParams!.id) {
268
+ throw new NotFoundError("Comment not found");
269
+ }
270
+ deleteComment(commentId);
271
+ broadcastMessage(
272
+ {
273
+ type: "document_comment_deleted",
274
+ conversationId: existing.conversationId,
275
+ surfaceId: pathParams!.id,
276
+ commentId,
277
+ },
278
+ existing.conversationId,
279
+ );
280
+ log.info(
281
+ { id: commentId, surfaceId: pathParams!.id },
282
+ "Deleted document comment via HTTP",
283
+ );
284
+ return { success: true as const };
285
+ },
286
+ },
287
+ ];
@@ -7,6 +7,7 @@
7
7
  import { z } from "zod";
8
8
 
9
9
  import {
10
+ addDocumentConversation,
10
11
  getDocumentById,
11
12
  getDocumentsForConversation,
12
13
  saveDocument,
@@ -181,6 +182,38 @@ export const ROUTES: RouteDefinition[] = [
181
182
  },
182
183
  },
183
184
 
185
+ {
186
+ operationId: "linkDocumentConversation",
187
+ endpoint: "documents/:id/conversations",
188
+ method: "POST",
189
+ policyKey: "documents",
190
+ requirePolicyEnforcement: true,
191
+ summary: "Link a document to a conversation",
192
+ description:
193
+ "Associate a document with a conversation so the assistant sees it as context.",
194
+ tags: ["documents"],
195
+ requestBody: z.object({
196
+ conversationId: z.string().describe("Conversation to link"),
197
+ }),
198
+ responseBody: z.object({ success: z.literal(true) }),
199
+ handler: ({ pathParams, body }) => {
200
+ const { conversationId } = (body ?? {}) as { conversationId?: string };
201
+ if (!conversationId) {
202
+ throw new BadRequestError("conversationId is required");
203
+ }
204
+ const doc = getDocumentById(pathParams!.id);
205
+ if (!doc) {
206
+ throw new NotFoundError("Document not found");
207
+ }
208
+ addDocumentConversation(pathParams!.id, conversationId);
209
+ log.info(
210
+ { surfaceId: pathParams!.id, conversationId },
211
+ "Linked document to conversation",
212
+ );
213
+ return { success: true as const };
214
+ },
215
+ },
216
+
184
217
  {
185
218
  operationId: "exportDocumentPDF",
186
219
  endpoint: "documents/:id/pdf",
@@ -29,6 +29,7 @@ import {
29
29
  suggestedPromptSchema,
30
30
  } from "../../home/feed-types.js";
31
31
  import { patchFeedItemStatus, readHomeFeed } from "../../home/feed-writer.js";
32
+ import { getPersonalizedGreeting } from "../../home/home-greeting.js";
32
33
  import { getSuggestedPrompts } from "../../home/suggested-prompts.js";
33
34
  import {
34
35
  addMessage,
@@ -123,14 +124,16 @@ export async function handleGetHomeFeed({
123
124
  const filtered = feed.items;
124
125
 
125
126
  const now = new Date();
127
+
128
+ const personalizedGreeting = getPersonalizedGreeting();
129
+ const suggestedPrompts = await getSuggestedPrompts();
130
+
126
131
  const contextBanner = {
127
- greeting: computeGreeting(now),
132
+ greeting: personalizedGreeting ?? computeGreeting(now),
128
133
  timeAwayLabel: formatRelativeTime(timeAwaySeconds),
129
134
  newCount: filtered.filter((i) => i.status === "new").length,
130
135
  };
131
136
 
132
- const suggestedPrompts = await getSuggestedPrompts();
133
-
134
137
  log.debug(
135
138
  {
136
139
  timeAwayBucket: timeAwayBucket(timeAwaySeconds),
@@ -105,7 +105,7 @@ function handleHostAppControlResult({ body, headers }: RouteHandlerArgs) {
105
105
  });
106
106
  }
107
107
 
108
- const interaction = pendingInteractions.resolve(requestId)!;
108
+ const interaction = pendingInteractions.resolve(requestId, "answered")!;
109
109
  const conversation = findConversation(interaction.conversationId);
110
110
  if (!conversation) {
111
111
  return { accepted: true };
@@ -10,6 +10,7 @@ import {
10
10
  markTargetInvalidated,
11
11
  publishCdpEvent,
12
12
  } from "../../browser-session/events.js";
13
+ import { clearPinnedTabByTabId } from "../../tools/browser/pinned-tabs.js";
13
14
  import {
14
15
  enforceSameActorOrThrow,
15
16
  SAME_ACTOR_FORBIDDEN_DESCRIPTION,
@@ -149,7 +150,7 @@ export function resolveHostBrowserResultByRequestId(
149
150
  const normalizedContent = typeof content === "string" ? content : "";
150
151
  const normalizedIsError = typeof isError === "boolean" ? isError : false;
151
152
 
152
- const interaction = pendingInteractions.resolve(requestId);
153
+ const interaction = pendingInteractions.resolve(requestId, "answered");
153
154
  interaction?.rpcResolve?.({
154
155
  content: normalizedContent,
155
156
  isError: normalizedIsError,
@@ -239,6 +240,12 @@ export function resolveHostBrowserSessionInvalidated(frame: {
239
240
  targetId,
240
241
  typeof reason === "string" ? reason : undefined,
241
242
  );
243
+ // Clear any pinned-tab entries pointing at this target so that
244
+ // subsequent `navigate` calls don't try to route to a dead tab.
245
+ // Without this, a user closing the pinned tab manually would see
246
+ // their next browser command fail with a `cdp_session_not_found`
247
+ // until the daemon process restarts.
248
+ clearPinnedTabByTabId(targetId);
242
249
  }
243
250
 
244
251
  return { ok: true };
@@ -11,10 +11,12 @@ import { getCpuLimit, getIsPlatform } from "../../config/env-registry.js";
11
11
  import { parseIdentityFields } from "../../daemon/handlers/identity.js";
12
12
  import { getProfilerRuntimeStatus } from "../../daemon/profiler-run-store.js";
13
13
  import { getMaxMigrationVersion } from "../../memory/migrations/registry.js";
14
+ import { getCesClient } from "../../security/secure-keys.js";
14
15
  import {
15
16
  getDiskUsageInfo,
16
17
  parseK8sMemoryBytes,
17
18
  } from "../../util/disk-usage.js";
19
+ import { getLogger } from "../../util/logger.js";
18
20
  import { getWorkspacePromptPath } from "../../util/platform.js";
19
21
  import { APP_VERSION } from "../../version.js";
20
22
  import { resolveHatchedAtReadOnly } from "../../workspace/hatched-date.js";
@@ -323,6 +325,8 @@ function getDetailedHealth() {
323
325
  // Profiler status is non-critical — omit on error
324
326
  }
325
327
 
328
+ const cesClient = getCesClient();
329
+
326
330
  return {
327
331
  status: "healthy",
328
332
  timestamp: new Date().toISOString(),
@@ -335,6 +339,9 @@ function getDetailedHealth() {
335
339
  lastWorkspaceMigrationId:
336
340
  getLastWorkspaceMigrationId(WORKSPACE_MIGRATIONS),
337
341
  },
342
+ ces: {
343
+ connected: cesClient?.isReady() ?? false,
344
+ },
338
345
  ...(profiler ? { profiler } : {}),
339
346
  };
340
347
  }
@@ -344,6 +351,15 @@ export function handleDetailedHealth(): Response {
344
351
  }
345
352
 
346
353
  export function handleReadyz(): Response {
354
+ const cesClient = getCesClient();
355
+ if (!cesClient?.isReady()) {
356
+ // TODO: Return 503 once we confirm via logs that this won't cause
357
+ // regressions in the K8s readinessProbe.
358
+ getLogger("health").warn(
359
+ { reason: cesClient ? "ces_not_ready" : "ces_unavailable" },
360
+ "CES not ready — pod would be unready if 503 were enabled",
361
+ );
362
+ }
347
363
  return Response.json({ status: "ok" });
348
364
  }
349
365
 
@@ -423,6 +439,10 @@ const profilerStatusSchema = z.object({
423
439
  lastCompletedRun: profilerLastCompletedRunSchema.nullable(),
424
440
  });
425
441
 
442
+ const cesHealthSchema = z.object({
443
+ connected: z.boolean(),
444
+ });
445
+
426
446
  const detailedHealthSchema = z.object({
427
447
  status: z.string(),
428
448
  timestamp: z.string(),
@@ -431,6 +451,7 @@ const detailedHealthSchema = z.object({
431
451
  memory: z.object({}).passthrough(),
432
452
  cpu: z.object({}).passthrough(),
433
453
  migrations: z.object({}).passthrough(),
454
+ ces: cesHealthSchema,
434
455
  profiler: profilerStatusSchema.optional(),
435
456
  });
436
457