@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
@@ -15,8 +15,9 @@
15
15
  * substitute in.
16
16
  *
17
17
  * Lifecycle:
18
- * 1. Bail if `config.memory.v2.enabled` is false (the worker may have
19
- * claimed a stale row from before v2 was disabled).
18
+ * 1. Bail if `config.memory.enabled` or `config.memory.v2.enabled` is false
19
+ * (the worker may have claimed a stale row from before memory was
20
+ * disabled).
20
21
  * 2. Acquire a single-process lock at `memory/.v2-state/consolidation.lock`
21
22
  * so two overlapping schedule windows can't fight over the same files.
22
23
  * The lock contains the holder's PID + timestamp so a crashed run leaves
@@ -41,9 +42,11 @@
41
42
  * a conservative full-reembed effectively free. On failure no follow-ups
42
43
  * are enqueued — the agent's writes may be partial and re-embedding
43
44
  * partial state would be misleading.
44
- * 7. Release the lock. If a prior holder's PID is no longer running, the
45
- * stale lock is taken over automatically (single-writer per workspace,
46
- * so a holder whose process died is unambiguously stale).
45
+ * 7. Release the lock. A stale lock is taken over automatically on the next
46
+ * run (single-writer per workspace): when the holder's PID is no longer
47
+ * running, or — because the daemon runs as PID 1 in containers and a
48
+ * restarted daemon collides with the dead holder's PID — when the lock is
49
+ * older than a TTL well above the run's hard timeout.
47
50
  *
48
51
  * The handler never propagates exceptions from the run path — `runBackgroundJob`
49
52
  * absorbs them and returns a structured result. A thrown error before the
@@ -96,6 +99,25 @@ const MEMORY_V3_LIVE = "memory-v3-live" as const;
96
99
  */
97
100
  const CONSOLIDATION_TIMEOUT_MS = 15 * 60 * 1000;
98
101
 
