@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
@@ -12,11 +12,6 @@ import {
12
12
  type OAuthConnectionRow,
13
13
  } from "../../oauth/oauth-store.js";
14
14
  import { credentialKey } from "../../security/credential-key.js";
15
- import {
16
- deleteSecureKeyAsync,
17
- getSecureKeyAsync,
18
- setSecureKeyAsync,
19
- } from "../../security/secure-keys.js";
20
15
  import {
21
16
  assertMetadataWritable,
22
17
  type CredentialMetadata,
@@ -26,9 +21,33 @@ import {
26
21
  listCredentialMetadata,
27
22
  upsertCredentialMetadata,
28
23
  } from "../../tools/credentials/metadata-store.js";
24
+ import {
25
+ deleteSecureKeyViaDaemon,
26
+ getSecureKeyResultViaDaemon,
27
+ getSecureKeyViaDaemon,
28
+ setSecureKeyViaDaemon,
29
+ } from "../lib/daemon-credential-client.js";
29
30
  import { log } from "../logger.js";
30
31
  import { shouldOutputJson, writeOutput } from "../output.js";
31
32
 
33
+ // ---------------------------------------------------------------------------
34
+ // Format-aware error output
35
+ // ---------------------------------------------------------------------------
36
+
37
+ /**
38
+ * Write an error message respecting the output format. In JSON mode, emit a
39
+ * structured `{ ok: false, error }` object to stdout. In human mode, write
40
+ * plain text to stderr so the assistant (LLM) doesn't receive JSON that it
41
+ * might misinterpret as data.
42
+ */
43
+ function writeError(cmd: Command, message: string): void {
44
+ if (shouldOutputJson(cmd)) {
45
+ writeOutput(cmd, { ok: false, error: message });
46
+ } else {
47
+ process.stderr.write(`Error: ${message}\n`);
48
+ }
49
+ }
50
+
32
51
  // ---------------------------------------------------------------------------
33
52
  // CES shell lockdown guard
34
53
  // ---------------------------------------------------------------------------
@@ -309,7 +328,7 @@ Examples:
309
328
 
310
329
  const credentials = await Promise.all(
311
330
  allMetadata.map(async (m) => {
312
- const secret = await getSecureKeyAsync(
331
+ const secret = await getSecureKeyViaDaemon(
313
332
  credentialKey(m.service, m.field),
314
333
  );
315
334
  const connection = connectionsByProvider.get(m.service);
@@ -335,13 +354,13 @@ Examples:
335
354
  managedOutputs = descriptors.map(buildManagedCredentialOutput);
336
355
  }
337
356
 
338
- writeOutput(cmd, {
339
- ok: true,
340
- credentials,
341
- managedCredentials: managedOutputs,
342
- });
343
-
344
- if (!shouldOutputJson(cmd)) {
357
+ if (shouldOutputJson(cmd)) {
358
+ writeOutput(cmd, {
359
+ ok: true,
360
+ credentials,
361
+ managedCredentials: managedOutputs,
362
+ });
363
+ } else {
345
364
  const totalCount = credentials.length + managedOutputs.length;
346
365
  if (totalCount === 0) {
347
366
  log.info("No credentials found");
@@ -366,7 +385,7 @@ Examples:
366
385
  }
367
386
  } catch (err) {
368
387
  const message = err instanceof Error ? err.message : String(err);
369
- writeOutput(cmd, { ok: false, error: message });
388
+ writeError(cmd, message);
370
389
  process.exitCode = 1;
371
390
  }
372
391
  });
@@ -417,16 +436,16 @@ Examples:
417
436
  ) => {
418
437
  try {
419
438
  const { service, field } = opts;
420
- const storageKey = credentialKey(service, field);
421
439
 
422
440
  assertMetadataWritable();
423
441
 
424
- const stored = await setSecureKeyAsync(storageKey, value);
442
+ const stored = await setSecureKeyViaDaemon(
443
+ "credential",
444
+ `${service}:${field}`,
445
+ value,
446
+ );
425
447
  if (!stored) {
426
- writeOutput(cmd, {
427
- ok: false,
428
- error: `Failed to store secret for ${service}:${field}`,
429
- });
448
+ writeError(cmd, `Failed to store secret for ${service}:${field}`);
430
449
  process.exitCode = 1;
431
450
  return;
432
451
  }
@@ -442,21 +461,21 @@ Examples:
442
461
  });
443
462
  await syncManualTokenConnection(service);
444
463
 
445
- writeOutput(cmd, {
446
- ok: true,
447
- credentialId: metadata.credentialId,
448
- service,
449
- field,
450
- });
451
-
452
- if (!shouldOutputJson(cmd)) {
464
+ if (shouldOutputJson(cmd)) {
465
+ writeOutput(cmd, {
466
+ ok: true,
467
+ credentialId: metadata.credentialId,
468
+ service,
469
+ field,
470
+ });
471
+ } else {
453
472
  log.info(
454
473
  `Stored credential ${service}:${field} (${metadata.credentialId})`,
455
474
  );
456
475
  }
457
476
  } catch (err) {
458
477
  const message = err instanceof Error ? err.message : String(err);
459
- writeOutput(cmd, { ok: false, error: message });
478
+ writeError(cmd, message);
460
479
  process.exitCode = 1;
461
480
  }
462
481
  },
@@ -484,16 +503,18 @@ Examples:
484
503
  .action(async (opts: { service: string; field: string }, cmd: Command) => {
485
504
  try {
486
505
  const { service, field } = opts;
487
- const storageKey = credentialKey(service, field);
488
506
 
489
507
  assertMetadataWritable();
490
508
 
491
- const secretResult = await deleteSecureKeyAsync(storageKey);
509
+ const secretResult = await deleteSecureKeyViaDaemon(
510
+ "credential",
511
+ `${service}:${field}`,
512
+ );
492
513
  if (secretResult === "error") {
493
- writeOutput(cmd, {
494
- ok: false,
495
- error: "Failed to delete credential from secure storage",
496
- });
514
+ writeError(
515
+ cmd,
516
+ "Failed to delete credential from secure storage",
517
+ );
497
518
  process.exitCode = 1;
498
519
  return;
499
520
  }
@@ -510,10 +531,10 @@ Examples:
510
531
  }
511
532
 
512
533
  if (oauthResult === "error") {
513
- writeOutput(cmd, {
514
- ok: false,
515
- error: "Failed to disconnect OAuth provider — please try again",
516
- });
534
+ writeError(
535
+ cmd,
536
+ "Failed to disconnect OAuth provider — please try again",
537
+ );
517
538
  process.exitCode = 1;
518
539
  return;
519
540
  }
@@ -523,19 +544,19 @@ Examples:
523
544
  !metadataDeleted &&
524
545
  oauthResult !== "disconnected"
525
546
  ) {
526
- writeOutput(cmd, { ok: false, error: "Credential not found" });
547
+ writeError(cmd, "Credential not found");
527
548
  process.exitCode = 1;
528
549
  return;
529
550
  }
530
551
 
531
- writeOutput(cmd, { ok: true, service, field });
532
-
533
- if (!shouldOutputJson(cmd)) {
552
+ if (shouldOutputJson(cmd)) {
553
+ writeOutput(cmd, { ok: true, service, field });
554
+ } else {
534
555
  log.info(`Deleted credential ${service}:${field}`);
535
556
  }
536
557
  } catch (err) {
537
558
  const message = err instanceof Error ? err.message : String(err);
538
- writeOutput(cmd, { ok: false, error: message });
559
+ writeError(cmd, message);
539
560
  process.exitCode = 1;
540
561
  }
541
562
  });
