@vellumai/assistant 0.4.56 → 0.5.0

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 (457) hide show
  1. package/ARCHITECTURE.md +10 -10
  2. package/Dockerfile +3 -0
  3. package/README.md +11 -11
  4. package/docs/architecture/integrations.md +2 -2
  5. package/docs/architecture/memory.md +3 -4
  6. package/docs/credential-execution-service.md +13 -20
  7. package/node_modules/@vellumai/ces-contracts/src/error.ts +5 -4
  8. package/package.json +1 -1
  9. package/src/__tests__/actor-token-service.test.ts +7 -7
  10. package/src/__tests__/anthropic-provider.test.ts +172 -0
  11. package/src/__tests__/app-builder-tool-scripts.test.ts +15 -1
  12. package/src/__tests__/approval-cascade.test.ts +2 -2
  13. package/src/__tests__/approval-routes-http.test.ts +3 -4
  14. package/src/__tests__/asset-materialize-tool.test.ts +5 -5
  15. package/src/__tests__/asset-search-tool.test.ts +1 -1
  16. package/src/__tests__/assistant-attachments.test.ts +5 -5
  17. package/src/__tests__/assistant-events-sse-hardening.test.ts +1 -1
  18. package/src/__tests__/assistant-feature-flags-integration.test.ts +50 -38
  19. package/src/__tests__/attachments-store.test.ts +2 -2
  20. package/src/__tests__/avatar-e2e.test.ts +5 -3
  21. package/src/__tests__/browser-skill-endstate.test.ts +0 -1
  22. package/src/__tests__/call-routes-http.test.ts +2 -2
  23. package/src/__tests__/callback-handoff-copy.test.ts +1 -1
  24. package/src/__tests__/cancel-resolves-conversation-key.test.ts +158 -0
  25. package/src/__tests__/channel-readiness-routes.test.ts +0 -1
  26. package/src/__tests__/channel-readiness-service.test.ts +0 -1
  27. package/src/__tests__/checker.test.ts +31 -32
  28. package/src/__tests__/chrome-cdp.test.ts +47 -18
  29. package/src/__tests__/claude-code-skill-regression.test.ts +2 -2
  30. package/src/__tests__/config-schema-cmd.test.ts +2 -2
  31. package/src/__tests__/config-schema.test.ts +9 -18
  32. package/src/__tests__/confirmation-request-guardian-bridge.test.ts +1 -1
  33. package/src/__tests__/conversation-abort-tool-results.test.ts +4 -4
  34. package/src/__tests__/conversation-agent-loop-overflow.test.ts +2 -2
  35. package/src/__tests__/conversation-agent-loop.test.ts +11 -4
  36. package/src/__tests__/conversation-attachments.test.ts +1 -1
  37. package/src/__tests__/conversation-confirmation-signals.test.ts +2 -2
  38. package/src/__tests__/conversation-error.test.ts +33 -0
  39. package/src/__tests__/conversation-init.benchmark.test.ts +0 -1
  40. package/src/__tests__/conversation-load-history-repair.test.ts +1 -1
  41. package/src/__tests__/conversation-pairing.test.ts +1 -1
  42. package/src/__tests__/conversation-pre-run-repair.test.ts +4 -4
  43. package/src/__tests__/conversation-provider-retry-repair.test.ts +4 -4
  44. package/src/__tests__/conversation-queue.test.ts +23 -14
  45. package/src/__tests__/conversation-routes-slash-commands.test.ts +3 -3
  46. package/src/__tests__/conversation-runtime-assembly.test.ts +204 -185
  47. package/src/__tests__/conversation-seed-composer.test.ts +1 -1
  48. package/src/__tests__/conversation-slash-queue.test.ts +4 -4
  49. package/src/__tests__/conversation-slash-unknown.test.ts +4 -4
  50. package/src/__tests__/conversation-starter-routes.test.ts +291 -0
  51. package/src/__tests__/conversation-wipe.test.ts +438 -0
  52. package/src/__tests__/conversation-workspace-cache-state.test.ts +2 -3
  53. package/src/__tests__/conversation-workspace-injection.test.ts +4 -5
  54. package/src/__tests__/conversation-workspace-tool-tracking.test.ts +4 -5
  55. package/src/__tests__/credential-security-e2e.test.ts +20 -0
  56. package/src/__tests__/credential-security-invariants.test.ts +1 -0
  57. package/src/__tests__/credential-vault-unit.test.ts +227 -0
  58. package/src/__tests__/credentials-cli.test.ts +3 -0
  59. package/src/__tests__/date-context.test.ts +59 -377
  60. package/src/__tests__/drop-capability-card-state-migration.test.ts +169 -0
  61. package/src/__tests__/dynamic-skill-workflow-prompt.test.ts +11 -45
  62. package/src/__tests__/emit-signal-routing-intent.test.ts +3 -3
  63. package/src/__tests__/encrypted-store.test.ts +249 -15
  64. package/src/__tests__/ephemeral-permissions.test.ts +4 -5
  65. package/src/__tests__/event-bus.test.ts +3 -3
  66. package/src/__tests__/file-read-tool.test.ts +40 -0
  67. package/src/__tests__/gateway-only-enforcement.test.ts +2 -2
  68. package/src/__tests__/gateway-only-guard.test.ts +1 -0
  69. package/src/__tests__/gemini-image-service.test.ts +4 -4
  70. package/src/__tests__/gemini-provider.test.ts +6 -9
  71. package/src/__tests__/guardian-binding-drift-heal.test.ts +128 -0
  72. package/src/__tests__/guardian-dispatch.test.ts +0 -1
  73. package/src/__tests__/host-file-read-tool.test.ts +87 -0
  74. package/src/__tests__/host-shell-tool.test.ts +6 -6
  75. package/src/__tests__/http-user-message-parity.test.ts +2 -2
  76. package/src/__tests__/identity-intro-cache.test.ts +209 -0
  77. package/src/__tests__/intent-routing.test.ts +51 -99
  78. package/src/__tests__/invite-routes-http.test.ts +5 -0
  79. package/src/__tests__/list-messages-attachments.test.ts +1 -1
  80. package/src/__tests__/managed-proxy-context.test.ts +2 -5
  81. package/src/__tests__/managed-skill-lifecycle.test.ts +8 -8
  82. package/src/__tests__/media-generate-image.test.ts +32 -15
  83. package/src/__tests__/media-reuse-story.e2e.test.ts +1 -1
  84. package/src/__tests__/memory-context-benchmark.benchmark.test.ts +1 -1
  85. package/src/__tests__/memory-lifecycle-e2e.test.ts +24 -18
  86. package/src/__tests__/memory-recall-quality.test.ts +4 -3
  87. package/src/__tests__/memory-regressions.test.ts +86 -90
  88. package/src/__tests__/migration-cross-version-compatibility.test.ts +32 -32
  89. package/src/__tests__/migration-export-http.test.ts +26 -27
  90. package/src/__tests__/migration-import-commit-http.test.ts +165 -37
  91. package/src/__tests__/migration-import-preflight-http.test.ts +81 -20
  92. package/src/__tests__/migration-validate-http.test.ts +16 -16
  93. package/src/__tests__/model-intents.test.ts +2 -2
  94. package/src/__tests__/no-domain-routing-in-prompt-guard.test.ts +1 -1
  95. package/src/__tests__/non-member-access-request.test.ts +3 -3
  96. package/src/__tests__/notification-broadcaster.test.ts +1 -1
  97. package/src/__tests__/notification-decision-fallback.test.ts +2 -2
  98. package/src/__tests__/notification-decision-identity.test.ts +8 -9
  99. package/src/__tests__/notification-decision-strategy.test.ts +1 -1
  100. package/src/__tests__/notification-deep-link.test.ts +1 -1
  101. package/src/__tests__/notification-guardian-path.test.ts +0 -1
  102. package/src/__tests__/notification-schedule-dedup.test.ts +7 -7
  103. package/src/__tests__/oauth-store.test.ts +1 -3
  104. package/src/__tests__/oauth2-gateway-transport.test.ts +6 -1
  105. package/src/__tests__/onboarding-template-contract.test.ts +23 -59
  106. package/src/__tests__/provider-error-scenarios.test.ts +154 -0
  107. package/src/__tests__/provider-fail-open-selection.test.ts +2 -2
  108. package/src/__tests__/provider-managed-proxy-integration.test.ts +8 -9
  109. package/src/__tests__/provider-registry-ollama.test.ts +5 -2
  110. package/src/__tests__/qdrant-manager.test.ts +7 -7
  111. package/src/__tests__/ratelimit.test.ts +0 -74
  112. package/src/__tests__/recording-handler.test.ts +0 -1
  113. package/src/__tests__/require-fresh-approval.test.ts +1 -1
  114. package/src/__tests__/runtime-attachment-metadata.test.ts +1 -1
  115. package/src/__tests__/runtime-events-sse-parity.test.ts +1 -1
  116. package/src/__tests__/runtime-events-sse.test.ts +1 -1
  117. package/src/__tests__/scheduler-recurrence.test.ts +46 -2
  118. package/src/__tests__/schema-transforms.test.ts +114 -54
  119. package/src/__tests__/secret-onetime-send.test.ts +20 -0
  120. package/src/__tests__/secret-routes-managed-proxy.test.ts +5 -2
  121. package/src/__tests__/secret-scanner-executor.test.ts +1 -2
  122. package/src/__tests__/send-endpoint-busy.test.ts +63 -4
  123. package/src/__tests__/send-notification-tool.test.ts +2 -2
  124. package/src/__tests__/shell-credential-ref.test.ts +0 -1
  125. package/src/__tests__/shell-tool-proxy-mode.test.ts +1 -2
  126. package/src/__tests__/skill-memory.test.ts +549 -0
  127. package/src/__tests__/skill-script-runner-sandbox.test.ts +1 -2
  128. package/src/__tests__/slack-app-setup-skill-regression.test.ts +37 -0
  129. package/src/__tests__/slack-channel-config.test.ts +109 -94
  130. package/src/__tests__/swarm-conversation-integration.test.ts +2 -2
  131. package/src/__tests__/swarm-recursion.test.ts +2 -2
  132. package/src/__tests__/swarm-tool.test.ts +2 -2
  133. package/src/__tests__/system-prompt.test.ts +19 -66
  134. package/src/__tests__/telegram-config.test.ts +121 -0
  135. package/src/__tests__/terminal-tools.test.ts +1 -1
  136. package/src/__tests__/tool-execution-abort-cleanup.test.ts +1 -2
  137. package/src/__tests__/tool-executor-lifecycle-events.test.ts +1 -1
  138. package/src/__tests__/tool-executor-shell-integration.test.ts +1 -1
  139. package/src/__tests__/tool-executor.test.ts +1 -1
  140. package/src/__tests__/trace-emitter.test.ts +8 -1
  141. package/src/__tests__/trust-store.test.ts +7 -8
  142. package/src/__tests__/twilio-routes.test.ts +1 -18
  143. package/src/__tests__/user-reference.test.ts +82 -2
  144. package/src/__tests__/vbundle-pax-and-symlink.test.ts +196 -0
  145. package/src/__tests__/verification-control-plane-policy.test.ts +1 -1
  146. package/src/approvals/guardian-request-resolvers.ts +3 -3
  147. package/src/avatar/ascii-renderer.ts +2 -2
  148. package/src/avatar/png-renderer.ts +2 -2
  149. package/src/avatar/resvg-lazy.ts +21 -0
  150. package/src/calls/guardian-dispatch.ts +1 -1
  151. package/src/calls/relay-access-wait.ts +2 -2
  152. package/src/calls/twilio-rest.ts +0 -248
  153. package/src/cli/AGENTS.md +5 -8
  154. package/src/cli/__tests__/notifications.test.ts +5 -5
  155. package/src/cli/commands/avatar.ts +64 -2
  156. package/src/cli/commands/conversations.ts +131 -1
  157. package/src/cli/commands/credentials.ts +2 -0
  158. package/src/cli/commands/notifications.ts +3 -3
  159. package/src/cli.ts +10 -0
  160. package/src/config/bundled-skills/acp/SKILL.md +5 -5
  161. package/src/config/bundled-skills/acp/TOOLS.json +6 -6
  162. package/src/config/bundled-skills/app-builder/SKILL.md +42 -42
  163. package/src/config/bundled-skills/app-builder/TOOLS.json +10 -10
  164. package/src/config/bundled-skills/browser/SKILL.md +15 -15
  165. package/src/config/bundled-skills/browser/TOOLS.json +14 -14
  166. package/src/config/bundled-skills/chatgpt-import/SKILL.md +2 -2
  167. package/src/config/bundled-skills/chatgpt-import/TOOLS.json +1 -1
  168. package/src/config/bundled-skills/chatgpt-import/tools/chatgpt-import.ts +1 -1
  169. package/src/config/bundled-skills/claude-code/SKILL.md +5 -5
  170. package/src/config/bundled-skills/computer-use/SKILL.md +2 -2
  171. package/src/config/bundled-skills/computer-use/TOOLS.json +15 -15
  172. package/src/config/bundled-skills/contacts/SKILL.md +3 -3
  173. package/src/config/bundled-skills/contacts/TOOLS.json +4 -4
  174. package/src/config/bundled-skills/document/SKILL.md +4 -4
  175. package/src/config/bundled-skills/document/TOOLS.json +2 -2
  176. package/src/config/bundled-skills/followups/TOOLS.json +3 -3
  177. package/src/config/bundled-skills/gmail/SKILL.md +32 -32
  178. package/src/config/bundled-skills/gmail/TOOLS.json +16 -16
  179. package/src/config/bundled-skills/gmail/tools/gmail-archive.ts +1 -1
  180. package/src/config/bundled-skills/gmail/tools/gmail-sender-digest.ts +1 -1
  181. package/src/config/bundled-skills/google-calendar/SKILL.md +1 -1
  182. package/src/config/bundled-skills/google-calendar/TOOLS.json +5 -5
  183. package/src/config/bundled-skills/google-calendar/types.ts +1 -1
  184. package/src/config/bundled-skills/heartbeat/SKILL.md +43 -0
  185. package/src/config/bundled-skills/image-studio/SKILL.md +3 -3
  186. package/src/config/bundled-skills/image-studio/TOOLS.json +2 -3
  187. package/src/config/bundled-skills/image-studio/tools/media-generate-image.ts +16 -12
  188. package/src/config/bundled-skills/media-processing/SKILL.md +40 -40
  189. package/src/config/bundled-skills/media-processing/TOOLS.json +8 -8
  190. package/src/config/bundled-skills/media-processing/__tests__/concurrency-pool.test.ts +2 -2
  191. package/src/config/bundled-skills/media-processing/__tests__/preprocess.test.ts +1 -1
  192. package/src/config/bundled-skills/media-processing/services/gemini-map.ts +5 -5
  193. package/src/config/bundled-skills/media-processing/services/gemini-video.ts +2 -2
  194. package/src/config/bundled-skills/media-processing/services/preprocess.ts +2 -2
  195. package/src/config/bundled-skills/media-processing/services/processing-pipeline.ts +2 -2
  196. package/src/config/bundled-skills/media-processing/services/reduce.ts +3 -3
  197. package/src/config/bundled-skills/media-processing/tools/generate-clip.ts +2 -2
  198. package/src/config/bundled-skills/media-processing/tools/query-media-events.ts +1 -1
  199. package/src/config/bundled-skills/messaging/SKILL.md +29 -25
  200. package/src/config/bundled-skills/messaging/TOOLS.json +11 -11
  201. package/src/config/bundled-skills/messaging/tools/messaging-send.ts +1 -1
  202. package/src/config/bundled-skills/messaging/tools/shared.ts +1 -1
  203. package/src/config/bundled-skills/notifications/SKILL.md +3 -3
  204. package/src/config/bundled-skills/notifications/TOOLS.json +2 -2
  205. package/src/config/bundled-skills/notifications/tools/send-notification.ts +3 -3
  206. package/src/config/bundled-skills/orchestration/SKILL.md +1 -1
  207. package/src/config/bundled-skills/orchestration/TOOLS.json +1 -1
  208. package/src/config/bundled-skills/phone-calls/SKILL.md +18 -14
  209. package/src/config/bundled-skills/phone-calls/TOOLS.json +3 -3
  210. package/src/config/bundled-skills/phone-calls/references/CONFIG.md +2 -2
  211. package/src/config/bundled-skills/phone-calls/references/TRANSCRIPTS.md +2 -2
  212. package/src/config/bundled-skills/phone-calls/references/TROUBLESHOOTING.md +1 -1
  213. package/src/config/bundled-skills/playbooks/TOOLS.json +4 -4
  214. package/src/config/bundled-skills/schedule/SKILL.md +26 -26
  215. package/src/config/bundled-skills/schedule/TOOLS.json +5 -5
  216. package/src/config/bundled-skills/screen-watch/SKILL.md +3 -3
  217. package/src/config/bundled-skills/screen-watch/TOOLS.json +1 -1
  218. package/src/config/bundled-skills/sequences/SKILL.md +2 -2
  219. package/src/config/bundled-skills/sequences/TOOLS.json +10 -10
  220. package/src/config/bundled-skills/sequences/tools/sequence-analytics.ts +2 -2
  221. package/src/config/bundled-skills/sequences/tools/sequence-enroll.ts +2 -2
  222. package/src/config/bundled-skills/sequences/tools/sequence-enrollment-list.ts +1 -1
  223. package/src/config/bundled-skills/sequences/tools/sequence-get.ts +1 -1
  224. package/src/config/bundled-skills/sequences/tools/sequence-import.ts +3 -3
  225. package/src/config/bundled-skills/sequences/tools/sequence-list.ts +1 -1
  226. package/src/config/bundled-skills/sequences/tools/sequence-update.ts +1 -1
  227. package/src/config/bundled-skills/settings/TOOLS.json +3 -3
  228. package/src/config/bundled-skills/settings/tools/open-system-settings.ts +1 -1
  229. package/src/config/bundled-skills/skill-management/TOOLS.json +5 -5
  230. package/src/config/bundled-skills/skills-catalog/SKILL.md +84 -0
  231. package/src/config/bundled-skills/slack/SKILL.md +2 -2
  232. package/src/config/bundled-skills/slack/TOOLS.json +8 -8
  233. package/src/config/bundled-skills/slack/tools/slack-scan-digest.ts +3 -3
  234. package/src/config/bundled-skills/subagent/TOOLS.json +5 -5
  235. package/src/config/bundled-skills/tasks/SKILL.md +1 -1
  236. package/src/config/bundled-skills/tasks/TOOLS.json +9 -9
  237. package/src/config/bundled-skills/transcribe/SKILL.md +5 -5
  238. package/src/config/bundled-skills/transcribe/TOOLS.json +1 -1
  239. package/src/config/bundled-skills/transcribe/tools/transcribe-media.ts +10 -10
  240. package/src/config/bundled-skills/watcher/SKILL.md +4 -4
  241. package/src/config/bundled-skills/watcher/TOOLS.json +5 -5
  242. package/src/config/feature-flag-registry.json +33 -17
  243. package/src/config/schemas/sandbox.ts +1 -1
  244. package/src/config/schemas/services.ts +13 -3
  245. package/src/config/schemas/timeouts.ts +0 -10
  246. package/src/contacts/contact-store.ts +63 -0
  247. package/src/contacts/contacts-write.ts +1 -1
  248. package/src/daemon/assistant-attachments.ts +2 -2
  249. package/src/daemon/conversation-agent-loop-handlers.ts +2 -2
  250. package/src/daemon/conversation-agent-loop.ts +7 -30
  251. package/src/daemon/conversation-error.ts +24 -0
  252. package/src/daemon/conversation-memory.ts +8 -7
  253. package/src/daemon/conversation-runtime-assembly.ts +141 -275
  254. package/src/daemon/conversation-slash.ts +7 -26
  255. package/src/daemon/conversation-surfaces.ts +14 -0
  256. package/src/daemon/conversation-tool-setup.ts +9 -8
  257. package/src/daemon/conversation.ts +2 -0
  258. package/src/daemon/daemon-control.ts +1 -1
  259. package/src/daemon/date-context.ts +10 -83
  260. package/src/daemon/handlers/config-channels.ts +12 -2
  261. package/src/daemon/handlers/config-slack-channel.ts +7 -1
  262. package/src/daemon/handlers/config-telegram.ts +6 -1
  263. package/src/daemon/handlers/conversations.ts +2 -2
  264. package/src/daemon/handlers/skills.ts +4 -0
  265. package/src/daemon/lifecycle.ts +28 -4
  266. package/src/daemon/providers-setup.ts +1 -1
  267. package/src/daemon/server.ts +1 -5
  268. package/src/daemon/shutdown-handlers.ts +9 -3
  269. package/src/daemon/tool-side-effects.ts +40 -0
  270. package/src/daemon/trace-emitter.ts +26 -2
  271. package/src/events/domain-events.ts +1 -1
  272. package/src/events/tool-permission-telemetry-listener.ts +46 -0
  273. package/src/inbound/platform-callback-registration.ts +0 -18
  274. package/src/media/app-icon-generator.ts +15 -8
  275. package/src/media/avatar-router.ts +15 -8
  276. package/src/media/gemini-image-service.ts +125 -21
  277. package/src/memory/attachments-store.ts +3 -3
  278. package/src/memory/channel-verification-sessions.ts +6 -6
  279. package/src/memory/conversation-crud.ts +196 -1
  280. package/src/memory/{thread-starters-cadence.ts → conversation-starters-cadence.ts} +9 -42
  281. package/src/memory/conversation-title-service.ts +2 -3
  282. package/src/memory/db-init.ts +25 -1
  283. package/src/memory/invite-store.ts +4 -4
  284. package/src/memory/items-extractor.ts +4 -4
  285. package/src/memory/job-handlers/{thread-starters.ts → conversation-starters.ts} +123 -38
  286. package/src/memory/jobs-store.ts +3 -2
  287. package/src/memory/jobs-worker.ts +7 -5
  288. package/src/memory/lifecycle-events-store.ts +63 -0
  289. package/src/memory/migrations/172-rename-created-by-session-id.ts +27 -0
  290. package/src/memory/migrations/173-rename-source-session-id.ts +16 -0
  291. package/src/memory/migrations/174-rename-thread-starters-table.ts +52 -0
  292. package/src/memory/migrations/175-create-lifecycle-events.ts +15 -0
  293. package/src/memory/migrations/176-drop-capability-card-state.ts +36 -0
  294. package/src/memory/migrations/177-create-trace-events-table.ts +40 -0
  295. package/src/memory/migrations/index.ts +6 -0
  296. package/src/memory/migrations/registry.ts +13 -0
  297. package/src/memory/retriever.test.ts +223 -96
  298. package/src/memory/retriever.ts +115 -138
  299. package/src/memory/schema/calls.ts +1 -1
  300. package/src/memory/schema/contacts.ts +1 -1
  301. package/src/memory/schema/infrastructure.ts +29 -0
  302. package/src/memory/schema/memory-core.ts +7 -17
  303. package/src/memory/schema/notifications.ts +1 -1
  304. package/src/memory/search/formatting.ts +23 -6
  305. package/src/memory/search/lexical.ts +2 -0
  306. package/src/memory/search/semantic.ts +2 -0
  307. package/src/memory/search/staleness.ts +5 -1
  308. package/src/memory/search/types.ts +4 -0
  309. package/src/memory/task-memory-cleanup.ts +96 -6
  310. package/src/memory/trace-event-store.ts +148 -0
  311. package/src/notifications/README.md +1 -1
  312. package/src/notifications/decision-engine.ts +45 -4
  313. package/src/notifications/emit-signal.ts +5 -4
  314. package/src/notifications/events-store.ts +4 -4
  315. package/src/notifications/signal.ts +1 -1
  316. package/src/oauth/manual-token-connection.ts +49 -25
  317. package/src/permissions/checker.ts +6 -5
  318. package/src/permissions/defaults.ts +4 -4
  319. package/src/prompts/__tests__/build-cli-reference-section.test.ts +9 -90
  320. package/src/prompts/cache-boundary.ts +8 -0
  321. package/src/prompts/system-prompt.ts +105 -634
  322. package/src/prompts/templates/BOOTSTRAP.md +172 -33
  323. package/src/prompts/templates/IDENTITY.md +8 -24
  324. package/src/prompts/templates/SOUL.md +20 -41
  325. package/src/prompts/templates/USER.md +3 -19
  326. package/src/prompts/user-reference.ts +14 -16
  327. package/src/providers/anthropic/client.ts +51 -19
  328. package/src/providers/gemini/client.ts +6 -9
  329. package/src/providers/managed-proxy/constants.ts +1 -7
  330. package/src/providers/managed-proxy/context.ts +0 -1
  331. package/src/providers/model-intents.ts +5 -5
  332. package/src/providers/openai/client.ts +10 -1
  333. package/src/providers/openrouter/client.ts +1 -0
  334. package/src/providers/ratelimit.ts +0 -35
  335. package/src/providers/registry.ts +3 -5
  336. package/src/providers/retry.ts +18 -1
  337. package/src/runtime/access-request-helper.ts +16 -2
  338. package/src/runtime/auth/route-policy.ts +7 -0
  339. package/src/runtime/channel-verification-service.ts +1 -1
  340. package/src/runtime/confirmation-request-guardian-bridge.ts +1 -1
  341. package/src/runtime/guardian-vellum-migration.ts +61 -1
  342. package/src/runtime/http-server.ts +8 -4
  343. package/src/runtime/migrations/vbundle-builder.ts +212 -32
  344. package/src/runtime/migrations/vbundle-import-analyzer.ts +74 -8
  345. package/src/runtime/migrations/vbundle-importer.ts +66 -1
  346. package/src/runtime/migrations/vbundle-validator.ts +17 -3
  347. package/src/runtime/routes/approval-strategies/guardian-callback-strategy.ts +4 -4
  348. package/src/runtime/routes/attachment-routes.ts +2 -2
  349. package/src/runtime/routes/btw-routes.ts +93 -0
  350. package/src/runtime/routes/channel-verification-routes.ts +19 -2
  351. package/src/runtime/routes/conversation-management-routes.ts +55 -1
  352. package/src/runtime/routes/conversation-query-routes.ts +1 -1
  353. package/src/runtime/routes/conversation-routes.ts +49 -5
  354. package/src/runtime/routes/conversation-starter-routes.ts +207 -0
  355. package/src/runtime/routes/guardian-bootstrap-routes.ts +13 -9
  356. package/src/runtime/routes/identity-intro-cache.ts +105 -0
  357. package/src/runtime/routes/identity-routes.ts +51 -0
  358. package/src/runtime/routes/inbound-stages/escalation-intercept.ts +1 -1
  359. package/src/runtime/routes/inbound-stages/verification-intercept.ts +1 -1
  360. package/src/runtime/routes/migration-routes.ts +25 -13
  361. package/src/runtime/routes/secret-routes.ts +18 -0
  362. package/src/runtime/routes/settings-routes.ts +9 -9
  363. package/src/runtime/routes/telemetry-routes.ts +53 -0
  364. package/src/runtime/routes/trace-event-routes.ts +62 -0
  365. package/src/runtime/tool-grant-request-helper.ts +1 -1
  366. package/src/runtime/verification-outbound-actions.ts +47 -31
  367. package/src/security/encrypted-store.ts +262 -78
  368. package/src/skills/catalog-install.ts +10 -0
  369. package/src/skills/managed-store.ts +2 -0
  370. package/src/skills/skill-memory.ts +222 -0
  371. package/src/subagent/manager.ts +1 -4
  372. package/src/telemetry/types.ts +10 -1
  373. package/src/telemetry/usage-telemetry-reporter.test.ts +7 -2
  374. package/src/telemetry/usage-telemetry-reporter.ts +53 -4
  375. package/src/tools/AGENTS.md +11 -11
  376. package/src/tools/acp/spawn.ts +1 -1
  377. package/src/tools/apps/executors.ts +8 -8
  378. package/src/tools/apps/registry.ts +1 -1
  379. package/src/tools/assets/materialize.ts +6 -6
  380. package/src/tools/assets/search.ts +10 -10
  381. package/src/tools/browser/__tests__/auth-cache.test.ts +2 -2
  382. package/src/tools/browser/__tests__/auth-detector.test.ts +4 -4
  383. package/src/tools/browser/auth-detector.ts +6 -6
  384. package/src/tools/browser/browser-execution.ts +13 -13
  385. package/src/tools/browser/browser-manager.ts +3 -3
  386. package/src/tools/browser/chrome-cdp.ts +5 -5
  387. package/src/tools/browser/jit-auth.ts +2 -2
  388. package/src/tools/browser/network-recorder.test.ts +2 -2
  389. package/src/tools/browser/network-recorder.ts +3 -3
  390. package/src/tools/browser/runtime-check.ts +3 -3
  391. package/src/tools/claude-code/claude-code.ts +2 -2
  392. package/src/tools/computer-use/definitions.ts +18 -18
  393. package/src/tools/credential-execution/make-authenticated-request.ts +4 -4
  394. package/src/tools/credential-execution/manage-secure-command-tool.ts +3 -3
  395. package/src/tools/credential-execution/run-authenticated-command.ts +4 -4
  396. package/src/tools/credentials/broker-types.ts +5 -5
  397. package/src/tools/credentials/broker.ts +15 -15
  398. package/src/tools/credentials/metadata-store.ts +2 -2
  399. package/src/tools/credentials/resolve.ts +1 -1
  400. package/src/tools/credentials/selection.ts +1 -1
  401. package/src/tools/credentials/tool-policy.ts +1 -1
  402. package/src/tools/credentials/vault.ts +115 -25
  403. package/src/tools/execution-target.ts +2 -2
  404. package/src/tools/executor.ts +7 -7
  405. package/src/tools/filesystem/edit.ts +2 -2
  406. package/src/tools/filesystem/read.ts +15 -4
  407. package/src/tools/filesystem/write.ts +1 -1
  408. package/src/tools/host-filesystem/edit.ts +2 -1
  409. package/src/tools/host-filesystem/read.ts +18 -1
  410. package/src/tools/host-filesystem/write.ts +1 -1
  411. package/src/tools/host-terminal/host-shell.ts +9 -8
  412. package/src/tools/mcp/mcp-tool-factory.ts +7 -6
  413. package/src/tools/memory/definitions.ts +6 -5
  414. package/src/tools/memory/handlers.test.ts +1 -1
  415. package/src/tools/network/__tests__/web-search.test.ts +3 -3
  416. package/src/tools/network/domain-normalize.ts +2 -2
  417. package/src/tools/network/script-proxy/session-manager.ts +10 -10
  418. package/src/tools/network/web-fetch.ts +1 -1
  419. package/src/tools/network/web-search.ts +3 -3
  420. package/src/tools/permission-checker.ts +8 -8
  421. package/src/tools/registry.ts +7 -7
  422. package/src/tools/schedule/list.ts +2 -2
  423. package/src/tools/schema-transforms.ts +31 -21
  424. package/src/tools/secret-detection-handler.ts +1 -1
  425. package/src/tools/sensitive-output-placeholders.ts +1 -1
  426. package/src/tools/shared/filesystem/edit-engine.ts +1 -1
  427. package/src/tools/shared/filesystem/file-ops-service.ts +3 -3
  428. package/src/tools/shared/filesystem/image-read.ts +25 -5
  429. package/src/tools/shared/filesystem/path-policy.ts +2 -2
  430. package/src/tools/shared/shell-output.ts +1 -1
  431. package/src/tools/side-effects.ts +1 -1
  432. package/src/tools/skills/execute.ts +1 -1
  433. package/src/tools/skills/load.ts +3 -3
  434. package/src/tools/skills/sandbox-runner.ts +3 -3
  435. package/src/tools/subagent/read.ts +1 -1
  436. package/src/tools/subagent/spawn.ts +2 -2
  437. package/src/tools/swarm/delegate.ts +3 -3
  438. package/src/tools/system/request-permission.ts +5 -4
  439. package/src/tools/terminal/backends/native.ts +4 -4
  440. package/src/tools/terminal/parser.ts +6 -6
  441. package/src/tools/terminal/sandbox-diagnostics.ts +1 -1
  442. package/src/tools/terminal/shell.ts +16 -16
  443. package/src/tools/tool-approval-handler.ts +21 -12
  444. package/src/tools/tool-manifest.ts +4 -4
  445. package/src/tools/types.ts +3 -3
  446. package/src/tools/ui-surface/definitions.ts +9 -37
  447. package/src/tools/watcher/list.ts +1 -1
  448. package/src/util/logger.ts +7 -2
  449. package/src/util/pricing.ts +4 -0
  450. package/src/util/retry.ts +29 -1
  451. package/src/workspace/migrations/007-web-search-provider-rename.ts +37 -0
  452. package/src/workspace/migrations/registry.ts +2 -0
  453. package/src/__tests__/cli-help-reference-sync.test.ts +0 -26
  454. package/src/__tests__/onboarding-starter-tasks.test.ts +0 -190
  455. package/src/cli/reference.ts +0 -38
  456. package/src/memory/job-handlers/capability-cards.ts +0 -420
  457. package/src/runtime/routes/thread-starter-routes.ts +0 -294
