modelmix 5.0.1 → 5.0.3
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 +111 -8
- package/RLM_PLUGIN_SPEC.md +465 -0
- package/demo/gemini.js +3 -4
- package/demo/grok.js +2 -2
- package/demo/images.js +2 -2
- package/demo/short.js +3 -3
- package/effort.js +3 -0
- package/index.d.ts +62 -1
- package/index.js +355 -49
- package/package.json +7 -4
- package/plugins/rlm/index.d.ts +194 -0
- package/plugins/rlm/index.js +25 -0
- package/plugins/rlm/lib/budget.js +153 -0
- package/plugins/rlm/lib/isolated-vm-sandbox.js +90 -0
- package/plugins/rlm/lib/markdown.js +156 -0
- package/plugins/rlm/lib/planner-prompt.js +137 -0
- package/plugins/rlm/lib/plugin.js +203 -0
- package/plugins/rlm/lib/runtime.js +146 -0
- package/plugins/rlm/lib/variable-descriptors.js +228 -0
- package/plugins/rlm/lib/worker-catalog.js +70 -0
- package/plugins/rlm/package.json +32 -0
- package/plugins/rlm/prompts/partials/processing-rules.md +8 -0
- package/plugins/rlm/prompts/planner.md +53 -0
- package/plugins/rlm/test/budget.test.js +86 -0
- package/plugins/rlm/test/fixtures/book.md +24 -0
- package/plugins/rlm/test/isolated-vm-sandbox.test.js +114 -0
- package/plugins/rlm/test/markdown.test.js +64 -0
- package/plugins/rlm/test/planner-template.test.js +140 -0
- package/plugins/rlm/test/plugin-contract.test.js +182 -0
- package/plugins/rlm/test/rlm-e2e.test.js +338 -0
- package/plugins/rlm/test/variable-descriptors.test.js +170 -0
- package/plugins/rlm/test/worker-catalog.test.js +104 -0
- package/pnpm-workspace.yaml +6 -0
- package/skills/modelmix/SKILL.md +23 -4
- package/test/effort.test.js +14 -1
- package/test/grok.test.js +74 -0
- package/test/live.mcp.js +8 -8
- package/test/live.test.js +9 -9
- package/test/plugins.test.js +356 -0
- package/test/tokens.test.js +37 -5
package/demo/images.js
CHANGED
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
import { ModelMix } from '../index.js';
|
|
2
2
|
try { process.loadEnvFile(); } catch {}
|
|
3
3
|
|
|
4
|
-
const model = ModelMix.new({ config: { max_history: 2, debug: 2 } }).
|
|
4
|
+
const model = ModelMix.new({ config: { max_history: 2, debug: 2 } }).grok46()
|
|
5
5
|
// model.addImageFromUrl('https://pbs.twimg.com/media/F6-GsjraAAADDGy?format=jpg');
|
|
6
6
|
model.addImage('./img.png');
|
|
7
7
|
model.addText('in one word, which is the main color of the image?');
|
|
8
8
|
|
|
9
|
-
console.log(await model.json({ color: "string" }));
|
|
9
|
+
console.log(await model.json({ color: "string" }));
|
package/demo/short.js
CHANGED
|
@@ -11,9 +11,9 @@ const setup = {
|
|
|
11
11
|
const mmix = await ModelMix.new(setup)
|
|
12
12
|
.sonnet46() // (main model) Anthropic claude-sonnet-4-6
|
|
13
13
|
.gpt56luna() // (fallback 1) OpenAI gpt-5.6-luna
|
|
14
|
-
.
|
|
14
|
+
.gemini37flash() // (fallback 2) Google gemini-3.7-flash
|
|
15
15
|
.gpt41nano() // (fallback 3) OpenAI gpt-4.1-nano
|
|
16
|
-
.
|
|
16
|
+
.grok46() // (fallback 4) Grok grok-4.6
|
|
17
17
|
.addText("What's your name?");
|
|
18
18
|
|
|
19
|
-
console.log(await mmix.message());
|
|
19
|
+
console.log(await mmix.message());
|
package/effort.js
CHANGED
|
@@ -35,6 +35,7 @@ const GEMINI_BANDS = [
|
|
|
35
35
|
|
|
36
36
|
/** Exact model → supported OpenAI reasoning_effort values */
|
|
37
37
|
const OPENAI_MODEL_LEVELS = {
|
|
38
|
+
'grok-4.6': ['low', 'medium', 'high', 'xhigh'],
|
|
38
39
|
'gpt-5': ['minimal', 'low', 'medium', 'high'],
|
|
39
40
|
'gpt-5-mini': ['minimal', 'low', 'medium', 'high'],
|
|
40
41
|
'gpt-5-nano': ['minimal', 'low', 'medium', 'high'],
|
|
@@ -69,6 +70,7 @@ const MINIMAX_BANDS = [
|
|
|
69
70
|
|
|
70
71
|
/** Exact model → supported Gemini thinkingLevel values */
|
|
71
72
|
const GEMINI_MODEL_LEVELS = {
|
|
73
|
+
'gemini-3.7-flash': ['low', 'medium', 'high'],
|
|
72
74
|
'gemini-3-pro-preview': ['low', 'high'],
|
|
73
75
|
'gemini-3.1-pro-preview': ['low', 'medium', 'high'],
|
|
74
76
|
'gemini-2.5-pro': ['low', 'medium', 'high'],
|
|
@@ -289,6 +291,7 @@ function mapAdaptiveEffort(providerFamily, modelKey) {
|
|
|
289
291
|
return { thinking: { type: 'adaptive' } };
|
|
290
292
|
}
|
|
291
293
|
if (providerFamily === 'google') {
|
|
294
|
+
if (modelKey === 'gemini-3.7-flash') return null;
|
|
292
295
|
// Gemini dynamic thinking: thinkingBudget -1 (2.5 official; accepted on 3.x as dynamic)
|
|
293
296
|
return { thinkingConfig: { thinkingBudget: -1 } };
|
|
294
297
|
}
|
package/index.d.ts
CHANGED
|
@@ -161,6 +161,8 @@ export interface TokenCostBreakdown {
|
|
|
161
161
|
export interface TokenUsage {
|
|
162
162
|
input: number;
|
|
163
163
|
output: number;
|
|
164
|
+
/** Internal reasoning tokens billed at the output rate when reported separately. */
|
|
165
|
+
thinking: number;
|
|
164
166
|
total: number;
|
|
165
167
|
cached: number;
|
|
166
168
|
cacheWrite: number;
|
|
@@ -187,9 +189,59 @@ export interface ModelMixResult {
|
|
|
187
189
|
tokens?: TokenUsage;
|
|
188
190
|
response?: unknown;
|
|
189
191
|
assistantMessage?: ChatMessage;
|
|
192
|
+
execution?: PluginExecutionMetadata;
|
|
190
193
|
[key: string]: unknown;
|
|
191
194
|
}
|
|
192
195
|
|
|
196
|
+
export type ModelMixOutputMode = 'message' | 'json' | 'block' | 'raw' | 'stream';
|
|
197
|
+
|
|
198
|
+
export interface PluginExecutionMetadata {
|
|
199
|
+
executionId: string;
|
|
200
|
+
parentExecutionId: string | null;
|
|
201
|
+
depth: number;
|
|
202
|
+
}
|
|
203
|
+
|
|
204
|
+
export type PluginInheritancePolicy =
|
|
205
|
+
| 'inherit'
|
|
206
|
+
| 'none'
|
|
207
|
+
| { include: string[] }
|
|
208
|
+
| { exclude: string[] };
|
|
209
|
+
|
|
210
|
+
export interface ChildInvocation {
|
|
211
|
+
system?: string;
|
|
212
|
+
systemFile?: string;
|
|
213
|
+
assign?: Record<string, unknown>;
|
|
214
|
+
messages: ChatMessage[];
|
|
215
|
+
tools?: ToolWithCallback[];
|
|
216
|
+
options?: ModelMixOptions;
|
|
217
|
+
config?: ModelMixConfig;
|
|
218
|
+
mix?: ModelMixMixFlags;
|
|
219
|
+
model?: ModelMix;
|
|
220
|
+
plugins?: PluginInheritancePolicy;
|
|
221
|
+
history?: false;
|
|
222
|
+
outputMode?: ModelMixOutputMode;
|
|
223
|
+
}
|
|
224
|
+
|
|
225
|
+
export interface PluginExecutionContext {
|
|
226
|
+
request: {
|
|
227
|
+
system: string;
|
|
228
|
+
messages: ChatMessage[];
|
|
229
|
+
options: ModelMixOptions;
|
|
230
|
+
config: ModelMixConfig;
|
|
231
|
+
outputMode: ModelMixOutputMode;
|
|
232
|
+
};
|
|
233
|
+
execution: Readonly<PluginExecutionMetadata>;
|
|
234
|
+
invoke(input: ChildInvocation): Promise<ModelMixResult>;
|
|
235
|
+
}
|
|
236
|
+
|
|
237
|
+
export interface ModelMixPlugin {
|
|
238
|
+
name: string;
|
|
239
|
+
execute(
|
|
240
|
+
context: PluginExecutionContext,
|
|
241
|
+
next: () => Promise<ModelMixResult>
|
|
242
|
+
): Promise<ModelMixResult>;
|
|
243
|
+
}
|
|
244
|
+
|
|
193
245
|
export interface StreamChunk {
|
|
194
246
|
response: unknown;
|
|
195
247
|
message: string;
|
|
@@ -263,6 +315,7 @@ export interface ProviderConstructorArgs {
|
|
|
263
315
|
export interface CreateArgs {
|
|
264
316
|
config?: ModelMixConfig;
|
|
265
317
|
options?: ModelMixOptions;
|
|
318
|
+
outputMode?: ModelMixOutputMode;
|
|
266
319
|
}
|
|
267
320
|
|
|
268
321
|
export type ProviderFamily =
|
|
@@ -279,6 +332,7 @@ export declare class ModelMix {
|
|
|
279
332
|
tools: Record<string, ToolDefinition[]>;
|
|
280
333
|
toolClient: Record<string, unknown>;
|
|
281
334
|
mcp: Record<string, unknown>;
|
|
335
|
+
plugins: ModelMixPlugin[];
|
|
282
336
|
options: ModelMixOptions;
|
|
283
337
|
config: ModelMixConfig;
|
|
284
338
|
mix: ModelMixMixFlags;
|
|
@@ -288,6 +342,7 @@ export declare class ModelMix {
|
|
|
288
342
|
constructor(setup?: ModelMixSetup);
|
|
289
343
|
|
|
290
344
|
static new(setup?: ModelMixSetup): ModelMix;
|
|
345
|
+
use(plugin: ModelMixPlugin): this;
|
|
291
346
|
static formatJSON(obj: unknown): string;
|
|
292
347
|
static formatMessage(message: unknown): unknown;
|
|
293
348
|
static truncate(str: string, maxLen?: number): string;
|
|
@@ -296,6 +351,7 @@ export declare class ModelMix {
|
|
|
296
351
|
tokens: {
|
|
297
352
|
input: number;
|
|
298
353
|
output: number;
|
|
354
|
+
thinking?: number;
|
|
299
355
|
total?: number;
|
|
300
356
|
cached?: number;
|
|
301
357
|
cacheWrite?: number;
|
|
@@ -308,6 +364,7 @@ export declare class ModelMix {
|
|
|
308
364
|
tokens: {
|
|
309
365
|
input: number;
|
|
310
366
|
output: number;
|
|
367
|
+
thinking?: number;
|
|
311
368
|
total?: number;
|
|
312
369
|
cached?: number;
|
|
313
370
|
cacheWrite?: number;
|
|
@@ -320,6 +377,7 @@ export declare class ModelMix {
|
|
|
320
377
|
tokens: {
|
|
321
378
|
input: number;
|
|
322
379
|
output: number;
|
|
380
|
+
thinking?: number;
|
|
323
381
|
total?: number;
|
|
324
382
|
cached?: number;
|
|
325
383
|
cacheWrite?: number;
|
|
@@ -330,6 +388,7 @@ export declare class ModelMix {
|
|
|
330
388
|
static normalizeTokenUsage(tokens?: {
|
|
331
389
|
input?: number;
|
|
332
390
|
output?: number;
|
|
391
|
+
thinking?: number;
|
|
333
392
|
total?: number;
|
|
334
393
|
cached?: number;
|
|
335
394
|
cacheWrite?: number;
|
|
@@ -395,6 +454,7 @@ export declare class ModelMix {
|
|
|
395
454
|
gemini31pro(args?: ModelAttachArgs): this;
|
|
396
455
|
gemini3pro(args?: ModelAttachArgs): this;
|
|
397
456
|
gemini3flash(args?: ModelAttachArgs): this;
|
|
457
|
+
gemini37flash(args?: ModelAttachArgs): this;
|
|
398
458
|
gemini36flash(args?: ModelAttachArgs): this;
|
|
399
459
|
gemini35flash(args?: ModelAttachArgs): this;
|
|
400
460
|
gemini35flashLite(args?: ModelAttachArgs): this;
|
|
@@ -406,6 +466,7 @@ export declare class ModelMix {
|
|
|
406
466
|
sonar(args?: ModelAttachArgs): this;
|
|
407
467
|
|
|
408
468
|
// Grok
|
|
469
|
+
grok46(args?: ModelAttachArgs): this;
|
|
409
470
|
grok45(args?: ModelAttachArgs): this;
|
|
410
471
|
grok43(args?: ModelAttachArgs): this;
|
|
411
472
|
grok420multiAgent(args?: ModelAttachArgs): this;
|
|
@@ -454,7 +515,7 @@ export declare class ModelMix {
|
|
|
454
515
|
|
|
455
516
|
assignKeyFromFile(key: string, filePath: string): this;
|
|
456
517
|
groupByRoles(messages: ChatMessage[]): ChatMessage[];
|
|
457
|
-
prepareMessages(): Promise<
|
|
518
|
+
prepareMessages(): Promise<ChatMessage[]>;
|
|
458
519
|
readFile(filePath: string, options?: { encoding?: BufferEncoding | null }): string | Buffer;
|
|
459
520
|
execute(args?: CreateArgs): Promise<ModelMixResult>;
|
|
460
521
|
processToolCalls(toolCalls: ToolCall[]): Promise<
|