@vellumai/assistant 0.12.1-dev.202609141913.5e16607 → 0.12.1-staging.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (439) hide show
  1. package/AGENTS.md +0 -4
  2. package/ARCHITECTURE.md +12 -11
  3. package/docs/architecture/turn-actor.md +8 -15
  4. package/docs/guardian-request-flow.md +0 -16
  5. package/openapi.yaml +49 -291
  6. package/package.json +1 -1
  7. package/src/__tests__/always-loaded-tools-guard.test.ts +10 -18
  8. package/src/__tests__/app-compiler.test.ts +0 -6
  9. package/src/__tests__/app-control-tool-schemas.test.ts +2 -5
  10. package/src/__tests__/app-dir-path-guard.test.ts +3 -1
  11. package/src/__tests__/app-source-watcher.test.ts +218 -0
  12. package/src/{calls/__tests__ → __tests__}/call-controller.test.ts +82 -503
  13. package/src/__tests__/computer-use-skill-proxy-bridge.test.ts +2 -5
  14. package/src/__tests__/computer-use-tools.test.ts +5 -17
  15. package/src/__tests__/config-schema-cmd.test.ts +2 -2
  16. package/src/__tests__/config-schema.test.ts +29 -28
  17. package/src/__tests__/config-watcher-skill-reseed.test.ts +359 -0
  18. package/src/__tests__/config-watcher.test.ts +8 -23
  19. package/src/__tests__/connection-model-compat.test.ts +2 -2
  20. package/src/__tests__/conversation-key-store-disk-view.test.ts +1 -1
  21. package/src/__tests__/conversation-pairing.test.ts +0 -26
  22. package/src/__tests__/conversation-process-app-control-preactivation.test.ts +10 -4
  23. package/src/__tests__/conversation-queue.test.ts +207 -48
  24. package/src/__tests__/conversation-retry-discard.test.ts +1 -54
  25. package/src/__tests__/conversation-skill-tools.test.ts +0 -27
  26. package/src/__tests__/conversation-surfaces-app-control.test.ts +3 -8
  27. package/src/__tests__/conversation-surfaces-task-progress.test.ts +0 -67
  28. package/src/__tests__/conversation-title-service.test.ts +10 -14
  29. package/src/__tests__/conversation-tool-setup-app-refresh.test.ts +5 -3
  30. package/src/__tests__/conversation-tool-setup-attribution.test.ts +0 -51
  31. package/src/__tests__/credential-record-retire.test.ts +1 -171
  32. package/src/__tests__/credential-routes.test.ts +3 -212
  33. package/src/__tests__/credential-security-invariants.test.ts +2 -4
  34. package/src/__tests__/cu-unified-flow.test.ts +2 -8
  35. package/src/__tests__/document-sync-tags.test.ts +0 -25
  36. package/src/__tests__/drain-kick-guard.test.ts +2 -0
  37. package/src/__tests__/drain-requeue-on-contention.test.ts +6 -0
  38. package/src/__tests__/evict-conversations-for-reload.test.ts +1 -1
  39. package/src/__tests__/host-bash-proxy.test.ts +45 -26
  40. package/src/__tests__/host-browser-proxy.test.ts +17 -6
  41. package/src/__tests__/host-file-proxy-targeted.test.ts +0 -23
  42. package/src/__tests__/host-file-proxy.test.ts +23 -11
  43. package/src/__tests__/host-transfer-proxy-targeted.test.ts +9 -30
  44. package/src/__tests__/llm-catalog-parity.test.ts +0 -25
  45. package/src/__tests__/mcp-auth-routes.test.ts +9 -6
  46. package/src/__tests__/mcp-config-secret-boundary.test.ts +136 -78
  47. package/src/__tests__/mcp-health-check.test.ts +11 -8
  48. package/src/__tests__/mcp-list-plugin-servers.test.ts +10 -8
  49. package/src/{calls/__tests__ → __tests__}/media-stream-audio-transcode.test.ts +1 -1
  50. package/src/{calls/__tests__ → __tests__}/media-stream-output.test.ts +8 -37
  51. package/src/{calls/__tests__ → __tests__}/media-stream-parser.test.ts +1 -1
  52. package/src/{calls/__tests__ → __tests__}/media-stream-server-integration.test.ts +57 -150
  53. package/src/{calls/__tests__ → __tests__}/media-stream-stt-session.test.ts +5 -5
  54. package/src/{calls/__tests__ → __tests__}/media-turn-detector.test.ts +1 -1
  55. package/src/__tests__/messages-after-tiebreaker.test.ts +0 -91
  56. package/src/__tests__/messages-read-boundary-guard.test.ts +1 -1
  57. package/src/__tests__/messaging-send-tool.test.ts +548 -355
  58. package/src/__tests__/model-intents.test.ts +0 -3
  59. package/src/__tests__/notification-vellum-adapter.test.ts +2 -85
  60. package/src/__tests__/outlook-messaging-provider.test.ts +6 -6
  61. package/src/__tests__/platform-callback-registration.test.ts +16 -8
  62. package/src/__tests__/platform-client-verify-credential.test.ts +0 -2
  63. package/src/__tests__/plugin-import-boundary-guard.test.ts +0 -13
  64. package/src/__tests__/script-proxy-certs.test.ts +0 -35
  65. package/src/__tests__/skill-feature-flags-integration.test.ts +1 -1
  66. package/src/__tests__/skill-feature-flags.test.ts +2 -2
  67. package/src/__tests__/speaker-identification.test.ts +56 -0
  68. package/src/__tests__/subagent-tool-gate-mode.test.ts +3 -19
  69. package/src/__tests__/subagent-tools.test.ts +2 -3
  70. package/src/__tests__/telephony-tts-guard.test.ts +3 -38
  71. package/src/__tests__/vellum-self-knowledge-inline-command.test.ts +0 -4
  72. package/src/{calls/__tests__/voice-session-bridge-turn-flow.test.ts → __tests__/voice-session-bridge.test.ts} +12 -20
  73. package/src/__tests__/watch-retro-tool-availability.test.ts +17 -8
  74. package/src/__tests__/workspace-git-service.test.ts +0 -26
  75. package/src/acp/__tests__/agent-process.test.ts +4 -258
  76. package/src/acp/__tests__/auth-required.test.ts +0 -96
  77. package/src/acp/__tests__/client-handler.test.ts +2 -90
  78. package/src/acp/__tests__/session-manager-persistence.test.ts +1 -5
  79. package/src/acp/__tests__/session-manager-resume.test.ts +6 -270
  80. package/src/acp/__tests__/session-manager-usage.test.ts +2 -4
  81. package/src/acp/__tests__/session-manager.test.ts +4 -895
  82. package/src/acp/agent-process.test.ts +1 -4
  83. package/src/acp/agent-process.ts +9 -94
  84. package/src/acp/auth-required.ts +1 -50
  85. package/src/acp/auto-install.test.ts +7 -9
  86. package/src/acp/client-handler.ts +3 -16
  87. package/src/acp/resolve-agent.test.ts +6 -220
  88. package/src/acp/resolve-agent.ts +23 -88
  89. package/src/acp/session-manager.test.ts +3 -196
  90. package/src/acp/session-manager.ts +18 -441
  91. package/src/acp/types.ts +5 -50
  92. package/src/api/events/app-files-changed.ts +3 -4
  93. package/src/api/events/notification-intent.ts +0 -2
  94. package/src/api/index.ts +0 -6
  95. package/src/apps/app-store.ts +1 -1
  96. package/src/bundler/app-compiler.ts +0 -15
  97. package/src/calls/__tests__/voice-control-protocol.test.ts +25 -58
  98. package/src/calls/__tests__/voice-session-bridge.test.ts +1 -37
  99. package/src/calls/__tests__/voice-triage-escalate.test.ts +0 -105
  100. package/src/calls/call-constants.ts +4 -24
  101. package/src/calls/call-controller.ts +199 -499
  102. package/src/calls/call-transport.ts +0 -16
  103. package/src/calls/media-stream-output.ts +0 -32
  104. package/src/calls/media-stream-server.ts +30 -82
  105. package/src/calls/media-stream-stt-session.ts +0 -15
  106. package/src/calls/resolve-call-tts-provider.ts +2 -33
  107. package/src/calls/speaker-identification.ts +233 -0
  108. package/src/calls/tts-call-strategy.ts +5 -9
  109. package/src/calls/types.ts +0 -2
  110. package/src/calls/voice-control-protocol.ts +21 -53
  111. package/src/calls/voice-session-bridge.ts +46 -59
  112. package/src/calls/voice-triage-escalate.ts +56 -175
  113. package/src/cli/commands/apps.help.ts +13 -67
  114. package/src/cli/commands/apps.ts +0 -183
  115. package/src/cli/commands/bash.help.ts +13 -8
  116. package/src/cli/commands/bash.ts +25 -7
  117. package/src/cli/commands/channels/index.help.ts +2 -70
  118. package/src/cli/commands/channels/index.ts +3 -16
  119. package/src/cli/commands/credentials.help.ts +2 -6
  120. package/src/cli/commands/credentials.ts +2 -2
  121. package/src/cli/commands/mcp.help.ts +8 -8
  122. package/src/cli/commands/mcp.ts +1 -1
  123. package/src/cli/commands/roadmap.help.ts +1 -5
  124. package/src/cli/commands/roadmap.ts +1 -1
  125. package/src/cli/lib/bundled-marketplace.json +90 -103
  126. package/src/config/__tests__/default-profile-catalog.test.ts +0 -22
  127. package/src/config/__tests__/memory-retrospective-schema.test.ts +1 -15
  128. package/src/config/__tests__/platform-rehydration.test.ts +9 -99
  129. package/src/config/acp-defaults.test.ts +3 -13
  130. package/src/config/acp-defaults.ts +6 -23
  131. package/src/config/acp-schema.ts +2 -30
  132. package/src/config/bundled-skills/acp/SKILL.md +14 -22
  133. package/src/config/bundled-skills/acp/TOOLS.json +1 -5
  134. package/src/config/bundled-skills/app-builder/SKILL.md +9 -12
  135. package/src/config/bundled-skills/app-builder/references/CUSTOM_ROUTES.md +1 -1
  136. package/src/config/bundled-skills/messaging/SKILL.md +3 -3
  137. package/src/config/bundled-skills/messaging/TOOLS.json +3 -3
  138. package/src/config/bundled-skills/messaging/tools/messaging-send.ts +139 -67
  139. package/src/config/bundled-skills/phone-calls/references/TRANSCRIPTS.md +1 -1
  140. package/src/config/bundled-skills/schedule/SKILL.md +4 -3
  141. package/src/config/bundled-skills/screen-annotation/SKILL.md +1 -8
  142. package/src/config/bundled-skills/screen-annotation/tools/screen-annotation.test.ts +1 -4
  143. package/src/config/bundled-skills/skill-management/TOOLS.json +2 -2
  144. package/src/config/default-profile-catalog.ts +1 -1
  145. package/src/config/env.ts +2 -2
  146. package/src/config/feature-flag-registry.json +12 -24
  147. package/src/config/loader.ts +0 -1
  148. package/src/config/memory-v3-gate.test.ts +0 -31
  149. package/src/config/memory-v3-gate.ts +16 -20
  150. package/src/config/platform-rehydration.ts +27 -11
  151. package/src/config/schema.ts +2 -2
  152. package/src/config/schemas/__tests__/live-voice.test.ts +158 -8
  153. package/src/config/schemas/calls.ts +28 -1
  154. package/src/config/schemas/live-voice.ts +173 -1
  155. package/src/config/schemas/mcp.ts +1 -1
  156. package/src/config/schemas/memory-retrospective.ts +0 -10
  157. package/src/config/schemas/services.ts +0 -8
  158. package/src/config/schemas/skills.ts +14 -0
  159. package/src/credential-execution/process-manager.test.ts +19 -18
  160. package/src/daemon/__tests__/conversation-tool-setup.test.ts +121 -66
  161. package/src/daemon/__tests__/plugin-mcp-reconcile.test.ts +1 -4
  162. package/src/daemon/app-source-watcher.ts +218 -0
  163. package/src/daemon/config-watcher.ts +194 -13
  164. package/src/daemon/conversation-process.ts +64 -35
  165. package/src/daemon/conversation-skill-tools.ts +31 -13
  166. package/src/daemon/conversation-store.ts +1 -1
  167. package/src/daemon/conversation-surfaces.ts +8 -10
  168. package/src/daemon/conversation-tool-setup.ts +43 -37
  169. package/src/daemon/conversation.ts +3 -0
  170. package/src/daemon/host-bash-proxy.ts +12 -8
  171. package/src/daemon/host-browser-proxy.ts +1 -15
  172. package/src/daemon/host-file-proxy.ts +10 -8
  173. package/src/daemon/host-transfer-proxy.ts +18 -14
  174. package/src/daemon/lifecycle.ts +5 -0
  175. package/src/daemon/mcp-reload-service.ts +5 -5
  176. package/src/daemon/message-types/sync.ts +0 -1
  177. package/src/daemon/orphan-reaper.ts +1 -1
  178. package/src/daemon/providers-setup.ts +1 -1
  179. package/src/daemon/shutdown-handlers.ts +9 -1
  180. package/src/daemon/skill-memory-refresh.ts +0 -64
  181. package/src/daemon/tool-side-effects.ts +18 -7
  182. package/src/home/__tests__/feed-writer.test.ts +0 -22
  183. package/src/home/feed-writer.ts +2 -11
  184. package/src/hooks/types.ts +0 -33
  185. package/src/inbound/platform-callback-registration.ts +5 -4
  186. package/src/live-voice/__tests__/live-voice-metrics.test.ts +3 -0
  187. package/src/live-voice/__tests__/live-voice-progress.test.ts +15 -15
  188. package/src/live-voice/__tests__/live-voice-vad.test.ts +2 -2
  189. package/src/{calls → live-voice}/__tests__/progress-narration.test.ts +4 -4
  190. package/src/{calls → live-voice}/__tests__/progress-phrases.test.ts +1 -1
  191. package/src/live-voice/__tests__/runtime-websocket-shell.test.ts +69 -13
  192. package/src/live-voice/live-voice-session.ts +693 -213
  193. package/src/{calls → live-voice}/progress-narration.ts +2 -2
  194. package/src/live-voice/protocol.ts +2 -0
  195. package/src/mcp/__tests__/effective-config.test.ts +2 -2
  196. package/src/mcp/effective-config.ts +3 -3
  197. package/src/mcp/mcp-header-store.ts +45 -29
  198. package/src/mcp/startup.ts +4 -8
  199. package/src/messaging/provider.ts +3 -10
  200. package/src/messaging/providers/callback-routing.ts +0 -18
  201. package/src/messaging/providers/channel-transport.ts +0 -56
  202. package/src/messaging/providers/discord/transport.ts +0 -17
  203. package/src/messaging/providers/slack/__tests__/adapter-token-routing.test.ts +17 -6
  204. package/src/messaging/providers/slack/adapter.ts +44 -7
  205. package/src/messaging/providers/slack/transport.ts +0 -16
  206. package/src/messaging/providers/telegram-bot/adapter.ts +48 -1
  207. package/src/messaging/providers/telegram-bot/client.ts +26 -0
  208. package/src/messaging/providers/telegram-bot/transport.ts +0 -20
  209. package/src/messaging/providers/whatsapp/adapter.ts +48 -1
  210. package/src/messaging/providers/whatsapp/client.ts +29 -0
  211. package/src/messaging/providers/whatsapp/transport.ts +0 -18
  212. package/src/monitoring/__tests__/workspace-git-heartbeat.test.ts +0 -8
  213. package/src/notifications/__tests__/assistant-reply-producer.test.ts +0 -55
  214. package/src/notifications/__tests__/guardian-feed-projection.test.ts +2 -158
  215. package/src/notifications/__tests__/home-feed-side-effect.test.ts +3 -153
  216. package/src/notifications/__tests__/schedule-result-producer.test.ts +3 -99
  217. package/src/notifications/adapters/macos.ts +0 -3
  218. package/src/notifications/assistant-reply-producer.ts +3 -8
  219. package/src/notifications/conversation-pairing.ts +16 -36
  220. package/src/notifications/delivered-post-record.ts +1 -11
  221. package/src/notifications/guardian-feed-projection.ts +5 -125
  222. package/src/notifications/home-feed-side-effect.ts +7 -55
  223. package/src/notifications/schedule-result-producer.ts +22 -66
  224. package/src/oauth/__tests__/seed-providers-managed.test.ts +0 -54
  225. package/src/oauth/byo-connection.test.ts +0 -45
  226. package/src/oauth/byo-connection.ts +6 -36
  227. package/src/oauth/connection-resolver.test.ts +0 -73
  228. package/src/oauth/connection-resolver.ts +2 -95
  229. package/src/oauth/seed-providers.ts +0 -165
  230. package/src/outbound-proxy/certs.ts +5 -3
  231. package/src/permissions/checker.test.ts +6 -11
  232. package/src/persistence/compaction-log-store-clickhouse.ts +3 -3
  233. package/src/persistence/conversation-crud.ts +63 -71
  234. package/src/persistence/conversation-lineage.ts +4 -12
  235. package/src/persistence/conversation-title-service.ts +26 -9
  236. package/src/persistence/llm-request-log-sink-clickhouse.ts +3 -3
  237. package/src/persistence/llm-request-log-source-clickhouse.ts +3 -3
  238. package/src/persistence/message-reads.ts +0 -30
  239. package/src/persistence/migrations/157-invite-contact-id.ts +6 -18
  240. package/src/persistence/schema/memory-core.ts +0 -5
  241. package/src/platform/client.test.ts +2 -4
  242. package/src/platform/client.ts +10 -2
  243. package/src/plugin-api/constants.ts +0 -2
  244. package/src/plugin-api/index.ts +0 -1
  245. package/src/plugin-api/types.ts +0 -2
  246. package/src/plugins/defaults/index.ts +0 -2
  247. package/src/plugins/defaults/memory/__tests__/memory-retrospective-accounting.test.ts +0 -46
  248. package/src/plugins/defaults/memory/__tests__/memory-retrospective-enqueue.test.ts +5 -9
  249. package/src/plugins/defaults/memory/__tests__/memory-retrospective-job.test.ts +10 -20
  250. package/src/plugins/defaults/memory/__tests__/memory-retrospective-state.test.ts +0 -219
  251. package/src/plugins/defaults/memory/__tests__/memory-retrospective-sweep.test.ts +0 -31
  252. package/src/plugins/defaults/memory/__tests__/memory-retrospective-trigger-check.test.ts +0 -63
  253. package/src/plugins/defaults/memory/__tests__/shutdown-hook.test.ts +0 -4
  254. package/src/plugins/defaults/memory/graph/capability-seed.ts +6 -4
  255. package/src/plugins/defaults/memory/hooks/init.ts +0 -10
  256. package/src/plugins/defaults/memory/hooks/shutdown.ts +0 -2
  257. package/src/plugins/defaults/memory/jobs-worker.ts +0 -13
  258. package/src/plugins/defaults/memory/memory-retrospective-accounting.ts +60 -34
  259. package/src/plugins/defaults/memory/memory-retrospective-enqueue.ts +5 -3
  260. package/src/plugins/defaults/memory/memory-retrospective-job.ts +3 -12
  261. package/src/plugins/defaults/memory/memory-retrospective-state.ts +71 -312
  262. package/src/plugins/defaults/memory/memory-retrospective-sweep.ts +1 -2
  263. package/src/plugins/defaults/memory/memory-retrospective-trigger-check.ts +3 -5
  264. package/src/plugins/defaults/memory/startup.ts +1 -6
  265. package/src/plugins/defaults/memory/substrate/__tests__/skill-content.test.ts +9 -7
  266. package/src/plugins/defaults/memory/substrate/skill-content.ts +2 -2
  267. package/src/plugins/defaults/memory/v3/__tests__/pool-select.test.ts +0 -89
  268. package/src/plugins/defaults/memory/worker.ts +0 -6
  269. package/src/plugins/mcp-servers.ts +75 -15
  270. package/src/providers/__tests__/connection-model-compat.test.ts +3 -3
  271. package/src/providers/gemini/client.ts +23 -9
  272. package/src/providers/inference/auth.ts +3 -2
  273. package/src/providers/inference/connection-availability.ts +8 -27
  274. package/src/providers/inference/resolve-auth.ts +4 -22
  275. package/src/providers/model-catalog.ts +0 -34
  276. package/src/providers/model-intents.ts +5 -10
  277. package/src/providers/openai/__tests__/chat-completions-provider-reasoning.test.ts +18 -146
  278. package/src/providers/openai/__tests__/tool-choice-mapping.test.ts +1 -83
  279. package/src/providers/openai/chat-completions-provider.ts +78 -192
  280. package/src/providers/openai/codex-models.ts +4 -0
  281. package/src/runtime/AGENTS.md +0 -2
  282. package/src/runtime/auth/same-actor.ts +3 -38
  283. package/src/runtime/http-server.ts +151 -160
  284. package/src/runtime/routes/__tests__/acp-routes.test.ts +4 -159
  285. package/src/runtime/routes/__tests__/conversation-query-routes.test.ts +1 -108
  286. package/src/runtime/routes/__tests__/default-provider-routes.test.ts +2 -2
  287. package/src/runtime/routes/__tests__/mcp-add-default-risk.test.ts +12 -16
  288. package/src/runtime/routes/acp-routes.test.ts +0 -15
  289. package/src/runtime/routes/acp-routes.ts +9 -72
  290. package/src/runtime/routes/app-management-routes.ts +0 -73
  291. package/src/runtime/routes/app-routes.ts +1 -1
  292. package/src/runtime/routes/conversation-list-routes.ts +3 -14
  293. package/src/runtime/routes/conversation-query-routes.ts +0 -40
  294. package/src/runtime/routes/credential-routes.ts +10 -19
  295. package/src/runtime/routes/debug-bash-routes.ts +173 -0
  296. package/src/runtime/routes/diagnostics-routes.ts +3 -55
  297. package/src/runtime/routes/index.ts +2 -4
  298. package/src/runtime/routes/log-export-routes.ts +0 -2
  299. package/src/runtime/routes/mcp-auth-routes.ts +47 -39
  300. package/src/runtime/routes/migration-routes.ts +20 -6
  301. package/src/runtime/routes/platform-routes.ts +15 -18
  302. package/src/runtime/services/__tests__/conversation-serializer.test.ts +0 -28
  303. package/src/runtime/services/conversation-serializer.ts +3 -16
  304. package/src/runtime/sync/resource-sync-events.ts +1 -2
  305. package/src/schedule/worker.ts +1 -1
  306. package/src/security/ces-rpc-record-backend.ts +0 -7
  307. package/src/subagent/consult-context.ts +25 -12
  308. package/src/tools/acp/list-agents.test.ts +1 -3
  309. package/src/tools/acp/spawn.test.ts +11 -146
  310. package/src/tools/acp/spawn.ts +3 -21
  311. package/src/tools/acp/status.ts +3 -40
  312. package/src/tools/app-control/skill-proxy-bridge.ts +1 -2
  313. package/src/tools/capability-offer.test.ts +2 -22
  314. package/src/tools/capability-offer.ts +1 -16
  315. package/src/tools/computer-use/definitions.ts +2 -4
  316. package/src/tools/computer-use/skill-proxy-bridge.ts +1 -2
  317. package/src/tools/credentials/metadata-store.ts +0 -100
  318. package/src/tools/host-filesystem/edit.test.ts +1 -2
  319. package/src/tools/host-filesystem/edit.ts +2 -2
  320. package/src/tools/host-filesystem/read.test.ts +1 -2
  321. package/src/tools/host-filesystem/read.ts +2 -2
  322. package/src/tools/host-filesystem/transfer.test.ts +1 -2
  323. package/src/tools/host-filesystem/transfer.ts +2 -2
  324. package/src/tools/host-filesystem/write.test.ts +1 -2
  325. package/src/tools/host-filesystem/write.ts +2 -2
  326. package/src/tools/host-terminal/host-shell.test.ts +0 -16
  327. package/src/tools/host-terminal/host-shell.ts +20 -4
  328. package/src/tools/policy-context.ts +7 -6
  329. package/src/tools/subagent/spawn.ts +8 -5
  330. package/src/tools/watch/watch-retro-report.ts +8 -0
  331. package/src/util/__tests__/language-subtag.test.ts +1 -23
  332. package/src/util/fs-watcher-error.ts +36 -0
  333. package/src/util/language-subtag.ts +0 -16
  334. package/src/util/platform.ts +0 -8
  335. package/src/workspace/git-service.ts +54 -5
  336. package/src/workspace/migrations/registry.ts +0 -6
  337. package/scripts/smoke-desktop-window-theme.ts +0 -186
  338. package/src/__tests__/git-porcelain.test.ts +0 -47
  339. package/src/__tests__/helpers/set-workspace-mcp.ts +0 -11
  340. package/src/__tests__/message-deleted-hook-dispatch.test.ts +0 -119
  341. package/src/__tests__/resolve-app.test.ts +0 -135
  342. package/src/__tests__/service-account-token.test.ts +0 -247
  343. package/src/__tests__/source-fingerprint.test.ts +0 -184
  344. package/src/__tests__/workspace-migration-154-repair-retired-codex-gpt-5-4-model-ids.test.ts +0 -336
  345. package/src/acp/__tests__/helpers/acp-model-option.ts +0 -51
  346. package/src/acp/model-config.test.ts +0 -166
  347. package/src/acp/model-config.ts +0 -138
  348. package/src/api/events/acp-session-model-update.test.ts +0 -88
  349. package/src/api/events/acp-session-model-update.ts +0 -46
  350. package/src/apps/resolve-app.ts +0 -81
  351. package/src/apps/source-fingerprint.ts +0 -266
  352. package/src/calls/__tests__/barge-in-guard.test.ts +0 -81
  353. package/src/calls/__tests__/voice-leg-coordinator.test.ts +0 -229
  354. package/src/calls/__tests__/voice-progress-cadence.test.ts +0 -274
  355. package/src/calls/barge-in-guard.ts +0 -118
  356. package/src/calls/voice-leg-coordinator.ts +0 -189
  357. package/src/calls/voice-progress-cadence.ts +0 -423
  358. package/src/cli/commands/__tests__/apps.test.ts +0 -245
  359. package/src/cli/commands/__tests__/bash.test.ts +0 -53
  360. package/src/cli/commands/__tests__/roadmap.help.test.ts +0 -19
  361. package/src/cli/commands/channels/__tests__/send.test.ts +0 -218
  362. package/src/cli/commands/channels/send.ts +0 -128
  363. package/src/config/__tests__/platform-identity.test.ts +0 -255
  364. package/src/config/acp-agent-write.ts +0 -43
  365. package/src/config/acp-schema.test.ts +0 -81
  366. package/src/config/platform-identity.ts +0 -201
  367. package/src/config/schemas/__tests__/voice.test.ts +0 -148
  368. package/src/config/schemas/voice.ts +0 -150
  369. package/src/daemon/__tests__/skill-memory-refresh-mtime.test.ts +0 -133
  370. package/src/daemon/app-change-notify.ts +0 -45
  371. package/src/desktop/__tests__/fake-desktop.ts +0 -119
  372. package/src/desktop/desktop-chrome-policy.test.ts +0 -71
  373. package/src/desktop/desktop-chrome-policy.ts +0 -42
  374. package/src/desktop/desktop-dependencies.test.ts +0 -102
  375. package/src/desktop/desktop-dependencies.ts +0 -306
  376. package/src/desktop/desktop-feature.test.ts +0 -18
  377. package/src/desktop/desktop-feature.ts +0 -19
  378. package/src/desktop/desktop-panel-config.test.ts +0 -135
  379. package/src/desktop/desktop-panel-config.ts +0 -149
  380. package/src/desktop/desktop-session-manager.test.ts +0 -627
  381. package/src/desktop/desktop-session-manager.ts +0 -814
  382. package/src/desktop/desktop-stream-bridge.test.ts +0 -395
  383. package/src/desktop/desktop-stream-bridge.ts +0 -214
  384. package/src/desktop/desktop-wallpaper.test.ts +0 -191
  385. package/src/desktop/desktop-wallpaper.ts +0 -113
  386. package/src/desktop/desktop-window-theme.ts +0 -170
  387. package/src/i18n/AGENTS.md +0 -22
  388. package/src/i18n/__tests__/i18n.test.ts +0 -108
  389. package/src/i18n/index.ts +0 -16
  390. package/src/i18n/locales.ts +0 -93
  391. package/src/i18n/messages.ts +0 -61
  392. package/src/i18n/title.ts +0 -25
  393. package/src/mcp/__tests__/workspace-mcp-config.test.ts +0 -135
  394. package/src/mcp/spec-schema.ts +0 -111
  395. package/src/mcp/workspace-mcp-config.ts +0 -188
  396. package/src/messaging/providers/__tests__/proactive-address.test.ts +0 -95
  397. package/src/persistence/conversation-title-placeholders.ts +0 -23
  398. package/src/persistence/message-cursor.ts +0 -78
  399. package/src/persistence/migrations/__tests__/157-invite-contact-id.test.ts +0 -149
  400. package/src/plugins/defaults/memory/__tests__/memory-retrospective-cursor-backfill.test.ts +0 -118
  401. package/src/plugins/defaults/memory/__tests__/memory-retrospective-cursor-preserve.test.ts +0 -83
  402. package/src/plugins/defaults/memory/hooks/message-deleted.ts +0 -21
  403. package/src/plugins/defaults/memory/memory-retrospective-cursor-backfill.ts +0 -126
  404. package/src/plugins/defaults/memory/memory-retrospective-cursor-preserve.ts +0 -79
  405. package/src/plugins/defaults/memory/memory-retrospective-cursor.ts +0 -28
  406. package/src/plugins/defaults/memory/skill-md-mtime-poll.ts +0 -9
  407. package/src/providers/gemini-thought-signature.test.ts +0 -63
  408. package/src/providers/gemini-thought-signature.ts +0 -44
  409. package/src/providers/inference/service-account-token.ts +0 -248
  410. package/src/providers/openai/__tests__/chat-completions-provider-thought-signature.test.ts +0 -613
  411. package/src/providers/openai/__tests__/google-thought-signature.test.ts +0 -235
  412. package/src/providers/openai/google-thought-signature.ts +0 -320
  413. package/src/runtime/__tests__/channel-send.test.ts +0 -443
  414. package/src/runtime/__tests__/desktop-stream-upgrade.test.ts +0 -89
  415. package/src/runtime/__tests__/live-voice-upgrade.test.ts +0 -58
  416. package/src/runtime/__tests__/runtime-ws-test-utils.ts +0 -72
  417. package/src/runtime/__tests__/watch-stream-upgrade.test.ts +0 -59
  418. package/src/runtime/channel-send.ts +0 -316
  419. package/src/runtime/routes/__tests__/apps-refresh-route.test.ts +0 -205
  420. package/src/runtime/routes/__tests__/channel-send-routes.test.ts +0 -127
  421. package/src/runtime/routes/__tests__/dictation-cleanup-guard.test.ts +0 -107
  422. package/src/runtime/routes/channel-send-routes.ts +0 -85
  423. package/src/runtime/routes/desktop-setup-routes.test.ts +0 -74
  424. package/src/runtime/routes/desktop-setup-routes.ts +0 -35
  425. package/src/security/__tests__/ces-http-record-backend.test.ts +0 -137
  426. package/src/security/ces-http-record-backend.ts +0 -120
  427. package/src/skills/__tests__/workspace-skill-md-signature.test.ts +0 -60
  428. package/src/skills/workspace-skill-md-signature.ts +0 -50
  429. package/src/tools/acp/status.test.ts +0 -94
  430. package/src/tools/terminal/__tests__/sanitized-bash.test.ts +0 -57
  431. package/src/tools/terminal/sanitized-bash.ts +0 -105
  432. package/src/util/ca-bundle.ts +0 -13
  433. package/src/workspace/git-porcelain.ts +0 -66
  434. package/src/workspace/migrations/154-repair-retired-codex-gpt-5-4-model-ids.ts +0 -258
  435. package/src/workspace/migrations/155-move-front-model-config-to-voice.ts +0 -78
  436. package/src/workspace/migrations/156-extract-workspace-mcp-json.ts +0 -214
  437. package/src/workspace/migrations/__tests__/155-move-front-model-config-to-voice.test.ts +0 -102
  438. package/src/workspace/migrations/__tests__/156-extract-workspace-mcp-json.test.ts +0 -199
  439. /package/src/{calls → live-voice}/progress-phrases.ts +0 -0
