@vellumai/assistant 0.7.0 → 0.7.1

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 (666) hide show
  1. package/ARCHITECTURE.md +6 -7
  2. package/Dockerfile +1 -0
  3. package/README.md +2 -2
  4. package/__tests__/permissions/gateway-threshold-reader.test.ts +79 -139
  5. package/bun.lock +3 -0
  6. package/docs/architecture/security.md +18 -16
  7. package/knip.json +1 -0
  8. package/node_modules/@vellumai/skill-host-contracts/__tests__/client.test.ts +1 -5
  9. package/node_modules/@vellumai/skill-host-contracts/src/assistant-event.ts +0 -5
  10. package/node_modules/@vellumai/skill-host-contracts/src/client.ts +10 -16
  11. package/node_modules/@vellumai/skill-host-contracts/src/skill-host.ts +1 -9
  12. package/node_modules/@vellumai/skill-host-contracts/src/tool-types.ts +12 -12
  13. package/node_modules/@vellumai/slack-text/bun.lock +24 -0
  14. package/node_modules/@vellumai/slack-text/package.json +18 -0
  15. package/node_modules/@vellumai/slack-text/src/index.test.ts +153 -0
  16. package/node_modules/@vellumai/slack-text/src/index.ts +235 -0
  17. package/node_modules/@vellumai/slack-text/tsconfig.json +20 -0
  18. package/openapi.yaml +294 -107
  19. package/package.json +4 -2
  20. package/scripts/generate-openapi.ts +16 -111
  21. package/src/__tests__/agent-wake-override-profile.test.ts +23 -1
  22. package/src/__tests__/anthropic-provider.test.ts +56 -13
  23. package/src/__tests__/app-conversation-ids-backfill.test.ts +278 -0
  24. package/src/__tests__/app-conversation-ids.test.ts +151 -0
  25. package/src/__tests__/approval-cascade.test.ts +0 -15
  26. package/src/__tests__/approval-routes-http.test.ts +6 -17
  27. package/src/__tests__/assistant-event-hub.test.ts +126 -77
  28. package/src/__tests__/assistant-event.test.ts +0 -5
  29. package/src/__tests__/assistant-events-sse-hardening.test.ts +37 -15
  30. package/src/__tests__/assistant-feature-flags-integration.test.ts +0 -29
  31. package/src/__tests__/background-shell-host-bash.test.ts +34 -43
  32. package/src/__tests__/call-controller.test.ts +1 -1
  33. package/src/__tests__/call-site-routing-provider.test.ts +193 -0
  34. package/src/__tests__/channel-approval-routes.test.ts +10 -296
  35. package/src/__tests__/channel-approvals.test.ts +25 -17
  36. package/src/__tests__/channel-guardian.test.ts +100 -146
  37. package/src/__tests__/checker.test.ts +20 -34
  38. package/src/__tests__/compact-event-conversation-id-guard.test.ts +50 -0
  39. package/src/__tests__/compaction-events.test.ts +2 -0
  40. package/src/__tests__/config-schema.test.ts +6 -48
  41. package/src/__tests__/config-watcher.test.ts +12 -0
  42. package/src/__tests__/connection-policy.test.ts +1 -52
  43. package/src/__tests__/contacts-write.test.ts +2 -64
  44. package/src/__tests__/context-image-dimensions.test.ts +1 -1
  45. package/src/__tests__/context-search-memory-source.test.ts +120 -1
  46. package/src/__tests__/context-search-memory-v2-source.test.ts +383 -0
  47. package/src/__tests__/context-search-pkb-source.test.ts +49 -0
  48. package/src/__tests__/context-search-workspace-source.test.ts +9 -22
  49. package/src/__tests__/context-window-manager.test.ts +46 -0
  50. package/src/__tests__/conversation-agent-loop-inference-profile.test.ts +2 -0
  51. package/src/__tests__/conversation-agent-loop-overflow.test.ts +102 -29
  52. package/src/__tests__/conversation-agent-loop.test.ts +980 -13
  53. package/src/__tests__/conversation-analysis-routes.test.ts +12 -10
  54. package/src/__tests__/conversation-attention-telegram.test.ts +11 -3
  55. package/src/__tests__/conversation-confirmation-signals.test.ts +0 -291
  56. package/src/__tests__/conversation-history-web-search.test.ts +4 -3
  57. package/src/__tests__/conversation-inference-profile-route.test.ts +12 -23
  58. package/src/__tests__/conversation-lifecycle.test.ts +4 -4
  59. package/src/__tests__/conversation-process-callsite.test.ts +79 -2
  60. package/src/__tests__/conversation-queue.test.ts +3 -8
  61. package/src/__tests__/conversation-routes-disk-view.test.ts +1 -161
  62. package/src/__tests__/conversation-routes-guardian-reply.test.ts +0 -32
  63. package/src/__tests__/conversation-routes-slash-commands.test.ts +75 -66
  64. package/src/__tests__/conversation-runtime-assembly.test.ts +257 -3
  65. package/src/__tests__/conversation-slash-commands.test.ts +24 -4
  66. package/src/__tests__/conversation-slash-queue.test.ts +2 -0
  67. package/src/__tests__/conversation-speed-override.test.ts +0 -3
  68. package/src/__tests__/conversation-starter-routes.test.ts +79 -2
  69. package/src/__tests__/conversation-surfaces-standalone-payloads.test.ts +12 -5
  70. package/src/__tests__/conversation-surfaces-standalone.test.ts +18 -14
  71. package/src/__tests__/conversation-surfaces-state-update.test.ts +3 -2
  72. package/src/__tests__/conversation-tool-setup-app-refresh.test.ts +8 -46
  73. package/src/__tests__/conversation-usage.test.ts +253 -3
  74. package/src/__tests__/credential-execution-shell-lockdown.test.ts +0 -39
  75. package/src/__tests__/credential-health-service.test.ts +68 -0
  76. package/src/__tests__/credential-security-e2e.test.ts +4 -3
  77. package/src/__tests__/credential-security-invariants.test.ts +1 -5
  78. package/src/__tests__/credential-token-resolver.test.ts +180 -0
  79. package/src/__tests__/cu-unified-flow.test.ts +33 -16
  80. package/src/__tests__/daemon-assistant-events.test.ts +34 -21
  81. package/src/__tests__/daemon-credential-client.test.ts +4 -1
  82. package/src/__tests__/db-connection-isolation.test.ts +125 -0
  83. package/src/__tests__/db-migration-rollback.test.ts +101 -0
  84. package/src/__tests__/db-slack-compaction-watermark-migration.test.ts +169 -0
  85. package/src/__tests__/deterministic-verification-control-plane.test.ts +7 -80
  86. package/src/__tests__/document-conversations.test.ts +332 -0
  87. package/src/__tests__/embedding-managed-proxy-selection.test.ts +2 -2
  88. package/src/__tests__/emit-event-signal.test.ts +4 -6
  89. package/src/__tests__/events-client-registration.test.ts +193 -49
  90. package/src/__tests__/filing-service.test.ts +58 -7
  91. package/src/__tests__/first-greeting.test.ts +156 -150
  92. package/src/__tests__/fixtures/mock-chrome-extension.ts +108 -66
  93. package/src/__tests__/get-skill-detail-audit.test.ts +3 -8
  94. package/src/__tests__/guardian-binding-drift-heal.test.ts +1 -1
  95. package/src/__tests__/guardian-dispatch.test.ts +1 -1
  96. package/src/__tests__/guardian-grant-minting.test.ts +7 -2
  97. package/src/__tests__/guardian-routing-invariants.test.ts +7 -2
  98. package/src/__tests__/guardian-routing-state.test.ts +1 -1
  99. package/src/__tests__/handlers-skills-memory-v2-reseed.test.ts +32 -11
  100. package/src/__tests__/handlers-user-message-approval-consumption.test.ts +2 -83
  101. package/src/__tests__/headless-browser-mode.test.ts +4 -9
  102. package/src/__tests__/headless-browser-navigate.test.ts +21 -20
  103. package/src/__tests__/heartbeat-service.test.ts +289 -7
  104. package/src/__tests__/helpers/channel-test-adapter.ts +2 -2
  105. package/src/__tests__/helpers/create-guardian-binding.ts +91 -0
  106. package/src/__tests__/host-bash-proxy.test.ts +46 -122
  107. package/src/__tests__/host-browser-e2e-cloud.test.ts +36 -497
  108. package/src/__tests__/host-browser-e2e-self-hosted-capability.test.ts +26 -96
  109. package/src/__tests__/host-browser-proxy.test.ts +111 -185
  110. package/src/__tests__/host-browser-routes.test.ts +45 -75
  111. package/src/__tests__/host-browser-ws-events-e2e.test.ts +26 -30
  112. package/src/__tests__/host-cu-proxy.test.ts +56 -111
  113. package/src/__tests__/host-file-proxy.test.ts +44 -98
  114. package/src/__tests__/host-file-read-tool.test.ts +42 -21
  115. package/src/__tests__/host-shell-tool.test.ts +33 -68
  116. package/src/__tests__/host-transfer-pending-interactions.test.ts +2 -18
  117. package/src/__tests__/host-transfer-proxy.test.ts +43 -53
  118. package/src/__tests__/http-user-message-parity.test.ts +0 -6
  119. package/src/__tests__/inbound-slack-persistence.test.ts +31 -0
  120. package/src/__tests__/injector-chain.test.ts +10 -5
  121. package/src/__tests__/injector-pkb-v2-silenced.test.ts +124 -0
  122. package/src/__tests__/inline-command-runner.test.ts +0 -66
  123. package/src/__tests__/inline-skill-load-permissions.test.ts +0 -2
  124. package/src/__tests__/install-skill-routing.test.ts +1 -13
  125. package/src/__tests__/llm-callsite-catalog.test.ts +34 -0
  126. package/src/__tests__/llm-catalog-parity.test.ts +90 -0
  127. package/src/__tests__/llm-context-resolution.test.ts +180 -0
  128. package/src/__tests__/llm-resolver.test.ts +80 -12
  129. package/src/__tests__/llm-usage-store.test.ts +269 -4
  130. package/src/__tests__/log-export-routes.test.ts +89 -0
  131. package/src/__tests__/managed-profile-guard.test.ts +225 -0
  132. package/src/__tests__/managed-skill-lifecycle.test.ts +0 -10
  133. package/src/__tests__/manual-token-reconciliation.test.ts +334 -0
  134. package/src/__tests__/memory-v2-static-injector.test.ts +95 -0
  135. package/src/__tests__/migration-cross-version-compatibility.test.ts +197 -291
  136. package/src/__tests__/migration-export-http.test.ts +33 -26
  137. package/src/__tests__/migration-export-streaming.test.ts +18 -10
  138. package/src/__tests__/migration-export-to-gcs.test.ts +49 -9
  139. package/src/__tests__/migration-import-commit-http.test.ts +66 -21
  140. package/src/__tests__/migration-import-from-gcs.test.ts +50 -9
  141. package/src/__tests__/migration-import-from-url.test.ts +20 -6
  142. package/src/__tests__/migration-import-preflight-http.test.ts +95 -95
  143. package/src/__tests__/migration-parity-persistence.test.ts +62 -25
  144. package/src/__tests__/migration-transport.test.ts +115 -23
  145. package/src/__tests__/migration-validate-http.test.ts +105 -80
  146. package/src/__tests__/migration-wizard.test.ts +133 -27
  147. package/src/__tests__/non-member-access-request.test.ts +1 -1
  148. package/src/__tests__/notification-guardian-path.test.ts +1 -1
  149. package/src/__tests__/oauth-store.test.ts +19 -0
  150. package/src/__tests__/platform-bash-auto-approve.test.ts +21 -12
  151. package/src/__tests__/prechat-onboarding-contract.test.ts +31 -7
  152. package/src/__tests__/pricing.test.ts +68 -4
  153. package/src/__tests__/process-message-background-slack.test.ts +331 -0
  154. package/src/__tests__/provider-managed-proxy-integration.test.ts +153 -17
  155. package/src/__tests__/provider-send-message-override-profile.test.ts +50 -0
  156. package/src/__tests__/provider-usage-tracking.test.ts +208 -0
  157. package/src/__tests__/reaction-persistence.test.ts +9 -6
  158. package/src/__tests__/rebind-secrets-screen.test.ts +53 -16
  159. package/src/__tests__/recording-handler.test.ts +64 -81
  160. package/src/__tests__/regenerate-fire-and-forget-trace.test.ts +4 -3
  161. package/src/__tests__/relay-server.test.ts +18 -13
  162. package/src/__tests__/require-fresh-approval.test.ts +13 -22
  163. package/src/__tests__/runtime-attachment-metadata.test.ts +1 -1
  164. package/src/__tests__/runtime-events-sse-parity.test.ts +3 -4
  165. package/src/__tests__/runtime-events-sse.test.ts +3 -12
  166. package/src/__tests__/search-skills-unified.test.ts +9 -15
  167. package/src/__tests__/secret-ingress-cli.test.ts +2 -5
  168. package/src/__tests__/secret-ingress-http.test.ts +0 -4
  169. package/src/__tests__/secret-onetime-send.test.ts +4 -2
  170. package/src/__tests__/secret-prompt-log-hygiene.test.ts +24 -7
  171. package/src/__tests__/secret-prompter-channel-fallback.test.ts +42 -47
  172. package/src/__tests__/secret-response-routing.test.ts +29 -15
  173. package/src/__tests__/secret-routes-managed-proxy.test.ts +5 -1
  174. package/src/__tests__/secret-scanner.test.ts +2 -545
  175. package/src/__tests__/send-endpoint-busy.test.ts +9 -24
  176. package/src/__tests__/settings-routes.test.ts +1 -1
  177. package/src/__tests__/shell-credential-ref.test.ts +0 -8
  178. package/src/__tests__/shell-tool-proxy-mode.test.ts +0 -56
  179. package/src/__tests__/skill-script-runner-sandbox.test.ts +0 -11
  180. package/src/__tests__/skill-tool-factory.test.ts +97 -0
  181. package/src/__tests__/skills-file-content-endpoint.test.ts +9 -30
  182. package/src/__tests__/skills-files-catalog-fallback.test.ts +11 -17
  183. package/src/__tests__/slack-inbound-verification.test.ts +1 -62
  184. package/src/__tests__/subagent-fork-notifications.test.ts +57 -47
  185. package/src/__tests__/subagent-manager-notify.test.ts +70 -70
  186. package/src/__tests__/subagent-notify-parent.test.ts +80 -83
  187. package/src/__tests__/system-prompt.test.ts +115 -13
  188. package/src/__tests__/terminal-tools.test.ts +0 -89
  189. package/src/__tests__/thread-backfill.test.ts +945 -31
  190. package/src/__tests__/tool-domain-event-publisher.test.ts +0 -36
  191. package/src/__tests__/tool-execute-pipeline.test.ts +0 -6
  192. package/src/__tests__/tool-execution-abort-cleanup.test.ts +0 -16
  193. package/src/__tests__/tool-execution-pipeline.benchmark.test.ts +9 -19
  194. package/src/__tests__/tool-executor-lifecycle-events.test.ts +4 -7
  195. package/src/__tests__/tool-executor.test.ts +12 -19
  196. package/src/__tests__/tool-metrics-listener.test.ts +0 -35
  197. package/src/__tests__/tool-side-effects-slack-dm.test.ts +1 -0
  198. package/src/__tests__/tool-trace-listener.test.ts +0 -17
  199. package/src/__tests__/transfer-progress-screen.test.ts +63 -26
  200. package/src/__tests__/trusted-contact-lifecycle-notifications.test.ts +2 -149
  201. package/src/__tests__/trusted-contact-multichannel.test.ts +2 -4
  202. package/src/__tests__/trusted-contact-verification.test.ts +1 -1
  203. package/src/__tests__/tts-catalog-parity.test.ts +16 -5
  204. package/src/__tests__/usage-attribution.test.ts +247 -0
  205. package/src/__tests__/usage-cli.test.ts +143 -0
  206. package/src/__tests__/usage-grouped-buckets.test.ts +155 -0
  207. package/src/__tests__/usage-routes.test.ts +150 -0
  208. package/src/__tests__/validation-results-screen.test.ts +39 -16
  209. package/src/__tests__/vbundle-pax-and-symlink.test.ts +12 -3
  210. package/src/__tests__/vellum-self-knowledge-inline-command.test.ts +49 -137
  211. package/src/__tests__/verification-control-plane-policy.test.ts +4 -7
  212. package/src/__tests__/voice-session-bridge.test.ts +5 -5
  213. package/src/__tests__/workspace-migration-062-drop-memory-v2-edges-json.test.ts +103 -0
  214. package/src/__tests__/workspace-migration-063-release-notes-dynamic-model-context.test.ts +77 -0
  215. package/src/__tests__/workspace-migration-064-unwind-main-agent-opus-seed.test.ts +225 -0
  216. package/src/__tests__/workspace-migration-memory-v2-init.test.ts +8 -30
  217. package/src/acp/index.ts +0 -15
  218. package/src/acp/session-manager.ts +37 -34
  219. package/src/agent/loop.ts +16 -1
  220. package/src/approvals/AGENTS.md +4 -0
  221. package/src/approvals/__tests__/guardian-feed-event.test.ts +10 -3
  222. package/src/approvals/guardian-request-resolvers.ts +10 -2
  223. package/src/backup/__tests__/backup-worker.test.ts +36 -8
  224. package/src/backup/__tests__/paths.test.ts +2 -2
  225. package/src/backup/__tests__/restore.test.ts +45 -28
  226. package/src/backup/backup-worker.ts +36 -2
  227. package/src/backup/paths.ts +9 -6
  228. package/src/browser-session/events.ts +0 -9
  229. package/src/calls/call-store.ts +1 -34
  230. package/src/calls/guardian-question-copy.ts +0 -108
  231. package/src/calls/relay-server.ts +0 -24
  232. package/src/calls/twilio-rest.ts +0 -38
  233. package/src/calls/twilio-routes.ts +1 -1
  234. package/src/calls/voice-session-bridge.ts +7 -38
  235. package/src/channels/types.ts +1 -36
  236. package/src/cli/commands/__tests__/cache.test.ts +152 -5
  237. package/src/cli/commands/__tests__/memory-v2.test.ts +14 -28
  238. package/src/cli/commands/__tests__/trust.test.ts +21 -387
  239. package/src/cli/commands/backup.ts +4 -4
  240. package/src/cli/commands/cache-fs.ts +8 -0
  241. package/src/cli/commands/cache.ts +153 -82
  242. package/src/cli/commands/clients.ts +63 -5
  243. package/src/cli/commands/completions.ts +3 -3
  244. package/src/cli/commands/contacts.ts +231 -76
  245. package/src/cli/commands/keys.ts +4 -1
  246. package/src/cli/commands/memory-v2.ts +24 -52
  247. package/src/cli/commands/oauth/shared.ts +2 -29
  248. package/src/cli/commands/pending.ts +102 -0
  249. package/src/cli/commands/skills.ts +77 -35
  250. package/src/cli/commands/trust.ts +70 -430
  251. package/src/cli/commands/usage.ts +25 -16
  252. package/src/cli/lib/daemon-credential-client.ts +14 -0
  253. package/src/cli/program.ts +2 -0
  254. package/src/cli.ts +0 -21
  255. package/src/config/__tests__/feature-flag-registry-guard.test.ts +2 -2
  256. package/src/config/bundled-skills/messaging/TOOLS.json +14 -4
  257. package/src/config/env-registry.ts +12 -2
  258. package/src/config/env.ts +3 -14
  259. package/src/config/feature-flag-registry.json +30 -30
  260. package/src/config/llm-callsite-catalog.ts +12 -0
  261. package/src/config/llm-context-resolution.ts +80 -0
  262. package/src/config/llm-resolver.ts +58 -22
  263. package/src/config/loader.ts +3 -3
  264. package/src/config/schema.ts +2 -158
  265. package/src/config/schemas/__tests__/memory-v2.test.ts +1 -0
  266. package/src/config/schemas/call-site-catalog.ts +271 -0
  267. package/src/config/schemas/calls.ts +5 -5
  268. package/src/config/schemas/inference.ts +1 -1
  269. package/src/config/schemas/ingress.ts +1 -1
  270. package/src/config/schemas/llm.ts +31 -3
  271. package/src/config/schemas/memory-retrieval.ts +2 -2
  272. package/src/config/schemas/memory-v2.ts +9 -0
  273. package/src/config/schemas/security.ts +1 -42
  274. package/src/config/schemas/services.ts +6 -6
  275. package/src/config/schemas/skills.ts +5 -5
  276. package/src/config/schemas/tts.ts +1 -1
  277. package/src/config/seed-inference-profiles.ts +117 -0
  278. package/src/config/skills.ts +0 -90
  279. package/src/config/types.ts +3 -6
  280. package/src/contacts/contact-store.ts +0 -17
  281. package/src/contacts/contacts-write.ts +1 -105
  282. package/src/context/window-manager.ts +44 -5
  283. package/src/credential-execution/process-manager.ts +34 -10
  284. package/src/credential-health/credential-health-service.ts +21 -16
  285. package/src/daemon/__tests__/conversation-surfaces-launch.test.ts +75 -82
  286. package/src/daemon/__tests__/daemon-skill-host.test.ts +2 -9
  287. package/src/daemon/connection-policy.ts +1 -26
  288. package/src/daemon/conversation-agent-loop-handlers.ts +53 -4
  289. package/src/daemon/conversation-agent-loop.ts +277 -36
  290. package/src/daemon/conversation-history.ts +8 -8
  291. package/src/daemon/conversation-launch.ts +20 -135
  292. package/src/daemon/conversation-lifecycle.ts +1 -1
  293. package/src/daemon/conversation-messaging.ts +1 -0
  294. package/src/daemon/conversation-process.ts +83 -163
  295. package/src/daemon/conversation-runtime-assembly.ts +219 -76
  296. package/src/daemon/conversation-slash.ts +47 -5
  297. package/src/daemon/conversation-store.ts +7 -31
  298. package/src/daemon/conversation-surfaces.ts +22 -28
  299. package/src/daemon/conversation-tool-setup.ts +3 -33
  300. package/src/daemon/conversation-usage.ts +36 -0
  301. package/src/daemon/conversation.ts +117 -233
  302. package/src/daemon/daemon-control.ts +3 -71
  303. package/src/daemon/daemon-skill-host.ts +8 -11
  304. package/src/daemon/dictation-profile-store.ts +2 -26
  305. package/src/daemon/first-greeting.ts +44 -156
  306. package/src/daemon/handlers/config-channels.ts +12 -12
  307. package/src/daemon/handlers/config-ingress.ts +4 -165
  308. package/src/daemon/handlers/config-model.ts +1 -1
  309. package/src/daemon/handlers/config-voice.ts +0 -42
  310. package/src/daemon/handlers/conversations.ts +11 -190
  311. package/src/daemon/handlers/recording.ts +26 -158
  312. package/src/daemon/handlers/shared.ts +23 -71
  313. package/src/daemon/handlers/skills.ts +42 -93
  314. package/src/daemon/host-bash-proxy.ts +67 -45
  315. package/src/daemon/host-browser-proxy.ts +65 -27
  316. package/src/daemon/host-cu-proxy.ts +40 -39
  317. package/src/daemon/host-file-proxy.ts +58 -37
  318. package/src/daemon/host-transfer-proxy.ts +84 -46
  319. package/src/daemon/lifecycle.ts +49 -15
  320. package/src/daemon/message-types/conversations.ts +7 -0
  321. package/src/daemon/message-types/host-bash.ts +1 -0
  322. package/src/daemon/message-types/host-cu.ts +1 -0
  323. package/src/daemon/message-types/host-file.ts +1 -0
  324. package/src/daemon/message-types/host-transfer.ts +1 -0
  325. package/src/daemon/message-types/messages.ts +10 -9
  326. package/src/daemon/message-types/workspace.ts +1 -1
  327. package/src/daemon/process-message.ts +102 -239
  328. package/src/daemon/server.ts +13 -462
  329. package/src/daemon/shutdown-handlers.ts +2 -2
  330. package/src/daemon/tool-side-effects.ts +125 -107
  331. package/src/daemon/trust-context.ts +13 -0
  332. package/src/daemon/wake-target-adapter.ts +4 -9
  333. package/src/events/domain-events.ts +0 -8
  334. package/src/events/tool-audit-listener.ts +3 -1
  335. package/src/events/tool-domain-event-publisher.ts +0 -10
  336. package/src/events/tool-metrics-listener.ts +0 -17
  337. package/src/events/tool-trace-listener.ts +0 -14
  338. package/src/filing/filing-service.ts +13 -1
  339. package/src/heartbeat/__tests__/heartbeat-feed-event.test.ts +6 -2
  340. package/src/heartbeat/heartbeat-service.ts +23 -5
  341. package/src/home/__tests__/feed-writer.test.ts +0 -4
  342. package/src/home/__tests__/relationship-state-writer.test.ts +30 -0
  343. package/src/home/feed-writer.ts +1 -2
  344. package/src/home/relationship-state-writer.ts +16 -3
  345. package/src/ipc/__tests__/browser-ipc.test.ts +2 -12
  346. package/src/ipc/__tests__/skill-server-bidirectional.test.ts +0 -1
  347. package/src/ipc/assistant-server.ts +3 -10
  348. package/src/ipc/routes/__tests__/memory-v2-backfill.test.ts +39 -20
  349. package/src/ipc/routes/route-adapter.ts +1 -1
  350. package/src/ipc/routes/trust-rules.test.ts +0 -95
  351. package/src/ipc/skill-ipc-types.ts +41 -0
  352. package/src/ipc/skill-routes/__tests__/events-ipc.test.ts +13 -27
  353. package/src/ipc/skill-routes/__tests__/identity.test.ts +4 -23
  354. package/src/ipc/skill-routes/events.ts +12 -23
  355. package/src/ipc/skill-routes/identity.ts +4 -17
  356. package/src/ipc/skill-routes/index.ts +1 -1
  357. package/src/ipc/skill-server.ts +6 -39
  358. package/src/live-voice/__tests__/runtime-websocket-shell.test.ts +0 -8
  359. package/src/live-voice/protocol.ts +4 -13
  360. package/src/mcp/manager.ts +0 -5
  361. package/src/memory/__tests__/fixtures/memory-v2-activation-fixtures.ts +55 -0
  362. package/src/memory/__tests__/memory-v2-activation-log-store.test.ts +127 -0
  363. package/src/memory/app-git-service.ts +0 -32
  364. package/src/memory/app-store.ts +154 -0
  365. package/src/memory/attachments-store.ts +6 -0
  366. package/src/memory/context-search/sources/memory-v2.ts +578 -0
  367. package/src/memory/context-search/sources/memory.ts +5 -0
  368. package/src/memory/context-search/sources/pkb.ts +10 -1
  369. package/src/memory/context-search/sources/workspace.ts +3 -2
  370. package/src/memory/conversation-crud.ts +29 -4
  371. package/src/memory/conversation-disk-view.ts +1 -5
  372. package/src/memory/conversation-starter-checkpoints.ts +63 -0
  373. package/src/memory/db-connection.ts +62 -0
  374. package/src/memory/db-init.ts +14 -0
  375. package/src/memory/embedding-backend.ts +3 -21
  376. package/src/memory/embedding-gemini.ts +0 -2
  377. package/src/memory/embedding-local.ts +6 -6
  378. package/src/memory/embedding-ollama.ts +6 -6
  379. package/src/memory/embedding-openai.ts +6 -6
  380. package/src/memory/embedding-types.ts +21 -0
  381. package/src/memory/graph/__tests__/conversation-graph-memory-v2-routing.test.ts +3 -7
  382. package/src/memory/graph/conversation-graph-memory.ts +35 -13
  383. package/src/memory/graph/injection.test.ts +2 -2
  384. package/src/memory/graph/injection.ts +1 -1
  385. package/src/memory/guardian-action-store.ts +0 -83
  386. package/src/memory/guardian-approvals.ts +0 -48
  387. package/src/memory/indexer.ts +1 -15
  388. package/src/memory/job-handlers/conversation-starters.ts +36 -53
  389. package/src/memory/job-utils.ts +0 -6
  390. package/src/memory/jobs-store.ts +0 -1
  391. package/src/memory/jobs-worker.ts +2 -16
  392. package/src/memory/llm-request-log-store.ts +0 -41
  393. package/src/memory/llm-usage-store.ts +129 -43
  394. package/src/memory/memory-v2-activation-log-store.ts +115 -0
  395. package/src/memory/migrations/233-document-conversations.ts +54 -0
  396. package/src/memory/migrations/234-memory-v2-activation-logs.ts +55 -0
  397. package/src/memory/migrations/235-llm-usage-attribution.ts +31 -0
  398. package/src/memory/migrations/235-slack-compaction-watermark.ts +44 -0
  399. package/src/memory/migrations/236-tool-invocations-matched-rule-id.ts +26 -0
  400. package/src/memory/migrations/__tests__/234-memory-v2-activation-logs.test.ts +182 -0
  401. package/src/memory/migrations/index.ts +14 -0
  402. package/src/memory/migrations/registry.ts +24 -0
  403. package/src/memory/raw-query.ts +2 -68
  404. package/src/memory/schema/conversations.ts +7 -0
  405. package/src/memory/schema/infrastructure.ts +25 -0
  406. package/src/memory/search/semantic.ts +5 -16
  407. package/src/memory/tool-usage-store.ts +2 -0
  408. package/src/memory/usage-buckets.ts +40 -1
  409. package/src/memory/usage-grouped-buckets.ts +127 -0
  410. package/src/memory/v2/__tests__/activation.test.ts +289 -90
  411. package/src/memory/v2/__tests__/backfill-jobs.test.ts +2 -129
  412. package/src/memory/v2/__tests__/consolidation-job.test.ts +28 -11
  413. package/src/memory/v2/__tests__/edge-index.test.ts +278 -0
  414. package/src/memory/v2/__tests__/injection.test.ts +384 -15
  415. package/src/memory/v2/__tests__/migration.test.ts +64 -36
  416. package/src/memory/v2/__tests__/page-store.test.ts +191 -8
  417. package/src/memory/v2/__tests__/prompts-consolidation.test.ts +181 -0
  418. package/src/memory/v2/__tests__/skill-store.test.ts +115 -3
  419. package/src/memory/v2/__tests__/static-context.test.ts +153 -0
  420. package/src/memory/v2/activation.ts +168 -97
  421. package/src/memory/v2/backfill-jobs.ts +15 -100
  422. package/src/memory/v2/consolidation-job.ts +14 -12
  423. package/src/memory/v2/edge-index.ts +191 -0
  424. package/src/memory/v2/injection.ts +182 -58
  425. package/src/memory/v2/migration.ts +57 -64
  426. package/src/memory/v2/now-text.ts +2 -3
  427. package/src/memory/v2/page-store.ts +168 -31
  428. package/src/memory/v2/prompts/consolidation.ts +118 -42
  429. package/src/memory/v2/prompts/sweep.ts +3 -3
  430. package/src/memory/v2/skill-store.ts +55 -7
  431. package/src/memory/v2/static-context.ts +62 -0
  432. package/src/memory/v2/types.ts +10 -20
  433. package/src/memory/validation.ts +0 -11
  434. package/src/messaging/draft-store.ts +0 -6
  435. package/src/messaging/provider-types.ts +8 -0
  436. package/src/messaging/provider.ts +7 -0
  437. package/src/messaging/providers/gmail/client.ts +1 -121
  438. package/src/messaging/providers/outlook/client.ts +0 -73
  439. package/src/messaging/providers/slack/__tests__/adapter-mention-rendering.test.ts +226 -0
  440. package/src/messaging/providers/slack/adapter.ts +122 -21
  441. package/src/messaging/providers/slack/backfill.test.ts +95 -6
  442. package/src/messaging/providers/slack/backfill.ts +89 -11
  443. package/src/messaging/providers/slack/client.ts +10 -124
  444. package/src/messaging/providers/slack/message-metadata.ts +12 -2
  445. package/src/messaging/providers/slack/render-transcript.test.ts +56 -0
  446. package/src/messaging/providers/slack/render-transcript.ts +126 -25
  447. package/src/messaging/providers/slack/types.ts +1 -0
  448. package/src/oauth/connection-resolver.test.ts +8 -0
  449. package/src/oauth/connection-resolver.ts +8 -16
  450. package/src/oauth/credential-token-resolver.ts +97 -0
  451. package/src/oauth/manual-token-connection.ts +30 -34
  452. package/src/oauth/oauth-store.ts +6 -4
  453. package/src/outbound-proxy/certs.ts +0 -7
  454. package/src/outbound-proxy/config.ts +0 -74
  455. package/src/outbound-proxy/health.ts +0 -44
  456. package/src/outbound-proxy/index.ts +0 -22
  457. package/src/permissions/approval-provenance.test.ts +184 -0
  458. package/src/permissions/approval-provenance.ts +70 -0
  459. package/src/permissions/checker.ts +4 -1
  460. package/src/permissions/gateway-threshold-reader.ts +4 -1
  461. package/src/permissions/prompter.ts +9 -2
  462. package/src/permissions/secret-prompter.ts +21 -48
  463. package/src/permissions/types.ts +33 -0
  464. package/src/permissions/workspace-policy.ts +0 -5
  465. package/src/platform/sync-identity.ts +0 -8
  466. package/src/plugins/defaults/injectors.ts +69 -2
  467. package/src/plugins/defaults/overflow-reduce.ts +3 -2
  468. package/src/plugins/types.ts +8 -0
  469. package/src/prompts/system-prompt.ts +34 -70
  470. package/src/prompts/templates/BOOTSTRAP.md +52 -6
  471. package/src/prompts/update-bulletin-job.ts +2 -0
  472. package/src/providers/__tests__/retry-callsite.test.ts +138 -1
  473. package/src/providers/anthropic/client.ts +72 -33
  474. package/src/providers/call-site-routing.ts +42 -3
  475. package/src/providers/gemini/client.ts +18 -2
  476. package/src/providers/managed-proxy/context.ts +0 -5
  477. package/src/providers/model-catalog.ts +105 -19
  478. package/src/providers/openai/chat-completions-provider.ts +6 -0
  479. package/src/providers/openai/responses-provider.ts +7 -1
  480. package/src/providers/provider-send-message.ts +45 -2
  481. package/src/providers/ratelimit.ts +7 -2
  482. package/src/providers/registry.ts +14 -9
  483. package/src/providers/retry.ts +96 -8
  484. package/src/providers/types.ts +13 -0
  485. package/src/providers/usage-tracking.ts +96 -0
  486. package/src/runtime/AGENTS.md +10 -6
  487. package/src/runtime/__tests__/agent-wake.test.ts +89 -0
  488. package/src/runtime/agent-wake.ts +39 -2
  489. package/src/runtime/assistant-event-hub.ts +541 -45
  490. package/src/runtime/assistant-event.ts +1 -6
  491. package/src/runtime/auth/context.ts +0 -9
  492. package/src/runtime/auth/middleware.ts +1 -1
  493. package/src/runtime/auth/route-policy.ts +11 -9
  494. package/src/runtime/auth/token-service.ts +0 -11
  495. package/src/runtime/channel-approvals.ts +6 -2
  496. package/src/runtime/channel-verification-service.ts +3 -5
  497. package/src/runtime/http-errors.ts +0 -34
  498. package/src/runtime/http-router.ts +6 -3
  499. package/src/runtime/http-server.ts +22 -82
  500. package/src/runtime/http-types.ts +5 -0
  501. package/src/runtime/interactive-ui.ts +0 -1
  502. package/src/runtime/middleware/auth.ts +0 -20
  503. package/src/runtime/migrations/__tests__/v1-test-helpers.ts +112 -0
  504. package/src/runtime/migrations/__tests__/vbundle-builder-credentials.test.ts +11 -4
  505. package/src/runtime/migrations/__tests__/vbundle-builder-v1-shape.test.ts +253 -0
  506. package/src/runtime/migrations/__tests__/vbundle-import-credentials.test.ts +19 -6
  507. package/src/runtime/migrations/__tests__/vbundle-legacy-user-md.test.ts +71 -27
  508. package/src/runtime/migrations/__tests__/vbundle-metadata-merge-integration.test.ts +41 -2
  509. package/src/runtime/migrations/__tests__/vbundle-streaming-importer.test.ts +143 -79
  510. package/src/runtime/migrations/__tests__/vbundle-streaming-validator.test.ts +143 -23
  511. package/src/runtime/migrations/__tests__/vbundle-tar-stream.test.ts +2 -2
  512. package/src/runtime/migrations/__tests__/vbundle-validator-v1-schema.test.ts +371 -0
  513. package/src/runtime/migrations/migration-transport.ts +46 -13
  514. package/src/runtime/migrations/migration-wizard.ts +2 -2
  515. package/src/runtime/migrations/origin-mode.ts +40 -0
  516. package/src/runtime/migrations/vbundle-builder.ts +133 -79
  517. package/src/runtime/migrations/vbundle-import-analyzer.ts +9 -7
  518. package/src/runtime/migrations/vbundle-importer.ts +7 -7
  519. package/src/runtime/migrations/vbundle-metadata-merge.ts +1 -1
  520. package/src/runtime/migrations/vbundle-streaming-importer.ts +3 -3
  521. package/src/runtime/migrations/vbundle-streaming-validator.ts +48 -26
  522. package/src/runtime/migrations/vbundle-validator.ts +214 -41
  523. package/src/runtime/pending-interactions.ts +13 -4
  524. package/src/runtime/routes/__tests__/acp-routes.test.ts +0 -1
  525. package/src/runtime/routes/__tests__/backup-routes.test.ts +28 -19
  526. package/src/runtime/routes/__tests__/conversation-query-routes.test.ts +235 -0
  527. package/src/runtime/routes/__tests__/llm-call-sites-routes.test.ts +58 -0
  528. package/src/runtime/routes/__tests__/migration-export-secrets-redacted.test.ts +54 -0
  529. package/src/runtime/routes/__tests__/migration-import-credential-filter.test.ts +19 -6
  530. package/src/runtime/routes/__tests__/user-route-dispatcher.test.ts +7 -7
  531. package/src/runtime/routes/acp-routes.test.ts +0 -3
  532. package/src/runtime/routes/acp-routes.ts +3 -7
  533. package/src/runtime/routes/app-management-routes.ts +18 -9
  534. package/src/runtime/routes/approval-routes.ts +55 -14
  535. package/src/runtime/routes/avatar-routes.ts +3 -5
  536. package/src/runtime/routes/browser-routes.ts +1 -15
  537. package/src/runtime/routes/channel-guardian-routes.ts +1 -5
  538. package/src/runtime/routes/channel-readiness-routes.ts +3 -7
  539. package/src/runtime/routes/channel-route-shared.ts +2 -28
  540. package/src/runtime/routes/client-routes.ts +45 -12
  541. package/src/runtime/routes/consolidation-routes.ts +115 -0
  542. package/src/runtime/routes/conversation-list-routes.ts +12 -29
  543. package/src/runtime/routes/conversation-management-routes.ts +14 -51
  544. package/src/runtime/routes/conversation-query-routes.ts +120 -8
  545. package/src/runtime/routes/conversation-routes.ts +44 -528
  546. package/src/runtime/routes/conversation-starter-routes.ts +19 -40
  547. package/src/runtime/routes/documents-routes.ts +53 -18
  548. package/src/runtime/routes/events-routes.ts +59 -91
  549. package/src/runtime/routes/filing-routes.ts +18 -1
  550. package/src/runtime/routes/guardian-action-routes.ts +4 -9
  551. package/src/runtime/routes/host-bash-routes.ts +3 -2
  552. package/src/runtime/routes/host-browser-routes.ts +9 -33
  553. package/src/runtime/routes/host-cu-routes.ts +6 -1
  554. package/src/runtime/routes/host-file-routes.ts +3 -2
  555. package/src/runtime/routes/host-transfer-routes.ts +11 -15
  556. package/src/runtime/routes/identity-routes.ts +78 -6
  557. package/src/runtime/routes/inbound-message-handler.ts +580 -137
  558. package/src/runtime/routes/inbound-stages/acl-enforcement.ts +2 -88
  559. package/src/runtime/routes/inbound-stages/background-dispatch.ts +3 -0
  560. package/src/runtime/routes/index.ts +4 -0
  561. package/src/runtime/routes/integrations/slack/channel.ts +0 -24
  562. package/src/runtime/routes/llm-call-sites-routes.ts +22 -0
  563. package/src/runtime/routes/memory-v2-routes.ts +10 -15
  564. package/src/runtime/routes/migration-routes.ts +188 -31
  565. package/src/runtime/routes/playground/guard.ts +1 -1
  566. package/src/runtime/routes/playground/index.ts +0 -2
  567. package/src/runtime/routes/recording-routes.ts +4 -24
  568. package/src/runtime/routes/rename-conversation-routes.ts +2 -6
  569. package/src/runtime/routes/schedule-routes.ts +3 -6
  570. package/src/runtime/routes/secret-routes.ts +87 -18
  571. package/src/runtime/routes/settings-routes.ts +29 -28
  572. package/src/runtime/routes/skills-routes.ts +12 -31
  573. package/src/runtime/routes/suggest-trust-rule-routes.ts +32 -1
  574. package/src/runtime/routes/task-routes.ts +6 -6
  575. package/src/runtime/routes/trust-rules-routes.ts +3 -94
  576. package/src/runtime/routes/types.ts +4 -4
  577. package/src/runtime/routes/upgrade-broadcast-routes.ts +3 -10
  578. package/src/runtime/routes/usage-routes.ts +87 -10
  579. package/src/runtime/routes/user-routes.ts +17 -31
  580. package/src/runtime/routes/work-items-routes.ts +1 -4
  581. package/src/runtime/services/__tests__/analyze-conversation.test.ts +2 -2
  582. package/src/runtime/services/analyze-conversation.ts +7 -17
  583. package/src/runtime/services/conversation-serializer.ts +2 -4
  584. package/src/runtime/verification-outbound-actions.ts +1 -1
  585. package/src/runtime/verification-rate-limiter.ts +1 -1
  586. package/src/schedule/schedule-store.ts +0 -16
  587. package/src/security/secret-scanner.ts +14 -547
  588. package/src/security/secure-keys.ts +31 -11
  589. package/src/security/token-manager.ts +7 -3
  590. package/src/signals/cancel.ts +16 -25
  591. package/src/signals/conversation-undo.ts +2 -27
  592. package/src/signals/emit-event.ts +1 -2
  593. package/src/signals/user-message.ts +108 -22
  594. package/src/skills/catalog-install.ts +1 -0
  595. package/src/skills/clawhub.ts +2 -2
  596. package/src/skills/inline-command-runner.ts +1 -7
  597. package/src/subagent/manager.ts +67 -84
  598. package/src/tasks/task-store.ts +1 -28
  599. package/src/telemetry/types.ts +6 -0
  600. package/src/telemetry/usage-telemetry-reporter.test.ts +38 -15
  601. package/src/telemetry/usage-telemetry-reporter.ts +3 -5
  602. package/src/tools/acp/spawn.test.ts +1 -2
  603. package/src/tools/acp/steer.test.ts +1 -2
  604. package/src/tools/browser/__tests__/browser-status.test.ts +44 -127
  605. package/src/tools/browser/browser-execution.ts +31 -147
  606. package/src/tools/browser/cdp-client/__tests__/factory.test.ts +92 -68
  607. package/src/tools/browser/cdp-client/factory.ts +48 -76
  608. package/src/tools/browser/cdp-client/index.ts +1 -14
  609. package/src/tools/executor.ts +44 -31
  610. package/src/tools/host-filesystem/edit.ts +3 -2
  611. package/src/tools/host-filesystem/read.ts +3 -2
  612. package/src/tools/host-filesystem/transfer.test.ts +45 -42
  613. package/src/tools/host-filesystem/transfer.ts +4 -3
  614. package/src/tools/host-filesystem/write.ts +3 -2
  615. package/src/tools/host-terminal/host-shell.ts +4 -3
  616. package/src/tools/network/script-proxy/index.ts +1 -10
  617. package/src/tools/permission-checker.ts +66 -1
  618. package/src/tools/skills/sandbox-runner.ts +1 -6
  619. package/src/tools/skills/skill-tool-factory.ts +32 -0
  620. package/src/tools/terminal/safe-env.ts +1 -0
  621. package/src/tools/terminal/shell.ts +2 -78
  622. package/src/tools/types.ts +12 -39
  623. package/src/tts/__tests__/provider-catalog.test.ts +2 -2
  624. package/src/tts/provider-catalog.ts +1 -1
  625. package/src/usage/actors.ts +2 -1
  626. package/src/usage/attribution.ts +185 -0
  627. package/src/usage/pricing.ts +166 -0
  628. package/src/usage/types.ts +14 -0
  629. package/src/util/json.ts +13 -0
  630. package/src/util/logger.ts +3 -3
  631. package/src/util/pricing.ts +50 -3
  632. package/src/work-items/work-item-runner.ts +15 -42
  633. package/src/workspace/migrations/050-seed-main-agent-opus-callsite.ts +4 -3
  634. package/src/workspace/migrations/052-seed-default-inference-profiles.ts +3 -3
  635. package/src/workspace/migrations/060-memory-v2-init.ts +2 -18
  636. package/src/workspace/migrations/061-move-backup-key-to-workspace.ts +59 -0
  637. package/src/workspace/migrations/062-drop-memory-v2-edges-json.ts +27 -0
  638. package/src/workspace/migrations/063-release-notes-dynamic-model-context.ts +70 -0
  639. package/src/workspace/migrations/064-unwind-main-agent-opus-seed.ts +64 -0
  640. package/src/workspace/migrations/registry.ts +8 -0
  641. package/src/workspace/provider-commit-message-generator.ts +3 -3
  642. package/src/__tests__/sandbox-diagnostics.test.ts +0 -138
  643. package/src/__tests__/sandbox-host-parity.test.ts +0 -1024
  644. package/src/__tests__/secret-detection-handler.test.ts +0 -67
  645. package/src/__tests__/secret-scanner-executor.test.ts +0 -450
  646. package/src/__tests__/tcc-sandbox-deny.test.ts +0 -198
  647. package/src/__tests__/terminal-sandbox.test.ts +0 -374
  648. package/src/__tests__/tool-notification-listener.test.ts +0 -65
  649. package/src/context/__tests__/microcompact.test.ts +0 -805
  650. package/src/context/microcompact.ts +0 -443
  651. package/src/daemon/handlers/slack-channel-oauth-install.ts +0 -197
  652. package/src/events/tool-notification-listener.ts +0 -17
  653. package/src/ipc/routes/__tests__/memory-v2-validate.test.ts +0 -219
  654. package/src/memory/v2/__tests__/edges.test.ts +0 -435
  655. package/src/memory/v2/edges.ts +0 -217
  656. package/src/prompts/__tests__/system-prompt-memory-v2.test.ts +0 -197
  657. package/src/runtime/__tests__/chrome-extension-registry.test.ts +0 -518
  658. package/src/runtime/__tests__/client-registry.test.ts +0 -271
  659. package/src/runtime/chrome-extension-registry.ts +0 -368
  660. package/src/runtime/client-registry.ts +0 -254
  661. package/src/runtime/routes/inbound-stages/verification-intercept.ts +0 -329
  662. package/src/tools/secret-detection-handler.ts +0 -269
  663. package/src/tools/terminal/backends/native.ts +0 -327
  664. package/src/tools/terminal/backends/types.ts +0 -37
  665. package/src/tools/terminal/sandbox-diagnostics.ts +0 -87
  666. package/src/tools/terminal/sandbox.ts +0 -40
