claude-web/node_modules/@instantlyeasy/claude-code-sdk-ts/examples/enhanced-features-demo.js

194 lines
5.6 KiB
JavaScript
Raw Blame History

This file contains invisible Unicode characters

This file contains invisible Unicode characters that are indistinguishable to humans but may be processed differently by a computer. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

#!/usr/bin/env node
/**
* Enhanced Features Demo
*
* This example demonstrates the new enhanced features added to Claude Code SDK:
* 1. Typed error handling
* 2. Token-level streaming
* 3. Per-call tool permissions
* 4. OpenTelemetry integration
* 5. Exponential backoff
*/
import {
query,
createTokenStream,
createPermissionManager,
createTelemetryProvider,
createRetryExecutor,
isRateLimitError,
isToolPermissionError
} from '../dist/index.mjs';
async function runDemo() {
console.log('🚀 Claude Code SDK Enhanced Features Demo\n');
// 1. Typed Error Handling Demo
console.log('1⃣ Typed Error Handling');
console.log('------------------------');
try {
// Simulate an error scenario
const messages = [];
for await (const message of query('Simulate a rate limit error')) {
messages.push(message);
if (message.type === 'error') {
throw new Error('Rate limit exceeded: too many requests');
}
}
} catch (error) {
if (isRateLimitError(error)) {
console.log(`❌ Rate limited! Retry after ${error.retryAfter} seconds`);
} else if (isToolPermissionError(error)) {
console.log(`❌ Tool permission denied: ${error.tool}`);
} else {
console.log(`❌ Error: ${error.message}`);
}
}
console.log();
// 2. Token Streaming Demo
console.log('2⃣ Token-Level Streaming');
console.log('------------------------');
const messageGenerator = query('Write a haiku about programming');
const tokenStream = createTokenStream(messageGenerator);
console.log('Streaming tokens in real-time:');
let tokenCount = 0;
for await (const chunk of tokenStream.tokens()) {
process.stdout.write(chunk.token);
tokenCount++;
// Demonstrate pause/resume
if (tokenCount === 10) {
console.log('\n⏸ Pausing stream...');
tokenStream.getController().pause();
setTimeout(() => {
console.log('▶️ Resuming stream...');
tokenStream.getController().resume();
}, 1000);
}
}
console.log(`\n\n📊 Stream metrics:`, tokenStream.getMetrics());
console.log();
// 3. Per-Call Permissions Demo
console.log('3⃣ Per-Call Tool Permissions');
console.log('-----------------------------');
const permissionManager = createPermissionManager({
allowedTools: ['Read', 'Write'],
deniedTools: ['Bash']
});
// Check permissions with different contexts
const contexts = [
{ userId: 'admin', role: 'admin' },
{ userId: 'user123', role: 'user' }
];
for (const context of contexts) {
console.log(`\nChecking permissions for ${context.role}:`);
const isReadAllowed = await permissionManager.isToolAllowed('Read', context);
const isBashAllowed = await permissionManager.isToolAllowed('Bash', context);
console.log(`- Read: ${isReadAllowed ? '✅ Allowed' : '❌ Denied'}`);
console.log(`- Bash: ${isBashAllowed ? '✅ Allowed' : '❌ Denied'}`);
}
// Dynamic permission based on time
const timeBasedOverride = {
dynamicPermissions: {
Write: async (ctx) => {
const hour = new Date().getHours();
return (hour >= 9 && hour < 17) ? 'allow' : 'deny';
}
}
};
const isWriteAllowed = await permissionManager.isToolAllowed(
'Write',
{ userId: 'user123' },
timeBasedOverride
);
console.log(`\n⏰ Write permission (business hours only): ${isWriteAllowed ? '✅ Allowed' : '❌ Denied'}`);
console.log();
// 4. OpenTelemetry Integration Demo
console.log('4⃣ OpenTelemetry Integration');
console.log('-----------------------------');
const telemetryProvider = createTelemetryProvider();
await telemetryProvider.initialize({
serviceName: 'claude-sdk-demo',
serviceVersion: '1.0.0',
environment: 'demo'
});
const logger = telemetryProvider.getLogger('demo');
const span = logger.startSpan('demo-query', {
attributes: {
'demo.feature': 'telemetry',
'demo.user': 'test-user'
}
});
try {
span.addEvent('query-start');
// Simulate some work
await new Promise(resolve => setTimeout(resolve, 100));
span.setAttribute('demo.result', 'success');
span.setStatus('ok');
} catch (error) {
span.recordException(error);
} finally {
span.end();
}
logger.recordMetric('demo_queries_total', 1, { feature: 'telemetry' });
console.log('📈 Telemetry span created and metrics recorded');
console.log(`📊 Query metrics:`, telemetryProvider.getQueryMetrics());
await telemetryProvider.shutdown();
console.log();
// 5. Exponential Backoff Demo
console.log('5⃣ Exponential Backoff & Retry');
console.log('--------------------------------');
const retryExecutor = createRetryExecutor({
maxAttempts: 3,
initialDelay: 1000,
multiplier: 2,
jitter: true
});
let attemptCount = 0;
try {
const result = await retryExecutor.execute(async () => {
attemptCount++;
console.log(`🔄 Attempt ${attemptCount}...`);
if (attemptCount < 3) {
throw new Error('Temporary network error');
}
return 'Success!';
}, {
onRetry: (attempt, error, nextDelay) => {
console.log(`⚠️ Retry ${attempt} after error: ${error.message}`);
console.log(`⏱️ Waiting ${nextDelay}ms before next attempt...`);
}
});
console.log(`✅ Result: ${result}`);
} catch (error) {
console.log(`❌ Failed after retries: ${error.message}`);
}
const stats = retryExecutor.getStats();
console.log(`\n📊 Retry statistics:`, stats);
console.log('\n✨ Demo completed!');
}
// Run the demo
runDemo().catch(console.error);