modelmix 4.2.2 → 4.2.4
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 +4 -5
- package/demo/demo.js +2 -2
- package/demo/free.js +1 -6
- package/demo/gpt51.js +3 -8
- package/demo/mcp-simple.js +1 -1
- package/demo/package-lock.json +449 -0
- package/demo/package.json +1 -0
- package/demo/repl-powers.js +77 -0
- package/index.js +107 -27
- package/package.json +2 -2
- package/test/bottleneck.test.js +9 -9
- package/test/images.test.js +1 -1
- package/test/json.test.js +2 -2
- package/test/live.mcp.js +10 -8
- package/test/templates.test.js +15 -15
package/README.md
CHANGED
|
@@ -41,7 +41,7 @@ import { ModelMix } from 'modelmix';
|
|
|
41
41
|
|
|
42
42
|
// Get structured JSON responses
|
|
43
43
|
const model = ModelMix.new()
|
|
44
|
-
.
|
|
44
|
+
.sonnet45() // Anthropic claude-sonnet-4-20250514
|
|
45
45
|
.addText("Name and capital of 3 South American countries.");
|
|
46
46
|
|
|
47
47
|
const outputExample = { countries: [{ name: "", capital: "" }] };
|
|
@@ -59,10 +59,9 @@ const setup = {
|
|
|
59
59
|
};
|
|
60
60
|
|
|
61
61
|
const model = await ModelMix.new(setup)
|
|
62
|
-
.
|
|
63
|
-
.gpt5mini() // (fallback
|
|
64
|
-
.
|
|
65
|
-
.gpt5nano() // (fallback 3) OpenAI gpt-5-nano
|
|
62
|
+
.sonnet45() // (main model) Anthropic claude-sonnet-4-5-20250929
|
|
63
|
+
.gpt5mini() // (fallback 2) OpenAI gpt-5-mini
|
|
64
|
+
.gemini3flash({ config: { temperature: 0 } }) // (fallback 3) Google gemini-3-flash
|
|
66
65
|
.grok3mini() // (fallback 4) Grok grok-3-mini
|
|
67
66
|
.addText("What's your name?");
|
|
68
67
|
|
package/demo/demo.js
CHANGED
|
@@ -27,8 +27,8 @@ const pplxSettings = {
|
|
|
27
27
|
mmix.replace({ '{name}': 'ALF' });
|
|
28
28
|
|
|
29
29
|
console.log("\n" + '--------| gpt51() |--------');
|
|
30
|
-
const
|
|
31
|
-
const gpt = mmix.gpt51(
|
|
30
|
+
const gptArgs = { options: { reasoning_effort: "none", verbosity: "low" } };
|
|
31
|
+
const gpt = mmix.gpt51(gptArgs).addText("Have you ever eaten a {animal}?");
|
|
32
32
|
gpt.replace({ '{animal}': 'cat' });
|
|
33
33
|
await gpt.json({ time: '24:00:00', message: 'Hello' }, { time: 'Time in format HH:MM:SS' });
|
|
34
34
|
|
package/demo/free.js
CHANGED
|
@@ -1,9 +1,4 @@
|
|
|
1
|
-
|
|
2
|
-
import { dirname, join } from 'path';
|
|
3
|
-
|
|
4
|
-
const __filename = fileURLToPath(import.meta.url);
|
|
5
|
-
const __dirname = dirname(__filename);
|
|
6
|
-
process.loadEnvFile(join(__dirname, '../.env'));
|
|
1
|
+
process.loadEnvFile();
|
|
7
2
|
import { ModelMix } from '../index.js';
|
|
8
3
|
|
|
9
4
|
const ai = ModelMix.new({ config: { debug: true } })
|
package/demo/gpt51.js
CHANGED
|
@@ -8,14 +8,9 @@ const mmix = new ModelMix({
|
|
|
8
8
|
});
|
|
9
9
|
|
|
10
10
|
console.log("\n" + '--------| gpt51() |--------');
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
effort: "low",
|
|
15
|
-
summary: "auto"
|
|
16
|
-
}
|
|
17
|
-
}
|
|
18
|
-
});
|
|
11
|
+
|
|
12
|
+
const gptArgs = { options: { reasoning_effort: "none", verbosity: "low" } };
|
|
13
|
+
const gpt = mmix.gpt51(gptArgs);
|
|
19
14
|
|
|
20
15
|
gpt.addText("Explain quantum entanglement in simple terms.");
|
|
21
16
|
const response = await gpt.message();
|
package/demo/mcp-simple.js
CHANGED
|
@@ -93,7 +93,7 @@ async function contentGenerator() {
|
|
|
93
93
|
console.log('\n=== Content Generator ===');
|
|
94
94
|
|
|
95
95
|
const mmix = ModelMix.new({ config: { debug: true, max_history: 1 } })
|
|
96
|
-
.
|
|
96
|
+
.gemini3flash()
|
|
97
97
|
.setSystem('You are a creative assistant that can generate different types of content.');
|
|
98
98
|
|
|
99
99
|
// Tool for generating passwords
|
package/demo/package-lock.json
CHANGED
|
@@ -10,6 +10,8 @@
|
|
|
10
10
|
"license": "ISC",
|
|
11
11
|
"dependencies": {
|
|
12
12
|
"@anthropic-ai/sdk": "^0.20.9",
|
|
13
|
+
"dotenv": "^17.2.3",
|
|
14
|
+
"isolated-vm": "^6.0.2",
|
|
13
15
|
"lemonlog": "^1.1.4"
|
|
14
16
|
}
|
|
15
17
|
},
|
|
@@ -82,6 +84,67 @@
|
|
|
82
84
|
"resolved": "https://registry.npmjs.org/asynckit/-/asynckit-0.4.0.tgz",
|
|
83
85
|
"integrity": "sha512-Oei9OH4tRh0YqU3GxhX79dM/mwVgvbZJaSNaRk+bshkj0S5cfHcgYakreBjrHwatXKbz+IoIdYLxrKim2MjW0Q=="
|
|
84
86
|
},
|
|
87
|
+
"node_modules/base64-js": {
|
|
88
|
+
"version": "1.5.1",
|
|
89
|
+
"resolved": "https://registry.npmjs.org/base64-js/-/base64-js-1.5.1.tgz",
|
|
90
|
+
"integrity": "sha512-AKpaYlHn8t4SVbOHCy+b5+KKgvR4vrsD8vbvrbiQJps7fKDTkjkDry6ji0rUJjC0kzbNePLwzxq8iypo41qeWA==",
|
|
91
|
+
"funding": [
|
|
92
|
+
{
|
|
93
|
+
"type": "github",
|
|
94
|
+
"url": "https://github.com/sponsors/feross"
|
|
95
|
+
},
|
|
96
|
+
{
|
|
97
|
+
"type": "patreon",
|
|
98
|
+
"url": "https://www.patreon.com/feross"
|
|
99
|
+
},
|
|
100
|
+
{
|
|
101
|
+
"type": "consulting",
|
|
102
|
+
"url": "https://feross.org/support"
|
|
103
|
+
}
|
|
104
|
+
],
|
|
105
|
+
"license": "MIT"
|
|
106
|
+
},
|
|
107
|
+
"node_modules/bl": {
|
|
108
|
+
"version": "4.1.0",
|
|
109
|
+
"resolved": "https://registry.npmjs.org/bl/-/bl-4.1.0.tgz",
|
|
110
|
+
"integrity": "sha512-1W07cM9gS6DcLperZfFSj+bWLtaPGSOHWhPiGzXmvVJbRLdG82sH/Kn8EtW1VqWVA54AKf2h5k5BbnIbwF3h6w==",
|
|
111
|
+
"license": "MIT",
|
|
112
|
+
"dependencies": {
|
|
113
|
+
"buffer": "^5.5.0",
|
|
114
|
+
"inherits": "^2.0.4",
|
|
115
|
+
"readable-stream": "^3.4.0"
|
|
116
|
+
}
|
|
117
|
+
},
|
|
118
|
+
"node_modules/buffer": {
|
|
119
|
+
"version": "5.7.1",
|
|
120
|
+
"resolved": "https://registry.npmjs.org/buffer/-/buffer-5.7.1.tgz",
|
|
121
|
+
"integrity": "sha512-EHcyIPBQ4BSGlvjB16k5KgAJ27CIsHY/2JBmCRReo48y9rQ3MaUzWX3KVlBa4U7MyX02HdVj0K7C3WaB3ju7FQ==",
|
|
122
|
+
"funding": [
|
|
123
|
+
{
|
|
124
|
+
"type": "github",
|
|
125
|
+
"url": "https://github.com/sponsors/feross"
|
|
126
|
+
},
|
|
127
|
+
{
|
|
128
|
+
"type": "patreon",
|
|
129
|
+
"url": "https://www.patreon.com/feross"
|
|
130
|
+
},
|
|
131
|
+
{
|
|
132
|
+
"type": "consulting",
|
|
133
|
+
"url": "https://feross.org/support"
|
|
134
|
+
}
|
|
135
|
+
],
|
|
136
|
+
"license": "MIT",
|
|
137
|
+
"dependencies": {
|
|
138
|
+
"base64-js": "^1.3.1",
|
|
139
|
+
"ieee754": "^1.1.13"
|
|
140
|
+
}
|
|
141
|
+
},
|
|
142
|
+
"node_modules/chownr": {
|
|
143
|
+
"version": "1.1.4",
|
|
144
|
+
"resolved": "https://registry.npmjs.org/chownr/-/chownr-1.1.4.tgz",
|
|
145
|
+
"integrity": "sha512-jJ0bqzaylmJtVnNgzTeSOs8DPavpbYgEr/b0YL8/2GO3xJEhInFmhKMUnEJQjZumK7KXGFhUy89PrsJWlakBVg==",
|
|
146
|
+
"license": "ISC"
|
|
147
|
+
},
|
|
85
148
|
"node_modules/combined-stream": {
|
|
86
149
|
"version": "1.0.8",
|
|
87
150
|
"resolved": "https://registry.npmjs.org/combined-stream/-/combined-stream-1.0.8.tgz",
|
|
@@ -110,6 +173,30 @@
|
|
|
110
173
|
}
|
|
111
174
|
}
|
|
112
175
|
},
|
|
176
|
+
"node_modules/decompress-response": {
|
|
177
|
+
"version": "6.0.0",
|
|
178
|
+
"resolved": "https://registry.npmjs.org/decompress-response/-/decompress-response-6.0.0.tgz",
|
|
179
|
+
"integrity": "sha512-aW35yZM6Bb/4oJlZncMH2LCoZtJXTRxES17vE3hoRiowU2kWHaJKFkSBDnDR+cm9J+9QhXmREyIfv0pji9ejCQ==",
|
|
180
|
+
"license": "MIT",
|
|
181
|
+
"dependencies": {
|
|
182
|
+
"mimic-response": "^3.1.0"
|
|
183
|
+
},
|
|
184
|
+
"engines": {
|
|
185
|
+
"node": ">=10"
|
|
186
|
+
},
|
|
187
|
+
"funding": {
|
|
188
|
+
"url": "https://github.com/sponsors/sindresorhus"
|
|
189
|
+
}
|
|
190
|
+
},
|
|
191
|
+
"node_modules/deep-extend": {
|
|
192
|
+
"version": "0.6.0",
|
|
193
|
+
"resolved": "https://registry.npmjs.org/deep-extend/-/deep-extend-0.6.0.tgz",
|
|
194
|
+
"integrity": "sha512-LOHxIOaPYdHlJRtCQfDIVZtfw/ufM8+rVj649RIHzcm/vGwQRXFt6OPqIFWsm2XEMrNIEtWR64sY1LEKD2vAOA==",
|
|
195
|
+
"license": "MIT",
|
|
196
|
+
"engines": {
|
|
197
|
+
"node": ">=4.0.0"
|
|
198
|
+
}
|
|
199
|
+
},
|
|
113
200
|
"node_modules/delayed-stream": {
|
|
114
201
|
"version": "1.0.0",
|
|
115
202
|
"resolved": "https://registry.npmjs.org/delayed-stream/-/delayed-stream-1.0.0.tgz",
|
|
@@ -118,6 +205,36 @@
|
|
|
118
205
|
"node": ">=0.4.0"
|
|
119
206
|
}
|
|
120
207
|
},
|
|
208
|
+
"node_modules/detect-libc": {
|
|
209
|
+
"version": "2.1.2",
|
|
210
|
+
"resolved": "https://registry.npmjs.org/detect-libc/-/detect-libc-2.1.2.tgz",
|
|
211
|
+
"integrity": "sha512-Btj2BOOO83o3WyH59e8MgXsxEQVcarkUOpEYrubB0urwnN10yQ364rsiByU11nZlqWYZm05i/of7io4mzihBtQ==",
|
|
212
|
+
"license": "Apache-2.0",
|
|
213
|
+
"engines": {
|
|
214
|
+
"node": ">=8"
|
|
215
|
+
}
|
|
216
|
+
},
|
|
217
|
+
"node_modules/dotenv": {
|
|
218
|
+
"version": "17.2.3",
|
|
219
|
+
"resolved": "https://registry.npmjs.org/dotenv/-/dotenv-17.2.3.tgz",
|
|
220
|
+
"integrity": "sha512-JVUnt+DUIzu87TABbhPmNfVdBDt18BLOWjMUFJMSi/Qqg7NTYtabbvSNJGOJ7afbRuv9D/lngizHtP7QyLQ+9w==",
|
|
221
|
+
"license": "BSD-2-Clause",
|
|
222
|
+
"engines": {
|
|
223
|
+
"node": ">=12"
|
|
224
|
+
},
|
|
225
|
+
"funding": {
|
|
226
|
+
"url": "https://dotenvx.com"
|
|
227
|
+
}
|
|
228
|
+
},
|
|
229
|
+
"node_modules/end-of-stream": {
|
|
230
|
+
"version": "1.4.5",
|
|
231
|
+
"resolved": "https://registry.npmjs.org/end-of-stream/-/end-of-stream-1.4.5.tgz",
|
|
232
|
+
"integrity": "sha512-ooEGc6HP26xXq/N+GCGOT0JKCLDGrq2bQUZrQ7gyrJiZANJ/8YDTxTpQBXGMn+WbIQXNVpyWymm7KYVICQnyOg==",
|
|
233
|
+
"license": "MIT",
|
|
234
|
+
"dependencies": {
|
|
235
|
+
"once": "^1.4.0"
|
|
236
|
+
}
|
|
237
|
+
},
|
|
121
238
|
"node_modules/event-target-shim": {
|
|
122
239
|
"version": "5.0.1",
|
|
123
240
|
"resolved": "https://registry.npmjs.org/event-target-shim/-/event-target-shim-5.0.1.tgz",
|
|
@@ -126,6 +243,15 @@
|
|
|
126
243
|
"node": ">=6"
|
|
127
244
|
}
|
|
128
245
|
},
|
|
246
|
+
"node_modules/expand-template": {
|
|
247
|
+
"version": "2.0.3",
|
|
248
|
+
"resolved": "https://registry.npmjs.org/expand-template/-/expand-template-2.0.3.tgz",
|
|
249
|
+
"integrity": "sha512-XYfuKMvj4O35f/pOXLObndIRvyQ+/+6AhODh+OKWj9S9498pHHn/IMszH+gt0fBCRWMNfk1ZSp5x3AifmnI2vg==",
|
|
250
|
+
"license": "(MIT OR WTFPL)",
|
|
251
|
+
"engines": {
|
|
252
|
+
"node": ">=6"
|
|
253
|
+
}
|
|
254
|
+
},
|
|
129
255
|
"node_modules/form-data": {
|
|
130
256
|
"version": "4.0.0",
|
|
131
257
|
"resolved": "https://registry.npmjs.org/form-data/-/form-data-4.0.0.tgz",
|
|
@@ -164,6 +290,18 @@
|
|
|
164
290
|
"node": ">= 14"
|
|
165
291
|
}
|
|
166
292
|
},
|
|
293
|
+
"node_modules/fs-constants": {
|
|
294
|
+
"version": "1.0.0",
|
|
295
|
+
"resolved": "https://registry.npmjs.org/fs-constants/-/fs-constants-1.0.0.tgz",
|
|
296
|
+
"integrity": "sha512-y6OAwoSIf7FyjMIv94u+b5rdheZEjzR63GTyZJm5qh4Bi+2YgwLCcI/fPFZkL5PSixOt6ZNKm+w+Hfp/Bciwow==",
|
|
297
|
+
"license": "MIT"
|
|
298
|
+
},
|
|
299
|
+
"node_modules/github-from-package": {
|
|
300
|
+
"version": "0.0.0",
|
|
301
|
+
"resolved": "https://registry.npmjs.org/github-from-package/-/github-from-package-0.0.0.tgz",
|
|
302
|
+
"integrity": "sha512-SyHy3T1v2NUXn29OsWdxmK6RwHD+vkj3v8en8AOBZ1wBQ/hCAQ5bAQTD02kW4W9tUp/3Qh6J8r9EvntiyCmOOw==",
|
|
303
|
+
"license": "MIT"
|
|
304
|
+
},
|
|
167
305
|
"node_modules/humanize-ms": {
|
|
168
306
|
"version": "1.2.1",
|
|
169
307
|
"resolved": "https://registry.npmjs.org/humanize-ms/-/humanize-ms-1.2.1.tgz",
|
|
@@ -172,6 +310,51 @@
|
|
|
172
310
|
"ms": "^2.0.0"
|
|
173
311
|
}
|
|
174
312
|
},
|
|
313
|
+
"node_modules/ieee754": {
|
|
314
|
+
"version": "1.2.1",
|
|
315
|
+
"resolved": "https://registry.npmjs.org/ieee754/-/ieee754-1.2.1.tgz",
|
|
316
|
+
"integrity": "sha512-dcyqhDvX1C46lXZcVqCpK+FtMRQVdIMN6/Df5js2zouUsqG7I6sFxitIC+7KYK29KdXOLHdu9zL4sFnoVQnqaA==",
|
|
317
|
+
"funding": [
|
|
318
|
+
{
|
|
319
|
+
"type": "github",
|
|
320
|
+
"url": "https://github.com/sponsors/feross"
|
|
321
|
+
},
|
|
322
|
+
{
|
|
323
|
+
"type": "patreon",
|
|
324
|
+
"url": "https://www.patreon.com/feross"
|
|
325
|
+
},
|
|
326
|
+
{
|
|
327
|
+
"type": "consulting",
|
|
328
|
+
"url": "https://feross.org/support"
|
|
329
|
+
}
|
|
330
|
+
],
|
|
331
|
+
"license": "BSD-3-Clause"
|
|
332
|
+
},
|
|
333
|
+
"node_modules/inherits": {
|
|
334
|
+
"version": "2.0.4",
|
|
335
|
+
"resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz",
|
|
336
|
+
"integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==",
|
|
337
|
+
"license": "ISC"
|
|
338
|
+
},
|
|
339
|
+
"node_modules/ini": {
|
|
340
|
+
"version": "1.3.8",
|
|
341
|
+
"resolved": "https://registry.npmjs.org/ini/-/ini-1.3.8.tgz",
|
|
342
|
+
"integrity": "sha512-JV/yugV2uzW5iMRSiZAyDtQd+nxtUnjeLt0acNdw98kKLrvuRVyB80tsREOE7yvGVgalhZ6RNXCmEHkUKBKxew==",
|
|
343
|
+
"license": "ISC"
|
|
344
|
+
},
|
|
345
|
+
"node_modules/isolated-vm": {
|
|
346
|
+
"version": "6.0.2",
|
|
347
|
+
"resolved": "https://registry.npmjs.org/isolated-vm/-/isolated-vm-6.0.2.tgz",
|
|
348
|
+
"integrity": "sha512-Qw6AJuagG/VJuh2AIcSWmQPsAArti/L+lKhjXU+lyhYkbt3J57XZr+ZjgfTnOr4NJcY1r3f8f0eePS7MRGp+pg==",
|
|
349
|
+
"hasInstallScript": true,
|
|
350
|
+
"license": "ISC",
|
|
351
|
+
"dependencies": {
|
|
352
|
+
"prebuild-install": "^7.1.3"
|
|
353
|
+
},
|
|
354
|
+
"engines": {
|
|
355
|
+
"node": ">=22.0.0"
|
|
356
|
+
}
|
|
357
|
+
},
|
|
175
358
|
"node_modules/lemonlog": {
|
|
176
359
|
"version": "1.1.4",
|
|
177
360
|
"resolved": "https://registry.npmjs.org/lemonlog/-/lemonlog-1.1.4.tgz",
|
|
@@ -200,11 +383,56 @@
|
|
|
200
383
|
"node": ">= 0.6"
|
|
201
384
|
}
|
|
202
385
|
},
|
|
386
|
+
"node_modules/mimic-response": {
|
|
387
|
+
"version": "3.1.0",
|
|
388
|
+
"resolved": "https://registry.npmjs.org/mimic-response/-/mimic-response-3.1.0.tgz",
|
|
389
|
+
"integrity": "sha512-z0yWI+4FDrrweS8Zmt4Ej5HdJmky15+L2e6Wgn3+iK5fWzb6T3fhNFq2+MeTRb064c6Wr4N/wv0DzQTjNzHNGQ==",
|
|
390
|
+
"license": "MIT",
|
|
391
|
+
"engines": {
|
|
392
|
+
"node": ">=10"
|
|
393
|
+
},
|
|
394
|
+
"funding": {
|
|
395
|
+
"url": "https://github.com/sponsors/sindresorhus"
|
|
396
|
+
}
|
|
397
|
+
},
|
|
398
|
+
"node_modules/minimist": {
|
|
399
|
+
"version": "1.2.8",
|
|
400
|
+
"resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.8.tgz",
|
|
401
|
+
"integrity": "sha512-2yyAR8qBkN3YuheJanUpWC5U3bb5osDywNB8RzDVlDwDHbocAJveqqj1u8+SVD7jkWT4yvsHCpWqqWqAxb0zCA==",
|
|
402
|
+
"license": "MIT",
|
|
403
|
+
"funding": {
|
|
404
|
+
"url": "https://github.com/sponsors/ljharb"
|
|
405
|
+
}
|
|
406
|
+
},
|
|
407
|
+
"node_modules/mkdirp-classic": {
|
|
408
|
+
"version": "0.5.3",
|
|
409
|
+
"resolved": "https://registry.npmjs.org/mkdirp-classic/-/mkdirp-classic-0.5.3.tgz",
|
|
410
|
+
"integrity": "sha512-gKLcREMhtuZRwRAfqP3RFW+TK4JqApVBtOIftVgjuABpAtpxhPGaDcfvbhNvD0B8iD1oUr/txX35NjcaY6Ns/A==",
|
|
411
|
+
"license": "MIT"
|
|
412
|
+
},
|
|
203
413
|
"node_modules/ms": {
|
|
204
414
|
"version": "2.1.3",
|
|
205
415
|
"resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz",
|
|
206
416
|
"integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA=="
|
|
207
417
|
},
|
|
418
|
+
"node_modules/napi-build-utils": {
|
|
419
|
+
"version": "2.0.0",
|
|
420
|
+
"resolved": "https://registry.npmjs.org/napi-build-utils/-/napi-build-utils-2.0.0.tgz",
|
|
421
|
+
"integrity": "sha512-GEbrYkbfF7MoNaoh2iGG84Mnf/WZfB0GdGEsM8wz7Expx/LlWf5U8t9nvJKXSp3qr5IsEbK04cBGhol/KwOsWA==",
|
|
422
|
+
"license": "MIT"
|
|
423
|
+
},
|
|
424
|
+
"node_modules/node-abi": {
|
|
425
|
+
"version": "3.85.0",
|
|
426
|
+
"resolved": "https://registry.npmjs.org/node-abi/-/node-abi-3.85.0.tgz",
|
|
427
|
+
"integrity": "sha512-zsFhmbkAzwhTft6nd3VxcG0cvJsT70rL+BIGHWVq5fi6MwGrHwzqKaxXE+Hl2GmnGItnDKPPkO5/LQqjVkIdFg==",
|
|
428
|
+
"license": "MIT",
|
|
429
|
+
"dependencies": {
|
|
430
|
+
"semver": "^7.3.5"
|
|
431
|
+
},
|
|
432
|
+
"engines": {
|
|
433
|
+
"node": ">=10"
|
|
434
|
+
}
|
|
435
|
+
},
|
|
208
436
|
"node_modules/node-domexception": {
|
|
209
437
|
"version": "1.0.0",
|
|
210
438
|
"resolved": "https://registry.npmjs.org/node-domexception/-/node-domexception-1.0.0.tgz",
|
|
@@ -242,16 +470,231 @@
|
|
|
242
470
|
}
|
|
243
471
|
}
|
|
244
472
|
},
|
|
473
|
+
"node_modules/once": {
|
|
474
|
+
"version": "1.4.0",
|
|
475
|
+
"resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz",
|
|
476
|
+
"integrity": "sha512-lNaJgI+2Q5URQBkccEKHTQOPaXdUxnZZElQTZY0MFUAuaEqe1E+Nyvgdz/aIyNi6Z9MzO5dv1H8n58/GELp3+w==",
|
|
477
|
+
"license": "ISC",
|
|
478
|
+
"dependencies": {
|
|
479
|
+
"wrappy": "1"
|
|
480
|
+
}
|
|
481
|
+
},
|
|
482
|
+
"node_modules/prebuild-install": {
|
|
483
|
+
"version": "7.1.3",
|
|
484
|
+
"resolved": "https://registry.npmjs.org/prebuild-install/-/prebuild-install-7.1.3.tgz",
|
|
485
|
+
"integrity": "sha512-8Mf2cbV7x1cXPUILADGI3wuhfqWvtiLA1iclTDbFRZkgRQS0NqsPZphna9V+HyTEadheuPmjaJMsbzKQFOzLug==",
|
|
486
|
+
"license": "MIT",
|
|
487
|
+
"dependencies": {
|
|
488
|
+
"detect-libc": "^2.0.0",
|
|
489
|
+
"expand-template": "^2.0.3",
|
|
490
|
+
"github-from-package": "0.0.0",
|
|
491
|
+
"minimist": "^1.2.3",
|
|
492
|
+
"mkdirp-classic": "^0.5.3",
|
|
493
|
+
"napi-build-utils": "^2.0.0",
|
|
494
|
+
"node-abi": "^3.3.0",
|
|
495
|
+
"pump": "^3.0.0",
|
|
496
|
+
"rc": "^1.2.7",
|
|
497
|
+
"simple-get": "^4.0.0",
|
|
498
|
+
"tar-fs": "^2.0.0",
|
|
499
|
+
"tunnel-agent": "^0.6.0"
|
|
500
|
+
},
|
|
501
|
+
"bin": {
|
|
502
|
+
"prebuild-install": "bin.js"
|
|
503
|
+
},
|
|
504
|
+
"engines": {
|
|
505
|
+
"node": ">=10"
|
|
506
|
+
}
|
|
507
|
+
},
|
|
508
|
+
"node_modules/pump": {
|
|
509
|
+
"version": "3.0.3",
|
|
510
|
+
"resolved": "https://registry.npmjs.org/pump/-/pump-3.0.3.tgz",
|
|
511
|
+
"integrity": "sha512-todwxLMY7/heScKmntwQG8CXVkWUOdYxIvY2s0VWAAMh/nd8SoYiRaKjlr7+iCs984f2P8zvrfWcDDYVb73NfA==",
|
|
512
|
+
"license": "MIT",
|
|
513
|
+
"dependencies": {
|
|
514
|
+
"end-of-stream": "^1.1.0",
|
|
515
|
+
"once": "^1.3.1"
|
|
516
|
+
}
|
|
517
|
+
},
|
|
518
|
+
"node_modules/rc": {
|
|
519
|
+
"version": "1.2.8",
|
|
520
|
+
"resolved": "https://registry.npmjs.org/rc/-/rc-1.2.8.tgz",
|
|
521
|
+
"integrity": "sha512-y3bGgqKj3QBdxLbLkomlohkvsA8gdAiUQlSBJnBhfn+BPxg4bc62d8TcBW15wavDfgexCgccckhcZvywyQYPOw==",
|
|
522
|
+
"license": "(BSD-2-Clause OR MIT OR Apache-2.0)",
|
|
523
|
+
"dependencies": {
|
|
524
|
+
"deep-extend": "^0.6.0",
|
|
525
|
+
"ini": "~1.3.0",
|
|
526
|
+
"minimist": "^1.2.0",
|
|
527
|
+
"strip-json-comments": "~2.0.1"
|
|
528
|
+
},
|
|
529
|
+
"bin": {
|
|
530
|
+
"rc": "cli.js"
|
|
531
|
+
}
|
|
532
|
+
},
|
|
533
|
+
"node_modules/readable-stream": {
|
|
534
|
+
"version": "3.6.2",
|
|
535
|
+
"resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.2.tgz",
|
|
536
|
+
"integrity": "sha512-9u/sniCrY3D5WdsERHzHE4G2YCXqoG5FTHUiCC4SIbr6XcLZBY05ya9EKjYek9O5xOAwjGq+1JdGBAS7Q9ScoA==",
|
|
537
|
+
"license": "MIT",
|
|
538
|
+
"dependencies": {
|
|
539
|
+
"inherits": "^2.0.3",
|
|
540
|
+
"string_decoder": "^1.1.1",
|
|
541
|
+
"util-deprecate": "^1.0.1"
|
|
542
|
+
},
|
|
543
|
+
"engines": {
|
|
544
|
+
"node": ">= 6"
|
|
545
|
+
}
|
|
546
|
+
},
|
|
547
|
+
"node_modules/safe-buffer": {
|
|
548
|
+
"version": "5.2.1",
|
|
549
|
+
"resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.2.1.tgz",
|
|
550
|
+
"integrity": "sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==",
|
|
551
|
+
"funding": [
|
|
552
|
+
{
|
|
553
|
+
"type": "github",
|
|
554
|
+
"url": "https://github.com/sponsors/feross"
|
|
555
|
+
},
|
|
556
|
+
{
|
|
557
|
+
"type": "patreon",
|
|
558
|
+
"url": "https://www.patreon.com/feross"
|
|
559
|
+
},
|
|
560
|
+
{
|
|
561
|
+
"type": "consulting",
|
|
562
|
+
"url": "https://feross.org/support"
|
|
563
|
+
}
|
|
564
|
+
],
|
|
565
|
+
"license": "MIT"
|
|
566
|
+
},
|
|
567
|
+
"node_modules/semver": {
|
|
568
|
+
"version": "7.7.3",
|
|
569
|
+
"resolved": "https://registry.npmjs.org/semver/-/semver-7.7.3.tgz",
|
|
570
|
+
"integrity": "sha512-SdsKMrI9TdgjdweUSR9MweHA4EJ8YxHn8DFaDisvhVlUOe4BF1tLD7GAj0lIqWVl+dPb/rExr0Btby5loQm20Q==",
|
|
571
|
+
"license": "ISC",
|
|
572
|
+
"bin": {
|
|
573
|
+
"semver": "bin/semver.js"
|
|
574
|
+
},
|
|
575
|
+
"engines": {
|
|
576
|
+
"node": ">=10"
|
|
577
|
+
}
|
|
578
|
+
},
|
|
579
|
+
"node_modules/simple-concat": {
|
|
580
|
+
"version": "1.0.1",
|
|
581
|
+
"resolved": "https://registry.npmjs.org/simple-concat/-/simple-concat-1.0.1.tgz",
|
|
582
|
+
"integrity": "sha512-cSFtAPtRhljv69IK0hTVZQ+OfE9nePi/rtJmw5UjHeVyVroEqJXP1sFztKUy1qU+xvz3u/sfYJLa947b7nAN2Q==",
|
|
583
|
+
"funding": [
|
|
584
|
+
{
|
|
585
|
+
"type": "github",
|
|
586
|
+
"url": "https://github.com/sponsors/feross"
|
|
587
|
+
},
|
|
588
|
+
{
|
|
589
|
+
"type": "patreon",
|
|
590
|
+
"url": "https://www.patreon.com/feross"
|
|
591
|
+
},
|
|
592
|
+
{
|
|
593
|
+
"type": "consulting",
|
|
594
|
+
"url": "https://feross.org/support"
|
|
595
|
+
}
|
|
596
|
+
],
|
|
597
|
+
"license": "MIT"
|
|
598
|
+
},
|
|
599
|
+
"node_modules/simple-get": {
|
|
600
|
+
"version": "4.0.1",
|
|
601
|
+
"resolved": "https://registry.npmjs.org/simple-get/-/simple-get-4.0.1.tgz",
|
|
602
|
+
"integrity": "sha512-brv7p5WgH0jmQJr1ZDDfKDOSeWWg+OVypG99A/5vYGPqJ6pxiaHLy8nxtFjBA7oMa01ebA9gfh1uMCFqOuXxvA==",
|
|
603
|
+
"funding": [
|
|
604
|
+
{
|
|
605
|
+
"type": "github",
|
|
606
|
+
"url": "https://github.com/sponsors/feross"
|
|
607
|
+
},
|
|
608
|
+
{
|
|
609
|
+
"type": "patreon",
|
|
610
|
+
"url": "https://www.patreon.com/feross"
|
|
611
|
+
},
|
|
612
|
+
{
|
|
613
|
+
"type": "consulting",
|
|
614
|
+
"url": "https://feross.org/support"
|
|
615
|
+
}
|
|
616
|
+
],
|
|
617
|
+
"license": "MIT",
|
|
618
|
+
"dependencies": {
|
|
619
|
+
"decompress-response": "^6.0.0",
|
|
620
|
+
"once": "^1.3.1",
|
|
621
|
+
"simple-concat": "^1.0.0"
|
|
622
|
+
}
|
|
623
|
+
},
|
|
624
|
+
"node_modules/string_decoder": {
|
|
625
|
+
"version": "1.3.0",
|
|
626
|
+
"resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.3.0.tgz",
|
|
627
|
+
"integrity": "sha512-hkRX8U1WjJFd8LsDJ2yQ/wWWxaopEsABU1XfkM8A+j0+85JAGppt16cr1Whg6KIbb4okU6Mql6BOj+uup/wKeA==",
|
|
628
|
+
"license": "MIT",
|
|
629
|
+
"dependencies": {
|
|
630
|
+
"safe-buffer": "~5.2.0"
|
|
631
|
+
}
|
|
632
|
+
},
|
|
633
|
+
"node_modules/strip-json-comments": {
|
|
634
|
+
"version": "2.0.1",
|
|
635
|
+
"resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-2.0.1.tgz",
|
|
636
|
+
"integrity": "sha512-4gB8na07fecVVkOI6Rs4e7T6NOTki5EmL7TUduTs6bu3EdnSycntVJ4re8kgZA+wx9IueI2Y11bfbgwtzuE0KQ==",
|
|
637
|
+
"license": "MIT",
|
|
638
|
+
"engines": {
|
|
639
|
+
"node": ">=0.10.0"
|
|
640
|
+
}
|
|
641
|
+
},
|
|
642
|
+
"node_modules/tar-fs": {
|
|
643
|
+
"version": "2.1.4",
|
|
644
|
+
"resolved": "https://registry.npmjs.org/tar-fs/-/tar-fs-2.1.4.tgz",
|
|
645
|
+
"integrity": "sha512-mDAjwmZdh7LTT6pNleZ05Yt65HC3E+NiQzl672vQG38jIrehtJk/J3mNwIg+vShQPcLF/LV7CMnDW6vjj6sfYQ==",
|
|
646
|
+
"license": "MIT",
|
|
647
|
+
"dependencies": {
|
|
648
|
+
"chownr": "^1.1.1",
|
|
649
|
+
"mkdirp-classic": "^0.5.2",
|
|
650
|
+
"pump": "^3.0.0",
|
|
651
|
+
"tar-stream": "^2.1.4"
|
|
652
|
+
}
|
|
653
|
+
},
|
|
654
|
+
"node_modules/tar-stream": {
|
|
655
|
+
"version": "2.2.0",
|
|
656
|
+
"resolved": "https://registry.npmjs.org/tar-stream/-/tar-stream-2.2.0.tgz",
|
|
657
|
+
"integrity": "sha512-ujeqbceABgwMZxEJnk2HDY2DlnUZ+9oEcb1KzTVfYHio0UE6dG71n60d8D2I4qNvleWrrXpmjpt7vZeF1LnMZQ==",
|
|
658
|
+
"license": "MIT",
|
|
659
|
+
"dependencies": {
|
|
660
|
+
"bl": "^4.0.3",
|
|
661
|
+
"end-of-stream": "^1.4.1",
|
|
662
|
+
"fs-constants": "^1.0.0",
|
|
663
|
+
"inherits": "^2.0.3",
|
|
664
|
+
"readable-stream": "^3.1.1"
|
|
665
|
+
},
|
|
666
|
+
"engines": {
|
|
667
|
+
"node": ">=6"
|
|
668
|
+
}
|
|
669
|
+
},
|
|
245
670
|
"node_modules/tr46": {
|
|
246
671
|
"version": "0.0.3",
|
|
247
672
|
"resolved": "https://registry.npmjs.org/tr46/-/tr46-0.0.3.tgz",
|
|
248
673
|
"integrity": "sha512-N3WMsuqV66lT30CrXNbEjx4GEwlow3v6rr4mCcv6prnfwhS01rkgyFdjPNBYd9br7LpXV1+Emh01fHnq2Gdgrw=="
|
|
249
674
|
},
|
|
675
|
+
"node_modules/tunnel-agent": {
|
|
676
|
+
"version": "0.6.0",
|
|
677
|
+
"resolved": "https://registry.npmjs.org/tunnel-agent/-/tunnel-agent-0.6.0.tgz",
|
|
678
|
+
"integrity": "sha512-McnNiV1l8RYeY8tBgEpuodCC1mLUdbSN+CYBL7kJsJNInOP8UjDDEwdk6Mw60vdLLrr5NHKZhMAOSrR2NZuQ+w==",
|
|
679
|
+
"license": "Apache-2.0",
|
|
680
|
+
"dependencies": {
|
|
681
|
+
"safe-buffer": "^5.0.1"
|
|
682
|
+
},
|
|
683
|
+
"engines": {
|
|
684
|
+
"node": "*"
|
|
685
|
+
}
|
|
686
|
+
},
|
|
250
687
|
"node_modules/undici-types": {
|
|
251
688
|
"version": "5.26.5",
|
|
252
689
|
"resolved": "https://registry.npmjs.org/undici-types/-/undici-types-5.26.5.tgz",
|
|
253
690
|
"integrity": "sha512-JlCMO+ehdEIKqlFxk6IfVoAUVmgz7cU7zD/h9XZ0qzeosSHmUJVOzSQvvYSYWXkFXC+IfLKSIffhv0sVZup6pA=="
|
|
254
691
|
},
|
|
692
|
+
"node_modules/util-deprecate": {
|
|
693
|
+
"version": "1.0.2",
|
|
694
|
+
"resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz",
|
|
695
|
+
"integrity": "sha512-EPD5q1uXyFxJpCrLnCc1nHnq3gOa6DZBocAIiI2TaSCA7VCJ1UJDMagCzIkXNsUYfD1daK//LTEQ8xiIbrHtcw==",
|
|
696
|
+
"license": "MIT"
|
|
697
|
+
},
|
|
255
698
|
"node_modules/web-streams-polyfill": {
|
|
256
699
|
"version": "3.3.3",
|
|
257
700
|
"resolved": "https://registry.npmjs.org/web-streams-polyfill/-/web-streams-polyfill-3.3.3.tgz",
|
|
@@ -273,6 +716,12 @@
|
|
|
273
716
|
"tr46": "~0.0.3",
|
|
274
717
|
"webidl-conversions": "^3.0.0"
|
|
275
718
|
}
|
|
719
|
+
},
|
|
720
|
+
"node_modules/wrappy": {
|
|
721
|
+
"version": "1.0.2",
|
|
722
|
+
"resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz",
|
|
723
|
+
"integrity": "sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ==",
|
|
724
|
+
"license": "ISC"
|
|
276
725
|
}
|
|
277
726
|
}
|
|
278
727
|
}
|
package/demo/package.json
CHANGED
|
@@ -0,0 +1,77 @@
|
|
|
1
|
+
process.loadEnvFile();
|
|
2
|
+
import { ModelMix } from '../index.js';
|
|
3
|
+
import ivm from 'isolated-vm';
|
|
4
|
+
|
|
5
|
+
console.log('🧬 ModelMix - JavaScript REPL Tool Demo');
|
|
6
|
+
|
|
7
|
+
// Crear isolate una sola vez (reutilizable)
|
|
8
|
+
const isolate = new ivm.Isolate({ memoryLimit: 128 }); // 128MB máximo
|
|
9
|
+
|
|
10
|
+
// Ejemplo simple: REPL de JavaScript para calcular potencias de 2
|
|
11
|
+
async function replPowersExample() {
|
|
12
|
+
console.log('\n=== JavaScript REPL - Potencias de 2 ===\n');
|
|
13
|
+
const gptArgs = { options: { reasoning_effort: "none", verbosity: null } };
|
|
14
|
+
const mmix = ModelMix.new({ config: { debug: true, max_history: 10 } })
|
|
15
|
+
.gpt41nano()
|
|
16
|
+
.gpt52(gptArgs)
|
|
17
|
+
.gemini3flash()
|
|
18
|
+
.setSystem('You are a helpful assistant with access to a JavaScript REPL. When you use the REPL and get results, always show them to the user in your response.');
|
|
19
|
+
|
|
20
|
+
// Variable para capturar el resultado de la herramienta
|
|
21
|
+
let toolResult = null;
|
|
22
|
+
|
|
23
|
+
// Agregar herramienta REPL personalizada
|
|
24
|
+
mmix.addTool({
|
|
25
|
+
name: "javascript_repl",
|
|
26
|
+
description: "Execute JavaScript code in a REPL environment. You can run any valid JavaScript code and get the result.",
|
|
27
|
+
inputSchema: {
|
|
28
|
+
type: "object",
|
|
29
|
+
properties: {
|
|
30
|
+
code: {
|
|
31
|
+
type: "string",
|
|
32
|
+
description: "JavaScript code to execute"
|
|
33
|
+
}
|
|
34
|
+
},
|
|
35
|
+
required: ["code"]
|
|
36
|
+
}
|
|
37
|
+
}, async ({ code }) => {
|
|
38
|
+
console.log('🔧 Ejecutando código JavaScript:');
|
|
39
|
+
console.log('─'.repeat(50));
|
|
40
|
+
console.log(code);
|
|
41
|
+
console.log('─'.repeat(50));
|
|
42
|
+
|
|
43
|
+
try {
|
|
44
|
+
const context = await isolate.createContext();
|
|
45
|
+
const result = await context.eval(`JSON.stringify(eval(${JSON.stringify(code)}))`, { timeout: 10000 });
|
|
46
|
+
toolResult = JSON.parse(result);
|
|
47
|
+
console.log('\n✅ Resultado:', toolResult);
|
|
48
|
+
return result;
|
|
49
|
+
} catch (error) {
|
|
50
|
+
console.log('\n❌ Error:', error.message);
|
|
51
|
+
return `Error: ${error.message}`;
|
|
52
|
+
}
|
|
53
|
+
});
|
|
54
|
+
|
|
55
|
+
// Pedir al modelo que calcule 100 potencias de 2
|
|
56
|
+
mmix.addText('Calcular las primeras 100 potencias de 2 (2^0 hasta 2^99). Después de ejecutar el código, menciona algunos valores del resultado como las primeras 5 y las últimas 5 potencias.');
|
|
57
|
+
|
|
58
|
+
const result = await mmix.message();
|
|
59
|
+
console.log('\n💬 Respuesta del modelo:');
|
|
60
|
+
console.log(result);
|
|
61
|
+
|
|
62
|
+
// Mostrar muestra del resultado si está disponible
|
|
63
|
+
if (toolResult && Array.isArray(toolResult)) {
|
|
64
|
+
console.log('\n📊 Muestra de resultados (primeros 10 y últimos 10):');
|
|
65
|
+
console.log('Primeros 10:', toolResult.slice(0, 10));
|
|
66
|
+
console.log('Últimos 10:', toolResult.slice(-10));
|
|
67
|
+
console.log(`\nTotal: ${toolResult.length} potencias calculadas`);
|
|
68
|
+
}
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
try {
|
|
72
|
+
await replPowersExample();
|
|
73
|
+
console.log('\n✅ Ejemplo completado');
|
|
74
|
+
} catch (error) {
|
|
75
|
+
console.error('❌ Error:', error);
|
|
76
|
+
}
|
|
77
|
+
|
package/index.js
CHANGED
|
@@ -20,7 +20,7 @@ class ModelMix {
|
|
|
20
20
|
this.mcp = {};
|
|
21
21
|
this.mcpToolsManager = new MCPToolsManager();
|
|
22
22
|
this.options = {
|
|
23
|
-
max_tokens:
|
|
23
|
+
max_tokens: 8192,
|
|
24
24
|
temperature: 1, // 1 --> More creative, 0 --> More deterministic.
|
|
25
25
|
...options
|
|
26
26
|
};
|
|
@@ -35,6 +35,7 @@ class ModelMix {
|
|
|
35
35
|
system: 'You are an assistant.',
|
|
36
36
|
max_history: 1, // Default max history
|
|
37
37
|
debug: false,
|
|
38
|
+
verbose: 2, // 0=silent, 1=minimal, 2=readable summary, 3=full details
|
|
38
39
|
bottleneck: defaultBottleneckConfig,
|
|
39
40
|
...config
|
|
40
41
|
}
|
|
@@ -55,8 +56,8 @@ class ModelMix {
|
|
|
55
56
|
return new ModelMix({ options, config, mix });
|
|
56
57
|
}
|
|
57
58
|
|
|
58
|
-
new() {
|
|
59
|
-
return new ModelMix({ options: this.options, config: this.config });
|
|
59
|
+
new({ options = {}, config = {}, mix = {} } = {}) {
|
|
60
|
+
return new ModelMix({ options: { ...this.options, ...options }, config: { ...this.config, ...config }, mix: { ...this.mix, ...mix } });
|
|
60
61
|
}
|
|
61
62
|
|
|
62
63
|
static formatJSON(obj) {
|
|
@@ -79,6 +80,57 @@ class ModelMix {
|
|
|
79
80
|
}
|
|
80
81
|
}
|
|
81
82
|
|
|
83
|
+
// Verbose logging helpers
|
|
84
|
+
static truncate(str, maxLen = 100) {
|
|
85
|
+
if (!str || typeof str !== 'string') return str;
|
|
86
|
+
return str.length > maxLen ? str.substring(0, maxLen) + '...' : str;
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
static getVerboseLevel(config) {
|
|
90
|
+
// debug=true acts as verbose level 3
|
|
91
|
+
return config.verbose || 0;
|
|
92
|
+
}
|
|
93
|
+
|
|
94
|
+
static verboseLog(level, config, ...args) {
|
|
95
|
+
const verboseLevel = ModelMix.getVerboseLevel(config);
|
|
96
|
+
if (verboseLevel >= level) {
|
|
97
|
+
console.log(...args);
|
|
98
|
+
}
|
|
99
|
+
}
|
|
100
|
+
|
|
101
|
+
static formatInputSummary(messages, system) {
|
|
102
|
+
const lastMessage = messages[messages.length - 1];
|
|
103
|
+
let inputText = '';
|
|
104
|
+
|
|
105
|
+
if (lastMessage && Array.isArray(lastMessage.content)) {
|
|
106
|
+
const textContent = lastMessage.content.find(c => c.type === 'text');
|
|
107
|
+
if (textContent) inputText = textContent.text;
|
|
108
|
+
} else if (lastMessage && typeof lastMessage.content === 'string') {
|
|
109
|
+
inputText = lastMessage.content;
|
|
110
|
+
}
|
|
111
|
+
|
|
112
|
+
const lines = [];
|
|
113
|
+
lines.push(` 📝 System: ${ModelMix.truncate(system, 60)}`);
|
|
114
|
+
lines.push(` 💬 Input: ${ModelMix.truncate(inputText, 150)}`);
|
|
115
|
+
lines.push(` 📊 Messages: ${messages.length}`);
|
|
116
|
+
return lines.join('\n');
|
|
117
|
+
}
|
|
118
|
+
|
|
119
|
+
static formatOutputSummary(result) {
|
|
120
|
+
const lines = [];
|
|
121
|
+
if (result.message) {
|
|
122
|
+
lines.push(` 📤 Output: ${ModelMix.truncate(result.message, 200)}`);
|
|
123
|
+
}
|
|
124
|
+
if (result.think) {
|
|
125
|
+
lines.push(` 🧠 Thinking: ${ModelMix.truncate(result.think, 100)}`);
|
|
126
|
+
}
|
|
127
|
+
if (result.toolCalls && result.toolCalls.length > 0) {
|
|
128
|
+
const toolNames = result.toolCalls.map(t => t.function?.name || t.name).join(', ');
|
|
129
|
+
lines.push(` 🔧 Tools: ${toolNames}`);
|
|
130
|
+
}
|
|
131
|
+
return lines.join('\n');
|
|
132
|
+
}
|
|
133
|
+
|
|
82
134
|
attach(key, provider) {
|
|
83
135
|
|
|
84
136
|
if (this.models.some(model => model.key === key)) {
|
|
@@ -102,9 +154,6 @@ class ModelMix {
|
|
|
102
154
|
gpt41nano({ options = {}, config = {} } = {}) {
|
|
103
155
|
return this.attach('gpt-4.1-nano', new MixOpenAI({ options, config }));
|
|
104
156
|
}
|
|
105
|
-
gpt4o({ options = {}, config = {} } = {}) {
|
|
106
|
-
return this.attach('gpt-4o', new MixOpenAI({ options, config }));
|
|
107
|
-
}
|
|
108
157
|
o4mini({ options = {}, config = {} } = {}) {
|
|
109
158
|
return this.attach('o4-mini', new MixOpenAI({ options, config }));
|
|
110
159
|
}
|
|
@@ -276,8 +325,11 @@ class ModelMix {
|
|
|
276
325
|
return this.attach('MiniMax-M2', new MixMiniMax({ options, config }));
|
|
277
326
|
}
|
|
278
327
|
|
|
279
|
-
minimaxM21({ options = {}, config = {} } = {}) {
|
|
280
|
-
|
|
328
|
+
minimaxM21({ options = {}, config = {}, mix = { minimax: true } } = {}) {
|
|
329
|
+
mix = { ...this.mix, ...mix };
|
|
330
|
+
if (mix.minimax) this.attach('MiniMax-M2.1', new MixMiniMax({ options, config }));
|
|
331
|
+
if (mix.cerebras) this.attach('MiniMax-M2.1', new MixCerebras({ options, config }));
|
|
332
|
+
return this;
|
|
281
333
|
}
|
|
282
334
|
|
|
283
335
|
minimaxM2Stable({ options = {}, config = {} } = {}) {
|
|
@@ -292,8 +344,10 @@ class ModelMix {
|
|
|
292
344
|
}
|
|
293
345
|
|
|
294
346
|
GLM47({ options = {}, config = {}, mix = { fireworks: true } } = {}) {
|
|
347
|
+
mix = { ...this.mix, ...mix };
|
|
295
348
|
if (mix.fireworks) this.attach('accounts/fireworks/models/glm-4p7', new MixFireworks({ options, config }));
|
|
296
349
|
if (mix.openrouter) this.attach('z-ai/glm-4.7', new MixOpenRouter({ options, config }));
|
|
350
|
+
if (mix.cerebras) this.attach('zai-glm-4.7', new MixCerebras({ options, config }));
|
|
297
351
|
return this;
|
|
298
352
|
}
|
|
299
353
|
|
|
@@ -656,9 +710,16 @@ class ModelMix {
|
|
|
656
710
|
...config,
|
|
657
711
|
};
|
|
658
712
|
|
|
659
|
-
|
|
713
|
+
const verboseLevel = ModelMix.getVerboseLevel(currentConfig);
|
|
714
|
+
|
|
715
|
+
if (verboseLevel >= 1) {
|
|
660
716
|
const isPrimary = i === 0;
|
|
661
|
-
|
|
717
|
+
const tag = isPrimary ? '🚀' : '🔄';
|
|
718
|
+
console.log(`\n${tag} [${currentModelKey}] Attempt #${i + 1}` + (isPrimary ? '' : ' (Fallback)'));
|
|
719
|
+
}
|
|
720
|
+
|
|
721
|
+
if (verboseLevel >= 2) {
|
|
722
|
+
console.log(ModelMix.formatInputSummary(this.messages, currentConfig.system));
|
|
662
723
|
}
|
|
663
724
|
|
|
664
725
|
try {
|
|
@@ -692,27 +753,36 @@ class ModelMix {
|
|
|
692
753
|
return this.execute();
|
|
693
754
|
}
|
|
694
755
|
|
|
695
|
-
|
|
696
|
-
|
|
756
|
+
// Verbose level 1: Just success indicator
|
|
757
|
+
if (verboseLevel >= 1) {
|
|
758
|
+
console.log(` ✅ Success`);
|
|
759
|
+
}
|
|
760
|
+
|
|
761
|
+
// Verbose level 2: Readable summary of output
|
|
762
|
+
if (verboseLevel >= 2) {
|
|
763
|
+
console.log(ModelMix.formatOutputSummary(result));
|
|
764
|
+
}
|
|
697
765
|
|
|
766
|
+
// Verbose level 3 (debug): Full response details
|
|
767
|
+
if (verboseLevel >= 3) {
|
|
698
768
|
if (result.response) {
|
|
699
|
-
console.log('\
|
|
769
|
+
console.log('\n 📦 RAW RESPONSE:');
|
|
700
770
|
console.log(ModelMix.formatJSON(result.response));
|
|
701
771
|
}
|
|
702
772
|
|
|
703
773
|
if (result.message) {
|
|
704
|
-
console.log('\
|
|
774
|
+
console.log('\n 💬 FULL MESSAGE:');
|
|
705
775
|
console.log(ModelMix.formatMessage(result.message));
|
|
706
776
|
}
|
|
707
777
|
|
|
708
778
|
if (result.think) {
|
|
709
|
-
console.log('\
|
|
779
|
+
console.log('\n 🧠 FULL THINKING:');
|
|
710
780
|
console.log(result.think);
|
|
711
781
|
}
|
|
712
|
-
|
|
713
|
-
console.log('');
|
|
714
782
|
}
|
|
715
783
|
|
|
784
|
+
if (verboseLevel >= 1) console.log('');
|
|
785
|
+
|
|
716
786
|
return result;
|
|
717
787
|
|
|
718
788
|
} catch (error) {
|
|
@@ -940,15 +1010,19 @@ class MixCustom {
|
|
|
940
1010
|
|
|
941
1011
|
options.messages = this.convertMessages(options.messages, config);
|
|
942
1012
|
|
|
943
|
-
|
|
944
|
-
console.log('\nREQUEST:');
|
|
1013
|
+
const verboseLevel = ModelMix.getVerboseLevel(config);
|
|
945
1014
|
|
|
946
|
-
|
|
1015
|
+
// Verbose level 3 (debug): Full request details
|
|
1016
|
+
if (verboseLevel >= 3) {
|
|
1017
|
+
console.log('\n 📡 REQUEST DETAILS:');
|
|
1018
|
+
|
|
1019
|
+
console.log('\n ⚙️ CONFIG:');
|
|
947
1020
|
const configToLog = { ...config };
|
|
948
1021
|
delete configToLog.debug;
|
|
1022
|
+
delete configToLog.verbose;
|
|
949
1023
|
console.log(ModelMix.formatJSON(configToLog));
|
|
950
1024
|
|
|
951
|
-
console.log('\
|
|
1025
|
+
console.log('\n 📋 OPTIONS:');
|
|
952
1026
|
console.log(ModelMix.formatJSON(options));
|
|
953
1027
|
}
|
|
954
1028
|
|
|
@@ -1680,7 +1754,8 @@ class MixGoogle extends MixCustom {
|
|
|
1680
1754
|
functionCall: {
|
|
1681
1755
|
name: toolCall.function.name,
|
|
1682
1756
|
args: JSON.parse(toolCall.function.arguments)
|
|
1683
|
-
}
|
|
1757
|
+
},
|
|
1758
|
+
thought_signature: toolCall.thought_signature || ""
|
|
1684
1759
|
}))
|
|
1685
1760
|
}
|
|
1686
1761
|
}
|
|
@@ -1766,15 +1841,19 @@ class MixGoogle extends MixCustom {
|
|
|
1766
1841
|
};
|
|
1767
1842
|
|
|
1768
1843
|
try {
|
|
1769
|
-
|
|
1770
|
-
console.log('\nREQUEST (GOOGLE):');
|
|
1844
|
+
const verboseLevel = ModelMix.getVerboseLevel(config);
|
|
1771
1845
|
|
|
1772
|
-
|
|
1846
|
+
// Verbose level 3 (debug): Full request details
|
|
1847
|
+
if (verboseLevel >= 3) {
|
|
1848
|
+
console.log('\n 📡 REQUEST DETAILS (GOOGLE):');
|
|
1849
|
+
|
|
1850
|
+
console.log('\n ⚙️ CONFIG:');
|
|
1773
1851
|
const configToLog = { ...config };
|
|
1774
1852
|
delete configToLog.debug;
|
|
1853
|
+
delete configToLog.verbose;
|
|
1775
1854
|
console.log(ModelMix.formatJSON(configToLog));
|
|
1776
1855
|
|
|
1777
|
-
console.log('\
|
|
1856
|
+
console.log('\n 📋 PAYLOAD:');
|
|
1778
1857
|
console.log(ModelMix.formatJSON(payload));
|
|
1779
1858
|
}
|
|
1780
1859
|
|
|
@@ -1808,7 +1887,8 @@ class MixGoogle extends MixCustom {
|
|
|
1808
1887
|
function: {
|
|
1809
1888
|
name: part.functionCall.name,
|
|
1810
1889
|
arguments: JSON.stringify(part.functionCall.args)
|
|
1811
|
-
}
|
|
1890
|
+
},
|
|
1891
|
+
thought_signature: part.thoughtSignature || ""
|
|
1812
1892
|
};
|
|
1813
1893
|
}
|
|
1814
1894
|
return null;
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "modelmix",
|
|
3
|
-
"version": "4.2.
|
|
3
|
+
"version": "4.2.4",
|
|
4
4
|
"description": "🧬 Reliable interface with automatic fallback for AI LLMs.",
|
|
5
5
|
"main": "index.js",
|
|
6
6
|
"repository": {
|
|
@@ -46,7 +46,7 @@
|
|
|
46
46
|
},
|
|
47
47
|
"homepage": "https://github.com/clasen/ModelMix#readme",
|
|
48
48
|
"dependencies": {
|
|
49
|
-
"@modelcontextprotocol/sdk": "^1.
|
|
49
|
+
"@modelcontextprotocol/sdk": "^1.25.2",
|
|
50
50
|
"axios": "^1.12.2",
|
|
51
51
|
"bottleneck": "^2.19.5",
|
|
52
52
|
"file-type": "^16.5.4",
|
package/test/bottleneck.test.js
CHANGED
|
@@ -72,7 +72,7 @@ describe('Rate Limiting with Bottleneck Tests', () => {
|
|
|
72
72
|
it('should enforce minimum time between requests', async () => {
|
|
73
73
|
const startTimes = [];
|
|
74
74
|
|
|
75
|
-
model.
|
|
75
|
+
model.gpt41();
|
|
76
76
|
|
|
77
77
|
// Mock API responses
|
|
78
78
|
nock('https://api.openai.com')
|
|
@@ -122,7 +122,7 @@ describe('Rate Limiting with Bottleneck Tests', () => {
|
|
|
122
122
|
}
|
|
123
123
|
});
|
|
124
124
|
|
|
125
|
-
model.
|
|
125
|
+
model.gpt41();
|
|
126
126
|
|
|
127
127
|
// Mock API with delay to simulate concurrent requests
|
|
128
128
|
nock('https://api.openai.com')
|
|
@@ -184,7 +184,7 @@ describe('Rate Limiting with Bottleneck Tests', () => {
|
|
|
184
184
|
it('should apply rate limiting to OpenAI requests', async () => {
|
|
185
185
|
const requestTimes = [];
|
|
186
186
|
|
|
187
|
-
model.
|
|
187
|
+
model.gpt41();
|
|
188
188
|
|
|
189
189
|
nock('https://api.openai.com')
|
|
190
190
|
.post('/v1/chat/completions')
|
|
@@ -267,7 +267,7 @@ describe('Rate Limiting with Bottleneck Tests', () => {
|
|
|
267
267
|
});
|
|
268
268
|
|
|
269
269
|
it('should handle rate limiting with API errors', async () => {
|
|
270
|
-
model.
|
|
270
|
+
model.gpt41();
|
|
271
271
|
|
|
272
272
|
nock('https://api.openai.com')
|
|
273
273
|
.post('/v1/chat/completions')
|
|
@@ -289,7 +289,7 @@ describe('Rate Limiting with Bottleneck Tests', () => {
|
|
|
289
289
|
it('should continue rate limiting after errors', async () => {
|
|
290
290
|
const requestTimes = [];
|
|
291
291
|
|
|
292
|
-
model.
|
|
292
|
+
model.gpt41();
|
|
293
293
|
|
|
294
294
|
// First request fails
|
|
295
295
|
nock('https://api.openai.com')
|
|
@@ -345,7 +345,7 @@ describe('Rate Limiting with Bottleneck Tests', () => {
|
|
|
345
345
|
}
|
|
346
346
|
});
|
|
347
347
|
|
|
348
|
-
model.
|
|
348
|
+
model.gpt41();
|
|
349
349
|
|
|
350
350
|
let requestCount = 0;
|
|
351
351
|
|
|
@@ -392,7 +392,7 @@ describe('Rate Limiting with Bottleneck Tests', () => {
|
|
|
392
392
|
}
|
|
393
393
|
});
|
|
394
394
|
|
|
395
|
-
model.
|
|
395
|
+
model.gpt41();
|
|
396
396
|
|
|
397
397
|
const results = [];
|
|
398
398
|
|
|
@@ -440,7 +440,7 @@ describe('Rate Limiting with Bottleneck Tests', () => {
|
|
|
440
440
|
}
|
|
441
441
|
});
|
|
442
442
|
|
|
443
|
-
model.
|
|
443
|
+
model.gpt41();
|
|
444
444
|
|
|
445
445
|
nock('https://api.openai.com')
|
|
446
446
|
.post('/v1/chat/completions')
|
|
@@ -489,7 +489,7 @@ describe('Rate Limiting with Bottleneck Tests', () => {
|
|
|
489
489
|
done();
|
|
490
490
|
});
|
|
491
491
|
|
|
492
|
-
model.
|
|
492
|
+
model.gpt41();
|
|
493
493
|
|
|
494
494
|
nock('https://api.openai.com')
|
|
495
495
|
.post('/v1/chat/completions')
|
package/test/images.test.js
CHANGED
|
@@ -25,7 +25,7 @@ describe('Image Processing and Multimodal Support Tests', () => {
|
|
|
25
25
|
it('should handle base64 image data correctly', async () => {
|
|
26
26
|
const base64Image = 'data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAoAAAAKCAYAAACNMs+9AAAAFUlEQVR42mP8z8BQz0AEYBxVSF+FABJADveWkH6oAAAAAElFTkSuQmCC';
|
|
27
27
|
|
|
28
|
-
model.
|
|
28
|
+
model.gpt41()
|
|
29
29
|
.addText('What do you see in this image?')
|
|
30
30
|
.addImageFromUrl(base64Image);
|
|
31
31
|
|
package/test/json.test.js
CHANGED
|
@@ -198,7 +198,7 @@ describe('JSON Schema and Structured Output Tests', () => {
|
|
|
198
198
|
}]
|
|
199
199
|
};
|
|
200
200
|
|
|
201
|
-
model.
|
|
201
|
+
model.gpt41().addText('List 3 countries');
|
|
202
202
|
|
|
203
203
|
// Mock the API response
|
|
204
204
|
nock('https://api.openai.com')
|
|
@@ -270,7 +270,7 @@ describe('JSON Schema and Structured Output Tests', () => {
|
|
|
270
270
|
});
|
|
271
271
|
|
|
272
272
|
it('should handle JSON parsing errors gracefully', async () => {
|
|
273
|
-
model.
|
|
273
|
+
model.gpt41().addText('Generate invalid JSON');
|
|
274
274
|
|
|
275
275
|
// Mock invalid JSON response
|
|
276
276
|
nock('https://api.openai.com')
|
package/test/live.mcp.js
CHANGED
|
@@ -110,8 +110,8 @@ describe('Live MCP Integration Tests', function () {
|
|
|
110
110
|
}
|
|
111
111
|
});
|
|
112
112
|
|
|
113
|
-
it('should use custom MCP tools with Gemini
|
|
114
|
-
const model = ModelMix.new(setup).
|
|
113
|
+
it('should use custom MCP tools with Gemini 3 Flash', async function () {
|
|
114
|
+
const model = ModelMix.new(setup).gemini3flash();
|
|
115
115
|
|
|
116
116
|
// Add password generator tool
|
|
117
117
|
model.addTool({
|
|
@@ -149,11 +149,13 @@ describe('Live MCP Integration Tests', function () {
|
|
|
149
149
|
model.addText('Generate a secure password of 16 characters with symbols.');
|
|
150
150
|
|
|
151
151
|
const response = await model.message();
|
|
152
|
-
console.log(`Gemini
|
|
152
|
+
console.log(`Gemini 3 Flash with MCP tools: ${response}`);
|
|
153
153
|
|
|
154
154
|
expect(response).to.be.a('string');
|
|
155
|
-
|
|
156
|
-
expect(response).to.include('
|
|
155
|
+
// Check password is mentioned and a generated password string is present
|
|
156
|
+
expect(response.toLowerCase()).to.include('password');
|
|
157
|
+
// Verify a generated password is in the response (at least 12 chars with mix of alphanumeric/symbols)
|
|
158
|
+
expect(response).to.match(/[a-zA-Z0-9!@#$%^&*()_+\-=\[\]{}|;:,.<>?]{12,}/);
|
|
157
159
|
});
|
|
158
160
|
|
|
159
161
|
});
|
|
@@ -374,8 +376,8 @@ describe('Live MCP Integration Tests', function () {
|
|
|
374
376
|
expect(result.factorial_result).to.equal(120);
|
|
375
377
|
});
|
|
376
378
|
|
|
377
|
-
it('should use MCP tools with JSON output using Gemini
|
|
378
|
-
const model = ModelMix.new(setup).
|
|
379
|
+
it('should use MCP tools with JSON output using Gemini 3 Flash', async function () {
|
|
380
|
+
const model = ModelMix.new(setup).gemini3flash();
|
|
379
381
|
|
|
380
382
|
// Add system info tool
|
|
381
383
|
model.addTool({
|
|
@@ -414,7 +416,7 @@ describe('Live MCP Integration Tests', function () {
|
|
|
414
416
|
generated_at: ""
|
|
415
417
|
});
|
|
416
418
|
|
|
417
|
-
console.log(`Gemini
|
|
419
|
+
console.log(`Gemini 3 Flash with MCP tools JSON result:`, result);
|
|
418
420
|
|
|
419
421
|
expect(result).to.be.an('object');
|
|
420
422
|
expect(result.timestamp).to.be.a('number');
|
package/test/templates.test.js
CHANGED
|
@@ -27,7 +27,7 @@ describe('Template and File Operations Tests', () => {
|
|
|
27
27
|
});
|
|
28
28
|
|
|
29
29
|
it('should replace simple template variables', async () => {
|
|
30
|
-
model.
|
|
30
|
+
model.gpt41()
|
|
31
31
|
.replace({
|
|
32
32
|
'{{name}}': 'Alice',
|
|
33
33
|
'{{age}}': '30',
|
|
@@ -56,7 +56,7 @@ describe('Template and File Operations Tests', () => {
|
|
|
56
56
|
});
|
|
57
57
|
|
|
58
58
|
it('should handle multiple template replacements', async () => {
|
|
59
|
-
model.
|
|
59
|
+
model.gpt41()
|
|
60
60
|
.replace({ '{{greeting}}': 'Hello' })
|
|
61
61
|
.replace({ '{{name}}': 'Bob' })
|
|
62
62
|
.replace({ '{{action}}': 'welcome' })
|
|
@@ -82,7 +82,7 @@ describe('Template and File Operations Tests', () => {
|
|
|
82
82
|
});
|
|
83
83
|
|
|
84
84
|
it('should handle nested template objects', async () => {
|
|
85
|
-
model.
|
|
85
|
+
model.gpt41()
|
|
86
86
|
.replace({
|
|
87
87
|
'{{user_name}}': 'Charlie',
|
|
88
88
|
'{{user_role}}': 'admin',
|
|
@@ -111,7 +111,7 @@ describe('Template and File Operations Tests', () => {
|
|
|
111
111
|
});
|
|
112
112
|
|
|
113
113
|
it('should preserve unreplaced templates', async () => {
|
|
114
|
-
model.
|
|
114
|
+
model.gpt41()
|
|
115
115
|
.replace({ '{{name}}': 'David' })
|
|
116
116
|
.addText('Hello {{name}}, your ID is {{user_id}} and status is {{status}}');
|
|
117
117
|
|
|
@@ -135,7 +135,7 @@ describe('Template and File Operations Tests', () => {
|
|
|
135
135
|
});
|
|
136
136
|
|
|
137
137
|
it('should handle empty and special character replacements', async () => {
|
|
138
|
-
model.
|
|
138
|
+
model.gpt41()
|
|
139
139
|
.replace({
|
|
140
140
|
'{{empty}}': '',
|
|
141
141
|
'{{special}}': 'Hello & "World" <test>',
|
|
@@ -175,7 +175,7 @@ describe('Template and File Operations Tests', () => {
|
|
|
175
175
|
});
|
|
176
176
|
|
|
177
177
|
it('should load and replace from template file', async () => {
|
|
178
|
-
model.
|
|
178
|
+
model.gpt41()
|
|
179
179
|
.replaceKeyFromFile('{{template}}', path.join(fixturesPath, 'template.txt'))
|
|
180
180
|
.replace({
|
|
181
181
|
'{{name}}': 'Eve',
|
|
@@ -214,7 +214,7 @@ describe('Template and File Operations Tests', () => {
|
|
|
214
214
|
});
|
|
215
215
|
|
|
216
216
|
it('should load and process JSON data file', async () => {
|
|
217
|
-
model.
|
|
217
|
+
model.gpt41()
|
|
218
218
|
.replaceKeyFromFile('{{data}}', path.join(fixturesPath, 'data.json'))
|
|
219
219
|
.addText('Process this data: {{data}}');
|
|
220
220
|
|
|
@@ -246,7 +246,7 @@ describe('Template and File Operations Tests', () => {
|
|
|
246
246
|
});
|
|
247
247
|
|
|
248
248
|
it('should handle file loading errors gracefully', async () => {
|
|
249
|
-
model.
|
|
249
|
+
model.gpt41()
|
|
250
250
|
.replaceKeyFromFile('{{missing}}', path.join(fixturesPath, 'nonexistent.txt'))
|
|
251
251
|
.addText('This should contain: {{missing}}');
|
|
252
252
|
|
|
@@ -271,7 +271,7 @@ describe('Template and File Operations Tests', () => {
|
|
|
271
271
|
});
|
|
272
272
|
|
|
273
273
|
it('should handle multiple file replacements', async () => {
|
|
274
|
-
model.
|
|
274
|
+
model.gpt41()
|
|
275
275
|
.replaceKeyFromFile('{{template}}', path.join(fixturesPath, 'template.txt'))
|
|
276
276
|
.replaceKeyFromFile('{{data}}', path.join(fixturesPath, 'data.json'))
|
|
277
277
|
.replace({
|
|
@@ -315,7 +315,7 @@ describe('Template and File Operations Tests', () => {
|
|
|
315
315
|
it('should handle relative and absolute paths', async () => {
|
|
316
316
|
const absolutePath = path.resolve(fixturesPath, 'template.txt');
|
|
317
317
|
|
|
318
|
-
model.
|
|
318
|
+
model.gpt41()
|
|
319
319
|
.replaceKeyFromFile('{{absolute}}', absolutePath)
|
|
320
320
|
.replace({
|
|
321
321
|
'{{name}}': 'Grace',
|
|
@@ -362,7 +362,7 @@ describe('Template and File Operations Tests', () => {
|
|
|
362
362
|
});
|
|
363
363
|
|
|
364
364
|
it('should combine file loading with template replacement in complex scenarios', async () => {
|
|
365
|
-
model.
|
|
365
|
+
model.gpt41()
|
|
366
366
|
.replaceKeyFromFile('{{user_data}}', path.join(fixturesPath, 'data.json'))
|
|
367
367
|
.replace({
|
|
368
368
|
'{{action}}': 'analyze',
|
|
@@ -402,7 +402,7 @@ describe('Template and File Operations Tests', () => {
|
|
|
402
402
|
roles: ['admin', 'user']
|
|
403
403
|
};
|
|
404
404
|
|
|
405
|
-
model.
|
|
405
|
+
model.gpt41()
|
|
406
406
|
.replaceKeyFromFile('{{data}}', path.join(fixturesPath, 'data.json'))
|
|
407
407
|
.replace({ '{{instruction}}': 'Count active users by role' })
|
|
408
408
|
.addText('{{instruction}} from this data: {{data}}');
|
|
@@ -447,16 +447,16 @@ describe('Template and File Operations Tests', () => {
|
|
|
447
447
|
|
|
448
448
|
it('should handle template replacement errors gracefully', () => {
|
|
449
449
|
expect(() => {
|
|
450
|
-
model.
|
|
450
|
+
model.gpt41().replace(null);
|
|
451
451
|
}).to.not.throw();
|
|
452
452
|
|
|
453
453
|
expect(() => {
|
|
454
|
-
model.
|
|
454
|
+
model.gpt41().replace(undefined);
|
|
455
455
|
}).to.not.throw();
|
|
456
456
|
});
|
|
457
457
|
|
|
458
458
|
it('should handle file reading errors without crashing', async () => {
|
|
459
|
-
model.
|
|
459
|
+
model.gpt41()
|
|
460
460
|
.replaceKeyFromFile('{{bad_file}}', '/path/that/does/not/exist.txt')
|
|
461
461
|
.addText('Content: {{bad_file}}');
|
|
462
462
|
|