genai-lite 0.4.0 → 0.4.2
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.
- package/README.md +47 -37
- package/dist/llm/LLMService.d.ts +29 -2
- package/dist/llm/LLMService.js +80 -36
- package/dist/llm/config.js +4 -4
- package/dist/llm/services/SettingsManager.js +17 -11
- package/dist/llm/types.d.ts +81 -22
- package/dist/prompting/parser.d.ts +2 -2
- package/dist/prompting/parser.js +2 -2
- package/package.json +1 -1
- package/dist/llm/LLMService.createMessages.test.d.ts +0 -4
- package/dist/llm/LLMService.createMessages.test.js +0 -364
- package/dist/llm/LLMService.original.d.ts +0 -147
- package/dist/llm/LLMService.original.js +0 -656
- package/dist/llm/LLMService.prepareMessage.test.d.ts +0 -1
- package/dist/llm/LLMService.prepareMessage.test.js +0 -303
- package/dist/llm/LLMService.presets.test.d.ts +0 -1
- package/dist/llm/LLMService.presets.test.js +0 -210
- package/dist/llm/LLMService.sendMessage.preset.test.d.ts +0 -1
- package/dist/llm/LLMService.sendMessage.preset.test.js +0 -153
- package/dist/llm/LLMService.test.d.ts +0 -1
- package/dist/llm/LLMService.test.js +0 -639
- package/dist/llm/clients/AnthropicClientAdapter.test.d.ts +0 -1
- package/dist/llm/clients/AnthropicClientAdapter.test.js +0 -273
- package/dist/llm/clients/GeminiClientAdapter.test.d.ts +0 -1
- package/dist/llm/clients/GeminiClientAdapter.test.js +0 -405
- package/dist/llm/clients/LlamaCppClientAdapter.test.d.ts +0 -1
- package/dist/llm/clients/LlamaCppClientAdapter.test.js +0 -447
- package/dist/llm/clients/LlamaCppServerClient.test.d.ts +0 -1
- package/dist/llm/clients/LlamaCppServerClient.test.js +0 -294
- package/dist/llm/clients/MockClientAdapter.test.d.ts +0 -1
- package/dist/llm/clients/MockClientAdapter.test.js +0 -250
- package/dist/llm/clients/OpenAIClientAdapter.test.d.ts +0 -1
- package/dist/llm/clients/OpenAIClientAdapter.test.js +0 -258
- package/dist/llm/clients/adapterErrorUtils.test.d.ts +0 -1
- package/dist/llm/clients/adapterErrorUtils.test.js +0 -123
- package/dist/llm/config.test.d.ts +0 -1
- package/dist/llm/config.test.js +0 -176
- package/dist/llm/services/AdapterRegistry.test.d.ts +0 -1
- package/dist/llm/services/AdapterRegistry.test.js +0 -239
- package/dist/llm/services/ModelResolver.test.d.ts +0 -1
- package/dist/llm/services/ModelResolver.test.js +0 -179
- package/dist/llm/services/PresetManager.test.d.ts +0 -1
- package/dist/llm/services/PresetManager.test.js +0 -210
- package/dist/llm/services/RequestValidator.test.d.ts +0 -1
- package/dist/llm/services/RequestValidator.test.js +0 -159
- package/dist/llm/services/SettingsManager.test.d.ts +0 -1
- package/dist/llm/services/SettingsManager.test.js +0 -266
- package/dist/prompting/builder.d.ts +0 -38
- package/dist/prompting/builder.js +0 -63
- package/dist/prompting/builder.test.d.ts +0 -4
- package/dist/prompting/builder.test.js +0 -109
- package/dist/prompting/content.test.d.ts +0 -4
- package/dist/prompting/content.test.js +0 -212
- package/dist/prompting/parser.test.d.ts +0 -4
- package/dist/prompting/parser.test.js +0 -464
- package/dist/prompting/template.test.d.ts +0 -1
- package/dist/prompting/template.test.js +0 -250
- package/dist/providers/fromEnvironment.test.d.ts +0 -1
- package/dist/providers/fromEnvironment.test.js +0 -59
|
@@ -1,258 +0,0 @@
|
|
|
1
|
-
"use strict";
|
|
2
|
-
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
3
|
-
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
4
|
-
};
|
|
5
|
-
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
|
-
const openai_1 = __importDefault(require("openai"));
|
|
7
|
-
const OpenAIClientAdapter_1 = require("./OpenAIClientAdapter");
|
|
8
|
-
const types_1 = require("./types");
|
|
9
|
-
// Mock the entire 'openai' module
|
|
10
|
-
jest.mock('openai');
|
|
11
|
-
// Cast the mocked module to allow setting up mock implementations
|
|
12
|
-
const MockOpenAI = openai_1.default;
|
|
13
|
-
describe('OpenAIClientAdapter', () => {
|
|
14
|
-
let adapter;
|
|
15
|
-
let mockCreate;
|
|
16
|
-
let basicRequest;
|
|
17
|
-
beforeEach(() => {
|
|
18
|
-
// Reset mocks before each test
|
|
19
|
-
MockOpenAI.mockClear();
|
|
20
|
-
mockCreate = jest.fn();
|
|
21
|
-
// Mock the chat.completions.create method
|
|
22
|
-
MockOpenAI.prototype.chat = {
|
|
23
|
-
completions: {
|
|
24
|
-
create: mockCreate,
|
|
25
|
-
},
|
|
26
|
-
};
|
|
27
|
-
adapter = new OpenAIClientAdapter_1.OpenAIClientAdapter();
|
|
28
|
-
basicRequest = {
|
|
29
|
-
providerId: 'openai',
|
|
30
|
-
modelId: 'gpt-4.1',
|
|
31
|
-
messages: [{ role: 'user', content: 'Hello' }],
|
|
32
|
-
settings: {
|
|
33
|
-
temperature: 0.7,
|
|
34
|
-
maxTokens: 100,
|
|
35
|
-
topP: 1,
|
|
36
|
-
frequencyPenalty: 0,
|
|
37
|
-
presencePenalty: 0,
|
|
38
|
-
stopSequences: [],
|
|
39
|
-
user: 'test-user',
|
|
40
|
-
geminiSafetySettings: [],
|
|
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
|
-
}
|
|
52
|
-
}
|
|
53
|
-
};
|
|
54
|
-
});
|
|
55
|
-
describe('sendMessage', () => {
|
|
56
|
-
it('should format the request correctly and call the OpenAI API', async () => {
|
|
57
|
-
// Setup mock response
|
|
58
|
-
mockCreate.mockResolvedValueOnce({
|
|
59
|
-
id: 'chatcmpl-123',
|
|
60
|
-
object: 'chat.completion',
|
|
61
|
-
created: 1234567890,
|
|
62
|
-
model: 'gpt-4.1',
|
|
63
|
-
choices: [{
|
|
64
|
-
index: 0,
|
|
65
|
-
message: {
|
|
66
|
-
role: 'assistant',
|
|
67
|
-
content: 'Hello! How can I help you today?'
|
|
68
|
-
},
|
|
69
|
-
finish_reason: 'stop'
|
|
70
|
-
}],
|
|
71
|
-
usage: {
|
|
72
|
-
prompt_tokens: 10,
|
|
73
|
-
completion_tokens: 20,
|
|
74
|
-
total_tokens: 30
|
|
75
|
-
}
|
|
76
|
-
});
|
|
77
|
-
const response = await adapter.sendMessage(basicRequest, 'test-api-key');
|
|
78
|
-
// Verify OpenAI was instantiated with the API key
|
|
79
|
-
expect(MockOpenAI).toHaveBeenCalledWith({
|
|
80
|
-
apiKey: 'test-api-key',
|
|
81
|
-
baseURL: undefined
|
|
82
|
-
});
|
|
83
|
-
// Verify the create method was called with correct parameters
|
|
84
|
-
expect(mockCreate).toHaveBeenCalledWith({
|
|
85
|
-
model: 'gpt-4.1',
|
|
86
|
-
messages: [{ role: 'user', content: 'Hello' }],
|
|
87
|
-
temperature: 0.7,
|
|
88
|
-
max_completion_tokens: 100,
|
|
89
|
-
top_p: 1,
|
|
90
|
-
user: 'test-user'
|
|
91
|
-
});
|
|
92
|
-
// Verify the response
|
|
93
|
-
expect(response.object).toBe('chat.completion');
|
|
94
|
-
const successResponse = response;
|
|
95
|
-
expect(successResponse.id).toBe('chatcmpl-123');
|
|
96
|
-
expect(successResponse.provider).toBe('openai');
|
|
97
|
-
expect(successResponse.model).toBe('gpt-4.1');
|
|
98
|
-
expect(successResponse.choices[0].message.content).toBe('Hello! How can I help you today?');
|
|
99
|
-
expect(successResponse.usage?.total_tokens).toBe(30);
|
|
100
|
-
});
|
|
101
|
-
it('should handle system messages correctly', async () => {
|
|
102
|
-
basicRequest.messages = [
|
|
103
|
-
{ role: 'system', content: 'You are a helpful assistant.' },
|
|
104
|
-
{ role: 'user', content: 'Hello' }
|
|
105
|
-
];
|
|
106
|
-
mockCreate.mockResolvedValueOnce({
|
|
107
|
-
id: 'chatcmpl-123',
|
|
108
|
-
object: 'chat.completion',
|
|
109
|
-
created: 1234567890,
|
|
110
|
-
model: 'gpt-4.1',
|
|
111
|
-
choices: [{
|
|
112
|
-
index: 0,
|
|
113
|
-
message: { role: 'assistant', content: 'Hello!' },
|
|
114
|
-
finish_reason: 'stop'
|
|
115
|
-
}]
|
|
116
|
-
});
|
|
117
|
-
await adapter.sendMessage(basicRequest, 'test-api-key');
|
|
118
|
-
expect(mockCreate).toHaveBeenCalledWith(expect.objectContaining({
|
|
119
|
-
messages: [
|
|
120
|
-
{ role: 'system', content: 'You are a helpful assistant.' },
|
|
121
|
-
{ role: 'user', content: 'Hello' }
|
|
122
|
-
]
|
|
123
|
-
}));
|
|
124
|
-
});
|
|
125
|
-
it('should handle stop sequences correctly', async () => {
|
|
126
|
-
basicRequest.settings.stopSequences = ['END', 'STOP'];
|
|
127
|
-
mockCreate.mockResolvedValueOnce({
|
|
128
|
-
id: 'chatcmpl-123',
|
|
129
|
-
object: 'chat.completion',
|
|
130
|
-
created: 1234567890,
|
|
131
|
-
model: 'gpt-4.1',
|
|
132
|
-
choices: [{
|
|
133
|
-
index: 0,
|
|
134
|
-
message: { role: 'assistant', content: 'Response' },
|
|
135
|
-
finish_reason: 'stop'
|
|
136
|
-
}]
|
|
137
|
-
});
|
|
138
|
-
await adapter.sendMessage(basicRequest, 'test-api-key');
|
|
139
|
-
expect(mockCreate).toHaveBeenCalledWith(expect.objectContaining({
|
|
140
|
-
stop: ['END', 'STOP']
|
|
141
|
-
}));
|
|
142
|
-
});
|
|
143
|
-
it('should use custom baseURL when provided', async () => {
|
|
144
|
-
const customAdapter = new OpenAIClientAdapter_1.OpenAIClientAdapter({ baseURL: 'https://custom.api.com' });
|
|
145
|
-
mockCreate.mockResolvedValueOnce({
|
|
146
|
-
id: 'chatcmpl-123',
|
|
147
|
-
object: 'chat.completion',
|
|
148
|
-
created: 1234567890,
|
|
149
|
-
model: 'gpt-4.1',
|
|
150
|
-
choices: [{
|
|
151
|
-
index: 0,
|
|
152
|
-
message: { role: 'assistant', content: 'Response' },
|
|
153
|
-
finish_reason: 'stop'
|
|
154
|
-
}]
|
|
155
|
-
});
|
|
156
|
-
await customAdapter.sendMessage(basicRequest, 'test-api-key');
|
|
157
|
-
expect(MockOpenAI).toHaveBeenCalledWith({
|
|
158
|
-
apiKey: 'test-api-key',
|
|
159
|
-
baseURL: 'https://custom.api.com'
|
|
160
|
-
});
|
|
161
|
-
});
|
|
162
|
-
describe('error handling', () => {
|
|
163
|
-
it('should handle authentication errors (401)', async () => {
|
|
164
|
-
const apiError = new Error('Invalid API key');
|
|
165
|
-
apiError.status = 401;
|
|
166
|
-
mockCreate.mockRejectedValueOnce(apiError);
|
|
167
|
-
const response = await adapter.sendMessage(basicRequest, 'invalid-key');
|
|
168
|
-
expect(response.object).toBe('error');
|
|
169
|
-
const errorResponse = response;
|
|
170
|
-
expect(errorResponse.error.code).toBe(types_1.ADAPTER_ERROR_CODES.INVALID_API_KEY);
|
|
171
|
-
expect(errorResponse.error.type).toBe('authentication_error');
|
|
172
|
-
expect(errorResponse.error.message).toContain('Invalid API key');
|
|
173
|
-
});
|
|
174
|
-
it('should handle rate limit errors (429)', async () => {
|
|
175
|
-
const apiError = new Error('Rate limit exceeded');
|
|
176
|
-
apiError.status = 429;
|
|
177
|
-
mockCreate.mockRejectedValueOnce(apiError);
|
|
178
|
-
const response = await adapter.sendMessage(basicRequest, 'test-key');
|
|
179
|
-
const errorResponse = response;
|
|
180
|
-
expect(errorResponse.error.code).toBe(types_1.ADAPTER_ERROR_CODES.RATE_LIMIT_EXCEEDED);
|
|
181
|
-
expect(errorResponse.error.type).toBe('rate_limit_error');
|
|
182
|
-
});
|
|
183
|
-
it('should handle insufficient quota errors (429 with specific message)', async () => {
|
|
184
|
-
const apiError = new Error('You exceeded your current quota, please check your plan and billing details');
|
|
185
|
-
apiError.status = 429;
|
|
186
|
-
mockCreate.mockRejectedValueOnce(apiError);
|
|
187
|
-
const response = await adapter.sendMessage(basicRequest, 'test-key');
|
|
188
|
-
const errorResponse = response;
|
|
189
|
-
// Without special handling for quota messages, this is just a rate limit error
|
|
190
|
-
expect(errorResponse.error.code).toBe(types_1.ADAPTER_ERROR_CODES.RATE_LIMIT_EXCEEDED);
|
|
191
|
-
expect(errorResponse.error.type).toBe('rate_limit_error');
|
|
192
|
-
});
|
|
193
|
-
it('should handle context length errors (400)', async () => {
|
|
194
|
-
const apiError = new Error("This model's maximum context length is 4096 tokens");
|
|
195
|
-
apiError.status = 400;
|
|
196
|
-
// Mock it as an OpenAI APIError
|
|
197
|
-
Object.setPrototypeOf(apiError, openai_1.default.APIError.prototype);
|
|
198
|
-
mockCreate.mockRejectedValueOnce(apiError);
|
|
199
|
-
const response = await adapter.sendMessage(basicRequest, 'test-key');
|
|
200
|
-
const errorResponse = response;
|
|
201
|
-
expect(errorResponse.error.code).toBe(types_1.ADAPTER_ERROR_CODES.CONTEXT_LENGTH_EXCEEDED);
|
|
202
|
-
expect(errorResponse.error.type).toBe('invalid_request_error');
|
|
203
|
-
});
|
|
204
|
-
it('should handle model not found errors (404)', async () => {
|
|
205
|
-
const apiError = new Error('The model does not exist');
|
|
206
|
-
apiError.status = 404;
|
|
207
|
-
mockCreate.mockRejectedValueOnce(apiError);
|
|
208
|
-
const response = await adapter.sendMessage(basicRequest, 'test-key');
|
|
209
|
-
const errorResponse = response;
|
|
210
|
-
expect(errorResponse.error.code).toBe(types_1.ADAPTER_ERROR_CODES.MODEL_NOT_FOUND);
|
|
211
|
-
expect(errorResponse.error.type).toBe('invalid_request_error');
|
|
212
|
-
});
|
|
213
|
-
it('should handle server errors (500)', async () => {
|
|
214
|
-
const apiError = new Error('Internal server error');
|
|
215
|
-
apiError.status = 500;
|
|
216
|
-
mockCreate.mockRejectedValueOnce(apiError);
|
|
217
|
-
const response = await adapter.sendMessage(basicRequest, 'test-key');
|
|
218
|
-
const errorResponse = response;
|
|
219
|
-
expect(errorResponse.error.code).toBe(types_1.ADAPTER_ERROR_CODES.PROVIDER_ERROR);
|
|
220
|
-
expect(errorResponse.error.type).toBe('server_error');
|
|
221
|
-
});
|
|
222
|
-
it('should handle network errors', async () => {
|
|
223
|
-
const networkError = new Error('Network error');
|
|
224
|
-
networkError.code = 'ECONNREFUSED';
|
|
225
|
-
mockCreate.mockRejectedValueOnce(networkError);
|
|
226
|
-
const response = await adapter.sendMessage(basicRequest, 'test-key');
|
|
227
|
-
const errorResponse = response;
|
|
228
|
-
expect(errorResponse.error.code).toBe(types_1.ADAPTER_ERROR_CODES.NETWORK_ERROR);
|
|
229
|
-
expect(errorResponse.error.type).toBe('connection_error');
|
|
230
|
-
});
|
|
231
|
-
it('should handle unknown errors', async () => {
|
|
232
|
-
mockCreate.mockRejectedValueOnce(new Error('Unknown error'));
|
|
233
|
-
const response = await adapter.sendMessage(basicRequest, 'test-key');
|
|
234
|
-
const errorResponse = response;
|
|
235
|
-
expect(errorResponse.error.code).toBe(types_1.ADAPTER_ERROR_CODES.UNKNOWN_ERROR);
|
|
236
|
-
expect(errorResponse.error.message).toContain('Unknown error');
|
|
237
|
-
});
|
|
238
|
-
});
|
|
239
|
-
});
|
|
240
|
-
describe('validateApiKey', () => {
|
|
241
|
-
it('should validate API key format', () => {
|
|
242
|
-
expect(adapter.validateApiKey('sk-test123456789012345678')).toBe(true);
|
|
243
|
-
expect(adapter.validateApiKey('sk-proj-test123456789012')).toBe(true);
|
|
244
|
-
expect(adapter.validateApiKey('invalid')).toBe(false);
|
|
245
|
-
expect(adapter.validateApiKey('')).toBe(false);
|
|
246
|
-
expect(adapter.validateApiKey('sk-short')).toBe(false); // Too short
|
|
247
|
-
});
|
|
248
|
-
});
|
|
249
|
-
describe('getAdapterInfo', () => {
|
|
250
|
-
it('should return correct adapter information', () => {
|
|
251
|
-
const info = adapter.getAdapterInfo();
|
|
252
|
-
expect(info.providerId).toBe('openai');
|
|
253
|
-
expect(info.name).toBe('OpenAI Client Adapter');
|
|
254
|
-
expect(info.version).toBeDefined();
|
|
255
|
-
// supportedModels is not part of the interface
|
|
256
|
-
});
|
|
257
|
-
});
|
|
258
|
-
});
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
export {};
|
|
@@ -1,123 +0,0 @@
|
|
|
1
|
-
"use strict";
|
|
2
|
-
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
const adapterErrorUtils_1 = require("./adapterErrorUtils");
|
|
4
|
-
const types_1 = require("./types");
|
|
5
|
-
describe('adapterErrorUtils', () => {
|
|
6
|
-
describe('getCommonMappedErrorDetails', () => {
|
|
7
|
-
it('should map 400 status to provider error', () => {
|
|
8
|
-
const error = { status: 400, message: 'Bad request' };
|
|
9
|
-
const result = (0, adapterErrorUtils_1.getCommonMappedErrorDetails)(error);
|
|
10
|
-
expect(result.errorCode).toBe(types_1.ADAPTER_ERROR_CODES.PROVIDER_ERROR);
|
|
11
|
-
expect(result.errorType).toBe('invalid_request_error');
|
|
12
|
-
expect(result.errorMessage).toBe('Bad request');
|
|
13
|
-
expect(result.status).toBe(400);
|
|
14
|
-
});
|
|
15
|
-
it('should map 401 status to invalid API key', () => {
|
|
16
|
-
const error = { status: 401, message: 'Unauthorized' };
|
|
17
|
-
const result = (0, adapterErrorUtils_1.getCommonMappedErrorDetails)(error);
|
|
18
|
-
expect(result.errorCode).toBe(types_1.ADAPTER_ERROR_CODES.INVALID_API_KEY);
|
|
19
|
-
expect(result.errorType).toBe('authentication_error');
|
|
20
|
-
expect(result.errorMessage).toBe('Unauthorized');
|
|
21
|
-
expect(result.status).toBe(401);
|
|
22
|
-
});
|
|
23
|
-
it('should map 402 status to insufficient credits', () => {
|
|
24
|
-
const error = { status: 402, message: 'Payment required' };
|
|
25
|
-
const result = (0, adapterErrorUtils_1.getCommonMappedErrorDetails)(error);
|
|
26
|
-
expect(result.errorCode).toBe(types_1.ADAPTER_ERROR_CODES.INSUFFICIENT_CREDITS);
|
|
27
|
-
expect(result.errorType).toBe('rate_limit_error');
|
|
28
|
-
expect(result.errorMessage).toBe('Payment required');
|
|
29
|
-
expect(result.status).toBe(402);
|
|
30
|
-
});
|
|
31
|
-
it('should map 404 status to model not found', () => {
|
|
32
|
-
const error = { status: 404, message: 'Not found' };
|
|
33
|
-
const result = (0, adapterErrorUtils_1.getCommonMappedErrorDetails)(error);
|
|
34
|
-
expect(result.errorCode).toBe(types_1.ADAPTER_ERROR_CODES.MODEL_NOT_FOUND);
|
|
35
|
-
expect(result.errorType).toBe('invalid_request_error');
|
|
36
|
-
expect(result.errorMessage).toBe('Not found');
|
|
37
|
-
expect(result.status).toBe(404);
|
|
38
|
-
});
|
|
39
|
-
it('should map 429 status to rate limit exceeded', () => {
|
|
40
|
-
const error = { status: 429, message: 'Too many requests' };
|
|
41
|
-
const result = (0, adapterErrorUtils_1.getCommonMappedErrorDetails)(error);
|
|
42
|
-
expect(result.errorCode).toBe(types_1.ADAPTER_ERROR_CODES.RATE_LIMIT_EXCEEDED);
|
|
43
|
-
expect(result.errorType).toBe('rate_limit_error');
|
|
44
|
-
expect(result.errorMessage).toBe('Too many requests');
|
|
45
|
-
expect(result.status).toBe(429);
|
|
46
|
-
});
|
|
47
|
-
it('should map 5xx status codes to provider error', () => {
|
|
48
|
-
const testCases = [500, 502, 503, 504];
|
|
49
|
-
testCases.forEach(status => {
|
|
50
|
-
const error = { status, message: `Server error ${status}` };
|
|
51
|
-
const result = (0, adapterErrorUtils_1.getCommonMappedErrorDetails)(error);
|
|
52
|
-
expect(result.errorCode).toBe(types_1.ADAPTER_ERROR_CODES.PROVIDER_ERROR);
|
|
53
|
-
expect(result.errorType).toBe('server_error');
|
|
54
|
-
expect(result.errorMessage).toBe(`Server error ${status}`);
|
|
55
|
-
expect(result.status).toBe(status);
|
|
56
|
-
});
|
|
57
|
-
});
|
|
58
|
-
it('should map other 4xx status codes to provider error', () => {
|
|
59
|
-
const error = { status: 403, message: 'Forbidden' };
|
|
60
|
-
const result = (0, adapterErrorUtils_1.getCommonMappedErrorDetails)(error);
|
|
61
|
-
expect(result.errorCode).toBe(types_1.ADAPTER_ERROR_CODES.PROVIDER_ERROR);
|
|
62
|
-
expect(result.errorType).toBe('invalid_request_error');
|
|
63
|
-
expect(result.errorMessage).toBe('Forbidden');
|
|
64
|
-
expect(result.status).toBe(403);
|
|
65
|
-
});
|
|
66
|
-
it('should map network errors to network error', () => {
|
|
67
|
-
const networkErrors = [
|
|
68
|
-
{ code: 'ENOTFOUND', message: 'DNS lookup failed' },
|
|
69
|
-
{ code: 'ECONNREFUSED', message: 'Connection refused' },
|
|
70
|
-
{ code: 'ETIMEDOUT', message: 'Request timed out' },
|
|
71
|
-
{ name: 'ConnectTimeoutError', message: 'Connection timeout' },
|
|
72
|
-
{ type: 'request-timeout', message: 'Request timeout' }
|
|
73
|
-
];
|
|
74
|
-
networkErrors.forEach(error => {
|
|
75
|
-
const result = (0, adapterErrorUtils_1.getCommonMappedErrorDetails)(error);
|
|
76
|
-
expect(result.errorCode).toBe(types_1.ADAPTER_ERROR_CODES.NETWORK_ERROR);
|
|
77
|
-
expect(result.errorType).toBe('connection_error');
|
|
78
|
-
expect(result.errorMessage).toBe(error.message);
|
|
79
|
-
expect(result.status).toBeUndefined();
|
|
80
|
-
});
|
|
81
|
-
});
|
|
82
|
-
it('should handle generic Error instances', () => {
|
|
83
|
-
const error = new Error('Something went wrong');
|
|
84
|
-
const result = (0, adapterErrorUtils_1.getCommonMappedErrorDetails)(error);
|
|
85
|
-
expect(result.errorCode).toBe(types_1.ADAPTER_ERROR_CODES.UNKNOWN_ERROR);
|
|
86
|
-
expect(result.errorType).toBe('client_error');
|
|
87
|
-
expect(result.errorMessage).toBe('Something went wrong');
|
|
88
|
-
expect(result.status).toBeUndefined();
|
|
89
|
-
});
|
|
90
|
-
it('should handle unknown error types', () => {
|
|
91
|
-
const testCases = [
|
|
92
|
-
null,
|
|
93
|
-
undefined,
|
|
94
|
-
'string error',
|
|
95
|
-
123,
|
|
96
|
-
{ random: 'object' }
|
|
97
|
-
];
|
|
98
|
-
testCases.forEach(error => {
|
|
99
|
-
const result = (0, adapterErrorUtils_1.getCommonMappedErrorDetails)(error);
|
|
100
|
-
expect(result.errorCode).toBe(types_1.ADAPTER_ERROR_CODES.UNKNOWN_ERROR);
|
|
101
|
-
expect(result.errorType).toBe('server_error');
|
|
102
|
-
expect(result.errorMessage).toBe('Unknown error occurred');
|
|
103
|
-
expect(result.status).toBeUndefined();
|
|
104
|
-
});
|
|
105
|
-
});
|
|
106
|
-
it('should use provider message override when provided', () => {
|
|
107
|
-
const error = { status: 400, message: 'Original message' };
|
|
108
|
-
const override = 'Custom error message';
|
|
109
|
-
const result = (0, adapterErrorUtils_1.getCommonMappedErrorDetails)(error, override);
|
|
110
|
-
expect(result.errorMessage).toBe(override);
|
|
111
|
-
});
|
|
112
|
-
it('should handle errors without message property', () => {
|
|
113
|
-
const error = { status: 400 };
|
|
114
|
-
const result = (0, adapterErrorUtils_1.getCommonMappedErrorDetails)(error);
|
|
115
|
-
expect(result.errorMessage).toBe('HTTP 400 error');
|
|
116
|
-
});
|
|
117
|
-
it('should handle errors with empty message', () => {
|
|
118
|
-
const error = { status: 400, message: '' };
|
|
119
|
-
const result = (0, adapterErrorUtils_1.getCommonMappedErrorDetails)(error);
|
|
120
|
-
expect(result.errorMessage).toBe('HTTP 400 error');
|
|
121
|
-
});
|
|
122
|
-
});
|
|
123
|
-
});
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
export {};
|
package/dist/llm/config.test.js
DELETED
|
@@ -1,176 +0,0 @@
|
|
|
1
|
-
"use strict";
|
|
2
|
-
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
const config_1 = require("./config");
|
|
4
|
-
describe('LLM Config', () => {
|
|
5
|
-
describe('isProviderSupported', () => {
|
|
6
|
-
it('should correctly identify supported providers', () => {
|
|
7
|
-
expect((0, config_1.isProviderSupported)('openai')).toBe(true);
|
|
8
|
-
expect((0, config_1.isProviderSupported)('anthropic')).toBe(true);
|
|
9
|
-
expect((0, config_1.isProviderSupported)('gemini')).toBe(true);
|
|
10
|
-
});
|
|
11
|
-
it('should return false for unsupported providers', () => {
|
|
12
|
-
expect((0, config_1.isProviderSupported)('unsupported-provider')).toBe(false);
|
|
13
|
-
expect((0, config_1.isProviderSupported)('')).toBe(false);
|
|
14
|
-
});
|
|
15
|
-
});
|
|
16
|
-
describe('getProviderById', () => {
|
|
17
|
-
it('should return provider info for valid providers', () => {
|
|
18
|
-
const openaiProvider = (0, config_1.getProviderById)('openai');
|
|
19
|
-
expect(openaiProvider).toBeDefined();
|
|
20
|
-
expect(openaiProvider?.id).toBe('openai');
|
|
21
|
-
expect(openaiProvider?.name).toBe('OpenAI');
|
|
22
|
-
});
|
|
23
|
-
it('should return undefined for invalid providers', () => {
|
|
24
|
-
expect((0, config_1.getProviderById)('unsupported-provider')).toBeUndefined();
|
|
25
|
-
expect((0, config_1.getProviderById)('')).toBeUndefined();
|
|
26
|
-
});
|
|
27
|
-
});
|
|
28
|
-
describe('getModelById', () => {
|
|
29
|
-
it('should return model info for valid model and provider combination', () => {
|
|
30
|
-
const model = (0, config_1.getModelById)('gpt-4.1', 'openai');
|
|
31
|
-
expect(model).toBeDefined();
|
|
32
|
-
expect(model?.id).toBe('gpt-4.1');
|
|
33
|
-
expect(model?.providerId).toBe('openai');
|
|
34
|
-
});
|
|
35
|
-
it('should return undefined for invalid model or provider', () => {
|
|
36
|
-
expect((0, config_1.getModelById)('invalid-model', 'openai')).toBeUndefined();
|
|
37
|
-
expect((0, config_1.getModelById)('gpt-4.1', 'anthropic')).toBeUndefined();
|
|
38
|
-
expect((0, config_1.getModelById)('gpt-4.1', 'invalid-provider')).toBeUndefined();
|
|
39
|
-
});
|
|
40
|
-
});
|
|
41
|
-
describe('getModelsByProvider', () => {
|
|
42
|
-
it('should return models for valid providers', () => {
|
|
43
|
-
const openaiModels = (0, config_1.getModelsByProvider)('openai');
|
|
44
|
-
expect(openaiModels.length).toBeGreaterThan(0);
|
|
45
|
-
expect(openaiModels.every(model => model.providerId === 'openai')).toBe(true);
|
|
46
|
-
});
|
|
47
|
-
it('should return empty array for invalid providers', () => {
|
|
48
|
-
expect((0, config_1.getModelsByProvider)('invalid-provider')).toEqual([]);
|
|
49
|
-
expect((0, config_1.getModelsByProvider)('')).toEqual([]);
|
|
50
|
-
});
|
|
51
|
-
});
|
|
52
|
-
describe('isModelSupported', () => {
|
|
53
|
-
it('should correctly identify supported model/provider combinations', () => {
|
|
54
|
-
expect((0, config_1.isModelSupported)('gpt-4.1', 'openai')).toBe(true);
|
|
55
|
-
expect((0, config_1.isModelSupported)('claude-sonnet-4-20250514', 'anthropic')).toBe(true);
|
|
56
|
-
expect((0, config_1.isModelSupported)('gemini-2.5-pro', 'gemini')).toBe(true);
|
|
57
|
-
});
|
|
58
|
-
it('should return false for unsupported combinations', () => {
|
|
59
|
-
expect((0, config_1.isModelSupported)('gpt-4.1', 'anthropic')).toBe(false);
|
|
60
|
-
expect((0, config_1.isModelSupported)('claude-sonnet-4-20250514', 'openai')).toBe(false);
|
|
61
|
-
expect((0, config_1.isModelSupported)('invalid-model', 'openai')).toBe(false);
|
|
62
|
-
});
|
|
63
|
-
});
|
|
64
|
-
describe('getDefaultSettingsForModel', () => {
|
|
65
|
-
it('should return default settings for valid models', () => {
|
|
66
|
-
const settings = (0, config_1.getDefaultSettingsForModel)('gpt-4.1', 'openai');
|
|
67
|
-
expect(settings).toBeDefined();
|
|
68
|
-
expect(settings.temperature).toBeDefined();
|
|
69
|
-
expect(settings.maxTokens).toBeDefined();
|
|
70
|
-
expect(settings.topP).toBeDefined();
|
|
71
|
-
});
|
|
72
|
-
it('should apply model-specific overrides', () => {
|
|
73
|
-
const gpt4Settings = (0, config_1.getDefaultSettingsForModel)('gpt-4.1', 'openai');
|
|
74
|
-
const gpt4MiniSettings = (0, config_1.getDefaultSettingsForModel)('gpt-4.1-mini', 'openai');
|
|
75
|
-
// These might have different maxTokens based on model capabilities
|
|
76
|
-
expect(gpt4Settings.maxTokens).toBeDefined();
|
|
77
|
-
expect(gpt4MiniSettings.maxTokens).toBeDefined();
|
|
78
|
-
});
|
|
79
|
-
});
|
|
80
|
-
describe('validateLLMSettings', () => {
|
|
81
|
-
it('should return empty array for valid settings', () => {
|
|
82
|
-
const validSettings = {
|
|
83
|
-
temperature: 0.7,
|
|
84
|
-
maxTokens: 1000,
|
|
85
|
-
topP: 0.9,
|
|
86
|
-
frequencyPenalty: 0.5,
|
|
87
|
-
presencePenalty: -0.5,
|
|
88
|
-
stopSequences: ['\\n', 'END'],
|
|
89
|
-
user: 'test-user'
|
|
90
|
-
};
|
|
91
|
-
expect((0, config_1.validateLLMSettings)(validSettings)).toEqual([]);
|
|
92
|
-
});
|
|
93
|
-
it('should validate temperature bounds', () => {
|
|
94
|
-
expect((0, config_1.validateLLMSettings)({ temperature: -0.1 })).toContain('temperature must be a number between 0 and 2');
|
|
95
|
-
expect((0, config_1.validateLLMSettings)({ temperature: 2.1 })).toContain('temperature must be a number between 0 and 2');
|
|
96
|
-
expect((0, config_1.validateLLMSettings)({ temperature: 'invalid' })).toContain('temperature must be a number between 0 and 2');
|
|
97
|
-
});
|
|
98
|
-
it('should validate maxTokens', () => {
|
|
99
|
-
expect((0, config_1.validateLLMSettings)({ maxTokens: 0 })).toContain('maxTokens must be an integer between 1 and 100000');
|
|
100
|
-
expect((0, config_1.validateLLMSettings)({ maxTokens: 100001 })).toContain('maxTokens must be an integer between 1 and 100000');
|
|
101
|
-
expect((0, config_1.validateLLMSettings)({ maxTokens: 1.5 })).toContain('maxTokens must be an integer between 1 and 100000');
|
|
102
|
-
});
|
|
103
|
-
it('should validate topP bounds', () => {
|
|
104
|
-
expect((0, config_1.validateLLMSettings)({ topP: -0.1 })).toContain('topP must be a number between 0 and 1');
|
|
105
|
-
expect((0, config_1.validateLLMSettings)({ topP: 1.1 })).toContain('topP must be a number between 0 and 1');
|
|
106
|
-
});
|
|
107
|
-
it('should validate frequencyPenalty bounds', () => {
|
|
108
|
-
expect((0, config_1.validateLLMSettings)({ frequencyPenalty: -2.1 })).toContain('frequencyPenalty must be a number between -2 and 2');
|
|
109
|
-
expect((0, config_1.validateLLMSettings)({ frequencyPenalty: 2.1 })).toContain('frequencyPenalty must be a number between -2 and 2');
|
|
110
|
-
});
|
|
111
|
-
it('should validate presencePenalty bounds', () => {
|
|
112
|
-
expect((0, config_1.validateLLMSettings)({ presencePenalty: -2.1 })).toContain('presencePenalty must be a number between -2 and 2');
|
|
113
|
-
expect((0, config_1.validateLLMSettings)({ presencePenalty: 2.1 })).toContain('presencePenalty must be a number between -2 and 2');
|
|
114
|
-
});
|
|
115
|
-
it('should validate stopSequences', () => {
|
|
116
|
-
expect((0, config_1.validateLLMSettings)({ stopSequences: 'invalid' })).toContain('stopSequences must be an array');
|
|
117
|
-
expect((0, config_1.validateLLMSettings)({ stopSequences: ['1', '2', '3', '4', '5'] })).toContain('stopSequences can contain at most 4 sequences');
|
|
118
|
-
expect((0, config_1.validateLLMSettings)({ stopSequences: ['valid', ''] })).toContain('stopSequences must contain only non-empty strings');
|
|
119
|
-
expect((0, config_1.validateLLMSettings)({ stopSequences: ['valid', 123] })).toContain('stopSequences must contain only non-empty strings');
|
|
120
|
-
});
|
|
121
|
-
it('should validate user field', () => {
|
|
122
|
-
expect((0, config_1.validateLLMSettings)({ user: 123 })).toContain('user must be a string');
|
|
123
|
-
});
|
|
124
|
-
it('should validate geminiSafetySettings', () => {
|
|
125
|
-
const invalidSettings = { geminiSafetySettings: 'invalid' };
|
|
126
|
-
expect((0, config_1.validateLLMSettings)(invalidSettings)).toContain('geminiSafetySettings must be an array');
|
|
127
|
-
const invalidCategory = {
|
|
128
|
-
geminiSafetySettings: [
|
|
129
|
-
{ category: 'INVALID_CATEGORY', threshold: 'BLOCK_NONE' }
|
|
130
|
-
]
|
|
131
|
-
};
|
|
132
|
-
expect((0, config_1.validateLLMSettings)(invalidCategory)).toContain('geminiSafetySettings[0].category must be a valid Gemini harm category');
|
|
133
|
-
const invalidThreshold = {
|
|
134
|
-
geminiSafetySettings: [
|
|
135
|
-
{ category: 'HARM_CATEGORY_HATE_SPEECH', threshold: 'INVALID_THRESHOLD' }
|
|
136
|
-
]
|
|
137
|
-
};
|
|
138
|
-
expect((0, config_1.validateLLMSettings)(invalidThreshold)).toContain('geminiSafetySettings[0].threshold must be a valid Gemini harm block threshold');
|
|
139
|
-
const validGeminiSettings = {
|
|
140
|
-
geminiSafetySettings: [
|
|
141
|
-
{ category: 'HARM_CATEGORY_HATE_SPEECH', threshold: 'BLOCK_NONE' }
|
|
142
|
-
]
|
|
143
|
-
};
|
|
144
|
-
expect((0, config_1.validateLLMSettings)(validGeminiSettings)).toEqual([]);
|
|
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
|
-
});
|
|
163
|
-
it('should return multiple errors for multiple invalid fields', () => {
|
|
164
|
-
const invalidSettings = {
|
|
165
|
-
temperature: -1,
|
|
166
|
-
maxTokens: 0,
|
|
167
|
-
topP: 2
|
|
168
|
-
};
|
|
169
|
-
const errors = (0, config_1.validateLLMSettings)(invalidSettings);
|
|
170
|
-
expect(errors).toHaveLength(3);
|
|
171
|
-
expect(errors).toContain('temperature must be a number between 0 and 2');
|
|
172
|
-
expect(errors).toContain('maxTokens must be an integer between 1 and 100000');
|
|
173
|
-
expect(errors).toContain('topP must be a number between 0 and 1');
|
|
174
|
-
});
|
|
175
|
-
});
|
|
176
|
-
});
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
export {};
|