@vellumai/assistant 0.4.26 → 0.4.30

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 (1360) hide show
  1. package/.env.example +2 -2
  2. package/AGENTS.md +5 -0
  3. package/ARCHITECTURE.md +207 -105
  4. package/Dockerfile +1 -1
  5. package/README.md +111 -113
  6. package/bun.lock +0 -3
  7. package/docs/architecture/integrations.md +0 -1
  8. package/docs/architecture/memory.md +100 -63
  9. package/docs/error-handling.md +71 -0
  10. package/docs/runbook-trusted-contacts.md +89 -52
  11. package/docs/trusted-contact-access.md +48 -46
  12. package/package.json +3 -3
  13. package/scripts/compare-benchmarks.sh +12 -5
  14. package/scripts/ipc/check-swift-decoder-drift.ts +5 -3
  15. package/scripts/test.sh +89 -5
  16. package/src/__tests__/__snapshots__/ipc-snapshot.test.ts.snap +50 -37
  17. package/src/__tests__/access-request-decision.test.ts +0 -1
  18. package/src/__tests__/account-registry.test.ts +1 -1
  19. package/src/__tests__/actor-token-service.test.ts +40 -26
  20. package/src/__tests__/agent-loop-thinking.test.ts +29 -13
  21. package/src/__tests__/agent-loop.test.ts +2 -1
  22. package/src/__tests__/app-builder-tool-scripts.test.ts +1 -1
  23. package/src/__tests__/app-executors.test.ts +7 -17
  24. package/src/__tests__/approval-routes-http.test.ts +2 -2
  25. package/src/__tests__/asset-materialize-tool.test.ts +7 -7
  26. package/src/__tests__/asset-search-tool.test.ts +7 -7
  27. package/src/__tests__/assistant-feature-flags-integration.test.ts +18 -10
  28. package/src/__tests__/browser-fill-credential.test.ts +1 -1
  29. package/src/__tests__/browser-skill-endstate.test.ts +10 -1
  30. package/src/__tests__/bundled-skill-retrieval-guard.test.ts +218 -0
  31. package/src/__tests__/call-controller.test.ts +99 -69
  32. package/src/__tests__/call-start-guardian-guard.test.ts +1 -1
  33. package/src/__tests__/channel-approval-routes.test.ts +157 -114
  34. package/src/__tests__/channel-approval.test.ts +8 -0
  35. package/src/__tests__/channel-approvals.test.ts +39 -1
  36. package/src/__tests__/channel-guardian.test.ts +176 -275
  37. package/src/__tests__/channel-readiness-service.test.ts +6 -2
  38. package/src/__tests__/channel-reply-delivery.test.ts +33 -2
  39. package/src/__tests__/channel-retry-sweep.test.ts +14 -14
  40. package/src/__tests__/checker.test.ts +12 -31
  41. package/src/__tests__/claude-code-tool-profiles.test.ts +1 -1
  42. package/src/__tests__/commit-message-enrichment-service.test.ts +71 -59
  43. package/src/__tests__/compaction.benchmark.test.ts +6 -2
  44. package/src/__tests__/computer-use-tools.test.ts +1 -1
  45. package/src/__tests__/config-schema.test.ts +66 -7
  46. package/src/__tests__/confirmation-request-guardian-bridge.test.ts +29 -29
  47. package/src/__tests__/contacts-tools.test.ts +63 -2
  48. package/src/__tests__/context-overflow-approval.test.ts +141 -0
  49. package/src/__tests__/context-overflow-policy.test.ts +171 -0
  50. package/src/__tests__/context-overflow-reducer.test.ts +533 -0
  51. package/src/__tests__/context-window-manager.test.ts +97 -0
  52. package/src/__tests__/conversation-attention-telegram.test.ts +38 -46
  53. package/src/__tests__/conversation-pairing.test.ts +2 -2
  54. package/src/__tests__/conversation-routes-guardian-reply.test.ts +214 -10
  55. package/src/__tests__/conversation-routes.test.ts +4 -7
  56. package/src/__tests__/credential-broker-browser-fill.test.ts +13 -2
  57. package/src/__tests__/credential-security-e2e.test.ts +1 -1
  58. package/src/__tests__/credential-security-invariants.test.ts +1 -1
  59. package/src/__tests__/credential-vault-unit.test.ts +1 -1
  60. package/src/__tests__/credential-vault.test.ts +11 -8
  61. package/src/__tests__/daemon-lifecycle.test.ts +2 -2
  62. package/src/__tests__/daemon-server-session-init.test.ts +6 -6
  63. package/src/__tests__/delete-managed-skill-tool.test.ts +1 -1
  64. package/src/__tests__/deterministic-verification-control-plane.test.ts +2 -2
  65. package/src/__tests__/dynamic-skill-workflow-prompt.test.ts +9 -0
  66. package/src/__tests__/emit-signal-routing-intent.test.ts +4 -0
  67. package/src/__tests__/encrypted-store.test.ts +10 -7
  68. package/src/__tests__/ephemeral-permissions.test.ts +3 -3
  69. package/src/__tests__/file-edit-tool.test.ts +1 -1
  70. package/src/__tests__/file-read-tool.test.ts +1 -1
  71. package/src/__tests__/file-write-tool.test.ts +1 -1
  72. package/src/__tests__/fixtures/credential-security-fixtures.ts +87 -64
  73. package/src/__tests__/fixtures/media-reuse-fixtures.ts +37 -31
  74. package/src/__tests__/fixtures/mock-signup-server.ts +171 -115
  75. package/src/__tests__/fixtures/proxy-fixtures.ts +39 -39
  76. package/src/__tests__/followup-tools.test.ts +1 -1
  77. package/src/__tests__/gateway-only-guard.test.ts +4 -0
  78. package/src/__tests__/gemini-image-service.test.ts +2 -2
  79. package/src/__tests__/guardian-actions-endpoint.test.ts +543 -1
  80. package/src/__tests__/guardian-control-plane-policy.test.ts +15 -15
  81. package/src/__tests__/guardian-dispatch.test.ts +79 -1
  82. package/src/__tests__/guardian-grant-minting.test.ts +20 -20
  83. package/src/__tests__/guardian-outbound-http.test.ts +1 -2
  84. package/src/__tests__/guardian-principal-id-roundtrip.test.ts +0 -41
  85. package/src/__tests__/guardian-routing-invariants.test.ts +36 -16
  86. package/src/__tests__/guardian-routing-state.test.ts +36 -52
  87. package/src/__tests__/guardian-verification-intent-routing.test.ts +4 -6
  88. package/src/__tests__/guardian-verify-setup-skill-regression.test.ts +6 -8
  89. package/src/__tests__/handle-user-message-secret-resume.test.ts +39 -1
  90. package/src/__tests__/handlers-cu-observation-blob.test.ts +21 -10
  91. package/src/__tests__/handlers-telegram-config.test.ts +14 -14
  92. package/src/__tests__/handlers-user-message-approval-consumption.test.ts +23 -2
  93. package/src/__tests__/headless-browser-interactions.test.ts +1 -1
  94. package/src/__tests__/headless-browser-navigate.test.ts +1 -1
  95. package/src/__tests__/headless-browser-read-tools.test.ts +1 -1
  96. package/src/__tests__/headless-browser-snapshot.test.ts +1 -1
  97. package/src/__tests__/heartbeat-service.test.ts +45 -2
  98. package/src/__tests__/host-file-edit-tool.test.ts +1 -1
  99. package/src/__tests__/host-file-read-tool.test.ts +1 -1
  100. package/src/__tests__/host-file-write-tool.test.ts +1 -1
  101. package/src/__tests__/host-shell-tool.test.ts +1 -1
  102. package/src/__tests__/inbound-invite-redemption.test.ts +17 -19
  103. package/src/__tests__/ingress-reconcile.test.ts +2 -2
  104. package/src/__tests__/integrations-cli.test.ts +232 -0
  105. package/src/__tests__/intent-routing.test.ts +7 -5
  106. package/src/__tests__/invite-redemption-service.test.ts +5 -4
  107. package/src/__tests__/{ingress-routes-http.test.ts → invite-routes-http.test.ts} +42 -321
  108. package/src/__tests__/ipc-snapshot.test.ts +32 -31
  109. package/src/__tests__/managed-skill-lifecycle.test.ts +1 -1
  110. package/src/__tests__/mcp-cli.test.ts +136 -57
  111. package/src/__tests__/mcp-client-auth.test.ts +95 -0
  112. package/src/__tests__/media-generate-image.test.ts +2 -2
  113. package/src/__tests__/media-reuse-story.e2e.test.ts +8 -8
  114. package/src/__tests__/memory-regressions.test.ts +6 -6
  115. package/src/__tests__/messaging-send-tool.test.ts +1 -1
  116. package/src/__tests__/migration-cross-version-compatibility.test.ts +1855 -0
  117. package/src/__tests__/migration-export-http.test.ts +540 -0
  118. package/src/__tests__/migration-import-commit-http.test.ts +823 -0
  119. package/src/__tests__/migration-import-preflight-http.test.ts +755 -0
  120. package/src/__tests__/migration-parity-persistence.test.ts +1854 -0
  121. package/src/__tests__/migration-transport.test.ts +904 -0
  122. package/src/__tests__/migration-validate-http.test.ts +698 -0
  123. package/src/__tests__/migration-wizard.test.ts +1289 -0
  124. package/src/__tests__/nl-approval-parser.test.ts +305 -0
  125. package/src/__tests__/non-member-access-request.test.ts +17 -17
  126. package/src/__tests__/notification-decision-strategy.test.ts +110 -2
  127. package/src/__tests__/notification-deep-link.test.ts +18 -0
  128. package/src/__tests__/notification-guardian-path.test.ts +0 -1
  129. package/src/__tests__/oauth-provider-profiles.test.ts +34 -0
  130. package/src/__tests__/oauth2-gateway-transport.test.ts +1 -1
  131. package/src/__tests__/playbook-execution.test.ts +1 -1
  132. package/src/__tests__/playbook-tools.test.ts +1 -1
  133. package/src/__tests__/provider-error-scenarios.test.ts +68 -0
  134. package/src/__tests__/provider-streaming.benchmark.test.ts +3 -1
  135. package/src/__tests__/proxy-approval-callback.test.ts +1 -1
  136. package/src/__tests__/qdrant-manager.test.ts +40 -11
  137. package/src/__tests__/rebind-secrets-screen.test.ts +839 -0
  138. package/src/__tests__/recording-handler.test.ts +2 -2
  139. package/src/__tests__/recording-intent-handler.test.ts +3 -3
  140. package/src/__tests__/recording-state-machine.test.ts +2 -2
  141. package/src/__tests__/relay-server.test.ts +507 -228
  142. package/src/__tests__/reminder-store.test.ts +8 -0
  143. package/src/__tests__/reminder.test.ts +8 -0
  144. package/src/__tests__/{resolve-guardian-trust-class.test.ts → resolve-trust-class.test.ts} +11 -17
  145. package/src/__tests__/retry-after-extraction.test.ts +111 -0
  146. package/src/__tests__/scaffold-managed-skill-tool.test.ts +1 -1
  147. package/src/__tests__/schedule-tools.test.ts +1 -1
  148. package/src/__tests__/script-proxy-certs.test.ts +1 -1
  149. package/src/__tests__/script-proxy-connect-tunnel.test.ts +2 -3
  150. package/src/__tests__/script-proxy-decision-trace.test.ts +2 -2
  151. package/src/__tests__/script-proxy-http-forwarder.test.ts +1 -1
  152. package/src/__tests__/script-proxy-injection-runtime.test.ts +5 -5
  153. package/src/__tests__/script-proxy-mitm-handler.test.ts +4 -4
  154. package/src/__tests__/script-proxy-policy-runtime.test.ts +2 -2
  155. package/src/__tests__/script-proxy-policy.test.ts +2 -2
  156. package/src/__tests__/script-proxy-profile-template-fallback.test.ts +127 -0
  157. package/src/__tests__/script-proxy-session-manager.test.ts +4 -7
  158. package/src/__tests__/script-proxy-session-runtime.test.ts +1 -6
  159. package/src/__tests__/secret-onetime-send.test.ts +4 -4
  160. package/src/__tests__/secret-scanner-executor.test.ts +2 -2
  161. package/src/__tests__/send-endpoint-busy.test.ts +11 -9
  162. package/src/__tests__/send-notification-tool.test.ts +2 -2
  163. package/src/__tests__/session-abort-tool-results.test.ts +17 -2
  164. package/src/__tests__/session-agent-loop.test.ts +456 -35
  165. package/src/__tests__/session-confirmation-signals.test.ts +3 -2
  166. package/src/__tests__/session-conflict-gate.test.ts +20 -3
  167. package/src/__tests__/session-init.benchmark.test.ts +2 -2
  168. package/src/__tests__/session-load-history-repair.test.ts +7 -7
  169. package/src/__tests__/session-media-retry.test.ts +147 -0
  170. package/src/__tests__/session-pre-run-repair.test.ts +17 -2
  171. package/src/__tests__/session-profile-injection.test.ts +20 -3
  172. package/src/__tests__/session-provider-retry-repair.test.ts +86 -6
  173. package/src/__tests__/session-queue.test.ts +33 -18
  174. package/src/__tests__/session-runtime-assembly.test.ts +147 -1
  175. package/src/__tests__/session-runtime-workspace.test.ts +40 -0
  176. package/src/__tests__/session-slash-known.test.ts +21 -3
  177. package/src/__tests__/session-slash-queue.test.ts +17 -2
  178. package/src/__tests__/session-slash-unknown.test.ts +17 -2
  179. package/src/__tests__/session-surfaces-deselection.test.ts +208 -0
  180. package/src/__tests__/session-workspace-cache-state.test.ts +2 -2
  181. package/src/__tests__/session-workspace-injection.test.ts +17 -2
  182. package/src/__tests__/session-workspace-tool-tracking.test.ts +17 -2
  183. package/src/__tests__/shell-credential-ref.test.ts +1 -1
  184. package/src/__tests__/shell-tool-proxy-mode.test.ts +1 -1
  185. package/src/__tests__/skill-feature-flags-integration.test.ts +9 -5
  186. package/src/__tests__/skill-feature-flags.test.ts +18 -12
  187. package/src/__tests__/skill-load-feature-flag.test.ts +5 -4
  188. package/src/__tests__/skill-load-tool.test.ts +1 -1
  189. package/src/__tests__/skill-script-runner-host.test.ts +1 -1
  190. package/src/__tests__/skill-script-runner-sandbox.test.ts +1 -1
  191. package/src/__tests__/skill-script-runner.test.ts +1 -1
  192. package/src/__tests__/skill-tool-factory.test.ts +1 -1
  193. package/src/__tests__/slack-block-formatting.test.ts +100 -0
  194. package/src/__tests__/slack-inbound-verification.test.ts +346 -0
  195. package/src/__tests__/slack-reaction-approvals.test.ts +77 -0
  196. package/src/__tests__/slack-skill.test.ts +4 -2
  197. package/src/__tests__/starter-task-flow.test.ts +0 -1
  198. package/src/__tests__/subagent-tools.test.ts +3 -3
  199. package/src/__tests__/swarm-recursion.test.ts +1 -1
  200. package/src/__tests__/swarm-session-integration.test.ts +1 -1
  201. package/src/__tests__/swarm-tool.test.ts +1 -1
  202. package/src/__tests__/task-management-tools.test.ts +1 -1
  203. package/src/__tests__/task-tools.test.ts +1 -1
  204. package/src/__tests__/terminal-tools.test.ts +1 -1
  205. package/src/__tests__/test-support/browser-skill-harness.ts +39 -27
  206. package/src/__tests__/test-support/computer-use-skill-harness.ts +14 -14
  207. package/src/__tests__/tool-approval-handler.test.ts +15 -15
  208. package/src/__tests__/tool-execution-abort-cleanup.test.ts +1 -1
  209. package/src/__tests__/tool-execution-pipeline.benchmark.test.ts +1 -1
  210. package/src/__tests__/tool-executor-lifecycle-events.test.ts +2 -2
  211. package/src/__tests__/tool-executor-shell-integration.test.ts +1 -1
  212. package/src/__tests__/tool-executor.test.ts +23 -182
  213. package/src/__tests__/tool-grant-request-escalation.test.ts +11 -11
  214. package/src/__tests__/tool-permission-simulate-handler.test.ts +4 -4
  215. package/src/__tests__/transfer-progress-screen.test.ts +1180 -0
  216. package/src/__tests__/trust-context-guards.test.ts +25 -29
  217. package/src/__tests__/trusted-contact-approval-notifier.test.ts +23 -21
  218. package/src/__tests__/trusted-contact-inline-approval-integration.test.ts +37 -40
  219. package/src/__tests__/trusted-contact-lifecycle-notifications.test.ts +29 -25
  220. package/src/__tests__/trusted-contact-multichannel.test.ts +25 -24
  221. package/src/__tests__/trusted-contact-verification.test.ts +64 -76
  222. package/src/__tests__/turn-commit.test.ts +18 -18
  223. package/src/__tests__/twilio-provider.test.ts +7 -7
  224. package/src/__tests__/validation-results-screen.test.ts +1107 -0
  225. package/src/__tests__/view-image-tool.test.ts +1 -1
  226. package/src/__tests__/voice-invite-redemption.test.ts +4 -3
  227. package/src/__tests__/voice-scoped-grant-consumer.test.ts +12 -12
  228. package/src/__tests__/voice-session-bridge.test.ts +24 -24
  229. package/src/agent/attachments.ts +3 -1
  230. package/src/agent/loop.ts +13 -13
  231. package/src/agent/message-types.ts +13 -7
  232. package/src/amazon/cart.ts +59 -32
  233. package/src/amazon/checkout.ts +25 -14
  234. package/src/amazon/client.ts +61 -58
  235. package/src/amazon/product-details.ts +3 -3
  236. package/src/amazon/request-extractor.ts +46 -31
  237. package/src/amazon/search.ts +6 -4
  238. package/src/amazon/session.ts +33 -24
  239. package/src/approvals/AGENTS.md +26 -0
  240. package/src/approvals/approval-primitive.ts +87 -64
  241. package/src/approvals/guardian-decision-primitive.ts +172 -81
  242. package/src/approvals/guardian-request-resolvers.ts +262 -155
  243. package/src/autonomy/autonomy-resolver.ts +7 -5
  244. package/src/autonomy/autonomy-store.ts +34 -19
  245. package/src/autonomy/disposition-mapper.ts +5 -5
  246. package/src/autonomy/index.ts +6 -6
  247. package/src/autonomy/types.ts +7 -3
  248. package/src/browser-extension-relay/client.ts +50 -19
  249. package/src/browser-extension-relay/protocol.ts +11 -11
  250. package/src/browser-extension-relay/server.ts +45 -20
  251. package/src/bundler/app-bundler.ts +75 -50
  252. package/src/bundler/bundle-scanner.ts +145 -41
  253. package/src/bundler/bundle-signer.ts +16 -14
  254. package/src/bundler/signature-verifier.ts +36 -33
  255. package/src/calls/call-constants.ts +10 -3
  256. package/src/calls/call-controller.ts +473 -214
  257. package/src/calls/call-conversation-messages.ts +25 -15
  258. package/src/calls/call-domain.ts +401 -148
  259. package/src/calls/call-pointer-message-composer.ts +26 -21
  260. package/src/calls/call-pointer-messages.ts +52 -28
  261. package/src/calls/call-recovery.ts +53 -37
  262. package/src/calls/call-state-machine.ts +37 -7
  263. package/src/calls/call-state.ts +35 -13
  264. package/src/calls/call-store.ts +165 -77
  265. package/src/calls/elevenlabs-client.ts +39 -20
  266. package/src/calls/guardian-action-sweep.ts +42 -24
  267. package/src/calls/guardian-dispatch.ts +79 -56
  268. package/src/calls/guardian-question-copy.ts +28 -23
  269. package/src/calls/relay-server.ts +1149 -532
  270. package/src/calls/speaker-identification.ts +21 -15
  271. package/src/calls/twilio-config.ts +34 -17
  272. package/src/calls/twilio-provider.ts +108 -55
  273. package/src/calls/twilio-rest.ts +212 -100
  274. package/src/calls/twilio-routes.ts +165 -92
  275. package/src/calls/types.ts +55 -7
  276. package/src/calls/voice-quality.ts +6 -4
  277. package/src/calls/voice-session-bridge.ts +181 -133
  278. package/src/channels/config.ts +18 -14
  279. package/src/channels/types.ts +38 -10
  280. package/src/cli/amazon.ts +333 -227
  281. package/src/cli/config-commands.ts +236 -146
  282. package/src/cli/core-commands.ts +403 -329
  283. package/src/cli/email-guardrails.ts +38 -19
  284. package/src/cli/email.ts +207 -153
  285. package/src/cli/influencer.ts +58 -56
  286. package/src/cli/integrations.ts +306 -0
  287. package/src/cli/ipc-client.ts +24 -19
  288. package/src/cli/map.ts +176 -129
  289. package/src/cli/mcp.ts +260 -152
  290. package/src/cli/sequence.ts +165 -107
  291. package/src/cli/twitter.ts +302 -218
  292. package/src/cli.ts +418 -279
  293. package/src/commands/cc-command-registry.ts +52 -27
  294. package/src/config/agent-schema.ts +217 -134
  295. package/src/config/assistant-feature-flags.ts +23 -18
  296. package/src/config/bundled-skills/_shared/CLI_RETRIEVAL_PATTERN.md +19 -0
  297. package/src/config/bundled-skills/app-builder/SKILL.md +193 -1500
  298. package/src/config/bundled-skills/app-builder/TOOLS.json +70 -18
  299. package/src/config/bundled-skills/app-builder/tools/app-create.ts +7 -4
  300. package/src/config/bundled-skills/app-builder/tools/app-delete.ts +6 -3
  301. package/src/config/bundled-skills/app-builder/tools/app-file-edit.ts +7 -4
  302. package/src/config/bundled-skills/app-builder/tools/app-file-list.ts +6 -3
  303. package/src/config/bundled-skills/app-builder/tools/app-file-read.ts +6 -3
  304. package/src/config/bundled-skills/app-builder/tools/app-file-write.ts +7 -4
  305. package/src/config/bundled-skills/app-builder/tools/app-list.ts +6 -3
  306. package/src/config/bundled-skills/app-builder/tools/app-query.ts +6 -3
  307. package/src/config/bundled-skills/app-builder/tools/app-update.ts +6 -3
  308. package/src/config/bundled-skills/browser/TOOLS.json +59 -2
  309. package/src/config/bundled-skills/browser/tools/browser-click.ts +5 -2
  310. package/src/config/bundled-skills/browser/tools/browser-close.ts +5 -2
  311. package/src/config/bundled-skills/browser/tools/browser-extract.ts +5 -2
  312. package/src/config/bundled-skills/browser/tools/browser-fill-credential.ts +5 -2
  313. package/src/config/bundled-skills/browser/tools/browser-hover.ts +5 -2
  314. package/src/config/bundled-skills/browser/tools/browser-navigate.ts +5 -2
  315. package/src/config/bundled-skills/browser/tools/browser-press-key.ts +5 -2
  316. package/src/config/bundled-skills/browser/tools/browser-screenshot.ts +5 -2
  317. package/src/config/bundled-skills/browser/tools/browser-scroll.ts +5 -2
  318. package/src/config/bundled-skills/browser/tools/browser-select-option.ts +5 -2
  319. package/src/config/bundled-skills/browser/tools/browser-snapshot.ts +5 -2
  320. package/src/config/bundled-skills/browser/tools/browser-type.ts +5 -2
  321. package/src/config/bundled-skills/browser/tools/browser-wait-for-download.ts +13 -6
  322. package/src/config/bundled-skills/browser/tools/browser-wait-for.ts +5 -2
  323. package/src/config/bundled-skills/chatgpt-import/TOOLS.json +4 -0
  324. package/src/config/bundled-skills/claude-code/TOOLS.json +4 -0
  325. package/src/config/bundled-skills/claude-code/tools/claude-code.ts +5 -2
  326. package/src/config/bundled-skills/computer-use/SKILL.md +2 -2
  327. package/src/config/bundled-skills/computer-use/TOOLS.json +50 -2
  328. package/src/config/bundled-skills/computer-use/tools/computer-use-click.ts +6 -3
  329. package/src/config/bundled-skills/computer-use/tools/computer-use-done.ts +6 -3
  330. package/src/config/bundled-skills/computer-use/tools/computer-use-double-click.ts +10 -3
  331. package/src/config/bundled-skills/computer-use/tools/computer-use-drag.ts +6 -3
  332. package/src/config/bundled-skills/computer-use/tools/computer-use-key.ts +6 -3
  333. package/src/config/bundled-skills/computer-use/tools/computer-use-open-app.ts +6 -3
  334. package/src/config/bundled-skills/computer-use/tools/computer-use-request-control.ts +10 -3
  335. package/src/config/bundled-skills/computer-use/tools/computer-use-respond.ts +6 -3
  336. package/src/config/bundled-skills/computer-use/tools/computer-use-right-click.ts +10 -3
  337. package/src/config/bundled-skills/computer-use/tools/computer-use-run-applescript.ts +10 -3
  338. package/src/config/bundled-skills/computer-use/tools/computer-use-scroll.ts +6 -3
  339. package/src/config/bundled-skills/computer-use/tools/computer-use-type-text.ts +6 -3
  340. package/src/config/bundled-skills/computer-use/tools/computer-use-wait.ts +6 -3
  341. package/src/config/bundled-skills/configure-settings/SKILL.md +28 -14
  342. package/src/config/bundled-skills/contacts/SKILL.md +453 -15
  343. package/src/config/bundled-skills/contacts/TOOLS.json +22 -2
  344. package/src/config/bundled-skills/contacts/tools/contact-merge.ts +79 -20
  345. package/src/config/bundled-skills/contacts/tools/contact-search.ts +55 -18
  346. package/src/config/bundled-skills/contacts/tools/contact-upsert.ts +64 -19
  347. package/src/config/bundled-skills/document/TOOLS.json +8 -0
  348. package/src/config/bundled-skills/document/tools/document-create.ts +5 -2
  349. package/src/config/bundled-skills/document/tools/document-update.ts +5 -2
  350. package/src/config/bundled-skills/doordash/doordash-cli.ts +17 -7
  351. package/src/config/bundled-skills/email-setup/SKILL.md +12 -9
  352. package/src/config/bundled-skills/followups/TOOLS.json +12 -0
  353. package/src/config/bundled-skills/followups/tools/followup-create.ts +5 -2
  354. package/src/config/bundled-skills/followups/tools/followup-list.ts +5 -2
  355. package/src/config/bundled-skills/followups/tools/followup-resolve.ts +5 -2
  356. package/src/config/bundled-skills/google-calendar/TOOLS.json +124 -26
  357. package/src/config/bundled-skills/google-calendar/calendar-client.ts +44 -32
  358. package/src/config/bundled-skills/google-calendar/tools/calendar-check-availability.ts +11 -5
  359. package/src/config/bundled-skills/google-calendar/tools/calendar-create-event.ts +13 -7
  360. package/src/config/bundled-skills/google-calendar/tools/calendar-get-event.ts +11 -5
  361. package/src/config/bundled-skills/google-calendar/tools/calendar-list-events.ts +13 -7
  362. package/src/config/bundled-skills/google-calendar/tools/calendar-rsvp.ts +28 -12
  363. package/src/config/bundled-skills/google-calendar/tools/shared.ts +6 -4
  364. package/src/config/bundled-skills/google-calendar/types.ts +3 -3
  365. package/src/config/bundled-skills/guardian-verify-setup/SKILL.md +88 -33
  366. package/src/config/bundled-skills/image-studio/TOOLS.json +12 -2
  367. package/src/config/bundled-skills/image-studio/tools/media-generate-image.ts +48 -25
  368. package/src/config/bundled-skills/knowledge-graph/TOOLS.json +13 -3
  369. package/src/config/bundled-skills/knowledge-graph/tools/graph-query.ts +60 -35
  370. package/src/config/bundled-skills/mcp-setup/SKILL.md +75 -0
  371. package/src/config/bundled-skills/media-processing/SKILL.md +55 -15
  372. package/src/config/bundled-skills/media-processing/TOOLS.json +48 -2
  373. package/src/config/bundled-skills/media-processing/__tests__/concurrency-pool.test.ts +12 -10
  374. package/src/config/bundled-skills/media-processing/__tests__/cost-tracker.test.ts +34 -19
  375. package/src/config/bundled-skills/media-processing/__tests__/preprocess.test.ts +82 -66
  376. package/src/config/bundled-skills/media-processing/services/audio-transcribe.ts +148 -0
  377. package/src/config/bundled-skills/media-processing/services/concurrency-pool.ts +1 -1
  378. package/src/config/bundled-skills/media-processing/services/cost-tracker.ts +8 -3
  379. package/src/config/bundled-skills/media-processing/services/gemini-map.ts +117 -53
  380. package/src/config/bundled-skills/media-processing/services/gemini-video.ts +273 -0
  381. package/src/config/bundled-skills/media-processing/services/preprocess.ts +185 -97
  382. package/src/config/bundled-skills/media-processing/services/processing-pipeline.ts +32 -27
  383. package/src/config/bundled-skills/media-processing/services/reduce.ts +101 -24
  384. package/src/config/bundled-skills/media-processing/tools/analyze-keyframes.ts +121 -55
  385. package/src/config/bundled-skills/media-processing/tools/extract-keyframes.ts +58 -24
  386. package/src/config/bundled-skills/media-processing/tools/generate-clip.ts +198 -92
  387. package/src/config/bundled-skills/media-processing/tools/ingest-media.ts +98 -70
  388. package/src/config/bundled-skills/media-processing/tools/media-diagnostics.ts +59 -19
  389. package/src/config/bundled-skills/media-processing/tools/media-status.ts +26 -10
  390. package/src/config/bundled-skills/media-processing/tools/query-media-events.ts +29 -14
  391. package/src/config/bundled-skills/messaging/SKILL.md +7 -5
  392. package/src/config/bundled-skills/messaging/TOOLS.json +232 -186
  393. package/src/config/bundled-skills/messaging/tools/gmail-archive-by-query.ts +31 -13
  394. package/src/config/bundled-skills/messaging/tools/gmail-archive.ts +16 -10
  395. package/src/config/bundled-skills/messaging/tools/gmail-batch-label.ts +18 -9
  396. package/src/config/bundled-skills/messaging/tools/gmail-download-attachment.ts +23 -16
  397. package/src/config/bundled-skills/messaging/tools/gmail-draft.ts +28 -12
  398. package/src/config/bundled-skills/messaging/tools/gmail-filters.ts +41 -21
  399. package/src/config/bundled-skills/messaging/tools/gmail-follow-up.ts +44 -23
  400. package/src/config/bundled-skills/messaging/tools/gmail-forward.ts +73 -33
  401. package/src/config/bundled-skills/messaging/tools/gmail-label.ts +15 -9
  402. package/src/config/bundled-skills/messaging/tools/gmail-list-attachments.ts +22 -14
  403. package/src/config/bundled-skills/messaging/tools/gmail-outreach-scan.ts +99 -50
  404. package/src/config/bundled-skills/messaging/tools/gmail-send-draft.ts +14 -8
  405. package/src/config/bundled-skills/messaging/tools/gmail-send-with-attachments.ts +63 -44
  406. package/src/config/bundled-skills/messaging/tools/gmail-sender-digest.ts +90 -46
  407. package/src/config/bundled-skills/messaging/tools/gmail-summarize-thread.ts +43 -22
  408. package/src/config/bundled-skills/messaging/tools/gmail-trash.ts +15 -9
  409. package/src/config/bundled-skills/messaging/tools/gmail-triage.ts +51 -22
  410. package/src/config/bundled-skills/messaging/tools/gmail-unsubscribe.ts +62 -26
  411. package/src/config/bundled-skills/messaging/tools/gmail-vacation.ts +34 -19
  412. package/src/config/bundled-skills/messaging/tools/google-contacts.ts +32 -16
  413. package/src/config/bundled-skills/messaging/tools/messaging-analyze-activity.ts +10 -4
  414. package/src/config/bundled-skills/messaging/tools/messaging-analyze-style.ts +91 -47
  415. package/src/config/bundled-skills/messaging/tools/messaging-archive-by-sender.ts +21 -9
  416. package/src/config/bundled-skills/messaging/tools/messaging-auth-test.ts +9 -3
  417. package/src/config/bundled-skills/messaging/tools/messaging-draft.ts +30 -17
  418. package/src/config/bundled-skills/messaging/tools/messaging-list-conversations.ts +10 -4
  419. package/src/config/bundled-skills/messaging/tools/messaging-mark-read.ts +14 -6
  420. package/src/config/bundled-skills/messaging/tools/messaging-read.ts +16 -5
  421. package/src/config/bundled-skills/messaging/tools/messaging-reply.ts +63 -36
  422. package/src/config/bundled-skills/messaging/tools/messaging-search.ts +10 -4
  423. package/src/config/bundled-skills/messaging/tools/messaging-send.ts +30 -12
  424. package/src/config/bundled-skills/messaging/tools/messaging-sender-digest.ts +48 -29
  425. package/src/config/bundled-skills/messaging/tools/scan-result-store.ts +20 -6
  426. package/src/config/bundled-skills/messaging/tools/send-notification.ts +1 -1
  427. package/src/config/bundled-skills/messaging/tools/sequence-analytics.ts +59 -22
  428. package/src/config/bundled-skills/messaging/tools/sequence-cancel.ts +13 -7
  429. package/src/config/bundled-skills/messaging/tools/sequence-create.ts +27 -12
  430. package/src/config/bundled-skills/messaging/tools/sequence-delete.ts +14 -6
  431. package/src/config/bundled-skills/messaging/tools/sequence-enroll.ts +30 -11
  432. package/src/config/bundled-skills/messaging/tools/sequence-enrollment-list.ts +16 -8
  433. package/src/config/bundled-skills/messaging/tools/sequence-get.ts +31 -13
  434. package/src/config/bundled-skills/messaging/tools/sequence-import.ts +38 -22
  435. package/src/config/bundled-skills/messaging/tools/sequence-list.ts +16 -7
  436. package/src/config/bundled-skills/messaging/tools/sequence-pause.ts +29 -10
  437. package/src/config/bundled-skills/messaging/tools/sequence-resume.ts +16 -8
  438. package/src/config/bundled-skills/messaging/tools/sequence-update.ts +35 -16
  439. package/src/config/bundled-skills/messaging/tools/shared.ts +26 -12
  440. package/src/config/bundled-skills/notifications/SKILL.md +3 -2
  441. package/src/config/bundled-skills/notifications/TOOLS.json +7 -13
  442. package/src/config/bundled-skills/notifications/tools/send-notification.ts +69 -34
  443. package/src/config/bundled-skills/notifications/tools/shared.ts +1 -1
  444. package/src/config/bundled-skills/phone-calls/SKILL.md +46 -48
  445. package/src/config/bundled-skills/phone-calls/TOOLS.json +13 -1
  446. package/src/config/bundled-skills/phone-calls/tools/call-end.ts +1 -1
  447. package/src/config/bundled-skills/phone-calls/tools/call-start.ts +1 -1
  448. package/src/config/bundled-skills/phone-calls/tools/call-status.ts +1 -1
  449. package/src/config/bundled-skills/playbooks/TOOLS.json +16 -0
  450. package/src/config/bundled-skills/playbooks/tools/playbook-create.ts +91 -51
  451. package/src/config/bundled-skills/playbooks/tools/playbook-delete.ts +30 -16
  452. package/src/config/bundled-skills/playbooks/tools/playbook-list.ts +66 -27
  453. package/src/config/bundled-skills/playbooks/tools/playbook-update.ts +89 -42
  454. package/src/config/bundled-skills/public-ingress/SKILL.md +26 -19
  455. package/src/config/bundled-skills/reminder/TOOLS.json +15 -2
  456. package/src/config/bundled-skills/reminder/tools/reminder-cancel.ts +5 -2
  457. package/src/config/bundled-skills/reminder/tools/reminder-create.ts +5 -2
  458. package/src/config/bundled-skills/reminder/tools/reminder-list.ts +5 -2
  459. package/src/config/bundled-skills/schedule/SKILL.md +33 -15
  460. package/src/config/bundled-skills/schedule/TOOLS.json +17 -1
  461. package/src/config/bundled-skills/schedule/tools/schedule-create.ts +5 -2
  462. package/src/config/bundled-skills/schedule/tools/schedule-delete.ts +5 -2
  463. package/src/config/bundled-skills/schedule/tools/schedule-list.ts +5 -2
  464. package/src/config/bundled-skills/schedule/tools/schedule-update.ts +5 -2
  465. package/src/config/bundled-skills/screen-recording/SKILL.md +11 -3
  466. package/src/config/bundled-skills/self-upgrade/SKILL.md +9 -8
  467. package/src/config/bundled-skills/slack/SKILL.md +30 -1
  468. package/src/config/bundled-skills/slack/TOOLS.json +122 -17
  469. package/src/config/bundled-skills/slack/tools/shared.ts +7 -5
  470. package/src/config/bundled-skills/slack/tools/slack-add-reaction.ts +11 -5
  471. package/src/config/bundled-skills/slack/tools/slack-channel-details.ts +11 -5
  472. package/src/config/bundled-skills/slack/tools/slack-channel-permissions.ts +146 -0
  473. package/src/config/bundled-skills/slack/tools/slack-configure-channels.ts +46 -16
  474. package/src/config/bundled-skills/slack/tools/slack-delete-message.ts +11 -5
  475. package/src/config/bundled-skills/slack/tools/slack-edit-message.ts +28 -0
  476. package/src/config/bundled-skills/slack/tools/slack-leave-channel.ts +12 -6
  477. package/src/config/bundled-skills/slack/tools/slack-scan-digest.ts +120 -0
  478. package/src/config/bundled-skills/slack-app-setup/SKILL.md +200 -0
  479. package/src/config/bundled-skills/sms-setup/SKILL.md +5 -8
  480. package/src/config/bundled-skills/subagent/TOOLS.json +22 -2
  481. package/src/config/bundled-skills/subagent/tools/subagent-abort.ts +5 -2
  482. package/src/config/bundled-skills/subagent/tools/subagent-message.ts +5 -2
  483. package/src/config/bundled-skills/subagent/tools/subagent-read.ts +5 -2
  484. package/src/config/bundled-skills/subagent/tools/subagent-spawn.ts +5 -2
  485. package/src/config/bundled-skills/subagent/tools/subagent-status.ts +5 -2
  486. package/src/config/bundled-skills/tasks/TOOLS.json +86 -14
  487. package/src/config/bundled-skills/tasks/tools/task-delete.ts +5 -2
  488. package/src/config/bundled-skills/tasks/tools/task-list-add.ts +5 -2
  489. package/src/config/bundled-skills/tasks/tools/task-list-remove.ts +5 -2
  490. package/src/config/bundled-skills/tasks/tools/task-list-show.ts +5 -2
  491. package/src/config/bundled-skills/tasks/tools/task-list-update.ts +5 -2
  492. package/src/config/bundled-skills/tasks/tools/task-list.ts +5 -2
  493. package/src/config/bundled-skills/tasks/tools/task-queue-run.ts +5 -2
  494. package/src/config/bundled-skills/tasks/tools/task-run.ts +5 -2
  495. package/src/config/bundled-skills/tasks/tools/task-save.ts +5 -2
  496. package/src/config/bundled-skills/telegram-setup/SKILL.md +7 -8
  497. package/src/config/bundled-skills/transcribe/TOOLS.json +4 -0
  498. package/src/config/bundled-skills/transcribe/tools/transcribe-media.ts +232 -127
  499. package/src/config/bundled-skills/twilio-setup/SKILL.md +7 -12
  500. package/src/config/bundled-skills/twitter/SKILL.md +19 -2
  501. package/src/config/bundled-skills/voice-setup/SKILL.md +5 -5
  502. package/src/config/bundled-skills/watcher/TOOLS.json +20 -0
  503. package/src/config/bundled-skills/watcher/tools/watcher-create.ts +5 -2
  504. package/src/config/bundled-skills/watcher/tools/watcher-delete.ts +5 -2
  505. package/src/config/bundled-skills/watcher/tools/watcher-digest.ts +5 -2
  506. package/src/config/bundled-skills/watcher/tools/watcher-list.ts +5 -2
  507. package/src/config/bundled-skills/watcher/tools/watcher-update.ts +5 -2
  508. package/src/config/bundled-skills/weather/TOOLS.json +4 -0
  509. package/src/config/bundled-skills/weather/tools/get-weather.ts +5 -2
  510. package/src/config/bundled-tool-registry.ts +2 -0
  511. package/src/config/calls-schema.ts +108 -63
  512. package/src/config/channel-permission-profiles.ts +155 -0
  513. package/src/config/computer-use-prompt.ts +7 -7
  514. package/src/config/core-schema.ts +239 -155
  515. package/src/config/defaults.ts +2 -2
  516. package/src/config/elevenlabs-schema.ts +15 -15
  517. package/src/config/env-registry.ts +33 -33
  518. package/src/config/env.ts +4 -1
  519. package/src/config/feature-flag-registry.json +31 -7
  520. package/src/config/loader.ts +118 -58
  521. package/src/config/mcp-schema.ts +29 -15
  522. package/src/config/memory-schema.ts +434 -229
  523. package/src/config/notifications-schema.ts +4 -4
  524. package/src/config/sandbox-schema.ts +2 -2
  525. package/src/config/schema.ts +12 -2
  526. package/src/config/skill-state.ts +27 -15
  527. package/src/config/skills-schema.ts +72 -23
  528. package/src/config/skills.ts +303 -143
  529. package/src/config/system-prompt.ts +25 -6
  530. package/src/config/types.ts +1 -1
  531. package/src/config/update-bulletin-format.ts +3 -3
  532. package/src/config/update-bulletin-state.ts +15 -6
  533. package/src/config/update-bulletin-template-path.ts +8 -4
  534. package/src/config/update-bulletin.ts +33 -14
  535. package/src/config/user-reference.ts +8 -8
  536. package/src/contacts/contact-events.ts +21 -0
  537. package/src/contacts/contact-store.ts +813 -100
  538. package/src/contacts/contacts-write.ts +287 -0
  539. package/src/contacts/index.ts +13 -4
  540. package/src/contacts/startup-migration.ts +21 -0
  541. package/src/contacts/types.ts +73 -2
  542. package/src/context/token-estimator.ts +54 -31
  543. package/src/context/tool-result-truncation.ts +41 -7
  544. package/src/context/window-manager.ts +225 -120
  545. package/src/daemon/approval-generators.ts +83 -55
  546. package/src/daemon/approved-devices-store.ts +33 -20
  547. package/src/daemon/assistant-attachments.ts +157 -101
  548. package/src/daemon/auth-manager.ts +17 -15
  549. package/src/daemon/classifier.ts +117 -46
  550. package/src/daemon/computer-use-session.ts +316 -187
  551. package/src/daemon/config-watcher.ts +91 -44
  552. package/src/daemon/connection-policy.ts +18 -10
  553. package/src/daemon/context-overflow-approval.ts +48 -0
  554. package/src/daemon/context-overflow-policy.ts +50 -0
  555. package/src/daemon/context-overflow-reducer.ts +300 -0
  556. package/src/daemon/daemon-control.ts +79 -51
  557. package/src/daemon/date-context.ts +119 -69
  558. package/src/daemon/dictation-profile-store.ts +94 -48
  559. package/src/daemon/dictation-text-processing.ts +33 -12
  560. package/src/daemon/doordash-steps.ts +92 -49
  561. package/src/daemon/guardian-action-generators.ts +62 -46
  562. package/src/daemon/guardian-verification-intent.ts +35 -19
  563. package/src/daemon/handlers/apps.ts +258 -113
  564. package/src/daemon/handlers/avatar.ts +20 -15
  565. package/src/daemon/handlers/computer-use.ts +82 -39
  566. package/src/daemon/handlers/config-channels.ts +146 -69
  567. package/src/daemon/handlers/config-heartbeat.ts +114 -59
  568. package/src/daemon/handlers/config-inbox.ts +213 -160
  569. package/src/daemon/handlers/config-ingress.ts +127 -55
  570. package/src/daemon/handlers/config-integrations.ts +145 -88
  571. package/src/daemon/handlers/config-model.ts +58 -22
  572. package/src/daemon/handlers/config-platform.ts +40 -16
  573. package/src/daemon/handlers/config-scheduling.ts +109 -48
  574. package/src/daemon/handlers/config-slack-channel.ts +67 -35
  575. package/src/daemon/handlers/config-slack.ts +21 -20
  576. package/src/daemon/handlers/config-telegram.ts +100 -70
  577. package/src/daemon/handlers/config-tools.ts +103 -55
  578. package/src/daemon/handlers/config-trust.ts +50 -20
  579. package/src/daemon/handlers/config.ts +72 -24
  580. package/src/daemon/handlers/contacts.ts +163 -0
  581. package/src/daemon/handlers/diagnostics.ts +90 -48
  582. package/src/daemon/handlers/documents.ts +74 -46
  583. package/src/daemon/handlers/guardian-actions.ts +57 -77
  584. package/src/daemon/handlers/home-base.ts +19 -16
  585. package/src/daemon/handlers/identity.ts +65 -45
  586. package/src/daemon/handlers/index.ts +78 -54
  587. package/src/daemon/handlers/misc.ts +664 -234
  588. package/src/daemon/handlers/navigate-settings.ts +14 -11
  589. package/src/daemon/handlers/oauth-connect.ts +48 -35
  590. package/src/daemon/handlers/open-bundle-handler.ts +31 -24
  591. package/src/daemon/handlers/pairing.ts +51 -25
  592. package/src/daemon/handlers/publish.ts +55 -33
  593. package/src/daemon/handlers/recording.ts +378 -162
  594. package/src/daemon/handlers/sessions.ts +922 -423
  595. package/src/daemon/handlers/shared.ts +202 -117
  596. package/src/daemon/handlers/signing.ts +25 -6
  597. package/src/daemon/handlers/subagents.ts +117 -56
  598. package/src/daemon/handlers/twitter-auth.ts +70 -49
  599. package/src/daemon/handlers/work-items.ts +264 -112
  600. package/src/daemon/handlers/workspace-files.ts +27 -20
  601. package/src/daemon/handlers.ts +2 -2
  602. package/src/daemon/history-repair.ts +16 -15
  603. package/src/daemon/identity-helpers.ts +4 -4
  604. package/src/daemon/install-cli-launchers.ts +33 -22
  605. package/src/daemon/ipc-blob-store.ts +38 -24
  606. package/src/daemon/ipc-contract/apps.ts +61 -50
  607. package/src/daemon/ipc-contract/computer-use.ts +47 -37
  608. package/src/daemon/ipc-contract/contacts.ts +69 -0
  609. package/src/daemon/ipc-contract/diagnostics.ts +14 -14
  610. package/src/daemon/ipc-contract/documents.ts +8 -8
  611. package/src/daemon/ipc-contract/guardian-actions.ts +4 -4
  612. package/src/daemon/ipc-contract/inbox.ts +12 -71
  613. package/src/daemon/ipc-contract/integrations.ts +57 -44
  614. package/src/daemon/ipc-contract/memory.ts +3 -5
  615. package/src/daemon/ipc-contract/messages.ts +95 -69
  616. package/src/daemon/ipc-contract/notifications.ts +10 -6
  617. package/src/daemon/ipc-contract/pairing.ts +8 -8
  618. package/src/daemon/ipc-contract/schedules.ts +20 -20
  619. package/src/daemon/ipc-contract/sessions.ts +89 -57
  620. package/src/daemon/ipc-contract/settings.ts +12 -7
  621. package/src/daemon/ipc-contract/shared.ts +9 -7
  622. package/src/daemon/ipc-contract/skills.ts +46 -26
  623. package/src/daemon/ipc-contract/subagents.ts +9 -9
  624. package/src/daemon/ipc-contract/surfaces.ts +0 -1
  625. package/src/daemon/ipc-contract/trust.ts +11 -11
  626. package/src/daemon/ipc-contract/work-items.ts +33 -28
  627. package/src/daemon/ipc-contract/workspace.ts +28 -21
  628. package/src/daemon/ipc-contract-inventory.json +10 -4
  629. package/src/daemon/ipc-contract-inventory.ts +29 -26
  630. package/src/daemon/ipc-contract.ts +111 -44
  631. package/src/daemon/ipc-handler.ts +27 -19
  632. package/src/daemon/ipc-protocol.ts +22 -12
  633. package/src/daemon/ipc-validate.ts +91 -46
  634. package/src/daemon/lifecycle.ts +39 -3
  635. package/src/daemon/main.ts +10 -8
  636. package/src/daemon/media-visibility-policy.ts +3 -1
  637. package/src/daemon/pairing-store.ts +72 -40
  638. package/src/daemon/providers-setup.ts +35 -25
  639. package/src/daemon/recording-executor.ts +37 -30
  640. package/src/daemon/recording-intent-fallback.ts +58 -28
  641. package/src/daemon/recording-intent.ts +71 -61
  642. package/src/daemon/ride-shotgun-handler.ts +201 -121
  643. package/src/daemon/seed-files.ts +28 -17
  644. package/src/daemon/server.ts +23 -14
  645. package/src/daemon/session-agent-loop-handlers.ts +270 -135
  646. package/src/daemon/session-agent-loop.ts +796 -253
  647. package/src/daemon/session-attachments.ts +109 -40
  648. package/src/daemon/session-conflict-gate.ts +72 -28
  649. package/src/daemon/session-dynamic-profile.ts +36 -22
  650. package/src/daemon/session-error.ts +68 -45
  651. package/src/daemon/session-evictor.ts +17 -10
  652. package/src/daemon/session-history.ts +201 -89
  653. package/src/daemon/session-lifecycle.ts +80 -44
  654. package/src/daemon/session-media-retry.ts +104 -42
  655. package/src/daemon/session-memory.ts +77 -55
  656. package/src/daemon/session-messaging.ts +261 -111
  657. package/src/daemon/session-notifiers.ts +57 -45
  658. package/src/daemon/session-process.ts +370 -154
  659. package/src/daemon/session-queue-manager.ts +30 -13
  660. package/src/daemon/session-runtime-assembly.ts +61 -15
  661. package/src/daemon/session-skill-tools.ts +84 -36
  662. package/src/daemon/session-slash.ts +178 -113
  663. package/src/daemon/session-surfaces.ts +498 -212
  664. package/src/daemon/session-tool-setup.ts +24 -16
  665. package/src/daemon/session-usage.ts +26 -13
  666. package/src/daemon/session-workspace.ts +7 -4
  667. package/src/daemon/session.ts +18 -19
  668. package/src/daemon/shutdown-handlers.ts +36 -33
  669. package/src/daemon/tls-certs.ts +90 -57
  670. package/src/daemon/tool-side-effects.ts +97 -65
  671. package/src/daemon/trace-emitter.ts +8 -7
  672. package/src/daemon/video-thumbnail.ts +55 -25
  673. package/src/daemon/watch-handler.ts +164 -86
  674. package/src/email/provider.ts +1 -1
  675. package/src/email/providers/agentmail.ts +87 -45
  676. package/src/email/providers/index.ts +19 -14
  677. package/src/email/service.ts +52 -24
  678. package/src/email/types.ts +2 -2
  679. package/src/errors.ts +1 -1
  680. package/src/events/bus.ts +30 -10
  681. package/src/events/domain-events.ts +20 -13
  682. package/src/events/index.ts +6 -6
  683. package/src/events/tool-audit-listener.ts +34 -20
  684. package/src/events/tool-domain-event-publisher.ts +22 -20
  685. package/src/events/tool-metrics-listener.ts +26 -21
  686. package/src/events/tool-notification-listener.ts +5 -5
  687. package/src/events/tool-profiling-listener.ts +33 -23
  688. package/src/events/tool-trace-listener.ts +70 -46
  689. package/src/export/formatter.ts +38 -32
  690. package/src/followups/followup-store.ts +43 -36
  691. package/src/followups/index.ts +2 -2
  692. package/src/followups/types.ts +1 -1
  693. package/src/gallery/default-gallery.ts +37 -34
  694. package/src/gallery/gallery-manifest.ts +9 -9
  695. package/src/heartbeat/heartbeat-service.ts +59 -37
  696. package/src/home-base/app-link-store.ts +14 -12
  697. package/src/home-base/bootstrap.ts +14 -8
  698. package/src/home-base/prebuilt/seed.ts +34 -26
  699. package/src/home-base/prebuilt-home-base-updater.ts +14 -8
  700. package/src/hooks/cli.ts +56 -43
  701. package/src/hooks/config.ts +27 -14
  702. package/src/hooks/discovery.ts +53 -33
  703. package/src/hooks/manager.ts +50 -26
  704. package/src/hooks/runner.ts +35 -29
  705. package/src/hooks/templates.ts +38 -15
  706. package/src/hooks/types.ts +13 -13
  707. package/src/inbound/platform-callback-registration.ts +21 -15
  708. package/src/inbound/public-ingress-urls.ts +9 -6
  709. package/src/index.ts +20 -19
  710. package/src/influencer/client.ts +261 -117
  711. package/src/instrument.ts +3 -1
  712. package/src/logfire.ts +64 -39
  713. package/src/mcp/client.ts +107 -55
  714. package/src/mcp/manager.ts +45 -18
  715. package/src/mcp/mcp-oauth-provider.ts +114 -62
  716. package/src/media/gemini-image-service.ts +75 -23
  717. package/src/memory/account-store.ts +16 -9
  718. package/src/memory/admin.ts +87 -57
  719. package/src/memory/app-git-service.ts +77 -47
  720. package/src/memory/app-store.ts +148 -78
  721. package/src/memory/attachments-store.ts +123 -53
  722. package/src/memory/canonical-guardian-store.ts +190 -48
  723. package/src/memory/channel-delivery-store.ts +5 -5
  724. package/src/memory/channel-guardian-store.ts +31 -16
  725. package/src/memory/checkpoints.ts +14 -7
  726. package/src/memory/clarification-resolver.ts +219 -104
  727. package/src/memory/conflict-intent.ts +74 -23
  728. package/src/memory/conflict-policy.ts +20 -7
  729. package/src/memory/conflict-store.ts +144 -94
  730. package/src/memory/contradiction-checker.ts +257 -132
  731. package/src/memory/conversation-attention-store.ts +74 -32
  732. package/src/memory/conversation-bootstrap.ts +28 -0
  733. package/src/memory/conversation-crud.ts +12 -5
  734. package/src/memory/conversation-display-order-migration.ts +7 -7
  735. package/src/memory/conversation-key-store.ts +18 -13
  736. package/src/memory/conversation-queries.ts +130 -52
  737. package/src/memory/conversation-store.ts +43 -26
  738. package/src/memory/conversation-title-service.ts +89 -66
  739. package/src/memory/db-init.ts +94 -2
  740. package/src/memory/db.ts +10 -3
  741. package/src/memory/delivery-channels.ts +12 -6
  742. package/src/memory/delivery-crud.ts +26 -12
  743. package/src/memory/delivery-status.ts +19 -16
  744. package/src/memory/embedding-backend.ts +205 -77
  745. package/src/memory/embedding-gemini.ts +23 -10
  746. package/src/memory/embedding-local.ts +89 -44
  747. package/src/memory/embedding-ollama.ts +25 -13
  748. package/src/memory/embedding-openai.ts +20 -11
  749. package/src/memory/embedding-runtime-manager.ts +163 -90
  750. package/src/memory/entity-extractor.ts +185 -123
  751. package/src/memory/external-conversation-store.ts +30 -12
  752. package/src/memory/fingerprint.ts +2 -2
  753. package/src/memory/fts-reconciler.ts +57 -28
  754. package/src/memory/guardian-action-store.ts +162 -100
  755. package/src/memory/guardian-approvals.ts +63 -129
  756. package/src/memory/guardian-rate-limits.ts +20 -9
  757. package/src/memory/guardian-verification.ts +82 -35
  758. package/src/memory/indexer.ts +96 -55
  759. package/src/memory/{ingress-invite-store.ts → invite-store.ts} +28 -169
  760. package/src/memory/items-extractor.ts +313 -157
  761. package/src/memory/job-handlers/backfill.ts +116 -63
  762. package/src/memory/job-handlers/cleanup.ts +64 -41
  763. package/src/memory/job-handlers/conflict.ts +90 -49
  764. package/src/memory/job-handlers/embedding.ts +32 -17
  765. package/src/memory/job-handlers/extraction.ts +58 -33
  766. package/src/memory/job-handlers/index-maintenance.ts +31 -17
  767. package/src/memory/job-handlers/media-processing.ts +65 -24
  768. package/src/memory/job-handlers/summarization.ts +186 -128
  769. package/src/memory/job-utils.ts +100 -57
  770. package/src/memory/jobs-store.ts +235 -142
  771. package/src/memory/jobs-worker.ts +167 -83
  772. package/src/memory/llm-request-log-store.ts +13 -11
  773. package/src/memory/llm-usage-store.ts +35 -26
  774. package/src/memory/media-store.ts +151 -44
  775. package/src/memory/message-content.ts +28 -18
  776. package/src/memory/migrations/001-job-deferrals.ts +11 -5
  777. package/src/memory/migrations/002-tool-invocations-fk.ts +14 -6
  778. package/src/memory/migrations/003-memory-fts-backfill.ts +11 -5
  779. package/src/memory/migrations/004-entity-relation-dedup.ts +17 -11
  780. package/src/memory/migrations/005-fingerprint-scope-unique.ts +36 -21
  781. package/src/memory/migrations/006-scope-salted-fingerprints.ts +35 -20
  782. package/src/memory/migrations/007-assistant-id-to-self.ts +40 -27
  783. package/src/memory/migrations/008-remove-assistant-id-columns.ts +58 -36
  784. package/src/memory/migrations/009-llm-usage-events-drop-assistant-id.ts +36 -22
  785. package/src/memory/migrations/010-ext-conv-bindings-channel-chat-unique.ts +21 -11
  786. package/src/memory/migrations/011-call-sessions-provider-sid-dedup.ts +30 -15
  787. package/src/memory/migrations/012-call-sessions-add-initiated-from.ts +4 -2
  788. package/src/memory/migrations/013-guardian-action-tables.ts +29 -11
  789. package/src/memory/migrations/014-backfill-inbox-thread-state.ts +35 -21
  790. package/src/memory/migrations/015-drop-active-search-index.ts +17 -11
  791. package/src/memory/migrations/016-memory-segments-indexes.ts +7 -3
  792. package/src/memory/migrations/017-memory-items-indexes.ts +4 -2
  793. package/src/memory/migrations/018-remaining-table-indexes.ts +13 -5
  794. package/src/memory/migrations/019-notification-tables-schema-migration.ts +34 -20
  795. package/src/memory/migrations/020-rename-macos-ios-channel-to-vellum.ts +87 -53
  796. package/src/memory/migrations/021-conversation-status-indexes.ts +7 -3
  797. package/src/memory/migrations/022-add-origin-interface.ts +4 -2
  798. package/src/memory/migrations/023-memory-item-sources-indexes.ts +4 -2
  799. package/src/memory/migrations/024-embedding-vector-blob.ts +34 -18
  800. package/src/memory/migrations/025-messages-fts-backfill.ts +11 -5
  801. package/src/memory/migrations/026-guardian-verification-sessions.ts +80 -14
  802. package/src/memory/migrations/026a-embeddings-nullable-vector-json.ts +42 -26
  803. package/src/memory/migrations/027-notification-delivery-pairing-columns.ts +22 -8
  804. package/src/memory/migrations/027a-guardian-bootstrap-token.ts +11 -3
  805. package/src/memory/migrations/028-call-session-mode.ts +13 -3
  806. package/src/memory/migrations/028-notification-delivery-client-ack.ts +22 -8
  807. package/src/memory/migrations/029-channel-inbound-delivered-segments.ts +7 -3
  808. package/src/memory/migrations/030-guardian-action-followup.ts +46 -8
  809. package/src/memory/migrations/030-guardian-verification-purpose.ts +4 -2
  810. package/src/memory/migrations/031-conversations-thread-type-index.ts +4 -2
  811. package/src/memory/migrations/032-guardian-delivery-conversation-index.ts +4 -2
  812. package/src/memory/migrations/032-notification-delivery-thread-decision.ts +22 -8
  813. package/src/memory/migrations/033-scoped-approval-grants.ts +1 -1
  814. package/src/memory/migrations/034-guardian-action-tool-metadata.ts +15 -3
  815. package/src/memory/migrations/035-guardian-action-supersession.ts +15 -3
  816. package/src/memory/migrations/036-normalize-phone-identities.ts +101 -87
  817. package/src/memory/migrations/037-voice-invite-columns.ts +22 -4
  818. package/src/memory/migrations/038-actor-token-records.ts +5 -9
  819. package/src/memory/migrations/039-actor-refresh-token-records.ts +7 -13
  820. package/src/memory/migrations/100-core-tables.ts +1 -1
  821. package/src/memory/migrations/101-watchers-and-logs.ts +1 -1
  822. package/src/memory/migrations/103-complex-migrations.ts +9 -9
  823. package/src/memory/migrations/104-core-indexes.ts +188 -64
  824. package/src/memory/migrations/105-contacts-and-triage.ts +28 -10
  825. package/src/memory/migrations/106-call-sessions.ts +58 -16
  826. package/src/memory/migrations/107-followups.ts +16 -6
  827. package/src/memory/migrations/108-tasks-and-work-items.ts +43 -11
  828. package/src/memory/migrations/109-external-conversation-bindings.ts +11 -5
  829. package/src/memory/migrations/110-channel-guardian.ts +48 -10
  830. package/src/memory/migrations/111-media-assets.ts +52 -18
  831. package/src/memory/migrations/112-assistant-inbox.ts +32 -12
  832. package/src/memory/migrations/113-late-migrations.ts +12 -12
  833. package/src/memory/migrations/114-notifications.ts +28 -12
  834. package/src/memory/migrations/115-sequences.ts +10 -4
  835. package/src/memory/migrations/116-messages-fts.ts +1 -1
  836. package/src/memory/migrations/117-conversation-attention.ts +16 -6
  837. package/src/memory/migrations/118-reminder-routing-intent.ts +7 -3
  838. package/src/memory/migrations/119-schema-indexes-and-columns.ts +35 -15
  839. package/src/memory/migrations/120-fk-cascade-rebuilds.ts +36 -17
  840. package/src/memory/migrations/121-canonical-guardian-requests.ts +25 -9
  841. package/src/memory/migrations/122-canonical-guardian-requester-chat-id.ts +11 -3
  842. package/src/memory/migrations/123-canonical-guardian-deliveries-destination-index.ts +4 -2
  843. package/src/memory/migrations/124-voice-invite-display-metadata.ts +15 -3
  844. package/src/memory/migrations/125-guardian-principal-id-columns.ts +22 -4
  845. package/src/memory/migrations/126-backfill-guardian-principal-id.ts +174 -126
  846. package/src/memory/migrations/127-guardian-principal-id-not-null.ts +58 -42
  847. package/src/memory/migrations/128-contacts-role-principal.ts +26 -0
  848. package/src/memory/migrations/129-contact-channels-access-fields.ts +105 -0
  849. package/src/memory/migrations/130-contact-channels-type-ext-chat-id-index.ts +15 -0
  850. package/src/memory/migrations/131-drop-legacy-member-guardian-tables.ts +134 -0
  851. package/src/memory/migrations/132-contacts-assistant-id.ts +21 -0
  852. package/src/memory/migrations/133-assistant-contact-metadata.ts +21 -0
  853. package/src/memory/migrations/index.ts +83 -73
  854. package/src/memory/migrations/registry.ts +53 -37
  855. package/src/memory/migrations/validate-migration-state.ts +73 -46
  856. package/src/memory/profile-compiler.ts +58 -24
  857. package/src/memory/published-pages-store.ts +12 -16
  858. package/src/memory/qdrant-circuit-breaker.ts +28 -20
  859. package/src/memory/qdrant-client.ts +99 -63
  860. package/src/memory/qdrant-manager.ts +89 -57
  861. package/src/memory/query-builder.ts +9 -7
  862. package/src/memory/raw-query.ts +63 -14
  863. package/src/memory/recall-cache.ts +15 -8
  864. package/src/memory/retrieval-budget.ts +0 -1
  865. package/src/memory/retriever.ts +385 -192
  866. package/src/memory/schema-migration.ts +1 -1
  867. package/src/memory/schema.ts +56 -56
  868. package/src/memory/scoped-approval-grants.ts +99 -45
  869. package/src/memory/search/entity.ts +102 -40
  870. package/src/memory/search/formatting.ts +70 -52
  871. package/src/memory/search/lexical.ts +82 -43
  872. package/src/memory/search/ranking.ts +103 -39
  873. package/src/memory/search/semantic.ts +59 -35
  874. package/src/memory/search/types.ts +8 -8
  875. package/src/memory/segmenter.ts +20 -12
  876. package/src/memory/shared-app-links-store.ts +21 -16
  877. package/src/memory/slack-thread-store.ts +187 -0
  878. package/src/memory/task-memory-cleanup.ts +18 -8
  879. package/src/memory/tool-usage-store.ts +27 -19
  880. package/src/memory/validation.ts +4 -2
  881. package/src/messaging/activity-analyzer.ts +7 -7
  882. package/src/messaging/draft-store.ts +13 -10
  883. package/src/messaging/email-classifier.ts +73 -37
  884. package/src/messaging/index.ts +3 -3
  885. package/src/messaging/outreach-classifier.ts +76 -38
  886. package/src/messaging/provider-types.ts +2 -4
  887. package/src/messaging/provider.ts +37 -8
  888. package/src/messaging/providers/gmail/adapter.ts +183 -66
  889. package/src/messaging/providers/gmail/client.ts +3 -1
  890. package/src/messaging/providers/gmail/mime-builder.ts +21 -19
  891. package/src/messaging/providers/gmail/people-client.ts +22 -9
  892. package/src/messaging/providers/gmail/types.ts +6 -6
  893. package/src/messaging/providers/slack/adapter.ts +93 -43
  894. package/src/messaging/providers/slack/client.ts +165 -48
  895. package/src/messaging/providers/slack/types.ts +10 -0
  896. package/src/messaging/providers/sms/adapter.ts +76 -40
  897. package/src/messaging/providers/sms/client.ts +4 -4
  898. package/src/messaging/providers/telegram-bot/adapter.ts +52 -30
  899. package/src/messaging/providers/telegram-bot/client.ts +7 -7
  900. package/src/messaging/providers/whatsapp/adapter.ts +58 -31
  901. package/src/messaging/providers/whatsapp/client.ts +4 -4
  902. package/src/messaging/registry.ts +9 -5
  903. package/src/messaging/style-analyzer.ts +69 -39
  904. package/src/messaging/thread-summarizer.ts +101 -53
  905. package/src/messaging/triage-engine.ts +111 -82
  906. package/src/messaging/types.ts +10 -10
  907. package/src/migrations/config-merge.ts +18 -10
  908. package/src/migrations/data-layout.ts +35 -22
  909. package/src/migrations/data-merge.ts +17 -7
  910. package/src/migrations/hooks-merge.ts +43 -16
  911. package/src/migrations/index.ts +6 -6
  912. package/src/migrations/log.ts +9 -5
  913. package/src/migrations/skills-merge.ts +17 -7
  914. package/src/migrations/workspace-layout.ts +39 -25
  915. package/src/notifications/AGENTS.md +5 -0
  916. package/src/notifications/adapters/macos.ts +21 -14
  917. package/src/notifications/adapters/slack.ts +90 -0
  918. package/src/notifications/adapters/sms.ts +28 -15
  919. package/src/notifications/adapters/telegram.ts +24 -15
  920. package/src/notifications/broadcaster.ts +108 -52
  921. package/src/notifications/conversation-pairing.ts +64 -29
  922. package/src/notifications/copy-composer.ts +165 -95
  923. package/src/notifications/decision-engine.ts +353 -147
  924. package/src/notifications/decisions-store.ts +26 -10
  925. package/src/notifications/deliveries-store.ts +23 -13
  926. package/src/notifications/destination-resolver.ts +83 -24
  927. package/src/notifications/deterministic-checks.ts +78 -27
  928. package/src/notifications/emit-signal.ts +95 -41
  929. package/src/notifications/events-store.ts +13 -7
  930. package/src/notifications/guardian-question-mode.ts +125 -75
  931. package/src/notifications/preference-extractor.ts +85 -53
  932. package/src/notifications/preference-summary.ts +31 -18
  933. package/src/notifications/preferences-store.ts +29 -18
  934. package/src/notifications/runtime-dispatch.ts +22 -12
  935. package/src/notifications/signal.ts +4 -4
  936. package/src/notifications/thread-candidates.ts +59 -23
  937. package/src/notifications/thread-seed-composer.ts +45 -27
  938. package/src/notifications/types.ts +19 -10
  939. package/src/oauth/connect-orchestrator.ts +105 -54
  940. package/src/oauth/connect-types.ts +3 -3
  941. package/src/oauth/provider-profiles.ts +102 -59
  942. package/src/oauth/scope-policy.ts +5 -2
  943. package/src/oauth/token-persistence.ts +58 -24
  944. package/src/outbound-proxy/certs.ts +284 -0
  945. package/src/outbound-proxy/config.ts +94 -0
  946. package/src/outbound-proxy/connect-tunnel.ts +84 -0
  947. package/src/outbound-proxy/health.ts +62 -0
  948. package/src/outbound-proxy/host-pattern-match.ts +67 -0
  949. package/src/outbound-proxy/http-forwarder.ts +162 -0
  950. package/src/outbound-proxy/index.ts +80 -0
  951. package/src/outbound-proxy/logging.ts +193 -0
  952. package/src/outbound-proxy/mitm-handler.ts +292 -0
  953. package/src/outbound-proxy/policy.ts +172 -0
  954. package/src/outbound-proxy/router.ts +64 -0
  955. package/src/outbound-proxy/server.ts +145 -0
  956. package/src/outbound-proxy/types.ts +150 -0
  957. package/src/permissions/checker.ts +481 -189
  958. package/src/permissions/defaults.ts +135 -108
  959. package/src/permissions/prompter.ts +53 -27
  960. package/src/permissions/secret-prompter.ts +21 -15
  961. package/src/permissions/shell-identity.ts +47 -16
  962. package/src/permissions/trust-store.ts +185 -73
  963. package/src/permissions/types.ts +22 -12
  964. package/src/permissions/workspace-policy.ts +47 -38
  965. package/src/playbooks/index.ts +10 -2
  966. package/src/playbooks/playbook-compiler.ts +30 -24
  967. package/src/playbooks/types.ts +11 -8
  968. package/src/providers/anthropic/client.ts +328 -168
  969. package/src/providers/failover.ts +57 -22
  970. package/src/providers/fireworks/client.ts +9 -5
  971. package/src/providers/gemini/client.ts +61 -39
  972. package/src/providers/model-intents.ts +40 -33
  973. package/src/providers/ollama/client.ts +7 -7
  974. package/src/providers/openai/client.ts +109 -68
  975. package/src/providers/openrouter/client.ts +9 -5
  976. package/src/providers/provider-send-message.ts +59 -27
  977. package/src/providers/ratelimit.ts +25 -8
  978. package/src/providers/registry.ts +86 -38
  979. package/src/providers/retry.ts +93 -37
  980. package/src/providers/stream-timeout.ts +5 -3
  981. package/src/providers/types.ts +7 -6
  982. package/src/runtime/AGENTS.md +42 -0
  983. package/src/runtime/access-request-helper.ts +118 -68
  984. package/src/runtime/actor-refresh-token-store.ts +21 -16
  985. package/src/runtime/actor-token-store.ts +25 -18
  986. package/src/runtime/actor-trust-resolver.ts +191 -80
  987. package/src/runtime/approval-conversation-turn.ts +39 -26
  988. package/src/runtime/approval-message-composer.ts +116 -84
  989. package/src/runtime/assistant-event-hub.ts +25 -6
  990. package/src/runtime/assistant-event.ts +4 -4
  991. package/src/runtime/assistant-scope.ts +1 -1
  992. package/src/runtime/auth/__tests__/guard-tests.test.ts +36 -14
  993. package/src/runtime/auth/context.ts +8 -7
  994. package/src/runtime/auth/credential-service.ts +60 -38
  995. package/src/runtime/auth/external-assistant-id.ts +16 -8
  996. package/src/runtime/auth/index.ts +23 -16
  997. package/src/runtime/auth/require-bound-guardian.ts +44 -0
  998. package/src/runtime/auth/route-policy.ts +166 -104
  999. package/src/runtime/auth/scopes.ts +22 -29
  1000. package/src/runtime/auth/subject.ts +19 -13
  1001. package/src/runtime/auth/token-service.ts +3 -3
  1002. package/src/runtime/auth/types.ts +23 -23
  1003. package/src/runtime/channel-approval-parser.ts +37 -14
  1004. package/src/runtime/channel-approval-types.ts +30 -4
  1005. package/src/runtime/channel-approvals.ts +49 -23
  1006. package/src/runtime/channel-guardian-service.ts +144 -103
  1007. package/src/runtime/channel-invite-transport.ts +5 -3
  1008. package/src/runtime/channel-invite-transports/telegram.ts +16 -10
  1009. package/src/runtime/channel-invite-transports/voice.ts +7 -7
  1010. package/src/runtime/channel-readiness-service.ts +139 -90
  1011. package/src/runtime/channel-readiness-types.ts +4 -2
  1012. package/src/runtime/channel-reply-delivery.ts +83 -14
  1013. package/src/runtime/channel-retry-sweep.ts +111 -62
  1014. package/src/runtime/confirmation-request-guardian-bridge.ts +73 -54
  1015. package/src/runtime/gateway-client.ts +122 -55
  1016. package/src/runtime/gateway-internal-client.ts +86 -0
  1017. package/src/runtime/guardian-action-conversation-turn.ts +34 -18
  1018. package/src/runtime/guardian-action-followup-executor.ts +115 -45
  1019. package/src/runtime/guardian-action-grant-minter.ts +40 -24
  1020. package/src/runtime/guardian-action-message-composer.ts +105 -84
  1021. package/src/runtime/guardian-action-service.ts +127 -0
  1022. package/src/runtime/guardian-decision-types.ts +28 -13
  1023. package/src/runtime/guardian-outbound-actions.ts +9 -0
  1024. package/src/runtime/guardian-reply-router.ts +274 -145
  1025. package/src/runtime/guardian-vellum-migration.ts +38 -24
  1026. package/src/runtime/guardian-verification-templates.ts +24 -12
  1027. package/src/runtime/http-router.ts +175 -0
  1028. package/src/runtime/http-server.ts +913 -680
  1029. package/src/runtime/http-types.ts +2 -2
  1030. package/src/runtime/invite-redemption-service.ts +211 -134
  1031. package/src/runtime/invite-redemption-templates.ts +18 -11
  1032. package/src/runtime/{ingress-service.ts → invite-service.ts} +92 -151
  1033. package/src/runtime/local-actor-identity.ts +73 -55
  1034. package/src/runtime/middleware/auth.ts +25 -14
  1035. package/src/runtime/middleware/error-handler.ts +15 -11
  1036. package/src/runtime/middleware/rate-limiter.ts +23 -17
  1037. package/src/runtime/middleware/request-logger.ts +4 -4
  1038. package/src/runtime/middleware/twilio-validation.ts +29 -20
  1039. package/src/runtime/migrations/migration-transport.ts +575 -0
  1040. package/src/runtime/migrations/migration-wizard.ts +715 -0
  1041. package/src/runtime/migrations/rebind-secrets-screen.ts +351 -0
  1042. package/src/runtime/migrations/transfer-progress-screen.ts +321 -0
  1043. package/src/runtime/migrations/validation-results-screen.ts +467 -0
  1044. package/src/runtime/migrations/vbundle-builder.ts +295 -0
  1045. package/src/runtime/migrations/vbundle-import-analyzer.ts +212 -0
  1046. package/src/runtime/migrations/vbundle-importer.ts +339 -0
  1047. package/src/runtime/migrations/vbundle-validator.ts +356 -0
  1048. package/src/runtime/nl-approval-parser.ts +138 -0
  1049. package/src/runtime/pending-interactions.ts +16 -7
  1050. package/src/runtime/routes/access-request-decision.ts +73 -52
  1051. package/src/runtime/routes/app-routes.ts +56 -38
  1052. package/src/runtime/routes/approval-routes.ts +144 -92
  1053. package/src/runtime/routes/approval-strategies/guardian-callback-strategy.ts +930 -0
  1054. package/src/runtime/routes/approval-strategies/guardian-legacy-fallback-strategy.ts +82 -0
  1055. package/src/runtime/routes/approval-strategies/guardian-text-engine-strategy.ts +151 -0
  1056. package/src/runtime/routes/attachment-routes.ts +59 -48
  1057. package/src/runtime/routes/brain-graph-routes.ts +85 -69
  1058. package/src/runtime/routes/call-routes.ts +79 -38
  1059. package/src/runtime/routes/canonical-guardian-expiry-sweep.ts +10 -10
  1060. package/src/runtime/routes/channel-delivery-routes.ts +19 -14
  1061. package/src/runtime/routes/channel-guardian-routes.ts +3 -3
  1062. package/src/runtime/routes/channel-inbound-routes.ts +2 -2
  1063. package/src/runtime/routes/channel-readiness-routes.ts +12 -6
  1064. package/src/runtime/routes/channel-route-shared.ts +67 -25
  1065. package/src/runtime/routes/channel-routes.ts +4 -6
  1066. package/src/runtime/routes/contact-routes.ts +374 -17
  1067. package/src/runtime/routes/conversation-attention-routes.ts +57 -28
  1068. package/src/runtime/routes/conversation-routes.ts +321 -174
  1069. package/src/runtime/routes/debug-routes.ts +14 -10
  1070. package/src/runtime/routes/events-routes.ts +90 -57
  1071. package/src/runtime/routes/global-search-routes.ts +266 -0
  1072. package/src/runtime/routes/guardian-action-routes.ts +112 -113
  1073. package/src/runtime/routes/guardian-approval-interception.ts +325 -874
  1074. package/src/runtime/routes/guardian-approval-prompt.ts +40 -24
  1075. package/src/runtime/routes/guardian-approval-reply-helpers.ts +135 -0
  1076. package/src/runtime/routes/guardian-bootstrap-routes.ts +55 -36
  1077. package/src/runtime/routes/guardian-expiry-sweep.ts +63 -37
  1078. package/src/runtime/routes/guardian-refresh-routes.ts +40 -19
  1079. package/src/runtime/routes/identity-routes.ts +71 -42
  1080. package/src/runtime/routes/inbound-conversation.ts +17 -11
  1081. package/src/runtime/routes/inbound-message-handler.ts +305 -1459
  1082. package/src/runtime/routes/inbound-stages/acl-enforcement.ts +880 -0
  1083. package/src/runtime/routes/inbound-stages/background-dispatch.ts +600 -0
  1084. package/src/runtime/routes/inbound-stages/bootstrap-intercept.ts +214 -0
  1085. package/src/runtime/routes/inbound-stages/edit-intercept.ts +116 -0
  1086. package/src/runtime/routes/inbound-stages/escalation-intercept.ts +167 -0
  1087. package/src/runtime/routes/inbound-stages/guardian-reply-intercept.ts +185 -0
  1088. package/src/runtime/routes/inbound-stages/secret-ingress-check.ts +132 -0
  1089. package/src/runtime/routes/inbound-stages/verification-intercept.ts +340 -0
  1090. package/src/runtime/routes/integration-routes.ts +60 -21
  1091. package/src/runtime/routes/invite-routes.ts +140 -0
  1092. package/src/runtime/routes/migration-routes.ts +434 -0
  1093. package/src/runtime/routes/pairing-routes.ts +157 -79
  1094. package/src/runtime/routes/secret-routes.ts +6 -2
  1095. package/src/runtime/routes/twilio-routes.ts +443 -249
  1096. package/src/runtime/slack-block-formatting.ts +176 -0
  1097. package/src/runtime/tool-grant-request-helper.ts +36 -27
  1098. package/src/runtime/{guardian-context-resolver.ts → trust-context-resolver.ts} +29 -41
  1099. package/src/schedule/integration-status.ts +44 -9
  1100. package/src/schedule/recurrence-engine.ts +47 -24
  1101. package/src/schedule/recurrence-types.ts +12 -7
  1102. package/src/schedule/schedule-store.ts +166 -83
  1103. package/src/schedule/scheduler.ts +37 -24
  1104. package/src/security/encrypted-store.ts +68 -38
  1105. package/src/security/keychain.ts +183 -120
  1106. package/src/security/oauth-callback-registry.ts +3 -3
  1107. package/src/security/oauth2.ts +226 -138
  1108. package/src/security/redaction.ts +24 -24
  1109. package/src/security/secret-allowlist.ts +46 -21
  1110. package/src/security/secret-ingress.ts +15 -7
  1111. package/src/security/secret-scanner.ts +193 -104
  1112. package/src/security/secure-keys.ts +9 -3
  1113. package/src/security/token-manager.ts +99 -40
  1114. package/src/security/tool-approval-digest.ts +3 -3
  1115. package/src/sequence/analytics.ts +52 -27
  1116. package/src/sequence/engine.ts +135 -72
  1117. package/src/sequence/guardrails.ts +32 -20
  1118. package/src/sequence/importer.ts +75 -37
  1119. package/src/sequence/reply-matcher.ts +36 -18
  1120. package/src/sequence/store.ts +137 -75
  1121. package/src/sequence/types.ts +30 -16
  1122. package/src/services/published-app-updater.ts +26 -16
  1123. package/src/services/vercel-deploy.ts +19 -15
  1124. package/src/skills/active-skill-tools.ts +3 -3
  1125. package/src/skills/clawhub.ts +178 -90
  1126. package/src/skills/include-graph.ts +24 -17
  1127. package/src/skills/managed-store.ts +89 -42
  1128. package/src/skills/path-classifier.ts +10 -10
  1129. package/src/skills/remote-skill-policy.ts +31 -22
  1130. package/src/skills/slash-commands.ts +36 -30
  1131. package/src/skills/tool-manifest.ts +60 -31
  1132. package/src/skills/version-hash.ts +25 -15
  1133. package/src/slack/slack-webhook.ts +19 -15
  1134. package/src/subagent/index.ts +4 -8
  1135. package/src/subagent/manager.ts +119 -69
  1136. package/src/subagent/types.ts +9 -12
  1137. package/src/swarm/backend-claude-code.ts +124 -45
  1138. package/src/swarm/checkpoint.ts +36 -16
  1139. package/src/swarm/graph-utils.ts +1 -3
  1140. package/src/swarm/index.ts +38 -19
  1141. package/src/swarm/limits.ts +13 -4
  1142. package/src/swarm/orchestrator.ts +108 -57
  1143. package/src/swarm/plan-validator.ts +23 -17
  1144. package/src/swarm/router-planner.ts +51 -22
  1145. package/src/swarm/router-prompts.ts +4 -1
  1146. package/src/swarm/synthesizer.ts +26 -18
  1147. package/src/swarm/types.ts +14 -4
  1148. package/src/swarm/worker-backend.ts +36 -26
  1149. package/src/swarm/worker-prompts.ts +13 -9
  1150. package/src/swarm/worker-runner.ts +40 -34
  1151. package/src/tasks/candidate-store.ts +14 -6
  1152. package/src/tasks/ephemeral-permissions.ts +9 -5
  1153. package/src/tasks/task-compiler.ts +41 -38
  1154. package/src/tasks/task-runner.ts +54 -26
  1155. package/src/tasks/task-scheduler.ts +1 -1
  1156. package/src/tasks/task-store.ts +20 -7
  1157. package/src/tasks/tool-sanitizer.ts +3 -3
  1158. package/src/tools/apps/definitions.ts +23 -15
  1159. package/src/tools/apps/executors.ts +122 -40
  1160. package/src/tools/apps/open-proxy.ts +5 -5
  1161. package/src/tools/apps/registry.ts +2 -2
  1162. package/src/tools/assets/materialize.ts +59 -41
  1163. package/src/tools/assets/search.ts +86 -48
  1164. package/src/tools/browser/api-map.ts +52 -36
  1165. package/src/tools/browser/auth-cache.ts +21 -18
  1166. package/src/tools/browser/auth-detector.ts +43 -28
  1167. package/src/tools/browser/auto-navigate.ts +149 -68
  1168. package/src/tools/browser/browser-execution.ts +9 -3
  1169. package/src/tools/browser/headless-browser.ts +287 -150
  1170. package/src/tools/browser/jit-auth.ts +37 -21
  1171. package/src/tools/browser/network-recorder.ts +138 -56
  1172. package/src/tools/browser/recording-store.ts +22 -15
  1173. package/src/tools/browser/runtime-check.ts +8 -5
  1174. package/src/tools/browser/x-auto-navigate.ts +88 -47
  1175. package/src/tools/calls/call-end.ts +10 -7
  1176. package/src/tools/calls/call-start.ts +30 -20
  1177. package/src/tools/calls/call-status.ts +8 -5
  1178. package/src/tools/claude-code/claude-code.ts +301 -165
  1179. package/src/tools/computer-use/definitions.ts +175 -130
  1180. package/src/tools/computer-use/registry.ts +2 -2
  1181. package/src/tools/computer-use/request-computer-control.ts +21 -13
  1182. package/src/tools/computer-use/skill-proxy-bridge.ts +1 -1
  1183. package/src/tools/credentials/account-registry.ts +52 -35
  1184. package/src/tools/credentials/broker-types.ts +1 -1
  1185. package/src/tools/credentials/broker.ts +97 -55
  1186. package/src/tools/credentials/domain-policy.ts +5 -2
  1187. package/src/tools/credentials/host-pattern-match.ts +15 -8
  1188. package/src/tools/credentials/metadata-store.ts +93 -43
  1189. package/src/tools/credentials/policy-types.ts +5 -2
  1190. package/src/tools/credentials/policy-validate.ts +21 -14
  1191. package/src/tools/credentials/post-connect-hooks.ts +18 -7
  1192. package/src/tools/credentials/resolve.ts +11 -10
  1193. package/src/tools/credentials/selection.ts +30 -25
  1194. package/src/tools/credentials/tool-policy.ts +5 -2
  1195. package/src/tools/credentials/vault.ts +538 -185
  1196. package/src/tools/document/document-tool.ts +23 -17
  1197. package/src/tools/document/editor-template.ts +12 -7
  1198. package/src/tools/execution-target.ts +13 -10
  1199. package/src/tools/execution-timeout.ts +6 -5
  1200. package/src/tools/executor.ts +141 -74
  1201. package/src/tools/filesystem/edit.ts +82 -45
  1202. package/src/tools/filesystem/fuzzy-match.ts +70 -32
  1203. package/src/tools/filesystem/read.ts +46 -28
  1204. package/src/tools/filesystem/view-image.ts +86 -42
  1205. package/src/tools/filesystem/write.ts +53 -32
  1206. package/src/tools/followups/followup_create.ts +43 -17
  1207. package/src/tools/followups/followup_list.ts +28 -13
  1208. package/src/tools/followups/followup_resolve.ts +9 -6
  1209. package/src/tools/guardian-control-plane-policy.ts +15 -14
  1210. package/src/tools/host-filesystem/edit.ts +77 -42
  1211. package/src/tools/host-filesystem/read.ts +52 -33
  1212. package/src/tools/host-filesystem/write.ts +50 -29
  1213. package/src/tools/host-terminal/host-shell.ts +97 -61
  1214. package/src/tools/mcp/mcp-tool-factory.ts +21 -14
  1215. package/src/tools/memory/definitions.ts +60 -28
  1216. package/src/tools/memory/handlers.ts +149 -77
  1217. package/src/tools/memory/register.ts +39 -16
  1218. package/src/tools/network/__tests__/web-search.test.ts +236 -177
  1219. package/src/tools/network/domain-normalize.ts +13 -9
  1220. package/src/tools/network/script-proxy/__tests__/logging.test.ts +193 -123
  1221. package/src/tools/network/script-proxy/__tests__/policy.test.ts +225 -127
  1222. package/src/tools/network/script-proxy/index.ts +1 -17
  1223. package/src/tools/network/script-proxy/session-manager.ts +178 -86
  1224. package/src/tools/network/url-safety.ts +56 -34
  1225. package/src/tools/network/web-fetch.ts +273 -155
  1226. package/src/tools/network/web-search.ts +166 -81
  1227. package/src/tools/permission-checker.ts +24 -25
  1228. package/src/tools/policy-context.ts +8 -5
  1229. package/src/tools/registry.ts +73 -46
  1230. package/src/tools/reminder/reminder-store.ts +65 -44
  1231. package/src/tools/reminder/reminder.ts +76 -35
  1232. package/src/tools/schedule/create.ts +44 -21
  1233. package/src/tools/schedule/delete.ts +8 -5
  1234. package/src/tools/schedule/list.ts +39 -19
  1235. package/src/tools/schedule/update.ts +49 -26
  1236. package/src/tools/secret-detection-handler.ts +130 -49
  1237. package/src/tools/sensitive-output-placeholders.ts +15 -8
  1238. package/src/tools/shared/filesystem/edit-engine.ts +45 -14
  1239. package/src/tools/shared/filesystem/errors.ts +18 -18
  1240. package/src/tools/shared/filesystem/file-ops-service.ts +59 -32
  1241. package/src/tools/shared/filesystem/format-diff.ts +21 -11
  1242. package/src/tools/shared/filesystem/path-policy.ts +17 -13
  1243. package/src/tools/shared/filesystem/size-guard.ts +8 -4
  1244. package/src/tools/shared/filesystem/types.ts +2 -2
  1245. package/src/tools/shared/shell-output.ts +4 -3
  1246. package/src/tools/side-effects.ts +36 -28
  1247. package/src/tools/skills/delete-managed.ts +30 -17
  1248. package/src/tools/skills/load.ts +88 -46
  1249. package/src/tools/skills/sandbox-runner.ts +62 -46
  1250. package/src/tools/skills/scaffold-managed.ts +98 -48
  1251. package/src/tools/skills/script-contract.ts +5 -2
  1252. package/src/tools/skills/skill-script-runner.ts +29 -13
  1253. package/src/tools/skills/skill-tool-factory.ts +20 -10
  1254. package/src/tools/subagent/abort.ts +10 -4
  1255. package/src/tools/subagent/message.ts +14 -8
  1256. package/src/tools/subagent/read.ts +20 -11
  1257. package/src/tools/subagent/spawn.ts +14 -6
  1258. package/src/tools/subagent/status.ts +7 -4
  1259. package/src/tools/swarm/delegate.ts +75 -49
  1260. package/src/tools/system/avatar-generator.ts +46 -33
  1261. package/src/tools/system/navigate-settings.ts +29 -19
  1262. package/src/tools/system/open-system-settings.ts +30 -20
  1263. package/src/tools/system/request-permission.ts +59 -44
  1264. package/src/tools/system/version.ts +27 -16
  1265. package/src/tools/system/voice-config.ts +116 -53
  1266. package/src/tools/tasks/index.ts +8 -8
  1267. package/src/tools/tasks/task-delete.ts +61 -22
  1268. package/src/tools/tasks/task-list.ts +23 -11
  1269. package/src/tools/tasks/task-run.ts +41 -16
  1270. package/src/tools/tasks/task-save.ts +27 -10
  1271. package/src/tools/tasks/work-item-enqueue.ts +114 -48
  1272. package/src/tools/tasks/work-item-list.ts +20 -10
  1273. package/src/tools/tasks/work-item-remove.ts +49 -15
  1274. package/src/tools/tasks/work-item-run.ts +34 -13
  1275. package/src/tools/tasks/work-item-update.ts +84 -31
  1276. package/src/tools/terminal/backends/native.ts +64 -35
  1277. package/src/tools/terminal/backends/types.ts +6 -2
  1278. package/src/tools/terminal/parser.ts +200 -125
  1279. package/src/tools/terminal/safe-env.ts +27 -21
  1280. package/src/tools/terminal/sandbox-diagnostics.ts +31 -13
  1281. package/src/tools/terminal/sandbox.ts +10 -6
  1282. package/src/tools/terminal/shell.ts +134 -68
  1283. package/src/tools/tool-approval-handler.ts +239 -140
  1284. package/src/tools/types.ts +79 -22
  1285. package/src/tools/ui-surface/definitions.ts +124 -89
  1286. package/src/tools/ui-surface/registry.ts +2 -2
  1287. package/src/tools/watch/screen-watch.ts +50 -32
  1288. package/src/tools/watch/watch-state.ts +41 -15
  1289. package/src/tools/watcher/create.ts +37 -15
  1290. package/src/tools/watcher/delete.ts +9 -6
  1291. package/src/tools/watcher/digest.ts +10 -6
  1292. package/src/tools/watcher/list.ts +37 -14
  1293. package/src/tools/watcher/update.ts +33 -18
  1294. package/src/tools/weather/service.ts +331 -174
  1295. package/src/twitter/client.ts +261 -138
  1296. package/src/twitter/oauth-client.ts +17 -13
  1297. package/src/twitter/router.ts +51 -23
  1298. package/src/twitter/session.ts +27 -18
  1299. package/src/types/qrcode.d.ts +6 -3
  1300. package/src/usage/actors.ts +16 -16
  1301. package/src/usage/types.ts +3 -3
  1302. package/src/util/bundled-asset.ts +10 -6
  1303. package/src/util/canonicalize-identity.ts +11 -4
  1304. package/src/util/clipboard.ts +7 -7
  1305. package/src/util/content-id.ts +3 -3
  1306. package/src/util/debounce.ts +3 -2
  1307. package/src/util/diff.ts +55 -33
  1308. package/src/util/errors.ts +31 -27
  1309. package/src/util/fs.ts +8 -2
  1310. package/src/util/log-redact.ts +12 -12
  1311. package/src/util/logger.ts +112 -51
  1312. package/src/util/network-info.ts +13 -5
  1313. package/src/util/object.ts +4 -2
  1314. package/src/util/phone.ts +4 -4
  1315. package/src/util/platform.ts +80 -58
  1316. package/src/util/pricing.ts +49 -31
  1317. package/src/util/retry.ts +39 -7
  1318. package/src/util/row-mapper.ts +7 -4
  1319. package/src/util/silently.ts +7 -4
  1320. package/src/util/spawn.ts +48 -0
  1321. package/src/util/spinner.ts +9 -7
  1322. package/src/util/time.ts +16 -3
  1323. package/src/util/truncate.ts +1 -1
  1324. package/src/util/voice-code.ts +6 -4
  1325. package/src/util/xml.ts +5 -1
  1326. package/src/version.ts +12 -8
  1327. package/src/watcher/engine.ts +71 -44
  1328. package/src/watcher/provider-registry.ts +1 -1
  1329. package/src/watcher/providers/github.ts +40 -23
  1330. package/src/watcher/providers/gmail.ts +59 -38
  1331. package/src/watcher/providers/google-calendar.ts +62 -48
  1332. package/src/watcher/providers/linear.ts +219 -150
  1333. package/src/watcher/providers/slack.ts +125 -29
  1334. package/src/watcher/watcher-store.ts +75 -55
  1335. package/src/work-items/work-item-runner.ts +62 -29
  1336. package/src/work-items/work-item-store.ts +137 -47
  1337. package/src/workspace/commit-message-enrichment-service.ts +65 -25
  1338. package/src/workspace/commit-message-provider.ts +14 -12
  1339. package/src/workspace/git-service.ts +355 -239
  1340. package/src/workspace/heartbeat-service.ts +74 -37
  1341. package/src/workspace/provider-commit-message-generator.ts +95 -70
  1342. package/src/workspace/top-level-renderer.ts +10 -8
  1343. package/src/workspace/top-level-scanner.ts +9 -3
  1344. package/src/workspace/turn-commit.ts +63 -36
  1345. package/src/__tests__/ingress-member-store.test.ts +0 -294
  1346. package/src/__tests__/script-proxy-router.test.ts +0 -215
  1347. package/src/config/bundled-skills/trusted-contacts/SKILL.md +0 -372
  1348. package/src/memory/guardian-bindings.ts +0 -158
  1349. package/src/memory/ingress-member-store.ts +0 -352
  1350. package/src/runtime/routes/ingress-routes.ts +0 -229
  1351. package/src/tools/network/script-proxy/__tests__/router.test.ts +0 -77
  1352. package/src/tools/network/script-proxy/certs.ts +0 -7
  1353. package/src/tools/network/script-proxy/connect-tunnel.ts +0 -1
  1354. package/src/tools/network/script-proxy/http-forwarder.ts +0 -2
  1355. package/src/tools/network/script-proxy/logging.ts +0 -12
  1356. package/src/tools/network/script-proxy/mitm-handler.ts +0 -2
  1357. package/src/tools/network/script-proxy/policy.ts +0 -4
  1358. package/src/tools/network/script-proxy/router.ts +0 -2
  1359. package/src/tools/network/script-proxy/server.ts +0 -5
  1360. package/src/tools/network/script-proxy/types.ts +0 -19
