@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.
- package/node_modules/@mycadet/ces-client/node_modules/@mycadet/service-contracts/src/__tests__/ingress.test.ts +2 -2
- package/node_modules/@mycadet/ces-client/node_modules/@mycadet/service-contracts/src/ingress.ts +2 -2
- package/node_modules/@mycadet/gateway-client/node_modules/@mycadet/service-contracts/src/__tests__/ingress.test.ts +2 -2
- package/node_modules/@mycadet/gateway-client/node_modules/@mycadet/service-contracts/src/ingress.ts +2 -2
- package/node_modules/@mycadet/gateway-client/src/gateway-ipc-contracts.ts +0 -20
- package/node_modules/@mycadet/service-contracts/src/__tests__/ingress.test.ts +2 -2
- package/node_modules/@mycadet/service-contracts/src/ingress.ts +2 -2
- package/openapi.yaml +2 -708
- package/package.json +2 -3
- package/scripts/sync-web-search-catalog.ts +1 -2
- package/src/__tests__/cloud-profile-guard.test.ts +2 -2
- package/src/__tests__/config-schema.test.ts +6 -38
- package/src/__tests__/conversation-queue.test.ts +45 -6
- package/src/__tests__/db-readiness-http-gate.test.ts +0 -6
- package/src/__tests__/persist-onboarding-artifacts.test.ts +0 -1
- package/src/__tests__/persona-resolver.test.ts +0 -51
- package/src/__tests__/provider-cloud-proxy-integration.test.ts +2 -110
- package/src/__tests__/run-due-schedules.test.ts +0 -4
- package/src/__tests__/schedule-store.test.ts +0 -12
- package/src/__tests__/stt-stream-session.test.ts +4 -4
- package/src/__tests__/telephony-tts-guard.test.ts +2 -50
- package/src/__tests__/voice-config-update.test.ts +12 -167
- package/src/__tests__/web-search-catalog-parity.test.ts +0 -2
- package/src/__tests__/workspace-migration-130-speech-mode-to-provider.test.ts +9 -7
- package/src/__tests__/workspace-migration-132-web-search-mode-to-provider.test.ts +6 -6
- package/src/calls/__tests__/voice-session-bridge.test.ts +1 -4
- package/src/calls/resolve-call-tts-provider.ts +6 -25
- package/src/calls/telephony-credential-preflight.ts +0 -10
- package/src/calls/telephony-tts-capability.ts +1 -17
- package/src/cli/commands/tts.ts +1 -2
- package/src/cli/index.help.ts +0 -2
- package/src/cli/program.ts +0 -2
- package/src/config/bundled-skills/settings/tools/voice-config-update.ts +4 -42
- package/src/config/schemas/__tests__/stt.test.ts +10 -14
- package/src/config/schemas/services.ts +5 -6
- package/src/config/schemas/stt.ts +1 -3
- package/src/config/schemas/tts.ts +1 -30
- package/src/daemon/daemon-readiness.ts +4 -29
- package/src/daemon/lifecycle.ts +0 -31
- package/src/daemon/providers-setup.ts +0 -8
- package/src/heartbeat/__tests__/heartbeat-service.test.ts +0 -1
- package/src/heartbeat/heartbeat-service.ts +1 -66
- package/src/ipc/__tests__/db-readiness-ipc-gate.test.ts +1 -9
- package/src/live-voice/__tests__/live-voice-credential-preflight.test.ts +0 -44
- package/src/live-voice/__tests__/live-voice-flux-turn-end.test.ts +4 -6
- package/src/live-voice/__tests__/live-voice-stt.test.ts +1 -1
- package/src/live-voice/live-voice-credential-preflight.ts +9 -33
- package/src/live-voice/live-voice-session.ts +10 -6
- package/src/live-voice/live-voice-tts.ts +1 -8
- package/src/plugins/defaults/memory/worker.ts +3 -3
- package/src/prompts/persona-resolver.ts +0 -35
- package/src/providers/__tests__/search-provider-catalog.test.ts +5 -8
- package/src/providers/__tests__/voice-error-copy.test.ts +9 -10
- package/src/providers/search-provider-catalog.ts +7 -39
- package/src/providers/speech-to-text/__tests__/provider-catalog.test.ts +3 -47
- package/src/providers/speech-to-text/__tests__/resolve.test.ts +6 -372
- package/src/providers/speech-to-text/provider-catalog.ts +2 -73
- package/src/providers/speech-to-text/resolve.ts +3 -120
- package/src/runtime/http-router-types.ts +1 -3
- package/src/runtime/http-server.ts +1 -1
- package/src/runtime/routes/__tests__/tts-routes.test.ts +2 -6
- package/src/runtime/routes/inbound-stages/transcribe-audio.test.ts +7 -7
- package/src/runtime/routes/index.ts +0 -4
- package/src/runtime/routes/live-voice-routes.test.ts +4 -11
- package/src/runtime/routes/live-voice-routes.ts +8 -11
- package/src/runtime/routes/secret-routes.ts +0 -6
- package/src/runtime/routes/tts-routes.ts +0 -38
- package/src/schedule/__tests__/plugin-schedule-reconciler.test.ts +1 -7
- package/src/schedule/__tests__/worker-mcp-readiness.test.ts +0 -4
- package/src/schedule/schedule-store.ts +0 -7
- package/src/schedule/scheduler.ts +0 -5
- package/src/schedule/worker.ts +1 -1
- package/src/stt/__tests__/daemon-batch-transcriber.test.ts +2 -10
- package/src/stt/daemon-batch-transcriber.ts +4 -38
- package/src/stt/types.ts +1 -9
- package/src/tools/network/__tests__/web-search.test.ts +3 -250
- package/src/tools/network/web-search.ts +4 -165
- package/src/tts/__tests__/provider-resolution.test.ts +0 -5
- package/src/tts/provider-catalog.ts +0 -4
- package/src/tts/types.ts +0 -1
- package/src/__tests__/cloud-speech-defaults.test.ts +0 -330
- package/src/__tests__/migration-cross-version-compatibility.test.ts +0 -1708
- package/src/__tests__/migration-export-http.test.ts +0 -557
- package/src/__tests__/migration-export-streaming.test.ts +0 -350
- package/src/__tests__/migration-export-to-gcs.test.ts +0 -706
- package/src/__tests__/migration-import-commit-http.test.ts +0 -1176
- package/src/__tests__/migration-import-from-gcs.test.ts +0 -534
- package/src/__tests__/migration-import-from-path.test.ts +0 -324
- package/src/__tests__/migration-import-from-url.test.ts +0 -588
- package/src/__tests__/migration-import-preflight-http.test.ts +0 -739
- package/src/__tests__/migration-jobs-status.test.ts +0 -139
- package/src/__tests__/migration-parity-persistence.test.ts +0 -1891
- package/src/__tests__/migration-transport.test.ts +0 -1089
- package/src/__tests__/migration-validate-http.test.ts +0 -634
- package/src/__tests__/migration-wizard.test.ts +0 -1395
- package/src/__tests__/rebind-secrets-screen.test.ts +0 -876
- package/src/__tests__/sanitize-config-for-transfer.test.ts +0 -259
- package/src/__tests__/transfer-progress-screen.test.ts +0 -1217
- package/src/__tests__/validation-results-screen.test.ts +0 -1130
- package/src/__tests__/vbundle-pax-and-symlink.test.ts +0 -147
- package/src/background-wake/background-wake-routes.test.ts +0 -906
- package/src/background-wake/cloud-client.test.ts +0 -328
- package/src/background-wake/cloud-client.ts +0 -196
- package/src/background-wake/next-wake.test.ts +0 -335
- package/src/background-wake/next-wake.ts +0 -188
- package/src/background-wake/publisher.ts +0 -93
- package/src/background-wake/wake-intent-hooks.test.ts +0 -234
- package/src/cli/commands/__tests__/backup.test.ts +0 -363
- package/src/cli/commands/backup.help.ts +0 -180
- package/src/cli/commands/backup.ts +0 -398
- package/src/cloud/cloud-speech.test.ts +0 -335
- package/src/cloud/cloud-speech.ts +0 -300
- package/src/config/cloud-speech-defaults.ts +0 -300
- package/src/config/sanitize-for-transfer.ts +0 -111
- package/src/live-voice/__tests__/live-voice-cloud-speech-fallback.test.ts +0 -250
- package/src/providers/speech-to-text/__tests__/cadet-cloud-realtime.test.ts +0 -457
- package/src/providers/speech-to-text/__tests__/cadet-cloud.test.ts +0 -271
- package/src/providers/speech-to-text/__tests__/cadet-speech-relay-connection.test.ts +0 -126
- package/src/providers/speech-to-text/cadet-cloud-flux-realtime.ts +0 -309
- package/src/providers/speech-to-text/cadet-cloud-realtime.ts +0 -315
- package/src/providers/speech-to-text/cadet-cloud.ts +0 -108
- package/src/providers/speech-to-text/cadet-speech-relay-connection.ts +0 -176
- package/src/runtime/migrations/__tests__/gcs-signed-url.test.ts +0 -254
- package/src/runtime/migrations/__tests__/job-registry.test.ts +0 -346
- package/src/runtime/migrations/__tests__/origin-mode.test.ts +0 -62
- package/src/runtime/migrations/__tests__/rebind-secrets-credentials.test.ts +0 -184
- package/src/runtime/migrations/__tests__/staged-import-path.test.ts +0 -110
- package/src/runtime/migrations/__tests__/v1-test-helpers.ts +0 -112
- package/src/runtime/migrations/__tests__/vbundle-builder-credentials.test.ts +0 -285
- package/src/runtime/migrations/__tests__/vbundle-builder-fd-leak.test.ts +0 -126
- package/src/runtime/migrations/__tests__/vbundle-builder-v1-shape.test.ts +0 -253
- package/src/runtime/migrations/__tests__/vbundle-import-credentials.test.ts +0 -208
- package/src/runtime/migrations/__tests__/vbundle-import-parity.test.ts +0 -485
- package/src/runtime/migrations/__tests__/vbundle-import-policy.test.ts +0 -349
- package/src/runtime/migrations/__tests__/vbundle-import-version-compat.test.ts +0 -196
- package/src/runtime/migrations/__tests__/vbundle-legacy-user-md.test.ts +0 -551
- package/src/runtime/migrations/__tests__/vbundle-metadata-merge-integration.test.ts +0 -428
- package/src/runtime/migrations/__tests__/vbundle-metadata-merge.test.ts +0 -220
- package/src/runtime/migrations/__tests__/vbundle-streaming-importer.test.ts +0 -1823
- package/src/runtime/migrations/__tests__/vbundle-streaming-validator.test.ts +0 -598
- package/src/runtime/migrations/__tests__/vbundle-symlink-importer.test.ts +0 -463
- package/src/runtime/migrations/__tests__/vbundle-symlink-streaming-importer.test.ts +0 -538
- package/src/runtime/migrations/__tests__/vbundle-symlink-streaming.test.ts +0 -515
- package/src/runtime/migrations/__tests__/vbundle-symlink-tar.test.ts +0 -453
- package/src/runtime/migrations/__tests__/vbundle-symlink-walker.test.ts +0 -319
- package/src/runtime/migrations/__tests__/vbundle-tar-stream.test.ts +0 -240
- package/src/runtime/migrations/__tests__/vbundle-validator-v1-schema.test.ts +0 -473
- package/src/runtime/migrations/gcs-signed-url.ts +0 -190
- package/src/runtime/migrations/job-registry.ts +0 -297
- package/src/runtime/migrations/migration-transport.ts +0 -612
- package/src/runtime/migrations/migration-wizard.ts +0 -747
- package/src/runtime/migrations/origin-mode.ts +0 -42
- package/src/runtime/migrations/rebind-secrets-screen.ts +0 -412
- package/src/runtime/migrations/staged-import-path.ts +0 -116
- package/src/runtime/migrations/transfer-progress-screen.ts +0 -323
- package/src/runtime/migrations/validation-results-screen.ts +0 -469
- package/src/runtime/migrations/vbundle-builder.ts +0 -1382
- package/src/runtime/migrations/vbundle-import-analyzer.ts +0 -405
- package/src/runtime/migrations/vbundle-import-policy.ts +0 -241
- package/src/runtime/migrations/vbundle-importer.ts +0 -826
- package/src/runtime/migrations/vbundle-metadata-merge.ts +0 -113
- package/src/runtime/migrations/vbundle-streaming-importer.ts +0 -2844
- package/src/runtime/migrations/vbundle-streaming-validator.ts +0 -426
- package/src/runtime/migrations/vbundle-tar-stream.ts +0 -244
- package/src/runtime/migrations/vbundle-validator.ts +0 -724
- package/src/runtime/routes/__tests__/migration-cadet-metadata-reconcile.test.ts +0 -227
- package/src/runtime/routes/__tests__/migration-export-secrets-redacted.test.ts +0 -54
- package/src/runtime/routes/__tests__/migration-import-allowed-hosts-env.test.ts +0 -70
- package/src/runtime/routes/__tests__/migration-import-credential-filter.test.ts +0 -257
- package/src/runtime/routes/background-wake-routes.ts +0 -387
- package/src/runtime/routes/migration-routes.ts +0 -2584
- package/src/tools/network/__tests__/cloud-search-proxy.test.ts +0 -282
- package/src/tools/network/cloud-search-proxy.ts +0 -211
- package/src/tts/__tests__/cadet-provider.test.ts +0 -253
- package/src/tts/providers/cadet-provider.ts +0 -244
- 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.
|
|
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
|
|
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 =
|
|
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: "
|
|
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("
|
|
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
|
-
|
|
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.
|
|
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"
|
|
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: {
|
|
2070
|
+
services: { tts: { provider: providerId } },
|
|
2097
2071
|
});
|
|
2098
2072
|
const resolved = resolveTtsConfig(config);
|
|
2099
2073
|
expect(resolved.provider).toBe(providerId);
|
|
2100
|
-
|
|
2101
|
-
|
|
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
|
-
|
|
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
|
-
|
|
3931
|
-
|
|
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
|
-
|
|
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);
|
|
@@ -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: (
|
|
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
|
|
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
|
|
144
|
-
*
|
|
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 = "
|
|
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("
|
|
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("
|
|
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("
|
|
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
|
-
});
|