@@ -594,24 +615,31 @@ Examples:
594
615
  field = metadata.field;
595
616
  } else {
596
617
  // No metadata found by UUID, and we can't determine the storage key
597
- writeOutput(cmd, { ok: false, error: "Credential not found" });
618
+ writeError(cmd, "Credential not found");
598
619
  process.exitCode = 1;
599
620
  return;
600
621
  }
601
622
  } else {
602
- writeOutput(cmd, {
603
- ok: false,
604
- error:
605
- "Either --service and --field flags or a credential UUID is required",
606
- });
623
+ writeError(
624
+ cmd,
625
+ "Either --service and --field flags or a credential UUID is required",
626
+ );
607
627
  process.exitCode = 1;
608
628
  return;
609
629
  }
610
630
 
611
- const secret = await getSecureKeyAsync(storageKey);
631
+ const { value: secret, unreachable } =
632
+ await getSecureKeyResultViaDaemon(storageKey);
612
633
 
613
634
  if (!metadata && (secret == null || secret.length === 0)) {
614
- writeOutput(cmd, { ok: false, error: "Credential not found" });
635
+ if (unreachable) {
636
+ writeError(
637
+ cmd,
638
+ "Keychain broker is unreachable — restart the Vellum app and accept the macOS Keychain prompt",
639
+ );
640
+ } else {
641
+ writeError(cmd, "Credential not found");
642
+ }
615
643
  process.exitCode = 1;
616
644
  return;
617
645
  }
