import * as Data from "effect/Data";import * as Effect from "effect/Effect";import { pipe } from "effect/Function";import * as ParseResult from "effect/ParseResult";import * as Schema from "effect/Schema"; import { parseOpenApiDocument } from "./openapi-document";import { extractOpenApiManifestJsonWithWasm } from "./openapi-extractor-wasm";import { OpenApiToolManifestSchema, type OpenApiExtractedTool, type OpenApiHeader, type OpenApiSecurityRequirement, type OpenApiServer, type OpenApiJsonObject, type OpenApiSpecInput, type OpenApiToolManifest,} from "./openapi-types"; type OpenApiExtractionStage = "validate" | "extract"; export class OpenApiExtractionError extends Data.TaggedError("OpenApiExtractionError")<{ sourceName: string; stage: OpenApiExtractionStage; message: string; details: string | null;}> {} const manifestFromJsonSchema = Schema.parseJson(OpenApiToolManifestSchema);const decodeManifestFromJson = Schema.decodeUnknown(manifestFromJsonSchema); const toExtractionError = ( sourceName: string, stage: OpenApiExtractionStage, cause: unknown,): OpenApiExtractionError => cause instanceof OpenApiExtractionError ? cause : new OpenApiExtractionError({ sourceName, stage, message: "OpenAPI extraction failed", details: ParseResult.isParseError(cause) ? ParseResult.TreeFormatter.formatErrorSync(cause) : String(cause), }); const normalizeOpenApiDocumentText = ( sourceName: string, openApiSpec: OpenApiSpecInput,): Effect.Effect<string, OpenApiExtractionError> => { if (typeof openApiSpec === "string") { return Effect.succeed(openApiSpec); } return Effect.try({ try: () => JSON.stringify(openApiSpec), catch: (cause) => new OpenApiExtractionError({ sourceName, stage: "validate", message: "Unable to serialize OpenAPI input", details: String(cause), }), });}; const asObject = (value: unknown): Record<string, unknown> => value !== null && typeof value === "object" && !Array.isArray(value) ? (value as Record<string, unknown>) : {}; const asArray = (value: unknown): ReadonlyArray<unknown> => Array.isArray(value) ? value : []; const asTrimmedString = (value: unknown): string | undefined => typeof value === "string" && value.trim().length > 0 ? value.trim() : undefined; const stableJsonValue = (value: unknown): unknown => { if (Array.isArray(value)) { return value.map((entry) => stableJsonValue(entry)); } if (value !== null && typeof value === "object") { return Object.fromEntries( Object.entries(value as Record<string, unknown>) .sort(([left], [right]) => left.localeCompare(right)) .map(([key, entry]) => [key, stableJsonValue(entry)]), ); } return value;}; const stableJsonStringify = (value: unknown): string => JSON.stringify(stableJsonValue(value)); const collectRefKeys = ( value: unknown, refs: Set<string>,): void => { if (Array.isArray(value)) { for (const item of value) { collectRefKeys(item, refs); } return; } if (value === null || typeof value !== "object") { return; } const record = value as Record<string, unknown>; if (typeof record.$ref === "string" && record.$ref.startsWith("#/")) { refs.add(record.$ref); } for (const nested of Object.values(record)) { collectRefKeys(nested, refs); }}; const resolvePointerSegment = (segment: string): string => segment.replaceAll("~1", "/").replaceAll("~0", "~"); const resolveLocalRef = ( document: OpenApiJsonObject, value: unknown, activeRefs: ReadonlySet<string> = new Set<string>(),): unknown => { const object = asObject(value); const ref = typeof object.$ref === "string" ? object.$ref : null; if (!ref || !ref.startsWith("#/") || activeRefs.has(ref)) { return value; } const resolved = ref .slice(2) .split("/") .reduce<unknown>((current, segment) => { if (current === undefined || current === null) { return undefined; } return asObject(current)[resolvePointerSegment(segment)]; }, document); if (resolved === undefined) { return value; } const nextActiveRefs = new Set(activeRefs); nextActiveRefs.add(ref); const resolvedObject = asObject(resolveLocalRef(document, resolved, nextActiveRefs)); const { $ref: _ignoredRef, ...rest } = object; return Object.keys(rest).length > 0 ? { ...resolvedObject, ...rest } : resolvedObject;}; const responseStatusRank = (statusCode: string): number => { if (/^2\d\d$/.test(statusCode)) { return 0; } if (statusCode === "default") { return 1; } return 2;}; const preferredContentEntry = ( content: unknown,): readonly [string, Record<string, unknown>] | undefined => { const entries = Object.entries(asObject(content)) .sort(([left], [right]) => left.localeCompare(right)) .map(([mediaType, value]) => [mediaType, asObject(value)] as const); return entries.find(([mediaType]) => mediaType === "application/json") ?? entries.find(([mediaType]) => mediaType.toLowerCase().includes("+json")) ?? entries.find(([mediaType]) => mediaType.toLowerCase().includes("json")) ?? entries[0];}; const contentSchemaFromOperationContent = ( content: unknown,): unknown | undefined => { return preferredContentEntry(content)?.[1].schema;}; const contentEntriesFromContent = ( document: OpenApiJsonObject, content: unknown,): ReadonlyArray<{ mediaType: string; schema?: unknown; examples?: Array<{ valueJson: string; mediaType?: string; label?: string; }>;}> => { const entries = Object.entries(asObject(content)) .sort(([left], [right]) => left.localeCompare(right)) .map(([mediaType, mediaValue]) => { const mediaRecord = asObject(resolveLocalRef(document, mediaValue)); const examples = examplesFromMediaType(mediaType, mediaRecord); return { mediaType, ...(mediaRecord.schema !== undefined ? { schema: mediaRecord.schema } : {}), ...(examples.length > 0 ? { examples } : {}), }; }); return entries;}; const examplesFromValue = ( value: unknown, input: { label?: string; mediaType?: string; } = {},): Array<{ valueJson: string; mediaType?: string; label?: string;}> => { const record = asObject(value); const examples: Array<{ valueJson: string; mediaType?: string; label?: string; }> = []; if (record.example !== undefined) { examples.push({ valueJson: stableJsonStringify(record.example), ...(input.mediaType ? { mediaType: input.mediaType } : {}), ...(input.label ? { label: input.label } : {}), }); } const exampleEntries = Object.entries(asObject(record.examples)) .sort(([left], [right]) => left.localeCompare(right)); for (const [key, exampleValue] of exampleEntries) { const exampleRecord = asObject(exampleValue); examples.push({ valueJson: stableJsonStringify( exampleRecord.value !== undefined ? exampleRecord.value : exampleValue, ), ...(input.mediaType ? { mediaType: input.mediaType } : {}), label: key, }); } return examples;}; const examplesFromSchema = ( schema: unknown,): Array<{ valueJson: string; mediaType?: string; label?: string;}> => examplesFromValue(schema); const examplesFromMediaType = ( mediaType: string, mediaTypeRecord: Record<string, unknown>,): Array<{ valueJson: string; mediaType?: string; label?: string;}> => { const direct = examplesFromValue(mediaTypeRecord, { mediaType }); if (direct.length > 0) { return direct; } return examplesFromSchema(mediaTypeRecord.schema).map((example) => ({ ...example, mediaType, }));}; const headerFromValue = ( document: OpenApiJsonObject, name: string, value: unknown,): OpenApiHeader | undefined => { const header = asObject(resolveLocalRef(document, value)); if (Object.keys(header).length === 0) { return undefined; } const content = contentEntriesFromContent(document, header.content); const directExamples = content.length > 0 ? [] : examplesFromValue(header); return { name, ...(asTrimmedString(header.description) ? { description: asTrimmedString(header.description) } : {}), ...(typeof header.required === "boolean" ? { required: header.required } : {}), ...(typeof header.deprecated === "boolean" ? { deprecated: header.deprecated } : {}), ...(header.schema !== undefined ? { schema: header.schema } : {}), ...(content.length > 0 ? { content } : {}), ...(asTrimmedString(header.style) ? { style: asTrimmedString(header.style) } : {}), ...(typeof header.explode === "boolean" ? { explode: header.explode } : {}), ...(directExamples.length > 0 ? { examples: directExamples } : {}), };}; const headersFromValue = ( document: OpenApiJsonObject, value: unknown,): ReadonlyArray<OpenApiHeader> => Object.entries(asObject(value)) .sort(([left], [right]) => left.localeCompare(right)) .flatMap(([name, headerValue]) => { const header = headerFromValue(document, name, headerValue); return header ? [header] : []; }); const serversFromValue = ( value: unknown,): ReadonlyArray<OpenApiServer> => asArray(value) .map((entry) => asObject(entry)) .flatMap((server) => { const url = asTrimmedString(server.url); if (!url) { return []; } const variables = Object.fromEntries( Object.entries(asObject(server.variables)) .sort(([left], [right]) => left.localeCompare(right)) .flatMap(([name, variableValue]) => { const variableRecord = asObject(variableValue); const defaultValue = asTrimmedString(variableRecord.default); return defaultValue ? [[name, defaultValue] as const] : []; }), ); return [{ url, ...(asTrimmedString(server.description) ? { description: asTrimmedString(server.description) } : {}), ...(Object.keys(variables).length > 0 ? { variables } : {}), }]; }); const pathItemForTool = ( document: OpenApiJsonObject, tool: OpenApiExtractedTool,): Record<string, unknown> => asObject(asObject(document.paths)[tool.path]); const parameterKey = (input: { location: string; name: string;}): string => `${input.location}:${input.name}`; const parameterRecordMapForTool = ( document: OpenApiJsonObject, tool: OpenApiExtractedTool,): ReadonlyMap<string, Record<string, unknown>> => { const merged = new Map<string, Record<string, unknown>>(); const pathItem = pathItemForTool(document, tool); const operation = operationForTool(document, tool); for (const parameterValue of asArray(pathItem.parameters)) { const parameter = asObject(resolveLocalRef(document, parameterValue)); const name = asTrimmedString(parameter.name); const location = asTrimmedString(parameter.in); if (!name || !location) { continue; } merged.set(parameterKey({ location, name }), parameter); } for (const parameterValue of asArray(operation.parameters)) { const parameter = asObject(resolveLocalRef(document, parameterValue)); const name = asTrimmedString(parameter.name); const location = asTrimmedString(parameter.in); if (!name || !location) { continue; } merged.set(parameterKey({ location, name }), parameter); } return merged;}; const operationForTool = ( document: OpenApiJsonObject, tool: OpenApiExtractedTool,): Record<string, unknown> => asObject( asObject(asObject(document.paths)[tool.path])[tool.method], ); const requestBodySchemaForTool = ( document: OpenApiJsonObject, tool: OpenApiExtractedTool,): unknown | undefined => { const operation = operationForTool(document, tool); if (Object.keys(operation).length === 0) { return undefined; } const requestBody = resolveLocalRef(document, operation.requestBody); return contentSchemaFromOperationContent(asObject(requestBody).content);}; const requestBodyPayloadForTool = ( document: OpenApiJsonObject, tool: OpenApiExtractedTool,): OpenApiExtractedTool["invocation"]["requestBody"] => { const operation = operationForTool(document, tool); if (Object.keys(operation).length === 0) { return tool.invocation.requestBody; } const requestBody = asObject(resolveLocalRef(document, operation.requestBody)); if (Object.keys(requestBody).length === 0) { return tool.invocation.requestBody; } const contents = contentEntriesFromContent(document, requestBody.content); const contentTypes = contents.map((content) => content.mediaType); return { required: typeof requestBody.required === "boolean" ? requestBody.required : (tool.invocation.requestBody?.required ?? false), contentTypes, ...(contents.length > 0 ? { contents } : {}), };}; const responseSchemaForTool = ( document: OpenApiJsonObject, tool: OpenApiExtractedTool,): unknown | undefined => { const operation = operationForTool(document, tool); if (Object.keys(operation).length === 0) { return undefined; } const responseEntries = Object.entries(asObject(operation.responses)); const preferredResponses = responseEntries .filter(([status]) => /^2\d\d$/.test(status)) .sort(([left], [right]) => left.localeCompare(right)); const fallbackResponses = responseEntries.filter(([status]) => status === "default"); for (const [, responseValue] of [...preferredResponses, ...fallbackResponses]) { const response = resolveLocalRef(document, responseValue); const schema = contentSchemaFromOperationContent(asObject(response).content); if (schema !== undefined) { return schema; } } return undefined;}; const responseVariantsForTool = ( document: OpenApiJsonObject, tool: OpenApiExtractedTool,): OpenApiExtractedTool["responses"] => { const operation = operationForTool(document, tool); if (Object.keys(operation).length === 0) { return undefined; } const responseEntries = Object.entries(asObject(operation.responses)) .sort(([left], [right]) => responseStatusRank(left) - responseStatusRank(right) || left.localeCompare(right), ); const responses = responseEntries.map(([statusCode, responseValue]) => { const response = asObject(resolveLocalRef(document, responseValue)); const contents = contentEntriesFromContent(document, response.content);Lines 1–500 of 893. Load more
import * as Data from "effect/Data"; import * as Effect from "effect/Effect"; import { pipe } from "effect/Function"; import * as ParseResult from "effect/ParseResult"; import * as Schema from "effect/Schema"; import { parseOpenApiDocument } from "./openapi-document"; import { extractOpenApiManifestJsonWithWasm } from "./openapi-extractor-wasm"; import { OpenApiToolManifestSchema, type OpenApiExtractedTool, type OpenApiHeader, type OpenApiSecurityRequirement, type OpenApiServer, type OpenApiJsonObject, type OpenApiSpecInput, type OpenApiToolManifest, } from "./openapi-types"; type OpenApiExtractionStage = "validate" | "extract"; export class OpenApiExtractionError extends Data.TaggedError("OpenApiExtractionError")<{ sourceName: string; stage: OpenApiExtractionStage; message: string; details: string | null; }> {} const manifestFromJsonSchema = Schema.parseJson(OpenApiToolManifestSchema); const decodeManifestFromJson = Schema.decodeUnknown(manifestFromJsonSchema); const toExtractionError = ( sourceName: string, stage: OpenApiExtractionStage, cause: unknown, ): OpenApiExtractionError => cause instanceof OpenApiExtractionError ? cause : new OpenApiExtractionError({ sourceName, stage, message: "OpenAPI extraction failed", details: ParseResult.isParseError(cause) ? ParseResult.TreeFormatter.formatErrorSync(cause) : String(cause), }); const normalizeOpenApiDocumentText = ( sourceName: string, openApiSpec: OpenApiSpecInput, ): Effect.Effect<string, OpenApiExtractionError> => { if (typeof openApiSpec === "string") { return Effect.succeed(openApiSpec); } return Effect.try({ try: () => JSON.stringify(openApiSpec), catch: (cause) => new OpenApiExtractionError({ sourceName, stage: "validate", message: "Unable to serialize OpenAPI input", details: String(cause), }), }); }; const asObject = (value: unknown): Record<string, unknown> => value !== null && typeof value === "object" && !Array.isArray(value) ? (value as Record<string, unknown>) : {}; const asArray = (value: unknown): ReadonlyArray<unknown> => Array.isArray(value) ? value : []; const asTrimmedString = (value: unknown): string | undefined => typeof value === "string" && value.trim().length > 0 ? value.trim() : undefined; const stableJsonValue = (value: unknown): unknown => { if (Array.isArray(value)) { return value.map((entry) => stableJsonValue(entry)); } if (value !== null && typeof value === "object") { return Object.fromEntries( Object.entries(value as Record<string, unknown>) .sort(([left], [right]) => left.localeCompare(right)) .map(([key, entry]) => [key, stableJsonValue(entry)]), ); } return value; }; const stableJsonStringify = (value: unknown): string => JSON.stringify(stableJsonValue(value)); const collectRefKeys = ( value: unknown, refs: Set<string>, ): void => { if (Array.isArray(value)) { for (const item of value) { collectRefKeys(item, refs); } return; } if (value === null || typeof value !== "object") { return; } const record = value as Record<string, unknown>; if (typeof record.$ref === "string" && record.$ref.startsWith("#/")) { refs.add(record.$ref); } for (const nested of Object.values(record)) { collectRefKeys(nested, refs); } }; const resolvePointerSegment = (segment: string): string => segment.replaceAll("~1", "/").replaceAll("~0", "~"); const resolveLocalRef = ( document: OpenApiJsonObject, value: unknown, activeRefs: ReadonlySet<string> = new Set<string>(), ): unknown => { const object = asObject(value); const ref = typeof object.$ref === "string" ? object.$ref : null; if (!ref || !ref.startsWith("#/") || activeRefs.has(ref)) { return value; } const resolved = ref .slice(2) .split("/") .reduce<unknown>((current, segment) => { if (current === undefined || current === null) { return undefined; } return asObject(current)[resolvePointerSegment(segment)]; }, document); if (resolved === undefined) { return value; } const nextActiveRefs = new Set(activeRefs); nextActiveRefs.add(ref); const resolvedObject = asObject(resolveLocalRef(document, resolved, nextActiveRefs)); const { $ref: _ignoredRef, ...rest } = object; return Object.keys(rest).length > 0 ? { ...resolvedObject, ...rest } : resolvedObject; }; const responseStatusRank = (statusCode: string): number => { if (/^2\d\d$/.test(statusCode)) { return 0; } if (statusCode === "default") { return 1; } return 2; }; const preferredContentEntry = ( content: unknown, ): readonly [string, Record<string, unknown>] | undefined => { const entries = Object.entries(asObject(content)) .sort(([left], [right]) => left.localeCompare(right)) .map(([mediaType, value]) => [mediaType, asObject(value)] as const); return entries.find(([mediaType]) => mediaType === "application/json") ?? entries.find(([mediaType]) => mediaType.toLowerCase().includes("+json")) ?? entries.find(([mediaType]) => mediaType.toLowerCase().includes("json")) ?? entries[0]; }; const contentSchemaFromOperationContent = ( content: unknown, ): unknown | undefined => { return preferredContentEntry(content)?.[1].schema; }; const contentEntriesFromContent = ( document: OpenApiJsonObject, content: unknown, ): ReadonlyArray<{ mediaType: string; schema?: unknown; examples?: Array<{ valueJson: string; mediaType?: string; label?: string; }>; }> => { const entries = Object.entries(asObject(content)) .sort(([left], [right]) => left.localeCompare(right)) .map(([mediaType, mediaValue]) => { const mediaRecord = asObject(resolveLocalRef(document, mediaValue)); const examples = examplesFromMediaType(mediaType, mediaRecord); return { mediaType, ...(mediaRecord.schema !== undefined ? { schema: mediaRecord.schema } : {}), ...(examples.length > 0 ? { examples } : {}), }; }); return entries; }; const examplesFromValue = ( value: unknown, input: { label?: string; mediaType?: string; } = {}, ): Array<{ valueJson: string; mediaType?: string; label?: string; }> => { const record = asObject(value); const examples: Array<{ valueJson: string; mediaType?: string; label?: string; }> = []; if (record.example !== undefined) { examples.push({ valueJson: stableJsonStringify(record.example), ...(input.mediaType ? { mediaType: input.mediaType } : {}), ...(input.label ? { label: input.label } : {}), }); } const exampleEntries = Object.entries(asObject(record.examples)) .sort(([left], [right]) => left.localeCompare(right)); for (const [key, exampleValue] of exampleEntries) { const exampleRecord = asObject(exampleValue); examples.push({ valueJson: stableJsonStringify( exampleRecord.value !== undefined ? exampleRecord.value : exampleValue, ), ...(input.mediaType ? { mediaType: input.mediaType } : {}), label: key, }); } return examples; }; const examplesFromSchema = ( schema: unknown, ): Array<{ valueJson: string; mediaType?: string; label?: string; }> => examplesFromValue(schema); const examplesFromMediaType = ( mediaType: string, mediaTypeRecord: Record<string, unknown>, ): Array<{ valueJson: string; mediaType?: string; label?: string; }> => { const direct = examplesFromValue(mediaTypeRecord, { mediaType }); if (direct.length > 0) { return direct; } return examplesFromSchema(mediaTypeRecord.schema).map((example) => ({ ...example, mediaType, })); }; const headerFromValue = ( document: OpenApiJsonObject, name: string, value: unknown, ): OpenApiHeader | undefined => { const header = asObject(resolveLocalRef(document, value)); if (Object.keys(header).length === 0) { return undefined; } const content = contentEntriesFromContent(document, header.content); const directExamples = content.length > 0 ? [] : examplesFromValue(header); return { name, ...(asTrimmedString(header.description) ? { description: asTrimmedString(header.description) } : {}), ...(typeof header.required === "boolean" ? { required: header.required } : {}), ...(typeof header.deprecated === "boolean" ? { deprecated: header.deprecated } : {}), ...(header.schema !== undefined ? { schema: header.schema } : {}), ...(content.length > 0 ? { content } : {}), ...(asTrimmedString(header.style) ? { style: asTrimmedString(header.style) } : {}), ...(typeof header.explode === "boolean" ? { explode: header.explode } : {}), ...(directExamples.length > 0 ? { examples: directExamples } : {}), }; }; const headersFromValue = ( document: OpenApiJsonObject, value: unknown, ): ReadonlyArray<OpenApiHeader> => Object.entries(asObject(value)) .sort(([left], [right]) => left.localeCompare(right)) .flatMap(([name, headerValue]) => { const header = headerFromValue(document, name, headerValue); return header ? [header] : []; }); const serversFromValue = ( value: unknown, ): ReadonlyArray<OpenApiServer> => asArray(value) .map((entry) => asObject(entry)) .flatMap((server) => { const url = asTrimmedString(server.url); if (!url) { return []; } const variables = Object.fromEntries( Object.entries(asObject(server.variables)) .sort(([left], [right]) => left.localeCompare(right)) .flatMap(([name, variableValue]) => { const variableRecord = asObject(variableValue); const defaultValue = asTrimmedString(variableRecord.default); return defaultValue ? [[name, defaultValue] as const] : []; }), ); return [{ url, ...(asTrimmedString(server.description) ? { description: asTrimmedString(server.description) } : {}), ...(Object.keys(variables).length > 0 ? { variables } : {}), }]; }); const pathItemForTool = ( document: OpenApiJsonObject, tool: OpenApiExtractedTool, ): Record<string, unknown> => asObject(asObject(document.paths)[tool.path]); const parameterKey = (input: { location: string; name: string; }): string => `${input.location}:${input.name}`; const parameterRecordMapForTool = ( document: OpenApiJsonObject, tool: OpenApiExtractedTool, ): ReadonlyMap<string, Record<string, unknown>> => { const merged = new Map<string, Record<string, unknown>>(); const pathItem = pathItemForTool(document, tool); const operation = operationForTool(document, tool); for (const parameterValue of asArray(pathItem.parameters)) { const parameter = asObject(resolveLocalRef(document, parameterValue)); const name = asTrimmedString(parameter.name); const location = asTrimmedString(parameter.in); if (!name || !location) { continue; } merged.set(parameterKey({ location, name }), parameter); } for (const parameterValue of asArray(operation.parameters)) { const parameter = asObject(resolveLocalRef(document, parameterValue)); const name = asTrimmedString(parameter.name); const location = asTrimmedString(parameter.in); if (!name || !location) { continue; } merged.set(parameterKey({ location, name }), parameter); } return merged; }; const operationForTool = ( document: OpenApiJsonObject, tool: OpenApiExtractedTool, ): Record<string, unknown> => asObject( asObject(asObject(document.paths)[tool.path])[tool.method], ); const requestBodySchemaForTool = ( document: OpenApiJsonObject, tool: OpenApiExtractedTool, ): unknown | undefined => { const operation = operationForTool(document, tool); if (Object.keys(operation).length === 0) { return undefined; } const requestBody = resolveLocalRef(document, operation.requestBody); return contentSchemaFromOperationContent(asObject(requestBody).content); }; const requestBodyPayloadForTool = ( document: OpenApiJsonObject, tool: OpenApiExtractedTool, ): OpenApiExtractedTool["invocation"]["requestBody"] => { const operation = operationForTool(document, tool); if (Object.keys(operation).length === 0) { return tool.invocation.requestBody; } const requestBody = asObject(resolveLocalRef(document, operation.requestBody)); if (Object.keys(requestBody).length === 0) { return tool.invocation.requestBody; } const contents = contentEntriesFromContent(document, requestBody.content); const contentTypes = contents.map((content) => content.mediaType); return { required: typeof requestBody.required === "boolean" ? requestBody.required : (tool.invocation.requestBody?.required ?? false), contentTypes, ...(contents.length > 0 ? { contents } : {}), }; }; const responseSchemaForTool = ( document: OpenApiJsonObject, tool: OpenApiExtractedTool, ): unknown | undefined => { const operation = operationForTool(document, tool); if (Object.keys(operation).length === 0) { return undefined; } const responseEntries = Object.entries(asObject(operation.responses)); const preferredResponses = responseEntries .filter(([status]) => /^2\d\d$/.test(status)) .sort(([left], [right]) => left.localeCompare(right)); const fallbackResponses = responseEntries.filter(([status]) => status === "default"); for (const [, responseValue] of [...preferredResponses, ...fallbackResponses]) { const response = resolveLocalRef(document, responseValue); const schema = contentSchemaFromOperationContent(asObject(response).content); if (schema !== undefined) { return schema; } } return undefined; }; const responseVariantsForTool = ( document: OpenApiJsonObject, tool: OpenApiExtractedTool, ): OpenApiExtractedTool["responses"] => { const operation = operationForTool(document, tool); if (Object.keys(operation).length === 0) { return undefined; } const responseEntries = Object.entries(asObject(operation.responses)) .sort(([left], [right]) => responseStatusRank(left) - responseStatusRank(right) || left.localeCompare(right), ); const responses = responseEntries.map(([statusCode, responseValue]) => { const response = asObject(resolveLocalRef(document, responseValue)); const contents = contentEntriesFromContent(document, response.content);