@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
@@ -0,0 +1,218 @@
1
+ /**
2
+ * Tests for `handleToolUse` stamping a tool start time both on the live
3
+ * `tool_use_start` event and on the already-durable persisted tool_use block.
4
+ *
5
+ * The live event carries `startedAt` so clients can anchor a running
6
+ * elapsed-time counter to the server clock instead of SSE receipt time. The
7
+ * persisted `_startedAt` (mapped to the wire `startedAt` in handlers/shared.ts)
8
+ * lets a `/messages` snapshot fetched mid-tool — e.g. after a refresh or
9
+ * reconnect, before the live event was seen — still render that counter.
10
+ */
11
+ import { beforeEach, describe, expect, mock, test } from "bun:test";
12
+
13
+ // ── Mock platform (must precede imports that read it) ─────────────────────────
14
+ mock.module("../util/logger.js", () => ({
15
+ getLogger: () =>
16
+ new Proxy({} as Record<string, unknown>, {
17
+ get: () => () => {},
18
+ }),
19
+ }));
20
+
21
+ mock.module("../config/loader.js", () => ({
22
+ getConfig: () => ({
23
+ skills: {
24
+ entries: {},
25
+ load: { extraDirs: [], watch: false, watchDebounceMs: 0 },
26
+ install: { nodeManager: "npm" },
27
+ allowBundled: null,
28
+ remoteProviders: {
29
+ skillssh: { enabled: true },
30
+ clawhub: { enabled: true },
31
+ },
32
+ remotePolicy: {
33
+ blockSuspicious: true,
34
+ blockMalware: true,
35
+ maxSkillsShRisk: "medium",
36
+ },
37
+ },
38
+ }),
39
+ loadConfig: () => ({}),
40
+ }));
41
+
42
+ let mockedRowContent = "";
43
+ const updates: Array<{ id: string; content: string }> = [];
44
+
45
+ mock.module("../memory/conversation-crud.js", () => ({
46
+ addMessage: () => ({ id: "mock-msg-id" }),
47
+ getMessageById: (id: string) =>
48
+ mockedRowContent ? { id, content: mockedRowContent } : null,
49
+ updateMessageContent: (id: string, content: string) => {
50
+ updates.push({ id, content });
51
+ },
52
+ provenanceFromTrustContext: () => ({}),
53
+ reserveMessage: mock(async () => ({ id: "msg-reserve" })),
54
+ }));
55
+
56
+ mock.module("../memory/llm-request-log-store.js", () => ({
57
+ recordRequestLog: () => {},
58
+ backfillMessageIdOnLogs: () => {},
59
+ }));
60
+
61
+ mock.module("../runtime/assistant-stream-state.js", () => ({
62
+ getCurrentSeq: () => 0,
63
+ recordPersistedSeq: () => {},
64
+ }));
65
+
66
+ // ── Imports (after mocks) ─────────────────────────────────────────────────────
67
+ import type { AgentEvent } from "../agent/loop.js";
68
+ import type {
69
+ EventHandlerDeps,
70
+ EventHandlerState,
71
+ } from "../daemon/conversation-agent-loop-handlers.js";
72
+ import {
73
+ createEventHandlerState,
74
+ handleToolUse,
75
+ } from "../daemon/conversation-agent-loop-handlers.js";
76
+ import type { ServerMessage } from "../daemon/message-protocol.js";
77
+
78
+ // ── Helpers ───────────────────────────────────────────────────────────────────
79
+
80
+ function makeDeps(onEvent: (event: ServerMessage) => void): EventHandlerDeps {
81
+ return {
82
+ ctx: {
83
+ conversationId: "test-conv",
84
+ provider: { name: "anthropic" },
85
+ traceEmitter: { emit: () => {} },
86
+ streamThinking: false,
87
+ emitActivityState: () => {},
88
+ markWorkspaceTopLevelDirty: () => {},
89
+ currentTurnSurfaces: [],
90
+ } as unknown as EventHandlerDeps["ctx"],
91
+ onEvent,
92
+ reqId: "test-req",
93
+ isFirstMessage: false,
94
+ shouldGenerateTitle: false,
95
+ rlog: new Proxy({} as Record<string, unknown>, {
96
+ get: () => () => {},
97
+ }) as unknown as EventHandlerDeps["rlog"],
98
+ turnChannelContext: {
99
+ userMessageChannel: "vellum",
100
+ assistantMessageChannel: "vellum",
101
+ } as unknown as EventHandlerDeps["turnChannelContext"],
102
+ turnInterfaceContext: {
103
+ userMessageInterface: "web",
104
+ assistantMessageInterface: "web",
105
+ } as unknown as EventHandlerDeps["turnInterfaceContext"],
106
+ applyCompaction: async () => {},
107
+ };
108
+ }
109
+
110
+ function toolUseEvent(
111
+ id: string,
112
+ name: string,
113
+ ): Extract<AgentEvent, { type: "tool_use" }> {
114
+ return { type: "tool_use", id, name, input: { command: "ls" } };
115
+ }
116
+
117
+ function findBlockById(
118
+ rawContent: string,
119
+ id: string,
120
+ ): Record<string, unknown> {
121
+ const parsed = JSON.parse(rawContent) as Array<Record<string, unknown>>;
122
+ const block = parsed.find((b) => b.id === id);
123
+ if (!block) throw new Error(`block ${id} not found`);
124
+ return block;
125
+ }
126
+
127
+ // ── Tests ─────────────────────────────────────────────────────────────────────
128
+
129
+ describe("handleToolUse — tool start timestamp", () => {
130
+ beforeEach(() => {
131
+ updates.length = 0;
132
+ mockedRowContent = "";
133
+ });
134
+
135
+ test("emits a numeric startedAt on the tool_use_start event and records it in state", () => {
136
+ // GIVEN a fresh handler state with a persisted assistant message
137
+ const toolUseId = "tu_bash";
138
+ const state: EventHandlerState = createEventHandlerState();
139
+ state.lastAssistantMessageId = "msg-1";
140
+ mockedRowContent = JSON.stringify([
141
+ {
142
+ type: "tool_use",
143
+ id: toolUseId,
144
+ name: "bash",
145
+ input: { command: "ls" },
146
+ },
147
+ ]);
148
+ const events: ServerMessage[] = [];
149
+ const before = Date.now();
150
+
151
+ // WHEN the tool begins
152
+ handleToolUse(
153
+ state,
154
+ makeDeps((e) => events.push(e)),
155
+ toolUseEvent(toolUseId, "bash"),
156
+ );
157
+
158
+ // THEN the emitted tool_use_start carries a numeric startedAt within the
159
+ // execution window AND the same value is recorded in toolCallTimestamps
160
+ const startEvent = events.find((e) => e.type === "tool_use_start");
161
+ expect(startEvent?.type).toBe("tool_use_start");
162
+ const startedAt =
163
+ startEvent?.type === "tool_use_start" ? startEvent.startedAt : undefined;
164
+ expect(typeof startedAt).toBe("number");
165
+ expect(startedAt).toBeGreaterThanOrEqual(before);
166
+ expect(startedAt).toBeLessThanOrEqual(Date.now());
167
+ expect(state.toolCallTimestamps.get(toolUseId)?.startedAt).toBe(startedAt);
168
+ });
169
+
170
+ test("stamps _startedAt onto the in-flight persisted tool_use block", () => {
171
+ // GIVEN a durable tool_use block with no timing metadata yet
172
+ const toolUseId = "tu_bash";
173
+ const state: EventHandlerState = createEventHandlerState();
174
+ state.lastAssistantMessageId = "msg-1";
175
+ mockedRowContent = JSON.stringify([
176
+ {
177
+ type: "tool_use",
178
+ id: toolUseId,
179
+ name: "bash",
180
+ input: { command: "ls" },
181
+ },
182
+ ]);
183
+ const events: ServerMessage[] = [];
184
+
185
+ // WHEN the tool begins
186
+ handleToolUse(
187
+ state,
188
+ makeDeps((e) => events.push(e)),
189
+ toolUseEvent(toolUseId, "bash"),
190
+ );
191
+
192
+ // THEN the persisted block is updated with _startedAt matching the event,
193
+ // so a mid-tool snapshot surfaces the start time via handlers/shared.ts
194
+ expect(updates).toHaveLength(1);
195
+ const block = findBlockById(updates[0].content, toolUseId);
196
+ const startEvent = events.find((e) => e.type === "tool_use_start");
197
+ const startedAt =
198
+ startEvent?.type === "tool_use_start" ? startEvent.startedAt : undefined;
199
+ expect(block._startedAt).toBe(startedAt);
200
+ });
201
+
202
+ test("does not write when no persisted block matches the tool id", () => {
203
+ // GIVEN a persisted message whose only block is unrelated to the tool
204
+ const state: EventHandlerState = createEventHandlerState();
205
+ state.lastAssistantMessageId = "msg-1";
206
+ mockedRowContent = JSON.stringify([{ type: "text", text: "thinking" }]);
207
+
208
+ // WHEN a tool begins
209
+ handleToolUse(
210
+ state,
211
+ makeDeps(() => {}),
212
+ toolUseEvent("tu_missing", "bash"),
213
+ );
214
+
215
+ // THEN no persisted-content write is attempted
216
+ expect(updates).toHaveLength(0);
217
+ });
218
+ });
@@ -0,0 +1,202 @@
1
+ /**
2
+ * Tests for the `tools` route handler (operationId `tools_get`), which backs
3
+ * both the macOS permission-simulator catalog (`names`/`schemas`) and the
4
+ * `assistant tools list` CLI command (`tools`). The `tools` array carries
5
+ * every registered tool with its description, author-asserted risk band,
6
+ * category, and the source (core / skill / plugin / mcp) that contributed it
7
+ * — with the source read from the registry's ownership map rather than off
8
+ * the tool object.
9
+ */
10
+
11
+ import { beforeEach, describe, expect, test } from "bun:test";
12
+
13
+ import type { Conversation } from "../daemon/conversation.js";
14
+ import {
15
+ clearConversations,
16
+ setConversation,
17
+ } from "../daemon/conversation-registry.js";
18
+ import { RiskLevel } from "../permissions/types.js";
19
+ import { ROUTES } from "../runtime/routes/settings-routes.js";
20
+ import {
21
+ __resetRegistryForTesting,
22
+ registerMcpTools,
23
+ registerPluginTools,
24
+ registerSkillTools,
25
+ registerTool,
26
+ } from "../tools/registry.js";
27
+ import type { Tool, ToolContext, ToolExecutionResult } from "../tools/types.js";
28
+
29
+ interface ToolListEntry {
30
+ name: string;
31
+ description: string;
32
+ riskLevel: string;
33
+ category: string;
34
+ source: string;
35
+ }
36
+
37
+ interface ToolsGetResponse {
38
+ names: string[];
39
+ schemas: Record<string, unknown>;
40
+ tools: ToolListEntry[];
41
+ }
42
+
43
+ function makeFakeTool(name: string, extras: Partial<Tool> = {}): Tool {
44
+ return {
45
+ name,
46
+ description: `Fake ${name}`,
47
+ defaultRiskLevel: RiskLevel.Low,
48
+ executionTarget: "sandbox",
49
+ input_schema: { type: "object", properties: {}, required: [] },
50
+ category: "",
51
+ async execute(
52
+ _input: Record<string, unknown>,
53
+ _context: ToolContext,
54
+ ): Promise<ToolExecutionResult> {
55
+ return { content: "ok", isError: false };
56
+ },
57
+ ...extras,
58
+ };
59
+ }
60
+
61
+ const handler = (() => {
62
+ const route = ROUTES.find(
63
+ (r) => r.endpoint === "tools" && r.method === "GET",
64
+ );
65
+ if (!route) {
66
+ throw new Error("No route found for GET tools");
67
+ }
68
+ return route.handler;
69
+ })();
70
+
71
+ /**
72
+ * Minimal Conversation stand-in exposing only the tool-snapshot accessor the
73
+ * route reads, registered into the live conversation registry by id.
74
+ */
75
+ function registerFakeConversation(id: string, toolNames: string[]): void {
76
+ setConversation(id, {
77
+ getRegisteredToolNames: () => new Set(toolNames),
78
+ } as unknown as Conversation);
79
+ }
80
+
81
+ describe("GET /tools", () => {
82
+ beforeEach(() => {
83
+ __resetRegistryForTesting();
84
+ clearConversations();
85
+ });
86
+
87
+ test("returns each registered tool's metadata, sorted by name, with core source", async () => {
88
+ // GIVEN two core tools registered out of alphabetical order
89
+ registerTool(
90
+ makeFakeTool("b_core_tool", {
91
+ description: "Beta tool",
92
+ defaultRiskLevel: RiskLevel.High,
93
+ category: "testing",
94
+ }),
95
+ );
96
+ registerTool(makeFakeTool("a_core_tool"));
97
+
98
+ // WHEN the tools handler runs
99
+ const { names, schemas, tools } = (await handler({})) as ToolsGetResponse;
100
+
101
+ // THEN the catalog fields the permission simulator reads are present
102
+ expect(names).toContain("a_core_tool");
103
+ expect(names).toContain("b_core_tool");
104
+ expect(schemas.a_core_tool).toBeDefined();
105
+
106
+ // AND the metadata array is sorted by name with full per-tool metadata
107
+ const toolNames = tools.map((t) => t.name);
108
+ expect(toolNames.indexOf("a_core_tool")).toBeLessThan(
109
+ toolNames.indexOf("b_core_tool"),
110
+ );
111
+ expect([...toolNames]).toEqual(
112
+ [...toolNames].sort((a, b) => a.localeCompare(b)),
113
+ );
114
+
115
+ // AND each core tool reports "core" as its source plus its metadata
116
+ const beta = tools.find((t) => t.name === "b_core_tool");
117
+ expect(beta).toEqual({
118
+ name: "b_core_tool",
119
+ description: "Beta tool",
120
+ riskLevel: RiskLevel.High,
121
+ category: "testing",
122
+ source: "core",
123
+ });
124
+ });
125
+
126
+ test("reports plugin, mcp, and skill tools as <kind>:<id>", async () => {
127
+ // GIVEN one tool from each non-core source
128
+ registerPluginTools("echo", [makeFakeTool("p_tool")]);
129
+ registerMcpTools("linear", [makeFakeTool("m_tool")]);
130
+ registerSkillTools("my-skill", [makeFakeTool("s_tool")]);
131
+
132
+ // WHEN the tools handler runs
133
+ const { tools } = (await handler({})) as ToolsGetResponse;
134
+
135
+ // THEN each tool's source encodes its owning extension
136
+ const sourceOf = (name: string) =>
137
+ tools.find((t) => t.name === name)?.source;
138
+ expect(sourceOf("p_tool")).toBe("plugin:echo");
139
+ expect(sourceOf("m_tool")).toBe("mcp:linear");
140
+ expect(sourceOf("s_tool")).toBe("skill:my-skill");
141
+ });
142
+
143
+ test("with conversationId, scopes to the conversation's tool snapshot and resolves metadata from the registry", async () => {
144
+ // GIVEN three core tools in the global registry
145
+ registerTool(makeFakeTool("a_core_tool"));
146
+ registerTool(
147
+ makeFakeTool("b_core_tool", {
148
+ description: "Beta tool",
149
+ defaultRiskLevel: RiskLevel.High,
150
+ category: "testing",
151
+ }),
152
+ );
153
+ registerTool(makeFakeTool("c_core_tool"));
154
+
155
+ // AND a conversation whose most-recent-turn snapshot saw only two of them
156
+ registerFakeConversation("conv-1", ["c_core_tool", "a_core_tool"]);
157
+
158
+ // WHEN the handler runs with that conversationId
159
+ const { names, schemas, tools } = (await handler({
160
+ queryParams: { conversationId: "conv-1" },
161
+ })) as ToolsGetResponse;
162
+
163
+ // THEN only the conversation's tools are returned, sorted, with schemas
164
+ expect(names).toEqual(["a_core_tool", "c_core_tool"]);
165
+ expect(tools.map((t) => t.name)).toEqual(["a_core_tool", "c_core_tool"]);
166
+ expect(schemas.a_core_tool).toBeDefined();
167
+ expect(schemas.b_core_tool).toBeUndefined();
168
+
169
+ // AND each entry's metadata is resolved from the global registry
170
+ expect(tools.find((t) => t.name === "a_core_tool")?.source).toBe("core");
171
+ });
172
+
173
+ test("with conversationId, marks a snapshot tool absent from the registry as unknown", async () => {
174
+ // GIVEN a conversation snapshot referencing a since-unloaded skill tool
175
+ registerFakeConversation("conv-1", ["ghost_skill_tool"]);
176
+
177
+ // WHEN the handler runs with that conversationId
178
+ const { tools } = (await handler({
179
+ queryParams: { conversationId: "conv-1" },
180
+ })) as ToolsGetResponse;
181
+
182
+ // THEN the tool still appears, with unknown source and empty metadata
183
+ expect(tools).toEqual([
184
+ {
185
+ name: "ghost_skill_tool",
186
+ description: "",
187
+ riskLevel: "unknown",
188
+ category: "",
189
+ source: "unknown",
190
+ },
191
+ ]);
192
+ });
193
+
194
+ test("with an unknown conversationId, throws a 404 RouteError", () => {
195
+ // GIVEN no conversation registered under the queried id
196
+ // WHEN the handler runs with a missing conversationId
197
+ // THEN it throws an actionable not-found error
198
+ expect(() =>
199
+ handler({ queryParams: { conversationId: "missing" } }),
200
+ ).toThrow(/No active conversation "missing"/);
201
+ });
202
+ });