@vellumai/assistant 0.7.0 → 0.7.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (666) hide show
  1. package/ARCHITECTURE.md +6 -7
  2. package/Dockerfile +1 -0
  3. package/README.md +2 -2
  4. package/__tests__/permissions/gateway-threshold-reader.test.ts +79 -139
  5. package/bun.lock +3 -0
  6. package/docs/architecture/security.md +18 -16
  7. package/knip.json +1 -0
  8. package/node_modules/@vellumai/skill-host-contracts/__tests__/client.test.ts +1 -5
  9. package/node_modules/@vellumai/skill-host-contracts/src/assistant-event.ts +0 -5
  10. package/node_modules/@vellumai/skill-host-contracts/src/client.ts +10 -16
  11. package/node_modules/@vellumai/skill-host-contracts/src/skill-host.ts +1 -9
  12. package/node_modules/@vellumai/skill-host-contracts/src/tool-types.ts +12 -12
  13. package/node_modules/@vellumai/slack-text/bun.lock +24 -0
  14. package/node_modules/@vellumai/slack-text/package.json +18 -0
  15. package/node_modules/@vellumai/slack-text/src/index.test.ts +153 -0
  16. package/node_modules/@vellumai/slack-text/src/index.ts +235 -0
  17. package/node_modules/@vellumai/slack-text/tsconfig.json +20 -0
  18. package/openapi.yaml +294 -107
  19. package/package.json +4 -2
  20. package/scripts/generate-openapi.ts +16 -111
  21. package/src/__tests__/agent-wake-override-profile.test.ts +23 -1
  22. package/src/__tests__/anthropic-provider.test.ts +56 -13
  23. package/src/__tests__/app-conversation-ids-backfill.test.ts +278 -0
  24. package/src/__tests__/app-conversation-ids.test.ts +151 -0
  25. package/src/__tests__/approval-cascade.test.ts +0 -15
  26. package/src/__tests__/approval-routes-http.test.ts +6 -17
  27. package/src/__tests__/assistant-event-hub.test.ts +126 -77
  28. package/src/__tests__/assistant-event.test.ts +0 -5
  29. package/src/__tests__/assistant-events-sse-hardening.test.ts +37 -15
  30. package/src/__tests__/assistant-feature-flags-integration.test.ts +0 -29
  31. package/src/__tests__/background-shell-host-bash.test.ts +34 -43
  32. package/src/__tests__/call-controller.test.ts +1 -1
  33. package/src/__tests__/call-site-routing-provider.test.ts +193 -0
  34. package/src/__tests__/channel-approval-routes.test.ts +10 -296
  35. package/src/__tests__/channel-approvals.test.ts +25 -17
  36. package/src/__tests__/channel-guardian.test.ts +100 -146
  37. package/src/__tests__/checker.test.ts +20 -34
  38. package/src/__tests__/compact-event-conversation-id-guard.test.ts +50 -0
  39. package/src/__tests__/compaction-events.test.ts +2 -0
  40. package/src/__tests__/config-schema.test.ts +6 -48
  41. package/src/__tests__/config-watcher.test.ts +12 -0
  42. package/src/__tests__/connection-policy.test.ts +1 -52
  43. package/src/__tests__/contacts-write.test.ts +2 -64
  44. package/src/__tests__/context-image-dimensions.test.ts +1 -1
  45. package/src/__tests__/context-search-memory-source.test.ts +120 -1
  46. package/src/__tests__/context-search-memory-v2-source.test.ts +383 -0
  47. package/src/__tests__/context-search-pkb-source.test.ts +49 -0
  48. package/src/__tests__/context-search-workspace-source.test.ts +9 -22
  49. package/src/__tests__/context-window-manager.test.ts +46 -0
  50. package/src/__tests__/conversation-agent-loop-inference-profile.test.ts +2 -0
  51. package/src/__tests__/conversation-agent-loop-overflow.test.ts +102 -29
  52. package/src/__tests__/conversation-agent-loop.test.ts +980 -13
  53. package/src/__tests__/conversation-analysis-routes.test.ts +12 -10
  54. package/src/__tests__/conversation-attention-telegram.test.ts +11 -3
  55. package/src/__tests__/conversation-confirmation-signals.test.ts +0 -291
  56. package/src/__tests__/conversation-history-web-search.test.ts +4 -3
  57. package/src/__tests__/conversation-inference-profile-route.test.ts +12 -23
  58. package/src/__tests__/conversation-lifecycle.test.ts +4 -4
  59. package/src/__tests__/conversation-process-callsite.test.ts +79 -2
  60. package/src/__tests__/conversation-queue.test.ts +3 -8
  61. package/src/__tests__/conversation-routes-disk-view.test.ts +1 -161
  62. package/src/__tests__/conversation-routes-guardian-reply.test.ts +0 -32
  63. package/src/__tests__/conversation-routes-slash-commands.test.ts +75 -66
  64. package/src/__tests__/conversation-runtime-assembly.test.ts +257 -3
  65. package/src/__tests__/conversation-slash-commands.test.ts +24 -4
  66. package/src/__tests__/conversation-slash-queue.test.ts +2 -0
  67. package/src/__tests__/conversation-speed-override.test.ts +0 -3
  68. package/src/__tests__/conversation-starter-routes.test.ts +79 -2
  69. package/src/__tests__/conversation-surfaces-standalone-payloads.test.ts +12 -5
  70. package/src/__tests__/conversation-surfaces-standalone.test.ts +18 -14
  71. package/src/__tests__/conversation-surfaces-state-update.test.ts +3 -2
  72. package/src/__tests__/conversation-tool-setup-app-refresh.test.ts +8 -46
  73. package/src/__tests__/conversation-usage.test.ts +253 -3
  74. package/src/__tests__/credential-execution-shell-lockdown.test.ts +0 -39
  75. package/src/__tests__/credential-health-service.test.ts +68 -0
  76. package/src/__tests__/credential-security-e2e.test.ts +4 -3
  77. package/src/__tests__/credential-security-invariants.test.ts +1 -5
  78. package/src/__tests__/credential-token-resolver.test.ts +180 -0
  79. package/src/__tests__/cu-unified-flow.test.ts +33 -16
  80. package/src/__tests__/daemon-assistant-events.test.ts +34 -21
  81. package/src/__tests__/daemon-credential-client.test.ts +4 -1
  82. package/src/__tests__/db-connection-isolation.test.ts +125 -0
  83. package/src/__tests__/db-migration-rollback.test.ts +101 -0
  84. package/src/__tests__/db-slack-compaction-watermark-migration.test.ts +169 -0
  85. package/src/__tests__/deterministic-verification-control-plane.test.ts +7 -80
  86. package/src/__tests__/document-conversations.test.ts +332 -0
  87. package/src/__tests__/embedding-managed-proxy-selection.test.ts +2 -2
  88. package/src/__tests__/emit-event-signal.test.ts +4 -6
  89. package/src/__tests__/events-client-registration.test.ts +193 -49
  90. package/src/__tests__/filing-service.test.ts +58 -7
  91. package/src/__tests__/first-greeting.test.ts +156 -150
  92. package/src/__tests__/fixtures/mock-chrome-extension.ts +108 -66
  93. package/src/__tests__/get-skill-detail-audit.test.ts +3 -8
  94. package/src/__tests__/guardian-binding-drift-heal.test.ts +1 -1
  95. package/src/__tests__/guardian-dispatch.test.ts +1 -1
  96. package/src/__tests__/guardian-grant-minting.test.ts +7 -2
  97. package/src/__tests__/guardian-routing-invariants.test.ts +7 -2
  98. package/src/__tests__/guardian-routing-state.test.ts +1 -1
  99. package/src/__tests__/handlers-skills-memory-v2-reseed.test.ts +32 -11
  100. package/src/__tests__/handlers-user-message-approval-consumption.test.ts +2 -83
  101. package/src/__tests__/headless-browser-mode.test.ts +4 -9
  102. package/src/__tests__/headless-browser-navigate.test.ts +21 -20
  103. package/src/__tests__/heartbeat-service.test.ts +289 -7
  104. package/src/__tests__/helpers/channel-test-adapter.ts +2 -2
  105. package/src/__tests__/helpers/create-guardian-binding.ts +91 -0
  106. package/src/__tests__/host-bash-proxy.test.ts +46 -122
  107. package/src/__tests__/host-browser-e2e-cloud.test.ts +36 -497
  108. package/src/__tests__/host-browser-e2e-self-hosted-capability.test.ts +26 -96
  109. package/src/__tests__/host-browser-proxy.test.ts +111 -185
  110. package/src/__tests__/host-browser-routes.test.ts +45 -75
  111. package/src/__tests__/host-browser-ws-events-e2e.test.ts +26 -30
  112. package/src/__tests__/host-cu-proxy.test.ts +56 -111
  113. package/src/__tests__/host-file-proxy.test.ts +44 -98
  114. package/src/__tests__/host-file-read-tool.test.ts +42 -21
  115. package/src/__tests__/host-shell-tool.test.ts +33 -68
  116. package/src/__tests__/host-transfer-pending-interactions.test.ts +2 -18
  117. package/src/__tests__/host-transfer-proxy.test.ts +43 -53
  118. package/src/__tests__/http-user-message-parity.test.ts +0 -6
  119. package/src/__tests__/inbound-slack-persistence.test.ts +31 -0
  120. package/src/__tests__/injector-chain.test.ts +10 -5
  121. package/src/__tests__/injector-pkb-v2-silenced.test.ts +124 -0
  122. package/src/__tests__/inline-command-runner.test.ts +0 -66
  123. package/src/__tests__/inline-skill-load-permissions.test.ts +0 -2
  124. package/src/__tests__/install-skill-routing.test.ts +1 -13
  125. package/src/__tests__/llm-callsite-catalog.test.ts +34 -0
  126. package/src/__tests__/llm-catalog-parity.test.ts +90 -0
  127. package/src/__tests__/llm-context-resolution.test.ts +180 -0
  128. package/src/__tests__/llm-resolver.test.ts +80 -12
  129. package/src/__tests__/llm-usage-store.test.ts +269 -4
  130. package/src/__tests__/log-export-routes.test.ts +89 -0
  131. package/src/__tests__/managed-profile-guard.test.ts +225 -0
  132. package/src/__tests__/managed-skill-lifecycle.test.ts +0 -10
  133. package/src/__tests__/manual-token-reconciliation.test.ts +334 -0
  134. package/src/__tests__/memory-v2-static-injector.test.ts +95 -0
  135. package/src/__tests__/migration-cross-version-compatibility.test.ts +197 -291
  136. package/src/__tests__/migration-export-http.test.ts +33 -26
  137. package/src/__tests__/migration-export-streaming.test.ts +18 -10
  138. package/src/__tests__/migration-export-to-gcs.test.ts +49 -9
  139. package/src/__tests__/migration-import-commit-http.test.ts +66 -21
  140. package/src/__tests__/migration-import-from-gcs.test.ts +50 -9
  141. package/src/__tests__/migration-import-from-url.test.ts +20 -6
  142. package/src/__tests__/migration-import-preflight-http.test.ts +95 -95
  143. package/src/__tests__/migration-parity-persistence.test.ts +62 -25
  144. package/src/__tests__/migration-transport.test.ts +115 -23
  145. package/src/__tests__/migration-validate-http.test.ts +105 -80
  146. package/src/__tests__/migration-wizard.test.ts +133 -27
  147. package/src/__tests__/non-member-access-request.test.ts +1 -1
  148. package/src/__tests__/notification-guardian-path.test.ts +1 -1
  149. package/src/__tests__/oauth-store.test.ts +19 -0
  150. package/src/__tests__/platform-bash-auto-approve.test.ts +21 -12
  151. package/src/__tests__/prechat-onboarding-contract.test.ts +31 -7
  152. package/src/__tests__/pricing.test.ts +68 -4
  153. package/src/__tests__/process-message-background-slack.test.ts +331 -0
  154. package/src/__tests__/provider-managed-proxy-integration.test.ts +153 -17
  155. package/src/__tests__/provider-send-message-override-profile.test.ts +50 -0
  156. package/src/__tests__/provider-usage-tracking.test.ts +208 -0
  157. package/src/__tests__/reaction-persistence.test.ts +9 -6
  158. package/src/__tests__/rebind-secrets-screen.test.ts +53 -16
  159. package/src/__tests__/recording-handler.test.ts +64 -81
  160. package/src/__tests__/regenerate-fire-and-forget-trace.test.ts +4 -3
  161. package/src/__tests__/relay-server.test.ts +18 -13
  162. package/src/__tests__/require-fresh-approval.test.ts +13 -22
  163. package/src/__tests__/runtime-attachment-metadata.test.ts +1 -1
  164. package/src/__tests__/runtime-events-sse-parity.test.ts +3 -4
  165. package/src/__tests__/runtime-events-sse.test.ts +3 -12
  166. package/src/__tests__/search-skills-unified.test.ts +9 -15
  167. package/src/__tests__/secret-ingress-cli.test.ts +2 -5
  168. package/src/__tests__/secret-ingress-http.test.ts +0 -4
  169. package/src/__tests__/secret-onetime-send.test.ts +4 -2
  170. package/src/__tests__/secret-prompt-log-hygiene.test.ts +24 -7
  171. package/src/__tests__/secret-prompter-channel-fallback.test.ts +42 -47
  172. package/src/__tests__/secret-response-routing.test.ts +29 -15
  173. package/src/__tests__/secret-routes-managed-proxy.test.ts +5 -1
  174. package/src/__tests__/secret-scanner.test.ts +2 -545
  175. package/src/__tests__/send-endpoint-busy.test.ts +9 -24
  176. package/src/__tests__/settings-routes.test.ts +1 -1
  177. package/src/__tests__/shell-credential-ref.test.ts +0 -8
  178. package/src/__tests__/shell-tool-proxy-mode.test.ts +0 -56
  179. package/src/__tests__/skill-script-runner-sandbox.test.ts +0 -11
  180. package/src/__tests__/skill-tool-factory.test.ts +97 -0
  181. package/src/__tests__/skills-file-content-endpoint.test.ts +9 -30
  182. package/src/__tests__/skills-files-catalog-fallback.test.ts +11 -17
  183. package/src/__tests__/slack-inbound-verification.test.ts +1 -62
  184. package/src/__tests__/subagent-fork-notifications.test.ts +57 -47
  185. package/src/__tests__/subagent-manager-notify.test.ts +70 -70
  186. package/src/__tests__/subagent-notify-parent.test.ts +80 -83
  187. package/src/__tests__/system-prompt.test.ts +115 -13
  188. package/src/__tests__/terminal-tools.test.ts +0 -89
  189. package/src/__tests__/thread-backfill.test.ts +945 -31
  190. package/src/__tests__/tool-domain-event-publisher.test.ts +0 -36
  191. package/src/__tests__/tool-execute-pipeline.test.ts +0 -6
  192. package/src/__tests__/tool-execution-abort-cleanup.test.ts +0 -16
  193. package/src/__tests__/tool-execution-pipeline.benchmark.test.ts +9 -19
  194. package/src/__tests__/tool-executor-lifecycle-events.test.ts +4 -7
  195. package/src/__tests__/tool-executor.test.ts +12 -19
  196. package/src/__tests__/tool-metrics-listener.test.ts +0 -35
  197. package/src/__tests__/tool-side-effects-slack-dm.test.ts +1 -0
  198. package/src/__tests__/tool-trace-listener.test.ts +0 -17
  199. package/src/__tests__/transfer-progress-screen.test.ts +63 -26
  200. package/src/__tests__/trusted-contact-lifecycle-notifications.test.ts +2 -149
  201. package/src/__tests__/trusted-contact-multichannel.test.ts +2 -4
  202. package/src/__tests__/trusted-contact-verification.test.ts +1 -1
  203. package/src/__tests__/tts-catalog-parity.test.ts +16 -5
  204. package/src/__tests__/usage-attribution.test.ts +247 -0
  205. package/src/__tests__/usage-cli.test.ts +143 -0
  206. package/src/__tests__/usage-grouped-buckets.test.ts +155 -0
  207. package/src/__tests__/usage-routes.test.ts +150 -0
  208. package/src/__tests__/validation-results-screen.test.ts +39 -16
  209. package/src/__tests__/vbundle-pax-and-symlink.test.ts +12 -3
  210. package/src/__tests__/vellum-self-knowledge-inline-command.test.ts +49 -137
  211. package/src/__tests__/verification-control-plane-policy.test.ts +4 -7
  212. package/src/__tests__/voice-session-bridge.test.ts +5 -5
  213. package/src/__tests__/workspace-migration-062-drop-memory-v2-edges-json.test.ts +103 -0
  214. package/src/__tests__/workspace-migration-063-release-notes-dynamic-model-context.test.ts +77 -0
  215. package/src/__tests__/workspace-migration-064-unwind-main-agent-opus-seed.test.ts +225 -0
  216. package/src/__tests__/workspace-migration-memory-v2-init.test.ts +8 -30
  217. package/src/acp/index.ts +0 -15
  218. package/src/acp/session-manager.ts +37 -34
  219. package/src/agent/loop.ts +16 -1
  220. package/src/approvals/AGENTS.md +4 -0
  221. package/src/approvals/__tests__/guardian-feed-event.test.ts +10 -3
  222. package/src/approvals/guardian-request-resolvers.ts +10 -2
  223. package/src/backup/__tests__/backup-worker.test.ts +36 -8
  224. package/src/backup/__tests__/paths.test.ts +2 -2
  225. package/src/backup/__tests__/restore.test.ts +45 -28
  226. package/src/backup/backup-worker.ts +36 -2
  227. package/src/backup/paths.ts +9 -6
  228. package/src/browser-session/events.ts +0 -9
  229. package/src/calls/call-store.ts +1 -34
  230. package/src/calls/guardian-question-copy.ts +0 -108
  231. package/src/calls/relay-server.ts +0 -24
  232. package/src/calls/twilio-rest.ts +0 -38
  233. package/src/calls/twilio-routes.ts +1 -1
  234. package/src/calls/voice-session-bridge.ts +7 -38
  235. package/src/channels/types.ts +1 -36
  236. package/src/cli/commands/__tests__/cache.test.ts +152 -5
  237. package/src/cli/commands/__tests__/memory-v2.test.ts +14 -28
  238. package/src/cli/commands/__tests__/trust.test.ts +21 -387
  239. package/src/cli/commands/backup.ts +4 -4
  240. package/src/cli/commands/cache-fs.ts +8 -0
  241. package/src/cli/commands/cache.ts +153 -82
  242. package/src/cli/commands/clients.ts +63 -5
  243. package/src/cli/commands/completions.ts +3 -3
  244. package/src/cli/commands/contacts.ts +231 -76
  245. package/src/cli/commands/keys.ts +4 -1
  246. package/src/cli/commands/memory-v2.ts +24 -52
  247. package/src/cli/commands/oauth/shared.ts +2 -29
  248. package/src/cli/commands/pending.ts +102 -0
  249. package/src/cli/commands/skills.ts +77 -35
  250. package/src/cli/commands/trust.ts +70 -430
  251. package/src/cli/commands/usage.ts +25 -16
  252. package/src/cli/lib/daemon-credential-client.ts +14 -0
  253. package/src/cli/program.ts +2 -0
  254. package/src/cli.ts +0 -21
  255. package/src/config/__tests__/feature-flag-registry-guard.test.ts +2 -2
  256. package/src/config/bundled-skills/messaging/TOOLS.json +14 -4
  257. package/src/config/env-registry.ts +12 -2
  258. package/src/config/env.ts +3 -14
  259. package/src/config/feature-flag-registry.json +30 -30
  260. package/src/config/llm-callsite-catalog.ts +12 -0
  261. package/src/config/llm-context-resolution.ts +80 -0
  262. package/src/config/llm-resolver.ts +58 -22
  263. package/src/config/loader.ts +3 -3
  264. package/src/config/schema.ts +2 -158
  265. package/src/config/schemas/__tests__/memory-v2.test.ts +1 -0
  266. package/src/config/schemas/call-site-catalog.ts +271 -0
  267. package/src/config/schemas/calls.ts +5 -5
  268. package/src/config/schemas/inference.ts +1 -1
  269. package/src/config/schemas/ingress.ts +1 -1
  270. package/src/config/schemas/llm.ts +31 -3
  271. package/src/config/schemas/memory-retrieval.ts +2 -2
  272. package/src/config/schemas/memory-v2.ts +9 -0
  273. package/src/config/schemas/security.ts +1 -42
  274. package/src/config/schemas/services.ts +6 -6
  275. package/src/config/schemas/skills.ts +5 -5
  276. package/src/config/schemas/tts.ts +1 -1
  277. package/src/config/seed-inference-profiles.ts +117 -0
  278. package/src/config/skills.ts +0 -90
  279. package/src/config/types.ts +3 -6
  280. package/src/contacts/contact-store.ts +0 -17
  281. package/src/contacts/contacts-write.ts +1 -105
  282. package/src/context/window-manager.ts +44 -5
  283. package/src/credential-execution/process-manager.ts +34 -10
  284. package/src/credential-health/credential-health-service.ts +21 -16
  285. package/src/daemon/__tests__/conversation-surfaces-launch.test.ts +75 -82
  286. package/src/daemon/__tests__/daemon-skill-host.test.ts +2 -9
  287. package/src/daemon/connection-policy.ts +1 -26
  288. package/src/daemon/conversation-agent-loop-handlers.ts +53 -4
  289. package/src/daemon/conversation-agent-loop.ts +277 -36
  290. package/src/daemon/conversation-history.ts +8 -8
  291. package/src/daemon/conversation-launch.ts +20 -135
  292. package/src/daemon/conversation-lifecycle.ts +1 -1
  293. package/src/daemon/conversation-messaging.ts +1 -0
  294. package/src/daemon/conversation-process.ts +83 -163
  295. package/src/daemon/conversation-runtime-assembly.ts +219 -76
  296. package/src/daemon/conversation-slash.ts +47 -5
  297. package/src/daemon/conversation-store.ts +7 -31
  298. package/src/daemon/conversation-surfaces.ts +22 -28
  299. package/src/daemon/conversation-tool-setup.ts +3 -33
  300. package/src/daemon/conversation-usage.ts +36 -0
  301. package/src/daemon/conversation.ts +117 -233
  302. package/src/daemon/daemon-control.ts +3 -71
  303. package/src/daemon/daemon-skill-host.ts +8 -11
  304. package/src/daemon/dictation-profile-store.ts +2 -26
  305. package/src/daemon/first-greeting.ts +44 -156
  306. package/src/daemon/handlers/config-channels.ts +12 -12
  307. package/src/daemon/handlers/config-ingress.ts +4 -165
  308. package/src/daemon/handlers/config-model.ts +1 -1
  309. package/src/daemon/handlers/config-voice.ts +0 -42
  310. package/src/daemon/handlers/conversations.ts +11 -190
  311. package/src/daemon/handlers/recording.ts +26 -158
  312. package/src/daemon/handlers/shared.ts +23 -71
  313. package/src/daemon/handlers/skills.ts +42 -93
  314. package/src/daemon/host-bash-proxy.ts +67 -45
  315. package/src/daemon/host-browser-proxy.ts +65 -27
  316. package/src/daemon/host-cu-proxy.ts +40 -39
  317. package/src/daemon/host-file-proxy.ts +58 -37
  318. package/src/daemon/host-transfer-proxy.ts +84 -46
  319. package/src/daemon/lifecycle.ts +49 -15
  320. package/src/daemon/message-types/conversations.ts +7 -0
  321. package/src/daemon/message-types/host-bash.ts +1 -0
  322. package/src/daemon/message-types/host-cu.ts +1 -0
  323. package/src/daemon/message-types/host-file.ts +1 -0
  324. package/src/daemon/message-types/host-transfer.ts +1 -0
  325. package/src/daemon/message-types/messages.ts +10 -9
  326. package/src/daemon/message-types/workspace.ts +1 -1
  327. package/src/daemon/process-message.ts +102 -239
  328. package/src/daemon/server.ts +13 -462
  329. package/src/daemon/shutdown-handlers.ts +2 -2
  330. package/src/daemon/tool-side-effects.ts +125 -107
  331. package/src/daemon/trust-context.ts +13 -0
  332. package/src/daemon/wake-target-adapter.ts +4 -9
  333. package/src/events/domain-events.ts +0 -8
  334. package/src/events/tool-audit-listener.ts +3 -1
  335. package/src/events/tool-domain-event-publisher.ts +0 -10
  336. package/src/events/tool-metrics-listener.ts +0 -17
  337. package/src/events/tool-trace-listener.ts +0 -14
  338. package/src/filing/filing-service.ts +13 -1
  339. package/src/heartbeat/__tests__/heartbeat-feed-event.test.ts +6 -2
  340. package/src/heartbeat/heartbeat-service.ts +23 -5
  341. package/src/home/__tests__/feed-writer.test.ts +0 -4
  342. package/src/home/__tests__/relationship-state-writer.test.ts +30 -0
  343. package/src/home/feed-writer.ts +1 -2
  344. package/src/home/relationship-state-writer.ts +16 -3
  345. package/src/ipc/__tests__/browser-ipc.test.ts +2 -12
  346. package/src/ipc/__tests__/skill-server-bidirectional.test.ts +0 -1
  347. package/src/ipc/assistant-server.ts +3 -10
  348. package/src/ipc/routes/__tests__/memory-v2-backfill.test.ts +39 -20
  349. package/src/ipc/routes/route-adapter.ts +1 -1
  350. package/src/ipc/routes/trust-rules.test.ts +0 -95
  351. package/src/ipc/skill-ipc-types.ts +41 -0
  352. package/src/ipc/skill-routes/__tests__/events-ipc.test.ts +13 -27
  353. package/src/ipc/skill-routes/__tests__/identity.test.ts +4 -23
  354. package/src/ipc/skill-routes/events.ts +12 -23
  355. package/src/ipc/skill-routes/identity.ts +4 -17
  356. package/src/ipc/skill-routes/index.ts +1 -1
  357. package/src/ipc/skill-server.ts +6 -39
  358. package/src/live-voice/__tests__/runtime-websocket-shell.test.ts +0 -8
  359. package/src/live-voice/protocol.ts +4 -13
  360. package/src/mcp/manager.ts +0 -5
  361. package/src/memory/__tests__/fixtures/memory-v2-activation-fixtures.ts +55 -0
  362. package/src/memory/__tests__/memory-v2-activation-log-store.test.ts +127 -0
  363. package/src/memory/app-git-service.ts +0 -32
  364. package/src/memory/app-store.ts +154 -0
  365. package/src/memory/attachments-store.ts +6 -0
  366. package/src/memory/context-search/sources/memory-v2.ts +578 -0
  367. package/src/memory/context-search/sources/memory.ts +5 -0
  368. package/src/memory/context-search/sources/pkb.ts +10 -1
  369. package/src/memory/context-search/sources/workspace.ts +3 -2
  370. package/src/memory/conversation-crud.ts +29 -4
  371. package/src/memory/conversation-disk-view.ts +1 -5
  372. package/src/memory/conversation-starter-checkpoints.ts +63 -0
  373. package/src/memory/db-connection.ts +62 -0
  374. package/src/memory/db-init.ts +14 -0
  375. package/src/memory/embedding-backend.ts +3 -21
  376. package/src/memory/embedding-gemini.ts +0 -2
  377. package/src/memory/embedding-local.ts +6 -6
  378. package/src/memory/embedding-ollama.ts +6 -6
  379. package/src/memory/embedding-openai.ts +6 -6
  380. package/src/memory/embedding-types.ts +21 -0
  381. package/src/memory/graph/__tests__/conversation-graph-memory-v2-routing.test.ts +3 -7
  382. package/src/memory/graph/conversation-graph-memory.ts +35 -13
  383. package/src/memory/graph/injection.test.ts +2 -2
  384. package/src/memory/graph/injection.ts +1 -1
  385. package/src/memory/guardian-action-store.ts +0 -83
  386. package/src/memory/guardian-approvals.ts +0 -48
  387. package/src/memory/indexer.ts +1 -15
  388. package/src/memory/job-handlers/conversation-starters.ts +36 -53
  389. package/src/memory/job-utils.ts +0 -6
  390. package/src/memory/jobs-store.ts +0 -1
  391. package/src/memory/jobs-worker.ts +2 -16
  392. package/src/memory/llm-request-log-store.ts +0 -41
  393. package/src/memory/llm-usage-store.ts +129 -43
  394. package/src/memory/memory-v2-activation-log-store.ts +115 -0
  395. package/src/memory/migrations/233-document-conversations.ts +54 -0
  396. package/src/memory/migrations/234-memory-v2-activation-logs.ts +55 -0
  397. package/src/memory/migrations/235-llm-usage-attribution.ts +31 -0
  398. package/src/memory/migrations/235-slack-compaction-watermark.ts +44 -0
  399. package/src/memory/migrations/236-tool-invocations-matched-rule-id.ts +26 -0
  400. package/src/memory/migrations/__tests__/234-memory-v2-activation-logs.test.ts +182 -0
  401. package/src/memory/migrations/index.ts +14 -0
  402. package/src/memory/migrations/registry.ts +24 -0
  403. package/src/memory/raw-query.ts +2 -68
  404. package/src/memory/schema/conversations.ts +7 -0
  405. package/src/memory/schema/infrastructure.ts +25 -0
  406. package/src/memory/search/semantic.ts +5 -16
  407. package/src/memory/tool-usage-store.ts +2 -0
  408. package/src/memory/usage-buckets.ts +40 -1
  409. package/src/memory/usage-grouped-buckets.ts +127 -0
  410. package/src/memory/v2/__tests__/activation.test.ts +289 -90
  411. package/src/memory/v2/__tests__/backfill-jobs.test.ts +2 -129
  412. package/src/memory/v2/__tests__/consolidation-job.test.ts +28 -11
  413. package/src/memory/v2/__tests__/edge-index.test.ts +278 -0
  414. package/src/memory/v2/__tests__/injection.test.ts +384 -15
  415. package/src/memory/v2/__tests__/migration.test.ts +64 -36
  416. package/src/memory/v2/__tests__/page-store.test.ts +191 -8
  417. package/src/memory/v2/__tests__/prompts-consolidation.test.ts +181 -0
  418. package/src/memory/v2/__tests__/skill-store.test.ts +115 -3
  419. package/src/memory/v2/__tests__/static-context.test.ts +153 -0
  420. package/src/memory/v2/activation.ts +168 -97
  421. package/src/memory/v2/backfill-jobs.ts +15 -100
  422. package/src/memory/v2/consolidation-job.ts +14 -12
  423. package/src/memory/v2/edge-index.ts +191 -0
  424. package/src/memory/v2/injection.ts +182 -58
  425. package/src/memory/v2/migration.ts +57 -64
  426. package/src/memory/v2/now-text.ts +2 -3
  427. package/src/memory/v2/page-store.ts +168 -31
  428. package/src/memory/v2/prompts/consolidation.ts +118 -42
  429. package/src/memory/v2/prompts/sweep.ts +3 -3
  430. package/src/memory/v2/skill-store.ts +55 -7
  431. package/src/memory/v2/static-context.ts +62 -0
  432. package/src/memory/v2/types.ts +10 -20
  433. package/src/memory/validation.ts +0 -11
  434. package/src/messaging/draft-store.ts +0 -6
  435. package/src/messaging/provider-types.ts +8 -0
  436. package/src/messaging/provider.ts +7 -0
  437. package/src/messaging/providers/gmail/client.ts +1 -121
  438. package/src/messaging/providers/outlook/client.ts +0 -73
  439. package/src/messaging/providers/slack/__tests__/adapter-mention-rendering.test.ts +226 -0
  440. package/src/messaging/providers/slack/adapter.ts +122 -21
  441. package/src/messaging/providers/slack/backfill.test.ts +95 -6
  442. package/src/messaging/providers/slack/backfill.ts +89 -11
  443. package/src/messaging/providers/slack/client.ts +10 -124
  444. package/src/messaging/providers/slack/message-metadata.ts +12 -2
  445. package/src/messaging/providers/slack/render-transcript.test.ts +56 -0
  446. package/src/messaging/providers/slack/render-transcript.ts +126 -25
  447. package/src/messaging/providers/slack/types.ts +1 -0
  448. package/src/oauth/connection-resolver.test.ts +8 -0
  449. package/src/oauth/connection-resolver.ts +8 -16
  450. package/src/oauth/credential-token-resolver.ts +97 -0
  451. package/src/oauth/manual-token-connection.ts +30 -34
  452. package/src/oauth/oauth-store.ts +6 -4
  453. package/src/outbound-proxy/certs.ts +0 -7
  454. package/src/outbound-proxy/config.ts +0 -74
  455. package/src/outbound-proxy/health.ts +0 -44
  456. package/src/outbound-proxy/index.ts +0 -22
  457. package/src/permissions/approval-provenance.test.ts +184 -0
  458. package/src/permissions/approval-provenance.ts +70 -0
  459. package/src/permissions/checker.ts +4 -1
  460. package/src/permissions/gateway-threshold-reader.ts +4 -1
  461. package/src/permissions/prompter.ts +9 -2
  462. package/src/permissions/secret-prompter.ts +21 -48
  463. package/src/permissions/types.ts +33 -0
  464. package/src/permissions/workspace-policy.ts +0 -5
  465. package/src/platform/sync-identity.ts +0 -8
  466. package/src/plugins/defaults/injectors.ts +69 -2
  467. package/src/plugins/defaults/overflow-reduce.ts +3 -2
  468. package/src/plugins/types.ts +8 -0
  469. package/src/prompts/system-prompt.ts +34 -70
  470. package/src/prompts/templates/BOOTSTRAP.md +52 -6
  471. package/src/prompts/update-bulletin-job.ts +2 -0
  472. package/src/providers/__tests__/retry-callsite.test.ts +138 -1
  473. package/src/providers/anthropic/client.ts +72 -33
  474. package/src/providers/call-site-routing.ts +42 -3
  475. package/src/providers/gemini/client.ts +18 -2
  476. package/src/providers/managed-proxy/context.ts +0 -5
  477. package/src/providers/model-catalog.ts +105 -19
  478. package/src/providers/openai/chat-completions-provider.ts +6 -0
  479. package/src/providers/openai/responses-provider.ts +7 -1
  480. package/src/providers/provider-send-message.ts +45 -2
  481. package/src/providers/ratelimit.ts +7 -2
  482. package/src/providers/registry.ts +14 -9
  483. package/src/providers/retry.ts +96 -8
  484. package/src/providers/types.ts +13 -0
  485. package/src/providers/usage-tracking.ts +96 -0
  486. package/src/runtime/AGENTS.md +10 -6
  487. package/src/runtime/__tests__/agent-wake.test.ts +89 -0
  488. package/src/runtime/agent-wake.ts +39 -2
  489. package/src/runtime/assistant-event-hub.ts +541 -45
  490. package/src/runtime/assistant-event.ts +1 -6
  491. package/src/runtime/auth/context.ts +0 -9
  492. package/src/runtime/auth/middleware.ts +1 -1
  493. package/src/runtime/auth/route-policy.ts +11 -9
  494. package/src/runtime/auth/token-service.ts +0 -11
  495. package/src/runtime/channel-approvals.ts +6 -2
  496. package/src/runtime/channel-verification-service.ts +3 -5
  497. package/src/runtime/http-errors.ts +0 -34
  498. package/src/runtime/http-router.ts +6 -3
  499. package/src/runtime/http-server.ts +22 -82
  500. package/src/runtime/http-types.ts +5 -0
  501. package/src/runtime/interactive-ui.ts +0 -1
  502. package/src/runtime/middleware/auth.ts +0 -20
  503. package/src/runtime/migrations/__tests__/v1-test-helpers.ts +112 -0
  504. package/src/runtime/migrations/__tests__/vbundle-builder-credentials.test.ts +11 -4
  505. package/src/runtime/migrations/__tests__/vbundle-builder-v1-shape.test.ts +253 -0
  506. package/src/runtime/migrations/__tests__/vbundle-import-credentials.test.ts +19 -6
  507. package/src/runtime/migrations/__tests__/vbundle-legacy-user-md.test.ts +71 -27
  508. package/src/runtime/migrations/__tests__/vbundle-metadata-merge-integration.test.ts +41 -2
  509. package/src/runtime/migrations/__tests__/vbundle-streaming-importer.test.ts +143 -79
  510. package/src/runtime/migrations/__tests__/vbundle-streaming-validator.test.ts +143 -23
  511. package/src/runtime/migrations/__tests__/vbundle-tar-stream.test.ts +2 -2
  512. package/src/runtime/migrations/__tests__/vbundle-validator-v1-schema.test.ts +371 -0
  513. package/src/runtime/migrations/migration-transport.ts +46 -13
  514. package/src/runtime/migrations/migration-wizard.ts +2 -2
  515. package/src/runtime/migrations/origin-mode.ts +40 -0
  516. package/src/runtime/migrations/vbundle-builder.ts +133 -79
  517. package/src/runtime/migrations/vbundle-import-analyzer.ts +9 -7
  518. package/src/runtime/migrations/vbundle-importer.ts +7 -7
  519. package/src/runtime/migrations/vbundle-metadata-merge.ts +1 -1
  520. package/src/runtime/migrations/vbundle-streaming-importer.ts +3 -3
  521. package/src/runtime/migrations/vbundle-streaming-validator.ts +48 -26
  522. package/src/runtime/migrations/vbundle-validator.ts +214 -41
  523. package/src/runtime/pending-interactions.ts +13 -4
  524. package/src/runtime/routes/__tests__/acp-routes.test.ts +0 -1
  525. package/src/runtime/routes/__tests__/backup-routes.test.ts +28 -19
  526. package/src/runtime/routes/__tests__/conversation-query-routes.test.ts +235 -0
  527. package/src/runtime/routes/__tests__/llm-call-sites-routes.test.ts +58 -0
  528. package/src/runtime/routes/__tests__/migration-export-secrets-redacted.test.ts +54 -0
  529. package/src/runtime/routes/__tests__/migration-import-credential-filter.test.ts +19 -6
  530. package/src/runtime/routes/__tests__/user-route-dispatcher.test.ts +7 -7
  531. package/src/runtime/routes/acp-routes.test.ts +0 -3
  532. package/src/runtime/routes/acp-routes.ts +3 -7
  533. package/src/runtime/routes/app-management-routes.ts +18 -9
  534. package/src/runtime/routes/approval-routes.ts +55 -14
  535. package/src/runtime/routes/avatar-routes.ts +3 -5
  536. package/src/runtime/routes/browser-routes.ts +1 -15
  537. package/src/runtime/routes/channel-guardian-routes.ts +1 -5
  538. package/src/runtime/routes/channel-readiness-routes.ts +3 -7
  539. package/src/runtime/routes/channel-route-shared.ts +2 -28
  540. package/src/runtime/routes/client-routes.ts +45 -12
  541. package/src/runtime/routes/consolidation-routes.ts +115 -0
  542. package/src/runtime/routes/conversation-list-routes.ts +12 -29
  543. package/src/runtime/routes/conversation-management-routes.ts +14 -51
  544. package/src/runtime/routes/conversation-query-routes.ts +120 -8
  545. package/src/runtime/routes/conversation-routes.ts +44 -528
  546. package/src/runtime/routes/conversation-starter-routes.ts +19 -40
  547. package/src/runtime/routes/documents-routes.ts +53 -18
  548. package/src/runtime/routes/events-routes.ts +59 -91
  549. package/src/runtime/routes/filing-routes.ts +18 -1
  550. package/src/runtime/routes/guardian-action-routes.ts +4 -9
  551. package/src/runtime/routes/host-bash-routes.ts +3 -2
  552. package/src/runtime/routes/host-browser-routes.ts +9 -33
  553. package/src/runtime/routes/host-cu-routes.ts +6 -1
  554. package/src/runtime/routes/host-file-routes.ts +3 -2
  555. package/src/runtime/routes/host-transfer-routes.ts +11 -15
  556. package/src/runtime/routes/identity-routes.ts +78 -6
  557. package/src/runtime/routes/inbound-message-handler.ts +580 -137
  558. package/src/runtime/routes/inbound-stages/acl-enforcement.ts +2 -88
  559. package/src/runtime/routes/inbound-stages/background-dispatch.ts +3 -0
  560. package/src/runtime/routes/index.ts +4 -0
  561. package/src/runtime/routes/integrations/slack/channel.ts +0 -24
  562. package/src/runtime/routes/llm-call-sites-routes.ts +22 -0
  563. package/src/runtime/routes/memory-v2-routes.ts +10 -15
  564. package/src/runtime/routes/migration-routes.ts +188 -31
  565. package/src/runtime/routes/playground/guard.ts +1 -1
  566. package/src/runtime/routes/playground/index.ts +0 -2
  567. package/src/runtime/routes/recording-routes.ts +4 -24
  568. package/src/runtime/routes/rename-conversation-routes.ts +2 -6
  569. package/src/runtime/routes/schedule-routes.ts +3 -6
  570. package/src/runtime/routes/secret-routes.ts +87 -18
  571. package/src/runtime/routes/settings-routes.ts +29 -28
  572. package/src/runtime/routes/skills-routes.ts +12 -31
  573. package/src/runtime/routes/suggest-trust-rule-routes.ts +32 -1
  574. package/src/runtime/routes/task-routes.ts +6 -6
  575. package/src/runtime/routes/trust-rules-routes.ts +3 -94
  576. package/src/runtime/routes/types.ts +4 -4
  577. package/src/runtime/routes/upgrade-broadcast-routes.ts +3 -10
  578. package/src/runtime/routes/usage-routes.ts +87 -10
  579. package/src/runtime/routes/user-routes.ts +17 -31
  580. package/src/runtime/routes/work-items-routes.ts +1 -4
  581. package/src/runtime/services/__tests__/analyze-conversation.test.ts +2 -2
  582. package/src/runtime/services/analyze-conversation.ts +7 -17
  583. package/src/runtime/services/conversation-serializer.ts +2 -4
  584. package/src/runtime/verification-outbound-actions.ts +1 -1
  585. package/src/runtime/verification-rate-limiter.ts +1 -1
  586. package/src/schedule/schedule-store.ts +0 -16
  587. package/src/security/secret-scanner.ts +14 -547
  588. package/src/security/secure-keys.ts +31 -11
  589. package/src/security/token-manager.ts +7 -3
  590. package/src/signals/cancel.ts +16 -25
  591. package/src/signals/conversation-undo.ts +2 -27
  592. package/src/signals/emit-event.ts +1 -2
  593. package/src/signals/user-message.ts +108 -22
  594. package/src/skills/catalog-install.ts +1 -0
  595. package/src/skills/clawhub.ts +2 -2
  596. package/src/skills/inline-command-runner.ts +1 -7
  597. package/src/subagent/manager.ts +67 -84
  598. package/src/tasks/task-store.ts +1 -28
  599. package/src/telemetry/types.ts +6 -0
  600. package/src/telemetry/usage-telemetry-reporter.test.ts +38 -15
  601. package/src/telemetry/usage-telemetry-reporter.ts +3 -5
  602. package/src/tools/acp/spawn.test.ts +1 -2
  603. package/src/tools/acp/steer.test.ts +1 -2
  604. package/src/tools/browser/__tests__/browser-status.test.ts +44 -127
  605. package/src/tools/browser/browser-execution.ts +31 -147
  606. package/src/tools/browser/cdp-client/__tests__/factory.test.ts +92 -68
  607. package/src/tools/browser/cdp-client/factory.ts +48 -76
  608. package/src/tools/browser/cdp-client/index.ts +1 -14
  609. package/src/tools/executor.ts +44 -31
  610. package/src/tools/host-filesystem/edit.ts +3 -2
  611. package/src/tools/host-filesystem/read.ts +3 -2
  612. package/src/tools/host-filesystem/transfer.test.ts +45 -42
  613. package/src/tools/host-filesystem/transfer.ts +4 -3
  614. package/src/tools/host-filesystem/write.ts +3 -2
  615. package/src/tools/host-terminal/host-shell.ts +4 -3
  616. package/src/tools/network/script-proxy/index.ts +1 -10
  617. package/src/tools/permission-checker.ts +66 -1
  618. package/src/tools/skills/sandbox-runner.ts +1 -6
  619. package/src/tools/skills/skill-tool-factory.ts +32 -0
  620. package/src/tools/terminal/safe-env.ts +1 -0
  621. package/src/tools/terminal/shell.ts +2 -78
  622. package/src/tools/types.ts +12 -39
  623. package/src/tts/__tests__/provider-catalog.test.ts +2 -2
  624. package/src/tts/provider-catalog.ts +1 -1
  625. package/src/usage/actors.ts +2 -1
  626. package/src/usage/attribution.ts +185 -0
  627. package/src/usage/pricing.ts +166 -0
  628. package/src/usage/types.ts +14 -0
  629. package/src/util/json.ts +13 -0
  630. package/src/util/logger.ts +3 -3
  631. package/src/util/pricing.ts +50 -3
  632. package/src/work-items/work-item-runner.ts +15 -42
  633. package/src/workspace/migrations/050-seed-main-agent-opus-callsite.ts +4 -3
  634. package/src/workspace/migrations/052-seed-default-inference-profiles.ts +3 -3
  635. package/src/workspace/migrations/060-memory-v2-init.ts +2 -18
  636. package/src/workspace/migrations/061-move-backup-key-to-workspace.ts +59 -0
  637. package/src/workspace/migrations/062-drop-memory-v2-edges-json.ts +27 -0
  638. package/src/workspace/migrations/063-release-notes-dynamic-model-context.ts +70 -0
  639. package/src/workspace/migrations/064-unwind-main-agent-opus-seed.ts +64 -0
  640. package/src/workspace/migrations/registry.ts +8 -0
  641. package/src/workspace/provider-commit-message-generator.ts +3 -3
  642. package/src/__tests__/sandbox-diagnostics.test.ts +0 -138
  643. package/src/__tests__/sandbox-host-parity.test.ts +0 -1024
  644. package/src/__tests__/secret-detection-handler.test.ts +0 -67
  645. package/src/__tests__/secret-scanner-executor.test.ts +0 -450
  646. package/src/__tests__/tcc-sandbox-deny.test.ts +0 -198
  647. package/src/__tests__/terminal-sandbox.test.ts +0 -374
  648. package/src/__tests__/tool-notification-listener.test.ts +0 -65
  649. package/src/context/__tests__/microcompact.test.ts +0 -805
  650. package/src/context/microcompact.ts +0 -443
  651. package/src/daemon/handlers/slack-channel-oauth-install.ts +0 -197
  652. package/src/events/tool-notification-listener.ts +0 -17
  653. package/src/ipc/routes/__tests__/memory-v2-validate.test.ts +0 -219
  654. package/src/memory/v2/__tests__/edges.test.ts +0 -435
  655. package/src/memory/v2/edges.ts +0 -217
  656. package/src/prompts/__tests__/system-prompt-memory-v2.test.ts +0 -197
  657. package/src/runtime/__tests__/chrome-extension-registry.test.ts +0 -518
  658. package/src/runtime/__tests__/client-registry.test.ts +0 -271
  659. package/src/runtime/chrome-extension-registry.ts +0 -368
  660. package/src/runtime/client-registry.ts +0 -254
  661. package/src/runtime/routes/inbound-stages/verification-intercept.ts +0 -329
  662. package/src/tools/secret-detection-handler.ts +0 -269
  663. package/src/tools/terminal/backends/native.ts +0 -327
  664. package/src/tools/terminal/backends/types.ts +0 -37
  665. package/src/tools/terminal/sandbox-diagnostics.ts +0 -87
  666. package/src/tools/terminal/sandbox.ts +0 -40
