@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
@@ -197,7 +197,7 @@ async function handleAddSecret({ body }: RouteHandlerArgs) {
197
197
  }
198
198
  }
199
199
 
200
- const stored = await setSecureKeyAsync(name, value);
200
+ const stored = await setSecureKeyAsync(credentialKey(name, "api_key"), value);
201
201
  if (!stored) {
202
202
  throw new InternalError(
203
203
  `Failed to store API key in secure storage (backend: ${getActiveBackendName()})`,
@@ -339,6 +339,7 @@ async function handleReadSecret({ body }: RouteHandlerArgs) {
339
339
 
340
340
  try {
341
341
  let accountKey: string;
342
+ let prefetchedResult: Awaited<ReturnType<typeof getSecureKeyResultAsync>> | undefined;
342
343
 
343
344
  if (type === "api_key") {
344
345
  if (
@@ -348,7 +349,14 @@ async function handleReadSecret({ body }: RouteHandlerArgs) {
348
349
  `Unknown API key provider: ${name}. Valid providers: ${API_KEY_PROVIDERS.join(", ")}`,
349
350
  );
350
351
  }
351
- accountKey = name;
352
+ // Check credential namespace first; fall back to bare key only if not found and store is reachable.
353
+ const credResult = await getSecureKeyResultAsync(credentialKey(name, "api_key"));
354
+ if (credResult.value === undefined && !credResult.unreachable) {
355
+ accountKey = name;
356
+ } else {
357
+ accountKey = credentialKey(name, "api_key");
358
+ prefetchedResult = credResult;
359
+ }
352
360
  } else if (type === "credential") {
353
361
  const colonIdx = name.lastIndexOf(":");
354
362
  if (colonIdx < 1 || colonIdx === name.length - 1) {
@@ -365,7 +373,7 @@ async function handleReadSecret({ body }: RouteHandlerArgs) {
365
373
  );
366
374
  }
367
375
 
368
- const { value, unreachable } = await getSecureKeyResultAsync(accountKey);
376
+ const { value, unreachable } = prefetchedResult ?? await getSecureKeyResultAsync(accountKey);
369
377
  if (value === undefined) {
370
378
  return { found: false, unreachable };
371
379
  }
@@ -418,12 +426,31 @@ async function handleDeleteSecret({ body }: RouteHandlerArgs) {
418
426
  `Unknown API key provider: ${name}. Valid providers: ${API_KEY_PROVIDERS.join(", ")}`,
419
427
  );
420
428
  }
421
- const existing = await getSecureKeyAsync(name);
422
- if (existing === undefined) {
423
- throw new NotFoundError(`API key not found: ${name}`);
429
+ const credKey = credentialKey(name, "api_key");
430
+ const credResult = await getSecureKeyResultAsync(credKey);
431
+ if (credResult.unreachable) {
432
+ throw new InternalError("Credential store is unreachable");
424
433
  }
425
- const deleteResult = await deleteSecureKeyAsync(name);
426
- if (deleteResult === "error") {
434
+ // Confirm at least one location holds the key before reporting success.
435
+ if (credResult.value === undefined) {
436
+ const bareResult = await getSecureKeyResultAsync(name);
437
+ if (bareResult.unreachable) {
438
+ throw new InternalError("Credential store is unreachable");
439
+ }
440
+ if (bareResult.value === undefined) {
441
+ throw new NotFoundError(`API key not found: ${name}`);
442
+ }
443
+ }
444
+ // Delete from both locations. During a migration overlap both may exist;
445
+ // ignore "not-found" since one location may already be empty.
446
+ const credDeleteResult = await deleteSecureKeyAsync(credKey);
447
+ if (credDeleteResult === "error") {
448
+ throw new InternalError(
449
+ `Failed to delete API key from secure storage: ${name}`,
450
+ );
451
+ }
452
+ const bareDeleteResult = await deleteSecureKeyAsync(name);
453
+ if (bareDeleteResult === "error") {
427
454
  throw new InternalError(
428
455
  `Failed to delete API key from secure storage: ${name}`,
429
456
  );
@@ -502,19 +529,61 @@ async function handleListSecrets() {
502
529
  throw new InternalError("Credential store is unreachable");
503
530
  }
504
531
 
505
- const secrets = accounts.map((account) => {
506
- if (account.startsWith(CREDENTIAL_KEY_PREFIX)) {
532
+ // First pass: collect provider names already stored under the credential/
533
+ // namespace. Used to deduplicate bare-key entries that co-exist when a
534
+ // crash interrupted migration 002 between the set(credentialKey) and
535
+ // delete(provider) steps.
536
+ const credentialNamespaceProviders = new Set<string>(
537
+ accounts.flatMap((account) => {
538
+ if (!account.startsWith(CREDENTIAL_KEY_PREFIX)) return [];
507
539
  const rest = account.slice(CREDENTIAL_KEY_PREFIX.length);
508
540
  const slashIdx = rest.indexOf("/");
509
- if (slashIdx > 0 && slashIdx < rest.length - 1) {
510
- return {
511
- type: "credential" as const,
512
- name: `${rest.slice(0, slashIdx)}:${rest.slice(slashIdx + 1)}`,
513
- };
541
+ if (slashIdx < 1 || slashIdx >= rest.length - 1) return [];
542
+ const service = rest.slice(0, slashIdx);
543
+ const field = rest.slice(slashIdx + 1);
544
+ if (
545
+ field === "api_key" &&
546
+ API_KEY_PROVIDERS.includes(service as (typeof API_KEY_PROVIDERS)[number])
547
+ ) {
548
+ return [service];
514
549
  }
515
- }
516
- return { type: "api_key" as const, name: account };
517
- });
550
+ return [];
551
+ }),
552
+ );
553
+
554
+ const secrets = accounts
555
+ .filter((account) => {
556
+ // Drop bare-key entries for providers already represented via the
557
+ // credential/ namespace to prevent duplicates after a partial migration.
558
+ if (account.startsWith(CREDENTIAL_KEY_PREFIX)) return true;
559
+ if (credentialNamespaceProviders.has(account)) return false;
560
+ return true;
561
+ })
562
+ .map((account) => {
563
+ if (account.startsWith(CREDENTIAL_KEY_PREFIX)) {
564
+ const rest = account.slice(CREDENTIAL_KEY_PREFIX.length);
565
+ const slashIdx = rest.indexOf("/");
566
+ if (slashIdx > 0 && slashIdx < rest.length - 1) {
567
+ const service = rest.slice(0, slashIdx);
568
+ const field = rest.slice(slashIdx + 1);
569
+ // api_key entries are stored as credential/{provider}/api_key
570
+ if (
571
+ field === "api_key" &&
572
+ API_KEY_PROVIDERS.includes(
573
+ service as (typeof API_KEY_PROVIDERS)[number],
574
+ )
575
+ ) {
576
+ return { type: "api_key" as const, name: service };
577
+ }
578
+ return {
579
+ type: "credential" as const,
580
+ name: `${service}:${field}`,
581
+ };
582
+ }
583
+ }
584
+ // Bare keys (pre-migration or unknown): treat as api_key
585
+ return { type: "api_key" as const, name: account };
586
+ });
518
587
 
519
588
  return { secrets, accounts: secrets };
520
589
  } catch (err) {
@@ -51,12 +51,7 @@ import { getLogger } from "../../util/logger.js";
51
51
  import { getAvatarImagePath, getWorkspaceDir } from "../../util/platform.js";
52
52
  import { buildAssistantEvent } from "../assistant-event.js";
53
53
  import { assistantEventHub } from "../assistant-event-hub.js";
54
- import { DAEMON_INTERNAL_ASSISTANT_ID } from "../assistant-scope.js";
55
- import {
56
- BadRequestError,
57
- InternalError,
58
- NotFoundError,
59
- } from "./errors.js";
54
+ import { BadRequestError, InternalError, NotFoundError } from "./errors.js";
60
55
  import type { RouteDefinition, RouteHandlerArgs } from "./types.js";
61
56
  import { resolveWorkspacePath } from "./workspace-utils.js";
62
57
 
@@ -101,7 +96,7 @@ async function handleGenerateAvatar({ body = {} }: RouteHandlerArgs) {
101
96
 
102
97
  assistantEventHub
103
98
  .publish(
104
- buildAssistantEvent(DAEMON_INTERNAL_ASSISTANT_ID, {
99
+ buildAssistantEvent({
105
100
  type: "avatar_updated",
106
101
  avatarPath,
107
102
  }),
@@ -112,7 +107,8 @@ async function handleGenerateAvatar({ body = {} }: RouteHandlerArgs) {
112
107
 
113
108
  return { ok: true, avatarPath };
114
109
  } catch (err) {
115
- if (err instanceof InternalError || err instanceof BadRequestError) throw err;
110
+ if (err instanceof InternalError || err instanceof BadRequestError)
111
+ throw err;
116
112
  const message = err instanceof Error ? err.message : String(err);
117
113
  log.error({ error: message }, "Avatar generation failed unexpectedly");
118
114
  throw new InternalError(message);
@@ -236,7 +232,7 @@ async function handleOAuthConnectStart({ body = {} }: RouteHandlerArgs) {
236
232
 
237
233
  assistantEventHub
238
234
  .publish(
239
- buildAssistantEvent(DAEMON_INTERNAL_ASSISTANT_ID, {
235
+ buildAssistantEvent({
240
236
  type: "oauth_connect_result",
241
237
  success: deferredResult.success,
242
238
  service: deferredResult.service,
@@ -296,7 +292,8 @@ async function handleOAuthConnectStart({ body = {} }: RouteHandlerArgs) {
296
292
  ...(authorizeUrl ? { authUrl: authorizeUrl } : {}),
297
293
  };
298
294
  } catch (err) {
299
- if (err instanceof InternalError || err instanceof BadRequestError) throw err;
295
+ if (err instanceof InternalError || err instanceof BadRequestError)
296
+ throw err;
300
297
  const message = err instanceof Error ? err.message : String(err);
301
298
  log.error({ err, service }, "OAuth connect flow failed");
302
299
  throw new InternalError(sanitizeOAuthError(message));
@@ -344,7 +341,8 @@ function handleWorkspaceFileRead({ queryParams = {} }: RouteHandlerArgs) {
344
341
  const content = readFileSync(resolved, "utf-8");
345
342
  return { path: filePath, content };
346
343
  } catch (err) {
347
- if (err instanceof NotFoundError || err instanceof BadRequestError) throw err;
344
+ if (err instanceof NotFoundError || err instanceof BadRequestError)
345
+ throw err;
348
346
  const message = err instanceof Error ? err.message : String(err);
349
347
  log.error({ err, path: filePath }, "Failed to read workspace file");
350
348
  throw new InternalError(message);
@@ -431,13 +429,17 @@ function handleToolNamesList() {
431
429
  }
432
430
 
433
431
  async function handleToolPermissionSimulate({ body = {} }: RouteHandlerArgs) {
434
- const { toolName, input, workingDir: rawWorkingDir, isInteractive } =
435
- body as {
436
- toolName?: string;
437
- input?: Record<string, unknown>;
438
- workingDir?: string;
439
- isInteractive?: boolean;
440
- };
432
+ const {
433
+ toolName,
434
+ input,
435
+ workingDir: rawWorkingDir,
436
+ isInteractive,
437
+ } = body as {
438
+ toolName?: string;
439
+ input?: Record<string, unknown>;
440
+ workingDir?: string;
441
+ isInteractive?: boolean;
442
+ };
441
443
 
442
444
  if (!toolName || typeof toolName !== "string") {
443
445
  throw new BadRequestError("toolName is required");
@@ -450,10 +452,7 @@ async function handleToolPermissionSimulate({ body = {} }: RouteHandlerArgs) {
450
452
 
451
453
  try {
452
454
  const manifestOverride = resolveManifestOverride(toolName);
453
- const executionTarget = resolveExecutionTarget(
454
- toolName,
455
- manifestOverride,
456
- );
455
+ const executionTarget = resolveExecutionTarget(toolName, manifestOverride);
457
456
  const executionContext =
458
457
  isInteractive === false ? "headless" : "conversation";
459
458
  const policyContext = { executionTarget, executionContext } as const;
@@ -491,10 +490,7 @@ async function handleToolPermissionSimulate({ body = {} }: RouteHandlerArgs) {
491
490
  | undefined;
492
491
 
493
492
  if (result.decision === "prompt") {
494
- const allowlistOptions = await generateAllowlistOptions(
495
- toolName,
496
- input,
497
- );
493
+ const allowlistOptions = await generateAllowlistOptions(toolName, input);
498
494
  const scopeOptions = generateScopeOptions(workingDir, toolName);
499
495
  promptPayload = {
500
496
  allowlistOptions,
@@ -509,7 +505,7 @@ async function handleToolPermissionSimulate({ body = {} }: RouteHandlerArgs) {
509
505
  riskLevel,
510
506
  reason: result.reason,
511
507
  executionTarget,
512
- matchedRuleId: result.matchedRule?.id,
508
+ matchedTrustRuleId: result.matchedRule?.id,
513
509
  promptPayload,
514
510
  };
515
511
  } catch (err) {
@@ -733,7 +729,12 @@ export const ROUTES: RouteDefinition[] = [
733
729
  tags: ["workspace"],
734
730
  requirePolicyEnforcement: true,
735
731
  queryParams: [
736
- { name: "path", type: "string", required: true, description: "File path to read" },
732
+ {
733
+ name: "path",
734
+ type: "string",
735
+ required: true,
736
+ description: "File path to read",
737
+ },
737
738
  ],
738
739
  handler: handleWorkspaceFileRead,
739
740
  },
@@ -7,9 +7,6 @@
7
7
 
8
8
  import { z } from "zod";
9
9
 
10
- import { broadcastToAllClients } from "../../acp/index.js";
11
- import { getConfigWatcher } from "../../daemon/config-watcher.js";
12
- import type { SkillOperationContext } from "../../daemon/handlers/skills.js";
13
10
  import {
14
11
  checkSkillUpdates,
15
12
  configureSkill,
@@ -31,18 +28,6 @@ import {
31
28
  import { BadRequestError, InternalError, NotFoundError } from "./errors.js";
32
29
  import type { RouteDefinition, RouteHandlerArgs } from "./types.js";
33
30
 
34
- /** Build SkillOperationContext from module-level globals. */
35
- function ctx(): SkillOperationContext {
36
- const cw = getConfigWatcher();
37
- return {
38
- debounceTimers: cw.timers,
39
- setSuppressConfigReload: (v) => {
40
- cw.suppressConfigReload = v;
41
- },
42
- updateConfigFingerprint: () => cw.updateFingerprint(),
43
- broadcast: broadcastToAllClients ?? (() => {}),
44
- };
45
- }
46
31
 
47
32
  const partnerAuditSchema = z.object({
48
33
  risk: z.enum(["safe", "low", "medium", "high", "critical", "unknown"]),
@@ -212,7 +197,6 @@ export const ROUTES: RouteDefinition[] = [
212
197
  ...(category ? { category } : {}),
213
198
  includeCatalog: include === "catalog",
214
199
  },
215
- ctx(),
216
200
  );
217
201
  return {
218
202
  skills: result.skills,
@@ -221,7 +205,7 @@ export const ROUTES: RouteDefinition[] = [
221
205
  };
222
206
  }
223
207
 
224
- const skills = listSkills(ctx());
208
+ const skills = listSkills();
225
209
  return { skills };
226
210
  },
227
211
  },
@@ -256,7 +240,7 @@ export const ROUTES: RouteDefinition[] = [
256
240
  if (!path) {
257
241
  throw new BadRequestError("path query parameter is required");
258
242
  }
259
- const result = await getSkillFileContent(pathParams!.id, path, ctx());
243
+ const result = await getSkillFileContent(pathParams!.id, path);
260
244
  if ("error" in result) {
261
245
  if (result.status === 400) throw new BadRequestError(result.error);
262
246
  if (result.status === 404) throw new NotFoundError(result.error);
@@ -275,7 +259,7 @@ export const ROUTES: RouteDefinition[] = [
275
259
  description: "Return skill metadata and directory contents.",
276
260
  tags: ["skills"],
277
261
  handler: async ({ pathParams }: RouteHandlerArgs) => {
278
- const result = await getSkillFiles(pathParams!.id, ctx());
262
+ const result = await getSkillFiles(pathParams!.id);
279
263
  if ("error" in result) {
280
264
  if (result.status === 404) throw new NotFoundError(result.error);
281
265
  throw new InternalError(result.error);
@@ -294,7 +278,7 @@ export const ROUTES: RouteDefinition[] = [
294
278
  tags: ["skills"],
295
279
  responseBody: z.object({ ok: z.boolean() }),
296
280
  handler: ({ pathParams }: RouteHandlerArgs) => {
297
- const result = enableSkill(pathParams!.id, ctx());
281
+ const result = enableSkill(pathParams!.id);
298
282
  if (!result.success) throw new InternalError(result.error);
299
283
  return { ok: true };
300
284
  },
@@ -310,7 +294,7 @@ export const ROUTES: RouteDefinition[] = [
310
294
  tags: ["skills"],
311
295
  responseBody: z.object({ ok: z.boolean() }),
312
296
  handler: ({ pathParams }: RouteHandlerArgs) => {
313
- const result = disableSkill(pathParams!.id, ctx());
297
+ const result = disableSkill(pathParams!.id);
314
298
  if (!result.success) throw new InternalError(result.error);
315
299
  return { ok: true };
316
300
  },
@@ -338,7 +322,6 @@ export const ROUTES: RouteDefinition[] = [
338
322
  apiKey: body.apiKey as string | undefined,
339
323
  config: body.config as Record<string, unknown> | undefined,
340
324
  },
341
- ctx(),
342
325
  );
343
326
  if (!result.success) throw new InternalError(result.error);
344
327
  return { ok: true };
@@ -357,7 +340,7 @@ export const ROUTES: RouteDefinition[] = [
357
340
  data: z.object({}).passthrough().describe("Update availability info"),
358
341
  }),
359
342
  handler: async () => {
360
- const result = await checkSkillUpdates(ctx());
343
+ const result = await checkSkillUpdates();
361
344
  if (!result.success) throw new InternalError(result.error);
362
345
  return { data: result.data };
363
346
  },
@@ -386,7 +369,7 @@ export const ROUTES: RouteDefinition[] = [
386
369
  handler: async ({ queryParams = {} }: RouteHandlerArgs) => {
387
370
  const query = queryParams.q ?? "";
388
371
  if (!query) throw new BadRequestError("q query parameter is required");
389
- const result = await searchSkills(query, ctx());
372
+ const result = await searchSkills(query);
390
373
  if (!result.success) throw new InternalError(result.error);
391
374
  return { skills: result.skills };
392
375
  },
@@ -408,7 +391,7 @@ export const ROUTES: RouteDefinition[] = [
408
391
  if (!sourceText || typeof sourceText !== "string") {
409
392
  throw new BadRequestError("sourceText is required");
410
393
  }
411
- const result = await draftSkill({ sourceText }, ctx());
394
+ const result = await draftSkill({ sourceText });
412
395
  if (!result.success) {
413
396
  throw new InternalError(result.error ?? "Draft failed");
414
397
  }
@@ -426,7 +409,7 @@ export const ROUTES: RouteDefinition[] = [
426
409
  tags: ["skills"],
427
410
  responseBody: z.object({ ok: z.boolean() }),
428
411
  handler: async ({ pathParams }: RouteHandlerArgs) => {
429
- const result = await updateSkill(pathParams!.id, ctx());
412
+ const result = await updateSkill(pathParams!.id);
430
413
  if (!result.success) throw new InternalError(result.error);
431
414
  return { ok: true };
432
415
  },
@@ -441,7 +424,7 @@ export const ROUTES: RouteDefinition[] = [
441
424
  description: "Return detailed skill information.",
442
425
  tags: ["skills"],
443
426
  handler: async ({ pathParams }: RouteHandlerArgs) => {
444
- const result = await inspectSkill(pathParams!.id, ctx());
427
+ const result = await inspectSkill(pathParams!.id);
445
428
  if (result.error && !result.data) {
446
429
  if (result.error.startsWith("Invalid skill slug:")) {
447
430
  throw new BadRequestError(result.error);
@@ -471,7 +454,7 @@ export const ROUTES: RouteDefinition[] = [
471
454
  skill: skillDetailSchema.describe("Skill detail object"),
472
455
  }),
473
456
  handler: async ({ pathParams }: RouteHandlerArgs) => {
474
- const result = await getSkill(pathParams!.id, ctx());
457
+ const result = await getSkill(pathParams!.id);
475
458
  if ("error" in result) {
476
459
  if (result.status === 404) throw new NotFoundError(result.error);
477
460
  throw new InternalError(result.error);
@@ -490,7 +473,7 @@ export const ROUTES: RouteDefinition[] = [
490
473
  tags: ["skills"],
491
474
  responseStatus: "204",
492
475
  handler: async ({ pathParams }: RouteHandlerArgs) => {
493
- const result = await uninstallSkill(pathParams!.id, ctx());
476
+ const result = await uninstallSkill(pathParams!.id);
494
477
  if (!result.success) throw new InternalError(result.error);
495
478
  return null;
496
479
  },
@@ -534,7 +517,6 @@ export const ROUTES: RouteDefinition[] = [
534
517
  version: body.version as string | undefined,
535
518
  origin: body.origin as "clawhub" | "skillssh" | undefined,
536
519
  },
537
- ctx(),
538
520
  );
539
521
  if (!result.success) throw new InternalError(result.error);
540
522
  return { ok: true, skillId: result.skillId };
@@ -569,7 +551,6 @@ export const ROUTES: RouteDefinition[] = [
569
551
  }
570
552
  const result = await createSkill(
571
553
  { skillId, name, description, bodyMarkdown },
572
- ctx(),
573
554
  );
574
555
  if (!result.success) throw new InternalError(result.error);
575
556
  return { ok: true };
@@ -40,6 +40,11 @@ interface SuggestTrustRuleRequest {
40
40
  directoryScopeOptions?: DirectoryScopeOption[];
41
41
  currentThreshold: string;
42
42
  intent: "auto_approve" | "escalate";
43
+ existingRule?: {
44
+ id: string;
45
+ pattern: string;
46
+ risk: string;
47
+ };
43
48
  }
44
49
 
45
50
  interface SuggestTrustRuleResponse {
@@ -107,7 +112,16 @@ broadest). You may select one of these or generate your own pattern that better
107
112
  captures the intent. The goal is a pattern specific enough to be meaningful but
108
113
  broad enough to cover similar future invocations.
109
114
 
110
- Respond using the suggest_trust_rule tool only.`;
115
+ Respond using the suggest_trust_rule tool only.
116
+
117
+ When \`existingRule\` is provided, you are in refinement mode:
118
+ - The user has an existing rule (pattern, risk) that already governs this tool.
119
+ - The pattern of an existing rule cannot be changed — only risk and description.
120
+ - Your job: suggest a NARROWER pattern the user could add as a new override rule
121
+ (e.g. existing: "bash *" → suggest "bash rm -rf *" for this specific invocation).
122
+ - Pick the narrowest scopeOption that still covers the command invocation shown.
123
+ - Risk suggestion: suggest the risk level for this narrower pattern specifically.
124
+ If the existing rule's risk level is appropriate for the narrow pattern too, keep it.`;
111
125
 
112
126
  // ── User message builder ─────────────────────────────────────────────
113
127
 
@@ -134,6 +148,16 @@ function buildUserMessage(req: SuggestTrustRuleRequest): string {
134
148
  }
135
149
  }
136
150
 
151
+ if (req.existingRule) {
152
+ lines.push("");
153
+ lines.push(
154
+ `Existing rule: "${req.existingRule.pattern}" → ${req.existingRule.risk}`,
155
+ );
156
+ lines.push(
157
+ `(This rule auto-approved the command above. Suggest a narrower override if applicable.)`,
158
+ );
159
+ }
160
+
137
161
  lines.push("");
138
162
  lines.push(
139
163
  `Current threshold: ${req.currentThreshold} (commands ≤ ${req.currentThreshold} auto-approve)`,
@@ -215,6 +239,13 @@ const RequestSchema = z.object({
215
239
  directoryScopeOptions: z.array(DirectoryScopeOptionSchema).optional(),
216
240
  currentThreshold: z.string(),
217
241
  intent: z.enum(["auto_approve", "escalate"]),
242
+ existingRule: z
243
+ .object({
244
+ id: z.string(),
245
+ pattern: z.string(),
246
+ risk: z.string(),
247
+ })
248
+ .optional(),
218
249
  });
219
250
 
220
251
  const ResponseSchema = z.object({
@@ -5,7 +5,7 @@
5
5
 
6
6
  import { z } from "zod";
7
7
 
8
- import { broadcastToAllClients } from "../../acp/index.js";
8
+ import { broadcastMessage } from "../../runtime/assistant-event-hub.js";
9
9
  import type { ToolContext } from "../../tools/types.js";
10
10
  import { getWorkspaceDir } from "../../util/platform.js";
11
11
  import { BadRequestError } from "./errors.js";
@@ -169,7 +169,7 @@ async function handleTaskDelete({ body = {} }: RouteHandlerArgs) {
169
169
  if (result.isError) {
170
170
  throw new BadRequestError(result.content);
171
171
  }
172
- broadcastToAllClients?.({ type: "tasks_changed" });
172
+ broadcastMessage({ type: "tasks_changed" });
173
173
  return { ok: true, content: result.content };
174
174
  }
175
175
 
@@ -197,7 +197,7 @@ async function handleTaskQueueAdd({ body = {} }: RouteHandlerArgs) {
197
197
  buildToolContext(),
198
198
  );
199
199
  if (!result.isError) {
200
- broadcastToAllClients?.({ type: "tasks_changed" });
200
+ broadcastMessage({ type: "tasks_changed" });
201
201
  }
202
202
  return { content: result.content, isError: result.isError };
203
203
  }
@@ -212,7 +212,7 @@ async function handleTaskQueueUpdate({ body = {} }: RouteHandlerArgs) {
212
212
  buildToolContext(),
213
213
  );
214
214
  if (!result.isError) {
215
- broadcastToAllClients?.({ type: "tasks_changed" });
215
+ broadcastMessage({ type: "tasks_changed" });
216
216
  }
217
217
  return { content: result.content, isError: result.isError };
218
218
  }
@@ -227,7 +227,7 @@ async function handleTaskQueueRemove({ body = {} }: RouteHandlerArgs) {
227
227
  buildToolContext(),
228
228
  );
229
229
  if (!result.isError) {
230
- broadcastToAllClients?.({ type: "tasks_changed" });
230
+ broadcastMessage({ type: "tasks_changed" });
231
231
  }
232
232
  return { content: result.content, isError: result.isError };
233
233
  }
@@ -242,7 +242,7 @@ async function handleTaskQueueRun({ body = {} }: RouteHandlerArgs) {
242
242
  buildToolContext(),
243
243
  );
244
244
  if (!result.isError) {
245
- broadcastToAllClients?.({ type: "tasks_changed" });
245
+ broadcastMessage({ type: "tasks_changed" });
246
246
  }
247
247
  return { content: result.content, isError: result.isError };
248
248
  }
@@ -1,10 +1,8 @@
1
1
  /**
2
- * Trust rule CRUD routes — gateway HTTP proxy.
2
+ * Trust rule listing route — gateway HTTP proxy.
3
3
  *
4
- * Each handler makes a single HTTP call to the gateway's trust-rules REST API
4
+ * The handler makes a single HTTP call to the gateway's trust-rules REST API
5
5
  * and surfaces the body's `.error` message on non-OK responses.
6
- *
7
- * Migrated from `ipc/routes/trust-rules.ts` into the shared ROUTES array.
8
6
  */
9
7
  import { z } from "zod";
10
8
 
@@ -44,28 +42,9 @@ const TrustRulesListParams = z
44
42
  })
45
43
  .strict();
46
44
 
47
- const TrustRulesCreateParams = z
48
- .object({
49
- tool: z.string(),
50
- pattern: z.string(),
51
- risk: z.string(),
52
- description: z.string().optional(),
53
- })
54
- .strict();
55
-
56
- const TrustRulesUpdateBody = z
57
- .object({
58
- risk: z.string().optional(),
59
- description: z.string().optional(),
60
- })
61
- .strict();
62
-
63
45
  // ── Handlers ────────────────────────────────────────────────────────────
64
46
 
65
- async function handleList({
66
- queryParams = {},
67
- body = {},
68
- }: RouteHandlerArgs) {
47
+ async function handleList({ queryParams = {}, body = {} }: RouteHandlerArgs) {
69
48
  // HTTP GET delivers filters via queryParams; CLI IPC puts them in body.
70
49
  const source = Object.keys(queryParams).length > 0 ? queryParams : body;
71
50
  const p = TrustRulesListParams.parse(source);
@@ -77,47 +56,6 @@ async function handleList({
77
56
  return gatewayFetch(`/v1/trust-rules${query ? `?${query}` : ""}`);
78
57
  }
79
58
 
80
- async function handleCreate({ body = {} }: RouteHandlerArgs) {
81
- const { tool, pattern, risk, description } = TrustRulesCreateParams.parse(body);
82
- return gatewayFetch("/v1/trust-rules", {
83
- method: "POST",
84
- headers: { "Content-Type": "application/json" },
85
- body: JSON.stringify({ tool, pattern, risk, description }),
86
- });
87
- }
88
-
89
- async function handleUpdate({
90
- pathParams = {},
91
- body = {},
92
- }: RouteHandlerArgs) {
93
- // HTTP path delivers id via pathParams; CLI IPC puts it in body.
94
- const rawBody = body as Record<string, unknown>;
95
- const id = pathParams.id ?? rawBody.id;
96
- if (!id || typeof id !== "string") throw new Error("id is required");
97
- const { id: _discarded, ...rest } = rawBody;
98
- const fields = TrustRulesUpdateBody.parse(rest);
99
- const patchBody: Record<string, unknown> = {};
100
- if (fields.risk !== undefined) patchBody.risk = fields.risk;
101
- if (fields.description !== undefined) patchBody.description = fields.description;
102
- return gatewayFetch(`/v1/trust-rules/${encodeURIComponent(id)}`, {
103
- method: "PATCH",
104
- headers: { "Content-Type": "application/json" },
105
- body: JSON.stringify(patchBody),
106
- });
107
- }
108
-
109
- async function handleRemove({
110
- pathParams = {},
111
- body = {},
112
- }: RouteHandlerArgs) {
113
- // HTTP path delivers id via pathParams; CLI IPC puts it in body.
114
- const id = pathParams.id ?? (body as Record<string, unknown>).id;
115
- if (!id || typeof id !== "string") throw new Error("id is required");
116
- return gatewayFetch(`/v1/trust-rules/${encodeURIComponent(id)}`, {
117
- method: "DELETE",
118
- });
119
- }
120
-
121
59
  // ── Route definitions ───────────────────────────────────────────────────
122
60
 
123
61
  export const ROUTES: RouteDefinition[] = [
@@ -136,33 +74,4 @@ export const ROUTES: RouteDefinition[] = [
136
74
  { name: "include_all", description: "Include unmodified defaults" },
137
75
  ],
138
76
  },
139
- {
140
- operationId: "trust_rules_create",
141
- method: "POST",
142
- endpoint: "trust-rules",
143
- handler: handleCreate,
144
- summary: "Create a trust rule",
145
- description: "Create a new trust rule with tool, pattern, risk level, and optional description.",
146
- tags: ["trust-rules"],
147
- requestBody: TrustRulesCreateParams,
148
- },
149
- {
150
- operationId: "trust_rules_update",
151
- method: "PATCH",
152
- endpoint: "trust-rules/:id",
153
- handler: handleUpdate,
154
- summary: "Update a trust rule",
155
- description: "Update the risk level or description of an existing trust rule.",
156
- tags: ["trust-rules"],
157
- requestBody: TrustRulesUpdateBody,
158
- },
159
- {
160
- operationId: "trust_rules_remove",
161
- method: "DELETE",
162
- endpoint: "trust-rules/:id",
163
- handler: handleRemove,
164
- summary: "Remove a trust rule",
165
- description: "Delete a trust rule by ID.",
166
- tags: ["trust-rules"],
167
- },
168
77
  ];