@@ -23,8 +23,8 @@
23
23
  *
24
24
  * - `host.events.buildEvent` — deterministic helper. Params
25
25
  * `{ message, conversationId? }`. Returns the `AssistantEvent` envelope a
26
- * skill would otherwise construct via `DAEMON_INTERNAL_ASSISTANT_ID`
27
- * keeping event-id allocation and timestamp generation on the daemon side
26
+ * skill would otherwise construct locally keeping event-id allocation
27
+ * and timestamp generation on the daemon side
28
28
  * so skill processes do not drift on UUID / clock sources.
29
29
  */
30
30
 
@@ -32,9 +32,8 @@ import { z } from "zod";
32
32
 
33
33
  import { buildAssistantEvent } from "../../runtime/assistant-event.js";
34
34
  import { assistantEventHub } from "../../runtime/assistant-event-hub.js";
35
- import { DAEMON_INTERNAL_ASSISTANT_ID } from "../../runtime/assistant-scope.js";
36
35
  import type { SkillIpcRoute } from "../skill-ipc-types.js";
37
- import type { SkillIpcStreamingRoute } from "../skill-server.js";
36
+ import type { SkillIpcStreamingRoute } from "../skill-ipc-types.js";
38
37
 
39
38
  // ---------------------------------------------------------------------------
