Skip to content

Commit b20d940

Browse files
committed
test: repair full-suite drift against current runtime contracts
Partial module mocks gain the attachGenAiAttributes export the chat terminals now call, and the api/runtime suites reset the module-global provider-health circuit between tests so one intentional failure burst cannot open the breaker for the rest of the file. The Anthropic transport tests pin maxRetries to 1 (the retry-era default re-reads a one-shot mock Response and masks the intended error) and the thinking-replay coverage now exercises both sides of the per-model split: strip on non-retaining models, verbatim replay on retaining ones. The OpenRouter session tests spy on the axios client seam instead of global fetch, mapOpenRouterUsage expectations carry inclusiveInputTokens, orchestration default-model pins move to claude-sonnet-4-6, assembleForPrompt expectations follow the maxTierRank option and embed dedup, the ExtensionLoader child_process mock exports execFile, and the container-repair fixture uses correctly escaped string-encoded JSON.
1 parent d3bfa61 commit b20d940

15 files changed

Lines changed: 125 additions & 39 deletions

src/api/runtime/__tests__/agentPromptEngine.test.ts

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33
* Tests for PromptEngine, Memory, and Skills integration in agent().
44
*/
55
import { describe, expect, it, vi, beforeEach } from 'vitest';
6+
import { globalLLMProviderHealth } from '../../../core/safety/LLMProviderHealthRegistry.js';
67

