@node-llm/core 1.5.0 → 1.5.2

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 (47) hide show
  1. package/dist/aliases.d.ts +563 -71
  2. package/dist/aliases.d.ts.map +1 -1
  3. package/dist/aliases.js +569 -77
  4. package/dist/chat/Chat.d.ts +8 -21
  5. package/dist/chat/Chat.d.ts.map +1 -1
  6. package/dist/chat/Chat.js +76 -122
  7. package/dist/chat/ChatOptions.d.ts +3 -3
  8. package/dist/chat/ChatOptions.d.ts.map +1 -1
  9. package/dist/chat/ChatStream.d.ts +3 -21
  10. package/dist/chat/ChatStream.d.ts.map +1 -1
  11. package/dist/chat/ChatStream.js +95 -97
  12. package/dist/chat/Content.d.ts +10 -0
  13. package/dist/chat/Content.d.ts.map +1 -1
  14. package/dist/chat/Content.js +34 -1
  15. package/dist/chat/Tool.d.ts +6 -0
  16. package/dist/chat/Tool.d.ts.map +1 -1
  17. package/dist/chat/ToolHandler.d.ts +11 -0
  18. package/dist/chat/ToolHandler.d.ts.map +1 -0
  19. package/dist/chat/ToolHandler.js +41 -0
  20. package/dist/chat/Validation.d.ts +10 -0
  21. package/dist/chat/Validation.d.ts.map +1 -0
  22. package/dist/chat/Validation.js +32 -0
  23. package/dist/config.d.ts +43 -14
  24. package/dist/config.d.ts.map +1 -1
  25. package/dist/config.js +58 -13
  26. package/dist/errors/index.d.ts +8 -0
  27. package/dist/errors/index.d.ts.map +1 -1
  28. package/dist/errors/index.js +13 -0
  29. package/dist/llm.d.ts.map +1 -1
  30. package/dist/llm.js +13 -3
  31. package/dist/models/models.d.ts +113 -1427
  32. package/dist/models/models.d.ts.map +1 -1
  33. package/dist/models/models.js +5700 -24218
  34. package/dist/models/types.js +0 -3
  35. package/dist/providers/openai/Capabilities.d.ts +1 -0
  36. package/dist/providers/openai/Capabilities.d.ts.map +1 -1
  37. package/dist/providers/openai/Capabilities.js +3 -0
  38. package/dist/providers/openai/Chat.d.ts.map +1 -1
  39. package/dist/providers/openai/Chat.js +11 -3
  40. package/dist/providers/openai/Streaming.d.ts.map +1 -1
  41. package/dist/providers/openai/Streaming.js +6 -1
  42. package/dist/providers/openai/types.d.ts +4 -0
  43. package/dist/providers/openai/types.d.ts.map +1 -1
  44. package/dist/utils/fetch.d.ts.map +1 -1
  45. package/dist/utils/fetch.js +2 -0
  46. package/dist/utils/logger.js +1 -1
  47. package/package.json +1 -1
@@ -1,8 +1,9 @@
1
1
  import { Message } from "./Message.js";
2
+ import { ContentPart } from "./Content.js";
2
3
  import { ChatOptions } from "./ChatOptions.js";
3
4
  import { Provider, Usage, ChatChunk } from "../providers/Provider.js";
4
5
  import { Stream } from "../streaming/Stream.js";
5
- import { Tool } from "./Tool.js";
6
+ import { ToolResolvable } from "./Tool.js";
6
7
  import { Schema } from "../schema/Schema.js";
7
8
  import { z } from "zod";
8
9
  import { ToolExecutionMode } from "../constants.js";
