@mycadet/assistant 0.12.10 → 0.13.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (180) hide show
  1. package/node_modules/@mycadet/ces-client/node_modules/@mycadet/service-contracts/src/__tests__/ingress.test.ts +10 -10
  2. package/node_modules/@mycadet/ces-client/node_modules/@mycadet/service-contracts/src/ingress.ts +3 -3
  3. package/node_modules/@mycadet/ces-client/src/http-credentials.ts +18 -1
  4. package/node_modules/@mycadet/gateway-client/node_modules/@mycadet/service-contracts/src/__tests__/ingress.test.ts +10 -10
  5. package/node_modules/@mycadet/gateway-client/node_modules/@mycadet/service-contracts/src/ingress.ts +3 -3
  6. package/node_modules/@mycadet/gateway-client/src/gateway-ipc-contracts.ts +0 -20
  7. package/node_modules/@mycadet/service-contracts/src/__tests__/ingress.test.ts +10 -10
  8. package/node_modules/@mycadet/service-contracts/src/ingress.ts +3 -3
  9. package/openapi.yaml +2 -708
  10. package/package.json +2 -3
  11. package/scripts/sync-web-search-catalog.ts +1 -2
  12. package/src/__tests__/cloud-profile-guard.test.ts +41 -5
  13. package/src/__tests__/config-schema.test.ts +6 -38
  14. package/src/__tests__/conversation-queue.test.ts +45 -6
  15. package/src/__tests__/db-readiness-http-gate.test.ts +0 -6
  16. package/src/__tests__/persist-onboarding-artifacts.test.ts +0 -1
  17. package/src/__tests__/persona-resolver.test.ts +0 -51
  18. package/src/__tests__/provider-cloud-proxy-integration.test.ts +2 -110
  19. package/src/__tests__/run-due-schedules.test.ts +0 -4
  20. package/src/__tests__/schedule-store.test.ts +0 -12
  21. package/src/__tests__/stt-stream-session.test.ts +4 -4
  22. package/src/__tests__/telephony-tts-guard.test.ts +2 -50
  23. package/src/__tests__/voice-config-update.test.ts +12 -167
  24. package/src/__tests__/web-search-catalog-parity.test.ts +0 -2
  25. package/src/__tests__/workspace-migration-130-speech-mode-to-provider.test.ts +9 -7
  26. package/src/__tests__/workspace-migration-132-web-search-mode-to-provider.test.ts +6 -6
  27. package/src/calls/__tests__/voice-session-bridge.test.ts +1 -4
  28. package/src/calls/resolve-call-tts-provider.ts +6 -25
  29. package/src/calls/telephony-credential-preflight.ts +0 -10
  30. package/src/calls/telephony-tts-capability.ts +1 -17
  31. package/src/cli/commands/tts.ts +1 -2
  32. package/src/cli/index.help.ts +0 -2
  33. package/src/cli/program.ts +0 -2
  34. package/src/config/bundled-skills/settings/tools/voice-config-update.ts +4 -42
  35. package/src/config/schemas/__tests__/stt.test.ts +10 -14
  36. package/src/config/schemas/llm.ts +3 -5
  37. package/src/config/schemas/services.ts +5 -6
  38. package/src/config/schemas/stt.ts +1 -3
  39. package/src/config/schemas/tts.ts +1 -30
  40. package/src/daemon/daemon-readiness.ts +4 -29
  41. package/src/daemon/lifecycle.ts +0 -31
  42. package/src/daemon/providers-setup.ts +0 -8
  43. package/src/heartbeat/__tests__/heartbeat-service.test.ts +0 -1
  44. package/src/heartbeat/heartbeat-service.ts +1 -66
  45. package/src/ipc/__tests__/db-readiness-ipc-gate.test.ts +1 -9
  46. package/src/live-voice/__tests__/live-voice-credential-preflight.test.ts +0 -44
  47. package/src/live-voice/__tests__/live-voice-flux-turn-end.test.ts +4 -6
  48. package/src/live-voice/__tests__/live-voice-stt.test.ts +1 -1
  49. package/src/live-voice/live-voice-credential-preflight.ts +9 -33
  50. package/src/live-voice/live-voice-session.ts +10 -6
  51. package/src/live-voice/live-voice-tts.ts +1 -8
  52. package/src/plugins/defaults/memory/worker.ts +3 -3
  53. package/src/prompts/persona-resolver.ts +0 -35
  54. package/src/providers/__tests__/search-provider-catalog.test.ts +5 -8
  55. package/src/providers/__tests__/voice-error-copy.test.ts +9 -10
  56. package/src/providers/search-provider-catalog.ts +7 -39
  57. package/src/providers/speech-to-text/__tests__/provider-catalog.test.ts +3 -47
  58. package/src/providers/speech-to-text/__tests__/resolve.test.ts +6 -372
  59. package/src/providers/speech-to-text/provider-catalog.ts +2 -73
  60. package/src/providers/speech-to-text/resolve.ts +3 -120
  61. package/src/runtime/http-router-types.ts +1 -3
  62. package/src/runtime/http-server.ts +1 -1
  63. package/src/runtime/routes/__tests__/conversation-query-routes.test.ts +13 -11
  64. package/src/runtime/routes/__tests__/tts-routes.test.ts +2 -6
  65. package/src/runtime/routes/conversation-query-routes.ts +0 -96
  66. package/src/runtime/routes/inbound-stages/transcribe-audio.test.ts +7 -7
  67. package/src/runtime/routes/index.ts +0 -4
  68. package/src/runtime/routes/live-voice-routes.test.ts +4 -11
  69. package/src/runtime/routes/live-voice-routes.ts +8 -11
  70. package/src/runtime/routes/secret-routes.ts +0 -6
  71. package/src/runtime/routes/tts-routes.ts +0 -38
  72. package/src/schedule/__tests__/plugin-schedule-reconciler.test.ts +1 -7
  73. package/src/schedule/__tests__/worker-mcp-readiness.test.ts +0 -4
  74. package/src/schedule/schedule-store.ts +0 -7
  75. package/src/schedule/scheduler.ts +0 -5
  76. package/src/schedule/worker.ts +1 -1
  77. package/src/stt/__tests__/daemon-batch-transcriber.test.ts +2 -10
  78. package/src/stt/daemon-batch-transcriber.ts +4 -38
  79. package/src/stt/types.ts +1 -9
  80. package/src/tools/network/__tests__/web-search.test.ts +3 -250
  81. package/src/tools/network/web-search.ts +4 -165
  82. package/src/tts/__tests__/provider-resolution.test.ts +0 -5
  83. package/src/tts/provider-catalog.ts +0 -4
  84. package/src/tts/types.ts +0 -1
  85. package/src/__tests__/cloud-speech-defaults.test.ts +0 -330
  86. package/src/__tests__/migration-cross-version-compatibility.test.ts +0 -1708
  87. package/src/__tests__/migration-export-http.test.ts +0 -557
  88. package/src/__tests__/migration-export-streaming.test.ts +0 -350
  89. package/src/__tests__/migration-export-to-gcs.test.ts +0 -706
  90. package/src/__tests__/migration-import-commit-http.test.ts +0 -1176
  91. package/src/__tests__/migration-import-from-gcs.test.ts +0 -534
  92. package/src/__tests__/migration-import-from-path.test.ts +0 -324
  93. package/src/__tests__/migration-import-from-url.test.ts +0 -588
  94. package/src/__tests__/migration-import-preflight-http.test.ts +0 -739
  95. package/src/__tests__/migration-jobs-status.test.ts +0 -139
  96. package/src/__tests__/migration-parity-persistence.test.ts +0 -1891
  97. package/src/__tests__/migration-transport.test.ts +0 -1089
  98. package/src/__tests__/migration-validate-http.test.ts +0 -634
  99. package/src/__tests__/migration-wizard.test.ts +0 -1395
  100. package/src/__tests__/rebind-secrets-screen.test.ts +0 -876
  101. package/src/__tests__/sanitize-config-for-transfer.test.ts +0 -259
  102. package/src/__tests__/transfer-progress-screen.test.ts +0 -1217
  103. package/src/__tests__/validation-results-screen.test.ts +0 -1130
  104. package/src/__tests__/vbundle-pax-and-symlink.test.ts +0 -147
  105. package/src/background-wake/background-wake-routes.test.ts +0 -906
  106. package/src/background-wake/cloud-client.test.ts +0 -328
  107. package/src/background-wake/cloud-client.ts +0 -196
  108. package/src/background-wake/next-wake.test.ts +0 -335
  109. package/src/background-wake/next-wake.ts +0 -188
  110. package/src/background-wake/publisher.ts +0 -93
  111. package/src/background-wake/wake-intent-hooks.test.ts +0 -234
  112. package/src/cli/commands/__tests__/backup.test.ts +0 -363
  113. package/src/cli/commands/backup.help.ts +0 -180
  114. package/src/cli/commands/backup.ts +0 -398
  115. package/src/cloud/cloud-speech.test.ts +0 -335
  116. package/src/cloud/cloud-speech.ts +0 -300
  117. package/src/config/cloud-speech-defaults.ts +0 -300
  118. package/src/config/sanitize-for-transfer.ts +0 -111
  119. package/src/live-voice/__tests__/live-voice-cloud-speech-fallback.test.ts +0 -250
  120. package/src/providers/speech-to-text/__tests__/cadet-cloud-realtime.test.ts +0 -457
  121. package/src/providers/speech-to-text/__tests__/cadet-cloud.test.ts +0 -271
  122. package/src/providers/speech-to-text/__tests__/cadet-speech-relay-connection.test.ts +0 -126
  123. package/src/providers/speech-to-text/cadet-cloud-flux-realtime.ts +0 -309
  124. package/src/providers/speech-to-text/cadet-cloud-realtime.ts +0 -315
  125. package/src/providers/speech-to-text/cadet-cloud.ts +0 -108
  126. package/src/providers/speech-to-text/cadet-speech-relay-connection.ts +0 -176
  127. package/src/runtime/migrations/__tests__/gcs-signed-url.test.ts +0 -254
  128. package/src/runtime/migrations/__tests__/job-registry.test.ts +0 -346
  129. package/src/runtime/migrations/__tests__/origin-mode.test.ts +0 -62
  130. package/src/runtime/migrations/__tests__/rebind-secrets-credentials.test.ts +0 -184
  131. package/src/runtime/migrations/__tests__/staged-import-path.test.ts +0 -110
  132. package/src/runtime/migrations/__tests__/v1-test-helpers.ts +0 -112
  133. package/src/runtime/migrations/__tests__/vbundle-builder-credentials.test.ts +0 -285
  134. package/src/runtime/migrations/__tests__/vbundle-builder-fd-leak.test.ts +0 -126
  135. package/src/runtime/migrations/__tests__/vbundle-builder-v1-shape.test.ts +0 -253
  136. package/src/runtime/migrations/__tests__/vbundle-import-credentials.test.ts +0 -208
  137. package/src/runtime/migrations/__tests__/vbundle-import-parity.test.ts +0 -485
  138. package/src/runtime/migrations/__tests__/vbundle-import-policy.test.ts +0 -349
  139. package/src/runtime/migrations/__tests__/vbundle-import-version-compat.test.ts +0 -196
  140. package/src/runtime/migrations/__tests__/vbundle-legacy-user-md.test.ts +0 -551
  141. package/src/runtime/migrations/__tests__/vbundle-metadata-merge-integration.test.ts +0 -428
  142. package/src/runtime/migrations/__tests__/vbundle-metadata-merge.test.ts +0 -220
  143. package/src/runtime/migrations/__tests__/vbundle-streaming-importer.test.ts +0 -1823
  144. package/src/runtime/migrations/__tests__/vbundle-streaming-validator.test.ts +0 -598
  145. package/src/runtime/migrations/__tests__/vbundle-symlink-importer.test.ts +0 -463
  146. package/src/runtime/migrations/__tests__/vbundle-symlink-streaming-importer.test.ts +0 -538
  147. package/src/runtime/migrations/__tests__/vbundle-symlink-streaming.test.ts +0 -515
  148. package/src/runtime/migrations/__tests__/vbundle-symlink-tar.test.ts +0 -453
  149. package/src/runtime/migrations/__tests__/vbundle-symlink-walker.test.ts +0 -319
  150. package/src/runtime/migrations/__tests__/vbundle-tar-stream.test.ts +0 -240
  151. package/src/runtime/migrations/__tests__/vbundle-validator-v1-schema.test.ts +0 -473
  152. package/src/runtime/migrations/gcs-signed-url.ts +0 -190
  153. package/src/runtime/migrations/job-registry.ts +0 -297
  154. package/src/runtime/migrations/migration-transport.ts +0 -612
  155. package/src/runtime/migrations/migration-wizard.ts +0 -747
  156. package/src/runtime/migrations/origin-mode.ts +0 -42
  157. package/src/runtime/migrations/rebind-secrets-screen.ts +0 -412
  158. package/src/runtime/migrations/staged-import-path.ts +0 -116
  159. package/src/runtime/migrations/transfer-progress-screen.ts +0 -323
  160. package/src/runtime/migrations/validation-results-screen.ts +0 -469
  161. package/src/runtime/migrations/vbundle-builder.ts +0 -1382
  162. package/src/runtime/migrations/vbundle-import-analyzer.ts +0 -405
  163. package/src/runtime/migrations/vbundle-import-policy.ts +0 -241
  164. package/src/runtime/migrations/vbundle-importer.ts +0 -826
  165. package/src/runtime/migrations/vbundle-metadata-merge.ts +0 -113
  166. package/src/runtime/migrations/vbundle-streaming-importer.ts +0 -2844
  167. package/src/runtime/migrations/vbundle-streaming-validator.ts +0 -426
  168. package/src/runtime/migrations/vbundle-tar-stream.ts +0 -244
  169. package/src/runtime/migrations/vbundle-validator.ts +0 -724
  170. package/src/runtime/routes/__tests__/migration-cadet-metadata-reconcile.test.ts +0 -227
  171. package/src/runtime/routes/__tests__/migration-export-secrets-redacted.test.ts +0 -54
  172. package/src/runtime/routes/__tests__/migration-import-allowed-hosts-env.test.ts +0 -70
  173. package/src/runtime/routes/__tests__/migration-import-credential-filter.test.ts +0 -257
  174. package/src/runtime/routes/background-wake-routes.ts +0 -387
  175. package/src/runtime/routes/migration-routes.ts +0 -2584
  176. package/src/tools/network/__tests__/cloud-search-proxy.test.ts +0 -282
  177. package/src/tools/network/cloud-search-proxy.ts +0 -211
  178. package/src/tts/__tests__/cadet-provider.test.ts +0 -253
  179. package/src/tts/providers/cadet-provider.ts +0 -244
  180. package/src/types/tar-stream.d.ts +0 -66