@@ -620,23 +648,23 @@ Examples:
620
648
  // This can happen if someone stored a key directly without going through the
621
649
  // credential set command. Build a minimal output in that case.
622
650
  if (!metadata) {
623
- writeOutput(cmd, {
624
- ok: true,
625
- service: service,
626
- field: field,
627
- credentialId: null,
628
- scrubbedValue: scrubSecret(secret),
629
- hasSecret: secret != null && secret.length > 0,
630
- alias: null,
631
- usageDescription: null,
632
- allowedTools: [],
633
- allowedDomains: [],
634
- createdAt: null,
635
- updatedAt: null,
636
- injectionTemplateCount: 0,
637
- });
638
-
639
- if (!shouldOutputJson(cmd)) {
651
+ if (shouldOutputJson(cmd)) {
652
+ writeOutput(cmd, {
653
+ ok: true,
654
+ service: service,
655
+ field: field,
656
+ credentialId: null,
657
+ scrubbedValue: scrubSecret(secret),
658
+ hasSecret: secret != null && secret.length > 0,
659
+ alias: null,
660
+ usageDescription: null,
661
+ allowedTools: [],
662
+ allowedDomains: [],
663
+ createdAt: null,
664
+ updatedAt: null,
665
+ injectionTemplateCount: 0,
666
+ });
667
+ } else {
640
668
  log.info(` ${service}:${field}`);
641
669
  log.info(` Value: ${scrubSecret(secret)}`);
642
670
  log.info(" (no metadata record)");
@@ -646,14 +674,25 @@ Examples:
646
674
 
647
675
  const connection = safeGetConnectionByProvider(metadata.service);
648
676
  const output = buildCredentialOutput(metadata, secret, connection);
649
- writeOutput(cmd, output);
650
677
 
651
- if (!shouldOutputJson(cmd)) {
678
+ if (unreachable && (secret == null || secret.length === 0)) {
679
+ output.scrubbedValue = "(broker unreachable)";
680
+ output.brokerUnreachable = true;
681
+ }
682
+
683
+ if (shouldOutputJson(cmd)) {
684
+ writeOutput(cmd, output);
685
+ } else {
652
686
  printCredentialHuman(output);
687
+ if (unreachable && (secret == null || secret.length === 0)) {
688
+ log.info(
689
+ " \u26A0 Keychain broker unreachable — restart the Vellum app and accept the macOS Keychain prompt to access credentials",
690
+ );
691
+ }
653
692
  }
654
693
  } catch (err) {
655
694
  const message = err instanceof Error ? err.message : String(err);
656
- writeOutput(cmd, { ok: false, error: message });
695
+ writeError(cmd, message);
657
696
  process.exitCode = 1;
658
697
  }
659
698
  },
@@ -697,7 +736,7 @@ Examples:
697
736
  try {
698
737
  // CES shell lockdown: deny raw secret reveal in untrusted shells.
699
738
  if (isUntrustedShell()) {
700
- writeOutput(cmd, { ok: false, error: UNTRUSTED_SHELL_ERROR });
739
+ writeError(cmd, UNTRUSTED_SHELL_ERROR);
701
740
  process.exitCode = 1;
702
741
  return;
703
742
  }
@@ -711,24 +750,31 @@ Examples:
711
750
  if (metadata) {
712
751
  storageKey = credentialKey(metadata.service, metadata.field);
713
752
  } else {
714
- writeOutput(cmd, { ok: false, error: "Credential not found" });
753
+ writeError(cmd, "Credential not found");
715
754
  process.exitCode = 1;
716
755
  return;
717
756
  }
718
757
  } else {
719
- writeOutput(cmd, {
720
- ok: false,
721
- error:
722
- "Either --service and --field flags or a credential UUID is required",
723
- });
758
+ writeError(
759
+ cmd,
760
+ "Either --service and --field flags or a credential UUID is required",
761
+ );
724
762
  process.exitCode = 1;
725
763
  return;
726
764
  }
727
765
 
728
- const secret = await getSecureKeyAsync(storageKey);
766
+ const { value: secret, unreachable } =
767
+ await getSecureKeyResultViaDaemon(storageKey);
729
768
 
730
769
  if (secret == null || secret.length === 0) {
731
- writeOutput(cmd, { ok: false, error: "Credential not found" });
770
+ if (unreachable) {
771
+ writeError(
772
+ cmd,
773
+ "Keychain broker is unreachable — restart the Vellum app and accept the macOS Keychain prompt",
774
+ );
775
+ } else {
776
+ writeError(cmd, "Credential not found");
777
+ }
732
778
  process.exitCode = 1;
733
779
  return;
734
780
  }
@@ -740,7 +786,7 @@ Examples:
740
786
  }
741
787
  } catch (err) {
742
788
  const message = err instanceof Error ? err.message : String(err);
743
- writeOutput(cmd, { ok: false, error: message });
789
+ writeError(cmd, message);
744
790
  process.exitCode = 1;
745
791
  }
