@vellumai/assistant 0.5.6 → 0.5.8

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 (442) hide show
  1. package/.env.example +16 -2
  2. package/ARCHITECTURE.md +6 -75
  3. package/Dockerfile +3 -2
  4. package/README.md +0 -2
  5. package/bun.lock +0 -414
  6. package/docker-entrypoint.sh +9 -0
  7. package/docs/architecture/keychain-broker.md +45 -240
  8. package/docs/architecture/memory.md +13 -11
  9. package/docs/architecture/security.md +0 -17
  10. package/docs/credential-execution-service.md +2 -2
  11. package/node_modules/@vellumai/ces-contracts/package.json +1 -0
  12. package/node_modules/@vellumai/ces-contracts/src/error.ts +1 -1
  13. package/node_modules/@vellumai/ces-contracts/src/grants.ts +1 -1
  14. package/node_modules/@vellumai/ces-contracts/src/handles.ts +1 -1
  15. package/node_modules/@vellumai/ces-contracts/src/index.ts +1 -1
  16. package/node_modules/@vellumai/ces-contracts/src/rpc.ts +120 -1
  17. package/node_modules/@vellumai/credential-storage/package.json +1 -0
  18. package/node_modules/@vellumai/egress-proxy/package.json +1 -0
  19. package/package.json +2 -3
  20. package/src/__tests__/actor-token-service.test.ts +0 -114
  21. package/src/__tests__/approval-cascade.test.ts +0 -1
  22. package/src/__tests__/assistant-feature-flags-integration.test.ts +30 -29
  23. package/src/__tests__/browser-fill-credential.test.ts +1 -1
  24. package/src/__tests__/browser-skill-endstate.test.ts +6 -5
  25. package/src/__tests__/btw-routes.test.ts +0 -39
  26. package/src/__tests__/call-controller.test.ts +0 -1
  27. package/src/__tests__/call-domain.test.ts +0 -128
  28. package/src/__tests__/ces-rpc-credential-backend.test.ts +199 -0
  29. package/src/__tests__/ces-startup-timeout.test.ts +40 -0
  30. package/src/__tests__/channel-approval-routes.test.ts +0 -5
  31. package/src/__tests__/channel-readiness-service.test.ts +1 -60
  32. package/src/__tests__/checker.test.ts +4 -2
  33. package/src/__tests__/cli-command-risk-guard.test.ts +112 -0
  34. package/src/__tests__/config-schema-cmd.test.ts +0 -2
  35. package/src/__tests__/config-schema.test.ts +3 -1
  36. package/src/__tests__/conversation-abort-tool-results.test.ts +0 -1
  37. package/src/__tests__/conversation-agent-loop-overflow.test.ts +0 -2
  38. package/src/__tests__/conversation-agent-loop.test.ts +2 -4
  39. package/src/__tests__/conversation-attention-telegram.test.ts +0 -5
  40. package/src/__tests__/conversation-confirmation-signals.test.ts +0 -1
  41. package/src/__tests__/conversation-error.test.ts +15 -1
  42. package/src/__tests__/conversation-init.benchmark.test.ts +0 -2
  43. package/src/__tests__/conversation-messaging-secret-redirect.test.ts +1 -1
  44. package/src/__tests__/conversation-pre-run-repair.test.ts +0 -1
  45. package/src/__tests__/conversation-provider-retry-repair.test.ts +0 -1
  46. package/src/__tests__/conversation-queue.test.ts +0 -1
  47. package/src/__tests__/conversation-skill-tools.test.ts +0 -54
  48. package/src/__tests__/conversation-slash-queue.test.ts +0 -1
  49. package/src/__tests__/conversation-slash-unknown.test.ts +0 -1
  50. package/src/__tests__/conversation-title-service.test.ts +87 -0
  51. package/src/__tests__/conversation-workspace-injection.test.ts +0 -1
  52. package/src/__tests__/conversation-workspace-tool-tracking.test.ts +0 -1
  53. package/src/__tests__/credential-execution-client.test.ts +5 -2
  54. package/src/__tests__/credential-execution-feature-gates.test.ts +59 -30
  55. package/src/__tests__/credential-execution-managed-contract.test.ts +35 -20
  56. package/src/__tests__/credential-security-e2e.test.ts +1 -67
  57. package/src/__tests__/credential-security-invariants.test.ts +6 -50
  58. package/src/__tests__/credentials-cli.test.ts +82 -3
  59. package/src/__tests__/daemon-credential-client.test.ts +123 -0
  60. package/src/__tests__/db-migration-rollback.test.ts +2015 -1
  61. package/src/__tests__/deterministic-verification-control-plane.test.ts +1 -0
  62. package/src/__tests__/docker-signing-key-bootstrap.test.ts +34 -143
  63. package/src/__tests__/dynamic-skill-workflow-prompt.test.ts +6 -4
  64. package/src/__tests__/gateway-client-managed-outbound.test.ts +79 -1
  65. package/src/__tests__/guardian-routing-state.test.ts +0 -5
  66. package/src/__tests__/host-shell-tool.test.ts +6 -7
  67. package/src/__tests__/http-user-message-parity.test.ts +3 -103
  68. package/src/__tests__/inbound-invite-redemption.test.ts +0 -4
  69. package/src/__tests__/inline-skill-load-permissions.test.ts +6 -8
  70. package/src/__tests__/intent-routing.test.ts +0 -13
  71. package/src/__tests__/jobs-store-qdrant-breaker.test.ts +178 -0
  72. package/src/__tests__/journal-context.test.ts +335 -0
  73. package/src/__tests__/keychain-broker-client.test.ts +161 -22
  74. package/src/__tests__/memory-context-benchmark.benchmark.test.ts +0 -3
  75. package/src/__tests__/memory-jobs-worker-backoff.test.ts +150 -0
  76. package/src/__tests__/memory-lifecycle-e2e.test.ts +70 -25
  77. package/src/__tests__/memory-recall-quality.test.ts +48 -17
  78. package/src/__tests__/memory-regressions.test.ts +408 -363
  79. package/src/__tests__/memory-retrieval.benchmark.test.ts +0 -3
  80. package/src/__tests__/migration-export-http.test.ts +2 -2
  81. package/src/__tests__/migration-import-commit-http.test.ts +2 -2
  82. package/src/__tests__/migration-import-preflight-http.test.ts +2 -2
  83. package/src/__tests__/migration-validate-http.test.ts +2 -2
  84. package/src/__tests__/non-member-access-request.test.ts +2 -7
  85. package/src/__tests__/notification-decision-fallback.test.ts +4 -0
  86. package/src/__tests__/notification-decision-identity.test.ts +4 -0
  87. package/src/__tests__/notification-decision-strategy.test.ts +71 -0
  88. package/src/__tests__/oauth-cli.test.ts +5 -1
  89. package/src/__tests__/permission-types.test.ts +1 -0
  90. package/src/__tests__/provider-commit-message-generator.test.ts +0 -37
  91. package/src/__tests__/provider-error-scenarios.test.ts +0 -267
  92. package/src/__tests__/provider-managed-proxy-integration.test.ts +5 -6
  93. package/src/__tests__/provider-streaming.benchmark.test.ts +2 -81
  94. package/src/__tests__/qdrant-manager.test.ts +28 -2
  95. package/src/__tests__/registry.test.ts +0 -6
  96. package/src/__tests__/relay-server.test.ts +1 -2
  97. package/src/__tests__/runtime-attachment-metadata.test.ts +0 -4
  98. package/src/__tests__/script-proxy-injection-runtime.test.ts +1 -1
  99. package/src/__tests__/secret-onetime-send.test.ts +1 -1
  100. package/src/__tests__/secret-routes-managed-proxy.test.ts +0 -4
  101. package/src/__tests__/secure-keys.test.ts +95 -272
  102. package/src/__tests__/shell-identity.test.ts +96 -6
  103. package/src/__tests__/skill-feature-flags-integration.test.ts +22 -14
  104. package/src/__tests__/skill-feature-flags.test.ts +46 -45
  105. package/src/__tests__/skill-load-feature-flag.test.ts +7 -10
  106. package/src/__tests__/skill-load-inline-command.test.ts +8 -12
  107. package/src/__tests__/skill-load-inline-includes.test.ts +6 -10
  108. package/src/__tests__/skill-load-tool.test.ts +0 -2
  109. package/src/__tests__/skill-memory.test.ts +17 -3
  110. package/src/__tests__/skill-projection-feature-flag.test.ts +33 -29
  111. package/src/__tests__/skills.test.ts +0 -2
  112. package/src/__tests__/slack-inbound-verification.test.ts +0 -4
  113. package/src/__tests__/stale-approval-dedup.test.ts +171 -0
  114. package/src/__tests__/stt-hints.test.ts +437 -0
  115. package/src/__tests__/suggestion-routes.test.ts +1 -32
  116. package/src/__tests__/system-prompt.test.ts +0 -1
  117. package/src/__tests__/task-memory-cleanup.test.ts +14 -0
  118. package/src/__tests__/tool-executor-shell-integration.test.ts +5 -3
  119. package/src/__tests__/trusted-contact-lifecycle-notifications.test.ts +0 -5
  120. package/src/__tests__/trusted-contact-multichannel.test.ts +0 -4
  121. package/src/__tests__/twilio-routes-twiml.test.ts +139 -1
  122. package/src/__tests__/update-bulletin.test.ts +0 -2
  123. package/src/__tests__/vellum-self-knowledge-inline-command.test.ts +6 -9
  124. package/src/__tests__/voice-quality.test.ts +58 -0
  125. package/src/__tests__/voice-scoped-grant-consumer.test.ts +0 -7
  126. package/src/__tests__/workspace-migration-015-migrate-credentials-to-keychain.test.ts +252 -0
  127. package/src/__tests__/workspace-migration-016-migrate-credentials-from-keychain.test.ts +220 -0
  128. package/src/__tests__/workspace-migration-down-functions.test.ts +1009 -0
  129. package/src/__tests__/workspace-migrations-runner.test.ts +114 -0
  130. package/src/acp/agent-process.ts +9 -1
  131. package/src/agent/loop.ts +1 -1
  132. package/src/approvals/guardian-request-resolvers.ts +164 -38
  133. package/src/calls/__tests__/tts-text-sanitizer.test.ts +254 -0
  134. package/src/calls/audio-store.test.ts +97 -0
  135. package/src/calls/audio-store.ts +205 -0
  136. package/src/calls/call-controller.ts +90 -8
  137. package/src/calls/call-domain.ts +3 -0
  138. package/src/calls/call-store.ts +10 -3
  139. package/src/calls/fish-audio-client.ts +129 -0
  140. package/src/calls/relay-server.ts +27 -0
  141. package/src/calls/stt-hints.ts +189 -0
  142. package/src/calls/tts-text-sanitizer.ts +61 -0
  143. package/src/calls/twilio-routes.ts +34 -5
  144. package/src/calls/types.ts +1 -0
  145. package/src/calls/voice-ingress-preflight.ts +0 -42
  146. package/src/calls/voice-quality.ts +38 -5
  147. package/src/calls/voice-session-bridge.ts +7 -12
  148. package/src/cli/commands/avatar.ts +2 -2
  149. package/src/cli/commands/config.ts +1 -4
  150. package/src/cli/commands/credentials.ts +128 -82
  151. package/src/cli/commands/doctor.ts +2 -2
  152. package/src/cli/commands/keys.ts +7 -7
  153. package/src/cli/commands/memory.ts +1 -1
  154. package/src/cli/commands/oauth/connections.ts +11 -29
  155. package/src/cli/commands/oauth/index.ts +7 -0
  156. package/src/cli/commands/oauth/platform.ts +525 -0
  157. package/src/cli/commands/platform.ts +3 -3
  158. package/src/cli/lib/daemon-credential-client.ts +284 -0
  159. package/src/cli.ts +1 -1
  160. package/src/config/assistant-feature-flags.ts +186 -5
  161. package/src/config/bundled-skills/AGENTS.md +34 -0
  162. package/src/config/bundled-skills/acp/SKILL.md +10 -0
  163. package/src/config/bundled-skills/app-builder/SKILL.md +0 -4
  164. package/src/config/bundled-skills/messaging/SKILL.md +5 -5
  165. package/src/config/bundled-skills/messaging/tools/messaging-analyze-style.ts +2 -2
  166. package/src/config/bundled-skills/phone-calls/TOOLS.json +4 -0
  167. package/src/config/bundled-skills/playbooks/tools/playbook-create.ts +1 -0
  168. package/src/config/bundled-skills/playbooks/tools/playbook-update.ts +1 -0
  169. package/src/config/bundled-skills/settings/SKILL.md +15 -2
  170. package/src/config/bundled-skills/settings/TOOLS.json +47 -2
  171. package/src/config/bundled-skills/settings/tools/avatar-remove.ts +59 -0
  172. package/src/config/bundled-skills/settings/tools/avatar-update.ts +80 -0
  173. package/src/config/bundled-skills/settings/tools/voice-config-update.ts +42 -0
  174. package/src/config/bundled-skills/slack/SKILL.md +1 -1
  175. package/src/config/bundled-tool-registry.ts +5 -11
  176. package/src/config/defaults.ts +0 -2
  177. package/src/config/env-registry.ts +5 -5
  178. package/src/config/env.ts +21 -14
  179. package/src/config/feature-flag-registry.json +49 -9
  180. package/src/config/loader.ts +106 -42
  181. package/src/config/schema.ts +9 -29
  182. package/src/config/schemas/calls.ts +30 -0
  183. package/src/config/schemas/fish-audio.ts +39 -0
  184. package/src/config/schemas/inference.ts +2 -2
  185. package/src/config/schemas/journal.ts +16 -0
  186. package/src/config/schemas/memory-processing.ts +2 -2
  187. package/src/config/schemas/security.ts +0 -4
  188. package/src/config/types.ts +1 -1
  189. package/src/contacts/contact-store.ts +39 -0
  190. package/src/contacts/types.ts +2 -0
  191. package/src/credential-execution/approval-bridge.ts +1 -0
  192. package/src/credential-execution/executable-discovery.ts +28 -4
  193. package/src/credential-execution/feature-gates.ts +16 -0
  194. package/src/credential-execution/process-manager.ts +38 -0
  195. package/src/credential-execution/startup-timeout.ts +36 -0
  196. package/src/daemon/approval-generators.ts +3 -9
  197. package/src/daemon/assistant-attachments.ts +9 -0
  198. package/src/daemon/config-watcher.ts +5 -0
  199. package/src/daemon/conversation-error.ts +13 -1
  200. package/src/daemon/conversation-memory.ts +1 -2
  201. package/src/daemon/conversation-process.ts +18 -1
  202. package/src/daemon/conversation-surfaces.ts +30 -1
  203. package/src/daemon/conversation-tool-setup.ts +0 -105
  204. package/src/daemon/conversation.ts +21 -1
  205. package/src/daemon/guardian-action-generators.ts +3 -9
  206. package/src/daemon/handlers/config-vercel.ts +92 -0
  207. package/src/daemon/handlers/skills.ts +2 -15
  208. package/src/daemon/install-symlink.ts +195 -0
  209. package/src/daemon/lifecycle.ts +234 -51
  210. package/src/daemon/message-types/conversations.ts +4 -4
  211. package/src/daemon/message-types/diagnostics.ts +3 -22
  212. package/src/daemon/message-types/messages.ts +0 -2
  213. package/src/daemon/message-types/upgrades.ts +8 -0
  214. package/src/daemon/server.ts +32 -95
  215. package/src/events/domain-events.ts +2 -1
  216. package/src/inbound/platform-callback-registration.ts +3 -3
  217. package/src/instrument.ts +8 -5
  218. package/src/memory/app-store.ts +31 -0
  219. package/src/memory/conversation-title-service.ts +50 -1
  220. package/src/memory/db-init.ts +16 -0
  221. package/src/memory/indexer.ts +19 -10
  222. package/src/memory/items-extractor.ts +328 -321
  223. package/src/memory/job-handlers/conversation-starters.ts +4 -1
  224. package/src/memory/job-handlers/summarization.ts +26 -16
  225. package/src/memory/jobs-store.ts +63 -6
  226. package/src/memory/jobs-worker.ts +31 -7
  227. package/src/memory/journal-memory.ts +214 -0
  228. package/src/memory/migrations/001-job-deferrals.ts +19 -0
  229. package/src/memory/migrations/004-entity-relation-dedup.ts +10 -0
  230. package/src/memory/migrations/005-fingerprint-scope-unique.ts +76 -0
  231. package/src/memory/migrations/006-scope-salted-fingerprints.ts +50 -0
  232. package/src/memory/migrations/007-assistant-id-to-self.ts +10 -0
  233. package/src/memory/migrations/008-remove-assistant-id-columns.ts +34 -0
  234. package/src/memory/migrations/009-llm-usage-events-drop-assistant-id.ts +26 -0
  235. package/src/memory/migrations/014-backfill-inbox-thread-state.ts +10 -0
  236. package/src/memory/migrations/015-drop-active-search-index.ts +17 -0
  237. package/src/memory/migrations/019-notification-tables-schema-migration.ts +12 -0
  238. package/src/memory/migrations/020-rename-macos-ios-channel-to-vellum.ts +121 -0
  239. package/src/memory/migrations/024-embedding-vector-blob.ts +74 -0
  240. package/src/memory/migrations/026a-embeddings-nullable-vector-json.ts +82 -0
  241. package/src/memory/migrations/036-normalize-phone-identities.ts +11 -0
  242. package/src/memory/migrations/116-messages-fts.ts +106 -1
  243. package/src/memory/migrations/126-backfill-guardian-principal-id.ts +52 -0
  244. package/src/memory/migrations/127-guardian-principal-id-not-null.ts +77 -0
  245. package/src/memory/migrations/134-contacts-notes-column.ts +13 -0
  246. package/src/memory/migrations/135-backfill-contact-interaction-stats.ts +20 -0
  247. package/src/memory/migrations/136-drop-assistant-id-columns.ts +52 -0
  248. package/src/memory/migrations/140-backfill-usage-cache-accounting.ts +13 -0
  249. package/src/memory/migrations/141-rename-verification-table.ts +54 -0
  250. package/src/memory/migrations/142-rename-verification-session-id-column.ts +25 -0
  251. package/src/memory/migrations/143-rename-guardian-verification-values.ts +35 -0
  252. package/src/memory/migrations/144-rename-voice-to-phone.ts +136 -0
  253. package/src/memory/migrations/145-drop-accounts-table.ts +32 -0
  254. package/src/memory/migrations/147-migrate-reminders-to-schedules.ts +14 -1
  255. package/src/memory/migrations/148-drop-reminders-table.ts +35 -1
  256. package/src/memory/migrations/150-oauth-apps-client-secret-path.ts +69 -1
  257. package/src/memory/migrations/162-guardian-timestamps-epoch-ms.ts +290 -0
  258. package/src/memory/migrations/169-rename-gmail-provider-key-to-google.ts +51 -1
  259. package/src/memory/migrations/174-rename-thread-starters-table.ts +47 -1
  260. package/src/memory/migrations/176-drop-capability-card-state.ts +13 -0
  261. package/src/memory/migrations/180-backfill-inline-attachments-to-disk.ts +16 -0
  262. package/src/memory/migrations/181-rename-thread-starters-checkpoints.ts +28 -1
  263. package/src/memory/migrations/190-call-session-skip-disclosure.ts +15 -0
  264. package/src/memory/migrations/191-backfill-audio-attachment-mime-types.ts +64 -0
  265. package/src/memory/migrations/192-contacts-user-file-column.ts +15 -0
  266. package/src/memory/migrations/193-add-source-type-columns.ts +81 -0
  267. package/src/memory/migrations/index.ts +5 -0
  268. package/src/memory/migrations/registry.ts +98 -0
  269. package/src/memory/migrations/validate-migration-state.ts +137 -11
  270. package/src/memory/qdrant-circuit-breaker.ts +9 -0
  271. package/src/memory/qdrant-manager.ts +64 -7
  272. package/src/memory/retriever.test.ts +37 -25
  273. package/src/memory/retriever.ts +24 -49
  274. package/src/memory/schema/calls.ts +1 -0
  275. package/src/memory/schema/contacts.ts +1 -0
  276. package/src/memory/schema/memory-core.ts +2 -0
  277. package/src/memory/search/formatting.ts +7 -44
  278. package/src/memory/search/staleness.ts +4 -0
  279. package/src/memory/search/tier-classifier.ts +10 -2
  280. package/src/memory/search/types.ts +2 -5
  281. package/src/memory/task-memory-cleanup.ts +4 -3
  282. package/src/notifications/adapters/slack.ts +168 -6
  283. package/src/notifications/broadcaster.ts +1 -0
  284. package/src/notifications/copy-composer.ts +59 -2
  285. package/src/notifications/decision-engine.ts +4 -1
  286. package/src/notifications/signal.ts +2 -0
  287. package/src/notifications/types.ts +2 -0
  288. package/src/oauth/connection-resolver.ts +6 -4
  289. package/src/permissions/checker.ts +0 -38
  290. package/src/permissions/shell-identity.ts +76 -22
  291. package/src/permissions/types.ts +4 -2
  292. package/src/platform/client.ts +35 -7
  293. package/src/prompts/journal-context.ts +133 -0
  294. package/src/prompts/persona-resolver.ts +194 -0
  295. package/src/prompts/system-prompt.ts +44 -4
  296. package/src/prompts/templates/SOUL.md +10 -0
  297. package/src/prompts/templates/users/default.md +1 -0
  298. package/src/providers/provider-send-message.ts +3 -32
  299. package/src/providers/registry.ts +29 -179
  300. package/src/providers/types.ts +1 -1
  301. package/src/runtime/access-request-helper.ts +4 -0
  302. package/src/runtime/auth/__tests__/credential-service.test.ts +0 -1
  303. package/src/runtime/auth/__tests__/external-assistant-id.test.ts +13 -68
  304. package/src/runtime/auth/__tests__/guard-tests.test.ts +9 -50
  305. package/src/runtime/auth/external-assistant-id.ts +13 -59
  306. package/src/runtime/auth/route-policy.ts +17 -1
  307. package/src/runtime/auth/token-service.ts +43 -138
  308. package/src/runtime/channel-readiness-service.ts +1 -16
  309. package/src/runtime/gateway-client.ts +47 -4
  310. package/src/runtime/guardian-decision-types.ts +45 -4
  311. package/src/runtime/http-server.ts +31 -3
  312. package/src/runtime/middleware/error-handler.ts +1 -9
  313. package/src/runtime/routes/access-request-decision.ts +2 -2
  314. package/src/runtime/routes/app-management-routes.ts +2 -1
  315. package/src/runtime/routes/approval-strategies/guardian-callback-strategy.ts +219 -30
  316. package/src/runtime/routes/approval-strategies/guardian-text-engine-strategy.ts +37 -14
  317. package/src/runtime/routes/audio-routes.ts +40 -0
  318. package/src/runtime/routes/btw-routes.ts +0 -17
  319. package/src/runtime/routes/channel-readiness-routes.ts +9 -4
  320. package/src/runtime/routes/conversation-query-routes.ts +63 -1
  321. package/src/runtime/routes/conversation-routes.ts +4 -44
  322. package/src/runtime/routes/debug-routes.ts +12 -9
  323. package/src/runtime/routes/diagnostics-routes.ts +1 -477
  324. package/src/runtime/routes/guardian-approval-interception.ts +168 -11
  325. package/src/runtime/routes/guardian-approval-prompt.ts +6 -1
  326. package/src/runtime/routes/guardian-approval-reply-helpers.ts +103 -21
  327. package/src/runtime/routes/identity-routes.ts +19 -30
  328. package/src/runtime/routes/inbound-message-handler.ts +31 -1
  329. package/src/runtime/routes/inbound-stages/acl-enforcement.ts +64 -5
  330. package/src/runtime/routes/inbound-stages/background-dispatch.ts +52 -40
  331. package/src/runtime/routes/inbound-stages/secret-ingress-check.ts +4 -33
  332. package/src/runtime/routes/inbound-stages/transcribe-audio.test.ts +1 -1
  333. package/src/runtime/routes/integrations/twilio.ts +52 -10
  334. package/src/runtime/routes/integrations/vercel.ts +89 -0
  335. package/src/runtime/routes/log-export-routes.ts +5 -0
  336. package/src/runtime/routes/memory-item-routes.test.ts +3 -3
  337. package/src/runtime/routes/memory-item-routes.ts +46 -14
  338. package/src/runtime/routes/migration-rollback-routes.ts +209 -0
  339. package/src/runtime/routes/migration-routes.ts +17 -1
  340. package/src/runtime/routes/notification-routes.ts +58 -0
  341. package/src/runtime/routes/schedule-routes.ts +65 -0
  342. package/src/runtime/routes/secret-routes.ts +141 -10
  343. package/src/runtime/routes/settings-routes.ts +41 -1
  344. package/src/runtime/routes/tts-routes.ts +96 -0
  345. package/src/runtime/routes/upgrade-broadcast-routes.ts +26 -2
  346. package/src/runtime/routes/workspace-commit-routes.ts +62 -0
  347. package/src/runtime/routes/workspace-routes.test.ts +22 -1
  348. package/src/runtime/routes/workspace-routes.ts +1 -1
  349. package/src/runtime/routes/workspace-utils.ts +86 -2
  350. package/src/security/ces-credential-client.ts +75 -29
  351. package/src/security/ces-rpc-credential-backend.ts +86 -0
  352. package/src/security/credential-backend.ts +22 -92
  353. package/src/security/keychain-broker-client.ts +10 -2
  354. package/src/security/secure-keys.ts +113 -115
  355. package/src/skills/catalog-install.ts +6 -32
  356. package/src/skills/skill-memory.ts +1 -0
  357. package/src/subagent/manager.ts +2 -5
  358. package/src/telemetry/usage-telemetry-reporter.ts +4 -2
  359. package/src/tools/acp/spawn.ts +78 -1
  360. package/src/tools/calls/call-start.ts +1 -0
  361. package/src/tools/credentials/vault.ts +5 -3
  362. package/src/tools/executor.ts +0 -4
  363. package/src/tools/memory/definitions.ts +3 -2
  364. package/src/tools/memory/handlers.ts +10 -7
  365. package/src/tools/network/script-proxy/session-manager.ts +19 -4
  366. package/src/tools/network/web-fetch.ts +3 -1
  367. package/src/tools/skills/execute.ts +1 -1
  368. package/src/tools/terminal/safe-env.ts +1 -0
  369. package/src/tools/types.ts +0 -8
  370. package/src/util/browser.ts +15 -0
  371. package/src/util/errors.ts +0 -12
  372. package/src/util/platform.ts +4 -51
  373. package/src/workspace/git-service.ts +5 -2
  374. package/src/workspace/migrations/001-avatar-rename.ts +15 -0
  375. package/src/workspace/migrations/003-seed-device-id.ts +17 -1
  376. package/src/workspace/migrations/004-extract-collect-usage-data.ts +33 -0
  377. package/src/workspace/migrations/005-add-send-diagnostics.ts +3 -0
  378. package/src/workspace/migrations/006-services-config.ts +49 -0
  379. package/src/workspace/migrations/007-web-search-provider-rename.ts +27 -0
  380. package/src/workspace/migrations/008-voice-timeout-and-max-steps.ts +3 -0
  381. package/src/workspace/migrations/009-backfill-conversation-disk-view.ts +4 -0
  382. package/src/workspace/migrations/010-app-dir-rename.ts +78 -0
  383. package/src/workspace/migrations/011-backfill-installation-id.ts +11 -0
  384. package/src/workspace/migrations/012-rename-conversation-disk-view-dirs.ts +44 -0
  385. package/src/workspace/migrations/013-repair-conversation-disk-view.ts +5 -0
  386. package/src/workspace/migrations/015-migrate-credentials-to-keychain.ts +153 -0
  387. package/src/workspace/migrations/016-extract-feature-flags-to-protected.ts +156 -0
  388. package/src/workspace/migrations/016-migrate-credentials-from-keychain.ts +150 -0
  389. package/src/workspace/migrations/017-seed-persona-dirs.ts +96 -0
  390. package/src/workspace/migrations/018-rekey-compound-credential-keys.ts +184 -0
  391. package/src/workspace/migrations/019-scope-journal-to-guardian.ts +103 -0
  392. package/src/workspace/migrations/migrate-to-workspace-volume.ts +27 -5
  393. package/src/workspace/migrations/registry.ts +12 -0
  394. package/src/workspace/migrations/runner.ts +106 -2
  395. package/src/workspace/migrations/types.ts +4 -0
  396. package/src/workspace/provider-commit-message-generator.ts +12 -21
  397. package/src/__tests__/claude-code-skill-regression.test.ts +0 -206
  398. package/src/__tests__/claude-code-tool-profiles.test.ts +0 -99
  399. package/src/__tests__/diagnostics-export.test.ts +0 -288
  400. package/src/__tests__/local-gateway-health.test.ts +0 -209
  401. package/src/__tests__/provider-fail-open-selection.test.ts +0 -271
  402. package/src/__tests__/provider-failover-actual-provider.test.ts +0 -66
  403. package/src/__tests__/secret-ingress-handler.test.ts +0 -120
  404. package/src/__tests__/swarm-conversation-integration.test.ts +0 -358
  405. package/src/__tests__/swarm-dag-pathological.test.ts +0 -547
  406. package/src/__tests__/swarm-orchestrator.test.ts +0 -463
  407. package/src/__tests__/swarm-plan-validator.test.ts +0 -384
  408. package/src/__tests__/swarm-recursion.test.ts +0 -197
  409. package/src/__tests__/swarm-router-planner.test.ts +0 -234
  410. package/src/__tests__/swarm-tool.test.ts +0 -185
  411. package/src/__tests__/swarm-worker-backend.test.ts +0 -144
  412. package/src/__tests__/swarm-worker-runner.test.ts +0 -288
  413. package/src/commands/__tests__/cc-command-registry.test.ts +0 -396
  414. package/src/commands/cc-command-registry.ts +0 -248
  415. package/src/config/bundled-skills/claude-code/SKILL.md +0 -53
  416. package/src/config/bundled-skills/claude-code/TOOLS.json +0 -47
  417. package/src/config/bundled-skills/claude-code/tools/claude-code.ts +0 -12
  418. package/src/config/bundled-skills/orchestration/SKILL.md +0 -33
  419. package/src/config/bundled-skills/orchestration/TOOLS.json +0 -35
  420. package/src/config/bundled-skills/orchestration/tools/swarm-delegate.ts +0 -12
  421. package/src/config/schemas/swarm.ts +0 -82
  422. package/src/logfire.ts +0 -135
  423. package/src/memory/search/lexical.ts +0 -48
  424. package/src/providers/failover.ts +0 -186
  425. package/src/runtime/local-gateway-health.ts +0 -275
  426. package/src/security/secret-ingress.ts +0 -68
  427. package/src/swarm/backend-claude-code.ts +0 -225
  428. package/src/swarm/checkpoint.ts +0 -137
  429. package/src/swarm/graph-utils.ts +0 -53
  430. package/src/swarm/index.ts +0 -55
  431. package/src/swarm/limits.ts +0 -66
  432. package/src/swarm/orchestrator.ts +0 -424
  433. package/src/swarm/plan-validator.ts +0 -117
  434. package/src/swarm/router-planner.ts +0 -162
  435. package/src/swarm/router-prompts.ts +0 -39
  436. package/src/swarm/synthesizer.ts +0 -81
  437. package/src/swarm/types.ts +0 -72
  438. package/src/swarm/worker-backend.ts +0 -131
  439. package/src/swarm/worker-prompts.ts +0 -80
  440. package/src/swarm/worker-runner.ts +0 -170
  441. package/src/tools/claude-code/claude-code.ts +0 -610
  442. package/src/tools/swarm/delegate.ts +0 -205