@@ -1,33 +1,59 @@
1
- import { createHash } from 'node:crypto';
2
- import { readFileSync } from 'node:fs';
3
- import * as net from 'node:net';
4
-
5
- import { v4 as uuid } from 'uuid';
6
-
7
- import { getConfig } from '../../config/loader.js';
8
- import * as conversationStore from '../../memory/conversation-store.js';
9
- import { GENERATING_TITLE, queueGenerateConversationTitle } from '../../memory/conversation-title-service.js';
10
- import { getConfiguredProvider } from '../../providers/provider-send-message.js';
11
- import type { Provider } from '../../providers/types.js';
12
- import { checkIngressForSecrets } from '../../security/secret-ingress.js';
13
- import { parseSlashCandidate } from '../../skills/slash-commands.js';
14
- import { classifyInteraction } from '../classifier.js';
15
- import { getAssistantName } from '../identity-helpers.js';
16
- import { deleteBlob, isValidBlobId, resolveBlobPath } from '../ipc-blob-store.js';
1
+ import { createHash } from "node:crypto";
2
+ import { readFileSync } from "node:fs";
3
+ import * as net from "node:net";
4
+
5
+ import { v4 as uuid } from "uuid";
6
+
7
+ import { getConfig } from "../../config/loader.js";
8
+ import * as conversationStore from "../../memory/conversation-store.js";
9
+ import {
10
+ GENERATING_TITLE,
11
+ queueGenerateConversationTitle,
12
+ } from "../../memory/conversation-title-service.js";
13
+ import { getConfiguredProvider } from "../../providers/provider-send-message.js";
14
+ import type { Provider } from "../../providers/types.js";
15
+ import { checkIngressForSecrets } from "../../security/secret-ingress.js";
16
+ import { parseSlashCandidate } from "../../skills/slash-commands.js";
17
+ import { classifyInteraction } from "../classifier.js";
18
+ import { getAssistantName } from "../identity-helpers.js";
19
+ import {
20
+ deleteBlob,
21
+ isValidBlobId,
22
+ resolveBlobPath,
23
+ } from "../ipc-blob-store.js";
17
24
  import type {
18
25
  CuSessionCreate,
19
26
  IpcBlobProbe,
20
27
  LinkOpenRequest,
21
28
  SuggestionRequest,
22
29
  TaskSubmit,
23
- } from '../ipc-protocol.js';
24
- import { executeRecordingIntent } from '../recording-executor.js';
25
- import { resolveRecordingIntent } from '../recording-intent.js';
26
- import { classifyRecordingIntentFallback, containsRecordingKeywords } from '../recording-intent-fallback.js';
27
- import { buildSessionErrorMessage,classifySessionError } from '../session-error.js';
28
- import { handleCuSessionCreate } from './computer-use.js';
29
- import { handleRecordingPause, handleRecordingRestart, handleRecordingResume, handleRecordingStart, handleRecordingStop, isRecordingIdle } from './recording.js';
30
- import { defineHandlers, type HandlerContext,log, renderHistoryContent, wireEscalationHandler } from './shared.js';
30
+ } from "../ipc-protocol.js";
31
+ import { executeRecordingIntent } from "../recording-executor.js";
32
+ import { resolveRecordingIntent } from "../recording-intent.js";
33
+ import {
34
+ classifyRecordingIntentFallback,
35
+ containsRecordingKeywords,
36
+ } from "../recording-intent-fallback.js";
37
+ import {
38
+ buildSessionErrorMessage,
39
+ classifySessionError,
40
+ } from "../session-error.js";
41
+ import { handleCuSessionCreate } from "./computer-use.js";
42
+ import {
43
+ handleRecordingPause,
44
+ handleRecordingRestart,
45
+ handleRecordingResume,
46
+ handleRecordingStart,
47
+ handleRecordingStop,
48
+ isRecordingIdle,
49
+ } from "./recording.js";
50
+ import {
51
+ defineHandlers,
52
+ type HandlerContext,
53
+ log,
54
+ renderHistoryContent,
55
+ wireEscalationHandler,
56
+ } from "./shared.js";
31
57
 
