@mycadet/assistant 0.12.11 → 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 (176) hide show
  1. package/node_modules/@mycadet/ces-client/node_modules/@mycadet/service-contracts/src/__tests__/ingress.test.ts +2 -2
  2. package/node_modules/@mycadet/ces-client/node_modules/@mycadet/service-contracts/src/ingress.ts +2 -2
  3. package/node_modules/@mycadet/gateway-client/node_modules/@mycadet/service-contracts/src/__tests__/ingress.test.ts +2 -2
  4. package/node_modules/@mycadet/gateway-client/node_modules/@mycadet/service-contracts/src/ingress.ts +2 -2
  5. package/node_modules/@mycadet/gateway-client/src/gateway-ipc-contracts.ts +0 -20
  6. package/node_modules/@mycadet/service-contracts/src/__tests__/ingress.test.ts +2 -2
  7. package/node_modules/@mycadet/service-contracts/src/ingress.ts +2 -2
  8. package/openapi.yaml +2 -708
  9. package/package.json +2 -3
  10. package/scripts/sync-web-search-catalog.ts +1 -2
  11. package/src/__tests__/cloud-profile-guard.test.ts +2 -2
  12. package/src/__tests__/config-schema.test.ts +6 -38
  13. package/src/__tests__/conversation-queue.test.ts +45 -6
  14. package/src/__tests__/db-readiness-http-gate.test.ts +0 -6
  15. package/src/__tests__/persist-onboarding-artifacts.test.ts +0 -1
  16. package/src/__tests__/persona-resolver.test.ts +0 -51
  17. package/src/__tests__/provider-cloud-proxy-integration.test.ts +2 -110
  18. package/src/__tests__/run-due-schedules.test.ts +0 -4
  19. package/src/__tests__/schedule-store.test.ts +0 -12
  20. package/src/__tests__/stt-stream-session.test.ts +4 -4
  21. package/src/__tests__/telephony-tts-guard.test.ts +2 -50
  22. package/src/__tests__/voice-config-update.test.ts +12 -167
  23. package/src/__tests__/web-search-catalog-parity.test.ts +0 -2
  24. package/src/__tests__/workspace-migration-130-speech-mode-to-provider.test.ts +9 -7
  25. package/src/__tests__/workspace-migration-132-web-search-mode-to-provider.test.ts +6 -6
  26. package/src/calls/__tests__/voice-session-bridge.test.ts +1 -4
  27. package/src/calls/resolve-call-tts-provider.ts +6 -25
  28. package/src/calls/telephony-credential-preflight.ts +0 -10
  29. package/src/calls/telephony-tts-capability.ts +1 -17
  30. package/src/cli/commands/tts.ts +1 -2
  31. package/src/cli/index.help.ts +0 -2
  32. package/src/cli/program.ts +0 -2
  33. package/src/config/bundled-skills/settings/tools/voice-config-update.ts +4 -42
  34. package/src/config/schemas/__tests__/stt.test.ts +10 -14
  35. package/src/config/schemas/services.ts +5 -6
  36. package/src/config/schemas/stt.ts +1 -3
  37. package/src/config/schemas/tts.ts +1 -30
  38. package/src/daemon/daemon-readiness.ts +4 -29
  39. package/src/daemon/lifecycle.ts +0 -31
  40. package/src/daemon/providers-setup.ts +0 -8
  41. package/src/heartbeat/__tests__/heartbeat-service.test.ts +0 -1
  42. package/src/heartbeat/heartbeat-service.ts +1 -66
  43. package/src/ipc/__tests__/db-readiness-ipc-gate.test.ts +1 -9
  44. package/src/live-voice/__tests__/live-voice-credential-preflight.test.ts +0 -44
  45. package/src/live-voice/__tests__/live-voice-flux-turn-end.test.ts +4 -6
  46. package/src/live-voice/__tests__/live-voice-stt.test.ts +1 -1
  47. package/src/live-voice/live-voice-credential-preflight.ts +9 -33
  48. package/src/live-voice/live-voice-session.ts +10 -6
  49. package/src/live-voice/live-voice-tts.ts +1 -8
  50. package/src/plugins/defaults/memory/worker.ts +3 -3
  51. package/src/prompts/persona-resolver.ts +0 -35
  52. package/src/providers/__tests__/search-provider-catalog.test.ts +5 -8
  53. package/src/providers/__tests__/voice-error-copy.test.ts +9 -10
  54. package/src/providers/search-provider-catalog.ts +7 -39
  55. package/src/providers/speech-to-text/__tests__/provider-catalog.test.ts +3 -47
  56. package/src/providers/speech-to-text/__tests__/resolve.test.ts +6 -372
  57. package/src/providers/speech-to-text/provider-catalog.ts +2 -73
  58. package/src/providers/speech-to-text/resolve.ts +3 -120
  59. package/src/runtime/http-router-types.ts +1 -3
  60. package/src/runtime/http-server.ts +1 -1
  61. package/src/runtime/routes/__tests__/tts-routes.test.ts +2 -6
  62. package/src/runtime/routes/inbound-stages/transcribe-audio.test.ts +7 -7
  63. package/src/runtime/routes/index.ts +0 -4
  64. package/src/runtime/routes/live-voice-routes.test.ts +4 -11
  65. package/src/runtime/routes/live-voice-routes.ts +8 -11
  66. package/src/runtime/routes/secret-routes.ts +0 -6
  67. package/src/runtime/routes/tts-routes.ts +0 -38
  68. package/src/schedule/__tests__/plugin-schedule-reconciler.test.ts +1 -7
  69. package/src/schedule/__tests__/worker-mcp-readiness.test.ts +0 -4
  70. package/src/schedule/schedule-store.ts +0 -7
  71. package/src/schedule/scheduler.ts +0 -5
  72. package/src/schedule/worker.ts +1 -1
  73. package/src/stt/__tests__/daemon-batch-transcriber.test.ts +2 -10
  74. package/src/stt/daemon-batch-transcriber.ts +4 -38
  75. package/src/stt/types.ts +1 -9
  76. package/src/tools/network/__tests__/web-search.test.ts +3 -250
  77. package/src/tools/network/web-search.ts +4 -165
  78. package/src/tts/__tests__/provider-resolution.test.ts +0 -5
  79. package/src/tts/provider-catalog.ts +0 -4
  80. package/src/tts/types.ts +0 -1
  81. package/src/__tests__/cloud-speech-defaults.test.ts +0 -330
  82. package/src/__tests__/migration-cross-version-compatibility.test.ts +0 -1708
  83. package/src/__tests__/migration-export-http.test.ts +0 -557
  84. package/src/__tests__/migration-export-streaming.test.ts +0 -350
  85. package/src/__tests__/migration-export-to-gcs.test.ts +0 -706
  86. package/src/__tests__/migration-import-commit-http.test.ts +0 -1176
  87. package/src/__tests__/migration-import-from-gcs.test.ts +0 -534
  88. package/src/__tests__/migration-import-from-path.test.ts +0 -324
  89. package/src/__tests__/migration-import-from-url.test.ts +0 -588
  90. package/src/__tests__/migration-import-preflight-http.test.ts +0 -739
  91. package/src/__tests__/migration-jobs-status.test.ts +0 -139
  92. package/src/__tests__/migration-parity-persistence.test.ts +0 -1891
  93. package/src/__tests__/migration-transport.test.ts +0 -1089
  94. package/src/__tests__/migration-validate-http.test.ts +0 -634
  95. package/src/__tests__/migration-wizard.test.ts +0 -1395
  96. package/src/__tests__/rebind-secrets-screen.test.ts +0 -876
  97. package/src/__tests__/sanitize-config-for-transfer.test.ts +0 -259
  98. package/src/__tests__/transfer-progress-screen.test.ts +0 -1217
  99. package/src/__tests__/validation-results-screen.test.ts +0 -1130
  100. package/src/__tests__/vbundle-pax-and-symlink.test.ts +0 -147
  101. package/src/background-wake/background-wake-routes.test.ts +0 -906
  102. package/src/background-wake/cloud-client.test.ts +0 -328
  103. package/src/background-wake/cloud-client.ts +0 -196
  104. package/src/background-wake/next-wake.test.ts +0 -335
  105. package/src/background-wake/next-wake.ts +0 -188
  106. package/src/background-wake/publisher.ts +0 -93
  107. package/src/background-wake/wake-intent-hooks.test.ts +0 -234
  108. package/src/cli/commands/__tests__/backup.test.ts +0 -363
  109. package/src/cli/commands/backup.help.ts +0 -180
  110. package/src/cli/commands/backup.ts +0 -398
  111. package/src/cloud/cloud-speech.test.ts +0 -335
  112. package/src/cloud/cloud-speech.ts +0 -300
  113. package/src/config/cloud-speech-defaults.ts +0 -300
  114. package/src/config/sanitize-for-transfer.ts +0 -111
  115. package/src/live-voice/__tests__/live-voice-cloud-speech-fallback.test.ts +0 -250
  116. package/src/providers/speech-to-text/__tests__/cadet-cloud-realtime.test.ts +0 -457
  117. package/src/providers/speech-to-text/__tests__/cadet-cloud.test.ts +0 -271
  118. package/src/providers/speech-to-text/__tests__/cadet-speech-relay-connection.test.ts +0 -126
  119. package/src/providers/speech-to-text/cadet-cloud-flux-realtime.ts +0 -309
  120. package/src/providers/speech-to-text/cadet-cloud-realtime.ts +0 -315
  121. package/src/providers/speech-to-text/cadet-cloud.ts +0 -108
  122. package/src/providers/speech-to-text/cadet-speech-relay-connection.ts +0 -176
  123. package/src/runtime/migrations/__tests__/gcs-signed-url.test.ts +0 -254
  124. package/src/runtime/migrations/__tests__/job-registry.test.ts +0 -346
  125. package/src/runtime/migrations/__tests__/origin-mode.test.ts +0 -62
  126. package/src/runtime/migrations/__tests__/rebind-secrets-credentials.test.ts +0 -184
  127. package/src/runtime/migrations/__tests__/staged-import-path.test.ts +0 -110
  128. package/src/runtime/migrations/__tests__/v1-test-helpers.ts +0 -112
  129. package/src/runtime/migrations/__tests__/vbundle-builder-credentials.test.ts +0 -285
  130. package/src/runtime/migrations/__tests__/vbundle-builder-fd-leak.test.ts +0 -126
  131. package/src/runtime/migrations/__tests__/vbundle-builder-v1-shape.test.ts +0 -253
  132. package/src/runtime/migrations/__tests__/vbundle-import-credentials.test.ts +0 -208
  133. package/src/runtime/migrations/__tests__/vbundle-import-parity.test.ts +0 -485
  134. package/src/runtime/migrations/__tests__/vbundle-import-policy.test.ts +0 -349
  135. package/src/runtime/migrations/__tests__/vbundle-import-version-compat.test.ts +0 -196
  136. package/src/runtime/migrations/__tests__/vbundle-legacy-user-md.test.ts +0 -551
  137. package/src/runtime/migrations/__tests__/vbundle-metadata-merge-integration.test.ts +0 -428
  138. package/src/runtime/migrations/__tests__/vbundle-metadata-merge.test.ts +0 -220
  139. package/src/runtime/migrations/__tests__/vbundle-streaming-importer.test.ts +0 -1823
  140. package/src/runtime/migrations/__tests__/vbundle-streaming-validator.test.ts +0 -598
  141. package/src/runtime/migrations/__tests__/vbundle-symlink-importer.test.ts +0 -463
  142. package/src/runtime/migrations/__tests__/vbundle-symlink-streaming-importer.test.ts +0 -538
  143. package/src/runtime/migrations/__tests__/vbundle-symlink-streaming.test.ts +0 -515
  144. package/src/runtime/migrations/__tests__/vbundle-symlink-tar.test.ts +0 -453
  145. package/src/runtime/migrations/__tests__/vbundle-symlink-walker.test.ts +0 -319
  146. package/src/runtime/migrations/__tests__/vbundle-tar-stream.test.ts +0 -240
  147. package/src/runtime/migrations/__tests__/vbundle-validator-v1-schema.test.ts +0 -473
  148. package/src/runtime/migrations/gcs-signed-url.ts +0 -190
  149. package/src/runtime/migrations/job-registry.ts +0 -297
  150. package/src/runtime/migrations/migration-transport.ts +0 -612
  151. package/src/runtime/migrations/migration-wizard.ts +0 -747
  152. package/src/runtime/migrations/origin-mode.ts +0 -42
  153. package/src/runtime/migrations/rebind-secrets-screen.ts +0 -412
  154. package/src/runtime/migrations/staged-import-path.ts +0 -116
  155. package/src/runtime/migrations/transfer-progress-screen.ts +0 -323
  156. package/src/runtime/migrations/validation-results-screen.ts +0 -469
  157. package/src/runtime/migrations/vbundle-builder.ts +0 -1382
  158. package/src/runtime/migrations/vbundle-import-analyzer.ts +0 -405
  159. package/src/runtime/migrations/vbundle-import-policy.ts +0 -241
  160. package/src/runtime/migrations/vbundle-importer.ts +0 -826
  161. package/src/runtime/migrations/vbundle-metadata-merge.ts +0 -113
  162. package/src/runtime/migrations/vbundle-streaming-importer.ts +0 -2844
  163. package/src/runtime/migrations/vbundle-streaming-validator.ts +0 -426
  164. package/src/runtime/migrations/vbundle-tar-stream.ts +0 -244
  165. package/src/runtime/migrations/vbundle-validator.ts +0 -724
  166. package/src/runtime/routes/__tests__/migration-cadet-metadata-reconcile.test.ts +0 -227
  167. package/src/runtime/routes/__tests__/migration-export-secrets-redacted.test.ts +0 -54
  168. package/src/runtime/routes/__tests__/migration-import-allowed-hosts-env.test.ts +0 -70
  169. package/src/runtime/routes/__tests__/migration-import-credential-filter.test.ts +0 -257
  170. package/src/runtime/routes/background-wake-routes.ts +0 -387
  171. package/src/runtime/routes/migration-routes.ts +0 -2584
  172. package/src/tools/network/__tests__/cloud-search-proxy.test.ts +0 -282
  173. package/src/tools/network/cloud-search-proxy.ts +0 -211
  174. package/src/tts/__tests__/cadet-provider.test.ts +0 -253
  175. package/src/tts/providers/cadet-provider.ts +0 -244
  176. 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.11",
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
  }
