@xynehq/jaf
Version:
Juspay Agent Framework - A purely functional agent framework with immutable state and composable tools
133 lines • 4.52 kB
JavaScript
// Common error codes
export const ToolErrorCodes = {
// Validation errors
INVALID_INPUT: 'INVALID_INPUT',
MISSING_REQUIRED_FIELD: 'MISSING_REQUIRED_FIELD',
INVALID_FORMAT: 'INVALID_FORMAT',
// Permission errors
PERMISSION_DENIED: 'PERMISSION_DENIED',
INSUFFICIENT_PERMISSIONS: 'INSUFFICIENT_PERMISSIONS',
// Resource errors
NOT_FOUND: 'NOT_FOUND',
RESOURCE_UNAVAILABLE: 'RESOURCE_UNAVAILABLE',
// Execution errors
EXECUTION_FAILED: 'EXECUTION_FAILED',
TIMEOUT: 'TIMEOUT',
EXTERNAL_SERVICE_ERROR: 'EXTERNAL_SERVICE_ERROR',
// Generic
UNKNOWN_ERROR: 'UNKNOWN_ERROR'
};
/**
* Helper functions for creating standardized tool results
*/
export class ToolResponse {
static success(data, metadata) {
return {
status: 'success',
data,
metadata
};
}
static error(code, message, details, metadata) {
return {
status: 'error',
error: {
code,
message,
details
},
metadata
};
}
static validationError(message, details, metadata) {
return {
status: 'validation_error',
error: {
code: ToolErrorCodes.INVALID_INPUT,
message,
details
},
metadata
};
}
static permissionDenied(message, requiredPermissions, metadata) {
return {
status: 'permission_denied',
error: {
code: ToolErrorCodes.PERMISSION_DENIED,
message,
details: { requiredPermissions }
},
metadata
};
}
static notFound(resource, identifier, metadata) {
return {
status: 'not_found',
error: {
code: ToolErrorCodes.NOT_FOUND,
message: `${resource} not found${identifier ? `: ${identifier}` : ''}`,
details: { resource, identifier }
},
metadata
};
}
}
/**
* Tool execution wrapper that provides standardized error handling
*/
export function withErrorHandling(toolName, executor) {
return async (args, context) => {
const startTime = Date.now();
try {
console.log(`[TOOL:${toolName}] Starting execution with args:`, args);
const result = await executor(args, context);
const executionTime = Date.now() - startTime;
console.log(`[TOOL:${toolName}] Completed successfully in ${executionTime}ms`);
return ToolResponse.success(result, {
executionTimeMs: executionTime,
toolName
});
}
catch (error) {
const executionTime = Date.now() - startTime;
console.error(`[TOOL:${toolName}] Failed after ${executionTime}ms:`, error);
if (error instanceof Error) {
return ToolResponse.error(ToolErrorCodes.EXECUTION_FAILED, error.message, { stack: error.stack }, { executionTimeMs: executionTime, toolName });
}
return ToolResponse.error(ToolErrorCodes.UNKNOWN_ERROR, 'Unknown error occurred', error, { executionTimeMs: executionTime, toolName });
}
};
}
/**
* Permission checking helper
*/
export function requirePermissions(requiredPermissions) {
return (context) => {
const userPermissions = context.permissions || [];
const missingPermissions = requiredPermissions.filter(perm => !userPermissions.includes(perm));
if (missingPermissions.length > 0) {
return ToolResponse.permissionDenied(`Missing required permissions: ${missingPermissions.join(', ')}`, requiredPermissions);
}
return null; // No error
};
}
/**
* Convert ToolResult to string for backward compatibility with existing tools
*/
export function toolResultToString(result) {
if (result.status === 'success') {
return typeof result.data === 'string' ? result.data : JSON.stringify(result.data);
}
// For errors, return a structured error message
const error = result.error;
const errorObj = {
error: result.status,
code: error.code,
message: error.message,
...(error.details && { details: error.details }),
...(result.metadata && { metadata: result.metadata })
};
return JSON.stringify(errorObj, null, 2);
}
//# sourceMappingURL=tool-results.js.map