Path: blob/main/extensions/copilot/src/extension/agents/node/test/openaiAdapter.spec.ts
13405 views
/*---------------------------------------------------------------------------------------------1* Copyright (c) Microsoft Corporation. All rights reserved.2* Licensed under the MIT License. See License.txt in the project root for license information.3*--------------------------------------------------------------------------------------------*/45import * as http from 'http';6import { describe, expect, it } from 'vitest';7import { OpenAIAdapterFactoryForSTests } from '../adapters/openaiAdapterForSTests';8import { Raw } from '@vscode/prompt-tsx';910describe('OpenAIAdapterFactory', () => {11it('should create an OpenAI adapter instance', () => {12const factory = new OpenAIAdapterFactoryForSTests();13const adapter = factory.createAdapter();1415// Verify the adapter has the correct name16expect(adapter.name).toBe('openai');17});1819it('should parse a basic OpenAI request', () => {20const factory = new OpenAIAdapterFactoryForSTests();21const adapter = factory.createAdapter();2223const requestBody = {24model: 'gpt-4o',25messages: [26{ role: 'user', content: 'Hello' }27],28temperature: 0.729};3031const parsedRequest = adapter.parseRequest(JSON.stringify(requestBody));3233expect(parsedRequest.model).toBe('gpt-4o');34expect(parsedRequest.messages).toHaveLength(1);35expect(parsedRequest.messages[0]).toEqual({ role: Raw.ChatRole.User, content: [{ text: 'Hello', type: Raw.ChatCompletionContentPartKind.Text }] } satisfies Raw.UserChatMessage);36expect(parsedRequest.options?.temperature).toBe(0.7);37});3839it('should parse an OpenAI request with tools', () => {40const factory = new OpenAIAdapterFactoryForSTests();41const adapter = factory.createAdapter();4243const requestBody = {44model: 'gpt-4o',45messages: [46{ role: 'user', content: 'What is the weather?' }47],48tools: [49{50type: 'function',51function: {52name: 'get_weather',53description: 'Get the current weather',54parameters: {55type: 'object',56properties: {57location: { type: 'string' }58}59}60}61}62]63};6465const parsedRequest = adapter.parseRequest(JSON.stringify(requestBody));6667expect(parsedRequest.model).toBe('gpt-4o');68expect(parsedRequest.messages).toHaveLength(1);69expect(parsedRequest.options?.tools).toBeDefined();70expect(parsedRequest.options?.tools).toHaveLength(1);71});7273it('should extract auth key from headers', () => {74const factory = new OpenAIAdapterFactoryForSTests();75const adapter = factory.createAdapter();7677const headers: http.IncomingHttpHeaders = {78'authorization': 'Bearer test-key-123'79};8081const authKey = adapter.extractAuthKey(headers);8283expect(authKey).toBe('test-key-123');84});8586it('should format text stream response', () => {87const factory = new OpenAIAdapterFactoryForSTests();88const adapter = factory.createAdapter();8990const context = {91requestId: 'test-request-id',92endpoint: {93modelId: 'gpt-4o',94modelMaxPromptTokens: 12800095}96};9798const streamData = {99type: 'text' as const,100content: 'Hello, world!'101};102103let events = adapter.formatStreamResponse(streamData, context);104105expect(events).toHaveLength(0);106107events = adapter.generateFinalEvents(context);108expect(events).toHaveLength(2);109expect(events[0].event).toBe('message');110expect(events[0].data).toContain('Hello, world!');111112expect(events[1].event).toBe('message');113expect(JSON.parse(events[1].data).choices).toEqual([{ 'index': 0, 'delta': { 'content': null }, 'finish_reason': 'stop' }]);114});115116it('should format tool call stream response', () => {117const factory = new OpenAIAdapterFactoryForSTests();118const adapter = factory.createAdapter();119120const context = {121requestId: 'test-request-id',122endpoint: {123modelId: 'gpt-4o',124modelMaxPromptTokens: 128000125}126};127128const streamData = {129type: 'tool_call' as const,130callId: 'call_123',131name: 'get_weather',132input: { location: 'Boston' }133};134135const events = adapter.formatStreamResponse(streamData, context);136137expect(events).toHaveLength(1);138expect(events[0].event).toBe('message');139expect(events[0].data).toContain('get_weather');140expect(events[0].data).toContain('Boston');141});142143it('should generate final events with usage', () => {144const factory = new OpenAIAdapterFactoryForSTests();145const adapter = factory.createAdapter();146147const context = {148requestId: 'test-request-id',149endpoint: {150modelId: 'gpt-4o',151modelMaxPromptTokens: 128000152}153};154155const usage = {156prompt_tokens: 10,157completion_tokens: 20,158total_tokens: 30159};160161const events = adapter.generateFinalEvents(context, usage);162163expect(events).toHaveLength(1);164expect(events[0].event).toBe('message');165expect(events[0].data).toContain('"prompt_tokens":10');166expect(events[0].data).toContain('"completion_tokens":20');167});168});169170