route-claudecode
Version:
Advanced routing and transformation system for Claude Code outputs to multiple AI providers
144 lines • 7.09 kB
JavaScript
;
/**
* Anthropic Request Validator
* Validates incoming requests against Anthropic API specification
*/
Object.defineProperty(exports, "__esModule", { value: true });
exports.validateAnthropicRequest = validateAnthropicRequest;
const types_1 = require("@/types");
function validateAnthropicRequest(request) {
if (!request || typeof request !== 'object') {
throw new types_1.ValidationError('Request must be an object');
}
// Required fields
if (!request.model || typeof request.model !== 'string') {
throw new types_1.ValidationError('Model is required and must be a string');
}
if (!request.messages || !Array.isArray(request.messages)) {
throw new types_1.ValidationError('Messages are required and must be an array');
}
if (request.messages.length === 0) {
throw new types_1.ValidationError('At least one message is required');
}
// Validate messages
for (let i = 0; i < request.messages.length; i++) {
const message = request.messages[i];
if (!message || typeof message !== 'object') {
throw new types_1.ValidationError(`Message at index ${i} must be an object`);
}
if (!message.role || typeof message.role !== 'string') {
throw new types_1.ValidationError(`Message at index ${i} must have a role`);
}
if (!['user', 'assistant', 'system'].includes(message.role)) {
throw new types_1.ValidationError(`Invalid role "${message.role}" at message index ${i}`);
}
if (message.content === undefined || message.content === null) {
throw new types_1.ValidationError(`Message at index ${i} must have content`);
}
// Validate content format
if (typeof message.content !== 'string' && !Array.isArray(message.content)) {
throw new types_1.ValidationError(`Message content at index ${i} must be string or array`);
}
if (Array.isArray(message.content)) {
validateContentBlocks(message.content, i);
}
}
// Optional field validation
if (request.system !== undefined) {
if (!Array.isArray(request.system)) {
throw new types_1.ValidationError('System must be an array');
}
for (let i = 0; i < request.system.length; i++) {
const systemMsg = request.system[i];
if (!systemMsg || typeof systemMsg !== 'object') {
throw new types_1.ValidationError(`System message at index ${i} must be an object`);
}
if (systemMsg.type !== 'text') {
throw new types_1.ValidationError(`System message at index ${i} must have type "text"`);
}
if (!systemMsg.text || typeof systemMsg.text !== 'string') {
throw new types_1.ValidationError(`System message at index ${i} must have text field`);
}
}
}
if (request.tools !== undefined) {
if (!Array.isArray(request.tools)) {
throw new types_1.ValidationError('Tools must be an array');
}
for (let i = 0; i < request.tools.length; i++) {
const tool = request.tools[i];
if (!tool || typeof tool !== 'object') {
throw new types_1.ValidationError(`Tool at index ${i} must be an object`);
}
if (!tool.name || typeof tool.name !== 'string') {
throw new types_1.ValidationError(`Tool at index ${i} must have a name`);
}
if (!tool.description || typeof tool.description !== 'string') {
throw new types_1.ValidationError(`Tool at index ${i} must have a description`);
}
if (!tool.input_schema || typeof tool.input_schema !== 'object') {
throw new types_1.ValidationError(`Tool at index ${i} must have input_schema`);
}
}
}
// Validate optional numeric fields
if (request.max_tokens !== undefined) {
if (typeof request.max_tokens !== 'number' || request.max_tokens <= 0) {
throw new types_1.ValidationError('max_tokens must be a positive number');
}
}
if (request.temperature !== undefined) {
if (typeof request.temperature !== 'number' || request.temperature < 0 || request.temperature > 1) {
throw new types_1.ValidationError('temperature must be a number between 0 and 1');
}
}
if (request.stream !== undefined && typeof request.stream !== 'boolean') {
throw new types_1.ValidationError('stream must be a boolean');
}
return true;
}
function validateContentBlocks(content, messageIndex) {
for (let i = 0; i < content.length; i++) {
const block = content[i];
if (!block || typeof block !== 'object') {
throw new types_1.ValidationError(`Content block at index ${i} in message ${messageIndex} must be an object`);
}
if (!block.type || typeof block.type !== 'string') {
throw new types_1.ValidationError(`Content block at index ${i} in message ${messageIndex} must have a type`);
}
switch (block.type) {
case 'text':
if (!block.text || typeof block.text !== 'string') {
throw new types_1.ValidationError(`Text block at index ${i} in message ${messageIndex} must have text field`);
}
break;
case 'tool_use':
if (!block.id || typeof block.id !== 'string') {
throw new types_1.ValidationError(`Tool use block at index ${i} in message ${messageIndex} must have id`);
}
if (!block.name || typeof block.name !== 'string') {
throw new types_1.ValidationError(`Tool use block at index ${i} in message ${messageIndex} must have name`);
}
if (block.input === undefined) {
throw new types_1.ValidationError(`Tool use block at index ${i} in message ${messageIndex} must have input`);
}
break;
case 'tool_result':
if (!block.tool_use_id || typeof block.tool_use_id !== 'string') {
throw new types_1.ValidationError(`Tool result block at index ${i} in message ${messageIndex} must have tool_use_id`);
}
if (block.content === undefined) {
throw new types_1.ValidationError(`Tool result block at index ${i} in message ${messageIndex} must have content`);
}
break;
case 'image':
if (!block.source || typeof block.source !== 'object') {
throw new types_1.ValidationError(`Image block at index ${i} in message ${messageIndex} must have source`);
}
break;
default:
throw new types_1.ValidationError(`Unknown content block type "${block.type}" at index ${i} in message ${messageIndex}`);
}
}
}
//# sourceMappingURL=validator.js.map