@@ -69,9 +69,9 @@ describe("SttServiceSchema", () => {
69
69
  test("language defaults to multilingual rather than staying absent", () => {
70
70
  // Every config carries a real language, so nothing downstream has to
71
71
  // infer one from an absent key. Omitting the param entirely is not a
72
- // neutral state on Deepgram and the cloud relay: it decodes as
73
- // English, which is what this default exists to stop.
74
- const parsed = SttServiceSchema.parse({ provider: "cadet" });
72
+ // neutral state on Deepgram: it decodes as English, which is what this
73
+ // default exists to stop.
74
+ const parsed = SttServiceSchema.parse({ provider: "deepgram" });
75
75
  expect(parsed.language).toBe("multi");
76
76
  });
77
77
 
@@ -86,7 +86,8 @@ describe("SttServiceSchema", () => {
86
86
 
87
87
  test("language round-trips a code and the multi code-switching mode", () => {
88
88
  expect(
89
- SttServiceSchema.parse({ provider: "cadet", language: "multi" }).language,
89
+ SttServiceSchema.parse({ provider: "deepgram", language: "multi" })
90
+ .language,
90
91
  ).toBe("multi");
91
92
  expect(
92
93
  SttServiceSchema.parse({ provider: "deepgram", language: "hi" }).language,
@@ -95,30 +96,25 @@ describe("SttServiceSchema", () => {
95
96
 
96
97
  test("language is trimmed and rejects blank strings", () => {
97
98
  expect(
98
- SttServiceSchema.parse({ provider: "cadet", language: " multi " })
99
+ SttServiceSchema.parse({ provider: "deepgram", language: " multi " })
99
100
  .language,
100
101
  ).toBe("multi");
101
102
  expect(() =>
102
- SttServiceSchema.parse({ provider: "cadet", language: " " }),
103
+ SttServiceSchema.parse({ provider: "deepgram", language: " " }),
103
104
  ).toThrow(/must not be empty/);
104
105
  });
105
106
  });
106
107
 
107
- describe("cloud provider", () => {
108
- test("accepts cadet as an ordinary provider choice", () => {
109
- const parsed = SttServiceSchema.parse({ provider: "cadet" });
110
- expect(parsed.provider).toBe("cadet");
111
- });
112
-
108
+ describe("provider parsing", () => {
113
109
  // Migration 130 folds mode into provider; a stale key must not resurrect
114
110
  // the second axis or fail the parse.
115
111
  test("ignores a legacy mode key", () => {
116
112
  const parsed = SttServiceSchema.parse({
117
113
  mode: "managed",
118
- provider: "cadet",
114
+ provider: "deepgram",
119
115
  });
120
116
  expect(parsed).toEqual({
121
- provider: "cadet",
117
+ provider: "deepgram",
122
118
  language: "multi",
123
119
  providers: {},
124
120
  roles: {},
@@ -54,9 +54,8 @@ const ALWAYS_RESOLVING_MANAGED_ONLY_PROFILE_KEYS =
54
54
  * an open string so a stored provider outside this list parses instead of
55
55
  * stripping its profile; dispatch resolves such a label as a connection
56
56
  * entry name and fails with an explainable resolution error when no row
57
- * carries it. Write-time membership is enforced at the profiles route and
58
- * the `commitConfigWrite` choke point (`unknownLlmProviderIssue`), which
59
- * is where entry names unlock when the entries model enables them.
57
+ * carries it. The generic config routes follow this open-string schema;
58
+ * dedicated profile routes apply their own provider selection rules.
60
59
  */
61
60
  export const KNOWN_LLM_PROVIDERS = [
62
61
  "anthropic",
@@ -153,8 +152,7 @@ export function isByokDefaultProviderChoice(
153
152
  * on that profile/call site deterministically — a call-site fragment naming
154
153
  * an identity without a model would inherit whatever model the winning
155
154
  * profile carries, which the identity may not serve. Enforced at parse time
156
- * (LLMSchema.superRefine), at the config write choke point
157
- * (commitConfigWrite), and by the profile write route.
155
+ * (LLMSchema.superRefine) and by the profile creation route.
158
156
  */
159
157
  export function routingIdentityModelIssue(
160
158
  provider: string,
@@ -71,12 +71,11 @@ const ImageGenerationServiceSchema = z.object({
71
71
  });
72
72
 
73
73
  /**
74
- * Web-search carries no `mode`: `provider` is the only axis. `"cadet"`
75
- * searches through the Cadet Cloud search proxy, billed to Cadet
76
- * credits; `"inference-provider-native"` prefers the inference model's own
77
- * hosted search, falling back to the user's keys and then the cloud
78
- * proxy; any other provider uses the user's own API key. A `mode` key sent
79
- * by an older client is stripped at parse.
74
+ * Web-search carries no `mode`: `provider` is the only axis.
75
+ * `"inference-provider-native"` prefers the inference model's own hosted
76
+ * search, falling back to the user's own keys; any other provider uses the
77
+ * user's own API key. A `mode` key sent by an older client is stripped at
78
+ * parse.
80
79
  */
81
80
  const WebSearchServiceSchema = z.object({
82
81
  provider: z
@@ -18,7 +18,6 @@ export const VALID_STT_PROVIDERS = [
18
18
  "google-gemini",
19
19
  "openai-whisper",
20
20
  "xai",
21
- "cadet",
22
21
  ] as const;
23
22
 
24
23
  /**
@@ -183,8 +182,7 @@ export { STT_ROLE_REQUIREMENTS, STT_ROLES, type SttRole };
183
182
  /**
184
183
  * Canonical STT service configuration.
185
184
  *
186
- * `provider` is the only axis: `"cadet"` transcribes through the cloud,
187
- * billed to Cadet credits; any other provider uses the user's own API key.
185
+ * `provider` is the only axis: every provider uses the user's own API key.
188
186
  */
189
187
  export const SttServiceSchema = z
190
188
  .object({
@@ -271,31 +271,6 @@ export const TtsXaiProviderConfigSchema = z
271
271
 
272
272
  export type TtsXaiProviderConfig = z.infer<typeof TtsXaiProviderConfigSchema>;
273
273
 
274
- /**
275
- * Cadet Cloud provider configuration under `services.tts.providers`.
276
- */
277
- const TtsCadetProviderConfigSchema = z
278
- .object({
279
- model: z
280
- .string()
281
- .optional()
282
- .describe(
283
- "Managed TTS voice model (e.g. aura-2-thalia-en). Unset means the cloud's default voice. The cloud rejects voices it does not offer.",
284
- ),
285
- languageVoices: languageVoicesSchema(
286
- "cadet",
287
- "values are managed TTS voice models (e.g. aura-2-thalia-en) and must " +
288
- "be voices offered by the cloud rate card: an unpriced model is " +
289
- "rejected by the relay (missing_price), the same contract as " +
290
- "services.tts.providers.cadet.model.",
291
- ),
292
- })
293
- .describe("Cadet Cloud provider configuration under services.tts");
294
-
295
- export type TtsCadetProviderConfig = z.infer<
296
- typeof TtsCadetProviderConfigSchema
297
- >;
298
-
299
274
  const TtsProvidersSchema = z.object({
300
275
  elevenlabs: TtsElevenLabsProviderConfigSchema.default(
301
276
  TtsElevenLabsProviderConfigSchema.parse({}),
@@ -307,9 +282,6 @@ const TtsProvidersSchema = z.object({
307
282
  TtsDeepgramProviderConfigSchema.parse({}),
308
283
  ),
309
284
  xai: TtsXaiProviderConfigSchema.default(TtsXaiProviderConfigSchema.parse({})),
310
- cadet: TtsCadetProviderConfigSchema.default(
311
- TtsCadetProviderConfigSchema.parse({}),
312
- ),
313
285
  });
314
286
  export type TtsProviders = z.infer<typeof TtsProvidersSchema>;
315
287
 
@@ -344,8 +316,7 @@ for (const id of schemaKeys) {
344
316
  /**
345
317
  * Canonical TTS service configuration.
346
318
  *
347
- * `provider` is the only axis: `"cadet"` synthesizes through the cloud,
348
- * billed to Cadet credits; any other provider uses the user's own API key.
319
+ * `provider` is the only axis: every provider uses the user's own API key.
349
320
  */
350
321
  export const TtsServiceSchema = z
351
322
  .object({
@@ -64,32 +64,13 @@ export const DB_MIGRATION_READINESS_EXEMPT_OPERATIONS: ReadonlySet<string> =
64
64
  /**
65
65
  * The migration-repair surface: operations additionally allowed while DB
66
66
  * migrations are in the terminal FAILED state — and only then, never while
67
- * they are still running. Rolling back migrations and importing a backup are
68
- * exactly the remedies for a failed migration (the upgrade CLI's
69
- * rollback/restore path), so gating them in that state would make recovery
70
- * impossible. Contains both the HTTP endpoint form and the IPC operationId
67
+ * they are still running. Rollback repairs a failed migration without racing
68
+ * an active migration runner. Contains both the HTTP endpoint form and the IPC operationId
71
69
  * form of each route. Bypasses only the migration gate — route policies
72
70
  * (gateway-principal scopes, guardian auth) still apply.
73
71
  */
74
72
  export const DB_MIGRATION_FAILED_STATE_EXEMPT_OPERATIONS: ReadonlySet<string> =
75
- new Set([
76
- "admin/rollback-migrations",
77
- "admin_rollbackmigrations_post",
78
- "migrations/import",
79
- "migrations_import_post",
80
- // Restore has three transports; all must stay repair-capable. The
81
- // preflights are read-only analysis; the GCS import is the cloud
82
- // platform's restore path and is job-based, so its job-status GET (a
83
- // parameterized route, matched by prefix in isDbMigrationGateBypassed)
84
- // must answer too.
85
- "migrations/import-preflight",
86
- "migrations_importpreflight_post",
87
- "migrations/import-from-gcs",
88
- "migrations_importfromgcs_post",
89
- "migrations/preflight-from-gcs",
90
- "migrations_preflightfromgcs_post",
91
- "migrations_jobs_by_job_id_get",
92
- ]);
73
+ new Set(["admin/rollback-migrations", "admin_rollbackmigrations_post"]);
93
74
 
94
75
  /**
95
76
  * Whether an operation may proceed despite unready DB migrations: always for
@@ -103,13 +84,7 @@ export function isDbMigrationGateBypassed(operation: string): boolean {
103
84
  if (dbMigrationReadiness.state !== "failed") {
104
85
  return false;
105
86
  }
106
- // The HTTP gate passes the raw path after /v1/, so the parameterized
107
- // job-status route (migrations/jobs/:job_id) is matched by prefix; the
108
- // IPC form is the exact operationId in the set above.
109
- return (
110
- DB_MIGRATION_FAILED_STATE_EXEMPT_OPERATIONS.has(operation) ||
111
- operation.startsWith("migrations/jobs/")
112
- );
87
+ return DB_MIGRATION_FAILED_STATE_EXEMPT_OPERATIONS.has(operation);
113
88
  }
114
89
 
115
90
  export function setDbReady(v: boolean): void {
@@ -49,7 +49,6 @@ import {
49
49
  startRuntimeHttpServerBackgroundSweeps,
50
50
  } from "../runtime/http-server.js";
51
51
  import { warmLocalGuardianPrincipalCache } from "../runtime/local-actor-identity.js";
52
- import { recoverInterruptedImport } from "../runtime/migrations/vbundle-streaming-importer.js";
53
52
  import { markCurrentProcessAsMainDaemon } from "../runtime/process-role.js";
54
53
  import { publishConfigChanged } from "../runtime/sync/resource-sync-events.js";
55
54
  import { reconcilePluginSchedules } from "../schedule/plugin-schedule-reconciler.js";
@@ -148,36 +147,6 @@ export async function runDaemon(): Promise<void> {
148
147
  // after it.
149
148
  recordDaemonBootTime(startupStartedAt);
150
149
 
151
- // Recover from any streaming `.vbundle` import that was interrupted by a
152
- // crash or SIGKILL. If the previous process died between
153
- // `carryOverPreservedPaths` and the atomic workspace swap, the live
154
- // workspace may be missing `data/db` / `data/qdrant` / etc. The marker
155
- // at `<workspaceDir>.import-marker.json` (persisted before any rename
156
- // runs) tells us where the orphaned preserved paths landed; the
157
- // recovery helper moves them back into the live workspace and cleans
158
- // up the temp tree. Running this BEFORE `initializeDb()` ensures the
159
- // DB singleton opens against the fully-restored `assistant.db`.
160
- try {
161
- const recoveryResult = await recoverInterruptedImport(getWorkspaceDir());
162
- if (!recoveryResult.ok) {
163
- // Rollback is intentionally unresolved — backup/temp/marker are
164
- // preserved on disk so an operator (or a later retry) can finish
165
- // the recovery. Log loudly so ops sees it, but don't block start-up:
166
- // the daemon still needs to come up for diagnostics. The next
167
- // `streamCommitImport` will refuse to start a new import until the
168
- // marker is resolved.
169
- log.error(
170
- { failedCount: recoveryResult.failedCount },
171
- "Interrupted-import recovery is INCOMPLETE; leftover .pre-import-* / .import-* scratch dirs remain in the workspace. Manual intervention may be required before the next import can run.",
172
- );
173
- }
174
- } catch (err) {
175
- log.warn(
176
- { err },
177
- "recoverInterruptedImport threw during daemon startup; continuing",
178
- );
179
- }
180
-
181
150
  // Load (or generate + persist) the auth signing key so tokens survive
182
151
  // daemon restarts.
183
152
  const signingKey = resolveSigningKey();
@@ -1,5 +1,4 @@
1
1
  import { ensureCloudIdentityIds } from "../config/cloud-identity.js";
2
- import { maybeDefaultSpeechToCloud } from "../config/cloud-speech-defaults.js";
3
2
  import type { AssistantConfig } from "../config/types.js";
4
3
  import { getMcpServerManager } from "../mcp/manager.js";
5
4
  import { startConfiguredMcpServers } from "../mcp/startup.js";
@@ -34,13 +33,6 @@ export async function initializeProvidersAndTools(
34
33
  // overrides are normally only set by the secret-routes handlers at runtime.
35
34
  await ensureCloudIdentityIds();
36
35
 
37
- // Speech defaulting normally fires when the cloud credentials land
38
- // (secret-routes); evaluating it once per boot also covers assistants whose
39
- // connection predates that trigger, so voice works for every connected
40
- // assistant with no configured speech credentials. Idempotent, and detached
41
- // per the startup philosophy — must not block boot.
42
- void maybeDefaultSpeechToCloud();
43
-
44
36
  await initializeProviders(config);
45
37
  // initializeTools() also loads workspace tool overrides from
46
38
  // `<workspaceDir>/tools/` once core tools have settled, so they own
@@ -58,7 +58,6 @@ mock.module("../../prompts/persona-resolver.js", () => ({
58
58
  resolveGuardianPersona: () => null,
59
59
  resolveGuardianPersonaPath: () => null,
60
60
  resolveGuardianPersonaStrict: () => null,
61
- isGuardianPersonaCustomized: () => false,
62
61
  resolveUserSlug: () => null,
63
62
  resolveUserPersona: () => null,
64
63
  resolveChannelPersona: () => null,
@@ -124,16 +124,6 @@ function recordReengagementTimestamp(): void {
124
124
  }
125
125
  }
126
126
 
127
- function refreshBackgroundWakeIntentSoon(reason: string): void {
128
- void import("../background-wake/publisher.js")
129
- .then(({ refreshBackgroundWakeIntent }) =>
130
- refreshBackgroundWakeIntent(reason),
131
- )
132
- .catch((err) =>
133
- log.warn({ err, reason }, "Failed to queue background wake refresh"),
134
- );
135
- }
136
-
137
127
  export interface HeartbeatDeps {
138
128
  /** Override for current hour (0-23), for testing. Used when no timezone is resolved. */
139
129
  getCurrentHour?: () => number;
@@ -141,19 +131,6 @@ export interface HeartbeatDeps {
141
131
  now?: () => Date;
142
132
  }
143
133
 
144
- export interface ManagedWakeHeartbeatRunOptions {
145
- now?: number;
146
- toleranceMs?: number;
147
- assumeDue?: boolean;
148
- scheduledFor?: number;
149
- }
150
-
151
- export interface ManagedWakeHeartbeatRunResult {
152
- due: boolean;
153
- completed: number;
154
- skipped: number;
155
- }
156
-
157
134
  export class HeartbeatService {
158
135
  private static instance?: HeartbeatService;
159
136
 
@@ -236,47 +213,12 @@ export class HeartbeatService {
236
213
  return countCompletedRunsToday() >= config.maxDailyRuns;
237
214
  }
238
215
 
239
- async runCloudWakeIfDue(
240
- options: ManagedWakeHeartbeatRunOptions = {},
241
- ): Promise<ManagedWakeHeartbeatRunResult> {
242
- const now = options.now ?? Date.now();
243
- const toleranceMs = options.toleranceMs ?? 0;
244
- const dueByLocalTimer =
245
- this._nextRunAt != null && this._nextRunAt <= now + toleranceMs;
246
-
247
- if (!dueByLocalTimer && options.assumeDue !== true) {
248
- return { due: false, completed: 0, skipped: 0 };
249
- }
250
-
251
- if (!dueByLocalTimer) {
252
- if (this._pendingRunId) {
253
- supersedePendingRun(this._pendingRunId);
254
- this._pendingRunId = null;
255
- }
256
- this._nextRunAt = options.scheduledFor ?? now;
257
- this._pendingRunId = insertPendingHeartbeatRun(this._nextRunAt);
258
- }
259
-
260
- const completed = await this.runOnce({ force: false });
261
-
262
- if (this.cronMode && !this.stopped) {
263
- this.scheduleNextCronRun(getConfig().heartbeat);
264
- }
265
-
266
- return {
267
- due: true,
268
- completed: completed ? 1 : 0,
269
- skipped: completed ? 0 : 1,
270
- };
271
- }
272
-
273
216
  start(): void {
274
217
  this.stopped = false;
275
218
  const config = getConfig().heartbeat;
276
219
  if (!config.enabled) {
277
220
  log.info("Heartbeat disabled by config");
278
221
  this._nextRunAt = null;
279
- refreshBackgroundWakeIntentSoon("heartbeat-disabled");
280
222
  return;
281
223
  }
282
224
  if (this.timer) {
@@ -405,7 +347,6 @@ export class HeartbeatService {
405
347
  { nextRunAt: new Date(nextRunAt).toISOString(), delayMs },
406
348
  "Heartbeat cron run scheduled",
407
349
  );
408
- refreshBackgroundWakeIntentSoon("heartbeat-cron-scheduled");
409
350
  } catch (err) {
410
351
  log.warn(
411
352
  { err },
@@ -432,7 +373,6 @@ export class HeartbeatService {
432
373
  this._nextRunAt = null;
433
374
  this.cronMode = false;
434
375
  this.start();
435
- refreshBackgroundWakeIntentSoon("heartbeat-reconfigured");
436
376
  }
437
377
 
438
378
  /**
@@ -449,7 +389,6 @@ export class HeartbeatService {
449
389
  supersedePendingRun(this._pendingRunId);
450
390
  this._pendingRunId = null;
451
391
  }
452
- refreshBackgroundWakeIntentSoon("heartbeat-counter-reset");
453
392
  if (!this.timer) {
454
393
  return;
455
394
  }
@@ -519,7 +458,6 @@ export class HeartbeatService {
519
458
  if (runId) {
520
459
  skipHeartbeatRun(runId, "disabled");
521
460
  }
522
- refreshBackgroundWakeIntentSoon("heartbeat-disabled");
523
461
  return false;
524
462
  }
525
463
 
@@ -680,7 +618,6 @@ export class HeartbeatService {
680
618
  if (!this.cronMode) {
681
619
  this.scheduleNextRun(getConfig().heartbeat.intervalMs);
682
620
  }
683
- refreshBackgroundWakeIntentSoon("heartbeat-run-complete");
684
621
  }
685
622
  return true;
686
623
  }
@@ -691,7 +628,6 @@ export class HeartbeatService {
691
628
  }
692
629
  this._nextRunAt = Date.now() + intervalMs;
693
630
  this._pendingRunId = insertPendingHeartbeatRun(this._nextRunAt);
694
- refreshBackgroundWakeIntentSoon("heartbeat-interval-scheduled");
695
631
  }
696
632
 
697
633
  /**
@@ -964,8 +900,7 @@ This is one of your first heartbeats. Your user hasn't heard from you yet and ma
964
900
  }
965
901
 
966
902
  /**
967
- * Construct and start the heartbeat service singleton, returning it so callers
968
- * can wire it into the background-wake runtime. start() self-gates on
903
+ * Construct and start the heartbeat service singleton. start() self-gates on
969
904
  * `heartbeat.enabled` and logs its own status.
970
905
  */
971
906
  export function startHeartbeatService(): HeartbeatService {
@@ -97,23 +97,15 @@ describe("AssistantIpcServer DB migration readiness gate", () => {
97
97
  });
98
98
 
99
99
  test("migration-repair surface is allowed only in the failed state", () => {
100
- // Rollback/import are the remedies for failed migrations — gating them in
100
+ // Rollback is the remedy for failed migrations — gating them in
101
101
  // that state would make recovery impossible (the upgrade CLI's
102
102
  // rollback/restore path). While migrations are merely RUNNING they stay
103
103
  // gated: a rollback would race the in-flight migration runner.
104
104
  setDbMigrating();
105
105
  expect(gate("admin_rollbackmigrations_post")?.statusCode).toBe(503);
106
- expect(gate("migrations_import_post")?.statusCode).toBe(503);
107
106
 
108
107
  setDbMigrationFailed(new Error("boom"));
109
108
  expect(gate("admin_rollbackmigrations_post")).toBeNull();
110
- expect(gate("migrations_import_post")).toBeNull();
111
- // All restore transports are repair-capable: preflights, the cloud
112
- // platform's GCS path, and its job-status polling.
113
- expect(gate("migrations_importpreflight_post")).toBeNull();
114
- expect(gate("migrations_importfromgcs_post")).toBeNull();
115
- expect(gate("migrations_preflightfromgcs_post")).toBeNull();
116
- expect(gate("migrations_jobs_by_job_id_get")).toBeNull();
117
109
  // Everything else stays gated in the failed state.
118
110
  expect(gate("db_proxy")?.statusCode).toBe(503);
119
111
  });
@@ -40,10 +40,6 @@ const realSttResolveModule = {
40
40
  const realSecureKeysModule = {
41
41
  ...(await import("../../security/secure-keys.js")),
42
42
  };
43
- const realCloudSpeechModule = {
44
- ...(await import("../../cloud/cloud-speech.js")),
45
- };
46
-
47
43
  // -- Mutable stub state --------------------------------------------------------
48
44
 
49
45
  import type { StreamingTranscriber } from "../../stt/types.js";
@@ -74,16 +70,6 @@ mock.module("../../security/secure-keys.js", () => ({
74
70
  : realSecureKeysModule.getSecureKeyAsync(account),
75
71
  }));
76
72
 
77
- let managedAvailable = false;
78
-
79
- mock.module("../../cloud/cloud-speech.js", () => ({
80
- ...realCloudSpeechModule,
81
- managedSpeechAvailable: async () =>
82
- preflightMocksActive
83
- ? managedAvailable
84
- : realCloudSpeechModule.managedSpeechAvailable(),
85
- }));
86
-
87
73
  import { setConfig } from "../../__tests__/helpers/set-config.js";
88
74
  import { getConfig } from "../../config/loader.js";
89
75
  import {
@@ -135,7 +121,6 @@ beforeEach(() => {
135
121
  sttProvider = "deepgram";
136
122
  ttsProvider = "fish-audio";
137
123
  ttsProviders = { "fish-audio": { referenceId: "ref-123" } };
138
- managedAvailable = false;
139
124
  });
140
125
 
141
126
  function expectNotReady(
@@ -284,32 +269,3 @@ describe("resolveLiveVoiceCredentialReadiness", () => {
284
269
  expect(readiness.userMessage.endsWith(".")).toBe(true);
285
270
  });
286
271
  });
287
-
288
- describe("resolveLiveVoiceCredentialReadiness — managed (cadet) TTS", () => {
289
- test("cadet TTS with a full platform connection → ready", async () => {
290
- ttsProvider = "cadet";
291
- ttsProviders = {};
292
- managedAvailable = true;
293
-
294
- const readiness = await runReadiness();
295
- expect(readiness).toEqual({ status: "ready" });
296
- });
297
-
298
- test("cadet TTS without a cloud connection → connection copy, not API-key copy", async () => {
299
- ttsProvider = "cadet";
300
- ttsProviders = {};
301
- managedAvailable = false;
302
-
303
- const readiness = expectNotReady(await runReadiness());
304
- expect(readiness.missing).toEqual([
305
- {
306
- kind: "tts",
307
- providerId: "cadet",
308
- reason:
309
- 'TTS provider "cadet" needs a Cadet Cloud connection for cloud speech',
310
- },
311
- ]);
312
- expect(readiness.userMessage).toContain("assistant cloud connect");
313
- expect(readiness.userMessage).not.toContain("API key");
314
- });
315
- });
@@ -1170,8 +1170,6 @@ describe("LiveVoiceSession Flux end-of-turn", () => {
1170
1170
  test.each([
1171
1171
  { providerId: "deepgram-flux" as const, flagOn: true },
1172
1172
  { providerId: "deepgram-flux" as const, flagOn: false },
1173
- { providerId: "cadet-flux" as const, flagOn: true },
1174
- { providerId: "cadet-flux" as const, flagOn: false },
1175
1173
  ])(
1176
1174
  "only provider speech starts interrupt playback: %j",
1177
1175
  async ({ providerId, flagOn }) => {
@@ -1518,7 +1516,7 @@ describe("LiveVoiceSession Flux end-of-turn during the STT dial", () => {
1518
1516
  async (flagOn) => {
1519
1517
  const gate = createDialGate();
1520
1518
  const { frames, session } = createHarness({
1521
- providerId: "cadet",
1519
+ providerId: "deepgram",
1522
1520
  fluxConfig: flagOn ? FLUX_ON : FLUX_OFF,
1523
1521
  silenceThresholdMs: 10_000,
1524
1522
  resolveGate: gate.promise,
@@ -1539,9 +1537,9 @@ describe("LiveVoiceSession Flux end-of-turn during the STT dial", () => {
1539
1537
  );
1540
1538
 
1541
1539
  test.each([
1542
- { providerId: "cadet" as const, audio: LOUD_CHUNK, interrupts: false },
1540
+ { providerId: "deepgram" as const, audio: LOUD_CHUNK, interrupts: false },
1543
1541
  {
1544
- providerId: "cadet" as const,
1542
+ providerId: "deepgram" as const,
1545
1543
  audio: SUSTAINED_LOUD_CHUNK,
1546
1544
  interrupts: true,
1547
1545
  },
@@ -1616,7 +1614,7 @@ describe("LiveVoiceSession Flux end-of-turn during the STT dial", () => {
1616
1614
  // The first input is released but cannot dispatch until its final arrives.
1617
1615
  await session.handleBinaryAudio(SUSTAINED_LOUD_CHUNK);
1618
1616
  await sleep(PAST_SILENCE_BOUNDARY_MS);
1619
- options.providerId = "cadet";
1617
+ options.providerId = "deepgram";
1620
1618
  first.flushStopEvents();
1621
1619
  await waitFor(() => countFrames(frames, "thinking") === 1);
1622
1620
  expect(countFrames(frames, "turn_cancelled")).toBe(0);
@@ -1609,7 +1609,7 @@ describe("LiveVoiceSession STT", () => {
1609
1609
  },
1610
1610
  },
1611
1611
  });
1612
- const transcriber = new MockStreamingTranscriber("cadet");
1612
+ const transcriber = new MockStreamingTranscriber("deepgram");
1613
1613
  const startVoiceTurn = speakingVoiceTurnStarter();
1614
1614
  const { streamTtsAudio, ttsCalls } = recordingTtsStreamer();
1615
1615
  const { context } = createContext();
@@ -11,24 +11,22 @@
11
11
  * Mirrors `calls/telephony-credential-preflight.ts` for the phone-call
12
12
  * transport.
13
13
  *
14
- * Both legs are checked against the effective providers
15
- * (`resolveEffectiveSpeechProviders`), which is what the transcriber and
16
- * synthesis paths resolve too — so a `ready` verdict earned on managed
17
- * speech is a verdict the runtime can honour.
14
+ * Both legs are checked against the providers the transcriber and synthesis
15
+ * paths resolve, so a `ready` verdict is one the runtime can honour.
18
16
  */
19
17
 
20
18
  import {
21
19
  fishAudioReferenceIdConfigured,
22
20
  ttsSecretResolves,
23
21
  } from "../calls/telephony-tts-capability.js";
24
- import { managedSpeechAvailable } from "../cloud/cloud-speech.js";
25
- import { resolveEffectiveSpeechProviders } from "../config/cloud-speech-defaults.js";
22
+ import { getConfig } from "../config/loader.js";
26
23
  import { getProviderEntry } from "../providers/speech-to-text/provider-catalog.js";
27
24
  import {
28
25
  resolveStreamingTranscriber,
29
26
  sttCredentialGapReason,
30
27
  sttProviderKeyResolves,
31
28
  } from "../providers/speech-to-text/resolve.js";
29
+ import { sttCatalogKeyForRole } from "../stt/roles.js";
32
30
  import type { SttProviderId } from "../stt/types.js";
33
31
  import type { TtsProviderCatalogEntry } from "../tts/provider-catalog.js";
34
32
  import { getCatalogProvider, getTtsProvider } from "../tts/provider-catalog.js";
@@ -78,13 +76,12 @@ export type LiveVoiceCredentialReadiness =
78
76
  export async function resolveLiveVoiceCredentialReadiness(): Promise<LiveVoiceCredentialReadiness> {
79
77
  // Readiness must ask about the same provider the session will dial, so it
80
78
  // reads the live-voice role rather than the global setting.
81
- const effective = await resolveEffectiveSpeechProviders(undefined, {
82
- role: "liveVoice",
83
- });
79
+ const config = getConfig();
80
+ const effectiveStt = sttCatalogKeyForRole(config.services.stt, "liveVoice");
84
81
  const gaps = (
85
82
  await Promise.all([
86
- resolveSttGap(effective.stt),
87
- resolveTtsGap(effective.tts),
83
+ resolveSttGap(effectiveStt),
84
+ resolveTtsGap(config.services.tts.provider),
88
85
  ])
89
86
  ).filter((gap) => gap !== null);
90
87
 
@@ -142,10 +139,7 @@ async function resolveSttGap(
142
139
  providerId: entry.id,
143
140
  reason: sttCredentialGapReason(entry.credentialProvider),
144
141
  },
145
- clause:
146
- entry.credentialProvider === "cadet"
147
- ? `a Cadet Cloud connection for cloud speech (run 'assistant cloud connect')`
148
- : `an API key for the speech-to-text provider "${entry.id}"`,
142
+ clause: `an API key for the speech-to-text provider "${entry.id}"`,
149
143
  };
150
144
  }
151
145
 
@@ -197,24 +191,6 @@ async function resolveTtsGap(
197
191
  };
198
192
  }
199
193
 
200
- // Cloud speech authenticates via the cloud connection — full
201
- // availability (API key + assistant ID) is the credential, so the
202
- // stored-secret loop below would pass half-connected states that
203
- // synthesis rejects.
204
- if (entry.id === "cadet") {
205
- if (!(await managedSpeechAvailable())) {
206
- return {
207
- gap: {
208
- kind: "tts",
209
- providerId: entry.id,
210
- reason: `TTS provider "${entry.id}" needs a Cadet Cloud connection for cloud speech`,
211
- },
212
- clause: `a Cadet Cloud connection for cloud speech (run 'assistant cloud connect')`,
213
- };
214
- }
215
- return null;
216
- }
217
-
218
194
  for (const secret of entry.secretRequirements) {
219
195
  if (!(await ttsSecretResolves(secret.credentialStoreKey))) {
220
196
  return {