@vellumai/assistant 0.4.44 → 0.4.45

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 (681) hide show
  1. package/.prettierignore +4 -0
  2. package/ARCHITECTURE.md +34 -31
  3. package/README.md +4 -4
  4. package/bun.lock +10 -35
  5. package/docs/architecture/integrations.md +102 -197
  6. package/docs/architecture/keychain-broker.md +1 -1
  7. package/docs/architecture/memory.md +2 -2
  8. package/docs/architecture/scheduling.md +1 -1
  9. package/docs/architecture/security.md +11 -11
  10. package/docs/error-handling.md +1 -1
  11. package/docs/trusted-contact-access.md +3 -3
  12. package/drizzle/meta/0000_snapshot.json +34 -100
  13. package/drizzle/meta/_journal.json +1 -1
  14. package/drizzle.config.ts +4 -4
  15. package/package.json +3 -2
  16. package/scripts/capture-x-graphql.ts +237 -141
  17. package/scripts/generate-bundled-tool-registry.ts +223 -0
  18. package/src/__tests__/access-request-decision.test.ts +0 -1
  19. package/src/__tests__/actor-token-service.test.ts +23 -24
  20. package/src/__tests__/agent-loop.test.ts +0 -131
  21. package/src/__tests__/always-loaded-tools-guard.test.ts +71 -0
  22. package/src/__tests__/amazon-cdp-integration.test.ts +11 -9
  23. package/src/__tests__/approval-primitive.test.ts +0 -1
  24. package/src/__tests__/approval-routes-http.test.ts +11 -1
  25. package/src/__tests__/asset-materialize-tool.test.ts +0 -1
  26. package/src/__tests__/asset-search-tool.test.ts +0 -1
  27. package/src/__tests__/assistant-attachment-directive.test.ts +1 -1
  28. package/src/__tests__/assistant-events-sse-hardening.test.ts +0 -1
  29. package/src/__tests__/assistant-feature-flag-guardrails.test.ts +0 -2
  30. package/src/__tests__/assistant-feature-flags-integration.test.ts +70 -18
  31. package/src/__tests__/assistant-id-boundary-guard.test.ts +6 -6
  32. package/src/__tests__/attachments-store.test.ts +0 -1
  33. package/src/__tests__/avatar-e2e.test.ts +74 -115
  34. package/src/__tests__/avatar-router.test.ts +25 -62
  35. package/src/__tests__/browser-manager.test.ts +24 -0
  36. package/src/__tests__/browser-skill-baseline-tool-payload.test.ts +4 -3
  37. package/src/__tests__/browser-skill-endstate.test.ts +8 -11
  38. package/src/__tests__/btw-routes.test.ts +326 -0
  39. package/src/__tests__/bundled-skill-retrieval-guard.test.ts +23 -9
  40. package/src/__tests__/call-controller.test.ts +0 -1
  41. package/src/__tests__/call-conversation-messages.test.ts +0 -1
  42. package/src/__tests__/call-domain.test.ts +0 -1
  43. package/src/__tests__/call-pointer-messages.test.ts +0 -1
  44. package/src/__tests__/call-recovery.test.ts +0 -1
  45. package/src/__tests__/call-routes-http.test.ts +0 -1
  46. package/src/__tests__/call-store.test.ts +0 -1
  47. package/src/__tests__/canonical-guardian-store.test.ts +0 -1
  48. package/src/__tests__/channel-approval-routes.test.ts +1 -1
  49. package/src/__tests__/channel-approvals.test.ts +1 -1
  50. package/src/__tests__/channel-delivery-store.test.ts +0 -1
  51. package/src/__tests__/channel-guardian.test.ts +5 -7
  52. package/src/__tests__/channel-retry-sweep.test.ts +0 -1
  53. package/src/__tests__/checker.test.ts +4 -11
  54. package/src/__tests__/compaction.benchmark.test.ts +16 -14
  55. package/src/__tests__/computer-use-session-lifecycle.test.ts +10 -11
  56. package/src/__tests__/computer-use-session-working-dir.test.ts +2 -6
  57. package/src/__tests__/computer-use-skill-lifecycle-cleanup.test.ts +2 -5
  58. package/src/__tests__/computer-use-tools.test.ts +35 -31
  59. package/src/__tests__/config-schema.test.ts +11 -15
  60. package/src/__tests__/config-watcher.test.ts +0 -1
  61. package/src/__tests__/confirmation-request-guardian-bridge.test.ts +0 -1
  62. package/src/__tests__/conflict-store.test.ts +0 -1
  63. package/src/__tests__/connection-policy.test.ts +4 -7
  64. package/src/__tests__/contacts-tools.test.ts +0 -1
  65. package/src/__tests__/context-memory-e2e.test.ts +2 -4
  66. package/src/__tests__/context-overflow-reducer.test.ts +2 -4
  67. package/src/__tests__/context-window-manager.test.ts +147 -60
  68. package/src/__tests__/contradiction-checker.test.ts +0 -1
  69. package/src/__tests__/conversation-attention-store.test.ts +0 -1
  70. package/src/__tests__/conversation-attention-telegram.test.ts +1 -1
  71. package/src/__tests__/conversation-pairing.test.ts +2 -2
  72. package/src/__tests__/conversation-routes-guardian-reply.test.ts +25 -1
  73. package/src/__tests__/conversation-routes-slash-commands.test.ts +381 -0
  74. package/src/__tests__/conversation-store.test.ts +0 -1
  75. package/src/__tests__/conversation-unread-route.test.ts +1 -2
  76. package/src/__tests__/credential-security-invariants.test.ts +7 -8
  77. package/src/__tests__/cross-provider-web-search.test.ts +353 -0
  78. package/src/__tests__/daemon-assistant-events.test.ts +6 -7
  79. package/src/__tests__/db-schedule-syntax-migration.test.ts +15 -3
  80. package/src/__tests__/delete-managed-skill-tool.test.ts +5 -9
  81. package/src/__tests__/deterministic-verification-control-plane.test.ts +0 -1
  82. package/src/__tests__/diagnostics-export.test.ts +189 -0
  83. package/src/__tests__/dynamic-skill-workflow-prompt.test.ts +0 -1
  84. package/src/__tests__/emit-signal-routing-intent.test.ts +3 -3
  85. package/src/__tests__/entity-extractor.test.ts +0 -1
  86. package/src/__tests__/entity-search.test.ts +0 -1
  87. package/src/__tests__/ephemeral-permissions.test.ts +2 -4
  88. package/src/__tests__/file-read-tool.test.ts +86 -0
  89. package/src/__tests__/followup-tools.test.ts +0 -1
  90. package/src/__tests__/frontmatter.test.ts +77 -34
  91. package/src/__tests__/gateway-only-enforcement.test.ts +0 -1
  92. package/src/__tests__/gateway-only-guard.test.ts +1 -1
  93. package/src/__tests__/guardian-action-conversation-turn.test.ts +0 -1
  94. package/src/__tests__/guardian-action-followup-executor.test.ts +0 -1
  95. package/src/__tests__/guardian-action-followup-store.test.ts +0 -1
  96. package/src/__tests__/guardian-action-grant-mint-consume.test.ts +0 -1
  97. package/src/__tests__/guardian-action-late-reply.test.ts +0 -1
  98. package/src/__tests__/guardian-action-store.test.ts +0 -1
  99. package/src/__tests__/guardian-action-sweep.test.ts +0 -1
  100. package/src/__tests__/guardian-decision-primitive-canonical.test.ts +0 -1
  101. package/src/__tests__/guardian-dispatch.test.ts +1 -2
  102. package/src/__tests__/guardian-grant-minting.test.ts +1 -1
  103. package/src/__tests__/guardian-outbound-http.test.ts +0 -1
  104. package/src/__tests__/guardian-principal-id-roundtrip.test.ts +0 -1
  105. package/src/__tests__/guardian-routing-invariants.test.ts +1 -1
  106. package/src/__tests__/guardian-routing-state.test.ts +0 -1
  107. package/src/__tests__/guardian-verification-voice-binding.test.ts +0 -1
  108. package/src/__tests__/guardian-verify-setup-skill-regression.test.ts +3 -5
  109. package/src/__tests__/handlers-user-message-approval-consumption.test.ts +28 -426
  110. package/src/__tests__/host-bash-proxy.test.ts +335 -0
  111. package/src/__tests__/host-file-proxy.test.ts +374 -0
  112. package/src/__tests__/host-shell-tool.test.ts +147 -1
  113. package/src/__tests__/http-user-message-parity.test.ts +361 -0
  114. package/src/__tests__/inbound-invite-redemption.test.ts +0 -1
  115. package/src/__tests__/integration-status.test.ts +3 -8
  116. package/src/__tests__/intent-routing.test.ts +7 -46
  117. package/src/__tests__/invite-redemption-service.test.ts +0 -1
  118. package/src/__tests__/invite-routes-http.test.ts +0 -1
  119. package/src/__tests__/llm-usage-store.test.ts +0 -1
  120. package/src/__tests__/managed-avatar-client.test.ts +101 -55
  121. package/src/__tests__/managed-skill-lifecycle.test.ts +9 -18
  122. package/src/__tests__/managed-store.test.ts +94 -21
  123. package/src/__tests__/media-reuse-story.e2e.test.ts +0 -1
  124. package/src/__tests__/memory-context-benchmark.benchmark.test.ts +2 -4
  125. package/src/__tests__/memory-lifecycle-e2e.test.ts +0 -1
  126. package/src/__tests__/memory-recall-quality.test.ts +0 -1
  127. package/src/__tests__/memory-regressions.experimental.test.ts +0 -1
  128. package/src/__tests__/memory-regressions.test.ts +0 -1
  129. package/src/__tests__/memory-retrieval.benchmark.test.ts +0 -1
  130. package/src/__tests__/memory-upsert-concurrency.test.ts +0 -1
  131. package/src/__tests__/messaging-send-tool.test.ts +35 -0
  132. package/src/__tests__/messaging-skill-split.test.ts +138 -0
  133. package/src/__tests__/migration-cross-version-compatibility.test.ts +0 -1
  134. package/src/__tests__/migration-export-http.test.ts +2 -3
  135. package/src/__tests__/migration-import-commit-http.test.ts +1 -2
  136. package/src/__tests__/migration-import-preflight-http.test.ts +1 -2
  137. package/src/__tests__/migration-validate-http.test.ts +1 -2
  138. package/src/__tests__/native-web-search.test.ts +475 -0
  139. package/src/__tests__/navigate-settings-tab.test.ts +84 -0
  140. package/src/__tests__/non-member-access-request.test.ts +0 -1
  141. package/src/__tests__/notification-broadcaster.test.ts +15 -15
  142. package/src/__tests__/notification-decision-strategy.test.ts +6 -6
  143. package/src/__tests__/notification-deep-link.test.ts +7 -7
  144. package/src/__tests__/notification-guardian-path.test.ts +2 -3
  145. package/src/__tests__/notification-telegram-adapter.test.ts +1 -1
  146. package/src/__tests__/notification-thread-candidates.test.ts +4 -4
  147. package/src/__tests__/onboarding-starter-tasks.test.ts +0 -1
  148. package/src/__tests__/playbook-execution.test.ts +0 -1
  149. package/src/__tests__/playbook-tools.test.ts +0 -1
  150. package/src/__tests__/profile-compiler.test.ts +0 -1
  151. package/src/__tests__/provider-managed-proxy-integration.test.ts +25 -0
  152. package/src/__tests__/qdrant-collection-migration.test.ts +223 -0
  153. package/src/__tests__/recording-handler.test.ts +30 -94
  154. package/src/__tests__/registry.test.ts +28 -35
  155. package/src/__tests__/relay-server.test.ts +0 -1
  156. package/src/__tests__/ride-shotgun-handler.test.ts +4 -20
  157. package/src/__tests__/runtime-attachment-metadata.test.ts +0 -1
  158. package/src/__tests__/runtime-events-sse-parity.test.ts +3 -4
  159. package/src/__tests__/runtime-events-sse.test.ts +0 -1
  160. package/src/__tests__/sandbox-diagnostics.test.ts +0 -1
  161. package/src/__tests__/scaffold-managed-skill-tool.test.ts +30 -28
  162. package/src/__tests__/schedule-store.test.ts +441 -1
  163. package/src/__tests__/schedule-tools.test.ts +468 -7
  164. package/src/__tests__/scheduler-recurrence.test.ts +196 -23
  165. package/src/__tests__/scoped-approval-grants.test.ts +0 -1
  166. package/src/__tests__/scoped-grant-security-matrix.test.ts +0 -1
  167. package/src/__tests__/secret-prompt-log-hygiene.test.ts +6 -3
  168. package/src/__tests__/secret-response-routing.test.ts +4 -1
  169. package/src/__tests__/send-endpoint-busy.test.ts +14 -2
  170. package/src/__tests__/send-notification-tool.test.ts +0 -7
  171. package/src/__tests__/sequence-store.test.ts +0 -1
  172. package/src/__tests__/server-history-render.test.ts +1 -2
  173. package/src/__tests__/session-abort-tool-results.test.ts +0 -1
  174. package/src/__tests__/session-agent-loop.test.ts +46 -6
  175. package/src/__tests__/session-confirmation-signals.test.ts +0 -1
  176. package/src/__tests__/session-conflict-gate.test.ts +2 -6
  177. package/src/__tests__/session-error.test.ts +5 -14
  178. package/src/__tests__/session-init.benchmark.test.ts +3 -5
  179. package/src/__tests__/session-load-history-repair.test.ts +0 -1
  180. package/src/__tests__/session-media-retry.test.ts +12 -74
  181. package/src/__tests__/session-pre-run-repair.test.ts +0 -1
  182. package/src/__tests__/session-profile-injection.test.ts +2 -6
  183. package/src/__tests__/session-provider-retry-repair.test.ts +2 -6
  184. package/src/__tests__/session-queue.test.ts +94 -139
  185. package/src/__tests__/session-skill-tools.test.ts +115 -115
  186. package/src/__tests__/session-slash-known.test.ts +0 -1
  187. package/src/__tests__/session-slash-queue.test.ts +0 -1
  188. package/src/__tests__/session-slash-unknown.test.ts +0 -1
  189. package/src/__tests__/session-surfaces-task-progress.test.ts +34 -0
  190. package/src/__tests__/session-usage.test.ts +0 -1
  191. package/src/__tests__/session-workspace-cache-state.test.ts +2 -6
  192. package/src/__tests__/session-workspace-injection.test.ts +2 -6
  193. package/src/__tests__/session-workspace-tool-tracking.test.ts +2 -6
  194. package/src/__tests__/skill-feature-flags-integration.test.ts +180 -184
  195. package/src/__tests__/skill-feature-flags.test.ts +125 -18
  196. package/src/__tests__/skill-load-feature-flag.test.ts +1 -2
  197. package/src/__tests__/skill-load-tool.test.ts +194 -2
  198. package/src/__tests__/skill-projection-feature-flag.test.ts +27 -16
  199. package/src/__tests__/skill-projection.benchmark.test.ts +15 -14
  200. package/src/__tests__/skills.test.ts +14 -53
  201. package/src/__tests__/slack-channel-config.test.ts +0 -1
  202. package/src/__tests__/slack-inbound-verification.test.ts +0 -1
  203. package/src/__tests__/slack-skill.test.ts +1 -1
  204. package/src/__tests__/subagent-tools.test.ts +2 -2
  205. package/src/__tests__/system-prompt.test.ts +4 -3
  206. package/src/__tests__/task-compiler.test.ts +0 -1
  207. package/src/__tests__/task-management-tools.test.ts +0 -1
  208. package/src/__tests__/task-memory-cleanup.test.ts +0 -1
  209. package/src/__tests__/task-runner.test.ts +0 -1
  210. package/src/__tests__/task-scheduler.test.ts +0 -1
  211. package/src/__tests__/terminal-tools.test.ts +0 -1
  212. package/src/__tests__/test-support/computer-use-skill-harness.ts +2 -4
  213. package/src/__tests__/thread-seed-composer.test.ts +5 -5
  214. package/src/__tests__/tool-approval-handler.test.ts +0 -1
  215. package/src/__tests__/tool-execution-abort-cleanup.test.ts +0 -1
  216. package/src/__tests__/tool-execution-pipeline.benchmark.test.ts +0 -1
  217. package/src/__tests__/tool-executor.test.ts +8 -86
  218. package/src/__tests__/tool-grant-request-escalation.test.ts +0 -1
  219. package/src/__tests__/tool-notification-listener.test.ts +1 -1
  220. package/src/__tests__/tool-preview-lifecycle.test.ts +416 -0
  221. package/src/__tests__/trust-store.test.ts +80 -4
  222. package/src/__tests__/trusted-contact-approval-notifier.test.ts +0 -1
  223. package/src/__tests__/trusted-contact-inline-approval-integration.test.ts +0 -1
  224. package/src/__tests__/trusted-contact-lifecycle-notifications.test.ts +0 -1
  225. package/src/__tests__/trusted-contact-multichannel.test.ts +0 -1
  226. package/src/__tests__/trusted-contact-verification.test.ts +0 -1
  227. package/src/__tests__/twilio-provider.test.ts +0 -1
  228. package/src/__tests__/twilio-routes.test.ts +0 -1
  229. package/src/__tests__/{request-file-tool.test.ts → ui-file-upload-surface.test.ts} +11 -72
  230. package/src/__tests__/update-bulletin.test.ts +0 -1
  231. package/src/__tests__/usage-cache-backfill-migration.test.ts +0 -1
  232. package/src/__tests__/usage-routes.test.ts +0 -1
  233. package/src/__tests__/verification-control-plane-policy.test.ts +4 -4
  234. package/src/__tests__/voice-invite-redemption.test.ts +0 -1
  235. package/src/__tests__/voice-scoped-grant-consumer.test.ts +0 -1
  236. package/src/__tests__/voice-session-bridge.test.ts +9 -1
  237. package/src/__tests__/web-fetch.test.ts +57 -0
  238. package/src/__tests__/workspace-git-service.test.ts +5 -14
  239. package/src/__tests__/workspace-policy.test.ts +0 -1
  240. package/src/agent/loop.ts +22 -34
  241. package/src/bundler/bundle-signer.ts +4 -4
  242. package/src/calls/call-controller.ts +1 -1
  243. package/src/calls/relay-server.ts +1 -1
  244. package/src/calls/twilio-rest.ts +1 -1
  245. package/src/calls/voice-session-bridge.ts +3 -1
  246. package/src/cli/__tests__/notifications.test.ts +3 -4
  247. package/src/cli/commands/map.ts +2 -6
  248. package/src/cli/commands/mcp.ts +73 -15
  249. package/src/cli/commands/notifications.ts +4 -4
  250. package/src/cli/commands/sessions.ts +9 -1
  251. package/src/cli/commands/skills.ts +6 -10
  252. package/src/cli/http-client.ts +2 -3
  253. package/src/cli/main-screen.tsx +10 -10
  254. package/src/cli/program.ts +0 -4
  255. package/src/cli/reference.ts +0 -2
  256. package/src/cli.ts +15 -9
  257. package/src/config/__tests__/bundled-tool-registry-guard.test.ts +120 -0
  258. package/src/config/bundled-skills/_shared/CLI_RETRIEVAL_PATTERN.md +11 -0
  259. package/src/config/bundled-skills/app-builder/SKILL.md +6 -1
  260. package/src/config/bundled-skills/browser/SKILL.md +6 -1
  261. package/src/config/bundled-skills/chatgpt-import/SKILL.md +5 -1
  262. package/src/config/bundled-skills/claude-code/SKILL.md +5 -1
  263. package/src/config/bundled-skills/computer-use/SKILL.md +6 -1
  264. package/src/config/bundled-skills/computer-use/TOOLS.json +6 -69
  265. package/src/config/bundled-skills/computer-use/tools/computer-use-click.ts +10 -1
  266. package/src/config/bundled-skills/contacts/SKILL.md +10 -1
  267. package/src/config/bundled-skills/contacts/TOOLS.json +35 -0
  268. package/src/config/bundled-skills/{messaging → contacts}/tools/google-contacts.ts +9 -2
  269. package/src/config/bundled-skills/document/SKILL.md +4 -1
  270. package/src/config/bundled-skills/doordash/SKILL.md +8 -1
  271. package/src/config/bundled-skills/doordash/lib/shared/platform.ts +4 -1
  272. package/src/config/bundled-skills/followups/SKILL.md +4 -1
  273. package/src/config/bundled-skills/gmail/SKILL.md +180 -0
  274. package/src/config/bundled-skills/gmail/TOOLS.json +506 -0
  275. package/src/config/bundled-skills/gmail/tools/gmail-archive.ts +149 -0
  276. package/src/config/bundled-skills/gmail/tools/gmail-attachments.ts +110 -0
  277. package/src/config/bundled-skills/{messaging → gmail}/tools/gmail-draft.ts +1 -1
  278. package/src/config/bundled-skills/{messaging → gmail}/tools/gmail-filters.ts +1 -1
  279. package/src/config/bundled-skills/{messaging → gmail}/tools/gmail-follow-up.ts +1 -1
  280. package/src/config/bundled-skills/{messaging → gmail}/tools/gmail-forward.ts +1 -1
  281. package/src/config/bundled-skills/gmail/tools/gmail-label.ts +50 -0
  282. package/src/config/bundled-skills/{messaging → gmail}/tools/gmail-outreach-scan.ts +8 -90
  283. package/src/config/bundled-skills/{messaging → gmail}/tools/gmail-send-draft.ts +1 -1
  284. package/src/config/bundled-skills/{messaging → gmail}/tools/gmail-sender-digest.ts +2 -2
  285. package/src/config/bundled-skills/{messaging → gmail}/tools/gmail-trash.ts +1 -1
  286. package/src/config/bundled-skills/{messaging → gmail}/tools/gmail-unsubscribe.ts +1 -1
  287. package/src/config/bundled-skills/{messaging → gmail}/tools/gmail-vacation.ts +1 -1
  288. package/src/config/bundled-skills/gmail/tools/shared.ts +47 -0
  289. package/src/config/bundled-skills/google-calendar/SKILL.md +5 -1
  290. package/src/config/bundled-skills/image-studio/SKILL.md +5 -1
  291. package/src/config/bundled-skills/knowledge-graph/SKILL.md +4 -1
  292. package/src/config/bundled-skills/media-processing/SKILL.md +7 -13
  293. package/src/config/bundled-skills/media-processing/TOOLS.json +0 -22
  294. package/src/config/bundled-skills/media-processing/tools/generate-clip.ts +12 -1
  295. package/src/config/bundled-skills/messaging/SKILL.md +23 -139
  296. package/src/config/bundled-skills/messaging/TOOLS.json +33 -1215
  297. package/src/config/bundled-skills/messaging/tools/gmail-mime-helpers.ts +42 -0
  298. package/src/config/bundled-skills/messaging/tools/messaging-send.ts +165 -2
  299. package/src/config/bundled-skills/messaging/tools/messaging-sender-digest.ts +1 -13
  300. package/src/config/bundled-skills/messaging/tools/shared.ts +81 -34
  301. package/src/config/bundled-skills/notifications/SKILL.md +5 -1
  302. package/src/config/bundled-skills/orchestration/SKILL.md +30 -0
  303. package/src/config/bundled-skills/orchestration/TOOLS.json +35 -0
  304. package/src/config/bundled-skills/{reminder/tools/reminder-create.ts → orchestration/tools/swarm-delegate.ts} +3 -3
  305. package/src/config/bundled-skills/phone-calls/SKILL.md +9 -1
  306. package/src/config/bundled-skills/playbooks/SKILL.md +4 -1
  307. package/src/config/bundled-skills/schedule/SKILL.md +70 -9
  308. package/src/config/bundled-skills/schedule/TOOLS.json +38 -6
  309. package/src/config/bundled-skills/screen-watch/SKILL.md +28 -0
  310. package/src/config/bundled-skills/screen-watch/TOOLS.json +35 -0
  311. package/src/config/bundled-skills/{reminder/tools/reminder-cancel.ts → screen-watch/tools/start-screen-watch.ts} +3 -3
  312. package/src/config/bundled-skills/sequences/SKILL.md +47 -0
  313. package/src/config/bundled-skills/sequences/TOOLS.json +340 -0
  314. package/src/config/bundled-skills/sequences/tools/sequence-update.ts +128 -0
  315. package/src/config/bundled-skills/sequences/tools/shared.ts +9 -0
  316. package/src/config/bundled-skills/settings/SKILL.md +12 -0
  317. package/src/config/bundled-skills/settings/TOOLS.json +112 -0
  318. package/src/config/bundled-skills/settings/tools/navigate-settings-tab.ts +43 -0
  319. package/src/config/bundled-skills/settings/tools/open-system-settings.ts +52 -0
  320. package/src/config/bundled-skills/{computer-use/tools/computer-use-right-click.ts → settings/tools/set-avatar.ts} +2 -6
  321. package/src/{tools/system/voice-config.ts → config/bundled-skills/settings/tools/voice-config-update.ts} +59 -96
  322. package/src/config/bundled-skills/skill-management/SKILL.md +18 -0
  323. package/src/config/bundled-skills/skill-management/TOOLS.json +90 -0
  324. package/src/config/bundled-skills/{computer-use/tools/computer-use-double-click.ts → skill-management/tools/delete-managed.ts} +2 -6
  325. package/src/config/bundled-skills/skill-management/tools/scaffold-managed.ts +12 -0
  326. package/src/config/bundled-skills/slack/SKILL.md +5 -1
  327. package/src/config/bundled-skills/subagent/SKILL.md +4 -1
  328. package/src/config/bundled-skills/tasks/SKILL.md +5 -2
  329. package/src/config/bundled-skills/transcribe/SKILL.md +4 -1
  330. package/src/config/bundled-skills/watcher/SKILL.md +4 -1
  331. package/src/config/bundled-tool-registry.ts +118 -107
  332. package/src/config/env.ts +5 -2
  333. package/src/config/feature-flag-registry.json +25 -9
  334. package/src/config/loader.ts +10 -2
  335. package/src/config/schema.ts +19 -16
  336. package/src/config/schemas/inference.ts +12 -22
  337. package/src/config/schemas/memory-storage.ts +19 -1
  338. package/src/config/schemas/platform.ts +0 -16
  339. package/src/config/skill-state.ts +11 -8
  340. package/src/config/skills.ts +83 -32
  341. package/src/context/token-estimator.ts +11 -0
  342. package/src/context/window-manager.ts +180 -151
  343. package/src/daemon/computer-use-session.ts +11 -43
  344. package/src/daemon/daemon-control.ts +4 -1
  345. package/src/daemon/handlers/config-channels.ts +5 -9
  346. package/src/daemon/handlers/config-ingress.ts +0 -4
  347. package/src/daemon/handlers/config-model.ts +7 -13
  348. package/src/daemon/handlers/config-telegram.ts +4 -8
  349. package/src/daemon/handlers/config-voice.ts +2 -5
  350. package/src/daemon/handlers/dictation.ts +2 -12
  351. package/src/daemon/handlers/identity.ts +0 -105
  352. package/src/daemon/handlers/recording.ts +3 -23
  353. package/src/daemon/handlers/session-history.ts +1 -1
  354. package/src/daemon/handlers/sessions.ts +53 -72
  355. package/src/daemon/handlers/shared.ts +7 -28
  356. package/src/daemon/handlers/skills.ts +31 -27
  357. package/src/daemon/host-bash-proxy.ts +148 -0
  358. package/src/daemon/host-file-proxy.ts +135 -0
  359. package/src/daemon/lifecycle.ts +49 -24
  360. package/src/daemon/mcp-reload-service.ts +123 -0
  361. package/src/daemon/message-protocol.ts +6 -0
  362. package/src/daemon/message-types/browser.ts +1 -1
  363. package/src/daemon/message-types/computer-use.ts +1 -4
  364. package/src/daemon/message-types/guardian-actions.ts +1 -1
  365. package/src/daemon/message-types/host-bash.ts +18 -0
  366. package/src/daemon/message-types/host-file.ts +44 -0
  367. package/src/daemon/message-types/integrations.ts +1 -67
  368. package/src/daemon/message-types/messages.ts +15 -0
  369. package/src/daemon/message-types/schedules.ts +11 -27
  370. package/src/daemon/message-types/sessions.ts +2 -1
  371. package/src/daemon/message-types/settings.ts +1 -1
  372. package/src/daemon/message-types/shared.ts +1 -1
  373. package/src/daemon/ride-shotgun-handler.ts +2 -42
  374. package/src/daemon/server.ts +43 -10
  375. package/src/daemon/session-agent-loop-handlers.ts +48 -7
  376. package/src/daemon/session-agent-loop.ts +97 -66
  377. package/src/daemon/session-attachments.ts +1 -1
  378. package/src/daemon/session-error.ts +17 -16
  379. package/src/daemon/session-lifecycle.ts +20 -1
  380. package/src/daemon/session-media-retry.ts +1 -15
  381. package/src/daemon/session-messaging.ts +14 -6
  382. package/src/daemon/session-process.ts +36 -7
  383. package/src/daemon/session-queue-manager.ts +62 -103
  384. package/src/daemon/session-runtime-assembly.ts +27 -0
  385. package/src/daemon/session-skill-tools.ts +12 -11
  386. package/src/daemon/session-slash.ts +7 -0
  387. package/src/daemon/session-surfaces.ts +19 -97
  388. package/src/daemon/session-tool-setup.ts +146 -6
  389. package/src/daemon/session.ts +77 -13
  390. package/src/errors.ts +0 -2
  391. package/src/export/formatter.ts +6 -0
  392. package/src/mcp/mcp-oauth-provider.ts +1 -3
  393. package/src/media/avatar-router.ts +20 -28
  394. package/src/media/avatar-types.ts +7 -14
  395. package/src/media/managed-avatar-client.ts +70 -34
  396. package/src/memory/conversation-title-service.ts +1 -2
  397. package/src/memory/db-init.ts +16 -0
  398. package/src/memory/embedding-backend.ts +129 -27
  399. package/src/memory/embedding-gemini.test.ts +256 -0
  400. package/src/memory/embedding-gemini.ts +47 -13
  401. package/src/memory/embedding-local.ts +14 -2
  402. package/src/memory/embedding-ollama.ts +15 -2
  403. package/src/memory/embedding-openai.ts +15 -2
  404. package/src/memory/embedding-types.test.ts +116 -0
  405. package/src/memory/embedding-types.ts +61 -0
  406. package/src/memory/fingerprint.ts +1 -1
  407. package/src/memory/indexer.ts +25 -1
  408. package/src/memory/job-handlers/embedding.test.ts +258 -0
  409. package/src/memory/job-handlers/embedding.ts +81 -1
  410. package/src/memory/job-handlers/index-maintenance.ts +35 -1
  411. package/src/memory/job-handlers/media-processing.ts +11 -1
  412. package/src/memory/job-utils.ts +21 -6
  413. package/src/memory/jobs-store.ts +5 -1
  414. package/src/memory/jobs-worker.ts +8 -0
  415. package/src/memory/message-content.ts +66 -0
  416. package/src/memory/migrations/100-core-tables.ts +1 -31
  417. package/src/memory/migrations/104-core-indexes.ts +0 -11
  418. package/src/memory/migrations/145-drop-accounts-table.ts +19 -0
  419. package/src/memory/migrations/146-schedule-oneshot-routing.ts +94 -0
  420. package/src/memory/migrations/147-migrate-reminders-to-schedules.ts +129 -0
  421. package/src/memory/migrations/148-drop-reminders-table.ts +18 -0
  422. package/src/memory/migrations/index.ts +4 -0
  423. package/src/memory/migrations/registry.ts +19 -0
  424. package/src/memory/qdrant-client.ts +158 -43
  425. package/src/memory/retriever.test.ts +0 -1
  426. package/src/memory/retriever.ts +12 -2
  427. package/src/memory/schema/infrastructure.ts +5 -29
  428. package/src/memory/search/formatting.ts +34 -9
  429. package/src/memory/search/semantic.ts +57 -2
  430. package/src/memory/search/types.ts +2 -1
  431. package/src/notifications/AGENTS.md +2 -2
  432. package/src/notifications/README.md +59 -58
  433. package/src/notifications/adapters/macos.ts +1 -1
  434. package/src/notifications/broadcaster.ts +5 -5
  435. package/src/notifications/copy-composer.ts +1 -1
  436. package/src/notifications/decision-engine.ts +2 -2
  437. package/src/notifications/destination-resolver.ts +2 -2
  438. package/src/notifications/emit-signal.ts +8 -8
  439. package/src/notifications/signal.ts +1 -1
  440. package/src/notifications/thread-seed-composer.ts +1 -1
  441. package/src/oauth/connect-orchestrator.ts +1 -1
  442. package/src/oauth/token-persistence.ts +1 -1
  443. package/src/permissions/checker.ts +12 -1
  444. package/src/permissions/defaults.ts +10 -14
  445. package/src/permissions/trust-store.ts +37 -0
  446. package/src/permissions/workspace-policy.ts +0 -1
  447. package/src/prompts/__tests__/build-cli-reference-section.test.ts +11 -0
  448. package/src/prompts/computer-use-prompt.ts +1 -1
  449. package/src/prompts/system-prompt.ts +29 -30
  450. package/src/prompts/templates/SOUL.md +1 -2
  451. package/src/prompts/templates/UPDATES.md +16 -7
  452. package/src/providers/anthropic/client.ts +87 -33
  453. package/src/providers/gemini/client.ts +6 -0
  454. package/src/providers/managed-proxy/constants.ts +5 -0
  455. package/src/providers/openai/client.ts +15 -0
  456. package/src/providers/registry.ts +2 -2
  457. package/src/providers/types.ts +24 -2
  458. package/src/runtime/AGENTS.md +18 -0
  459. package/src/runtime/assistant-event-hub.ts +2 -3
  460. package/src/runtime/assistant-event.ts +4 -4
  461. package/src/runtime/auth/__tests__/context.test.ts +5 -5
  462. package/src/runtime/auth/__tests__/credential-service.test.ts +0 -1
  463. package/src/runtime/auth/__tests__/guard-tests.test.ts +2 -2
  464. package/src/runtime/auth/__tests__/{ipc-auth-context.test.ts → local-auth-context.test.ts} +21 -21
  465. package/src/runtime/auth/__tests__/route-policy.test.ts +2 -2
  466. package/src/runtime/auth/__tests__/scopes.test.ts +7 -7
  467. package/src/runtime/auth/__tests__/subject.test.ts +8 -8
  468. package/src/runtime/auth/__tests__/token-service.test.ts +0 -1
  469. package/src/runtime/auth/route-policy.ts +8 -4
  470. package/src/runtime/auth/scopes.ts +1 -1
  471. package/src/runtime/auth/subject.ts +4 -4
  472. package/src/runtime/auth/token-service.ts +0 -23
  473. package/src/runtime/auth/types.ts +3 -3
  474. package/src/runtime/guardian-action-followup-executor.ts +1 -1
  475. package/src/runtime/guardian-action-grant-minter.ts +1 -1
  476. package/src/runtime/guardian-action-service.ts +3 -3
  477. package/src/runtime/http-server.ts +15 -2
  478. package/src/runtime/invite-service.ts +3 -3
  479. package/src/runtime/local-actor-identity.ts +17 -22
  480. package/src/runtime/pending-interactions.ts +21 -9
  481. package/src/runtime/routes/app-management-routes.ts +2 -3
  482. package/src/runtime/routes/approval-routes.ts +1 -3
  483. package/src/runtime/routes/btw-routes.ts +155 -0
  484. package/src/runtime/routes/computer-use-routes.ts +77 -31
  485. package/src/runtime/routes/conversation-routes.ts +230 -46
  486. package/src/runtime/routes/diagnostics-routes.ts +63 -29
  487. package/src/runtime/routes/documents-routes.ts +2 -2
  488. package/src/runtime/routes/global-search-routes.ts +1 -1
  489. package/src/runtime/routes/host-bash-routes.ts +83 -0
  490. package/src/runtime/routes/host-file-routes.ts +79 -0
  491. package/src/runtime/routes/integrations/slack/share.ts +1 -1
  492. package/src/runtime/routes/log-export-routes.ts +120 -0
  493. package/src/runtime/routes/mcp-routes.ts +20 -0
  494. package/src/runtime/routes/migration-routes.ts +3 -3
  495. package/src/runtime/routes/pairing-routes.ts +1 -1
  496. package/src/runtime/routes/recording-routes.ts +6 -4
  497. package/src/runtime/routes/schedule-routes.ts +31 -5
  498. package/src/runtime/routes/session-management-routes.ts +2 -6
  499. package/src/runtime/routes/session-query-routes.ts +18 -15
  500. package/src/runtime/routes/settings-routes.ts +7 -261
  501. package/src/runtime/routes/skills-routes.ts +7 -6
  502. package/src/runtime/routes/subagents-routes.ts +4 -10
  503. package/src/runtime/routes/surface-action-routes.ts +3 -14
  504. package/src/runtime/routes/surface-content-routes.ts +22 -5
  505. package/src/runtime/routes/work-items-routes.ts +21 -25
  506. package/src/runtime/routes/workspace-routes.test.ts +3 -3
  507. package/src/runtime/routes/workspace-utils.ts +1 -1
  508. package/src/runtime/telegram-streaming-delivery.ts +3 -0
  509. package/src/runtime/verification-outbound-actions.ts +2 -2
  510. package/src/schedule/integration-status.ts +0 -6
  511. package/src/schedule/schedule-store.ts +234 -43
  512. package/src/schedule/scheduler.ts +73 -74
  513. package/src/security/oauth2.ts +1 -1
  514. package/src/sequence/store.ts +12 -2
  515. package/src/skills/frontmatter.ts +19 -77
  516. package/src/skills/managed-store.ts +11 -2
  517. package/src/subagent/manager.ts +5 -3
  518. package/src/tasks/ephemeral-permissions.ts +3 -5
  519. package/src/tools/AGENTS.md +0 -1
  520. package/src/tools/browser/browser-manager.ts +17 -11
  521. package/src/tools/browser/jit-auth.ts +4 -1
  522. package/src/tools/claude-code/claude-code.ts +1 -1
  523. package/src/tools/computer-use/definitions.ts +48 -60
  524. package/src/tools/document/document-tool.ts +6 -6
  525. package/src/tools/filesystem/edit.ts +2 -1
  526. package/src/tools/filesystem/read.ts +20 -2
  527. package/src/tools/filesystem/write.ts +2 -1
  528. package/src/tools/host-filesystem/edit.ts +17 -1
  529. package/src/tools/host-filesystem/read.ts +16 -1
  530. package/src/tools/host-filesystem/write.ts +15 -1
  531. package/src/tools/host-terminal/host-shell.ts +24 -0
  532. package/src/tools/memory/definitions.ts +45 -81
  533. package/src/tools/memory/handlers.test.ts +0 -1
  534. package/src/tools/memory/handlers.ts +1 -1
  535. package/src/tools/memory/register.ts +26 -60
  536. package/src/tools/network/script-proxy/session-manager.ts +6 -8
  537. package/src/tools/network/web-fetch.ts +7 -1
  538. package/src/tools/network/web-search.ts +2 -1
  539. package/src/tools/registry.ts +23 -0
  540. package/src/tools/schedule/create.ts +113 -5
  541. package/src/tools/schedule/list.ts +57 -15
  542. package/src/tools/schedule/update.ts +73 -3
  543. package/src/tools/shared/filesystem/image-read.ts +192 -0
  544. package/src/tools/side-effects.ts +1 -7
  545. package/src/tools/skills/delete-managed.ts +27 -64
  546. package/src/tools/skills/execute.ts +54 -0
  547. package/src/tools/skills/load.ts +127 -5
  548. package/src/tools/skills/scaffold-managed.ts +93 -172
  549. package/src/tools/subagent/message.ts +0 -7
  550. package/src/tools/subagent/spawn.ts +1 -1
  551. package/src/tools/swarm/delegate.ts +0 -3
  552. package/src/tools/system/avatar-generator.ts +13 -19
  553. package/src/tools/system/request-permission.ts +2 -1
  554. package/src/tools/terminal/safe-env.ts +1 -0
  555. package/src/tools/tool-manifest.ts +41 -47
  556. package/src/tools/types.ts +6 -2
  557. package/src/tools/ui-surface/definitions.ts +0 -55
  558. package/src/util/errors.ts +0 -10
  559. package/src/workspace/git-service.ts +0 -2
  560. package/src/__tests__/account-registry.test.ts +0 -258
  561. package/src/__tests__/email-classifier.test.ts +0 -25
  562. package/src/__tests__/gmail-integration.test.ts +0 -97
  563. package/src/__tests__/handle-user-message-secret-resume.test.ts +0 -172
  564. package/src/__tests__/managed-twitter-guardrails.test.ts +0 -357
  565. package/src/__tests__/recording-intent-fallback.test.ts +0 -199
  566. package/src/__tests__/recording-intent.test.ts +0 -985
  567. package/src/__tests__/recording-state-machine.test.ts +0 -1574
  568. package/src/__tests__/reminder-store.test.ts +0 -350
  569. package/src/__tests__/reminder.test.ts +0 -337
  570. package/src/__tests__/scan-result-store.test.ts +0 -121
  571. package/src/__tests__/twitter-platform-proxy-client.test.ts +0 -475
  572. package/src/__tests__/view-image-tool.test.ts +0 -241
  573. package/src/cli/commands/amazon/cart.ts +0 -513
  574. package/src/cli/commands/amazon/checkout.ts +0 -394
  575. package/src/cli/commands/amazon/client.ts +0 -513
  576. package/src/cli/commands/amazon/index.ts +0 -885
  577. package/src/cli/commands/amazon/product-details.ts +0 -145
  578. package/src/cli/commands/amazon/request-extractor.ts +0 -187
  579. package/src/cli/commands/amazon/search.ts +0 -76
  580. package/src/cli/commands/amazon/session.ts +0 -108
  581. package/src/cli/commands/twitter/__tests__/cli-read-routing.test.ts +0 -345
  582. package/src/cli/commands/twitter/__tests__/cli-routing.test.ts +0 -252
  583. package/src/cli/commands/twitter/__tests__/oauth-client.test.ts +0 -151
  584. package/src/cli/commands/twitter/index.ts +0 -420
  585. package/src/cli/commands/twitter/oauth-client.ts +0 -60
  586. package/src/cli/commands/twitter/router.ts +0 -351
  587. package/src/cli/commands/twitter/types.ts +0 -30
  588. package/src/config/bundled-skills/agentmail/SKILL.md +0 -132
  589. package/src/config/bundled-skills/agentmail/icon.svg +0 -21
  590. package/src/config/bundled-skills/amazon/SKILL.md +0 -136
  591. package/src/config/bundled-skills/amazon/icon.svg +0 -13
  592. package/src/config/bundled-skills/api-mapping/SKILL.md +0 -78
  593. package/src/config/bundled-skills/api-mapping/icon.svg +0 -18
  594. package/src/config/bundled-skills/cli-discover/SKILL.md +0 -68
  595. package/src/config/bundled-skills/deploy-fullstack-vercel/SKILL.md +0 -179
  596. package/src/config/bundled-skills/document-writer/SKILL.md +0 -195
  597. package/src/config/bundled-skills/elevenlabs-voice/SKILL.md +0 -140
  598. package/src/config/bundled-skills/email-setup/SKILL.md +0 -68
  599. package/src/config/bundled-skills/frontend-design/SKILL.md +0 -44
  600. package/src/config/bundled-skills/frontend-design/icon.svg +0 -16
  601. package/src/config/bundled-skills/google-oauth-setup/SKILL.md +0 -452
  602. package/src/config/bundled-skills/guardian-verify-setup/SKILL.md +0 -203
  603. package/src/config/bundled-skills/influencer/SKILL.md +0 -144
  604. package/src/config/bundled-skills/influencer/scripts/client.ts +0 -1269
  605. package/src/config/bundled-skills/influencer/scripts/influencer.ts +0 -267
  606. package/src/config/bundled-skills/macos-automation/SKILL.md +0 -65
  607. package/src/config/bundled-skills/macos-automation/icon.svg +0 -12
  608. package/src/config/bundled-skills/mcp-setup/SKILL.md +0 -75
  609. package/src/config/bundled-skills/media-processing/tools/media-diagnostics.ts +0 -184
  610. package/src/config/bundled-skills/messaging/tools/gmail-archive-by-query.ts +0 -80
  611. package/src/config/bundled-skills/messaging/tools/gmail-archive.ts +0 -29
  612. package/src/config/bundled-skills/messaging/tools/gmail-batch-archive.ts +0 -56
  613. package/src/config/bundled-skills/messaging/tools/gmail-batch-label.ts +0 -34
  614. package/src/config/bundled-skills/messaging/tools/gmail-download-attachment.ts +0 -47
  615. package/src/config/bundled-skills/messaging/tools/gmail-label.ts +0 -31
  616. package/src/config/bundled-skills/messaging/tools/gmail-list-attachments.ts +0 -67
  617. package/src/config/bundled-skills/messaging/tools/gmail-send-with-attachments.ts +0 -97
  618. package/src/config/bundled-skills/messaging/tools/gmail-summarize-thread.ts +0 -87
  619. package/src/config/bundled-skills/messaging/tools/gmail-triage.ts +0 -135
  620. package/src/config/bundled-skills/messaging/tools/messaging-analyze-activity.ts +0 -24
  621. package/src/config/bundled-skills/messaging/tools/messaging-reply.ts +0 -201
  622. package/src/config/bundled-skills/messaging/tools/send-notification.ts +0 -1
  623. package/src/config/bundled-skills/messaging/tools/sequence-cancel.ts +0 -27
  624. package/src/config/bundled-skills/messaging/tools/sequence-pause.ts +0 -48
  625. package/src/config/bundled-skills/messaging/tools/sequence-resume.ts +0 -27
  626. package/src/config/bundled-skills/messaging/tools/sequence-update.ts +0 -56
  627. package/src/config/bundled-skills/notion/SKILL.md +0 -240
  628. package/src/config/bundled-skills/notion-oauth-setup/SKILL.md +0 -126
  629. package/src/config/bundled-skills/oauth-setup/SKILL.md +0 -143
  630. package/src/config/bundled-skills/public-ingress/SKILL.md +0 -258
  631. package/src/config/bundled-skills/reminder/SKILL.md +0 -79
  632. package/src/config/bundled-skills/reminder/TOOLS.json +0 -89
  633. package/src/config/bundled-skills/reminder/tools/reminder-list.ts +0 -12
  634. package/src/config/bundled-skills/restaurant-reservation/SKILL.md +0 -141
  635. package/src/config/bundled-skills/screen-recording/SKILL.md +0 -148
  636. package/src/config/bundled-skills/self-upgrade/SKILL.md +0 -69
  637. package/src/config/bundled-skills/skills-catalog/SKILL.md +0 -78
  638. package/src/config/bundled-skills/slack-app-setup/SKILL.md +0 -178
  639. package/src/config/bundled-skills/slack-digest-setup/SKILL.md +0 -163
  640. package/src/config/bundled-skills/slack-oauth-setup/SKILL.md +0 -157
  641. package/src/config/bundled-skills/start-the-day/SKILL.md +0 -70
  642. package/src/config/bundled-skills/start-the-day/icon.svg +0 -13
  643. package/src/config/bundled-skills/telegram-setup/SKILL.md +0 -105
  644. package/src/config/bundled-skills/time-based-actions/SKILL.md +0 -142
  645. package/src/config/bundled-skills/twilio-setup/SKILL.md +0 -232
  646. package/src/config/bundled-skills/twitter/SKILL.md +0 -206
  647. package/src/config/bundled-skills/twitter/icon.svg +0 -14
  648. package/src/config/bundled-skills/typescript-eval/SKILL.md +0 -60
  649. package/src/config/bundled-skills/vercel-token-setup/SKILL.md +0 -214
  650. package/src/config/bundled-skills/voice-setup/SKILL.md +0 -131
  651. package/src/config/bundled-skills/voice-setup/icon.svg +0 -20
  652. package/src/daemon/handlers/pairing.ts +0 -119
  653. package/src/daemon/handlers/session-user-message.ts +0 -961
  654. package/src/daemon/recording-executor.ts +0 -180
  655. package/src/daemon/recording-intent-fallback.ts +0 -162
  656. package/src/daemon/recording-intent.ts +0 -493
  657. package/src/memory/account-store.ts +0 -117
  658. package/src/messaging/activity-analyzer.ts +0 -76
  659. package/src/messaging/email-classifier.ts +0 -208
  660. package/src/messaging/index.ts +0 -2
  661. package/src/messaging/outreach-classifier.ts +0 -185
  662. package/src/messaging/thread-summarizer.ts +0 -346
  663. package/src/messaging/types.ts +0 -17
  664. package/src/tools/browser/x-auto-navigate.ts +0 -254
  665. package/src/tools/credentials/account-registry.ts +0 -144
  666. package/src/tools/filesystem/view-image.ts +0 -244
  667. package/src/tools/reminder/reminder-store.ts +0 -194
  668. package/src/tools/reminder/reminder.ts +0 -158
  669. package/src/tools/system/navigate-settings.ts +0 -74
  670. package/src/tools/system/open-system-settings.ts +0 -85
  671. package/src/tools/system/version.ts +0 -54
  672. package/src/twitter/platform-proxy-client.ts +0 -408
  673. /package/src/config/bundled-skills/{messaging → gmail}/tools/scan-result-store.ts +0 -0
  674. /package/src/config/bundled-skills/{messaging → sequences}/tools/sequence-analytics.ts +0 -0
  675. /package/src/config/bundled-skills/{messaging → sequences}/tools/sequence-create.ts +0 -0
  676. /package/src/config/bundled-skills/{messaging → sequences}/tools/sequence-delete.ts +0 -0
  677. /package/src/config/bundled-skills/{messaging → sequences}/tools/sequence-enroll.ts +0 -0
  678. /package/src/config/bundled-skills/{messaging → sequences}/tools/sequence-enrollment-list.ts +0 -0
  679. /package/src/config/bundled-skills/{messaging → sequences}/tools/sequence-get.ts +0 -0
  680. /package/src/config/bundled-skills/{messaging → sequences}/tools/sequence-import.ts +0 -0
  681. /package/src/config/bundled-skills/{messaging → sequences}/tools/sequence-list.ts +0 -0
