@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
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@mycadet/assistant",
3
- "version": "0.12.10",
3
+ "version": "0.13.0",
4
4
  "license": "MIT",
5
5
  "type": "module",
6
6
  "exports": {
@@ -20,7 +20,7 @@
20
20
  "probe:skill-retrieval": "bun run scripts/probe-skill-retrieval.ts",
21
21
  "format": "prettier --write .",
22
22
  "format:check": "prettier --check .",
23
- "lint": "bun run lint:skills && bun run lint:openapi && eslint --max-warnings 2863",
23
+ "lint": "bun run lint:skills && bun run lint:openapi && eslint --max-warnings 2829",
24
24
  "lint:unused": "knip --include files,dependencies,unlisted",
25
25
  "lint:circular": "bun run scripts/check-circular-deps.ts",
26
26
  "lint:unused:production": "knip --production --include exports",
@@ -79,7 +79,6 @@
79
79
  "semver": "7.8.0",
80
80
  "sharp": "0.35.4",
81
81
  "stemmer": "2.0.1",
82
- "tar-stream": "3.1.7",
83
82
  "tldts": "7.0.25",
84
83
  "unified": "11.0.5",
85
84
  "uuid": "11.1.0",
@@ -39,7 +39,7 @@ const OUTPUT_PATHS = [
39
39
  * downstream consumers must opt into. Adding optional fields that older
40
40
  * consumers can ignore does NOT require a bump.
41
41
  */
42
- const CLIENT_CATALOG_VERSION = 1;
42
+ const CLIENT_CATALOG_VERSION = 2;
43
43
 
44
44
  function projectProvider(
45
45
  entry: SearchProviderCatalogEntry,
@@ -51,7 +51,6 @@ function projectProvider(
51
51
  if (entry.displayNameLong !== undefined) {
52
52
  projected.displayNameLong = entry.displayNameLong;
53
53
  }
54
- projected.kind = entry.kind;
55
54
  if (entry.apiKeyPrefix !== undefined) {
56
55
  projected.apiKeyPrefix = entry.apiKeyPrefix;
57
56
  }
@@ -138,6 +138,42 @@ function savedProfile(name: string): Record<string, unknown> {
138
138
  >;
139
139
  }
140
140
 
141
+ describe("partial default-provider config", () => {
142
+ for (const provider of ["cadet", "chatgpt"]) {
143
+ test(`timezone PATCH accepts a model-less ${provider} default`, async () => {
144
+ seedRawConfig({ llm: { default: { provider } } });
145
+ await patchRoute.handler({
146
+ body: { ui: { userTimezone: "America/New_York" } },
147
+ });
148
+ const saved = committedRaw() as {
149
+ ui: { userTimezone: string };
150
+ llm: { default: { provider: string; model?: string } };
151
+ };
152
+ expect(saved.ui.userTimezone).toBe("America/New_York");
153
+ expect(saved.llm.default).toEqual({ provider });
154
+ expectOneCommitCycle();
155
+ });
156
+ test(`PATCH can select ${provider} as default without a model`, async () => {
157
+ seedRawConfig({});
158
+ await patchRoute.handler({ body: { llm: { default: { provider } } } });
159
+ expect(
160
+ (committedRaw() as { llm: { default: { provider: string } } }).llm
161
+ .default,
162
+ ).toEqual({ provider });
163
+ });
164
+ }
165
+ test("Zod rejects a default model with the wrong type", async () => {
166
+ await expect(
167
+ patchRoute.handler({
168
+ body: {
169
+ llm: { default: { provider: "cadet", model: 42 } },
170
+ },
171
+ }),
172
+ ).rejects.toThrow(/model|expected string/i);
173
+ expectNothingCommitted();
174
+ });
175
+ });
176
+
141
177
  // ---------------------------------------------------------------------------
142
178
  // PUT /v1/config/llm/profiles/:name — replace inference profile
143
179
  // ---------------------------------------------------------------------------
@@ -210,13 +246,13 @@ describe("PUT /v1/config/llm/profiles/:name — cloud profile guard", () => {
210
246
  ).toBeUndefined();
211
247
  });
212
248
 
213
- test("rejects a routing identity with an unroutable model at the write choke point", async () => {
249
+ test("Zod rejects invalid fields in a replacement profile", async () => {
214
250
  await expect(
215
251
  replaceRoute.handler({
216
252
  pathParams: { name: "my-custom" },
217
- body: { provider: "cadet", model: "not-a-real-model" },
253
+ body: { provider: "cadet", model: "claude-opus-4-8", maxTokens: 0 },
218
254
  }),
219
- ).rejects.toThrow(/not served by the Cadet Cloud route/);
255
+ ).rejects.toThrow(/expected number to be >0/);
220
256
  expect(committedRaw()).toBeNull();
221
257
  });
222
258
 
@@ -1061,7 +1097,7 @@ describe("PATCH /v1/config — provider-only services scrub legacy mode", () =>
1061
1097
  body: {
1062
1098
  services: {
1063
1099
  "image-generation": { provider: "cadet", mode: "managed" },
1064
- "web-search": { provider: "cadet", mode: "managed" },
1100
+ "web-search": { provider: "brave", mode: "managed" },
1065
1101
  },
1066
1102
  },
1067
1103
  } as never);
@@ -1075,6 +1111,6 @@ describe("PATCH /v1/config — provider-only services scrub legacy mode", () =>
1075
1111
  expect("mode" in raw.services["image-generation"]!).toBe(false);
1076
1112
  expect(raw.services["image-generation"]!.provider).toBe("cadet");
1077
1113
  expect("mode" in raw.services["web-search"]!).toBe(false);
1078
- expect(raw.services["web-search"]!.provider).toBe("cadet");
1114
+ expect(raw.services["web-search"]!.provider).toBe("brave");
1079
1115
  });
1080
1116
  });
