@vellumai/assistant 0.10.12 → 0.11.0-staging.2

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 (809) hide show
  1. package/AGENTS.md +1 -1
  2. package/ARCHITECTURE.md +4 -5
  3. package/README.md +1 -1
  4. package/docs/architecture/memory.md +60 -23
  5. package/docs/error-handling.md +3 -3
  6. package/docs/guardian-request-flow.md +112 -0
  7. package/node_modules/@vellumai/ces-client/node_modules/@vellumai/service-contracts/package.json +1 -0
  8. package/node_modules/@vellumai/ces-client/node_modules/@vellumai/service-contracts/src/__tests__/channels.test.ts +9 -1
  9. package/node_modules/@vellumai/ces-client/node_modules/@vellumai/service-contracts/src/__tests__/secret-detection.test.ts +449 -0
  10. package/node_modules/@vellumai/ces-client/node_modules/@vellumai/service-contracts/src/channels.ts +1 -0
  11. package/node_modules/@vellumai/ces-client/node_modules/@vellumai/service-contracts/src/secret-detection.ts +468 -0
  12. package/node_modules/@vellumai/gateway-client/node_modules/@slack/types/dist/events/app.d.ts +28 -0
  13. package/node_modules/@vellumai/gateway-client/node_modules/@slack/types/dist/events/app.d.ts.map +1 -1
  14. package/node_modules/@vellumai/gateway-client/node_modules/@slack/types/dist/events/index.d.ts +2 -2
  15. package/node_modules/@vellumai/gateway-client/node_modules/@slack/types/dist/events/index.d.ts.map +1 -1
  16. package/node_modules/@vellumai/gateway-client/node_modules/@slack/types/dist/events/index.js.map +1 -1
  17. package/node_modules/@vellumai/gateway-client/node_modules/@slack/types/dist/events/message.d.ts +2 -0
  18. package/node_modules/@vellumai/gateway-client/node_modules/@slack/types/dist/events/message.d.ts.map +1 -1
  19. package/node_modules/@vellumai/gateway-client/node_modules/@slack/types/package.json +1 -1
  20. package/node_modules/@vellumai/gateway-client/node_modules/@vellumai/service-contracts/package.json +1 -0
  21. package/node_modules/@vellumai/gateway-client/node_modules/@vellumai/service-contracts/src/__tests__/channels.test.ts +9 -1
  22. package/node_modules/@vellumai/gateway-client/node_modules/@vellumai/service-contracts/src/__tests__/secret-detection.test.ts +449 -0
  23. package/node_modules/@vellumai/gateway-client/node_modules/@vellumai/service-contracts/src/channels.ts +1 -0
  24. package/node_modules/@vellumai/gateway-client/node_modules/@vellumai/service-contracts/src/secret-detection.ts +468 -0
  25. package/node_modules/@vellumai/gateway-client/package.json +1 -1
  26. package/node_modules/@vellumai/gateway-client/src/admission-policy-contract.ts +6 -0
  27. package/node_modules/@vellumai/gateway-client/src/inbound-contract.ts +34 -0
  28. package/node_modules/@vellumai/service-contracts/package.json +1 -0
  29. package/node_modules/@vellumai/service-contracts/src/__tests__/channels.test.ts +9 -1
  30. package/node_modules/@vellumai/service-contracts/src/__tests__/secret-detection.test.ts +449 -0
  31. package/node_modules/@vellumai/service-contracts/src/channels.ts +1 -0
  32. package/node_modules/@vellumai/service-contracts/src/secret-detection.ts +468 -0
  33. package/openapi.yaml +264 -14
  34. package/package.json +2 -2
  35. package/src/__tests__/acp-session.test.ts +3 -3
  36. package/src/__tests__/agent-loop-mutable-latest-user-message.test.ts +3 -0
  37. package/src/__tests__/anthropic-provider.test.ts +40 -0
  38. package/src/__tests__/app-conversation-ids-backfill.test.ts +33 -2
  39. package/src/__tests__/app-conversation-ids.test.ts +204 -0
  40. package/src/__tests__/approval-cascade.test.ts +5 -5
  41. package/src/__tests__/approval-routes-http.test.ts +3 -3
  42. package/src/__tests__/ask-question-resolver.test.ts +207 -0
  43. package/src/__tests__/assistant-event-hub-self-exclusion.test.ts +16 -16
  44. package/src/__tests__/assistant-event-hub-targeted.test.ts +13 -11
  45. package/src/__tests__/assistant-event-hub.test.ts +13 -11
  46. package/src/__tests__/assistant-event.test.ts +12 -9
  47. package/src/__tests__/assistant-feature-flag-guard.test.ts +3 -3
  48. package/src/__tests__/assistant-feature-flag-guardrails.test.ts +1 -1
  49. package/src/__tests__/assistant-id-boundary-guard.test.ts +0 -58
  50. package/src/__tests__/assistant-stream-state.test.ts +17 -7
  51. package/src/__tests__/avatar-identity-sync.test.ts +3 -3
  52. package/src/__tests__/background-workers-disk-pressure.test.ts +1 -0
  53. package/src/__tests__/call-conversation-messages.test.ts +134 -18
  54. package/src/__tests__/call-start-guardian-guard.test.ts +27 -0
  55. package/src/__tests__/channel-approvals.test.ts +0 -27
  56. package/src/__tests__/channel-guardian.test.ts +85 -512
  57. package/src/__tests__/channel-readiness-slack-remote.test.ts +151 -3
  58. package/src/__tests__/channel-retry-sweep.test.ts +88 -1
  59. package/src/__tests__/channel-setup-panel-ack.test.ts +12 -9
  60. package/src/__tests__/chat-reveal-guard-priming.test.ts +31 -34
  61. package/src/__tests__/cli-memory-v2-reembed-skills.test.ts +2 -2
  62. package/src/__tests__/compaction-events.test.ts +8 -8
  63. package/src/__tests__/config-loader-platform-defaults.test.ts +54 -28
  64. package/src/__tests__/config-model-image-provider.test.ts +20 -0
  65. package/src/__tests__/config-schema-memory-substrate.test.ts +306 -0
  66. package/src/__tests__/config-schema.test.ts +14 -2
  67. package/src/__tests__/config-set-platform-guard.test.ts +11 -12
  68. package/src/__tests__/config-sounds-sync.test.ts +4 -4
  69. package/src/__tests__/confirmation-request-guardian-bridge.test.ts +5 -0
  70. package/src/__tests__/context-search-memory-source.test.ts +1 -1
  71. package/src/__tests__/context-search-memory-v2-source.test.ts +6 -6
  72. package/src/__tests__/context-token-estimator.test.ts +54 -1
  73. package/src/__tests__/conversation-agent-loop-disk-pressure.test.ts +12 -3
  74. package/src/__tests__/conversation-agent-loop-fatal-cleanup.test.ts +13 -4
  75. package/src/__tests__/conversation-agent-loop-handlers-max-tokens.test.ts +4 -4
  76. package/src/__tests__/conversation-agent-loop-inference-profile.test.ts +10 -1
  77. package/src/__tests__/conversation-agent-loop-overflow.test.ts +22 -13
  78. package/src/__tests__/conversation-agent-loop.test.ts +39 -30
  79. package/src/__tests__/conversation-confirmation-signals.test.ts +14 -14
  80. package/src/__tests__/conversation-evictor.test.ts +49 -0
  81. package/src/__tests__/conversation-fork-crud.test.ts +1 -1
  82. package/src/__tests__/conversation-group-tools.test.ts +279 -0
  83. package/src/__tests__/conversation-history-web-search.test.ts +1 -1
  84. package/src/__tests__/conversation-key-store-disk-view.test.ts +5 -5
  85. package/src/__tests__/conversation-lineage.test.ts +235 -0
  86. package/src/__tests__/conversation-loop-db-lock-resilience.test.ts +5 -5
  87. package/src/__tests__/conversation-message-sync-tags.test.ts +4 -4
  88. package/src/__tests__/conversation-queue.test.ts +81 -81
  89. package/src/__tests__/conversation-routes-enabled-plugins.test.ts +8 -1
  90. package/src/__tests__/conversation-routes-hidden-queue.test.ts +8 -1
  91. package/src/__tests__/conversation-routes-slash-commands.test.ts +10 -1
  92. package/src/__tests__/conversation-runtime-assembly.test.ts +29 -2
  93. package/src/__tests__/conversation-slash-queue.test.ts +11 -11
  94. package/src/__tests__/conversation-slash-unknown.test.ts +2 -2
  95. package/src/__tests__/conversation-speed-override.test.ts +2 -2
  96. package/src/__tests__/conversation-summarize-route.test.ts +9 -0
  97. package/src/__tests__/conversation-surfaces-action-delivery.test.ts +18 -16
  98. package/src/__tests__/conversation-surfaces-activation-emit.test.ts +17 -17
  99. package/src/__tests__/conversation-surfaces-app-open.test.ts +7 -4
  100. package/src/__tests__/conversation-surfaces-data-persist.test.ts +7 -7
  101. package/src/__tests__/conversation-surfaces-standalone-payloads.test.ts +9 -9
  102. package/src/__tests__/conversation-surfaces-standalone.test.ts +12 -12
  103. package/src/__tests__/conversation-surfaces-state-update.test.ts +8 -5
  104. package/src/__tests__/conversation-surfaces-table-action.test.ts +6 -3
  105. package/src/__tests__/conversation-surfaces-task-progress.test.ts +46 -46
  106. package/src/__tests__/conversation-sync-tags.test.ts +5 -5
  107. package/src/__tests__/conversation-wait-for-idle.test.ts +2 -2
  108. package/src/__tests__/conversation-workspace-cache-state.test.ts +0 -4
  109. package/src/__tests__/conversation-workspace-injection.test.ts +0 -3
  110. package/src/__tests__/conversation-workspace-tool-tracking.test.ts +0 -3
  111. package/src/__tests__/copy-composer-tc-templates.test.ts +3 -131
  112. package/src/__tests__/credential-security-invariants.test.ts +1 -0
  113. package/src/__tests__/daemon-assistant-events.test.ts +14 -15
  114. package/src/__tests__/db-test-helpers.ts +13 -27
  115. package/src/__tests__/disk-pressure-routes.test.ts +12 -3
  116. package/src/__tests__/document-tool-security.test.ts +95 -0
  117. package/src/__tests__/drain-kick-guard.test.ts +232 -0
  118. package/src/__tests__/dynamic-skill-background-guard.test.ts +19 -6
  119. package/src/__tests__/emit-event-signal.test.ts +5 -6
  120. package/src/__tests__/encrypted-store-test-helpers.ts +10 -20
  121. package/src/__tests__/events-tail-route.test.ts +6 -4
  122. package/src/__tests__/feature-flag-test-helpers.ts +10 -20
  123. package/src/__tests__/file-edit-tool.test.ts +24 -4
  124. package/src/__tests__/file-list-tool.test.ts +2 -1
  125. package/src/__tests__/file-read-tool.test.ts +62 -10
  126. package/src/__tests__/file-write-tool.test.ts +24 -5
  127. package/src/__tests__/followup-tools.test.ts +58 -0
  128. package/src/__tests__/gateway-threshold-reader-mock.ts +99 -0
  129. package/src/__tests__/graph-extraction-event-date.test.ts +1 -1
  130. package/src/__tests__/guardian-question-mode.test.ts +42 -3
  131. package/src/__tests__/guardian-reply-router-answer-mode.test.ts +283 -0
  132. package/src/__tests__/guardian-vellum-destination-pinning.test.ts +221 -0
  133. package/src/__tests__/heartbeat-disk-pressure.test.ts +1 -0
  134. package/src/__tests__/heartbeat-service.test.ts +1 -0
  135. package/src/__tests__/helpers/native-web-search-harness.ts +10 -10
  136. package/src/__tests__/host-browser-proxy.test.ts +1 -1
  137. package/src/__tests__/host-file-edit-tool.test.ts +3 -3
  138. package/src/__tests__/host-file-read-tool.test.ts +2 -2
  139. package/src/__tests__/host-file-write-tool.test.ts +7 -3
  140. package/src/__tests__/host-shell-tool.test.ts +17 -5
  141. package/src/__tests__/host-transfer-pending-interactions.test.ts +8 -8
  142. package/src/__tests__/image-credentials.test.ts +65 -8
  143. package/src/__tests__/injection-block.test.ts +4 -4
  144. package/src/__tests__/injector-chain.test.ts +1 -1
  145. package/src/__tests__/injector-pkb-v2-silenced.test.ts +2 -2
  146. package/src/__tests__/injector-registry-order-guard.test.ts +4 -9
  147. package/src/__tests__/injector-v3-suppression.test.ts +6 -4
  148. package/src/__tests__/lifecycle-memory-v2-seed.test.ts +27 -28
  149. package/src/__tests__/list-messages-page-latest.test.ts +2 -2
  150. package/src/__tests__/llm-usage-store.test.ts +67 -4
  151. package/src/__tests__/log-redact.test.ts +18 -0
  152. package/src/__tests__/managed-profile-guard.test.ts +27 -0
  153. package/src/__tests__/managed-skill-lifecycle.test.ts +2 -2
  154. package/src/__tests__/media-generate-image.test.ts +62 -11
  155. package/src/__tests__/memory-identity-context-parity.test.ts +1 -1
  156. package/src/__tests__/memory-jobs-worker-lanes.test.ts +9 -1
  157. package/src/__tests__/memory-retrieval-hook.test.ts +4 -4
  158. package/src/__tests__/notification-decision-strategy.test.ts +115 -11
  159. package/src/__tests__/notification-deep-link.test.ts +12 -12
  160. package/src/__tests__/notification-vellum-adapter.test.ts +8 -8
  161. package/src/__tests__/outbound-slack-persistence.test.ts +8 -8
  162. package/src/__tests__/path-policy.test.ts +315 -0
  163. package/src/__tests__/pending-interactions-resolved-event.test.ts +6 -6
  164. package/src/__tests__/persistence-layering-guard.test.ts +2 -2
  165. package/src/__tests__/pkb-autoinject.test.ts +1 -1
  166. package/src/__tests__/platform-bash-auto-approve.test.ts +1 -0
  167. package/src/__tests__/platform-callback-registration.test.ts +10 -10
  168. package/src/__tests__/plugin-event-hub-facade.test.ts +22 -15
  169. package/src/__tests__/plugin-import-boundary-guard.test.ts +15 -15
  170. package/src/__tests__/processing-flag-persist-failure.test.ts +0 -4
  171. package/src/__tests__/provider-platform-proxy-integration.test.ts +0 -1
  172. package/src/__tests__/rebuild-index-graph-nodes.test.ts +1 -1
  173. package/src/__tests__/request-secret-standalone-channel-gate.test.ts +5 -5
  174. package/src/__tests__/require-fresh-approval.test.ts +38 -38
  175. package/src/__tests__/resolve-app-id.test.ts +32 -0
  176. package/src/__tests__/run-due-schedules.test.ts +72 -1
  177. package/src/__tests__/runtime-events-sse-parity.test.ts +11 -10
  178. package/src/__tests__/runtime-events-sse.test.ts +1 -1
  179. package/src/__tests__/schedule-routes.test.ts +44 -5
  180. package/src/__tests__/schedule-store.test.ts +3 -3
  181. package/src/__tests__/schedule-tools.test.ts +176 -0
  182. package/src/__tests__/secret-prompt-log-hygiene.test.ts +3 -3
  183. package/src/__tests__/secret-prompter-channel-fallback.test.ts +3 -3
  184. package/src/__tests__/secret-response-routing.test.ts +3 -3
  185. package/src/__tests__/secret-routes-platform-proxy.test.ts +4 -7
  186. package/src/__tests__/secret-scanner.test.ts +36 -0
  187. package/src/__tests__/send-endpoint-busy.test.ts +7 -7
  188. package/src/__tests__/slack-required-scopes-mirror.test.ts +81 -0
  189. package/src/__tests__/starter-task-flow.test.ts +26 -3
  190. package/src/__tests__/subagent-call-site-routing.test.ts +2 -2
  191. package/src/__tests__/subagent-disposal.test.ts +40 -11
  192. package/src/__tests__/subagent-fork-notifications.test.ts +4 -4
  193. package/src/__tests__/subagent-fork-prompt-role.test.ts +3 -3
  194. package/src/__tests__/subagent-fork-spawn.test.ts +4 -4
  195. package/src/__tests__/subagent-manager-notify.test.ts +73 -14
  196. package/src/__tests__/subagent-notify-parent.test.ts +48 -4
  197. package/src/__tests__/subagent-spawn-and-await.test.ts +62 -14
  198. package/src/__tests__/subagent-tools.test.ts +64 -0
  199. package/src/__tests__/sync-message-contract.test.ts +3 -3
  200. package/src/__tests__/terminal-tools.test.ts +12 -3
  201. package/src/__tests__/test-preload.ts +9 -0
  202. package/src/__tests__/tool-approval-handler.test.ts +587 -43
  203. package/src/__tests__/tool-execution-pipeline.benchmark.test.ts +7 -4
  204. package/src/__tests__/tool-executor.test.ts +116 -0
  205. package/src/__tests__/tool-grant-request-escalation.test.ts +5 -0
  206. package/src/__tests__/tool-preview-lifecycle.test.ts +32 -29
  207. package/src/__tests__/tool-result-metadata-plumbing.test.ts +5 -5
  208. package/src/__tests__/tool-side-effects-slack-dm.test.ts +1 -0
  209. package/src/__tests__/tool-start-timestamp.test.ts +4 -4
  210. package/src/__tests__/trusted-contact-lifecycle-notifications.test.ts +9 -22
  211. package/src/__tests__/ui-choice-copy-surfaces.test.ts +13 -13
  212. package/src/__tests__/ui-work-result-surface.test.ts +3 -3
  213. package/src/__tests__/voice-scoped-grant-consumer.test.ts +6 -6
  214. package/src/__tests__/voice-session-bridge.test.ts +44 -44
  215. package/src/__tests__/workspace-migration-134-image-generation-mode-to-provider.test.ts +284 -0
  216. package/src/__tests__/workspace-policy.test.ts +482 -2
  217. package/src/acp/__tests__/client-handler.test.ts +3 -3
  218. package/src/acp/__tests__/session-manager-persistence.test.ts +10 -10
  219. package/src/acp/__tests__/session-manager-resume.test.ts +7 -7
  220. package/src/acp/client-handler.ts +3 -3
  221. package/src/acp/session-manager.ts +8 -8
  222. package/src/api/events/subagent-event.ts +2 -2
  223. package/src/api/responses/memory-v2-activation-log.ts +2 -2
  224. package/src/api/responses/subagent-detail.ts +13 -0
  225. package/src/approvals/AGENTS.md +2 -0
  226. package/src/approvals/guardian-request-resolvers.ts +118 -24
  227. package/src/apps/app-store.ts +95 -4
  228. package/src/calls/__tests__/voice-control-protocol.test.ts +57 -0
  229. package/src/calls/__tests__/voice-session-bridge.test.ts +229 -7
  230. package/src/calls/__tests__/voice-triage-escalate.test.ts +3 -4
  231. package/src/calls/call-controller.ts +27 -27
  232. package/src/calls/call-conversation-messages.ts +58 -18
  233. package/src/calls/voice-control-protocol.ts +56 -0
  234. package/src/calls/voice-session-bridge.ts +178 -65
  235. package/src/calls/voice-triage-escalate.ts +2 -3
  236. package/src/channels/config.ts +8 -0
  237. package/src/channels/types.ts +1 -0
  238. package/src/cli/commands/config.ts +49 -13
  239. package/src/cli/commands/memory/index.help.ts +4 -2
  240. package/src/cli/commands/memory/memory-retrospective.ts +5 -0
  241. package/src/cli/commands/webhooks.help.ts +9 -4
  242. package/src/cli/lib/bundled-marketplace.json +12 -0
  243. package/src/cli.ts +2 -109
  244. package/src/config/__tests__/deployment-context-defaults.test.ts +9 -0
  245. package/src/config/__tests__/substrate-twin-shadowing.test.ts +191 -0
  246. package/src/config/assistant-feature-flags.ts +1 -1
  247. package/src/config/bundled-skills/conversation-groups/SKILL.md +29 -0
  248. package/src/config/bundled-skills/conversation-groups/TOOLS.json +58 -0
  249. package/src/config/bundled-skills/conversation-groups/tools/group-create.ts +12 -0
  250. package/src/config/bundled-skills/conversation-groups/tools/group-list.ts +12 -0
  251. package/src/config/bundled-skills/conversation-groups/tools/move-to-group.ts +12 -0
  252. package/src/config/bundled-skills/image-studio/tools/media-generate-image.ts +13 -7
  253. package/src/config/bundled-skills/schedule/SKILL.md +2 -0
  254. package/src/config/feature-flag-cache.ts +6 -16
  255. package/src/config/feature-flag-registry.json +14 -38
  256. package/src/config/loader.ts +7 -1
  257. package/src/config/memory-tier.ts +15 -10
  258. package/src/config/memory-v3-gate.test.ts +278 -1
  259. package/src/config/memory-v3-gate.ts +88 -26
  260. package/src/config/raw-config-utils.ts +1 -1
  261. package/src/config/schemas/__tests__/live-voice.test.ts +27 -16
  262. package/src/config/schemas/__tests__/memory-v3.test.ts +1 -0
  263. package/src/config/schemas/live-voice.ts +33 -7
  264. package/src/config/schemas/llm.ts +1 -0
  265. package/src/config/schemas/memory-retrospective.ts +13 -0
  266. package/src/config/schemas/memory-substrate.ts +183 -0
  267. package/src/config/schemas/memory-v2.ts +3 -2
  268. package/src/config/schemas/memory-v3.ts +11 -4
  269. package/src/config/schemas/memory.ts +35 -1
  270. package/src/config/schemas/services.ts +10 -2
  271. package/src/config/substrate-twin-shadowing.ts +195 -0
  272. package/src/config/webhook-routing.ts +67 -0
  273. package/src/context/compactor.ts +10 -3
  274. package/src/context/token-estimator.ts +21 -0
  275. package/src/daemon/__tests__/channel-ui-capability.test.ts +85 -0
  276. package/src/daemon/__tests__/conversation-surfaces-launch.test.ts +3 -3
  277. package/src/daemon/__tests__/embedding-reconcile.test.ts +3 -3
  278. package/src/daemon/__tests__/inference-profile-notification.test.ts +3 -6
  279. package/src/daemon/__tests__/native-web-search-metadata.test.ts +5 -5
  280. package/src/daemon/__tests__/web-search-status-text.test.ts +2 -2
  281. package/src/daemon/channel-ui-capability.ts +70 -1
  282. package/src/daemon/conversation-agent-loop-handlers.ts +4 -4
  283. package/src/daemon/conversation-agent-loop.ts +12 -5
  284. package/src/daemon/conversation-evictor.ts +26 -4
  285. package/src/daemon/conversation-launch.ts +11 -14
  286. package/src/daemon/conversation-lineage.ts +76 -0
  287. package/src/daemon/conversation-messaging.ts +14 -14
  288. package/src/daemon/conversation-notifiers.ts +2 -2
  289. package/src/daemon/conversation-process.ts +133 -21
  290. package/src/daemon/conversation-queue-manager.ts +7 -7
  291. package/src/daemon/conversation-runtime-assembly.ts +16 -0
  292. package/src/daemon/conversation-store.ts +11 -3
  293. package/src/daemon/conversation-surfaces.ts +8 -14
  294. package/src/daemon/conversation-tool-setup.ts +13 -7
  295. package/src/daemon/conversation-usage.ts +12 -11
  296. package/src/daemon/conversation.ts +38 -15
  297. package/src/daemon/disk-pressure-guard.ts +5 -12
  298. package/src/daemon/embedding-reconcile.ts +14 -9
  299. package/src/daemon/handlers/config-channels.ts +40 -134
  300. package/src/daemon/handlers/config-model.ts +15 -7
  301. package/src/daemon/handlers/conversations.ts +4 -2
  302. package/src/daemon/handlers/shared.ts +29 -0
  303. package/src/daemon/host-proxy-base.ts +4 -4
  304. package/src/daemon/lifecycle.ts +13 -0
  305. package/src/daemon/message-protocol.ts +8 -144
  306. package/src/daemon/message-types/computer-use.ts +0 -12
  307. package/src/daemon/message-types/conversations.ts +9 -345
  308. package/src/daemon/message-types/host-app-control.ts +0 -9
  309. package/src/daemon/message-types/host-browser.ts +0 -7
  310. package/src/daemon/message-types/host-ui-snapshot.ts +0 -7
  311. package/src/daemon/message-types/messages.ts +0 -48
  312. package/src/daemon/message-types/notifications.ts +0 -7
  313. package/src/daemon/message-types/skills.ts +0 -5
  314. package/src/daemon/message-types/surfaces.ts +0 -9
  315. package/src/daemon/message-types/sync.ts +0 -2
  316. package/src/daemon/process-message.ts +5 -5
  317. package/src/daemon/skill-memory-refresh.ts +5 -5
  318. package/src/daemon/tool-side-effects.ts +32 -16
  319. package/src/daemon/trust-context.ts +1 -1
  320. package/src/daemon/wake-conversation-ops.ts +4 -4
  321. package/src/heartbeat/__tests__/heartbeat-run-store.test.ts +100 -7
  322. package/src/heartbeat/__tests__/heartbeat-service.test.ts +67 -0
  323. package/src/heartbeat/heartbeat-run-store.ts +81 -4
  324. package/src/heartbeat/heartbeat-service.ts +32 -1
  325. package/src/home/__tests__/feed-writer.test.ts +7 -7
  326. package/src/home/__tests__/home-content-refresh.test.ts +3 -0
  327. package/src/home/__tests__/suggested-prompts.test.ts +1 -0
  328. package/src/home/feed-writer.ts +6 -13
  329. package/src/home/home-content-refresh.ts +6 -9
  330. package/src/home/relationship-state-writer.ts +5 -12
  331. package/src/home/suggested-prompts-cache.ts +6 -19
  332. package/src/ipc/__tests__/events-publish-client.test.ts +67 -0
  333. package/src/ipc/events-publish-client.ts +44 -0
  334. package/src/ipc/routes/__tests__/conversation-sync-ipc-routes.test.ts +2 -2
  335. package/src/ipc/routes/__tests__/events-ipc-routes.test.ts +38 -9
  336. package/src/ipc/routes/events-ipc-routes.ts +11 -31
  337. package/src/live-voice/__tests__/front-decision.test.ts +4 -176
  338. package/src/live-voice/__tests__/live-voice-agent-turn.test.ts +276 -68
  339. package/src/live-voice/__tests__/live-voice-continuation-fork-hydration.test.ts +286 -0
  340. package/src/live-voice/__tests__/live-voice-events.test.ts +6 -3
  341. package/src/live-voice/__tests__/live-voice-progress.test.ts +185 -46
  342. package/src/live-voice/__tests__/live-voice-triage-escalate.test.ts +24 -59
  343. package/src/live-voice/__tests__/live-voice-tts-session.test.ts +38 -54
  344. package/src/live-voice/__tests__/live-voice-vad.test.ts +1154 -636
  345. package/src/live-voice/front-decision.ts +5 -155
  346. package/src/live-voice/live-voice-metrics.ts +4 -1
  347. package/src/live-voice/live-voice-session.ts +1288 -439
  348. package/src/live-voice/progress-phrases.ts +17 -0
  349. package/src/live-voice/protocol.ts +15 -0
  350. package/src/media/app-icon-generator.ts +15 -8
  351. package/src/media/avatar-router.ts +9 -5
  352. package/src/media/image-credentials.ts +42 -10
  353. package/src/media/image-service.ts +1 -13
  354. package/src/media/types.ts +26 -3
  355. package/src/notifications/AGENTS.md +2 -0
  356. package/src/notifications/__tests__/broadcaster.test.ts +95 -0
  357. package/src/notifications/adapters/macos.ts +3 -3
  358. package/src/notifications/broadcaster.ts +57 -0
  359. package/src/notifications/copy-composer.ts +0 -15
  360. package/src/notifications/decision-engine.ts +21 -22
  361. package/src/notifications/guardian-question-mode.ts +57 -2
  362. package/src/notifications/home-feed-side-effect.ts +4 -0
  363. package/src/notifications/signal.ts +6 -4
  364. package/src/notifications/trusted-contact-payloads.ts +3 -4
  365. package/src/notifications/vellum-card-affinity.ts +39 -0
  366. package/src/oauth/AGENTS.md +1 -1
  367. package/src/permissions/channel-permission-query.test.ts +69 -0
  368. package/src/permissions/channel-permission-query.ts +73 -1
  369. package/src/permissions/checker.test.ts +298 -15
  370. package/src/permissions/checker.ts +102 -36
  371. package/src/permissions/confirmation-guardian-request.test.ts +2 -2
  372. package/src/permissions/confirmation-guardian-request.ts +2 -2
  373. package/src/permissions/gateway-threshold-reader.test.ts +224 -17
  374. package/src/permissions/gateway-threshold-reader.ts +82 -10
  375. package/src/permissions/ipc-risk-types.ts +8 -0
  376. package/src/permissions/prompter.ts +5 -5
  377. package/src/permissions/question-guardian-request.test.ts +222 -0
  378. package/src/permissions/question-guardian-request.ts +179 -0
  379. package/src/permissions/question-prompter.test.ts +8 -8
  380. package/src/permissions/question-prompter.ts +18 -0
  381. package/src/permissions/secret-prompter.ts +2 -4
  382. package/src/permissions/workspace-policy.ts +269 -34
  383. package/src/persistence/__tests__/lifecycle-quiesce.test.ts +82 -0
  384. package/src/persistence/__tests__/message-content-file.test.ts +58 -3
  385. package/src/persistence/conversation-crud.ts +93 -0
  386. package/src/persistence/conversation-key-store.ts +63 -0
  387. package/src/persistence/conversation-parent.ts +27 -0
  388. package/src/persistence/db-async-query.ts +1 -1
  389. package/src/persistence/db-singleton.ts +14 -27
  390. package/src/persistence/delivery-crud.ts +45 -0
  391. package/src/persistence/embeddings/embedding-backend.ts +2 -1
  392. package/src/persistence/embeddings/embedding-identity.ts +7 -3
  393. package/src/persistence/job-utils.ts +32 -27
  394. package/src/persistence/jobs-store.ts +92 -3
  395. package/src/persistence/lifecycle-quiesce.ts +80 -0
  396. package/src/persistence/llm-usage-store.ts +45 -8
  397. package/src/persistence/message-content-file.ts +4 -4
  398. package/src/persistence/migrations/336-move-memory-v2-activation-logs-to-memory-db.ts +1 -1
  399. package/src/persistence/migrations/351-schedule-skill-script-handoff.ts +39 -0
  400. package/src/persistence/migrations/352-drop-schedule-skill-script-handoff.test.ts +83 -0
  401. package/src/persistence/migrations/352-drop-schedule-skill-script-handoff.ts +36 -0
  402. package/src/persistence/migrations/353-add-llm-usage-conversation-type.test.ts +110 -0
  403. package/src/persistence/migrations/353-add-llm-usage-conversation-type.ts +49 -0
  404. package/src/persistence/migrations/354-backfill-app-conversation-lineage.ts +41 -0
  405. package/src/persistence/schema/infrastructure.ts +11 -0
  406. package/src/persistence/steps.ts +9 -1
  407. package/src/plugin-api/__tests__/publish-event-forwarding.test.ts +113 -0
  408. package/src/plugin-api/__tests__/publish-event.test.ts +57 -0
  409. package/src/plugin-api/conversation-turn.ts +4 -4
  410. package/src/plugin-api/event-hub-facade.ts +15 -6
  411. package/src/plugin-api/index.ts +10 -4
  412. package/src/plugin-api/publish-event.ts +36 -0
  413. package/src/plugins/AGENTS.md +2 -0
  414. package/src/plugins/defaults/compaction/window-manager.ts +9 -0
  415. package/src/plugins/defaults/index.ts +9 -13
  416. package/src/plugins/defaults/memory/AGENTS.md +775 -0
  417. package/src/plugins/defaults/memory/__tests__/capability-seed-embed-gate.test.ts +186 -0
  418. package/src/plugins/defaults/memory/__tests__/fixtures/memory-v2-activation-fixtures.ts +1 -1
  419. package/src/plugins/defaults/memory/__tests__/indexer-tier-dispatch.test.ts +129 -0
  420. package/src/plugins/defaults/memory/__tests__/jobs-worker-quiesce-gate.test.ts +91 -0
  421. package/src/plugins/defaults/memory/__tests__/jobs-worker-v1-graph-substrate-noop.test.ts +342 -0
  422. package/src/plugins/defaults/memory/__tests__/jobs-worker-v2-graph-trigger-embed.test.ts +9 -1
  423. package/src/plugins/defaults/memory/__tests__/jobs-worker-v2-schedule.test.ts +36 -1
  424. package/src/plugins/defaults/memory/__tests__/jobs-worker-v2-sweep-defer.test.ts +9 -1
  425. package/src/plugins/defaults/memory/__tests__/memory-log-stores-degraded.test.ts +2 -2
  426. package/src/plugins/defaults/memory/__tests__/memory-retrospective-job.test.ts +44 -10
  427. package/src/plugins/defaults/memory/__tests__/memory-retrospective-sweep.test.ts +151 -10
  428. package/src/plugins/defaults/memory/__tests__/memory-tier-boundary-guard.test.ts +1155 -0
  429. package/src/plugins/defaults/memory/__tests__/memory-v2-activation-log-store.test.ts +1 -1
  430. package/src/plugins/defaults/memory/__tests__/memory-v2-concept-frequency.test.ts +3 -3
  431. package/src/plugins/defaults/memory/__tests__/tools-delete-memory-page.test.ts +1 -1
  432. package/src/plugins/defaults/memory/context-search/sources/memory-v2.ts +71 -35
  433. package/src/plugins/defaults/memory/context-search/sources/memory.ts +5 -1
  434. package/src/plugins/defaults/memory/fork-conversation-memory.ts +4 -4
  435. package/src/plugins/defaults/memory/graph/__tests__/conversation-graph-memory-v2-routing.test.ts +80 -10
  436. package/src/plugins/defaults/memory/graph/__tests__/handle-remember-v2.test.ts +1 -1
  437. package/src/plugins/defaults/memory/graph/capability-seed.ts +24 -10
  438. package/src/plugins/defaults/memory/graph/conversation-graph-memory.ts +123 -49
  439. package/src/plugins/defaults/memory/graph/graph-search.ts +6 -118
  440. package/src/plugins/defaults/memory/graph/in-context-tracker.test.ts +173 -0
  441. package/src/plugins/defaults/memory/graph/in-context-tracker.ts +109 -0
  442. package/src/plugins/defaults/memory/graph/store.ts +1 -0
  443. package/src/plugins/defaults/memory/graph/tool-handlers.test.ts +1 -1
  444. package/src/plugins/defaults/memory/graph/tool-handlers.ts +5 -2
  445. package/src/plugins/defaults/memory/graph-topology/__tests__/build-memory-graph.test.ts +1 -1
  446. package/src/plugins/defaults/memory/graph-topology/build-memory-graph.ts +6 -9
  447. package/src/plugins/defaults/memory/hooks/__tests__/user-prompt-submit.test.ts +30 -16
  448. package/src/plugins/defaults/memory/hooks/user-prompt-submit.ts +18 -14
  449. package/src/plugins/defaults/memory/indexer.ts +146 -89
  450. package/src/plugins/defaults/memory/injectors.ts +86 -41
  451. package/src/plugins/defaults/memory/job-handlers.ts +130 -39
  452. package/src/plugins/defaults/memory/jobs/__tests__/embed-concept-page.test.ts +2 -2
  453. package/src/plugins/defaults/memory/jobs/embed-concept-page.ts +22 -10
  454. package/src/plugins/defaults/memory/jobs-worker.ts +279 -208
  455. package/src/plugins/defaults/memory/memory-retrospective-enqueue.ts +4 -2
  456. package/src/plugins/defaults/memory/memory-retrospective-job.ts +40 -3
  457. package/src/plugins/defaults/memory/memory-retrospective-sweep.ts +99 -11
  458. package/src/plugins/defaults/memory/src/__tests__/memory-v2-routes.test.ts +5 -3
  459. package/src/plugins/defaults/memory/src/__tests__/memory-v2-simulate-route.test.ts +3 -4
  460. package/src/plugins/defaults/memory/src/memory-graph-routes.ts +2 -1
  461. package/src/plugins/defaults/memory/src/memory-item-routes.test.ts +7 -5
  462. package/src/plugins/defaults/memory/src/memory-item-routes.ts +51 -19
  463. package/src/plugins/defaults/memory/src/memory-v2-routes.ts +31 -20
  464. package/src/plugins/defaults/memory/startup.ts +58 -21
  465. package/src/plugins/defaults/memory/substrate/__tests__/boot-maintenance.test.ts +335 -0
  466. package/src/plugins/defaults/memory/{v3/substrate → substrate}/__tests__/cli-command-store.test.ts +14 -8
  467. package/src/plugins/defaults/memory/{v3/substrate → substrate}/__tests__/consolidation-job.test.ts +51 -21
  468. package/src/plugins/defaults/memory/{v3/substrate → substrate}/__tests__/edge-index.test.ts +1 -1
  469. package/src/plugins/defaults/memory/{v3/substrate → substrate}/__tests__/frontmatter-sweep.test.ts +3 -3
  470. package/src/plugins/defaults/memory/{v3/substrate → substrate}/__tests__/page-index.test.ts +1 -1
  471. package/src/plugins/defaults/memory/{v3/substrate → substrate}/__tests__/page-store.test.ts +1 -1
  472. package/src/plugins/defaults/memory/{v3/substrate → substrate}/__tests__/prompts-consolidation.test.ts +2 -2
  473. package/src/plugins/defaults/memory/{v3/substrate → substrate}/__tests__/qdrant.test.ts +23 -14
  474. package/src/plugins/defaults/memory/substrate/__tests__/reembed-job.test.ts +262 -0
  475. package/src/plugins/defaults/memory/{v3/substrate → substrate}/__tests__/sim.test.ts +9 -12
  476. package/src/plugins/defaults/memory/{v3/substrate → substrate}/__tests__/skill-content.test.ts +2 -2
  477. package/src/plugins/defaults/memory/{v3/substrate → substrate}/__tests__/skill-store.test.ts +9 -9
  478. package/src/plugins/defaults/memory/{v3/substrate → substrate}/__tests__/sparse-bm25.test.ts +12 -5
  479. package/src/plugins/defaults/memory/substrate/__tests__/spread.test.ts +276 -0
  480. package/src/plugins/defaults/memory/{v3/substrate → substrate}/__tests__/static-context.test.ts +17 -8
  481. package/src/plugins/defaults/memory/{v3/substrate → substrate}/__tests__/sweep-job.test.ts +9 -9
  482. package/src/plugins/defaults/memory/{v3/substrate/memory-v2-startup.ts → substrate/boot-maintenance.ts} +43 -24
  483. package/src/plugins/defaults/memory/{v3/substrate → substrate}/cli-command-store.ts +13 -8
  484. package/src/plugins/defaults/memory/{v3/substrate → substrate}/consolidation-job.ts +51 -27
  485. package/src/plugins/defaults/memory/{v3/substrate → substrate}/constants.ts +1 -0
  486. package/src/plugins/defaults/memory/{v3/substrate → substrate}/edge-index.ts +28 -9
  487. package/src/plugins/defaults/memory/{v3/substrate → substrate}/frontmatter-sweep.ts +14 -7
  488. package/src/plugins/defaults/memory/{v3/substrate → substrate}/injected-block-slugs.ts +9 -3
  489. package/src/plugins/defaults/memory/{v3/substrate → substrate}/page-index.ts +29 -10
  490. package/src/plugins/defaults/memory/{v3/substrate → substrate}/page-store.ts +35 -12
  491. package/src/plugins/defaults/memory/{v3/substrate → substrate}/prompts/consolidation.ts +14 -8
  492. package/src/plugins/defaults/memory/{v3/substrate → substrate}/prompts/sweep.ts +4 -1
  493. package/src/plugins/defaults/memory/{v3/substrate → substrate}/qdrant.ts +96 -36
  494. package/src/plugins/defaults/memory/substrate/reembed-job.ts +54 -0
  495. package/src/plugins/defaults/memory/{v3/substrate → substrate}/sim.ts +26 -15
  496. package/src/plugins/defaults/memory/{v3/substrate → substrate}/skill-content.ts +1 -1
  497. package/src/plugins/defaults/memory/{v3/substrate → substrate}/skill-store.ts +13 -8
  498. package/src/plugins/defaults/memory/{v3/substrate → substrate}/sparse-bm25.ts +27 -10
  499. package/src/plugins/defaults/memory/substrate/spread.ts +165 -0
  500. package/src/plugins/defaults/memory/{v3/substrate → substrate}/static-context.ts +12 -7
  501. package/src/plugins/defaults/memory/{v3/substrate → substrate}/sweep-job.ts +20 -15
  502. package/src/plugins/defaults/memory/substrate/tuning.ts +93 -0
  503. package/src/plugins/defaults/memory/{v3/substrate → substrate}/types.ts +7 -4
  504. package/src/plugins/defaults/memory/tools.test.ts +1 -1
  505. package/src/plugins/defaults/memory/tools.ts +1 -1
  506. package/src/plugins/defaults/memory/v1/README.md +5 -0
  507. package/src/plugins/defaults/memory/{__tests__ → v1/__tests__}/filing-jobs.test.ts +4 -4
  508. package/src/plugins/defaults/memory/{filing-jobs.ts → v1/filing-jobs.ts} +3 -3
  509. package/src/plugins/defaults/memory/{graph → v1/graph}/bootstrap.test.ts +68 -6
  510. package/src/plugins/defaults/memory/{graph → v1/graph}/bootstrap.ts +40 -21
  511. package/src/plugins/defaults/memory/{graph → v1/graph}/consolidation.ts +14 -14
  512. package/src/plugins/defaults/memory/{graph → v1/graph}/decay.test.ts +1 -1
  513. package/src/plugins/defaults/memory/{graph → v1/graph}/decay.ts +3 -3
  514. package/src/plugins/defaults/memory/{graph → v1/graph}/extraction-job.ts +5 -5
  515. package/src/plugins/defaults/memory/{graph → v1/graph}/extraction.test.ts +1 -1
  516. package/src/plugins/defaults/memory/{graph → v1/graph}/extraction.ts +20 -14
  517. package/src/plugins/defaults/memory/{graph → v1/graph}/graph-search.test.ts +3 -3
  518. package/src/plugins/defaults/memory/v1/graph/graph-search.ts +123 -0
  519. package/src/plugins/defaults/memory/{graph → v1/graph}/injection.test.ts +1 -118
  520. package/src/plugins/defaults/memory/{graph → v1/graph}/injection.ts +9 -111
  521. package/src/plugins/defaults/memory/{graph → v1/graph}/narrative.ts +6 -6
  522. package/src/plugins/defaults/memory/{graph → v1/graph}/pattern-scan.ts +5 -5
  523. package/src/plugins/defaults/memory/{graph → v1/graph}/retriever.test.ts +135 -42
  524. package/src/plugins/defaults/memory/{graph → v1/graph}/retriever.ts +40 -22
  525. package/src/plugins/defaults/memory/{graph → v1/graph}/scoring.test.ts +1 -1
  526. package/src/plugins/defaults/memory/{graph → v1/graph}/scoring.ts +1 -1
  527. package/src/plugins/defaults/memory/{graph → v1/graph}/serendipity.ts +1 -1
  528. package/src/plugins/defaults/memory/{graph → v1/graph}/triggers.test.ts +1 -1
  529. package/src/plugins/defaults/memory/{graph → v1/graph}/triggers.ts +1 -1
  530. package/src/plugins/defaults/memory/{identity-context.ts → v1/identity-context.ts} +4 -4
  531. package/src/plugins/defaults/memory/{job-handlers → v1/job-handlers}/backfill.ts +6 -6
  532. package/src/plugins/defaults/memory/{job-handlers → v1/job-handlers}/embedding.test.ts +6 -6
  533. package/src/plugins/defaults/memory/{job-handlers → v1/job-handlers}/embedding.ts +6 -6
  534. package/src/plugins/defaults/memory/{job-handlers → v1/job-handlers}/index-maintenance.ts +8 -8
  535. package/src/plugins/defaults/memory/{jobs → v1/jobs}/embed-pkb-file.test.ts +7 -7
  536. package/src/plugins/defaults/memory/{jobs → v1/jobs}/embed-pkb-file.ts +5 -5
  537. package/src/plugins/defaults/memory/{pkb → v1/pkb}/autoinject.ts +1 -1
  538. package/src/plugins/defaults/memory/{pkb → v1/pkb}/context.ts +2 -2
  539. package/src/plugins/defaults/memory/{pkb → v1/pkb}/pkb-index.test.ts +3 -3
  540. package/src/plugins/defaults/memory/{pkb → v1/pkb}/pkb-index.ts +2 -2
  541. package/src/plugins/defaults/memory/{pkb → v1/pkb}/pkb-reconcile.test.ts +3 -3
  542. package/src/plugins/defaults/memory/{pkb → v1/pkb}/pkb-reconcile.ts +2 -2
  543. package/src/plugins/defaults/memory/{pkb → v1/pkb}/pkb-search.test.ts +3 -3
  544. package/src/plugins/defaults/memory/{pkb → v1/pkb}/pkb-search.ts +6 -6
  545. package/src/plugins/defaults/memory/{pkb → v1/pkb}/types.ts +3 -5
  546. package/src/plugins/defaults/memory/{pkb-schedule.ts → v1/pkb-schedule.ts} +2 -2
  547. package/src/plugins/defaults/memory/{search/semantic.ts → v1/semantic-search.ts} +1 -1
  548. package/src/plugins/defaults/memory/v2/__tests__/activation-store.test.ts +1 -1
  549. package/src/plugins/defaults/memory/v2/__tests__/activation.test.ts +11 -274
  550. package/src/plugins/defaults/memory/v2/__tests__/backfill-jobs.test.ts +9 -131
  551. package/src/plugins/defaults/memory/v2/__tests__/harness-compare.test.ts +1 -1
  552. package/src/plugins/defaults/memory/v2/__tests__/harness-oracle.test.ts +1 -1
  553. package/src/plugins/defaults/memory/v2/__tests__/harness-replay-input.test.ts +1 -1
  554. package/src/plugins/defaults/memory/v2/__tests__/injection.test.ts +14 -10
  555. package/src/plugins/defaults/memory/v2/__tests__/reranker.test.ts +7 -5
  556. package/src/plugins/defaults/memory/v2/__tests__/router.test.ts +12 -6
  557. package/src/plugins/defaults/memory/{memory-v2-activation-log-store.ts → v2/activation-log-store.ts} +2 -2
  558. package/src/plugins/defaults/memory/v2/activation-store.ts +22 -8
  559. package/src/plugins/defaults/memory/v2/activation.ts +30 -163
  560. package/src/plugins/defaults/memory/v2/backfill-jobs.ts +7 -54
  561. package/src/plugins/defaults/memory/{memory-v2-concept-frequency.ts → v2/concept-frequency.ts} +3 -3
  562. package/src/plugins/defaults/memory/v2/harness/oracle.ts +1 -1
  563. package/src/plugins/defaults/memory/v2/harness/replay-input.ts +2 -2
  564. package/src/plugins/defaults/memory/v2/harness/retriever.ts +1 -1
  565. package/src/plugins/defaults/memory/v2/injection.ts +36 -26
  566. package/src/plugins/defaults/memory/v2/migration.ts +2 -2
  567. package/src/plugins/defaults/memory/{rerank-local.ts → v2/rerank-local.ts} +44 -18
  568. package/src/plugins/defaults/memory/v2/reranker.ts +29 -11
  569. package/src/plugins/defaults/memory/v2/router.ts +38 -15
  570. package/src/plugins/defaults/memory/v3/__tests__/candidate-match.test.ts +5 -3
  571. package/src/plugins/defaults/memory/v3/__tests__/carry-integration.test.ts +21 -8
  572. package/src/plugins/defaults/memory/v3/__tests__/edge.test.ts +1 -1
  573. package/src/plugins/defaults/memory/v3/__tests__/live-integration.test.ts +1 -1
  574. package/src/plugins/defaults/memory/v3/__tests__/maintain-job.test.ts +4 -1
  575. package/src/plugins/defaults/memory/v3/__tests__/orchestrate.test.ts +181 -3
  576. package/src/plugins/defaults/memory/v3/__tests__/selection-log-store.test.ts +3 -0
  577. package/src/plugins/defaults/memory/v3/__tests__/shadow-integration.test.ts +14 -5
  578. package/src/plugins/defaults/memory/v3/__tests__/shadow-plugin.test.ts +40 -50
  579. package/src/plugins/defaults/memory/v3/__tests__/tuning-profile.test.ts +1 -0
  580. package/src/plugins/defaults/memory/v3/candidate-match.ts +2 -2
  581. package/src/plugins/defaults/memory/v3/capabilities.ts +6 -4
  582. package/src/plugins/defaults/memory/v3/card.ts +25 -9
  583. package/src/plugins/defaults/memory/v3/edge.ts +52 -18
  584. package/src/plugins/defaults/memory/v3/gate.ts +4 -4
  585. package/src/plugins/defaults/memory/v3/injector.ts +10 -3
  586. package/src/plugins/defaults/memory/v3/maintain-job.ts +3 -3
  587. package/src/plugins/defaults/memory/v3/orchestrate.ts +100 -18
  588. package/src/plugins/defaults/memory/v3/page-content.ts +26 -10
  589. package/src/plugins/defaults/memory/v3/prune.ts +40 -16
  590. package/src/plugins/defaults/memory/v3/selection-log-store.ts +34 -12
  591. package/src/plugins/defaults/memory/v3/shadow-plugin.ts +9 -13
  592. package/src/plugins/defaults/memory/v3/span-query.test.ts +86 -0
  593. package/src/plugins/defaults/memory/v3/span-query.ts +71 -0
  594. package/src/plugins/defaults/memory/v3/tuning-profile.ts +3 -0
  595. package/src/plugins/defaults/memory/v3/types.ts +4 -1
  596. package/src/plugins/defaults/memory/v3-eval/eval-packets.ts +2 -2
  597. package/src/plugins/defaults/memory/validation.ts +1 -1
  598. package/src/plugins/defaults/memory/worker.ts +2 -1
  599. package/src/plugins/defaults/platform-hosted/__tests__/reengage.test.ts +104 -12
  600. package/src/plugins/defaults/platform-hosted/routes/reengage.ts +104 -12
  601. package/src/plugins/types.ts +2 -2
  602. package/src/prompts/sections.ts +4 -16
  603. package/src/providers/__tests__/registry-native-web-search.test.ts +47 -2
  604. package/src/providers/anthropic/client.ts +15 -6
  605. package/src/providers/content-block-schema.ts +26 -0
  606. package/src/providers/inference/__tests__/connections-credential-normalize.test.ts +87 -0
  607. package/src/providers/inference/adapter-factory.ts +6 -0
  608. package/src/providers/inference/connections.ts +30 -14
  609. package/src/providers/model-catalog.ts +77 -0
  610. package/src/providers/openai/__tests__/chat-completions-input-audio.test.ts +260 -0
  611. package/src/providers/openai/chat-completions-provider.ts +65 -17
  612. package/src/providers/openai/input-audio.ts +76 -0
  613. package/src/providers/openrouter/client.ts +0 -2
  614. package/src/providers/platform-proxy/constants.ts +4 -0
  615. package/src/providers/poolside/client.ts +42 -0
  616. package/src/providers/registry.ts +40 -8
  617. package/src/providers/retry.ts +2 -0
  618. package/src/providers/types.ts +39 -1
  619. package/src/providers/vercel-ai-gateway/client.ts +0 -2
  620. package/src/runtime/AGENTS.md +7 -5
  621. package/src/runtime/__tests__/question-request-guardian-bridge.test.ts +173 -0
  622. package/src/runtime/__tests__/question-resolution.test.ts +111 -0
  623. package/src/runtime/access-request-helper.ts +7 -15
  624. package/src/runtime/assistant-event-hub.ts +43 -31
  625. package/src/runtime/assistant-event-publish-options.ts +31 -0
  626. package/src/runtime/assistant-event.ts +19 -30
  627. package/src/runtime/assistant-stream-state.ts +4 -4
  628. package/src/runtime/channel-approvals.ts +0 -25
  629. package/src/runtime/channel-readiness-service.ts +99 -40
  630. package/src/runtime/channel-retry-sweep.ts +38 -15
  631. package/src/runtime/confirmation-request-guardian-bridge.ts +4 -0
  632. package/src/runtime/guardian-reply-router.ts +108 -0
  633. package/src/runtime/http-server.ts +8 -0
  634. package/src/runtime/http-types.ts +2 -2
  635. package/src/runtime/process-role.ts +42 -0
  636. package/src/runtime/question-request-guardian-bridge.ts +184 -0
  637. package/src/runtime/question-resolution.ts +153 -0
  638. package/src/runtime/routes/__tests__/bookmark-routes.test.ts +6 -2
  639. package/src/runtime/routes/__tests__/conversation-query-routes.test.ts +1 -1
  640. package/src/runtime/routes/__tests__/subagents-routes.test.ts +250 -0
  641. package/src/runtime/routes/__tests__/webhook-routes.test.ts +201 -0
  642. package/src/runtime/routes/acp-routes.ts +2 -2
  643. package/src/runtime/routes/bookmark-routes.ts +3 -15
  644. package/src/runtime/routes/canned-message-complete.ts +2 -2
  645. package/src/runtime/routes/consolidation-routes.ts +8 -2
  646. package/src/runtime/routes/conversation-list-routes.ts +3 -19
  647. package/src/runtime/routes/conversation-management-routes.ts +1 -5
  648. package/src/runtime/routes/conversation-query-routes.ts +52 -8
  649. package/src/runtime/routes/conversation-routes.ts +36 -22
  650. package/src/runtime/routes/credential-request-routes.ts +0 -1
  651. package/src/runtime/routes/filing-routes.ts +7 -7
  652. package/src/runtime/routes/global-search-routes.ts +1 -1
  653. package/src/runtime/routes/guardian-approval-prompt.ts +2 -2
  654. package/src/runtime/routes/image-generation-routes.ts +12 -9
  655. package/src/runtime/routes/inbound-message-handler.ts +17 -0
  656. package/src/runtime/routes/inbound-stages/acl-enforcement.test.ts +50 -0
  657. package/src/runtime/routes/inbound-stages/acl-enforcement.ts +19 -0
  658. package/src/runtime/routes/inbound-stages/background-dispatch.ts +4 -4
  659. package/src/runtime/routes/inbound-stages/inbound-content-prep.test.ts +129 -0
  660. package/src/runtime/routes/inbound-stages/inbound-content-prep.ts +141 -9
  661. package/src/runtime/routes/index.ts +2 -0
  662. package/src/runtime/routes/lifecycle-routes.ts +199 -0
  663. package/src/runtime/routes/platform-routes.ts +3 -8
  664. package/src/runtime/routes/playground/__tests__/inject-failures.test.ts +7 -7
  665. package/src/runtime/routes/playground/__tests__/reset-circuit.test.ts +5 -5
  666. package/src/runtime/routes/question-routes.ts +34 -87
  667. package/src/runtime/routes/secret-routes.ts +11 -1
  668. package/src/runtime/routes/settings-routes.ts +8 -18
  669. package/src/runtime/routes/subagents-routes.ts +35 -8
  670. package/src/runtime/routes/upgrade-broadcast-routes.ts +4 -5
  671. package/src/runtime/routes/webhook-routes.ts +89 -30
  672. package/src/runtime/routes/workspace-routes.test.ts +7 -4
  673. package/src/runtime/slack-reply-session.test.ts +12 -12
  674. package/src/runtime/slack-reply-session.ts +17 -17
  675. package/src/runtime/sync/sync-publisher.test.ts +7 -5
  676. package/src/runtime/tool-grant-request-helper.ts +4 -0
  677. package/src/schedule/schedule-store.ts +70 -0
  678. package/src/schedule/scheduler.ts +27 -0
  679. package/src/security/AGENTS.md +1 -1
  680. package/src/security/credential-key.ts +17 -0
  681. package/src/security/secret-ingress.ts +14 -105
  682. package/src/security/secret-patterns.ts +8 -139
  683. package/src/security/secret-scanner.ts +8 -3
  684. package/src/security/store-path-override.ts +6 -16
  685. package/src/sequence/store.ts +8 -0
  686. package/src/signals/emit-event.ts +5 -10
  687. package/src/signals/event-stream.ts +20 -10
  688. package/src/subagent/manager.ts +76 -25
  689. package/src/subagent/notify.ts +8 -0
  690. package/src/subagent/types.ts +13 -3
  691. package/src/telegram/__tests__/webhook-health.test.ts +442 -0
  692. package/src/telegram/webhook-health.ts +478 -0
  693. package/src/telemetry/AGENTS.md +6 -0
  694. package/src/telemetry/memory-corpus-size.test.ts +129 -0
  695. package/src/telemetry/memory-corpus-size.ts +184 -0
  696. package/src/telemetry/memory-tier-reporter.test.ts +67 -2
  697. package/src/telemetry/memory-tier-reporter.ts +30 -3
  698. package/src/tools/__tests__/conversation-group-tool-input-schemas.test.ts +61 -0
  699. package/src/tools/__tests__/document-tool-input-schemas.test.ts +103 -0
  700. package/src/tools/__tests__/followup-call-acp-tool-input-schemas.test.ts +125 -0
  701. package/src/tools/__tests__/schedule-tool-input-schemas.test.ts +83 -0
  702. package/src/tools/__tests__/subagent-workflow-tool-input-schemas.test.ts +116 -0
  703. package/src/tools/__tests__/tool-input-schemas.test.ts +192 -0
  704. package/src/tools/__tests__/tool-schema-drift-harness.ts +142 -0
  705. package/src/tools/acp/abort.ts +21 -1
  706. package/src/tools/acp/context.ts +5 -5
  707. package/src/tools/acp/spawn.test.ts +15 -5
  708. package/src/tools/acp/spawn.ts +26 -3
  709. package/src/tools/acp/status.ts +20 -1
  710. package/src/tools/acp/steer.test.ts +20 -0
  711. package/src/tools/acp/steer.ts +23 -2
  712. package/src/tools/apps/resolve-app-id.ts +15 -3
  713. package/src/tools/ask-question/ask-question-tool.test.ts +65 -0
  714. package/src/tools/ask-question/ask-question-tool.ts +68 -92
  715. package/src/tools/browser/browser-screencast.ts +6 -6
  716. package/src/tools/calls/call-end.ts +24 -3
  717. package/src/tools/calls/call-start.ts +35 -11
  718. package/src/tools/calls/call-status.ts +20 -1
  719. package/src/tools/conversation-groups/group_create.ts +63 -0
  720. package/src/tools/conversation-groups/group_list.ts +20 -0
  721. package/src/tools/conversation-groups/group_shared.ts +52 -0
  722. package/src/tools/conversation-groups/move_to_group.ts +106 -0
  723. package/src/tools/document/document-comment-tool.test.ts +49 -0
  724. package/src/tools/document/document-comment-tool.ts +45 -6
  725. package/src/tools/document/document-tool.ts +142 -24
  726. package/src/tools/executor.ts +27 -13
  727. package/src/tools/filesystem/edit.ts +62 -60
  728. package/src/tools/filesystem/list.ts +36 -29
  729. package/src/tools/filesystem/read.ts +56 -39
  730. package/src/tools/filesystem/write.ts +44 -38
  731. package/src/tools/followups/followup_create.ts +41 -12
  732. package/src/tools/followups/followup_list.ts +34 -6
  733. package/src/tools/followups/followup_resolve.ts +26 -4
  734. package/src/tools/host-filesystem/edit.ts +50 -60
  735. package/src/tools/host-filesystem/read.ts +45 -39
  736. package/src/tools/host-filesystem/write.ts +31 -36
  737. package/src/tools/host-terminal/host-shell.ts +76 -62
  738. package/src/tools/policy-context.ts +27 -10
  739. package/src/tools/schedule/create.ts +76 -33
  740. package/src/tools/schedule/delete.ts +21 -2
  741. package/src/tools/schedule/list.ts +25 -3
  742. package/src/tools/schedule/update.ts +105 -48
  743. package/src/tools/shared/filesystem/path-policy.ts +246 -40
  744. package/src/tools/shared/zod-tool-schema.ts +117 -0
  745. package/src/tools/subagent/abort.ts +12 -4
  746. package/src/tools/subagent/consult-deadline.ts +9 -3
  747. package/src/tools/subagent/message.ts +21 -5
  748. package/src/tools/subagent/notify-parent.ts +44 -23
  749. package/src/tools/subagent/read.ts +15 -4
  750. package/src/tools/subagent/resolve.ts +26 -4
  751. package/src/tools/subagent/spawn.ts +37 -13
  752. package/src/tools/subagent/status.ts +12 -4
  753. package/src/tools/system/request-permission.ts +35 -26
  754. package/src/tools/terminal/shell.ts +68 -55
  755. package/src/tools/tool-approval-handler.ts +327 -53
  756. package/src/tools/tool-input-schemas.ts +85 -0
  757. package/src/tools/tool-types.ts +7 -0
  758. package/src/tools/types.ts +8 -0
  759. package/src/tools/workflows/manage-workflows.ts +30 -2
  760. package/src/tools/workflows/run-workflow.test.ts +54 -2
  761. package/src/tools/workflows/run-workflow.ts +32 -4
  762. package/src/util/fs-symlinks.ts +30 -0
  763. package/src/util/log-redact.ts +7 -3
  764. package/src/util/platform.ts +15 -0
  765. package/src/vellum-assistant-namespace.d.ts +80 -0
  766. package/src/watcher/watcher-store.ts +8 -0
  767. package/src/workflows/leaf-runner.test.ts +104 -2
  768. package/src/workflows/leaf-runner.ts +31 -6
  769. package/src/workspace/migrations/070-memory-v2-summary-schema-rebuild.ts +2 -2
  770. package/src/workspace/migrations/134-image-generation-mode-to-provider.ts +128 -0
  771. package/src/workspace/migrations/135-copy-substrate-tunables.ts +248 -0
  772. package/src/workspace/migrations/__tests__/135-copy-substrate-tunables.test.ts +446 -0
  773. package/src/workspace/migrations/__tests__/backfill-v3-leaves.test.ts +2 -2
  774. package/src/workspace/migrations/registry.ts +4 -0
  775. package/tsconfig.plugin-api.json +1 -1
  776. package/src/__tests__/memory-retrieval-budget.test.ts +0 -49
  777. package/src/__tests__/secret-patterns.test.ts +0 -27
  778. package/src/config/__tests__/proc-to-skills.test.ts +0 -21
  779. package/src/config/memory-tier.test.ts +0 -44
  780. package/src/daemon/message-types/acp.ts +0 -20
  781. package/src/daemon/message-types/apps.ts +0 -11
  782. package/src/daemon/message-types/background-tools.ts +0 -14
  783. package/src/daemon/message-types/bookmarks.ts +0 -13
  784. package/src/daemon/message-types/contacts.ts +0 -13
  785. package/src/daemon/message-types/document-comments.ts +0 -14
  786. package/src/daemon/message-types/documents.ts +0 -13
  787. package/src/daemon/message-types/home.ts +0 -15
  788. package/src/daemon/message-types/host-bash.ts +0 -12
  789. package/src/daemon/message-types/host-cu.ts +0 -10
  790. package/src/daemon/message-types/host-file.ts +0 -12
  791. package/src/daemon/message-types/host-transfer.ts +0 -12
  792. package/src/daemon/message-types/integrations.ts +0 -90
  793. package/src/daemon/message-types/memory.ts +0 -10
  794. package/src/daemon/message-types/schedules.ts +0 -14
  795. package/src/daemon/message-types/settings.ts +0 -17
  796. package/src/daemon/message-types/subagents.ts +0 -63
  797. package/src/daemon/message-types/upgrades.ts +0 -14
  798. package/src/daemon/message-types/workflows.ts +0 -25
  799. package/src/daemon/message-types/workspace.ts +0 -137
  800. package/src/live-voice/ack-phrases.ts +0 -58
  801. package/src/plugins/defaults/memory/retrieval-budget.ts +0 -29
  802. package/src/plugins/defaults/memory/v3/__tests__/gate-flag.test.ts +0 -69
  803. package/src/plugins/defaults/memory/v3/gate-flag.ts +0 -20
  804. package/src/plugins/defaults/memory/v3/substrate/__tests__/memory-v2-startup.test.ts +0 -86
  805. package/src/plugins/defaults/memory/v3/substrate/memory-v2-startup.test.ts +0 -205
  806. /package/src/plugins/defaults/memory/{v3/substrate → substrate}/__tests__/concept-page-frontmatter-schema.test.ts +0 -0
  807. /package/src/plugins/defaults/memory/{v3/substrate → substrate}/__tests__/consolidation-prompt-flag-gating-guard.test.ts +0 -0
  808. /package/src/plugins/defaults/memory/{v3/substrate → substrate}/__tests__/injected-block-slugs.test.ts +0 -0
  809. /package/src/plugins/defaults/memory/{v3/substrate → substrate}/cli-command-content.ts +0 -0
