modelmix 3.8.4 → 3.8.8

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 CHANGED
@@ -39,7 +39,7 @@ import { ModelMix } from 'modelmix';
39
39
 
40
40
  // Get structured JSON responses
41
41
  const model = ModelMix.new()
42
- .sonnet37() // Anthropic claude-3-7-sonnet-20250219
42
+ .sonnet4() // Anthropic claude-sonnet-4-20250514
43
43
  .addText("Name and capital of 3 South American countries.");
44
44
 
45
45
  const outputExample = { countries: [{ name: "", capital: "" }] };
@@ -58,9 +58,9 @@ const setup = {
58
58
 
59
59
  const model = await ModelMix.new(setup)
60
60
  .sonnet4() // (main model) Anthropic claude-sonnet-4-20250514
61
- .o4mini() // (fallback 1) OpenAI o4-mini
62
- .gemini25proExp({ config: { temperature: 0 } }) // (fallback 2) Google gemini-2.5-pro-exp-03-25
63
- .gpt41nano() // (fallback 3) OpenAI gpt-4.1-nano
61
+ .gpt5mini() // (fallback 1) OpenAI gpt-5-mini
62
+ .gemini25flash({ config: { temperature: 0 } }) // (fallback 2) Google gemini-2.5-flash
63
+ .gpt5nano() // (fallback 3) OpenAI gpt-5-nano
64
64
  .grok3mini() // (fallback 4) Grok grok-3-mini
65
65
  .addText("What's your name?");
66
66
 
@@ -94,7 +94,7 @@ BRAVE_API_KEY="BSA0..._fm"
94
94
  ```
95
95
 
96
96
  ```javascript
97
- const mmix = ModelMix.new({ config: { max_history: 10 } }).gpt41nano();
97
+ const mmix = ModelMix.new({ config: { max_history: 10 } }).gpt5nano();
98
98
  mmix.setSystem('You are an assistant and today is ' + new Date().toISOString());
99
99
 
100
100
  // Add web search capability through MCP
@@ -126,9 +126,8 @@ Here's a comprehensive list of available methods:
126
126
  | `o3()` | OpenAI | o3 | [\$10.00 / \$40.00][1] |
127
127
  | `gptOss()` | Together | gpt-oss-120B | [\$0.15 / \$0.60][7] |
128
128
  | `opus41[think]()` | Anthropic | claude-opus-4-1-20250805 | [\$15.00 / \$75.00][2] |
129
+ | `sonnet45[think]()`| Anthropic | claude-sonnet-4-5-20250929 | [\$3.00 / \$15.00][2] |
129
130
  | `sonnet4[think]()` | Anthropic | claude-sonnet-4-20250514 | [\$3.00 / \$15.00][2] |
130
- | `sonnet37[think]()`| Anthropic | claude-3-7-sonnet-20250219 | [\$3.00 / \$15.00][2] |
131
- | `sonnet35()` | Anthropic | claude-3-5-sonnet-20241022 | [\$3.00 / \$15.00][2] |
132
131
  | `haiku35()` | Anthropic | claude-3-5-haiku-20241022 | [\$0.80 / \$4.00][2] |
133
132
  | `gemini25flash()` | Google | gemini-2.5-flash-preview-04-17 | [\$0.00 / \$0.00][3] |
134
133
  | `gemini25proExp()` | Google | gemini-2.5-pro-exp-03-25 | [\$0.00 / \$0.00][3] |
@@ -331,7 +330,6 @@ new ModelMix(args = { options: {}, config: {} })
331
330
  - **options**: This object contains default options that are applied to all models. These options can be overridden when creating a specific model instance. Examples of default options include:
332
331
  - `max_tokens`: Sets the maximum number of tokens to generate, e.g., 2000.
333
332
  - `temperature`: Controls the randomness of the model's output, e.g., 1.
334
- - `top_p`: Controls the diversity of the output, e.g., 1.
335
333
  - ...(Additional default options can be added as needed)
336
334
  - **config**: This object contains configuration settings that control the behavior of the `ModelMix` instance. These settings can also be overridden for specific model instances. Examples of configuration settings include:
337
335
  - `system`: Sets the default system message for the model, e.g., "You are an assistant."
@@ -0,0 +1,166 @@
1
+ import 'dotenv/config';
2
+ import { ModelMix } from '../index.js';
3
+
4
+ console.log('🧬 ModelMix - Simple MCP Tools Demo');
5
+
6
+ // Simple example: Calculator with custom tool
7
+ async function simpleCalculator() {
8
+ console.log('\n=== Smart Calculator ===');
9
+
10
+ const mmix = ModelMix.new()
11
+ .gpt41nano()
12
+ .setSystem('You are a smart calculator. Use the available tools to perform calculations.');
13
+
14
+ // Add custom tool for advanced operations
15
+ mmix.addTool({
16
+ name: "advanced_math",
17
+ description: "Perform advanced mathematical operations like power, square root, factorial",
18
+ inputSchema: {
19
+ type: "object",
20
+ properties: {
21
+ operation: {
22
+ type: "string",
23
+ enum: ["power", "sqrt", "factorial", "sin", "cos", "tan"],
24
+ description: "Type of operation to perform"
25
+ },
26
+ value: {
27
+ type: "number",
28
+ description: "Input value"
29
+ },
30
+ exponent: {
31
+ type: "number",
32
+ description: "Exponent for power operation (optional)"
33
+ }
34
+ },
35
+ required: ["operation", "value"]
36
+ }
37
+ }, async ({ operation, value, exponent }) => {
38
+ switch (operation) {
39
+ case "power":
40
+ if (exponent === undefined) return "Error: exponent required for power operation";
41
+ return `${value}^${exponent} = ${Math.pow(value, exponent)}`;
42
+ case "sqrt":
43
+ return `√${value} = ${Math.sqrt(value)}`;
44
+ case "factorial":
45
+ if (value < 0 || !Number.isInteger(value)) return "Error: factorial only works with non-negative integers";
46
+ let result = 1;
47
+ for (let i = 2; i <= value; i++) result *= i;
48
+ return `${value}! = ${result}`;
49
+ case "sin":
50
+ return `sin(${value}) = ${Math.sin(value)}`;
51
+ case "cos":
52
+ return `cos(${value}) = ${Math.cos(value)}`;
53
+ case "tan":
54
+ return `tan(${value}) = ${Math.tan(value)}`;
55
+ default:
56
+ return "Unknown operation";
57
+ }
58
+ });
59
+
60
+ // Also add the custom basic calculator
61
+ mmix.addTool({
62
+ name: "calculate",
63
+ description: "Perform basic mathematical calculations",
64
+ inputSchema: {
65
+ type: "object",
66
+ properties: {
67
+ expression: {
68
+ type: "string",
69
+ description: "Mathematical expression to evaluate (e.g., '2 + 2', '10 * 5')"
70
+ }
71
+ },
72
+ required: ["expression"]
73
+ }
74
+ }, async ({ expression }) => {
75
+ try {
76
+ // Sanitize the expression to avoid malicious code
77
+ const sanitized = expression.replace(/[^0-9+\-*/().\s]/g, '');
78
+ const result = eval(sanitized);
79
+ return `${expression} = ${result}`;
80
+ } catch (error) {
81
+ throw new Error(`Invalid mathematical expression: ${expression}`);
82
+ }
83
+ });
84
+
85
+ mmix.addText('Calculate 2^10, the square root of 144, and the factorial of 5');
86
+
87
+ const result = await mmix.message();
88
+ console.log(result);
89
+ }
90
+
91
+ // Example of tool for generating content
92
+ async function contentGenerator() {
93
+ console.log('\n=== Content Generator ===');
94
+
95
+ const mmix = ModelMix.new({ config: { debug: true, max_history: 1 } })
96
+ .gemini25flash()
97
+ .setSystem('You are a creative assistant that can generate different types of content.');
98
+
99
+ // Tool for generating passwords
100
+ mmix.addTool({
101
+ name: "generate_password",
102
+ description: "Generate a secure password with specified criteria",
103
+ inputSchema: {
104
+ type: "object",
105
+ properties: {
106
+ length: {
107
+ type: "integer",
108
+ description: "Length of the password",
109
+ default: 12
110
+ },
111
+ includeSymbols: {
112
+ type: "boolean",
113
+ description: "Include special symbols",
114
+ default: true
115
+ },
116
+ includeNumbers: {
117
+ type: "boolean",
118
+ description: "Include numbers",
119
+ default: true
120
+ }
121
+ }
122
+ }
123
+ }, async ({ length = 12, includeSymbols = true, includeNumbers = true }) => {
124
+
125
+ let password = "@@@@@@@@@@@@";
126
+ return `Generated password (${length} chars): ${password}`;
127
+ });
128
+
129
+ // Tool for generating UUID
130
+ mmix.addTool({
131
+ name: "generate_uuid",
132
+ description: "Generate a UUID (Universally Unique Identifier)",
133
+ inputSchema: {
134
+ type: "object",
135
+ properties: {
136
+ version: {
137
+ type: "string",
138
+ enum: ["v4"],
139
+ description: "UUID version",
140
+ default: "v4"
141
+ }
142
+ }
143
+ }
144
+ }, async ({ version = "v4" }) => {
145
+ // Simple UUID v4 generator
146
+ return 'xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx';
147
+ });
148
+
149
+ mmix.addText('Generate a secure 16-character password with symbols and a UUID');
150
+
151
+ const result = await mmix.message();
152
+ console.log(result);
153
+ }
154
+
155
+ // Run examples
156
+ async function runExamples() {
157
+ try {
158
+ // await simpleCalculator();
159
+ await contentGenerator();
160
+ console.log('\nāœ… Simple examples completed');
161
+ } catch (error) {
162
+ console.error('āŒ Error:', error);
163
+ }
164
+ }
165
+
166
+ runExamples();
@@ -0,0 +1,344 @@
1
+ import 'dotenv/config';
2
+ import { ModelMix } from '../index.js';
3
+ import fs from 'fs';
4
+ import axios from 'axios';
5
+
6
+ console.log('🧬 ModelMix - MCP Tools Demo with Callbacks');
7
+
8
+ // Example 1: Basic predefined tools
9
+ async function example1() {
10
+ console.log('\n=== Example 1: Common Tools ===');
11
+
12
+ const mmix = ModelMix.new({ config: { max_history: 10 } })
13
+ .gpt41nano();
14
+
15
+ // Add custom tools
16
+ mmix.addTool({
17
+ name: "get_current_time",
18
+ description: "Get the current date and time",
19
+ inputSchema: {
20
+ type: "object",
21
+ properties: {
22
+ timezone: {
23
+ type: "string",
24
+ description: "Timezone (optional, defaults to UTC)"
25
+ }
26
+ }
27
+ }
28
+ }, async ({ timezone = 'UTC' }) => {
29
+ const now = new Date();
30
+ if (timezone === 'UTC') {
31
+ return now.toISOString();
32
+ }
33
+ return now.toLocaleString('en-US', { timeZone: timezone });
34
+ });
35
+
36
+ mmix.addTool({
37
+ name: "calculate",
38
+ description: "Perform basic mathematical calculations",
39
+ inputSchema: {
40
+ type: "object",
41
+ properties: {
42
+ expression: {
43
+ type: "string",
44
+ description: "Mathematical expression to evaluate"
45
+ }
46
+ },
47
+ required: ["expression"]
48
+ }
49
+ }, async ({ expression }) => {
50
+ try {
51
+ const sanitized = expression.replace(/[^0-9+\-*/().\s]/g, '');
52
+ const result = eval(sanitized);
53
+ return `${expression} = ${result}`;
54
+ } catch (error) {
55
+ throw new Error(`Invalid mathematical expression: ${expression}`);
56
+ }
57
+ });
58
+
59
+ mmix.setSystem('You are a helpful assistant. Use the available tools when necessary.');
60
+ mmix.addText('What time is it and what is 15 * 23?');
61
+
62
+ console.log(await mmix.message());
63
+ }
64
+
65
+ // Example 2: Custom tool for reading files
66
+ async function example2() {
67
+ console.log('\n=== Example 2: Custom Tool - Read Files ===');
68
+
69
+ const mmix = ModelMix.new({ config: { max_history: 10 } })
70
+ .gpt41nano();
71
+
72
+ // Register custom tool for reading files
73
+ mmix.addTool({
74
+ name: "read_file",
75
+ description: "Read the contents of a file from the filesystem",
76
+ inputSchema: {
77
+ type: "object",
78
+ properties: {
79
+ path: {
80
+ type: "string",
81
+ description: "Path to the file to read"
82
+ }
83
+ },
84
+ required: ["path"]
85
+ }
86
+ }, async ({ path }) => {
87
+ try {
88
+ const content = fs.readFileSync(path, 'utf8');
89
+ return `File content of ${path}:\n\n${content}`;
90
+ } catch (error) {
91
+ return `Error reading file ${path}: ${error.message}`;
92
+ }
93
+ });
94
+
95
+ mmix.setSystem('You are an assistant that can read files. Use the read_file tool when you need to read a file.');
96
+ mmix.addText('Read the contents of the package.json file and tell me what the project name and version are');
97
+
98
+ console.log(await mmix.message());
99
+ }
100
+
101
+ // Example 3: Tool for making HTTP requests
102
+ async function example3() {
103
+ console.log('\n=== Example 3: HTTP Request Tool ===');
104
+
105
+ const mmix = ModelMix.new({ config: { max_history: 10 } })
106
+ .gpt41nano();
107
+
108
+ // Register tool for making HTTP requests
109
+ mmix.addTool({
110
+ name: "http_request",
111
+ description: "Make HTTP requests to external APIs",
112
+ inputSchema: {
113
+ type: "object",
114
+ properties: {
115
+ url: {
116
+ type: "string",
117
+ description: "URL to make the request to"
118
+ },
119
+ method: {
120
+ type: "string",
121
+ enum: ["GET", "POST", "PUT", "DELETE"],
122
+ description: "HTTP method",
123
+ default: "GET"
124
+ }
125
+ },
126
+ required: ["url"]
127
+ }
128
+ }, async ({ url, method = "GET" }) => {
129
+ try {
130
+ const response = await axios({ method, url, timeout: 5000 });
131
+ return `HTTP ${method} ${url}\nStatus: ${response.status}\nResponse: ${JSON.stringify(response.data, null, 2)}`;
132
+ } catch (error) {
133
+ return `Error making HTTP request to ${url}: ${error.message}`;
134
+ }
135
+ });
136
+
137
+ mmix.setSystem('You are an assistant that can make HTTP requests. Use the http_request tool when you need to get data from APIs.');
138
+ mmix.addText('Make a GET request to https://jsonplaceholder.typicode.com/posts/1 and tell me what information it contains');
139
+
140
+ console.log(await mmix.message());
141
+ }
142
+
143
+ // Example 4: Multiple tools working together
144
+ async function example4() {
145
+ console.log('\n=== Example 4: Multiple Tools Working Together ===');
146
+
147
+ const mmix = ModelMix.new({ config: { max_history: 10 } })
148
+ .gpt41nano();
149
+
150
+ // Register multiple tools at once
151
+ mmix.addTools([
152
+ {
153
+ tool: {
154
+ name: "write_file",
155
+ description: "Write content to a file",
156
+ inputSchema: {
157
+ type: "object",
158
+ properties: {
159
+ path: {
160
+ type: "string",
161
+ description: "Path where to write the file"
162
+ },
163
+ content: {
164
+ type: "string",
165
+ description: "Content to write"
166
+ }
167
+ },
168
+ required: ["path", "content"]
169
+ }
170
+ },
171
+ callback: async ({ path, content }) => {
172
+ try {
173
+ fs.writeFileSync(path, content, 'utf8');
174
+ return `Successfully wrote content to ${path}`;
175
+ } catch (error) {
176
+ return `Error writing to file ${path}: ${error.message}`;
177
+ }
178
+ }
179
+ },
180
+ {
181
+ tool: {
182
+ name: "list_files",
183
+ description: "List files in a directory",
184
+ inputSchema: {
185
+ type: "object",
186
+ properties: {
187
+ directory: {
188
+ type: "string",
189
+ description: "Directory to list files from",
190
+ default: "."
191
+ }
192
+ }
193
+ }
194
+ },
195
+ callback: async ({ directory = "." }) => {
196
+ try {
197
+ const files = fs.readdirSync(directory);
198
+ return `Files in ${directory}:\n${files.join('\n')}`;
199
+ } catch (error) {
200
+ return `Error listing files in ${directory}: ${error.message}`;
201
+ }
202
+ }
203
+ }
204
+ ]);
205
+
206
+ // Also add time tool
207
+ mmix.addTool({
208
+ name: "get_current_time",
209
+ description: "Get the current date and time",
210
+ inputSchema: {
211
+ type: "object",
212
+ properties: {
213
+ timezone: {
214
+ type: "string",
215
+ description: "Timezone (optional, defaults to UTC)"
216
+ }
217
+ }
218
+ }
219
+ }, async ({ timezone = 'UTC' }) => {
220
+ const now = new Date();
221
+ if (timezone === 'UTC') {
222
+ return now.toISOString();
223
+ }
224
+ return now.toLocaleString('en-US', { timeZone: timezone });
225
+ });
226
+
227
+ mmix.setSystem('You are an assistant that can handle files and directories. Use the available tools as needed.');
228
+ mmix.addText('List the files in the current directory, then create a file called "demo-output.txt" with the current date and the list of files');
229
+
230
+ console.log(await mmix.message());
231
+ }
232
+
233
+ // Example 5: Combining external MCP with local tools
234
+ async function example5() {
235
+ console.log('\n=== Example 5: External MCP + Local Tools ===');
236
+
237
+ const mmix = ModelMix.new({ config: { max_history: 10 } })
238
+ .gpt41nano();
239
+
240
+ // Add external MCP (if available)
241
+ try {
242
+ await mmix.addMCP('@modelcontextprotocol/server-brave-search');
243
+ console.log('āœ“ MCP Brave Search added');
244
+ } catch (error) {
245
+ console.log('āš ļø MCP Brave Search not available:', error.message);
246
+ }
247
+
248
+ // Add custom local tools
249
+ mmix.addTool({
250
+ name: "get_current_time",
251
+ description: "Get the current date and time",
252
+ inputSchema: {
253
+ type: "object",
254
+ properties: {
255
+ timezone: {
256
+ type: "string",
257
+ description: "Timezone (optional, defaults to UTC)"
258
+ }
259
+ }
260
+ }
261
+ }, async ({ timezone = 'UTC' }) => {
262
+ const now = new Date();
263
+ return timezone === 'UTC' ? now.toISOString() : now.toLocaleString('en-US', { timeZone: timezone });
264
+ });
265
+
266
+ mmix.addTool({
267
+ name: "calculate",
268
+ description: "Perform basic mathematical calculations",
269
+ inputSchema: {
270
+ type: "object",
271
+ properties: {
272
+ expression: {
273
+ type: "string",
274
+ description: "Mathematical expression to evaluate"
275
+ }
276
+ },
277
+ required: ["expression"]
278
+ }
279
+ }, async ({ expression }) => {
280
+ const sanitized = expression.replace(/[^0-9+\-*/().\s]/g, '');
281
+ const result = eval(sanitized);
282
+ return `${expression} = ${result}`;
283
+ });
284
+
285
+ mmix.addTool({
286
+ name: "save_search_result",
287
+ description: "Save search results to a file",
288
+ inputSchema: {
289
+ type: "object",
290
+ properties: {
291
+ filename: {
292
+ type: "string",
293
+ description: "Name of the file to save results"
294
+ },
295
+ content: {
296
+ type: "string",
297
+ description: "Content to save"
298
+ }
299
+ },
300
+ required: ["filename", "content"]
301
+ }
302
+ }, async ({ filename, content }) => {
303
+ try {
304
+ const timestamp = new Date().toISOString();
305
+ const fullContent = `Search Results - ${timestamp}\n\n${content}`;
306
+ fs.writeFileSync(`search-${filename}`, fullContent, 'utf8');
307
+ return `Search results saved to search-${filename}`;
308
+ } catch (error) {
309
+ return `Error saving search results: ${error.message}`;
310
+ }
311
+ });
312
+
313
+ mmix.setSystem('You are an assistant that can search the internet and save results. Use the available tools.');
314
+ mmix.addText('Search for information about "ModelMix npm package" and save the results to a file called "modelmix-info.txt"');
315
+
316
+ console.log(await mmix.message());
317
+ }
318
+
319
+ // Run examples
320
+ async function runExamples() {
321
+ try {
322
+ await example1();
323
+ await example2();
324
+ await example3();
325
+ await example4();
326
+ await example5();
327
+
328
+ console.log('\nāœ… All examples completed');
329
+
330
+ // Show registered tools
331
+ const mmix = ModelMix.new().gpt41nano();
332
+ mmix.addTool({
333
+ name: "example_tool",
334
+ description: "Example tool for demonstration",
335
+ inputSchema: { type: "object", properties: {} }
336
+ }, async () => "Example response");
337
+ console.log('\nšŸ“‹ Available tools:', mmix.listTools());
338
+
339
+ } catch (error) {
340
+ console.error('āŒ Error in examples:', error);
341
+ }
342
+ }
343
+
344
+ runExamples();