@@ -1097,7 +1097,7 @@ describe("PATCH /v1/config — provider-only services scrub legacy mode", () =>
1097
1097
  body: {
1098
1098
  services: {
1099
1099
  "image-generation": { provider: "cadet", mode: "managed" },
1100
- "web-search": { provider: "cadet", mode: "managed" },
1100
+ "web-search": { provider: "brave", mode: "managed" },
1101
1101
  },
1102
1102
  },
1103
1103
  } as never);
@@ -1111,6 +1111,6 @@ describe("PATCH /v1/config — provider-only services scrub legacy mode", () =>
1111
1111
  expect("mode" in raw.services["image-generation"]!).toBe(false);
1112
1112
  expect(raw.services["image-generation"]!.provider).toBe("cadet");
1113
1113
  expect("mode" in raw.services["web-search"]!).toBe(false);
1114
- expect(raw.services["web-search"]!.provider).toBe("cadet");
1114
+ expect(raw.services["web-search"]!.provider).toBe("brave");
1115
1115
  });
1116
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
 
@@ -99,7 +99,6 @@ const fakeCatalog: FakeCatalogEntry[] = [
99
99
  makeEntry("fish-audio", "synthesized-play", "pcm", true),
100
100
  makeEntry("deepgram", "synthesized-play", "pcm", false),
101
101
  makeEntry("compressed-only", "synthesized-play", "none", false),
102
- makeEntry("cadet", "synthesized-play", "pcm", false),
103
102
  ];