@@ -1,95 +0,0 @@
1
- import { describe, expect, test } from "bun:test";
2
- // The addressing capability resolves a named chat into exactly what each
3
- // transport's own operations read: the callback URL `channelForCallback`
4
- // resolves and the params `deliver` consumes. Resolution is local, so these
5
- // assertions make no platform call; the tests import the transports'
6
- // modules, which pull in their provider-API senders, so the senders'
7
- // credential lookups are stubbed to keep the import inert.
8
- import { mock } from "bun:test";
9
-
10
- const actualSecureKeys = await import("../../../security/secure-keys.js");
11
- mock.module("../../../security/secure-keys.js", () => ({
12
- ...actualSecureKeys,
13
- getSecureKeyAsync: async () => null,
14
- getSecureKeyResultAsync: async () => ({ value: null }),
15
- }));
16
-
17
- const { channelForCallback } = await import("../callback-routing.js");
18
- const { discordTransport } = await import("../discord/transport.js");
19
- const { slackTransport } = await import("../slack/transport.js");
20
- const { telegramTransport } = await import("../telegram-bot/transport.js");
21
- const { whatsappTransport } = await import("../whatsapp/transport.js");
22
-
23
- describe("addressFor resolves to the channel's own routing state", () => {
24
- test("slack: a chat, optionally under a thread", () => {
25
- const room = slackTransport.addressFor!({ kind: "chat", chatId: "C123" });
26
- expect(room).toEqual({
27
- ctx: { callbackUrl: "/deliver/slack", params: {} },
28
- chatId: "C123",
29
- });
30
- const thread = slackTransport.addressFor!({
31
- kind: "chat",
32
- chatId: "C123",
33
- threadId: "1690000000.000001",
34
- });
35
- expect(thread).toEqual({
36
- ctx: {
37
- callbackUrl: "/deliver/slack?threadTs=1690000000.000001",
38
- params: { threadTs: "1690000000.000001" },
39
- },
40
- chatId: "C123",
41
- threadId: "1690000000.000001",
42
- });
43
- expect(channelForCallback(thread!.ctx.callbackUrl)).toBe("slack");
44
- });
45
-
46
- test("telegram: a chat with a topic; binds on send", () => {
47
- expect(
48
- telegramTransport.addressFor!({
49
- kind: "chat",
50
- chatId: "123",
51
- threadId: "42",
52
- }),
53
- ).toEqual({
54
- ctx: {
55
- callbackUrl: "/deliver/telegram?threadId=42",
56
- params: { threadId: "42" },
57
- },
58
- chatId: "123",
59
- threadId: "42",
60
- });
61
- expect(telegramTransport.bindsChatOnProactiveSend).toBe(true);
62
- });
63
-
64
- test("discord: a chat with a thread, which is its own channel", () => {
65
- const thread = discordTransport.addressFor!({
66
- kind: "chat",
67
- chatId: "C1",
68
- threadId: "T1",
69
- });
70
- expect(thread).toEqual({
71
- ctx: {
72
- callbackUrl: "/deliver/discord?threadId=T1",
73
- params: { threadId: "T1" },
74
- },
75
- chatId: "C1",
76
- threadId: "T1",
77
- });
78
- expect(channelForCallback(thread!.ctx.callbackUrl)).toBe("discord");
79
- expect(discordTransport.bindsChatOnProactiveSend).toBeUndefined();
80
- });
81
-
82
- test("whatsapp: the number is the chat; no threads; binds on send", () => {
83
- expect(
84
- whatsappTransport.addressFor!({
85
- kind: "chat",
86
- chatId: "12125550100",
87
- threadId: "ignored",
88
- }),
89
- ).toEqual({
90
- ctx: { callbackUrl: "/deliver/whatsapp", params: {} },
91
- chatId: "12125550100",
92
- });
93
- expect(whatsappTransport.bindsChatOnProactiveSend).toBe(true);
94
- });
95
- });
@@ -1,23 +0,0 @@
1
- import { isMessageKey } from "../i18n/index.js";
2
-
3
- const REPLACEABLE_PATTERNS = [
4
- /^Runtime:\s/,
5
- /^New Conversation$/,
6
- /^Untitled$/,
7
- /^Untitled Conversation$/,
8
- /^Generating title\.\.\.$/,
9
- ];
10
-
11
- /**
12
- * Check whether a title is a system-generated placeholder that can be
13
- * replaced or omitted without discarding user-provided copy.
14
- */
15
- export function isReplaceableTitle(title: string | null): boolean {
16
- if (title == null || title.trim() === "") {
17
- return true;
18
- }
19
- if (isMessageKey(title.trim())) {
20
- return true;
21
- }
22
- return REPLACEABLE_PATTERNS.some((pattern) => pattern.test(title));
23
- }
@@ -1,78 +0,0 @@
1
- // ---------------------------------------------------------------------------
2
- // Message cursors: the "(createdAt, id) after which" reference behind the
3
- // messages-after reads, resilient to the referenced row being deleted.
4
- // ---------------------------------------------------------------------------
5
- //
6
- // A bare message id bounds a read only while its row exists. A regenerated
7
- // reply (the conversation retry route discards the latest assistant turn) or a
8
- // retried turn deletes the row, and a caller holding just the id can no longer
9
- // say where it sat. A `MessageCursor` carries the row's `createdAt` alongside
10
- // its id, so the `(createdAt, id)` bound is reconstructible from the cursor
11
- // alone. The live row stays authoritative whenever it exists.
12
-
13
- import { eq } from "drizzle-orm";
14
-
15
- import type { LineageBound } from "./conversation-lineage.js";
16
- import { getDb } from "./db-connection.js";
17
- import { messages } from "./schema/index.js";
18
-
19
- export { messagesAfterBoundFilter } from "./conversation-lineage.js";
20
-
21
- /**
22
- * A `(createdAt, id)` message reference. `createdAt` is null when the holder
23
- * never recorded it; such a cursor bounds a read only while its row exists.
24
- */
25
- export interface MessageCursor {
26
- readonly id: string;
27
- readonly createdAt: number | null;
28
- }
29
-
30
- /**
31
- * Accepted "after" references: a message id, a {@link MessageCursor}, or
32
- * null. `null`, `""`, and a cursor whose id is `""` all mean "no lower bound".
33
- */
34
- export type MessagesAfterRef = string | MessageCursor | null;
35
-
36
- /** Where a messages-after read starts. */
37
- export type MessagesAfterBound =
38
- /** No lower bound: every row the conversation owns. */
39
- | { kind: "all" }
40
- /** Rows strictly after `bound` in `(createdAt, id)` order. */
41
- | { kind: "after"; bound: LineageBound }
42
- /**
43
- * The referenced row is gone and the reference carried no timestamp, so
44
- * the read has no defensible starting point. Readers return nothing.
45
- */
46
- | { kind: "vanished" };
47
-
48
- /** The `(createdAt, id)` bound of a single message, or null when it is gone. */
49
- export function loadMessageBound(messageId: string): LineageBound | null {
50
- const row = getDb()
51
- .select({ createdAt: messages.createdAt, id: messages.id })
52
- .from(messages)
53
- .where(eq(messages.id, messageId))
54
- .get();
55
- return row ?? null;
56
- }
57
-
58
- /**
59
- * Resolve an "after" reference to the bound a read filters on. A live row
60
- * wins; a cursor whose row is gone falls back to the `createdAt` it carries,
61
- * paired with its id so same-millisecond neighbours keep their order.
62
- */
63
- export function resolveMessagesAfterBound(
64
- after: MessagesAfterRef,
65
- ): MessagesAfterBound {
66
- const id = typeof after === "string" ? after : (after?.id ?? "");
67
- if (id === "") {
68
- return { kind: "all" };
69
- }
70
- const live = loadMessageBound(id);
71
- if (live) {
72
- return { kind: "after", bound: live };
73
- }
74
- if (typeof after === "object" && after !== null && after.createdAt !== null) {
75
- return { kind: "after", bound: { createdAt: after.createdAt, id } };
76
- }
77
- return { kind: "vanished" };
78
- }
@@ -1,149 +0,0 @@
1
- import { Database } from "bun:sqlite";
2
- import { describe, expect, test } from "bun:test";
3
-
4
- import { drizzle } from "drizzle-orm/bun-sqlite";
5
-
6
- import { getSqliteFrom } from "../../db-connection.js";
7
- import * as schema from "../../schema.js";
8
- import { migrateInviteContactId } from "../157-invite-contact-id.js";
9
- import { tableExists, tableHasColumn } from "../schema-introspection.js";
10
-
11
- function createTestDb() {
12
- const sqlite = new Database(":memory:");
13
- sqlite.exec("PRAGMA journal_mode=WAL");
14
- return drizzle(sqlite, { schema });
15
- }
16
-
17
- function columnNotNull(raw: Database, name: string): boolean {
18
- const cols = raw.query(`PRAGMA table_info(assistant_ingress_invites)`).all() as Array<{
19
- name: string;
20
- notnull: number;
21
- }>;
22
- return cols.some((c) => c.name === name && c.notnull === 1);
23
- }
24
-
25
- describe("migrateInviteContactId", () => {
26
- test("rebuilds a legacy created_by_session_id table with NOT NULL contact_id", () => {
27
- const db = createTestDb();
28
- const raw = getSqliteFrom(db);
29
- raw.exec(/*sql*/ `
30
- CREATE TABLE assistant_ingress_invites (
31
- id TEXT PRIMARY KEY,
32
- source_channel TEXT NOT NULL,
33
- token_hash TEXT NOT NULL,
34
- created_by_session_id TEXT,
35
- note TEXT,
36
- max_uses INTEGER NOT NULL DEFAULT 1,
37
- use_count INTEGER NOT NULL DEFAULT 0,
38
- expires_at INTEGER NOT NULL,
39
- status TEXT NOT NULL DEFAULT 'active',
40
- redeemed_by_external_user_id TEXT,
41
- redeemed_by_external_chat_id TEXT,
42
- redeemed_at INTEGER,
43
- expected_external_user_id TEXT,
44
- voice_code_hash TEXT,
45
- voice_code_digits INTEGER,
46
- invite_code_hash TEXT,
47
- friend_name TEXT,
48
- guardian_name TEXT,
49
- created_at INTEGER NOT NULL,
50
- updated_at INTEGER NOT NULL
51
- )
52
- `);
53
- raw.run(
54
- `INSERT INTO assistant_ingress_invites
55
- (id, source_channel, token_hash, created_by_session_id, max_uses, use_count,
56
- expires_at, status, created_at, updated_at)
57
- VALUES ('inv-keep', 'slack', 'hash-keep', 'conv-1', 1, 0, 9, 'active', 1, 1)`,
58
- );
59
- raw.exec(
60
- `ALTER TABLE assistant_ingress_invites ADD COLUMN contact_id TEXT`,
61
- );
62
- raw.run(
63
- `UPDATE assistant_ingress_invites SET contact_id = 'contact-keep' WHERE id = 'inv-keep'`,
64
- );
65
- raw.run(
66
- `INSERT INTO assistant_ingress_invites
67
- (id, source_channel, token_hash, max_uses, use_count, expires_at, status,
68
- created_at, updated_at)
69
- VALUES ('inv-drop', 'slack', 'hash-drop', 1, 0, 9, 'active', 1, 1)`,
70
- );
71
-
72
- migrateInviteContactId(db);
73
-
74
- expect(tableHasColumn(db, "assistant_ingress_invites", "contact_id")).toBe(
75
- true,
76
- );
77
- expect(columnNotNull(raw, "contact_id")).toBe(true);
78
- expect(
79
- tableHasColumn(db, "assistant_ingress_invites", "created_by_session_id"),
80
- ).toBe(true);
81
- const rows = raw
82
- .query(`SELECT id, contact_id FROM assistant_ingress_invites ORDER BY id`)
83
- .all() as Array<{ id: string; contact_id: string }>;
84
- expect(rows).toEqual([{ id: "inv-keep", contact_id: "contact-keep" }]);
85
- });
86
-
87
- test("rebuilds after created_by_session_id was renamed to source_conversation_id", () => {
88
- const db = createTestDb();
89
- const raw = getSqliteFrom(db);
90
- raw.exec(/*sql*/ `
91
- CREATE TABLE assistant_ingress_invites (
92
- id TEXT PRIMARY KEY,
93
- source_channel TEXT NOT NULL,
94
- token_hash TEXT NOT NULL,
95
- source_conversation_id TEXT,
96
- note TEXT,
97
- max_uses INTEGER NOT NULL DEFAULT 1,
98
- use_count INTEGER NOT NULL DEFAULT 0,
99
- expires_at INTEGER NOT NULL,
100
- status TEXT NOT NULL DEFAULT 'active',
101
- redeemed_by_external_user_id TEXT,
102
- redeemed_by_external_chat_id TEXT,
103
- redeemed_at INTEGER,
104
- expected_external_user_id TEXT,
105
- voice_code_hash TEXT,
106
- voice_code_digits INTEGER,
107
- invite_code_hash TEXT,
108
- friend_name TEXT,
109
- guardian_name TEXT,
110
- created_at INTEGER NOT NULL,
111
- updated_at INTEGER NOT NULL
112
- )
113
- `);
114
- raw.exec(
115
- `ALTER TABLE assistant_ingress_invites ADD COLUMN contact_id TEXT`,
116
- );
117
- raw.run(
118
- `INSERT INTO assistant_ingress_invites
119
- (id, source_channel, token_hash, source_conversation_id, contact_id,
120
- max_uses, use_count, expires_at, status, created_at, updated_at)
121
- VALUES ('inv-1', 'slack', 'hash-1', 'conv-9', 'contact-1', 1, 0, 9, 'active', 1, 1)`,
122
- );
123
-
124
- migrateInviteContactId(db);
125
-
126
- expect(columnNotNull(raw, "contact_id")).toBe(true);
127
- expect(
128
- tableHasColumn(db, "assistant_ingress_invites", "source_conversation_id"),
129
- ).toBe(true);
130
- expect(
131
- tableHasColumn(db, "assistant_ingress_invites", "created_by_session_id"),
132
- ).toBe(false);
133
- const row = raw
134
- .query(
135
- `SELECT source_conversation_id, contact_id FROM assistant_ingress_invites WHERE id = 'inv-1'`,
136
- )
137
- .get() as { source_conversation_id: string; contact_id: string };
138
- expect(row).toEqual({
139
- source_conversation_id: "conv-9",
140
- contact_id: "contact-1",
141
- });
142
- });
143
-
144
- test("is a no-op when the table does not exist", () => {
145
- const db = createTestDb();
146
- migrateInviteContactId(db);
147
- expect(tableExists(db, "assistant_ingress_invites")).toBe(false);
148
- });
149
- });
@@ -1,118 +0,0 @@
1
- import { beforeEach, describe, expect, test } from "bun:test";
2
-
3
- import { setConfig } from "../../../../__tests__/helpers/set-config.js";
4
-
5
- // Disable memory so persistence writes don't index into the real memory
6
- // pipeline (both flags default true under the real loader).
7
- setConfig("memory", { enabled: false, v2: { enabled: false } });
8
-
9
- import { createConversation } from "../../../../persistence/conversation-crud.js";
10
- import {
11
- getDb,
12
- getMemorySqlite,
13
- } from "../../../../persistence/db-connection.js";
14
- import { initializeDb } from "../../../../persistence/db-init.js";
15
- import { messages } from "../../../../persistence/schema/index.js";
16
- import { backfillRetrospectiveCursorTimestamps } from "../memory-retrospective-cursor-backfill.js";
17
- import {
18
- ensureRetrospectiveCursorColumn,
19
- getRetrospectiveState,
20
- } from "../memory-retrospective-state.js";
21
-
22
- await initializeDb();
23
-
24
- function resetTables(): void {
25
- const db = getDb();
26
- db.run(`DELETE FROM messages`);
27
- db.run(`DELETE FROM conversations`);
28
- getMemorySqlite()!.exec(`DELETE FROM memory_retrospective_state`);
29
- }
30
-
31
- /** A state row as written before the timestamp column existed. */
32
- function insertLegacyState(conversationId: string, messageId: string): void {
33
- ensureRetrospectiveCursorColumn("test");
34
- getMemorySqlite()!
35
- .query(
36
- `INSERT INTO memory_retrospective_state
37
- (conversation_id, last_processed_message_id, last_run_at, remembered_log, last_processed_created_at)
38
- VALUES (?, ?, 1, NULL, NULL)`,
39
- )
40
- .run(conversationId, messageId);
41
- }
42
-
43
- function insertMessage(
44
- conversationId: string,
45
- id: string,
46
- createdAt: number,
47
- ): void {
48
- getDb()
49
- .insert(messages)
50
- .values({
51
- id,
52
- conversationId,
53
- role: "user",
54
- content: "[]",
55
- createdAt,
56
- metadata: null,
57
- })
58
- .run();
59
- }
60
-
61
- describe("backfillRetrospectiveCursorTimestamps", () => {
62
- beforeEach(() => {
63
- resetTables();
64
- });
65
-
66
- test("fills the timestamp from the cursor's message, leaves vanished cursors NULL, and is idempotent", async () => {
67
- createConversation({ id: "conv-a" });
68
- createConversation({ id: "conv-b" });
69
- createConversation({ id: "conv-c" });
70
- insertMessage("conv-a", "a-m1", 1_000);
71
- insertLegacyState("conv-a", "a-m1");
72
- // Cursor row already deleted: nothing left to recover.
73
- insertLegacyState("conv-b", "gone");
74
- // The failure-only sentinel is never a cursor, so it is never scanned.
75
- insertLegacyState("conv-c", "");
76
-
77
- const first = await backfillRetrospectiveCursorTimestamps();
78
-
79
- expect(first).toEqual({ scanned: 2, backfilled: 1, unrecoverable: 1 });
80
- expect(getRetrospectiveState("conv-a")?.lastProcessedCreatedAt).toBe(1_000);
81
- expect(getRetrospectiveState("conv-b")?.lastProcessedCreatedAt).toBeNull();
82
- expect(getRetrospectiveState("conv-c")?.lastProcessedCreatedAt).toBeNull();
83
-
84
- const second = await backfillRetrospectiveCursorTimestamps();
85
-
86
- expect(second).toEqual({ scanned: 1, backfilled: 0, unrecoverable: 1 });
87
- });
88
-
89
- test("pages through the backlog by conversation id, advancing past unrecoverable rows", async () => {
90
- for (const id of ["conv-1", "conv-2", "conv-3", "conv-4", "conv-5"]) {
91
- createConversation({ id });
92
- }
93
- insertMessage("conv-1", "m-1", 1_000);
94
- insertLegacyState("conv-1", "m-1");
95
- insertLegacyState("conv-2", "gone-2");
96
- insertMessage("conv-3", "m-3", 3_000);
97
- insertLegacyState("conv-3", "m-3");
98
- insertLegacyState("conv-4", "gone-4");
99
- insertMessage("conv-5", "m-5", 5_000);
100
- insertLegacyState("conv-5", "m-5");
101
-
102
- const result = await backfillRetrospectiveCursorTimestamps({ pageSize: 2 });
103
-
104
- expect(result).toEqual({ scanned: 5, backfilled: 3, unrecoverable: 2 });
105
- expect(getRetrospectiveState("conv-1")?.lastProcessedCreatedAt).toBe(1_000);
106
- expect(getRetrospectiveState("conv-3")?.lastProcessedCreatedAt).toBe(3_000);
107
- expect(getRetrospectiveState("conv-5")?.lastProcessedCreatedAt).toBe(5_000);
108
- expect(getRetrospectiveState("conv-4")?.lastProcessedCreatedAt).toBeNull();
109
- });
110
-
111
- test("a table with nothing to fill is a clean no-op", async () => {
112
- expect(await backfillRetrospectiveCursorTimestamps()).toEqual({
113
- scanned: 0,
114
- backfilled: 0,
115
- unrecoverable: 0,
116
- });
117
- });
118
- });
@@ -1,83 +0,0 @@
1
- import { beforeEach, describe, expect, test } from "bun:test";
2
-
3
- import { setConfig } from "../../../../__tests__/helpers/set-config.js";
4
-
5
- // Disable memory so persistence writes don't index into the real memory
6
- // pipeline (both flags default true under the real loader).
7
- setConfig("memory", { enabled: false, v2: { enabled: false } });
8
-
9
- import { getMemorySqlite } from "../../../../persistence/db-connection.js";
10
- import { initializeDb } from "../../../../persistence/db-init.js";
11
- import { preserveRetrospectiveCursorTimestamps } from "../memory-retrospective-cursor-preserve.js";
12
- import {
13
- ensureRetrospectiveCursorColumn,
14
- getRetrospectiveState,
15
- upsertRetrospectiveState,
16
- } from "../memory-retrospective-state.js";
17
-
18
- await initializeDb();
19
-
20
- /** A state row as written before the timestamp column existed. */
21
- function insertLegacyState(conversationId: string, messageId: string): void {
22
- ensureRetrospectiveCursorColumn("test");
23
- getMemorySqlite()!
24
- .query(
25
- `INSERT INTO memory_retrospective_state
26
- (conversation_id, last_processed_message_id, last_run_at, remembered_log, last_processed_created_at)
27
- VALUES (?, ?, 1, NULL, NULL)`,
28
- )
29
- .run(conversationId, messageId);
30
- }
31
-
32
- describe("preserveRetrospectiveCursorTimestamps", () => {
33
- beforeEach(() => {
34
- getMemorySqlite()!.exec(`DELETE FROM memory_retrospective_state`);
35
- });
36
-
37
- test("records the timestamp of a legacy cursor whose row is about to be deleted", async () => {
38
- insertLegacyState("conv-a", "reply-1");
39
-
40
- await preserveRetrospectiveCursorTimestamps("conv-a", [
41
- { id: "tool-1", createdAt: 1_500 },
42
- { id: "reply-1", createdAt: 2_000 },
43
- ]);
44
-
45
- expect(getRetrospectiveState("conv-a")?.lastProcessedCreatedAt).toBe(2_000);
46
- });
47
-
48
- test("leaves a cursor that already has a timestamp, points elsewhere, or does not exist untouched", async () => {
49
- await upsertRetrospectiveState({
50
- conversationId: "conv-stamped",
51
- lastProcessedMessageId: "reply-1",
52
- lastProcessedCreatedAt: 1_000,
53
- lastRunAt: 1,
54
- });
55
- insertLegacyState("conv-elsewhere", "older-reply");
56
-
57
- await preserveRetrospectiveCursorTimestamps("conv-stamped", [
58
- { id: "reply-1", createdAt: 9_999 },
59
- ]);
60
- await preserveRetrospectiveCursorTimestamps("conv-elsewhere", [
61
- { id: "reply-1", createdAt: 9_999 },
62
- ]);
63
- await preserveRetrospectiveCursorTimestamps("conv-missing", [
64
- { id: "reply-1", createdAt: 9_999 },
65
- ]);
66
-
67
- expect(getRetrospectiveState("conv-stamped")?.lastProcessedCreatedAt).toBe(
68
- 1_000,
69
- );
70
- expect(
71
- getRetrospectiveState("conv-elsewhere")?.lastProcessedCreatedAt,
72
- ).toBeNull();
73
- expect(getRetrospectiveState("conv-missing")).toBeNull();
74
- });
75
-
76
- test("an empty row list is a no-op", async () => {
77
- insertLegacyState("conv-a", "reply-1");
78
-
79
- await preserveRetrospectiveCursorTimestamps("conv-a", []);
80
-
81
- expect(getRetrospectiveState("conv-a")?.lastProcessedCreatedAt).toBeNull();
82
- });
83
- });
@@ -1,21 +0,0 @@
1
- /**
2
- * Default `memory` message-deleted hook.
3
- *
4
- * Stamps the conversation's retrospective cursor with the deleted row's
5
- * `createdAt` when the cursor points at that row and was written without a
6
- * timestamp (by a build before the column existed). The cursor usually sits
7
- * on the latest assistant reply, which is exactly the row a regenerate
8
- * deletes, and once the row is gone only the timestamp can place it.
9
- */
10
-
11
- import type { HookFunction, MessageDeletedContext } from "@vellumai/plugin-api";
12
-
13
- import { preserveRetrospectiveCursorTimestamps } from "../memory-retrospective-cursor-preserve.js";
14
-
15
- const messageDeleted: HookFunction<MessageDeletedContext> = async (ctx) => {
16
- await preserveRetrospectiveCursorTimestamps(ctx.conversationId, [
17
- { id: ctx.messageId, createdAt: ctx.createdAt },
18
- ]);
19
- };
20
-
21
- export default messageDeleted;