@@ -1,6 +1,8 @@
1
1
  import type { ChildProcess } from "node:child_process";
2
2
  import { spawn } from "node:child_process";
3
3
 
4
+ import { z } from "zod";
5
+
4
6
  import type { BackgroundToolCompletedEvent } from "../../api/events/background-tool-completed.js";
5
7
  import { getConfig } from "../../config/loader.js";
6
8
  import { RiskLevel } from "../../permissions/types.js";
@@ -30,6 +32,10 @@ import {
30
32
  formatShellOutput,
31
33
  MAX_OUTPUT_LENGTH,
32
34
  } from "../shared/shell-output.js";
35
+ import {
36
+ invalidToolInputResult,
37
+ toToolInputSchema,
38
+ } from "../shared/zod-tool-schema.js";
33
39
  import type { ProxyEnvVars } from "../tool-types.js";
34
40
  import type {
35
41
  ToolContext,
@@ -49,6 +55,55 @@ function buildCredentialRefTrace(
49
55
 
50
56
  const log = getLogger("shell-tool");
51
57
 
58
+ /**
59
+ * Model-input schema, the single source for both runtime validation (via
60
+ * `TOOL_INPUT_SCHEMAS`) and the advertised `input_schema` below. Optional
61
+ * fields catch to `undefined` so a malformed value degrades to its
62
+ * default: `timeout_seconds` falls back to the configured
63
+ * default (it is also read defensively pre-execution by
64
+ * `computePerToolTimeoutMs`), `network_mode` falls back to "off" (the
65
+ * `=== "proxied"` coercion), `background` to foreground (the `=== true`
66
+ * coercion), `credential_ids` to none, and `activity` is status-only.
67
+ */
68
+ export const shellInputSchema = z.looseObject({
69
+ command: z.string().min(1).describe("The shell command to execute"),
70
+ activity: z
71
+ .string()
72
+ .describe(
73
+ 'Brief non-technical explanation of what this command does and why, shown to a non-technical user in the permission prompt. Avoid jargon and technical terms. Good: "to check if a required program is installed on your computer". Bad: "to check if gcloud CLI is installed". Good: "to download a helper program". Bad: "to run npm install".',
74
+ )
75
+ .optional()
76
+ .catch(undefined),
77
+ timeout_seconds: z
78
+ .number()
79
+ .describe(
80
+ "Optional timeout in seconds. Defaults to the configured default (120s). Cannot exceed the configured maximum.",
81
+ )
82
+ .optional()
83
+ .catch(undefined),
84
+ network_mode: z
85
+ .enum(["off", "proxied"])
86
+ .describe(
87
+ 'Network access mode for the command. "off" (default) blocks network access; "proxied" routes traffic through the credential proxy.',
88
+ )
89
+ .optional()
90
+ .catch(undefined),
91
+ credential_ids: z
92
+ .array(z.string())
93
+ .describe(
94
+ 'Optional list of credential IDs to inject via the proxy when network_mode is "proxied".',
95
+ )
96
+ .optional()
97
+ .catch(undefined),
98
+ background: z
99
+ .boolean()
100
+ .describe(
101
+ "Run the command in the background. The tool returns immediately with a background tool ID. When the process exits, its output is delivered to the conversation as a wake.",
102
+ )
103
+ .optional()
104
+ .catch(undefined),
105
+ });
106
+
52
107
  export const shellTool = {
53
108
  name: "bash",
54
109
  description: "Execute a shell command on the local machine",
@@ -56,55 +111,19 @@ export const shellTool = {
56
111
  executionTarget: "sandbox",
57
112
  defaultRiskLevel: RiskLevel.Medium,
58
113
 
59
- input_schema: {
60
- type: "object",
61
- properties: {
62
- command: {
63
- type: "string",
64
- description: "The shell command to execute",
65
- },
66
- activity: {
67
- type: "string",
68
- description:
69
- 'Brief non-technical explanation of what this command does and why, shown to a non-technical user in the permission prompt. Avoid jargon and technical terms. Good: "to check if a required program is installed on your computer". Bad: "to check if gcloud CLI is installed". Good: "to download a helper program". Bad: "to run npm install".',
70
- },
71
- timeout_seconds: {
72
- type: "number",
73
- description:
74
- "Optional timeout in seconds. Defaults to the configured default (120s). Cannot exceed the configured maximum.",
75
- },
76
- network_mode: {
77
- type: "string",
78
- enum: ["off", "proxied"],
79
- description:
80
- 'Network access mode for the command. "off" (default) blocks network access; "proxied" routes traffic through the credential proxy.',
81
- },
82
- credential_ids: {
83
- type: "array",
84
- items: { type: "string" },
85
- description:
86
- 'Optional list of credential IDs to inject via the proxy when network_mode is "proxied".',
87
- },
88
- background: {
89
- type: "boolean",
90
- description:
91
- "Run the command in the background. The tool returns immediately with a background tool ID. When the process exits, its output is delivered to the conversation as a wake.",
92
- },
93
- },
94
- required: ["command", "activity"],
95
- },
114
+ input_schema: toToolInputSchema(shellInputSchema, {
115
+ advertiseRequired: ["activity"],
116
+ }),
96
117
 
97
118
  async execute(
98
119
  input: Record<string, unknown>,
99
120
  context: ToolContext,
100
121
  ): Promise<ToolExecutionResult> {
101
- const command = input.command as string;
102
- if (!command || typeof command !== "string") {
103
- return {
104
- content: "Error: command is required and must be a string",
105
- isError: true,
106
- };
122
+ const parsed = shellInputSchema.safeParse(input);
123
+ if (!parsed.success) {
124
+ return invalidToolInputResult("bash", parsed.error);
107
125
  }
126
+ const command = parsed.data.command;
108
127
 
109
128
  // Reject commands containing null bytes - they cause truncation at the
110
129
  // OS level while the parser sees the full string, enabling bypass.
@@ -112,7 +131,7 @@ export const shellTool = {
112
131
  return { content: "Error: command contains null bytes", isError: true };
113
132
  }
114
133
 
115
- const background = input.background === true;
134
+ const background = parsed.data.background === true;
116
135
  if (background && context.diskPressureCleanupModeActive === true) {
117
136
  return {
118
137
  content:
@@ -123,15 +142,12 @@ export const shellTool = {
123
142
 
124
143
  const config = getConfig();
125
144
 
126
- const networkMode: "off" | "proxied" =
127
- input.network_mode === "proxied" ? "proxied" : "off";
145
+ const networkMode: "off" | "proxied" = parsed.data.network_mode ?? "off";
128
146
 
129
147
  const rawCredentialRefs: string[] = [];
130
- if (Array.isArray(input.credential_ids)) {
131
- for (const id of input.credential_ids) {
132
- if (typeof id === "string" && id.length > 0) {
133
- rawCredentialRefs.push(id);
134
- }
148
+ for (const id of parsed.data.credential_ids ?? []) {
149
+ if (id.length > 0) {
150
+ rawCredentialRefs.push(id);
135
151
  }
136
152
  }
137
153
 
@@ -222,10 +238,7 @@ export const shellTool = {
222
238
  }
223
239
 
224
240
  const { shellDefaultTimeoutSec, shellMaxTimeoutSec } = config.timeouts;
225
- const requestedSec =
226
- typeof input.timeout_seconds === "number"
227
- ? input.timeout_seconds
228
- : shellDefaultTimeoutSec;
241
+ const requestedSec = parsed.data.timeout_seconds ?? shellDefaultTimeoutSec;
229
242
  const timeoutSec = Math.max(1, Math.min(requestedSec, shellMaxTimeoutSec));
230
243
  const timeoutMs = timeoutSec * 1000;
231
244
 
@@ -6,8 +6,25 @@ import {
6
6
  import { isToolAllowedInChannel } from "../channels/permission-profiles.js";
7
7
  import type { ChannelId } from "../channels/types.js";
8
8
  import { getConfig } from "../config/loader.js";
9
+ import { isMemoryEnabled } from "../config/memory-v3-gate.js";
9
10
  import type { AutoApproveThreshold } from "../permissions/approval-policy.js";
10
- import { isDynamicSkillLoadInvocation } from "../permissions/checker.js";
11
+ import {
12
+ buildChannelPermissionCellQuery,
13
+ effectiveChannelCellThreshold,
14
+ } from "../permissions/channel-permission-query.js";
15
+ import {
16
+ isDynamicSkillLoadInvocation,
17
+ isToolOwnerSkillBundled,
18
+ } from "../permissions/checker.js";
19
+ import {
20
+ channelNoCellDefault,
21
+ resolveChannelPermissionCell,
22
+ } from "../permissions/gateway-threshold-reader.js";
23
+ import {
24
+ isControlPlaneWorkspaceWrite,
25
+ isOutOfWorkspaceFileInvocation,
26
+ isWorkspaceWriteTool,
27
+ } from "../permissions/workspace-policy.js";
11
28
  import {
12
29
  isUnparseableToolArgs,
13
30
  unparseableToolArgsMessage,
@@ -22,8 +39,10 @@ import { computeToolApprovalDigest } from "../security/tool-approval-digest.js";
22
39
  import { recordToolDenied, recordToolError } from "../telemetry/tool-audit.js";
23
40
  import { getLogger } from "../util/logger.js";
24
41
  import { resolveExecutionTarget } from "./execution-target.js";
42
+ import { channelCoordinatesFromToolContext } from "./policy-context.js";
25
43
  import { getAllTools, getTool, getToolOwner } from "./registry.js";
26
44
  import { isSideEffectTool } from "./side-effects.js";
45
+ import { parseToolInput } from "./tool-input-schemas.js";
27
46
  import { summarizeToolInput } from "./tool-input-summary.js";
28
47
  import { suggestToolName } from "./tool-name-aliases.js";
29
48
  import { recordToolCompletion } from "./tool-profiler.js";
@@ -238,25 +257,40 @@ async function stampFollowupState(
238
257
  const UI_SURFACE_TOOLS = new Set(["ui_show", "ui_update", "ui_dismiss"]);
239
258
 
240
259
  /**
241
- * Tool-sensitivity predicate: does invoking this tool require an approval
242
- * decision at all? This is about the tool, where it executes, and — for
243
- * `skill_load` — whether the invocation will execute embedded shell at load
244
- * time (inline command expansions run outside the tool pipeline, so they must
245
- * be gated like other code execution). Actor identity never feeds in here; it
246
- * enters the decision only through the `CapabilitySet` floor, see
247
- * {@link resolveSensitiveToolDecision}.
260
+ * How far a sensitive invocation reaches — the axis that decides whether a
261
+ * channel's approval cell may lift its floor. See {@link sensitiveToolReach}.
248
262
  */
249
- export function isSensitiveTool(
263
+ export type SensitiveToolReach = "none" | "sandbox" | "host";
264
+
265
+ /**
266
+ * Classify how far a sensitive invocation reaches. This is about the tool,
267
+ * where it executes, and — for `skill_load` — whether the invocation will
268
+ * execute embedded shell at load time (inline command expansions run outside
269
+ * the tool pipeline, so they must be gated like other code execution). Actor
270
+ * identity never feeds in here; it enters the decision only through the
271
+ * `CapabilitySet` floor, see {@link resolveSensitiveToolDecision}.
272
+ *
273
+ * - `"none"`: not sensitive.
274
+ * - `"sandbox"`: side effects confined to the assistant's own workspace. An
275
+ * owner can delegate these per room, so a cell may lift the floor.
276
+ * - `"host"`: reaches the guardian's own machine and accounts — host
277
+ * execution, and sandbox file tools escaping the workspace, which the
278
+ * host-fallback path policy turns into real host access. No cell lifts
279
+ * this: a room-level posture is about what the assistant may do in that
280
+ * room, never a grant of the owner's own machine.
281
+ */
282
+ export function sensitiveToolReach(
250
283
  toolName: string,
251
284
  executionTarget: ExecutionTarget,
252
285
  input?: Record<string, unknown>,
253
- ): boolean {
286
+ workingDir?: string,
287
+ ): SensitiveToolReach {
254
288
  // UI surface tools are passive, user-visible operations (cards, forms,
255
289
  // tables). User input is voluntary and user-controlled — they are not
256
290
  // sensitive, so they work during fresh onboarding before trust is
257
291
  // established.
258
292
  if (UI_SURFACE_TOOLS.has(toolName)) {
259
- return false;
293
+ return "none";
260
294
  }
261
295
 
262
296
  // An inline-command ("dynamic") skill_load executes embedded shell at load
@@ -271,12 +305,67 @@ export function isSensitiveTool(
271
305
  input &&
272
306
  isDynamicSkillLoadInvocation(toolName, input)
273
307
  ) {
274
- return true;
308
+ return "host";
309
+ }
310
+
311
+ // A sandbox file tool targeting a path outside the workspace reaches the
312
+ // host filesystem on non-containerized installs (the host-fallback path
313
+ // policy executes the escape once the permission lane approves). That is
314
+ // host-equivalent access — a read-only escape can leak local secrets — so
315
+ // it carries the same capability floor as executionTarget === "host":
316
+ // non-guardian actors escalate to the guardian, and no risk threshold or
317
+ // trust rule lifts it.
318
+ if (
319
+ input &&
320
+ workingDir &&
321
+ isOutOfWorkspaceFileInvocation(toolName, input, workingDir)
322
+ ) {
323
+ return "host";
324
+ }
325
+
326
+ // Read-only host execution is sensitive too, because it can leak sensitive
327
+ // local information (e.g. shell/file reads).
328
+ if (executionTarget === "host") {
329
+ return "host";
275
330
  }
276
331
 
277
- // Side-effect tools are sensitive. Read-only host execution is too,
278
- // because it can leak sensitive local information (e.g. shell/file reads).
279
- return isSideEffectTool(toolName) || executionTarget === "host";
332
+ // Extension-owned code that is not first-party bundled is unvetted: its
333
+ // manifest declares its own risk, and nothing reviewed it. It is sensitive
334
+ // whatever it is named — a novel name is in no side-effect list, so without
335
+ // this it would not be gated at all, and the risk its own manifest claims
336
+ // would be the only thing standing between it and an auto-approval.
337
+ if (isUnvettedExtensionTool(toolName)) {
338
+ return "sandbox";
339
+ }
340
+
341
+ // Side-effect tools are sensitive, and what is left here acts only on the
342
+ // assistant's own workspace.
343
+ return isSideEffectTool(toolName) ? "sandbox" : "none";
344
+ }
345
+
346
+ /**
347
+ * Whether a tool comes from code nobody in-repo reviewed. Vetted is an
348
+ * allowlist — the built-in default set and first-party bundled skills —
349
+ * and every other owner is unvetted: third-party and workspace skills,
350
+ * plugins, workspace tools (arbitrary on-disk code imported into the
351
+ * daemon), MCP servers, and owner kinds that do not exist yet. An
352
+ * allowlist fails closed when the owner vocabulary grows, the same reason
353
+ * the read-only subagent gate (`conversation-tool-setup.ts`) allowlists
354
+ * names and verifies `ownerKind === "default"` rather than naming the
355
+ * kinds it distrusts.
356
+ *
357
+ * An absent owner record is the built-in registration path, so it reads
358
+ * as `default`; a tool that is not registered at all cannot execute.
359
+ */
360
+ function isUnvettedExtensionTool(toolName: string): boolean {
361
+ const kind = getToolOwner(toolName)?.kind;
362
+ if (kind === undefined || kind === "default") {
363
+ return false;
364
+ }
365
+ if (kind === "skill") {
366
+ return !isToolOwnerSkillBundled(getTool(toolName));
367
+ }
368
+ return true;
280
369
  }
281
370
 
282
371
  /**
@@ -299,37 +388,179 @@ export type SensitiveToolDecision = "proceed" | "escalate-and-wait" | "deny";
299
388
 
300
389
  /**
301
390
  * Single composition point for the sensitive-tool approval decision:
302
- * approval-cell threshold × tool risk level × `CapabilitySet` floor.
391
+ * `CapabilitySet` floor × the actor's approval-matrix cell.
392
+ *
393
+ * The floor is the starting point — a sensitive invocation by a non-guardian
394
+ * needs a scoped grant. The cell is what can lift it: an owner who has given
395
+ * this contact type a non-`none` level in this room has said the assistant
396
+ * may act there without minting a per-call grant.
303
397
  *
304
- * The decision is about the tool; actor identity feeds in only through the
305
- * already-resolved `sensitiveToolApproval` capability. That floor is
306
- * deterministic and cannot be lifted by the other axes: when the capability
307
- * is not `"self"`, a sensitive invocation without a grant always escalates
308
- * or denies. `cellThreshold` and `riskLevel` are composition axes the
309
- * decision does not consult — no threshold/risk combination may lift the
310
- * outcome above the floor.
398
+ * Three things no cell lifts:
399
+ * - `host` reach. A room-level posture says what the assistant may do in that
400
+ * room; it is never a grant of the owner's own machine or accounts, so host
401
+ * execution and workspace escapes stay floored at every level.
402
+ * - `deny` — an actor with no established identity has no cell to stand on.
403
+ * - A `none` cell authorizes nothing, so the floor stands unchanged.
404
+ *
405
+ * Lifting is not approval. It decides only that a scoped grant is not the
406
+ * mechanism; the risk/threshold policy in `permissions/approval-policy.ts`
407
+ * then applies that same cell against the fully-classified risk. Whatever the
408
+ * cell does not cover still reaches the guardian — a lane-B `"prompt"` is
409
+ * promoted to a guardian-bound `tool_approval` request
410
+ * (`permissions/confirmation-guardian-request.ts`), the same principal the
411
+ * escalation path would have asked.
311
412
  */
312
413
  export function resolveSensitiveToolDecision(input: {
313
- sensitive: boolean;
414
+ /** How far the invocation reaches; see {@link sensitiveToolReach}. */
415
+ reach: SensitiveToolReach;
314
416
  /**
315
- * Approval-matrix cell axis. The decision does not consult it — the floor
316
- * alone resolves the outcome — so callers pass `undefined` rather than
317
- * paying a threshold lookup to populate it.
417
+ * Threshold of the approval-matrix cell governing this invocation.
418
+ * `undefined` when no cell covers it — including when the cell could not be
419
+ * read, since an unreadable cell must never lift the floor.
318
420
  */
319
421
  cellThreshold: ApprovalCellThreshold | undefined;
320
- /**
321
- * Risk level as known at gate time. The full risk classification runs
322
- * after this gate (in the permission checker), so callers may only have
323
- * the pre-classification level here — composing decisions on this axis
324
- * requires moving classification ahead of the gate first.
325
- */
326
- riskLevel: string;
327
422
  sensitiveToolApproval: SensitiveToolApproval;
328
423
  }): SensitiveToolDecision {
329
- if (!input.sensitive || input.sensitiveToolApproval === "self") {
424
+ if (input.reach === "none" || input.sensitiveToolApproval === "self") {
330
425
  return "proceed";
331
426
  }
332
- return input.sensitiveToolApproval;
427
+ if (input.sensitiveToolApproval === "deny" || input.reach === "host") {
428
+ return input.sensitiveToolApproval;
429
+ }
430
+ if (input.cellThreshold === undefined || input.cellThreshold === "none") {
431
+ return input.sensitiveToolApproval;
432
+ }
433
+ return "proceed";
434
+ }
435
+
436
+ /**
437
+ * Sandbox tools that execute code. Running code in the workspace is how you
438
+ * write everything else in it — including the directories
439
+ * {@link isControlPlaneWorkspaceWrite} covers — so a cell that lifted one of
440
+ * these would lift those by the back door.
441
+ *
442
+ * `skill_execute` is deliberately absent rather than overlooked: it is
443
+ * dispatch indirection, and `conversation-tool-setup` resolves it to its inner
444
+ * tool name before the gate runs, so the gate already classifies the tool the
445
+ * skill actually calls rather than the wrapper.
446
+ */
447
+ const CODE_EXECUTION_TOOLS: ReadonlySet<string> = new Set(["bash"]);
448
+
449
+ /**
450
+ * Whether an invocation reaches the private network — localhost, which is the
451
+ * daemon's own HTTP surface, the gateway, and whatever else listens on the
452
+ * guardian's machine. Keyed on the input rather than the tool, because the
453
+ * same tool is delegable against a public URL.
454
+ */
455
+ function reachesPrivateNetwork(
456
+ toolName: string,
457
+ input: Record<string, unknown>,
458
+ ): boolean {
459
+ return toolName === "web_fetch" && input.allow_private_network === true;
460
+ }
461
+
462
+ /**
463
+ * Whether a channel's approval cell may lift the floor for this invocation.
464
+ *
465
+ * The cell delegates ordinary work in the assistant's own workspace. Three
466
+ * sandbox side effects are not ordinary, because each is a way back out of
467
+ * the sandbox — and excluding only some of them would be a false safeguard,
468
+ * since any one reaches the others:
469
+ *
470
+ * - `bash` runs code. A room that can run code in the workspace can write
471
+ * anything into it, including the executable directories below, so lifting
472
+ * bash would lift those by the back door.
473
+ * - Control-plane workspace writes ({@link isControlPlaneWorkspaceWrite}) —
474
+ * the directories the daemon imports and executes, and the prompt surfaces
475
+ * it reads as its own instructions. Approving the write approves the later
476
+ * execution.
477
+ * - Unvetted extension-owned tools ({@link isUnvettedExtensionTool}). Nothing
478
+ * reviewed them, so the risk their own manifest claims must not be what
479
+ * decides whether a room may run them unattended.
480
+ * - `web_fetch` with `allow_private_network`. The private network is the
481
+ * guardian's own machine — the daemon's HTTP surface, the gateway, whatever
482
+ * else is listening on it. Fetching a public URL is delegable; reaching
483
+ * localhost is the machine floor by another door.
484
+ *
485
+ * Each stays on the capability floor, so a channel actor escalates to the
486
+ * guardian for them at every level. None of this touches the guardian's own
487
+ * lane — it decides what a *cell* may delegate, not how risk is classified.
488
+ */
489
+ function isChannelLiftable(
490
+ reach: SensitiveToolReach,
491
+ toolName: string,
492
+ input: Record<string, unknown>,
493
+ workingDir: string | undefined,
494
+ ): boolean {
495
+ if (reach !== "sandbox") {
496
+ return false;
497
+ }
498
+ if (CODE_EXECUTION_TOOLS.has(toolName)) {
499
+ return false;
500
+ }
501
+ // A write is liftable only when its target can be resolved and resolves
502
+ // outside the control plane. With no workingDir there is no way to see
503
+ // where the write lands, so the check fails closed rather than being
504
+ // skipped.
505
+ if (
506
+ isWorkspaceWriteTool(toolName) &&
507
+ (!workingDir || isControlPlaneWorkspaceWrite(toolName, input, workingDir))
508
+ ) {
509
+ return false;
510
+ }
511
+ if (isUnvettedExtensionTool(toolName)) {
512
+ return false;
513
+ }
514
+ if (reachesPrivateNetwork(toolName, input)) {
515
+ return false;
516
+ }
517
+ return true;
518
+ }
519
+
520
+ /**
521
+ * Threshold of the approval-matrix cell governing this invocation, read only
522
+ * when it can change the outcome: a channel-liftable invocation whose actor
523
+ * sits on the escalate floor. Guardians, non-sensitive tools, host reach,
524
+ * everything {@link isChannelLiftable} excludes, and identity-less actors
525
+ * return early, so the gateway lookup never lands on the paths where it could
526
+ * only add latency — grant consumption for an already-approved call, and voice
527
+ * abort handling.
528
+ *
529
+ * The permission checker reads this same cell later in the turn, within the
530
+ * reader's cache window, so the lift costs at most one lookup per turn.
531
+ *
532
+ * Returns `undefined` when the turn has no channel coordinates or a lookup
533
+ * fails — nothing lifts the floor then. A successful walk that finds no cell
534
+ * resolves the room's default — the owner's global setting collapsed to the
535
+ * channel's two levels — so an unconfigured room behaves exactly as the
536
+ * picker's "· default" marker and the legend present it
537
+ * ({@link effectiveChannelCellThreshold}).
538
+ */
539
+ async function resolveApprovalCellThreshold(
540
+ reach: SensitiveToolReach,
541
+ toolName: string,
542
+ input: Record<string, unknown>,
543
+ sensitiveToolApproval: SensitiveToolApproval,
544
+ context: ToolContext,
545
+ ): Promise<ApprovalCellThreshold | undefined> {
546
+ if (
547
+ sensitiveToolApproval !== "escalate-and-wait" ||
548
+ !isChannelLiftable(reach, toolName, input, context.workingDir)
549
+ ) {
550
+ return undefined;
551
+ }
552
+ const query = buildChannelPermissionCellQuery(
553
+ channelCoordinatesFromToolContext(context),
554
+ );
555
+ if (!query) {
556
+ return undefined;
557
+ }
558
+ const cell = await resolveChannelPermissionCell(query);
559
+ return effectiveChannelCellThreshold(
560
+ cell,
561
+ query.contactType,
562
+ await channelNoCellDefault(cell, query.contactType),
563
+ );
333
564
  }
334
565
 
335
566
  /**
@@ -347,7 +578,18 @@ function sensitiveToolDeniedMessage(
347
578
  }
348
579
 
349
580
  export type PreExecutionGateResult =
350
- | { allowed: true; tool: Tool; grantConsumed?: boolean }
581
+ | {
582
+ allowed: true;
583
+ tool: Tool;
584
+ grantConsumed?: boolean;
585
+ /**
586
+ * Input parsed against the tool's registered schema in
587
+ * `TOOL_INPUT_SCHEMAS` (with `.catch()` recoveries applied). Set only
588
+ * for built-in tools with a registered schema; the executor substitutes
589
+ * it for the raw input so validation and execution see the same value.
590
+ */
591
+ parsedInput?: Record<string, unknown>;
592
+ }
351
593
  | { allowed: false; result: ToolExecutionResult };
352
594
 
353
595
  /** Configuration for the inline grant wait behavior. */
@@ -506,16 +748,22 @@ export class ToolApprovalHandler {
506
748
  | Parameters<typeof consumeGrantForInvocation>[0]
507
749
  | null = null;
508
750
 
509
- const sensitive = isSensitiveTool(name, executionTarget, input);
751
+ const reach = sensitiveToolReach(
752
+ name,
753
+ executionTarget,
754
+ input,
755
+ context.workingDir,
756
+ );
510
757
  const { sensitiveToolApproval } = resolveCapabilities(context.trustClass);
511
- // cellThreshold stays unresolved: the decision does not consult it
512
- // (the floor is deterministic), and resolving a live threshold here
513
- // would block grant consumption — including already-approved calls and
514
- // voice abort handling — on a gateway IPC read.
515
758
  const sensitiveDecision = resolveSensitiveToolDecision({
516
- sensitive,
517
- cellThreshold: undefined,
518
- riskLevel,
759
+ reach,
760
+ cellThreshold: await resolveApprovalCellThreshold(
761
+ reach,
762
+ name,
763
+ input,
764
+ sensitiveToolApproval,
765
+ context,
766
+ ),
519
767
  sensitiveToolApproval,
520
768
  });
521
769
 
@@ -570,7 +818,7 @@ export class ToolApprovalHandler {
570
818
  if (context.allowedToolNames && !context.allowedToolNames.has(name)) {
571
819
  let memoryEnabled = true;
572
820
  try {
573
- memoryEnabled = getConfig().memory?.enabled !== false;
821
+ memoryEnabled = isMemoryEnabled(getConfig());
574
822
  } catch {
575
823
  // Config unavailable — leave the memory hint out rather than guess.
576
824
  }
@@ -616,10 +864,36 @@ export class ToolApprovalHandler {
616
864
  }
617
865
  }
618
866
 
619
- // All policy gates passed. Now consume the scoped grant if one is
620
- // required. Deferring consumption to this point ensures a downstream
621
- // rejection (allowedToolNames, task-run preflight, registry lookup)
622
- // does not waste the one-time-use grant.
867
+ // All deterministic policy gates passed. Parse model-generated input for
868
+ // built-in tools with a registered schema BEFORE the grant consumption
869
+ // and guardian escalation below: a malformed invocation can never
870
+ // execute, so failing it here means it cannot burn a one-time grant or
871
+ // interrupt the guardian with an approval card (and up to a 60s inline
872
+ // wait) for a call validation would reject anyway. Extension-owned and
873
+ // workspace-override tools own their input contracts and are skipped.
874
+ let parsedInput: Record<string, unknown> | undefined;
875
+ if (getToolOwner(name)?.kind === "default") {
876
+ const parsed = parseToolInput(name, input);
877
+ if (!parsed.ok) {
878
+ this.auditGateError(
879
+ context,
880
+ name,
881
+ input,
882
+ riskLevel,
883
+ startTime,
884
+ parsed.message,
885
+ );
886
+ return {
887
+ allowed: false,
888
+ result: { content: parsed.message, isError: true },
889
+ };
890
+ }
891
+ parsedInput = parsed.data;
892
+ }
893
+
894
+ // Now consume the scoped grant if one is required. Deferring consumption
895
+ // to this point ensures a prior gate rejection (allowedToolNames, input
896
+ // validation, registry lookup) does not waste the one-time-use grant.
623
897
  //
624
898
  // Retry polling is scoped to the voice channel where a race condition
625
899
  // exists between fire-and-forget turn execution and LLM fallback grant
@@ -644,7 +918,7 @@ export class ToolApprovalHandler {
644
918
  "Scoped grant consumed - allowing untrusted actor tool invocation",
645
919
  );
646
920
 
647
- return { allowed: true, tool, grantConsumed: true };
921
+ return { allowed: true, tool, grantConsumed: true, parsedInput };
648
922
  }
649
923
 
650
924
  // Treat abort as a cancellation - not a grant denial. This matches
@@ -738,7 +1012,7 @@ export class ToolApprovalHandler {
738
1012
  },
739
1013
  "Inline grant wait succeeded - allowing trusted contact tool invocation",
740
1014
  );
741
- return { allowed: true, tool, grantConsumed: true };
1015
+ return { allowed: true, tool, grantConsumed: true, parsedInput };
742
1016
  }
743
1017
 
744
1018
  if (waitResult.outcome === "aborted") {
@@ -825,6 +1099,6 @@ export class ToolApprovalHandler {
825
1099
  return { allowed: false, result: { content: reason, isError: true } };
826
1100
  }
827
1101
 
828
- return { allowed: true, tool };
1102
+ return { allowed: true, tool, parsedInput };
829
1103
  }
830
1104
  }