@aragon-agent/core 0.1.3

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.
Files changed (74) hide show
  1. package/CHANGELOG.md +126 -0
  2. package/LICENSE +21 -0
  3. package/README.md +147 -0
  4. package/dist/engine/agent-loop.d.ts +52 -0
  5. package/dist/engine/agent-loop.js +260 -0
  6. package/dist/engine/agent.d.ts +129 -0
  7. package/dist/engine/agent.js +283 -0
  8. package/dist/engine/message-manager.d.ts +26 -0
  9. package/dist/engine/message-manager.js +39 -0
  10. package/dist/engine/steering.d.ts +27 -0
  11. package/dist/engine/steering.js +51 -0
  12. package/dist/engine/watchdog.d.ts +24 -0
  13. package/dist/engine/watchdog.js +50 -0
  14. package/dist/index.d.ts +46 -0
  15. package/dist/index.js +63 -0
  16. package/dist/llm/model-registry.d.ts +51 -0
  17. package/dist/llm/model-registry.js +277 -0
  18. package/dist/llm/provider.d.ts +72 -0
  19. package/dist/llm/provider.js +77 -0
  20. package/dist/llm/providers/anthropic.d.ts +23 -0
  21. package/dist/llm/providers/anthropic.js +420 -0
  22. package/dist/llm/providers/google.d.ts +22 -0
  23. package/dist/llm/providers/google.js +336 -0
  24. package/dist/llm/providers/index.d.ts +67 -0
  25. package/dist/llm/providers/index.js +127 -0
  26. package/dist/llm/providers/openai.d.ts +22 -0
  27. package/dist/llm/providers/openai.js +353 -0
  28. package/dist/llm/stream-utils.d.ts +33 -0
  29. package/dist/llm/stream-utils.js +132 -0
  30. package/dist/llm/types.d.ts +129 -0
  31. package/dist/llm/types.js +17 -0
  32. package/dist/sandbox/console-capture.d.ts +29 -0
  33. package/dist/sandbox/console-capture.js +56 -0
  34. package/dist/sandbox/http-bridge.d.ts +47 -0
  35. package/dist/sandbox/http-bridge.js +143 -0
  36. package/dist/sandbox/isolated-vm-sandbox.d.ts +50 -0
  37. package/dist/sandbox/isolated-vm-sandbox.js +226 -0
  38. package/dist/sandbox/tool-bridge.d.ts +42 -0
  39. package/dist/sandbox/tool-bridge.js +98 -0
  40. package/dist/sandbox/types.d.ts +84 -0
  41. package/dist/sandbox/types.js +8 -0
  42. package/dist/skills/constants.d.ts +122 -0
  43. package/dist/skills/constants.js +179 -0
  44. package/dist/skills/disclosure.d.ts +146 -0
  45. package/dist/skills/disclosure.js +788 -0
  46. package/dist/skills/frontmatter.d.ts +27 -0
  47. package/dist/skills/frontmatter.js +177 -0
  48. package/dist/skills/index.d.ts +21 -0
  49. package/dist/skills/index.js +18 -0
  50. package/dist/skills/skill-find-tool.d.ts +41 -0
  51. package/dist/skills/skill-find-tool.js +117 -0
  52. package/dist/skills/skill-registry.d.ts +96 -0
  53. package/dist/skills/skill-registry.js +208 -0
  54. package/dist/skills/skill-tool.d.ts +44 -0
  55. package/dist/skills/skill-tool.js +96 -0
  56. package/dist/skills/tool-policy.d.ts +91 -0
  57. package/dist/skills/tool-policy.js +272 -0
  58. package/dist/skills/types.d.ts +271 -0
  59. package/dist/skills/types.js +8 -0
  60. package/dist/skills/validate.d.ts +37 -0
  61. package/dist/skills/validate.js +264 -0
  62. package/dist/tools/executor.d.ts +54 -0
  63. package/dist/tools/executor.js +206 -0
  64. package/dist/tools/helpers.d.ts +69 -0
  65. package/dist/tools/helpers.js +87 -0
  66. package/dist/tools/registry.d.ts +58 -0
  67. package/dist/tools/registry.js +119 -0
  68. package/dist/tools/types.d.ts +140 -0
  69. package/dist/tools/types.js +7 -0
  70. package/dist/tools/validator.d.ts +46 -0
  71. package/dist/tools/validator.js +210 -0
  72. package/dist/types.d.ts +56 -0
  73. package/dist/types.js +7 -0
  74. package/package.json +115 -0
