/**
* Harmonic API error response format
*/
export interface HarmonicErrorResponse {
detail?: string;
message?: string;
error?: string;
}
/**
* Custom error class for Harmonic API errors
*/
export class HarmonicApiError extends Error {
public readonly statusCode: number;
public readonly detail?: string;
constructor(statusCode: number, response: HarmonicErrorResponse) {
const message = response.detail || response.message || response.error || 'Unknown error';
super(message);
this.name = 'HarmonicApiError';
this.statusCode = statusCode;
this.detail = response.detail;
}
/**
* Format error for LLM-friendly output with actionable guidance
*/
toUserMessage(): string {
const parts: string[] = [];
switch (this.statusCode) {
case 400:
parts.push('Bad Request: The request parameters are invalid.');
parts.push(`Details: ${this.message}`);
parts.push('Action: Check parameter formats and values match the API requirements.');
break;
case 401:
parts.push('Authentication Failed: The API key is invalid or missing.');
parts.push('Action: Check that HARMONIC_API_KEY is set correctly in environment variables.');
break;
case 403:
parts.push('Permission Denied: You do not have access to this resource.');
parts.push('Action: Verify your API key has the required permissions.');
break;
case 404:
parts.push('Not Found: The requested resource does not exist.');
parts.push(`Details: ${this.message}`);
parts.push('Action: For companies/persons, the ID may not exist in Harmonic\'s database. Try using lookup tools (harmonic_lookup_company, harmonic_lookup_person) with a domain or LinkedIn URL instead.');
break;
case 429:
parts.push('Rate Limited: Too many requests (max 10/second).');
parts.push('Action: Wait a moment before retrying. Consider reducing request frequency.');
break;
case 500:
case 502:
case 503:
parts.push('Server Error: Harmonic API is temporarily unavailable.');
parts.push('Action: Wait a moment and try again.');
break;
default:
parts.push(`Error (${this.statusCode}): ${this.message}`);
}
return parts.join('\n');
}
}
/**
* Parse error response from Harmonic API
*/
export async function parseErrorResponse(response: Response): Promise<HarmonicApiError> {
try {
const data = await response.json() as HarmonicErrorResponse;
return new HarmonicApiError(response.status, data);
} catch {
return new HarmonicApiError(response.status, {
detail: `HTTP ${response.status}: ${response.statusText}`
});
}
}
/**
* Format any error for tool output
*/
export function formatError(error: unknown): string {
if (error instanceof HarmonicApiError) {
return error.toUserMessage();
}
if (error instanceof Error) {
return `Error: ${error.message}`;
}
return `Unknown error: ${String(error)}`;
}