40
39
  // Param schemas
@@ -42,14 +41,13 @@ import type { SkillIpcStreamingRoute } from "../skill-server.js";
42
41
 
43
42
  /**
44
43
  * `AssistantEvent` wire shape accepted by `host.events.publish`. The
45
- * envelope fields (`id`, `assistantId`, `emittedAt`, `message`) are
46
- * required; `conversationId` is optional. The `message` payload is an
47
- * opaque JSON object — the daemon does not narrow it before handing it to
44
+ * envelope fields (`id`, `emittedAt`, `message`) are required;
45
+ * `conversationId` is optional. The `message` payload is an opaque JSON
46
+ * object — the daemon does not narrow it before handing it to
48
47
  * `assistantEventHub.publish`, matching the in-process hub contract.
49
48
  */
50
49
  const AssistantEventSchema = z.object({
51
50
  id: z.string().min(1),
52
- assistantId: z.string().min(1),
53
51
  conversationId: z.string().optional(),
54
52
  emittedAt: z.string().min(1),
55
53
  message: z.record(z.string(), z.unknown()),
@@ -60,7 +58,6 @@ const PublishParams = z.object({
60
58
  });
61
59
 
62
60
  const FilterSchema = z.object({
63
- assistantId: z.string().min(1),
64
61
  conversationId: z.string().optional(),
65
62
  });
66
63
 
@@ -90,11 +87,7 @@ async function handlePublish(
90
87
 
91
88
  function handleBuildEvent(params?: Record<string, unknown>): unknown {
92
89
  const { message, conversationId } = BuildEventParams.parse(params);
93
- return buildAssistantEvent(
94
- DAEMON_INTERNAL_ASSISTANT_ID,
95
- message as never,
96
- conversationId,
97
- );
90
+ return buildAssistantEvent(message as never, conversationId);
98
91
  }
99
92
 
100
93
  // ---------------------------------------------------------------------------
@@ -111,18 +104,14 @@ export const eventsStreamingRoutes: SkillIpcStreamingRoute[] = [
111
104
  method: "host.events.subscribe",
112
105
  handler: (stream, params) => {
113
106
  const { filter } = SubscribeParams.parse(params);
114
- const subscription = assistantEventHub.subscribe(
107
+ const subscription = assistantEventHub.subscribe({
108
+ type: "process",
115
109
  filter,
116
- (event) => {
110
+ callback: (event) => {
117
111
  stream.send(event);
118
112
  },
119
- // The hub evicts the oldest subscriber when its cap fills. Without
120
- // this callback the IPC stream would silently stop receiving events
121
- // while the client still believed it was subscribed. Mirror the SSE
122
- // route's behavior by tearing the stream down with a terminal error
123
- // frame so the client can resubscribe.
124
- { onEvict: () => stream.close("subscription evicted by hub cap") },
125
- );
113
+ onEvict: () => stream.close("subscription evicted by hub cap"),
114
+ });
126
115
  return () => {
127
116
  subscription.dispose();
128
117
  };
@@ -1,17 +1,12 @@
1
1
  /**
2
- * Skill IPC routes: `host.identity.getAssistantName` and
3
- * `host.identity.getInternalAssistantId`.
2
+ * Skill IPC route: `host.identity.getAssistantName`.
4
3
  *
5
- * Match the `IdentityFacet` surface exposed by `DaemonSkillHost`:
6
- * - `getAssistantName` reads the assistant's display name from IDENTITY.md,
7
- * normalizing the daemon helper's `null` to `undefined` (serialized as
8
- * `null` over JSON, which clients translate back to `undefined`).
9
- * - `getInternalAssistantId` returns the `DAEMON_INTERNAL_ASSISTANT_ID`
10
- * constant (`"self"`) so skill-side code uses the same internal scope.
4
+ * Reads the assistant's display name from IDENTITY.md, normalizing the
5
+ * daemon helper's `null` to `undefined` (serialized as `null` over JSON,
6
+ * which clients translate back to `undefined`).
11
7
  */
12
8
 
13
9
  import { getAssistantName } from "../../daemon/identity-helpers.js";
14
- import { DAEMON_INTERNAL_ASSISTANT_ID } from "../../runtime/assistant-scope.js";
15
10
  import type { SkillIpcRoute } from "../skill-ipc-types.js";
16
11
 
17
12
  export const hostIdentityGetAssistantNameRoute: SkillIpcRoute = {
@@ -21,14 +16,6 @@ export const hostIdentityGetAssistantNameRoute: SkillIpcRoute = {
21
16
  },
22
17
  };
23
18
 
24
- export const hostIdentityGetInternalAssistantIdRoute: SkillIpcRoute = {
25
- method: "host.identity.getInternalAssistantId",
26
- handler: () => {
27
- return DAEMON_INTERNAL_ASSISTANT_ID;
28
- },
29
- };
30
-
31
19
  export const identityRoutes: SkillIpcRoute[] = [
32
20
  hostIdentityGetAssistantNameRoute,
33
- hostIdentityGetInternalAssistantIdRoute,
34
21
  ];
@@ -1,5 +1,5 @@
1
1
  import type { SkillIpcRoute } from "../skill-ipc-types.js";
2
- import type { SkillIpcStreamingRoute } from "../skill-server.js";
2
+ import type { SkillIpcStreamingRoute } from "../skill-ipc-types.js";
3
3
  import { configRoutes } from "./config.js";
4
4
  import { eventsRoutes, eventsStreamingRoutes } from "./events.js";
5
5
  import { identityRoutes } from "./identity.js";
@@ -50,7 +50,11 @@ import { getLogger } from "../util/logger.js";
50
50
  import type { IpcRequest, IpcResponse } from "./assistant-server.js";
51
51
 
52
52
  export type { SkillIpcRoute, SkillMethodHandler } from "./skill-ipc-types.js";
53
- import type { SkillMethodHandler } from "./skill-ipc-types.js";
53
+ import type {
54
+ SkillIpcStream,
55
+ SkillIpcStreamingHandler,
56
+ SkillMethodHandler,
57
+ } from "./skill-ipc-types.js";
54
58
  import {
55
59
  skillIpcRoutes,
56
60
  skillIpcStreamingRoutes,
@@ -82,28 +86,6 @@ const DEFAULT_SEND_REQUEST_TIMEOUT_MS = 30_000;
82
86
  const SKILL_IPC_SUBSCRIBE_CLOSE_METHOD = "host.events.subscribe.close" as const;
83
87
 
84
88
  /** Stream handle passed to streaming-handler implementations. */
85
- export interface SkillIpcStream {
86
- /** The original request id that opened this stream (used as the stream id). */
87
- readonly id: string;
88
- /**
89
- * Send a delivery frame to the client. No-op after the stream has been
90
- * closed (client disconnect, explicit close, or server shutdown).
91
- */
92
- send(payload: unknown): void;
93
- /**
94
- * Terminate the stream from the server side. Sends a final error frame to
95
- * the client (if `errorMessage` is provided and the socket is still
96
- * writable), invokes the handler-returned dispose, and unregisters the
97
- * stream from the per-socket subscription map. Idempotent — subsequent
98
- * calls are no-ops. Use from `onEvict`-style callbacks where the upstream
99
- * source has decided to terminate the subscription, or to surface
100
- * unrecoverable conditions like backpressure.
101
- */
102
- close(errorMessage?: string): void;
103
- /** True until the stream has been disposed. */
104
- readonly active: boolean;
105
- }
106
-
107
89
  /**
108
90
  * Maximum bytes Node may have queued in the socket's outbound buffer before
109
91
  * the next streaming `send` will close the stream with a backpressure error.
@@ -115,22 +97,7 @@ export interface SkillIpcStream {
115
97
  */
116
98
  const STREAM_BACKPRESSURE_BYTES = 1024 * 1024;
117
99
 
118
- /**
119
- * Handler signature for long-lived streaming methods (e.g.
120
- * `host.events.subscribe`). Runs synchronously with the opening request and
121
- * returns a dispose callback that the server invokes on client disconnect,
122
- * explicit close, or server shutdown.
123
- */
124
- export type SkillIpcStreamingHandler = (
125
- stream: SkillIpcStream,
126
- params?: Record<string, unknown>,
127
- ) => () => void;
128
-
129
- /** Long-lived streaming route — method name + handler function. */
130
- export type SkillIpcStreamingRoute = {
131
- method: string;
132
- handler: SkillIpcStreamingHandler;
133
- };
100
+
134
101
 
135
102
  // ---------------------------------------------------------------------------
136
103
  // Per-connection context
@@ -97,7 +97,6 @@ type JsonFrame = Record<string, unknown>;
97
97
 
98
98
  const savedAuthEnv = {
99
99
  DISABLE_HTTP_AUTH: process.env.DISABLE_HTTP_AUTH,
100
- VELLUM_UNSAFE_AUTH_BYPASS: process.env.VELLUM_UNSAFE_AUTH_BYPASS,
101
100
  };
102
101
 
103
102
  function mintGatewayToken(): string {
@@ -238,7 +237,6 @@ describe("RuntimeHttpServer live voice WebSocket shell", () => {
238
237
 
239
238
  beforeEach(async () => {
240
239
  delete process.env.DISABLE_HTTP_AUTH;
241
- delete process.env.VELLUM_UNSAFE_AUTH_BYPASS;
242
240
  resolveStreamingTranscriberImpl = async () => createResolvedTranscriber();
243
241
  resolveStreamingTranscriberMock.mockClear();
244
242
  resolvedTranscribers.length = 0;
@@ -260,12 +258,6 @@ describe("RuntimeHttpServer live voice WebSocket shell", () => {
260
258
  } else {
261
259
  process.env.DISABLE_HTTP_AUTH = savedAuthEnv.DISABLE_HTTP_AUTH;
262
260
  }
263
- if (savedAuthEnv.VELLUM_UNSAFE_AUTH_BYPASS === undefined) {
264
- delete process.env.VELLUM_UNSAFE_AUTH_BYPASS;
265
- } else {
266
- process.env.VELLUM_UNSAFE_AUTH_BYPASS =
267
- savedAuthEnv.VELLUM_UNSAFE_AUTH_BYPASS;
268
- }
269
261
  });
270
262
 
271
263
  function openLiveVoiceClient(token = mintGatewayToken()): WebSocket {
@@ -1,4 +1,4 @@
1
- export const LIVE_VOICE_CLIENT_FRAME_TYPES = [
1
+ const LIVE_VOICE_CLIENT_FRAME_TYPES = [
2
2
  "start",
3
3
  "audio",
4
4
  "ptt_release",
@@ -9,7 +9,7 @@ export const LIVE_VOICE_CLIENT_FRAME_TYPES = [
9
9
  export type LiveVoiceClientFrameType =
10
10
  (typeof LIVE_VOICE_CLIENT_FRAME_TYPES)[number];
11
11
 
12
- export const LIVE_VOICE_SERVER_FRAME_TYPES = [
12
+ const _LIVE_VOICE_SERVER_FRAME_TYPES = [
13
13
  "ready",
14
14
  "busy",
15
15
  "stt_partial",
@@ -24,7 +24,7 @@ export const LIVE_VOICE_SERVER_FRAME_TYPES = [
24
24
  ] as const;
25
25
 
26
26
  export type LiveVoiceServerFrameType =
27
- (typeof LIVE_VOICE_SERVER_FRAME_TYPES)[number];
27
+ (typeof _LIVE_VOICE_SERVER_FRAME_TYPES)[number];
28
28
 
29
29
  export const LiveVoiceProtocolErrorCode = {
30
30
  InvalidJson: "invalid_json",
@@ -38,15 +38,6 @@ export const LiveVoiceProtocolErrorCode = {
38
38
  export type LiveVoiceProtocolErrorCode =
39
39
  (typeof LiveVoiceProtocolErrorCode)[keyof typeof LiveVoiceProtocolErrorCode];
40
40
 
41
- export const LIVE_VOICE_PROTOCOL_ERROR_CODES = [
42
- LiveVoiceProtocolErrorCode.InvalidJson,
43
- LiveVoiceProtocolErrorCode.InvalidFrame,
44
- LiveVoiceProtocolErrorCode.UnknownType,
45
- LiveVoiceProtocolErrorCode.MissingRequiredField,
46
- LiveVoiceProtocolErrorCode.InvalidField,
47
- LiveVoiceProtocolErrorCode.InvalidAudioPayload,
48
- ] as const satisfies readonly LiveVoiceProtocolErrorCode[];
49
-
50
41
  export interface LiveVoiceProtocolError {
51
42
  readonly code: LiveVoiceProtocolErrorCode;
52
43
  readonly message: string;
@@ -208,7 +199,7 @@ export type LiveVoiceServerFramePayload =
208
199
  | WithoutSeq<LiveVoiceArchivedServerFrame>
209
200
  | WithoutSeq<LiveVoiceErrorServerFrame>;
210
201
 
211
- export class LiveVoiceServerFrameSequencer {
202
+ class LiveVoiceServerFrameSequencer {
212
203
  private seq: number;
213
204
 
214
205
  constructor(initialSeq = 0) {
@@ -169,8 +169,3 @@ export function getMcpServerManager(): McpServerManager {
169
169
  }
170
170
  return instance;
171
171
  }
172
-
173
- /** Reset singleton for testing. */
174
- export function __resetMcpManagerForTesting(): void {
175
- instance = null;
176
- }
@@ -0,0 +1,55 @@
1
+ import type {
2
+ MemoryV2ConceptRowRecord,
3
+ MemoryV2ConfigSnapshot,
4
+ MemoryV2SkillRowRecord,
5
+ } from "../../memory-v2-activation-log-store.js";
6
+
7
+ export const sampleConcepts: MemoryV2ConceptRowRecord[] = [
8
+ {
9
+ slug: "concept-a",
10
+ finalActivation: 0.9,
11
+ ownActivation: 0.7,
12
+ priorActivation: 0.5,
13
+ simUser: 0.6,
14
+ simAssistant: 0.4,
15
+ simNow: 0.3,
16
+ spreadContribution: 0.2,
17
+ source: "both",
18
+ status: "injected",
19
+ },
20
+ {
21
+ slug: "concept-b",
22
+ finalActivation: 0.4,
23
+ ownActivation: 0.3,
24
+ priorActivation: 0.1,
25
+ simUser: 0.2,
26
+ simAssistant: 0.1,
27
+ simNow: 0.05,
28
+ spreadContribution: 0.0,
29
+ source: "ann_top50",
30
+ status: "not_injected",
31
+ },
32
+ ];
33
+
34
+ export const sampleSkills: MemoryV2SkillRowRecord[] = [
35
+ {
36
+ id: "skill-1",
37
+ activation: 0.8,
38
+ simUser: 0.5,
39
+ simAssistant: 0.4,
40
+ simNow: 0.3,
41
+ status: "injected",
42
+ },
43
+ ];
44
+
45
+ export const sampleConfig: MemoryV2ConfigSnapshot = {
46
+ d: 0.85,
47
+ c_user: 1.0,
48
+ c_assistant: 0.5,
49
+ c_now: 0.25,
50
+ k: 5,
51
+ hops: 2,
52
+ top_k: 10,
53
+ top_k_skills: 3,
54
+ epsilon: 0.001,
55
+ };
@@ -0,0 +1,127 @@
1
+ import { beforeEach, describe, expect, mock, test } from "bun:test";
2
+
3
+ mock.module("../../util/logger.js", () => ({
4
+ getLogger: () =>
5
+ new Proxy({} as Record<string, unknown>, {
6
+ get: () => () => {},
7
+ }),
8
+ }));
9
+
10
+ mock.module("../../config/loader.js", () => ({
11
+ getConfig: () => ({
12
+ ui: {},
13
+ model: "test",
14
+ provider: "test",
15
+ memory: { enabled: false },
16
+ rateLimit: { maxRequestsPerMinute: 0 },
17
+ secretDetection: { enabled: false },
18
+ }),
19
+ }));
20
+
21
+ import { getDb } from "../db-connection.js";
22
+ import { initializeDb } from "../db-init.js";
23
+ import {
24
+ backfillMemoryV2ActivationMessageId,
25
+ getMemoryV2ActivationLogByMessageIds,
26
+ recordMemoryV2ActivationLog,
27
+ } from "../memory-v2-activation-log-store.js";
28
+ import { memoryV2ActivationLogs } from "../schema.js";
29
+ import {
30
+ sampleConcepts,
31
+ sampleConfig,
32
+ sampleSkills,
33
+ } from "./fixtures/memory-v2-activation-fixtures.js";
34
+
35
+ initializeDb();
36
+
37
+ function resetTables(): void {
38
+ const db = getDb();
39
+ db.delete(memoryV2ActivationLogs).run();
40
+ }
41
+
42
+ describe("memory-v2-activation-log-store", () => {
43
+ beforeEach(() => {
44
+ resetTables();
45
+ });
46
+
47
+ test("round-trip: record → backfill messageId → query by messageId", () => {
48
+ const conversationId = "conv-1";
49
+ const messageId = "msg-1";
50
+
51
+ recordMemoryV2ActivationLog({
52
+ conversationId,
53
+ turn: 3,
54
+ mode: "per-turn",
55
+ concepts: sampleConcepts,
56
+ skills: sampleSkills,
57
+ config: sampleConfig,
58
+ });
59
+
60
+ backfillMemoryV2ActivationMessageId(conversationId, messageId);
61
+
62
+ const result = getMemoryV2ActivationLogByMessageIds([messageId]);
63
+ expect(result).not.toBeNull();
64
+ expect(result!.conversationId).toBe(conversationId);
65
+ expect(result!.turn).toBe(3);
66
+ expect(result!.mode).toBe("per-turn");
67
+ expect(result!.concepts).toEqual(sampleConcepts);
68
+ expect(result!.skills).toEqual(sampleSkills);
69
+ expect(result!.config).toEqual(sampleConfig);
70
+ });
71
+
72
+ test("returns null for empty messageIds array", () => {
73
+ const result = getMemoryV2ActivationLogByMessageIds([]);
74
+ expect(result).toBeNull();
75
+ });
76
+
77
+ test("backfill only updates rows with NULL messageId", () => {
78
+ const conversationId = "conv-2";
79
+
80
+ recordMemoryV2ActivationLog({
81
+ conversationId,
82
+ turn: 1,
83
+ mode: "context-load",
84
+ concepts: sampleConcepts,
85
+ skills: sampleSkills,
86
+ config: sampleConfig,
87
+ });
88
+ recordMemoryV2ActivationLog({
89
+ conversationId,
90
+ turn: 2,
91
+ mode: "per-turn",
92
+ concepts: sampleConcepts,
93
+ skills: sampleSkills,
94
+ config: sampleConfig,
95
+ });
96
+
97
+ // First backfill: both rows should now have msg-a.
98
+ backfillMemoryV2ActivationMessageId(conversationId, "msg-a");
99
+
100
+ const db = getDb();
101
+ const afterFirstBackfill = db.select().from(memoryV2ActivationLogs).all();
102
+ expect(afterFirstBackfill).toHaveLength(2);
103
+ for (const row of afterFirstBackfill) {
104
+ expect(row.messageId).toBe("msg-a");
105
+ }
106
+
107
+ // Record a third row (messageId is NULL initially).
108
+ recordMemoryV2ActivationLog({
109
+ conversationId,
110
+ turn: 3,
111
+ mode: "per-turn",
112
+ concepts: sampleConcepts,
113
+ skills: sampleSkills,
114
+ config: sampleConfig,
115
+ });
116
+
117
+ // Second backfill with msg-b should only set the third row,
118
+ // and must not overwrite the first two rows already set to msg-a.
119
+ backfillMemoryV2ActivationMessageId(conversationId, "msg-b");
120
+
121
+ const afterSecondBackfill = db.select().from(memoryV2ActivationLogs).all();
122
+ const byTurn = new Map(afterSecondBackfill.map((r) => [r.turn, r]));
123
+ expect(byTurn.get(1)!.messageId).toBe("msg-a");
124
+ expect(byTurn.get(2)!.messageId).toBe("msg-a");
125
+ expect(byTurn.get(3)!.messageId).toBe("msg-b");
126
+ });
127
+ });
@@ -132,38 +132,6 @@ function validateRelativePath(path: string): void {
132
132
  }
133
133
  }
134
134
 
135
- // ---------------------------------------------------------------------------
136
- // Initialization & commit
137
- // ---------------------------------------------------------------------------
138
-
139
- /**
140
- * Eagerly initialize the app git repo so that the "Initial commit" is
141
- * created before any app files are written. Without this, the first
142
- * mutation's files get absorbed into WorkspaceGitService's bootstrap
143
- * commit and the "Create app: ..." commit ends up empty.
144
- *
145
- * Safe to call multiple times -- ensureInitialized() is idempotent.
146
- * Commit app changes to the apps git repository.
147
- *
148
- * This is fire-and-forget: errors are logged but never thrown.
149
- * The caller should not await the returned promise unless it needs
150
- * to guarantee the commit completed (e.g. in tests).
151
- */
152
- export async function commitAppChange(message: string): Promise<void> {
153
- try {
154
- const appsDir = getAppsDir();
155
-
156
- // Re-check .gitignore rules every call in case the apps dir was
157
- // recreated while the process was running.
158
- ensureAppGitignoreRules(appsDir);
159
-
160
- const gitService = getWorkspaceGitService(appsDir);
161
- await gitService.commitChanges(message);
162
- } catch (err) {
163
- log.error({ err, message }, "Failed to commit app change");
164
- }
165
- }
166
-
167
135
  /**
168
136
  * Commit app changes at turn boundaries.
169
137
  *
@@ -36,7 +36,9 @@ import {
36
36
 
37
37
  import type { EditEngineResult } from "../tools/shared/filesystem/edit-engine.js";
38
38
  import { applyEdit } from "../tools/shared/filesystem/edit-engine.js";
39
+ import { getLogger } from "../util/logger.js";
39
40
  import { getDataDir } from "../util/platform.js";
41
+ import { rawAll } from "./raw-query.js";
40
42
 
41
43
  export interface AppDefinition {
42
44
  id: string;
@@ -55,6 +57,8 @@ export interface AppDefinition {
55
57
  formatVersion?: number;
56
58
  /** Filesystem directory/file stem. Frozen at creation -- never changes on rename. */
57
59
  dirName?: string;
60
+ /** Conversation IDs that have interacted with this app (create/open/refresh). */
61
+ conversationIds?: string[];
58
62
  }
59
63
 
60
64
  /**
@@ -901,4 +905,154 @@ export function editAppFile(
901
905
  return result;
902
906
  }
903
907
 
908
+ // ---------------------------------------------------------------------------
909
+ // Conversation association helpers
910
+ // ---------------------------------------------------------------------------
911
+
912
+ /**
913
+ * Associate a conversation with an app. Writes directly to the JSON metadata
914
+ * file without bumping `updatedAt` so the app list ordering is preserved.
915
+ *
916
+ * @returns `true` if the association was added, `false` if the app was not
917
+ * found or the conversationId was already present (dedup).
918
+ */
919
+ export function addAppConversationId(
920
+ appId: string,
921
+ conversationId: string,
922
+ ): boolean {
923
+ const app = getApp(appId);
924
+ if (!app) return false;
925
+
926
+ const { dirName } = resolveAppDir(appId);
927
+ const dir = getAppsDir();
928
+ const jsonPath = join(dir, `${dirName}.json`);
929
+
930
+ // Atomic read-modify-write: re-read the file immediately before writing
931
+ // so concurrent callers (e.g. two tool_result handlers for the same app
932
+ // in different conversations) merge against the latest on-disk state.
933
+ // Because readFileSync → JSON.parse → writeFileSync is a synchronous
934
+ // chain with no async gaps, Node/Bun's single-threaded event loop
935
+ // guarantees no interleaving between the read and the write.
936
+ const raw = readFileSync(jsonPath, "utf-8");
937
+ const parsed = JSON.parse(raw) as Record<string, unknown>;
938
+ const onDiskIds = Array.isArray(parsed.conversationIds)
939
+ ? (parsed.conversationIds as string[])
940
+ : [];
941
+
942
+ if (onDiskIds.includes(conversationId)) return false;
943
+
944
+ parsed.conversationIds = [...onDiskIds, conversationId];
945
+ writeFileSync(jsonPath, JSON.stringify(parsed, null, 2));
946
+
947
+ return true;
948
+ }
949
+
950
+ /**
951
+ * Return all apps associated with a given conversation ID.
952
+ */
953
+ export function listAppsByConversation(
954
+ conversationId: string,
955
+ ): AppDefinition[] {
956
+ return listApps().filter((app) =>
957
+ app.conversationIds?.includes(conversationId),
958
+ );
959
+ }
960
+
961
+ // ---------------------------------------------------------------------------
962
+ // Backfill: scan message history for ui_surface blocks referencing apps
963
+ // ---------------------------------------------------------------------------
964
+
965
+ /**
966
+ * Single-pass scan over the messages table to populate `conversationIds` on
967
+ * existing app definitions. Finds messages containing `ui_surface` blocks
968
+ * with a `data.appId`, then calls `addAppConversationId` for each pair.
969
+ *
970
+ * Runs once per workspace: after a successful backfill a sentinel file
971
+ * (`<appsDir>/.conversation-ids-backfilled`) is written. Subsequent daemon
972
+ * startups skip the scan entirely. If the apps directory is wiped the
973
+ * sentinel disappears and the backfill re-runs — which is correct behavior.
974
+ *
975
+ * Wrapped in try/catch so failures never block daemon start.
976
+ */
977
+ export function backfillAppConversationIds(): void {
978
+ const log = getLogger("app-store");
979
+
980
+ // Check sentinel — skip the potentially expensive scan when already done.
981
+ const sentinelPath = join(getAppsDir(), ".conversation-ids-backfilled");
982
+ if (existsSync(sentinelPath)) {
983
+ log.debug("Skipping backfillAppConversationIds — sentinel exists");
984
+ return;
985
+ }
986
+
987
+ try {
988
+ const rows = rawAll<{ conversation_id: string; content: string }>(
989
+ `SELECT conversation_id, content FROM messages WHERE content LIKE '%"type":"ui_surface"%'`,
990
+ );
991
+
992
+ // Build appId → Set<conversationId> map in a single pass
993
+ const appConvMap = new Map<string, Set<string>>();
994
+
995
+ for (const row of rows) {
996
+ let parsed: unknown;
997
+ try {
998
+ parsed = JSON.parse(row.content);
999
+ } catch {
1000
+ // Skip rows that fail to parse
1001
+ continue;
1002
+ }
1003
+
1004
+ if (!Array.isArray(parsed)) continue;
1005
+
1006
+ for (const block of parsed) {
1007
+ if (
1008
+ block &&
1009
+ typeof block === "object" &&
1010
+ (block as Record<string, unknown>).type === "ui_surface"
1011
+ ) {
1012
+ const data = (block as Record<string, unknown>).data;
1013
+ if (data && typeof data === "object") {
1014
+ const appId = (data as Record<string, unknown>).appId;
1015
+ if (typeof appId === "string" && appId.length > 0) {
1016
+ let convIds = appConvMap.get(appId);
1017
+ if (!convIds) {
1018
+ convIds = new Set<string>();
1019
+ appConvMap.set(appId, convIds);
1020
+ }
1021
+ convIds.add(row.conversation_id);
1022
+ }
1023
+ }
1024
+ }
1025
+ }
1026
+ }
1027
+
1028
+ // Apply associations
1029
+ let appsUpdated = 0;
1030
+ let associationsAdded = 0;
1031
+
1032
+ for (const [appId, conversationIds] of appConvMap) {
1033
+ let appHadNewAssociation = false;
1034
+ for (const conversationId of conversationIds) {
1035
+ const added = addAppConversationId(appId, conversationId);
1036
+ if (added) {
1037
+ associationsAdded++;
1038
+ appHadNewAssociation = true;
1039
+ }
1040
+ }
1041
+ if (appHadNewAssociation) {
1042
+ appsUpdated++;
1043
+ }
1044
+ }
1045
+
1046
+ log.info(
1047
+ { appsUpdated, associationsAdded },
1048
+ `Backfilled app conversationIds: ${appsUpdated} apps, ${associationsAdded} associations`,
1049
+ );
1050
+
1051
+ // Write sentinel so subsequent startups skip this scan.
1052
+ writeFileSync(sentinelPath, new Date().toISOString(), "utf-8");
1053
+ } catch (err) {
1054
+ log.error({ err }, "Failed to backfill app conversationIds");
1055
+ }
1056
+ }
1057
+
904
1058
  export type { EditEngineResult };