@pod-protocol/cli
Version:
Command-line interface for PoD Protocol (Prompt or Die) AI Agent Communication Protocol
325 lines (324 loc) • 13.9 kB
JavaScript
import { BRAND_COLORS, statusMessage } from "./branding.js";
/**
* Enhanced Error Handling System for PoD CLI
* Provides structured error codes, detailed diagnostics, and helpful suggestions
*/
export var ErrorCode;
(function (ErrorCode) {
// Network & Connection Errors (1000-1099)
ErrorCode[ErrorCode["NETWORK_CONNECTION_FAILED"] = 1001] = "NETWORK_CONNECTION_FAILED";
ErrorCode[ErrorCode["NETWORK_TIMEOUT"] = 1002] = "NETWORK_TIMEOUT";
ErrorCode[ErrorCode["NETWORK_INVALID_URL"] = 1003] = "NETWORK_INVALID_URL";
ErrorCode[ErrorCode["RPC_ENDPOINT_UNREACHABLE"] = 1004] = "RPC_ENDPOINT_UNREACHABLE";
// Authentication & Wallet Errors (1100-1199)
ErrorCode[ErrorCode["WALLET_NOT_FOUND"] = 1101] = "WALLET_NOT_FOUND";
ErrorCode[ErrorCode["WALLET_INVALID_KEYPAIR"] = 1102] = "WALLET_INVALID_KEYPAIR";
ErrorCode[ErrorCode["WALLET_INSUFFICIENT_FUNDS"] = 1103] = "WALLET_INSUFFICIENT_FUNDS";
ErrorCode[ErrorCode["WALLET_UNAUTHORIZED"] = 1104] = "WALLET_UNAUTHORIZED";
ErrorCode[ErrorCode["KEYPAIR_FILE_NOT_FOUND"] = 1105] = "KEYPAIR_FILE_NOT_FOUND";
// Agent Errors (1200-1299)
ErrorCode[ErrorCode["AGENT_NOT_FOUND"] = 1201] = "AGENT_NOT_FOUND";
ErrorCode[ErrorCode["AGENT_ALREADY_EXISTS"] = 1202] = "AGENT_ALREADY_EXISTS";
ErrorCode[ErrorCode["AGENT_INVALID_CAPABILITIES"] = 1203] = "AGENT_INVALID_CAPABILITIES";
ErrorCode[ErrorCode["AGENT_REGISTRATION_FAILED"] = 1204] = "AGENT_REGISTRATION_FAILED";
ErrorCode[ErrorCode["AGENT_UPDATE_FAILED"] = 1205] = "AGENT_UPDATE_FAILED";
// Message Errors (1300-1399)
ErrorCode[ErrorCode["MESSAGE_SEND_FAILED"] = 1301] = "MESSAGE_SEND_FAILED";
ErrorCode[ErrorCode["MESSAGE_NOT_FOUND"] = 1302] = "MESSAGE_NOT_FOUND";
ErrorCode[ErrorCode["MESSAGE_INVALID_RECIPIENT"] = 1303] = "MESSAGE_INVALID_RECIPIENT";
ErrorCode[ErrorCode["MESSAGE_PAYLOAD_TOO_LARGE"] = 1304] = "MESSAGE_PAYLOAD_TOO_LARGE";
ErrorCode[ErrorCode["MESSAGE_INVALID_TYPE"] = 1305] = "MESSAGE_INVALID_TYPE";
// Channel Errors (1400-1499)
ErrorCode[ErrorCode["CHANNEL_NOT_FOUND"] = 1401] = "CHANNEL_NOT_FOUND";
ErrorCode[ErrorCode["CHANNEL_ALREADY_EXISTS"] = 1402] = "CHANNEL_ALREADY_EXISTS";
ErrorCode[ErrorCode["CHANNEL_ACCESS_DENIED"] = 1403] = "CHANNEL_ACCESS_DENIED";
ErrorCode[ErrorCode["CHANNEL_FULL"] = 1404] = "CHANNEL_FULL";
ErrorCode[ErrorCode["CHANNEL_CREATION_FAILED"] = 1405] = "CHANNEL_CREATION_FAILED";
// Escrow Errors (1500-1599)
ErrorCode[ErrorCode["ESCROW_INSUFFICIENT_BALANCE"] = 1501] = "ESCROW_INSUFFICIENT_BALANCE";
ErrorCode[ErrorCode["ESCROW_DEPOSIT_FAILED"] = 1502] = "ESCROW_DEPOSIT_FAILED";
ErrorCode[ErrorCode["ESCROW_WITHDRAWAL_FAILED"] = 1503] = "ESCROW_WITHDRAWAL_FAILED";
ErrorCode[ErrorCode["ESCROW_NOT_FOUND"] = 1504] = "ESCROW_NOT_FOUND";
// Configuration Errors (1600-1699)
ErrorCode[ErrorCode["CONFIG_FILE_NOT_FOUND"] = 1601] = "CONFIG_FILE_NOT_FOUND";
ErrorCode[ErrorCode["CONFIG_INVALID_FORMAT"] = 1602] = "CONFIG_INVALID_FORMAT";
ErrorCode[ErrorCode["CONFIG_MISSING_REQUIRED_FIELD"] = 1603] = "CONFIG_MISSING_REQUIRED_FIELD";
ErrorCode[ErrorCode["CONFIG_WRITE_FAILED"] = 1604] = "CONFIG_WRITE_FAILED";
// Validation Errors (1700-1799)
ErrorCode[ErrorCode["VALIDATION_INVALID_ADDRESS"] = 1701] = "VALIDATION_INVALID_ADDRESS";
ErrorCode[ErrorCode["VALIDATION_INVALID_AMOUNT"] = 1702] = "VALIDATION_INVALID_AMOUNT";
ErrorCode[ErrorCode["VALIDATION_INVALID_INPUT"] = 1703] = "VALIDATION_INVALID_INPUT";
ErrorCode[ErrorCode["VALIDATION_MISSING_REQUIRED_PARAM"] = 1704] = "VALIDATION_MISSING_REQUIRED_PARAM";
// System Errors (1800-1899)
ErrorCode[ErrorCode["SYSTEM_COMMAND_NOT_FOUND"] = 1801] = "SYSTEM_COMMAND_NOT_FOUND";
ErrorCode[ErrorCode["SYSTEM_PERMISSION_DENIED"] = 1802] = "SYSTEM_PERMISSION_DENIED";
ErrorCode[ErrorCode["SYSTEM_DISK_FULL"] = 1803] = "SYSTEM_DISK_FULL";
ErrorCode[ErrorCode["SYSTEM_UNEXPECTED_ERROR"] = 1804] = "SYSTEM_UNEXPECTED_ERROR";
// Program/Contract Errors (1900-1999)
ErrorCode[ErrorCode["PROGRAM_NOT_DEPLOYED"] = 1901] = "PROGRAM_NOT_DEPLOYED";
ErrorCode[ErrorCode["PROGRAM_ACCOUNT_NOT_FOUND"] = 1902] = "PROGRAM_ACCOUNT_NOT_FOUND";
ErrorCode[ErrorCode["PROGRAM_INSTRUCTION_FAILED"] = 1903] = "PROGRAM_INSTRUCTION_FAILED";
ErrorCode[ErrorCode["PROGRAM_SIMULATION_FAILED"] = 1904] = "PROGRAM_SIMULATION_FAILED";
})(ErrorCode || (ErrorCode = {}));
export class PodError extends Error {
constructor(details) {
super(details.message);
this.name = 'PodError';
this.code = details.code;
this.title = details.title;
this.cause = details.cause;
this.suggestions = details.suggestions;
this.technicalDetails = details.technicalDetails;
this.documentationUrl = details.documentationUrl;
}
}
/**
* Predefined error templates for common issues
*/
export const ERROR_TEMPLATES = {
[ErrorCode.NETWORK_CONNECTION_FAILED]: {
title: 'Network Connection Failed',
message: 'Unable to connect to the Solana network',
suggestions: [
'Check your internet connection',
'Verify the RPC endpoint URL is correct',
'Try switching to a different network (devnet/mainnet)',
'Check if the network is experiencing downtime'
],
documentationUrl: 'https://docs.solana.com/cluster/rpc-endpoints'
},
[ErrorCode.WALLET_NOT_FOUND]: {
title: 'Wallet Not Found',
message: 'No wallet configured or keypair file not found',
suggestions: [
'Generate a new keypair with: solana-keygen new',
'Set your keypair path with: pod config set-keypair <path>',
'Verify the keypair file exists and is readable'
],
documentationUrl: 'https://docs.solana.com/wallet-guide/cli'
},
[ErrorCode.WALLET_INSUFFICIENT_FUNDS]: {
title: 'Insufficient Funds',
message: 'Wallet does not have enough SOL for this transaction',
suggestions: [
'Check your wallet balance with: pod config wallet-info',
'For devnet: Get test SOL with: solana airdrop 2',
'For mainnet: Transfer SOL to your wallet address',
'Consider reducing the transaction amount'
]
},
[ErrorCode.AGENT_NOT_FOUND]: {
title: 'Agent Not Found',
message: 'The specified agent does not exist on the network',
suggestions: [
'Verify the agent address is correct',
'Check if the agent is registered with: pod agent info <address>',
'Register a new agent with: pod agent register',
'List all agents with: pod agent list'
]
},
[ErrorCode.AGENT_ALREADY_EXISTS]: {
title: 'Agent Already Exists',
message: 'An agent is already registered for this wallet',
suggestions: [
'Update existing agent with: pod agent update',
'View current agent with: pod agent info <address>',
'Use a different wallet for a new agent'
]
},
[ErrorCode.PROGRAM_NOT_DEPLOYED]: {
title: 'Program Not Deployed',
message: 'PoD Protocol program is not deployed on this network',
suggestions: [
'Switch to devnet where the program is deployed',
'Check network status with: pod config get-network',
'Contact support if program should be available on this network'
]
},
[ErrorCode.CONFIG_FILE_NOT_FOUND]: {
title: 'Configuration Not Found',
message: 'CLI configuration file does not exist',
suggestions: [
'Initialize configuration with: pod config init',
'Set network with: pod config set-network devnet',
'Set keypair with: pod config set-keypair <path>'
]
},
[ErrorCode.VALIDATION_INVALID_ADDRESS]: {
title: 'Invalid Address',
message: 'The provided address is not a valid Solana public key',
suggestions: [
'Ensure address is a 44-character base58 string',
'Check for typos in the address',
'Use tab completion if available',
'Verify the address format: 11111111111111111111111111111111'
]
},
[ErrorCode.MESSAGE_SEND_FAILED]: {
title: 'Message Send Failed',
message: 'Unable to send message to the specified recipient',
suggestions: [
'Verify recipient agent exists and is active',
'Check wallet has sufficient SOL for transaction fees',
'Ensure message payload is within size limits',
'Try again in a few moments'
]
},
[ErrorCode.CHANNEL_NOT_FOUND]: {
title: 'Channel Not Found',
message: 'The specified channel does not exist',
suggestions: [
'List available channels with: pod channel list',
'Create a new channel with: pod channel create',
'Verify the channel name or address is correct'
]
},
// Add more error templates as needed...
};
/**
* Enhanced error handler with rich formatting and suggestions
*/
export class EnhancedErrorHandler {
constructor(options = {}) {
this.verbose = false;
this.debugMode = false;
this.verbose = options.verbose || false;
this.debugMode = options.debug || false;
}
/**
* Handle and display a PodError with full formatting
*/
handleError(error) {
if (error instanceof PodError) {
this.displayPodError(error);
}
else {
this.displayGenericError(error);
}
process.exit(1);
}
/**
* Display a formatted PodError
*/
displayPodError(error) {
console.log();
// Error header
console.log(statusMessage('error', error.title));
console.log(BRAND_COLORS.muted(`Error Code: ${error.code}`));
console.log();
// Main message
console.log(BRAND_COLORS.error(error.message));
// Cause if available
if (error.cause) {
console.log();
console.log(BRAND_COLORS.muted('Cause:'));
console.log(` ${error.cause}`);
}
// Suggestions
if (error.suggestions.length > 0) {
console.log();
console.log(BRAND_COLORS.accent('💡 Suggestions:'));
error.suggestions.forEach((suggestion, index) => {
console.log(` ${index + 1}. ${suggestion}`);
});
}
// Technical details in verbose mode
if (this.verbose && error.technicalDetails) {
console.log();
console.log(BRAND_COLORS.muted('Technical Details:'));
Object.entries(error.technicalDetails).forEach(([key, value]) => {
console.log(` ${key}: ${JSON.stringify(value, null, 2)}`);
});
}
// Documentation link
if (error.documentationUrl) {
console.log();
console.log(BRAND_COLORS.info(`📚 Documentation: ${error.documentationUrl}`));
}
// Debug info
if (this.debugMode) {
console.log();
console.log(BRAND_COLORS.muted('Debug Information:'));
console.log(` Stack Trace:`);
console.log(error.stack?.split('\n').map(line => ` ${line}`).join('\n'));
}
console.log();
}
/**
* Display a generic error with basic formatting
*/
displayGenericError(error) {
console.log();
console.log(statusMessage('error', 'Unexpected Error'));
console.log(BRAND_COLORS.error(error.message));
if (this.debugMode && error.stack) {
console.log();
console.log(BRAND_COLORS.muted('Stack Trace:'));
console.log(error.stack.split('\n').map(line => ` ${line}`).join('\n'));
}
console.log();
console.log(BRAND_COLORS.muted('If this error persists, please report it at:'));
console.log(BRAND_COLORS.info('https://github.com/Dexploarer/PoD-Protocol/issues'));
console.log();
}
/**
* Create a PodError from an error code
*/
static createError(code, overrides = {}) {
const template = ERROR_TEMPLATES[code];
if (!template) {
throw new Error(`Unknown error code: ${code}`);
}
return new PodError({
code,
...template,
...overrides,
});
}
/**
* Wrap async operations with error handling
*/
async safeExecute(operation, errorCode, errorOverrides = {}) {
try {
return await operation();
}
catch (error) {
const podError = EnhancedErrorHandler.createError(errorCode, {
cause: error.message,
technicalDetails: {
originalError: error.name,
timestamp: new Date().toISOString(),
},
...errorOverrides,
});
this.handleError(podError);
throw podError; // This won't be reached due to process.exit
}
}
/**
* Display a warning message
*/
displayWarning(message, details) {
console.log(statusMessage('warning', message, details));
}
/**
* Display a success message
*/
displaySuccess(message, details) {
console.log(statusMessage('success', message, details));
}
/**
* Display an info message
*/
displayInfo(message, details) {
console.log(statusMessage('info', message, details));
}
}
/**
* Global error handler instance
*/
export const errorHandler = new EnhancedErrorHandler();
/**
* Convenience function to create common errors
*/
export const createError = EnhancedErrorHandler.createError;