openai-mock-api
Version:
A mock OpenAI API server for testing LLM applications
135 lines • 6.82 kB
JavaScript
;
Object.defineProperty(exports, "__esModule", { value: true });
exports.RequestValidator = void 0;
const error_middleware_1 = require("../middleware/error.middleware");
class RequestValidator {
constructor(logger) {
this.logger = logger;
}
validateChatCompletionRequest(request) {
if (!request || typeof request !== 'object') {
throw new error_middleware_1.ValidationError('Request body must be an object');
}
// Validate messages
if (!request.messages || !Array.isArray(request.messages) || request.messages.length === 0) {
throw new error_middleware_1.ValidationError('messages is required and must be a non-empty array', 'messages');
}
// Validate each message
request.messages.forEach((message, index) => {
this.validateMessage(message, index);
});
// Validate model
if (!request.model || typeof request.model !== 'string') {
throw new error_middleware_1.ValidationError('model is required and must be a string', 'model');
}
// Validate optional parameters
if (request.max_tokens !== undefined) {
if (typeof request.max_tokens !== 'number' || request.max_tokens <= 0) {
throw new error_middleware_1.ValidationError('max_tokens must be a positive number', 'max_tokens');
}
}
if (request.temperature !== undefined) {
if (typeof request.temperature !== 'number' ||
request.temperature < 0 ||
request.temperature > 2) {
throw new error_middleware_1.ValidationError('temperature must be a number between 0 and 2', 'temperature');
}
}
if (request.top_p !== undefined) {
if (typeof request.top_p !== 'number' || request.top_p < 0 || request.top_p > 1) {
throw new error_middleware_1.ValidationError('top_p must be a number between 0 and 1', 'top_p');
}
}
if (request.n !== undefined) {
if (typeof request.n !== 'number' || request.n <= 0 || !Number.isInteger(request.n)) {
throw new error_middleware_1.ValidationError('n must be a positive integer', 'n');
}
}
if (request.stream !== undefined && typeof request.stream !== 'boolean') {
throw new error_middleware_1.ValidationError('stream must be a boolean', 'stream');
}
if (request.stop !== undefined) {
if (typeof request.stop !== 'string' && !Array.isArray(request.stop)) {
throw new error_middleware_1.ValidationError('stop must be a string or array of strings', 'stop');
}
if (Array.isArray(request.stop)) {
request.stop.forEach((s) => {
if (typeof s !== 'string') {
throw new error_middleware_1.ValidationError('stop array must contain only strings', 'stop');
}
});
}
}
return request;
}
validateMessage(message, index) {
if (!message || typeof message !== 'object') {
throw new error_middleware_1.ValidationError(`messages[${index}] must be an object`, `messages[${index}]`);
}
// Validate role
const validRoles = ['system', 'user', 'assistant', 'tool'];
if (!message.role || !validRoles.includes(message.role)) {
throw new error_middleware_1.ValidationError(`messages[${index}].role must be one of: ${validRoles.join(', ')}`, `messages[${index}].role`);
}
// Validate content based on role
if (message.role === 'tool') {
if (!message.tool_call_id || typeof message.tool_call_id !== 'string') {
throw new error_middleware_1.ValidationError(`messages[${index}].tool_call_id is required for tool messages`, `messages[${index}].tool_call_id`);
}
}
// Validate tool_calls if present
if (message.tool_calls) {
if (!Array.isArray(message.tool_calls)) {
throw new error_middleware_1.ValidationError(`messages[${index}].tool_calls must be an array`, `messages[${index}].tool_calls`);
}
message.tool_calls.forEach((toolCall, toolIndex) => {
this.validateToolCall(toolCall, `messages[${index}].tool_calls[${toolIndex}]`);
});
}
// Ensure either content or tool_calls is present for assistant messages
if (message.role === 'assistant' && !message.content && !message.tool_calls) {
throw new error_middleware_1.ValidationError(`messages[${index}] must have either content or tool_calls`, `messages[${index}]`);
}
}
validateToolCalls(toolCalls) {
if (!toolCalls)
return;
toolCalls.forEach((toolCall, index) => {
this.validateToolCall(toolCall, `tool_calls[${index}]`);
});
}
validateToolCall(toolCall, path) {
if (!toolCall || typeof toolCall !== 'object') {
throw new error_middleware_1.ValidationError(`${path} must be an object`, path);
}
// Validate id
if (!toolCall.id || typeof toolCall.id !== 'string') {
throw new error_middleware_1.ValidationError(`${path}.id is required and must be a string`, `${path}.id`);
}
// Validate type
if (toolCall.type !== 'function') {
throw new error_middleware_1.ValidationError(`${path}.type must be 'function'`, `${path}.type`);
}
// Validate function
if (!toolCall.function || typeof toolCall.function !== 'object') {
throw new error_middleware_1.ValidationError(`${path}.function is required and must be an object`, `${path}.function`);
}
// Validate function.name
if (!toolCall.function.name || typeof toolCall.function.name !== 'string') {
throw new error_middleware_1.ValidationError(`${path}.function.name is required and must be a string`, `${path}.function.name`);
}
// Validate function.arguments
if (!toolCall.function.arguments || typeof toolCall.function.arguments !== 'string') {
throw new error_middleware_1.ValidationError(`${path}.function.arguments is required and must be a string`, `${path}.function.arguments`);
}
// Validate that arguments is valid JSON
try {
JSON.parse(toolCall.function.arguments);
}
catch (e) {
throw new error_middleware_1.ValidationError(`${path}.function.arguments must be a valid JSON string`, `${path}.function.arguments`);
}
}
}
exports.RequestValidator = RequestValidator;
//# sourceMappingURL=request-validator.js.map