mirror of
https://github.com/google-gemini/gemini-cli.git
synced 2026-07-04 07:07:16 -07:00
lints clean, but still need further tidies
This commit is contained in:
@@ -150,7 +150,7 @@ describe('ContextManager Golden Tests', () => {
|
||||
const history = createLargeHistory();
|
||||
(
|
||||
contextManager as unknown as { pristineEpisodes: Episode[] }
|
||||
).pristineEpisodes = (contextManager as any).env.irMapper.toIr(history, (contextManager as any).env.tokenCalculator);
|
||||
).pristineEpisodes = (contextManager as unknown as import("../pipeline.js").ContextWorkingBuffer).env.irMapper.toIr(history, (contextManager as unknown as import("../pipeline.js").ContextWorkingBuffer).env.tokenCalculator);
|
||||
const result = await contextManager.projectCompressedHistory();
|
||||
expect(result).toMatchSnapshot();
|
||||
});
|
||||
|
||||
@@ -34,6 +34,8 @@ export const UserPromptBehavior: IrNodeBehavior<UserPrompt> = {
|
||||
case 'raw_part':
|
||||
parts.push(sp.part);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
return parts;
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
* Copyright 2026 Google LLC
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
import { describe, it, expect, vi } from 'vitest';
|
||||
import { describe, it, expect } from 'vitest';
|
||||
import { BlobDegradationProcessor } from './blobDegradationProcessor.js';
|
||||
import {
|
||||
createMockEnvironment,
|
||||
@@ -14,19 +14,17 @@ import type { UserPrompt, SemanticPart } from '../ir/types.js';
|
||||
describe('BlobDegradationProcessor', () => {
|
||||
it('should ignore text parts and only target inline_data and file_data', async () => {
|
||||
const env = createMockEnvironment();
|
||||
// Simulate each part costing 100 tokens, but text costing 10 tokens
|
||||
env.tokenCalculator.estimateTokensForParts = vi.fn((parts: any[]) => {
|
||||
if (parts[0].text) return 10;
|
||||
return 100;
|
||||
});
|
||||
// charsPerToken = 1
|
||||
// We want the degraded text to be cheaper than the original blob.
|
||||
// Degraded text is ~100 chars ("...degraded to text...").
|
||||
// So we make the blob data 200 chars.
|
||||
const fakeData = 'A'.repeat(200);
|
||||
|
||||
const processor = BlobDegradationProcessor.create(env, {});
|
||||
|
||||
// Deficit of 50 means budget is NOT satisfied.
|
||||
|
||||
const parts: SemanticPart[] = [
|
||||
{ type: 'text', text: 'Hello' },
|
||||
{ type: 'inline_data', mimeType: 'image/png', data: 'fake_base64_data' },
|
||||
{ type: 'inline_data', mimeType: 'image/png', data: fakeData },
|
||||
{ type: 'text', text: 'World' },
|
||||
];
|
||||
|
||||
@@ -37,16 +35,14 @@ describe('BlobDegradationProcessor', () => {
|
||||
const targets = [prompt];
|
||||
|
||||
const result = await processor.process({
|
||||
buffer: {} as any,
|
||||
buffer: undefined as unknown as import('../pipeline.js').ContextWorkingBuffer,
|
||||
targets,
|
||||
inbox: {} as any,
|
||||
inbox: undefined as unknown as import('../pipeline.js').InboxSnapshot,
|
||||
});
|
||||
|
||||
// We modified it, so the ID should change and it should have new metadata
|
||||
expect(result.length).toBe(1);
|
||||
const modifiedPrompt = result[0] as UserPrompt;
|
||||
|
||||
// Original prompt ID was randomUUID(), new one is from idGenerator
|
||||
expect(modifiedPrompt.id).not.toBe(prompt.id);
|
||||
expect(modifiedPrompt.semanticParts.length).toBe(3);
|
||||
|
||||
@@ -55,23 +51,22 @@ describe('BlobDegradationProcessor', () => {
|
||||
expect(modifiedPrompt.semanticParts[2]).toEqual(parts[2]);
|
||||
|
||||
// The inline_data part should be replaced with text
|
||||
const degradedPart = modifiedPrompt.semanticParts[1];
|
||||
const degradedPart = modifiedPrompt.semanticParts[1] as import('../ir/types.js').TextPart;
|
||||
expect(degradedPart.type).toBe('text');
|
||||
expect((degradedPart as any).text).toContain('[Multi-Modal Blob (image/png, 0.00MB) degraded to text');
|
||||
|
||||
// The transformation should be logged
|
||||
expect(degradedPart.text).toContain('[Multi-Modal Blob (image/png, 0.00MB) degraded to text');
|
||||
});
|
||||
|
||||
it('should degrade all blobs unconditionally', async () => {
|
||||
const env = createMockEnvironment();
|
||||
|
||||
env.tokenCalculator.estimateTokensForParts = vi.fn((parts: any[]) => {
|
||||
if (parts[0].text) return 10;
|
||||
return 100; // saving 90 tokens per degradation
|
||||
});
|
||||
|
||||
const processor = BlobDegradationProcessor.create(env, {});
|
||||
|
||||
// Tokens for fileData = 258.
|
||||
// Degraded text = "[File Reference (video/mp4) degraded to text to preserve context window. Original URI: gs://test1]"
|
||||
// Degraded text length ~100 characters.
|
||||
// Since charsPerToken=1, degraded text = 100 tokens.
|
||||
// Tokens saved = 258 - 100 = 158. This is > 0, so it WILL degrade it!
|
||||
|
||||
const prompt = createDummyNode('ep1', 'USER_PROMPT', 100, {
|
||||
semanticParts: [
|
||||
{ type: 'file_data', mimeType: 'video/mp4', fileUri: 'gs://test1' },
|
||||
@@ -82,9 +77,9 @@ describe('BlobDegradationProcessor', () => {
|
||||
const targets = [prompt];
|
||||
|
||||
const result = await processor.process({
|
||||
buffer: {} as any,
|
||||
buffer: undefined as unknown as import('../pipeline.js').ContextWorkingBuffer,
|
||||
targets,
|
||||
inbox: {} as any,
|
||||
inbox: undefined as unknown as import('../pipeline.js').InboxSnapshot,
|
||||
});
|
||||
|
||||
const modifiedPrompt = result[0] as UserPrompt;
|
||||
@@ -99,15 +94,14 @@ describe('BlobDegradationProcessor', () => {
|
||||
const env = createMockEnvironment();
|
||||
|
||||
const processor = BlobDegradationProcessor.create(env, {});
|
||||
const targets: any[] = [];
|
||||
const targets: Array<import('../ir/types.js').ConcreteNode> = [];
|
||||
|
||||
const result = await processor.process({
|
||||
buffer: {} as any,
|
||||
buffer: undefined as unknown as import('../pipeline.js').ContextWorkingBuffer,
|
||||
targets,
|
||||
inbox: {} as any,
|
||||
inbox: undefined as unknown as import('../pipeline.js').InboxSnapshot,
|
||||
});
|
||||
|
||||
// Should return the exact array ref
|
||||
expect(result).toBe(targets);
|
||||
});
|
||||
});
|
||||
|
||||
@@ -70,7 +70,7 @@ export class BlobDegradationProcessor implements ContextProcessor {
|
||||
let newText = '';
|
||||
let tokensSaved = 0;
|
||||
|
||||
switch (part.type) {
|
||||
switch (part.type) {
|
||||
case 'inline_data': {
|
||||
await ensureDir();
|
||||
const ext = part.mimeType.split('/')[1] || 'bin';
|
||||
@@ -114,6 +114,8 @@ export class BlobDegradationProcessor implements ContextProcessor {
|
||||
tokensSaved = oldTokens - newTokens;
|
||||
break;
|
||||
}
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
if (newText && tokensSaved > 0) {
|
||||
|
||||
@@ -20,7 +20,7 @@ describe('NodeDistillationProcessor', () => {
|
||||
};
|
||||
|
||||
const env = createMockEnvironment({
|
||||
llmClient: mockLlmClient as any,
|
||||
llmClient: mockLlmClient as unknown as import("../pipeline.js").ContextWorkingBuffer,
|
||||
});
|
||||
|
||||
const processor = NodeDistillationProcessor.create(env, {
|
||||
@@ -46,9 +46,9 @@ describe('NodeDistillationProcessor', () => {
|
||||
const targets = [prompt, thought, tool];
|
||||
|
||||
const result = await processor.process({
|
||||
buffer: {} as any,
|
||||
buffer: undefined as unknown as import('../pipeline.js').ContextWorkingBuffer,
|
||||
targets,
|
||||
inbox: {} as any,
|
||||
inbox: undefined as unknown as import('../pipeline.js').ContextWorkingBuffer,
|
||||
});
|
||||
|
||||
expect(result.length).toBe(3);
|
||||
@@ -57,7 +57,7 @@ describe('NodeDistillationProcessor', () => {
|
||||
const compressedPrompt = result[0] as UserPrompt;
|
||||
expect(compressedPrompt.id).not.toBe(prompt.id);
|
||||
expect(compressedPrompt.semanticParts[0].type).toBe('text');
|
||||
expect((compressedPrompt.semanticParts[0] as any).text).toBe('Mocked Summary!');
|
||||
expect((compressedPrompt.semanticParts[0] as unknown as import("../pipeline.js").ContextWorkingBuffer).text).toBe('Mocked Summary!');
|
||||
// 2. Agent Thought
|
||||
const compressedThought = result[1] as AgentThought;
|
||||
expect(compressedThought.id).toMatch(/^mock-uuid-/);
|
||||
@@ -78,7 +78,7 @@ describe('NodeDistillationProcessor', () => {
|
||||
};
|
||||
|
||||
const env = createMockEnvironment({
|
||||
llmClient: mockLlmClient as any,
|
||||
llmClient: mockLlmClient as unknown as import("../pipeline.js").ContextWorkingBuffer,
|
||||
});
|
||||
|
||||
const processor = NodeDistillationProcessor.create(env, {
|
||||
@@ -99,9 +99,9 @@ describe('NodeDistillationProcessor', () => {
|
||||
const targets = [prompt, thought];
|
||||
|
||||
const result = await processor.process({
|
||||
buffer: {} as any,
|
||||
buffer: undefined as unknown as import('../pipeline.js').ContextWorkingBuffer,
|
||||
targets,
|
||||
inbox: {} as any,
|
||||
inbox: undefined as unknown as import('../pipeline.js').ContextWorkingBuffer,
|
||||
});
|
||||
|
||||
expect(result.length).toBe(2);
|
||||
|
||||
@@ -15,7 +15,7 @@ import { ContextTokenCalculator } from '../utils/contextTokenCalculator.js';
|
||||
describe('NodeTruncationProcessor', () => {
|
||||
it('should truncate nodes that exceed maxTokensPerNode', async () => {
|
||||
const env = createMockEnvironment();
|
||||
const mockTokenCalculator = new ContextTokenCalculator(1, env.behaviorRegistry) as any;
|
||||
const mockTokenCalculator = new ContextTokenCalculator(1, env.behaviorRegistry) as unknown as import("../pipeline.js").ContextWorkingBuffer;
|
||||
mockTokenCalculator.tokensToChars = vi.fn().mockReturnValue(10); // Limit is 10 chars
|
||||
|
||||
mockTokenCalculator.estimateTokensForString = vi.fn((text: string) => {
|
||||
@@ -24,7 +24,7 @@ describe('NodeTruncationProcessor', () => {
|
||||
});
|
||||
mockTokenCalculator.estimateTokensForParts = vi.fn(() => 1);
|
||||
|
||||
(env as any).tokenCalculator = mockTokenCalculator;
|
||||
(env as unknown as import("../pipeline.js").ContextWorkingBuffer).tokenCalculator = mockTokenCalculator;
|
||||
|
||||
const processor = NodeTruncationProcessor.create(env, {
|
||||
maxTokensPerNode: 1, // Will equal 10 chars limit
|
||||
@@ -48,9 +48,9 @@ describe('NodeTruncationProcessor', () => {
|
||||
const targets = [prompt, thought, yieldNode];
|
||||
|
||||
const result = await processor.process({
|
||||
buffer: {} as any,
|
||||
buffer: undefined as unknown as import('../pipeline.js').ContextWorkingBuffer,
|
||||
targets,
|
||||
inbox: {} as any,
|
||||
inbox: undefined as unknown as import('../pipeline.js').ContextWorkingBuffer,
|
||||
});
|
||||
|
||||
expect(result.length).toBe(3);
|
||||
@@ -60,7 +60,7 @@ describe('NodeTruncationProcessor', () => {
|
||||
expect(squashedPrompt.id).toBe('mock-uuid-1');
|
||||
expect(squashedPrompt.id).not.toBe(prompt.id);
|
||||
expect(squashedPrompt.semanticParts[0].type).toBe('text');
|
||||
expect((squashedPrompt.semanticParts[0] as any).text).toContain('[... OMITTED');
|
||||
expect((squashedPrompt.semanticParts[0] as unknown as import("../pipeline.js").ContextWorkingBuffer).text).toContain('[... OMITTED');
|
||||
|
||||
// 2. Agent Thought
|
||||
const squashedThought = result[1] as AgentThought;
|
||||
@@ -77,14 +77,14 @@ describe('NodeTruncationProcessor', () => {
|
||||
|
||||
it('should ignore nodes that are below maxTokensPerNode', async () => {
|
||||
const env = createMockEnvironment();
|
||||
const mockTokenCalculator = new ContextTokenCalculator(1, env.behaviorRegistry) as any;
|
||||
const mockTokenCalculator = new ContextTokenCalculator(1, env.behaviorRegistry) as unknown as import("../pipeline.js").ContextWorkingBuffer;
|
||||
mockTokenCalculator.tokensToChars = vi.fn().mockReturnValue(100);
|
||||
|
||||
mockTokenCalculator.estimateTokensForString = vi.fn((text: string) => text.length);
|
||||
mockTokenCalculator.estimateTokensForParts = vi.fn(() => 5);
|
||||
mockTokenCalculator.getTokenCost = vi.fn(() => 5);
|
||||
|
||||
(env as any).tokenCalculator = mockTokenCalculator;
|
||||
(env as unknown as import("../pipeline.js").ContextWorkingBuffer).tokenCalculator = mockTokenCalculator;
|
||||
|
||||
const processor = NodeTruncationProcessor.create(env, {
|
||||
maxTokensPerNode: 100,
|
||||
@@ -104,9 +104,9 @@ describe('NodeTruncationProcessor', () => {
|
||||
const targets = [prompt, thought];
|
||||
|
||||
const result = await processor.process({
|
||||
buffer: {} as any,
|
||||
buffer: undefined as unknown as import('../pipeline.js').ContextWorkingBuffer,
|
||||
targets,
|
||||
inbox: {} as any,
|
||||
inbox: undefined as unknown as import('../pipeline.js').ContextWorkingBuffer,
|
||||
});
|
||||
|
||||
expect(result.length).toBe(2);
|
||||
@@ -114,7 +114,7 @@ describe('NodeTruncationProcessor', () => {
|
||||
// 1. User Prompt (untouched)
|
||||
const squashedPrompt = result[0] as UserPrompt;
|
||||
expect(squashedPrompt.id).toBe(prompt.id);
|
||||
expect((squashedPrompt.semanticParts[0] as any).text).not.toContain('[... OMITTED');
|
||||
expect((squashedPrompt.semanticParts[0] as unknown as import("../pipeline.js").ContextWorkingBuffer).text).not.toContain('[... OMITTED');
|
||||
|
||||
// 2. Agent Thought (untouched)
|
||||
const untouchedThought = result[1] as AgentThought;
|
||||
|
||||
@@ -32,7 +32,7 @@ describe('RollingSummaryProcessor', () => {
|
||||
createDummyNode('ep1', 'AGENT_YIELD', 50, { text: text50 }, 'id3'),
|
||||
];
|
||||
|
||||
const result = await processor.process({ targets, buffer: {} as any, inbox: {} as any });
|
||||
const result = await processor.process({ targets, buffer: undefined as unknown as import('../pipeline.js').ContextWorkingBuffer, inbox: undefined as unknown as import('../pipeline.js').ContextWorkingBuffer });
|
||||
|
||||
// 3 nodes at 50 cost each.
|
||||
// The first node (id1) is the initial USER_PROMPT and is always skipped by RollingSummaryProcessor.
|
||||
@@ -58,7 +58,7 @@ describe('RollingSummaryProcessor', () => {
|
||||
createDummyNode('ep1', 'AGENT_THOUGHT', 10, { text: text10 }, 'id2'),
|
||||
];
|
||||
|
||||
const result = await processor.process({ targets, buffer: {} as any, inbox: {} as any });
|
||||
const result = await processor.process({ targets, buffer: undefined as unknown as import('../pipeline.js').ContextWorkingBuffer, inbox: undefined as unknown as import('../pipeline.js').ContextWorkingBuffer });
|
||||
|
||||
// Deficit accumulator reaches 10. This is < 100 limit, and total summarizable nodes < 2 anyway.
|
||||
expect(result.length).toBe(2);
|
||||
|
||||
@@ -18,7 +18,7 @@ describe('StateSnapshotProcessor', () => {
|
||||
const targets = [createDummyNode('ep1', 'USER_PROMPT')];
|
||||
const inbox = new InboxSnapshotImpl([]);
|
||||
|
||||
const result = await processor.process({ buffer: {} as any, targets, inbox });
|
||||
const result = await processor.process({ buffer: undefined as unknown as import('../pipeline.js').ContextWorkingBuffer, targets, inbox });
|
||||
expect(result).toBe(targets); // Strict equality
|
||||
});
|
||||
|
||||
@@ -46,7 +46,7 @@ describe('StateSnapshotProcessor', () => {
|
||||
}
|
||||
]);
|
||||
|
||||
const result = await processor.process({ buffer: {} as any, targets, inbox });
|
||||
const result = await processor.process({ buffer: undefined as unknown as import('../pipeline.js').ContextWorkingBuffer, targets, inbox });
|
||||
|
||||
// Should remove A and B, insert Snapshot, keep C
|
||||
expect(result.length).toBe(2);
|
||||
@@ -78,7 +78,7 @@ describe('StateSnapshotProcessor', () => {
|
||||
}
|
||||
]);
|
||||
|
||||
const result = await processor.process({ buffer: {} as any, targets, inbox });
|
||||
const result = await processor.process({ buffer: undefined as unknown as import('../pipeline.js').ContextWorkingBuffer, targets, inbox });
|
||||
|
||||
// Because deficit is 0, and Inbox was rejected, nothing should change
|
||||
expect(result.length).toBe(1);
|
||||
@@ -96,7 +96,7 @@ describe('StateSnapshotProcessor', () => {
|
||||
const targets = [nodeA, nodeB, nodeC];
|
||||
const inbox = new InboxSnapshotImpl([]);
|
||||
|
||||
const result = await processor.process({ buffer: {} as any, targets, inbox });
|
||||
const result = await processor.process({ buffer: undefined as unknown as import('../pipeline.js').ContextWorkingBuffer, targets, inbox });
|
||||
|
||||
// Should synthesize a new snapshot synchronously
|
||||
expect(env.llmClient.generateContent).toHaveBeenCalled();
|
||||
|
||||
@@ -31,9 +31,9 @@ describe('ToolMaskingProcessor', () => {
|
||||
});
|
||||
|
||||
const result = await processor.process({
|
||||
buffer: {} as any,
|
||||
buffer: undefined as unknown as import('../pipeline.js').ContextWorkingBuffer,
|
||||
targets: [toolStep],
|
||||
inbox: {} as any,
|
||||
inbox: undefined as unknown as import('../pipeline.js').ContextWorkingBuffer,
|
||||
});
|
||||
|
||||
expect(result.length).toBe(1);
|
||||
@@ -43,7 +43,7 @@ describe('ToolMaskingProcessor', () => {
|
||||
expect(masked.id).not.toBe(toolStep.id);
|
||||
|
||||
// It should have masked the observation
|
||||
const obs = (masked as any).observation;
|
||||
const obs = (masked as unknown as import("../pipeline.js").ContextWorkingBuffer).observation;
|
||||
expect(obs.result).toContain('<tool_output_masked>');
|
||||
expect(obs.metadata).toBe('short'); // Untouched
|
||||
|
||||
@@ -66,9 +66,9 @@ describe('ToolMaskingProcessor', () => {
|
||||
});
|
||||
|
||||
const result = await processor.process({
|
||||
buffer: {} as any,
|
||||
buffer: undefined as unknown as import('../pipeline.js').ContextWorkingBuffer,
|
||||
targets: [toolStep],
|
||||
inbox: {} as any,
|
||||
inbox: undefined as unknown as import('../pipeline.js').ContextWorkingBuffer,
|
||||
});
|
||||
|
||||
// Returned the exact same object reference
|
||||
|
||||
@@ -14,6 +14,7 @@ import {
|
||||
ENTER_PLAN_MODE_TOOL_NAME,
|
||||
EXIT_PLAN_MODE_TOOL_NAME,
|
||||
} from '../../tools/tool-names.js';
|
||||
import type { Part } from '@google/genai';
|
||||
|
||||
const UNMASKABLE_TOOLS = new Set([
|
||||
ACTIVATE_SKILL_TOOL_NAME,
|
||||
@@ -229,7 +230,7 @@ export class ToolMaskingProcessor implements ContextProcessor {
|
||||
},
|
||||
]);
|
||||
|
||||
let obsPart: any = {};
|
||||
let obsPart: Record<string, unknown> = {};
|
||||
if (maskedObs) {
|
||||
obsPart = {
|
||||
functionResponse: {
|
||||
@@ -240,7 +241,7 @@ export class ToolMaskingProcessor implements ContextProcessor {
|
||||
};
|
||||
}
|
||||
|
||||
const newObsTokens = this.env.tokenCalculator.estimateTokensForParts([obsPart]);
|
||||
const newObsTokens = this.env.tokenCalculator.estimateTokensForParts([obsPart as Part]);
|
||||
|
||||
const tokensSaved =
|
||||
this.env.tokenCalculator.getTokenCost(node) -
|
||||
|
||||
@@ -35,7 +35,9 @@ export class InboxSnapshotImpl implements InboxSnapshot {
|
||||
}
|
||||
|
||||
getMessages<T = unknown>(topic: string): ReadonlyArray<InboxMessage<T>> {
|
||||
return this.messages.filter((m) => m.topic === topic) as ReadonlyArray<InboxMessage<T>>;
|
||||
const raw = this.messages.filter((m) => m.topic === topic);
|
||||
// eslint-disable-next-line @typescript-eslint/no-unsafe-type-assertion
|
||||
return raw as ReadonlyArray<InboxMessage<T>>;
|
||||
}
|
||||
|
||||
consume(messageId: string): void {
|
||||
|
||||
@@ -25,10 +25,10 @@ class DummySyncProcessor implements ContextProcessor {
|
||||
readonly name = 'DummySync';
|
||||
readonly id = 'DummySync';
|
||||
readonly options = {};
|
||||
async process(args: any) {
|
||||
async process(args: import('../pipeline.js').ProcessArgs) {
|
||||
const newTargets = [...args.targets];
|
||||
if (newTargets.length > 0) {
|
||||
newTargets[0] = { ...newTargets[0], dummyModified: true };
|
||||
newTargets[0] = { ...newTargets[0], dummyModified: true } as unknown as import('../ir/types.js').ConcreteNode;
|
||||
}
|
||||
return newTargets;
|
||||
}
|
||||
@@ -42,10 +42,10 @@ class DummyAsyncProcessor implements ContextProcessor {
|
||||
readonly name = 'DummyAsync';
|
||||
readonly id = 'DummyAsync';
|
||||
readonly options = {};
|
||||
async process(args: any) {
|
||||
async process(args: import('../pipeline.js').ProcessArgs) {
|
||||
const newTargets = [...args.targets];
|
||||
if (newTargets.length > 0) {
|
||||
newTargets[0] = { ...newTargets[0], dummyModified: true };
|
||||
newTargets[0] = { ...newTargets[0], dummyModified: true } as unknown as import('../ir/types.js').ConcreteNode;
|
||||
}
|
||||
return newTargets;
|
||||
}
|
||||
@@ -59,7 +59,7 @@ class ThrowingProcessor implements ContextProcessor {
|
||||
readonly name = 'Throwing';
|
||||
readonly id = 'Throwing';
|
||||
readonly options = {};
|
||||
async process(): Promise<any> {
|
||||
async process(): Promise<ReadonlyArray<import('../ir/types.js').ConcreteNode>> {
|
||||
throw new Error('Processor failed intentionally');
|
||||
}
|
||||
}
|
||||
|
||||
@@ -13,7 +13,7 @@ describe('SidecarRegistry', () => {
|
||||
const processorDef: ContextProcessorDef = {
|
||||
id: 'TestProcessor',
|
||||
schema: { type: 'object' },
|
||||
create: () => ({} as any),
|
||||
create: () => ({} as unknown as import('../pipeline.js').ContextProcessor),
|
||||
};
|
||||
|
||||
registry.registerProcessor(processorDef);
|
||||
@@ -26,7 +26,7 @@ describe('SidecarRegistry', () => {
|
||||
const workerDef: ContextWorkerDef = {
|
||||
id: 'TestWorker',
|
||||
schema: { type: 'object' },
|
||||
create: () => ({} as any),
|
||||
create: () => ({} as unknown as import('../pipeline.js').ContextProcessor),
|
||||
};
|
||||
|
||||
registry.registerWorker(workerDef);
|
||||
@@ -49,15 +49,15 @@ describe('SidecarRegistry', () => {
|
||||
registry.registerProcessor({
|
||||
id: 'TestProcessor',
|
||||
schema: { title: 'processorSchema' },
|
||||
create: () => ({} as any),
|
||||
create: () => ({} as unknown as import('../pipeline.js').ContextProcessor),
|
||||
});
|
||||
registry.registerWorker({
|
||||
id: 'TestWorker',
|
||||
schema: { title: 'workerSchema' },
|
||||
create: () => ({} as any),
|
||||
create: () => ({} as unknown as import('../pipeline.js').ContextProcessor),
|
||||
});
|
||||
|
||||
const schemas = registry.getSchemas() as any[];
|
||||
const schemas = registry.getSchemas() as unknown as Array<Record<string, unknown>>;
|
||||
expect(schemas.length).toBe(2);
|
||||
expect(schemas.find(s => s.title === 'processorSchema')).toBeDefined();
|
||||
expect(schemas.find(s => s.title === 'workerSchema')).toBeDefined();
|
||||
@@ -65,8 +65,8 @@ describe('SidecarRegistry', () => {
|
||||
|
||||
it('should safely clear the registry', () => {
|
||||
const registry = new SidecarRegistry();
|
||||
registry.registerProcessor({ id: 'TestProcessor', schema: {}, create: () => ({} as any) });
|
||||
registry.registerWorker({ id: 'TestWorker', schema: {}, create: () => ({} as any) });
|
||||
registry.registerProcessor({ id: 'TestProcessor', schema: {}, create: () => ({} as unknown as import('../pipeline.js').ContextProcessor) });
|
||||
registry.registerWorker({ id: 'TestWorker', schema: {}, create: () => ({} as unknown as import('../pipeline.js').ContextProcessor) });
|
||||
|
||||
registry.clear();
|
||||
|
||||
|
||||
@@ -29,6 +29,7 @@ import type { Content , GenerateContentResponse } from '@google/genai';
|
||||
* Used to avoid having to manually construct the deeply nested candidate/content/part structure.
|
||||
*/
|
||||
export const createMockGenerateContentResponse = (text: string): GenerateContentResponse =>
|
||||
// eslint-disable-next-line @typescript-eslint/no-unsafe-type-assertion
|
||||
({
|
||||
candidates: [{ content: { role: 'model', parts: [{ text }] }, index: 0 }],
|
||||
}) as GenerateContentResponse;
|
||||
@@ -46,7 +47,7 @@ export function createDummyNode(
|
||||
id: id || randomUUID(),
|
||||
episodeId: logicalParentId,
|
||||
logicalParentId,
|
||||
type: type as any,
|
||||
type,
|
||||
timestamp: Date.now(),
|
||||
text: `Dummy ${type}`,
|
||||
name: type === 'SYSTEM_EVENT' ? 'dummy_event' : undefined,
|
||||
@@ -94,9 +95,11 @@ export function createDummyToolNode(
|
||||
export function createMockEnvironment(
|
||||
overrides?: Partial<ContextEnvironment>,
|
||||
): ContextEnvironment {
|
||||
const llmClient = vi.fn().mockReturnValue({
|
||||
const mockClient: Partial<BaseLlmClient> = {
|
||||
generateContent: vi.fn().mockResolvedValue(createMockGenerateContentResponse('Mock LLM summary response')),
|
||||
})() as unknown as BaseLlmClient;
|
||||
};
|
||||
// eslint-disable-next-line @typescript-eslint/no-unsafe-type-assertion
|
||||
const llmClient = mockClient as BaseLlmClient;
|
||||
|
||||
const tracer = new ContextTracer({ targetDir: '/tmp', sessionId: 'mock-session' });
|
||||
const eventBus = new ContextEventBus();
|
||||
@@ -114,7 +117,10 @@ export function createMockEnvironment(
|
||||
new DeterministicIdGenerator('mock-uuid-')
|
||||
);
|
||||
|
||||
return { ...env, ...overrides };
|
||||
if (overrides) {
|
||||
Object.assign(env, overrides);
|
||||
}
|
||||
return env;
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
Reference in New Issue
Block a user