@vellumai/assistant 0.8.10 → 0.8.11-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 (400) hide show
  1. package/bun.lock +62 -1
  2. package/docs/workspace-tools.md +196 -0
  3. package/examples/plugins/echo/README.md +3 -3
  4. package/knip.json +1 -0
  5. package/openapi.yaml +460 -128
  6. package/package.json +2 -1
  7. package/scripts/build-plugin-api.ts +299 -0
  8. package/src/__tests__/agent-loop-callsite-precedence.test.ts +7 -0
  9. package/src/__tests__/agent-loop-compaction-events.test.ts +197 -0
  10. package/src/__tests__/agent-loop-exit-reason.test.ts +93 -96
  11. package/src/__tests__/agent-loop-mutable-latest-user-message.test.ts +2 -0
  12. package/src/__tests__/agent-loop-output-hooks.test.ts +274 -1
  13. package/src/__tests__/agent-loop-override-profile.test.ts +3 -0
  14. package/src/__tests__/agent-loop-provider-error-recording.test.ts +4 -0
  15. package/src/__tests__/agent-loop-thinking.test.ts +4 -0
  16. package/src/__tests__/agent-loop.test.ts +578 -5
  17. package/src/__tests__/agent-wake-disk-pressure-callsite.test.ts +0 -1
  18. package/src/__tests__/approval-cascade.test.ts +1 -0
  19. package/src/__tests__/background-workers-disk-pressure.test.ts +0 -2
  20. package/src/__tests__/btw-routes.test.ts +0 -1
  21. package/src/__tests__/build-persisted-content.test.ts +75 -1
  22. package/src/__tests__/catalog-install-normalize.test.ts +141 -0
  23. package/src/__tests__/ces-startup-timeout.test.ts +60 -0
  24. package/src/__tests__/compaction-events.test.ts +1 -0
  25. package/src/__tests__/config-managed-gemini-defaults.test.ts +2 -46
  26. package/src/__tests__/context-overflow-reducer.test.ts +264 -124
  27. package/src/__tests__/context-window-manager-overflow-rung.test.ts +351 -0
  28. package/src/__tests__/conversation-abort-tool-results.test.ts +1 -1
  29. package/src/__tests__/conversation-agent-loop-inference-profile.test.ts +13 -5
  30. package/src/__tests__/conversation-agent-loop-overflow.test.ts +284 -455
  31. package/src/__tests__/conversation-agent-loop.test.ts +131 -551
  32. package/src/__tests__/conversation-app-control-instantiation.test.ts +13 -0
  33. package/src/__tests__/conversation-confirmation-signals.test.ts +1 -0
  34. package/src/__tests__/conversation-fork-crud.test.ts +259 -0
  35. package/src/__tests__/conversation-history-web-search.test.ts +1 -1
  36. package/src/__tests__/conversation-lifecycle.test.ts +257 -1
  37. package/src/__tests__/conversation-process-callsite.test.ts +1 -0
  38. package/src/__tests__/conversation-provider-retry-repair.test.ts +38 -377
  39. package/src/__tests__/conversation-queue.test.ts +1 -39
  40. package/src/__tests__/conversation-runtime-assembly.test.ts +119 -8
  41. package/src/__tests__/conversation-skill-tools.test.ts +491 -5
  42. package/src/__tests__/conversation-slash-queue.test.ts +1 -1
  43. package/src/__tests__/conversation-slash-unknown.test.ts +1 -0
  44. package/src/__tests__/conversation-speed-override.test.ts +1 -0
  45. package/src/__tests__/conversation-store.test.ts +74 -0
  46. package/src/__tests__/conversation-surfaces-app-control.test.ts +4 -1
  47. package/src/__tests__/conversation-tool-setup-attribution.test.ts +323 -0
  48. package/src/__tests__/conversation-tool-setup-tools-disabled.test.ts +34 -0
  49. package/src/__tests__/conversation-workspace-cache-state.test.ts +1 -0
  50. package/src/__tests__/conversation-workspace-injection.test.ts +1 -1
  51. package/src/__tests__/conversation-workspace-tool-tracking.test.ts +1 -0
  52. package/src/__tests__/corrected-target.test.ts +93 -0
  53. package/src/__tests__/credential-execution-feature-gates.test.ts +3 -5
  54. package/src/__tests__/credential-execution-tools.test.ts +23 -11
  55. package/src/__tests__/credential-security-invariants.test.ts +6 -1
  56. package/src/__tests__/db-schedule-syntax-migration.test.ts +80 -0
  57. package/src/__tests__/device-id.test.ts +70 -1
  58. package/src/__tests__/embedding-managed-proxy-selection.test.ts +6 -40
  59. package/src/__tests__/empty-response-hook.test.ts +242 -66
  60. package/src/__tests__/external-plugin-loader.test.ts +0 -31
  61. package/src/__tests__/get-skill-detail-audit.test.ts +43 -1
  62. package/src/__tests__/guardian-routing-invariants.test.ts +91 -0
  63. package/src/__tests__/history-repair-hook.test.ts +228 -3
  64. package/src/__tests__/host-app-control-proxy.test.ts +45 -0
  65. package/src/__tests__/host-browser-proxy.test.ts +254 -9
  66. package/src/__tests__/identity-routes.test.ts +1 -0
  67. package/src/__tests__/image-recovery-hook.test.ts +387 -0
  68. package/src/__tests__/injector-chain.test.ts +5 -4
  69. package/src/__tests__/injector-v3-suppression.test.ts +373 -47
  70. package/src/__tests__/intent-routing.test.ts +7 -0
  71. package/src/__tests__/memory-retrieval-hook.test.ts +117 -15
  72. package/src/__tests__/notification-decision-strategy.test.ts +3 -3
  73. package/src/__tests__/oauth-store.test.ts +0 -85
  74. package/src/__tests__/{context-overflow-policy.test.ts → overflow-policy.test.ts} +1 -1
  75. package/src/__tests__/parallel-tool.benchmark.test.ts +4 -0
  76. package/src/__tests__/persist-unsendable-image-downscale.test.ts +29 -9
  77. package/src/__tests__/persist-unsendable-image.test.ts +4 -4
  78. package/src/__tests__/persistence-secret-redaction.test.ts +78 -0
  79. package/src/__tests__/plugin-bootstrap.test.ts +82 -73
  80. package/src/__tests__/plugin-tool-contribution.test.ts +7 -4
  81. package/src/__tests__/plugin-types.test.ts +0 -8
  82. package/src/__tests__/provider-catalog-visibility.test.ts +1 -9
  83. package/src/__tests__/prune-old-conversations-job.test.ts +99 -0
  84. package/src/__tests__/registry.test.ts +240 -1
  85. package/src/__tests__/require-fresh-approval.test.ts +3 -0
  86. package/src/__tests__/schedule-routes.test.ts +116 -1
  87. package/src/__tests__/schedule-store.test.ts +28 -0
  88. package/src/__tests__/schedule-tools.test.ts +94 -1
  89. package/src/__tests__/server-history-render.test.ts +39 -0
  90. package/src/__tests__/skill-projection-feature-flag.test.ts +13 -0
  91. package/src/__tests__/skill-projection.benchmark.test.ts +25 -7
  92. package/src/__tests__/skills.test.ts +202 -0
  93. package/src/__tests__/slim-skill-category.test.ts +195 -0
  94. package/src/__tests__/strip-memory-injections.test.ts +33 -39
  95. package/src/__tests__/test-support/tool-invocation-seed.ts +79 -0
  96. package/src/__tests__/title-generate-hook.test.ts +9 -7
  97. package/src/__tests__/tool-audit-listener.test.ts +264 -1
  98. package/src/__tests__/tool-error-hook.test.ts +4 -3
  99. package/src/__tests__/tool-execution-pipeline.benchmark.test.ts +1 -0
  100. package/src/__tests__/tool-executor-lifecycle-events.test.ts +273 -0
  101. package/src/__tests__/tool-result-truncate-hook.test.ts +1 -0
  102. package/src/__tests__/tool-start-timestamp.test.ts +218 -0
  103. package/src/__tests__/tools-get-route.test.ts +202 -0
  104. package/src/__tests__/workspace-tool-loader.test.ts +319 -0
  105. package/src/__tests__/workspace-tools-watcher-flag.test.ts +70 -0
  106. package/src/agent/loop.ts +569 -319
  107. package/src/api/events/tool-result.ts +9 -0
  108. package/src/api/events/tool-use-start.ts +7 -0
  109. package/src/api/index.ts +10 -0
  110. package/src/api/responses/conversation-message.ts +135 -27
  111. package/src/api/responses/memory-v3-selection-log.ts +4 -4
  112. package/src/approvals/guardian-request-resolvers.ts +26 -0
  113. package/src/browser-session/backends/host-bridge.ts +29 -0
  114. package/src/browser-session/index.ts +1 -0
  115. package/src/browser-session/types.ts +5 -1
  116. package/src/cli/commands/__tests__/schedules.test.ts +62 -4
  117. package/src/cli/commands/__tests__/skills.test.ts +53 -0
  118. package/src/cli/commands/channel-verification-sessions.ts +6 -6
  119. package/src/cli/commands/inference-providers.ts +0 -8
  120. package/src/cli/commands/plugins.ts +2 -2
  121. package/src/cli/commands/schedules.ts +27 -4
  122. package/src/cli/commands/skills.ts +187 -146
  123. package/src/cli/commands/tools.ts +106 -0
  124. package/src/cli/lib/__tests__/install-from-github.test.ts +256 -328
  125. package/src/cli/lib/__tests__/plugin-catalog-cache.test.ts +6 -2
  126. package/src/cli/lib/__tests__/plugin-details.test.ts +10 -16
  127. package/src/cli/lib/__tests__/plugin-marketplace.test.ts +2 -2
  128. package/src/cli/lib/__tests__/search-plugins.test.ts +145 -240
  129. package/src/cli/lib/install-from-github.ts +187 -117
  130. package/src/cli/lib/plugin-catalog-cache.ts +9 -9
  131. package/src/cli/lib/plugin-details.ts +38 -68
  132. package/src/cli/lib/plugin-marketplace.ts +42 -14
  133. package/src/cli/lib/search-plugins.ts +29 -129
  134. package/src/cli/program.ts +2 -0
  135. package/src/config/bundled-skills/acp/SKILL.md +1 -0
  136. package/src/config/bundled-skills/app-builder/SKILL.md +1 -0
  137. package/src/config/bundled-skills/app-control/SKILL.md +1 -0
  138. package/src/config/bundled-skills/computer-use/SKILL.md +1 -0
  139. package/src/config/bundled-skills/contacts/SKILL.md +1 -0
  140. package/src/config/bundled-skills/document-editor/SKILL.md +1 -0
  141. package/src/config/bundled-skills/followups/SKILL.md +1 -0
  142. package/src/config/bundled-skills/image-studio/SKILL.md +1 -0
  143. package/src/config/bundled-skills/media-processing/SKILL.md +1 -0
  144. package/src/config/bundled-skills/messaging/SKILL.md +1 -0
  145. package/src/config/bundled-skills/phone-calls/SKILL.md +1 -0
  146. package/src/config/bundled-skills/playbooks/SKILL.md +1 -0
  147. package/src/config/bundled-skills/schedule/SKILL.md +1 -0
  148. package/src/config/bundled-skills/schedule/TOOLS.json +11 -3
  149. package/src/config/bundled-skills/sequences/SKILL.md +1 -0
  150. package/src/config/bundled-skills/settings/SKILL.md +1 -0
  151. package/src/config/bundled-skills/skill-management/SKILL.md +101 -1
  152. package/src/config/bundled-skills/subagent/SKILL.md +1 -0
  153. package/src/config/bundled-skills/transcribe/SKILL.md +1 -0
  154. package/src/config/env-registry.ts +23 -0
  155. package/src/config/feature-flag-registry.json +17 -81
  156. package/src/config/loader.ts +5 -22
  157. package/src/config/schema.ts +2 -0
  158. package/src/config/schemas/__tests__/compaction-logs.test.ts +56 -0
  159. package/src/config/schemas/__tests__/memory-v2.test.ts +0 -1
  160. package/src/config/schemas/__tests__/memory-v3.test.ts +61 -1
  161. package/src/config/schemas/compaction-logs.ts +79 -0
  162. package/src/config/schemas/memory-v2.ts +0 -8
  163. package/src/config/schemas/memory-v3.ts +104 -33
  164. package/src/config/seed-inference-profiles.ts +1 -1
  165. package/src/config/skills.ts +117 -47
  166. package/src/context/compactor.ts +11 -0
  167. package/src/context/strip-injections.ts +38 -4
  168. package/src/credential-execution/feature-gates.ts +0 -21
  169. package/src/credential-execution/startup-timeout.ts +32 -4
  170. package/src/daemon/__tests__/conversation-tool-setup-exclude.test.ts +18 -0
  171. package/src/daemon/conversation-agent-loop-handlers.ts +140 -91
  172. package/src/daemon/conversation-agent-loop.ts +123 -658
  173. package/src/daemon/conversation-error.ts +6 -33
  174. package/src/daemon/conversation-lifecycle.ts +1 -1
  175. package/src/daemon/conversation-runtime-assembly.ts +183 -22
  176. package/src/daemon/conversation-skill-tools.ts +137 -8
  177. package/src/daemon/conversation-slash.ts +0 -14
  178. package/src/daemon/conversation-store.ts +2 -19
  179. package/src/daemon/conversation-tool-setup.ts +87 -1
  180. package/src/daemon/conversation.ts +119 -50
  181. package/src/daemon/external-plugins-bootstrap.ts +36 -95
  182. package/src/daemon/handlers/config-channels.ts +11 -2
  183. package/src/daemon/handlers/shared.ts +9 -1
  184. package/src/daemon/handlers/skills.ts +10 -4
  185. package/src/daemon/host-app-control-proxy.ts +72 -57
  186. package/src/daemon/host-browser-proxy.ts +117 -22
  187. package/src/daemon/lifecycle.ts +34 -5
  188. package/src/daemon/message-protocol.ts +0 -7
  189. package/src/daemon/message-types/schedules.ts +1 -0
  190. package/src/daemon/message-types/skills.ts +17 -0
  191. package/src/daemon/providers-setup.ts +3 -0
  192. package/src/daemon/server.ts +3 -3
  193. package/src/daemon/tool-setup-types.ts +9 -3
  194. package/src/daemon/trust-context.ts +23 -0
  195. package/src/daemon/workspace-tools-watcher.ts +324 -0
  196. package/src/events/tool-audit-listener.ts +78 -16
  197. package/src/events/tool-metrics-listener.ts +2 -5
  198. package/src/memory/__tests__/compaction-log-writer-clickhouse.test.ts +227 -0
  199. package/src/memory/__tests__/conversation-queries.test.ts +176 -0
  200. package/src/memory/__tests__/jobs-worker-v2-schedule.test.ts +20 -32
  201. package/src/memory/compaction-log-writer-clickhouse.ts +418 -0
  202. package/src/memory/conversation-crud.ts +134 -3
  203. package/src/memory/conversation-queries.ts +64 -7
  204. package/src/memory/db-init.ts +14 -0
  205. package/src/memory/embedding-backend.test.ts +130 -1
  206. package/src/memory/embedding-backend.ts +79 -106
  207. package/src/memory/embedding-gemini.ts +5 -0
  208. package/src/memory/graph/__tests__/conversation-graph-memory-v2-routing.test.ts +12 -0
  209. package/src/memory/graph/__tests__/handle-remember-v2.test.ts +19 -0
  210. package/src/memory/graph/conversation-graph-memory.ts +36 -25
  211. package/src/memory/graph/tool-handlers.ts +3 -0
  212. package/src/memory/job-handlers/cleanup.ts +3 -1
  213. package/src/memory/jobs-store.ts +0 -28
  214. package/src/memory/jobs-worker.ts +10 -22
  215. package/src/memory/memory-marker.ts +29 -0
  216. package/src/memory/memory-retrospective-startup-cleanup.ts +1 -1
  217. package/src/memory/migrations/268-add-memory-v3-selections.ts +6 -0
  218. package/src/memory/migrations/270-schedule-description.ts +36 -0
  219. package/src/memory/migrations/275-tool-invocations-add-skill-id.test.ts +81 -0
  220. package/src/memory/migrations/275-tool-invocations-add-skill-id.ts +20 -0
  221. package/src/memory/migrations/276-tool-invocations-created-at-id-index.test.ts +68 -0
  222. package/src/memory/migrations/276-tool-invocations-created-at-id-index.ts +20 -0
  223. package/src/memory/migrations/277-add-memory-v3-ever-injected.ts +29 -0
  224. package/src/memory/migrations/278-tool-invocations-telemetry-columns.test.ts +96 -0
  225. package/src/memory/migrations/278-tool-invocations-telemetry-columns.ts +39 -0
  226. package/src/memory/migrations/279-create-skill-loaded-events.test.ts +84 -0
  227. package/src/memory/migrations/279-create-skill-loaded-events.ts +26 -0
  228. package/src/memory/migrations/280-conversations-surfaced-at.test.ts +88 -0
  229. package/src/memory/migrations/280-conversations-surfaced-at.ts +24 -0
  230. package/src/memory/migrations/index.ts +10 -0
  231. package/src/memory/migrations/registry.ts +8 -0
  232. package/src/memory/schema/conversations.ts +16 -0
  233. package/src/memory/schema/infrastructure.ts +26 -0
  234. package/src/memory/skill-loaded-events-store.test.ts +160 -0
  235. package/src/memory/skill-loaded-events-store.ts +95 -0
  236. package/src/memory/tool-executed-events-store.test.ts +219 -0
  237. package/src/memory/tool-executed-events-store.ts +102 -0
  238. package/src/memory/tool-usage-store.ts +15 -3
  239. package/src/memory/v2/__tests__/consolidation-job.test.ts +117 -12
  240. package/src/memory/v2/__tests__/consolidation-prompt-flag-gating-guard.test.ts +189 -0
  241. package/src/memory/v2/__tests__/injected-block-slugs.test.ts +90 -0
  242. package/src/memory/v2/__tests__/page-store.test.ts +33 -0
  243. package/src/memory/v2/__tests__/prompts-consolidation.test.ts +88 -15
  244. package/src/memory/v2/activation-store.ts +50 -1
  245. package/src/memory/v2/consolidation-job.ts +113 -29
  246. package/src/memory/v2/injected-block-slugs.ts +79 -0
  247. package/src/memory/v2/injection.ts +6 -1
  248. package/src/memory/v2/prompts/consolidation.ts +414 -13
  249. package/src/memory/v2/router.ts +2 -28
  250. package/src/memory/v2/static-context.ts +1 -1
  251. package/src/memory/v2/types.ts +16 -0
  252. package/src/notifications/__tests__/copy-composer.test.ts +244 -0
  253. package/src/notifications/access-request-copy.ts +298 -0
  254. package/src/notifications/adapters/slack.ts +3 -3
  255. package/src/notifications/adapters/telegram.ts +2 -1
  256. package/src/notifications/copy-composer.ts +49 -267
  257. package/src/notifications/decision-engine.ts +16 -35
  258. package/src/notifications/home-feed-side-effect.ts +1 -6
  259. package/src/oauth/oauth-store.ts +0 -9
  260. package/src/permissions/checker.test.ts +83 -1
  261. package/src/permissions/checker.ts +25 -2
  262. package/src/permissions/gateway-threshold-reader.test.ts +182 -0
  263. package/src/permissions/gateway-threshold-reader.ts +80 -0
  264. package/src/platform/client.ts +1 -3
  265. package/src/platform/feature-gate.ts +3 -12
  266. package/src/plugin-api/constants.ts +4 -2
  267. package/src/plugin-api/index.ts +63 -11
  268. package/src/plugin-api/types.ts +236 -71
  269. package/src/plugins/defaults/compaction/compact.ts +66 -2
  270. package/src/plugins/defaults/compaction/context-overflow-reducer.ts +240 -32
  271. package/src/plugins/defaults/compaction/corrected-target.ts +53 -0
  272. package/src/{daemon/context-overflow-policy.ts → plugins/defaults/compaction/overflow-policy.ts} +1 -1
  273. package/src/plugins/defaults/compaction/window-manager.ts +303 -1
  274. package/src/plugins/defaults/empty-response/hooks/post-model-call.ts +173 -0
  275. package/src/plugins/defaults/empty-response/hooks/stop.ts +11 -115
  276. package/src/plugins/defaults/empty-response/nudge-state-store.ts +46 -0
  277. package/src/plugins/defaults/history-repair/hooks/post-model-call.ts +50 -0
  278. package/src/plugins/defaults/history-repair/hooks/stop.ts +22 -0
  279. package/src/plugins/defaults/history-repair/repair-state-store.ts +51 -0
  280. package/src/plugins/defaults/history-repair/terminal.ts +39 -2
  281. package/src/plugins/defaults/image-recovery/detect.ts +25 -0
  282. package/src/plugins/defaults/image-recovery/hooks/post-model-call.ts +73 -0
  283. package/src/plugins/defaults/image-recovery/hooks/stop.ts +22 -0
  284. package/src/plugins/defaults/image-recovery/image-recovery-state-store.ts +48 -0
  285. package/src/plugins/defaults/image-recovery/package.json +14 -0
  286. package/src/{daemon/persist-unsendable-image.ts → plugins/defaults/image-recovery/recover.ts} +67 -14
  287. package/src/plugins/defaults/index.ts +71 -5
  288. package/src/plugins/defaults/memory-retrieval/hooks/post-compact.ts +76 -112
  289. package/src/plugins/defaults/memory-retrieval/hooks/{user-prompt-submit-temp.ts → user-prompt-submit.ts} +83 -74
  290. package/src/plugins/defaults/memory-retrieval/injector-chain.ts +14 -8
  291. package/src/plugins/defaults/memory-retrieval/injectors.ts +2 -18
  292. package/src/plugins/defaults/memory-retrieval/package.json +14 -0
  293. package/src/plugins/defaults/memory-v3-shadow/__tests__/carry-integration.test.ts +1157 -0
  294. package/src/plugins/defaults/memory-v3-shadow/__tests__/injection.test.ts +683 -0
  295. package/src/plugins/defaults/memory-v3-shadow/__tests__/live-integration.test.ts +161 -140
  296. package/src/plugins/defaults/memory-v3-shadow/__tests__/maintain-job.test.ts +160 -0
  297. package/src/plugins/defaults/memory-v3-shadow/__tests__/orchestrate.test.ts +335 -316
  298. package/src/plugins/defaults/memory-v3-shadow/__tests__/pool-select.test.ts +145 -53
  299. package/src/plugins/defaults/memory-v3-shadow/__tests__/render-injection.test.ts +38 -1
  300. package/src/plugins/defaults/memory-v3-shadow/__tests__/selection-log-store.test.ts +18 -8
  301. package/src/plugins/defaults/memory-v3-shadow/__tests__/shadow-integration.test.ts +112 -71
  302. package/src/plugins/defaults/memory-v3-shadow/__tests__/shadow-plugin.test.ts +192 -51
  303. package/src/plugins/defaults/memory-v3-shadow/__tests__/types.test.ts +4 -16
  304. package/src/plugins/defaults/memory-v3-shadow/card.test.ts +173 -0
  305. package/src/plugins/defaults/memory-v3-shadow/card.ts +116 -0
  306. package/src/plugins/defaults/memory-v3-shadow/core-set.test.ts +104 -0
  307. package/src/plugins/defaults/memory-v3-shadow/core-set.ts +59 -0
  308. package/src/plugins/defaults/memory-v3-shadow/ever-injected-store.test.ts +305 -0
  309. package/src/plugins/defaults/memory-v3-shadow/ever-injected-store.ts +278 -0
  310. package/src/plugins/defaults/memory-v3-shadow/hot-set.test.ts +138 -0
  311. package/src/plugins/defaults/memory-v3-shadow/hot-set.ts +85 -0
  312. package/src/plugins/defaults/memory-v3-shadow/injector.ts +331 -24
  313. package/src/plugins/defaults/memory-v3-shadow/maintain-job.ts +119 -13
  314. package/src/plugins/defaults/memory-v3-shadow/orchestrate.ts +169 -114
  315. package/src/plugins/defaults/memory-v3-shadow/page-content.ts +47 -16
  316. package/src/plugins/defaults/memory-v3-shadow/pool-select.ts +144 -66
  317. package/src/plugins/defaults/memory-v3-shadow/prune.test.ts +758 -0
  318. package/src/plugins/defaults/memory-v3-shadow/prune.ts +471 -0
  319. package/src/plugins/defaults/memory-v3-shadow/render-injection.ts +68 -16
  320. package/src/plugins/defaults/memory-v3-shadow/selection-log-store.ts +19 -12
  321. package/src/plugins/defaults/memory-v3-shadow/shadow-plugin.ts +96 -43
  322. package/src/plugins/defaults/memory-v3-shadow/types.ts +34 -17
  323. package/src/plugins/defaults/title-generate/hooks/stop.ts +9 -11
  324. package/src/plugins/pipeline.ts +8 -5
  325. package/src/plugins/types.ts +5 -51
  326. package/src/providers/cache-control.ts +26 -0
  327. package/src/providers/inference/__tests__/base-url-route-validation.test.ts +1 -2
  328. package/src/providers/model-catalog.ts +13 -1
  329. package/src/providers/openai/__tests__/tool-choice-mapping.test.ts +147 -0
  330. package/src/providers/openai/chat-completions-provider.ts +46 -0
  331. package/src/providers/openai/responses-provider.ts +45 -0
  332. package/src/providers/registry.ts +0 -8
  333. package/src/runtime/__tests__/agent-wake.test.ts +0 -1
  334. package/src/runtime/agent-wake.ts +13 -0
  335. package/src/runtime/routes/__tests__/acp-routes.test.ts +151 -0
  336. package/src/runtime/routes/__tests__/consolidation-routes.test.ts +12 -50
  337. package/src/runtime/routes/__tests__/conversation-surface-routes.test.ts +322 -0
  338. package/src/runtime/routes/__tests__/inference-provider-connection-routes.test.ts +0 -62
  339. package/src/runtime/routes/__tests__/plugins-routes.test.ts +31 -11
  340. package/src/runtime/routes/acp-routes.test.ts +106 -0
  341. package/src/runtime/routes/acp-routes.ts +248 -2
  342. package/src/runtime/routes/browser-tabs-routes.ts +1 -1
  343. package/src/runtime/routes/channel-verification-routes.ts +14 -5
  344. package/src/runtime/routes/chatgpt-subscription-auth-routes.ts +0 -14
  345. package/src/runtime/routes/consolidation-routes.ts +6 -82
  346. package/src/runtime/routes/conversation-list-routes.ts +6 -0
  347. package/src/runtime/routes/conversation-management-routes.ts +71 -0
  348. package/src/runtime/routes/identity-routes.ts +8 -0
  349. package/src/runtime/routes/inbound-stages/acl-enforcement.ts +33 -34
  350. package/src/runtime/routes/inference-provider-connection-routes.ts +0 -45
  351. package/src/runtime/routes/plugins-routes.ts +34 -45
  352. package/src/runtime/routes/schedule-routes.ts +43 -5
  353. package/src/runtime/routes/settings-routes.ts +140 -15
  354. package/src/runtime/routes/skills-routes.ts +18 -6
  355. package/src/runtime/services/__tests__/conversation-serializer.test.ts +140 -0
  356. package/src/runtime/services/conversation-serializer.ts +38 -1
  357. package/src/runtime/verification-outbound-actions.ts +147 -2
  358. package/src/runtime/verification-templates.ts +29 -3
  359. package/src/schedule/schedule-store.ts +19 -0
  360. package/src/skills/catalog-install.ts +77 -13
  361. package/src/tasks/task-scheduler.ts +1 -0
  362. package/src/telemetry/types.ts +66 -1
  363. package/src/telemetry/usage-telemetry-reporter.test.ts +542 -13
  364. package/src/telemetry/usage-telemetry-reporter.ts +213 -20
  365. package/src/tools/browser/__tests__/browser-execution-acquire.test.ts +49 -2
  366. package/src/tools/browser/__tests__/browser-status.test.ts +29 -5
  367. package/src/tools/browser/browser-execution.ts +27 -9
  368. package/src/tools/browser/cdp-client/__tests__/factory.test.ts +380 -4
  369. package/src/tools/browser/cdp-client/__tests__/host-bridge-cdp-client.test.ts +107 -0
  370. package/src/tools/browser/cdp-client/__tests__/types.test.ts +6 -1
  371. package/src/tools/browser/cdp-client/factory.ts +217 -17
  372. package/src/tools/browser/cdp-client/host-bridge-cdp-client.ts +67 -0
  373. package/src/tools/browser/cdp-client/types.ts +22 -2
  374. package/src/tools/credential-execution/make-authenticated-request.ts +2 -1
  375. package/src/tools/credential-execution/manage-secure-command-tool.ts +169 -164
  376. package/src/tools/credential-execution/run-authenticated-command.ts +2 -1
  377. package/src/tools/executor.ts +39 -7
  378. package/src/tools/registry.ts +387 -5
  379. package/src/tools/schedule/create.ts +16 -0
  380. package/src/tools/schedule/list.ts +12 -4
  381. package/src/tools/schedule/update.ts +12 -0
  382. package/src/tools/skills/load.ts +11 -6
  383. package/src/tools/terminal/safe-env.ts +2 -0
  384. package/src/tools/types.ts +65 -9
  385. package/src/tools/workspace-tools/loader.ts +673 -0
  386. package/src/usage/attribution.ts +28 -0
  387. package/src/util/device-id.ts +17 -3
  388. package/src/util/platform.ts +16 -0
  389. package/tsconfig.plugin-api.json +13 -0
  390. package/src/__tests__/plugin-external-api.test.ts +0 -68
  391. package/src/__tests__/plugin-skill-contribution.test.ts +0 -355
  392. package/src/daemon/message-types/browser.ts +0 -10
  393. package/src/notifications/__tests__/emit-signal-home-feed.test.ts +0 -187
  394. package/src/plugins/defaults/memory-v3-shadow/__tests__/fixtures/eval-turns.json +0 -36
  395. package/src/plugins/defaults/memory-v3-shadow/__tests__/fixtures/live-turns.json +0 -37
  396. package/src/plugins/defaults/memory-v3-shadow/__tests__/working-set-eviction.test.ts +0 -106
  397. package/src/plugins/defaults/memory-v3-shadow/__tests__/working-set-skeleton.test.ts +0 -44
  398. package/src/plugins/defaults/memory-v3-shadow/working-set.ts +0 -91
  399. package/src/plugins/external-api.ts +0 -114
  400. package/src/plugins/plugin-skill-contributions.ts +0 -292
