diff options
Diffstat (limited to 'packages/core/src/telemetry/loggers.test.circular.ts')
| -rw-r--r-- | packages/core/src/telemetry/loggers.test.circular.ts | 119 |
1 files changed, 119 insertions, 0 deletions
diff --git a/packages/core/src/telemetry/loggers.test.circular.ts b/packages/core/src/telemetry/loggers.test.circular.ts new file mode 100644 index 00000000..62a61bfd --- /dev/null +++ b/packages/core/src/telemetry/loggers.test.circular.ts @@ -0,0 +1,119 @@ +/** + * @license + * Copyright 2025 Google LLC + * SPDX-License-Identifier: Apache-2.0 + */ + +/** + * Test to verify circular reference handling in telemetry logging + */ + +import { describe, it, expect } from 'vitest'; +import { logToolCall } from './loggers.js'; +import { ToolCallEvent } from './types.js'; +import { Config } from '../config/config.js'; +import { CompletedToolCall } from '../core/coreToolScheduler.js'; +import { ToolCallRequestInfo, ToolCallResponseInfo } from '../core/turn.js'; +import { Tool } from '../tools/tools.js'; + +describe('Circular Reference Handling', () => { + it('should handle circular references in tool function arguments', () => { + // Create a mock config + const mockConfig = { + getTelemetryEnabled: () => true, + getUsageStatisticsEnabled: () => true, + getSessionId: () => 'test-session', + getModel: () => 'test-model', + getEmbeddingModel: () => 'test-embedding', + getDebugMode: () => false, + } as unknown as Config; + + // Create an object with circular references (similar to HttpsProxyAgent) + // eslint-disable-next-line @typescript-eslint/no-explicit-any + const circularObject: any = { + sockets: {}, + agent: null, + }; + circularObject.agent = circularObject; // Create circular reference + circularObject.sockets['test-host'] = [ + { _httpMessage: { agent: circularObject } }, + ]; + + // Create a mock CompletedToolCall with circular references in function_args + const mockRequest: ToolCallRequestInfo = { + callId: 'test-call-id', + name: 'ReadFile', + args: circularObject, // This would cause the original error + isClientInitiated: false, + prompt_id: 'test-prompt-id', + }; + + const mockResponse: ToolCallResponseInfo = { + callId: 'test-call-id', + responseParts: [{ text: 'test result' }], + resultDisplay: undefined, + error: undefined, // undefined means success + }; + + const mockCompletedToolCall: CompletedToolCall = { + status: 'success', + request: mockRequest, + response: mockResponse, + tool: {} as Tool, + durationMs: 100, + }; + + // Create a tool call event with circular references in function_args + const event = new ToolCallEvent(mockCompletedToolCall); + + // This should not throw an error + expect(() => { + logToolCall(mockConfig, event); + }).not.toThrow(); + }); + + it('should handle normal objects without circular references', () => { + const mockConfig = { + getTelemetryEnabled: () => true, + getUsageStatisticsEnabled: () => true, + getSessionId: () => 'test-session', + getModel: () => 'test-model', + getEmbeddingModel: () => 'test-embedding', + getDebugMode: () => false, + } as unknown as Config; + + const normalObject = { + filePath: '/test/path', + options: { encoding: 'utf8' }, + }; + + const mockRequest: ToolCallRequestInfo = { + callId: 'test-call-id', + name: 'ReadFile', + args: normalObject, + isClientInitiated: false, + prompt_id: 'test-prompt-id', + }; + + const mockResponse: ToolCallResponseInfo = { + callId: 'test-call-id', + responseParts: [{ text: 'test result' }], + resultDisplay: undefined, + error: undefined, // undefined means success + }; + + const mockCompletedToolCall: CompletedToolCall = { + status: 'success', + request: mockRequest, + response: mockResponse, + tool: {} as Tool, + durationMs: 100, + }; + + const event = new ToolCallEvent(mockCompletedToolCall); + + expect(() => { + logToolCall(mockConfig, event); + }).not.toThrow(); + }); +}); |
