Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
81 changes: 81 additions & 0 deletions web/src/common/openai.test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,81 @@
// web/src/common/openai.test.ts
import { OpenAiChannel, MyMessage } from './openai'; // Adjust path as needed
import { describe, it, expect, beforeEach } from 'vitest';

describe('OpenAiChannel.messages_format', () => {
let channel: OpenAiChannel;

beforeEach(() => {
// Minimal options needed for OpenAiChannel instantiation for this test
channel = new OpenAiChannel({ apiKey: 'test', baseURL: 'test' });
});

it('should omit tool_calls if content_tool_calls is undefined', async () => {
const messages: MyMessage[] = [
{ role: 'user', content: 'Hello' },
{
role: 'assistant',
content: 'Thinking...',
content_tool_calls: undefined
}
];
const formattedMessages = await channel.messages_format(messages);
const assistantMessage = formattedMessages.find(m => m.role === 'assistant');
expect(assistantMessage).toBeDefined();
expect(assistantMessage).not.toHaveProperty('tool_calls');
});

it('should omit tool_calls if content_tool_calls is null', async () => {
const messages: MyMessage[] = [
{ role: 'user', content: 'Hello' },
{
role: 'assistant',
content: 'Thinking...',
// @ts-ignore // To allow null assignment for testing, if MyMessage['content_tool_calls'] doesn't normally allow null
content_tool_calls: null
}
];
const formattedMessages = await channel.messages_format(messages);
const assistantMessage = formattedMessages.find(m => m.role === 'assistant');
expect(assistantMessage).toBeDefined();
expect(assistantMessage).not.toHaveProperty('tool_calls');
});

it('should omit tool_calls if content_tool_calls is an empty array', async () => {
const messages: MyMessage[] = [
{ role: 'user', content: 'Hello' },
{
role: 'assistant',
content: 'Thinking...',
content_tool_calls: []
}
];
const formattedMessages = await channel.messages_format(messages);
const assistantMessage = formattedMessages.find(m => m.role === 'assistant');
expect(assistantMessage).toBeDefined();
expect(assistantMessage).not.toHaveProperty('tool_calls');
});

// Optional: Add a test case for when content_tool_calls is valid and non-empty
it('should include tool_calls if content_tool_calls is valid and non-empty', async () => {
const messages: MyMessage[] = [
{ role: 'user', content: 'Hello' },
{
role: 'assistant',
content: 'Thinking...',
content_tool_calls: [{
id: 'call_123',
type: 'function',
function: { name: 'get_weather', arguments: '{"location": "Boston"}' }
}]
}
];
const formattedMessages = await channel.messages_format(messages);
const assistantMessage = formattedMessages.find(m => m.role === 'assistant');
expect(assistantMessage).toBeDefined();
expect(assistantMessage).toHaveProperty('tool_calls');
expect(assistantMessage.tool_calls).toHaveLength(1);
// @ts-ignore
expect(assistantMessage.tool_calls[0].function.name).toBe('get_weather');
});
});
19 changes: 12 additions & 7 deletions web/src/common/openai.ts
Original file line number Diff line number Diff line change
Expand Up @@ -754,13 +754,18 @@ export class OpenAiChannel {
...rest
} = m;
if (rest.role == "assistant") {
rest.tool_calls = content_tool_calls?.map((x: Tool_Call) => {
let { origin_name, restore_name, ...rest } = x;
let { argumentsOBJ, ...functionRest } = rest.function;
rest.function = functionRest as any;
return rest;
}) as any;
if (rest.tool_calls?.length == 0) {
// Check if content_tool_calls is valid and has items before mapping
if (content_tool_calls && content_tool_calls.length > 0) {
rest.tool_calls = content_tool_calls.map((x: Tool_Call) => {
// Using 'restCall' to avoid shadowing the outer 'rest' variable from message destructuring
let { origin_name, restore_name, ...restCall } = x;
let { argumentsOBJ, ...functionRest } = restCall.function; // argumentsOBJ is part of x.function
restCall.function = functionRest as any;
return restCall; // Return the modified 'restCall' object
}) as any;
} else {
// If content_tool_calls is null, undefined, or empty,
// ensure tool_calls is not part of the resulting object.
delete rest.tool_calls;
}
}
Expand Down