Initial commit

This commit is contained in:
Jordan
2026-04-01 23:16:45 +01:00
commit 91cfdaee72
200 changed files with 25589 additions and 0 deletions

View File

@@ -0,0 +1,215 @@
/**
* Centralized error handling for tools
* Provides consistent error responses and logging
*/
/**
* Handle and format tool errors
* @param {Error|string} error - The error object or message
* @param {string} context - Context where the error occurred (e.g., "save_module", "create_record")
* @param {Object} additionalInfo - Additional information to include in response
* @returns {Object} Formatted error response
*/
export function handleToolError(error, context = "unknown", additionalInfo = {}) {
// Log error to console
console.error(`[Tool Error - ${context}]`, error instanceof Error ? error.message : error);
if (error instanceof Error && error.stack) {
console.error(`Stack:`, error.stack);
}
// Extract error message
let errorMessage = error instanceof Error ? error.message : String(error);
let errorCode = "UNKNOWN_ERROR";
let statusCode = 500;
// Handle specific error types
if (error.response) {
// Axios error with response
statusCode = error.response.status || 500;
errorMessage = error.response.data?.message ||
error.response.data?.error ||
errorMessage;
errorCode = `HTTP_${statusCode}`;
} else if (error.code) {
// Error with code (like ENOTFOUND, ECONNREFUSED, etc.)
errorCode = error.code;
errorMessage = `${error.code}: ${errorMessage}`;
}
// Return formatted error response
return {
content: [{
type: "text",
text: JSON.stringify({
success: false,
error: {
code: errorCode,
message: errorMessage,
context: context,
...additionalInfo
}
}, null, 2)
}],
isError: true
};
}
/**
* Handle API response errors (when response contains error indication)
* @param {Object} data - Response data from API
* @param {string} context - Context where error occurred
* @returns {Object|null} Error response or null if no error
*/
export function handleApiResponse(data, context = "unknown") {
// Check for common error patterns in Acai CMS responses
/*if (!data) {
return handleToolError("Empty response from API", context, { details: "API returned null or undefined" });
}*/
// PHP/Acai error responses typically have error field or PHPSyntax errors
if (data.error || data.Error) {
return handleToolError(data.error || data.Error, context, { details: data });
}
if (data.PHPSyntax) {
return handleToolError(`PHP Syntax Error: ${data.PHPSyntax}`, context, { details: data });
}
// If it's a string response with error indicators
if (typeof data === 'string' && data.trim().length > 0) {
// Check for common error patterns
if (data.toLowerCase().includes('error') ||
data.toLowerCase().includes('fatal') ||
data.toLowerCase().includes('undefined') ||
data.toLowerCase().includes('syntax')) {
return handleToolError(data, context, { details: "API returned error string" });
}
}
// If success field exists and is false
if (data.success === false) {
return handleToolError(data.message || "API returned success: false", context, { details: data });
}
// No error detected
return null;
}
/**
* Validate required parameters
* @param {Object} params - Parameters object
* @param {string[]} requiredFields - Array of required field names
* @param {string} context - Context where validation occurs
* @returns {Object|null} Error response or null if all valid
*/
export function validateRequired(params, requiredFields, context = "unknown") {
const missingFields = [];
requiredFields.forEach(field => {
const value = params[field];
if (value === null || value === undefined ||
(typeof value === 'string' && value.trim() === '')) {
missingFields.push(field);
}
});
if (missingFields.length > 0) {
return handleToolError(
`Missing required parameters: ${missingFields.join(', ')}`,
context,
{ requiredFields, missingFields }
);
}
return null;
}
/**
* Validate parameter types
* @param {Object} params - Parameters object
* @param {Object} schema - Schema of expected types {fieldName: 'string'|'number'|'boolean'|'array'|'object'}
* @param {string} context - Context where validation occurs
* @returns {Object|null} Error response or null if all valid
*/
export function validateTypes(params, schema, context = "unknown") {
const typeErrors = [];
for (const [field, expectedType] of Object.entries(schema)) {
const value = params[field];
if (value === null || value === undefined) {
continue; // Skip optional fields that are not provided
}
let actualType = typeof value;
if (Array.isArray(value)) actualType = 'array';
if (value instanceof Date) actualType = 'date';
if (actualType !== expectedType) {
typeErrors.push(`${field}: expected ${expectedType}, got ${actualType}`);
}
}
if (typeErrors.length > 0) {
return handleToolError(
`Type validation failed: ${typeErrors.join('; ')}`,
context,
{ typeErrors }
);
}
return null;
}
/**
* Safely parse JSON with error handling
* @param {string} jsonString - JSON string to parse
* @param {string} context - Context where parsing occurs
* @returns {Object} Parsed object or error response object
*/
export function safeJsonParse(jsonString, context = "unknown") {
try {
return { success: true, data: JSON.parse(jsonString) };
} catch (error) {
return {
success: false,
error: handleToolError(error, `${context} - JSON parsing`, { input: jsonString.substring(0, 100) })
};
}
}
/**
* Create a validation middleware for tools
* @param {string[]} requiredFields - Required parameter names
* @param {Object} typeSchema - Type validation schema
* @returns {Function} Middleware function
*/
export function createValidator(requiredFields = [], typeSchema = {}) {
return function validateInput(params, context = "unknown") {
// Check required fields
const requiredError = validateRequired(params, requiredFields, context);
if (requiredError) return requiredError;
// Check types
const typeError = validateTypes(params, typeSchema, context);
if (typeError) return typeError;
return null; // No errors
};
}
/**
* Wrap a tool handler with automatic error handling
* @param {Function} handler - The tool handler function
* @param {string} toolName - Name of the tool for logging
* @returns {Function} Wrapped handler
*/
export function withErrorHandling(handler, toolName = "unknown") {
return async (params, extra) => {
try {
return await handler(params, extra);
} catch (error) {
return handleToolError(error, toolName);
}
};
}