@@ -54,7 +54,6 @@ mock.module("../config/loader.js", () => ({
54
54
  getConfig: () => ({
55
55
  ui: {},
56
56
 
57
- sandbox: { enabled: false, backend: "local" },
58
57
  assistantFeatureFlagValues: {},
59
58
  services: {
60
59
  inference: {
@@ -65,9 +64,9 @@ mock.module("../config/loader.js", () => ({
65
64
  "image-generation": {
66
65
  mode: "your-own",
67
66
  provider: "gemini",
68
- model: "gemini-2.5-flash-image",
67
+ model: "gemini-3.1-flash-image-preview",
69
68
  },
70
- "web-search": { mode: "your-own", provider: "anthropic-native" },
69
+ "web-search": { mode: "your-own", provider: "inference-provider-native" },
71
70
  },
72
71
  }),
73
72
  loadConfig: () => ({}),
@@ -105,11 +104,25 @@ const scheduleCreateDef = scheduleToolsJson.tools.find(
105
104
  (t: { name: string }) => t.name === "schedule_create",
106
105
  );
107
106
 
107
+ // Load send_notification description from the bundled skill TOOLS.json
108
+ const notifToolsJson = JSON.parse(
109
+ readFileSync(
110
+ join(
111
+ import.meta.dirname,
112
+ "../config/bundled-skills/notifications/TOOLS.json",
113
+ ),
114
+ "utf-8",
115
+ ),
116
+ );
117
+ const sendNotificationDef = notifToolsJson.tools.find(
118
+ (t: { name: string }) => t.name === "send_notification",
119
+ );
120
+
108
121
  // =====================================================================
109
- // 1. System prompt: buildTaskScheduleReminderRoutingSection
122
+ // 1. Routing section removed from system prompt — guidance in tool descriptions
110
123
  // =====================================================================
111
124
 
112
- describe("Task/Schedule routing section in system prompt", () => {
125
+ describe("Task/Schedule routing NOT in system prompt (moved to tool descriptions)", () => {
113
126
  beforeEach(() => {
114
127
  mkdirSync(TEST_DIR, { recursive: true });
115
128
  });
@@ -120,55 +133,12 @@ describe("Task/Schedule routing section in system prompt", () => {
120
133
  }
121
134
  });
122
135
 
123
- test("system prompt includes the routing section heading", () => {
136
+ test("system prompt does not contain the old routing section", () => {
124
137
  const prompt = buildSystemPrompt();
125
- expect(prompt).toContain(
138
+ expect(prompt).not.toContain(
126
139
  "## Tool Routing: Tasks vs Schedules vs Notifications",
127
140
  );
128
141
  });
129
-
130
- test("routing section lists all three tools in the summary table", () => {
131
- const prompt = buildSystemPrompt();
132
- expect(prompt).toContain("`task_list_add`");
133
- expect(prompt).toContain("`schedule_create`");
134
- expect(prompt).toContain("`send_notification`");
135
- });
136
-
137
- test("routing section warns that send_notification is immediate-only", () => {
138
- const prompt = buildSystemPrompt();
139
- expect(prompt).toContain("send_notification` is immediate-only");
140
- expect(prompt).toContain("fires NOW");
141
- });
142
-
143
- test("routing section includes quick routing rules", () => {
144
- const prompt = buildSystemPrompt();
145
- expect(prompt).toContain("Quick routing rules");
146
- expect(prompt).toContain("Future time, one-shot");
147
- expect(prompt).toContain("Recurring pattern");
148
- expect(prompt).toContain("No time, track as work");
149
- });
150
-
151
- test("routing section documents entity type routing", () => {
152
- const prompt = buildSystemPrompt();
153
- expect(prompt).toContain(
154
- "Entity type routing: work items vs task templates",
155
- );
156
- expect(prompt).toContain("**Work items**");
157
- expect(prompt).toContain("**Task templates**");
158
- });
159
-
160
- test("routing section references the Time-Based Actions skill", () => {
161
- const prompt = buildSystemPrompt();
162
- expect(prompt).toContain("Time-Based Actions");
163
- });
164
-
165
- test("routing section is present in the system prompt", () => {
166
- const prompt = buildSystemPrompt();
167
- const taskRoutingIdx = prompt.indexOf(
168
- "## Tool Routing: Tasks vs Schedules vs Notifications",
169
- );
170
- expect(taskRoutingIdx).toBeGreaterThanOrEqual(0);
171
- });
172
142
  });
173
143
 
174
144
  // =====================================================================
@@ -228,6 +198,18 @@ describe("schedule_create tool description", () => {
228
198
  });
229
199
  });
230
200
 
201
+ describe("send_notification tool description", () => {
202
+ test("states it fires immediately with no delay", () => {
203
+ expect(sendNotificationDef).toBeDefined();
204
+ expect(sendNotificationDef.description).toContain("immediate");
205
+ expect(sendNotificationDef.description).toContain("no delay");
206
+ });
207
+
208
+ test("redirects to schedule_create for future alerts", () => {
209
+ expect(sendNotificationDef.description).toContain("schedule_create");
210
+ });
211
+ });
212
+
231
213
  // =====================================================================
232
214
  // 3. Cross-tool consistency: schedule and task tools agree on routing boundaries
233
215
  // =====================================================================
@@ -244,10 +226,10 @@ describe("cross-tool routing consistency", () => {
244
226
  });
245
227
 
246
228
  // =====================================================================
247
- // 4. Activation hints in <available_skills> XML (replaces domain routing sections)
229
+ // 4. Activation hints in skills catalog (replaces domain routing sections)
248
230
  // =====================================================================
249
231
 
250
- describe("Activation hints in available_skills XML", () => {
232
+ describe("Activation hints in skills catalog", () => {
251
233
  beforeEach(() => {
252
234
  mkdirSync(TEST_DIR, { recursive: true });
253
235
  });
@@ -258,61 +240,31 @@ describe("Activation hints in available_skills XML", () => {
258
240
  }
259
241
  });
260
242
 
261
- test("available_skills XML does NOT contain location attribute", () => {
243
+ test("phone-calls skill includes hints and avoid-when in catalog line", () => {
262
244
  const prompt = buildSystemPrompt();
263
- const start = prompt.indexOf("<available_skills>");
264
- const end = prompt.indexOf("</available_skills>");
265
- expect(start).not.toBe(-1);
266
- expect(end).not.toBe(-1);
267
- const skillsXml = prompt.substring(start, end);
268
- expect(skillsXml).not.toContain("location=");
245
+ const line = prompt.split("\n").find((l) => l.includes("**phone-calls**"));
246
+ expect(line).toBeDefined();
247
+ // Activation hints and avoid-when are folded into the description
248
+ expect(line).toContain("Twilio");
249
+ expect(line).toContain("Avoid: ");
250
+ expect(line).toContain("voice-setup");
269
251
  });
270
252
 
271
- test("phone-calls bundled skill has hints and avoid-when attributes in XML", () => {
253
+ test("orchestration skill includes hints and avoid-when in catalog line", () => {
272
254
  const prompt = buildSystemPrompt();
273
- const start = prompt.indexOf("<available_skills>");
274
- const end = prompt.indexOf("</available_skills>");
275
- expect(start).not.toBe(-1);
276
- expect(end).not.toBe(-1);
277
- const skillsXml = prompt.substring(start, end);
278
- expect(skillsXml).toContain('id="phone-calls"');
279
- const skillLine = skillsXml
255
+ const line = prompt
280
256
  .split("\n")
281
- .find((l) => l.includes('id="phone-calls"'));
282
- expect(skillLine).toBeDefined();
283
- expect(skillLine).toContain("hints=");
284
- expect(skillLine).toContain("avoid-when=");
257
+ .find((l) => l.includes("**orchestration**"));
258
+ expect(line).toBeDefined();
259
+ expect(line).toContain("parallel");
260
+ expect(line).toContain("Single-focus");
285
261
  });
286
262
 
287
- test("orchestration bundled skill has hints and avoid-when attributes in XML", () => {
263
+ test("browser skill includes hints in catalog line", () => {
288
264
  const prompt = buildSystemPrompt();
289
- const start = prompt.indexOf("<available_skills>");
290
- const end = prompt.indexOf("</available_skills>");
291
- expect(start).not.toBe(-1);
292
- expect(end).not.toBe(-1);
293
- const skillsXml = prompt.substring(start, end);
294
- expect(skillsXml).toContain('id="orchestration"');
295
- const skillLine = skillsXml
296
- .split("\n")
297
- .find((l) => l.includes('id="orchestration"'));
298
- expect(skillLine).toBeDefined();
299
- expect(skillLine).toContain("hints=");
300
- expect(skillLine).toContain("avoid-when=");
301
- });
302
-
303
- test("browser bundled skill has hints attribute in XML", () => {
304
- const prompt = buildSystemPrompt();
305
- const start = prompt.indexOf("<available_skills>");
306
- const end = prompt.indexOf("</available_skills>");
307
- expect(start).not.toBe(-1);
308
- expect(end).not.toBe(-1);
309
- const skillsXml = prompt.substring(start, end);
310
- expect(skillsXml).toContain('id="browser"');
311
- const skillLine = skillsXml
312
- .split("\n")
313
- .find((l) => l.includes('id="browser"'));
314
- expect(skillLine).toBeDefined();
315
- expect(skillLine).toContain("hints=");
265
+ const line = prompt.split("\n").find((l) => l.includes("**browser**"));
266
+ expect(line).toBeDefined();
267
+ expect(line).toContain("browser_*");
316
268
  });
317
269
 
318
270
  test("domain routing sections are no longer in system prompt", () => {
@@ -38,6 +38,11 @@ mock.module("../telegram/bot-username.js", () => ({
38
38
  getTelegramBotUsername: () => mockTelegramBotUsername,
39
39
  }));
40
40
 
41
+ // Mock invite instruction generator — skip LLM calls in tests.
42
+ mock.module("../runtime/invite-instruction-generator.js", () => ({
43
+ generateInviteInstruction: async () => "Mock invite instruction for testing.",
44
+ }));
45
+
41
46
  // Mock startInviteCall from call-domain — test env lacks Twilio credentials.
42
47
  let mockStartInviteCallResult:
43
48
  | { ok: true; callSid: string }
@@ -39,7 +39,7 @@ mock.module("../config/loader.js", () => ({
39
39
  model: "test",
40
40
  provider: "test",
41
41
  memory: { enabled: false },
42
- rateLimit: { maxRequestsPerMinute: 0, maxTokensPerSession: 0 },
42
+ rateLimit: { maxRequestsPerMinute: 0 },
43
43
  }),
44
44
  }));
45
45
 
@@ -110,10 +110,7 @@ describe("buildManagedBaseUrl", () => {
110
110
  "https://platform.example.com/v1/runtime-proxy/anthropic",
111
111
  );
112
112
  expect(await buildManagedBaseUrl("gemini")).toBe(
113
- "https://platform.example.com/v1/runtime-proxy/vertex",
114
- );
115
- expect(await buildManagedBaseUrl("vertex")).toBe(
116
- "https://platform.example.com/v1/runtime-proxy/vertex",
113
+ "https://platform.example.com/v1/runtime-proxy/gemini",
117
114
  );
118
115
  });
119
116
 
@@ -132,7 +129,7 @@ describe("buildManagedBaseUrl", () => {
132
129
  mockPlatformBaseUrl = "";
133
130
  mockAssistantApiKey = null;
134
131
  expect(await buildManagedBaseUrl("anthropic")).toBeUndefined();
135
- expect(await buildManagedBaseUrl("vertex")).toBeUndefined();
132
+ expect(await buildManagedBaseUrl("gemini")).toBeUndefined();
136
133
  });
137
134
  });
138
135
 
@@ -16,8 +16,7 @@ const mockConfig = {
16
16
  shellMaxTimeoutSec: 600,
17
17
  permissionTimeoutSec: 300,
18
18
  },
19
- sandbox: { enabled: false },
20
- rateLimit: { maxRequestsPerMinute: 0, maxTokensPerSession: 0 },
19
+ rateLimit: { maxRequestsPerMinute: 0 },
21
20
  secretDetection: {
22
21
  enabled: true,
23
22
  action: "warn" as const,
@@ -33,9 +32,9 @@ const mockConfig = {
33
32
  "image-generation": {
34
33
  mode: "your-own",
35
34
  provider: "gemini",
36
- model: "gemini-2.5-flash-image",
35
+ model: "gemini-3.1-flash-image-preview",
37
36
  },
38
- "web-search": { mode: "your-own", provider: "anthropic-native" },
37
+ "web-search": { mode: "your-own", provider: "inference-provider-native" },
39
38
  },
40
39
  };
41
40
 
@@ -138,11 +137,12 @@ describe("managed skill lifecycle: scaffold → catalog → prompt → delete",
138
137
  expect(found!.name).toBe("Lifecycle Test");
139
138
  expect(found!.description).toBe("Integration test skill.");
140
139
 
141
- // Step 4: Verify skill appears in system prompt
140
+ // Step 4: Verify skill appears in system prompt (markdown bullet: **id**: description)
142
141
  const prompt = buildSystemPrompt();
143
- expect(prompt).toContain("lifecycle-test");
144
- expect(prompt).toContain("Lifecycle Test");
145
- expect(prompt).toContain("## Dynamic Skill Authoring Workflow");
142
+ expect(prompt).toContain("**lifecycle-test**");
143
+ expect(prompt).toContain("Integration test skill");
144
+ // Dynamic Skill Authoring section moved to tool descriptions; prompt should not contain it
145
+ expect(prompt).not.toContain("## Dynamic Skill Authoring Workflow");
146
146
 
147
147
  // Step 5: Delete the skill
148
148
  const deleteResult = await executeDeleteManagedSkill(
@@ -11,10 +11,11 @@ import type { ToolContext } from "../tools/types.js";
11
11
  // ---------------------------------------------------------------------------
12
12
 
13
13
  let mockApiKey: string | undefined = "test-gemini-key";
14
+ let mockImageGenMode: "your-own" | "managed" = "your-own";
14
15
  let mockGenerateResult = {
15
16
  images: [{ mimeType: "image/png", dataBase64: "generated-data" }],
16
17
  text: "A beautiful image",
17
- resolvedModel: "gemini-2.5-flash-image",
18
+ resolvedModel: "gemini-3.1-flash-image-preview",
18
19
  };
19
20
  let mockGenerateError: Error | null = null;
20
21
  let lastGenerateCredentials: unknown = null;
@@ -29,11 +30,11 @@ mock.module("../config/loader.js", () => ({
29
30
  model: "claude-opus-4-6",
30
31
  },
31
32
  "image-generation": {
32
- mode: "your-own",
33
+ mode: mockImageGenMode,
33
34
  provider: "gemini",
34
- model: "gemini-2.5-flash-image",
35
+ model: "gemini-3.1-flash-image-preview",
35
36
  },
36
- "web-search": { mode: "your-own", provider: "anthropic-native" },
37
+ "web-search": { mode: "your-own", provider: "inference-provider-native" },
37
38
  },
38
39
  }),
39
40
  }));
@@ -43,6 +44,10 @@ mock.module("../security/secure-keys.js", () => ({
43
44
  if (account === "gemini") return mockApiKey;
44
45
  return undefined;
45
46
  },
47
+ getProviderKeyAsync: async (provider: string) => {
48
+ if (provider === "gemini") return mockApiKey;
49
+ return undefined;
50
+ },
46
51
  }));
47
52
 
48
53
  mock.module("../media/gemini-image-service.js", () => ({
@@ -171,10 +176,11 @@ const CONFIG_DIR = join(
171
176
 
172
177
  beforeEach(() => {
173
178
  mockApiKey = "test-gemini-key";
179
+ mockImageGenMode = "your-own";
174
180
  mockGenerateResult = {
175
181
  images: [{ mimeType: "image/png", dataBase64: "generated-data" }],
176
182
  text: "A beautiful image",
177
- resolvedModel: "gemini-2.5-flash-image",
183
+ resolvedModel: "gemini-3.1-flash-image-preview",
178
184
  };
179
185
  mockGenerateError = null;
180
186
  mockAttachments = [];
@@ -208,9 +214,9 @@ describe("image-studio skill script wrapper", () => {
208
214
  expect(result.content).toContain("No Gemini API key");
209
215
  });
210
216
 
211
- test("falls back to managed proxy when no API key is configured", async () => {
212
- mockApiKey = undefined;
213
- mockManagedBaseUrl = "https://platform.example.com/v1/runtime-proxy/vertex";
217
+ test("managed mode uses managed proxy credentials", async () => {
218
+ mockImageGenMode = "managed";
219
+ mockManagedBaseUrl = "https://platform.example.com/v1/runtime-proxy/gemini";
214
220
  mockManagedProxyContext = {
215
221
  enabled: true,
216
222
  platformBaseUrl: "https://platform.example.com",
@@ -224,13 +230,25 @@ describe("image-studio skill script wrapper", () => {
224
230
  expect(lastGenerateCredentials).toEqual({
225
231
  type: "managed-proxy",
226
232
  assistantApiKey: "managed-key-123",
227
- baseUrl: "https://platform.example.com/v1/runtime-proxy/vertex",
233
+ baseUrl: "https://platform.example.com/v1/runtime-proxy/gemini",
228
234
  });
229
235
  });
230
236
 
231
- test("prefers direct API key over managed proxy", async () => {
237
+ test("managed mode returns error when managed proxy is unavailable", async () => {
238
+ mockImageGenMode = "managed";
239
+ mockApiKey = "direct-key"; // should be ignored in managed mode
240
+ mockManagedBaseUrl = undefined;
241
+
242
+ const result = await run({ prompt: "a cat" }, fakeContext);
243
+
244
+ expect(result.isError).toBe(true);
245
+ expect(result.content).toContain("Managed proxy is not available");
246
+ });
247
+
248
+ test("your-own mode uses direct API key", async () => {
249
+ mockImageGenMode = "your-own";
232
250
  mockApiKey = "direct-key";
233
- mockManagedBaseUrl = "https://platform.example.com/v1/runtime-proxy/vertex";
251
+ mockManagedBaseUrl = "https://platform.example.com/v1/runtime-proxy/gemini";
234
252
  mockManagedProxyContext = {
235
253
  enabled: true,
236
254
  platformBaseUrl: "https://platform.example.com",
@@ -250,7 +268,7 @@ describe("image-studio skill script wrapper", () => {
250
268
 
251
269
  expect(result.isError).toBe(false);
252
270
  expect(result.content).toContain("Generated 1 image");
253
- expect(result.content).toContain("gemini-2.5-flash-image");
271
+ expect(result.content).toContain("gemini-3.1-flash-image-preview");
254
272
  expect(result.content).toContain("A beautiful image");
255
273
  expect(result.contentBlocks).toHaveLength(1);
256
274
  expect(result.contentBlocks![0]).toEqual({
@@ -270,7 +288,7 @@ describe("image-studio skill script wrapper", () => {
270
288
  { mimeType: "image/png", dataBase64: "img2" },
271
289
  ],
272
290
  text: undefined as unknown as string,
273
- resolvedModel: "gemini-2.5-flash-image",
291
+ resolvedModel: "gemini-3.1-flash-image-preview",
274
292
  };
275
293
 
276
294
  const result = await run({ prompt: "test", variants: 2 }, fakeContext);
@@ -357,8 +375,7 @@ describe("image-studio TOOLS.json manifest", () => {
357
375
  expect(props.mode.enum).toEqual(["generate", "edit"]);
358
376
  expect(props.attachment_ids.type).toBe("array");
359
377
  expect(props.model.enum).toEqual([
360
- "gemini-2.5-flash-image",
361
- "gemini-3-pro-image",
378
+ "gemini-3.1-flash-image-preview",
362
379
  "gemini-3-pro-image-preview",
363
380
  ]);
364
381
  expect(props.variants.type).toBe("number");
@@ -53,7 +53,7 @@ mock.module("../config/loader.js", () => ({
53
53
  model: "test",
54
54
  provider: "test",
55
55
  memory: { enabled: false },
56
- rateLimit: { maxRequestsPerMinute: 0, maxTokensPerSession: 0 },
56
+ rateLimit: { maxRequestsPerMinute: 0 },
57
57
  timeouts: { shellDefaultTimeoutSec: 30, shellMaxTimeoutSec: 60 },
58
58
  sandbox: { enabled: false, backend: "native" },
59
59
  }),
@@ -248,7 +248,7 @@ describe("Memory context benchmark", () => {
248
248
  ...DEFAULT_CONFIG.memory,
249
249
  embeddings: {
250
250
  ...DEFAULT_CONFIG.memory.embeddings,
251
- provider: "openai" as const,
251
+ provider: "local" as const,
252
252
  required: false,
253
253
  },
254
254
  retrieval: {
@@ -82,6 +82,7 @@ mock.module("../config/loader.js", () => ({
82
82
  invalidateConfigCache: () => {},
83
83
  }));
84
84
 
85
+ import { stripUserTextBlocksByPrefix } from "../daemon/conversation-runtime-assembly.js";
85
86
  import { getDb, initializeDb, resetDb } from "../memory/db.js";
86
87
  import {
87
88
  resetCleanupScheduleThrottle,
@@ -89,8 +90,7 @@ import {
89
90
  } from "../memory/jobs-worker.js";
90
91
  import {
91
92
  buildMemoryRecall,
92
- injectMemoryRecallAsSeparateMessage,
93
- stripMemoryRecallMessages,
93
+ injectMemoryRecallAsUserBlock,
94
94
  } from "../memory/retriever.js";
95
95
  import {
96
96
  conversations,
@@ -98,6 +98,7 @@ import {
98
98
  memoryItemSources,
99
99
  messages,
100
100
  } from "../memory/schema.js";
101
+ import type { Message } from "../providers/types.js";
101
102
 
102
103
  describe("Memory lifecycle E2E regression", () => {
103
104
  beforeAll(() => {
@@ -322,7 +323,7 @@ describe("Memory lifecycle E2E regression", () => {
322
323
  totalOutputTokens: 0,
323
324
  totalEstimatedCost: 0,
324
325
  contextSummary: null,
325
- contextCompactedMessageCount: 0,
326
+ contextCompactedMessageCount: 1,
326
327
  contextCompactedAt: null,
327
328
  })
328
329
  .run();
@@ -365,34 +366,39 @@ describe("Memory lifecycle E2E regression", () => {
365
366
  expect(recall.enabled).toBe(true);
366
367
  expect(recall.injectedText.length).toBeGreaterThan(0);
367
368
  expect(recall.injectedTokens).toBeGreaterThan(0);
368
- expect(recall.injectedText).toContain("<memory_context>");
369
+ expect(recall.injectedText).toContain("<memory_context __injected>");
369
370
  expect(recall.injectedText).toContain("</memory_context>");
370
371
  });
371
372
 
372
- test("stripping removes <memory_context> tags from injected recall", () => {
373
+ test("stripping removes <memory_context> block from injected recall", () => {
373
374
  const memoryRecallText =
374
- "<memory_context>\n\n<relevant_context>\nuser prefers concise answers\n</relevant_context>\n\n</memory_context>";
375
- const originalMessages = [
375
+ "<memory_context __injected>\n\n<relevant_context>\nuser prefers concise answers\n</relevant_context>\n\n</memory_context>";
376
+ const originalMessages: Message[] = [
376
377
  {
377
- role: "user" as const,
378
- content: [{ type: "text", text: "Actual user request" }],
378
+ role: "user",
379
+ content: [{ type: "text" as const, text: "Actual user request" }],
379
380
  },
380
381
  ];
381
- const injected = injectMemoryRecallAsSeparateMessage(
382
+ const injected = injectMemoryRecallAsUserBlock(
382
383
  originalMessages,
383
384
  memoryRecallText,
384
385
  );
385
386
 
386
- expect(injected).toHaveLength(3);
387
+ // Memory context prepended to the last user message as a content block
388
+ expect(injected).toHaveLength(1);
387
389
  expect(injected[0].role).toBe("user");
388
- expect(injected[0].content[0].text).toBe(memoryRecallText);
389
- expect(injected[1].role as string).toBe("assistant");
390
- expect(injected[2].role).toBe("user");
391
- expect(injected[2].content[0].text).toBe("Actual user request");
392
-
393
- const cleaned = stripMemoryRecallMessages(injected, memoryRecallText);
390
+ expect(injected[0].content).toHaveLength(2);
391
+ const b0 = injected[0].content[0];
392
+ const b1 = injected[0].content[1];
393
+ expect(b0.type === "text" && b0.text).toBe(memoryRecallText);
394
+ expect(b1.type === "text" && b1.text).toBe("Actual user request");
395
+
396
+ // Stripped by prefix-based stripping (same mechanism as workspace/temporal)
397
+ const cleaned = stripUserTextBlocksByPrefix(injected, ["<memory_context __injected>"]);
394
398
  expect(cleaned).toHaveLength(1);
395
- expect(cleaned[0].content[0].text).toBe("Actual user request");
399
+ expect(cleaned[0].content).toHaveLength(1);
400
+ const cb0 = cleaned[0].content[0];
401
+ expect(cb0.type === "text" && cb0.text).toBe("Actual user request");
396
402
  });
397
403
 
398
404
  test("empty retrieval returns no injection", async () => {
@@ -112,6 +112,7 @@ function insertConversation(
112
112
  db: ReturnType<typeof getDb>,
113
113
  id: string,
114
114
  createdAt: number,
115
+ contextCompactedMessageCount = 0,
115
116
  ) {
116
117
  db.insert(conversations)
117
118
  .values({
@@ -123,7 +124,7 @@ function insertConversation(
123
124
  totalOutputTokens: 0,
124
125
  totalEstimatedCost: 0,
125
126
  contextSummary: null,
126
- contextCompactedMessageCount: 0,
127
+ contextCompactedMessageCount,
127
128
  contextCompactedAt: null,
128
129
  })
129
130
  .run();
@@ -629,7 +630,7 @@ describe("Memory Recall Quality", () => {
629
630
  test("invalidated items are excluded from recall", async () => {
630
631
  const db = getDb();
631
632
  const now = 1_700_000_275_000;
632
- insertConversation(db, "conv-invalid-status", now);
633
+ insertConversation(db, "conv-invalid-status", now, 1);
633
634
  insertMessage(
634
635
  db,
635
636
  "msg-invalid-status",
@@ -989,7 +990,7 @@ describe("Memory Recall Quality", () => {
989
990
  test("precision@k guard verifies pipeline completes with seeded segments", async () => {
990
991
  const db = getDb();
991
992
  const now = 1_700_000_700_000;
992
- insertConversation(db, "conv-pk", now);
993
+ insertConversation(db, "conv-pk", now, 3);
993
994
 
994
995
  const prefs = [
995
996
  {