@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
@@ -8262,14 +8262,18 @@ export async function defaultSpawnBackgroundContinuation(args: {
8262
8262
  async function defaultResolveStreamingTranscriber(
8263
8263
  options: ResolveStreamingTranscriberOptions,
8264
8264
  ): Promise<StreamingTranscriber | null> {
8265
- const { resolveEffectiveSpeechProviders } =
8266
- await import("../config/cloud-speech-defaults.js");
8267
8265
  const { resolveStreamingTranscriber } =
8268
8266
  await import("../providers/speech-to-text/resolve.js");
8269
- const { stt } = await resolveEffectiveSpeechProviders(undefined, {
8270
- role: "liveVoice",
8271
- });
8272
- return resolveStreamingTranscriber({ ...options, providerId: stt });
8267
+ const { sttCatalogKeyForRole } = await import("../stt/roles.js");
8268
+ const { getConfig } = await import("../config/loader.js");
8269
+ // The live-voice role's configured provider is the one that gets dialed —
8270
+ // the session resolves it here (rather than trusting a caller's override)
8271
+ // so readiness and transcription agree.
8272
+ const providerId = sttCatalogKeyForRole(
8273
+ getConfig().services.stt,
8274
+ "liveVoice",
8275
+ );
8276
+ return resolveStreamingTranscriber({ ...options, providerId });
8273
8277
  }
8274
8278
 
8275
8279
  async function defaultResolveLiveVoiceCredentialReadiness(): Promise<LiveVoiceCredentialReadiness> {
@@ -220,14 +220,7 @@ async function resolveLiveVoiceStreamingTtsProvider(
220
220
  configOverride?: LiveVoiceTtsConfig,
221
221
  ): Promise<ResolvedStreamingTtsProvider> {
222
222
  const config = configOverride ?? (await loadAssistantConfig());
223
- const { resolveEffectiveSpeechProviders } =
224
- await import("../config/cloud-speech-defaults.js");
225
- const { tts: effectiveProviderId } =
226
- await resolveEffectiveSpeechProviders(config);
227
- const { provider: providerId, providerConfig } = resolveTtsConfig(
228
- config,
229
- effectiveProviderId,
230
- );
223
+ const { provider: providerId, providerConfig } = resolveTtsConfig(config);
231
224
 
232
225
  let provider: TtsProvider;
233
226
  try {
@@ -60,9 +60,9 @@ async function main(): Promise<void> {
60
60
  // standalone process must do it itself so getCloudBaseUrl() resolves to
61
61
  // the persisted platform environment instead of the CADET_ENVIRONMENT
62
62
  // default. Retrospective and consolidation passes wake real agent
63
- // conversations whose inference and background-wake requests go through the
64
- // cloud proxy — without rehydration those requests hit the wrong platform
65
- // and are rejected.
63
+ // conversations whose inference requests go through the cloud proxy —
64
+ // without rehydration those requests hit the wrong platform and are
65
+ // rejected.
66
66
  await ensureCloudIdentityIds();
67
67
 
68
68
  // Jobs in this process wake real agent conversations, so it registers the
@@ -385,41 +385,6 @@ export function ensureGuardianPersonaFile(userFile: string): void {
385
385
  log.debug({ path: filePath }, "Wrote guardian persona scaffold");
386
386
  }
387
387
 
388
- /**
389
- * Return `true` when the persona file at `filePath` has been edited by
390
- * the user (its stripped content differs from the bare scaffold
391
- * template). Returns `false` when the file is missing, unreadable,
392
- * empty after stripping, or byte-identical to the template after
393
- * stripping comment lines.
394
- *
395
- * Used by the vbundle importer to decide whether a legacy
396
- * `prompts/USER.md` entry may safely overwrite `users/<slug>.md`.
397
- */
398
- export function isGuardianPersonaCustomized(filePath: string): boolean {
399
- if (!existsSync(filePath)) {
400
- return false;
401
- }
402
-
403
- let content: string;
404
- try {
405
- content = readFileSync(filePath, "utf-8");
406
- } catch (err) {
407
- log.warn(
408
- { err, path: filePath },
409
- "Failed to read persona file while checking customization",
410
- );
411
- return false;
412
- }
413
-
414
- const stripped = stripCommentLines(content);
415
- if (stripped.length === 0) {
416
- return false;
417
- }
418
-
419
- const templateStripped = stripCommentLines(GUARDIAN_PERSONA_TEMPLATE);
420
- return stripped !== templateStripped;
421
- }
422
-
423
388
  // ── Onboarding section writer ────────────────────────────────────
424
389
 
425
390
  const ONBOARDING_HEADING = "## Onboarding Context";
@@ -38,7 +38,9 @@ describe("search-provider-catalog", () => {
38
38
  });
39
39
 
40
40
  test("cloud providers omit BYOK-only fields", () => {
41
- const managed = SEARCH_PROVIDER_CATALOG.filter((p) => p.kind === "managed");
41
+ const managed = SEARCH_PROVIDER_CATALOG.filter(
42
+ (p) => p.secretKey === undefined,
43
+ );
42
44
  for (const provider of managed) {
43
45
  expect(provider.envVar).toBeUndefined();
44
46
  expect(provider.secretKey).toBeUndefined();
@@ -75,9 +77,8 @@ describe("search-provider-catalog", () => {
75
77
  expect(SEARCH_PROVIDER_FALLBACK_ORDER).toEqual(sorted);
76
78
  });
77
79
 
78
- test("cadet is a cloud provider outside the BYOK fallback chain", () => {
79
- expect(getSearchProvider("cadet")?.kind).toBe("managed");
80
- expect(BYOK_SEARCH_PROVIDERS.map((p) => p.id)).not.toContain("cadet");
80
+ test("the retired cadet cloud search provider is no longer in the catalog", () => {
81
+ expect(getSearchProvider("cadet")).toBeUndefined();
81
82
  expect(SEARCH_PROVIDER_FALLBACK_ORDER).not.toContain("cadet");
82
83
  });
83
84
 
@@ -89,7 +90,6 @@ describe("search-provider-catalog", () => {
89
90
 
90
91
  test("SearXNG is a keyless BYOK provider that requires an instance URL", () => {
91
92
  const searxng = getSearchProvider("searxng");
92
- expect(searxng?.kind).toBe("byok");
93
93
  expect(searxng?.keyless).toBe(true);
94
94
  expect(searxng?.supportsApiBase).toBe(true);
95
95
  expect(searxng?.defaultApiBase).toBeUndefined();
@@ -98,7 +98,6 @@ describe("search-provider-catalog", () => {
98
98
 
99
99
  test("TinyFish is a keyed BYOK provider with a cloud API base", () => {
100
100
  const tinyfish = getSearchProvider("tinyfish");
101
- expect(tinyfish?.kind).toBe("byok");
102
101
  expect(tinyfish?.keyless).toBeUndefined();
103
102
  expect(tinyfish?.supportsApiBase).toBe(true);
104
103
  expect(tinyfish?.defaultApiBase).toBe("https://api.search.tinyfish.ai");
@@ -107,7 +106,6 @@ describe("search-provider-catalog", () => {
107
106
 
108
107
  test("Exa is a keyed BYOK provider without a custom API base", () => {
109
108
  const exa = getSearchProvider("exa");
110
- expect(exa?.kind).toBe("byok");
111
109
  expect(exa?.keyless).toBeUndefined();
112
110
  expect(exa?.supportsApiBase).toBeUndefined();
113
111
  expect(exa?.envVar).toBe("EXA_API_KEY");
@@ -115,7 +113,6 @@ describe("search-provider-catalog", () => {
115
113
 
116
114
  test("Serply is a keyed BYOK provider without a custom API base", () => {
117
115
  const serply = getSearchProvider("serply");
118
- expect(serply?.kind).toBe("byok");
119
116
  expect(serply?.keyless).toBeUndefined();
120
117
  expect(serply?.supportsApiBase).toBeUndefined();
121
118
  expect(serply?.envVar).toBe("SERPLY_API_KEY");
@@ -33,10 +33,8 @@ describe("describeSttFailure", () => {
33
33
  test("timeout uses provider-agnostic copy", () => {
34
34
  const copy = describeSttFailure(
35
35
  new SttError("timeout", "The operation was aborted"),
36
- "cadet",
36
+ "deepgram",
37
37
  );
38
- // A managed timeout (AbortError) carries no marker, so it still gets the
39
- // friendly copy rather than the raw abort string.
40
38
  expect(copy).toBe("Transcription timed out.");
41
39
  });
42
40
 
@@ -50,27 +48,28 @@ describe("describeSttFailure", () => {
50
48
  });
51
49
  });
52
50
 
53
- describe("cloud speech (userFacing marker)", () => {
51
+ describe("userFacing marker passthrough", () => {
54
52
  test("auth failure surfaces the reconnect remediation verbatim", () => {
55
53
  const message =
56
54
  "Cloud speech needs a working Cadet Cloud connection — reconnect with 'assistant cloud connect'.";
57
55
  const copy = describeSttFailure(
58
56
  new SttError("auth", message, { userFacing: true }),
59
- "cadet",
57
+ "deepgram",
60
58
  );
61
- // The BYOK "check your API key in Settings → Voice" rewrite must not
62
- // clobber managed remediation — managed users hold no speech key.
59
+ // The userFacing marker means upstream already produced provider-
60
+ // appropriate copy — the BYOK "check your API key in Settings →
61
+ // Voice" rewrite must not clobber it.
63
62
  expect(copy).toBe(message);
64
63
  expect(copy).not.toContain("API key");
65
64
  expect(copy).not.toContain("Settings → Voice");
66
65
  });
67
66
 
68
- test("credits-exhausted message survives the provider-error branch", () => {
67
+ test("a provider-error message with the marker survives verbatim", () => {
69
68
  const message =
70
- "Cadet credits are exhausted — add funds to your Cadet account to continue using managed transcription.";
69
+ "Upstream transcription is temporarily unavailable — try again shortly.";
71
70
  const copy = describeSttFailure(
72
71
  new SttError("provider-error", message, { userFacing: true }),
73
- "cadet",
72
+ "deepgram",
74
73
  );
75
74
  expect(copy).toBe(message);
76
75
  expect(copy).not.toContain("returned an error while transcribing");
@@ -27,11 +27,10 @@
27
27
  * The split between adapter (which carries the executor) and catalog (which
28
28
  * carries metadata) keeps the catalog purely declarative — adding an entry
29
29
  * never forces a code rebuild downstream and the JSON projection stays
30
- * trivial.
30
+ * trivial. BYOK-ness is expressed by the presence of key fields (secretKey /
31
+ * envVar / apiKeyPrefix).
31
32
  */
32
33
 
33
- export type SearchProviderKind = "managed" | "byok";
34
-
35
34
  export interface SearchProviderCatalogEntry {
36
35
  /** Stable provider identifier. Matches config + secret-catalog values. */
37
36
  readonly id: string;
@@ -42,26 +41,14 @@ export interface SearchProviderCatalogEntry {
42
41
  * privacy notices). Defaults to {@link displayName} when omitted.
43
42
  */
44
43
  readonly displayNameLong?: string;
45
- /**
46
- * Authentication style for the search provider choice.
47
- *
48
- * `managed` means the choice does not require a user-supplied search API key.
49
- * `cadet` searches through the Cadet Cloud search proxy, billed to
50
- * Cadet credits; the cloud connection is the credential. For
51
- * `inference-provider-native`, the daemon uses the inference API's native
52
- * hosted web-search tool only when the selected inference provider/model
53
- * supports it; otherwise the app-executed `web_search` tool runs, falling
54
- * back to the cloud search proxy only when no user search key is
55
- * configured.
56
- *
57
- * `byok` providers require a user-supplied API key.
58
- */
59
- readonly kind: SearchProviderKind;
60
44
  /**
61
45
  * BYOK provider that also works without a user-supplied key (keyless by
62
46
  * default; a key is optional and only lifts rate limits). The daemon adapter
63
47
  * runs it even when no key is stored, and the missing-key fallback/error path
64
- * does not treat it as fatal.
48
+ * does not treat it as fatal. The one managed-shaped entry
49
+ * (`inference-provider-native`) routes to the inference provider's own
50
+ * hosted web-search tool when the model supports one, and never carries
51
+ * key fields.
65
52
  */
66
53
  readonly keyless?: boolean;
67
54
  /** Placeholder shown in the API-key input. BYOK providers only. */
@@ -87,23 +74,13 @@ export interface SearchProviderCatalogEntry {
87
74
  }
88
75
 
89
76
  export const SEARCH_PROVIDER_CATALOG: readonly SearchProviderCatalogEntry[] = [
90
- // cadet leads: it is the cloud option, selected like any other provider.
91
- // Legacy configs carrying the pre-rebrand id `cadet` normalize on parse.
92
- {
93
- id: "cadet",
94
- displayName: "Cadet",
95
- displayNameLong: "Cadet Managed Search",
96
- kind: "managed",
97
- },
98
77
  {
99
78
  id: "inference-provider-native",
100
79
  displayName: "Provider Native",
101
- kind: "managed",
102
80
  },
103
81
  {
104
82
  id: "perplexity",
105
83
  displayName: "Perplexity",
106
- kind: "byok",
107
84
  apiKeyPrefix: "pplx-...",
108
85
  envVar: "PERPLEXITY_API_KEY",
109
86
  secretKey: "perplexity",
@@ -114,7 +91,6 @@ export const SEARCH_PROVIDER_CATALOG: readonly SearchProviderCatalogEntry[] = [
114
91
  id: "brave",
115
92
  displayName: "Brave",
116
93
  displayNameLong: "Brave Search",
117
- kind: "byok",
118
94
  apiKeyPrefix: "BSA...",
119
95
  envVar: "BRAVE_API_KEY",
120
96
  secretKey: "brave",
@@ -124,7 +100,6 @@ export const SEARCH_PROVIDER_CATALOG: readonly SearchProviderCatalogEntry[] = [
124
100
  {
125
101
  id: "tavily",
126
102
  displayName: "Tavily",
127
- kind: "byok",
128
103
  apiKeyPrefix: "tvly-...",
129
104
  envVar: "TAVILY_API_KEY",
130
105
  secretKey: "tavily",
@@ -134,7 +109,6 @@ export const SEARCH_PROVIDER_CATALOG: readonly SearchProviderCatalogEntry[] = [
134
109
  {
135
110
  id: "firecrawl",
136
111
  displayName: "Firecrawl",
137
- kind: "byok",
138
112
  apiKeyPrefix: "fc-...",
139
113
  envVar: "FIRECRAWL_API_KEY",
140
114
  secretKey: "firecrawl",
@@ -144,7 +118,6 @@ export const SEARCH_PROVIDER_CATALOG: readonly SearchProviderCatalogEntry[] = [
144
118
  {
145
119
  id: "keenable",
146
120
  displayName: "Keenable",
147
- kind: "byok",
148
121
  keyless: true,
149
122
  apiKeyPrefix: "keen_... (optional)",
150
123
  envVar: "KEENABLE_API_KEY",
@@ -155,7 +128,6 @@ export const SEARCH_PROVIDER_CATALOG: readonly SearchProviderCatalogEntry[] = [
155
128
  {
156
129
  id: "fastcrw",
157
130
  displayName: "fastCRW",
158
- kind: "byok",
159
131
  apiKeyPrefix: "crw_live_...",
160
132
  envVar: "FASTCRW_API_KEY",
161
133
  secretKey: "fastcrw",
@@ -167,7 +139,6 @@ export const SEARCH_PROVIDER_CATALOG: readonly SearchProviderCatalogEntry[] = [
167
139
  {
168
140
  id: "searxng",
169
141
  displayName: "SearXNG",
170
- kind: "byok",
171
142
  keyless: true,
172
143
  apiKeyPrefix: "token (optional)",
173
144
  envVar: "SEARXNG_API_KEY",
@@ -179,7 +150,6 @@ export const SEARCH_PROVIDER_CATALOG: readonly SearchProviderCatalogEntry[] = [
179
150
  {
180
151
  id: "tinyfish",
181
152
  displayName: "TinyFish",
182
- kind: "byok",
183
153
  apiKeyPrefix: "TinyFish API key...",
184
154
  envVar: "TINYFISH_API_KEY",
185
155
  secretKey: "tinyfish",
@@ -191,7 +161,6 @@ export const SEARCH_PROVIDER_CATALOG: readonly SearchProviderCatalogEntry[] = [
191
161
  {
192
162
  id: "exa",
193
163
  displayName: "Exa",
194
- kind: "byok",
195
164
  apiKeyPrefix: "Exa API key...",
196
165
  envVar: "EXA_API_KEY",
197
166
  secretKey: "exa",
@@ -201,7 +170,6 @@ export const SEARCH_PROVIDER_CATALOG: readonly SearchProviderCatalogEntry[] = [
201
170
  {
202
171
  id: "serply",
203
172
  displayName: "Serply",
204
- kind: "byok",
205
173
  apiKeyPrefix: "Serply API key...",
206
174
  envVar: "SERPLY_API_KEY",
207
175
  secretKey: "serply",
@@ -216,7 +184,7 @@ export const SEARCH_PROVIDER_IDS: readonly string[] =
216
184
 
217
185
  /** Catalog entries that store an API key under their bare provider name. */
218
186
  export const BYOK_SEARCH_PROVIDERS: readonly SearchProviderCatalogEntry[] =
219
- SEARCH_PROVIDER_CATALOG.filter((p) => p.kind === "byok");
187
+ SEARCH_PROVIDER_CATALOG.filter((p) => p.secretKey !== undefined);
220
188
 
221
189
  /** BYOK provider ids, ordered by `fallbackOrder` (ascending). */
222
190
  export const SEARCH_PROVIDER_FALLBACK_ORDER: readonly string[] =
@@ -14,7 +14,6 @@ import {
14
14
  sttConfigForCatalogKey,
15
15
  supportsBoundary,
16
16
  supportsDiarization,
17
- supportsProviderTurnDetection,
18
17
  } from "../provider-catalog.js";
19
18
 
20
19
  // ---------------------------------------------------------------------------
@@ -177,7 +176,6 @@ describe("STT provider catalog", () => {
177
176
 
178
177
  const expectedLanguageSelection = [
179
178
  ["deepgram", "manual"],
180
- ["cadet", "manual"],
181
179
  ["xai", "manual"],
182
180
  // Flux takes no language parameter: its model is monolingual English.
183
181
  ["deepgram-flux", "auto"],
@@ -268,12 +266,12 @@ describe("model families", () => {
268
266
  test("flux rows are variants, not separately selectable providers", () => {
269
267
  // The whole point of folding these back: a model choice must not cost a
270
268
  // provider enum entry and a picker row.
271
- for (const id of ["deepgram-flux", "cadet-flux"] as const) {
269
+ for (const id of ["deepgram-flux"] as const) {
272
270
  expect(getProviderEntry(id)?.variantOf).toBeDefined();
273
271
  expect(listSelectableProviderIds()).not.toContain(id);
274
272
  }
275
273
  expect(listSelectableProviderIds()).toEqual(
276
- expect.arrayContaining(["deepgram", "cadet"]),
274
+ expect.arrayContaining(["deepgram"]),
277
275
  );
278
276
  });
279
277
 
@@ -284,12 +282,6 @@ describe("model families", () => {
284
282
  providers: { deepgram: { model: "flux" } },
285
283
  }),
286
284
  ).toBe("deepgram-flux");
287
- expect(
288
- resolveSttCatalogKey({
289
- provider: "cadet",
290
- providers: { cadet: { model: "flux" } },
291
- }),
292
- ).toBe("cadet-flux");
293
285
  });
294
286
 
295
287
  test("no model, or one the provider does not offer, resolves to the base row", () => {
@@ -314,7 +306,7 @@ describe("model families", () => {
314
306
  expect(
315
307
  resolveSttCatalogKey({
316
308
  provider: "deepgram",
317
- providers: { cadet: { model: "flux" } },
309
+ providers: { xai: { model: "flux" } },
318
310
  }),
319
311
  ).toBe("deepgram");
320
312
  });
@@ -322,20 +314,14 @@ describe("model families", () => {
322
314
  test("names the base family so a stale variant model can be overwritten", () => {
323
315
  // Substituting away from a variant has to write something: leaving the
324
316
  // old model behind resolves straight back to the variant on next load.
325
- expect(baseModelFamilyFor("cadet")).toBe("nova-3");
326
317
  expect(baseModelFamilyFor("deepgram")).toBe("nova-3");
327
318
  // Nothing to write, and no variant that could have left a stale value.
328
319
  expect(baseModelFamilyFor("openai-whisper")).toBeUndefined();
329
- expect(baseModelFamilyFor("cadet-flux")).toBeUndefined();
330
320
  });
331
321
 
332
322
  test("round-trips a resolved key back to the config that selects it", () => {
333
323
  // Anything persisting a resolved provider needs this: the key itself is
334
324
  // not a valid services.stt.provider value.
335
- expect(sttConfigForCatalogKey("cadet-flux")).toEqual({
336
- provider: "cadet",
337
- model: "flux",
338
- });
339
325
  expect(sttConfigForCatalogKey("deepgram")).toEqual({
340
326
  provider: "deepgram",
341
327
  });
@@ -347,33 +333,3 @@ describe("model families", () => {
347
333
  expect(listProviderModelFamilies("deepgram-flux")).toEqual([]);
348
334
  });
349
335
  });
350
-
351
- describe("cadet-flux (managed Flux)", () => {
352
- test("shares the cadet connection rather than a second credential", () => {
353
- expect(getProviderEntry("cadet-flux")?.credentialProvider).toBe("cadet");
354
- expect(listCredentialProviderNames()).not.toContain("cadet-flux");
355
- });
356
-
357
- test("is streaming-only, like the BYOK Flux entry", () => {
358
- expect(supportsBoundary("cadet-flux", "daemon-streaming")).toBe(true);
359
- expect(supportsBoundary("cadet-flux", "daemon-batch")).toBe(false);
360
- });
361
-
362
- test("decides end-of-turn itself, unlike plain cadet", () => {
363
- // The relay is dialed with contract=flux, so Flux's turn events survive.
364
- expect(supportsProviderTurnDetection("cadet-flux")).toBe(true);
365
- expect(supportsProviderTurnDetection("cadet")).toBe(false);
366
- });
367
-
368
- test("stays off telephony", () => {
369
- // The relay maps Finalize onto CloseStream and utterance-boundary finals
370
- // are a nova-3 concept, so calls stay on `cadet`.
371
- expect(getProviderEntry("cadet-flux")?.telephonyMode).toBe("none");
372
- });
373
-
374
- test("exposes a language picker, unlike BYOK Flux", () => {
375
- // The relay picks flux-general-en or flux-general-multi from the language
376
- // it is sent, so the selection is meaningful here.
377
- expect(getProviderEntry("cadet-flux")?.languageSelection).toBe("manual");
378
- });
379
- });