@openai/agents-core
Version:
The OpenAI Agents SDK is a lightweight yet powerful framework for building multi-agent workflows.
262 lines • 11.2 kB
JavaScript
;
Object.defineProperty(exports, "__esModule", { value: true });
exports.toFunctionToolName = toFunctionToolName;
exports.getSchemaAndParserFromInputType = getSchemaAndParserFromInputType;
exports.convertAgentOutputTypeToSerializable = convertAgentOutputTypeToSerializable;
const zod_1 = require("openai/helpers/zod");
const errors_1 = require("../errors.js");
const typeGuards_1 = require("./typeGuards.js");
const zodJsonSchemaCompat_1 = require("./zodJsonSchemaCompat.js");
const zodCompat_1 = require("./zodCompat.js");
const strictToolSchema_1 = require("./strictToolSchema.js");
const standardSchema_1 = require("./standardSchema.js");
const zodResponsesFunctionCompat = zod_1.zodResponsesFunction;
// The `.schema` payload is all we need, so a lightweight signature keeps the compiler happy.
const zodTextFormatCompat = zod_1.zodTextFormat;
// openai/helpers/zod cannot emit strict schemas for every Zod runtime
// (notably Zod v4), so we delegate to a small local converter living in
// zodJsonSchemaCompat.ts whenever its output is missing the required JSON Schema bits.
function buildJsonSchemaFromZod(inputType) {
return (0, zodJsonSchemaCompat_1.zodJsonSchemaCompat)(inputType);
}
/**
* Convert a string to a function tool name by replacing spaces with underscores and
* non-alphanumeric characters with underscores.
* @param name - The name of the tool.
* @returns The function tool name.
*/
function toFunctionToolName(name) {
// Replace spaces with underscores
name = name.replace(/\s/g, '_');
// Replace non-alphanumeric characters with underscores
name = name.replace(/[^a-zA-Z0-9]/g, '_');
// Ensure the name is not empty
if (name.length === 0) {
throw new Error('Tool name cannot be empty');
}
return name;
}
/**
* Get the schema and parser from an input type. Supported Standard Schema and Zod values are
* converted to JSON Schema and retain runtime validation. Plain JSON Schema values use JSON.parse.
* @param inputType - The input type to get the schema and parser from.
* @param name - The name of the tool.
* @returns The schema and parser.
*/
function getSchemaAndParserFromInputType(inputType, name, options = {}) {
const parser = (input) => JSON.parse(input);
if ((0, typeGuards_1.isZodObject)(inputType)) {
const useFallback = (originalError) => {
const strictFallback = options.strict
? (0, zodJsonSchemaCompat_1.zodJsonSchemaCompatForOpenAIStrict)(inputType)
: undefined;
if (strictFallback?.loweredObjectIntersection ||
strictFallback?.loweredPrimitiveIntersection) {
(0, zodJsonSchemaCompat_1.assertLosslessOpenAIStrictZodSchemaConversion)(strictFallback);
}
const fallbackSchema = options.strict
? strictFallback?.schema
: buildJsonSchemaFromZod(inputType);
if (fallbackSchema) {
return {
schema: options.strict
? (0, strictToolSchema_1.toOpenAIStrictToolSchema)(fallbackSchema)
: fallbackSchema,
parser: (rawInput) => options.strict
? inputType.parse((0, strictToolSchema_1.stripStrictNullsForZodSchema)(inputType, JSON.parse(rawInput)))
: inputType.parse(JSON.parse(rawInput)),
};
}
const errorMessage = originalError instanceof Error
? ` Upstream helper error: ${originalError.message}`
: '';
throw new errors_1.UserError(`Unable to convert the provided Zod schema to JSON Schema. Ensure that the \`zod\` package is available at runtime or provide a JSON schema object instead.${errorMessage}`);
};
let formattedFunction;
try {
formattedFunction = zodResponsesFunctionCompat({
name,
parameters: (0, zodCompat_1.asZodType)(inputType),
function: () => { }, // empty function here to satisfy the OpenAI helper
description: '',
});
}
catch (error) {
return useFallback(error);
}
if ((0, zodJsonSchemaCompat_1.hasJsonSchemaObjectShape)(formattedFunction.parameters)) {
const strictFallback = options.strict
? (0, zodJsonSchemaCompat_1.zodJsonSchemaCompatForOpenAIStrict)(inputType)
: undefined;
const fallbackSchema = strictFallback?.schema ?? buildJsonSchemaFromZod(inputType);
if (fallbackSchema) {
(0, zodJsonSchemaCompat_1.mergeJsonSchemaDescriptions)(formattedFunction.parameters, fallbackSchema);
}
const upstreamSchema = formattedFunction.parameters;
const strictSchemaSource = strictFallback?.loweredObjectIntersection ||
(strictFallback?.loweredPrimitiveIntersection &&
containsJsonSchemaAllOf(upstreamSchema))
? useLosslessStrictFallback(strictFallback)
: upstreamSchema;
return {
schema: options.strict
? (0, strictToolSchema_1.toOpenAIStrictToolSchema)(strictSchemaSource)
: formattedFunction.parameters,
parser: options.strict
? (rawInput) => inputType.parse((0, strictToolSchema_1.stripStrictNullsForZodSchema)(inputType, JSON.parse(rawInput)))
: formattedFunction.$parseRaw,
};
}
return useFallback();
}
else if ((0, standardSchema_1.isStandardSchemaWithJSON)(inputType)) {
if (!options.strict) {
throw new errors_1.UserError('Strict mode is required for Standard Schema parameters');
}
const inputSchema = (0, standardSchema_1.standardSchemaToJsonSchema)(inputType, 'input');
(0, standardSchema_1.assertStandardSchemaObjectRoot)(inputSchema, 'Tool parameter');
const preparedSchema = (0, strictToolSchema_1.prepareOpenAIStrictToolSchema)(inputSchema);
return {
schema: preparedSchema.schema,
parser: (rawInput) => (0, standardSchema_1.validateStandardSchema)(inputType, preparedSchema.normalizeInput(JSON.parse(rawInput))),
};
}
else if ((0, standardSchema_1.hasStandardSchemaMarker)(inputType)) {
throw (0, standardSchema_1.unsupportedStandardSchemaError)();
}
else if (typeof inputType === 'object' && inputType !== null) {
const jsonSchema = inputType;
const preparedSchema = options.strict
? (0, strictToolSchema_1.prepareOpenAIStrictToolSchema)(jsonSchema)
: undefined;
return {
schema: preparedSchema?.schema ?? jsonSchema,
parser: preparedSchema
? (rawInput) => preparedSchema.normalizeInput(JSON.parse(rawInput))
: parser,
};
}
throw new errors_1.UserError('Input type is not a supported Standard Schema or a valid JSON schema');
}
function useLosslessStrictFallback(conversion) {
(0, zodJsonSchemaCompat_1.assertLosslessOpenAIStrictZodSchemaConversion)(conversion);
return conversion.schema;
}
function containsJsonSchemaAllOf(value, visited = new WeakSet()) {
if (typeof value !== 'object' ||
value === null ||
Array.isArray(value) ||
visited.has(value)) {
return false;
}
visited.add(value);
const schema = value;
if (Array.isArray(schema.allOf)) {
return true;
}
for (const key of [
'additionalItems',
'additionalProperties',
'contains',
'contentSchema',
'else',
'if',
'items',
'not',
'propertyNames',
'then',
'unevaluatedItems',
'unevaluatedProperties',
]) {
const nested = schema[key];
if (Array.isArray(nested)) {
if (nested.some((entry) => containsJsonSchemaAllOf(entry, visited))) {
return true;
}
}
else if (containsJsonSchemaAllOf(nested, visited)) {
return true;
}
}
for (const key of ['anyOf', 'oneOf', 'prefixItems']) {
const nested = schema[key];
if (Array.isArray(nested) &&
nested.some((entry) => containsJsonSchemaAllOf(entry, visited))) {
return true;
}
}
for (const key of [
'$defs',
'definitions',
'dependencies',
'dependentSchemas',
'patternProperties',
'properties',
]) {
const nested = schema[key];
if (typeof nested === 'object' &&
nested !== null &&
!Array.isArray(nested) &&
Object.values(nested).some((entry) => containsJsonSchemaAllOf(entry, visited))) {
return true;
}
}
return false;
}
/**
* Converts the agent output type provided to a serializable version
*/
function convertAgentOutputTypeToSerializable(outputType) {
if (outputType === 'text') {
return 'text';
}
if ((0, typeGuards_1.isZodObject)(outputType)) {
const useFallback = (existing, originalError) => {
const fallbackSchema = buildJsonSchemaFromZod(outputType);
if (fallbackSchema) {
return {
type: existing?.type ?? 'json_schema',
name: existing?.name ?? 'output',
strict: existing?.strict ?? false,
schema: fallbackSchema,
};
}
const errorMessage = originalError instanceof Error
? ` Upstream helper error: ${originalError.message}`
: '';
throw new errors_1.UserError(`Unable to convert the provided Zod schema to JSON Schema. Ensure that the \`zod\` package is available at runtime or provide a JSON schema object instead.${errorMessage}`);
};
let output;
try {
output = zodTextFormatCompat((0, zodCompat_1.asZodType)(outputType), 'output');
}
catch (error) {
return useFallback(undefined, error);
}
if ((0, zodJsonSchemaCompat_1.hasJsonSchemaObjectShape)(output.schema)) {
return {
type: output.type,
name: output.name,
strict: output.strict || false,
schema: output.schema,
};
}
return useFallback(output);
}
if ((0, standardSchema_1.isStandardSchemaWithJSON)(outputType)) {
const schema = (0, standardSchema_1.standardSchemaToJsonSchema)(outputType, 'input');
(0, standardSchema_1.assertStandardSchemaObjectRoot)(schema, 'Agent output');
return {
type: 'json_schema',
name: 'output',
strict: true,
schema: (0, strictToolSchema_1.prepareOpenAIStrictToolSchema)(schema)
.schema,
};
}
if ((0, standardSchema_1.hasStandardSchemaMarker)(outputType)) {
throw (0, standardSchema_1.unsupportedStandardSchemaError)();
}
return outputType;
}
//# sourceMappingURL=tools.js.map