package/dist/index.js ADDED
@@ -0,0 +1,63 @@
1
+ /**
2
+ * Agent core — barrel export.
3
+ *
4
+ * This is the single entry point for importing agent-core functionality.
5
+ * Other tasks will expand this file as more modules are added (engine, tools,
6
+ * sandbox).
7
+ */
8
+ export { THINKING_BUDGET } from './llm/types.js';
9
+ export { LLMError, classifyHttpError, wrapFetchError, } from './llm/provider.js';
10
+ export { parseSSEStream, consumeStream, } from './llm/stream-utils.js';
11
+ // ---------------------------------------------------------------------------
12
+ // Provider registry
13
+ // ---------------------------------------------------------------------------
14
+ export { ProviderRegistry, initProviders, getProviderRegistry, setProviderRegistry, streamLLM, completeLLM, } from './llm/providers/index.js';
15
+ // ---------------------------------------------------------------------------
16
+ // Individual providers (for direct use when needed)
17
+ // ---------------------------------------------------------------------------
18
+ export { AnthropicProvider } from './llm/providers/anthropic.js';
19
+ export { OpenAIProvider } from './llm/providers/openai.js';
20
+ export { GoogleProvider } from './llm/providers/google.js';
21
+ // ---------------------------------------------------------------------------
22
+ // Model registry
23
+ // ---------------------------------------------------------------------------
24
+ export { ModelRegistry, getModelRegistry, setModelRegistry, } from './llm/model-registry.js';
25
+ export { textResult, errorResult, imageResult, multiResult, defineTool, } from './tools/helpers.js';
26
+ export { ToolRegistry } from './tools/registry.js';
27
+ export { ToolParamValidator, ToolValidationError, formatValidationErrors, } from './tools/validator.js';
28
+ export { ToolExecutor } from './tools/executor.js';
29
+ // ---------------------------------------------------------------------------
30
+ // Skills — progressive-disclosure skill system
31
+ //
32
+ // Pure logic only (D1): parsing, validation, registry, budgeting, rendering and
33
+ // the Level 2 tool factory. All filesystem / network / process work lives in the
34
+ // CLI and reaches this module through the injected `SkillHost` port, which is
35
+ // what keeps this package free of `node:*` imports.
36
+ // ---------------------------------------------------------------------------
37
+ export { SkillRegistry } from './skills/skill-registry.js';
38
+ export { parseFrontmatter } from './skills/frontmatter.js';
39
+ export { validateSkillFrontmatter, validateStagedSkill } from './skills/validate.js';
40
+ export { renderSkillCatalog, renderSkillBody, renderSkillInvocation, renderSkillFindResults, rankCatalogRecords, applySkillArguments, suggestSkillNames, sanitizeForPromptBlock, } from './skills/disclosure.js';
41
+ export { createSkillTool } from './skills/skill-tool.js';
42
+ export { createSkillFindTool } from './skills/skill-find-tool.js';
43
+ // The turn-scoped tool ceiling (§5). Only the two entry points the host needs to
44
+ // decide and to judge a call; the alias tables and the rendering helpers stay on
45
+ // the `./skills` subpath, matching the existing split of this barrel.
46
+ export { computeToolPolicy, evaluateToolCall } from './skills/tool-policy.js';
47
+ export {
48
+ // Every budget below is measured in UTF-8 BYTES (D19).
49
+ SKILL_CATALOG_MAX_BYTES, SKILL_BODY_MAX_BYTES, SKILL_RESULT_MAX_BYTES, ALWAYS_SKILLS_MAX_BYTES, SKILL_MD_MAX_BYTES, SKILL_DESC_LINE_MAX, SKILL_FILES_MAX, SKILL_FIND_MAX_BYTES, SKILL_NAME_PATTERN, } from './skills/constants.js';
50
+ // ---------------------------------------------------------------------------
51
+ // Agent engine
52
+ // ---------------------------------------------------------------------------
53
+ export { Agent } from './engine/agent.js';
54
+ export { MessageManager } from './engine/message-manager.js';
55
+ export { MessageQueueManager } from './engine/steering.js';
56
+ export { IdleWatchdog } from './engine/watchdog.js';
57
+ // Sandbox exports are NOT re-exported here — isolated-vm is incompatible with Electron's V8.
58
+ // Import directly from './sandbox/*.js' when needed (lazy loading only).
59
+ // ---------------------------------------------------------------------------
60
+ // AragonAgent — published brand alias of the engine's `Agent` class.
61
+ // The original `Agent` name is preserved above; consumers may use either.
62
+ // ---------------------------------------------------------------------------
63
+ export { Agent as AragonAgent } from './engine/agent.js';
@@ -0,0 +1,51 @@
1
+ /**
2
+ * Model registry — static builtin model metadata + runtime API discovery with
3
+ * caching.
4
+ *
5
+ * The builtin lists are migrated from `src/lib/model-options.ts` and the
6
+ * discovery logic mirrors `server/services/model-detection.ts`, but uses the
7
+ * new LLMProvider interface for API queries.
8
+ */
9
+ import type { ModelInfo } from './types.js';
10
+ import type { ProviderRegistry } from './providers/index.js';
11
+ export declare class ModelRegistry {
12
+ /** Static/builtin models keyed by provider id. */
13
+ private readonly builtinModels;
14
+ /** API-discovered models cache keyed by `${providerId}:${baseUrl}`. */
15
+ private readonly discoveryCache;
16
+ /** Optional reference to the provider registry for API discovery. */
17
+ private providerRegistry;
18
+ constructor(providerRegistry?: ProviderRegistry);
19
+ /** Register (or replace) the builtin model list for a provider. */
20
+ registerBuiltinModels(providerId: string, models: ModelInfo[]): void;
21
+ /** Retrieve the static builtin models for a provider. */
22
+ getModels(providerId: string): ModelInfo[];
23
+ /** Look up a specific model by provider + model id. */
24
+ getModel(providerId: string, modelId: string): ModelInfo | undefined;
25
+ /**
26
+ * Discover models from the provider's API. Results are cached for 5 min.
27
+ *
28
+ * Falls back to an empty array on failure — never throws.
29
+ */
30
+ discoverModels(providerId: string, apiKey: string, baseUrl?: string): Promise<ModelInfo[]>;
31
+ /** Invalidate the discovery cache for a provider (or all). */
32
+ clearCache(providerId?: string): void;
33
+ /**
34
+ * Build a runtime ModelInfo for a model that isn't in the registry.
35
+ *
36
+ * Uses sensible defaults — callers can override specific fields.
37
+ */
38
+ buildRuntimeModel(providerId: string, modelId: string, overrides?: Partial<ModelInfo>): ModelInfo;
39
+ /** Set or replace the provider registry reference. */
40
+ setProviderRegistry(registry: ProviderRegistry): void;
41
+ private registerDefaults;
42
+ }
43
+ /**
44
+ * Get (or lazily create) the global singleton model registry.
45
+ */
46
+ export declare function getModelRegistry(): ModelRegistry;
47
+ /**
48
+ * Replace the global singleton (useful for testing or re-initialization
49
+ * with a provider registry reference).
50
+ */
51
+ export declare function setModelRegistry(registry: ModelRegistry): void;
@@ -0,0 +1,277 @@
1
+ /**
2
+ * Model registry — static builtin model metadata + runtime API discovery with
3
+ * caching.
4
+ *
5
+ * The builtin lists are migrated from `src/lib/model-options.ts` and the
6
+ * discovery logic mirrors `server/services/model-detection.ts`, but uses the
7
+ * new LLMProvider interface for API queries.
8
+ */
9
+ /** Cache TTL: 5 minutes. */
10
+ const CACHE_TTL_MS = 5 * 60 * 1000;
11
+ // ---------------------------------------------------------------------------
12
+ // ModelRegistry
13
+ // ---------------------------------------------------------------------------
14
+ export class ModelRegistry {
15
+ /** Static/builtin models keyed by provider id. */
16
+ builtinModels = new Map();
17
+ /** API-discovered models cache keyed by `${providerId}:${baseUrl}`. */
18
+ discoveryCache = new Map();
19
+ /** Optional reference to the provider registry for API discovery. */
20
+ providerRegistry;
21
+ constructor(providerRegistry) {
22
+ this.providerRegistry = providerRegistry;
23
+ this.registerDefaults();
24
+ }
25
+ // -----------------------------------------------------------------------
26
+ // Public API
27
+ // -----------------------------------------------------------------------
28
+ /** Register (or replace) the builtin model list for a provider. */
29
+ registerBuiltinModels(providerId, models) {
30
+ this.builtinModels.set(providerId, models);
31
+ }
32
+ /** Retrieve the static builtin models for a provider. */
33
+ getModels(providerId) {
34
+ return this.builtinModels.get(providerId) || [];
35
+ }
36
+ /** Look up a specific model by provider + model id. */
37
+ getModel(providerId, modelId) {
38
+ const models = this.builtinModels.get(providerId);
39
+ return models?.find((m) => m.id === modelId);
40
+ }
41
+ /**
42
+ * Discover models from the provider's API. Results are cached for 5 min.
43
+ *
44
+ * Falls back to an empty array on failure — never throws.
45
+ */
46
+ async discoverModels(providerId, apiKey, baseUrl) {
47
+ const cacheKey = `${providerId}:${baseUrl || ''}`;
48
+ const cached = this.discoveryCache.get(cacheKey);
49
+ if (cached && Date.now() - cached.timestamp < CACHE_TTL_MS) {
50
+ return cached.models;
51
+ }
52
+ if (!this.providerRegistry)
53
+ return [];
54
+ const provider = this.providerRegistry.get(providerId);
55
+ if (!provider)
56
+ return [];
57
+ try {
58
+ const models = await provider.listModels(apiKey, baseUrl);
59
+ this.discoveryCache.set(cacheKey, { models, timestamp: Date.now() });
60
+ return models;
61
+ }
62
+ catch {
63
+ return [];
64
+ }
65
+ }
66
+ /** Invalidate the discovery cache for a provider (or all). */
67
+ clearCache(providerId) {
68
+ if (providerId) {
69
+ for (const key of this.discoveryCache.keys()) {
70
+ if (key.startsWith(`${providerId}:`)) {
71
+ this.discoveryCache.delete(key);
72
+ }
73
+ }
74
+ }
75
+ else {
76
+ this.discoveryCache.clear();
77
+ }
78
+ }
79
+ /**
80
+ * Build a runtime ModelInfo for a model that isn't in the registry.
81
+ *
82
+ * Uses sensible defaults — callers can override specific fields.
83
+ */
84
+ buildRuntimeModel(providerId, modelId, overrides) {
85
+ return {
86
+ id: modelId,
87
+ name: modelId,
88
+ provider: providerId,
89
+ contextWindow: 128_000,
90
+ maxOutputTokens: 16_384,
91
+ supportsThinking: false,
92
+ supportsTools: true,
93
+ supportsImages: false,
94
+ cost: { input: 0, output: 0 },
95
+ ...overrides,
96
+ };
97
+ }
98
+ /** Set or replace the provider registry reference. */
99
+ setProviderRegistry(registry) {
100
+ this.providerRegistry = registry;
101
+ }
102
+ // -----------------------------------------------------------------------
103
+ // Default builtin models (migrated from src/lib/model-options.ts)
104
+ // -----------------------------------------------------------------------
105
+ registerDefaults() {
106
+ this.builtinModels.set('anthropic', ANTHROPIC_MODELS);
107
+ this.builtinModels.set('openai', OPENAI_MODELS);
108
+ this.builtinModels.set('google', GOOGLE_MODELS);
109
+ this.builtinModels.set('xai', XAI_MODELS);
110
+ this.builtinModels.set('groq', GROQ_MODELS);
111
+ }
112
+ }
113
+ // ---------------------------------------------------------------------------
114
+ // Builtin model lists
115
+ // ---------------------------------------------------------------------------
116
+ const ANTHROPIC_MODELS = [
117
+ {
118
+ id: 'claude-sonnet-4-5-20250929',
119
+ name: 'Claude Sonnet 4.5',
120
+ provider: 'anthropic',
121
+ contextWindow: 200_000,
122
+ maxOutputTokens: 8192,
123
+ supportsThinking: true,
124
+ supportsTools: true,
125
+ supportsImages: true,
126
+ cost: { input: 3, output: 15, cacheRead: 0.3, cacheWrite: 3.75 },
127
+ },
128
+ {
129
+ id: 'claude-opus-4-6',
130
+ name: 'Claude Opus 4.6',
131
+ provider: 'anthropic',
132
+ contextWindow: 200_000,
133
+ maxOutputTokens: 32_000,
134
+ supportsThinking: true,
135
+ supportsTools: true,
136
+ supportsImages: true,
137
+ cost: { input: 15, output: 75, cacheRead: 1.5, cacheWrite: 18.75 },
138
+ },
139
+ {
140
+ id: 'claude-haiku-4-5-20251001',
141
+ name: 'Claude Haiku 4.5',
142
+ provider: 'anthropic',
143
+ contextWindow: 200_000,
144
+ maxOutputTokens: 8192,
145
+ supportsThinking: true,
146
+ supportsTools: true,
147
+ supportsImages: true,
148
+ cost: { input: 0.8, output: 4, cacheRead: 0.08, cacheWrite: 1 },
149
+ },
150
+ ];
151
+ const OPENAI_MODELS = [
152
+ {
153
+ id: 'gpt-4o',
154
+ name: 'GPT-4o',
155
+ provider: 'openai',
156
+ contextWindow: 128_000,
157
+ maxOutputTokens: 16_384,
158
+ supportsThinking: false,
159
+ supportsTools: true,
160
+ supportsImages: true,
161
+ cost: { input: 2.5, output: 10 },
162
+ },
163
+ {
164
+ id: 'gpt-4o-mini',
165
+ name: 'GPT-4o Mini',
166
+ provider: 'openai',
167
+ contextWindow: 128_000,
168
+ maxOutputTokens: 16_384,
169
+ supportsThinking: false,
170
+ supportsTools: true,
171
+ supportsImages: true,
172
+ cost: { input: 0.15, output: 0.6 },
173
+ },
174
+ {
175
+ id: 'o1',
176
+ name: 'o1',
177
+ provider: 'openai',
178
+ contextWindow: 200_000,
179
+ maxOutputTokens: 100_000,
180
+ supportsThinking: false,
181
+ supportsTools: true,
182
+ supportsImages: true,
183
+ cost: { input: 15, output: 60 },
184
+ },
185
+ {
186
+ id: 'o1-mini',
187
+ name: 'o1 Mini',
188
+ provider: 'openai',
189
+ contextWindow: 128_000,
190
+ maxOutputTokens: 65_536,
191
+ supportsThinking: false,
192
+ supportsTools: true,
193
+ supportsImages: false,
194
+ cost: { input: 3, output: 12 },
195
+ },
196
+ ];
197
+ const GOOGLE_MODELS = [
198
+ {
199
+ id: 'gemini-1.5-pro',
200
+ name: 'Gemini 1.5 Pro',
201
+ provider: 'google',
202
+ contextWindow: 2_097_152,
203
+ maxOutputTokens: 8192,
204
+ supportsThinking: false,
205
+ supportsTools: true,
206
+ supportsImages: true,
207
+ cost: { input: 1.25, output: 5 },
208
+ },
209
+ {
210
+ id: 'gemini-1.5-flash',
211
+ name: 'Gemini 1.5 Flash',
212
+ provider: 'google',
213
+ contextWindow: 1_048_576,
214
+ maxOutputTokens: 8192,
215
+ supportsThinking: false,
216
+ supportsTools: true,
217
+ supportsImages: true,
218
+ cost: { input: 0.075, output: 0.3 },
219
+ },
220
+ ];
221
+ const XAI_MODELS = [
222
+ {
223
+ id: 'grok-2',
224
+ name: 'Grok-2',
225
+ provider: 'xai',
226
+ contextWindow: 131_072,
227
+ maxOutputTokens: 8192,
228
+ supportsThinking: false,
229
+ supportsTools: true,
230
+ supportsImages: false,
231
+ cost: { input: 2, output: 10 },
232
+ },
233
+ ];
234
+ const GROQ_MODELS = [
235
+ {
236
+ id: 'llama-3.1-70b-versatile',
237
+ name: 'Llama 3.1 70B',
238
+ provider: 'groq',
239
+ contextWindow: 131_072,
240
+ maxOutputTokens: 8192,
241
+ supportsThinking: false,
242
+ supportsTools: true,
243
+ supportsImages: false,
244
+ cost: { input: 0.59, output: 0.79 },
245
+ },
246
+ {
247
+ id: 'mixtral-8x7b-32768',
248
+ name: 'Mixtral 8x7B',
249
+ provider: 'groq',
250
+ contextWindow: 32_768,
251
+ maxOutputTokens: 8192,
252
+ supportsThinking: false,
253
+ supportsTools: true,
254
+ supportsImages: false,
255
+ cost: { input: 0.24, output: 0.24 },
256
+ },
257
+ ];
258
+ // ---------------------------------------------------------------------------
259
+ // Singleton
260
+ // ---------------------------------------------------------------------------
261
+ let _singleton;
262
+ /**
263
+ * Get (or lazily create) the global singleton model registry.
264
+ */
265
+ export function getModelRegistry() {
266
+ if (!_singleton) {
267
+ _singleton = new ModelRegistry();
268
+ }
269
+ return _singleton;
270
+ }
271
+ /**
272
+ * Replace the global singleton (useful for testing or re-initialization
273
+ * with a provider registry reference).
274
+ */
275
+ export function setModelRegistry(registry) {
276
+ _singleton = registry;
277
+ }
@@ -0,0 +1,72 @@
1
+ /**
2
+ * LLM Provider interface, request types, and error classification.
3
+ */
4
+ import type { AssistantMessage, Message, ModelInfo, StreamEvent, ThinkingLevel, ToolDefinition } from './types.js';
5
+ export interface LLMRequest {
6
+ /** Model identifier, e.g. 'claude-sonnet-4-5-20250929'. */
7
+ model: string;
8
+ /** Conversation messages. */
9
+ messages: Message[];
10
+ /** System prompt — injected provider-appropriately (system field, system message, etc.). */
11
+ systemPrompt?: string;
12
+ /** Tool schemas the model may invoke. */
13
+ tools?: ToolDefinition[];
14
+ /** Provider API key. */
15
+ apiKey: string;
16
+ /** Override the default API base URL. */
17
+ baseUrl?: string;
18
+ /** Abort signal for cancellation. */
19
+ signal?: AbortSignal;
20
+ temperature?: number;
21
+ maxTokens?: number;
22
+ /** Anthropic extended thinking level. Ignored by non-Anthropic providers. */
23
+ thinkingLevel?: ThinkingLevel;
24
+ /** Explicit thinking budget (tokens). Overrides thinkingLevel if both are set. */
25
+ thinkingBudget?: number;
26
+ stopSequences?: string[];
27
+ }
28
+ export interface LLMProvider {
29
+ /** Unique provider identifier, e.g. 'anthropic', 'openai', 'google'. */
30
+ readonly id: string;
31
+ /** Human-readable display name. */
32
+ readonly displayName: string;
33
+ /** Default base URL for this provider's API. */
34
+ readonly defaultBaseUrl: string;
35
+ /**
36
+ * Stream a completion from the model.
37
+ *
38
+ * The returned iterator yields {@link StreamEvent} items and MUST terminate
39
+ * with either a `done` or an `error` event.
40
+ */
41
+ stream(request: LLMRequest): AsyncIterableIterator<StreamEvent>;
42
+ /**
43
+ * Non-streaming completion — internally consumes the stream and returns the
44
+ * final assembled {@link AssistantMessage}.
45
+ */
46
+ complete(request: LLMRequest): Promise<AssistantMessage>;
47
+ /**
48
+ * List models available under the given API key.
49
+ *
50
+ * Implementations should apply a reasonable timeout (15 s) and return an
51
+ * empty array on failure rather than throwing.
52
+ */
53
+ listModels(apiKey: string, baseUrl?: string): Promise<ModelInfo[]>;
54
+ }
55
+ export type LLMErrorType = 'auth_error' | 'rate_limit' | 'overloaded' | 'invalid_request' | 'context_overflow' | 'network_error' | 'timeout' | 'server_error' | 'unknown';
56
+ export declare class LLMError extends Error {
57
+ readonly provider: string;
58
+ readonly errorType: LLMErrorType;
59
+ readonly retryable: boolean;
60
+ readonly statusCode?: number | undefined;
61
+ readonly raw?: unknown | undefined;
62
+ constructor(message: string, provider: string, errorType: LLMErrorType, retryable: boolean, statusCode?: number | undefined, raw?: unknown | undefined);
63
+ }
64
+ /**
65
+ * Classify an HTTP status code into an {@link LLMErrorType} and determine
66
+ * whether the request is retryable.
67
+ */
68
+ export declare function classifyHttpError(statusCode: number, body: string, provider: string): LLMError;
69
+ /**
70
+ * Wrap a network-level fetch error (DNS, TLS, abort, etc.) into an LLMError.
71
+ */
72
+ export declare function wrapFetchError(err: unknown, provider: string): LLMError;
@@ -0,0 +1,77 @@
1
+ /**
2
+ * LLM Provider interface, request types, and error classification.
3
+ */
4
+ export class LLMError extends Error {
5
+ provider;
6
+ errorType;
7
+ retryable;
8
+ statusCode;
9
+ raw;
10
+ constructor(message, provider, errorType, retryable, statusCode, raw) {
11
+ super(message);
12
+ this.provider = provider;
13
+ this.errorType = errorType;
14
+ this.retryable = retryable;
15
+ this.statusCode = statusCode;
16
+ this.raw = raw;
17
+ this.name = 'LLMError';
18
+ }
19
+ }
20
+ /**
21
+ * Classify an HTTP status code into an {@link LLMErrorType} and determine
22
+ * whether the request is retryable.
23
+ */
24
+ export function classifyHttpError(statusCode, body, provider) {
25
+ let errorType;
26
+ let retryable;
27
+ switch (statusCode) {
28
+ case 400:
29
+ // Check for context overflow indicators
30
+ if (/context|token|length/i.test(body)) {
31
+ errorType = 'context_overflow';
32
+ retryable = false;
33
+ }
34
+ else {
35
+ errorType = 'invalid_request';
36
+ retryable = false;
37
+ }
38
+ break;
39
+ case 401:
40
+ case 403:
41
+ errorType = 'auth_error';
42
+ retryable = false;
43
+ break;
44
+ case 429:
45
+ errorType = 'rate_limit';
46
+ retryable = true;
47
+ break;
48
+ case 529:
49
+ errorType = 'overloaded';
50
+ retryable = true;
51
+ break;
52
+ default:
53
+ if (statusCode >= 500) {
54
+ errorType = 'server_error';
55
+ retryable = true;
56
+ }
57
+ else {
58
+ errorType = 'unknown';
59
+ retryable = false;
60
+ }
61
+ }
62
+ // Truncate body for the error message to avoid huge payloads
63
+ const truncated = body.length > 300 ? body.slice(0, 300) + '...' : body;
64
+ return new LLMError(`${provider} API error ${statusCode}: ${truncated}`, provider, errorType, retryable, statusCode, body);
65
+ }
66
+ /**
67
+ * Wrap a network-level fetch error (DNS, TLS, abort, etc.) into an LLMError.
68
+ */
69
+ export function wrapFetchError(err, provider) {
70
+ if (err instanceof LLMError)
71
+ return err;
72
+ const message = err instanceof Error ? err.message : String(err);
73
+ if (err instanceof Error && err.name === 'AbortError') {
74
+ return new LLMError(`${provider} request aborted: ${message}`, provider, 'timeout', true);
75
+ }
76
+ return new LLMError(`${provider} network error: ${message}`, provider, 'network_error', true, undefined, err);
77
+ }
@@ -0,0 +1,23 @@
1
+ /**
2
+ * Anthropic Messages API adapter.
3
+ *
4
+ * Converts the universal LLM types to/from Anthropic's wire format and maps
5
+ * SSE events to the unified StreamEvent protocol.
6
+ *
7
+ * Supports:
8
+ * - Streaming via `POST /v1/messages` with `stream: true`
9
+ * - Extended thinking (thinking_start / thinking_delta)
10
+ * - Tool use (content_block_start type=tool_use → tool_call_*)
11
+ * - Multimodal user messages (text + image)
12
+ * - Model list via `GET /v1/models`
13
+ */
14
+ import type { AssistantMessage, ModelInfo, StreamEvent } from '../types.js';
15
+ import type { LLMProvider, LLMRequest } from '../provider.js';
16
+ export declare class AnthropicProvider implements LLMProvider {
17
+ readonly id = "anthropic";
18
+ readonly displayName = "Anthropic";
19
+ readonly defaultBaseUrl = "https://api.anthropic.com";
20
+ stream(request: LLMRequest): AsyncIterableIterator<StreamEvent>;
21
+ complete(request: LLMRequest): Promise<AssistantMessage>;
22
+ listModels(apiKey: string, baseUrl?: string): Promise<ModelInfo[]>;
23
+ }