@@ -40,7 +41,7 @@ export declare class Chat {
40
41
  * Add a tool to the chat session (fluent API)
41
42
  * Supports passing a tool instance or a tool class (which will be instantiated).
42
43
  */
43
- withTool(tool: any): this;
44
+ withTool(tool: ToolResolvable): this;
44
45
  /**
45
46
  * Add multiple tools to the chat session.
46
47
  * Supports passing Tool classes (which will be instantiated) or instances.
@@ -49,9 +50,7 @@ export declare class Chat {
49
50
  * @example
50
51
  * chat.withTools([WeatherTool, new CalculatorTool()], { replace: true });
51
52
  */
52
- withTools(tools: (Tool | {
53
- new (): Tool;
54
- } | any)[], options?: {
53
+ withTools(tools: ToolResolvable[], options?: {
55
54
  replace?: boolean;
56
55
  }): this;
57
56
  /**
@@ -107,10 +106,7 @@ export declare class Chat {
107
106
  * Called when a tool call ends successfully.
108
107
  */
109
108
  onToolCallEnd(handler: (toolCall: any, result: any) => void): this;
110
- /**
111
- * Called when a tool call fails.
112
- */
113
- onToolCallError(handler: (toolCall: any, error: Error) => void): this;
109
+ onToolCallError(handler: (toolCall: any, error: Error) => 'STOP' | 'CONTINUE' | void | Promise<'STOP' | 'CONTINUE' | void>): this;
114
110
  /**
115
111
  * Set the tool execution mode.
116
112
  * - "auto": (Default) Automatically execute all tool calls.
@@ -140,19 +136,10 @@ export declare class Chat {
140
136
  /**
141
137
  * Streams the model's response to a user question.
142
138
  */
143
- stream(content: string): Stream<ChatChunk>;
144
- /**
145
- * Check if tool execution should proceed based on the current mode.
146
- */
147
- private shouldExecuteTools;
148
- /**
149
- * Request user confirmation for a tool call in "confirm" mode.
150
- * Returns true if approved, false if rejected.
151
- */
152
- private requestToolConfirmation;
139
+ stream(content: string | ContentPart[], options?: AskOptions): Stream<ChatChunk>;
153
140
  /**
154
- * Execute a single tool call and return the result message.
141
+ * Normalizes a ToolResolvable into a ToolDefinition.
155
142
  */
156
- private executeToolCall;
143
+ private normalizeTool;
157
144
  }
158
145
  //# sourceMappingURL=Chat.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"Chat.d.ts","sourceRoot":"","sources":["../../src/chat/Chat.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,OAAO,EAAE,MAAM,cAAc,CAAC;AACvC,OAAO,EAAE,WAAW,EAAE,MAAM,kBAAkB,CAAC;AAC/C,OAAO,EAAE,QAAQ,EAAE,KAAK,EAAE,SAAS,EAAE,MAAM,0BAA0B,CAAC;AAGtE,OAAO,EAAE,MAAM,EAAE,MAAM,wBAAwB,CAAC;AAChD,OAAO,EAAE,IAAI,EAAkB,MAAM,WAAW,CAAC;AACjD,OAAO,EAAE,MAAM,EAAE,MAAM,qBAAqB,CAAC;AAE7C,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AAExB,OAAO,EAAE,iBAAiB,EAAE,MAAM,iBAAiB,CAAC;AAEpD,MAAM,WAAW,UAAU;IACzB,MAAM,CAAC,EAAE,MAAM,EAAE,CAAC;IAClB,KAAK,CAAC,EAAE,MAAM,EAAE,CAAC;IACjB,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,OAAO,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IACjC,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,cAAc,CAAC,EAAE,MAAM,CAAC;CACzB;AAED,OAAO,EAAE,kBAAkB,EAAE,MAAM,mBAAmB,CAAC;AAEvD,qBAAa,IAAI;IAMb,OAAO,CAAC,QAAQ,CAAC,QAAQ;IACzB,OAAO,CAAC,KAAK;IACb,OAAO,CAAC,QAAQ,CAAC,OAAO;IAP1B,OAAO,CAAC,QAAQ,CAAiB;IACjC,OAAO,CAAC,cAAc,CAAiB;IACvC,OAAO,CAAC,QAAQ,CAAW;gBAGR,QAAQ,EAAE,QAAQ,EAC3B,KAAK,EAAE,MAAM,EACJ,OAAO,GAAE,WAAgB,EAC1C,WAAW,GAAE;QAAE,QAAQ,EAAE,MAAM,CAAC;QAAC,OAAO,EAAE,MAAM,CAAA;KAAgC;IA0BlF;;OAEG;IACH,IAAI,OAAO,IAAI,SAAS,OAAO,EAAE,CAEhC;IAED,IAAI,OAAO,IAAI,MAAM,CAEpB;IAED;;OAEG;IACH,IAAI,UAAU,IAAI,KAAK,CAetB;IAED;;;OAGG;IACH,QAAQ,CAAC,IAAI,EAAE,GAAG,GAAG,IAAI;IAIvB;;;;;;;KAOC;IACH,SAAS,CAAC,KAAK,EAAE,CAAC,IAAI,GAAG;QAAE,QAAO,IAAI,CAAA;KAAE,GAAG,GAAG,CAAC,EAAE,EAAE,OAAO,CAAC,EAAE;QAAE,OAAO,CAAC,EAAE,OAAO,CAAA;KAAE,GAAG,IAAI;IAmCzF;;;;OAIG;IACH,gBAAgB,CAAC,WAAW,EAAE,MAAM,EAAE,OAAO,CAAC,EAAE;QAAE,OAAO,CAAC,EAAE,OAAO,CAAA;KAAE,GAAG,IAAI;IAW5E;;OAEG;IACH,gBAAgB,CAAC,WAAW,EAAE,MAAM,EAAE,OAAO,CAAC,EAAE;QAAE,OAAO,CAAC,EAAE,OAAO,CAAA;KAAE,GAAG,IAAI;IAI5E;;;OAGG;IACH,eAAe,CAAC,IAAI,EAAE,MAAM,GAAG,IAAI;IAKnC;;OAEG;IACH,SAAS,CAAC,KAAK,EAAE,MAAM,GAAG,IAAI;IAK9B;;;OAGG;IACH,kBAAkB,CAAC,OAAO,EAAE;QAAE,OAAO,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;QAAC,cAAc,CAAC,EAAE,GAAG,CAAA;KAAE,GAAG,IAAI;IAU7F;;;OAGG;IACH,UAAU,CAAC,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,GAAG,IAAI;IAK7C;;;OAGG;IACH,UAAU,CAAC,MAAM,EAAE,MAAM,GAAG,CAAC,CAAC,OAAO,CAAC,GAAG,CAAC,GAAG,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,GAAG,IAAI,GAAG,IAAI;IAkB9E,YAAY,CAAC,OAAO,EAAE,MAAM,IAAI,GAAG,IAAI;IAKvC,YAAY,CAAC,OAAO,EAAE,CAAC,OAAO,EAAE,kBAAkB,KAAK,IAAI,GAAG,IAAI;IAKlE,UAAU,CAAC,OAAO,EAAE,CAAC,QAAQ,EAAE,GAAG,KAAK,IAAI,GAAG,IAAI;IAIlD,YAAY,CAAC,OAAO,EAAE,CAAC,MAAM,EAAE,GAAG,KAAK,IAAI,GAAG,IAAI;IAIlD;;OAEG;IACH,eAAe,CAAC,OAAO,EAAE,CAAC,QAAQ,EAAE,GAAG,KAAK,IAAI,GAAG,IAAI;IAKvD;;OAEG;IACH,aAAa,CAAC,OAAO,EAAE,CAAC,QAAQ,EAAE,GAAG,EAAE,MAAM,EAAE,GAAG,KAAK,IAAI,GAAG,IAAI;IAKlE;;OAEG;IACH,eAAe,CAAC,OAAO,EAAE,CAAC,QAAQ,EAAE,GAAG,EAAE,KAAK,EAAE,KAAK,KAAK,IAAI,GAAG,IAAI;IAKrE;;;;;OAKG;IACH,iBAAiB,CAAC,IAAI,EAAE,iBAAiB,GAAG,IAAI;IAKhD;;;OAGG;IACH,iBAAiB,CAAC,OAAO,EAAE,CAAC,QAAQ,EAAE,GAAG,KAAK,OAAO,CAAC,OAAO,CAAC,GAAG,OAAO,GAAG,IAAI;IAK/E;;;OAGG;IACH,aAAa,CAAC,OAAO,EAAE,CAAC,QAAQ,EAAE,OAAO,EAAE,KAAK,OAAO,CAAC,OAAO,EAAE,GAAG,IAAI,CAAC,GAAG,IAAI;IAKhF;;;OAGG;IACH,aAAa,CAAC,OAAO,EAAE,CAAC,QAAQ,EAAE,kBAAkB,KAAK,OAAO,CAAC,kBAAkB,GAAG,IAAI,CAAC,GAAG,IAAI;IAKlG;;OAEG;IACG,GAAG,CAAC,OAAO,EAAE,MAAM,GAAG,GAAG,EAAE,EAAE,OAAO,CAAC,EAAE,UAAU,GAAG,OAAO,CAAC,kBAAkB,CAAC;IA0OrF;;OAEG;IACH,MAAM,CAAC,OAAO,EAAE,MAAM,GAAG,MAAM,CAAC,SAAS,CAAC;IAK1C;;OAEG;IACH,OAAO,CAAC,kBAAkB;IAM1B;;;OAGG;YACW,uBAAuB;IASrC;;OAEG;YACW,eAAe;CA2C9B"}
1
+ {"version":3,"file":"Chat.d.ts","sourceRoot":"","sources":["../../src/chat/Chat.ts"],"names":[],"mappings":"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"}
package/dist/chat/Chat.js CHANGED
@@ -1,4 +1,5 @@
1
1
  import { FileLoader } from "../utils/FileLoader.js";
2
+ import { isBinaryContent, formatMultimodalContent } from "./Content.js";
2
3
  import { Executor } from "../executor/Executor.js";
3
4
  import { ChatStream } from "./ChatStream.js";
4
5
  import { Schema } from "../schema/Schema.js";
@@ -6,6 +7,9 @@ import { toJsonSchema } from "../schema/to-json-schema.js";
6
7
  import { z } from "zod";
7
8
  import { config } from "../config.js";
8
9
  import { ToolExecutionMode } from "../constants.js";
10
+ import { ConfigurationError } from "../errors/index.js";
11
+ import { ChatValidator } from "./Validation.js";
12
+ import { ToolHandler } from "./ToolHandler.js";
9
13
  import { ChatResponseString } from "./ChatResponse.js";
10
14
  export class Chat {
11
15
  provider;
@@ -35,6 +39,11 @@ export class Chat {
35
39
  if (!this.options.toolExecution) {
36
40
  this.options.toolExecution = config.toolExecution || ToolExecutionMode.AUTO;
37
41
  }
42
+ if (options.tools) {
43
+ const toolList = options.tools;
44
+ this.options.tools = []; // Clear and re-add via normalized method
45
+ this.withTools(toolList);
46
+ }
38
47
  }
39
48
  /**
40
49
  * Read-only access to message history
@@ -84,27 +93,9 @@ export class Chat {
84
93
  this.options.tools = [];
85
94
  }
86
95
  for (const tool of tools) {
87
- let toolInstance;
88
- // Handle class constructor
89
- if (typeof tool === "function") {
90
- try {
91
- toolInstance = new tool();
92
- }
93
- catch (e) {
94
- console.error(`[NodeLLM] Failed to instantiate tool class: ${tool.name}`, e);
95
- continue;
96
- }
97
- }
98
- else {
99
- toolInstance = tool;
100
- }
101
- // Normalized to standard ToolDefinition interface if it's a Tool class instance
102
- if (toolInstance && typeof toolInstance.toLLMTool === "function") {
103
- this.options.tools.push(toolInstance.toLLMTool());
104
- }
105
- else {
106
- // Fallback for legacy raw tool objects (defined as objects with type: 'function')
107
- this.options.tools.push(toolInstance);
96
+ const normalized = this.normalizeTool(tool);
97
+ if (normalized) {
98
+ this.options.tools.push(normalized);
108
99
  }
109
100
  }
110
101
  return this;
@@ -213,9 +204,6 @@ export class Chat {
213
204
  this.options.onToolCallEnd = handler;
214
205
  return this;
215
206
  }
216
- /**
217
- * Called when a tool call fails.
218
- */
219
207
  onToolCallError(handler) {
220
208
  this.options.onToolCallError = handler;
221
209
  return this;
@@ -261,41 +249,13 @@ export class Chat {
261
249
  let messageContent = content;
262
250
  const files = [...(options?.images ?? []), ...(options?.files ?? [])];
263
251
  if (files.length > 0) {
264
- const processedFiles = await Promise.all(files.map(f => FileLoader.load(f)));
265
- const hasBinary = processedFiles.some(p => p.type === "image_url" || p.type === "input_audio" || p.type === "video_url");
266
- if (hasBinary && !this.options.assumeModelExists && this.provider.capabilities && !this.provider.capabilities.supportsVision(this.model)) {
267
- throw new Error(`Model ${this.model} does not support vision/binary files.`);
268
- }
269
- if (hasBinary && this.options.assumeModelExists) {
270
- console.warn(`[NodeLLM] Skipping vision capability validation for model ${this.model}`);
271
- }
272
- // Separate text files from binary files
273
- const textFiles = processedFiles.filter(p => p.type === "text");
274
- const binaryFiles = processedFiles.filter(p => p.type !== "text");
275
- // Concatenate text files into the main content
276
- let fullText = content;
277
- if (textFiles.length > 0) {
278
- fullText += "\n" + textFiles.map(f => f.text).join("\n");
279
- }
280
- // If we have binary files, create multimodal content
281
- if (binaryFiles.length > 0) {
282
- messageContent = [
283
- { type: "text", text: fullText },
284
- ...binaryFiles
285
- ];
286
- }
287
- else {
288
- // Only text files, keep as string
289
- messageContent = fullText;
290
- }
252
+ const processedFiles = await Promise.all(files.map((f) => FileLoader.load(f)));
253
+ const hasBinary = processedFiles.some(isBinaryContent);
254
+ ChatValidator.validateVision(this.provider, this.model, hasBinary, this.options);
255
+ messageContent = formatMultimodalContent(content, processedFiles);
291
256
  }
292
257
  if (this.options.tools && this.options.tools.length > 0) {
293
- if (!this.options.assumeModelExists && this.provider.capabilities && !this.provider.capabilities.supportsTools(this.model)) {
294
- throw new Error(`Model ${this.model} does not support tool calling.`);
295
- }
296
- if (this.options.assumeModelExists) {
297
- console.warn(`[NodeLLM] Skipping tool capability validation for model ${this.model}`);
298
- }
258
+ ChatValidator.validateTools(this.provider, this.model, true, this.options);
299
259
  }
300
260
  this.messages.push({
301
261
  role: "user",
@@ -304,12 +264,7 @@ export class Chat {
304
264
  // Process Schema/Structured Output
305
265
  let responseFormat = this.options.responseFormat;
306
266
  if (this.options.schema) {
307
- if (!this.options.assumeModelExists && this.provider.capabilities && !this.provider.capabilities.supportsStructuredOutput(this.model)) {
308
- throw new Error(`Model ${this.model} does not support structured output.`);
309
- }
310
- if (this.options.assumeModelExists) {
311
- console.warn(`[NodeLLM] Skipping structured output capability validation for model ${this.model}`);
312
- }
267
+ ChatValidator.validateStructuredOutput(this.provider, this.model, true, this.options);
313
268
  const jsonSchema = toJsonSchema(this.options.schema.definition.schema);
314
269
  responseFormat = {
315
270
  type: "json_schema",
@@ -381,7 +336,7 @@ export class Chat {
381
336
  let stepCount = 0;
382
337
  while (response.tool_calls && response.tool_calls.length > 0) {
383
338
  // Dry-run mode: stop after proposing tools
384
- if (!this.shouldExecuteTools(response.tool_calls, this.options.toolExecution)) {
339
+ if (!ToolHandler.shouldExecuteTools(response.tool_calls, this.options.toolExecution)) {
385
340
  break;
386
341
  }
387
342
  stepCount++;
@@ -389,9 +344,9 @@ export class Chat {
389
344
  throw new Error(`[NodeLLM] Maximum tool execution calls (${maxToolCalls}) exceeded.`);
390
345
  }
391
346
  for (const toolCall of response.tool_calls) {
392
- // Confirm mode: request approval
347
+ // Human-in-the-loop: check for approval
393
348
  if (this.options.toolExecution === ToolExecutionMode.CONFIRM) {
394
- const approved = await this.requestToolConfirmation(toolCall, this.options.onConfirmToolCall);
349
+ const approved = await ToolHandler.requestToolConfirmation(toolCall, this.options.onConfirmToolCall);
395
350
  if (!approved) {
396
351
  this.messages.push({
397
352
  role: "tool",
@@ -401,9 +356,30 @@ export class Chat {
401
356
  continue;
402
357
  }
403
358
  }
404
- // Execute the tool
405
- const toolResult = await this.executeToolCall(toolCall, this.options.tools, this.options.onToolCallStart, this.options.onToolCallEnd, this.options.onToolCallError);
406
- this.messages.push(toolResult);
359
+ try {
360
+ const toolResult = await ToolHandler.execute(toolCall, this.options.tools, this.options.onToolCallStart, this.options.onToolCallEnd);
361
+ this.messages.push(toolResult);
362
+ }
363
+ catch (error) {
364
+ const directive = await this.options.onToolCallError?.(toolCall, error);
365
+ if (directive === 'STOP') {
366
+ throw error;
367
+ }
368
+ this.messages.push({
369
+ role: "tool",
370
+ tool_call_id: toolCall.id,
371
+ content: `Fatal error executing tool '${toolCall.function.name}': ${error.message}`,
372
+ });
373
+ if (directive === 'CONTINUE') {
374
+ continue;
375
+ }
376
+ // Default short-circuit logic
377
+ const isFatal = error.fatal === true || error.status === 401 || error.status === 403;
378
+ if (isFatal) {
379
+ throw error;
380
+ }
381
+ console.error(`[NodeLLM] Tool execution failed for '${toolCall.function.name}':`, error);
382
+ }
407
383
  }
408
384
  response = await this.executor.executeChat({
409
385
  model: this.model,
@@ -438,68 +414,46 @@ export class Chat {
438
414
  /**
439
415
  * Streams the model's response to a user question.
440
416
  */
441
- stream(content) {
417
+ stream(content, options = {}) {
442
418
  const streamer = new ChatStream(this.provider, this.model, this.options, this.messages, this.systemMessages);
443
- return streamer.create(content);
444
- }
445
- /**
446
- * Check if tool execution should proceed based on the current mode.
447
- */
448
- shouldExecuteTools(toolCalls, mode) {
449
- if (!toolCalls || toolCalls.length === 0)
450
- return false;
451
- if (mode === ToolExecutionMode.DRY_RUN)
452
- return false;
453
- return true;
419
+ return streamer.create(content, options);
454
420
  }
455
421
  /**
456
- * Request user confirmation for a tool call in "confirm" mode.
457
- * Returns true if approved, false if rejected.
422
+ * Normalizes a ToolResolvable into a ToolDefinition.
458
423
  */
459
- async requestToolConfirmation(toolCall, onConfirm) {
460
- if (!onConfirm)
461
- return true;
462
- const confirmed = await onConfirm(toolCall);
463
- return confirmed !== false;
464
- }
465
- /**
466
- * Execute a single tool call and return the result message.
467
- */
468
- async executeToolCall(toolCall, tools, onStart, onEnd, onError) {
469
- if (onStart)
470
- onStart(toolCall);
471
- const tool = tools?.find((t) => t.function.name === toolCall.function.name);
472
- if (tool?.handler) {
424
+ normalizeTool(tool) {
425
+ let toolInstance;
426
+ // Handle class constructor
427
+ if (typeof tool === "function") {
473
428
  try {
474
- const args = JSON.parse(toolCall.function.arguments);
475
- const result = await tool.handler(args);
476
- if (onEnd)
477
- onEnd(toolCall, result);
478
- return {
479
- role: "tool",
480
- tool_call_id: toolCall.id,
481
- content: result,
482
- };
429
+ toolInstance = new tool();
483
430
  }
484
- catch (error) {
485
- if (onError)
486
- onError(toolCall, error);
487
- return {
488
- role: "tool",
489
- tool_call_id: toolCall.id,
490
- content: `Error executing tool: ${error.message}`,
491
- };
431
+ catch (e) {
432
+ console.error(`[NodeLLM] Failed to instantiate tool class: ${tool.name}`, e);
433
+ return null;
492
434
  }
493
435
  }
494
436
  else {
495
- const error = new Error("Tool not found or no handler provided");
496
- if (onError)
497
- onError(toolCall, error);
498
- return {
499
- role: "tool",
500
- tool_call_id: toolCall.id,
501
- content: "Error: Tool not found or no handler provided",
502
- };
437
+ toolInstance = tool;
438
+ }
439
+ if (!toolInstance)
440
+ return null;
441
+ // Normalized to standard ToolDefinition interface if it's a Tool class instance
442
+ if (typeof toolInstance.toLLMTool === "function") {
443
+ return toolInstance.toLLMTool();
444
+ }
445
+ if (!toolInstance.function || !toolInstance.function.name) {
446
+ // 1. Validate structure
447
+ throw new ConfigurationError(`[NodeLLM] Tool validation failed: 'function.name' is required for raw tool objects.`);
448
+ }
449
+ if (toolInstance.type !== 'function') {
450
+ // 2. Ensure 'type: function' exists (standardize for providers)
451
+ toolInstance.type = 'function';
452
+ }
453
+ if (typeof toolInstance.handler !== 'function') {
454
+ // 3. Validate handler existence
455
+ throw new ConfigurationError(`[NodeLLM] Tool validation failed: Tool '${toolInstance.function.name}' must have a 'handler' function. (Note: Only Tool subclasses use 'execute()')`);
503
456
  }
457
+ return toolInstance;
504
458
  }
505
459
  }
@@ -1,19 +1,19 @@
1
1
  import { Message } from "./Message.js";
2
- import { ToolDefinition } from "./Tool.js";
2
+ import { ToolResolvable } from "./Tool.js";
3
3
  import { Schema } from "../schema/Schema.js";
4
4
  import { ChatResponseString } from "./ChatResponse.js";
5
5
  import { ToolExecutionMode } from "../constants.js";
6
6
  export interface ChatOptions {
7
7
  systemPrompt?: string;
8
8
  messages?: Message[];
9
- tools?: ToolDefinition[];
9
+ tools?: ToolResolvable[];
10
10
  temperature?: number;
11
11
  maxTokens?: number;
12
12
  onNewMessage?: () => void;
13
13
  onEndMessage?: (message: any) => void;
14
14
  onToolCallStart?: (toolCall: any) => void;
15
15
  onToolCallEnd?: (toolCall: any, result: any) => void;
16
- onToolCallError?: (toolCall: any, error: Error) => void;
16
+ onToolCallError?: (toolCall: any, error: Error) => 'STOP' | 'CONTINUE' | void | Promise<'STOP' | 'CONTINUE' | void>;
17
17
  headers?: Record<string, string>;
18
18
  schema?: Schema;
19
19
  responseFormat?: {
@@ -1 +1 @@
1
- {"version":3,"file":"ChatOptions.d.ts","sourceRoot":"","sources":["../../src/chat/ChatOptions.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAE,MAAM,cAAc,CAAC;AACvC,OAAO,EAAE,cAAc,EAAE,MAAM,WAAW,CAAC;AAC3C,OAAO,EAAE,MAAM,EAAE,MAAM,qBAAqB,CAAC;AAC7C,OAAO,EAAE,kBAAkB,EAAE,MAAM,mBAAmB,CAAC;AACvD,OAAO,EAAE,iBAAiB,EAAE,MAAM,iBAAiB,CAAC;AAEpD,MAAM,WAAW,WAAW;IAC1B,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,QAAQ,CAAC,EAAE,OAAO,EAAE,CAAC;IACrB,KAAK,CAAC,EAAE,cAAc,EAAE,CAAC;IACzB,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,YAAY,CAAC,EAAE,MAAM,IAAI,CAAC;IAC1B,YAAY,CAAC,EAAE,CAAC,OAAO,EAAE,GAAG,KAAK,IAAI,CAAC;IACtC,eAAe,CAAC,EAAE,CAAC,QAAQ,EAAE,GAAG,KAAK,IAAI,CAAC;IAC1C,aAAa,CAAC,EAAE,CAAC,QAAQ,EAAE,GAAG,EAAE,MAAM,EAAE,GAAG,KAAK,IAAI,CAAC;IACrD,eAAe,CAAC,EAAE,CAAC,QAAQ,EAAE,GAAG,EAAE,KAAK,EAAE,KAAK,KAAK,IAAI,CAAC;IACxD,OAAO,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IACjC,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,cAAc,CAAC,EAAE;QAAE,IAAI,EAAE,aAAa,GAAG,MAAM,CAAA;KAAE,CAAC;IAClD,MAAM,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,CAAC;IAC7B,iBAAiB,CAAC,EAAE,OAAO,CAAC;IAC5B,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,cAAc,CAAC,EAAE,MAAM,CAAC;IACxB,aAAa,CAAC,EAAE,iBAAiB,CAAC;IAClC,iBAAiB,CAAC,EAAE,CAAC,QAAQ,EAAE,GAAG,KAAK,OAAO,CAAC,OAAO,CAAC,GAAG,OAAO,CAAC;IAClE,eAAe,CAAC,EAAE,CAAC,QAAQ,EAAE,OAAO,EAAE,KAAK,OAAO,CAAC,OAAO,EAAE,GAAG,IAAI,CAAC,CAAC;IACrE,eAAe,CAAC,EAAE,CAAC,QAAQ,EAAE,kBAAkB,KAAK,OAAO,CAAC,kBAAkB,GAAG,IAAI,CAAC,CAAC;CACxF"}
1
+ {"version":3,"file":"ChatOptions.d.ts","sourceRoot":"","sources":["../../src/chat/ChatOptions.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAE,MAAM,cAAc,CAAC;AACvC,OAAO,EAAkB,cAAc,EAAE,MAAM,WAAW,CAAC;AAC3D,OAAO,EAAE,MAAM,EAAE,MAAM,qBAAqB,CAAC;AAC7C,OAAO,EAAE,kBAAkB,EAAE,MAAM,mBAAmB,CAAC;AACvD,OAAO,EAAE,iBAAiB,EAAE,MAAM,iBAAiB,CAAC;AAEpD,MAAM,WAAW,WAAW;IAC1B,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,QAAQ,CAAC,EAAE,OAAO,EAAE,CAAC;IACrB,KAAK,CAAC,EAAE,cAAc,EAAE,CAAC;IACzB,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,YAAY,CAAC,EAAE,MAAM,IAAI,CAAC;IAC1B,YAAY,CAAC,EAAE,CAAC,OAAO,EAAE,GAAG,KAAK,IAAI,CAAC;IACtC,eAAe,CAAC,EAAE,CAAC,QAAQ,EAAE,GAAG,KAAK,IAAI,CAAC;IAC1C,aAAa,CAAC,EAAE,CAAC,QAAQ,EAAE,GAAG,EAAE,MAAM,EAAE,GAAG,KAAK,IAAI,CAAC;IACrD,eAAe,CAAC,EAAE,CAAC,QAAQ,EAAE,GAAG,EAAE,KAAK,EAAE,KAAK,KAAK,MAAM,GAAG,UAAU,GAAG,IAAI,GAAG,OAAO,CAAC,MAAM,GAAG,UAAU,GAAG,IAAI,CAAC,CAAC;IACpH,OAAO,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IACjC,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,cAAc,CAAC,EAAE;QAAE,IAAI,EAAE,aAAa,GAAG,MAAM,CAAA;KAAE,CAAC;IAClD,MAAM,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,CAAC;IAC7B,iBAAiB,CAAC,EAAE,OAAO,CAAC;IAC5B,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,cAAc,CAAC,EAAE,MAAM,CAAC;IACxB,aAAa,CAAC,EAAE,iBAAiB,CAAC;IAClC,iBAAiB,CAAC,EAAE,CAAC,QAAQ,EAAE,GAAG,KAAK,OAAO,CAAC,OAAO,CAAC,GAAG,OAAO,CAAC;IAClE,eAAe,CAAC,EAAE,CAAC,QAAQ,EAAE,OAAO,EAAE,KAAK,OAAO,CAAC,OAAO,EAAE,GAAG,IAAI,CAAC,CAAC;IACrE,eAAe,CAAC,EAAE,CAAC,QAAQ,EAAE,kBAAkB,KAAK,OAAO,CAAC,kBAAkB,GAAG,IAAI,CAAC,CAAC;CACxF"}
@@ -1,7 +1,9 @@
1
1
  import { Message } from "./Message.js";
2
+ import { ContentPart } from "./Content.js";
2
3
  import { ChatOptions } from "./ChatOptions.js";
3
4
  import { Provider, ChatChunk } from "../providers/Provider.js";
4
5
  import { Stream } from "../streaming/Stream.js";
6
+ import { AskOptions } from "./Chat.js";
5
7
  /**
6
8
  * Internal handler for chat streaming logic.
7
9
  * Wraps the provider's stream with side effects like history updates and events.
@@ -13,27 +15,7 @@ export declare class ChatStream {
13
15
  private messages;
14
16
  private systemMessages;
15
17
  constructor(provider: Provider, model: string, options?: ChatOptions, messages?: Message[], systemMessages?: Message[]);
16
- /**
17
- * Read-only access to message history
18
- */
19
18
  get history(): readonly Message[];
20
- /**
21
- * Creates a high-level Stream object for the chat response.
22
- * @param content The user's question.
23
- */
24
- create(content: string): Stream<ChatChunk>;
25
- /**
26
- * Check if tool execution should proceed based on the current mode.
27
- */
28
- private shouldExecuteTools;
29
- /**
30
- * Request user confirmation for a tool call in "confirm" mode.
31
- * Returns true if approved, false if rejected.
32
- */
33
- private requestToolConfirmation;
34
- /**
35
- * Execute a single tool call and return the result message.
36
- */
37
- private executeToolCall;
19
+ create(content: string | ContentPart[], options?: AskOptions): Stream<ChatChunk>;
38
20
  }
39
21
  //# sourceMappingURL=ChatStream.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"ChatStream.d.ts","sourceRoot":"","sources":["../../src/chat/ChatStream.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAE,MAAM,cAAc,CAAC;AACvC,OAAO,EAAE,WAAW,EAAE,MAAM,kBAAkB,CAAC;AAC/C,OAAO,EAAE,QAAQ,EAAE,SAAS,EAAE,MAAM,0BAA0B,CAAC;AAE/D,OAAO,EAAE,MAAM,EAAE,MAAM,wBAAwB,CAAC;AAIhD;;;GAGG;AACH,qBAAa,UAAU;IAKnB,OAAO,CAAC,QAAQ,CAAC,QAAQ;IACzB,OAAO,CAAC,QAAQ,CAAC,KAAK;IACtB,OAAO,CAAC,QAAQ,CAAC,OAAO;IAN1B,OAAO,CAAC,QAAQ,CAAY;IAC5B,OAAO,CAAC,cAAc,CAAY;gBAGf,QAAQ,EAAE,QAAQ,EAClB,KAAK,EAAE,MAAM,EACb,OAAO,GAAE,WAAgB,EAC1C,QAAQ,CAAC,EAAE,OAAO,EAAE,EACpB,cAAc,CAAC,EAAE,OAAO,EAAE;IA8B5B;;OAEG;IACH,IAAI,OAAO,IAAI,SAAS,OAAO,EAAE,CAEhC;IAED;;;OAGG;IACH,MAAM,CAAC,OAAO,EAAE,MAAM,GAAG,MAAM,CAAC,SAAS,CAAC;IA6J1C;;OAEG;IACH,OAAO,CAAC,kBAAkB;IAM1B;;;OAGG;YACW,uBAAuB;IASrC;;OAEG;YACW,eAAe;CA2C9B"}
1
+ {"version":3,"file":"ChatStream.d.ts","sourceRoot":"","sources":["../../src/chat/ChatStream.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAE,MAAM,cAAc,CAAC;AACvC,OAAO,EAAE,WAAW,EAA4C,MAAM,cAAc,CAAC;AACrF,OAAO,EAAE,WAAW,EAAE,MAAM,kBAAkB,CAAC;AAC/C,OAAO,EAAE,QAAQ,EAAE,SAAS,EAAS,MAAM,0BAA0B,CAAC;AAEtE,OAAO,EAAE,MAAM,EAAE,MAAM,wBAAwB,CAAC;AAGhD,OAAO,EAAE,UAAU,EAAE,MAAM,WAAW,CAAC;AAOvC;;;GAGG;AACH,qBAAa,UAAU;IAKnB,OAAO,CAAC,QAAQ,CAAC,QAAQ;IACzB,OAAO,CAAC,QAAQ,CAAC,KAAK;IACtB,OAAO,CAAC,QAAQ,CAAC,OAAO;IAN1B,OAAO,CAAC,QAAQ,CAAY;IAC5B,OAAO,CAAC,cAAc,CAAY;gBAGf,QAAQ,EAAE,QAAQ,EAClB,KAAK,EAAE,MAAM,EACb,OAAO,GAAE,WAAgB,EAC1C,QAAQ,CAAC,EAAE,OAAO,EAAE,EACpB,cAAc,CAAC,EAAE,OAAO,EAAE;IA6B5B,IAAI,OAAO,IAAI,SAAS,OAAO,EAAE,CAEhC;IAED,MAAM,CAAC,OAAO,EAAE,MAAM,GAAG,WAAW,EAAE,EAAE,OAAO,GAAE,UAAe,GAAG,MAAM,CAAC,SAAS,CAAC;CAsOrF"}