104
103
 
105
104
  // The catalog is also the adapter-resolution point (`getTtsProvider`), so the
@@ -192,12 +191,6 @@ mock.module("../calls/audio-store.js", () => ({
192
191
  },
193
192
  }));
194
193
 
195
- let mockCloudSpeechAvailable = true;
196
-
197
- mock.module("../cloud/cloud-speech.js", () => ({
198
- managedSpeechAvailable: async () => mockCloudSpeechAvailable,
199
- }));
200
-
201
194
  mock.module("../inbound/public-ingress-urls.js", () => ({
202
195
  ...realPublicIngressUrlsModule,
203
196
  getPublicBaseUrl: (
@@ -470,35 +463,14 @@ describe("resolveCallTtsProvider with requiresPcmAudio", () => {
470
463
  expect(result.audioFormat).toBe("mp3");
471
464
  });
472
465
 
473
- test("cloud speech stands in for a configured provider whose credential is missing", async () => {
466
+ test("a credential-less configured provider is kept", async () => {
474
467
  testConfig.services.tts.provider = "deepgram";
475
- // No deepgram key, cloud speech available: the phone speaks through
476
- // cloud speech, the same substitution live voice makes.
477
468
  registerStubProvider("deepgram", async () => {
478
- throw new Error("should not be used");
479
- });
480
- registerStubProvider("cadet", async () => {
481
469
  return { audio: Buffer.from("x"), contentType: "audio/mpeg" };
482
470
  });
483
471
 
484
472
  const result = await resolveCallTtsProvider();
485
- expect(result.provider?.id).toBe("cadet");
486
- expect(result.useSynthesizedPath).toBe(true);
487
- });
488
-
489
- test("without cloud speech a credential-less configured provider is kept", async () => {
490
- mockCloudSpeechAvailable = false;
491
- try {
492
- testConfig.services.tts.provider = "deepgram";
493
- registerStubProvider("deepgram", async () => {
494
- return { audio: Buffer.from("x"), contentType: "audio/mpeg" };
495
- });
496
-
497
- const result = await resolveCallTtsProvider();
498
- expect(result.provider?.id).toBe("deepgram");
499
- } finally {
500
- mockCloudSpeechAvailable = true;
501
- }
473
+ expect(result.provider?.id).toBe("deepgram");
502
474
  });
503
475
  });
504
476
 
@@ -793,23 +765,3 @@ describe("speakSystemPrompt aborted synthesis", () => {
793
765
  ]);
794
766
  });
795
767
  });
796
-
797
- describe("cadet managed playability", () => {
798
- test("playable only when the cloud identity is fully provisioned", async () => {
799
- // The stored secret resolves, but availability decides.
800
- storedKeys["cadet"] = "stored";
801
- mockCloudSpeechAvailable = true;
802
- const playable = await evaluateTelephonyTtsPlayability("cadet");
803
- expect(playable.status).toBe("playable");
804
- });
805
-
806
- test("half-connected platform (secret without identity) is not playable", async () => {
807
- storedKeys["cadet"] = "stored";
808
- mockCloudSpeechAvailable = false;
809
- const playable = await evaluateTelephonyTtsPlayability("cadet");
810
- expect(playable).toMatchObject({
811
- status: "not-playable",
812
- reason: "missing-cloud-connection",
813
- });
814
- });
815
- });