@vellumai/assistant 0.10.0 → 0.10.1-staging.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 (824) hide show
  1. package/ARCHITECTURE.md +36 -37
  2. package/bun.lock +3 -0
  3. package/docs/workflows.md +12 -7
  4. package/eslint-rules/cli-no-daemon-internals.js +6 -0
  5. package/node_modules/@slack/types/LICENSE +23 -0
  6. package/node_modules/@slack/types/README.md +32 -0
  7. package/node_modules/@slack/types/dist/block-kit/block-elements.d.ts +953 -0
  8. package/node_modules/@slack/types/dist/block-kit/block-elements.d.ts.map +1 -0
  9. package/node_modules/@slack/types/dist/block-kit/block-elements.js +4 -0
  10. package/node_modules/@slack/types/dist/block-kit/block-elements.js.map +1 -0
  11. package/node_modules/@slack/types/dist/block-kit/blocks.d.ts +474 -0
  12. package/node_modules/@slack/types/dist/block-kit/blocks.d.ts.map +1 -0
  13. package/node_modules/@slack/types/dist/block-kit/blocks.js +3 -0
  14. package/node_modules/@slack/types/dist/block-kit/blocks.js.map +1 -0
  15. package/node_modules/@slack/types/dist/block-kit/composition-objects.d.ts +237 -0
  16. package/node_modules/@slack/types/dist/block-kit/composition-objects.d.ts.map +1 -0
  17. package/node_modules/@slack/types/dist/block-kit/composition-objects.js +4 -0
  18. package/node_modules/@slack/types/dist/block-kit/composition-objects.js.map +1 -0
  19. package/node_modules/@slack/types/dist/block-kit/extensions.d.ts +88 -0
  20. package/node_modules/@slack/types/dist/block-kit/extensions.d.ts.map +1 -0
  21. package/node_modules/@slack/types/dist/block-kit/extensions.js +3 -0
  22. package/node_modules/@slack/types/dist/block-kit/extensions.js.map +1 -0
  23. package/node_modules/@slack/types/dist/calls.d.ts +26 -0
  24. package/node_modules/@slack/types/dist/calls.d.ts.map +1 -0
  25. package/node_modules/@slack/types/dist/calls.js +6 -0
  26. package/node_modules/@slack/types/dist/calls.js.map +1 -0
  27. package/node_modules/@slack/types/dist/chunk.d.ts +52 -0
  28. package/node_modules/@slack/types/dist/chunk.d.ts.map +1 -0
  29. package/node_modules/@slack/types/dist/chunk.js +3 -0
  30. package/node_modules/@slack/types/dist/chunk.js.map +1 -0
  31. package/node_modules/@slack/types/dist/common/bot-profile.d.ts +12 -0
  32. package/node_modules/@slack/types/dist/common/bot-profile.d.ts.map +1 -0
  33. package/node_modules/@slack/types/dist/common/bot-profile.js +3 -0
  34. package/node_modules/@slack/types/dist/common/bot-profile.js.map +1 -0
  35. package/node_modules/@slack/types/dist/common/status-emoji-display-info.d.ts +6 -0
  36. package/node_modules/@slack/types/dist/common/status-emoji-display-info.d.ts.map +1 -0
  37. package/node_modules/@slack/types/dist/common/status-emoji-display-info.js +3 -0
  38. package/node_modules/@slack/types/dist/common/status-emoji-display-info.js.map +1 -0
  39. package/node_modules/@slack/types/dist/dialog.d.ts +36 -0
  40. package/node_modules/@slack/types/dist/dialog.d.ts.map +1 -0
  41. package/node_modules/@slack/types/dist/dialog.js +3 -0
  42. package/node_modules/@slack/types/dist/dialog.js.map +1 -0
  43. package/node_modules/@slack/types/dist/events/app.d.ts +204 -0
  44. package/node_modules/@slack/types/dist/events/app.d.ts.map +1 -0
  45. package/node_modules/@slack/types/dist/events/app.js +3 -0
  46. package/node_modules/@slack/types/dist/events/app.js.map +1 -0
  47. package/node_modules/@slack/types/dist/events/assistant.d.ts +29 -0
  48. package/node_modules/@slack/types/dist/events/assistant.d.ts.map +1 -0
  49. package/node_modules/@slack/types/dist/events/assistant.js +3 -0
  50. package/node_modules/@slack/types/dist/events/assistant.js.map +1 -0
  51. package/node_modules/@slack/types/dist/events/call.d.ts +8 -0
  52. package/node_modules/@slack/types/dist/events/call.d.ts.map +1 -0
  53. package/node_modules/@slack/types/dist/events/call.js +3 -0
  54. package/node_modules/@slack/types/dist/events/call.js.map +1 -0
  55. package/node_modules/@slack/types/dist/events/channel.d.ts +85 -0
  56. package/node_modules/@slack/types/dist/events/channel.d.ts.map +1 -0
  57. package/node_modules/@slack/types/dist/events/channel.js +3 -0
  58. package/node_modules/@slack/types/dist/events/channel.js.map +1 -0
  59. package/node_modules/@slack/types/dist/events/dnd.d.ts +24 -0
  60. package/node_modules/@slack/types/dist/events/dnd.d.ts.map +1 -0
  61. package/node_modules/@slack/types/dist/events/dnd.js +3 -0
  62. package/node_modules/@slack/types/dist/events/dnd.js.map +1 -0
  63. package/node_modules/@slack/types/dist/events/email.d.ts +6 -0
  64. package/node_modules/@slack/types/dist/events/email.d.ts.map +1 -0
  65. package/node_modules/@slack/types/dist/events/email.js +3 -0
  66. package/node_modules/@slack/types/dist/events/email.js.map +1 -0
  67. package/node_modules/@slack/types/dist/events/emoji.d.ts +11 -0
  68. package/node_modules/@slack/types/dist/events/emoji.d.ts.map +1 -0
  69. package/node_modules/@slack/types/dist/events/emoji.js +3 -0
  70. package/node_modules/@slack/types/dist/events/emoji.js.map +1 -0
  71. package/node_modules/@slack/types/dist/events/entity-details-requested.d.ts +21 -0
  72. package/node_modules/@slack/types/dist/events/entity-details-requested.d.ts.map +1 -0
  73. package/node_modules/@slack/types/dist/events/entity-details-requested.js +3 -0
  74. package/node_modules/@slack/types/dist/events/entity-details-requested.js.map +1 -0
  75. package/node_modules/@slack/types/dist/events/file.d.ts +60 -0
  76. package/node_modules/@slack/types/dist/events/file.d.ts.map +1 -0
  77. package/node_modules/@slack/types/dist/events/file.js +4 -0
  78. package/node_modules/@slack/types/dist/events/file.js.map +1 -0
  79. package/node_modules/@slack/types/dist/events/function.d.ts +33 -0
  80. package/node_modules/@slack/types/dist/events/function.d.ts.map +1 -0
  81. package/node_modules/@slack/types/dist/events/function.js +3 -0
  82. package/node_modules/@slack/types/dist/events/function.js.map +1 -0
  83. package/node_modules/@slack/types/dist/events/grid-migration.d.ts +9 -0
  84. package/node_modules/@slack/types/dist/events/grid-migration.d.ts.map +1 -0
  85. package/node_modules/@slack/types/dist/events/grid-migration.js +3 -0
  86. package/node_modules/@slack/types/dist/events/grid-migration.js.map +1 -0
  87. package/node_modules/@slack/types/dist/events/group.d.ts +55 -0
  88. package/node_modules/@slack/types/dist/events/group.d.ts.map +1 -0
  89. package/node_modules/@slack/types/dist/events/group.js +3 -0
  90. package/node_modules/@slack/types/dist/events/group.js.map +1 -0
  91. package/node_modules/@slack/types/dist/events/im.d.ts +26 -0
  92. package/node_modules/@slack/types/dist/events/im.d.ts.map +1 -0
  93. package/node_modules/@slack/types/dist/events/im.js +3 -0
  94. package/node_modules/@slack/types/dist/events/im.js.map +1 -0
  95. package/node_modules/@slack/types/dist/events/index.d.ts +60 -0
  96. package/node_modules/@slack/types/dist/events/index.d.ts.map +1 -0
  97. package/node_modules/@slack/types/dist/events/index.js +43 -0
  98. package/node_modules/@slack/types/dist/events/index.js.map +1 -0
  99. package/node_modules/@slack/types/dist/events/invite.d.ts +20 -0
  100. package/node_modules/@slack/types/dist/events/invite.d.ts.map +1 -0
  101. package/node_modules/@slack/types/dist/events/invite.js +3 -0
  102. package/node_modules/@slack/types/dist/events/invite.js.map +1 -0
  103. package/node_modules/@slack/types/dist/events/link-shared.d.ts +16 -0
  104. package/node_modules/@slack/types/dist/events/link-shared.d.ts.map +1 -0
  105. package/node_modules/@slack/types/dist/events/link-shared.js +3 -0
  106. package/node_modules/@slack/types/dist/events/link-shared.js.map +1 -0
  107. package/node_modules/@slack/types/dist/events/member.d.ts +19 -0
  108. package/node_modules/@slack/types/dist/events/member.d.ts.map +1 -0
  109. package/node_modules/@slack/types/dist/events/member.js +3 -0
  110. package/node_modules/@slack/types/dist/events/member.js.map +1 -0
  111. package/node_modules/@slack/types/dist/events/message-metadata.d.ts +38 -0
  112. package/node_modules/@slack/types/dist/events/message-metadata.d.ts.map +1 -0
  113. package/node_modules/@slack/types/dist/events/message-metadata.js +3 -0
  114. package/node_modules/@slack/types/dist/events/message-metadata.js.map +1 -0
  115. package/node_modules/@slack/types/dist/events/message.d.ts +306 -0
  116. package/node_modules/@slack/types/dist/events/message.d.ts.map +1 -0
  117. package/node_modules/@slack/types/dist/events/message.js +3 -0
  118. package/node_modules/@slack/types/dist/events/message.js.map +1 -0
  119. package/node_modules/@slack/types/dist/events/pin.d.ts +60 -0
  120. package/node_modules/@slack/types/dist/events/pin.d.ts.map +1 -0
  121. package/node_modules/@slack/types/dist/events/pin.js +3 -0
  122. package/node_modules/@slack/types/dist/events/pin.js.map +1 -0
  123. package/node_modules/@slack/types/dist/events/reaction.d.ts +23 -0
  124. package/node_modules/@slack/types/dist/events/reaction.d.ts.map +1 -0
  125. package/node_modules/@slack/types/dist/events/reaction.js +3 -0
  126. package/node_modules/@slack/types/dist/events/reaction.js.map +1 -0
  127. package/node_modules/@slack/types/dist/events/shared-channel.d.ts +134 -0
  128. package/node_modules/@slack/types/dist/events/shared-channel.d.ts.map +1 -0
  129. package/node_modules/@slack/types/dist/events/shared-channel.js +3 -0
  130. package/node_modules/@slack/types/dist/events/shared-channel.js.map +1 -0
  131. package/node_modules/@slack/types/dist/events/star.d.ts +13 -0
  132. package/node_modules/@slack/types/dist/events/star.d.ts.map +1 -0
  133. package/node_modules/@slack/types/dist/events/star.js +3 -0
  134. package/node_modules/@slack/types/dist/events/star.js.map +1 -0
  135. package/node_modules/@slack/types/dist/events/steps-from-apps.d.ts +82 -0
  136. package/node_modules/@slack/types/dist/events/steps-from-apps.d.ts.map +1 -0
  137. package/node_modules/@slack/types/dist/events/steps-from-apps.js +3 -0
  138. package/node_modules/@slack/types/dist/events/steps-from-apps.js.map +1 -0
  139. package/node_modules/@slack/types/dist/events/subteam.d.ts +66 -0
  140. package/node_modules/@slack/types/dist/events/subteam.d.ts.map +1 -0
  141. package/node_modules/@slack/types/dist/events/subteam.js +3 -0
  142. package/node_modules/@slack/types/dist/events/subteam.js.map +1 -0
  143. package/node_modules/@slack/types/dist/events/team.d.ts +99 -0
  144. package/node_modules/@slack/types/dist/events/team.d.ts.map +1 -0
  145. package/node_modules/@slack/types/dist/events/team.js +3 -0
  146. package/node_modules/@slack/types/dist/events/team.js.map +1 -0
  147. package/node_modules/@slack/types/dist/events/token.d.ts +8 -0
  148. package/node_modules/@slack/types/dist/events/token.d.ts.map +1 -0
  149. package/node_modules/@slack/types/dist/events/token.js +3 -0
  150. package/node_modules/@slack/types/dist/events/token.js.map +1 -0
  151. package/node_modules/@slack/types/dist/events/user.d.ts +313 -0
  152. package/node_modules/@slack/types/dist/events/user.d.ts.map +1 -0
  153. package/node_modules/@slack/types/dist/events/user.js +3 -0
  154. package/node_modules/@slack/types/dist/events/user.js.map +1 -0
  155. package/node_modules/@slack/types/dist/index.d.ts +12 -0
  156. package/node_modules/@slack/types/dist/index.d.ts.map +1 -0
  157. package/node_modules/@slack/types/dist/index.js +28 -0
  158. package/node_modules/@slack/types/dist/index.js.map +1 -0
  159. package/node_modules/@slack/types/dist/message-attachments.d.ts +171 -0
  160. package/node_modules/@slack/types/dist/message-attachments.d.ts.map +1 -0
  161. package/node_modules/@slack/types/dist/message-attachments.js +3 -0
  162. package/node_modules/@slack/types/dist/message-attachments.js.map +1 -0
  163. package/node_modules/@slack/types/dist/message-metadata.d.ts +281 -0
  164. package/node_modules/@slack/types/dist/message-metadata.d.ts.map +1 -0
  165. package/node_modules/@slack/types/dist/message-metadata.js +27 -0
  166. package/node_modules/@slack/types/dist/message-metadata.js.map +1 -0
  167. package/node_modules/@slack/types/dist/views.d.ts +71 -0
  168. package/node_modules/@slack/types/dist/views.d.ts.map +1 -0
  169. package/node_modules/@slack/types/dist/views.js +3 -0
  170. package/node_modules/@slack/types/dist/views.js.map +1 -0
  171. package/node_modules/@slack/types/package.json +47 -0
  172. package/node_modules/@vellumai/gateway-client/bun.lock +3 -0
  173. package/node_modules/@vellumai/gateway-client/package.json +1 -0
  174. package/node_modules/@vellumai/gateway-client/src/__tests__/contact-read-contracts.test.ts +69 -0
  175. package/node_modules/@vellumai/gateway-client/src/__tests__/trust-verdict-contract.test.ts +65 -0
  176. package/node_modules/@vellumai/gateway-client/src/gateway-ipc-contracts.ts +162 -0
  177. package/node_modules/@vellumai/gateway-client/src/inbound-contract.ts +8 -0
  178. package/node_modules/@vellumai/gateway-client/src/index.ts +14 -0
  179. package/node_modules/@vellumai/gateway-client/src/ipc-client.ts +4 -2
  180. package/node_modules/@vellumai/gateway-client/src/outbound-contract.ts +3 -2
  181. package/node_modules/@vellumai/gateway-client/src/trust-verdict-contract.ts +78 -0
  182. package/openapi.yaml +345 -18
  183. package/package.json +2 -1
  184. package/scripts/memory-inspect.ts +24 -14
  185. package/src/__tests__/access-request-seed-content-blocks.test.ts +83 -103
  186. package/src/__tests__/activation-early-marking.test.ts +1 -1
  187. package/src/__tests__/actor-token-service.test.ts +3 -3
  188. package/src/__tests__/agent-loop-callsite-precedence.test.ts +1 -40
  189. package/src/__tests__/agent-loop-compaction-events.test.ts +0 -1
  190. package/src/__tests__/agent-loop-compaction-strip.test.ts +0 -1
  191. package/src/__tests__/agent-loop-exit-reason.test.ts +0 -1
  192. package/src/__tests__/agent-loop-pushes-post-hook-prompt.test.ts +306 -0
  193. package/src/__tests__/agent-loop-regrowth-guard.test.ts +0 -1
  194. package/src/__tests__/agent-loop.test.ts +3 -0
  195. package/src/__tests__/agent-wake-override-profile.test.ts +2 -0
  196. package/src/__tests__/anthropic-provider.test.ts +143 -9
  197. package/src/__tests__/app-builder-skill-instructions.test.ts +47 -5
  198. package/src/__tests__/app-conversation-ids-backfill.test.ts +1 -1
  199. package/src/__tests__/app-source-watcher.test.ts +30 -10
  200. package/src/__tests__/approval-cascade.test.ts +6 -0
  201. package/src/__tests__/approval-interception-trust-gates.test.ts +151 -0
  202. package/src/__tests__/approval-primitive.test.ts +1 -1
  203. package/src/__tests__/approval-routes-http.test.ts +1 -1
  204. package/src/__tests__/assistant-attachments.test.ts +155 -0
  205. package/src/__tests__/assistant-event-hub-machine-name.test.ts +2 -4
  206. package/src/__tests__/assistant-events-sse-hardening.test.ts +1 -1
  207. package/src/__tests__/assistant-events-sse-shed.test.ts +1 -1
  208. package/src/__tests__/attachment-upload-trusted-source.test.ts +13 -8
  209. package/src/__tests__/attachments-store.test.ts +1 -1
  210. package/src/__tests__/audit-log-rotation.test.ts +50 -54
  211. package/src/__tests__/auth-fallback-events-store.test.ts +1 -1
  212. package/src/__tests__/auto-analysis-end-to-end.test.ts +9 -14
  213. package/src/__tests__/background-shell-bash.test.ts +4 -1
  214. package/src/__tests__/background-shell-host-bash.test.ts +17 -3
  215. package/src/__tests__/background-workers-disk-pressure.test.ts +1 -0
  216. package/src/__tests__/call-controller.test.ts +1 -1
  217. package/src/__tests__/call-conversation-messages.test.ts +1 -1
  218. package/src/__tests__/call-domain.test.ts +1 -1
  219. package/src/__tests__/call-pointer-messages.test.ts +3 -4
  220. package/src/__tests__/call-recovery.test.ts +1 -1
  221. package/src/__tests__/call-routes-http.test.ts +1 -1
  222. package/src/__tests__/call-store.test.ts +1 -1
  223. package/src/__tests__/cancel-resolves-conversation-key.test.ts +1 -1
  224. package/src/__tests__/canonical-guardian-store.test.ts +24 -1
  225. package/src/__tests__/channel-approval-routes.test.ts +73 -1119
  226. package/src/__tests__/channel-delivery-store.test.ts +1 -1
  227. package/src/__tests__/channel-guardian.test.ts +265 -641
  228. package/src/__tests__/channel-inbound-disk-pressure.test.ts +1 -2
  229. package/src/__tests__/channel-retry-sweep.test.ts +1 -1
  230. package/src/__tests__/compaction-events.test.ts +6 -0
  231. package/src/__tests__/compaction-trail-store.test.ts +6 -5
  232. package/src/__tests__/compaction.benchmark.test.ts +0 -1
  233. package/src/__tests__/compactor-image-manifest-trust.test.ts +1 -1
  234. package/src/__tests__/config-loader-backfill.test.ts +183 -51
  235. package/src/__tests__/config-schema.test.ts +34 -0
  236. package/src/__tests__/confirmation-request-guardian-bridge.test.ts +1 -2
  237. package/src/__tests__/contact-store-user-file.test.ts +2 -2
  238. package/src/__tests__/contacts-relay-reads.test.ts +409 -0
  239. package/src/__tests__/contacts-tools.test.ts +4 -4
  240. package/src/__tests__/contacts-write.test.ts +1 -2
  241. package/src/__tests__/context-search-conversations-source.test.ts +1 -1
  242. package/src/__tests__/context-window-manager-compact-retry.test.ts +6 -2
  243. package/src/__tests__/context-window-manager-overflow-rung.test.ts +6 -2
  244. package/src/__tests__/conversation-abort-tool-results.test.ts +6 -0
  245. package/src/__tests__/conversation-agent-loop-disk-pressure.test.ts +3 -0
  246. package/src/__tests__/conversation-agent-loop-inference-profile.test.ts +3 -0
  247. package/src/__tests__/conversation-agent-loop-overflow.test.ts +3 -0
  248. package/src/__tests__/conversation-agent-loop.test.ts +3 -0
  249. package/src/__tests__/conversation-attachments.test.ts +2 -5
  250. package/src/__tests__/conversation-attention-store.test.ts +1 -1
  251. package/src/__tests__/conversation-attention-telegram.test.ts +1 -2
  252. package/src/__tests__/conversation-clear-safety.test.ts +1 -1
  253. package/src/__tests__/conversation-confirmation-signals.test.ts +6 -0
  254. package/src/__tests__/conversation-crud-inference-profile.test.ts +1 -1
  255. package/src/__tests__/conversation-delete-schedule-cleanup.test.ts +12 -19
  256. package/src/__tests__/conversation-disk-view-integration.test.ts +1 -1
  257. package/src/__tests__/conversation-disk-view.test.ts +1 -1
  258. package/src/__tests__/conversation-fork-crud.test.ts +10 -8
  259. package/src/__tests__/conversation-fork-retrospective.test.ts +250 -0
  260. package/src/__tests__/conversation-fork-route.test.ts +1 -1
  261. package/src/__tests__/conversation-inference-profile-list.test.ts +1 -1
  262. package/src/__tests__/conversation-inference-profile-route.test.ts +1 -1
  263. package/src/__tests__/conversation-init.benchmark.test.ts +1 -1
  264. package/src/__tests__/conversation-key-store-disk-view.test.ts +1 -1
  265. package/src/__tests__/conversation-lifecycle.test.ts +117 -0
  266. package/src/__tests__/conversation-list-source.test.ts +3 -3
  267. package/src/__tests__/conversation-process-callsite.test.ts +6 -14
  268. package/src/__tests__/conversation-provider-retry-repair.test.ts +6 -0
  269. package/src/__tests__/conversation-queue.test.ts +6 -0
  270. package/src/__tests__/conversation-routes-disk-view.test.ts +1 -1
  271. package/src/__tests__/conversation-runtime-assembly.test.ts +115 -12
  272. package/src/__tests__/conversation-slash-queue.test.ts +6 -0
  273. package/src/__tests__/conversation-slash-unknown.test.ts +6 -0
  274. package/src/__tests__/conversation-speed-override.test.ts +6 -0
  275. package/src/__tests__/conversation-starter-routes.test.ts +5 -5
  276. package/src/__tests__/conversation-store.test.ts +1 -1
  277. package/src/__tests__/conversation-surfaces-activation-emit.test.ts +1 -1
  278. package/src/__tests__/conversation-sync-tags.test.ts +1 -1
  279. package/src/__tests__/conversation-usage.test.ts +1 -1
  280. package/src/__tests__/conversation-wipe.test.ts +9 -8
  281. package/src/__tests__/conversation-workspace-cache-state.test.ts +6 -0
  282. package/src/__tests__/conversation-workspace-injection.test.ts +6 -0
  283. package/src/__tests__/conversation-workspace-tool-tracking.test.ts +6 -0
  284. package/src/__tests__/conversations-import-system-filter.test.ts +1 -1
  285. package/src/__tests__/copy-composer-tc-templates.test.ts +17 -0
  286. package/src/__tests__/credential-security-invariants.test.ts +0 -1
  287. package/src/__tests__/db-acp-history.test.ts +2 -2
  288. package/src/__tests__/db-conversation-fork-lineage-migration.test.ts +5 -7
  289. package/src/__tests__/db-conversation-inference-profile-migration.test.ts +6 -7
  290. package/src/__tests__/db-llm-request-log-provider-migration.test.ts +5 -10
  291. package/src/__tests__/db-migration-rollback.test.ts +129 -39
  292. package/src/__tests__/db-proxy-transaction.test.ts +1 -1
  293. package/src/__tests__/db-schedule-syntax-migration.test.ts +0 -11
  294. package/src/__tests__/db-test-helpers.ts +36 -19
  295. package/src/__tests__/delete-propagation.test.ts +1 -1
  296. package/src/__tests__/deterministic-verification-control-plane.test.ts +26 -8
  297. package/src/__tests__/disk-pressure-tools.test.ts +41 -1
  298. package/src/__tests__/dm-backfill.test.ts +1 -1
  299. package/src/__tests__/drop-capability-card-state-migration.test.ts +0 -8
  300. package/src/__tests__/edit-propagation.test.ts +1 -1
  301. package/src/__tests__/emit-signal-routing-intent.test.ts +83 -0
  302. package/src/__tests__/empty-response-hook.test.ts +42 -0
  303. package/src/__tests__/events-client-registration.test.ts +1 -1
  304. package/src/__tests__/followup-tools.test.ts +1 -1
  305. package/src/__tests__/gemini-count-tokens.test.ts +70 -0
  306. package/src/__tests__/guardian-action-sweep.test.ts +9 -2
  307. package/src/__tests__/guardian-binding-drift-heal.test.ts +1 -1
  308. package/src/__tests__/guardian-card-withdrawal.test.ts +1 -1
  309. package/src/__tests__/guardian-decision-primitive-canonical.test.ts +1 -1
  310. package/src/__tests__/guardian-dispatch.test.ts +1 -1
  311. package/src/__tests__/guardian-outbound-http.test.ts +7 -12
  312. package/src/__tests__/guardian-principal-id-roundtrip.test.ts +1 -1
  313. package/src/__tests__/guardian-routing-invariants.test.ts +2 -4
  314. package/src/__tests__/guardian-routing-state.test.ts +1 -2
  315. package/src/__tests__/guardian-verification-voice-binding.test.ts +1 -1
  316. package/src/__tests__/headless-browser-mode.test.ts +2 -2
  317. package/src/__tests__/heartbeat-disk-pressure.test.ts +4 -0
  318. package/src/__tests__/heartbeat-service.test.ts +6 -0
  319. package/src/__tests__/helpers/channel-test-adapter.ts +98 -0
  320. package/src/__tests__/http-conversation-lineage.test.ts +1 -1
  321. package/src/__tests__/image-recovery-hook.test.ts +1 -1
  322. package/src/__tests__/inbound-invite-redemption.test.ts +1 -2
  323. package/src/__tests__/inbound-trust-verdict.test.ts +254 -0
  324. package/src/__tests__/inference-profile-reaper.test.ts +1 -1
  325. package/src/__tests__/inference-profile-session-handler.test.ts +1 -1
  326. package/src/__tests__/inference-profile-session-ipc.test.ts +1 -1
  327. package/src/__tests__/injector-chain.test.ts +1 -1
  328. package/src/__tests__/injector-disk-pressure.test.ts +11 -6
  329. package/src/__tests__/internal-telemetry-routes.test.ts +1 -1
  330. package/src/__tests__/invite-redemption-service.test.ts +244 -43
  331. package/src/__tests__/invite-routes-http.test.ts +35 -186
  332. package/src/__tests__/invite-service-ipc.test.ts +287 -0
  333. package/src/__tests__/jobs-store-qdrant-breaker.test.ts +5 -5
  334. package/src/__tests__/jobs-store-upsert-debounced.test.ts +9 -12
  335. package/src/__tests__/list-messages-attachments.test.ts +42 -1
  336. package/src/__tests__/list-messages-client-message-id.test.ts +1 -1
  337. package/src/__tests__/list-messages-hidden-metadata.test.ts +1 -1
  338. package/src/__tests__/list-messages-page-latest.test.ts +1 -1
  339. package/src/__tests__/list-messages-tool-merge.test.ts +1 -1
  340. package/src/__tests__/llm-context-route-provider.test.ts +69 -4
  341. package/src/__tests__/llm-request-log-agent-loop-exit-reason.test.ts +9 -5
  342. package/src/__tests__/llm-request-log-call-site.test.ts +6 -6
  343. package/src/__tests__/llm-request-log-turn-query.test.ts +27 -13
  344. package/src/__tests__/llm-usage-store.test.ts +40 -1
  345. package/src/__tests__/log-export-routes.test.ts +1 -1
  346. package/src/__tests__/log-export-workspace.test.ts +3 -3
  347. package/src/__tests__/memory-jobs-worker-lanes.test.ts +5 -5
  348. package/src/__tests__/memory-recall-log-store.test.ts +1 -1
  349. package/src/__tests__/memory-upsert-concurrency.test.ts +3 -4
  350. package/src/__tests__/messages-after-tiebreaker.test.ts +1 -1
  351. package/src/__tests__/migration-import-from-url.test.ts +2 -2
  352. package/src/__tests__/mtime-cache.test.ts +375 -0
  353. package/src/__tests__/non-member-access-request.test.ts +1 -2
  354. package/src/__tests__/notification-candidate-guardian-context.test.ts +203 -0
  355. package/src/__tests__/notification-guardian-path.test.ts +1 -1
  356. package/src/__tests__/notification-schedule-notify-dedup.test.ts +1 -1
  357. package/src/__tests__/oauth-provider-profiles.test.ts +1 -1
  358. package/src/__tests__/oauth-provider-visibility.test.ts +1 -1
  359. package/src/__tests__/oauth-store.test.ts +1 -1
  360. package/src/__tests__/persist-unsendable-image-downscale.test.ts +1 -1
  361. package/src/__tests__/persist-unsendable-image.test.ts +1 -1
  362. package/src/__tests__/persona-resolver.test.ts +39 -1
  363. package/src/__tests__/platform-bash-auto-approve.test.ts +1 -1
  364. package/src/__tests__/playbook-execution.test.ts +1 -1
  365. package/src/__tests__/playbook-tools.test.ts +1 -1
  366. package/src/__tests__/plugin-api-model-profiles.test.ts +74 -21
  367. package/src/__tests__/plugin-bootstrap.test.ts +78 -0
  368. package/src/__tests__/provider-platform-proxy-integration.test.ts +25 -5
  369. package/src/__tests__/provider-usage-tracking.test.ts +1 -1
  370. package/src/__tests__/prune-old-conversations-job.test.ts +1 -1
  371. package/src/__tests__/reaction-persistence.test.ts +1 -1
  372. package/src/__tests__/relay-server.test.ts +357 -56
  373. package/src/__tests__/runtime-attachment-metadata.test.ts +10 -1
  374. package/src/__tests__/runtime-events-sse-bilingual.test.ts +7 -9
  375. package/src/__tests__/runtime-events-sse-parity.test.ts +1 -1
  376. package/src/__tests__/runtime-events-sse-reconnect.test.ts +1 -1
  377. package/src/__tests__/runtime-events-sse.test.ts +1 -1
  378. package/src/__tests__/schedule-retry.test.ts +1 -1
  379. package/src/__tests__/schedule-routes-workflow-validation.test.ts +1 -1
  380. package/src/__tests__/schedule-routes.test.ts +1 -1
  381. package/src/__tests__/schedule-store.test.ts +1 -1
  382. package/src/__tests__/schedule-tools.test.ts +1 -1
  383. package/src/__tests__/scheduler-disk-pressure.test.ts +1 -1
  384. package/src/__tests__/scheduler-recurrence.test.ts +1 -1
  385. package/src/__tests__/scheduler-reuse-conversation.test.ts +1 -1
  386. package/src/__tests__/scheduler-wake.test.ts +2 -1
  387. package/src/__tests__/scoped-approval-grants.test.ts +1 -1
  388. package/src/__tests__/scoped-grant-security-matrix.test.ts +5 -5
  389. package/src/__tests__/scrub-corrupted-image-attachments.test.ts +0 -8
  390. package/src/__tests__/secret-routes-platform-proxy.test.ts +1 -0
  391. package/src/__tests__/send-endpoint-busy.test.ts +1 -1
  392. package/src/__tests__/sequence-store.test.ts +1 -1
  393. package/src/__tests__/server-history-render.test.ts +40 -1
  394. package/src/__tests__/settings-routes.test.ts +11 -10
  395. package/src/__tests__/skill-load-tool.test.ts +72 -0
  396. package/src/__tests__/slack-inbound-verification.test.ts +1 -3
  397. package/src/__tests__/slack-messaging-token-resolution.test.ts +13 -2
  398. package/src/__tests__/slack-reaction-canonical-approval.test.ts +1 -1
  399. package/src/__tests__/subagent-tool-gate-mode.test.ts +2 -73
  400. package/src/__tests__/subagent-tools.test.ts +1 -31
  401. package/src/__tests__/system-prompt.test.ts +1 -1
  402. package/src/__tests__/system-storage-cleanup-skill.test.ts +56 -0
  403. package/src/__tests__/task-compiler.test.ts +1 -1
  404. package/src/__tests__/task-management-tools.test.ts +1 -1
  405. package/src/__tests__/task-memory-cleanup.test.ts +9 -6
  406. package/src/__tests__/task-scheduler.test.ts +1 -1
  407. package/src/__tests__/thread-backfill.test.ts +1 -1
  408. package/src/__tests__/tool-approval-handler.test.ts +1 -1
  409. package/src/__tests__/tool-approval-seed-content-blocks.test.ts +2 -0
  410. package/src/__tests__/tool-executor.test.ts +32 -1
  411. package/src/__tests__/tool-grant-request-escalation.test.ts +1 -2
  412. package/src/__tests__/trusted-contact-inline-approval-integration.test.ts +73 -1
  413. package/src/__tests__/trusted-contact-lifecycle-notifications.test.ts +34 -34
  414. package/src/__tests__/trusted-contact-multichannel.test.ts +1 -2
  415. package/src/__tests__/trusted-contact-verification.test.ts +1 -1
  416. package/src/__tests__/turn-boundary-resolution.test.ts +3 -3
  417. package/src/__tests__/turn-events-store.test.ts +1 -1
  418. package/src/__tests__/twilio-routes.test.ts +2 -3
  419. package/src/__tests__/usage-cache-backfill-migration.test.ts +20 -10
  420. package/src/__tests__/usage-routes.test.ts +1 -1
  421. package/src/__tests__/user-plugin-loader.test.ts +34 -29
  422. package/src/__tests__/verification-control-plane-policy.test.ts +2 -2
  423. package/src/__tests__/voice-invite-redemption.test.ts +134 -36
  424. package/src/__tests__/voice-scoped-grant-consumer.test.ts +1 -1
  425. package/src/__tests__/voice-session-bridge.test.ts +1 -1
  426. package/src/__tests__/workspace-git-service.test.ts +114 -1
  427. package/src/__tests__/workspace-heartbeat-service.test.ts +45 -0
  428. package/src/__tests__/workspace-migration-009-backfill-conversation-disk-view.test.ts +1 -1
  429. package/src/__tests__/workspace-migration-013-repair-conversation-disk-view.test.ts +1 -1
  430. package/src/__tests__/workspace-migration-028-recover-conversations-from-disk-view.test.ts +88 -18
  431. package/src/__tests__/workspace-migration-108-drop-balanced-economy-profile.test.ts +6 -6
  432. package/src/__tests__/workspace-migration-109-swap-quality-profile-to-glm-5p2.test.ts +281 -0
  433. package/src/__tests__/workspace-migration-110-flip-balanced-profile-to-together.test.ts +167 -0
  434. package/src/__tests__/workspace-migrations-runner.test.ts +55 -0
  435. package/src/a2a/__tests__/e2e-a2a-channel.test.ts +1 -1
  436. package/src/a2a/__tests__/task-store.test.ts +1 -1
  437. package/src/acp/__tests__/session-manager-persistence.test.ts +1 -1
  438. package/src/acp/__tests__/session-manager-resume.test.ts +22 -11
  439. package/src/acp/__tests__/session-manager-startup.test.ts +1 -1
  440. package/src/acp/__tests__/session-manager.test.ts +72 -1
  441. package/src/acp/index.ts +10 -0
  442. package/src/acp/session-manager.ts +35 -0
  443. package/src/agent/loop.ts +45 -27
  444. package/src/api/index.ts +0 -6
  445. package/src/approvals/AGENTS.md +1 -2
  446. package/src/approvals/guardian-decision-primitive.ts +13 -210
  447. package/src/approvals/guardian-request-resolvers.ts +104 -58
  448. package/src/background-wake/wake-intent-hooks.test.ts +1 -1
  449. package/src/calls/__tests__/inbound-trust-reader.test.ts +110 -0
  450. package/src/calls/__tests__/relay-setup-router.test.ts +88 -62
  451. package/src/calls/inbound-trust-reader.ts +40 -0
  452. package/src/calls/relay-server.ts +65 -23
  453. package/src/calls/relay-setup-router.ts +20 -6
  454. package/src/calls/relay-verification.ts +7 -7
  455. package/src/cli/commands/contacts.ts +6 -24
  456. package/src/cli/commands/db/__tests__/repair.test.ts +15 -6
  457. package/src/cli/commands/db/__tests__/status.test.ts +7 -3
  458. package/src/cli/commands/db/status.ts +212 -33
  459. package/src/cli/commands/memory/__tests__/memory-v3.test.ts +6 -1
  460. package/src/cli/commands/memory/index.ts +2 -0
  461. package/src/cli/commands/memory/memory-retrospective.ts +129 -0
  462. package/src/cli/commands/memory/memory-v3.ts +176 -4
  463. package/src/cli/commands/plugins.ts +268 -11
  464. package/src/cli/lib/__tests__/install-from-github.test.ts +40 -0
  465. package/src/cli/lib/__tests__/plugin-pin-history.test.ts +162 -0
  466. package/src/cli/lib/__tests__/toggle-plugin.test.ts +158 -0
  467. package/src/cli/lib/install-from-github.ts +47 -6
  468. package/src/cli/lib/plugin-marketplace.ts +11 -0
  469. package/src/cli/lib/plugin-pin-history.ts +257 -0
  470. package/src/cli/lib/toggle-plugin.ts +146 -0
  471. package/src/config/__tests__/sync-gated-profiles.test.ts +2 -2
  472. package/src/config/bundled-skills/app-builder/SKILL.md +15 -33
  473. package/src/config/bundled-skills/app-builder/references/DESIGN_SYSTEM.md +3 -8
  474. package/src/config/bundled-skills/app-builder/references/INTERACTION_HOOKS.md +64 -37
  475. package/src/config/bundled-skills/app-builder/references/RESPONSIVE.md +1 -1
  476. package/src/config/bundled-skills/app-builder/references/WIDGETS.md +14 -72
  477. package/src/config/bundled-skills/app-builder/references/examples/README.md +1 -2
  478. package/src/config/bundled-skills/contacts/SKILL.md +7 -12
  479. package/src/config/bundled-skills/messaging/tools/shared.ts +4 -1
  480. package/src/config/bundled-skills/system-storage-cleanup/SKILL.md +74 -0
  481. package/src/config/bundled-skills/workflows/SKILL.md +4 -3
  482. package/src/config/call-site-defaults.ts +11 -2
  483. package/src/config/feature-flag-registry.json +0 -8
  484. package/src/config/profile-dispatchability.ts +11 -0
  485. package/src/config/schemas/call-site-catalog.ts +7 -0
  486. package/src/config/schemas/llm.ts +2 -0
  487. package/src/config/schemas/memory-lifecycle.ts +5 -3
  488. package/src/config/schemas/timeouts.ts +24 -0
  489. package/src/config/seed-inference-profiles.ts +133 -45
  490. package/src/config/sync-gated-profiles.ts +13 -1
  491. package/src/contacts/contact-store.ts +21 -0
  492. package/src/contacts/member-status.ts +9 -0
  493. package/src/credential-health/credential-health-service.ts +1 -5
  494. package/src/daemon/__tests__/conversation-tool-setup.test.ts +44 -0
  495. package/src/daemon/app-source-watcher.ts +31 -18
  496. package/src/daemon/assistant-attachments.ts +94 -4
  497. package/src/daemon/conversation-agent-loop-handlers.ts +3 -0
  498. package/src/daemon/conversation-agent-loop.ts +9 -36
  499. package/src/daemon/conversation-runtime-assembly.ts +91 -66
  500. package/src/daemon/conversation-tool-setup.ts +20 -63
  501. package/src/daemon/conversation.ts +144 -52
  502. package/src/daemon/event-loop-watchdog.test.ts +85 -0
  503. package/src/daemon/event-loop-watchdog.ts +133 -0
  504. package/src/daemon/external-plugins-bootstrap.ts +26 -80
  505. package/src/daemon/handlers/__tests__/config-a2a-accept.test.ts +1 -1
  506. package/src/daemon/handlers/__tests__/config-a2a-complete.test.ts +1 -1
  507. package/src/daemon/handlers/__tests__/config-a2a-invite.test.ts +1 -1
  508. package/src/daemon/handlers/__tests__/config-a2a-redeem.test.ts +1 -1
  509. package/src/daemon/handlers/__tests__/config-a2a.test.ts +1 -1
  510. package/src/daemon/handlers/config-channels.ts +32 -18
  511. package/src/daemon/handlers/conversations.ts +7 -0
  512. package/src/daemon/handlers/shared.ts +7 -0
  513. package/src/daemon/lifecycle.ts +16 -3
  514. package/src/daemon/message-types/inbox.ts +0 -6
  515. package/src/daemon/message-types/messages.ts +0 -4
  516. package/src/daemon/message-types/surfaces.ts +18 -8
  517. package/src/daemon/server.ts +0 -4
  518. package/src/daemon/tool-setup-types.ts +0 -7
  519. package/src/daemon/trust-context.ts +6 -0
  520. package/src/daemon/wake-conversation-ops.ts +70 -0
  521. package/src/daemon/workspace-tools-watcher.ts +7 -3
  522. package/src/documents/document-comments-store.test.ts +1 -1
  523. package/src/heartbeat/__tests__/heartbeat-run-store.test.ts +1 -1
  524. package/src/heartbeat/__tests__/heartbeat-service.test.ts +6 -0
  525. package/src/heartbeat/heartbeat-service.ts +3 -4
  526. package/src/ipc/__tests__/attachment-ipc.test.ts +1 -1
  527. package/src/ipc/__tests__/browser-ipc.test.ts +73 -2
  528. package/src/ipc/__tests__/watcher-ipc.test.ts +59 -39
  529. package/src/ipc/assistant-server.ts +8 -0
  530. package/src/ipc/gateway-client.ts +2 -1
  531. package/src/ipc/routes/__tests__/invite-ipc-routes.test.ts +58 -0
  532. package/src/ipc/routes/invite-ipc-routes.ts +66 -0
  533. package/src/live-voice/__tests__/live-voice-archive.test.ts +1 -1
  534. package/src/memory/__tests__/activation-session-store.test.ts +1 -1
  535. package/src/memory/__tests__/auto-analysis-guard.test.ts +1 -1
  536. package/src/memory/__tests__/conversation-group-migration.test.ts +1 -1
  537. package/src/memory/__tests__/conversation-queries.test.ts +1 -1
  538. package/src/memory/__tests__/db-async-query.test.ts +1 -1
  539. package/src/memory/__tests__/db-logs-attach.test.ts +110 -0
  540. package/src/memory/__tests__/db-maintenance.test.ts +28 -36
  541. package/src/memory/__tests__/db-memory-attach.test.ts +113 -0
  542. package/src/memory/__tests__/find-analysis-conversation.test.ts +1 -1
  543. package/src/memory/__tests__/find-most-recent-retrospective-for.test.ts +1 -1
  544. package/src/memory/__tests__/fork-message-copy.test.ts +232 -0
  545. package/src/memory/__tests__/jobs-store-enqueue-gate.test.ts +3 -0
  546. package/src/memory/__tests__/jobs-worker-v2-graph-trigger-embed.test.ts +5 -5
  547. package/src/memory/__tests__/jobs-worker-v2-schedule.test.ts +8 -6
  548. package/src/memory/__tests__/memory-retrospective-job.test.ts +30 -37
  549. package/src/memory/__tests__/memory-retrospective-startup-cleanup.test.ts +69 -66
  550. package/src/memory/__tests__/memory-retrospective-state.test.ts +1 -1
  551. package/src/memory/__tests__/memory-v2-activation-log-store.test.ts +1 -1
  552. package/src/memory/__tests__/memory-v2-concept-frequency.test.ts +1 -1
  553. package/src/memory/__tests__/onboarding-events-store.test.ts +1 -1
  554. package/src/memory/__tests__/table-relocation.test.ts +129 -0
  555. package/src/memory/conversation-crud.ts +461 -152
  556. package/src/memory/db-async-query.ts +89 -5
  557. package/src/memory/db-connection.ts +101 -18
  558. package/src/memory/db-init.ts +409 -234
  559. package/src/memory/db-maintenance.ts +43 -38
  560. package/src/memory/db-singleton.ts +45 -19
  561. package/src/memory/fork-message-copy.ts +170 -0
  562. package/src/memory/graph/__tests__/handle-remember-v2.test.ts +92 -0
  563. package/src/memory/graph/bootstrap.test.ts +6 -3
  564. package/src/memory/graph/retriever.test.ts +12 -12
  565. package/src/memory/graph/store.test.ts +15 -25
  566. package/src/memory/graph/store.ts +23 -14
  567. package/src/memory/graph/tool-handlers.ts +34 -5
  568. package/src/memory/graph/tools.ts +5 -2
  569. package/src/memory/indexer.ts +21 -9
  570. package/src/memory/job-handlers/cleanup.ts +10 -3
  571. package/src/memory/job-handlers/embedding.test.ts +4 -4
  572. package/src/memory/jobs/__tests__/embed-concept-page.test.ts +4 -4
  573. package/src/memory/jobs/embed-pkb-file.test.ts +7 -7
  574. package/src/memory/jobs-store.ts +36 -24
  575. package/src/memory/llm-request-log-store.ts +51 -19
  576. package/src/memory/llm-usage-store.ts +31 -1
  577. package/src/memory/memory-retrospective-job.ts +27 -19
  578. package/src/memory/memory-retrospective-startup-cleanup.ts +10 -2
  579. package/src/memory/migrations/{100-core-tables.ts → 000-core-tables.ts} +6 -10
  580. package/src/memory/migrations/104-core-indexes.ts +1 -1
  581. package/src/memory/migrations/126-backfill-guardian-principal-id.ts +189 -196
  582. package/src/memory/migrations/127-guardian-principal-id-not-null.ts +98 -105
  583. package/src/memory/migrations/134-contacts-notes-column.ts +66 -69
  584. package/src/memory/migrations/135-backfill-contact-interaction-stats.ts +19 -22
  585. package/src/memory/migrations/136-drop-assistant-id-columns.ts +227 -230
  586. package/src/memory/migrations/140-backfill-usage-cache-accounting.ts +204 -209
  587. package/src/memory/migrations/141-rename-verification-table.ts +45 -48
  588. package/src/memory/migrations/142-rename-verification-session-id-column.ts +16 -23
  589. package/src/memory/migrations/143-rename-guardian-verification-values.ts +23 -30
  590. package/src/memory/migrations/144-rename-voice-to-phone.ts +133 -136
  591. package/src/memory/migrations/145-drop-accounts-table.ts +4 -7
  592. package/src/memory/migrations/147-migrate-reminders-to-schedules.ts +79 -82
  593. package/src/memory/migrations/148-drop-reminders-table.ts +3 -6
  594. package/src/memory/migrations/150-oauth-apps-client-secret-path.ts +71 -78
  595. package/src/memory/migrations/157-invite-contact-id.ts +73 -76
  596. package/src/memory/migrations/162-guardian-timestamps-epoch-ms.ts +44 -58
  597. package/src/memory/migrations/169-rename-gmail-provider-key-to-google.ts +36 -43
  598. package/src/memory/migrations/174-rename-thread-starters-table.ts +30 -37
  599. package/src/memory/migrations/176-drop-capability-card-state.ts +17 -22
  600. package/src/memory/migrations/177-create-trace-events-table.ts +23 -28
  601. package/src/memory/migrations/180-backfill-inline-attachments-to-disk.ts +36 -43
  602. package/src/memory/migrations/181-rename-thread-starters-checkpoints.ts +14 -21
  603. package/src/memory/migrations/191-backfill-audio-attachment-mime-types.ts +17 -24
  604. package/src/memory/migrations/192-contacts-user-file-column.ts +6 -9
  605. package/src/memory/migrations/193-add-source-type-columns.ts +33 -36
  606. package/src/memory/migrations/194-memory-recall-logs.ts +34 -39
  607. package/src/memory/migrations/196-strip-integration-prefix-from-provider-keys.ts +59 -66
  608. package/src/memory/migrations/199-guardian-request-enrichment-columns.ts +41 -48
  609. package/src/memory/migrations/204-rename-memory-graph-type-values.ts +11 -18
  610. package/src/memory/migrations/206-scrub-corrupted-image-attachments.ts +76 -83
  611. package/src/memory/migrations/209-strip-thinking-from-consolidated.ts +50 -57
  612. package/src/memory/migrations/211-memory-recall-logs-query-context.ts +6 -11
  613. package/src/memory/migrations/212-llm-request-logs-created-at-index.ts +4 -9
  614. package/src/memory/migrations/217-conversation-host-access.ts +13 -18
  615. package/src/memory/migrations/220-normalize-user-file-by-principal.ts +86 -93
  616. package/src/memory/migrations/222-strip-placeholder-sentinels-from-messages.ts +41 -48
  617. package/src/memory/migrations/230-acp-session-history.ts +23 -28
  618. package/src/memory/migrations/231-repair-memory-graph-event-dates.ts +58 -62
  619. package/src/memory/migrations/232-activation-state.ts +11 -16
  620. package/src/memory/migrations/233-document-conversations.ts +20 -25
  621. package/src/memory/migrations/234-memory-v2-activation-logs.ts +26 -31
  622. package/src/memory/migrations/235-slack-compaction-watermark.ts +5 -10
  623. package/src/memory/migrations/236-tool-invocations-matched-rule-id.ts +6 -11
  624. package/src/memory/migrations/237-heartbeat-runs.ts +22 -27
  625. package/src/memory/migrations/239-trace-events-created-at-index.ts +4 -9
  626. package/src/memory/migrations/242-message-bookmarks.ts +17 -22
  627. package/src/memory/migrations/245-memory-retrospective-state.ts +8 -13
  628. package/src/memory/migrations/249-normalize-slack-external-content.ts +37 -41
  629. package/src/memory/migrations/251-a2a-tasks.ts +27 -32
  630. package/src/memory/migrations/254-external-conversation-binding-chat-name.ts +12 -17
  631. package/src/memory/migrations/255-channel-inbound-delivery-attempts.ts +10 -15
  632. package/src/memory/migrations/256-memory-v2-injection-events.ts +70 -74
  633. package/src/memory/migrations/259-conversation-cleaned-at.ts +4 -9
  634. package/src/memory/migrations/260-rename-cleaned-at.ts +11 -16
  635. package/src/memory/migrations/261-llm-usage-add-raw-usage.ts +3 -8
  636. package/src/memory/migrations/262-memory-v3-coactivation.ts +21 -26
  637. package/src/memory/migrations/263-memory-v3-auto-edges.ts +14 -19
  638. package/src/memory/migrations/270-schedule-description.ts +7 -12
  639. package/src/memory/migrations/272-acp-session-history-cwd.ts +8 -13
  640. package/src/memory/migrations/281-memory-retrospective-remembered-log.ts +8 -13
  641. package/src/memory/migrations/297-move-llm-request-logs-to-logs-db.ts +111 -0
  642. package/src/memory/migrations/298-move-memory-jobs-to-memory-db.ts +128 -0
  643. package/src/memory/migrations/299-canonical-guardian-deliveries-conversation-index.ts +19 -0
  644. package/src/memory/migrations/__tests__/297-move-llm-request-logs.test.ts +180 -0
  645. package/src/memory/migrations/__tests__/run-migrations.test.ts +333 -7
  646. package/src/memory/migrations/helpers/relocation.ts +227 -0
  647. package/src/memory/migrations/registry.ts +63 -0
  648. package/src/memory/migrations/run-migrations.ts +187 -16
  649. package/src/memory/migrations/validate-migration-state.ts +50 -145
  650. package/src/memory/raw-query.ts +47 -2
  651. package/src/memory/skill-loaded-events-store.test.ts +1 -1
  652. package/src/memory/task-memory-cleanup.ts +62 -41
  653. package/src/memory/tool-executed-events-store.test.ts +1 -1
  654. package/src/memory/turn-trace-store.test.ts +1 -1
  655. package/src/memory/v2/__tests__/backfill-jobs.test.ts +16 -15
  656. package/src/memory/v2/__tests__/harness-compare.test.ts +1 -1
  657. package/src/memory/v2/__tests__/harness-oracle.test.ts +1 -1
  658. package/src/memory/v2/__tests__/harness-replay-input.test.ts +1 -1
  659. package/src/memory/v2/__tests__/sweep-job.test.ts +2 -2
  660. package/src/memory/v3-eval/__tests__/eval-packets.test.ts +38 -0
  661. package/src/memory/v3-eval/__tests__/eval-tally.test.ts +139 -0
  662. package/src/memory/v3-eval/eval-packets.ts +197 -12
  663. package/src/memory/v3-eval/eval-tally.ts +234 -0
  664. package/src/messaging/provider.ts +10 -0
  665. package/src/messaging/providers/gmail/adapter.ts +1 -0
  666. package/src/messaging/providers/gmail/client.ts +14 -0
  667. package/src/messaging/providers/index.ts +1 -1
  668. package/src/messaging/providers/slack/send.test.ts +87 -39
  669. package/src/messaging/providers/slack/send.ts +84 -105
  670. package/src/notifications/README.md +9 -5
  671. package/src/notifications/__tests__/deterministic-checks.test.ts +43 -1
  672. package/src/notifications/adapters/slack.ts +12 -10
  673. package/src/notifications/approval-card-builder.ts +81 -20
  674. package/src/notifications/approval-card-data.ts +8 -5
  675. package/src/notifications/canonical-delivery-recorder.ts +7 -5
  676. package/src/notifications/conversation-candidates.ts +24 -59
  677. package/src/notifications/copy-composer.ts +48 -68
  678. package/src/notifications/deterministic-checks.ts +19 -16
  679. package/src/notifications/emit-signal.ts +29 -1
  680. package/src/notifications/trusted-contact-payloads.ts +70 -0
  681. package/src/oauth/byo-connection.test.ts +9 -0
  682. package/src/oauth/connection-resolver.test.ts +146 -6
  683. package/src/oauth/connection-resolver.ts +132 -5
  684. package/src/oauth/oauth-store.ts +16 -3
  685. package/src/oauth/scope-utils.ts +21 -0
  686. package/src/plugin-api/index.ts +9 -4
  687. package/src/plugin-api/model-profiles.test.ts +123 -0
  688. package/src/plugin-api/model-profiles.ts +5 -1
  689. package/src/plugin-api/vision-support.test.ts +149 -0
  690. package/src/plugin-api/vision-support.ts +78 -0
  691. package/src/plugins/defaults/compaction/window-manager.ts +45 -64
  692. package/src/plugins/defaults/empty-response/hooks/post-model-call.ts +13 -4
  693. package/src/plugins/defaults/image-fallback/__tests__/image-fallback.test.ts +302 -0
  694. package/src/plugins/defaults/image-fallback/hooks/user-prompt-submit.ts +103 -0
  695. package/src/plugins/defaults/image-fallback/package.json +14 -0
  696. package/src/plugins/defaults/image-fallback/src/caption-cache.ts +49 -0
  697. package/src/plugins/defaults/image-fallback/src/image-persist.ts +59 -0
  698. package/src/plugins/defaults/image-fallback/src/vision-caption.ts +120 -0
  699. package/src/plugins/defaults/index.ts +23 -0
  700. package/src/plugins/defaults/memory-retrieval/hooks/user-prompt-submit.ts +14 -1
  701. package/src/plugins/defaults/memory-retrieval/injectors.ts +4 -4
  702. package/src/plugins/external-plugin-loader.ts +47 -6
  703. package/src/plugins/mtime-cache.ts +772 -0
  704. package/src/plugins/pipeline.ts +7 -2
  705. package/src/plugins/registry.ts +16 -5
  706. package/src/plugins/user-loader.ts +22 -76
  707. package/src/prompts/persona-resolver.ts +29 -11
  708. package/src/prompts/system-prompt.ts +1 -1
  709. package/src/prompts/templates/system-sections.ts +4 -4
  710. package/src/providers/__tests__/count-tokens-forwarding.test.ts +98 -0
  711. package/src/providers/anthropic/client.ts +254 -185
  712. package/src/providers/call-site-routing.ts +10 -0
  713. package/src/providers/gemini/client.ts +43 -0
  714. package/src/providers/inference/adapter-factory.ts +6 -0
  715. package/src/providers/inference/connections.ts +6 -1
  716. package/src/providers/model-catalog.ts +37 -0
  717. package/src/providers/platform-proxy/constants.ts +5 -0
  718. package/src/providers/ratelimit.ts +9 -0
  719. package/src/providers/retry.ts +10 -0
  720. package/src/providers/together/client.ts +35 -0
  721. package/src/providers/types.ts +16 -0
  722. package/src/providers/usage-tracking.ts +7 -0
  723. package/src/runtime/AGENTS.md +9 -1
  724. package/src/runtime/__tests__/agent-wake.test.ts +259 -4
  725. package/src/runtime/__tests__/slack-block-formatting.test.ts +39 -10
  726. package/src/runtime/__tests__/trust-verdict-consumer.test.ts +417 -0
  727. package/src/runtime/actor-trust-resolver.ts +8 -16
  728. package/src/runtime/agent-wake.ts +183 -60
  729. package/src/runtime/channel-reply-delivery.ts +6 -3
  730. package/src/runtime/guardian-decision-types.ts +3 -22
  731. package/src/runtime/http-server.ts +1 -15
  732. package/src/runtime/invite-redemption-service.ts +155 -6
  733. package/src/runtime/invite-service.ts +113 -62
  734. package/src/runtime/migrations/__tests__/vbundle-builder-fd-leak.test.ts +3 -0
  735. package/src/runtime/routes/__tests__/acp-routes.test.ts +1 -1
  736. package/src/runtime/routes/__tests__/bookmark-routes.test.ts +1 -1
  737. package/src/runtime/routes/__tests__/channel-verification-revoke.test.ts +277 -0
  738. package/src/runtime/routes/__tests__/channel-verification-routes.test.ts +140 -0
  739. package/src/runtime/routes/__tests__/connection-routes-vs-cli-parity.test.ts +26 -7
  740. package/src/runtime/routes/__tests__/consolidation-routes.test.ts +14 -10
  741. package/src/runtime/routes/__tests__/contact-routes-update-channel-relay.test.ts +164 -0
  742. package/src/runtime/routes/__tests__/conversation-list-routes.test.ts +1 -1
  743. package/src/runtime/routes/__tests__/conversation-management-routes.test.ts +1 -1
  744. package/src/runtime/routes/__tests__/conversation-query-routes.test.ts +8 -8
  745. package/src/runtime/routes/__tests__/conversation-surface-routes.test.ts +1 -1
  746. package/src/runtime/routes/__tests__/inference-provider-connection-routes.test.ts +1 -3
  747. package/src/runtime/routes/__tests__/invite-relay-routes.test.ts +240 -0
  748. package/src/runtime/routes/__tests__/memory-v2-simulate-route.test.ts +4 -0
  749. package/src/runtime/routes/__tests__/plugins-routes.test.ts +143 -0
  750. package/src/runtime/routes/__tests__/retrospective-routes.test.ts +1 -1
  751. package/src/runtime/routes/__tests__/slack-channel-routes.test.ts +1 -1
  752. package/src/runtime/routes/acp-routes-list.test.ts +4 -0
  753. package/src/runtime/routes/acp-routes.test.ts +5 -6
  754. package/src/runtime/routes/attachment-routes.ts +21 -17
  755. package/src/runtime/routes/browser-routes.ts +19 -1
  756. package/src/runtime/routes/canonical-guardian-expiry-sweep.ts +5 -9
  757. package/src/runtime/routes/channel-verification-routes.ts +12 -1
  758. package/src/runtime/routes/contact-routes.ts +275 -164
  759. package/src/runtime/routes/conversation-query-routes.ts +15 -5
  760. package/src/runtime/routes/conversation-routes.ts +24 -3
  761. package/src/runtime/routes/conversation-starter-routes.ts +7 -8
  762. package/src/runtime/routes/guardian-approval-interception.ts +13 -274
  763. package/src/runtime/routes/inbound-message-handler.ts +20 -15
  764. package/src/runtime/routes/inbound-stages/acl-enforcement.test.ts +285 -0
  765. package/src/runtime/routes/inbound-stages/acl-enforcement.ts +45 -34
  766. package/src/runtime/routes/inbound-stages/admission-policy.ts +20 -5
  767. package/src/runtime/routes/log-export-routes.ts +2 -2
  768. package/src/runtime/routes/memory-eval-routes.ts +92 -0
  769. package/src/runtime/routes/memory-item-routes.test.ts +12 -11
  770. package/src/runtime/routes/migration-routes.ts +51 -40
  771. package/src/runtime/routes/plugins-routes.ts +164 -8
  772. package/src/runtime/routes/schedule-routes.ts +1 -0
  773. package/src/runtime/routes/usage-routes.ts +3 -0
  774. package/src/runtime/routes/work-items-routes.test.ts +1 -1
  775. package/src/runtime/slack-block-formatting.ts +46 -48
  776. package/src/runtime/trust-verdict-consumer.ts +172 -0
  777. package/src/schedule/scheduler.ts +6 -9
  778. package/src/telemetry/usage-telemetry-reporter.test.ts +1 -1
  779. package/src/tools/ask-question/ask-question-tool.test.ts +60 -52
  780. package/src/tools/ask-question/ask-question-tool.ts +14 -73
  781. package/src/tools/browser/__tests__/browser-status.test.ts +20 -0
  782. package/src/tools/browser/browser-execution.ts +16 -4
  783. package/src/tools/document/document-comment-tool.test.ts +1 -1
  784. package/src/tools/executor.ts +15 -3
  785. package/src/tools/host-terminal/host-shell.ts +28 -9
  786. package/src/tools/memory/register.test.ts +32 -0
  787. package/src/tools/skills/load.ts +43 -2
  788. package/src/tools/subagent/spawn.ts +4 -10
  789. package/src/tools/terminal/shell.ts +16 -5
  790. package/src/tools/types.ts +1 -0
  791. package/src/util/fs-watcher-error.ts +36 -0
  792. package/src/util/logs-db-path.ts +22 -0
  793. package/src/util/memory-db-path.ts +23 -0
  794. package/src/watcher/providers/gmail.ts +7 -2
  795. package/src/workflows/engine-integration.test.ts +1 -1
  796. package/src/workflows/engine.test.ts +1 -1
  797. package/src/workflows/engine.ts +22 -0
  798. package/src/workflows/fanout-load.test.ts +1 -1
  799. package/src/workflows/journal-store.test.ts +1 -1
  800. package/src/workflows/leaf-runner.test.ts +40 -1
  801. package/src/workflows/leaf-runner.ts +26 -1
  802. package/src/workspace/git-service.ts +144 -29
  803. package/src/workspace/migrations/109-swap-quality-profile-to-glm-5p2.ts +121 -0
  804. package/src/workspace/migrations/110-flip-balanced-profile-to-together.ts +82 -0
  805. package/src/workspace/migrations/registry.ts +4 -0
  806. package/src/workspace/migrations/runner.ts +32 -2
  807. package/src/__tests__/access-request-decision.test.ts +0 -375
  808. package/src/__tests__/guardian-grant-minting.test.ts +0 -607
  809. package/src/__tests__/plugin-source-watcher.test.ts +0 -302
  810. package/src/api/events/turn-profile-auto-routed.ts +0 -28
  811. package/src/daemon/__tests__/switch-inference-profile-tool.test.ts +0 -107
  812. package/src/daemon/plugin-source-watcher.ts +0 -278
  813. package/src/daemon/switch-inference-profile-tool.ts +0 -62
  814. package/src/memory/guardian-approvals.ts +0 -361
  815. package/src/memory/migrations/010-ext-conv-bindings-channel-chat-unique.ts +0 -66
  816. package/src/memory/migrations/038-actor-token-records.ts +0 -45
  817. package/src/memory/migrations/039-actor-refresh-token-records.ts +0 -57
  818. package/src/memory/migrations/103-complex-migrations.ts +0 -23
  819. package/src/memory/migrations/113-late-migrations.ts +0 -30
  820. package/src/memory/migrations/index.ts +0 -301
  821. package/src/runtime/routes/access-request-decision.ts +0 -297
  822. package/src/runtime/routes/approval-strategies/guardian-callback-strategy.ts +0 -963
  823. package/src/runtime/routes/channel-guardian-routes.ts +0 -19
  824. package/src/runtime/routes/guardian-expiry-sweep.ts +0 -132