746
792
  },
@@ -7,7 +7,6 @@ import { getRuntimeHttpPort } from "../../config/env.js";
7
7
  import { loadRawConfig } from "../../config/loader.js";
8
8
  import { shouldAutoStartDaemon } from "../../daemon/connection-policy.js";
9
9
  import { isHttpHealthy } from "../../daemon/daemon-control.js";
10
- import { getProviderKeyAsync } from "../../security/secure-keys.js";
11
10
  import {
12
11
  getDbPath,
13
12
  getHooksDir,
@@ -16,6 +15,7 @@ import {
16
15
  getWorkspaceDir,
17
16
  getWorkspaceSkillsDir,
18
17
  } from "../../util/platform.js";
18
+ import { getProviderKeyViaDaemon } from "../lib/daemon-credential-client.js";
19
19
  import { log } from "../logger.js";
20
20
 
21
21
  export function registerDoctorCommand(program: Command): void {
@@ -81,7 +81,7 @@ Examples:
81
81
  typeof rawInferenceProvider === "string"
82
82
  ? rawInferenceProvider
83
83
  : "anthropic";
84
- const configKey = await getProviderKeyAsync(provider);
84
+ const configKey = await getProviderKeyViaDaemon(provider);
85
85
 
86
86
  if (provider === "ollama") {
87
87
  pass("Provider configured (Ollama; API key optional)");
@@ -2,10 +2,10 @@ import type { Command } from "commander";
2
2
 
3
3
  import { API_KEY_PROVIDERS } from "../../config/loader.js";
4
4
  import {
5
- deleteSecureKeyAsync,
6
- getSecureKeyAsync,
7
- setSecureKeyAsync,
8
- } from "../../security/secure-keys.js";
5
+ deleteSecureKeyViaDaemon,
6
+ getSecureKeyViaDaemon,
7
+ setSecureKeyViaDaemon,
8
+ } from "../lib/daemon-credential-client.js";
9
9
  import { log } from "../logger.js";
10
10
 
11
11
  // ---------------------------------------------------------------------------
@@ -61,7 +61,7 @@ Examples:
61
61
  .action(async () => {
62
62
  const stored: string[] = [];
63
63
  for (const provider of API_KEY_PROVIDERS) {
64
- const value = await getSecureKeyAsync(provider);
64
+ const value = await getSecureKeyViaDaemon(provider);
65
65
  if (value) stored.push(provider);
66
66
  }
67
67
  if (stored.length === 0) {
@@ -99,7 +99,7 @@ Examples:
99
99
  process.exit(1);
100
100
  }
101
101
 
102
- if (await setSecureKeyAsync(provider, key)) {
102
+ if (await setSecureKeyViaDaemon("api_key", provider, key)) {
103
103
  log.info(`Stored API key for "${provider}"`);
104
104
  } else {
105
105
  log.error(`Failed to store API key for "${provider}"`);
@@ -130,7 +130,7 @@ Examples:
130
130
  process.exit(1);
131
131
  }
132
132
 
133
- const result = await deleteSecureKeyAsync(provider);
133
+ const result = await deleteSecureKeyViaDaemon("api_key", provider);
134
134
  if (result === "deleted") {
135
135
  log.info(`Deleted API key for "${provider}"`);
136
136
  } else if (result === "error") {
@@ -183,7 +183,7 @@ Examples:
183
183
  log.info(`Memory degraded: ${result.reason ?? "unknown reason"}`);
184
184
  }
185
185
  log.info(`Semantic hits: ${result.semanticHits}`);
186
- log.info(`Recency hits: ${result.recencyHits}`);
186
+ log.info("Recency hits: 0");
187
187
  log.info(`Injected tokens: ${result.injectedTokens}`);
188
188
  log.info(`Latency: ${result.latencyMs}ms`);
189
189
  if (result.injectedText.length > 0) {
@@ -19,17 +19,16 @@ import {
19
19
  getProviderBehavior,
20
20
  resolveService,
21
21
  } from "../../../oauth/provider-behaviors.js";
22
- import { credentialKey } from "../../../security/credential-key.js";
23
- import {
24
- deleteSecureKeyAsync,
25
- getSecureKeyAsync,
26
- } from "../../../security/secure-keys.js";
27
22
  import { withValidToken } from "../../../security/token-manager.js";
28
23
  import {
29
24
  assertMetadataWritable,
30
25
  deleteCredentialMetadata,
31
26
  } from "../../../tools/credentials/metadata-store.js";
32
- import { isLinux, isMacOS } from "../../../util/platform.js";
27
+ import { openInBrowser } from "../../../util/browser.js";
28
+ import {
29
+ deleteSecureKeyViaDaemon,
30
+ getSecureKeyViaDaemon,
31
+ } from "../../lib/daemon-credential-client.js";
33
32
  import { getCliLogger } from "../../logger.js";
34
33
  import { shouldOutputJson, writeOutput } from "../../output.js";
35
34
 
@@ -538,8 +537,10 @@ Examples:
538
537
  "client_secret",
539
538
  ];
540
539
  for (const field of legacyFields) {
541
- const key = credentialKey(providerKey, field);
542
- const result = await deleteSecureKeyAsync(key);
540
+ const result = await deleteSecureKeyViaDaemon(
541
+ "credential",
542
+ `${providerKey}:${field}`,
543
+ );
543
544
  if (result === "deleted") cleanedUp = true;
544
545
 
545
546
  const metaDeleted = deleteCredentialMetadata(providerKey, field);
@@ -633,7 +634,7 @@ Examples:
633
634
 
634
635
  if (dbApp) {
635
636
  if (!clientId) clientId = dbApp.clientId;
636
- const storedSecret = await getSecureKeyAsync(
637
+ const storedSecret = await getSecureKeyViaDaemon(
637
638
  dbApp.clientSecretCredentialPath,
638
639
  );
639
640
  if (storedSecret) clientSecret = storedSecret;
@@ -685,26 +686,7 @@ Examples:
685
686
  clientId,
686
687
  clientSecret,
687
688
  isInteractive: !!opts.openBrowser,
688
- openUrl: opts.openBrowser
689
- ? (url) => {
690
- if (isMacOS()) {
691
- Bun.spawn(["open", url], {
692
- stdout: "ignore",
693
- stderr: "ignore",
694
- });
695
- } else if (isLinux()) {
696
- Bun.spawn(["xdg-open", url], {
697
- stdout: "ignore",
698
- stderr: "ignore",
699
- });
700
- } else {
701
- // Fallback: print URL for manual opening (stderr to keep --json stdout clean)
702
- process.stderr.write(
703
- `Open this URL to authorize:\n\n${url}\n`,
704
- );
705
- }
706
- }
707
- : undefined,
689
+ openUrl: opts.openBrowser ? openInBrowser : undefined,
708
690
  ...(opts.scopes ? { requestedScopes: opts.scopes } : {}),
709
691
  });
710
692
 
@@ -2,6 +2,7 @@ import type { Command } from "commander";
2
2
 
3
3
  import { registerAppCommands } from "./apps.js";
4
4
  import { registerConnectionCommands } from "./connections.js";
5
+ import { registerPlatformCommands } from "./platform.js";
5
6
  import { registerProviderCommands } from "./providers.js";
6
7
 
7
8
  export function registerOAuthCommand(program: Command): void {
@@ -49,4 +50,10 @@ Examples:
49
50
  // ---------------------------------------------------------------------------
50
51
 
51
52
  registerConnectionCommands(oauth);
53
+
54
+ // ---------------------------------------------------------------------------
55
+ // platform — subcommand group
56
+ // ---------------------------------------------------------------------------
57
+
58
+ registerPlatformCommands(oauth);
52
59
  }