32
58
  // ─── Task submit handler ────────────────────────────────────────────────────
33
59
 
@@ -43,175 +69,331 @@ export async function handleTaskSubmit(
43
69
  // Block inbound tasks that contain secrets and redirect to secure prompt
44
70
  const taskIngressCheck = checkIngressForSecrets(msg.task);
45
71
  if (taskIngressCheck.blocked) {
46
- rlog.warn({ detectedTypes: taskIngressCheck.detectedTypes }, 'Blocked task_submit containing secrets');
72
+ rlog.warn(
73
+ { detectedTypes: taskIngressCheck.detectedTypes },
74
+ "Blocked task_submit containing secrets",
75
+ );
47
76
  ctx.send(socket, {
48
- type: 'error',
77
+ type: "error",
49
78
  message: taskIngressCheck.userNotice!,
50
79
  });
51
80
  // Create an ephemeral session so the secret_response lifecycle works
52
81
  // end-to-end. The conversation is deleted after the prompt resolves
53
82
  // to avoid accumulating placeholder entries in session history.
54
- const conversation = conversationStore.createConversation('(blocked — secret detected)');
83
+ const conversation = conversationStore.createConversation(
84
+ "(blocked — secret detected)",
85
+ );
55
86
  ctx.socketToSession.set(socket, conversation.id);
56
- const session = await ctx.getOrCreateSession(conversation.id, socket, true);
57
- session.redirectToSecurePrompt(taskIngressCheck.detectedTypes, { onComplete: () => {
58
- conversationStore.deleteConversation(conversation.id);
59
- // Clean up in-memory session and socket binding so the ephemeral
60
- // session doesn't accumulate in the daemon's session map.
61
- const s = ctx.sessions.get(conversation.id);
62
- if (s) {
63
- s.dispose();
64
- ctx.sessions.delete(conversation.id);
65
- }
66
- // Only unbind if the socket still points to this ephemeral conversation;
67
- // a new task_submit may have already rebound it to a real session.
68
- if (ctx.socketToSession.get(socket) === conversation.id) {
69
- ctx.socketToSession.delete(socket);
70
- }
71
- } });
87
+ const session = await ctx.getOrCreateSession(
88
+ conversation.id,
89
+ socket,
90
+ true,
91
+ );
92
+ session.redirectToSecurePrompt(taskIngressCheck.detectedTypes, {
93
+ onComplete: () => {
94
+ conversationStore.deleteConversation(conversation.id);
95
+ // Clean up in-memory session and socket binding so the ephemeral
96
+ // session doesn't accumulate in the daemon's session map.
97
+ const s = ctx.sessions.get(conversation.id);
98
+ if (s) {
99
+ s.dispose();
100
+ ctx.sessions.delete(conversation.id);
101
+ }
102
+ // Only unbind if the socket still points to this ephemeral conversation;
103
+ // a new task_submit may have already rebound it to a real session.
104
+ if (ctx.socketToSession.get(socket) === conversation.id) {
105
+ ctx.socketToSession.delete(socket);
106
+ }
107
+ },
108
+ });
72
109
  return;
73
110
  }
74
111
 
75
112
  // ── Structured command intent (bypasses text parsing) ──────────────────
76
113
  const config = getConfig();
77
- if (config.daemon.standaloneRecording && msg.commandIntent?.domain === 'screen_recording') {
114
+ if (
115
+ config.daemon.standaloneRecording &&
116
+ msg.commandIntent?.domain === "screen_recording"
117
+ ) {
78
118
  const action = msg.commandIntent.action;
79
- rlog.info({ action, source: 'commandIntent' }, 'Recording command intent received');
80
- if (action === 'start') {
81
- const conversation = conversationStore.createConversation(msg.task || 'Screen Recording');
119
+ rlog.info(
120
+ { action, source: "commandIntent" },
121
+ "Recording command intent received",
122
+ );
123
+ if (action === "start") {
124
+ const conversation = conversationStore.createConversation(
125
+ msg.task || "Screen Recording",
126
+ );
82
127
  ctx.socketToSession.set(socket, conversation.id);
83
- const recordingId = handleRecordingStart(conversation.id, { promptForSource: true }, socket, ctx);
84
- const responseText = recordingId ? 'Starting screen recording.' : 'A recording is already active.';
85
- ctx.send(socket, { type: 'task_routed', sessionId: conversation.id, interactionType: 'text_qa' });
128
+ const recordingId = handleRecordingStart(
129
+ conversation.id,
130
+ { promptForSource: true },
131
+ socket,
132
+ ctx,
133
+ );
134
+ const responseText = recordingId
135
+ ? "Starting screen recording."
136
+ : "A recording is already active.";
137
+ ctx.send(socket, {
138
+ type: "task_routed",
139
+ sessionId: conversation.id,
140
+ interactionType: "text_qa",
141
+ });
86
142
  ctx.send(socket, {
87
- type: 'assistant_text_delta',
143
+ type: "assistant_text_delta",
88
144
  text: responseText,
89
145
  sessionId: conversation.id,
90
146
  });
91
- ctx.send(socket, { type: 'message_complete', sessionId: conversation.id });
92
- await conversationStore.addMessage(conversation.id, 'user', JSON.stringify([{ type: 'text', text: msg.task || '' }]));
93
- await conversationStore.addMessage(conversation.id, 'assistant', JSON.stringify([{ type: 'text', text: responseText }]));
147
+ ctx.send(socket, {
148
+ type: "message_complete",
149
+ sessionId: conversation.id,
150
+ });
151
+ await conversationStore.addMessage(
152
+ conversation.id,
153
+ "user",
154
+ JSON.stringify([{ type: "text", text: msg.task || "" }]),
155
+ );
156
+ await conversationStore.addMessage(
157
+ conversation.id,
158
+ "assistant",
159
+ JSON.stringify([{ type: "text", text: responseText }]),
160
+ );
94
161
  // Sync in-memory session if one exists for this conversation
95
162
  const startSession = ctx.sessions.get(conversation.id);
96
163
  if (startSession && !startSession.isProcessing()) {
97
- startSession.messages.push({ role: 'user', content: [{ type: 'text', text: msg.task || '' }] });
98
- startSession.messages.push({ role: 'assistant', content: [{ type: 'text', text: responseText }] });
164
+ startSession.messages.push({
165
+ role: "user",
166
+ content: [{ type: "text", text: msg.task || "" }],
167
+ });
168
+ startSession.messages.push({
169
+ role: "assistant",
170
+ content: [{ type: "text", text: responseText }],
171
+ });
99
172
  }
100
173
  if (!recordingId) ctx.socketToSession.delete(socket);
101
174
  return;
102
- } else if (action === 'stop') {
175
+ } else if (action === "stop") {
103
176
  let activeSessionId = ctx.socketToSession.get(socket);
104
177
  if (!activeSessionId) {
105
- const conversation = conversationStore.createConversation(msg.task || 'Stop Recording');
178
+ const conversation = conversationStore.createConversation(
179
+ msg.task || "Stop Recording",
180
+ );
106
181
  activeSessionId = conversation.id;
107
182
  ctx.socketToSession.set(socket, activeSessionId);
108
183
  }
109
184
  const stopped = handleRecordingStop(activeSessionId, ctx) !== undefined;
110
- const responseText = stopped ? 'Stopping the recording.' : 'No active recording to stop.';
111
- ctx.send(socket, { type: 'task_routed', sessionId: activeSessionId, interactionType: 'text_qa' });
185
+ const responseText = stopped
186
+ ? "Stopping the recording."
187
+ : "No active recording to stop.";
188
+ ctx.send(socket, {
189
+ type: "task_routed",
190
+ sessionId: activeSessionId,
191
+ interactionType: "text_qa",
192
+ });
112
193
  ctx.send(socket, {
113
- type: 'assistant_text_delta',
194
+ type: "assistant_text_delta",
114
195
  text: responseText,
115
196
  sessionId: activeSessionId,
116
197
  });
117
- ctx.send(socket, { type: 'message_complete', sessionId: activeSessionId });
118
- await conversationStore.addMessage(activeSessionId, 'user', JSON.stringify([{ type: 'text', text: msg.task || '' }]));
119
- await conversationStore.addMessage(activeSessionId, 'assistant', JSON.stringify([{ type: 'text', text: responseText }]));
198
+ ctx.send(socket, {
199
+ type: "message_complete",
200
+ sessionId: activeSessionId,
201
+ });
202
+ await conversationStore.addMessage(
203
+ activeSessionId,
204
+ "user",
205
+ JSON.stringify([{ type: "text", text: msg.task || "" }]),
206
+ );
207
+ await conversationStore.addMessage(
208
+ activeSessionId,
209
+ "assistant",
210
+ JSON.stringify([{ type: "text", text: responseText }]),
211
+ );
120
212
  const stopSession = ctx.sessions.get(activeSessionId);
121
213
  if (stopSession && !stopSession.isProcessing()) {
122
- stopSession.messages.push({ role: 'user', content: [{ type: 'text', text: msg.task || '' }] });
123
- stopSession.messages.push({ role: 'assistant', content: [{ type: 'text', text: responseText }] });
214
+ stopSession.messages.push({
215
+ role: "user",
216
+ content: [{ type: "text", text: msg.task || "" }],
217
+ });
218
+ stopSession.messages.push({
219
+ role: "assistant",
220
+ content: [{ type: "text", text: responseText }],
221
+ });
124
222
  }
125
223
  return;
126
- } else if (action === 'restart') {
224
+ } else if (action === "restart") {
127
225
  let activeSessionId = ctx.socketToSession.get(socket);
128
226
  if (!activeSessionId) {
129
- const conversation = conversationStore.createConversation(msg.task || 'Restart Recording');
227
+ const conversation = conversationStore.createConversation(
228
+ msg.task || "Restart Recording",
229
+ );
130
230
  activeSessionId = conversation.id;
131
231
  ctx.socketToSession.set(socket, activeSessionId);
132
232
  }
133
- const restartResult = handleRecordingRestart(activeSessionId, socket, ctx);
134
- ctx.send(socket, { type: 'task_routed', sessionId: activeSessionId, interactionType: 'text_qa' });
233
+ const restartResult = handleRecordingRestart(
234
+ activeSessionId,
235
+ socket,
236
+ ctx,
237
+ );
238
+ ctx.send(socket, {
239
+ type: "task_routed",
240
+ sessionId: activeSessionId,
241
+ interactionType: "text_qa",
242
+ });
135
243
  ctx.send(socket, {
136
- type: 'assistant_text_delta',
244
+ type: "assistant_text_delta",
137
245
  text: restartResult.responseText,
138
246
  sessionId: activeSessionId,
139
247
  });
140
- ctx.send(socket, { type: 'message_complete', sessionId: activeSessionId });
141
- await conversationStore.addMessage(activeSessionId, 'user', JSON.stringify([{ type: 'text', text: msg.task || '' }]));
142
- await conversationStore.addMessage(activeSessionId, 'assistant', JSON.stringify([{ type: 'text', text: restartResult.responseText }]));
248
+ ctx.send(socket, {
249
+ type: "message_complete",
250
+ sessionId: activeSessionId,
251
+ });
252
+ await conversationStore.addMessage(
253
+ activeSessionId,
254
+ "user",
255
+ JSON.stringify([{ type: "text", text: msg.task || "" }]),
256
+ );
257
+ await conversationStore.addMessage(
258
+ activeSessionId,
259
+ "assistant",
260
+ JSON.stringify([{ type: "text", text: restartResult.responseText }]),
261
+ );
143
262
  const restartSession = ctx.sessions.get(activeSessionId);
144
263
  if (restartSession && !restartSession.isProcessing()) {
145
- restartSession.messages.push({ role: 'user', content: [{ type: 'text', text: msg.task || '' }] });
146
- restartSession.messages.push({ role: 'assistant', content: [{ type: 'text', text: restartResult.responseText }] });
264
+ restartSession.messages.push({
265
+ role: "user",
266
+ content: [{ type: "text", text: msg.task || "" }],
267
+ });
268
+ restartSession.messages.push({
269
+ role: "assistant",
270
+ content: [{ type: "text", text: restartResult.responseText }],
271
+ });
147
272
  }
148
273
  return;
149
- } else if (action === 'pause') {
274
+ } else if (action === "pause") {
150
275
  let activeSessionId = ctx.socketToSession.get(socket);
151
276
  if (!activeSessionId) {
152
- const conversation = conversationStore.createConversation(msg.task || 'Pause Recording');
277
+ const conversation = conversationStore.createConversation(
278
+ msg.task || "Pause Recording",
279
+ );
153
280
  activeSessionId = conversation.id;
154
281
  ctx.socketToSession.set(socket, activeSessionId);
155
282
  }
156
283
  const paused = handleRecordingPause(activeSessionId, ctx) !== undefined;
157
- const responseText = paused ? 'Pausing the recording.' : 'No active recording to pause.';
158
- ctx.send(socket, { type: 'task_routed', sessionId: activeSessionId, interactionType: 'text_qa' });
284
+ const responseText = paused
285
+ ? "Pausing the recording."
286
+ : "No active recording to pause.";
287
+ ctx.send(socket, {
288
+ type: "task_routed",
289
+ sessionId: activeSessionId,
290
+ interactionType: "text_qa",
291
+ });
159
292
  ctx.send(socket, {
160
- type: 'assistant_text_delta',
293
+ type: "assistant_text_delta",
161
294
  text: responseText,
162
295
  sessionId: activeSessionId,
163
296
  });
164
- ctx.send(socket, { type: 'message_complete', sessionId: activeSessionId });
165
- await conversationStore.addMessage(activeSessionId, 'user', JSON.stringify([{ type: 'text', text: msg.task || '' }]));
166
- await conversationStore.addMessage(activeSessionId, 'assistant', JSON.stringify([{ type: 'text', text: responseText }]));
297
+ ctx.send(socket, {
298
+ type: "message_complete",
299
+ sessionId: activeSessionId,
300
+ });
301
+ await conversationStore.addMessage(
302
+ activeSessionId,
303
+ "user",
304
+ JSON.stringify([{ type: "text", text: msg.task || "" }]),
305
+ );
306
+ await conversationStore.addMessage(
307
+ activeSessionId,
308
+ "assistant",
309
+ JSON.stringify([{ type: "text", text: responseText }]),
310
+ );
167
311
  const pauseSession = ctx.sessions.get(activeSessionId);
168
312
  if (pauseSession && !pauseSession.isProcessing()) {
169
- pauseSession.messages.push({ role: 'user', content: [{ type: 'text', text: msg.task || '' }] });
170
- pauseSession.messages.push({ role: 'assistant', content: [{ type: 'text', text: responseText }] });
313
+ pauseSession.messages.push({
314
+ role: "user",
315
+ content: [{ type: "text", text: msg.task || "" }],
316
+ });
317
+ pauseSession.messages.push({
318
+ role: "assistant",
319
+ content: [{ type: "text", text: responseText }],
320
+ });
171
321
  }
172
322
  return;
173
- } else if (action === 'resume') {
323
+ } else if (action === "resume") {
174
324
  let activeSessionId = ctx.socketToSession.get(socket);
175
325
  if (!activeSessionId) {
176
- const conversation = conversationStore.createConversation(msg.task || 'Resume Recording');
326
+ const conversation = conversationStore.createConversation(
327
+ msg.task || "Resume Recording",
328
+ );
177
329
  activeSessionId = conversation.id;
178
330
  ctx.socketToSession.set(socket, activeSessionId);
179
331
  }
180
- const resumed = handleRecordingResume(activeSessionId, ctx) !== undefined;
181
- const responseText = resumed ? 'Resuming the recording.' : 'No active recording to resume.';
182
- ctx.send(socket, { type: 'task_routed', sessionId: activeSessionId, interactionType: 'text_qa' });
332
+ const resumed =
333
+ handleRecordingResume(activeSessionId, ctx) !== undefined;
334
+ const responseText = resumed
335
+ ? "Resuming the recording."
336
+ : "No active recording to resume.";
337
+ ctx.send(socket, {
338
+ type: "task_routed",
339
+ sessionId: activeSessionId,
340
+ interactionType: "text_qa",
341
+ });
183
342
  ctx.send(socket, {
184
- type: 'assistant_text_delta',
343
+ type: "assistant_text_delta",
185
344
  text: responseText,
186
345
  sessionId: activeSessionId,
187
346
  });
188
- ctx.send(socket, { type: 'message_complete', sessionId: activeSessionId });
189
- await conversationStore.addMessage(activeSessionId, 'user', JSON.stringify([{ type: 'text', text: msg.task || '' }]));
190
- await conversationStore.addMessage(activeSessionId, 'assistant', JSON.stringify([{ type: 'text', text: responseText }]));
347
+ ctx.send(socket, {
348
+ type: "message_complete",
349
+ sessionId: activeSessionId,
350
+ });
351
+ await conversationStore.addMessage(
352
+ activeSessionId,
353
+ "user",
354
+ JSON.stringify([{ type: "text", text: msg.task || "" }]),
355
+ );
356
+ await conversationStore.addMessage(
357
+ activeSessionId,
358
+ "assistant",
359
+ JSON.stringify([{ type: "text", text: responseText }]),
360
+ );
191
361
  const resumeSession = ctx.sessions.get(activeSessionId);
192
362
  if (resumeSession && !resumeSession.isProcessing()) {
193
- resumeSession.messages.push({ role: 'user', content: [{ type: 'text', text: msg.task || '' }] });
194
- resumeSession.messages.push({ role: 'assistant', content: [{ type: 'text', text: responseText }] });
363
+ resumeSession.messages.push({
364
+ role: "user",
365
+ content: [{ type: "text", text: msg.task || "" }],
366
+ });
367
+ resumeSession.messages.push({
368
+ role: "assistant",
369
+ content: [{ type: "text", text: responseText }],
370
+ });
195
371
  }
196
372
  return;
197
373
  } else {
198
374
  // Unrecognized action — fall through to normal text handling so the
199
375
  // task is not silently dropped.
200
- rlog.warn({ action, source: 'commandIntent' }, 'Unrecognized screen_recording action, falling through to text handling');
376
+ rlog.warn(
377
+ { action, source: "commandIntent" },
378
+ "Unrecognized screen_recording action, falling through to text handling",
379
+ );
201
380
  }
202
381
  }
203
382
 
204
383
  // ── Standalone recording intent interception ──────────────────────────
205
384
  let pendingRecordingStart = false;
206
385
  let pendingRecordingStop = false;
207
- let pendingRecordingRestart: 'restart_with_remainder' | 'start_and_stop_with_remainder' | false = false;
386
+ let pendingRecordingRestart:
387
+ | "restart_with_remainder"
388
+ | "start_and_stop_with_remainder"
389
+ | false = false;
208
390
  let originalTaskBeforeStrip: string | undefined;
209
391
  if (config.daemon.standaloneRecording) {
210
392
  const name = getAssistantName();
211
393
  const dynamicNames = [name].filter(Boolean) as string[];
212
394
  const intentResult = resolveRecordingIntent(msg.task, dynamicNames);
213
395
 
214
- if (intentResult.kind === 'start_only') {
396
+ if (intentResult.kind === "start_only") {
215
397
  // Create a conversation so the recording can be attached later
216
398
  const conversation = conversationStore.createConversation(msg.task);
217
399
  ctx.socketToSession.set(socket, conversation.id);
@@ -222,15 +404,40 @@ export async function handleTaskSubmit(
222
404
  ctx,
223
405
  });
224
406
 
225
- ctx.send(socket, { type: 'task_routed', sessionId: conversation.id, interactionType: 'text_qa' });
226
- ctx.send(socket, { type: 'assistant_text_delta', text: execResult.responseText!, sessionId: conversation.id });
227
- ctx.send(socket, { type: 'message_complete', sessionId: conversation.id });
228
- await conversationStore.addMessage(conversation.id, 'user', JSON.stringify([{ type: 'text', text: msg.task || '' }]));
229
- await conversationStore.addMessage(conversation.id, 'assistant', JSON.stringify([{ type: 'text', text: execResult.responseText! }]));
407
+ ctx.send(socket, {
408
+ type: "task_routed",
409
+ sessionId: conversation.id,
410
+ interactionType: "text_qa",
411
+ });
412
+ ctx.send(socket, {
413
+ type: "assistant_text_delta",
414
+ text: execResult.responseText!,
415
+ sessionId: conversation.id,
416
+ });
417
+ ctx.send(socket, {
418
+ type: "message_complete",
419
+ sessionId: conversation.id,
420
+ });
421
+ await conversationStore.addMessage(
422
+ conversation.id,
423
+ "user",
424
+ JSON.stringify([{ type: "text", text: msg.task || "" }]),
425
+ );
426
+ await conversationStore.addMessage(
427
+ conversation.id,
428
+ "assistant",
429
+ JSON.stringify([{ type: "text", text: execResult.responseText! }]),
430
+ );
230
431
  const startOnlySession = ctx.sessions.get(conversation.id);
231
432
  if (startOnlySession && !startOnlySession.isProcessing()) {
232
- startOnlySession.messages.push({ role: 'user', content: [{ type: 'text', text: msg.task || '' }] });
233
- startOnlySession.messages.push({ role: 'assistant', content: [{ type: 'text', text: execResult.responseText! }] });
433
+ startOnlySession.messages.push({
434
+ role: "user",
435
+ content: [{ type: "text", text: msg.task || "" }],
436
+ });
437
+ startOnlySession.messages.push({
438
+ role: "assistant",
439
+ content: [{ type: "text", text: execResult.responseText! }],
440
+ });
234
441
  }
235
442
 
236
443
  // If recording rejected, unbind socket
@@ -238,11 +445,14 @@ export async function handleTaskSubmit(
238
445
  ctx.socketToSession.delete(socket);
239
446
  }
240
447
 
241
- rlog.info({ sessionId: conversation.id }, 'Recording-only intent intercepted — routed to standalone recording');
448
+ rlog.info(
449
+ { sessionId: conversation.id },
450
+ "Recording-only intent intercepted — routed to standalone recording",
451
+ );
242
452
  return;
243
453
  }
244
454
 
245
- if (intentResult.kind === 'stop_only') {
455
+ if (intentResult.kind === "stop_only") {
246
456
  let activeSessionId = ctx.socketToSession.get(socket);
247
457
  if (!activeSessionId) {
248
458
  const conversation = conversationStore.createConversation(msg.task);
@@ -256,21 +466,46 @@ export async function handleTaskSubmit(
256
466
  ctx,
257
467
  });
258
468
 
259
- rlog.info('Recording stop intent intercepted');
260
- ctx.send(socket, { type: 'task_routed', sessionId: activeSessionId, interactionType: 'text_qa' });
261
- ctx.send(socket, { type: 'assistant_text_delta', text: execResult.responseText!, sessionId: activeSessionId });
262
- ctx.send(socket, { type: 'message_complete', sessionId: activeSessionId });
263
- await conversationStore.addMessage(activeSessionId, 'user', JSON.stringify([{ type: 'text', text: msg.task || '' }]));
264
- await conversationStore.addMessage(activeSessionId, 'assistant', JSON.stringify([{ type: 'text', text: execResult.responseText! }]));
469
+ rlog.info("Recording stop intent intercepted");
470
+ ctx.send(socket, {
471
+ type: "task_routed",
472
+ sessionId: activeSessionId,
473
+ interactionType: "text_qa",
474
+ });
475
+ ctx.send(socket, {
476
+ type: "assistant_text_delta",
477
+ text: execResult.responseText!,
478
+ sessionId: activeSessionId,
479
+ });
480
+ ctx.send(socket, {
481
+ type: "message_complete",
482
+ sessionId: activeSessionId,
483
+ });
484
+ await conversationStore.addMessage(
485
+ activeSessionId,
486
+ "user",
487
+ JSON.stringify([{ type: "text", text: msg.task || "" }]),
488
+ );
489
+ await conversationStore.addMessage(
490
+ activeSessionId,
491
+ "assistant",
492
+ JSON.stringify([{ type: "text", text: execResult.responseText! }]),
493
+ );
265
494
  const stopOnlySession = ctx.sessions.get(activeSessionId);
266
495
  if (stopOnlySession && !stopOnlySession.isProcessing()) {
267
- stopOnlySession.messages.push({ role: 'user', content: [{ type: 'text', text: msg.task || '' }] });
268
- stopOnlySession.messages.push({ role: 'assistant', content: [{ type: 'text', text: execResult.responseText! }] });
496
+ stopOnlySession.messages.push({
497
+ role: "user",
498
+ content: [{ type: "text", text: msg.task || "" }],
499
+ });
500
+ stopOnlySession.messages.push({
501
+ role: "assistant",
502
+ content: [{ type: "text", text: execResult.responseText! }],
503
+ });
269
504
  }
270
505
  return;
271
506
  }
272
507
 
273
- if (intentResult.kind === 'start_and_stop_only') {
508
+ if (intentResult.kind === "start_and_stop_only") {
274
509
  let activeSessionId = ctx.socketToSession.get(socket);
275
510
  if (!activeSessionId) {
276
511
  const conversation = conversationStore.createConversation(msg.task);
@@ -284,22 +519,51 @@ export async function handleTaskSubmit(
284
519
  ctx,
285
520
  });
286
521
 
287
- rlog.info('Recording start+stop intent intercepted');
288
- ctx.send(socket, { type: 'task_routed', sessionId: activeSessionId, interactionType: 'text_qa' });
289
- ctx.send(socket, { type: 'assistant_text_delta', text: execResult.responseText!, sessionId: activeSessionId });
290
- ctx.send(socket, { type: 'message_complete', sessionId: activeSessionId });
291
- await conversationStore.addMessage(activeSessionId, 'user', JSON.stringify([{ type: 'text', text: msg.task || '' }]));
292
- await conversationStore.addMessage(activeSessionId, 'assistant', JSON.stringify([{ type: 'text', text: execResult.responseText! }]));
522
+ rlog.info("Recording start+stop intent intercepted");
523
+ ctx.send(socket, {
524
+ type: "task_routed",
525
+ sessionId: activeSessionId,
526
+ interactionType: "text_qa",
527
+ });
528
+ ctx.send(socket, {
529
+ type: "assistant_text_delta",
530
+ text: execResult.responseText!,
531
+ sessionId: activeSessionId,
532
+ });
533
+ ctx.send(socket, {
534
+ type: "message_complete",
535
+ sessionId: activeSessionId,
536
+ });
537
+ await conversationStore.addMessage(
538
+ activeSessionId,
539
+ "user",
540
+ JSON.stringify([{ type: "text", text: msg.task || "" }]),
541
+ );
542
+ await conversationStore.addMessage(
543
+ activeSessionId,
544
+ "assistant",
545
+ JSON.stringify([{ type: "text", text: execResult.responseText! }]),
546
+ );
293
547
  const startStopOnlySession = ctx.sessions.get(activeSessionId);
294
548
  if (startStopOnlySession && !startStopOnlySession.isProcessing()) {
295
- startStopOnlySession.messages.push({ role: 'user', content: [{ type: 'text', text: msg.task || '' }] });
296
- startStopOnlySession.messages.push({ role: 'assistant', content: [{ type: 'text', text: execResult.responseText! }] });
549
+ startStopOnlySession.messages.push({
550
+ role: "user",
551
+ content: [{ type: "text", text: msg.task || "" }],
552
+ });
553
+ startStopOnlySession.messages.push({
554
+ role: "assistant",
555
+ content: [{ type: "text", text: execResult.responseText! }],
556
+ });
297
557
  }
298
558
  return;
299
559
  }
300
560
 
301
561
  // Restart/pause/resume — fully handled intents
302
- if (intentResult.kind === 'restart_only' || intentResult.kind === 'pause_only' || intentResult.kind === 'resume_only') {
562
+ if (
563
+ intentResult.kind === "restart_only" ||
564
+ intentResult.kind === "pause_only" ||
565
+ intentResult.kind === "resume_only"
566
+ ) {
303
567
  let activeSessionId = ctx.socketToSession.get(socket);
304
568
  if (!activeSessionId) {
305
569
  const conversation = conversationStore.createConversation(msg.task);
@@ -313,63 +577,109 @@ export async function handleTaskSubmit(
313
577
  ctx,
314
578
  });
315
579
 
316
- rlog.info({ kind: intentResult.kind }, 'Recording intent intercepted');
317
- ctx.send(socket, { type: 'task_routed', sessionId: activeSessionId, interactionType: 'text_qa' });
318
- ctx.send(socket, { type: 'assistant_text_delta', text: execResult.responseText!, sessionId: activeSessionId });
319
- ctx.send(socket, { type: 'message_complete', sessionId: activeSessionId });
320
- await conversationStore.addMessage(activeSessionId, 'user', JSON.stringify([{ type: 'text', text: msg.task || '' }]));
321
- await conversationStore.addMessage(activeSessionId, 'assistant', JSON.stringify([{ type: 'text', text: execResult.responseText! }]));
580
+ rlog.info({ kind: intentResult.kind }, "Recording intent intercepted");
581
+ ctx.send(socket, {
582
+ type: "task_routed",
583
+ sessionId: activeSessionId,
584
+ interactionType: "text_qa",
585
+ });
586
+ ctx.send(socket, {
587
+ type: "assistant_text_delta",
588
+ text: execResult.responseText!,
589
+ sessionId: activeSessionId,
590
+ });
591
+ ctx.send(socket, {
592
+ type: "message_complete",
593
+ sessionId: activeSessionId,
594
+ });
595
+ await conversationStore.addMessage(
596
+ activeSessionId,
597
+ "user",
598
+ JSON.stringify([{ type: "text", text: msg.task || "" }]),
599
+ );
600
+ await conversationStore.addMessage(
601
+ activeSessionId,
602
+ "assistant",
603
+ JSON.stringify([{ type: "text", text: execResult.responseText! }]),
604
+ );
322
605
  const handledSession = ctx.sessions.get(activeSessionId);
323
606
  if (handledSession && !handledSession.isProcessing()) {
324
- handledSession.messages.push({ role: 'user', content: [{ type: 'text', text: msg.task || '' }] });
325
- handledSession.messages.push({ role: 'assistant', content: [{ type: 'text', text: execResult.responseText! }] });
607
+ handledSession.messages.push({
608
+ role: "user",
609
+ content: [{ type: "text", text: msg.task || "" }],
610
+ });
611
+ handledSession.messages.push({
612
+ role: "assistant",
613
+ content: [{ type: "text", text: execResult.responseText! }],
614
+ });
326
615
  }
327
616
  return;
328
617
  }
329
618
 
330
- if (intentResult.kind === 'start_with_remainder' || intentResult.kind === 'stop_with_remainder' ||
331
- intentResult.kind === 'start_and_stop_with_remainder' || intentResult.kind === 'restart_with_remainder') {
619
+ if (
620
+ intentResult.kind === "start_with_remainder" ||
621
+ intentResult.kind === "stop_with_remainder" ||
622
+ intentResult.kind === "start_and_stop_with_remainder" ||
623
+ intentResult.kind === "restart_with_remainder"
624
+ ) {
332
625
  // Defer recording action until after classifier creates the final conversation
333
- pendingRecordingStop = intentResult.kind === 'stop_with_remainder';
626
+ pendingRecordingStop = intentResult.kind === "stop_with_remainder";
334
627
  // start_and_stop_with_remainder is semantically a restart — route through
335
628
  // handleRecordingRestart which properly cleans up maps between stop and start.
336
629
  // However, when there's no active recording the stop is a no-op, so fall
337
630
  // back to a plain start instead of restart.
338
- if (intentResult.kind === 'start_and_stop_with_remainder') {
631
+ if (intentResult.kind === "start_and_stop_with_remainder") {
339
632
  if (isRecordingIdle()) {
340
633
  pendingRecordingStart = true;
341
634
  } else {
342
- pendingRecordingRestart = 'start_and_stop_with_remainder';
635
+ pendingRecordingRestart = "start_and_stop_with_remainder";
343
636
  }
344
637
  } else {
345
- pendingRecordingStart = intentResult.kind === 'start_with_remainder';
346
- pendingRecordingRestart = intentResult.kind === 'restart_with_remainder' ? 'restart_with_remainder' : false;
638
+ pendingRecordingStart = intentResult.kind === "start_with_remainder";
639
+ pendingRecordingRestart =
640
+ intentResult.kind === "restart_with_remainder"
641
+ ? "restart_with_remainder"
642
+ : false;
347
643
  }
348
644
  // Preserve the original text so the DB stores the full message
349
645
  originalTaskBeforeStrip = msg.task;
350
646
  (msg as { task: string }).task = intentResult.remainder;
351
- rlog.info({ remaining: intentResult.remainder }, 'Recording intent deferred, continuing with remaining text');
647
+ rlog.info(
648
+ { remaining: intentResult.remainder },
649
+ "Recording intent deferred, continuing with remaining text",
650
+ );
352
651
  }
353
652
 
354
653
  // 'none' — deterministic resolver found nothing; try LLM fallback
355
654
  // if the text contains recording-related keywords.
356
- if (intentResult.kind === 'none' && containsRecordingKeywords(msg.task)) {
655
+ if (intentResult.kind === "none" && containsRecordingKeywords(msg.task)) {
357
656
  const fallback = await classifyRecordingIntentFallback(msg.task);
358
- rlog.info({ fallbackAction: fallback.action, fallbackConfidence: fallback.confidence }, 'Recording intent LLM fallback result');
359
-
360
- if (fallback.action !== 'none' && fallback.confidence === 'high') {
361
- const kindMap: Record<string, import('../recording-intent.js').RecordingIntentResult> = {
362
- start: { kind: 'start_only' },
363
- stop: { kind: 'stop_only' },
364
- restart: { kind: 'restart_only' },
365
- pause: { kind: 'pause_only' },
366
- resume: { kind: 'resume_only' },
657
+ rlog.info(
658
+ {
659
+ fallbackAction: fallback.action,
660
+ fallbackConfidence: fallback.confidence,
661
+ },
662
+ "Recording intent LLM fallback result",
663
+ );
664
+
665
+ if (fallback.action !== "none" && fallback.confidence === "high") {
666
+ const kindMap: Record<
667
+ string,
668
+ import("../recording-intent.js").RecordingIntentResult
669
+ > = {
670
+ start: { kind: "start_only" },
671
+ stop: { kind: "stop_only" },
672
+ restart: { kind: "restart_only" },
673
+ pause: { kind: "pause_only" },
674
+ resume: { kind: "resume_only" },
367
675
  };
368
676
  const mapped = kindMap[fallback.action];
369
677
  if (mapped) {
370
678
  let activeSessionId = ctx.socketToSession.get(socket);
371
679
  if (!activeSessionId) {
372
- const conversation = conversationStore.createConversation(msg.task);
680
+ const conversation = conversationStore.createConversation(
681
+ msg.task,
682
+ );
373
683
  activeSessionId = conversation.id;
374
684
  ctx.socketToSession.set(socket, activeSessionId);
375
685
  }
@@ -381,20 +691,46 @@ export async function handleTaskSubmit(
381
691
  });
382
692
 
383
693
  if (execResult.handled) {
384
- rlog.info({ kind: mapped.kind, source: 'llm_fallback' }, 'Recording intent intercepted via LLM fallback');
385
- ctx.send(socket, { type: 'task_routed', sessionId: activeSessionId, interactionType: 'text_qa' });
694
+ rlog.info(
695
+ { kind: mapped.kind, source: "llm_fallback" },
696
+ "Recording intent intercepted via LLM fallback",
697
+ );
386
698
  ctx.send(socket, {
387
- type: 'assistant_text_delta',
699
+ type: "task_routed",
700
+ sessionId: activeSessionId,
701
+ interactionType: "text_qa",
702
+ });
703
+ ctx.send(socket, {
704
+ type: "assistant_text_delta",
388
705
  text: execResult.responseText!,
389
706
  sessionId: activeSessionId,
390
707
  });
391
- ctx.send(socket, { type: 'message_complete', sessionId: activeSessionId });
392
- await conversationStore.addMessage(activeSessionId, 'user', JSON.stringify([{ type: 'text', text: msg.task || '' }]));
393
- await conversationStore.addMessage(activeSessionId, 'assistant', JSON.stringify([{ type: 'text', text: execResult.responseText! }]));
708
+ ctx.send(socket, {
709
+ type: "message_complete",
710
+ sessionId: activeSessionId,
711
+ });
712
+ await conversationStore.addMessage(
713
+ activeSessionId,
714
+ "user",
715
+ JSON.stringify([{ type: "text", text: msg.task || "" }]),
716
+ );
717
+ await conversationStore.addMessage(
718
+ activeSessionId,
719
+ "assistant",
720
+ JSON.stringify([
721
+ { type: "text", text: execResult.responseText! },
722
+ ]),
723
+ );
394
724
  const fallbackSession = ctx.sessions.get(activeSessionId);
395
725
  if (fallbackSession && !fallbackSession.isProcessing()) {
396
- fallbackSession.messages.push({ role: 'user', content: [{ type: 'text', text: msg.task || '' }] });
397
- fallbackSession.messages.push({ role: 'assistant', content: [{ type: 'text', text: execResult.responseText! }] });
726
+ fallbackSession.messages.push({
727
+ role: "user",
728
+ content: [{ type: "text", text: msg.task || "" }],
729
+ });
730
+ fallbackSession.messages.push({
731
+ role: "assistant",
732
+ content: [{ type: "text", text: execResult.responseText! }],
733
+ });
398
734
  }
399
735
 
400
736
  // If recording was rejected (e.g. already active), unbind the
@@ -411,94 +747,174 @@ export async function handleTaskSubmit(
411
747
 
412
748
  // Slash candidates always route to text_qa — bypass classifier
413
749
  const slashCandidate = parseSlashCandidate(msg.task);
414
- const interactionType = slashCandidate.kind === 'candidate'
415
- ? 'text_qa' as const
416
- : await classifyInteraction(msg.task, msg.source);
417
- rlog.info({ interactionType, slashBypass: slashCandidate.kind === 'candidate', taskLength: msg.task.length }, 'Task classified');
750
+ const interactionType =
751
+ slashCandidate.kind === "candidate"
752
+ ? ("text_qa" as const)
753
+ : await classifyInteraction(msg.task, msg.source);
754
+ rlog.info(
755
+ {
756
+ interactionType,
757
+ slashBypass: slashCandidate.kind === "candidate",
758
+ taskLength: msg.task.length,
759
+ },
760
+ "Task classified",
761
+ );
418
762
 
419
- if (interactionType === 'computer_use') {
763
+ if (interactionType === "computer_use") {
420
764
  // Create CU session (reuse handleCuSessionCreate logic)
421
765
  const sessionId = uuid();
422
766
  const cuMsg: CuSessionCreate = {
423
- type: 'cu_session_create',
767
+ type: "cu_session_create",
424
768
  sessionId,
425
769
  task: msg.task,
426
770
  screenWidth: msg.screenWidth,
427
771
  screenHeight: msg.screenHeight,
428
772
  attachments: msg.attachments,
429
- interactionType: 'computer_use',
773
+ interactionType: "computer_use",
430
774
  };
431
775
  handleCuSessionCreate(cuMsg, socket, ctx);
432
776
 
433
777
  // Start deferred recording from mixed intent (create a DB conversation
434
778
  // for the recording attachment since CU sessions don't have one).
435
- if (pendingRecordingStart || pendingRecordingStop || pendingRecordingRestart) {
436
- const recConversation = conversationStore.createConversation('Screen Recording');
779
+ if (
780
+ pendingRecordingStart ||
781
+ pendingRecordingStop ||
782
+ pendingRecordingRestart
783
+ ) {
784
+ const recConversation =
785
+ conversationStore.createConversation("Screen Recording");
437
786
  if (pendingRecordingStop) handleRecordingStop(recConversation.id, ctx);
438
- if (pendingRecordingStart) handleRecordingStart(recConversation.id, { promptForSource: true }, socket, ctx);
787
+ if (pendingRecordingStart)
788
+ handleRecordingStart(
789
+ recConversation.id,
790
+ { promptForSource: true },
791
+ socket,
792
+ ctx,
793
+ );
439
794
  if (pendingRecordingRestart) {
440
- const restartResult = handleRecordingRestart(recConversation.id, socket, ctx);
795
+ const restartResult = handleRecordingRestart(
796
+ recConversation.id,
797
+ socket,
798
+ ctx,
799
+ );
441
800
  // TOCTOU: recording may have stopped between intent resolution and
442
801
  // deferred execution. Fall back to plain start for stop-and-start
443
802
  // intents (user wants a new recording), but not for pure restart.
444
- if (!restartResult.initiated && restartResult.reason === 'no_active_recording'
445
- && pendingRecordingRestart === 'start_and_stop_with_remainder') {
446
- handleRecordingStart(recConversation.id, { promptForSource: true }, socket, ctx);
803
+ if (
804
+ !restartResult.initiated &&
805
+ restartResult.reason === "no_active_recording" &&
806
+ pendingRecordingRestart === "start_and_stop_with_remainder"
807
+ ) {
808
+ handleRecordingStart(
809
+ recConversation.id,
810
+ { promptForSource: true },
811
+ socket,
812
+ ctx,
813
+ );
447
814
  }
448
815
  }
449
816
  }
450
817
 
451
818
  ctx.send(socket, {
452
- type: 'task_routed',
819
+ type: "task_routed",
453
820
  sessionId,
454
- interactionType: 'computer_use',
821
+ interactionType: "computer_use",
455
822
  });
456
823
  } else {
457
824
  // Create text QA session and immediately start processing
458
- const conversation = conversationStore.createConversation(GENERATING_TITLE);
825
+ const conversation =
826
+ conversationStore.createConversation(GENERATING_TITLE);
459
827
  queueGenerateConversationTitle({
460
828
  conversationId: conversation.id,
461
- context: { origin: 'task_submit' },
829
+ context: { origin: "task_submit" },
462
830
  userMessage: msg.task,
463
831
  });
464
832
  ctx.socketToSession.set(socket, conversation.id);
465
- const session = await ctx.getOrCreateSession(conversation.id, socket, true);
833
+ const session = await ctx.getOrCreateSession(
834
+ conversation.id,
835
+ socket,
836
+ true,
837
+ );
466
838
 
467
839
  // Wire escalation handler so the agent can call computer_use_request_control
468
- wireEscalationHandler(session, socket, ctx, msg.screenWidth, msg.screenHeight);
840
+ wireEscalationHandler(
841
+ session,
842
+ socket,
843
+ ctx,
844
+ msg.screenWidth,
845
+ msg.screenHeight,
846
+ );
469
847
 
470
848
  // Start deferred recording from mixed intent, now using the real conversation
471
849
  if (pendingRecordingStop) handleRecordingStop(conversation.id, ctx);
472
- if (pendingRecordingStart) handleRecordingStart(conversation.id, { promptForSource: true }, socket, ctx);
850
+ if (pendingRecordingStart)
851
+ handleRecordingStart(
852
+ conversation.id,
853
+ { promptForSource: true },
854
+ socket,
855
+ ctx,
856
+ );
473
857
  if (pendingRecordingRestart) {
474
- const restartResult = handleRecordingRestart(conversation.id, socket, ctx);
475
- if (!restartResult.initiated && restartResult.reason === 'no_active_recording'
476
- && pendingRecordingRestart === 'start_and_stop_with_remainder') {
477
- handleRecordingStart(conversation.id, { promptForSource: true }, socket, ctx);
858
+ const restartResult = handleRecordingRestart(
859
+ conversation.id,
860
+ socket,
861
+ ctx,
862
+ );
863
+ if (
864
+ !restartResult.initiated &&
865
+ restartResult.reason === "no_active_recording" &&
866
+ pendingRecordingRestart === "start_and_stop_with_remainder"
867
+ ) {
868
+ handleRecordingStart(
869
+ conversation.id,
870
+ { promptForSource: true },
871
+ socket,
872
+ ctx,
873
+ );
478
874
  }
479
875
  }
480
876
 
481
877
  ctx.send(socket, {
482
- type: 'task_routed',
878
+ type: "task_routed",
483
879
  sessionId: conversation.id,
484
- interactionType: 'text_qa',
880
+ interactionType: "text_qa",
485
881
  });
486
882
 
487
883
  // Start streaming immediately — client doesn't need to send user_message
488
- session.processMessage(msg.task, msg.attachments ?? [], (event) => {
489
- ctx.send(socket, event);
490
- }, requestId, undefined, undefined, undefined, originalTaskBeforeStrip).catch((err) => {
491
- const message = err instanceof Error ? err.message : String(err);
492
- rlog.error({ err }, 'Error processing task_submit text QA');
493
- ctx.send(socket, { type: 'error', message: `Failed to process message: ${message}` });
494
- const classified = classifySessionError(err, { phase: 'agent_loop' });
495
- ctx.send(socket, buildSessionErrorMessage(conversation.id, classified));
496
- });
884
+ session
885
+ .processMessage(
886
+ msg.task,
887
+ msg.attachments ?? [],
888
+ (event) => {
889
+ ctx.send(socket, event);
890
+ },
891
+ requestId,
892
+ undefined,
893
+ undefined,
894
+ undefined,
895
+ originalTaskBeforeStrip,
896
+ )
897
+ .catch((err) => {
898
+ const message = err instanceof Error ? err.message : String(err);
899
+ rlog.error({ err }, "Error processing task_submit text QA");
900
+ ctx.send(socket, {
901
+ type: "error",
902
+ message: `Failed to process message: ${message}`,
903
+ });
904
+ const classified = classifySessionError(err, { phase: "agent_loop" });
905
+ ctx.send(
906
+ socket,
907
+ buildSessionErrorMessage(conversation.id, classified),
908
+ );
909
+ });
497
910
  }
498
911
  } catch (err) {
499
912
  const message = err instanceof Error ? err.message : String(err);
500
- rlog.error({ err }, 'Error handling task_submit');
501
- ctx.send(socket, { type: 'error', message: `Failed to route task: ${message}` });
913
+ rlog.error({ err }, "Error handling task_submit");
914
+ ctx.send(socket, {
915
+ type: "error",
916
+ message: `Failed to route task: ${message}`,
917
+ });
502
918
  }
503
919
  }
504
920
 
@@ -515,37 +931,47 @@ export async function handleSuggestionRequest(
515
931
  ): Promise<void> {
516
932
  const noSuggestion = () => {
517
933
  ctx.send(socket, {
518
- type: 'suggestion_response',
934
+ type: "suggestion_response",
519
935
  requestId: msg.requestId,
520
936
  suggestion: null,
521
- source: 'none' as const,
937
+ source: "none" as const,
522
938
  });
523
939
  };
524
940
 
525
941
  const rawMessages = conversationStore.getMessages(msg.sessionId);
526
- if (rawMessages.length === 0) { noSuggestion(); return; }
942
+ if (rawMessages.length === 0) {
943
+ noSuggestion();
944
+ return;
945
+ }
527
946
 
528
947
  // Find the most recent assistant message — only use it if it has text content.
529
948
  // Do NOT fall back to older turns; if the latest assistant message is tool-only,
530
949
  // return no suggestion rather than reusing stale text from a previous turn.
531
950
  for (let i = rawMessages.length - 1; i >= 0; i--) {
532
951
  const m = rawMessages[i];
533
- if (m.role !== 'assistant') continue;
952
+ if (m.role !== "assistant") continue;
534
953
 
535
954
  let content: unknown;
536
- try { content = JSON.parse(m.content); } catch { content = m.content; }
955
+ try {
956
+ content = JSON.parse(m.content);
957
+ } catch {
958
+ content = m.content;
959
+ }
537
960
  const rendered = renderHistoryContent(content);
538
961
  const text = rendered.text.trim();
539
- if (!text) { noSuggestion(); return; }
962
+ if (!text) {
963
+ noSuggestion();
964
+ return;
965
+ }
540
966
 
541
967
  // Return cached suggestion
542
968
  const cached = suggestionCache.get(m.id);
543
969
  if (cached !== undefined) {
544
970
  ctx.send(socket, {
545
- type: 'suggestion_response',
971
+ type: "suggestion_response",
546
972
  requestId: msg.requestId,
547
973
  suggestion: cached,
548
- source: 'llm' as const,
974
+ source: "llm" as const,
549
975
  });
550
976
  return;
551
977
  }
@@ -570,16 +996,16 @@ export async function handleSuggestionRequest(
570
996
  suggestionCache.set(m.id, llmSuggestion);
571
997
 
572
998
  ctx.send(socket, {
573
- type: 'suggestion_response',
999
+ type: "suggestion_response",
574
1000
  requestId: msg.requestId,
575
1001
  suggestion: llmSuggestion,
576
- source: 'llm' as const,
1002
+ source: "llm" as const,
577
1003
  });
578
1004
  return;
579
1005
  }
580
1006
  } catch (err) {
581
1007
  suggestionInFlight.delete(m.id);
582
- log.warn({ err }, 'LLM suggestion failed');
1008
+ log.warn({ err }, "LLM suggestion failed");
583
1009
  }
584
1010
  }
585
1011
 
@@ -590,24 +1016,26 @@ export async function handleSuggestionRequest(
590
1016
  noSuggestion();
591
1017
  }
592
1018
 
593
- async function generateSuggestion(provider: Provider, assistantText: string): Promise<string | null> {
594
- const truncated = assistantText.length > 2000
595
- ? assistantText.slice(-2000)
596
- : assistantText;
1019
+ async function generateSuggestion(
1020
+ provider: Provider,
1021
+ assistantText: string,
1022
+ ): Promise<string | null> {
1023
+ const truncated =
1024
+ assistantText.length > 2000 ? assistantText.slice(-2000) : assistantText;
597
1025
 
598
1026
  const prompt = `Given this assistant message, write a very short tab-complete suggestion (max 50 chars) the user could send next to keep the conversation going. Be casual, curious, or actionable — like a quick reply, not a formal request. Reply with ONLY the suggestion text.\n\nAssistant's message:\n${truncated}`;
599
1027
  const response = await provider.sendMessage(
600
- [{ role: 'user', content: [{ type: 'text', text: prompt }] }],
1028
+ [{ role: "user", content: [{ type: "text", text: prompt }] }],
601
1029
  [], // no tools
602
1030
  undefined, // no system prompt
603
1031
  { config: { max_tokens: 30 } },
604
1032
  );
605
1033
 
606
- const textBlock = response.content.find((b) => b.type === 'text');
607
- const raw = textBlock && 'text' in textBlock ? textBlock.text.trim() : '';
1034
+ const textBlock = response.content.find((b) => b.type === "text");
1035
+ const raw = textBlock && "text" in textBlock ? textBlock.text.trim() : "";
608
1036
  if (!raw || raw.length > 50) return null;
609
1037
 
610
- const firstLine = raw.split('\n')[0].trim();
1038
+ const firstLine = raw.split("\n")[0].trim();
611
1039
  return firstLine || null;
612
1040
  }
613
1041
 
@@ -620,17 +1048,17 @@ export function handleLinkOpenRequest(
620
1048
  ): void {
621
1049
  try {
622
1050
  const parsed = new URL(msg.url);
623
- if (!['http:', 'https:'].includes(parsed.protocol)) {
624
- log.warn({ url: msg.url }, 'link_open_request: blocked non-http URL');
1051
+ if (!["http:", "https:"].includes(parsed.protocol)) {
1052
+ log.warn({ url: msg.url }, "link_open_request: blocked non-http URL");
625
1053
  return;
626
1054
  }
627
1055
  } catch {
628
- log.warn({ url: msg.url }, 'link_open_request: invalid URL');
1056
+ log.warn({ url: msg.url }, "link_open_request: invalid URL");
629
1057
  return;
630
1058
  }
631
1059
  // V1: passthrough. Future: affiliate param injection based on metadata
632
1060
  const finalUrl = msg.url;
633
- ctx.send(socket, { type: 'open_url', url: finalUrl });
1061
+ ctx.send(socket, { type: "open_url", url: finalUrl });
634
1062
  }
635
1063
 
636
1064
  // ─── IPC blob probe handler ─────────────────────────────────────────────────
@@ -642,10 +1070,10 @@ export function handleIpcBlobProbe(
642
1070
  ): void {
643
1071
  if (!isValidBlobId(msg.probeId)) {
644
1072
  ctx.send(socket, {
645
- type: 'ipc_blob_probe_result',
1073
+ type: "ipc_blob_probe_result",
646
1074
  probeId: msg.probeId,
647
1075
  ok: false,
648
- reason: 'invalid_probe_id',
1076
+ reason: "invalid_probe_id",
649
1077
  });
650
1078
  return;
651
1079
  }
@@ -655,10 +1083,10 @@ export function handleIpcBlobProbe(
655
1083
  filePath = resolveBlobPath(msg.probeId);
656
1084
  } catch {
657
1085
  ctx.send(socket, {
658
- type: 'ipc_blob_probe_result',
1086
+ type: "ipc_blob_probe_result",
659
1087
  probeId: msg.probeId,
660
1088
  ok: false,
661
- reason: 'invalid_probe_id',
1089
+ reason: "invalid_probe_id",
662
1090
  });
663
1091
  return;
664
1092
  }
@@ -668,32 +1096,32 @@ export function handleIpcBlobProbe(
668
1096
  content = readFileSync(filePath);
669
1097
  } catch {
670
1098
  ctx.send(socket, {
671
- type: 'ipc_blob_probe_result',
1099
+ type: "ipc_blob_probe_result",
672
1100
  probeId: msg.probeId,
673
1101
  ok: false,
674
- reason: 'missing_probe_file',
1102
+ reason: "missing_probe_file",
675
1103
  });
676
1104
  return;
677
1105
  }
678
1106
 
679
- const observedHash = createHash('sha256').update(content).digest('hex');
1107
+ const observedHash = createHash("sha256").update(content).digest("hex");
680
1108
 
681
1109
  // Best-effort cleanup regardless of match outcome
682
1110
  deleteBlob(msg.probeId);
683
1111
 
684
1112
  if (observedHash !== msg.nonceSha256) {
685
1113
  ctx.send(socket, {
686
- type: 'ipc_blob_probe_result',
1114
+ type: "ipc_blob_probe_result",
687
1115
  probeId: msg.probeId,
688
1116
  ok: false,
689
1117
  observedNonceSha256: observedHash,
690
- reason: 'hash_mismatch',
1118
+ reason: "hash_mismatch",
691
1119
  });
692
1120
  return;
693
1121
  }
694
1122
 
695
1123
  ctx.send(socket, {
696
- type: 'ipc_blob_probe_result',
1124
+ type: "ipc_blob_probe_result",
697
1125
  probeId: msg.probeId,
698
1126
  ok: true,
699
1127
  observedNonceSha256: observedHash,
@@ -705,5 +1133,7 @@ export const miscHandlers = defineHandlers({
705
1133
  suggestion_request: handleSuggestionRequest,
706
1134
  link_open_request: handleLinkOpenRequest,
707
1135
  ipc_blob_probe: handleIpcBlobProbe,
708
- ping: (_msg, socket, ctx) => { ctx.send(socket, { type: 'pong' }); },
1136
+ ping: (_msg, socket, ctx) => {
1137
+ ctx.send(socket, { type: "pong" });
1138
+ },
709
1139
  });