78
const mockGenerateCompletion = vi.hoisted(() =>
89
vi.fn().mockResolvedValue({
@@ -38,9 +39,16 @@ vi.mock('../../model.js', () => ({
3839

3940
vi.mock('../../observability.js', () => ({
4041
attachUsageAttributes: vi.fn(),
42+
attachGenAiAttributes: vi.fn(),
4143
toTurnMetricUsage: vi.fn().mockReturnValue({}),
4244
}));
4345

46+
// The provider-health circuit is module-global state: one test's intentional
47+
// failure burst must not open the breaker for the rest of the file.
48+
beforeEach(() => {
49+
globalLLMProviderHealth.reset();
50+
});
51+
4452
vi.mock('../../../evaluation/observability/otel.js', () => ({
4553
withAgentOSSpan: vi.fn((_name: string, _attrs: unknown, fn?: Function) => {
4654
const callback = fn ?? _attrs;

src/api/runtime/__tests__/analyzeVideo.test.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -66,6 +66,7 @@ vi.mock('../../../io/hearing/providers/OpenAIWhisperSpeechToTextProvider.js', ()
6666
// Mock observability to avoid OTel dependencies
6767
vi.mock('../../observability.js', () => ({
6868
attachUsageAttributes: vi.fn(),
69+
attachGenAiAttributes: vi.fn(),
6970
toTurnMetricUsage: vi.fn().mockReturnValue(undefined),
7071
}));
7172

src/api/runtime/__tests__/generateMusic.test.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -82,6 +82,7 @@ vi.mock('../../../media/audio/index.js', () => {
8282

8383
vi.mock('../../observability.js', () => ({
8484
attachUsageAttributes: vi.fn(),
85+
attachGenAiAttributes: vi.fn(),
8586
toTurnMetricUsage: vi.fn().mockReturnValue(undefined),
8687
}));
8788

src/api/runtime/__tests__/generateObject.test.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -911,7 +911,7 @@ describe('string-encoded container repair', () => {
911911
),
912912
});
913913
hoisted.generateCompletion.mockResolvedValue(
914-
mockResponse('{"verdicts":"[{\"trackId\":\"t\",\"verdict\":\"purple\"}]"}'),
914+
mockResponse('{"verdicts":"[{\\"trackId\\":\\"t\\",\\"verdict\\":\\"purple\\"}]"}'),
915915
);
916916

917917
const err = await generateObject({

src/api/runtime/__tests__/generateSFX.test.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -82,6 +82,7 @@ vi.mock('../../../media/audio/index.js', () => {
8282

8383
vi.mock('../../observability.js', () => ({
8484
attachUsageAttributes: vi.fn(),
85+
attachGenAiAttributes: vi.fn(),
8586
toTurnMetricUsage: vi.fn().mockReturnValue(undefined),
8687
}));
8788

src/api/runtime/__tests__/generateVideo.test.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -80,6 +80,7 @@ vi.mock('../../../io/media/video/index.js', () => {
8080

8181
vi.mock('../../observability.js', () => ({
8282
attachUsageAttributes: vi.fn(),
83+
attachGenAiAttributes: vi.fn(),
8384
toTurnMetricUsage: vi.fn().mockReturnValue(undefined),
8485
}));
8586

src/api/runtime/__tests__/generationHooks.test.ts

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33
* Tests for generation lifecycle hooks on generateText/streamText.
44
*/
55
import { describe, expect, it, vi, beforeEach } from 'vitest';
6+
import { globalLLMProviderHealth } from '../../../core/safety/LLMProviderHealthRegistry.js';
67

78
const mockGenerateCompletion = vi.hoisted(() =>
89
vi.fn().mockResolvedValue({
@@ -42,9 +43,16 @@ vi.mock('../../model.js', () => ({
4243

4344
vi.mock('../../observability.js', () => ({
4445
attachUsageAttributes: vi.fn(),
46+
attachGenAiAttributes: vi.fn(),
4547
toTurnMetricUsage: vi.fn().mockReturnValue({}),
4648
}));
4749

50+
// The provider-health circuit is module-global state: one test's intentional
51+
// failure burst must not open the breaker for the rest of the file.
52+
beforeEach(() => {
53+
globalLLMProviderHealth.reset();
54+
});
55+
4856
vi.mock('../../../evaluation/observability/otel.js', () => ({
4957
withAgentOSSpan: vi.fn((_name: string, _attrs: unknown, fn?: Function) => {
5058
const callback = fn ?? _attrs;

src/api/runtime/__tests__/modelRouter.test.ts

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33
* Tests for ModelRouter integration into generateText/streamText/agent.
44
*/
55
import { describe, expect, it, vi, beforeEach } from 'vitest';
6+
import { globalLLMProviderHealth } from '../../../core/safety/LLMProviderHealthRegistry.js';
67

78
const mockGenerateCompletion = vi.hoisted(() =>
89
vi.fn().mockResolvedValue({
@@ -50,9 +51,16 @@ vi.mock('../../model.js', () => ({
5051

5152
vi.mock('../../observability.js', () => ({
5253
attachUsageAttributes: vi.fn(),
54+
attachGenAiAttributes: vi.fn(),
5355
toTurnMetricUsage: vi.fn().mockReturnValue({}),
5456
}));
5557

58+
// The provider-health circuit is module-global state: one test's intentional
59+
// failure burst must not open the breaker for the rest of the file.
60+
beforeEach(() => {
61+
globalLLMProviderHealth.reset();
62+
});
63+
5664
vi.mock('../../../evaluation/observability/otel.js', () => ({
5765
withAgentOSSpan: vi.fn((_name: string, _attrs: unknown, fn?: Function) => {
5866
const callback = fn ?? _attrs;

src/cognition/memory/__tests__/AgentMemory.mood-args.test.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -51,12 +51,12 @@ describe('AgentMemory.getContext mood arg', () => {
5151
it('omitted → NEUTRAL passed to assembleForPrompt', async () => {
5252
const { mem, manager } = cognitiveMemoryWithManagerSpy();
5353
await mem.getContext('q', { tokenBudget: 1000 });
54-
expect(manager.assembleForPrompt).toHaveBeenCalledWith('q', 1000, { valence: 0, arousal: 0, dominance: 0 });
54+
expect(manager.assembleForPrompt).toHaveBeenCalledWith('q', 1000, { valence: 0, arousal: 0, dominance: 0 }, { maxTierRank: undefined });
5555
});
5656
it('supplied currentMood passes through; default budget 2000 preserved', async () => {
5757
const { mem, manager } = cognitiveMemoryWithManagerSpy();
5858
await mem.getContext('q', { currentMood: { valence: 0.4, arousal: 0.2, dominance: 0 } });
59-
expect(manager.assembleForPrompt).toHaveBeenCalledWith('q', 2000, { valence: 0.4, arousal: 0.2, dominance: 0 });
59+
expect(manager.assembleForPrompt).toHaveBeenCalledWith('q', 2000, { valence: 0.4, arousal: 0.2, dominance: 0 }, { maxTierRank: undefined });
6060
});
6161
});
6262

src/cognition/memory/__tests__/assemble-for-prompt-concurrency.test.ts

Lines changed: 12 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -118,17 +118,27 @@ describe('assembleForPrompt concurrency', () => {
118118
return { documents: [] };
119119
});
120120

121+
const checkSpy = vi.spyOn(
122+
(manager as unknown as { prospective: { check: (...a: unknown[]) => Promise<unknown[]> } })
123+
.prospective,
124+
'check',
125+
);
126+
121127
const pending = manager.assembleForPrompt('what did we plan for friday', 2048, MOOD);
122128

123129
// Let the event loop drain everything that isn't blocked on the latch.
124130
await new Promise((resolve) => setTimeout(resolve, 25));
125131

126132
// Serial implementation: neither fires until retrieve() resolves.
127-
// Concurrent implementation: both have already started.
133+
// Concurrent implementation: both have already started. Identical query
134+
// embeds can be served from the embedding cache (one manager hit shared
135+
// by the store and prospective paths), so assert the prospective stage
136+
// itself ran during the latch window instead of counting embed calls.
128137
expect(persistentRead).toHaveBeenCalledTimes(1);
138+
expect(checkSpy).toHaveBeenCalledTimes(1);
129139
expect(
130140
mocks.mockEmbeddingManager.generateEmbeddings.mock.calls.length,
131-
).toBeGreaterThanOrEqual(2); // store's query embed + prospective's query embed
141+
).toBeGreaterThanOrEqual(1);
132142

133143
releaseQuery();
134144
const out = await pending;

0 commit comments

Comments
 (0)