@@ -11,10 +11,11 @@ export interface QdrantClientConfig {
11
11
  vectorSize: number;
12
12
  onDisk: boolean;
13
13
  quantization: "scalar" | "none";
14
+ embeddingModel?: string;
14
15
  }
15
16
 
16
17
  export interface QdrantPointPayload {
17
- target_type: "segment" | "item" | "summary";
18
+ target_type: "segment" | "item" | "summary" | "media";
18
19
  target_id: string;
19
20
  text: string;
20
21
  kind?: string;
@@ -26,7 +27,9 @@ export interface QdrantPointPayload {
26
27
  last_seen_at?: number;
27
28
  conversation_id?: string;
28
29
  message_id?: string;
30
+ memory_scope_id?: string;
29
31
  entity_ids?: string[];
32
+ modality?: "text" | "image" | "audio" | "video";
30
33
  }
31
34
 
32
35
  export interface QdrantSearchResult {
@@ -59,8 +62,11 @@ export class VellumQdrantClient {
59
62
  private readonly vectorSize: number;
60
63
  private readonly onDisk: boolean;
61
64
  private readonly quantization: "scalar" | "none";
65
+ private readonly embeddingModel?: string;
62
66
  private collectionReady = false;
63
67
 
68
+ private readonly SENTINEL_ID = "00000000-0000-0000-0000-000000000000";
69
+
64
70
  constructor(config: QdrantClientConfig) {
65
71
  this.client = new QdrantRestClient({
66
72
  url: config.url,
@@ -70,6 +76,7 @@ export class VellumQdrantClient {
70
76
  this.vectorSize = config.vectorSize;
71
77
  this.onDisk = config.onDisk;
72
78
  this.quantization = config.quantization;
79
+ this.embeddingModel = config.embeddingModel;
73
80
  }
74
81
 
75
82
  async ensureCollection(): Promise<void> {
@@ -78,8 +85,51 @@ export class VellumQdrantClient {
78
85
  try {
79
86
  const exists = await this.client.collectionExists(this.collection);
80
87
  if (exists.exists) {
81
- this.collectionReady = true;
82
- return;
88
+ try {
89
+ const info = await this.client.getCollection(this.collection);
90
+ const currentSize = (
91
+ info.config?.params?.vectors as { size?: number }
92
+ )?.size;
93
+ const dimMismatch =
94
+ currentSize != null && currentSize !== this.vectorSize;
95
+
96
+ // Check model identity via a sentinel point that stores the embedding model
97
+ let modelMismatch = false;
98
+ if (this.embeddingModel) {
99
+ const sentinel = await this.readSentinel();
100
+ if (sentinel && sentinel !== this.embeddingModel) {
101
+ modelMismatch = true;
102
+ }
103
+ }
104
+
105
+ if (dimMismatch || modelMismatch) {
106
+ log.warn(
107
+ {
108
+ collection: this.collection,
109
+ currentSize,
110
+ expectedSize: this.vectorSize,
111
+ modelMismatch,
112
+ },
113
+ "Qdrant collection incompatible (dimension or model change) — deleting and recreating. Embeddings will be regenerated on demand.",
114
+ );
115
+ await this.client.deleteCollection(this.collection);
116
+ // Fall through to collection creation below
117
+ } else {
118
+ if (await this.ensurePayloadIndexesSafe()) {
119
+ this.collectionReady = true;
120
+ }
121
+ return;
122
+ }
123
+ } catch (err) {
124
+ log.warn(
125
+ { err },
126
+ "Failed to verify collection compatibility, assuming compatible",
127
+ );
128
+ if (await this.ensurePayloadIndexesSafe()) {
129
+ this.collectionReady = true;
130
+ }
131
+ return;
132
+ }
83
133
  }
84
134
  } catch {
85
135
  // Collection doesn't exist, create it
@@ -121,49 +171,30 @@ export class VellumQdrantClient {
121
171
  "status" in err &&
122
172
  (err as { status: number }).status === 409
123
173
  ) {
124
- this.collectionReady = true;
174
+ if (await this.ensurePayloadIndexesSafe()) {
175
+ this.collectionReady = true;
176
+ }
125
177
  return;
126
178
  }
127
179
  throw err;
128
180
  }
129
181
 
130
- // Create payload indexes for efficient filtering
131
- await Promise.all([
132
- this.client.createPayloadIndex(this.collection, {
133
- field_name: "target_type",
134
- field_schema: "keyword",
135
- }),
136
- this.client.createPayloadIndex(this.collection, {
137
- field_name: "target_id",
138
- field_schema: "keyword",
139
- }),
140
- this.client.createPayloadIndex(this.collection, {
141
- field_name: "kind",
142
- field_schema: "keyword",
143
- }),
144
- this.client.createPayloadIndex(this.collection, {
145
- field_name: "status",
146
- field_schema: "keyword",
147
- }),
148
- this.client.createPayloadIndex(this.collection, {
149
- field_name: "created_at",
150
- field_schema: "integer",
151
- }),
152
- this.client.createPayloadIndex(this.collection, {
153
- field_name: "conversation_id",
154
- field_schema: "keyword",
155
- }),
156
- ]);
182
+ if (await this.ensurePayloadIndexesSafe()) {
183
+ // Write sentinel point to record the active embedding model
184
+ if (this.embeddingModel) {
185
+ await this.writeSentinel(this.embeddingModel);
186
+ }
157
187
 
158
- this.collectionReady = true;
159
- log.info(
160
- { collection: this.collection },
161
- "Qdrant collection created with payload indexes",
162
- );
188
+ this.collectionReady = true;
189
+ log.info(
190
+ { collection: this.collection },
191
+ "Qdrant collection created with payload indexes",
192
+ );
193
+ }
163
194
  }
164
195
 
165
196
  async upsert(
166
- targetType: "segment" | "item" | "summary",
197
+ targetType: "segment" | "item" | "summary" | "media",
167
198
  targetId: string,
168
199
  vector: number[],
169
200
  payload: Omit<QdrantPointPayload, "target_type" | "target_id">,
@@ -257,7 +288,7 @@ export class VellumQdrantClient {
257
288
  async searchWithFilter(
258
289
  vector: number[],
259
290
  limit: number,
260
- targetTypes: Array<"segment" | "item" | "summary">,
291
+ targetTypes: Array<"segment" | "item" | "summary" | "media">,
261
292
  excludeMessageIds?: string[],
262
293
  ): Promise<QdrantSearchResult[]> {
263
294
  const mustConditions: Array<Record<string, unknown>> = [
@@ -277,12 +308,17 @@ export class VellumQdrantClient {
277
308
  { key: "status", match: { value: "active" } },
278
309
  ],
279
310
  },
280
- { key: "target_type", match: { any: ["segment", "summary"] } },
311
+ {
312
+ key: "target_type",
313
+ match: { any: ["segment", "summary", "media"] },
314
+ },
281
315
  ],
282
316
  });
283
317
  }
284
318
 
285
- const mustNotConditions: Array<Record<string, unknown>> = [];
319
+ const mustNotConditions: Array<Record<string, unknown>> = [
320
+ { key: "_meta", match: { value: true } },
321
+ ];
286
322
  if (excludeMessageIds && excludeMessageIds.length > 0) {
287
323
  mustNotConditions.push({
288
324
  key: "message_id",
@@ -292,10 +328,8 @@ export class VellumQdrantClient {
292
328
 
293
329
  const filter: Record<string, unknown> = {
294
330
  must: mustConditions,
331
+ must_not: mustNotConditions,
295
332
  };
296
- if (mustNotConditions.length > 0) {
297
- filter.must_not = mustNotConditions;
298
- }
299
333
 
300
334
  return this.search(vector, limit, filter);
301
335
  }
@@ -384,6 +418,87 @@ export class VellumQdrantClient {
384
418
  );
385
419
  }
386
420
 
421
+ /**
422
+ * Wraps ensurePayloadIndexes so that a 404 (collection deleted between
423
+ * our existence check and index creation) resets collectionReady instead
424
+ * of propagating — the next operation will self-heal via ensureCollection.
425
+ */
426
+ private async ensurePayloadIndexesSafe(): Promise<boolean> {
427
+ try {
428
+ await this.ensurePayloadIndexes();
429
+ return true;
430
+ } catch (err) {
431
+ if (this.isCollectionMissing(err)) {
432
+ this.collectionReady = false;
433
+ return false;
434
+ }
435
+ throw err;
436
+ }
437
+ }
438
+
439
+ private async ensurePayloadIndexes(): Promise<void> {
440
+ await Promise.all([
441
+ this.client.createPayloadIndex(this.collection, {
442
+ field_name: "target_type",
443
+ field_schema: "keyword",
444
+ }),
445
+ this.client.createPayloadIndex(this.collection, {
446
+ field_name: "target_id",
447
+ field_schema: "keyword",
448
+ }),
449
+ this.client.createPayloadIndex(this.collection, {
450
+ field_name: "kind",
451
+ field_schema: "keyword",
452
+ }),
453
+ this.client.createPayloadIndex(this.collection, {
454
+ field_name: "status",
455
+ field_schema: "keyword",
456
+ }),
457
+ this.client.createPayloadIndex(this.collection, {
458
+ field_name: "created_at",
459
+ field_schema: "integer",
460
+ }),
461
+ this.client.createPayloadIndex(this.collection, {
462
+ field_name: "conversation_id",
463
+ field_schema: "keyword",
464
+ }),
465
+ this.client.createPayloadIndex(this.collection, {
466
+ field_name: "modality",
467
+ field_schema: "keyword",
468
+ }),
469
+ ]);
470
+ }
471
+
472
+ private async readSentinel(): Promise<string | null> {
473
+ try {
474
+ const points = await this.client.retrieve(this.collection, {
475
+ ids: [this.SENTINEL_ID],
476
+ with_payload: true,
477
+ with_vector: false,
478
+ });
479
+ if (points.length === 0) return null;
480
+ return (
481
+ ((points[0].payload as Record<string, unknown>)
482
+ ?.embedding_model as string) ?? null
483
+ );
484
+ } catch {
485
+ return null;
486
+ }
487
+ }
488
+
489
+ private async writeSentinel(model: string): Promise<void> {
490
+ await this.client.upsert(this.collection, {
491
+ wait: true,
492
+ points: [
493
+ {
494
+ id: this.SENTINEL_ID,
495
+ vector: new Array(this.vectorSize).fill(0), // zero vector, never matched in search
496
+ payload: { _meta: true, embedding_model: model },
497
+ },
498
+ ],
499
+ });
500
+ }
501
+
387
502
  private async findByTarget(
388
503
  targetType: string,
389
504
  targetId: string,
@@ -26,7 +26,6 @@ mock.module("../util/platform.js", () => ({
26
26
  isMacOS: () => process.platform === "darwin",
27
27
  isLinux: () => process.platform === "linux",
28
28
  isWindows: () => process.platform === "win32",
29
- getSocketPath: () => join(testDir, "test.sock"),
30
29
  getPidPath: () => join(testDir, "test.pid"),
31
30
  getDbPath: () => join(testDir, "test.db"),
32
31
  getLogPath: () => join(testDir, "test.log"),
@@ -538,7 +538,7 @@ async function generateQueryEmbedding(
538
538
  };
539
539
  }
540
540
  logMemoryEmbeddingWarning(err, "query");
541
- degraded = config.memory.embeddings.required;
541
+ degraded = true;
542
542
  reason = `memory.embedding_failure: ${
543
543
  err instanceof Error ? err.message : String(err)
544
544
  }`;
@@ -828,7 +828,17 @@ export async function buildMemoryRecall(
828
828
  // degradation state. This ensures results computed with boosted limits
829
829
  // are marked degraded and excluded from the recall cache — preventing
830
830
  // stale boosted results from being served after the breaker closes.
831
- if (collected.semanticSearchFailed || collected.semanticUnavailable) {
831
+ //
832
+ // Exception: when semanticUnavailable is solely because no embedding
833
+ // provider is configured (queryVector == null) and embeddings are not
834
+ // required, lexical-only results are the expected steady state — do not
835
+ // mark as degraded.
836
+ const semanticActuallyFailed =
837
+ collected.semanticSearchFailed ||
838
+ (collected.semanticUnavailable &&
839
+ (embeddingResult.queryVector != null ||
840
+ config.memory.embeddings.required));
841
+ if (semanticActuallyFailed) {
832
842
  embeddingResult.degraded = true;
833
843
  embeddingResult.reason =
834
844
  embeddingResult.reason ??
@@ -7,39 +7,11 @@ import {
7
7
  text,
8
8
  } from "drizzle-orm/sqlite-core";
9
9
 
10
- export const accounts = sqliteTable("accounts", {
11
- id: text("id").primaryKey(),
12
- service: text("service").notNull(),
13
- username: text("username"),
14
- email: text("email"),
15
- displayName: text("display_name"),
16
- status: text("status").notNull().default("active"),
17
- credentialRef: text("credential_ref"),
18
- metadataJson: text("metadata_json"),
19
- createdAt: integer("created_at").notNull(),
20
- updatedAt: integer("updated_at").notNull(),
21
- });
22
-
23
- export const reminders = sqliteTable("reminders", {
24
- id: text("id").primaryKey(),
25
- label: text("label").notNull(),
26
- message: text("message").notNull(),
27
- fireAt: integer("fire_at").notNull(), // epoch ms, absolute timestamp
28
- mode: text("mode").notNull(), // 'notify' | 'execute'
29
- status: text("status").notNull(), // 'pending' | 'firing' | 'fired' | 'cancelled'
30
- firedAt: integer("fired_at"),
31
- conversationId: text("conversation_id"),
32
- routingIntent: text("routing_intent").notNull().default("all_channels"), // 'single_channel' | 'multi_channel' | 'all_channels'
33
- routingHintsJson: text("routing_hints_json").notNull().default("{}"),
34
- createdAt: integer("created_at").notNull(),
35
- updatedAt: integer("updated_at").notNull(),
36
- });
37
-
38
10
  export const cronJobs = sqliteTable("cron_jobs", {
39
11
  id: text("id").primaryKey(),
40
12
  name: text("name").notNull(),
41
13
  enabled: integer("enabled", { mode: "boolean" }).notNull().default(true),
42
- cronExpression: text("cron_expression").notNull(), // e.g. '0 9 * * 1-5'
14
+ cronExpression: text("cron_expression"), // nullable for one-shot schedules; e.g. '0 9 * * 1-5'
43
15
  scheduleSyntax: text("schedule_syntax").notNull().default("cron"), // 'cron' | 'rrule'
44
16
  timezone: text("timezone"), // e.g. 'America/Los_Angeles'
45
17
  message: text("message").notNull(),
@@ -48,6 +20,10 @@ export const cronJobs = sqliteTable("cron_jobs", {
48
20
  lastStatus: text("last_status"), // 'ok' | 'error'
49
21
  retryCount: integer("retry_count").notNull().default(0),
50
22
  createdBy: text("created_by").notNull(), // 'agent' | 'user'
23
+ mode: text("mode").notNull().default("execute"), // 'notify' | 'execute'
24
+ routingIntent: text("routing_intent").notNull().default("all_channels"), // 'single_channel' | 'multi_channel' | 'all_channels'
25
+ routingHintsJson: text("routing_hints_json").notNull().default("{}"),
26
+ status: text("status").notNull().default("active"), // 'active' | 'firing' | 'fired' | 'cancelled'
51
27
  createdAt: integer("created_at").notNull(),
52
28
  updatedAt: integer("updated_at").notNull(),
53
29
  });
@@ -99,15 +99,25 @@ function buildStructuredInjectedText(candidates: Candidate[]): string {
99
99
  for (const candidate of ordered) {
100
100
  const absolute = formatAbsoluteTime(candidate.createdAt);
101
101
  const relative = formatRelativeTime(candidate.createdAt);
102
- parts.push(
103
- `<entry kind="${escapeXmlAttr(candidate.kind)}" type="${
104
- candidate.type
105
- }" confidence="${candidate.confidence.toFixed(
106
- 2,
107
- )}" time="${absolute} (${relative})">` +
108
- escapeXmlTags(truncate(candidate.text, 320)) +
109
- "</entry>",
110
- );
102
+ if (candidate.type === "media") {
103
+ const modality = candidate.modality ?? "media";
104
+ const subject = candidate.kind !== "media" ? ` (${candidate.kind})` : "";
105
+ parts.push(
106
+ `<entry kind="${escapeXmlAttr(candidate.kind)}" type="media" confidence="${candidate.confidence.toFixed(
107
+ 2,
108
+ )}" time="${absolute} (${relative})">[Recalled ${modality}${subject}]</entry>`,
109
+ );
110
+ } else {
111
+ parts.push(
112
+ `<entry kind="${escapeXmlAttr(candidate.kind)}" type="${
113
+ candidate.type
114
+ }" confidence="${candidate.confidence.toFixed(
115
+ 2,
116
+ )}" time="${absolute} (${relative})">` +
117
+ escapeXmlTags(truncate(candidate.text, 320)) +
118
+ "</entry>",
119
+ );
120
+ }
111
121
  }
112
122
  parts.push("</entries>");
113
123
  parts.push(MEMORY_RECALL_CLOSE_TAG);
@@ -146,6 +156,9 @@ export function applyAttentionOrdering(candidates: Candidate[]): Candidate[] {
146
156
  }
147
157
 
148
158
  function formatCandidateLine(candidate: Candidate): string {
159
+ if (candidate.type === "media") {
160
+ return formatMediaCandidateLine(candidate);
161
+ }
149
162
  const absolute = formatAbsoluteTime(candidate.createdAt);
150
163
  const relative = formatRelativeTime(candidate.createdAt);
151
164
  return `- <kind>${candidate.kind}</kind> ${escapeXmlTags(
@@ -153,6 +166,18 @@ function formatCandidateLine(candidate: Candidate): string {
153
166
  )} (${absolute} \u00b7 ${relative})`;
154
167
  }
155
168
 
169
+ /**
170
+ * Format a media candidate as a descriptive reference. Since the LLM can't
171
+ * see the actual image/audio from memory recall text, we provide a reference
172
+ * that gives awareness of relevant media in memory.
173
+ */
174
+ function formatMediaCandidateLine(candidate: Candidate): string {
175
+ const modality = candidate.modality ?? "media";
176
+ const subject = candidate.kind !== "media" ? ` (${candidate.kind})` : "";
177
+ const relative = formatRelativeTime(candidate.createdAt);
178
+ return `- [Recalled ${modality}${subject} from ${relative}]`;
179
+ }
180
+
156
181
  /**
157
182
  * Escape XML-like tag sequences in recalled text to prevent delimiter injection.
158
183
  * Recalled content is interpolated verbatim inside `<memory>` wrapper tags,
@@ -10,6 +10,7 @@ import {
10
10
  import type { QdrantSearchResult } from "../qdrant-client.js";
11
11
  import { getQdrantClient } from "../qdrant-client.js";
12
12
  import {
13
+ conversations,
13
14
  memoryItems,
14
15
  memoryItemSources,
15
16
  memorySegments,
@@ -43,7 +44,7 @@ export async function semanticSearch(
43
44
  qdrant.searchWithFilter(
44
45
  queryVector,
45
46
  fetchLimit,
46
- ["item", "summary", "segment"],
47
+ ["item", "summary", "segment", "media"],
47
48
  excludedMessageIds,
48
49
  ),
49
50
  );
@@ -54,12 +55,16 @@ export async function semanticSearch(
54
55
  const itemTargetIds: string[] = [];
55
56
  const summaryTargetIds: string[] = [];
56
57
  const segmentTargetIds: string[] = [];
58
+ const mediaConversationIds: string[] = [];
57
59
  for (const r of results) {
58
60
  if (r.payload.target_type === "item")
59
61
  itemTargetIds.push(r.payload.target_id);
60
62
  else if (r.payload.target_type === "summary")
61
63
  summaryTargetIds.push(r.payload.target_id);
62
- else segmentTargetIds.push(r.payload.target_id);
64
+ else if (r.payload.target_type === "segment")
65
+ segmentTargetIds.push(r.payload.target_id);
66
+ else if (r.payload.target_type === "media" && r.payload.conversation_id)
67
+ mediaConversationIds.push(r.payload.conversation_id);
63
68
  }
64
69
 
65
70
  const itemsMap = new Map<string, typeof memoryItems.$inferSelect>();
@@ -109,6 +114,23 @@ export async function semanticSearch(
109
114
  for (const seg of allSegments) segmentsMap.set(seg.id, seg);
110
115
  }
111
116
 
117
+ // Batch-fetch conversation scope IDs for media results to avoid N+1 queries.
118
+ // When a conversation is not found (deleted), its media is excluded rather than
119
+ // falling back to "default" scope, which would leak private media.
120
+ const mediaScopeMap = new Map<string, string>();
121
+ if (scopeIds && mediaConversationIds.length > 0) {
122
+ const unique = [...new Set(mediaConversationIds)];
123
+ const rows = db
124
+ .select({
125
+ id: conversations.id,
126
+ memoryScopeId: conversations.memoryScopeId,
127
+ })
128
+ .from(conversations)
129
+ .where(inArray(conversations.id, unique))
130
+ .all();
131
+ for (const row of rows) mediaScopeMap.set(row.id, row.memoryScopeId);
132
+ }
133
+
112
134
  const excludedSet =
113
135
  excludedMessageIds.length > 0 ? new Set(excludedMessageIds) : null;
114
136
 
@@ -164,6 +186,39 @@ export async function semanticSearch(
164
186
  recency: computeRecencyScore(payload.last_seen_at ?? createdAt),
165
187
  finalScore: 0,
166
188
  });
189
+ } else if (payload.target_type === "media") {
190
+ // Use stored memory_scope_id when available; fall back to deriving
191
+ // scope from conversation_id for legacy media points.
192
+ // If the conversation was deleted, skip the media to avoid leaking
193
+ // private media into the default scope.
194
+ if (scopeIds) {
195
+ let mediaScopeId: string | undefined;
196
+ if (payload.memory_scope_id) {
197
+ mediaScopeId = payload.memory_scope_id;
198
+ } else if (payload.conversation_id) {
199
+ mediaScopeId = mediaScopeMap.get(payload.conversation_id);
200
+ if (!mediaScopeId) continue; // conversation deleted — skip
201
+ } else {
202
+ mediaScopeId = "default";
203
+ }
204
+ if (!scopeIds.includes(mediaScopeId)) continue;
205
+ }
206
+ candidates.push({
207
+ key: `media:${payload.target_id}`,
208
+ type: "media",
209
+ id: payload.target_id,
210
+ source: "semantic",
211
+ text: payload.text,
212
+ kind: payload.kind ?? "media",
213
+ modality: payload.modality,
214
+ confidence: 0.7,
215
+ importance: 0.6,
216
+ createdAt,
217
+ lexical: 0,
218
+ semantic,
219
+ recency: computeRecencyScore(createdAt),
220
+ finalScore: 0,
221
+ });
167
222
  } else {
168
223
  if (scopeIds) {
169
224
  const segment = segmentsMap.get(payload.target_id);
@@ -1,4 +1,4 @@
1
- export type CandidateType = "segment" | "item" | "summary";
1
+ export type CandidateType = "segment" | "item" | "summary" | "media";
2
2
  export type CandidateSource =
3
3
  | "lexical"
4
4
  | "semantic"
@@ -14,6 +14,7 @@ export interface Candidate {
14
14
  source: CandidateSource;
15
15
  text: string;
16
16
  kind: string;
17
+ modality?: "text" | "image" | "audio" | "video";
17
18
  confidence: number;
18
19
  importance: number;
19
20
  createdAt: number;
@@ -1,5 +1,5 @@
1
1
  # Notification Pipeline
2
2
 
3
- All notification producers **MUST** go through `emitNotificationSignal()` in `notifications/emit-signal.ts`. Do not bypass the pipeline by broadcasting IPC events directly -- the pipeline handles event persistence, deduplication, decision routing, and delivery audit.
3
+ All notification producers **MUST** go through `emitNotificationSignal()` in `notifications/emit-signal.ts`. Do not bypass the pipeline by broadcasting events directly -- the pipeline handles event persistence, deduplication, decision routing, and delivery audit.
4
4
 
5
- When a notification flow creates a server-side conversation (e.g. guardian question threads, task run threads), the conversation and initial message **MUST** be persisted before the IPC thread-created event is emitted. This ensures the macOS/iOS client can immediately fetch the conversation contents when it receives the event.
5
+ When a notification flow creates a server-side conversation (e.g. guardian question threads, task run threads), the conversation and initial message **MUST** be persisted before the thread-created event is emitted. This ensures the macOS/iOS client can immediately fetch the conversation contents when it receives the event.