@openai/agents-openai
Version:
The OpenAI Agents SDK is a lightweight yet powerful framework for building multi-agent workflows.
262 lines • 9.31 kB
JavaScript
import { UserError, } from '@openai/agents-core';
export function convertToolChoice(toolChoice) {
if (toolChoice == undefined || toolChoice == null)
return undefined;
if (toolChoice === 'auto' ||
toolChoice === 'required' ||
toolChoice === 'none')
return toolChoice;
return {
type: 'function',
function: { name: toolChoice },
};
}
export function extractAllAssistantContent(content) {
if (typeof content === 'string') {
return content;
}
const out = [];
for (const c of content) {
if (c.type === 'output_text') {
out.push({
type: 'text',
text: c.text,
...c.providerData,
});
}
else if (c.type === 'refusal') {
out.push({
type: 'refusal',
refusal: c.refusal,
...c.providerData,
});
}
else if (c.type === 'audio' || c.type === 'image') {
// ignoring audio as it is handled on the assistant message level
continue;
}
else {
const exhaustive = c; // ensures that the type is exhaustive
throw new Error(`Unknown content: ${JSON.stringify(exhaustive)}`);
}
}
return out;
}
export function extractAllUserContent(content) {
if (typeof content === 'string') {
return content;
}
const out = [];
for (const c of content) {
if (c.type === 'input_text') {
out.push({ type: 'text', text: c.text, ...c.providerData });
}
else if (c.type === 'input_image') {
if (typeof c.image !== 'string') {
throw new Error(`Only image URLs are supported for input_image: ${JSON.stringify(c)}`);
}
const { image_url, ...rest } = c.providerData || {};
out.push({
type: 'image_url',
image_url: {
url: c.image,
...image_url,
},
...rest,
});
}
else if (c.type === 'input_file') {
throw new Error(`File uploads are not supported for chat completions: ${JSON.stringify(c)}`);
}
else if (c.type === 'audio') {
const { input_audio, ...rest } = c.providerData || {};
out.push({
type: 'input_audio',
input_audio: {
data: c.audio,
...input_audio,
},
...rest,
});
}
else {
const exhaustive = c; // ensures that the type is exhaustive
throw new Error(`Unknown content: ${JSON.stringify(exhaustive)}`);
}
}
return out;
}
function isMessageItem(item) {
if (item.type === 'message') {
return true;
}
if (typeof item.type === 'undefined' && typeof item.role === 'string') {
return true;
}
return false;
}
export function itemsToMessages(items) {
if (typeof items === 'string') {
return [{ role: 'user', content: items }];
}
const result = [];
let currentAssistantMsg = null;
const flushAssistantMessage = () => {
if (currentAssistantMsg) {
if (!currentAssistantMsg.tool_calls ||
currentAssistantMsg.tool_calls.length === 0) {
delete currentAssistantMsg.tool_calls;
}
result.push(currentAssistantMsg);
currentAssistantMsg = null;
}
};
const ensureAssistantMessage = () => {
if (!currentAssistantMsg) {
currentAssistantMsg = { role: 'assistant', tool_calls: [] };
}
return currentAssistantMsg;
};
for (const item of items) {
if (isMessageItem(item)) {
const { content, role, providerData } = item;
flushAssistantMessage();
if (role === 'assistant') {
const assistant = {
role: 'assistant',
content: extractAllAssistantContent(content),
...providerData,
};
if (Array.isArray(content)) {
const audio = content.find((c) => c.type === 'audio');
if (audio) {
assistant.audio = {
id: '', // setting this to empty ID and expecting that the user sets providerData.id
...audio.providerData,
};
}
}
result.push(assistant);
}
else if (role === 'user') {
result.push({
role,
content: extractAllUserContent(content),
...providerData,
});
}
else if (role === 'system') {
result.push({
role: 'system',
content: content,
...providerData,
});
}
}
else if (item.type === 'reasoning') {
const asst = ensureAssistantMessage();
// @ts-expect-error - reasoning is not supported in the official Chat Completion API spec
// this is handling third party providers that support reasoning
asst.reasoning = item.rawContent?.[0]?.text;
continue;
}
else if (item.type === 'hosted_tool_call') {
if (item.name === 'file_search_call') {
const asst = ensureAssistantMessage();
const toolCalls = asst.tool_calls ?? [];
const fileSearch = item;
const { function: functionData, ...rest } = fileSearch.providerData ?? {};
const { arguments: argumentData, ...remainingFunctionData } = functionData ?? {};
toolCalls.push({
id: fileSearch.id || '',
type: 'function',
function: {
name: 'file_search_call',
arguments: JSON.stringify({
queries: fileSearch.providerData?.queries ?? [],
status: fileSearch.status,
...argumentData,
}),
...remainingFunctionData,
},
...rest,
});
asst.tool_calls = toolCalls;
continue;
}
else {
throw new UserError('Hosted tool calls are not supported for chat completions. Got item: ' +
JSON.stringify(item));
}
}
else if (item.type === 'computer_call' ||
item.type === 'computer_call_result') {
throw new UserError('Computer use calls are not supported for chat completions. Got item: ' +
JSON.stringify(item));
}
else if (item.type === 'function_call') {
const asst = ensureAssistantMessage();
const toolCalls = asst.tool_calls ?? [];
const funcCall = item;
toolCalls.push({
id: funcCall.callId,
type: 'function',
function: {
name: funcCall.name,
arguments: funcCall.arguments ?? '{}',
},
});
asst.tool_calls = toolCalls;
}
else if (item.type === 'function_call_result') {
flushAssistantMessage();
const funcOutput = item;
if (funcOutput.output.type !== 'text') {
throw new UserError('Only text output is supported for chat completions. Got item: ' +
JSON.stringify(item));
}
result.push({
role: 'tool',
tool_call_id: funcOutput.callId,
content: funcOutput.output.text,
...funcOutput.providerData,
});
}
else if (item.type === 'unknown') {
result.push({
...item.providerData,
});
}
else {
const exhaustive = item; // ensures that the type is exhaustive
throw new Error(`Unknown item type: ${JSON.stringify(exhaustive)}`);
}
}
flushAssistantMessage();
return result;
}
export function toolToOpenAI(tool) {
if (tool.type === 'function') {
return {
type: 'function',
function: {
name: tool.name,
description: tool.description || '',
parameters: tool.parameters,
strict: tool.strict,
},
};
}
throw new Error(`Hosted tools are not supported with the ChatCompletions API. Got tool type: ${tool.type}, tool: ${JSON.stringify(tool)}`);
}
export function convertHandoffTool(handoff) {
return {
type: 'function',
function: {
name: handoff.toolName,
description: handoff.toolDescription || '',
parameters: handoff.inputJsonSchema,
},
};
}
//# sourceMappingURL=openaiChatCompletionsConverter.mjs.map