@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
@@ -58,6 +58,7 @@ import {
58
58
  migrateCanonicalGuardianRequesterChatId,
59
59
  migrateCapabilityCardColumns,
60
60
  migrateChannelInboundDeliveredSegments,
61
+ migrateChannelInboundDeliveryAttempts,
61
62
  migrateChannelInteractionColumns,
62
63
  migrateContactChannelsAccessFields,
63
64
  migrateContactChannelsTypeChatIdIndex,
@@ -65,13 +66,16 @@ import {
65
66
  migrateContactsNotesColumn,
66
67
  migrateContactsRolePrincipal,
67
68
  migrateContactsUserFileColumn,
69
+ migrateConversationCleanedAt,
68
70
  migrateConversationForkLineage,
69
71
  migrateConversationHostAccess,
70
72
  migrateConversationInferenceProfileSession,
73
+ migrateConversationLastNotifiedProfile,
71
74
  migrateConversationsArchivedAt,
72
75
  migrateConversationsLastMessageAt,
73
76
  migrateConversationsThreadTypeIndex,
74
77
  migrateCreateConversationGraphMemoryState,
78
+ migrateCreateDocumentComments,
75
79
  migrateCreateDocumentConversations,
76
80
  migrateCreateMemoryGraphNodeEdits,
77
81
  migrateCreateMemoryGraphTables,
@@ -96,6 +100,7 @@ import {
96
100
  migrateDropSetupSkillIdColumn,
97
101
  migrateDropSimplifiedMemory,
98
102
  migrateDropUsageCompositeIndexes,
103
+ migrateExternalConversationBindingChatName,
99
104
  migrateExternalConversationBindingThreadId,
100
105
  migrateFkCascadeRebuilds,
101
106
  migrateGuardianActionFollowup,
@@ -122,6 +127,7 @@ import {
122
127
  migrateMemoryRecallLogsQueryContext,
123
128
  migrateMemoryRetrospectiveState,
124
129
  migrateMemoryV2ActivationLogs,
130
+ migrateMemoryV2InjectionEvents,
125
131
  migrateMessageBookmarks,
126
132
  migrateMessagesConversationCreatedAtIndex,
127
133
  migrateMessagesFtsBackfill,
@@ -144,6 +150,7 @@ import {
144
150
  migrateOAuthProvidersScopeSeparator,
145
151
  migrateOAuthProvidersTokenAuthMethodDefault,
146
152
  migrateOAuthProvidersTokenExchangeBodyFormat,
153
+ migrateOnboardingEventsPriorAssistants,
147
154
  migrateProviderConnectionBaseUrlAndModels,
148
155
  migrateProviderConnectionStatusLabel,
149
156
  migrateReminderRoutingIntent,
@@ -174,6 +181,7 @@ import {
174
181
  migrateSchemaIndexesAndColumns,
175
182
  migrateScrubCorruptedImageAttachments,
176
183
  migrateSlackCompactionWatermark,
184
+ migrateStripBaseUrlNonOpenaiCompatible,
177
185
  migrateStripIntegrationPrefixFromProviderKeys,
178
186
  migrateStripPlaceholderSentinelsFromMessages,
179
187
  migrateStripThinkingFromConsolidated,
@@ -436,6 +444,14 @@ export function initializeDb(): void {
436
444
  migrateProviderConnectionBaseUrlAndModels,
437
445
  migrateA2ATasks,
438
446
  migrateLlmRequestLogAgentLoopExitReason,
447
+ migrateCreateDocumentComments,
448
+ migrateExternalConversationBindingChatName,
449
+ migrateChannelInboundDeliveryAttempts,
450
+ migrateMemoryV2InjectionEvents,
451
+ migrateConversationLastNotifiedProfile,
452
+ migrateStripBaseUrlNonOpenaiCompatible,
453
+ migrateOnboardingEventsPriorAssistants,
454
+ migrateConversationCleanedAt,
439
455
  ];
440
456
 
441
457
  // Run each migration step, catching and logging individual failures so one
@@ -313,6 +313,47 @@ export function storePayload(
313
313
  .run();
314
314
  }
315
315
 
316
+ /**
317
+ * Persist the assistant reply row generated for an inbound event so callback
318
+ * delivery retries target that exact response instead of the latest message in
319
+ * the conversation.
320
+ */
321
+ export function storeReplyMessageId(
322
+ eventId: string,
323
+ replyMessageId: string,
324
+ ): void {
325
+ const db = getDb();
326
+ const row = db
327
+ .select({ rawPayload: channelInboundEvents.rawPayload })
328
+ .from(channelInboundEvents)
329
+ .where(eq(channelInboundEvents.id, eventId))
330
+ .get();
331
+ if (!row?.rawPayload) return;
332
+
333
+ let payload: Record<string, unknown>;
334
+ try {
335
+ const parsed = JSON.parse(row.rawPayload) as unknown;
336
+ if (
337
+ parsed === null ||
338
+ typeof parsed !== "object" ||
339
+ Array.isArray(parsed)
340
+ ) {
341
+ return;
342
+ }
343
+ payload = parsed as Record<string, unknown>;
344
+ } catch {
345
+ return;
346
+ }
347
+
348
+ db.update(channelInboundEvents)
349
+ .set({
350
+ rawPayload: JSON.stringify({ ...payload, replyMessageId }),
351
+ updatedAt: Date.now(),
352
+ })
353
+ .where(eq(channelInboundEvents.id, eventId))
354
+ .run();
355
+ }
356
+
316
357
  /**
317
358
  * Clear a previously stored payload. Used when the ingress check
318
359
  * detects secret-bearing content — the payload must not remain on disk.
@@ -6,7 +6,7 @@
6
6
  * retryable and dead-lettered events, and replaying dead letters.
7
7
  */
8
8
 
9
- import { and, eq, lte } from "drizzle-orm";
9
+ import { and, eq, lte, or } from "drizzle-orm";
10
10
 
11
11
  import { getDb } from "./db-connection.js";
12
12
  import {
@@ -44,6 +44,7 @@ export function acknowledgeDelivery(
44
44
  db.update(channelInboundEvents)
45
45
  .set({
46
46
  deliveryStatus: "delivered",
47
+ retryAfter: null,
47
48
  updatedAt: now,
48
49
  })
49
50
  .where(eq(channelInboundEvents.id, existing.id))
@@ -61,6 +62,23 @@ export function markProcessed(eventId: string): void {
61
62
  .run();
62
63
  }
63
64
 
65
+ /** Mark an event's outbound callback delivery as complete. */
66
+ export function markDeliveryDelivered(eventId: string): void {
67
+ const db = getDb();
68
+ db.update(channelInboundEvents)
69
+ .set({
70
+ deliveryStatus: "delivered",
71
+ retryAfter: null,
72
+ updatedAt: Date.now(),
73
+ })
74
+ .where(eq(channelInboundEvents.id, eventId))
75
+ .run();
76
+ }
77
+
78
+ function errorMessage(err: unknown): string {
79
+ return err instanceof Error ? err.message : String(err);
80
+ }
81
+
64
82
  /**
65
83
  * Record a processing failure. Classifies the error to decide whether
66
84
  * the event should be retried (status='failed') or dead-lettered
@@ -79,7 +97,7 @@ export function recordProcessingFailure(eventId: string, err: unknown): void {
79
97
 
80
98
  const attempts = (row?.attempts ?? 0) + 1;
81
99
  const category = classifyError(err);
82
- const errorMsg = err instanceof Error ? err.message : String(err);
100
+ const errorMsg = errorMessage(err);
83
101
 
84
102
  if (category === "fatal" || attempts >= RETRY_MAX_ATTEMPTS) {
85
103
  db.update(channelInboundEvents)
@@ -107,6 +125,51 @@ export function recordProcessingFailure(eventId: string, err: unknown): void {
107
125
  }
108
126
  }
109
127
 
128
+ /**
129
+ * Record an outbound callback delivery failure without changing the processing
130
+ * status. Delivery uses its own retry budget so a turn that needed processing
131
+ * retries still gets a full delivery retry window.
132
+ */
133
+ export function recordDeliveryFailure(eventId: string, err: unknown): void {
134
+ const db = getDb();
135
+ const now = Date.now();
136
+
137
+ const row = db
138
+ .select({ attempts: channelInboundEvents.deliveryAttempts })
139
+ .from(channelInboundEvents)
140
+ .where(eq(channelInboundEvents.id, eventId))
141
+ .get();
142
+
143
+ const attempts = (row?.attempts ?? 0) + 1;
144
+ const category = classifyError(err);
145
+ const errorMsg = errorMessage(err);
146
+
147
+ if (category === "fatal" || attempts >= RETRY_MAX_ATTEMPTS) {
148
+ db.update(channelInboundEvents)
149
+ .set({
150
+ deliveryStatus: "dead_letter",
151
+ deliveryAttempts: attempts,
152
+ lastProcessingError: errorMsg,
153
+ retryAfter: null,
154
+ updatedAt: now,
155
+ })
156
+ .where(eq(channelInboundEvents.id, eventId))
157
+ .run();
158
+ } else {
159
+ const delay = retryDelayForAttempt(attempts);
160
+ db.update(channelInboundEvents)
161
+ .set({
162
+ deliveryStatus: "failed",
163
+ deliveryAttempts: attempts,
164
+ lastProcessingError: errorMsg,
165
+ retryAfter: now + delay,
166
+ updatedAt: now,
167
+ })
168
+ .where(eq(channelInboundEvents.id, eventId))
169
+ .run();
170
+ }
171
+ }
172
+
110
173
  /**
111
174
  * Mark an event as failed with a specific error message, bypassing error
112
175
  * classification. Use this when the failure reason is known and the event
@@ -180,6 +243,38 @@ export function getRetryableEvents(limit = 20): Array<{
180
243
  .all();
181
244
  }
182
245
 
246
+ /** Fetch callback deliveries eligible for retry without rerunning processing. */
247
+ export function getRetryableDeliveryEvents(limit = 20): Array<{
248
+ id: string;
249
+ conversationId: string;
250
+ messageId: string | null;
251
+ processingAttempts: number;
252
+ rawPayload: string | null;
253
+ deliveredSegmentCount: number;
254
+ }> {
255
+ const db = getDb();
256
+ const now = Date.now();
257
+ return db
258
+ .select({
259
+ id: channelInboundEvents.id,
260
+ conversationId: channelInboundEvents.conversationId,
261
+ messageId: channelInboundEvents.messageId,
262
+ processingAttempts: channelInboundEvents.processingAttempts,
263
+ rawPayload: channelInboundEvents.rawPayload,
264
+ deliveredSegmentCount: channelInboundEvents.deliveredSegmentCount,
265
+ })
266
+ .from(channelInboundEvents)
267
+ .where(
268
+ and(
269
+ eq(channelInboundEvents.processingStatus, "processed"),
270
+ eq(channelInboundEvents.deliveryStatus, "failed"),
271
+ lte(channelInboundEvents.retryAfter, now),
272
+ ),
273
+ )
274
+ .limit(limit)
275
+ .all();
276
+ }
277
+
183
278
  /** Fetch dead-lettered events. */
184
279
  export function getDeadLetterEvents(): Array<{
185
280
  id: string;
@@ -204,7 +299,15 @@ export function getDeadLetterEvents(): Array<{
204
299
  createdAt: channelInboundEvents.createdAt,
205
300
  })
206
301
  .from(channelInboundEvents)
207
- .where(eq(channelInboundEvents.processingStatus, "dead_letter"))
302
+ .where(
303
+ or(
304
+ eq(channelInboundEvents.processingStatus, "dead_letter"),
305
+ and(
306
+ eq(channelInboundEvents.processingStatus, "processed"),
307
+ eq(channelInboundEvents.deliveryStatus, "dead_letter"),
308
+ ),
309
+ ),
310
+ )
208
311
  .all();
209
312
  }
210
313
 
@@ -218,27 +321,50 @@ export function replayDeadLetters(eventIds: string[]): number {
218
321
  let count = 0;
219
322
  for (const id of eventIds) {
220
323
  const existing = db
221
- .select({ id: channelInboundEvents.id })
324
+ .select({
325
+ id: channelInboundEvents.id,
326
+ processingStatus: channelInboundEvents.processingStatus,
327
+ deliveryStatus: channelInboundEvents.deliveryStatus,
328
+ })
222
329
  .from(channelInboundEvents)
223
330
  .where(
224
331
  and(
225
332
  eq(channelInboundEvents.id, id),
226
- eq(channelInboundEvents.processingStatus, "dead_letter"),
333
+ or(
334
+ eq(channelInboundEvents.processingStatus, "dead_letter"),
335
+ and(
336
+ eq(channelInboundEvents.processingStatus, "processed"),
337
+ eq(channelInboundEvents.deliveryStatus, "dead_letter"),
338
+ ),
339
+ ),
227
340
  ),
228
341
  )
229
342
  .get();
230
343
  if (!existing) continue;
231
344
 
232
- db.update(channelInboundEvents)
233
- .set({
234
- processingStatus: "failed",
235
- processingAttempts: 0,
236
- lastProcessingError: null,
237
- retryAfter: now,
238
- updatedAt: now,
239
- })
240
- .where(eq(channelInboundEvents.id, id))
241
- .run();
345
+ if (existing.processingStatus === "dead_letter") {
346
+ db.update(channelInboundEvents)
347
+ .set({
348
+ processingStatus: "failed",
349
+ processingAttempts: 0,
350
+ lastProcessingError: null,
351
+ retryAfter: now,
352
+ updatedAt: now,
353
+ })
354
+ .where(eq(channelInboundEvents.id, id))
355
+ .run();
356
+ } else {
357
+ db.update(channelInboundEvents)
358
+ .set({
359
+ deliveryStatus: "failed",
360
+ deliveryAttempts: 0,
361
+ lastProcessingError: null,
362
+ retryAfter: now,
363
+ updatedAt: now,
364
+ })
365
+ .where(eq(channelInboundEvents.id, id))
366
+ .run();
367
+ }
242
368
  count++;
243
369
  }
244
370
  return count;
@@ -7,7 +7,7 @@
7
7
  * list APIs.
8
8
  */
9
9
 
10
- import { and, eq, inArray, isNull } from "drizzle-orm";
10
+ import { and, eq, inArray, isNull, sql } from "drizzle-orm";
11
11
 
12
12
  import { getDb } from "./db-connection.js";
13
13
  import { externalConversationBindings } from "./schema.js";
@@ -16,6 +16,7 @@ export interface ExternalConversationBinding {
16
16
  conversationId: string;
17
17
  sourceChannel: string;
18
18
  externalChatId: string;
19
+ externalChatName?: string | null;
19
20
  externalThreadId?: string | null;
20
21
  externalUserId?: string | null;
21
22
  displayName?: string | null;
@@ -30,6 +31,7 @@ export interface UpsertBindingInput {
30
31
  conversationId: string;
31
32
  sourceChannel: string;
32
33
  externalChatId: string;
34
+ externalChatName?: string | null;
33
35
  externalThreadId?: string | null;
34
36
  externalUserId?: string | null;
35
37
  displayName?: string | null;
@@ -43,6 +45,13 @@ function normalizeExternalThreadId(
43
45
  return trimmed ? trimmed : null;
44
46
  }
45
47
 
48
+ function normalizeExternalChatName(
49
+ externalChatName?: string | null,
50
+ ): string | null {
51
+ const trimmed = externalChatName?.trim();
52
+ return trimmed ? trimmed : null;
53
+ }
54
+
46
55
  /**
47
56
  * Insert or update an external conversation binding on conflict (conversationId).
48
57
  * On conflict, updates channel metadata and timestamps.
@@ -51,6 +60,7 @@ export function upsertBinding(input: UpsertBindingInput): void {
51
60
  const db = getDb();
52
61
  const now = Date.now();
53
62
  const externalThreadId = normalizeExternalThreadId(input.externalThreadId);
63
+ const externalChatName = normalizeExternalChatName(input.externalChatName);
54
64
 
55
65
  // If a stale binding exists for this channel/chat/thread tuple under a
56
66
  // different conversationId, remove it first so the unique index is not violated.
@@ -75,6 +85,7 @@ export function upsertBinding(input: UpsertBindingInput): void {
75
85
  conversationId: input.conversationId,
76
86
  sourceChannel: input.sourceChannel,
77
87
  externalChatId: input.externalChatId,
88
+ externalChatName,
78
89
  externalThreadId,
79
90
  externalUserId: input.externalUserId ?? null,
80
91
  displayName: input.displayName ?? null,
@@ -88,6 +99,9 @@ export function upsertBinding(input: UpsertBindingInput): void {
88
99
  set: {
89
100
  sourceChannel: input.sourceChannel,
90
101
  externalChatId: input.externalChatId,
102
+ externalChatName:
103
+ externalChatName ??
104
+ sql`${externalConversationBindings.externalChatName}`,
91
105
  externalThreadId,
92
106
  externalUserId: input.externalUserId ?? null,
93
107
  displayName: input.displayName ?? null,
@@ -158,6 +172,23 @@ export function upsertOutboundBinding(input: {
158
172
  .run();
159
173
  }
160
174
 
175
+ export function updateExternalChatName(
176
+ conversationId: string,
177
+ externalChatName: string,
178
+ ): void {
179
+ const db = getDb();
180
+ const trimmedName = externalChatName.trim();
181
+ if (!trimmedName) return;
182
+
183
+ db.update(externalConversationBindings)
184
+ .set({
185
+ externalChatName: trimmedName,
186
+ updatedAt: Date.now(),
187
+ })
188
+ .where(eq(externalConversationBindings.conversationId, conversationId))
189
+ .run();
190
+ }
191
+
161
192
  /**
162
193
  * Look up an external binding by conversation ID.
163
194
  */
@@ -1,3 +1,5 @@
1
+ import { join } from "node:path";
2
+
1
3
  import { getConfig } from "../config/loader.js";
2
4
  import type { AssistantConfig } from "../config/types.js";
3
5
  import {
@@ -6,6 +8,7 @@ import {
6
8
  shouldLogDiskPressureBackgroundSkip,
7
9
  } from "../daemon/disk-pressure-background-gate.js";
8
10
  import { getLogger } from "../util/logger.js";
11
+ import { getWorkspaceDir } from "../util/platform.js";
9
12
  import { getMemoryCheckpoint, setMemoryCheckpoint } from "./checkpoints.js";
10
13
  import {
11
14
  getLastScheduledCleanupEnqueueMs,
@@ -75,7 +78,10 @@ import {
75
78
  memoryV2MigrateJob,
76
79
  memoryV2ReembedJob,
77
80
  } from "./v2/backfill-jobs.js";
78
- import { memoryV2ConsolidateJob } from "./v2/consolidation-job.js";
81
+ import {
82
+ countBufferLines,
83
+ memoryV2ConsolidateJob,
84
+ } from "./v2/consolidation-job.js";
79
85
  import { memoryV2SweepJob } from "./v2/sweep-job.js";
80
86
 
81
87
  const log = getLogger("memory-jobs-worker");
@@ -739,11 +745,25 @@ export function maybeEnqueueGraphMaintenanceJobs(
739
745
  },
740
746
  ];
741
747
 
748
+ let enqueuedV2 = false;
742
749
  for (const { key, intervalMs, jobType } of schedule) {
743
750
  const lastRun = parseInt(getMemoryCheckpoint(key) ?? "0", 10);
744
751
  if (nowMs - lastRun >= intervalMs) {
745
752
  enqueueMemoryJob(jobType, {});
746
753
  setMemoryCheckpoint(key, String(nowMs));
754
+ if (jobType === "memory_v2_consolidate") enqueuedV2 = true;
755
+ }
756
+ }
757
+
758
+ const maxLines = config.memory.v2.consolidation_max_buffer_lines;
759
+ if (v2Active && !enqueuedV2 && maxLines !== null) {
760
+ const bufferPath = join(getWorkspaceDir(), "memory", "buffer.md");
761
+ if (countBufferLines(bufferPath) >= maxLines) {
762
+ enqueueMemoryJob("memory_v2_consolidate", {});
763
+ setMemoryCheckpoint(
764
+ GRAPH_MAINTENANCE_CHECKPOINTS.memoryV2Consolidate,
765
+ String(nowMs),
766
+ );
747
767
  }
748
768
  }
749
769
  }
@@ -5,9 +5,37 @@
5
5
  */
6
6
  export const MEMORY_RETROSPECTIVE_SOURCE = "memory-retrospective";
7
7
 
8
+ /**
9
+ * Sentinel value for the `source` column of fork-based memory-retrospective
10
+ * conversations (the new `memory-retrospective-fork` flag path). Distinct
11
+ * from MEMORY_RETROSPECTIVE_SOURCE so dedup can scope its message scan to the
12
+ * post-fork tail — fork-kind rows carry the full source prefix and would
13
+ * otherwise pollute prior-remember dedup with source-inline `remember` calls.
14
+ */
15
+ export const MEMORY_RETROSPECTIVE_FORK_SOURCE = "memory-retrospective-fork";
16
+
17
+ /**
18
+ * Union of both retrospective source sentinels. Use when looking up the most
19
+ * recent retrospective for a source conversation (either kind is valid) or
20
+ * when filtering retrospective bg conversations out of recursion queries.
21
+ */
22
+ export const MEMORY_RETROSPECTIVE_SOURCES: readonly string[] = [
23
+ MEMORY_RETROSPECTIVE_SOURCE,
24
+ MEMORY_RETROSPECTIVE_FORK_SOURCE,
25
+ ];
26
+
8
27
  /**
9
28
  * Dedicated `group_id` value for memory-retrospective background
10
29
  * conversations. Placed under `system:background` alongside auto-analysis,
11
30
  * heartbeat, and filing conversations.
12
31
  */
13
32
  export const MEMORY_RETROSPECTIVE_GROUP_ID = "system:background";
33
+
34
+ /**
35
+ * `metadata.kind` value stamped on the user-role instruction message that
36
+ * fork-based retrospectives append to the forked conversation. Used purely
37
+ * for observability — operators inspecting a retrospective fork's history
38
+ * can tell the user-role message apart from a real user turn.
39
+ */
40
+ export const MEMORY_RETROSPECTIVE_INSTRUCTION_KIND =
41
+ "memory_retrospective_instruction";
@@ -20,7 +20,7 @@ import {
20
20
  import { getLogger } from "../util/logger.js";
21
21
  import { getConversationSource } from "./conversation-crud.js";
22
22
  import { upsertMemoryRetrospectiveJob } from "./jobs-store.js";
23
- import { MEMORY_RETROSPECTIVE_SOURCE } from "./memory-retrospective-constants.js";
23
+ import { MEMORY_RETROSPECTIVE_SOURCES } from "./memory-retrospective-constants.js";
24
24
 
25
25
  const log = getLogger("memory-retrospective-enqueue");
26
26
 
@@ -67,7 +67,8 @@ export function enqueueMemoryRetrospectiveIfEnabled(args: {
67
67
  export function isMemoryRetrospectiveConversation(
68
68
  conversationId: string,
69
69
  ): boolean {
70
- return getConversationSource(conversationId) === MEMORY_RETROSPECTIVE_SOURCE;
70
+ const source = getConversationSource(conversationId);
71
+ return source !== null && MEMORY_RETROSPECTIVE_SOURCES.includes(source);
71
72
  }
72
73
 
73
74
  /**