102
+ /**
103
+ * Age past which a lock held by an apparently-live PID is taken over anyway.
104
+ *
105
+ * The PID-liveness probe alone is not sufficient in containers: the daemon
106
+ * runs as PID 1, so after a container restart `isProcessAlive(1)` reports the
107
+ * NEW daemon as alive even though it is not the process that wrote the lock.
108
+ * PID-1 collision means a lock left behind by a crashed/restarted run can
109
+ * never be declared stale by liveness alone, and consolidation wedges
110
+ * permanently (every scheduled run skips with `locked`).
111
+ *
112
+ * A lock older than this TTL is treated as abandoned regardless of PID
113
+ * liveness. The bound is a large multiple of the run's hard timeout — the
114
+ * lock timestamp is written at acquire time and a run can hold the lock for
115
+ * at most `CONSOLIDATION_TIMEOUT_MS`, so a TTL well above that can never fire
116
+ * against a legitimately in-flight run while still recovering a wedged lock
117
+ * within a couple of scheduled passes.
118
+ */
119
+ const STALE_LOCK_TTL_MS = 4 * CONSOLIDATION_TIMEOUT_MS;
120
+
99
121
  /**
100
122
  * Follow-up jobs to fan out after a successful consolidation.
101
123
  *
@@ -129,6 +151,11 @@ export async function memoryV2ConsolidateJob(
129
151
  _job: MemoryJob,
130
152
  config: AssistantConfig,
131
153
  ): Promise<ConsolidationOutcome> {
154
+ if (config.memory.enabled === false) {
155
+ log.debug("memory.enabled is false; consolidation skipped");
156
+ return { kind: "disabled" };
157
+ }
158
+
132
159
  if (!config.memory.v2.enabled) {
133
160
  log.debug("memory.v2.enabled is false; consolidation skipped");
134
161
  return { kind: "disabled" };
@@ -175,10 +202,23 @@ export async function memoryV2ConsolidateJob(
175
202
  // the `memory.v2.consolidation_prompt_path` config override but bounds
176
203
  // it to a regular file under 1 MiB before substitution so a stray path
177
204
  // (or a `/dev/zero`-style pseudo-file) cannot exfiltrate megabytes of
178
- // bytes through the wake hint.
205
+ // bytes through the wake hint. The core-pages curation section rides the
206
+ // same v3 gate as the maintenance follow-up: the file feeds the v3 core
207
+ // lane, so on a v2-only install the instruction would curate a file
208
+ // nothing reads.
209
+ // The article SHAPE is keyed on the live flag alone: under shadow, live
210
+ // prompts are still assembled by v2's injection model, so consolidation
211
+ // must keep producing `summary:`-bearing fragment pages until the flip.
212
+ const memoryV3Live = isAssistantFeatureFlagEnabled(MEMORY_V3_LIVE, config);
213
+ const memoryV3Active =
214
+ isAssistantFeatureFlagEnabled(MEMORY_V3_SHADOW, config) || memoryV3Live;
179
215
  const prompt = resolveConsolidationPrompt(
180
216
  config.memory.v2.consolidation_prompt_path,
181
217
  cutoff,
218
+ {
219
+ includeCorePagesSection: memoryV3Active,
220
+ articleShape: memoryV3Live ? "v3" : "v2",
221
+ },
182
222
  );
183
223
 
184
224
  const runResult = await runBackgroundJob({
@@ -212,10 +252,7 @@ export async function memoryV2ConsolidateJob(
212
252
  // is active, so it never fans out on v2-only installs.
213
253
  const followUpJobIds: string[] = [];
214
254
  const jobTypes: MemoryJobType[] = [...FOLLOW_UP_JOB_TYPES];
215
- if (
216
- isAssistantFeatureFlagEnabled(MEMORY_V3_SHADOW, config) ||
217
- isAssistantFeatureFlagEnabled(MEMORY_V3_LIVE, config)
218
- ) {
255
+ if (memoryV3Active) {
219
256
  jobTypes.push(V3_FOLLOW_UP_JOB_TYPE);
220
257
  }
221
258
  for (const jobType of jobTypes) {
@@ -282,11 +319,13 @@ export function countBufferLines(bufferPath: string): number {
282
319
  * `null` on success, or the current holder string (file contents, typically
283
320
  * `pid timestamp`) when the file already exists and the holder is still alive.
284
321
  *
285
- * Stale-lock takeover: if the file exists but its holder PID is not running,
286
- * unlink the stale file and retry the create exactly once. This recovers
287
- * automatically from a crashed daemon that died with the lock held —
288
- * otherwise every subsequent scheduled consolidation would skip with `locked`
289
- * indefinitely until an operator manually removed the file.
322
+ * Stale-lock takeover: if the file exists but its holder is stale (PID not
323
+ * running, payload corrupt, or — for the container PID-1 collision — older
324
+ * than the TTL; see {@link holderStaleReason}), unlink the stale file and
325
+ * retry the create exactly once. This recovers automatically from a crashed
326
+ * or restarted daemon that died with the lock held — otherwise every
327
+ * subsequent scheduled consolidation would skip with `locked` indefinitely
328
+ * until an operator manually removed the file.
290
329
  *
291
330
  * The simple takeover-then-retry is safe here (unlike `snapshot-lock.ts`'s
292
331
  * full rename-aside dance) because only the assistant's jobs worker calls
@@ -303,11 +342,12 @@ function tryAcquireLock(lockPath: string): string | null {
303
342
 
304
343
  const firstHolder = tryCreate(lockPath);
305
344
  if (firstHolder === null) return null;
306
- if (!isHolderStale(firstHolder)) return firstHolder;
345
+ const staleReason = holderStaleReason(firstHolder);
346
+ if (staleReason === null) return firstHolder;
307
347
 
308
348
  log.info(
309
- { lockPath, holder: firstHolder },
310
- "consolidation: taking over stale lock (holder not running)",
349
+ { lockPath, holder: firstHolder, reason: staleReason },
350
+ "consolidation: taking over stale lock",
311
351
  );
312
352
  try {
313
353
  unlinkSync(lockPath);
@@ -359,18 +399,62 @@ function tryCreate(lockPath: string): string | null {
359
399
  }
360
400
 
361
401
  /**
362
- * A holder string is stale when its PID parses to a non-running process.
363
- * The payload format is `<pid> <timestamp>` (see `tryCreate`'s write), but
364
- * an unparseable / empty / `"unknown"` payload is also treated as stale:
365
- * the only writer is `tryCreate` itself, so corruption indicates a partial
366
- * write from a crashed prior holder rather than a live writer mid-flush.
402
+ * Why a lock holder is considered stale, for diagnosable takeover logs:
403
+ * - `unparseable`: empty / corrupt payload (partial write from a crash).
404
+ * - `pid_dead`: the holder's PID is no longer running.
405
+ * - `expired`: the lock is older than {@link STALE_LOCK_TTL_MS} even though
406
+ * its PID still appears alive — the PID-1 collision case in containers.
367
407
  */