@@ -31,6 +31,7 @@ import {
31
31
  getConfiguredProvider,
32
32
  userMessage,
33
33
  } from "../../providers/provider-send-message.js";
34
+ import { broadcastMessage } from "../../runtime/assistant-event-hub.js";
34
35
  import {
35
36
  isTextMimeType as isTextMime,
36
37
  MAX_INLINE_TEXT_SIZE,
@@ -50,7 +51,6 @@ import {
50
51
  upsertSkillsIndex,
51
52
  } from "../../skills/catalog-install.js";
52
53
  import { filterByQuery } from "../../skills/catalog-search.js";
53
- import type { SkillCategory } from "../../skills/category-inference.js";
54
54
  import { inferCategory } from "../../skills/category-inference.js";
55
55
  import {
56
56
  clawhubCheckUpdates,
@@ -81,36 +81,14 @@ import {
81
81
  type SkillAuditData,
82
82
  } from "../../skills/skillssh-registry.js";
83
83
  import { getWorkspaceSkillsDir } from "../../util/platform.js";
84
+ import { getConfigWatcher } from "../config-watcher.js";
84
85
  import { maybeSeedMemoryV2Skills } from "../memory-v2-startup.js";
85
86
  import type {
86
87
  SkillDetailResponse,
87
88
  SkillFileContentResponse,
88
89
  SlimSkillResponse,
89
90
  } from "../message-types/skills.js";
90
-
91
- // Re-export for use by route layer and future consumers.
92
- export type { SkillCategory };
93
- export { inferCategory };
94
- import {
95
- CONFIG_RELOAD_DEBOUNCE_MS,
96
- ensureSkillEntry,
97
- type HandlerContext,
98
- log,
99
- } from "./shared.js";
100
-
101
- // ─── Shared context for standalone functions ─────────────────────────────────
102
-
103
- /**
104
- * Minimal context needed by the standalone skill business-logic functions.
105
- * HandlerContext satisfies this interface, but HTTP routes can also provide
106
- * a compatible object without coupling to handler internals.
107
- */
108
- export interface SkillOperationContext {
109
- debounceTimers: HandlerContext["debounceTimers"];
110
- setSuppressConfigReload(value: boolean): void;
111
- updateConfigFingerprint(): void;
112
- broadcast: HandlerContext["broadcast"];
113
- }
91
+ import { CONFIG_RELOAD_DEBOUNCE_MS, ensureSkillEntry, log } from "./shared.js";
114
92
 
115
93
  // ─── Provider chain for uninstalled skill file preview ───────────────────────
116
94
  // Ordered by priority: vellum first (most common and cheapest to check),
@@ -258,28 +236,25 @@ const LLM_DRAFT_TIMEOUT_MS = 15_000;
258
236
  // These are consumed by both the handlers below and the HTTP route layer.
259
237
 
260
238
  /** Helper: suppress config reload, save, debounce, and update fingerprint. */
261
- function saveConfigWithSuppression(
262
- raw: Record<string, unknown>,
263
- ctx: SkillOperationContext,
264
- ): void {
265
- ctx.setSuppressConfigReload(true);
239
+ function saveConfigWithSuppression(raw: Record<string, unknown>): void {
240
+ getConfigWatcher().suppressConfigReload = true;
266
241
  try {
267
242
  saveRawConfig(raw);
268
243
  } catch (err) {
269
- ctx.setSuppressConfigReload(false);
244
+ getConfigWatcher().suppressConfigReload = false;
270
245
  throw err;
271
246
  }
272
247
  invalidateConfigCache();
273
248
 
274
- ctx.debounceTimers.schedule(
249
+ getConfigWatcher().timers.schedule(
275
250
  "__suppress_reset__",
276
251
  () => {
277
- ctx.setSuppressConfigReload(false);
252
+ getConfigWatcher().suppressConfigReload = false;
278
253
  },
279
254
  CONFIG_RELOAD_DEBOUNCE_MS,
280
255
  );
281
256
 
282
- ctx.updateConfigFingerprint();
257
+ getConfigWatcher().updateFingerprint();
283
258
  }
284
259
 
285
260
  /**
@@ -296,11 +271,7 @@ function saveConfigWithSuppression(
296
271
  * NOT used for bundled skills — those have a simpler inline path in
297
272
  * `installSkill()` that only auto-enables, broadcasts, and seeds memories.
298
273
  */
299
- function postInstallSkill(
300
- skillId: string,
301
- _skillDir: string,
302
- ctx: SkillOperationContext,
303
- ): void {
274
+ function postInstallSkill(skillId: string, _skillDir: string): void {
304
275
  // Reload skill catalog so the newly installed skill is picked up
305
276
  loadSkillCatalog();
306
277
 
@@ -308,8 +279,8 @@ function postInstallSkill(
308
279
  try {
309
280
  const raw = loadRawConfig();
310
281
  ensureSkillEntry(raw, skillId).enabled = true;
311
- saveConfigWithSuppression(raw, ctx);
312
- ctx.broadcast({
282
+ saveConfigWithSuppression(raw);
283
+ broadcastMessage({
313
284
  type: "skills_state_changed",
314
285
  name: skillId,
315
286
  state: "enabled",
@@ -413,7 +384,7 @@ function toSlimSkillResponse(
413
384
  }
414
385
  }
415
386
 
416
- export function listSkills(_ctx: SkillOperationContext): SlimSkillResponse[] {
387
+ export function listSkills(): SlimSkillResponse[] {
417
388
  const config = getConfig();
418
389
  const catalog = loadSkillCatalog();
419
390
  const resolved = resolveSkillStates(catalog, config);
@@ -431,10 +402,8 @@ export function listSkills(_ctx: SkillOperationContext): SlimSkillResponse[] {
431
402
  * List installed skills merged with available catalog skills.
432
403
  * Installed skills take precedence when deduplicating by ID.
433
404
  */
434
- async function listSkillsWithCatalog(
435
- ctx: SkillOperationContext,
436
- ): Promise<SlimSkillResponse[]> {
437
- const installed = listSkills(ctx);
405
+ async function listSkillsWithCatalog(): Promise<SlimSkillResponse[]> {
406
+ const installed = listSkills();
438
407
  const installedIds = new Set(installed.map((s) => s.id));
439
408
 
440
409
  let catalogSkills: CatalogSkill[];
@@ -503,18 +472,15 @@ function originMatchesQuery(origin: string, query: string): boolean {
503
472
  * List skills with filtering, category counts, and sorting.
504
473
  * Calls listSkillsWithCatalog for the full merged list, then applies filters.
505
474
  */
506
- export async function listSkillsFiltered(
507
- filter: SkillListFilter,
508
- ctx: SkillOperationContext,
509
- ): Promise<{
475
+ export async function listSkillsFiltered(filter: SkillListFilter): Promise<{
510
476
  skills: SlimSkillResponse[];
511
477
  categoryCounts: Record<string, number>;
512
478
  totalCount: number;
513
479
  }> {
514
480
  let skills =
515
481
  filter.includeCatalog !== false
516
- ? await listSkillsWithCatalog(ctx)
517
- : listSkills(ctx);
482
+ ? await listSkillsWithCatalog()
483
+ : listSkills();
518
484
 
519
485
  // Apply origin filter
520
486
  if (filter.origin) {
@@ -608,7 +574,6 @@ function findSkillById(
608
574
 
609
575
  export async function getSkill(
610
576
  skillId: string,
611
- _ctx: SkillOperationContext,
612
577
  ): Promise<{ skill: SkillDetailResponse } | { error: string; status: number }> {
613
578
  const found = findSkillById(skillId);
614
579
  if (!found) {
@@ -812,7 +777,6 @@ function readDirRecursive(dir: string, rootDir: string): SkillFileEntry[] {
812
777
  export async function getSkillFileContent(
813
778
  skillId: string,
814
779
  relativePath: string,
815
- _ctx: SkillOperationContext,
816
780
  ): Promise<SkillFileContentResponse | { error: string; status: number }> {
817
781
  const sanitized = sanitizeRelativePath(relativePath);
818
782
  if (!sanitized) {
@@ -935,7 +899,6 @@ export async function getSkillFileContent(
935
899
 
936
900
  export async function getSkillFiles(
937
901
  skillId: string,
938
- _ctx: SkillOperationContext,
939
902
  ): Promise<
940
903
  | { skill: SlimSkillResponse; files: SkillFileEntry[] }
941
904
  | { error: string; status: number }
@@ -976,13 +939,12 @@ export async function getSkillFiles(
976
939
 
977
940
  export function enableSkill(
978
941
  skillId: string,
979
- ctx: SkillOperationContext,
980
942
  ): { success: true } | { success: false; error: string } {
981
943
  try {
982
944
  const raw = loadRawConfig();
983
945
  ensureSkillEntry(raw, skillId).enabled = true;
984
- saveConfigWithSuppression(raw, ctx);
985
- ctx.broadcast({
946
+ saveConfigWithSuppression(raw);
947
+ broadcastMessage({
986
948
  type: "skills_state_changed",
987
949
  name: skillId,
988
950
  state: "enabled",
@@ -1000,13 +962,12 @@ export function enableSkill(
1000
962
 
1001
963
  export function disableSkill(
1002
964
  skillId: string,
1003
- ctx: SkillOperationContext,
1004
965
  ): { success: true } | { success: false; error: string } {
1005
966
  try {
1006
967
  const raw = loadRawConfig();
1007
968
  ensureSkillEntry(raw, skillId).enabled = false;
1008
- saveConfigWithSuppression(raw, ctx);
1009
- ctx.broadcast({
969
+ saveConfigWithSuppression(raw);
970
+ broadcastMessage({
1010
971
  type: "skills_state_changed",
1011
972
  name: skillId,
1012
973
  state: "disabled",
@@ -1029,7 +990,6 @@ export function configureSkill(
1029
990
  apiKey?: string;
1030
991
  config?: Record<string, unknown>;
1031
992
  },
1032
- ctx: SkillOperationContext,
1033
993
  ): { success: true } | { success: false; error: string } {
1034
994
  try {
1035
995
  const raw = loadRawConfig();
@@ -1037,7 +997,7 @@ export function configureSkill(
1037
997
  if (config.env) entry.env = config.env;
1038
998
  if (config.apiKey !== undefined) entry.apiKey = config.apiKey;
1039
999
  if (config.config) entry.config = config.config;
1040
- saveConfigWithSuppression(raw, ctx);
1000
+ saveConfigWithSuppression(raw);
1041
1001
  return { success: true };
1042
1002
  } catch (err) {
1043
1003
  const message = err instanceof Error ? err.message : String(err);
@@ -1054,15 +1014,12 @@ function looksLikeSkillsShSlug(slug: string): boolean {
1054
1014
  return slug.split("/").length >= 3;
1055
1015
  }
1056
1016
 
1057
- export async function installSkill(
1058
- spec: {
1059
- slug: string;
1060
- version?: string;
1061
- origin?: "clawhub" | "skillssh";
1062
- contactId?: string;
1063
- },
1064
- ctx: SkillOperationContext,
1065
- ): Promise<
1017
+ export async function installSkill(spec: {
1018
+ slug: string;
1019
+ version?: string;
1020
+ origin?: "clawhub" | "skillssh";
1021
+ contactId?: string;
1022
+ }): Promise<
1066
1023
  { success: true; skillId: string } | { success: false; error: string }
1067
1024
  > {
1068
1025
  try {
@@ -1095,8 +1052,8 @@ export async function installSkill(
1095
1052
  try {
1096
1053
  const raw = loadRawConfig();
1097
1054
  ensureSkillEntry(raw, spec.slug).enabled = true;
1098
- saveConfigWithSuppression(raw, ctx);
1099
- ctx.broadcast({
1055
+ saveConfigWithSuppression(raw);
1056
+ broadcastMessage({
1100
1057
  type: "skills_state_changed",
1101
1058
  name: spec.slug,
1102
1059
  state: "enabled",
@@ -1130,7 +1087,7 @@ export async function installSkill(
1130
1087
  );
1131
1088
 
1132
1089
  const skillDir = join(getWorkspaceSkillsDir(), spec.slug);
1133
- postInstallSkill(spec.slug, skillDir, ctx);
1090
+ postInstallSkill(spec.slug, skillDir);
1134
1091
  return { success: true, skillId: spec.slug };
1135
1092
  }
1136
1093
  } catch (err) {
@@ -1158,7 +1115,7 @@ export async function installSkill(
1158
1115
  );
1159
1116
 
1160
1117
  const skillDir = join(getWorkspaceSkillsDir(), resolved.skillSlug);
1161
- postInstallSkill(resolved.skillSlug, skillDir, ctx);
1118
+ postInstallSkill(resolved.skillSlug, skillDir);
1162
1119
  return { success: true, skillId: resolved.skillSlug };
1163
1120
  }
1164
1121
 
@@ -1186,7 +1143,7 @@ export async function installSkill(
1186
1143
  }
1187
1144
  upsertSkillsIndex(skillId);
1188
1145
 
1189
- postInstallSkill(skillId, skillDir, ctx);
1146
+ postInstallSkill(skillId, skillDir);
1190
1147
  return { success: true, skillId };
1191
1148
  } catch (err) {
1192
1149
  const message = err instanceof Error ? err.message : String(err);
@@ -1197,7 +1154,6 @@ export async function installSkill(
1197
1154
 
1198
1155
  export async function uninstallSkill(
1199
1156
  skillId: string,
1200
- ctx: SkillOperationContext,
1201
1157
  ): Promise<{ success: true } | { success: false; error: string }> {
1202
1158
  // Validate skill name to prevent path traversal while allowing namespaced slugs (org/name)
1203
1159
  const validNamespacedSlug =
@@ -1245,10 +1201,10 @@ export async function uninstallSkill(
1245
1201
  const entries = skills?.entries as Record<string, unknown> | undefined;
1246
1202
  if (entries?.[skillId]) {
1247
1203
  delete entries[skillId];
1248
- saveConfigWithSuppression(raw, ctx);
1204
+ saveConfigWithSuppression(raw);
1249
1205
  }
1250
1206
 
1251
- ctx.broadcast({
1207
+ broadcastMessage({
1252
1208
  type: "skills_state_changed",
1253
1209
  name: skillId,
1254
1210
  state: "uninstalled",
@@ -1264,7 +1220,6 @@ export async function uninstallSkill(
1264
1220
 
1265
1221
  export async function updateSkill(
1266
1222
  skillId: string,
1267
- _ctx: SkillOperationContext,
1268
1223
  ): Promise<{ success: true } | { success: false; error: string }> {
1269
1224
  try {
1270
1225
  const result = await clawhubUpdate(skillId);
@@ -1281,9 +1236,7 @@ export async function updateSkill(
1281
1236
  }
1282
1237
  }
1283
1238
 
1284
- export async function checkSkillUpdates(
1285
- _ctx: SkillOperationContext,
1286
- ): Promise<
1239
+ export async function checkSkillUpdates(): Promise<
1287
1240
  { success: true; data: unknown } | { success: false; error: string }
1288
1241
  > {
1289
1242
  try {
@@ -1298,7 +1251,6 @@ export async function checkSkillUpdates(
1298
1251
 
1299
1252
  export async function searchSkills(
1300
1253
  query: string,
1301
- _ctx: SkillOperationContext,
1302
1254
  ): Promise<
1303
1255
  | { success: true; skills: SlimSkillResponse[] }
1304
1256
  | { success: false; error: string }
@@ -1461,7 +1413,6 @@ export async function searchSkills(
1461
1413
 
1462
1414
  export async function inspectSkill(
1463
1415
  skillId: string,
1464
- _ctx: SkillOperationContext,
1465
1416
  ): Promise<{ slug: string; data?: ClawhubInspectResult; error?: string }> {
1466
1417
  try {
1467
1418
  const result = await clawhubInspect(skillId);
@@ -1490,10 +1441,9 @@ export interface DraftResult {
1490
1441
  error?: string;
1491
1442
  }
1492
1443
 
1493
- export async function draftSkill(
1494
- params: { sourceText: string },
1495
- _ctx: SkillOperationContext,
1496
- ): Promise<DraftResult> {
1444
+ export async function draftSkill(params: {
1445
+ sourceText: string;
1446
+ }): Promise<DraftResult> {
1497
1447
  try {
1498
1448
  const warnings: string[] = [];
1499
1449
  const parsed = parseFrontmatter(params.sourceText);
@@ -1645,7 +1595,6 @@ export interface CreateSkillParams {
1645
1595
 
1646
1596
  export async function createSkill(
1647
1597
  params: CreateSkillParams,
1648
- ctx: SkillOperationContext,
1649
1598
  ): Promise<{ success: true } | { success: false; error: string }> {
1650
1599
  try {
1651
1600
  const result = createManagedSkill({
@@ -1669,8 +1618,8 @@ export async function createSkill(
1669
1618
  try {
1670
1619
  const raw = loadRawConfig();
1671
1620
  ensureSkillEntry(raw, params.skillId).enabled = true;
1672
- saveConfigWithSuppression(raw, ctx);
1673
- ctx.broadcast({
1621
+ saveConfigWithSuppression(raw);
1622
+ broadcastMessage({
1674
1623
  type: "skills_state_changed",
1675
1624
  name: params.skillId,
1676
1625
  state: "enabled",
@@ -1,6 +1,11 @@
1
1
  import { v4 as uuid } from "uuid";
2
2
 
3
3
  import { getConfig } from "../config/loader.js";
4
+ import {
5
+ assistantEventHub,
6
+ broadcastMessage,
7
+ } from "../runtime/assistant-event-hub.js";
8
+ import * as pendingInteractions from "../runtime/pending-interactions.js";
4
9
  import { formatShellOutput } from "../tools/shared/shell-output.js";
5
10
  import type { ToolExecutionResult } from "../tools/types.js";
6
11
  import { AssistantError, ErrorCode } from "../util/errors.js";
@@ -14,30 +19,53 @@ interface PendingRequest {
14
19
  reject: (err: Error) => void;
15
20
  timer: ReturnType<typeof setTimeout>;
16
21
  timeoutSec: number;
22
+ conversationId: string;
17
23
  /** Detach the abort listener from the caller's signal. No-op when no signal was passed. */
18
24
  detachAbort: () => void;
19
25
  }
20
26
 
21
27
  export class HostBashProxy {
28
+ private static _instance: HostBashProxy | null = null;
29
+
30
+ /**
31
+ * Lazily-initialized singleton. Availability of an actual desktop
32
+ * connection is checked at send time via the assistant event hub,
33
+ * not at construction time.
34
+ */
35
+ static get instance(): HostBashProxy {
36
+ if (!HostBashProxy._instance) {
37
+ log.info("Creating singleton HostBashProxy");
38
+ HostBashProxy._instance = new HostBashProxy();
39
+ }
40
+ return HostBashProxy._instance;
41
+ }
42
+
43
+ /** Dispose the singleton. Called during graceful shutdown. */
44
+ static disposeInstance(): void {
45
+ if (HostBashProxy._instance) {
46
+ HostBashProxy._instance.dispose();
47
+ HostBashProxy._instance = null;
48
+ }
49
+ }
50
+
51
+ /** For tests. */
52
+ static reset(): void {
53
+ HostBashProxy._instance = null;
54
+ }
55
+
22
56
  private pending = new Map<string, PendingRequest>();
23
- private sendToClient: (msg: ServerMessage) => void;
24
- private onInternalResolve?: (requestId: string) => void;
25
- private clientConnected = false;
26
-
27
- constructor(
28
- sendToClient: (msg: ServerMessage) => void,
29
- onInternalResolve?: (requestId: string) => void,
30
- ) {
31
- this.sendToClient = sendToClient;
32
- this.onInternalResolve = onInternalResolve;
57
+
58
+ /**
59
+ * Whether a client with `host_bash` capability is connected.
60
+ */
61
+ isAvailable(): boolean {
62
+ return (
63
+ assistantEventHub.getMostRecentClientByCapability("host_bash") != null
64
+ );
33
65
  }
34
66
 
35
- updateSender(
36
- sendToClient: (msg: ServerMessage) => void,
37
- clientConnected: boolean,
38
- ): void {
39
- this.sendToClient = sendToClient;
40
- this.clientConnected = clientConnected;
67
+ private send(msg: ServerMessage): void {
68
+ broadcastMessage(msg, undefined, { targetCapability: "host_bash" });
41
69
  }
42
70
 
43
71
  request(
@@ -70,7 +98,7 @@ export class HostBashProxy {
70
98
  const timer = setTimeout(() => {
71
99
  this.pending.delete(requestId);
72
100
  detachAbort();
73
- this.onInternalResolve?.(requestId);
101
+ pendingInteractions.resolve(requestId);
74
102
  log.warn(
75
103
  { requestId, command: input.command },
76
104
  "Host bash proxy request timed out",
@@ -91,15 +119,14 @@ export class HostBashProxy {
91
119
  if (this.pending.has(requestId)) {
92
120
  clearTimeout(timer);
93
121
  this.pending.delete(requestId);
94
- // Abort fired — nothing to detach, but call the no-op for symmetry
95
- // so callers can rely on detachAbort being idempotent.
96
122
  detachAbort();
97
- this.onInternalResolve?.(requestId);
123
+ pendingInteractions.resolve(requestId);
98
124
  try {
99
- this.sendToClient({
125
+ this.send({
100
126
  type: "host_bash_cancel",
101
127
  requestId,
102
- } as ServerMessage);
128
+ conversationId,
129
+ });
103
130
  } catch {
104
131
  // Best-effort cancel notification — connection may already be closed.
105
132
  }
@@ -115,11 +142,12 @@ export class HostBashProxy {
115
142
  reject,
116
143
  timer,
117
144
  timeoutSec,
145
+ conversationId,
118
146
  detachAbort,
119
147
  });
120
148
 
121
149
  try {
122
- this.sendToClient({
150
+ this.send({
123
151
  type: "host_bash_request",
124
152
  requestId,
125
153
  conversationId,
@@ -127,17 +155,14 @@ export class HostBashProxy {
127
155
  working_dir: input.working_dir,
128
156
  timeout_seconds: input.timeout_seconds,
129
157
  ...(input.env && Object.keys(input.env).length > 0
130
- ? { env: input.env }
131
- : {}),
132
- } as ServerMessage);
158
+ ? { env: input.env }
159
+ : {}),
160
+ });
133
161
  } catch (err) {
134
- // Sender threw synchronously (e.g. client transport error during
135
- // event emission). Clean up pending state and timer so we don't
136
- // leak an in-flight entry that nothing will ever resolve.
137
162
  clearTimeout(timer);
138
163
  this.pending.delete(requestId);
139
164
  detachAbort();
140
- this.onInternalResolve?.(requestId);
165
+ pendingInteractions.resolve(requestId);
141
166
  log.warn(
142
167
  { requestId, command: input.command, err },
143
168
  "Host bash proxy send failed",
@@ -178,23 +203,20 @@ export class HostBashProxy {
178
203
  return this.pending.has(requestId);
179
204
  }
180
205
 
181
- isAvailable(): boolean {
182
- return this.clientConnected;
183
- }
184
-
185
206
  dispose(): void {
186
207
  for (const [requestId, entry] of this.pending) {
187
- clearTimeout(entry.timer);
188
- entry.detachAbort();
189
- this.onInternalResolve?.(requestId);
190
- try {
191
- this.sendToClient({
192
- type: "host_bash_cancel",
193
- requestId,
194
- } as ServerMessage);
195
- } catch {
196
- // Best-effort cancel notification — connection may already be closed.
197
- }
208
+ clearTimeout(entry.timer);
209
+ entry.detachAbort();
210
+ pendingInteractions.resolve(requestId);
211
+ try {
212
+ this.send({
213
+ type: "host_bash_cancel",
214
+ requestId,
215
+ conversationId: entry.conversationId,
216
+ });
217
+ } catch {
218
+ // Best-effort cancel notification — connection may already be closed.
219
+ }
198
220
  entry.reject(
199
221
  new AssistantError(
200
222
  "Host bash proxy disposed",