Reference implementation for the Phoenix Architecture. Work in progress.
aicoding.leaflet.pub/
ai
coding
crazy
1/**
2 * Anthropic (Claude) LLM Provider.
3 *
4 * Uses the Messages API via native fetch.
5 * Requires ANTHROPIC_API_KEY env var.
6 */
7
8import type { LLMProvider, GenerateOptions } from './provider.js';
9
10const API_URL = 'https://api.anthropic.com/v1/messages';
11const API_VERSION = '2023-06-01';
12
13export class AnthropicProvider implements LLMProvider {
14 readonly name = 'anthropic';
15 readonly model: string;
16 private apiKey: string;
17
18 constructor(apiKey: string, model: string) {
19 this.apiKey = apiKey;
20 this.model = model;
21 }
22
23 async generate(prompt: string, options?: GenerateOptions): Promise<string> {
24 const body: Record<string, unknown> = {
25 model: this.model,
26 max_tokens: options?.maxTokens ?? 8192,
27 messages: [{ role: 'user', content: prompt }],
28 };
29
30 if (options?.system) {
31 body.system = options.system;
32 }
33 if (options?.temperature !== undefined) {
34 body.temperature = options.temperature;
35 }
36
37 const res = await fetch(API_URL, {
38 method: 'POST',
39 headers: {
40 'Content-Type': 'application/json',
41 'x-api-key': this.apiKey,
42 'anthropic-version': API_VERSION,
43 },
44 body: JSON.stringify(body),
45 });
46
47 if (!res.ok) {
48 const text = await res.text();
49 throw new Error(`Anthropic API error ${res.status}: ${text}`);
50 }
51
52 const data = await res.json() as {
53 content: Array<{ type: string; text: string }>;
54 };
55
56 const textBlocks = data.content.filter(b => b.type === 'text');
57 if (textBlocks.length === 0) {
58 throw new Error('Anthropic returned no text content');
59 }
60
61 return textBlocks.map(b => b.text).join('');
62 }
63}