368
- function isHolderStale(holder: string): boolean {
369
- const match = /^\d+/.exec(holder);
370
- if (!match) return true;
371
- const pid = Number.parseInt(match[0], 10);
372
- if (!Number.isFinite(pid) || pid <= 0) return true;
373
- return !isProcessAlive(pid);
408
+ type StaleReason = "unparseable" | "pid_dead" | "expired";
409
+
410
+ /**
411
+ * Parse a `<pid> <timestamp>` holder payload (see `tryCreate`'s write).
412
+ * Returns `null` when the PID cannot be parsed; a missing/garbled timestamp
413
+ * yields `timestamp: null` so a partial payload still gives us the PID.
414
+ */
415
+ function parseHolder(
416
+ holder: string,
417
+ ): { pid: number; timestamp: number | null } | null {
418
+ const match = /^(\d+)(?:\s+(\d+))?/.exec(holder);
419
+ if (!match) return null;
420
+ const pid = Number.parseInt(match[1], 10);
421
+ if (!Number.isFinite(pid) || pid <= 0) return null;
422
+ const timestamp =
423
+ match[2] !== undefined ? Number.parseInt(match[2], 10) : null;
424
+ return {
425
+ pid,
426
+ timestamp:
427
+ timestamp !== null && Number.isFinite(timestamp) ? timestamp : null,
428
+ };
429
+ }
430
+
431
+ /**
432
+ * Classify a holder string, returning the reason it is stale or `null` when
433
+ * the lock is held by a live process and must be respected.
434
+ *
435
+ * Takeover triggers, in order:
436
+ * 1. Unparseable / empty / `"unknown"` payload → `unparseable`. The only
437
+ * writer is `tryCreate`, so corruption is a partial write from a crashed
438
+ * prior holder, not a live writer mid-flush.
439
+ * 2. PID not running → `pid_dead`. The fast path for a crashed daemon (or a
440
+ * different process now occupying that PID on a normal host).
441
+ * 3. Lock older than {@link STALE_LOCK_TTL_MS} → `expired`. Required because
442
+ * the daemon runs as PID 1 in containers: after a restart the new daemon
443
+ * is also PID 1, so the liveness probe alone reports the holder as alive
444
+ * forever and could never reclaim an abandoned lock. The TTL is far above
445
+ * the run's hard timeout, so it never fires against an in-flight run.
446
+ */
447
+ function holderStaleReason(holder: string): StaleReason | null {
448
+ const parsed = parseHolder(holder);
449
+ if (parsed === null) return "unparseable";
450
+ if (!isProcessAlive(parsed.pid)) return "pid_dead";
451
+ if (
452
+ parsed.timestamp !== null &&
453
+ Date.now() - parsed.timestamp > STALE_LOCK_TTL_MS
454
+ ) {
455
+ return "expired";
456
+ }
457
+ return null;
374
458
  }
375
459
 
376
460
  /**
@@ -0,0 +1,79 @@
1
+ /**
2
+ * The `# memory/concepts/<slug>.md` header convention for persisted
3
+ * memory-injection blocks — builder, matcher, and slug extraction.
4
+ *
5
+ * Both the v2 injection renderer (`injection.ts`) and the v3 card renderers
6
+ * (`plugins/defaults/memory-v3-shadow/card.ts` / `page-content.ts`) emit each
7
+ * concept page under this exact header inside the block that is persisted on
8
+ * the user message (`metadata.memoryInjectedBlock` /
9
+ * `metadata.memoryV3InjectedBlock`) and re-attached at request build. The
10
+ * v3 prune valve's card-section parser keys on the same header. Keeping the
11
+ * builder and the matcher in one place is what guarantees the writers and the
12
+ * read-side parsers never drift apart.
13
+ *
14
+ * Skill (`skills/<id>`) and CLI-command sections render under their own
15
+ * `# Skill:` / `# CLI command:` headers without a recoverable slug, so they
16
+ * are intentionally not extracted.
17
+ *
18
+ * Kept as a dependency-free leaf (like `memory-marker.ts`) so the
19
+ * conversation-fork path can import it without pulling in the heavyweight
20
+ * injection module.
21
+ */
22
+
23
+ /** Render the concept-page path header that opens a page's section inside an
24
+ * injected memory block. The read-side inverse is
25
+ * {@link INJECTED_CONCEPT_HEADER_REGEX}. */
26
+ export function injectedConceptHeader(slug: string): string {
27
+ return `# memory/concepts/${slug}.md`;
28
+ }
29
+
30
+ /**
31
+ * Matches a {@link injectedConceptHeader} line inside an injected block;
32
+ * capture group 1 is the page slug.
33
+ *
34
+ * Flagged `gm` for `String.prototype.matchAll`, which clones the regex per
35
+ * spec and so never mutates this shared instance's `lastIndex`. Do NOT call
36
+ * `exec`/`test` on it directly — a `g`-flagged regex is stateful under those.
37
+ */
38
+ export const INJECTED_CONCEPT_HEADER_REGEX = /^# memory\/concepts\/(.+)\.md$/gm;
39
+
40
+ /** Recover the (deduplicated, in-order) concept slugs a persisted injection
41
+ * block contains. */
42
+ export function extractInjectedConceptSlugs(block: string): string[] {
43
+ const slugs: string[] = [];
44
+ const seen = new Set<string>();
45
+ for (const match of block.matchAll(INJECTED_CONCEPT_HEADER_REGEX)) {
46
+ const slug = match[1]!;
47
+ if (seen.has(slug)) continue;
48
+ seen.add(slug);
49
+ slugs.push(slug);
50
+ }
51
+ return slugs;
52
+ }
53
+
54
+ /**
55
+ * Read a persisted memory-injection block off a message's metadata JSON, or
56
+ * `null` when absent/malformed. `key` selects the injection layer: v2's
57
+ * `memoryInjectedBlock` or memory-v3's card block
58
+ * (`MEMORY_V3_INJECTED_BLOCK_METADATA_KEY`).
59
+ *
60
+ * NOTE: `memory/conversation-crud.ts` carries a private copy of this exact
61
+ * helper (its fork-seeding scan predates this export); consolidating it onto
62
+ * this one is a pending cleanup tracked alongside the prune-valve work.
63
+ */
64
+ export function readInjectedBlock(
65
+ metadata: string | null | undefined,
66
+ key: string,
67
+ ): string | null {
68
+ if (!metadata) return null;
69
+ try {
70
+ const parsed: unknown = JSON.parse(metadata);
71
+ if (parsed && typeof parsed === "object" && !Array.isArray(parsed)) {
72
+ const block = (parsed as Record<string, unknown>)[key];
73
+ if (typeof block === "string") return block;
74
+ }
75
+ } catch {
76
+ // Malformed metadata — treat as no block.
77
+ }
78
+ return null;
79
+ }
@@ -727,8 +727,13 @@ interface RenderInjectionBlockResult {
727
727
  * if relevant. Suppressed when every section is a full-page fallback —
728
728
  * claiming "these are summaries" over already-complete content would mislead
729
729
  * the agent into wasted reads.
730
+ *
731
+ * Exported for the v2-suppression regression tests: memory-v3's
732
+ * `V3_CARDS_INJECTION_HEADER` is deliberately byte-identical to this header,
733
+ * which is exactly why the v3-era tail strip must discriminate the two
734
+ * `<memory>` layers by block identity rather than by this shared prefix.
730
735
  */
731
- const INJECTION_HEADER =
736
+ export const INJECTION_HEADER =
732
737
  'Use `file_read("memory/concepts/path/to/file.md")` to read the full pages for any of the injected memory summaries you want more information on.';
733
738
 
734
739
  /**