@mlx-node/lm 0.0.13 → 0.0.15

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.
Files changed (42) hide show
  1. package/dist/chat-session.d.ts +1 -1
  2. package/dist/chat-session.d.ts.map +1 -1
  3. package/dist/chat-session.js +2 -2
  4. package/dist/draft-companion.d.ts +16 -0
  5. package/dist/draft-companion.d.ts.map +1 -0
  6. package/dist/draft-companion.js +76 -0
  7. package/dist/family-data.d.ts +2 -0
  8. package/dist/family-data.d.ts.map +1 -1
  9. package/dist/family-data.js +2 -0
  10. package/dist/gguf-metadata.d.ts +2 -0
  11. package/dist/gguf-metadata.d.ts.map +1 -0
  12. package/dist/gguf-metadata.js +128 -0
  13. package/dist/model-detection.d.ts +6 -0
  14. package/dist/model-detection.d.ts.map +1 -0
  15. package/dist/model-detection.js +38 -0
  16. package/dist/model-discovery.d.ts +24 -0
  17. package/dist/model-discovery.d.ts.map +1 -0
  18. package/dist/model-discovery.js +274 -0
  19. package/dist/models/model-loader.d.ts +6 -0
  20. package/dist/models/model-loader.d.ts.map +1 -1
  21. package/dist/models/model-loader.js +10 -32
  22. package/dist/models/paged-config-override.d.ts.map +1 -1
  23. package/dist/models/paged-config-override.js +21 -1
  24. package/dist/stream.d.ts.map +1 -1
  25. package/dist/stream.js +5 -5
  26. package/package.json +21 -3
  27. package/src/chat-session.ts +2369 -0
  28. package/src/draft-companion.ts +74 -0
  29. package/src/family-data.ts +542 -0
  30. package/src/gguf-metadata.ts +117 -0
  31. package/src/index.ts +151 -0
  32. package/src/model-detection.ts +46 -0
  33. package/src/model-discovery.ts +329 -0
  34. package/src/models/lfm2-configs.ts +110 -0
  35. package/src/models/model-loader.ts +256 -0
  36. package/src/models/paged-config-override.ts +387 -0
  37. package/src/models/qwen3-configs.ts +113 -0
  38. package/src/models/qwen3_5-configs.ts +60 -0
  39. package/src/profiling.ts +69 -0
  40. package/src/stream.ts +960 -0
  41. package/src/tools/index.ts +58 -0
  42. package/src/tools/types.ts +215 -0
