Skip to main content
Glama
client.ts4.98 kB
import Anthropic from '@anthropic-ai/sdk'; export type StreamEvent = | { type: 'analysis_started'; message: string } | { type: 'section_started'; message: string; section: string } | { type: 'content_chunk'; chunk: string; section: string } | { type: 'analysis_complete'; message: string }; export class ClaudeClient { private anthropic: Anthropic; constructor() { const apiKey = process.env.ANTHROPIC_API_KEY; if (!apiKey) { throw new Error('ANTHROPIC_API_KEY is not set'); } this.anthropic = new Anthropic({ apiKey }); } async executePromptWithStreaming( promptText: string, documentText: string, onProgress: (event: StreamEvent) => void ): Promise<string> { try { console.log('ClaudeClient.executePromptWithStreaming: Starting, document length:', documentText.length, 'prompt length:', promptText.length); onProgress({ type: 'analysis_started', message: 'Starting analysis...' }); // Create the API request console.log('ClaudeClient.executePromptWithStreaming: Creating Claude API request...'); let stream; try { stream = await this.anthropic.messages.create({ model: 'claude-sonnet-4-20250514', max_tokens: 8000, stream: true, messages: [ { role: 'user', content: [ { type: 'text', text: `Document:\n${documentText}` }, { type: 'text', text: promptText } ] } ] }); console.log('ClaudeClient.executePromptWithStreaming: Stream created successfully'); } catch (error) { const errorMsg = `Failed to create Claude API stream: ${error instanceof Error ? error.message : String(error)}`; console.error('ClaudeClient.executePromptWithStreaming:', errorMsg, error); throw new Error(errorMsg); } let fullResponse = ''; let currentSection = ''; let chunkCount = 0; // Process the stream console.log('ClaudeClient.executePromptWithStreaming: Processing stream...'); try { for await (const event of stream) { if (event.type === 'content_block_delta' && event.delta?.type === 'text_delta') { const chunk: string = event.delta.text; fullResponse += chunk; chunkCount++; const normalized = chunk.toUpperCase(); if (normalized.includes('EXECUTIVE SUMMARY')) { currentSection = 'Executive Summary'; onProgress({ type: 'section_started', section: currentSection, message: 'Analyzing executive summary...' }); } else if (normalized.includes('DETAILED ANALYSIS')) { currentSection = 'Detailed Analysis'; onProgress({ type: 'section_started', section: currentSection, message: 'Performing detailed analysis...' }); } else if (normalized.includes('RISK ASSESSMENT')) { currentSection = 'Risk Assessment'; onProgress({ type: 'section_started', section: currentSection, message: 'Assessing risks...' }); } else if (normalized.includes('RECOMMENDATIONS')) { currentSection = 'Recommendations'; onProgress({ type: 'section_started', section: currentSection, message: 'Generating recommendations...' }); } onProgress({ type: 'content_chunk', chunk, section: currentSection }); } else { // Log other event types for debugging console.log(`ClaudeClient.executePromptWithStreaming: Received event type: ${event.type}`); } } console.log(`ClaudeClient.executePromptWithStreaming: Stream processing complete, received ${chunkCount} chunks, total response length: ${fullResponse.length}`); } catch (error) { const errorMsg = `Failed to process Claude API stream: ${error instanceof Error ? error.message : String(error)}`; console.error('ClaudeClient.executePromptWithStreaming:', errorMsg, error); throw new Error(errorMsg); } onProgress({ type: 'analysis_complete', message: 'Analysis complete' }); console.log('ClaudeClient.executePromptWithStreaming: Returning response, length:', fullResponse.length); return fullResponse; } catch (error) { const errorMsg = `ClaudeClient.executePromptWithStreaming failed: ${error instanceof Error ? error.message : String(error)}`; console.error('ClaudeClient.executePromptWithStreaming:', errorMsg, error); throw error; } } }

Latest Blog Posts

MCP directory API

We provide all the information about MCP servers via our MCP API.

curl -X GET 'https://glama.ai/api/mcp/v1/servers/MCP-Agent766/Legal-MCP'

If you have feedback or need assistance with the MCP directory API, please join our Discord server