@startsimpli/llm 0.1.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,353 @@
1
+ import { ZodError, ZodSchema } from 'zod';
2
+
3
+ /**
4
+ * LLM error codes for classifying provider failures.
5
+ */
6
+ type LLMErrorCode = 'RATE_LIMITED' | 'AUTHENTICATION_ERROR' | 'INVALID_REQUEST' | 'CONTEXT_LENGTH_EXCEEDED' | 'CONTENT_FILTERED' | 'SERVICE_UNAVAILABLE' | 'TIMEOUT' | 'PARSE_ERROR' | 'UNKNOWN_ERROR';
7
+ /**
8
+ * Typed error for LLM provider failures.
9
+ * Carries a machine-readable code and a retryable flag so callers can
10
+ * decide whether to retry or surface the error to the user.
11
+ */
12
+ declare class LLMProviderError extends Error {
13
+ readonly code: LLMErrorCode;
14
+ readonly retryable: boolean;
15
+ readonly statusCode?: number | undefined;
16
+ readonly provider?: string | undefined;
17
+ constructor(message: string, code: LLMErrorCode, retryable?: boolean, statusCode?: number | undefined, provider?: string | undefined);
18
+ }
19
+
20
+ /**
21
+ * Token usage statistics returned by every provider call.
22
+ */
23
+ interface TokenUsage {
24
+ promptTokens: number;
25
+ completionTokens: number;
26
+ totalTokens: number;
27
+ }
28
+ /**
29
+ * Raw response envelope from an LLM provider.
30
+ */
31
+ interface LLMResponse {
32
+ /** The raw text content from the LLM */
33
+ content: string;
34
+ /** Token usage statistics */
35
+ usage: TokenUsage;
36
+ /** Model identifier used for generation */
37
+ model: string;
38
+ /** Response ID for debugging/logging */
39
+ responseId?: string;
40
+ /** Finish reason (e.g., 'stop', 'length', 'content_filter') */
41
+ finishReason?: string;
42
+ }
43
+ /**
44
+ * Options passed through to the provider for a single generation call.
45
+ */
46
+ interface GenerateOptions {
47
+ /** Model to use (provider-specific) */
48
+ model?: string;
49
+ /** Temperature for response randomness (0-1) */
50
+ temperature?: number;
51
+ /** Maximum tokens in response */
52
+ maxTokens?: number;
53
+ /** Request timeout in milliseconds */
54
+ timeout?: number;
55
+ /** Arbitrary extra data the caller wants to thread through (e.g. domain preferences) */
56
+ extra?: Record<string, unknown>;
57
+ }
58
+ /**
59
+ * Provider configuration — everything needed to construct a provider instance.
60
+ */
61
+ interface ProviderConfig {
62
+ apiKey: string;
63
+ baseUrl?: string;
64
+ defaultModel?: string;
65
+ defaultTemperature?: number;
66
+ defaultMaxTokens?: number;
67
+ timeoutMs?: number;
68
+ }
69
+ /**
70
+ * Result of attempting to extract JSON from an LLM response string.
71
+ */
72
+ interface JsonExtractionResult {
73
+ success: boolean;
74
+ json?: unknown;
75
+ error?: string;
76
+ raw: string;
77
+ }
78
+ /**
79
+ * Generic validation result — parameterized over the domain data type.
80
+ */
81
+ interface ValidationResult<T> {
82
+ valid: boolean;
83
+ data?: T;
84
+ zodError?: ZodError;
85
+ errors?: string[];
86
+ }
87
+ /**
88
+ * Configuration for the generic LLMService.
89
+ */
90
+ interface LLMServiceConfig {
91
+ /** Maximum number of retry attempts for validation failures */
92
+ maxRetries?: number;
93
+ /** Preferred provider (will fallback to available if not configured) */
94
+ preferredProvider?: 'openai' | 'anthropic' | 'mock';
95
+ /** Default model override */
96
+ defaultModel?: string;
97
+ /** Default temperature */
98
+ defaultTemperature?: number;
99
+ /** Default max tokens */
100
+ defaultMaxTokens?: number;
101
+ }
102
+ /**
103
+ * Default LLM configuration values.
104
+ * Apps can override these via LLMServiceConfig or environment variables.
105
+ */
106
+ declare const LLM_DEFAULTS: {
107
+ readonly openaiModel: "gpt-4o-mini";
108
+ readonly anthropicModel: "claude-sonnet-4-20250514";
109
+ /**
110
+ * Default sampling temperature.
111
+ * Note: base gpt-5 models (gpt-5, gpt-5.1, gpt-5.2) require temperature=1.0
112
+ * and the OpenAI provider enforces this automatically.
113
+ */
114
+ readonly temperature: 0.7;
115
+ readonly maxTokens: 8192;
116
+ readonly timeoutMs: 60000;
117
+ };
118
+
119
+ /**
120
+ * Contract that every LLM provider must implement.
121
+ *
122
+ * Generic over nothing — the provider just takes string prompts and returns
123
+ * string content. Domain-specific parsing/validation lives in the service layer.
124
+ */
125
+ interface ILLMProvider {
126
+ /** Unique identifier for the provider (e.g. 'openai', 'anthropic') */
127
+ readonly name: string;
128
+ /** List of available models */
129
+ readonly availableModels: readonly string[];
130
+ /** Default model for this provider */
131
+ readonly defaultModel: string;
132
+ /**
133
+ * Send a prompt pair to the LLM and return the raw response.
134
+ *
135
+ * @param userPrompt - The user's message / generation request
136
+ * @param systemPrompt - System-level instructions
137
+ * @param options - Generation options (model, temperature, etc.)
138
+ */
139
+ generate(userPrompt: string, systemPrompt: string, options?: GenerateOptions): Promise<LLMResponse>;
140
+ /** Check if the provider is properly configured and available */
141
+ isAvailable(): boolean;
142
+ /**
143
+ * Estimate cost for a request (in USD).
144
+ * Returns undefined if cost cannot be estimated.
145
+ */
146
+ estimateCost?(promptTokens: number, completionTokens: number, model?: string): number | undefined;
147
+ }
148
+
149
+ /**
150
+ * OpenAI Provider Implementation
151
+ *
152
+ * Uses native fetch to minimize dependencies.
153
+ * Supports GPT-5.x, GPT-4o models, and custom fine-tuned models.
154
+ *
155
+ * To use a custom fine-tuned model:
156
+ * 1. Set OPENAI_MODEL or LLM_MODEL to your fine-tuned model ID (e.g., "ft:gpt-4o-2024-08-06:org:name:id")
157
+ * 2. Fine-tuned models will use the configured temperature setting (not forced to 1.0 like base gpt-5)
158
+ */
159
+
160
+ declare class OpenAIProvider implements ILLMProvider {
161
+ readonly name = "openai";
162
+ readonly availableModels: readonly ["gpt-5.2", "gpt-5.1", "gpt-5", "gpt-4o", "gpt-4o-mini"];
163
+ readonly defaultModel: string;
164
+ private readonly config;
165
+ constructor(config: ProviderConfig);
166
+ isAvailable(): boolean;
167
+ generate(userPrompt: string, systemPrompt: string, options?: GenerateOptions): Promise<LLMResponse>;
168
+ estimateCost(promptTokens: number, completionTokens: number, model?: string): number | undefined;
169
+ private handleApiError;
170
+ }
171
+ /**
172
+ * Create an OpenAI provider from environment variables.
173
+ * Returns null if OPENAI_API_KEY is not set.
174
+ */
175
+ declare function createOpenAIProvider(): OpenAIProvider | null;
176
+
177
+ /**
178
+ * Anthropic Provider Implementation
179
+ *
180
+ * Uses native fetch to minimize dependencies.
181
+ * Supports Claude 4 and Claude 3.x models.
182
+ */
183
+
184
+ declare class AnthropicProvider implements ILLMProvider {
185
+ readonly name = "anthropic";
186
+ readonly availableModels: readonly ["claude-opus-4-6", "claude-opus-4-20250514", "claude-sonnet-4-6", "claude-sonnet-4-20250514", "claude-3-5-sonnet-20241022", "claude-3-5-haiku-20241022", "claude-3-opus-20240229", "claude-3-sonnet-20240229", "claude-3-haiku-20240307"];
187
+ readonly defaultModel: string;
188
+ private readonly config;
189
+ private readonly apiVersion;
190
+ constructor(config: ProviderConfig, apiVersion?: string);
191
+ isAvailable(): boolean;
192
+ generate(userPrompt: string, systemPrompt: string, options?: GenerateOptions): Promise<LLMResponse>;
193
+ estimateCost(promptTokens: number, completionTokens: number, model?: string): number | undefined;
194
+ private handleApiError;
195
+ }
196
+ /**
197
+ * Create an Anthropic provider from environment variables.
198
+ * Returns null if ANTHROPIC_API_KEY is not set.
199
+ */
200
+ declare function createAnthropicProvider(): AnthropicProvider | null;
201
+
202
+ /**
203
+ * Mock LLM Provider for Testing
204
+ *
205
+ * Provides deterministic responses for testing.
206
+ * Can simulate errors, delays, and custom responses.
207
+ */
208
+
209
+ interface MockBehavior {
210
+ /** Delay before responding (ms) */
211
+ delay?: number;
212
+ /** Simulate an error */
213
+ error?: {
214
+ code: 'RATE_LIMITED' | 'SERVICE_UNAVAILABLE' | 'CONTENT_FILTERED' | 'TIMEOUT';
215
+ message: string;
216
+ };
217
+ /** Return invalid JSON (for validation retry testing) */
218
+ returnInvalidJson?: boolean;
219
+ /** Custom response content string */
220
+ customResponse?: string;
221
+ }
222
+ /**
223
+ * Set mock behavior for testing.
224
+ */
225
+ declare function setMockBehavior(behavior: MockBehavior): void;
226
+ /**
227
+ * Reset mock behavior to defaults.
228
+ */
229
+ declare function resetMockBehavior(): void;
230
+ declare class MockLLMProvider implements ILLMProvider {
231
+ readonly name = "mock";
232
+ readonly availableModels: readonly ["mock-model-1", "mock-model-2"];
233
+ readonly defaultModel = "mock-model-1";
234
+ private callCount;
235
+ generate(_userPrompt: string, _systemPrompt: string, _options?: GenerateOptions): Promise<LLMResponse>;
236
+ isAvailable(): boolean;
237
+ estimateCost(promptTokens: number, completionTokens: number, _model?: string): number;
238
+ getCallCount(): number;
239
+ resetCallCount(): void;
240
+ }
241
+
242
+ /**
243
+ * Extract a JSON object from LLM response content.
244
+ *
245
+ * Tries three strategies in order:
246
+ * 1. Direct JSON.parse of the trimmed content
247
+ * 2. Extract from markdown code blocks (```json ... ```)
248
+ * 3. Find JSON object boundaries ({ ... })
249
+ */
250
+ declare function extractJson(content: string): JsonExtractionResult;
251
+
252
+ /**
253
+ * Maps an LLM error code to an HTTP status code.
254
+ * Use this in Next.js API routes to return appropriate HTTP responses
255
+ * when an LLM generation call fails.
256
+ */
257
+ declare function llmErrorToHttpStatus(code: LLMErrorCode | string): number;
258
+
259
+ /**
260
+ * Build a correction prompt for schema validation errors.
261
+ *
262
+ * Domain-agnostic: accepts the raw previous response and a ZodError,
263
+ * formats them into a prompt asking the LLM to fix specific field errors.
264
+ */
265
+ declare function buildSchemaErrorCorrectionPrompt(previousResponse: string, zodError: ZodError): string;
266
+ /**
267
+ * Build a correction prompt for JSON parsing errors.
268
+ *
269
+ * Domain-agnostic: accepts the raw response and a parse error message.
270
+ */
271
+ declare function buildParseErrorCorrectionPrompt(previousResponse: string, parseError: string): string;
272
+ /**
273
+ * Build a generic retry prompt when all corrections have failed.
274
+ *
275
+ * Domain-agnostic: just re-states the original request and asks for a simpler output.
276
+ */
277
+ declare function buildGenericRetryPrompt(originalPrompt: string, attemptNumber: number): string;
278
+
279
+ /**
280
+ * Generic LLM Service
281
+ *
282
+ * Orchestrates provider selection, generation, JSON extraction,
283
+ * schema validation, and retry logic. Parameterized over <TOutput>
284
+ * so domain-specific schemas (Pattern, Recipe, etc.) stay in their apps.
285
+ */
286
+
287
+ /**
288
+ * Metadata about a generation attempt (tokens, model, retries).
289
+ */
290
+ interface GenerationMetadata {
291
+ model: string;
292
+ promptTokens: number;
293
+ completionTokens: number;
294
+ validationAttempts: number;
295
+ }
296
+ /**
297
+ * Result of a validated generation. The caller checks `success` to narrow the union.
298
+ */
299
+ type GenerationResult<TOutput> = {
300
+ success: true;
301
+ data: TOutput;
302
+ metadata: GenerationMetadata;
303
+ } | {
304
+ success: false;
305
+ error: {
306
+ code: string;
307
+ message: string;
308
+ retryable: boolean;
309
+ };
310
+ metadata?: GenerationMetadata;
311
+ };
312
+ /**
313
+ * Generic LLM service. Consumers supply:
314
+ * - A Zod schema for output validation
315
+ * - Prompt builders for their domain
316
+ *
317
+ * The service handles provider selection, retries, JSON extraction, and validation.
318
+ */
319
+ declare class LLMService<TOutput> {
320
+ private readonly config;
321
+ private readonly providers;
322
+ constructor(config?: LLMServiceConfig);
323
+ private initializeProviders;
324
+ private getProvider;
325
+ /** Check if any LLM provider is available. */
326
+ isAvailable(): boolean;
327
+ /** Get list of available provider names. */
328
+ getAvailableProviders(): string[];
329
+ /**
330
+ * Simple chat-style generation with no schema validation.
331
+ * Returns the raw LLM response.
332
+ */
333
+ chat(userPrompt: string, systemPrompt: string, options?: GenerateOptions): Promise<LLMResponse>;
334
+ /**
335
+ * Generate structured output validated against a Zod schema.
336
+ *
337
+ * @param userPrompt - User's request
338
+ * @param systemPrompt - System instructions
339
+ * @param schema - Zod schema to validate the parsed JSON against
340
+ * @param options - Generation options
341
+ */
342
+ generate(userPrompt: string, systemPrompt: string, schema: ZodSchema<TOutput>, options?: GenerateOptions): Promise<GenerationResult<TOutput>>;
343
+ /**
344
+ * Register an additional provider instance (useful for custom/third-party providers).
345
+ */
346
+ registerProvider(name: string, provider: ILLMProvider): void;
347
+ private retryWithCorrection;
348
+ private validate;
349
+ private buildSuccess;
350
+ private buildError;
351
+ }
352
+
353
+ export { AnthropicProvider, type GenerateOptions, type GenerationMetadata, type GenerationResult, type ILLMProvider, type JsonExtractionResult, type LLMErrorCode, LLMProviderError, type LLMResponse, LLMService, type LLMServiceConfig, LLM_DEFAULTS, type MockBehavior, MockLLMProvider, OpenAIProvider, type ProviderConfig, type TokenUsage, type ValidationResult, buildGenericRetryPrompt, buildParseErrorCorrectionPrompt, buildSchemaErrorCorrectionPrompt, createAnthropicProvider, createOpenAIProvider, extractJson, llmErrorToHttpStatus, resetMockBehavior, setMockBehavior };
@@ -0,0 +1,353 @@
1
+ import { ZodError, ZodSchema } from 'zod';
2
+
3
+ /**
4
+ * LLM error codes for classifying provider failures.
5
+ */
6
+ type LLMErrorCode = 'RATE_LIMITED' | 'AUTHENTICATION_ERROR' | 'INVALID_REQUEST' | 'CONTEXT_LENGTH_EXCEEDED' | 'CONTENT_FILTERED' | 'SERVICE_UNAVAILABLE' | 'TIMEOUT' | 'PARSE_ERROR' | 'UNKNOWN_ERROR';
7
+ /**
8
+ * Typed error for LLM provider failures.
9
+ * Carries a machine-readable code and a retryable flag so callers can
10
+ * decide whether to retry or surface the error to the user.
11
+ */
12
+ declare class LLMProviderError extends Error {
13
+ readonly code: LLMErrorCode;
14
+ readonly retryable: boolean;
15
+ readonly statusCode?: number | undefined;
16
+ readonly provider?: string | undefined;
17
+ constructor(message: string, code: LLMErrorCode, retryable?: boolean, statusCode?: number | undefined, provider?: string | undefined);
18
+ }
19
+
20
+ /**
21
+ * Token usage statistics returned by every provider call.
22
+ */
23
+ interface TokenUsage {
24
+ promptTokens: number;
25
+ completionTokens: number;
26
+ totalTokens: number;
27
+ }
28
+ /**
29
+ * Raw response envelope from an LLM provider.
30
+ */
31
+ interface LLMResponse {
32
+ /** The raw text content from the LLM */
33
+ content: string;
34
+ /** Token usage statistics */
35
+ usage: TokenUsage;
36
+ /** Model identifier used for generation */
37
+ model: string;
38
+ /** Response ID for debugging/logging */
39
+ responseId?: string;
40
+ /** Finish reason (e.g., 'stop', 'length', 'content_filter') */
41
+ finishReason?: string;
42
+ }
43
+ /**
44
+ * Options passed through to the provider for a single generation call.
45
+ */
46
+ interface GenerateOptions {
47
+ /** Model to use (provider-specific) */
48
+ model?: string;
49
+ /** Temperature for response randomness (0-1) */
50
+ temperature?: number;
51
+ /** Maximum tokens in response */
52
+ maxTokens?: number;
53
+ /** Request timeout in milliseconds */
54
+ timeout?: number;
55
+ /** Arbitrary extra data the caller wants to thread through (e.g. domain preferences) */
56
+ extra?: Record<string, unknown>;
57
+ }
58
+ /**
59
+ * Provider configuration — everything needed to construct a provider instance.
60
+ */
61
+ interface ProviderConfig {
62
+ apiKey: string;
63
+ baseUrl?: string;
64
+ defaultModel?: string;
65
+ defaultTemperature?: number;
66
+ defaultMaxTokens?: number;
67
+ timeoutMs?: number;
68
+ }
69
+ /**
70
+ * Result of attempting to extract JSON from an LLM response string.
71
+ */
72
+ interface JsonExtractionResult {
73
+ success: boolean;
74
+ json?: unknown;
75
+ error?: string;
76
+ raw: string;
77
+ }
78
+ /**
79
+ * Generic validation result — parameterized over the domain data type.
80
+ */
81
+ interface ValidationResult<T> {
82
+ valid: boolean;
83
+ data?: T;
84
+ zodError?: ZodError;
85
+ errors?: string[];
86
+ }
87
+ /**
88
+ * Configuration for the generic LLMService.
89
+ */
90
+ interface LLMServiceConfig {
91
+ /** Maximum number of retry attempts for validation failures */
92
+ maxRetries?: number;
93
+ /** Preferred provider (will fallback to available if not configured) */
94
+ preferredProvider?: 'openai' | 'anthropic' | 'mock';
95
+ /** Default model override */
96
+ defaultModel?: string;
97
+ /** Default temperature */
98
+ defaultTemperature?: number;
99
+ /** Default max tokens */
100
+ defaultMaxTokens?: number;
101
+ }
102
+ /**
103
+ * Default LLM configuration values.
104
+ * Apps can override these via LLMServiceConfig or environment variables.
105
+ */
106
+ declare const LLM_DEFAULTS: {
107
+ readonly openaiModel: "gpt-4o-mini";
108
+ readonly anthropicModel: "claude-sonnet-4-20250514";
109
+ /**
110
+ * Default sampling temperature.
111
+ * Note: base gpt-5 models (gpt-5, gpt-5.1, gpt-5.2) require temperature=1.0
112
+ * and the OpenAI provider enforces this automatically.
113
+ */
114
+ readonly temperature: 0.7;
115
+ readonly maxTokens: 8192;
116
+ readonly timeoutMs: 60000;
117
+ };
118
+
119
+ /**
120
+ * Contract that every LLM provider must implement.
121
+ *
122
+ * Generic over nothing — the provider just takes string prompts and returns
123
+ * string content. Domain-specific parsing/validation lives in the service layer.
124
+ */
125
+ interface ILLMProvider {
126
+ /** Unique identifier for the provider (e.g. 'openai', 'anthropic') */
127
+ readonly name: string;
128
+ /** List of available models */
129
+ readonly availableModels: readonly string[];
130
+ /** Default model for this provider */
131
+ readonly defaultModel: string;
132
+ /**
133
+ * Send a prompt pair to the LLM and return the raw response.
134
+ *
135
+ * @param userPrompt - The user's message / generation request
136
+ * @param systemPrompt - System-level instructions
137
+ * @param options - Generation options (model, temperature, etc.)
138
+ */
139
+ generate(userPrompt: string, systemPrompt: string, options?: GenerateOptions): Promise<LLMResponse>;
140
+ /** Check if the provider is properly configured and available */
141
+ isAvailable(): boolean;
142
+ /**
143
+ * Estimate cost for a request (in USD).
144
+ * Returns undefined if cost cannot be estimated.
145
+ */
146
+ estimateCost?(promptTokens: number, completionTokens: number, model?: string): number | undefined;
147
+ }
148
+
149
+ /**
150
+ * OpenAI Provider Implementation
151
+ *
152
+ * Uses native fetch to minimize dependencies.
153
+ * Supports GPT-5.x, GPT-4o models, and custom fine-tuned models.
154
+ *
155
+ * To use a custom fine-tuned model:
156
+ * 1. Set OPENAI_MODEL or LLM_MODEL to your fine-tuned model ID (e.g., "ft:gpt-4o-2024-08-06:org:name:id")
157
+ * 2. Fine-tuned models will use the configured temperature setting (not forced to 1.0 like base gpt-5)
158
+ */
159
+
160
+ declare class OpenAIProvider implements ILLMProvider {
161
+ readonly name = "openai";
162
+ readonly availableModels: readonly ["gpt-5.2", "gpt-5.1", "gpt-5", "gpt-4o", "gpt-4o-mini"];
163
+ readonly defaultModel: string;
164
+ private readonly config;
165
+ constructor(config: ProviderConfig);
166
+ isAvailable(): boolean;
167
+ generate(userPrompt: string, systemPrompt: string, options?: GenerateOptions): Promise<LLMResponse>;
168
+ estimateCost(promptTokens: number, completionTokens: number, model?: string): number | undefined;
169
+ private handleApiError;
170
+ }
171
+ /**
172
+ * Create an OpenAI provider from environment variables.
173
+ * Returns null if OPENAI_API_KEY is not set.
174
+ */
175
+ declare function createOpenAIProvider(): OpenAIProvider | null;
176
+
177
+ /**
178
+ * Anthropic Provider Implementation
179
+ *
180
+ * Uses native fetch to minimize dependencies.
181
+ * Supports Claude 4 and Claude 3.x models.
182
+ */
183
+
184
+ declare class AnthropicProvider implements ILLMProvider {
185
+ readonly name = "anthropic";
186
+ readonly availableModels: readonly ["claude-opus-4-6", "claude-opus-4-20250514", "claude-sonnet-4-6", "claude-sonnet-4-20250514", "claude-3-5-sonnet-20241022", "claude-3-5-haiku-20241022", "claude-3-opus-20240229", "claude-3-sonnet-20240229", "claude-3-haiku-20240307"];
187
+ readonly defaultModel: string;
188
+ private readonly config;
189
+ private readonly apiVersion;
190
+ constructor(config: ProviderConfig, apiVersion?: string);
191
+ isAvailable(): boolean;
192
+ generate(userPrompt: string, systemPrompt: string, options?: GenerateOptions): Promise<LLMResponse>;
193
+ estimateCost(promptTokens: number, completionTokens: number, model?: string): number | undefined;
194
+ private handleApiError;
195
+ }
196
+ /**
197
+ * Create an Anthropic provider from environment variables.
198
+ * Returns null if ANTHROPIC_API_KEY is not set.
199
+ */
200
+ declare function createAnthropicProvider(): AnthropicProvider | null;
201
+
202
+ /**
203
+ * Mock LLM Provider for Testing
204
+ *
205
+ * Provides deterministic responses for testing.
206
+ * Can simulate errors, delays, and custom responses.
207
+ */
208
+
209
+ interface MockBehavior {
210
+ /** Delay before responding (ms) */
211
+ delay?: number;
212
+ /** Simulate an error */
213
+ error?: {
214
+ code: 'RATE_LIMITED' | 'SERVICE_UNAVAILABLE' | 'CONTENT_FILTERED' | 'TIMEOUT';
215
+ message: string;
216
+ };
217
+ /** Return invalid JSON (for validation retry testing) */
218
+ returnInvalidJson?: boolean;
219
+ /** Custom response content string */
220
+ customResponse?: string;
221
+ }
222
+ /**
223
+ * Set mock behavior for testing.
224
+ */
225
+ declare function setMockBehavior(behavior: MockBehavior): void;
226
+ /**
227
+ * Reset mock behavior to defaults.
228
+ */
229
+ declare function resetMockBehavior(): void;
230
+ declare class MockLLMProvider implements ILLMProvider {
231
+ readonly name = "mock";
232
+ readonly availableModels: readonly ["mock-model-1", "mock-model-2"];
233
+ readonly defaultModel = "mock-model-1";
234
+ private callCount;
235
+ generate(_userPrompt: string, _systemPrompt: string, _options?: GenerateOptions): Promise<LLMResponse>;
236
+ isAvailable(): boolean;
237
+ estimateCost(promptTokens: number, completionTokens: number, _model?: string): number;
238
+ getCallCount(): number;
239
+ resetCallCount(): void;
240
+ }
241
+
242
+ /**
243
+ * Extract a JSON object from LLM response content.
244
+ *
245
+ * Tries three strategies in order:
246
+ * 1. Direct JSON.parse of the trimmed content
247
+ * 2. Extract from markdown code blocks (```json ... ```)
248
+ * 3. Find JSON object boundaries ({ ... })
249
+ */
250
+ declare function extractJson(content: string): JsonExtractionResult;
251
+
252
+ /**
253
+ * Maps an LLM error code to an HTTP status code.
254
+ * Use this in Next.js API routes to return appropriate HTTP responses
255
+ * when an LLM generation call fails.
256
+ */
257
+ declare function llmErrorToHttpStatus(code: LLMErrorCode | string): number;
258
+
259
+ /**
260
+ * Build a correction prompt for schema validation errors.
261
+ *
262
+ * Domain-agnostic: accepts the raw previous response and a ZodError,
263
+ * formats them into a prompt asking the LLM to fix specific field errors.
264
+ */
265
+ declare function buildSchemaErrorCorrectionPrompt(previousResponse: string, zodError: ZodError): string;
266
+ /**
267
+ * Build a correction prompt for JSON parsing errors.
268
+ *
269
+ * Domain-agnostic: accepts the raw response and a parse error message.
270
+ */
271
+ declare function buildParseErrorCorrectionPrompt(previousResponse: string, parseError: string): string;
272
+ /**
273
+ * Build a generic retry prompt when all corrections have failed.
274
+ *
275
+ * Domain-agnostic: just re-states the original request and asks for a simpler output.
276
+ */
277
+ declare function buildGenericRetryPrompt(originalPrompt: string, attemptNumber: number): string;
278
+
279
+ /**
280
+ * Generic LLM Service
281
+ *
282
+ * Orchestrates provider selection, generation, JSON extraction,
283
+ * schema validation, and retry logic. Parameterized over <TOutput>
284
+ * so domain-specific schemas (Pattern, Recipe, etc.) stay in their apps.
285
+ */
286
+
287
+ /**
288
+ * Metadata about a generation attempt (tokens, model, retries).
289
+ */
290
+ interface GenerationMetadata {
291
+ model: string;
292
+ promptTokens: number;
293
+ completionTokens: number;
294
+ validationAttempts: number;
295
+ }
296
+ /**
297
+ * Result of a validated generation. The caller checks `success` to narrow the union.
298
+ */
299
+ type GenerationResult<TOutput> = {
300
+ success: true;
301
+ data: TOutput;
302
+ metadata: GenerationMetadata;
303
+ } | {
304
+ success: false;
305
+ error: {
306
+ code: string;
307
+ message: string;
308
+ retryable: boolean;
309
+ };
310
+ metadata?: GenerationMetadata;
311
+ };
312
+ /**
313
+ * Generic LLM service. Consumers supply:
314
+ * - A Zod schema for output validation
315
+ * - Prompt builders for their domain
316
+ *
317
+ * The service handles provider selection, retries, JSON extraction, and validation.
318
+ */
319
+ declare class LLMService<TOutput> {
320
+ private readonly config;
321
+ private readonly providers;
322
+ constructor(config?: LLMServiceConfig);
323
+ private initializeProviders;
324
+ private getProvider;
325
+ /** Check if any LLM provider is available. */
326
+ isAvailable(): boolean;
327
+ /** Get list of available provider names. */
328
+ getAvailableProviders(): string[];
329
+ /**
330
+ * Simple chat-style generation with no schema validation.
331
+ * Returns the raw LLM response.
332
+ */
333
+ chat(userPrompt: string, systemPrompt: string, options?: GenerateOptions): Promise<LLMResponse>;
334
+ /**
335
+ * Generate structured output validated against a Zod schema.
336
+ *
337
+ * @param userPrompt - User's request
338
+ * @param systemPrompt - System instructions
339
+ * @param schema - Zod schema to validate the parsed JSON against
340
+ * @param options - Generation options
341
+ */
342
+ generate(userPrompt: string, systemPrompt: string, schema: ZodSchema<TOutput>, options?: GenerateOptions): Promise<GenerationResult<TOutput>>;
343
+ /**
344
+ * Register an additional provider instance (useful for custom/third-party providers).
345
+ */
346
+ registerProvider(name: string, provider: ILLMProvider): void;
347
+ private retryWithCorrection;
348
+ private validate;
349
+ private buildSuccess;
350
+ private buildError;
351
+ }
352
+
353
+ export { AnthropicProvider, type GenerateOptions, type GenerationMetadata, type GenerationResult, type ILLMProvider, type JsonExtractionResult, type LLMErrorCode, LLMProviderError, type LLMResponse, LLMService, type LLMServiceConfig, LLM_DEFAULTS, type MockBehavior, MockLLMProvider, OpenAIProvider, type ProviderConfig, type TokenUsage, type ValidationResult, buildGenericRetryPrompt, buildParseErrorCorrectionPrompt, buildSchemaErrorCorrectionPrompt, createAnthropicProvider, createOpenAIProvider, extractJson, llmErrorToHttpStatus, resetMockBehavior, setMockBehavior };