mirror of
https://github.com/danny-avila/LibreChat.git
synced 2025-12-17 00:40:14 +01:00
📋 feat: Support Custom Content-Types in Action Descriptors (#9364)
This commit is contained in:
parent
49e8443ec5
commit
3a47deac07
3 changed files with 81 additions and 2 deletions
|
|
@ -15,6 +15,7 @@ import {
|
||||||
getWeatherOpenapiSpec,
|
getWeatherOpenapiSpec,
|
||||||
whimsicalOpenapiSpec,
|
whimsicalOpenapiSpec,
|
||||||
scholarAIOpenapiSpec,
|
scholarAIOpenapiSpec,
|
||||||
|
formOpenAPISpec,
|
||||||
swapidev,
|
swapidev,
|
||||||
} from './openapiSpecs';
|
} from './openapiSpecs';
|
||||||
import { AuthorizationTypeEnum, AuthTypeEnum } from '../src/types/agents';
|
import { AuthorizationTypeEnum, AuthTypeEnum } from '../src/types/agents';
|
||||||
|
|
@ -960,6 +961,34 @@ describe('openapiToFunction', () => {
|
||||||
|
|
||||||
expect(requestBuilders).toHaveProperty('GetCurrentWeather');
|
expect(requestBuilders).toHaveProperty('GetCurrentWeather');
|
||||||
expect(requestBuilders.GetCurrentWeather).toBeInstanceOf(ActionRequest);
|
expect(requestBuilders.GetCurrentWeather).toBeInstanceOf(ActionRequest);
|
||||||
|
expect(requestBuilders.GetCurrentWeather.contentType).toBe('application/json');
|
||||||
|
});
|
||||||
|
|
||||||
|
it('preserves OpenAPI spec content-type', () => {
|
||||||
|
const { functionSignatures, requestBuilders } = openapiToFunction(formOpenAPISpec);
|
||||||
|
expect(functionSignatures.length).toBe(1);
|
||||||
|
expect(functionSignatures[0].name).toBe('SubmitForm');
|
||||||
|
|
||||||
|
const parameters = functionSignatures[0].parameters as ParametersSchema & {
|
||||||
|
properties: {
|
||||||
|
'entry.123': {
|
||||||
|
type: 'string';
|
||||||
|
};
|
||||||
|
'entry.456': {
|
||||||
|
type: 'string';
|
||||||
|
};
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
expect(parameters).toBeDefined();
|
||||||
|
expect(parameters.properties['entry.123']).toBeDefined();
|
||||||
|
expect(parameters.properties['entry.123'].type).toBe('string');
|
||||||
|
expect(parameters.properties['entry.456']).toBeDefined();
|
||||||
|
expect(parameters.properties['entry.456'].type).toBe('string');
|
||||||
|
|
||||||
|
expect(requestBuilders).toHaveProperty('SubmitForm');
|
||||||
|
expect(requestBuilders.SubmitForm).toBeInstanceOf(ActionRequest);
|
||||||
|
expect(requestBuilders.SubmitForm.contentType).toBe('application/x-www-form-urlencoded');
|
||||||
});
|
});
|
||||||
|
|
||||||
describe('openapiToFunction with $ref resolution', () => {
|
describe('openapiToFunction with $ref resolution', () => {
|
||||||
|
|
|
||||||
|
|
@ -162,6 +162,53 @@ export const whimsicalOpenapiSpec: OpenAPIV3.Document = {
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
|
export const formOpenAPISpec: OpenAPIV3.Document = {
|
||||||
|
openapi: '3.1.0',
|
||||||
|
info: {
|
||||||
|
title: 'Submit Google Form',
|
||||||
|
description: 'Submit data to a Google Forms',
|
||||||
|
version: 'v1.0.0',
|
||||||
|
},
|
||||||
|
servers: [
|
||||||
|
{
|
||||||
|
url: 'https://docs.google.com/forms',
|
||||||
|
},
|
||||||
|
],
|
||||||
|
paths: {
|
||||||
|
'/formResponse': {
|
||||||
|
post: {
|
||||||
|
description: 'Submit a Google Form',
|
||||||
|
operationId: 'SubmitForm',
|
||||||
|
requestBody: {
|
||||||
|
required: true,
|
||||||
|
content: {
|
||||||
|
'application/x-www-form-urlencoded': {
|
||||||
|
schema: {
|
||||||
|
type: 'object',
|
||||||
|
properties: {
|
||||||
|
'entry.123': {
|
||||||
|
type: 'string',
|
||||||
|
description: 'Name',
|
||||||
|
},
|
||||||
|
'entry.456': {
|
||||||
|
type: 'string',
|
||||||
|
description: 'Address',
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
deprecated: false,
|
||||||
|
responses: {},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
components: {
|
||||||
|
schemas: {},
|
||||||
|
},
|
||||||
|
};
|
||||||
|
|
||||||
export const scholarAIOpenapiSpec = `
|
export const scholarAIOpenapiSpec = `
|
||||||
openapi: 3.0.1
|
openapi: 3.0.1
|
||||||
info:
|
info:
|
||||||
|
|
|
||||||
|
|
@ -500,10 +500,11 @@ export function openapiToFunction(
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
let contentType = '';
|
||||||
if (operationObj.requestBody) {
|
if (operationObj.requestBody) {
|
||||||
const requestBody = operationObj.requestBody as RequestBodyObject;
|
const requestBody = operationObj.requestBody as RequestBodyObject;
|
||||||
const content = requestBody.content;
|
const content = requestBody.content;
|
||||||
const contentType = Object.keys(content ?? {})[0];
|
contentType = Object.keys(content ?? {})[0];
|
||||||
const schema = content?.[contentType]?.schema;
|
const schema = content?.[contentType]?.schema;
|
||||||
const resolvedSchema = resolveRef(
|
const resolvedSchema = resolveRef(
|
||||||
schema as OpenAPIV3.ReferenceObject | OpenAPIV3.SchemaObject,
|
schema as OpenAPIV3.ReferenceObject | OpenAPIV3.SchemaObject,
|
||||||
|
|
@ -522,6 +523,8 @@ export function openapiToFunction(
|
||||||
paramLocations[key] = 'body';
|
paramLocations[key] = 'body';
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
contentType = contentType ?? 'application/json';
|
||||||
}
|
}
|
||||||
|
|
||||||
const functionSignature = new FunctionSignature(
|
const functionSignature = new FunctionSignature(
|
||||||
|
|
@ -538,7 +541,7 @@ export function openapiToFunction(
|
||||||
method,
|
method,
|
||||||
operationId,
|
operationId,
|
||||||
!!(operationObj['x-openai-isConsequential'] ?? false),
|
!!(operationObj['x-openai-isConsequential'] ?? false),
|
||||||
operationObj.requestBody ? 'application/json' : '',
|
contentType,
|
||||||
paramLocations,
|
paramLocations,
|
||||||
);
|
);
|
||||||
|
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue