Initial commit

This commit is contained in:
Zhongwei Li
2025-11-30 08:24:01 +08:00
commit 7ca465850c
24 changed files with 5512 additions and 0 deletions

194
templates/streaming-chat.ts Normal file
View File

@@ -0,0 +1,194 @@
import Anthropic from '@anthropic-ai/sdk';
const anthropic = new Anthropic({
apiKey: process.env.ANTHROPIC_API_KEY || '',
});
// Method 1: Using SDK stream helper with event listeners
async function streamWithEvents() {
console.log('Claude:');
const stream = anthropic.messages.stream({
model: 'claude-sonnet-4-5-20250929',
max_tokens: 1024,
messages: [
{
role: 'user',
content: 'Write a short poem about coding.',
},
],
});
stream
.on('text', (text) => {
process.stdout.write(text);
})
.on('message', (message) => {
console.log('\n\nFinal message:', message);
console.log('Stop reason:', message.stop_reason);
})
.on('error', (error) => {
console.error('\nStream error:', error);
})
.on('abort', (error) => {
console.warn('\nStream aborted:', error);
})
.on('end', () => {
console.log('\n\nStream ended');
});
// Wait for stream to complete
const finalMessage = await stream.finalMessage();
return finalMessage;
}
// Method 2: Manual iteration over stream events
async function streamWithManualIteration() {
console.log('Claude:');
const stream = await anthropic.messages.create({
model: 'claude-sonnet-4-5-20250929',
max_tokens: 1024,
messages: [
{
role: 'user',
content: 'Explain quantum computing in simple terms.',
},
],
stream: true,
});
let fullText = '';
try {
for await (const event of stream) {
if (event.type === 'content_block_delta' && event.delta.type === 'text_delta') {
const text = event.delta.text;
fullText += text;
process.stdout.write(text);
}
if (event.type === 'message_stop') {
console.log('\n\nStream complete');
}
}
} catch (error) {
console.error('\nStream error:', error);
throw error;
}
return fullText;
}
// Method 3: Streaming with abort control
async function streamWithAbort() {
console.log('Claude (can be aborted):');
const stream = anthropic.messages.stream({
model: 'claude-sonnet-4-5-20250929',
max_tokens: 2048,
messages: [
{
role: 'user',
content: 'Write a long essay about the history of computers.',
},
],
});
let charCount = 0;
const maxChars = 200; // Abort after 200 characters
stream.on('text', (text) => {
process.stdout.write(text);
charCount += text.length;
// Abort stream after reaching limit
if (charCount >= maxChars) {
console.log('\n\n[Aborting stream after', charCount, 'characters]');
stream.abort();
}
});
stream.on('abort', () => {
console.log('Stream was aborted successfully');
});
stream.on('error', (error) => {
console.error('Stream error:', error);
});
try {
await stream.done();
} catch (error) {
// Handle abort error
if (error.name === 'APIUserAbortError') {
console.log('Stream aborted by user');
} else {
throw error;
}
}
}
// Method 4: Streaming with retry logic
async function streamWithRetry(maxRetries = 3) {
for (let attempt = 0; attempt < maxRetries; attempt++) {
try {
const stream = anthropic.messages.stream({
model: 'claude-sonnet-4-5-20250929',
max_tokens: 1024,
messages: [
{
role: 'user',
content: 'Tell me a fun fact about space.',
},
],
});
let fullText = '';
stream.on('text', (text) => {
fullText += text;
process.stdout.write(text);
});
stream.on('error', (error) => {
console.error(`\nStream error on attempt ${attempt + 1}:`, error);
throw error;
});
await stream.finalMessage();
console.log('\n\nStream completed successfully');
return fullText;
} catch (error) {
if (attempt < maxRetries - 1) {
const delay = Math.pow(2, attempt) * 1000;
console.log(`\nRetrying in ${delay}ms...`);
await new Promise(resolve => setTimeout(resolve, delay));
} else {
console.error('\nMax retries exceeded');
throw error;
}
}
}
}
// Run examples
if (require.main === module) {
console.log('=== Stream with Events ===\n');
streamWithEvents()
.then(() => {
console.log('\n\n=== Stream with Manual Iteration ===\n');
return streamWithManualIteration();
})
.then(() => {
console.log('\n\n=== Stream with Abort ===\n');
return streamWithAbort();
})
.then(() => {
console.log('\n\n=== Stream with Retry ===\n');
return streamWithRetry();
})
.catch(console.error);
}
export { streamWithEvents, streamWithManualIteration, streamWithAbort, streamWithRetry };