llmjs2 1.1.0 → 1.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.
package/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 littlellmjs
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
package/index.js CHANGED
@@ -148,11 +148,29 @@ export async function completion(modelOrOptions, prompt, apiKey) {
148
148
 
149
149
  // Validate messages format
150
150
  for (const msg of messages) {
151
- if (!msg.role || !msg.content) {
152
- throw new Error('Each message must have "role" and "content" properties');
151
+ if (!msg.role) {
152
+ throw new Error('Each message must have a "role" property');
153
153
  }
154
- if (!['system', 'user', 'assistant'].includes(msg.role)) {
155
- throw new Error('Message role must be "system", "user", or "assistant"');
154
+
155
+ // Tool messages have role='tool' and tool_call_id instead of content
156
+ if (msg.role === 'tool') {
157
+ if (!msg.tool_call_id && !msg.name) {
158
+ throw new Error('Tool message must have "tool_call_id" and "name" properties');
159
+ }
160
+ if (msg.content !== undefined && typeof msg.content !== 'string') {
161
+ throw new Error('Tool message "content" must be a string');
162
+ }
163
+ } else {
164
+ // Non-tool messages must have content
165
+ // Assistant messages with tool_calls can have empty content
166
+ const hasContent = msg.content && msg.content.trim().length > 0;
167
+ const isAssistantWithToolCalls = msg.role === 'assistant' && msg.tool_calls && msg.tool_calls.length > 0;
168
+ if (!hasContent && !isAssistantWithToolCalls) {
169
+ throw new Error(`Message with role "${msg.role}" must have "content" property`);
170
+ }
171
+ if (!['system', 'user', 'assistant', 'tool'].includes(msg.role)) {
172
+ throw new Error(`Message role must be "system", "user", "assistant", or "tool"`);
173
+ }
156
174
  }
157
175
  }
158
176
 
package/package.json CHANGED
@@ -1,12 +1,18 @@
1
1
  {
2
2
  "name": "llmjs2",
3
- "version": "1.1.0",
3
+ "version": "1.1.1",
4
4
  "description": "Abstract layer for LLM completion supporting multiple providers",
5
5
  "main": "index.js",
6
6
  "type": "module",
7
7
  "exports": {
8
8
  ".": "./index.js"
9
9
  },
10
+ "files": [
11
+ "index.js",
12
+ "providers/",
13
+ "README.md",
14
+ "LICENSE"
15
+ ],
10
16
  "keywords": [
11
17
  "llm",
12
18
  "ai",
@@ -1,4 +1,4 @@
1
- const OLLAMA_API_URL = 'http://localhost:11434/api/chat';
1
+ const OLLAMA_API_URL = 'https://ollama.com/api/chat';
2
2
  const REQUEST_TIMEOUT = 180000; // 60 seconds
3
3
 
4
4
  /**
@@ -83,6 +83,6 @@ export async function ollamaCompletion(model, messages, apiKey, tools) {
83
83
  throw error;
84
84
  }
85
85
 
86
- throw new Error(`Ollama request failed: ${error.message}`);
86
+ throw new Error(`Ollama request failed: ${error}`);
87
87
  }
88
88
  }
package/example.js DELETED
@@ -1,298 +0,0 @@
1
- import { completion } from './index.js';
2
-
3
- /**
4
- * Real usage test program for vs code
5
- * This demonstrates actual API calls to Ollama and OpenRouter
6
- * Shows all three calling conventions including simple API with model
7
- */
8
-
9
- async function testSimpleAPI() {
10
- console.log('=== Testing Simple API (Auto-Detection) ===\n');
11
-
12
- try {
13
- const prompt = 'Explain the use of vs code in 2-3 sentences.';
14
- console.log(`Prompt: ${prompt}\n`);
15
-
16
- const result = await completion(prompt);
17
-
18
- console.log('Response:');
19
- console.log(result);
20
- console.log('\n✓ Simple API test completed successfully\n');
21
- return true;
22
- } catch (error) {
23
- console.error('✗ Simple API test failed:', error.message);
24
- return false;
25
- }
26
- }
27
-
28
- async function testSimpleAPIWithModel() {
29
- console.log('=== Testing Simple API with Model ===\n');
30
-
31
- try {
32
- const model = 'ollama/qwen3.5:397b-cloud';
33
- const prompt = 'Explain the use of vs code in 2-3 sentences.';
34
- console.log(`Model: ${model}`);
35
- console.log(`Prompt: ${prompt}\n`);
36
-
37
- const result = await completion(model, prompt);
38
-
39
- console.log('Response:');
40
- console.log(result);
41
- console.log('\n✓ Simple API with model test completed successfully\n');
42
- return true;
43
- } catch (error) {
44
- console.error('✗ Simple API with model test failed:', error.message);
45
- return false;
46
- }
47
- }
48
-
49
- async function testOllamaFunctionAPI() {
50
- console.log('=== Testing Ollama with Function-Based API ===\n');
51
-
52
- try {
53
- const prompt = 'Explain the use of vs code in 2-3 sentences.';
54
- console.log(`Prompt: ${prompt}\n`);
55
-
56
- const result = await completion('ollama/minimax-m2.5:cloud', prompt);
57
-
58
- console.log('Response:');
59
- console.log(result);
60
- console.log('\n✓ Ollama function-based API test completed successfully\n');
61
- return true;
62
- } catch (error) {
63
- console.error('✗ Ollama function-based API test failed:', error.message);
64
- return false;
65
- }
66
- }
67
-
68
- async function testOllamaObjectAPI() {
69
- console.log('=== Testing Ollama with Object-Based API ===\n');
70
-
71
- try {
72
- const result = await completion({
73
- model: 'ollama/minimax-m2.5:cloud',
74
- messages: [
75
- { role: 'system', content: 'You are a helpful AI assistant.' },
76
- { role: 'user', content: 'Explain the use of vs code in 2-3 sentences.' }
77
- ]
78
- });
79
-
80
- console.log('Response:');
81
- console.log(result);
82
- console.log('\n✓ Ollama object-based API test completed successfully\n');
83
- return true;
84
- } catch (error) {
85
- console.error('✗ Ollama object-based API test failed:', error.message);
86
- return false;
87
- }
88
- }
89
-
90
- async function testOllamaWithTools() {
91
- console.log('=== Testing Ollama with Tools ===\n');
92
-
93
- try {
94
- const result = await completion({
95
- model: 'ollama/minimax-m2.5:cloud',
96
- messages: [
97
- { role: 'user', content: 'What is the weather like in Paris?' }
98
- ],
99
- tools: [
100
- {
101
- type: 'function',
102
- function: {
103
- name: 'get_weather',
104
- description: 'Get the current weather in a given location',
105
- parameters: {
106
- type: 'object',
107
- properties: {
108
- location: {
109
- type: 'string',
110
- description: 'The city and state, e.g. San Francisco, CA'
111
- },
112
- unit: {
113
- type: 'string',
114
- enum: ['celsius', 'fahrenheit'],
115
- description: 'The temperature unit to use'
116
- }
117
- },
118
- required: ['location']
119
- }
120
- }
121
- }
122
- ]
123
- });
124
-
125
- console.log('Response:');
126
- console.log(JSON.stringify(result, null, 2));
127
- console.log('\n✓ Ollama tools test completed successfully\n');
128
- return true;
129
- } catch (error) {
130
- console.error('✗ Ollama tools test failed:', error.message);
131
- return false;
132
- }
133
- }
134
-
135
- async function testOpenRouterFunctionAPI() {
136
- console.log('=== Testing OpenRouter with Function-Based API ===\n');
137
-
138
- try {
139
- const prompt = 'What is the capital of France? Answer in one sentence.';
140
- console.log(`Prompt: ${prompt}\n`);
141
-
142
- const result = await completion('openrouter/openrouter/free', prompt);
143
-
144
- console.log('Response:');
145
- console.log(result);
146
- console.log('\n✓ OpenRouter function-based API test completed successfully\n');
147
- return true;
148
- } catch (error) {
149
- console.error('✗ OpenRouter function-based API test failed:', error.message);
150
- return false;
151
- }
152
- }
153
-
154
- async function testOpenRouterObjectAPI() {
155
- console.log('=== Testing OpenRouter with Object-Based API ===\n');
156
-
157
- try {
158
- const result = await completion({
159
- model: 'openrouter/openrouter/free',
160
- messages: [
161
- { role: 'system', content: 'You are a helpful AI assistant.' },
162
- { role: 'user', content: 'What is the capital of France? Answer in one sentence.' }
163
- ]
164
- });
165
-
166
- console.log('Response:');
167
- console.log(result);
168
- console.log('\n✓ OpenRouter object-based API test completed successfully\n');
169
- return true;
170
- } catch (error) {
171
- console.error('✗ OpenRouter object-based API test failed:', error.message);
172
- return false;
173
- }
174
- }
175
-
176
- async function testOpenRouterWithTools() {
177
- console.log('=== Testing OpenRouter with Tools ===\n');
178
-
179
- try {
180
- const result = await completion({
181
- model: 'openrouter/openrouter/free',
182
- messages: [
183
- { role: 'user', content: 'What is the weather like in Paris?' }
184
- ],
185
- tools: [
186
- {
187
- type: 'function',
188
- function: {
189
- name: 'get_weather',
190
- description: 'Get the current weather in a given location',
191
- parameters: {
192
- type: 'object',
193
- properties: {
194
- location: {
195
- type: 'string',
196
- description: 'The city and state, e.g. San Francisco, CA'
197
- },
198
- unit: {
199
- type: 'string',
200
- enum: ['celsius', 'fahrenheit'],
201
- description: 'The temperature unit to use'
202
- }
203
- },
204
- required: ['location']
205
- }
206
- }
207
- }
208
- ]
209
- });
210
-
211
- console.log('Response:');
212
- console.log(JSON.stringify(result, null, 2));
213
- console.log('\n✓ OpenRouter tools test completed successfully\n');
214
- return true;
215
- } catch (error) {
216
- console.error('✗ OpenRouter tools test failed:', error.message);
217
- return false;
218
- }
219
- }
220
-
221
- async function main() {
222
- console.log('vs code Real Usage Test Program');
223
- console.log('==============================\n');
224
-
225
- // Check for API keys
226
- const hasOllamaKey = !!process.env.OLLAMA_API_KEY;
227
- const hasOpenRouterKey = !!process.env.OPEN_ROUTER_API_KEY;
228
-
229
- console.log('API Key Status:');
230
- console.log(` Ollama: ${hasOllamaKey ? '✓ Set' : '✗ Not set'}`);
231
- console.log(` OpenRouter: ${hasOpenRouterKey ? '✓ Set' : '✗ Not set'}\n`);
232
-
233
- if (!hasOllamaKey && !hasOpenRouterKey) {
234
- console.log('⚠ No API keys found. Please set environment variables:');
235
- console.log(' export OLLAMA_API_KEY=your-ollama-api-key');
236
- console.log(' export OPEN_ROUTER_API_KEY=your-openrouter-api-key\n');
237
- console.log('Or modify this script to pass API keys directly.\n');
238
- }
239
-
240
- const results = {
241
- simpleAPI: false,
242
- simpleAPIWithModel: false,
243
- ollamaFunction: false,
244
- ollamaObject: false,
245
- ollamaTools: false,
246
- openrouterFunction: false,
247
- openrouterObject: false,
248
- openrouterTools: false
249
- };
250
-
251
- // Test simple API if any key is available
252
- if (hasOllamaKey || hasOpenRouterKey) {
253
- results.simpleAPI = await testSimpleAPI();
254
- results.simpleAPIWithModel = await testSimpleAPIWithModel();
255
- } else {
256
- console.log('=== Skipping Simple API tests (no API key) ===\n');
257
- }
258
-
259
- // Test Ollama if key is available
260
- if (hasOllamaKey) {
261
- results.ollamaFunction = await testOllamaFunctionAPI();
262
- results.ollamaObject = await testOllamaObjectAPI();
263
- results.ollamaTools = await testOllamaWithTools();
264
- } else {
265
- console.log('=== Skipping Ollama tests (no API key) ===\n');
266
- }
267
-
268
- // Test OpenRouter if key is available
269
- if (hasOpenRouterKey) {
270
- results.openrouterFunction = await testOpenRouterFunctionAPI();
271
- results.openrouterObject = await testOpenRouterObjectAPI();
272
- results.openrouterTools = await testOpenRouterWithTools();
273
- } else {
274
- console.log('=== Skipping OpenRouter tests (no API key) ===\n');
275
- }
276
-
277
- // Summary
278
- console.log('==============================');
279
- console.log('Test Summary:');
280
- console.log(` Simple API: ${results.simpleAPI ? '✓ Passed' : '✗ Failed/Skipped'}`);
281
- console.log(` Simple API with Model: ${results.simpleAPIWithModel ? '✓ Passed' : '✗ Failed/Skipped'}`);
282
- console.log(` Ollama Function API: ${results.ollamaFunction ? '✓ Passed' : '✗ Failed/Skipped'}`);
283
- console.log(` Ollama Object API: ${results.ollamaObject ? '✓ Passed' : '✗ Failed/Skipped'}`);
284
- console.log(` Ollama Tools: ${results.ollamaTools ? '✓ Passed' : '✗ Failed/Skipped'}`);
285
- console.log(` OpenRouter Function API: ${results.openrouterFunction ? '✓ Passed' : '✗ Failed/Skipped'}`);
286
- console.log(` OpenRouter Object API: ${results.openrouterObject ? '✓ Passed' : '✗ Failed/Skipped'}`);
287
- console.log(` OpenRouter Tools: ${results.openrouterTools ? '✓ Passed' : '✗ Failed/Skipped'}`);
288
- console.log('==============================\n');
289
-
290
- if (results.simpleAPI || results.simpleAPIWithModel || results.ollamaFunction || results.ollamaObject || results.ollamaTools ||
291
- results.openrouterFunction || results.openrouterObject || results.openrouterTools) {
292
- console.log('✓ At least one test passed!');
293
- } else {
294
- console.log('✗ No tests passed. Check your API keys and try again.');
295
- }
296
- }
297
-
298
- main().catch(console.error);
package/test.js DELETED
@@ -1,296 +0,0 @@
1
- import { completion } from './index.js';
2
-
3
- // Test 1: Verify completion function is exported
4
- console.log('Test 1: Checking if completion function is exported...');
5
- if (typeof completion === 'function') {
6
- console.log('✓ completion function is properly exported');
7
- } else {
8
- console.error('✗ completion is not a function');
9
- process.exit(1);
10
- }
11
-
12
- // Test 2: Verify error handling for empty prompt (simple API)
13
- console.log('\nTest 2: Testing error handling for empty prompt (simple API)...');
14
- try {
15
- await completion('');
16
- console.error('✗ Should have thrown an error for empty prompt');
17
- process.exit(1);
18
- } catch (error) {
19
- if (error.message.includes('Prompt parameter cannot be empty')) {
20
- console.log('✓ Properly throws error for empty prompt');
21
- } else {
22
- console.error('✗ Wrong error message:', error.message);
23
- process.exit(1);
24
- }
25
- }
26
-
27
- // Test 3: Verify error handling for missing API keys (simple API)
28
- console.log('\nTest 3: Testing error handling for missing API keys (simple API)...');
29
- try {
30
- delete process.env.OLLAMA_API_KEY;
31
- delete process.env.OPEN_ROUTER_API_KEY;
32
- await completion('test prompt');
33
- console.error('✗ Should have thrown an error for missing API keys');
34
- process.exit(1);
35
- } catch (error) {
36
- if (error.message.includes('No API key found')) {
37
- console.log('✓ Properly throws error for missing API keys');
38
- } else {
39
- console.error('✗ Wrong error message:', error.message);
40
- process.exit(1);
41
- }
42
- }
43
-
44
- // Test 4: Verify error handling for empty model (simple API with model)
45
- console.log('\nTest 4: Testing error handling for empty model (simple API with model)...');
46
- try {
47
- delete process.env.OLLAMA_API_KEY;
48
- delete process.env.OPEN_ROUTER_API_KEY;
49
- await completion('', 'test prompt');
50
- console.error('✗ Should have thrown an error for empty model');
51
- process.exit(1);
52
- } catch (error) {
53
- if (error.message.includes('Model must be in format')) {
54
- console.log('✓ Properly throws error for empty model');
55
- } else {
56
- console.error('✗ Wrong error message:', error.message);
57
- process.exit(1);
58
- }
59
- }
60
-
61
- // Test 5: Verify error handling for missing model (function API)
62
- console.log('\nTest 5: Testing error handling for missing model (function API)...');
63
- try {
64
- await completion();
65
- console.error('✗ Should have thrown an error for missing model');
66
- process.exit(1);
67
- } catch (error) {
68
- if (error.message.includes('Model parameter is required')) {
69
- console.log('✓ Properly throws error for missing model');
70
- } else {
71
- console.error('✗ Wrong error message:', error.message);
72
- process.exit(1);
73
- }
74
- }
75
-
76
- // Test 6: Verify error handling for missing prompt (function API)
77
- console.log('\nTest 6: Testing error handling for missing prompt (function API)...');
78
- try {
79
- await completion('ollama/minimax-m2.5:cloud');
80
- console.error('✗ Should have thrown an error for missing prompt');
81
- process.exit(1);
82
- } catch (error) {
83
- if (error.message.includes('Prompt parameter is required')) {
84
- console.log('✓ Properly throws error for missing prompt');
85
- } else {
86
- console.error('✗ Wrong error message:', error.message);
87
- process.exit(1);
88
- }
89
- }
90
-
91
- // Test 7: Verify error handling for invalid model format (function API)
92
- console.log('\nTest 7: Testing error handling for invalid model format (function API)...');
93
- try {
94
- await completion('invalidmodel', 'test prompt');
95
- console.error('✗ Should have thrown an error for invalid model format');
96
- process.exit(1);
97
- } catch (error) {
98
- if (error.message.includes('Model must be in format')) {
99
- console.log('✓ Properly throws error for invalid model format');
100
- } else {
101
- console.error('✗ Wrong error message:', error.message);
102
- process.exit(1);
103
- }
104
- }
105
-
106
- // Test 8: Verify error handling for unsupported provider (function API)
107
- console.log('\nTest 8: Testing error handling for unsupported provider (function API)...');
108
- try {
109
- await completion('unsupported/model', 'test prompt');
110
- console.error('✗ Should have thrown an error for unsupported provider');
111
- process.exit(1);
112
- } catch (error) {
113
- if (error.message.includes('Unsupported provider')) {
114
- console.log('✓ Properly throws error for unsupported provider');
115
- } else {
116
- console.error('✗ Wrong error message:', error.message);
117
- process.exit(1);
118
- }
119
- }
120
-
121
- // Test 9: Verify error handling for missing API key (Ollama, function API)
122
- console.log('\nTest 9: Testing error handling for missing API key (Ollama, function API)...');
123
- try {
124
- delete process.env.OLLAMA_API_KEY;
125
- delete process.env.OPEN_ROUTER_API_KEY;
126
- await completion('ollama/minimax-m2.5:cloud', 'test prompt');
127
- console.error('✗ Should have thrown an error for missing API key');
128
- process.exit(1);
129
- } catch (error) {
130
- if (error.message.includes('API key is required')) {
131
- console.log('✓ Properly throws error for missing API key');
132
- } else {
133
- console.error('✗ Wrong error message:', error.message);
134
- process.exit(1);
135
- }
136
- }
137
-
138
- // Test 10: Verify error handling for missing API key (OpenRouter, function API)
139
- console.log('\nTest 10: Testing error handling for missing API key (OpenRouter, function API)...');
140
- try {
141
- delete process.env.OLLAMA_API_KEY;
142
- delete process.env.OPEN_ROUTER_API_KEY;
143
- await completion('openrouter/openrouter/free', 'test prompt');
144
- console.error('✗ Should have thrown an error for missing API key');
145
- process.exit(1);
146
- } catch (error) {
147
- if (error.message.includes('API key is required')) {
148
- console.log('✓ Properly throws error for missing API key');
149
- } else {
150
- console.error('✗ Wrong error message:', error.message);
151
- process.exit(1);
152
- }
153
- }
154
-
155
- // Test 11: Verify error handling for missing model (object API)
156
- console.log('\nTest 11: Testing error handling for missing model (object API)...');
157
- try {
158
- await completion({
159
- messages: [{ role: 'user', content: 'test' }]
160
- });
161
- console.error('✗ Should have thrown an error for missing model');
162
- process.exit(1);
163
- } catch (error) {
164
- if (error.message.includes('Model parameter is required')) {
165
- console.log('✓ Properly throws error for missing model');
166
- } else {
167
- console.error('✗ Wrong error message:', error.message);
168
- process.exit(1);
169
- }
170
- }
171
-
172
- // Test 12: Verify error handling for missing messages (object API)
173
- console.log('\nTest 12: Testing error handling for missing messages (object API)...');
174
- try {
175
- await completion({
176
- model: 'ollama/minimax-m2.5:cloud'
177
- });
178
- console.error('✗ Should have thrown an error for missing messages');
179
- process.exit(1);
180
- } catch (error) {
181
- if (error.message.includes('Messages parameter is required')) {
182
- console.log('✓ Properly throws error for missing messages');
183
- } else {
184
- console.error('✗ Wrong error message:', error.message);
185
- process.exit(1);
186
- }
187
- }
188
-
189
- // Test 13: Verify error handling for invalid message format (object API)
190
- console.log('\nTest 13: Testing error handling for invalid message format (object API)...');
191
- try {
192
- await completion({
193
- model: 'ollama/minimax-m2.5:cloud',
194
- messages: [{ content: 'test' }]
195
- });
196
- console.error('✗ Should have thrown an error for invalid message format');
197
- process.exit(1);
198
- } catch (error) {
199
- if (error.message.includes('Each message must have')) {
200
- console.log('✓ Properly throws error for invalid message format');
201
- } else {
202
- console.error('✗ Wrong error message:', error.message);
203
- process.exit(1);
204
- }
205
- }
206
-
207
- // Test 14: Verify error handling for invalid message role (object API)
208
- console.log('\nTest 14: Testing error handling for invalid message role (object API)...');
209
- try {
210
- await completion({
211
- model: 'ollama/minimax-m2.5:cloud',
212
- messages: [{ role: 'invalid', content: 'test' }]
213
- });
214
- console.error('✗ Should have thrown an error for invalid message role');
215
- process.exit(1);
216
- } catch (error) {
217
- if (error.message.includes('Message role must be')) {
218
- console.log('✓ Properly throws error for invalid message role');
219
- } else {
220
- console.error('✗ Wrong error message:', error.message);
221
- process.exit(1);
222
- }
223
- }
224
-
225
- // Test 15: Verify error handling for invalid tools format (object API)
226
- console.log('\nTest 15: Testing error handling for invalid tools format (object API)...');
227
- try {
228
- await completion({
229
- model: 'ollama/minimax-m2.5:cloud',
230
- messages: [{ role: 'user', content: 'test' }],
231
- tools: 'invalid'
232
- });
233
- console.error('✗ Should have thrown an error for invalid tools format');
234
- process.exit(1);
235
- } catch (error) {
236
- if (error.message.includes('Tools parameter must be an array')) {
237
- console.log('✓ Properly throws error for invalid tools format');
238
- } else {
239
- console.error('✗ Wrong error message:', error.message);
240
- process.exit(1);
241
- }
242
- }
243
-
244
- // Test 16: Verify error handling for invalid tool format (object API)
245
- console.log('\nTest 16: Testing error handling for invalid tool format (object API)...');
246
- try {
247
- await completion({
248
- model: 'ollama/minimax-m2.5:cloud',
249
- messages: [{ role: 'user', content: 'test' }],
250
- tools: [{ invalid: 'tool' }]
251
- });
252
- console.error('✗ Should have thrown an error for invalid tool format');
253
- process.exit(1);
254
- } catch (error) {
255
- if (error.message.includes('Each tool must have type "function"')) {
256
- console.log('✓ Properly throws error for invalid tool format');
257
- } else {
258
- console.error('✗ Wrong error message:', error.message);
259
- process.exit(1);
260
- }
261
- }
262
-
263
- // Test 17: Verify error handling for missing tool function name (object API)
264
- console.log('\nTest 17: Testing error handling for missing tool function name (object API)...');
265
- try {
266
- await completion({
267
- model: 'ollama/minimax-m2.5:cloud',
268
- messages: [{ role: 'user', content: 'test' }],
269
- tools: [{ type: 'function', function: {} }]
270
- });
271
- console.error('✗ Should have thrown an error for missing tool function name');
272
- process.exit(1);
273
- } catch (error) {
274
- if (error.message.includes('Each tool must have a function with a name')) {
275
- console.log('✓ Properly throws error for missing tool function name');
276
- } else {
277
- console.error('✗ Wrong error message:', error.message);
278
- process.exit(1);
279
- }
280
- }
281
-
282
- console.log('\n✓ All tests passed!');
283
- console.log('\nLibrary structure is valid and ready for use.');
284
- console.log('\nSupported APIs:');
285
- console.log(' - Simple API: completion(prompt) or completion(model, prompt)');
286
- console.log(' - Function API: completion(model, prompt, apiKey)');
287
- console.log(' - Object API: completion({ model, messages, apiKey, tools })');
288
- console.log('\nSupported models:');
289
- console.log(' - Ollama: ollama/minimax-m2.5:cloud');
290
- console.log(' - OpenRouter: openrouter/openrouter/free');
291
- console.log('\nSimple API features:');
292
- console.log(' - Auto-detects provider based on available API keys');
293
- console.log(' - Uses OLLAMA_DEFAULT_MODEL or defaults to minimax-m2.5:cloud');
294
- console.log(' - Uses OPEN_ROUTER_DEFAULT_MODEL or defaults to openrouter/free');
295
- console.log(' - Randomly chooses provider if both API keys are set');
296
- console.log(' - Supports optional model parameter: completion(model, prompt)');