mirror of
http://10.0.2.1:3031/sauer/claude-code.git
synced 2026-06-30 19:26:58 +10:00
124 lines
23 KiB
TypeScript
124 lines
23 KiB
TypeScript
|
|
import { getPluginErrorMessage, type PluginError } from '../../types/plugin.js';
|
||
|
|
export function formatErrorMessage(error: PluginError): string {
|
||
|
|
switch (error.type) {
|
||
|
|
case 'path-not-found':
|
||
|
|
return `${error.component} path not found: ${error.path}`;
|
||
|
|
case 'git-auth-failed':
|
||
|
|
return `Git ${error.authType.toUpperCase()} authentication failed for ${error.gitUrl}`;
|
||
|
|
case 'git-timeout':
|
||
|
|
return `Git ${error.operation} timed out for ${error.gitUrl}`;
|
||
|
|
case 'network-error':
|
||
|
|
return `Network error accessing ${error.url}${error.details ? `: ${error.details}` : ''}`;
|
||
|
|
case 'manifest-parse-error':
|
||
|
|
return `Failed to parse manifest at ${error.manifestPath}: ${error.parseError}`;
|
||
|
|
case 'manifest-validation-error':
|
||
|
|
return `Invalid manifest at ${error.manifestPath}: ${error.validationErrors.join(', ')}`;
|
||
|
|
case 'plugin-not-found':
|
||
|
|
return `Plugin "${error.pluginId}" not found in marketplace "${error.marketplace}"`;
|
||
|
|
case 'marketplace-not-found':
|
||
|
|
return `Marketplace "${error.marketplace}" not found`;
|
||
|
|
case 'marketplace-load-failed':
|
||
|
|
return `Failed to load marketplace "${error.marketplace}": ${error.reason}`;
|
||
|
|
case 'mcp-config-invalid':
|
||
|
|
return `Invalid MCP server config for "${error.serverName}": ${error.validationError}`;
|
||
|
|
case 'mcp-server-suppressed-duplicate':
|
||
|
|
{
|
||
|
|
const dup = error.duplicateOf.startsWith('plugin:') ? `server provided by plugin "${error.duplicateOf.split(':')[1] ?? '?'}"` : `already-configured "${error.duplicateOf}"`;
|
||
|
|
return `MCP server "${error.serverName}" skipped — same command/URL as ${dup}`;
|
||
|
|
}
|
||
|
|
case 'hook-load-failed':
|
||
|
|
return `Failed to load hooks from ${error.hookPath}: ${error.reason}`;
|
||
|
|
case 'component-load-failed':
|
||
|
|
return `Failed to load ${error.component} from ${error.path}: ${error.reason}`;
|
||
|
|
case 'mcpb-download-failed':
|
||
|
|
return `Failed to download MCPB from ${error.url}: ${error.reason}`;
|
||
|
|
case 'mcpb-extract-failed':
|
||
|
|
return `Failed to extract MCPB ${error.mcpbPath}: ${error.reason}`;
|
||
|
|
case 'mcpb-invalid-manifest':
|
||
|
|
return `MCPB manifest invalid at ${error.mcpbPath}: ${error.validationError}`;
|
||
|
|
case 'marketplace-blocked-by-policy':
|
||
|
|
return error.blockedByBlocklist ? `Marketplace "${error.marketplace}" is blocked by enterprise policy` : `Marketplace "${error.marketplace}" is not in the allowed marketplace list`;
|
||
|
|
case 'dependency-unsatisfied':
|
||
|
|
return error.reason === 'not-enabled' ? `Dependency "${error.dependency}" is disabled` : `Dependency "${error.dependency}" is not installed`;
|
||
|
|
case 'lsp-config-invalid':
|
||
|
|
return `Invalid LSP server config for "${error.serverName}": ${error.validationError}`;
|
||
|
|
case 'lsp-server-start-failed':
|
||
|
|
return `LSP server "${error.serverName}" failed to start: ${error.reason}`;
|
||
|
|
case 'lsp-server-crashed':
|
||
|
|
return error.signal ? `LSP server "${error.serverName}" crashed with signal ${error.signal}` : `LSP server "${error.serverName}" crashed with exit code ${error.exitCode ?? 'unknown'}`;
|
||
|
|
case 'lsp-request-timeout':
|
||
|
|
return `LSP server "${error.serverName}" timed out on ${error.method} after ${error.timeoutMs}ms`;
|
||
|
|
case 'lsp-request-failed':
|
||
|
|
return `LSP server "${error.serverName}" ${error.method} failed: ${error.error}`;
|
||
|
|
case 'plugin-cache-miss':
|
||
|
|
return `Plugin "${error.plugin}" not cached at ${error.installPath}`;
|
||
|
|
case 'generic-error':
|
||
|
|
return error.error;
|
||
|
|
}
|
||
|
|
const _exhaustive: never = error;
|
||
|
|
return getPluginErrorMessage(_exhaustive);
|
||
|
|
}
|
||
|
|
export function getErrorGuidance(error: PluginError): string | null {
|
||
|
|
switch (error.type) {
|
||
|
|
case 'path-not-found':
|
||
|
|
return 'Check that the path in your manifest or marketplace config is correct';
|
||
|
|
case 'git-auth-failed':
|
||
|
|
return error.authType === 'ssh' ? 'Configure SSH keys or use HTTPS URL instead' : 'Configure credentials or use SSH URL instead';
|
||
|
|
case 'git-timeout':
|
||
|
|
case 'network-error':
|
||
|
|
return 'Check your internet connection and try again';
|
||
|
|
case 'manifest-parse-error':
|
||
|
|
return 'Check manifest file syntax in the plugin directory';
|
||
|
|
case 'manifest-validation-error':
|
||
|
|
return 'Check manifest file follows the required schema';
|
||
|
|
case 'plugin-not-found':
|
||
|
|
return `Plugin may not exist in marketplace "${error.marketplace}"`;
|
||
|
|
case 'marketplace-not-found':
|
||
|
|
return error.availableMarketplaces.length > 0 ? `Available marketplaces: ${error.availableMarketplaces.join(', ')}` : 'Add the marketplace first using /plugin marketplace add';
|
||
|
|
case 'mcp-config-invalid':
|
||
|
|
return 'Check MCP server configuration in .mcp.json or manifest';
|
||
|
|
case 'mcp-server-suppressed-duplicate':
|
||
|
|
{
|
||
|
|
// duplicateOf is "plugin:name:srv" when another plugin won dedup —
|
||
|
|
// users can't remove plugin-provided servers from their MCP config,
|
||
|
|
// so point them at the winning plugin instead.
|
||
|
|
if (error.duplicateOf.startsWith('plugin:')) {
|
||
|
|
const winningPlugin = error.duplicateOf.split(':')[1] ?? 'the other plugin';
|
||
|
|
return `Disable plugin "${winningPlugin}" if you want this plugin's version instead`;
|
||
|
|
}
|
||
|
|
return `Remove "${error.duplicateOf}" from your MCP config if you want the plugin's version instead`;
|
||
|
|
}
|
||
|
|
case 'hook-load-failed':
|
||
|
|
return 'Check hooks.json file syntax and structure';
|
||
|
|
case 'component-load-failed':
|
||
|
|
return `Check ${error.component} directory structure and file permissions`;
|
||
|
|
case 'mcpb-download-failed':
|
||
|
|
return 'Check your internet connection and URL accessibility';
|
||
|
|
case 'mcpb-extract-failed':
|
||
|
|
return 'Verify the MCPB file is valid and not corrupted';
|
||
|
|
case 'mcpb-invalid-manifest':
|
||
|
|
return 'Contact the plugin author about the invalid manifest';
|
||
|
|
case 'marketplace-blocked-by-policy':
|
||
|
|
if (error.blockedByBlocklist) {
|
||
|
|
return 'This marketplace source is explicitly blocked by your administrator';
|
||
|
|
}
|
||
|
|
return error.allowedSources.length > 0 ? `Allowed sources: ${error.allowedSources.join(', ')}` : 'Contact your administrator to configure allowed marketplace sources';
|
||
|
|
case 'dependency-unsatisfied':
|
||
|
|
return error.reason === 'not-enabled' ? `Enable "${error.dependency}" or uninstall "${error.plugin}"` : `Install "${error.dependency}" or uninstall "${error.plugin}"`;
|
||
|
|
case 'lsp-config-invalid':
|
||
|
|
return 'Check LSP server configuration in the plugin manifest';
|
||
|
|
case 'lsp-server-start-failed':
|
||
|
|
case 'lsp-server-crashed':
|
||
|
|
case 'lsp-request-timeout':
|
||
|
|
case 'lsp-request-failed':
|
||
|
|
return 'Check LSP server logs with --debug for details';
|
||
|
|
case 'plugin-cache-miss':
|
||
|
|
return 'Run /plugins to refresh the plugin cache';
|
||
|
|
case 'marketplace-load-failed':
|
||
|
|
case 'generic-error':
|
||
|
|
return null;
|
||
|
|
}
|
||
|
|
const _exhaustive: never = error;
|
||
|
|
return null;
|
||
|
|
}
|
||
|
|
//# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJuYW1lcyI6WyJnZXRQbHVnaW5FcnJvck1lc3NhZ2UiLCJQbHVnaW5FcnJvciIsImZvcm1hdEVycm9yTWVzc2FnZSIsImVycm9yIiwidHlwZSIsImNvbXBvbmVudCIsInBhdGgiLCJhdXRoVHlwZSIsInRvVXBwZXJDYXNlIiwiZ2l0VXJsIiwib3BlcmF0aW9uIiwidXJsIiwiZGV0YWlscyIsIm1hbmlmZXN0UGF0aCIsInBhcnNlRXJyb3IiLCJ2YWxpZGF0aW9uRXJyb3JzIiwiam9pbiIsInBsdWdpbklkIiwibWFya2V0cGxhY2UiLCJyZWFzb24iLCJzZXJ2ZXJOYW1lIiwidmFsaWRhdGlvbkVycm9yIiwiZHVwIiwiZHVwbGljYXRlT2YiLCJzdGFydHNXaXRoIiwic3BsaXQiLCJob29rUGF0aCIsIm1jcGJQYXRoIiwiYmxvY2tlZEJ5QmxvY2tsaXN0IiwiZGVwZW5kZW5jeSIsInNpZ25hbCIsImV4aXRDb2RlIiwibWV0aG9kIiwidGltZW91dE1zIiwicGx1Z2luIiwiaW5zdGFsbFBhdGgiLCJfZXhoYXVzdGl2ZSIsImdldEVycm9yR3VpZGFuY2UiLCJhdmFpbGFibGVNYXJrZXRwbGFjZXMiLCJsZW5ndGgiLCJ3aW5uaW5nUGx1Z2luIiwiYWxsb3dlZFNvdXJjZXMiXSwic291cmNlcyI6WyJQbHVnaW5FcnJvcnMudHN4Il0sInNvdXJjZXNDb250ZW50IjpbImltcG9ydCB7IGdldFBsdWdpbkVycm9yTWVzc2FnZSwgdHlwZSBQbHVnaW5FcnJvciB9IGZyb20gJy4uLy4uL3R5cGVzL3BsdWdpbi5qcydcblxuZXhwb3J0IGZ1bmN0aW9uIGZvcm1hdEVycm9yTWVzc2FnZShlcnJvcjogUGx1Z2luRXJyb3IpOiBzdHJpbmcge1xuICBzd2l0Y2ggKGVycm9yLnR5cGUpIHtcbiAgICBjYXNlICdwYXRoLW5vdC1mb3VuZCc6XG4gICAgICByZXR1cm4gYCR7ZXJyb3IuY29tcG9uZW50fSBwYXRoIG5vdCBmb3VuZDogJHtlcnJvci5wYXRofWBcbiAgICBjYXNlICdnaXQtYXV0aC1mYWlsZWQnOlxuICAgICAgcmV0dXJuIGBHaXQgJHtlcnJvci5hdXRoVHlwZS50b1VwcGVyQ2FzZSgpfSBhdXRoZW50aWNhdGlvbiBmYWlsZWQgZm9yICR7ZXJyb3IuZ2l0VXJsfWBcbiAgICBjYXNlICdnaXQtdGltZW91dCc6XG4gICAgICByZXR1cm4gYEdpdCAke2Vycm9yLm9wZXJhdGlvbn0gdGltZWQgb3V0IGZvciAke2Vycm9yLmdpdFVybH1gXG4gICAgY2FzZSAnbmV0d29yay1lcnJvcic6XG4gICAgICByZXR1cm4gYE5ldHdvcmsgZXJyb3IgYWNjZXNzaW5nICR7ZXJyb3IudXJsfSR7ZXJyb3IuZGV0YWlscyA/IGA6ICR7ZXJyb3IuZGV0YWlsc31gIDogJyd9YFxuICAgIGNhc2UgJ21hbmlmZXN0LXBhcnNlLWVycm9yJzpcbiAgICAgIHJldHVybiBgRmFpbGVkIHRvIHBhcnNlIG1hbmlmZXN0IGF0ICR7ZXJyb3IubWFuaWZlc3RQYXRofTogJHtlcnJvci5wYXJzZUVycm9yfWBcbiAgICBjYXNlICdtYW5pZmVzdC12YWxpZGF0aW9uLWVycm9yJzpcbiAgICAgIHJldHVybiBgSW52YWxpZCBtYW5pZmVzdCBhdCAke2Vycm9yLm1hbmlmZXN0UGF0aH06ICR7ZXJyb3IudmFsaWRhdGlvbkVycm9ycy5qb2luKCcsICcpfWBcbiAgICBjYXNlICdwbHVnaW4tbm90LWZvdW5kJzpcbiAgICAgIHJldHVybiBgUGx1Z2luIFwiJHtlcnJvci5wbHVnaW5JZH1cIiBub3QgZm91bmQgaW4gbWFya2V0cGxhY2UgXCIke2Vycm9yLm1hcmtldHBsYWNlfVwiYFxuICAgIGNhc2UgJ21hcmtldHBsYWNlLW5vdC1mb3VuZCc6XG4gICAgICByZXR1cm4gYE1hcmtldHBsYWNlIFwiJHtlcnJvci5tYXJrZXRwbGFjZX1cIiBub3QgZm91bmRgXG4gICAgY2FzZSAnbWFya2V0cGxhY2UtbG9hZC1mYWlsZWQnOlxuICAgICAgcmV0dXJuIGBGYWlsZWQgdG8gbG9hZCBtYXJrZXRwbGFjZSBcIiR7ZXJyb3IubWFya2V0cGxhY2V9XCI6ICR7ZXJyb3IucmVhc29ufWBcbiAgICBjYXNlICdtY3AtY29uZmlnLWludmFsaWQnOlxuICAgICAgcmV0dXJuIGBJbnZhbGlkIE1DUCBzZXJ2ZXIgY29uZmlnIGZvciBcIiR7ZXJyb3Iuc2VydmVyTmFtZX1cIjogJHtlcnJvci52YWxpZGF0aW9uRXJyb3J9YFxuICAgIGNhc2UgJ21jcC1zZXJ2ZXItc3VwcHJlc3NlZC1kdXBsaWNhdGUnOiB7XG4gICAgICBjb25zdCBkdXAgPSBlcnJvci5kdXBsaWNhdGVPZi5zdGFydHNXaXRoKCdwbHVnaW46JylcbiAgICAgICAgPyBgc2VydmVyIHByb3ZpZGVkIGJ5IHBsdWdpbiBcIiR7ZXJyb3IuZHVwbGljYXRlT2Yuc3BsaXQoJzonKVsxXSA/PyAnPyd9XCJgXG4gICAgICAgIDogYGFscmVhZHktY29uZmlndXJlZCBcIiR7ZXJyb3IuZHVwbGljYXRlT2Z9XCJgXG4gICAgICByZXR1cm4gYE1DUCBzZXJ2ZXIgXCIke2Vycm9yLnNlcnZlck5hbWV9XCIgc2tpcHBlZCDigJQgc2FtZSBjb21tYW5kL1VSTCBhcyAke2R1cH1gXG4gICAgfVxuICAgIGNhc2UgJ2hvb2stbG9hZC1mYWlsZWQnOlxuICAgICAgcmV0dXJuIGBGYWlsZWQgdG8gbG9hZCBob29rcyBmcm9tICR7ZXJyb3IuaG9va1BhdGh9OiAke2Vycm9yLnJlYXNvbn1gXG4gICAgY2FzZSAnY29tcG9uZW50LWxvYWQtZmFpbGVkJzpcbiAgICAgIHJldHVybiBgRmFpbGVkIHRvIGxvYWQgJHtlcnJvci5jb21wb25lbnR9IGZyb20gJHtlcnJvci5wYXRofTogJHtlcnJvci5yZWFzb259YFxuICAgIGNhc2UgJ21jcGItZG93bmxvYWQtZmFpbGVkJzpcbiAgICAgIHJldHVybiBgRmFpbGVkIHRvIGRvd25sb2FkIE1DUEIgZnJvbSAke2Vycm9yLnVybH06ICR7ZXJyb3IucmVhc29ufWBcbiAgICBjYXNlICdtY3BiLWV4dHJhY3QtZmFpbGVkJzpcbiAgICAgIHJldHVybiBgRmFpbGVkIHRvIGV4dHJhY3QgTUNQQiAke2Vycm9yLm1jcGJQYXRofTogJHtlcnJvci5yZWFzb259YFxuICAgIGNhc2UgJ21jcGItaW52YWxpZC1tYW5pZmVzdCc6XG4gICAgICByZXR1cm4gYE1DUEIgbWFuaWZlc3QgaW52YWxpZCBhdCAke2Vycm9yLm1jcGJQYXRofTogJHtlcnJvci52YWxpZGF0aW9uRXJyb3J9YFxuICAgIGNhc2UgJ21hcmtldHBsYWNlLWJsb2NrZWQtYnktcG9saWN5JzpcbiAgICAgIHJldHVybiBlcnJvci5ibG9ja2VkQnlCbG9ja2xpc3RcbiAgICAgICAgPyBgTWFya2V0cGxhY2UgXCIke2Vycm9yLm1hcmtldHBsYWNlfVwiIGlzIGJsb2NrZWQgYnkgZW50ZXJwcmlzZSBwb2xpY3lgXG4gICAgICA
|