@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
@@ -14,7 +14,6 @@
14
14
  import {
15
15
  isCredentialError,
16
16
  isTokenExpired,
17
- oauthConnectionAccessTokenPath,
18
17
  oauthConnectionRefreshTokenPath,
19
18
  persistRefreshedTokens,
20
19
  RefreshCircuitBreaker,
@@ -22,6 +21,7 @@ import {
22
21
  type SecureKeyBackend,
23
22
  } from "@vellumai/credential-storage";
24
23
 
24
+ import { getConnectionAccessTokenResult } from "../oauth/credential-token-resolver.js";
25
25
  import {
26
26
  getApp,
27
27
  getConnection,
@@ -321,9 +321,13 @@ export async function withValidToken<T>(
321
321
  opts && typeof opts === "object"
322
322
  ? getConnection(opts.connectionId)
323
323
  : getConnectionByProvider(service, opts);
324
- let token = conn
325
- ? await getSecureKeyAsync(oauthConnectionAccessTokenPath(conn.id))
324
+ const tokenResult = conn
325
+ ? await getConnectionAccessTokenResult({
326
+ provider: conn.provider,
327
+ connectionId: conn.id,
328
+ })
326
329
  : undefined;
330
+ let token = tokenResult?.value;
327
331
  if (!token || !conn) {
328
332
  throw new TokenExpiredError(
329
333
  service,
@@ -5,34 +5,23 @@
5
5
  * HTTP POST to `/v1/conversations/:id/cancel`. The daemon's ConfigWatcher
6
6
  * detects the file change and invokes {@link handleCancelSignal}, which
7
7
  * reads the payload and aborts the target conversation.
8
- *
9
- * Because the signal handler needs access to the daemon's conversation map, the
10
- * daemon registers a callback at startup via {@link registerCancelCallback}.
11
8
  */
12
9
 
13
10
  import { readFileSync } from "node:fs";
14
11
  import { join } from "node:path";
15
12
 
16
13
  import { getIsContainerized } from "../config/env-registry.js";
14
+ import {
15
+ findConversation,
16
+ touchConversation,
17
+ } from "../daemon/conversation-store.js";
18
+ import { getSubagentManager } from "../subagent/index.js";
19
+ import { createAbortReason } from "../util/abort-reasons.js";
17
20
  import { getLogger } from "../util/logger.js";
18
21
  import { getSignalsDir } from "../util/platform.js";
19
22
 
20
23
  const log = getLogger("signal:cancel");
21
24
 
22
- // ── Daemon callback registry ─────────────────────────────────────────
23
-
24
- type CancelCallback = (conversationId: string) => boolean;
25
-
26
- let _cancelGeneration: CancelCallback | null = null;
27
-
28
- /**
29
- * Register the cancel-generation callback. Called once by the daemon
30
- * server at startup so the signal handler can reach the conversation map.
31
- */
32
- export function registerCancelCallback(cb: CancelCallback): void {
33
- _cancelGeneration = cb;
34
- }
35
-
36
25
  // ── Signal handler ───────────────────────────────────────────────────
37
26
 
38
27
  /**
@@ -52,17 +41,19 @@ export function handleCancelSignal(): void {
52
41
  return;
53
42
  }
54
43
 
55
- if (!_cancelGeneration) {
56
- log.warn("Cancel callback not registered; daemon may not be ready");
44
+ const conversation = findConversation(conversationId);
45
+ if (!conversation) {
46
+ log.warn({ conversationId }, "No active conversation for cancel signal");
57
47
  return;
58
48
  }
59
49
 
60
- const found = _cancelGeneration(conversationId);
61
- if (found) {
62
- log.info({ conversationId }, "Generation cancelled via signal file");
63
- } else {
64
- log.warn({ conversationId }, "No active conversation for cancel signal");
65
- }
50
+ touchConversation(conversationId);
51
+ conversation.abort(
52
+ createAbortReason("signal_cancel", "handleCancelSignal", conversationId),
53
+ );
54
+ getSubagentManager().abortAllForParent(conversationId);
55
+
56
+ log.info({ conversationId }, "Generation cancelled via signal file");
66
57
  } catch (err) {
67
58
  log.error({ err }, "Failed to handle cancel signal");
68
59
  }
@@ -7,37 +7,18 @@
7
7
  * {@link handleConversationUndoSignal}, which reads the payload, performs
8
8
  * the undo, and writes `signals/conversation-undo.result` so the CLI
9
9
  * receives feedback.
10
- *
11
- * Because the signal handler needs access to the daemon's conversation map, the
12
- * daemon registers a callback at startup via
13
- * {@link registerConversationUndoCallback}.
14
10
  */
15
11
 
16
12
  import { readFileSync, writeFileSync } from "node:fs";
17
13
  import { join } from "node:path";
18
14
 
19
15
  import { getIsContainerized } from "../config/env-registry.js";
16
+ import { undoLastMessage } from "../daemon/handlers/conversations.js";
20
17
  import { getLogger } from "../util/logger.js";
21
18
  import { getSignalsDir } from "../util/platform.js";
22
19
 
23
20
  const log = getLogger("signal:conversation-undo");
24
21
 
25
- // ── Daemon callback registry ─────────────────────────────────────────
26
-
27
- type UndoCallback = (
28
- conversationId: string,
29
- ) => Promise<{ removedCount: number } | null>;
30
-
31
- let _undoLastMessage: UndoCallback | null = null;
32
-
33
- /**
34
- * Register the undo callback. Called once by the daemon server at startup
35
- * so the signal handler can reach the conversation map.
36
- */
37
- export function registerConversationUndoCallback(cb: UndoCallback): void {
38
- _undoLastMessage = cb;
39
- }
40
-
41
22
  // ── Signal handler ───────────────────────────────────────────────────
42
23
 
43
24
  /**
@@ -93,13 +74,7 @@ export async function handleConversationUndoSignal(): Promise<void> {
93
74
  return;
94
75
  }
95
76
 
96
- if (!_undoLastMessage) {
97
- log.warn("Undo callback not registered; daemon may not be ready");
98
- writeResult({ ok: false, error: "Assistant not ready", requestId });
99
- return;
100
- }
101
-
102
- const result = await _undoLastMessage(conversationId);
77
+ const result = await undoLastMessage(conversationId);
103
78
  if (!result) {
104
79
  log.warn({ conversationId }, "No active conversation for undo signal");
105
80
  writeResult({ ok: false, error: "No active conversation", requestId });
@@ -18,7 +18,6 @@ import { join } from "node:path";
18
18
  import type { ServerMessage } from "../daemon/message-protocol.js";
19
19
  import { buildAssistantEvent } from "../runtime/assistant-event.js";
20
20
  import { assistantEventHub } from "../runtime/assistant-event-hub.js";
21
- import { DAEMON_INTERNAL_ASSISTANT_ID } from "../runtime/assistant-scope.js";
22
21
  import { getLogger } from "../util/logger.js";
23
22
  import { getSignalsDir } from "../util/platform.js";
24
23
 
@@ -30,7 +29,7 @@ export function handleEmitEventSignal(): void {
30
29
  const message = JSON.parse(content) as ServerMessage;
31
30
 
32
31
  assistantEventHub
33
- .publish(buildAssistantEvent(DAEMON_INTERNAL_ASSISTANT_ID, message))
32
+ .publish(buildAssistantEvent(message))
34
33
  .catch((err: unknown) => {
35
34
  log.error({ err }, "Failed to publish event from signal");
36
35
  });
@@ -9,15 +9,24 @@
9
9
  *
10
10
  * Per-request filenames avoid dropped messages when overlapping invocations
11
11
  * race on the same signal file.
12
- *
13
- * Because the signal handler needs access to the daemon's conversation map and
14
- * event hub, the daemon registers a callback at startup via
15
- * {@link registerUserMessageCallback}.
16
12
  */
17
13
 
18
- import { readFileSync, unlinkSync, writeFileSync } from "node:fs";
14
+ import { readFileSync, statSync, unlinkSync, writeFileSync } from "node:fs";
19
15
  import { join } from "node:path";
20
16
 
17
+ import { getOrCreateConversation } from "../daemon/conversation-store.js";
18
+ import type { UserMessageAttachment } from "../daemon/message-types/shared.js";
19
+ import {
20
+ processMessageInBackground,
21
+ resolveTurnChannel,
22
+ resolveTurnInterface,
23
+ } from "../daemon/process-message.js";
24
+ import {
25
+ uploadFileBackedAttachment,
26
+ validateAttachmentUpload,
27
+ } from "../memory/attachments-store.js";
28
+ import { getOrCreateConversation as getOrCreateConversationKey } from "../memory/conversation-key-store.js";
29
+ import { checkIngressForSecrets } from "../security/secret-ingress.js";
21
30
  import { getLogger } from "../util/logger.js";
22
31
  import { getSignalsDir } from "../util/platform.js";
23
32
 
@@ -35,25 +44,108 @@ export interface SignalAttachment {
35
44
  mimeType: string;
36
45
  }
37
46
 
38
- // ── Daemon callback registry ─────────────────────────────────────────
47
+ // ── Dispatch helper ──────────────────────────────────────────────────
39
48
 
40
- type UserMessageCallback = (params: {
49
+ async function dispatchUserMessage(params: {
41
50
  conversationKey: string;
42
51
  content: string;
43
52
  sourceChannel: string;
44
53
  sourceInterface: string;
45
54
  bypassSecretCheck?: boolean;
46
55
  attachments?: SignalAttachment[];
47
- }) => Promise<{ accepted: boolean; error?: string; message?: string }>;
56
+ }): Promise<{ accepted: boolean; error?: string; message?: string }> {
57
+ if (!params.bypassSecretCheck) {
58
+ const ingressResult = checkIngressForSecrets(params.content);
59
+ if (ingressResult.blocked) {
60
+ return {
61
+ accepted: false,
62
+ error: "secret_blocked" as const,
63
+ message: ingressResult.userNotice,
64
+ };
65
+ }
66
+ }
48
67
 
49
- let _sendUserMessage: UserMessageCallback | null = null;
68
+ const { conversationId } = getOrCreateConversationKey(params.conversationKey);
69
+ const conversation = await getOrCreateConversation(conversationId);
50
70
 
51
- /**
52
- * Register the user-message callback. Called once by the daemon server at
53
- * startup so the signal handler can reach the conversation map and event hub.
54
- */
55
- export function registerUserMessageCallback(cb: UserMessageCallback): void {
56
- _sendUserMessage = cb;
71
+ const attachmentIds: string[] = [];
72
+ const resolvedAttachments: UserMessageAttachment[] = [];
73
+ if (params.attachments && params.attachments.length > 0) {
74
+ for (const a of params.attachments) {
75
+ try {
76
+ const validation = validateAttachmentUpload(a.filename, a.mimeType);
77
+ if (!validation.ok) {
78
+ log.warn(
79
+ { error: validation.error, path: a.path },
80
+ "Signal attachment rejected by validation",
81
+ );
82
+ continue;
83
+ }
84
+ const size = statSync(a.path).size;
85
+ const stored = uploadFileBackedAttachment(
86
+ a.filename,
87
+ a.mimeType,
88
+ a.path,
89
+ size,
90
+ );
91
+ attachmentIds.push(stored.id);
92
+ resolvedAttachments.push({
93
+ id: stored.id,
94
+ filename: a.filename,
95
+ mimeType: a.mimeType,
96
+ data: "",
97
+ filePath: a.path,
98
+ });
99
+ } catch (err) {
100
+ log.warn({ err, path: a.path }, "Failed to register signal attachment");
101
+ }
102
+ }
103
+ }
104
+
105
+ if (conversation.isProcessing()) {
106
+ for (let i = resolvedAttachments.length - 1; i >= 0; i--) {
107
+ const att = resolvedAttachments[i];
108
+ if (att.filePath && !att.data) {
109
+ try {
110
+ att.data = readFileSync(att.filePath).toString("base64");
111
+ } catch (err) {
112
+ log.warn(
113
+ { err, path: att.filePath },
114
+ "Failed to read queued signal attachment, skipping",
115
+ );
116
+ resolvedAttachments.splice(i, 1);
117
+ }
118
+ }
119
+ }
120
+ const requestId = crypto.randomUUID();
121
+ const resolvedChannel = resolveTurnChannel(params.sourceChannel);
122
+ const resolvedInterface = resolveTurnInterface(params.sourceInterface);
123
+ const result = conversation.enqueueMessage(
124
+ params.content,
125
+ resolvedAttachments,
126
+ undefined,
127
+ requestId,
128
+ undefined,
129
+ undefined,
130
+ {
131
+ userMessageChannel: resolvedChannel,
132
+ assistantMessageChannel: resolvedChannel,
133
+ userMessageInterface: resolvedInterface,
134
+ assistantMessageInterface: resolvedInterface,
135
+ },
136
+ );
137
+ return { accepted: !result.rejected };
138
+ }
139
+
140
+ await processMessageInBackground(
141
+ conversationId,
142
+ params.content,
143
+ attachmentIds.length > 0 ? attachmentIds : undefined,
144
+ undefined,
145
+ params.sourceChannel,
146
+ params.sourceInterface,
147
+ );
148
+ return { accepted: true };
57
149
  }
58
150
 
59
151
  // ── Signal handler ───────────────────────────────────────────────────
@@ -143,12 +235,6 @@ export async function handleUserMessageSignal(filename: string): Promise<void> {
143
235
  return;
144
236
  }
145
237
 
146
- if (!_sendUserMessage) {
147
- log.warn("User-message callback not registered; daemon may not be ready");
148
- writeResult({ ok: false, error: "Assistant not ready", requestId });
149
- return;
150
- }
151
-
152
238
  // Validate and normalize attachments
153
239
  const attachments: SignalAttachment[] = [];
154
240
  if (Array.isArray(parsed.attachments)) {
@@ -167,7 +253,7 @@ export async function handleUserMessageSignal(filename: string): Promise<void> {
167
253
  }
168
254
  }
169
255
 
170
- const result = await _sendUserMessage({
256
+ const result = await dispatchUserMessage({
171
257
  conversationKey: parsed.conversationKey,
172
258
  content: parsed.content,
173
259
  sourceChannel: parsed.sourceChannel ?? "vellum",
@@ -30,6 +30,7 @@ export interface CatalogSkill {
30
30
  emoji?: string;
31
31
  includes?: string[];
32
32
  version?: string;
33
+ updatedAt?: string;
33
34
  metadata?: {
34
35
  vellum?: {
35
36
  "display-name"?: string;
@@ -181,7 +181,7 @@ async function runClawhub(
181
181
  const { mkdirSync } = await import("node:fs");
182
182
  mkdirSync(cwd, { recursive: true });
183
183
 
184
- log.info({ args, cwd }, "Running clawhub command");
184
+ log.debug({ args, cwd }, "Running clawhub command");
185
185
 
186
186
  const proc = Bun.spawn(["npx", "clawhub", ...args], {
187
187
  cwd,
@@ -211,7 +211,7 @@ async function runClawhub(
211
211
 
212
212
  const exitCode = await proc.exited;
213
213
 
214
- log.info(
214
+ log.debug(
215
215
  { exitCode, stdoutLen: stdout.length, stderrLen: stderr.length },
216
216
  "clawhub command completed",
217
217
  );
@@ -24,7 +24,6 @@
24
24
  import { spawn } from "node:child_process";
25
25
 
26
26
  import { buildSanitizedEnv } from "../tools/terminal/safe-env.js";
27
- import { wrapCommand } from "../tools/terminal/sandbox.js";
28
27
  import { getLogger } from "../util/logger.js";
29
28
 
30
29
  const log = getLogger("inline-command-runner");
@@ -105,12 +104,7 @@ export async function runInlineCommand(
105
104
  const timeoutMs = options?.timeoutMs ?? DEFAULT_TIMEOUT_MS;
106
105
  const maxChars = options?.maxOutputChars ?? MAX_OUTPUT_CHARS;
107
106
 
108
- // Sandbox is disabled the assistant runs in Docker or platform-managed
109
- // environments where the container provides isolation. The networkMode
110
- // option is a no-op when sandbox is disabled (wrapCommand returns a plain
111
- // bash invocation); network isolation is handled at the container level.
112
- const sandboxConfig = { enabled: false } as const;
113
- const wrapped = wrapCommand(command, workingDir, sandboxConfig);
107
+ const wrapped = { command: "bash", args: ["-c", "--", command] };
114
108
 
115
109
  // Build a minimal, sanitized environment. Explicitly exclude gateway URL,
116
110
  // workspace dir, and data dir since inline commands have no business calling
@@ -116,13 +116,6 @@ export interface SubagentNotificationInfo {
116
116
  conversationId?: string;
117
117
  }
118
118
 
119
- export type ParentNotifyCallback = (
120
- parentConversationId: string,
121
- message: string,
122
- sendToClient: (msg: ServerMessage) => void,
123
- notification: SubagentNotificationInfo,
124
- ) => void;
125
-
126
119
  export class SubagentManager {
127
120
  /** subagentId → ManagedSubagent */
128
121
  private subagents = new Map<string, ManagedSubagent>();
@@ -131,26 +124,12 @@ export class SubagentManager {
131
124
  /** `${parentConversationId}:${normalizedLabel}` → subagentId */
132
125
  private labelIndex = new Map<string, string>();
133
126
 
134
- /**
135
- * Optional callback to inject a completion/failure message into the parent
136
- * conversation so the LLM can automatically inform the user.
137
- * Wired by DaemonServer at startup.
138
- */
139
- onSubagentFinished?: ParentNotifyCallback;
140
-
141
127
  /**
142
128
  * Shared rate-limit timestamps array from the daemon server.
143
129
  * Set by DaemonServer at startup so subagents share the global rate limit.
144
130
  */
145
131
  sharedRequestTimestamps: number[] = [];
146
132
 
147
- /**
148
- * Broadcast callback from the daemon server.
149
- * Set by DaemonServer at startup so subagent conversations can broadcast
150
- * to all connected clients (e.g. app_files_changed side-effects).
151
- */
152
- broadcastToAllClients?: (msg: ServerMessage) => void;
153
-
154
133
  // ── Spawn ───────────────────────────────────────────────────────────
155
134
 
156
135
  /**
@@ -310,7 +289,6 @@ export class SubagentManager {
310
289
  maxTokens,
311
290
  wrappedSendToClient,
312
291
  workingDir,
313
- this.broadcastToAllClients, // forward parent's broadcast so tool side-effects (e.g. app_files_changed) reach all clients
314
292
  memoryPolicy,
315
293
  undefined, // sharedCesClient
316
294
  undefined, // speedOverride
@@ -427,8 +405,6 @@ export class SubagentManager {
427
405
  this.setStatus(subagentId, "running", getSender());
428
406
  managed.state.startedAt = Date.now();
429
407
 
430
- const onEvent = conversation.sendToClient;
431
-
432
408
  try {
433
409
  // For forks, inject the parent's message history before the first message.
434
410
  // This prepends the inherited context so the fork has full conversational
@@ -462,7 +438,7 @@ export class SubagentManager {
462
438
  ].join("\n")
463
439
  : objective;
464
440
  const messageId = await conversation.persistUserMessage(message, []);
465
- await conversation.runAgentLoop(message, messageId, onEvent, {
441
+ await conversation.runAgentLoop(message, messageId, undefined, {
466
442
  callSite: "subagentSpawn",
467
443
  ...(managed.state.config.overrideProfile
468
444
  ? { overrideProfile: managed.state.config.overrideProfile }
@@ -480,7 +456,7 @@ export class SubagentManager {
480
456
  log.info({ subagentId }, "Subagent completed");
481
457
 
482
458
  // Notify the parent conversation so the LLM can call subagent_read.
483
- this.notifyParentTerminal(managed, "completed", getSender());
459
+ this.notifyParentTerminal(managed, "completed");
484
460
  }
485
461
  } catch (err) {
486
462
  const errorMsg = err instanceof Error ? err.message : String(err);
@@ -493,7 +469,7 @@ export class SubagentManager {
493
469
  // Only update status if not already terminal (e.g. aborted).
494
470
  if (!TERMINAL_STATUSES.has(managed.state.status)) {
495
471
  this.setStatus(subagentId, "failed", getSender(), errorMsg);
496
- this.notifyParentTerminal(managed, "failed", getSender());
472
+ this.notifyParentTerminal(managed, "failed");
497
473
  }
498
474
 
499
475
  log.error({ subagentId, err }, "Subagent failed");
@@ -566,30 +542,24 @@ export class SubagentManager {
566
542
  this.setStatus(subagentId, "aborted", statusSender);
567
543
  // Notify parent that the subagent was explicitly aborted — tell it NOT to re-spawn.
568
544
  // Skip when the parent LLM itself called subagent_abort (it already has the tool result).
569
- if (this.onSubagentFinished && !options?.suppressNotification) {
545
+ if (!options?.suppressNotification) {
570
546
  const label = managed.state.config.label;
571
547
  const prefix = managed.state.isFork ? "Fork" : "Subagent";
572
548
  const message =
573
549
  `[${prefix} "${label}" was explicitly aborted]\n\n` +
574
550
  `This ${prefix.toLowerCase()} was cancelled on purpose. Do NOT re-spawn or retry it.`;
575
- try {
576
- // Use the managed subagent's stored parentSendToClient so the
577
- // notification routes to the parent conversation's socket, not the
578
- // aborting socket (which may be a different conversation after switching).
579
- this.onSubagentFinished(
580
- managed.state.config.parentConversationId,
581
- message,
582
- managed.parentSendToClient,
583
- {
551
+ this.injectMessageIntoParent(
552
+ managed.state.config.parentConversationId,
553
+ message,
554
+ {
555
+ subagentNotification: {
584
556
  subagentId,
585
557
  label,
586
- status: "aborted",
558
+ status: "aborted" as const,
587
559
  conversationId: managed.state.conversationId,
588
560
  },
589
- );
590
- } catch (err) {
591
- log.error({ subagentId, err }, "Failed to notify parent about abort");
592
- }
561
+ },
562
+ );
593
563
  }
594
564
  } else {
595
565
  managed.state.status = "aborted";
@@ -640,18 +610,10 @@ export class SubagentManager {
640
610
  if (TERMINAL_STATUSES.has(managed.state.status) || !managed.conversation)
641
611
  return "terminal";
642
612
 
643
- const onEvent = managed.conversation.sendToClient;
644
- const requestId = uuid();
645
-
646
613
  // If the conversation is busy, queue the message; otherwise process immediately.
647
- const result = managed.conversation.enqueueMessage(
648
- trimmed,
649
- [],
650
- onEvent,
651
- requestId,
652
- );
614
+ const result = managed.conversation.enqueueMessage(trimmed, []);
653
615
  if (result.rejected) {
654
- return "sent"; // error event already delivered via onEvent
616
+ return "sent"; // error event already delivered via sendToClient
655
617
  }
656
618
  if (result.queued) {
657
619
  managed.hadEnqueuedMessages = true;
@@ -662,7 +624,7 @@ export class SubagentManager {
662
624
  const conversation = managed.conversation;
663
625
  const messageId = await conversation.persistUserMessage(trimmed, []);
664
626
  conversation
665
- .runAgentLoop(trimmed, messageId, onEvent, {
627
+ .runAgentLoop(trimmed, messageId, undefined, {
666
628
  callSite: "subagentSpawn",
667
629
  ...(managed.state.config.overrideProfile
668
630
  ? { overrideProfile: managed.state.config.overrideProfile }
@@ -928,7 +890,6 @@ export class SubagentManager {
928
890
 
929
891
  const managed = this.subagents.get(info.subagentId);
930
892
  if (!managed || TERMINAL_STATUSES.has(managed.state.status)) return false;
931
- if (!this.onSubagentFinished) return false;
932
893
 
933
894
  const prefix = managed.state.isFork ? "Fork" : "Subagent";
934
895
  let notificationString = `[${prefix} "${info.label}" — ${urgency}] ${message}`;
@@ -936,25 +897,18 @@ export class SubagentManager {
936
897
  notificationString += `\nUse subagent_message to send guidance to this ${prefix.toLowerCase()}.`;
937
898
  }
938
899
 
939
- try {
940
- this.onSubagentFinished(
941
- info.parentConversationId,
942
- notificationString,
943
- info.parentSendToClient,
944
- {
900
+ this.injectMessageIntoParent(
901
+ info.parentConversationId,
902
+ notificationString,
903
+ {
904
+ subagentNotification: {
945
905
  subagentId: info.subagentId,
946
906
  label: info.label,
947
- status: "running",
907
+ status: "running" as const,
948
908
  },
949
- );
950
- return true;
951
- } catch (err) {
952
- log.error(
953
- { subagentId: info.subagentId, err },
954
- "Failed to notify parent from subagent",
955
- );
956
- return false;
957
- }
909
+ },
910
+ );
911
+ return true;
958
912
  }
959
913
 
960
914
  /**
@@ -964,10 +918,7 @@ export class SubagentManager {
964
918
  private notifyParentTerminal(
965
919
  managed: ManagedSubagent,
966
920
  outcome: "completed" | "failed",
967
- parentSendToClient: (msg: ServerMessage) => void,
968
921
  ): void {
969
- if (!this.onSubagentFinished) return;
970
-
971
922
  const { config } = managed.state;
972
923
  const isFork = managed.state.isFork;
973
924
  let message: string;
@@ -1009,18 +960,50 @@ export class SubagentManager {
1009
960
  : {}),
1010
961
  };
1011
962
 
1012
- try {
1013
- this.onSubagentFinished(
1014
- config.parentConversationId,
1015
- message,
1016
- parentSendToClient,
1017
- notification,
1018
- );
1019
- } catch (err) {
1020
- log.error(
1021
- { subagentId: config.id, err },
1022
- "Failed to notify parent conversation",
963
+ this.injectMessageIntoParent(config.parentConversationId, message, {
964
+ subagentNotification: notification,
965
+ });
966
+ }
967
+
968
+ /**
969
+ * Inject a notification message into the parent conversation so the LLM
970
+ * sees subagent lifecycle events. Relies on the parent conversation's
971
+ * sendToClient (backed by broadcastMessage) for event delivery.
972
+ */
973
+ private injectMessageIntoParent(
974
+ parentConversationId: string,
975
+ message: string,
976
+ metadata?: Record<string, unknown>,
977
+ ): void {
978
+ const parentConversation = findConversation(parentConversationId);
979
+ if (!parentConversation) {
980
+ log.warn(
981
+ { parentConversationId },
982
+ "Subagent finished but parent conversation not found",
1023
983
  );
984
+ return;
985
+ }
986
+ const enqueueResult = parentConversation.enqueueMessage(
987
+ message,
988
+ [],
989
+ undefined,
990
+ undefined,
991
+ undefined,
992
+ undefined,
993
+ metadata,
994
+ );
995
+ if (!enqueueResult.queued && !enqueueResult.rejected) {
996
+ parentConversation
997
+ .persistUserMessage(message, [], undefined, metadata)
998
+ .then((messageId) =>
999
+ parentConversation.runAgentLoop(message, messageId),
1000
+ )
1001
+ .catch((err) => {
1002
+ log.error(
1003
+ { parentConversationId, err },
1004
+ "Failed to process subagent notification in parent",
1005
+ );
1006
+ });
1024
1007
  }
1025
1008
  }
1026
1009
  }