genai-lite 0.2.0 → 0.3.0

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 (59) hide show
  1. package/README.md +508 -30
  2. package/dist/config/presets.json +121 -17
  3. package/dist/index.d.ts +3 -3
  4. package/dist/index.js +4 -3
  5. package/dist/llm/LLMService.createMessages.test.d.ts +4 -0
  6. package/dist/llm/LLMService.createMessages.test.js +364 -0
  7. package/dist/llm/LLMService.d.ts +49 -47
  8. package/dist/llm/LLMService.js +208 -303
  9. package/dist/llm/LLMService.original.d.ts +147 -0
  10. package/dist/llm/LLMService.original.js +656 -0
  11. package/dist/llm/LLMService.prepareMessage.test.d.ts +1 -0
  12. package/dist/llm/LLMService.prepareMessage.test.js +303 -0
  13. package/dist/llm/LLMService.sendMessage.preset.test.d.ts +1 -0
  14. package/dist/llm/LLMService.sendMessage.preset.test.js +153 -0
  15. package/dist/llm/LLMService.test.js +275 -0
  16. package/dist/llm/clients/AnthropicClientAdapter.js +64 -10
  17. package/dist/llm/clients/AnthropicClientAdapter.test.js +11 -1
  18. package/dist/llm/clients/GeminiClientAdapter.js +70 -11
  19. package/dist/llm/clients/GeminiClientAdapter.test.js +125 -1
  20. package/dist/llm/clients/MockClientAdapter.js +9 -3
  21. package/dist/llm/clients/MockClientAdapter.test.js +11 -1
  22. package/dist/llm/clients/OpenAIClientAdapter.js +26 -10
  23. package/dist/llm/clients/OpenAIClientAdapter.test.js +11 -1
  24. package/dist/llm/config.js +117 -2
  25. package/dist/llm/config.test.js +17 -0
  26. package/dist/llm/services/AdapterRegistry.d.ts +59 -0
  27. package/dist/llm/services/AdapterRegistry.js +113 -0
  28. package/dist/llm/services/AdapterRegistry.test.d.ts +1 -0
  29. package/dist/llm/services/AdapterRegistry.test.js +239 -0
  30. package/dist/llm/services/ModelResolver.d.ts +35 -0
  31. package/dist/llm/services/ModelResolver.js +116 -0
  32. package/dist/llm/services/ModelResolver.test.d.ts +1 -0
  33. package/dist/llm/services/ModelResolver.test.js +158 -0
  34. package/dist/llm/services/PresetManager.d.ts +27 -0
  35. package/dist/llm/services/PresetManager.js +50 -0
  36. package/dist/llm/services/PresetManager.test.d.ts +1 -0
  37. package/dist/llm/services/PresetManager.test.js +210 -0
  38. package/dist/llm/services/RequestValidator.d.ts +31 -0
  39. package/dist/llm/services/RequestValidator.js +122 -0
  40. package/dist/llm/services/RequestValidator.test.d.ts +1 -0
  41. package/dist/llm/services/RequestValidator.test.js +159 -0
  42. package/dist/llm/services/SettingsManager.d.ts +32 -0
  43. package/dist/llm/services/SettingsManager.js +223 -0
  44. package/dist/llm/services/SettingsManager.test.d.ts +1 -0
  45. package/dist/llm/services/SettingsManager.test.js +266 -0
  46. package/dist/llm/types.d.ts +107 -0
  47. package/dist/prompting/builder.d.ts +4 -0
  48. package/dist/prompting/builder.js +12 -61
  49. package/dist/prompting/content.js +3 -9
  50. package/dist/prompting/index.d.ts +2 -3
  51. package/dist/prompting/index.js +4 -5
  52. package/dist/prompting/parser.d.ts +80 -0
  53. package/dist/prompting/parser.js +133 -0
  54. package/dist/prompting/parser.test.js +348 -0
  55. package/dist/prompting/template.d.ts +8 -0
  56. package/dist/prompting/template.js +89 -6
  57. package/dist/prompting/template.test.js +116 -0
  58. package/package.json +3 -2
  59. package/src/config/presets.json +122 -17
