162 lines
4.7 KiB
JavaScript
162 lines
4.7 KiB
JavaScript
/**
|
||
* Error Handling Example
|
||
* Demonstrates proper error handling with the Claude Code SDK
|
||
*/
|
||
|
||
import { query, ClaudeSDKError, CLINotFoundError, ProcessError } from '@instantlyeasy/claude-code-sdk-ts';
|
||
|
||
async function demonstrateErrorHandling() {
|
||
console.log('🛡️ Error Handling Examples\n');
|
||
console.log('─'.repeat(60) + '\n');
|
||
|
||
// Example 1: Handle CLI not found
|
||
console.log('1️⃣ Handling missing CLI:\n');
|
||
try {
|
||
// This will fail if CLI is not installed
|
||
for await (const message of query('Hello')) {
|
||
// Process messages
|
||
}
|
||
} catch (error) {
|
||
if (error instanceof CLINotFoundError) {
|
||
console.log('❌ Claude CLI not found!');
|
||
console.log('💡 Install with: npm install -g @anthropic-ai/claude-code');
|
||
console.log('📖 Visit: https://github.com/anthropics/claude-code\n');
|
||
}
|
||
}
|
||
|
||
// Example 2: Handle authentication errors
|
||
console.log('2️⃣ Handling authentication issues:\n');
|
||
try {
|
||
const options = { timeout: 5000 };
|
||
for await (const message of query('Create a test file', options)) {
|
||
// Process messages
|
||
}
|
||
} catch (error) {
|
||
if (error.message?.includes('authentication') || error.message?.includes('unauthorized')) {
|
||
console.log('❌ Authentication required!');
|
||
console.log('💡 Run: claude login');
|
||
console.log('📖 The Claude CLI handles all authentication\n');
|
||
}
|
||
}
|
||
|
||
// Example 3: Handle timeout
|
||
console.log('3️⃣ Handling timeouts:\n');
|
||
try {
|
||
const options = {
|
||
timeout: 1000, // Very short timeout
|
||
permissionMode: 'bypassPermissions'
|
||
};
|
||
|
||
for await (const message of query('Analyze all files in the system', options)) {
|
||
// This might timeout
|
||
}
|
||
} catch (error) {
|
||
if (error.name === 'AbortError' || error.message?.includes('timeout')) {
|
||
console.log('⏱️ Operation timed out!');
|
||
console.log('💡 Try increasing the timeout in options\n');
|
||
}
|
||
}
|
||
|
||
// Example 4: Handle specific tool errors
|
||
console.log('4️⃣ Handling tool restrictions:\n');
|
||
try {
|
||
const options = {
|
||
allowedTools: ['Read'], // Only allow Read
|
||
deniedTools: ['Write'], // Explicitly deny Write
|
||
permissionMode: 'bypassPermissions'
|
||
};
|
||
|
||
// This will fail because Write is not allowed
|
||
for await (const message of query('Create a new file called test.txt', options)) {
|
||
if (message.type === 'assistant') {
|
||
for (const block of message.content) {
|
||
if (block.type === 'text') {
|
||
console.log('Claude:', block.text);
|
||
}
|
||
}
|
||
}
|
||
}
|
||
} catch (error) {
|
||
console.log('⚠️ Tool usage was restricted');
|
||
console.log('💡 Check your allowedTools/deniedTools configuration\n');
|
||
}
|
||
}
|
||
|
||
async function robustQueryWrapper(prompt, options = {}) {
|
||
/**
|
||
* A robust wrapper that handles common errors gracefully
|
||
*/
|
||
const maxRetries = 3;
|
||
let lastError;
|
||
|
||
for (let attempt = 1; attempt <= maxRetries; attempt++) {
|
||
try {
|
||
console.log(`🔄 Attempt ${attempt} of ${maxRetries}...`);
|
||
|
||
const messages = [];
|
||
for await (const message of query(prompt, options)) {
|
||
messages.push(message);
|
||
|
||
// Process message as needed
|
||
if (message.type === 'result') {
|
||
return {
|
||
success: true,
|
||
result: message.content,
|
||
messages,
|
||
cost: message.cost?.total_cost
|
||
};
|
||
}
|
||
}
|
||
|
||
} catch (error) {
|
||
lastError = error;
|
||
console.log(`❌ Attempt ${attempt} failed: ${error.message}`);
|
||
|
||
// Don't retry certain errors
|
||
if (error instanceof CLINotFoundError ||
|
||
error.message?.includes('authentication')) {
|
||
throw error;
|
||
}
|
||
|
||
// Wait before retrying
|
||
if (attempt < maxRetries) {
|
||
const waitTime = attempt * 1000;
|
||
console.log(`⏳ Waiting ${waitTime}ms before retry...`);
|
||
await new Promise(resolve => setTimeout(resolve, waitTime));
|
||
}
|
||
}
|
||
}
|
||
|
||
// All retries failed
|
||
return {
|
||
success: false,
|
||
error: lastError,
|
||
attempts: maxRetries
|
||
};
|
||
}
|
||
|
||
// Example usage with the robust wrapper
|
||
async function main() {
|
||
console.log('🚀 Robust Query Example\n');
|
||
|
||
const result = await robustQueryWrapper(
|
||
'What is 2 + 2?',
|
||
{
|
||
timeout: 30000,
|
||
permissionMode: 'bypassPermissions'
|
||
}
|
||
);
|
||
|
||
if (result.success) {
|
||
console.log('✅ Success:', result.result);
|
||
console.log('💰 Cost:', `$${result.cost || 0}`);
|
||
} else {
|
||
console.log('❌ Failed after', result.attempts, 'attempts');
|
||
console.log('Error:', result.error?.message);
|
||
}
|
||
}
|
||
|
||
// Run examples
|
||
demonstrateErrorHandling().catch(console.error);
|
||
|
||
export { robustQueryWrapper }; |