Files
gh-jezweb-claude-skills-ski…/templates/nodejs-example.ts
2025-11-30 08:24:01 +08:00

382 lines
10 KiB
TypeScript

// Complete Node.js examples for Claude API
import Anthropic from '@anthropic-ai/sdk';
import * as dotenv from 'dotenv';
import * as readline from 'readline';
dotenv.config();
const anthropic = new Anthropic({
apiKey: process.env.ANTHROPIC_API_KEY,
});
// Example 1: Simple CLI chatbot
async function simpleCLIChatbot() {
const rl = readline.createInterface({
input: process.stdin,
output: process.stdout,
});
const messages: Anthropic.MessageParam[] = [];
console.log('Claude CLI Chatbot (type "exit" to quit)\n');
const chat = async () => {
rl.question('You: ', async (userInput) => {
if (userInput.toLowerCase() === 'exit') {
console.log('Goodbye!');
rl.close();
return;
}
messages.push({ role: 'user', content: userInput });
try {
const response = await anthropic.messages.create({
model: 'claude-sonnet-4-5-20250929',
max_tokens: 1024,
messages,
});
const textContent = response.content.find(b => b.type === 'text');
if (textContent && textContent.type === 'text') {
console.log(`\nClaude: ${textContent.text}\n`);
messages.push({ role: 'assistant', content: textContent.text });
}
} catch (error) {
console.error('Error:', error.message);
}
chat();
});
};
chat();
}
// Example 2: Streaming CLI chatbot
async function streamingCLIChatbot() {
const rl = readline.createInterface({
input: process.stdin,
output: process.stdout,
});
console.log('Streaming Claude CLI Chatbot (type "exit" to quit)\n');
const chat = async () => {
rl.question('You: ', async (userInput) => {
if (userInput.toLowerCase() === 'exit') {
console.log('Goodbye!');
rl.close();
return;
}
try {
process.stdout.write('\nClaude: ');
const stream = anthropic.messages.stream({
model: 'claude-sonnet-4-5-20250929',
max_tokens: 1024,
messages: [{ role: 'user', content: userInput }],
});
let fullText = '';
stream.on('text', (text) => {
process.stdout.write(text);
fullText += text;
});
await stream.finalMessage();
console.log('\n');
} catch (error) {
console.error('\nError:', error.message);
}
chat();
});
};
chat();
}
// Example 3: Batch processing from file
import * as fs from 'fs';
async function batchProcessing(inputFile: string, outputFile: string) {
const lines = fs.readFileSync(inputFile, 'utf-8').split('\n').filter(Boolean);
const results = [];
console.log(`Processing ${lines.length} prompts...`);
for (let i = 0; i < lines.length; i++) {
const prompt = lines[i];
console.log(`\n[${i + 1}/${lines.length}] Processing: ${prompt.substring(0, 50)}...`);
try {
const message = await anthropic.messages.create({
model: 'claude-sonnet-4-5-20250929',
max_tokens: 1024,
messages: [{ role: 'user', content: prompt }],
});
const textContent = message.content.find(b => b.type === 'text');
if (textContent && textContent.type === 'text') {
results.push({
prompt,
response: textContent.text,
tokens: message.usage,
});
}
// Rate limiting pause
await new Promise(resolve => setTimeout(resolve, 1000));
} catch (error) {
console.error(`Error processing prompt ${i + 1}:`, error.message);
results.push({
prompt,
error: error.message,
});
}
}
fs.writeFileSync(outputFile, JSON.stringify(results, null, 2));
console.log(`\nResults written to ${outputFile}`);
}
// Example 4: Document summarization
async function summarizeDocument(filePath: string) {
const document = fs.readFileSync(filePath, 'utf-8');
const message = await anthropic.messages.create({
model: 'claude-sonnet-4-5-20250929',
max_tokens: 2048,
system: 'You are an expert document summarizer. Provide concise, accurate summaries.',
messages: [
{
role: 'user',
content: [
{
type: 'text',
text: 'Summarize the following document in 3-5 bullet points:',
},
{
type: 'text',
text: document,
cache_control: { type: 'ephemeral' },
},
],
},
],
});
const textContent = message.content.find(b => b.type === 'text');
if (textContent && textContent.type === 'text') {
console.log('Summary:');
console.log(textContent.text);
console.log('\nToken usage:', message.usage);
}
}
// Example 5: Code review assistant
async function codeReview(codeContent: string, language: string) {
const message = await anthropic.messages.create({
model: 'claude-sonnet-4-5-20250929',
max_tokens: 2048,
system: `You are an expert ${language} code reviewer. Analyze code for:
- Bugs and potential issues
- Performance optimizations
- Security vulnerabilities
- Best practices
- Code style and readability`,
messages: [
{
role: 'user',
content: `Review this ${language} code:\n\n\`\`\`${language}\n${codeContent}\n\`\`\``,
},
],
});
const textContent = message.content.find(b => b.type === 'text');
if (textContent && textContent.type === 'text') {
console.log('Code Review:');
console.log(textContent.text);
}
}
// Example 6: Translation service
async function translateText(text: string, from: string, to: string) {
const message = await anthropic.messages.create({
model: 'claude-sonnet-4-5-20250929',
max_tokens: 1024,
messages: [
{
role: 'user',
content: `Translate the following text from ${from} to ${to}:\n\n${text}`,
},
],
});
const textContent = message.content.find(b => b.type === 'text');
if (textContent && textContent.type === 'text') {
return textContent.text;
}
return null;
}
// Example 7: Parallel requests
async function parallelRequests(prompts: string[]) {
console.log(`Processing ${prompts.length} prompts in parallel...`);
const promises = prompts.map(async (prompt, index) => {
try {
const message = await anthropic.messages.create({
model: 'claude-sonnet-4-5-20250929',
max_tokens: 512,
messages: [{ role: 'user', content: prompt }],
});
const textContent = message.content.find(b => b.type === 'text');
return {
index,
prompt,
response: textContent && textContent.type === 'text' ? textContent.text : null,
};
} catch (error) {
return {
index,
prompt,
error: error.message,
};
}
});
const results = await Promise.all(promises);
return results;
}
// Example 8: Retry logic with exponential backoff
async function requestWithRetry(
prompt: string,
maxRetries = 3,
baseDelay = 1000
): Promise<string> {
for (let attempt = 0; attempt < maxRetries; attempt++) {
try {
const message = await anthropic.messages.create({
model: 'claude-sonnet-4-5-20250929',
max_tokens: 1024,
messages: [{ role: 'user', content: prompt }],
});
const textContent = message.content.find(b => b.type === 'text');
if (textContent && textContent.type === 'text') {
return textContent.text;
}
throw new Error('No text content in response');
} catch (error) {
if (error instanceof Anthropic.APIError && error.status === 429) {
if (attempt < maxRetries - 1) {
const delay = baseDelay * Math.pow(2, attempt);
console.warn(`Rate limited. Retrying in ${delay}ms...`);
await new Promise(resolve => setTimeout(resolve, delay));
continue;
}
}
throw error;
}
}
throw new Error('Max retries exceeded');
}
// Example 9: Conversation logger
class ConversationLogger {
private messages: Anthropic.MessageParam[] = [];
private logFile: string;
constructor(logFile: string) {
this.logFile = logFile;
}
async chat(userMessage: string): Promise<string> {
this.messages.push({ role: 'user', content: userMessage });
const response = await anthropic.messages.create({
model: 'claude-sonnet-4-5-20250929',
max_tokens: 1024,
messages: this.messages,
});
const textContent = response.content.find(b => b.type === 'text');
if (textContent && textContent.type === 'text') {
this.messages.push({ role: 'assistant', content: textContent.text });
this.save();
return textContent.text;
}
throw new Error('No response');
}
private save() {
fs.writeFileSync(this.logFile, JSON.stringify(this.messages, null, 2));
}
load() {
if (fs.existsSync(this.logFile)) {
this.messages = JSON.parse(fs.readFileSync(this.logFile, 'utf-8'));
}
}
}
// Run examples
if (require.main === module) {
const args = process.argv.slice(2);
const example = args[0];
switch (example) {
case 'cli':
simpleCLIChatbot();
break;
case 'stream':
streamingCLIChatbot();
break;
case 'batch':
batchProcessing(args[1], args[2] || 'output.json');
break;
case 'summarize':
summarizeDocument(args[1]);
break;
case 'review':
const code = fs.readFileSync(args[1], 'utf-8');
codeReview(code, args[2] || 'typescript');
break;
case 'translate':
translateText(args[1], args[2], args[3]).then(console.log);
break;
default:
console.log('Available examples:');
console.log('- cli: Interactive chatbot');
console.log('- stream: Streaming chatbot');
console.log('- batch <input> [output]: Batch processing');
console.log('- summarize <file>: Document summarization');
console.log('- review <file> [language]: Code review');
console.log('- translate <text> <from> <to>: Translation');
}
}
export {
simpleCLIChatbot,
streamingCLIChatbot,
batchProcessing,
summarizeDocument,
codeReview,
translateText,
parallelRequests,
requestWithRetry,
ConversationLogger,
};