@@ -1532,9 +1532,6 @@ describe("AssistantConfigSchema", () => {
1532
1532
  expect(result.services.tts.providers.deepgram.languageVoices).toEqual({
1533
1533
  hi: "aura-2-hi-voice",
1534
1534
  });
1535
- expect(result.services.tts.providers.cadet.languageVoices).toEqual({
1536
- hi: "aura-2-hi-voice",
1537
- });
1538
1535
  });
1539
1536
 
1540
1537
  test("normalizes user-entered languageVoices keys to lowercase base subtags", () => {
@@ -1586,7 +1583,7 @@ describe("AssistantConfigSchema", () => {
1586
1583
  services: {
1587
1584
  tts: {
1588
1585
  providers: {
1589
- cadet: {
1586
+ deepgram: {
1590
1587
  languageVoices: {
1591
1588
  "": "voice-empty",
1592
1589
  " ": "voice-blank",
@@ -1598,7 +1595,7 @@ describe("AssistantConfigSchema", () => {
1598
1595
  },
1599
1596
  },
1600
1597
  });
1601
- expect(result.services.tts.providers.cadet.languageVoices).toEqual({
1598
+ expect(result.services.tts.providers.deepgram.languageVoices).toEqual({
1602
1599
  hi: "voice-hindi",
1603
1600
  });
1604
1601
  });
@@ -1611,11 +1608,10 @@ describe("AssistantConfigSchema", () => {
1611
1608
  expect(
1612
1609
  result.services.tts.providers.deepgram.languageVoices,
1613
1610
  ).toBeUndefined();
1614
- expect(result.services.tts.providers.cadet.languageVoices).toBeUndefined();
1615
1611
  });
1616
1612
 
1617
1613
  test("rejects non-string services.tts.providers languageVoices values", () => {
1618
- for (const provider of ["elevenlabs", "deepgram", "cadet"]) {
1614
+ for (const provider of ["elevenlabs", "deepgram"]) {
1619
1615
  const result = AssistantConfigSchema.safeParse({
1620
1616
  services: {
1621
1617
  tts: {
@@ -1647,13 +1643,6 @@ describe("AssistantConfigSchema", () => {
1647
1643
  expect(result.services.tts.provider).toBe("elevenlabs");
1648
1644
  });
1649
1645
 
1650
- test("accepts tts provider cadet as an ordinary choice", () => {
1651
- const result = AssistantConfigSchema.safeParse({
1652
- services: { tts: { provider: "cadet" } },
1653
- });
1654
- expect(result.success).toBe(true);
1655
- });
1656
-
1657
1646
  // ── hostBrowser.cdpInspect.desktopAuto config ───────────────────────
1658
1647
 
1659
1648
  test("applies hostBrowser.cdpInspect.desktopAuto defaults", () => {
@@ -1719,9 +1708,6 @@ describe("AssistantConfigSchema", () => {
1719
1708
  expect(defaulted.data.provider).toBe("elevenlabs");
1720
1709
  }
1721
1710
 
1722
- expect(TtsServiceSchema.safeParse({ provider: "cadet" }).success).toBe(
1723
- true,
1724
- );
1725
1711
  expect(
1726
1712
  TtsServiceSchema.safeParse({ provider: "self-hosted" }).success,
1727
1713
  ).toBe(false);
@@ -1809,13 +1795,6 @@ describe("AssistantConfigSchema", () => {
1809
1795
  expect(result.services.stt.provider).toBe("deepgram");
1810
1796
  });
1811
1797
 
1812
- test("accepts stt provider cadet as an ordinary choice", () => {
1813
- const result = AssistantConfigSchema.safeParse({
1814
- services: { stt: { provider: "cadet" } },
1815
- });
1816
- expect(result.success).toBe(true);
1817
- });
1818
-
1819
1798
  test("rejects invalid services.stt.provider", () => {
1820
1799
  const result = AssistantConfigSchema.safeParse({
1821
1800
  services: { stt: { provider: "azure-speech" } },
@@ -1892,9 +1871,6 @@ describe("AssistantConfigSchema", () => {
1892
1871
  expect(
1893
1872
  SttServiceSchema.safeParse({ provider: "openai-whisper" }).success,
1894
1873
  ).toBe(true);
1895
- expect(SttServiceSchema.safeParse({ provider: "cadet" }).success).toBe(
1896
- true,
1897
- );
1898
1874
  expect(
1899
1875
  SttServiceSchema.safeParse({ provider: "self-hosted" }).success,
1900
1876
  ).toBe(false);
@@ -2090,21 +2066,13 @@ describe("TTS provider catalog integration", () => {
2090
2066
 
2091
2067
  test("resolveTtsConfig returns correct defaults for each catalog provider", () => {
2092
2068
  for (const providerId of listCatalogProviderIds()) {
2093
- // cadet is connection-based and only valid under managed mode.
2094
- const mode = providerId === "cadet" ? "managed" : "your-own";
2095
2069
  const config = AssistantConfigSchema.parse({
2096
- services: { tts: { mode, provider: providerId } },
2070
+ services: { tts: { provider: providerId } },
2097
2071
  });
2098
2072
  const resolved = resolveTtsConfig(config);
2099
2073
  expect(resolved.provider).toBe(providerId);
2100
- if (providerId === "cadet") {
2101
- // The cadet config block is intentionally empty — the cloud
2102
- // pins the voice and model.
2103
- expect(resolved.providerConfig).toEqual({});
2104
- } else {
2105
- // Every BYOK provider resolves to a non-empty config object.
2106
- expect(Object.keys(resolved.providerConfig).length).toBeGreaterThan(0);
2107
- }
2074
+ // Every provider resolves to a non-empty config object.
2075
+ expect(Object.keys(resolved.providerConfig).length).toBeGreaterThan(0);
2108
2076
  }
2109
2077
  });
2110
2078
 
@@ -372,6 +372,11 @@ type ConversationWithWorkspaceDeps = Conversation & {
372
372
  provider?: unknown,
373
373
  deadlineMs?: number,
374
374
  ) => Promise<void>;
375
+ turnCommitLog?: Array<{
376
+ workspaceDir: string;
377
+ conversationId: string;
378
+ turnNumber: number;
379
+ }>;
375
380
  };
376
381
 
377
382
  function makeConversation(
@@ -401,12 +406,24 @@ function makeConversation(
401
406
  conversationWithWorkspaceDeps.getWorkspaceGitService = () => ({
402
407
  ensureInitialized: async () => {},
403
408
  });
409
+ // Per-instance commit log: the shared turnCommitCalls counter also catches
410
+ // commits from stale turns of EARLIER tests (an abort watchdog that fired
411
+ // late under CI worker starvation drives the dead conversation's turn into
412
+ // commitTurnChanges). Assertions scoped to this log stay race-free.
413
+ const turnCommitLog: Array<{
414
+ workspaceDir: string;
415
+ conversationId: string;
416
+ turnNumber: number;
417
+ }> = [];
418
+ conversationWithWorkspaceDeps.turnCommitLog = turnCommitLog;
404
419
  conversationWithWorkspaceDeps.commitTurnChanges = async (
405
420
  workspaceDir: string,
406
421
  conversationId: string,
407
422
  turnNumber: number,
408
423
  ) => {
409
- turnCommitCalls.push({ workspaceDir, conversationId, turnNumber });
424
+ const entry = { workspaceDir, conversationId, turnNumber };
425
+ turnCommitCalls.push(entry);
426
+ turnCommitLog.push(entry);
410
427
  if (turnCommitHangForever) {
411
428
  // Simulate a commit that never resolves within the timeout budget
412
429
  await new Promise<void>(() => {});
@@ -2717,6 +2734,15 @@ describe("Batched drain correctness fixes", () => {
2717
2734
  expect(events4.filter((e) => e.type === "message_dequeued")).toHaveLength(
2718
2735
  0,
2719
2736
  );
2737
+ // Settle any run the aborted drain started (run 0 was resolved mid-test)
2738
+ // so its abort watchdog clears the real-time timer it armed. A leaked
2739
+ // ~5s timer otherwise fires during a later test and drives this stale
2740
+ // turn into commitTurnChanges, inflating the shared turnCommitCalls
2741
+ // counter that other tests assert against.
2742
+ for (let i = 1; i < pendingRuns.length; i++) {
2743
+ await resolveRun(i);
2744
+ }
2745
+ await new Promise((r) => setTimeout(r, 10));
2720
2746
  });
2721
2747
 
2722
2748
  test("failed tail persist uses last-successful requestId", async () => {
@@ -3926,9 +3952,16 @@ describe("Regression: cancel semantics and error channel split", () => {
3926
3952
  await run.onEvent({ type: "message_complete", message: assistantMsg });
3927
3953
  run.resolve([...run.messages, assistantMsg]);
3928
3954
  await p1;
3929
-
3930
- expect(turnCommitCalls).toHaveLength(1);
3931
- expect(turnCommitCalls[0]).toEqual({
3955
+ // The turn commit should have been called — scoped to this test's
3956
+ // conversation instance (see the turnCommitLog note in makeConversation:
3957
+ // the shared counter also catches stale turns whose abort watchdog fired
3958
+ // late under CI worker starvation).
3959
+ expect(
3960
+ (conversation as ConversationWithWorkspaceDeps).turnCommitLog,
3961
+ ).toHaveLength(1);
3962
+ expect(
3963
+ (conversation as ConversationWithWorkspaceDeps).turnCommitLog?.[0],
3964
+ ).toEqual({
3932
3965
  workspaceDir: "/tmp",
3933
3966
  conversationId: "conv-1",
3934
3967
  turnNumber: 1,
@@ -4062,8 +4095,14 @@ describe("Regression: cancel semantics and error channel split", () => {
4062
4095
  const dequeued = events2.find((e) => e.type === "message_dequeued");
4063
4096
  expect(dequeued).toBeDefined();
4064
4097
 
4065
- // The turn commit should have been called
4066
- expect(turnCommitCalls).toHaveLength(1);
4098
+ // The turn commit should have been called — scoped to this test's
4099
+ // conversation instance (see the turnCommitLog note in
4100
+ // makeConversation: the shared counter also catches stale turns from
4101
+ // earlier tests whose abort watchdog fired late under CI worker
4102
+ // starvation).
4103
+ expect(
4104
+ (conversation as ConversationWithWorkspaceDeps).turnCommitLog,
4105
+ ).toHaveLength(1);
4067
4106
 
4068
4107
  // Complete the second run so the test can clean up
4069
4108
  turnCommitHangForever = false;
@@ -100,12 +100,6 @@ describe("DB migration readiness HTTP gate", () => {
100
100
  body = (await response.json().catch(() => ({}))) as Record<string, unknown>;
101
101
  expect(body.reason).not.toBe("db_migrations_failed");
102
102
 
103
- // The parameterized job-status route (GCS import polling) passes the
104
- // gate by prefix in the failed state.
105
- response = await fetch(url("/migrations/jobs/some-job-id"));
106
- body = (await response.json().catch(() => ({}))) as Record<string, unknown>;
107
- expect(body.reason).not.toBe("db_migrations_failed");
108
-
109
103
  // Non-repair routes stay gated in the failed state.
110
104
  response = await fetch(url("/conversations"));
111
105
  expect(response.status).toBe(503);
@@ -41,7 +41,6 @@ mock.module("../prompts/persona-resolver.js", () => ({
41
41
  }),
42
42
  resolveUserSlug: () => null,
43
43
  ensureGuardianPersonaFile: () => {},
44
- isGuardianPersonaCustomized: () => false,
45
44
  GUARDIAN_PERSONA_TEMPLATE: "",
46
45
  }));
47
46
 
@@ -98,7 +98,6 @@ import { resolveUserName } from "../daemon/identity-helpers.js";
98
98
  import type { TrustContext } from "../daemon/trust-context-types.js";
99
99
  import {
100
100
  ensureGuardianPersonaFile,
101
- isGuardianPersonaCustomized,
102
101
  resolveGuardianPersona,
103
102
  resolveGuardianPersonaPath,
104
103
  resolveGuardianPersonaStrict,
@@ -242,56 +241,6 @@ describe("resolveGuardianPersonaStrict", () => {
242
241
  });
243
242
  });
244
243
 
245
- // ── isGuardianPersonaCustomized ────────────────────────────────────
246
-
247
- describe("isGuardianPersonaCustomized", () => {
248
- test("returns false when the file does not exist", () => {
249
- const filePath = join(mockWorkspaceDir, "users", "nobody.md");
250
- expect(isGuardianPersonaCustomized(filePath)).toBe(false);
251
- });
252
-
253
- test("returns false for the bare scaffold template (no user edits)", () => {
254
- const userFile = "alice.md";
255
- const filePath = join(mockWorkspaceDir, "users", userFile);
256
-
257
- // ensureGuardianPersonaFile writes the canonical template — the
258
- // exact bytes that "not customized" accepts.
259
- ensureGuardianPersonaFile(userFile);
260
-
261
- expect(isGuardianPersonaCustomized(filePath)).toBe(false);
262
- });
263
-
264
- test("returns false when the file contains only comment lines", () => {
265
- const userFile = "alice.md";
266
- const dir = join(mockWorkspaceDir, "users");
267
- const filePath = join(dir, userFile);
268
-
269
- mkdirSync(dir, { recursive: true });
270
- writeFileSync(
271
- filePath,
272
- "_ only comments here\n_ nothing meaningful\n",
273
- "utf-8",
274
- );
275
-
276
- expect(isGuardianPersonaCustomized(filePath)).toBe(false);
277
- });
278
-
279
- test("returns true when the file has user-authored content", () => {
280
- const userFile = "alice.md";
281
- const dir = join(mockWorkspaceDir, "users");
282
- const filePath = join(dir, userFile);
283
-
284
- mkdirSync(dir, { recursive: true });
285
- writeFileSync(
286
- filePath,
287
- "# My profile\n\n- Preferred name/reference: Real User\n",
288
- "utf-8",
289
- );
290
-
291
- expect(isGuardianPersonaCustomized(filePath)).toBe(true);
292
- });
293
- });
294
-
295
244
  // ── resolveUserSlug — background/scheduled guardian turns ──────────
296
245
  //
297
246
  // Background and scheduled turns carry a guardian trust context with no
@@ -43,7 +43,6 @@ mock.module("@google/genai", () => ({
43
43
  // Mock OpenAI SDK to capture OpenAI/Fireworks tool definitions and preserve
44
44
  // constructor baseURL assertions. Must be before importing the registry.
45
45
  // ---------------------------------------------------------------------------
46
- let lastOpenAIChatParams: Record<string, unknown> | null = null;
47
46
 
48
47
  mock.module("openai", () => {
49
48
  class FakeAPIError extends Error {
@@ -69,8 +68,7 @@ mock.module("openai", () => {
69
68
 
70
69
  chat = {
71
70
  completions: {
72
- create: (params: Record<string, unknown>) => {
73
- lastOpenAIChatParams = JSON.parse(JSON.stringify(params));
71
+ create: (_params: Record<string, unknown>) => {
74
72
  return (async function* () {
75
73
  yield {
76
74
  choices: [
@@ -119,7 +117,7 @@ import {
119
117
  initializeProviders,
120
118
  listProviders,
121
119
  } from "../providers/registry.js";
122
- import type { Message, ToolDefinition } from "../providers/types.js";
120
+ import type { Message } from "../providers/types.js";
123
121
  import { setConfig } from "./helpers/set-config.js";
124
122
 
125
123
  function makeProvidersConfig(
@@ -152,10 +150,6 @@ const PLATFORM_BASE = "https://test-cloud.mycadet.ai";
152
150
  const MANAGED_API_KEY = "ast-managed-key-123";
153
151
  const PLATFORM_ASSISTANT_ID = "assistant-abc123";
154
152
 
155
- const MANAGED_NATIVE_WEB_SEARCH: Services["web-search"] = {
156
- provider: "inference-provider-native",
157
- };
158
-
159
153
  const DIRECT_OR_MANAGED_PROVIDER_KEYS: string[] = [
160
154
  "openai",
161
155
  "anthropic",
@@ -226,22 +220,6 @@ function userMsg(text: string): Message {
226
220
  return { role: "user", content: [{ type: "text", text }] };
227
221
  }
228
222
 
229
- const sampleTools: ToolDefinition[] = [
230
- {
231
- name: "file_read",
232
- description: "Read a file",
233
- input_schema: { type: "object", properties: { path: { type: "string" } } },
234
- },
235
- {
236
- name: "web_search",
237
- description: "Search the web",
238
- input_schema: {
239
- type: "object",
240
- properties: { query: { type: "string" } },
241
- },
242
- },
243
- ];
244
-
245
223
  // ---------------------------------------------------------------------------
246
224
  // Tests
247
225
  // ---------------------------------------------------------------------------
@@ -251,7 +229,6 @@ beforeEach(() => {
251
229
  clearUserKeys();
252
230
  lastGeminiConstructorOpts = null;
253
231
  lastGeminiGenerateContentStreamParams = null;
254
- lastOpenAIChatParams = null;
255
232
  // Reset the workspace config to pure schema defaults (the default
256
233
  // web-search service — your-own / inference-provider-native — IS the
257
234
  // schema default, so only divergent tests seed `services`).
@@ -541,91 +518,6 @@ describe("cloud proxy integration — credential precedence", () => {
541
518
  });
542
519
  });
543
520
 
544
- describe("cloud proxy integration — managed web search routing", () => {
545
- test("managed Fireworks/Kimi tool call completes through the cloud Brave proxy", async () => {
546
- enableCloudProxy();
547
- clearUserKeys();
548
- setConfig("services", { "web-search": MANAGED_NATIVE_WEB_SEARCH });
549
-
550
- const originalFetch = globalThis.fetch;
551
- const fetchUrls: string[] = [];
552
- globalThis.fetch = (async (url: URL | RequestInfo) => {
553
- fetchUrls.push(String(url));
554
- return new Response(
555
- JSON.stringify({
556
- status: 200,
557
- headers: { "content-type": "application/json" },
558
- body: {
559
- web: {
560
- results: [
561
- {
562
- title: "Cloud Result",
563
- url: "https://example.com/platform-result",
564
- description: "Returned by the cloud Brave proxy.",
565
- age: "1 day ago",
566
- },
567
- ],
568
- },
569
- },
570
- }),
571
- {
572
- status: 200,
573
- headers: { "content-type": "application/json" },
574
- },
575
- );
576
- }) as unknown as typeof fetch;
577
-
578
- try {
579
- await initializeProviders(
580
- makeProvidersConfig(
581
- "fireworks",
582
- "accounts/fireworks/models/kimi-k2p6",
583
- MANAGED_NATIVE_WEB_SEARCH,
584
- ),
585
- );
586
-
587
- const provider = getProvider("fireworks");
588
- await provider.sendMessage([userMsg("Search using managed Brave")], {
589
- tools: sampleTools,
590
- });
591
-
592
- const tools = lastOpenAIChatParams!.tools as Array<{
593
- type: string;
594
- function?: { name: string; description?: string };
595
- }>;
596
- expect(tools).toHaveLength(2);
597
- expect(tools[1]).toMatchObject({
598
- type: "function",
599
- function: {
600
- name: "web_search",
601
- description: "Search the web",
602
- },
603
- });
604
-
605
- const { webSearchTool } = await import("../tools/network/web-search.js");
606
- const result = await webSearchTool.execute(
607
- { query: "managed kimi query", count: 1, offset: 2, freshness: "pw" },
608
- {
609
- conversationId: "conv-123",
610
- workingDir: "/tmp",
611
- trustClass: "guardian",
612
- },
613
- );
614
-
615
- expect(result.isError).toBe(false);
616
- expect(result.content).toContain("Cloud Result");
617
- expect(result.activityMetadata?.webSearch?.provider).toBe("brave");
618
- expect(result.activityMetadata?.webSearch?.resultCount).toBe(1);
619
-
620
- expect(fetchUrls).toEqual([
621
- `${PLATFORM_BASE}/v1/assistants/${PLATFORM_ASSISTANT_ID}/cloud-search-proxy/brave/`,
622
- ]);
623
- } finally {
624
- globalThis.fetch = originalFetch;
625
- }
626
- });
627
- });
628
-
629
521
  describe("cloud proxy integration — ollama exclusion", () => {
630
522
  test("ollama is never registered via cloud proxy fallback", async () => {
631
523
  enableCloudProxy();
@@ -9,10 +9,6 @@ import { existsSync, mkdirSync, rmSync, writeFileSync } from "node:fs";
9
9
  import { join } from "node:path";
10
10
  import { beforeEach, describe, expect, mock, test } from "bun:test";
11
11
 
12
- mock.module("../background-wake/publisher.js", () => ({
13
- refreshBackgroundWakeIntent: () => {},
14
- }));
15
-
16
12
  mock.module("../daemon/disk-pressure-background-gate.js", () => ({
17
13
  checkDiskPressureBackgroundGate: () => ({
18
14
  action: "allow",
@@ -1,18 +1,6 @@
1
1
  import { mkdirSync, rmSync, writeFileSync } from "node:fs";
2
2
  import { join } from "node:path";
3
3
  import { beforeEach, describe, expect, test } from "bun:test";
4
- import { mock } from "bun:test";
5
-
6
- // Stub the background-wake publisher so these store-level unit tests stay
7
- // hermetic. `notifySchedulesChanged()` fires a debounced background-wake
8
- // refresh on every mutation; left real, that 250ms timer performs a
9
- // synchronous DB read plus a cloud-client lookup which compete with the
10
- // serialized async event delivery and can push a `sync_changed` past the
11
- // wait deadline on loaded runners. Background-wake behavior is covered by the
12
- // background-wake tests.
13
- mock.module("../background-wake/publisher.js", () => ({
14
- refreshBackgroundWakeIntent: () => {},
15
- }));
16
4
 
17
5
  import type { AssistantEventEnvelope } from "../api/index.js";
18
6
  import { SYNC_TAGS } from "../daemon/message-types/sync.js";
@@ -140,11 +140,11 @@ class FailingTranscriber implements StreamingTranscriber {
140
140
  }
141
141
 
142
142
  /**
143
- * Mock managed transcriber whose start() throws a userFacing SttError,
144
- * mirroring the cloud relay's mapped dial rejection.
143
+ * Mock transcriber whose start() throws a userFacing SttError, mirroring
144
+ * an adapter's mapped upstream rejection.
145
145
  */
146
146
  class ManagedFailingTranscriber implements StreamingTranscriber {
147
- readonly providerId = "cadet" as const;
147
+ readonly providerId = "deepgram" as const;
148
148
  readonly boundaryId = "daemon-streaming" as const;
149
149
 
150
150
  constructor(private readonly message: string) {}
@@ -357,7 +357,7 @@ describe("SttStreamSession", () => {
357
357
  });
358
358
 
359
359
  test("managed start failure surfaces its remediation verbatim", async () => {
360
- const { ws, session } = createSession("cadet");
360
+ const { ws, session } = createSession("deepgram");
361
361
  const managedMessage =
362
362
  "Cloud speech needs a working Cadet Cloud connection — reconnect with 'assistant cloud connect'.";
363
363