@@ -19,7 +19,11 @@ import type {
19
19
  Message,
20
20
  ProviderResponse,
21
21
  } from "../providers/types.js";
22
- import { createMockProvider, textResponse } from "./helpers/mock-provider.js";
22
+ import {
23
+ createMockProvider,
24
+ textResponse,
25
+ toolUseResponse,
26
+ } from "./helpers/mock-provider.js";
23
27
 
24
28
  const userMessage: Message = {
25
29
  role: "user",
@@ -101,6 +105,7 @@ describe("agent loop output hooks", () => {
101
105
  });
102
106
  const events: AgentEvent[] = [];
103
107
  const { history } = await loop.run({
108
+ requestId: "test-request",
104
109
  messages: [userMessage],
105
110
  onEvent: collect(events),
106
111
  trust: { sourceChannel: "vellum", trustClass: "unknown" },
@@ -125,6 +130,7 @@ describe("agent loop output hooks", () => {
125
130
  });
126
131
  const events: AgentEvent[] = [];
127
132
  const { history } = await loop.run({
133
+ requestId: "test-request",
128
134
  messages: [userMessage],
129
135
  onEvent: collect(events),
130
136
  trust: { sourceChannel: "vellum", trustClass: "unknown" },
@@ -149,6 +155,7 @@ describe("agent loop output hooks", () => {
149
155
  });
150
156
  const events: AgentEvent[] = [];
151
157
  const { history } = await loop.run({
158
+ requestId: "test-request",
152
159
  messages: [userMessage],
153
160
  onEvent: collect(events),
154
161
  trust: { sourceChannel: "vellum", trustClass: "unknown" },
@@ -192,6 +199,7 @@ describe("agent loop output hooks", () => {
192
199
  toolExecutor: async () => ({ content: "ok", isError: false }),
193
200
  });
194
201
  const { history } = await loop.run({
202
+ requestId: "test-request",
195
203
  messages: [userMessage],
196
204
  onEvent: collect([]),
197
205
  trust: { sourceChannel: "vellum", trustClass: "unknown" },
@@ -224,6 +232,7 @@ describe("agent loop output hooks", () => {
224
232
  conversationId: "test-conversation",
225
233
  });
226
234
  await loop.run({
235
+ requestId: "test-request",
227
236
  messages: [userMessage],
228
237
  onEvent: collect([]),
229
238
  trust: { sourceChannel: "vellum", trustClass: "unknown" },
@@ -249,6 +258,7 @@ describe("agent loop output hooks", () => {
249
258
  conversationId: "test-conversation",
250
259
  });
251
260
  const { history } = await loop.run({
261
+ requestId: "test-request",
252
262
  messages: [userMessage],
253
263
  onEvent: collect([]),
254
264
  trust: { sourceChannel: "vellum", trustClass: "unknown" },
@@ -290,6 +300,7 @@ describe("agent loop output hooks", () => {
290
300
  });
291
301
  const events: AgentEvent[] = [];
292
302
  const { history } = await loop.run({
303
+ requestId: "test-request",
293
304
  messages: [userMessage],
294
305
  onEvent: collect(events),
295
306
  trust: { sourceChannel: "vellum", trustClass: "unknown" },
@@ -341,6 +352,7 @@ describe("agent loop output hooks", () => {
341
352
  });
342
353
  const events: AgentEvent[] = [];
343
354
  const { history } = await loop.run({
355
+ requestId: "test-request",
344
356
  messages: [userMessage],
345
357
  onEvent: collect(events),
346
358
  trust: { sourceChannel: "vellum", trustClass: "unknown" },
@@ -355,3 +367,264 @@ describe("agent loop output hooks", () => {
355
367
  expect(streamedText(events)).not.toContain(placeholder);
356
368
  });
357
369
  });
370
+
371
+ /**
372
+ * Tests for the `post-model-call` retry decision: a hook can set
373
+ * `decision: "continue"` to re-query the model with a repaired/extended
374
+ * `messages` history. The decision is honored only at actionable outcomes — a
375
+ * no-tool reply or a provider rejection — and a per-run backstop bounds a
376
+ * misbehaving hook. The hook also receives the rejection via `error` so it can
377
+ * recover from a thrown provider call, not just a finalized reply.
378
+ */
379
+ describe("agent loop post-model-call retry decision", () => {
380
+ beforeEach(() => {
381
+ resetPluginRegistryAndRegisterDefaults();
382
+ });
383
+
384
+ test("a no-tool reply with decision=continue re-queries with the hook's messages", async () => {
385
+ // GIVEN a hook that, once, asks to continue and appends a nudge turn,
386
+ // deferring output so the discarded reply was never streamed live
387
+ let continued = false;
388
+ const nudge: Message = {
389
+ role: "user",
390
+ content: [{ type: "text", text: "try again" }],
391
+ };
392
+ registerOutputHookPlugin({
393
+ preModelCall: (ctx) => {
394
+ ctx.deferAssistantOutput = true;
395
+ },
396
+ postModelCall: (ctx) => {
397
+ if (ctx.error) return;
398
+ if (continued) return;
399
+ continued = true;
400
+ ctx.messages = [...ctx.messages, nudge];
401
+ ctx.decision = "continue";
402
+ },
403
+ });
404
+ // AND a provider that returns a first reply then a second
405
+ const { provider, calls } = createMockProvider([
406
+ textResponse("first"),
407
+ textResponse("second"),
408
+ ]);
409
+ const loop = new AgentLoop({
410
+ provider,
411
+ systemPrompt: "system",
412
+ conversationId: "test-conversation",
413
+ });
414
+
415
+ // WHEN the loop runs
416
+ const { history } = await loop.run({
417
+ requestId: "test-request",
418
+ messages: [userMessage],
419
+ onEvent: collect([]),
420
+ trust: { sourceChannel: "vellum", trustClass: "unknown" },
421
+ });
422
+
423
+ // THEN the model was re-queried with the hook's repaired history
424
+ expect(calls.length).toBe(2);
425
+ expect(textOf(calls[1].messages.at(-1)!.content)).toBe("try again");
426
+ // AND the kept reply is the re-queried one, not the discarded first reply
427
+ expect(textOf(lastAssistant(history).content)).toBe("second");
428
+ expect(history.some((m) => textOf(m.content) === "first")).toBe(false);
429
+ });
430
+
431
+ test("a hook that always continues is bounded by the per-run backstop", async () => {
432
+ // GIVEN a hook that asks to continue on every no-tool reply, deferring
433
+ // output so each discarded reply was never streamed live
434
+ registerOutputHookPlugin({
435
+ preModelCall: (ctx) => {
436
+ ctx.deferAssistantOutput = true;
437
+ },
438
+ postModelCall: (ctx) => {
439
+ if (ctx.error) return;
440
+ ctx.decision = "continue";
441
+ },
442
+ });
443
+ // AND a provider that always returns a no-tool reply
444
+ const { provider, calls } = createMockProvider([textResponse("loop")]);
445
+ const loop = new AgentLoop({
446
+ provider,
447
+ systemPrompt: "system",
448
+ conversationId: "test-conversation",
449
+ });
450
+
451
+ // WHEN the loop runs
452
+ const { history } = await loop.run({
453
+ requestId: "test-request",
454
+ messages: [userMessage],
455
+ onEvent: collect([]),
456
+ trust: { sourceChannel: "vellum", trustClass: "unknown" },
457
+ });
458
+
459
+ // THEN it terminates after the backstop is spent (5 continues + 1 accepted)
460
+ expect(calls.length).toBe(6);
461
+ expect(textOf(lastAssistant(history).content)).toBe("loop");
462
+ });
463
+
464
+ test("decision=continue is ignored on an already-streamed visible reply", async () => {
465
+ /**
466
+ * A retry discards the reply and re-queries; honoring it on a reply whose
467
+ * text already streamed live would strand the user on an answer the
468
+ * transcript silently replaces. The loop keeps such a turn instead.
469
+ */
470
+ // GIVEN a hook that asks to continue on a visible reply without deferring
471
+ // its output, so the reply was streamed to the client live
472
+ let asked = false;
473
+ registerOutputHookPlugin({
474
+ postModelCall: (ctx) => {
475
+ if (ctx.error) return;
476
+ asked = true;
477
+ ctx.decision = "continue";
478
+ },
479
+ });
480
+ // AND a provider whose first reply carries visible text
481
+ const { provider, calls } = createMockProvider([
482
+ textResponse("visible"),
483
+ textResponse("second"),
484
+ ]);
485
+ const loop = new AgentLoop({
486
+ provider,
487
+ systemPrompt: "system",
488
+ conversationId: "test-conversation",
489
+ });
490
+
491
+ // WHEN the loop runs
492
+ const events: AgentEvent[] = [];
493
+ const { history } = await loop.run({
494
+ requestId: "test-request",
495
+ messages: [userMessage],
496
+ onEvent: collect(events),
497
+ trust: { sourceChannel: "vellum", trustClass: "unknown" },
498
+ });
499
+
500
+ // THEN the hook ran but the streamed reply is kept rather than discarded
501
+ expect(asked).toBe(true);
502
+ expect(calls.length).toBe(1);
503
+ expect(textOf(lastAssistant(history).content)).toBe("visible");
504
+ // AND the visible text the user already saw is the one that stands
505
+ expect(streamedText(events)).toBe("visible");
506
+ });
507
+
508
+ test("a provider rejection invokes the hook with the error and can recover", async () => {
509
+ // GIVEN a hook that recovers from a rejection once, recording what it saw
510
+ const seen: { error?: Error; contentLength?: number } = {};
511
+ let recovered = false;
512
+ registerOutputHookPlugin({
513
+ postModelCall: (ctx) => {
514
+ if (!ctx.error) return;
515
+ seen.error = ctx.error;
516
+ seen.contentLength = ctx.content.length;
517
+ if (recovered) return;
518
+ recovered = true;
519
+ ctx.decision = "continue";
520
+ },
521
+ });
522
+ // AND a provider that throws once then succeeds
523
+ const rejection = new Error("ordering violation");
524
+ const { provider, calls } = createMockProvider([
525
+ rejection,
526
+ textResponse("recovered"),
527
+ ]);
528
+ const loop = new AgentLoop({
529
+ provider,
530
+ systemPrompt: "system",
531
+ conversationId: "test-conversation",
532
+ });
533
+
534
+ // WHEN the loop runs
535
+ const events: AgentEvent[] = [];
536
+ const { history } = await loop.run({
537
+ requestId: "test-request",
538
+ messages: [userMessage],
539
+ onEvent: collect(events),
540
+ trust: { sourceChannel: "vellum", trustClass: "unknown" },
541
+ });
542
+
543
+ // THEN the hook saw the rejection with empty content
544
+ expect(seen.error).toBe(rejection);
545
+ expect(seen.contentLength).toBe(0);
546
+ // AND the call was re-issued and the recovery reply kept, no error surfaced
547
+ expect(calls.length).toBe(2);
548
+ expect(textOf(lastAssistant(history).content)).toBe("recovered");
549
+ expect(events.some((e) => e.type === "error")).toBe(false);
550
+ });
551
+
552
+ test("a provider rejection the hook does not recover is surfaced", async () => {
553
+ // GIVEN a hook that inspects but never continues on a rejection
554
+ registerOutputHookPlugin({
555
+ postModelCall: (ctx) => {
556
+ if (!ctx.error) return;
557
+ },
558
+ });
559
+ // AND a provider that always throws
560
+ const { provider, calls } = createMockProvider([new Error("boom")]);
561
+ const loop = new AgentLoop({
562
+ provider,
563
+ systemPrompt: "system",
564
+ conversationId: "test-conversation",
565
+ });
566
+
567
+ // WHEN the loop runs
568
+ const events: AgentEvent[] = [];
569
+ await loop.run({
570
+ requestId: "test-request",
571
+ messages: [userMessage],
572
+ onEvent: collect(events),
573
+ trust: { sourceChannel: "vellum", trustClass: "unknown" },
574
+ });
575
+
576
+ // THEN the rejection is surfaced and not retried
577
+ expect(calls.length).toBe(1);
578
+ expect(events.some((e) => e.type === "error")).toBe(true);
579
+ });
580
+
581
+ test("decision=continue is ignored on a tool-bearing turn", async () => {
582
+ // GIVEN a hook that asks to continue only on a reply carrying a tool_use
583
+ registerOutputHookPlugin({
584
+ postModelCall: (ctx) => {
585
+ if (ctx.content.some((b) => b.type === "tool_use")) {
586
+ ctx.decision = "continue";
587
+ }
588
+ },
589
+ });
590
+ // AND a provider that calls a tool then returns a final reply
591
+ const { provider, calls } = createMockProvider([
592
+ toolUseResponse("t1", "noop", {}),
593
+ textResponse("done"),
594
+ ]);
595
+ let toolRuns = 0;
596
+ const loop = new AgentLoop({
597
+ provider,
598
+ systemPrompt: "system",
599
+ conversationId: "test-conversation",
600
+ tools: [
601
+ {
602
+ name: "noop",
603
+ description: "",
604
+ input_schema: { type: "object", properties: {} },
605
+ },
606
+ ],
607
+ toolExecutor: async () => {
608
+ toolRuns += 1;
609
+ return { content: "ok", isError: false };
610
+ },
611
+ });
612
+
613
+ // WHEN the loop runs
614
+ const { history } = await loop.run({
615
+ requestId: "test-request",
616
+ messages: [userMessage],
617
+ onEvent: collect([]),
618
+ trust: { sourceChannel: "vellum", trustClass: "unknown" },
619
+ });
620
+
621
+ // THEN the tool ran normally (the continue did not discard the tool_use)
622
+ expect(toolRuns).toBe(1);
623
+ expect(
624
+ history.some((m) => m.content.some((b) => b.type === "tool_result")),
625
+ ).toBe(true);
626
+ // AND the loop continued naturally to the final reply, no extra re-query
627
+ expect(calls.length).toBe(2);
628
+ expect(textOf(lastAssistant(history).content)).toBe("done");
629
+ });
630
+ });
@@ -120,6 +120,7 @@ describe("AgentLoop.run — overrideProfile plumbing", () => {
120
120
  });
121
121
 
122
122
  await loop.run({
123
+ requestId: "test-request",
123
124
  messages: [userMessage],
124
125
  onEvent: () => {},
125
126
  trust: { sourceChannel: "vellum", trustClass: "unknown" },
@@ -144,6 +145,7 @@ describe("AgentLoop.run — overrideProfile plumbing", () => {
144
145
  });
145
146
 
146
147
  await loop.run({
148
+ requestId: "test-request",
147
149
  messages: [userMessage],
148
150
  onEvent: () => {},
149
151
  trust: { sourceChannel: "vellum", trustClass: "unknown" },
@@ -169,6 +171,7 @@ describe("AgentLoop.run — overrideProfile plumbing", () => {
169
171
  });
170
172
 
171
173
  await loop.run({
174
+ requestId: "test-request",
172
175
  messages: [userMessage],
173
176
  onEvent: () => {},
174
177
  trust: { sourceChannel: "vellum", trustClass: "unknown" },
@@ -90,6 +90,7 @@ describe("AgentLoop provider_error event emission", () => {
90
90
  });
91
91
 
92
92
  await loop.run({
93
+ requestId: "test-request",
93
94
  messages: [{ role: "user", content: [{ type: "text", text: "hi" }] }],
94
95
  onEvent: (e) => {
95
96
  events.push(e);
@@ -134,6 +135,7 @@ describe("AgentLoop provider_error event emission", () => {
134
135
  });
135
136
 
136
137
  await loop.run({
138
+ requestId: "test-request",
137
139
  messages: [{ role: "user", content: [{ type: "text", text: "hi" }] }],
138
140
  onEvent: (e) => {
139
141
  events.push(e);
@@ -165,6 +167,7 @@ describe("AgentLoop provider_error event emission", () => {
165
167
  });
166
168
 
167
169
  await loop.run({
170
+ requestId: "test-request",
168
171
  messages: [{ role: "user", content: [{ type: "text", text: "hi" }] }],
169
172
  onEvent: (e) => {
170
173
  events.push(e);
@@ -201,6 +204,7 @@ describe("AgentLoop provider_error event emission", () => {
201
204
  });
202
205
 
203
206
  await loop.run({
207
+ requestId: "test-request",
204
208
  messages: [{ role: "user", content: [{ type: "text", text: "hi" }] }],
205
209
  onEvent: (e) => {
206
210
  events.push(e);
@@ -48,6 +48,7 @@ describe("AgentLoop thinking and effort", () => {
48
48
  });
49
49
 
50
50
  await loop.run({
51
+ requestId: "test-request",
51
52
  messages: [{ role: "user", content: [{ type: "text", text: "Hi" }] }],
52
53
  onEvent: () => {},
53
54
  trust: { sourceChannel: "vellum", trustClass: "unknown" },
@@ -71,6 +72,7 @@ describe("AgentLoop thinking and effort", () => {
71
72
  });
72
73
 
73
74
  await loop.run({
75
+ requestId: "test-request",
74
76
  messages: [{ role: "user", content: [{ type: "text", text: "Hi" }] }],
75
77
  onEvent: () => {},
76
78
  trust: { sourceChannel: "vellum", trustClass: "unknown" },
@@ -93,6 +95,7 @@ describe("AgentLoop thinking and effort", () => {
93
95
  });
94
96
 
95
97
  await loop.run({
98
+ requestId: "test-request",
96
99
  messages: [{ role: "user", content: [{ type: "text", text: "Hi" }] }],
97
100
  onEvent: () => {},
98
101
  trust: { sourceChannel: "vellum", trustClass: "unknown" },
@@ -116,6 +119,7 @@ describe("AgentLoop thinking and effort", () => {
116
119
  });
117
120
 
118
121
  await loop.run({
122
+ requestId: "test-request",
119
123
  messages: [{ role: "user", content: [{ type: "text", text: "Hi" }] }],
120
124
  onEvent: () => {},
121
125
  trust: { sourceChannel: "vellum", trustClass: "unknown" },