@@ -31,7 +31,8 @@ class MockClientAdapter {
31
31
  try {
32
32
  // Check for special test patterns in the last user message
33
33
  const lastMessage = request.messages[request.messages.length - 1];
34
- const content = lastMessage?.content?.toLowerCase() || "";
34
+ const originalContent = lastMessage?.content || "";
35
+ const content = originalContent.toLowerCase();
35
36
  // Simulate various error conditions based on message content
36
37
  if (content.includes("error_invalid_key")) {
37
38
  return this.createErrorResponse("Invalid API key provided", types_1.ADAPTER_ERROR_CODES.INVALID_API_KEY, 401, request);
@@ -58,7 +59,7 @@ class MockClientAdapter {
58
59
  return this.createErrorResponse("Generic provider error", types_1.ADAPTER_ERROR_CODES.PROVIDER_ERROR, 500, request);
59
60
  }
60
61
  // Generate successful mock response
61
- return this.createSuccessResponse(request, content);
62
+ return this.createSuccessResponse(request, content, originalContent);
62
63
  }
63
64
  catch (error) {
64
65
  return this.createErrorResponse(`Mock adapter error: ${error instanceof Error ? error.message : "Unknown error"}`, types_1.ADAPTER_ERROR_CODES.UNKNOWN_ERROR, 500, request);
@@ -84,7 +85,7 @@ class MockClientAdapter {
84
85
  /**
85
86
  * Creates a successful mock response
86
87
  */
87
- createSuccessResponse(request, userContent) {
88
+ createSuccessResponse(request, userContent, originalContent) {
88
89
  // Generate response content based on user input and settings
89
90
  let responseContent;
90
91
  // Check for settings-based test patterns
@@ -94,6 +95,11 @@ class MockClientAdapter {
94
95
  else if (userContent.includes("test_settings")) {
95
96
  responseContent = this.generateSettingsTestResponse(request.settings);
96
97
  }
98
+ else if (userContent.includes("test_thinking:")) {
99
+ // Extract content after "test_thinking:" for testing thinking extraction
100
+ const startIndex = originalContent.indexOf("test_thinking:") + "test_thinking:".length;
101
+ responseContent = originalContent.substring(startIndex).trim();
102
+ }
97
103
  else if (userContent.includes("hello") || userContent.includes("hi")) {
98
104
  responseContent =
99
105
  "Hello! I'm a mock LLM assistant. How can I help you today?";
@@ -20,7 +20,17 @@ describe('MockClientAdapter', () => {
20
20
  stopSequences: [],
21
21
  user: 'test-user',
22
22
  geminiSafetySettings: [],
23
- supportsSystemMessage: true
23
+ supportsSystemMessage: true,
24
+ reasoning: {
25
+ enabled: false,
26
+ effort: undefined,
27
+ maxTokens: undefined,
28
+ exclude: false
29
+ },
30
+ thinkingExtraction: {
31
+ enabled: true,
32
+ tag: 'thinking'
33
+ }
24
34
  }
25
35
  };
26
36
  });
@@ -64,6 +64,18 @@ class OpenAIClientAdapter {
64
64
  user: request.settings.user,
65
65
  }),
66
66
  };
67
+ // Handle reasoning configuration for OpenAI models (o-series)
68
+ if (request.settings.reasoning && !request.settings.reasoning.exclude) {
69
+ const reasoning = request.settings.reasoning;
70
+ // OpenAI uses reasoning_effort for o-series models
71
+ if (reasoning.effort) {
72
+ completionParams.reasoning_effort = reasoning.effort;
73
+ }
74
+ else if (reasoning.enabled !== false) {
75
+ // Default to medium effort if reasoning is enabled
76
+ completionParams.reasoning_effort = 'medium';
77
+ }
78
+ }
67
79
  console.log(`OpenAI API parameters:`, {
68
80
  model: completionParams.model,
69
81
  temperature: completionParams.temperature,
@@ -163,21 +175,25 @@ class OpenAIClientAdapter {
163
175
  if (!choice || !choice.message) {
164
176
  throw new Error("Invalid completion structure from OpenAI API");
165
177
  }
178
+ const responseChoice = {
179
+ message: {
180
+ role: choice.message.role,
181
+ content: choice.message.content || "",
182
+ },
183
+ finish_reason: choice.finish_reason,
184
+ index: choice.index,
185
+ };
186
+ // Check for reasoning content if OpenAI starts returning it
187
+ // (Currently o-series models don't return reasoning tokens)
188
+ if (choice.reasoning && request.settings.reasoning && !request.settings.reasoning.exclude) {
189
+ responseChoice.reasoning = choice.reasoning;
190
+ }
166
191
  return {
167
192
  id: completion.id,
168
193
  provider: request.providerId,
169
194
  model: completion.model || request.modelId,
170
195
  created: completion.created,
171
- choices: [
172
- {
173
- message: {
174
- role: choice.message.role,
175
- content: choice.message.content || "",
176
- },
177
- finish_reason: choice.finish_reason,
178
- index: choice.index,
179
- },
180
- ],
196
+ choices: [responseChoice],
181
197
  usage: completion.usage
182
198
  ? {
183
199
  prompt_tokens: completion.usage.prompt_tokens,
@@ -38,7 +38,17 @@ describe('OpenAIClientAdapter', () => {
38
38
  stopSequences: [],
39
39
  user: 'test-user',
40
40
  geminiSafetySettings: [],
41
- supportsSystemMessage: true
41
+ supportsSystemMessage: true,
42
+ reasoning: {
43
+ enabled: false,
44
+ effort: undefined,
45
+ maxTokens: undefined,
46
+ exclude: false
47
+ },
48
+ thinkingExtraction: {
49
+ enabled: true,
50
+ tag: 'thinking'
51
+ }
42
52
  }
43
53
  };
44
54
  });
@@ -57,6 +57,17 @@ exports.DEFAULT_LLM_SETTINGS = {
57
57
  { category: "HARM_CATEGORY_DANGEROUS_CONTENT", threshold: "BLOCK_NONE" },
58
58
  { category: "HARM_CATEGORY_HARASSMENT", threshold: "BLOCK_NONE" },
59
59
  ],
60
+ reasoning: {
61
+ enabled: false,
62
+ effort: undefined,
63
+ maxTokens: undefined,
64
+ exclude: false,
65
+ },
66
+ thinkingExtraction: {
67
+ enabled: false, // Now requires explicit opt-in, works with onMissing: 'auto'
68
+ tag: 'thinking',
69
+ onMissing: 'auto' // Smart enforcement based on native reasoning status
70
+ },
60
71
  };
61
72
  /**
62
73
  * Per-provider default setting overrides
@@ -126,6 +137,16 @@ exports.SUPPORTED_MODELS = [
126
137
  supportsPromptCache: true,
127
138
  cacheWritesPrice: 3.75,
128
139
  cacheReadsPrice: 0.3,
140
+ reasoning: {
141
+ supported: true,
142
+ enabledByDefault: false,
143
+ canDisable: true,
144
+ minBudget: 1024,
145
+ maxBudget: 32000,
146
+ defaultBudget: 10000,
147
+ outputType: 'summary',
148
+ requiresStreamingAbove: 21333,
149
+ },
129
150
  },
130
151
  {
131
152
  id: "claude-opus-4-20250514",
@@ -140,6 +161,16 @@ exports.SUPPORTED_MODELS = [
140
161
  supportsPromptCache: true,
141
162
  cacheWritesPrice: 18.75,
142
163
  cacheReadsPrice: 1.5,
164
+ reasoning: {
165
+ supported: true,
166
+ enabledByDefault: false,
167
+ canDisable: true,
168
+ minBudget: 1024,
169
+ maxBudget: 32000,
170
+ defaultBudget: 10000,
171
+ outputType: 'summary',
172
+ requiresStreamingAbove: 21333,
173
+ },
143
174
  },
144
175
  {
145
176
  id: "claude-3-7-sonnet-20250219",
@@ -154,6 +185,16 @@ exports.SUPPORTED_MODELS = [
154
185
  supportsPromptCache: true,
155
186
  cacheWritesPrice: 3.75,
156
187
  cacheReadsPrice: 0.3,
188
+ reasoning: {
189
+ supported: true,
190
+ enabledByDefault: false,
191
+ canDisable: true,
192
+ minBudget: 1024,
193
+ maxBudget: 32000,
194
+ defaultBudget: 10000,
195
+ outputType: 'full',
196
+ requiresStreamingAbove: 21333,
197
+ },
157
198
  },
158
199
  {
159
200
  id: "claude-3-5-sonnet-20241022",
@@ -196,6 +237,19 @@ exports.SUPPORTED_MODELS = [
196
237
  supportsImages: true,
197
238
  supportsPromptCache: true,
198
239
  cacheReadsPrice: 0.31,
240
+ reasoning: {
241
+ supported: true,
242
+ enabledByDefault: true,
243
+ canDisable: false,
244
+ minBudget: 1024,
245
+ maxBudget: 65536,
246
+ defaultBudget: -1,
247
+ dynamicBudget: {
248
+ value: -1,
249
+ description: "Let model decide based on query complexity",
250
+ },
251
+ outputType: 'summary',
252
+ },
199
253
  },
200
254
  {
201
255
  id: "gemini-2.5-flash",
@@ -208,9 +262,18 @@ exports.SUPPORTED_MODELS = [
208
262
  maxTokens: 65536,
209
263
  supportsImages: true,
210
264
  supportsPromptCache: true,
211
- thinkingConfig: {
265
+ reasoning: {
266
+ supported: true,
267
+ enabledByDefault: true,
268
+ canDisable: true,
269
+ minBudget: 1024,
212
270
  maxBudget: 24576,
213
- outputPrice: 2.5,
271
+ defaultBudget: -1,
272
+ dynamicBudget: {
273
+ value: -1,
274
+ description: "Let model decide based on query complexity",
275
+ },
276
+ outputType: 'summary',
214
277
  },
215
278
  },
216
279
  {
@@ -224,6 +287,19 @@ exports.SUPPORTED_MODELS = [
224
287
  maxTokens: 64000,
225
288
  supportsImages: true,
226
289
  supportsPromptCache: true,
290
+ reasoning: {
291
+ supported: true,
292
+ enabledByDefault: false,
293
+ canDisable: true,
294
+ minBudget: 512,
295
+ maxBudget: 24576,
296
+ defaultBudget: -1,
297
+ dynamicBudget: {
298
+ value: -1,
299
+ description: "Let model decide based on query complexity",
300
+ },
301
+ outputType: 'summary',
302
+ },
227
303
  },
228
304
  {
229
305
  id: "gemini-2.0-flash",
@@ -265,6 +341,12 @@ exports.SUPPORTED_MODELS = [
265
341
  supportsPromptCache: true,
266
342
  cacheReadsPrice: 0.275,
267
343
  unsupportedParameters: ["topP"],
344
+ reasoning: {
345
+ supported: true,
346
+ enabledByDefault: true,
347
+ canDisable: false,
348
+ outputType: 'none',
349
+ },
268
350
  },
269
351
  {
270
352
  id: "gpt-4.1",
@@ -401,6 +483,16 @@ function getDefaultSettingsForModel(modelId, providerId) {
401
483
  if (modelInfo && modelInfo.maxTokens !== undefined) {
402
484
  mergedSettings.maxTokens = modelInfo.maxTokens;
403
485
  }
486
+ // Handle reasoning settings based on model capabilities
487
+ if (modelInfo?.reasoning?.supported) {
488
+ // If the model has reasoning enabled by default, update the settings
489
+ if (modelInfo.reasoning.enabledByDefault) {
490
+ mergedSettings.reasoning = {
491
+ ...mergedSettings.reasoning,
492
+ enabled: true,
493
+ };
494
+ }
495
+ }
404
496
  // Filter out undefined values and ensure required fields
405
497
  return Object.fromEntries(Object.entries(mergedSettings).filter(([_, value]) => value !== undefined));
406
498
  }
@@ -504,5 +596,28 @@ function validateLLMSettings(settings) {
504
596
  }
505
597
  }
506
598
  }
599
+ if (settings.reasoning !== undefined) {
600
+ if (typeof settings.reasoning !== "object" || settings.reasoning === null) {
601
+ errors.push("reasoning must be an object");
602
+ }
603
+ else {
604
+ if (settings.reasoning.enabled !== undefined && typeof settings.reasoning.enabled !== "boolean") {
605
+ errors.push("reasoning.enabled must be a boolean");
606
+ }
607
+ if (settings.reasoning.effort !== undefined) {
608
+ if (!["high", "medium", "low"].includes(settings.reasoning.effort)) {
609
+ errors.push("reasoning.effort must be 'high', 'medium', or 'low'");
610
+ }
611
+ }
612
+ if (settings.reasoning.maxTokens !== undefined) {
613
+ if (!Number.isInteger(settings.reasoning.maxTokens) || settings.reasoning.maxTokens < 0) {
614
+ errors.push("reasoning.maxTokens must be a non-negative integer");
615
+ }
616
+ }
617
+ if (settings.reasoning.exclude !== undefined && typeof settings.reasoning.exclude !== "boolean") {
618
+ errors.push("reasoning.exclude must be a boolean");
619
+ }
620
+ }
621
+ }
507
622
  return errors;
508
623
  }
@@ -143,6 +143,23 @@ describe('LLM Config', () => {
143
143
  };
144
144
  expect((0, config_1.validateLLMSettings)(validGeminiSettings)).toEqual([]);
145
145
  });
146
+ it('should validate reasoning settings', () => {
147
+ // Invalid reasoning object
148
+ expect((0, config_1.validateLLMSettings)({ reasoning: 'invalid' })).toContain('reasoning must be an object');
149
+ // Invalid enabled value
150
+ expect((0, config_1.validateLLMSettings)({ reasoning: { enabled: 'yes' } })).toContain('reasoning.enabled must be a boolean');
151
+ // Invalid effort value
152
+ expect((0, config_1.validateLLMSettings)({ reasoning: { effort: 'maximum' } })).toContain("reasoning.effort must be 'high', 'medium', or 'low'");
153
+ expect((0, config_1.validateLLMSettings)({ reasoning: { effort: 'high' } })).toEqual([]);
154
+ // Invalid maxTokens value
155
+ expect((0, config_1.validateLLMSettings)({ reasoning: { maxTokens: -100 } })).toContain('reasoning.maxTokens must be a non-negative integer');
156
+ expect((0, config_1.validateLLMSettings)({ reasoning: { maxTokens: 1.5 } })).toContain('reasoning.maxTokens must be a non-negative integer');
157
+ expect((0, config_1.validateLLMSettings)({ reasoning: { maxTokens: 5000 } })).toEqual([]);
158
+ // Invalid exclude value
159
+ expect((0, config_1.validateLLMSettings)({ reasoning: { exclude: 'yes' } })).toContain('reasoning.exclude must be a boolean');
160
+ // Valid reasoning settings
161
+ expect((0, config_1.validateLLMSettings)({ reasoning: { enabled: true, effort: 'medium', maxTokens: 10000, exclude: false } })).toEqual([]);
162
+ });
146
163
  it('should return multiple errors for multiple invalid fields', () => {
147
164
  const invalidSettings = {
148
165
  temperature: -1,
@@ -0,0 +1,59 @@
1
+ import type { ApiProviderId } from "../types";
2
+ import type { ILLMClientAdapter } from "../clients/types";
3
+ /**
4
+ * Information about a registered adapter
5
+ */
6
+ export interface AdapterInfo {
7
+ providerId: ApiProviderId;
8
+ hasAdapter: boolean;
9
+ adapterInfo: {
10
+ name: string;
11
+ };
12
+ }
13
+ /**
14
+ * Summary of provider availability
15
+ */
16
+ export interface ProviderSummary {
17
+ totalProviders: number;
18
+ providersWithAdapters: number;
19
+ availableProviders: string[];
20
+ unavailableProviders: string[];
21
+ }
22
+ /**
23
+ * Registry for managing LLM client adapters
24
+ */
25
+ export declare class AdapterRegistry {
26
+ private clientAdapters;
27
+ private mockClientAdapter;
28
+ constructor();
29
+ /**
30
+ * Initializes adapters for all supported providers
31
+ */
32
+ private initializeAdapters;
33
+ /**
34
+ * Registers a client adapter for a specific provider
35
+ *
36
+ * @param providerId - The provider ID
37
+ * @param adapter - The client adapter implementation
38
+ */
39
+ registerAdapter(providerId: ApiProviderId, adapter: ILLMClientAdapter): void;
40
+ /**
41
+ * Gets the appropriate client adapter for a provider
42
+ *
43
+ * @param providerId - The provider ID
44
+ * @returns The client adapter to use
45
+ */
46
+ getAdapter(providerId: ApiProviderId): ILLMClientAdapter;
47
+ /**
48
+ * Gets information about registered adapters
49
+ *
50
+ * @returns Map of provider IDs to adapter info
51
+ */
52
+ getRegisteredAdapters(): Map<ApiProviderId, AdapterInfo>;
53
+ /**
54
+ * Gets a summary of available providers and their adapter status
55
+ *
56
+ * @returns Summary of provider availability
57
+ */
58
+ getProviderSummary(): ProviderSummary;
59
+ }
@@ -0,0 +1,113 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.AdapterRegistry = void 0;
4
+ const MockClientAdapter_1 = require("../clients/MockClientAdapter");
5
+ const config_1 = require("../config");
6
+ /**
7
+ * Registry for managing LLM client adapters
8
+ */
9
+ class AdapterRegistry {
10
+ constructor() {
11
+ this.clientAdapters = new Map();
12
+ this.mockClientAdapter = new MockClientAdapter_1.MockClientAdapter();
13
+ this.initializeAdapters();
14
+ }
15
+ /**
16
+ * Initializes adapters for all supported providers
17
+ */
18
+ initializeAdapters() {
19
+ let registeredCount = 0;
20
+ const successfullyRegisteredProviders = [];
21
+ for (const provider of config_1.SUPPORTED_PROVIDERS) {
22
+ const AdapterClass = config_1.ADAPTER_CONSTRUCTORS[provider.id];
23
+ if (AdapterClass) {
24
+ try {
25
+ const adapterConfig = config_1.ADAPTER_CONFIGS[provider.id];
26
+ const adapterInstance = new AdapterClass(adapterConfig);
27
+ this.registerAdapter(provider.id, adapterInstance);
28
+ registeredCount++;
29
+ successfullyRegisteredProviders.push(provider.id);
30
+ }
31
+ catch (error) {
32
+ console.error(`LLMService: Failed to instantiate adapter for provider '${provider.id}'. This provider will use the mock adapter. Error:`, error);
33
+ }
34
+ }
35
+ else {
36
+ console.warn(`LLMService: No adapter constructor found for supported provider '${provider.id}'. This provider will use the mock adapter as a fallback.`);
37
+ }
38
+ }
39
+ if (registeredCount > 0) {
40
+ console.log(`LLMService: Initialized with ${registeredCount} dynamically registered adapter(s) for: ${successfullyRegisteredProviders.join(", ")}.`);
41
+ }
42
+ else {
43
+ console.log(`LLMService: No real adapters were dynamically registered. All providers will use the mock adapter.`);
44
+ }
45
+ }
46
+ /**
47
+ * Registers a client adapter for a specific provider
48
+ *
49
+ * @param providerId - The provider ID
50
+ * @param adapter - The client adapter implementation
51
+ */
52
+ registerAdapter(providerId, adapter) {
53
+ this.clientAdapters.set(providerId, adapter);
54
+ console.log(`Registered client adapter for provider: ${providerId}`);
55
+ }
56
+ /**
57
+ * Gets the appropriate client adapter for a provider
58
+ *
59
+ * @param providerId - The provider ID
60
+ * @returns The client adapter to use
61
+ */
62
+ getAdapter(providerId) {
63
+ // Check for registered real adapters first
64
+ const registeredAdapter = this.clientAdapters.get(providerId);
65
+ if (registeredAdapter) {
66
+ console.log(`Using registered adapter for provider: ${providerId}`);
67
+ return registeredAdapter;
68
+ }
69
+ // Fall back to mock adapter for unsupported providers
70
+ console.log(`No real adapter found for ${providerId}, using mock adapter`);
71
+ return this.mockClientAdapter;
72
+ }
73
+ /**
74
+ * Gets information about registered adapters
75
+ *
76
+ * @returns Map of provider IDs to adapter info
77
+ */
78
+ getRegisteredAdapters() {
79
+ const adapterInfo = new Map();
80
+ for (const [providerId, adapter] of this.clientAdapters.entries()) {
81
+ adapterInfo.set(providerId, {
82
+ providerId,
83
+ hasAdapter: true,
84
+ adapterInfo: adapter.getAdapterInfo?.() || { name: "Unknown Adapter" },
85
+ });
86
+ }
87
+ return adapterInfo;
88
+ }
89
+ /**
90
+ * Gets a summary of available providers and their adapter status
91
+ *
92
+ * @returns Summary of provider availability
93
+ */
94
+ getProviderSummary() {
95
+ const availableProviders = [];
96
+ const unavailableProviders = [];
97
+ for (const provider of config_1.SUPPORTED_PROVIDERS) {
98
+ if (this.clientAdapters.has(provider.id)) {
99
+ availableProviders.push(provider.id);
100
+ }
101
+ else {
102
+ unavailableProviders.push(provider.id);
103
+ }
104
+ }
105
+ return {
106
+ totalProviders: config_1.SUPPORTED_PROVIDERS.length,
107
+ providersWithAdapters: availableProviders.length,
108
+ availableProviders,
109
+ unavailableProviders,
110
+ };
111
+ }
112
+ }
113
+ exports.AdapterRegistry = AdapterRegistry;
@@ -0,0 +1 @@
1
+ export {};