@@ -0,0 +1,58 @@
1
+ /**
2
+ * Tool calling utilities
3
+ *
4
+ * Provides types and helpers for working with tool/function calling
5
+ * through the `ChatSession` API. Tools are passed via `ChatConfig.tools`
6
+ * on `session.send()`, and a tool result is fed back through
7
+ * `session.sendToolResult()`.
8
+ *
9
+ * **Single tool call per assistant turn.** Each `sendToolResult(...)`
10
+ * call appends one tool message and immediately re-opens the assistant
11
+ * turn, so the session API only supports assistant turns that emit
12
+ * exactly one tool call. If the model emits multiple tool calls in a
13
+ * single turn, the caller must treat that as an unsupported state:
14
+ * throw, surface an error to the user, or tighten the system prompt /
15
+ * tool spec so the model produces at most one call per turn. Do **not**
16
+ * loop `sendToolResult` across the remaining calls — later results
17
+ * would be interleaved with a new assistant reply from the first, and
18
+ * the conversation state would become inconsistent (especially for
19
+ * stateful tools whose effects must land in order).
20
+ *
21
+ * @example
22
+ * ```typescript
23
+ * import { createToolDefinition, loadSession } from '@mlx-node/lm';
24
+ *
25
+ * const weatherTool = createToolDefinition(
26
+ * 'get_weather',
27
+ * 'Get weather for a location',
28
+ * { location: { type: 'string', description: 'City name' } },
29
+ * ['location'],
30
+ * );
31
+ *
32
+ * const session = await loadSession('./my-model');
33
+ *
34
+ * const result = await session.send('What is the weather in Tokyo?', {
35
+ * config: { tools: [weatherTool] },
36
+ * });
37
+ *
38
+ * const okCalls = result.toolCalls.filter((c) => c.status === 'ok');
39
+ * if (okCalls.length > 1) {
40
+ * throw new Error(
41
+ * `ChatSession only supports one tool call per assistant turn; ` +
42
+ * `model emitted ${okCalls.length}. Tighten the prompt or tool spec.`,
43
+ * );
44
+ * }
45
+ * const call = okCalls[0];
46
+ * if (call) {
47
+ * const toolOutput = await executeMyTool(call.name, call.arguments);
48
+ * const followUp = await session.sendToolResult(call.id, JSON.stringify(toolOutput), {
49
+ * config: { tools: [weatherTool] },
50
+ * });
51
+ * console.log(followUp.text);
52
+ * }
53
+ * ```
54
+ *
55
+ * @module tools
56
+ */
57
+
58
+ export * from './types.js';
@@ -0,0 +1,215 @@
1
+ /**
2
+ * OpenAI-compatible tool calling types for Qwen3
3
+ *
4
+ * These types match the OpenAI function calling API format and can be used
5
+ * with applyChatTemplate() when tools are provided.
6
+ *
7
+ * @remarks
8
+ * **Important**: Due to NAPI-RS limitations with recursive generic types,
9
+ * `FunctionParameters.properties` must be passed as a JSON string to the Rust layer.
10
+ * Use the {@link createToolDefinition} helper to automatically handle this conversion.
11
+ *
12
+ * @example
13
+ * ```typescript
14
+ * // Recommended: Use the helper function
15
+ * const tool = createToolDefinition('get_weather', 'Get weather info', {
16
+ * location: { type: 'string', description: 'City name' },
17
+ * units: { type: 'string', enum: ['celsius', 'fahrenheit'] }
18
+ * }, ['location']);
19
+ *
20
+ * // Manual approach (if needed)
21
+ * const manualTool: ToolDefinition = {
22
+ * type: 'function',
23
+ * function: {
24
+ * name: 'get_weather',
25
+ * parameters: {
26
+ * type: 'object',
27
+ * properties: JSON.stringify({ location: { type: 'string' } }),
28
+ * required: ['location']
29
+ * }
30
+ * }
31
+ * };
32
+ * ```
33
+ */
34
+
35
+ /**
36
+ * Tool type - currently only "function" is supported
37
+ */
38
+ export type ToolType = 'function';
39
+
40
+ /**
41
+ * Function parameter property definition (JSON Schema subset)
42
+ *
43
+ * This type is used for the developer-friendly API in {@link createToolDefinition}.
44
+ * It represents the structure of JSON Schema properties.
45
+ */
46
+ export interface FunctionParameterProperty {
47
+ type: 'string' | 'number' | 'boolean' | 'integer' | 'array' | 'object';
48
+ description?: string;
49
+ enum?: string[];
50
+ items?: FunctionParameterProperty;
51
+ properties?: Record<string, FunctionParameterProperty>;
52
+ required?: string[];
53
+ }
54
+
55
+ /**
56
+ * Function parameters schema (JSON Schema subset)
57
+ *
58
+ * @remarks
59
+ * **NAPI Limitation**: The `properties` field must be a JSON string, not an object.
60
+ * This is because NAPI-RS cannot expose recursive generic types like
61
+ * `Record<string, FunctionParameterProperty>` directly to Rust.
62
+ *
63
+ * Use {@link createToolDefinition} to avoid manual JSON.stringify() calls.
64
+ */
65
+ export interface FunctionParameters {
66
+ /** Type of the parameters object (always "object") */
67
+ type: 'object';
68
+ /**
69
+ * JSON string of property definitions.
70
+ *
71
+ * @remarks
72
+ * Must be a JSON-stringified object, e.g.: `JSON.stringify({ name: { type: 'string' } })`
73
+ * Use {@link createToolDefinition} helper to avoid manual stringification.
74
+ */
75
+ properties?: string;
76
+ /** List of required parameter names */
77
+ required?: string[];
78
+ }
79
+
80
+ /**
81
+ * Function definition for tool calling
82
+ */
83
+ export interface FunctionDefinition {
84
+ /** Name of the function */
85
+ name: string;
86
+ /** Description of what the function does */
87
+ description?: string;
88
+ /** JSON Schema for the function parameters */
89
+ parameters?: FunctionParameters;
90
+ }
91
+
92
+ /**
93
+ * OpenAI-compatible tool definition
94
+ */
95
+ export interface ToolDefinition {
96
+ /** Tool type (currently only "function" is supported) */
97
+ type: ToolType;
98
+ /** Function definition */
99
+ function: FunctionDefinition;
100
+ }
101
+
102
+ /**
103
+ * Tool call made by an assistant
104
+ */
105
+ export interface ToolCall {
106
+ /** Optional unique identifier for the tool call */
107
+ id?: string;
108
+ /** Name of the tool/function to call */
109
+ name: string;
110
+ /** JSON string of arguments to pass to the tool */
111
+ arguments: string;
112
+ }
113
+
114
+ /**
115
+ * Chat message roles (matches core ChatMessage.role type)
116
+ */
117
+ export type ChatRole = 'system' | 'user' | 'assistant' | 'tool';
118
+
119
+ /**
120
+ * Chat message with tool calling support
121
+ *
122
+ * This extends the basic ChatMessage to support tool calls and responses.
123
+ */
124
+ export interface ChatMessageWithTools {
125
+ /** Message role */
126
+ role: ChatRole;
127
+ /** Message content */
128
+ content: string;
129
+ /** Tool calls made by the assistant (for assistant messages) */
130
+ toolCalls?: ToolCall[];
131
+ /** Tool call ID this message is responding to (for tool messages) */
132
+ toolCallId?: string;
133
+ /** Reasoning content for thinking mode (used with <think> tags) */
134
+ reasoningContent?: string;
135
+ }
136
+
137
+ /**
138
+ * Options for applying chat template with tools
139
+ */
140
+ export interface ApplyChatTemplateOptions {
141
+ /** Whether to add generation prompt at end (default: true) */
142
+ addGenerationPrompt?: boolean;
143
+ /** Array of tool definitions for function calling */
144
+ tools?: ToolDefinition[];
145
+ /**
146
+ * Control thinking mode behavior.
147
+ *
148
+ * @remarks
149
+ * **Counter-intuitive semantics** (from Qwen3's Jinja2 template):
150
+ * - `undefined` or `true`: Model thinks naturally (no tags added)
151
+ * - `false`: Adds empty `<think>\n\n</think>\n\n` tags to **disable** thinking
152
+ *
153
+ * The default is `false` for tool use, which disables thinking to avoid
154
+ * verbose reasoning during tool calls.
155
+ *
156
+ * @example
157
+ * ```typescript
158
+ * // Allow model to think (default behavior without tools)
159
+ * { enableThinking: true }
160
+ *
161
+ * // Disable thinking (adds empty <think></think> tags)
162
+ * { enableThinking: false }
163
+ * ```
164
+ */
165
+ enableThinking?: boolean;
166
+ }
167
+
168
+ /**
169
+ * Create a tool definition with automatic JSON stringification of properties.
170
+ *
171
+ * This helper handles the NAPI-RS limitation where `properties` must be a JSON string.
172
+ *
173
+ * @param name - The function name
174
+ * @param description - Description of what the function does
175
+ * @param properties - Object defining the function parameters (will be JSON stringified)
176
+ * @param required - Array of required parameter names
177
+ * @returns A properly formatted ToolDefinition ready to pass via `ChatConfig.tools`
178
+ * on `ChatSession.send()` / `sendToolResult()`.
179
+ *
180
+ * @example
181
+ * ```typescript
182
+ * const weatherTool = createToolDefinition(
183
+ * 'get_weather',
184
+ * 'Get weather information for a location',
185
+ * {
186
+ * location: { type: 'string', description: 'City name' },
187
+ * units: { type: 'string', enum: ['celsius', 'fahrenheit'] },
188
+ * },
189
+ * ['location'],
190
+ * );
191
+ *
192
+ * const result = await session.send(userPrompt, { config: { tools: [weatherTool] } });
193
+ * ```
194
+ */
195
+ export function createToolDefinition(
196
+ name: string,
197
+ description?: string,
198
+ properties?: Record<string, FunctionParameterProperty>,
199
+ required?: string[],
200
+ ): ToolDefinition {
201
+ return {
202
+ type: 'function',
203
+ function: {
204
+ name,
205
+ description,
206
+ parameters: properties
207
+ ? {
208
+ type: 'object',
209
+ properties: JSON.stringify(properties),
210
+ required,
211
+ }
212
+ : undefined,
213
+ },
214
+ };
215
+ }