@@ -209,11 +209,9 @@ mock.module("../util/logger.js", () => ({
209
209
  mock.module("../config/loader.js", () => ({
210
210
  getConfig: () => ({
211
211
  skills: { entries: {}, allowBundled: null },
212
- assistantFeatureFlagValues: {},
213
212
  }),
214
213
  loadConfig: () => ({
215
214
  skills: { entries: {}, allowBundled: null },
216
- assistantFeatureFlagValues: {},
217
215
  }),
218
216
  invalidateConfigCache: () => {},
219
217
  }));
@@ -1721,58 +1719,6 @@ describe("bundled skill: gmail", () => {
1721
1719
  });
1722
1720
  });
1723
1721
 
1724
- describe("bundled skill: claude-code", () => {
1725
- let sessionState: Map<string, string>;
1726
-
1727
- beforeEach(() => {
1728
- mockCatalog = [];
1729
- mockManifests = {};
1730
- mockRegisteredTools = new Map();
1731
- mockUnregisteredSkillIds = [];
1732
- mockSkillRefCount = new Map();
1733
- mockSkillRefCount = new Map();
1734
- mockVersionHashes = {};
1735
- mockVersionHashErrors = new Set();
1736
- sessionState = new Map<string, string>();
1737
- });
1738
-
1739
- test("claude-code skill activation registers claude_code in allowedToolNames", () => {
1740
- mockCatalog = [
1741
- makeSkill("claude-code", "/path/to/bundled-skills/claude-code"),
1742
- ];
1743
- mockManifests = { "claude-code": makeManifest(["claude_code"]) };
1744
-
1745
- const history: Message[] = [
1746
- ...skillLoadMessages('<loaded_skill id="claude-code" />'),
1747
- ];
1748
-
1749
- const result = projectSkillTools(history, {
1750
- previouslyActiveSkillIds: sessionState,
1751
- });
1752
-
1753
- expect(result.toolDefinitions).toEqual([]);
1754
- expect(result.allowedToolNames).toEqual(new Set(["claude_code"]));
1755
- });
1756
-
1757
- test("claude_code tool is absent when claude-code skill is not active", () => {
1758
- mockCatalog = [
1759
- makeSkill("claude-code", "/path/to/bundled-skills/claude-code"),
1760
- ];
1761
- mockManifests = { "claude-code": makeManifest(["claude_code"]) };
1762
-
1763
- const history: Message[] = [
1764
- { role: "user", content: [{ type: "text", text: "Hello" }] },
1765
- ];
1766
-
1767
- const result = projectSkillTools(history, {
1768
- previouslyActiveSkillIds: sessionState,
1769
- });
1770
-
1771
- expect(result.toolDefinitions).toHaveLength(0);
1772
- expect(result.allowedToolNames.has("claude_code")).toBe(false);
1773
- });
1774
- });
1775
-
1776
1722
  // ---------------------------------------------------------------------------
1777
1723
  // Bundled skill: app-builder
1778
1724
  // ---------------------------------------------------------------------------
@@ -130,7 +130,6 @@ mock.module("../memory/retriever.js", () => ({
130
130
  injectedText: "",
131
131
 
132
132
  semanticHits: 0,
133
- recencyHits: 0,
134
133
  injectedTokens: 0,
135
134
  latencyMs: 0,
136
135
  }),
@@ -137,7 +137,6 @@ mock.module("../memory/retriever.js", () => ({
137
137
  injectedText: "",
138
138
 
139
139
  semanticHits: 0,
140
- recencyHits: 0,
141
140
  injectedTokens: 0,
142
141
  latencyMs: 0,
143
142
  }),
@@ -107,6 +107,93 @@ describe("conversation-title-service", () => {
107
107
  );
108
108
  });
109
109
 
110
+ test("regeneration extracts text from JSON content blocks", async () => {
111
+ mockGetMessages.mockReturnValueOnce([
112
+ {
113
+ role: "user",
114
+ content: JSON.stringify([
115
+ { type: "text", text: "Help me plan the kickoff" },
116
+ ]),
117
+ },
118
+ {
119
+ role: "assistant",
120
+ content: JSON.stringify([
121
+ { type: "text", text: "Sure, here's a plan" },
122
+ { type: "tool_use", id: "toolu_1", name: "web_search", input: {} },
123
+ ]),
124
+ },
125
+ {
126
+ role: "user",
127
+ content: JSON.stringify([{ type: "text", text: "Looks good" }]),
128
+ },
129
+ ]);
130
+
131
+ const provider = {
132
+ name: "test-provider",
133
+ sendMessage: mock(async () => {
134
+ throw new Error("should not call directly");
135
+ }),
136
+ };
137
+
138
+ await regenerateConversationTitle({ conversationId: "conv-1", provider });
139
+
140
+ // The prompt sent to the sidechain should contain plain text, not raw JSON
141
+ const prompt = (mockRunBtwSidechain.mock.calls[0] as any)?.[0]
142
+ ?.content as string;
143
+ expect(prompt).not.toContain('"type":"text"');
144
+ expect(prompt).not.toContain('"type":"tool_use"');
145
+ // Tool metadata should NOT appear in the title prompt
146
+ expect(prompt).not.toContain("Tool use");
147
+ expect(prompt).not.toContain("web_search");
148
+ expect(prompt).toContain("Help me plan the kickoff");
149
+ expect(prompt).toContain("Sure, here's a plan");
150
+ expect(prompt).toContain("Looks good");
151
+ });
152
+
153
+ test("regeneration extracts text from tool_result content blocks", async () => {
154
+ mockGetMessages.mockReturnValueOnce([
155
+ {
156
+ role: "user",
157
+ content: JSON.stringify([
158
+ { type: "text", text: "Search for restaurants" },
159
+ ]),
160
+ },
161
+ {
162
+ role: "assistant",
163
+ content: JSON.stringify([
164
+ { type: "tool_use", id: "toolu_1", name: "web_search", input: {} },
165
+ ]),
166
+ },
167
+ {
168
+ role: "user",
169
+ content: JSON.stringify([
170
+ {
171
+ type: "tool_result",
172
+ tool_use_id: "toolu_1",
173
+ content: "Found 3 restaurants nearby",
174
+ },
175
+ ]),
176
+ },
177
+ ]);
178
+
179
+ const provider = {
180
+ name: "test-provider",
181
+ sendMessage: mock(async () => {
182
+ throw new Error("should not call directly");
183
+ }),
184
+ };
185
+
186
+ await regenerateConversationTitle({ conversationId: "conv-1", provider });
187
+
188
+ const prompt = (mockRunBtwSidechain.mock.calls[0] as any)?.[0]
189
+ ?.content as string;
190
+ expect(prompt).not.toContain('"type":"tool_result"');
191
+ // Tool-only assistant message should be skipped entirely
192
+ expect(prompt).not.toContain("Tool use");
193
+ expect(prompt).toContain("Search for restaurants");
194
+ expect(prompt).toContain("Found 3 restaurants nearby");
195
+ });
196
+
110
197
  test("uses the BTW side-chain helper for title regeneration", async () => {
111
198
  const provider = {
112
199
  name: "test-provider",
@@ -149,7 +149,6 @@ mock.module("../memory/retriever.js", () => ({
149
149
  model: "mock",
150
150
  injectedText: "",
151
151
  semanticHits: 0,
152
- recencyHits: 0,
153
152
  mergedCount: 0,
154
153
  selectedCount: 0,
155
154
  injectedTokens: 0,
@@ -145,7 +145,6 @@ mock.module("../memory/retriever.js", () => ({
145
145
  model: "mock",
146
146
  injectedText: "",
147
147
  semanticHits: 0,
148
- recencyHits: 0,
149
148
  mergedCount: 0,
150
149
  selectedCount: 0,
151
150
  injectedTokens: 0,
@@ -84,6 +84,9 @@ describe("local CES discovery", () => {
84
84
  if (result.mode === "unavailable") {
85
85
  expect(result.reason).toContain("CES executable not found");
86
86
  expect(result.mode).toBe("unavailable");
87
+ } else if (result.mode === "local-source") {
88
+ // Source entry point exists in the monorepo — verify the success shape.
89
+ expect(result.sourcePath).toBeTruthy();
87
90
  } else {
88
91
  // Binary exists in this environment — verify the success shape.
89
92
  expect(result.mode).toBe("local");
@@ -95,9 +98,9 @@ describe("local CES discovery", () => {
95
98
 
96
99
  test("never returns a fallback or in-process mode", () => {
97
100
  const result = discoverLocalCes();
98
- // The result must be either "local" (with a valid path) or "unavailable".
101
+ // The result must be "local", "local-source", or "unavailable".
99
102
  // There must never be a fallback mode like "in-process" or "degraded".
100
- expect(["local", "unavailable"]).toContain(result.mode);
103
+ expect(["local", "local-source", "unavailable"]).toContain(result.mode);
101
104
  });
102
105
  });
103
106
 
@@ -2,15 +2,18 @@
2
2
  * Tests for CES (Credential Execution Service) feature gates.
3
3
  *
4
4
  * Verifies:
5
- * - All CES flags default to disabled (safe dark-launch).
6
- * - Each flag can be enabled independently via config overrides.
5
+ * - Each CES flag defaults to its registry-declared value.
6
+ * - Each flag can be toggled independently via config overrides.
7
7
  * - Enabling CES flags does not implicitly change unrelated approval
8
8
  * behavior or existing feature flags.
9
9
  */
10
10
 
11
- import { describe, expect, test } from "bun:test";
11
+ import { afterEach, beforeEach, describe, expect, test } from "bun:test";
12
12
 
13
- import { isAssistantFeatureFlagEnabled } from "../config/assistant-feature-flags.js";
13
+ import {
14
+ _setOverridesForTesting,
15
+ isAssistantFeatureFlagEnabled,
16
+ } from "../config/assistant-feature-flags.js";
14
17
  import type { AssistantConfig } from "../config/schema.js";
15
18
  import {
16
19
  CES_GRANT_AUDIT_FLAG_KEY,
@@ -25,15 +28,21 @@ import {
25
28
  isCesToolsEnabled,
26
29
  } from "../credential-execution/feature-gates.js";
27
30
 
31
+ beforeEach(() => {
32
+ _setOverridesForTesting({});
33
+ });
34
+
35
+ afterEach(() => {
36
+ _setOverridesForTesting({});
37
+ });
38
+
28
39
  // ---------------------------------------------------------------------------
29
40
  // Helpers
30
41
  // ---------------------------------------------------------------------------
31
42
 
32
- /** Create a minimal AssistantConfig with optional feature flag values. */
33
- function makeConfig(flagOverrides?: Record<string, boolean>): AssistantConfig {
34
- return {
35
- ...(flagOverrides ? { assistantFeatureFlagValues: flagOverrides } : {}),
36
- } as AssistantConfig;
43
+ /** Create a minimal AssistantConfig (flag overrides are now set via _setOverridesForTesting). */
44
+ function makeConfig(): AssistantConfig {
45
+ return {} as AssistantConfig;
37
46
  }
38
47
 
39
48
  /** All CES flag keys for iteration. */
@@ -45,28 +54,37 @@ const ALL_CES_FLAG_KEYS = [
45
54
  CES_MANAGED_SIDECAR_FLAG_KEY,
46
55
  ] as const;
47
56
 
48
- /** All CES predicate functions paired with their flag keys. */
57
+ /** All CES predicate functions paired with their flag keys and expected defaults. */
49
58
  const ALL_CES_PREDICATES = [
50
- { name: "isCesToolsEnabled", fn: isCesToolsEnabled, key: CES_TOOLS_FLAG_KEY },
59
+ {
60
+ name: "isCesToolsEnabled",
61
+ fn: isCesToolsEnabled,
62
+ key: CES_TOOLS_FLAG_KEY,
63
+ defaultEnabled: false,
64
+ },
51
65
  {
52
66
  name: "isCesShellLockdownEnabled",
53
67
  fn: isCesShellLockdownEnabled,
54
68
  key: CES_SHELL_LOCKDOWN_FLAG_KEY,
69
+ defaultEnabled: false,
55
70
  },
56
71
  {
57
72
  name: "isCesSecureInstallEnabled",
58
73
  fn: isCesSecureInstallEnabled,
59
74
  key: CES_SECURE_INSTALL_FLAG_KEY,
75
+ defaultEnabled: false,
60
76
  },
61
77
  {
62
78
  name: "isCesGrantAuditEnabled",
63
79
  fn: isCesGrantAuditEnabled,
64
80
  key: CES_GRANT_AUDIT_FLAG_KEY,
81
+ defaultEnabled: false,
65
82
  },
66
83
  {
67
84
  name: "isCesManagedSidecarEnabled",
68
85
  fn: isCesManagedSidecarEnabled,
69
86
  key: CES_MANAGED_SIDECAR_FLAG_KEY,
87
+ defaultEnabled: true,
70
88
  },
71
89
  ] as const;
72
90
 
@@ -83,21 +101,23 @@ describe("CES flag key format", () => {
83
101
  });
84
102
 
85
103
  // ---------------------------------------------------------------------------
86
- // Default-safe: all CES flags disabled by default
104
+ // Defaults: each CES flag matches its registry-declared default
87
105
  // ---------------------------------------------------------------------------
88
106
 
89
- describe("CES flags default safely (all disabled)", () => {
90
- const config = makeConfig();
91
-
92
- for (const { name, fn } of ALL_CES_PREDICATES) {
93
- test(`${name} returns false with no config overrides`, () => {
94
- expect(fn(config)).toBe(false);
107
+ describe("CES flags match registry defaults", () => {
108
+ for (const { name, fn, defaultEnabled } of ALL_CES_PREDICATES) {
109
+ test(`${name} returns ${defaultEnabled} with no config overrides`, () => {
110
+ const config = makeConfig();
111
+ expect(fn(config)).toBe(defaultEnabled);
95
112
  });
96
113
  }
97
114
 
98
- for (const key of ALL_CES_FLAG_KEYS) {
99
- test(`isAssistantFeatureFlagEnabled('${key}') returns false with no overrides`, () => {
100
- expect(isAssistantFeatureFlagEnabled(key, config)).toBe(false);
115
+ for (const pred of ALL_CES_PREDICATES) {
116
+ test(`isAssistantFeatureFlagEnabled('${pred.key}') returns ${pred.defaultEnabled} with no overrides`, () => {
117
+ const config = makeConfig();
118
+ expect(isAssistantFeatureFlagEnabled(pred.key, config)).toBe(
119
+ pred.defaultEnabled,
120
+ );
101
121
  });
102
122
  }
103
123
  });
@@ -106,18 +126,24 @@ describe("CES flags default safely (all disabled)", () => {
106
126
  // Independent enablement: each flag can be enabled without affecting others
107
127
  // ---------------------------------------------------------------------------
108
128
 
109
- describe("CES flags can be enabled independently", () => {
129
+ describe("CES flags can be toggled independently", () => {
110
130
  for (const { name, fn, key } of ALL_CES_PREDICATES) {
111
131
  test(`enabling ${key} makes ${name} return true`, () => {
112
- const config = makeConfig({ [key]: true });
132
+ _setOverridesForTesting({ [key]: true });
133
+ const config = makeConfig();
113
134
  expect(fn(config)).toBe(true);
114
135
  });
115
136
 
116
- test(`enabling ${key} does not enable other CES flags`, () => {
117
- const config = makeConfig({ [key]: true });
118
- for (const { fn: otherFn, key: otherKey } of ALL_CES_PREDICATES) {
137
+ test(`enabling ${key} does not change other CES flags from their defaults`, () => {
138
+ _setOverridesForTesting({ [key]: true });
139
+ const config = makeConfig();
140
+ for (const {
141
+ fn: otherFn,
142
+ key: otherKey,
143
+ defaultEnabled,
144
+ } of ALL_CES_PREDICATES) {
119
145
  if (otherKey === key) continue;
120
- expect(otherFn(config)).toBe(false);
146
+ expect(otherFn(config)).toBe(defaultEnabled);
121
147
  }
122
148
  });
123
149
  }
@@ -130,7 +156,8 @@ describe("CES flags can be enabled independently", () => {
130
156
  describe("CES flags respect explicit false overrides", () => {
131
157
  for (const { name, fn, key } of ALL_CES_PREDICATES) {
132
158
  test(`${name} returns false when explicitly set to false`, () => {
133
- const config = makeConfig({ [key]: false });
159
+ _setOverridesForTesting({ [key]: false });
160
+ const config = makeConfig();
134
161
  expect(fn(config)).toBe(false);
135
162
  });
136
163
  }
@@ -146,7 +173,8 @@ describe("CES flags do not affect unrelated flags", () => {
146
173
  for (const key of ALL_CES_FLAG_KEYS) {
147
174
  overrides[key] = true;
148
175
  }
149
- const config = makeConfig(overrides);
176
+ _setOverridesForTesting(overrides);
177
+ const config = makeConfig();
150
178
 
151
179
  // browser defaults to true in the registry and should stay true
152
180
  expect(
@@ -159,7 +187,8 @@ describe("CES flags do not affect unrelated flags", () => {
159
187
  for (const key of ALL_CES_FLAG_KEYS) {
160
188
  overrides[key] = true;
161
189
  }
162
- const config = makeConfig(overrides);
190
+ _setOverridesForTesting(overrides);
191
+ const config = makeConfig();
163
192
 
164
193
  // contacts defaults to true in the registry and should stay true
165
194
  expect(
@@ -26,7 +26,17 @@
26
26
  * contracts — no real CES process or socket dependencies are needed.
27
27
  */
28
28
 
29
- import { describe, expect, test } from "bun:test";
29
+ import { afterEach, beforeEach, describe, expect, test } from "bun:test";
30
+
31
+ import { _setOverridesForTesting } from "../config/assistant-feature-flags.js";
32
+
33
+ beforeEach(() => {
34
+ _setOverridesForTesting({});
35
+ });
36
+
37
+ afterEach(() => {
38
+ _setOverridesForTesting({});
39
+ });
30
40
 
31
41
  import {
32
42
  CES_PROTOCOL_VERSION,
@@ -58,11 +68,9 @@ import {
58
68
  // Helpers
59
69
  // ---------------------------------------------------------------------------
60
70
 
61
- /** Create a minimal AssistantConfig with optional feature flag values. */
62
- function makeConfig(flagOverrides?: Record<string, boolean>): AssistantConfig {
63
- return {
64
- ...(flagOverrides ? { assistantFeatureFlagValues: flagOverrides } : {}),
65
- } as AssistantConfig;
71
+ /** Create a minimal AssistantConfig (flag overrides are now set via _setOverridesForTesting). */
72
+ function makeConfig(): AssistantConfig {
73
+ return {} as AssistantConfig;
66
74
  }
67
75
 
68
76
  // ---------------------------------------------------------------------------
@@ -438,38 +446,42 @@ describe("managed OAuth materialization through CES sidecar", () => {
438
446
  // ---------------------------------------------------------------------------
439
447
 
440
448
  describe("feature-flag rollback safety", () => {
441
- test("managed sidecar flag defaults to false (safe dark-launch)", () => {
449
+ test("managed sidecar flag defaults to true (enabled by default)", () => {
442
450
  const config = makeConfig();
443
- expect(isCesManagedSidecarEnabled(config)).toBe(false);
451
+ expect(isCesManagedSidecarEnabled(config)).toBe(true);
444
452
  });
445
453
 
446
454
  test("managed sidecar flag can be explicitly enabled", () => {
447
- const config = makeConfig({
455
+ _setOverridesForTesting({
448
456
  "feature_flags.ces-managed-sidecar.enabled": true,
449
457
  });
458
+ const config = makeConfig();
450
459
  expect(isCesManagedSidecarEnabled(config)).toBe(true);
451
460
  });
452
461
 
453
462
  test("managed sidecar flag can be explicitly disabled", () => {
454
- const config = makeConfig({
463
+ _setOverridesForTesting({
455
464
  "feature_flags.ces-managed-sidecar.enabled": false,
456
465
  });
466
+ const config = makeConfig();
457
467
  expect(isCesManagedSidecarEnabled(config)).toBe(false);
458
468
  });
459
469
 
460
470
  test("enabling managed sidecar does not enable CES tools", () => {
461
- const config = makeConfig({
471
+ _setOverridesForTesting({
462
472
  "feature_flags.ces-managed-sidecar.enabled": true,
463
473
  });
474
+ const config = makeConfig();
464
475
  // CES tools flag should remain independently controlled
465
476
  expect(isCesToolsEnabled(config)).toBe(false);
466
477
  });
467
478
 
468
479
  test("disabling managed sidecar does not affect other CES flags", () => {
469
- const config = makeConfig({
480
+ _setOverridesForTesting({
470
481
  "feature_flags.ces-managed-sidecar.enabled": false,
471
482
  "feature_flags.ces-tools.enabled": true,
472
483
  });
484
+ const config = makeConfig();
473
485
  expect(isCesToolsEnabled(config)).toBe(true);
474
486
  });
475
487
  });
@@ -480,10 +492,11 @@ describe("feature-flag rollback safety", () => {
480
492
 
481
493
  describe("process manager config wiring", () => {
482
494
  test("CesProcessManagerConfig accepts assistantConfig for flag gating", () => {
495
+ _setOverridesForTesting({
496
+ "feature_flags.ces-managed-sidecar.enabled": true,
497
+ });
483
498
  const config: CesProcessManagerConfig = {
484
- assistantConfig: makeConfig({
485
- "feature_flags.ces-managed-sidecar.enabled": true,
486
- }),
499
+ assistantConfig: makeConfig(),
487
500
  };
488
501
  expect(config.assistantConfig).toBeDefined();
489
502
  expect(isCesManagedSidecarEnabled(config.assistantConfig!)).toBe(true);
@@ -491,16 +504,17 @@ describe("process manager config wiring", () => {
491
504
 
492
505
  test("CesProcessManagerConfig requires assistantConfig for feature-flag gate", () => {
493
506
  const config: CesProcessManagerConfig = {
494
- assistantConfig: makeConfig({}),
507
+ assistantConfig: makeConfig(),
495
508
  };
496
509
  expect(config.assistantConfig).toBeDefined();
497
510
  });
498
511
 
499
512
  test("when flag is off, managed discovery is skipped", () => {
513
+ _setOverridesForTesting({
514
+ "feature_flags.ces-managed-sidecar.enabled": false,
515
+ });
500
516
  const config: CesProcessManagerConfig = {
501
- assistantConfig: makeConfig({
502
- "feature_flags.ces-managed-sidecar.enabled": false,
503
- }),
517
+ assistantConfig: makeConfig(),
504
518
  };
505
519
  // The managed path should be gated
506
520
  expect(isCesManagedSidecarEnabled(config.assistantConfig!)).toBe(false);
@@ -513,9 +527,10 @@ describe("process manager config wiring", () => {
513
527
 
514
528
  describe("non-CES internal consumers intact when flag is off", () => {
515
529
  test("existing non-agent flows are unaffected by managed sidecar flag", () => {
516
- const config = makeConfig({
530
+ _setOverridesForTesting({
517
531
  "feature_flags.ces-managed-sidecar.enabled": false,
518
532
  });
533
+ const config = makeConfig();
519
534
  expect(isCesManagedSidecarEnabled(config)).toBe(false);
520
535
  });
521
536
 
@@ -10,7 +10,6 @@ const mockConfig = {
10
10
  action: "block" as "redact" | "warn" | "block",
11
11
  entropyThreshold: 4.0,
12
12
  allowOneTimeSend: false,
13
- blockIngress: true,
14
13
  },
15
14
  timeouts: { permissionTimeoutSec: 300 },
16
15
  };
@@ -67,7 +66,7 @@ mock.module("../security/secure-keys.js", () => {
67
66
  setSecureKeyAsync: async (key: string, value: string) =>
68
67
  syncSet(key, value),
69
68
  deleteSecureKeyAsync: async (key: string) => syncDelete(key),
70
- listSecureKeysAsync: async () => [...storedKeys.keys()],
69
+ listSecureKeysAsync: async () => ({ accounts: [...storedKeys.keys()], unreachable: false }),
71
70
  };
72
71
  });
73
72
 
@@ -118,8 +117,6 @@ mock.module("../tools/credentials/policy-validate.js", () => ({
118
117
 
119
118
  // Import modules under test
120
119
  const { credentialStoreTool } = await import("../tools/credentials/vault.js");
121
- const { checkIngressForSecrets } =
122
- await import("../security/secret-ingress.js");
123
120
  const { isToolAllowed } = await import("../tools/credentials/tool-policy.js");
124
121
  const { isDomainAllowed } =
125
122
  await import("../tools/credentials/domain-policy.js");
@@ -203,61 +200,6 @@ describe("E2E: secure store and list lifecycle", () => {
203
200
  });
204
201
  });
205
202
 
206
- // ---------------------------------------------------------------------------
207
- // E2E Scenario 2 — Secret-in-chat blocked and redirected
208
- // ---------------------------------------------------------------------------
209
-
210
- describe("E2E: secret ingress blocking", () => {
211
- beforeEach(() => {
212
- mockConfig.secretDetection.enabled = true;
213
- mockConfig.secretDetection.action = "block";
214
- });
215
-
216
- test("blocks message containing AWS access key", () => {
217
- const awsKey = ["AKIA", "IOSFODNN7", "REALKEY"].join("");
218
- const check = checkIngressForSecrets(`Here is my key: ${awsKey}`);
219
- expect(check.blocked).toBe(true);
220
- expect(check.detectedTypes.length).toBeGreaterThan(0);
221
- // Notice must never contain the actual secret
222
- expect(check.userNotice).toBeDefined();
223
- expect(check.userNotice).not.toContain(awsKey);
224
- });
225
-
226
- test("blocks message containing GitHub token", () => {
227
- const ghToken = ["ghp_", "ABCDEFghijklMN01234567", "89abcdef"].join("");
228
- const check = checkIngressForSecrets(`Use this token: ${ghToken}`);
229
- expect(check.blocked).toBe(true);
230
- });
231
-
232
- test("allows normal text through", () => {
233
- const check = checkIngressForSecrets("Please help me configure my project");
234
- expect(check.blocked).toBe(false);
235
- expect(check.detectedTypes).toEqual([]);
236
- });
237
-
238
- test("bypasses when detection is disabled", () => {
239
- mockConfig.secretDetection.enabled = false;
240
- const awsKey = ["AKIA", "IOSFODNN7", "REALKEY"].join("");
241
- const check = checkIngressForSecrets(awsKey);
242
- expect(check.blocked).toBe(false);
243
- });
244
-
245
- test("bypasses when blockIngress is false", () => {
246
- mockConfig.secretDetection.blockIngress = false;
247
- const awsKey = ["AKIA", "IOSFODNN7", "REALKEY"].join("");
248
- const check = checkIngressForSecrets(awsKey);
249
- expect(check.blocked).toBe(false);
250
- });
251
-
252
- test("still blocks when action is warn but blockIngress is true", () => {
253
- mockConfig.secretDetection.action = "warn";
254
- mockConfig.secretDetection.blockIngress = true;
255
- const awsKey = ["AKIA", "IOSFODNN7", "REALKEY"].join("");
256
- const check = checkIngressForSecrets(awsKey);
257
- expect(check.blocked).toBe(true);
258
- });
259
- });
260
-
261
203
  // ---------------------------------------------------------------------------
262
204
  // E2E Scenario 3 — One-time send override path
263
205
  // ---------------------------------------------------------------------------
@@ -411,12 +353,4 @@ describe("E2E: cross-cutting secret leak prevention", () => {
411
353
  );
412
354
  expect(result.content).not.toContain(secret);
413
355
  });
414
-
415
- test("ingress notice never contains the detected secret", () => {
416
- const awsKey = ["AKIA", "IOSFODNN7", "REALKEY"].join("");
417
- const check = checkIngressForSecrets(awsKey);
418
- expect(check.blocked).toBe(true);
419
- expect(check.userNotice).toBeDefined();
420
- expect(check.userNotice).not.toContain(awsKey);
421
- });
422
356
  });