@@ -0,0 +1,172 @@
1
+ /**
2
+ * Consume a gateway-stamped {@link TrustVerdict} into the daemon's local
3
+ * trust shapes.
4
+ *
5
+ * The gateway resolves a per-actor verdict from its ACL DB and stamps it onto
6
+ * inbound `sourceMetadata`. These pure mappers turn that verdict into the same
7
+ * {@link TrustContext} / {@link ResolvedMember} the local resolver would have
8
+ * produced — ACL + identity only. INFO fields (notes, userFile, contactType,
9
+ * interactionCount) are never carried on the wire; the consumer re-joins them
10
+ * locally by contactId.
11
+ */
12
+
13
+ import type { TrustVerdict } from "@vellumai/gateway-client";
14
+
15
+ import type { ChannelId } from "../channels/types.js";
16
+ import { channelStatusToMemberStatus } from "../contacts/member-status.js";
17
+ import type {
18
+ ChannelPolicy,
19
+ ChannelStatus,
20
+ ContactChannel,
21
+ ContactWithChannels,
22
+ } from "../contacts/types.js";
23
+ import type { TrustContext } from "../daemon/trust-context.js";
24
+ import type { ActorTrustContext } from "./actor-trust-resolver.js";
25
+ import { toTrustContext } from "./actor-trust-resolver.js";
26
+ import type { ResolvedMember } from "./routes/inbound-stages/acl-enforcement.js";
27
+
28
+ export interface TrustVerdictTransport {
29
+ sourceChannel: ChannelId;
30
+ conversationExternalId: string;
31
+ actorUsername?: string;
32
+ actorDisplayName?: string;
33
+ }
34
+
35
+ /**
36
+ * Build a {@link TrustContext} from a gateway verdict + transport identity.
37
+ *
38
+ * Reassembles an {@link ActorTrustContext} (mirroring `resolveActorTrust`) and
39
+ * routes it through {@link toTrustContext}, so the output is byte-identical to
40
+ * the local resolution path.
41
+ */
42
+ export function trustContextFromVerdict(
43
+ verdict: TrustVerdict,
44
+ input: TrustVerdictTransport,
45
+ ): TrustContext {
46
+ const canonicalSenderId = verdict.canonicalSenderId;
47
+ const memberDisplayName = verdict.memberDisplayName;
48
+ const senderDisplayName = input.actorDisplayName;
49
+ const username = input.actorUsername;
50
+ const identifier = username
51
+ ? `@${username}`
52
+ : (canonicalSenderId ?? undefined);
53
+
54
+ const actorTrustContext: ActorTrustContext = {
55
+ canonicalSenderId,
56
+ guardianBindingMatch: verdict.guardianExternalUserId
57
+ ? {
58
+ guardianExternalUserId: verdict.guardianExternalUserId,
59
+ guardianDeliveryChatId: verdict.guardianDeliveryChatId ?? null,
60
+ }
61
+ : null,
62
+ guardianPrincipalId: verdict.guardianPrincipalId,
63
+ memberRecord: null,
64
+ trustClass: verdict.trustClass,
65
+ actorMetadata: {
66
+ identifier,
67
+ displayName: memberDisplayName ?? senderDisplayName,
68
+ senderDisplayName,
69
+ memberDisplayName,
70
+ username,
71
+ channel: input.sourceChannel,
72
+ trustStatus: verdict.trustClass,
73
+ },
74
+ };
75
+
76
+ const context = toTrustContext(
77
+ actorTrustContext,
78
+ input.conversationExternalId,
79
+ );
80
+
81
+ // Stamp the verdict's ACL member fields onto the context so downstream turn
82
+ // assembly reads member status/policy from the verdict rather than a local
83
+ // re-resolution. The contact ID anchors the local info-only join.
84
+ const member = resolvedMemberFromVerdict(verdict);
85
+ if (member) {
86
+ context.requesterContactId = member.contact.id;
87
+ context.memberStatus = channelStatusToMemberStatus(member.channel.status);
88
+ context.memberPolicy = member.channel.policy;
89
+ }
90
+
91
+ return context;
92
+ }
93
+
94
+ // Allowed ACL enum values, kept in sync with the ContactChannel union types.
95
+ const CHANNEL_STATUS_VALUES: readonly ChannelStatus[] = [
96
+ "active",
97
+ "pending",
98
+ "revoked",
99
+ "blocked",
100
+ "unverified",
101
+ ];
102
+ const CHANNEL_POLICY_VALUES: readonly ChannelPolicy[] = [
103
+ "allow",
104
+ "deny",
105
+ "escalate",
106
+ ];
107
+
108
+ function isChannelStatus(value: string): value is ChannelStatus {
109
+ return (CHANNEL_STATUS_VALUES as readonly string[]).includes(value);
110
+ }
111
+
112
+ function isChannelPolicy(value: string): value is ChannelPolicy {
113
+ return (CHANNEL_POLICY_VALUES as readonly string[]).includes(value);
114
+ }
115
+
116
+ /**
117
+ * Build a synthetic {@link ResolvedMember} from a gateway verdict.
118
+ *
119
+ * ACL + identity only; info fields are placeholders, re-joined locally by
120
+ * contactId. Returns null for memberless verdicts.
121
+ */
122
+ export function resolvedMemberFromVerdict(
123
+ verdict: TrustVerdict,
124
+ ): ResolvedMember | null {
125
+ if (!verdict.contactId || !verdict.channelId) return null;
126
+ // Member verdict requires valid known status+policy enums, else null
127
+ // (fail-closed): a partial/mixed-version verdict (absent OR
128
+ // present-but-unknown ACL value) must not synthesize an active/allow channel
129
+ // that would skip ingress ACL gates.
130
+ if (!verdict.status || !verdict.policy) return null;
131
+ if (!isChannelStatus(verdict.status) || !isChannelPolicy(verdict.policy)) {
132
+ return null;
133
+ }
134
+
135
+ const channel: ContactChannel = {
136
+ id: verdict.channelId,
137
+ contactId: verdict.contactId,
138
+ type: verdict.type ?? "",
139
+ address: verdict.address ?? "",
140
+ isPrimary: false,
141
+ externalChatId: verdict.externalChatId ?? null,
142
+ status: verdict.status,
143
+ policy: verdict.policy,
144
+ verifiedAt: verdict.verifiedAt ?? null,
145
+ verifiedVia: verdict.verifiedVia ?? null,
146
+ inviteId: null,
147
+ revokedReason: null,
148
+ blockedReason: null,
149
+ lastSeenAt: null,
150
+ interactionCount: 0,
151
+ lastInteraction: null,
152
+ updatedAt: null,
153
+ createdAt: 0,
154
+ };
155
+
156
+ const contact: ContactWithChannels = {
157
+ id: verdict.contactId,
158
+ displayName: verdict.memberDisplayName ?? "",
159
+ notes: null,
160
+ lastInteraction: null,
161
+ interactionCount: 0,
162
+ createdAt: 0,
163
+ updatedAt: 0,
164
+ role: verdict.trustClass === "guardian" ? "guardian" : "contact",
165
+ contactType: "human",
166
+ principalId: verdict.guardianPrincipalId ?? null,
167
+ userFile: null,
168
+ channels: [channel],
169
+ };
170
+
171
+ return { contact, channel };
172
+ }
@@ -1,3 +1,4 @@
1
+ import { getConfig } from "../config/loader.js";
1
2
  import {
2
3
  checkDiskPressureBackgroundGate,
3
4
  diskPressureBackgroundSkipLogFields,
@@ -85,14 +86,6 @@ const TICK_INTERVAL_MS = 15_000;
85
86
  */
86
87
  const WAKE_MAX_RETRIES = 20;
87
88
 
88
- /**
89
- * Hard timeout for `talk`-mode scheduled jobs. Schedules can do
90
- * non-trivial work (research, summarize the day, etc.), so the cap is
91
- * generous; it exists primarily so a wedged turn cannot block the next
92
- * scheduler tick indefinitely. Mirrors the heartbeat/filing budgets.
93
- */
94
- const SCHEDULE_TALK_TIMEOUT_MS = 30 * 60 * 1000;
95
-
96
89
  /**
97
90
  * Apply retry policy on schedule-execution failure. Retries are scheduled by
98
91
  * `applyRetryDecision`; once retries are exhausted, the `emitAlert` callback
@@ -362,6 +355,7 @@ export async function runScheduleDueWorkOnce(
362
355
  conversationId: wakeConversationId,
363
356
  hint: job.message,
364
357
  source: "defer",
358
+ persistTriggerAsEvent: true,
365
359
  ...(job.inferenceProfile
366
360
  ? { forceOverrideProfile: job.inferenceProfile }
367
361
  : {}),
@@ -718,7 +712,10 @@ export async function runScheduleDueWorkOnce(
718
712
  ...(job.inferenceProfile
719
713
  ? { overrideProfile: job.inferenceProfile }
720
714
  : {}),
721
- timeoutMs: SCHEDULE_TALK_TIMEOUT_MS,
715
+ // Hard timeout for talk-mode scheduled turns: bounds a wedged turn so
716
+ // it cannot block the next scheduler tick. Configurable via
717
+ // timeouts.scheduleTurnTimeoutSec (default 1800s).
718
+ timeoutMs: getConfig().timeouts.scheduleTurnTimeoutSec * 1000,
722
719
  origin: "schedule",
723
720
  groupId: "system:scheduled",
724
721
  conversationType: "scheduled",
@@ -241,7 +241,7 @@ import {
241
241
  } from "./activation-funnel.js";
242
242
  import { UsageTelemetryReporter } from "./usage-telemetry-reporter.js";
243
243
 
244
- initializeDb();
244
+ await initializeDb();
245
245
 
246
246
  // ---------------------------------------------------------------------------
247
247
  // Helpers
@@ -59,7 +59,9 @@ beforeEach(() => {
59
59
  };
60
60
  });
61
61
 
62
- const validInput = {
62
+ // A single question used to build batches. The tool only accepts the
63
+ // batched `{ questions: [...] }` shape.
64
+ const singleQ = {
63
65
  question: "Which fruit?",
64
66
  description: "Pick one to add to the smoothie.",
65
67
  options: [
@@ -69,12 +71,7 @@ const validInput = {
69
71
  freeTextPlaceholder: "Type a fruit",
70
72
  };
71
73
 
72
- const singleQ = {
73
- question: validInput.question,
74
- description: validInput.description,
75
- options: validInput.options,
76
- freeTextPlaceholder: validInput.freeTextPlaceholder,
77
- };
74
+ const validInput = { questions: [singleQ] };
78
75
 
79
76
  describe("askQuestionTool definition", () => {
80
77
  test("exposes the expected schema shape and description language", () => {
@@ -91,7 +88,6 @@ describe("askQuestionTool definition", () => {
91
88
  expect(def.description).toContain("remove guessing");
92
89
  expect(def.description).toContain("a question is skipped");
93
90
  expect(def.description).toContain("every question in the batch is skipped");
94
- // Batching language is back now that the prompter handles batches.
95
91
  expect(def.description).toContain("Batch related clarifications");
96
92
  expect(def.description).toContain("up to 5");
97
93
  expect(def.description).toContain("Skip button");
@@ -99,13 +95,23 @@ describe("askQuestionTool definition", () => {
99
95
  const schema = def.input_schema as {
100
96
  properties: Record<
101
97
  string,
102
- { type?: string; minItems?: number; maxItems?: number }
98
+ {
99
+ type?: string;
100
+ items?: {
101
+ properties?: Record<
102
+ string,
103
+ { type?: string; minItems?: number; maxItems?: number }
104
+ >;
105
+ };
106
+ }
103
107
  >;
104
108
  required?: string[];
105
109
  };
106
- expect(schema.properties.options?.type).toBe("array");
107
- expect(schema.properties.options?.minItems).toBe(2);
108
- expect(schema.properties.options?.maxItems).toBe(4);
110
+ const optionsSchema =
111
+ schema.properties.questions?.items?.properties?.options;
112
+ expect(optionsSchema?.type).toBe("array");
113
+ expect(optionsSchema?.minItems).toBe(2);
114
+ expect(optionsSchema?.maxItems).toBe(4);
109
115
  });
110
116
  });
111
117
 
@@ -132,17 +138,17 @@ describe("AskQuestionTool.execute", () => {
132
138
  expect(calls).toHaveLength(1);
133
139
  expect(calls[0]?.conversationId).toBe("conv-1");
134
140
  expect(calls[0]?.questions).toHaveLength(1);
135
- expect(calls[0]?.questions[0]?.question).toBe(validInput.question);
136
- expect(calls[0]?.questions[0]?.description).toBe(validInput.description);
137
- expect(calls[0]?.questions[0]?.options).toEqual(validInput.options);
141
+ expect(calls[0]?.questions[0]?.question).toBe(singleQ.question);
142
+ expect(calls[0]?.questions[0]?.description).toBe(singleQ.description);
143
+ expect(calls[0]?.questions[0]?.options).toEqual(singleQ.options);
138
144
  expect(calls[0]?.questions[0]?.freeTextPlaceholder).toBe(
139
- validInput.freeTextPlaceholder,
145
+ singleQ.freeTextPlaceholder,
140
146
  );
141
147
  expect(calls[0]?.toolUseId).toBe("tu-1");
142
148
 
143
149
  expect(result.isError).toBe(false);
144
150
  expect(result.content).toBe(
145
- `Question "${validInput.question}" → Option: a (Apple)`,
151
+ `Question "${singleQ.question}" → Option: a (Apple)`,
146
152
  );
147
153
  });
148
154
 
@@ -150,7 +156,7 @@ describe("AskQuestionTool.execute", () => {
150
156
  setNextResult(singleCompleted({ decision: "option", optionId: "b" }));
151
157
  const result = await askQuestionTool.execute(validInput, makeContext());
152
158
  expect(result.content).toBe(
153
- `Question "${validInput.question}" → Option: b (Banana)`,
159
+ `Question "${singleQ.question}" → Option: b (Banana)`,
154
160
  );
155
161
  expect(result.isError).toBe(false);
156
162
  });
@@ -159,7 +165,7 @@ describe("AskQuestionTool.execute", () => {
159
165
  setNextResult(singleCompleted({ decision: "option", optionId: "ghost" }));
160
166
  const result = await askQuestionTool.execute(validInput, makeContext());
161
167
  expect(result.content).toBe(
162
- `Question "${validInput.question}" → Option: ghost ((unknown))`,
168
+ `Question "${singleQ.question}" → Option: ghost ((unknown))`,
163
169
  );
164
170
  expect(result.isError).toBe(false);
165
171
  });
@@ -168,7 +174,7 @@ describe("AskQuestionTool.execute", () => {
168
174
  setNextResult(singleCompleted({ decision: "free_text", text: "Cherry" }));
169
175
  const result = await askQuestionTool.execute(validInput, makeContext());
170
176
  expect(result.content).toBe(
171
- `Question "${validInput.question}" → Free text: Cherry`,
177
+ `Question "${singleQ.question}" → Free text: Cherry`,
172
178
  );
173
179
  expect(result.isError).toBe(false);
174
180
  });
@@ -176,7 +182,7 @@ describe("AskQuestionTool.execute", () => {
176
182
  test("formats skipped result", async () => {
177
183
  setNextResult(singleCompleted({ decision: "skipped" }));
178
184
  const result = await askQuestionTool.execute(validInput, makeContext());
179
- expect(result.content).toBe(`Question "${validInput.question}" → Skipped`);
185
+ expect(result.content).toBe(`Question "${singleQ.question}" → Skipped`);
180
186
  expect(result.isError).toBe(false);
181
187
  });
182
188
 
@@ -200,10 +206,10 @@ describe("AskQuestionTool.execute", () => {
200
206
  expect(result.content).toBe("Question aborted");
201
207
  });
202
208
 
203
- test("rejects input with fewer than 2 options", async () => {
209
+ test("rejects a question with fewer than 2 options", async () => {
204
210
  setNextResult(singleCompleted({ decision: "option", optionId: "a" }));
205
211
  const result = await askQuestionTool.execute(
206
- { ...validInput, options: [{ id: "a", label: "Apple" }] },
212
+ { questions: [{ ...singleQ, options: [{ id: "a", label: "Apple" }] }] },
207
213
  makeContext(),
208
214
  );
209
215
  expect(result.isError).toBe(true);
@@ -211,17 +217,21 @@ describe("AskQuestionTool.execute", () => {
211
217
  expect(calls).toHaveLength(0);
212
218
  });
213
219
 
214
- test("rejects input with more than 4 options", async () => {
220
+ test("rejects a question with more than 4 options", async () => {
215
221
  setNextResult(singleCompleted({ decision: "option", optionId: "a" }));
216
222
  const result = await askQuestionTool.execute(
217
223
  {
218
- ...validInput,
219
- options: [
220
- { id: "a", label: "A" },
221
- { id: "b", label: "B" },
222
- { id: "c", label: "C" },
223
- { id: "d", label: "D" },
224
- { id: "e", label: "E" },
224
+ questions: [
225
+ {
226
+ ...singleQ,
227
+ options: [
228
+ { id: "a", label: "A" },
229
+ { id: "b", label: "B" },
230
+ { id: "c", label: "C" },
231
+ { id: "d", label: "D" },
232
+ { id: "e", label: "E" },
233
+ ],
234
+ },
225
235
  ],
226
236
  },
227
237
  makeContext(),
@@ -230,10 +240,10 @@ describe("AskQuestionTool.execute", () => {
230
240
  expect(calls).toHaveLength(0);
231
241
  });
232
242
 
233
- test("rejects input with empty question", async () => {
243
+ test("rejects a question with empty text", async () => {
234
244
  setNextResult(singleCompleted({ decision: "option", optionId: "a" }));
235
245
  const result = await askQuestionTool.execute(
236
- { ...validInput, question: "" },
246
+ { questions: [{ ...singleQ, question: "" }] },
237
247
  makeContext(),
238
248
  );
239
249
  expect(result.isError).toBe(true);
@@ -254,18 +264,6 @@ describe("AskQuestionTool.execute", () => {
254
264
  // ── Batched input ───────────────────────────────────────────────────
255
265
 
256
266
  describe("AskQuestionTool batched input", () => {
257
- test("normalizes legacy flat input into a one-element batch forwarded to the prompter", async () => {
258
- setNextResult(singleCompleted({ decision: "option", optionId: "a" }));
259
-
260
- const result = await askQuestionTool.execute(validInput, makeContext());
261
-
262
- expect(calls).toHaveLength(1);
263
- expect(calls[0]?.questions).toHaveLength(1);
264
- expect(calls[0]?.questions[0]?.question).toBe(validInput.question);
265
- expect(calls[0]?.questions[0]?.options).toEqual(validInput.options);
266
- expect(result.isError).toBe(false);
267
- });
268
-
269
267
  test("accepts a single-element `questions` batch", async () => {
270
268
  setNextResult(singleCompleted({ decision: "option", optionId: "a" }));
271
269
 
@@ -454,7 +452,7 @@ describe("AskQuestionTool batched input", () => {
454
452
  expect(calls).toHaveLength(0);
455
453
  });
456
454
 
457
- test("rejects input missing both `questions` and flat fields", async () => {
455
+ test("rejects input missing `questions`", async () => {
458
456
  setNextResult(singleCompleted({ decision: "option", optionId: "a" }));
459
457
 
460
458
  const result = await askQuestionTool.execute({}, makeContext());
@@ -464,11 +462,17 @@ describe("AskQuestionTool batched input", () => {
464
462
  expect(calls).toHaveLength(0);
465
463
  });
466
464
 
467
- test("rejects legacy `question` without `options`", async () => {
465
+ test("rejects the dropped flat single-question shape", async () => {
468
466
  setNextResult(singleCompleted({ decision: "option", optionId: "a" }));
469
467
 
470
468
  const result = await askQuestionTool.execute(
471
- { question: "Hi?" },
469
+ {
470
+ question: "Hi?",
471
+ options: [
472
+ { id: "a", label: "A" },
473
+ { id: "b", label: "B" },
474
+ ],
475
+ },
472
476
  makeContext(),
473
477
  );
474
478
 
@@ -479,7 +483,7 @@ describe("AskQuestionTool batched input", () => {
479
483
  });
480
484
 
481
485
  describe("askQuestionTool definition (batched schema)", () => {
482
- test("exposes `questions[]` shape, keeps legacy fields, omits per-question id", () => {
486
+ test("exposes `questions[]` shape, requires it, and drops the flat fields", () => {
483
487
  const def = askQuestionTool;
484
488
  const schema = def.input_schema as unknown as {
485
489
  properties: Record<
@@ -517,8 +521,12 @@ describe("askQuestionTool definition (batched schema)", () => {
517
521
 
518
522
  expect(questions?.items?.required).toEqual(["question", "options"]);
519
523
 
520
- // Legacy fields still present.
521
- expect(schema.properties.question).toBeDefined();
522
- expect(schema.properties.options).toBeDefined();
524
+ // `questions` is the only top-level input now.
525
+ expect(schema.required).toEqual(["questions"]);
526
+ expect(Object.keys(schema.properties)).toEqual(["questions"]);
527
+
528
+ // The legacy flat fields are gone.
529
+ expect(schema.properties.question).toBeUndefined();
530
+ expect(schema.properties.options).toBeUndefined();
523
531
  });
524
532
  });
@@ -40,35 +40,16 @@ const SingleQuestionSchema = z.object({
40
40
  // input with ≥6 entries is rejected with a clear Zod error.
41
41
  const MAX_QUESTIONS_PER_BATCH = 5;
42
42
 
43
- // Both the new batched shape (`questions[]`) and the legacy flat shape are
44
- // accepted. `execute()` normalizes legacy callers into a one-element
45
- // `questions` array before forwarding to the prompter.
46
- const InputSchema = z
47
- .object({
48
- questions: z
49
- .array(SingleQuestionSchema)
50
- .min(1)
51
- .max(MAX_QUESTIONS_PER_BATCH, {
52
- message: `At most ${MAX_QUESTIONS_PER_BATCH} questions per batch; split into multiple turns if you need more.`,
53
- })
54
- .optional(),
55
- // Legacy flat fields. Optional so batched callers can omit them; when
56
- // present and `questions` is absent, they are normalized into a
57
- // one-element batch in `execute()`.
58
- question: z.string().min(1).optional(),
59
- description: z.string().optional(),
60
- options: z.array(OptionSchema).min(2).max(4).optional(),
61
- freeTextPlaceholder: z.string().optional(),
62
- })
63
- .refine(
64
- (v) =>
65
- v.questions !== undefined ||
66
- (v.question !== undefined && v.options !== undefined),
67
- {
68
- message:
69
- "Provide `questions` (preferred) or the legacy flat fields (`question` + `options`).",
70
- },
71
- );
43
+ // Callers pass a (possibly single-element) batch of questions. `execute()`
44
+ // forwards them straight to the prompter.
45
+ const InputSchema = z.object({
46
+ questions: z
47
+ .array(SingleQuestionSchema)
48
+ .min(1)
49
+ .max(MAX_QUESTIONS_PER_BATCH, {
50
+ message: `At most ${MAX_QUESTIONS_PER_BATCH} questions per batch; split into multiple turns if you need more.`,
51
+ }),
52
+ });
72
53
 
73
54
  export type SingleQuestion = z.infer<typeof SingleQuestionSchema>;
74
55
  export type AskQuestionInput = z.infer<typeof InputSchema>;
@@ -111,8 +92,7 @@ const DESCRIPTION = [
111
92
  "context shown beneath the label.",
112
93
  ].join("\n");
113
94
 
114
- // Shared option-schema fragment used by both the batched `questions[]`
115
- // shape and the legacy flat `options` field.
95
+ // Option-schema fragment for the items in `questions[].options`.
116
96
  const OPTION_ITEMS_SCHEMA = {
117
97
  type: "object",
118
98
  properties: {
@@ -150,12 +130,11 @@ export const askQuestionTool = {
150
130
  input_schema: {
151
131
  type: "object",
152
132
  properties: {
153
- // ── Recommended shape ─────────────────────────────────────
154
133
  questions: {
155
134
  type: "array",
156
135
  minItems: 1,
157
136
  maxItems: MAX_QUESTIONS_PER_BATCH,
158
- description: `Recommended shape. 1–${MAX_QUESTIONS_PER_BATCH} clarifying questions to ask in a single turn. Use a batch when several independent ambiguities block progress; ask one at a time when they're sequentially dependent. Past ${MAX_QUESTIONS_PER_BATCH} questions you should be implementing, not asking.`,
137
+ description: `1–${MAX_QUESTIONS_PER_BATCH} clarifying questions to ask in a single turn. Use a batch when several independent ambiguities block progress; ask one at a time when they're sequentially dependent. Past ${MAX_QUESTIONS_PER_BATCH} questions you should be implementing, not asking.`,
159
138
  items: {
160
139
  type: "object",
161
140
  properties: {
@@ -185,35 +164,8 @@ export const askQuestionTool = {
185
164
  required: ["question", "options"],
186
165
  },
187
166
  },
188
- // ── Legacy single-question fields ─────────────────────────
189
- // Kept optional so existing prompt caches and any single-question
190
- // callers continue to work. New callers should use `questions`.
191
- question: {
192
- type: "string",
193
- description:
194
- "Legacy: the single clarifying question. Prefer `questions[]` for new code.",
195
- },
196
- description: {
197
- type: "string",
198
- description:
199
- "Legacy: optional one-line context shown beneath the question. Prefer `questions[].description`.",
200
- },
201
- options: {
202
- type: "array",
203
- minItems: 2,
204
- maxItems: 4,
205
- description:
206
- "Legacy: 2–4 structured options. Prefer `questions[].options`. The UI always appends a free-text fallback slot, so do not include a 'something else' option here.",
207
- items: OPTION_ITEMS_SCHEMA,
208
- },
209
- freeTextPlaceholder: {
210
- type: "string",
211
- description:
212
- "Legacy: optional placeholder text for the free-text fallback input. Prefer `questions[].freeTextPlaceholder`.",
213
- },
214
167
  },
215
- // No top-level `required` — caller must supply either `questions`
216
- // or the legacy flat trio (`question` + `options`). Enforced in Zod.
168
+ required: ["questions"],
217
169
  },
218
170
 
219
171
  async execute(
@@ -228,18 +180,7 @@ export const askQuestionTool = {
228
180
  };
229
181
  }
230
182
 
231
- // Normalize legacy flat input into a one-element `questions` batch so
232
- // downstream code only has to deal with the batched shape. The refine
233
- // above guarantees `question` and `options` are present whenever
234
- // `questions` is absent.
235
- const questions: SingleQuestion[] = parsed.data.questions ?? [
236
- {
237
- question: parsed.data.question!,
238
- description: parsed.data.description,
239
- options: parsed.data.options!,
240
- freeTextPlaceholder: parsed.data.freeTextPlaceholder,
241
- },
242
- ];
183
+ const questions: SingleQuestion[] = parsed.data.questions;
243
184
 
244
185
  const prompter = new QuestionPrompter();
245
186
  const result = await prompter.prompt({
@@ -296,4 +296,24 @@ describe("executeBrowserStatus", () => {
296
296
  expect(extension.available).toBe(true);
297
297
  expect(extension.details.transport).toBe("extension-ws");
298
298
  });
299
+
300
+ test("reports extension as connected when probe fails on the Chrome Web Store / extensions gallery", async () => {
301
+ mockSingletonProxy = { isAvailable: () => true, hasExtensionClient: () => true, request: () => {} };
302
+ probeOutcomes[BROWSER_STATUS_MODE.EXTENSION] = "fail";
303
+ probeErrors[BROWSER_STATUS_MODE.EXTENSION] = new CdpError(
304
+ "cdp_error",
305
+ "The extensions gallery cannot be scripted.",
306
+ );
307
+
308
+ const result = await executeBrowserStatus({}, makeContext());
309
+ expect(result.isError).toBe(false);
310
+ const payload = JSON.parse(result.content);
311
+ const extension = payload.modes.find(
312
+ (m: { mode: string }) => m.mode === BROWSER_STATUS_MODE.EXTENSION,
313
+ );
314
+ expect(extension).toBeDefined();
315
+ expect(extension.available).toBe(true);
316
+ expect(extension.verified).toBe("active_probe");
317
+ expect(extension.details.restrictedActiveTab).toBe(true);
318
+ });
299
319
  });
@@ -345,10 +345,22 @@ function collectRemediationHints(
345
345
 
346
346
  /**
347
347
  * Detect the common extension CDP failure where the active tab is a
348
- * restricted Chrome internal page (e.g. `chrome://newtab`).
348
+ * page Chrome forbids extensions from scripting — either a privileged
349
+ * `chrome://` internal page (e.g. `chrome://newtab`) or the Chrome Web
350
+ * Store / extensions gallery (which yields "The extensions gallery
351
+ * cannot be scripted."). The latter is especially common right after
352
+ * install, when the Web Store page is still the active tab.
353
+ *
354
+ * Keep this restricted-error match in sync with the Page.navigate
355
+ * recovery in the chrome-extension dispatcher (host-browser-dispatcher.ts,
356
+ * separate package, duplicated by necessity): the status side reports the
357
+ * tab as recoverable, and the navigate side must actually recover it.
349
358
  */
350
359
  function isRestrictedChromePageProbeError(error: CdpError): boolean {
351
- return error.message.toLowerCase().includes("chrome://");
360
+ const message = error.message.toLowerCase();
361
+ return (
362
+ message.includes("chrome://") || message.includes("cannot be scripted")
363
+ );
352
364
  }
353
365
 
354
366
  /**
@@ -2450,9 +2462,9 @@ async function checkExtensionModeStatus(
2450
2462
  verified: "active_probe",
2451
2463
  autoCandidate,
2452
2464
  summary:
2453
- "Extension mode transport is connected, but the active Chrome tab is a restricted chrome:// page. Switch to a regular website tab if browser actions fail.",
2465
+ "Extension mode transport is connected, but the active Chrome tab is a page Chrome won't let extensions script (a chrome:// page or the Chrome Web Store / extensions gallery). Switch to a regular website tab if browser actions fail.",
2454
2466
  userActions: [
2455
- "Switch Chrome to a regular http(s) tab (not chrome://...) and retry.",
2467
+ "Switch Chrome to a regular http(s) tab not a chrome:// page or the Chrome Web Store / extensions gallery — and retry.",
2456
2468
  ],
2457
2469
  tradeoffs: modeTradeoffs(BROWSER_STATUS_MODE.EXTENSION),
2458
2470
  details: {
@@ -20,7 +20,7 @@ import {
20
20
  executeCommentResolve,
21
21
  } from "./document-comment-tool.js";
22
22
 
23
- initializeDb();
23
+ await initializeDb();
24
24
 
25
25
  // ---------------------------------------------------------------------------
26
26
  // Helpers