UNPKG

adk-typescript

Version:

TypeScript port of Google's Agent Development Kit (ADK)

234 lines (233 loc) 8.29 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.OperationParser = void 0; const common_1 = require("../common/common"); /** * Generates parameters for TypeScript functions from an OpenAPI operation. * * This class processes an OpenApiOperation object and provides helper methods * to extract information needed to generate TypeScript function declarations, * docstrings, signatures, and JSON schemas. It handles parameter processing, * name deduplication, and type hint generation. */ class OperationParser { /** * Initializes the OperationParser with an OpenApiOperation. * * @param operation The OpenApiOperation object or a dictionary to process * @param shouldParse Whether to parse the operation during initialization */ constructor(operation, shouldParse = true) { /** * Parameters for the operation */ this.params = []; /** * Return value for the operation */ this.returnValue = null; if (typeof operation === 'string') { this.operation = JSON.parse(operation); } else { this.operation = operation; } if (shouldParse) { this._processOperationParameters(); this._processRequestBody(); this._processReturnValue(); this._dedupeParamNames(); } } /** * Creates an OperationParser with pre-defined params and return value * * @param operation The OpenApiOperation object * @param params Parameters for the operation * @param returnValue Return value for the operation * @returns A new OperationParser instance */ static load(operation, params, returnValue = null) { const parser = new OperationParser(operation, false); parser.params = params; parser.returnValue = returnValue; return parser; } /** * Processes parameters from the OpenAPI operation */ _processOperationParameters() { const parameters = this.operation.parameters || []; for (const param of parameters) { const originalName = param.name; const description = param.description || ''; const location = param.in || ''; const schema = param.schema || {}; // Preserve description in schema if not already present if (schema.description === undefined && description !== '') { schema.description = description; } const required = param.required; this.params.push(new common_1.ApiParameter(originalName, location, schema, description, '', required)); } } /** * Processes the request body from the OpenAPI operation */ _processRequestBody() { const requestBody = this.operation.requestBody; if (!requestBody) { return; } const content = requestBody.content || {}; if (Object.keys(content).length === 0) { return; } // Process first mime type only const firstMimeType = Object.keys(content)[0]; const mediaTypeObject = content[firstMimeType]; const schema = mediaTypeObject.schema || {}; const description = requestBody.description || ''; const required = requestBody.required; if (schema.type === 'object') { const properties = schema.properties || {}; // For objects, extract each property as a parameter Object.entries(properties).forEach(([propName, propDetails]) => { const propRequired = Array.isArray(schema.required) && schema.required.includes(propName); this.params.push(new common_1.ApiParameter(propName, 'body', propDetails, propDetails.description || '', '', propRequired)); }); } else if (schema.type === 'array') { this.params.push(new common_1.ApiParameter('array', 'body', schema, description, '', required)); } else { // Empty name for unnamed body param this.params.push(new common_1.ApiParameter('', 'body', schema, description, '', required)); } } /** * Deduplicates parameter names to avoid conflicts */ _dedupeParamNames() { const paramsCnt = {}; for (const param of this.params) { const name = param.pyName; if (!(name in paramsCnt)) { paramsCnt[name] = 0; } else { paramsCnt[name]++; param.pyName = `${name}_${paramsCnt[name] - 1}`; } } } /** * Processes the return value from the OpenAPI operation */ _processReturnValue() { const responses = this.operation.responses || {}; // Default to Any if no 2xx response or if schema is missing let returnSchema = { type: 'any' }; // Take the 20x response with the smallest response code const validCodes = Object.keys(responses).filter(code => code.startsWith('2')); const min20xStatusCode = validCodes.length > 0 ? validCodes.sort()[0] : null; if (min20xStatusCode && responses[min20xStatusCode].content) { const content = responses[min20xStatusCode].content; for (const mimeType in content) { if (content[mimeType].schema) { returnSchema = content[mimeType].schema; break; } } } this.returnValue = new common_1.ApiParameter('', '', returnSchema, ''); } /** * Returns the generated function name * @returns The function name */ getFunctionName() { const operationId = this.operation.operationId; if (!operationId) { throw new Error('Operation ID is missing'); } return (0, common_1.toSnakeCase)(operationId).substring(0, 60); } /** * Returns the return type hint string (like 'string', 'number', etc.) * @returns The return type hint */ getReturnTypeHint() { return this.returnValue ? this.returnValue.typeHint : 'any'; } /** * Returns the return type value * @returns The return type value */ getReturnTypeValue() { return this.returnValue ? this.returnValue.typeValue : Object; } /** * Returns the list of Parameter objects * @returns The parameters */ getParameters() { return this.params; } /** * Returns the return value Parameter object * @returns The return value */ getReturnValue() { return this.returnValue; } /** * Returns the name of the auth scheme for this operation from the spec * @returns The auth scheme name */ getAuthSchemeName() { if (this.operation.security && this.operation.security.length > 0) { const schemeNames = Object.keys(this.operation.security[0]); if (schemeNames.length > 0) { return schemeNames[0]; } } return ''; } /** * Returns the generated JSDoc string * @returns The JSDoc string */ getJSDocString() { const jsDocParams = this.params.map(param => param.toJSDocString()); const jsDocDescription = this.operation.summary || this.operation.description || ''; const jsDocReturn = common_1.JsDocHelper.generateReturnDoc(this.operation.responses || {}); return `/** * ${jsDocDescription} * ${jsDocParams.map(param => ` * ${param}`).join('\n')} * * ${jsDocReturn} */`; } /** * Returns the JSON schema for the function arguments * @returns The JSON schema */ getJsonSchema() { const properties = {}; for (const p of this.params) { properties[p.pyName] = p.paramSchema; } return { properties, required: this.params .filter(p => p.required !== false) .map(p => p.pyName), title: `${this.operation.operationId || 'unnamed'}_Arguments`, type: 'object' }; } } exports.OperationParser = OperationParser;