@node-llm/core 1.17.1 → 1.19.0

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 (211) hide show
  1. package/README.md +14 -11
  2. package/dist/agent/Agent.d.ts +41 -14
  3. package/dist/agent/Agent.d.ts.map +1 -1
  4. package/dist/agent/Agent.js +12 -3
  5. package/dist/aliases.d.ts +477 -283
  6. package/dist/aliases.d.ts.map +1 -1
  7. package/dist/aliases.js +546 -352
  8. package/dist/chat/Chat.d.ts +23 -13
  9. package/dist/chat/Chat.d.ts.map +1 -1
  10. package/dist/chat/Chat.js +59 -16
  11. package/dist/chat/ChatOptions.d.ts +28 -11
  12. package/dist/chat/ChatOptions.d.ts.map +1 -1
  13. package/dist/chat/ChatResponse.d.ts +5 -0
  14. package/dist/chat/ChatResponse.d.ts.map +1 -1
  15. package/dist/chat/ChatResponse.js +12 -4
  16. package/dist/chat/ChatStream.d.ts.map +1 -1
  17. package/dist/chat/ChatStream.js +20 -10
  18. package/dist/chat/PromptCache.d.ts +7 -0
  19. package/dist/chat/PromptCache.d.ts.map +1 -0
  20. package/dist/chat/PromptCache.js +7 -0
  21. package/dist/chat/Temperature.d.ts +7 -0
  22. package/dist/chat/Temperature.d.ts.map +1 -0
  23. package/dist/chat/Temperature.js +17 -0
  24. package/dist/chat/Tool.d.ts +52 -8
  25. package/dist/chat/Tool.d.ts.map +1 -1
  26. package/dist/chat/Tool.js +53 -5
  27. package/dist/chat/ToolCallOutcome.d.ts +18 -6
  28. package/dist/chat/ToolCallOutcome.d.ts.map +1 -1
  29. package/dist/chat/ToolCallOutcome.js +14 -0
  30. package/dist/chat/ToolHandler.d.ts +2 -2
  31. package/dist/chat/ToolHandler.d.ts.map +1 -1
  32. package/dist/chat/ToolResultWindow.d.ts +16 -0
  33. package/dist/chat/ToolResultWindow.d.ts.map +1 -0
  34. package/dist/chat/ToolResultWindow.js +25 -0
  35. package/dist/config.d.ts +42 -2
  36. package/dist/config.d.ts.map +1 -1
  37. package/dist/config.js +80 -27
  38. package/dist/constants.d.ts +7 -0
  39. package/dist/constants.d.ts.map +1 -1
  40. package/dist/constants.js +3 -1
  41. package/dist/errors/billing.d.ts +7 -0
  42. package/dist/errors/billing.d.ts.map +1 -0
  43. package/dist/errors/billing.js +24 -0
  44. package/dist/errors/index.d.ts +28 -0
  45. package/dist/errors/index.d.ts.map +1 -1
  46. package/dist/errors/index.js +32 -0
  47. package/dist/executor/Executor.d.ts.map +1 -1
  48. package/dist/executor/Executor.js +5 -3
  49. package/dist/index.d.ts +12 -3
  50. package/dist/index.d.ts.map +1 -1
  51. package/dist/index.js +4 -1
  52. package/dist/judge/Judge.d.ts +107 -0
  53. package/dist/judge/Judge.d.ts.map +1 -0
  54. package/dist/judge/Judge.js +104 -0
  55. package/dist/judge/Judgment.d.ts +116 -0
  56. package/dist/judge/Judgment.d.ts.map +1 -0
  57. package/dist/judge/Judgment.js +159 -0
  58. package/dist/judge/Question.d.ts +91 -0
  59. package/dist/judge/Question.d.ts.map +1 -0
  60. package/dist/judge/Question.js +180 -0
  61. package/dist/llm.d.ts +48 -1
  62. package/dist/llm.d.ts.map +1 -1
  63. package/dist/llm.js +111 -5
  64. package/dist/models/ModelRegistry.d.ts +23 -19
  65. package/dist/models/ModelRegistry.d.ts.map +1 -1
  66. package/dist/models/ModelRegistry.js +28 -2
  67. package/dist/models/models.json +15154 -4786
  68. package/dist/models/types.d.ts +14 -1
  69. package/dist/models/types.d.ts.map +1 -1
  70. package/dist/providers/BaseProvider.d.ts +2 -1
  71. package/dist/providers/BaseProvider.d.ts.map +1 -1
  72. package/dist/providers/BaseProvider.js +3 -0
  73. package/dist/providers/Provider.d.ts +60 -1
  74. package/dist/providers/Provider.d.ts.map +1 -1
  75. package/dist/providers/anthropic/AnthropicProvider.d.ts +2 -0
  76. package/dist/providers/anthropic/AnthropicProvider.d.ts.map +1 -1
  77. package/dist/providers/anthropic/AnthropicProvider.js +2 -0
  78. package/dist/providers/anthropic/Capabilities.d.ts +1 -0
  79. package/dist/providers/anthropic/Capabilities.d.ts.map +1 -1
  80. package/dist/providers/anthropic/Capabilities.js +3 -0
  81. package/dist/providers/anthropic/Chat.d.ts.map +1 -1
  82. package/dist/providers/anthropic/Chat.js +7 -75
  83. package/dist/providers/anthropic/Errors.d.ts.map +1 -1
  84. package/dist/providers/anthropic/Errors.js +4 -3
  85. package/dist/providers/anthropic/Streaming.d.ts.map +1 -1
  86. package/dist/providers/anthropic/Streaming.js +4 -66
  87. package/dist/providers/anthropic/Utils.d.ts +33 -1
  88. package/dist/providers/anthropic/Utils.d.ts.map +1 -1
  89. package/dist/providers/anthropic/Utils.js +114 -0
  90. package/dist/providers/anthropic/types.d.ts +17 -3
  91. package/dist/providers/anthropic/types.d.ts.map +1 -1
  92. package/dist/providers/azure/AzureProvider.d.ts +54 -0
  93. package/dist/providers/azure/AzureProvider.d.ts.map +1 -0
  94. package/dist/providers/azure/AzureProvider.js +110 -0
  95. package/dist/providers/azure/Capabilities.d.ts +16 -0
  96. package/dist/providers/azure/Capabilities.d.ts.map +1 -0
  97. package/dist/providers/azure/Capabilities.js +36 -0
  98. package/dist/providers/azure/Embedding.d.ts +11 -0
  99. package/dist/providers/azure/Embedding.d.ts.map +1 -0
  100. package/dist/providers/azure/Embedding.js +23 -0
  101. package/dist/providers/azure/Models.d.ts +18 -0
  102. package/dist/providers/azure/Models.d.ts.map +1 -0
  103. package/dist/providers/azure/Models.js +29 -0
  104. package/dist/providers/azure/index.d.ts +5 -0
  105. package/dist/providers/azure/index.d.ts.map +1 -0
  106. package/dist/providers/azure/index.js +28 -0
  107. package/dist/providers/bedrock/BedrockProvider.d.ts.map +1 -1
  108. package/dist/providers/bedrock/BedrockProvider.js +1 -0
  109. package/dist/providers/bedrock/Capabilities.d.ts +1 -0
  110. package/dist/providers/bedrock/Capabilities.d.ts.map +1 -1
  111. package/dist/providers/bedrock/Capabilities.js +3 -0
  112. package/dist/providers/bedrock/Chat.d.ts.map +1 -1
  113. package/dist/providers/bedrock/Chat.js +6 -2
  114. package/dist/providers/bedrock/Errors.d.ts.map +1 -1
  115. package/dist/providers/bedrock/Errors.js +4 -0
  116. package/dist/providers/bedrock/Streaming.d.ts.map +1 -1
  117. package/dist/providers/bedrock/Streaming.js +4 -1
  118. package/dist/providers/deepseek/Capabilities.d.ts +1 -0
  119. package/dist/providers/deepseek/Capabilities.d.ts.map +1 -1
  120. package/dist/providers/deepseek/Capabilities.js +3 -0
  121. package/dist/providers/deepseek/Chat.d.ts.map +1 -1
  122. package/dist/providers/deepseek/Chat.js +3 -2
  123. package/dist/providers/deepseek/DeepSeekProvider.d.ts +1 -0
  124. package/dist/providers/deepseek/DeepSeekProvider.d.ts.map +1 -1
  125. package/dist/providers/deepseek/DeepSeekProvider.js +1 -0
  126. package/dist/providers/deepseek/Errors.d.ts.map +1 -1
  127. package/dist/providers/deepseek/Errors.js +5 -4
  128. package/dist/providers/gemini/Capabilities.d.ts +1 -0
  129. package/dist/providers/gemini/Capabilities.d.ts.map +1 -1
  130. package/dist/providers/gemini/Capabilities.js +3 -0
  131. package/dist/providers/gemini/Chat.d.ts.map +1 -1
  132. package/dist/providers/gemini/Chat.js +3 -2
  133. package/dist/providers/gemini/Errors.d.ts.map +1 -1
  134. package/dist/providers/gemini/Errors.js +4 -3
  135. package/dist/providers/gemini/GeminiProvider.d.ts +1 -0
  136. package/dist/providers/gemini/GeminiProvider.d.ts.map +1 -1
  137. package/dist/providers/gemini/GeminiProvider.js +1 -0
  138. package/dist/providers/mistral/Capabilities.d.ts +1 -0
  139. package/dist/providers/mistral/Capabilities.d.ts.map +1 -1
  140. package/dist/providers/mistral/Capabilities.js +3 -0
  141. package/dist/providers/mistral/Chat.d.ts.map +1 -1
  142. package/dist/providers/mistral/Chat.js +3 -2
  143. package/dist/providers/mistral/Errors.d.ts.map +1 -1
  144. package/dist/providers/mistral/Errors.js +4 -3
  145. package/dist/providers/mistral/MistralProvider.d.ts +1 -0
  146. package/dist/providers/mistral/MistralProvider.d.ts.map +1 -1
  147. package/dist/providers/mistral/MistralProvider.js +1 -0
  148. package/dist/providers/ollama/OllamaProvider.d.ts.map +1 -1
  149. package/dist/providers/ollama/OllamaProvider.js +1 -0
  150. package/dist/providers/openai/Capabilities.d.ts +6 -0
  151. package/dist/providers/openai/Capabilities.d.ts.map +1 -1
  152. package/dist/providers/openai/Capabilities.js +10 -0
  153. package/dist/providers/openai/Chat.d.ts +3 -0
  154. package/dist/providers/openai/Chat.d.ts.map +1 -1
  155. package/dist/providers/openai/Chat.js +26 -7
  156. package/dist/providers/openai/Embedding.d.ts +2 -0
  157. package/dist/providers/openai/Embedding.d.ts.map +1 -1
  158. package/dist/providers/openai/Embedding.js +8 -5
  159. package/dist/providers/openai/Errors.d.ts.map +1 -1
  160. package/dist/providers/openai/Errors.js +4 -3
  161. package/dist/providers/openai/Models.d.ts +10 -0
  162. package/dist/providers/openai/Models.d.ts.map +1 -1
  163. package/dist/providers/openai/Models.js +12 -8
  164. package/dist/providers/openai/OpenAIProvider.d.ts +11 -1
  165. package/dist/providers/openai/OpenAIProvider.d.ts.map +1 -1
  166. package/dist/providers/openai/OpenAIProvider.js +36 -0
  167. package/dist/providers/openai/Responses.d.ts +30 -0
  168. package/dist/providers/openai/Responses.d.ts.map +1 -0
  169. package/dist/providers/openai/Responses.js +176 -0
  170. package/dist/providers/openai/Streaming.d.ts +2 -0
  171. package/dist/providers/openai/Streaming.d.ts.map +1 -1
  172. package/dist/providers/openai/Streaming.js +19 -5
  173. package/dist/providers/openrouter/Capabilities.d.ts +1 -0
  174. package/dist/providers/openrouter/Capabilities.d.ts.map +1 -1
  175. package/dist/providers/openrouter/Capabilities.js +3 -0
  176. package/dist/providers/openrouter/OpenRouterProvider.d.ts +1 -0
  177. package/dist/providers/openrouter/OpenRouterProvider.d.ts.map +1 -1
  178. package/dist/providers/openrouter/OpenRouterProvider.js +1 -0
  179. package/dist/providers/registry.d.ts +3 -1
  180. package/dist/providers/registry.d.ts.map +1 -1
  181. package/dist/providers/registry.js +3 -1
  182. package/dist/providers/typesafe/SystemOne.d.ts +11 -0
  183. package/dist/providers/typesafe/SystemOne.d.ts.map +1 -0
  184. package/dist/providers/typesafe/SystemOne.js +171 -0
  185. package/dist/providers/typesafe/TypeSafeProvider.d.ts +27 -0
  186. package/dist/providers/typesafe/TypeSafeProvider.d.ts.map +1 -0
  187. package/dist/providers/typesafe/TypeSafeProvider.js +76 -0
  188. package/dist/providers/typesafe/index.d.ts +4 -0
  189. package/dist/providers/typesafe/index.d.ts.map +1 -0
  190. package/dist/providers/typesafe/index.js +19 -0
  191. package/dist/providers/xai/Capabilities.d.ts +1 -0
  192. package/dist/providers/xai/Capabilities.d.ts.map +1 -1
  193. package/dist/providers/xai/Capabilities.js +3 -0
  194. package/dist/providers/xai/Chat.d.ts.map +1 -1
  195. package/dist/providers/xai/Chat.js +3 -2
  196. package/dist/providers/xai/Errors.d.ts.map +1 -1
  197. package/dist/providers/xai/Errors.js +5 -2
  198. package/dist/providers/xai/XAIProvider.d.ts +1 -0
  199. package/dist/providers/xai/XAIProvider.d.ts.map +1 -1
  200. package/dist/providers/xai/XAIProvider.js +1 -0
  201. package/dist/schema/Schema.d.ts +3 -3
  202. package/dist/schema/Schema.d.ts.map +1 -1
  203. package/dist/schema/to-json-schema.d.ts +2 -2
  204. package/dist/schema/to-json-schema.d.ts.map +1 -1
  205. package/dist/schema/to-json-schema.js +3 -8
  206. package/dist/schema/zod.d.ts +32 -0
  207. package/dist/schema/zod.d.ts.map +1 -0
  208. package/dist/schema/zod.js +31 -0
  209. package/dist/types/Middleware.d.ts +9 -0
  210. package/dist/types/Middleware.d.ts.map +1 -1
  211. package/package.json +5 -3
@@ -1,12 +1,12 @@
1
1
  import { Message } from "./Message.js";
2
2
  import { ContentPart, MessageContent } from "./Content.js";
3
3
  import { ChatOptions } from "./ChatOptions.js";
4
- import { Provider, Usage, ChatChunk, ThinkingConfig, ToolChoice } from "../providers/Provider.js";
4
+ import { Provider, Usage, ChatChunk, ThinkingConfig, ThinkingEffort, ToolChoice } from "../providers/Provider.js";
5
5
  import { Stream } from "../streaming/Stream.js";
6
- import { ToolResolvable } from "./Tool.js";
6
+ import { ToolResolvable, ToolCall } from "./Tool.js";
7
7
  import { Schema } from "../schema/Schema.js";
8
- import { z } from "zod";
9
- import { ToolExecutionMode } from "../constants.js";
8
+ import { Zod3Schema, Zod4Schema, ZodSchema } from "../schema/zod.js";
9
+ import { ToolExecutionModeInput } from "../constants.js";
10
10
  export interface AskOptions {
11
11
  images?: string[];
12
12
  files?: string[];
@@ -134,7 +134,9 @@ export declare class Chat<S = unknown> {
134
134
  * Enforce a specific schema for the output.
135
135
  * Can accept a Schema object or a Zod schema/JSON Schema directly.
136
136
  */
137
- withSchema<T>(schema: Schema | z.ZodType<T> | Record<string, unknown> | null): Chat<T>;
137
+ withSchema<T>(schema: Zod4Schema<T>): Chat<T>;
138
+ withSchema<T>(schema: Zod3Schema<T>): Chat<T>;
139
+ withSchema<T = unknown>(schema: Schema | ZodSchema<T> | Record<string, unknown> | null): Chat<T>;
138
140
  /**
139
141
  * Provide a prediction of the expected output to reduce latency.
140
142
  * Particularly useful for code-editing agents modifying existing text.
@@ -147,41 +149,47 @@ export declare class Chat<S = unknown> {
147
149
  /**
148
150
  * Shortcut to set thinking effort.
149
151
  */
150
- withEffort(effort: "low" | "medium" | "high" | "none"): this;
152
+ withEffort(effort: ThinkingEffort): this;
151
153
  onNewMessage(handler: () => void): this;
152
154
  onEndMessage(handler: (message: ChatResponseString) => void): this;
153
- onToolCall(handler: (toolCall: unknown) => void): this;
155
+ onToolCall(handler: (toolCall: ToolCall) => void): this;
154
156
  onToolResult(handler: (result: unknown) => void): this;
155
157
  /**
156
158
  * Called when a tool call starts. Calling this more than once registers
157
159
  * additional handlers rather than replacing the previous one.
158
160
  */
159
- onToolCallStart(handler: (toolCall: unknown) => void): this;
161
+ onToolCallStart(handler: (toolCall: ToolCall) => void): this;
160
162
  /**
161
163
  * Called when a tool call ends successfully. Calling this more than once
162
164
  * registers additional handlers rather than replacing the previous one.
163
165
  */
164
- onToolCallEnd(handler: (toolCall: unknown, result: unknown) => void): this;
165
- onToolCallError(handler: (toolCall: unknown, error: Error) => "STOP" | "CONTINUE" | "RETRY" | void | Promise<"STOP" | "CONTINUE" | "RETRY" | void>): this;
166
+ onToolCallEnd(handler: (toolCall: ToolCall, result: unknown) => void): this;
167
+ onToolCallError(handler: (toolCall: ToolCall, error: Error) => "STOP" | "CONTINUE" | "RETRY" | void | Promise<"STOP" | "CONTINUE" | "RETRY" | void>): this;
166
168
  /**
167
169
  * Set the tool execution mode.
168
170
  * - "auto": (Default) Automatically execute all tool calls.
169
171
  * - "confirm": Call onConfirmToolCall before executing each tool.
170
172
  * - "dry-run": Propose tool calls but do not execute them.
171
173
  */
172
- withToolExecution(mode: ToolExecutionMode): this;
174
+ withToolExecution(mode: ToolExecutionModeInput): this;
173
175
  /**
174
176
  * Enable or disable concurrent execution of independent tool calls
175
177
  * returned in the same turn. Disabled ("confirm" mode always runs
176
178
  * sequentially since approval is interactive).
177
179
  */
178
180
  withToolConcurrency(enabled: boolean): this;
181
+ /**
182
+ * Cache the repeated start of each request (instructions, tools and earlier turns), so a
183
+ * long conversation or agent loop pays the full input price only once. Providers that cache
184
+ * automatically, such as OpenAI and Gemini, need no change and ignore this.
185
+ */
186
+ withPromptCache(enabled?: boolean): this;
179
187
  /**
180
188
  * Hook for confirming tool execution in "confirm" mode.
181
189
  * Return true to proceed, false to cancel the specific call. When multiple
182
190
  * handlers are registered, every one of them must approve.
183
191
  */
184
- onConfirmToolCall(handler: (toolCall: unknown) => Promise<boolean> | boolean): this;
192
+ onConfirmToolCall(handler: (toolCall: ToolCall) => Promise<boolean> | boolean): this;
185
193
  /**
186
194
  * Add a hook to process messages before sending to the LLM.
187
195
  * Useful for PII detection, redaction, and input moderation. Multiple
@@ -197,7 +205,9 @@ export declare class Chat<S = unknown> {
197
205
  /**
198
206
  * Ask the model a question
199
207
  */
200
- ask(content: string | ContentPart[], options?: AskOptions): Promise<ChatResponseString>;
208
+ ask(content: string | ContentPart[], options?: AskOptions): Promise<ChatResponseString & {
209
+ data: S;
210
+ }>;
201
211
  /**
202
212
  * Streams the model's response to a user question.
203
213
  */
@@ -1 +1 @@
1
- {"version":3,"file":"Chat.d.ts","sourceRoot":"","sources":["../../src/chat/Chat.ts"],"names":[],"mappings":"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"}
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,18 +1,21 @@
1
+ import { windowToolResults } from "./ToolResultWindow.js";
1
2
  import { FileLoader } from "../utils/FileLoader.js";
2
3
  import { isBinaryContent, formatMultimodalContent } from "./Content.js";
3
4
  import { Executor } from "../executor/Executor.js";
4
5
  import { ChatStream } from "./ChatStream.js";
6
+ import { requestTemperature } from "./Temperature.js";
7
+ import { requestPromptCache } from "./PromptCache.js";
5
8
  import { ModelRegistry } from "../models/ModelRegistry.js";
6
9
  import { Schema } from "../schema/Schema.js";
7
10
  import { toJsonSchema } from "../schema/to-json-schema.js";
11
+ import { isZodSchema } from "../schema/zod.js";
8
12
  import { randomUUID } from "node:crypto";
9
- import { z } from "zod";
10
13
  import { config } from "../config.js";
11
- import { ToolExecutionMode, DEFAULT_MAX_CORRECTIONS } from "../constants.js";
12
- import { ConfigurationError } from "../errors/index.js";
14
+ import { ToolExecutionMode, DEFAULT_MAX_CORRECTIONS, DEFAULT_MAX_TOOL_CALLS } from "../constants.js";
15
+ import { ConfigurationError, CostLimitError, ToolCallLimitError } from "../errors/index.js";
13
16
  import { ChatValidator } from "./Validation.js";
14
17
  import { ToolHandler } from "./ToolHandler.js";
15
- import { shouldRunToolCallsConcurrently, executeToolCallOutcomes } from "./ToolCallOutcome.js";
18
+ import { shouldRunToolCallsConcurrently, executeToolCallOutcomes, toolCallLimitResults, unrunToolCallResults } from "./ToolCallOutcome.js";
16
19
  import { logger } from "../utils/logger.js";
17
20
  import { runMiddleware } from "../utils/middleware-runner.js";
18
21
  import { collectHandlers, runAllHandlers, runDirectiveHandlers, runConfirmHandlers, runChainHandlers } from "../utils/handler-stacking.js";
@@ -31,6 +34,19 @@ export class Chat {
31
34
  this.options = options;
32
35
  this.middlewares = options.middlewares || [];
33
36
  this.executor = new Executor(provider, retryConfig);
37
+ // A Zod object or plain JSON Schema passed as the `schema` option was stored
38
+ // as-is, and the request builders then read `.definition` off it and
39
+ // crashed. Convert those the way withSchema() does. Anything already shaped
40
+ // like a Schema - an instance, or an object carrying `definition` - is left
41
+ // exactly as it was.
42
+ const rawSchema = options.schema;
43
+ if (isZodSchema(rawSchema) ||
44
+ (rawSchema &&
45
+ typeof rawSchema === "object" &&
46
+ !(rawSchema instanceof Schema) &&
47
+ !("definition" in rawSchema))) {
48
+ this.withSchema(rawSchema);
49
+ }
34
50
  if (options.systemPrompt) {
35
51
  this.withInstructions(options.systemPrompt);
36
52
  }
@@ -242,10 +258,6 @@ export class Chat {
242
258
  this.options.params = { ...this.options.params, ...params };
243
259
  return this;
244
260
  }
245
- /**
246
- * Enforce a specific schema for the output.
247
- * Can accept a Schema object or a Zod schema/JSON Schema directly.
248
- */
249
261
  withSchema(schema) {
250
262
  if (schema === null) {
251
263
  this.options.schema = undefined;
@@ -254,7 +266,7 @@ export class Chat {
254
266
  if (schema instanceof Schema) {
255
267
  this.options.schema = schema;
256
268
  }
257
- else if (schema instanceof z.ZodType) {
269
+ else if (isZodSchema(schema)) {
258
270
  this.options.schema = Schema.fromZod("output", schema);
259
271
  }
260
272
  else {
@@ -348,6 +360,15 @@ export class Chat {
348
360
  this.options.toolConcurrency = enabled;
349
361
  return this;
350
362
  }
363
+ /**
364
+ * Cache the repeated start of each request (instructions, tools and earlier turns), so a
365
+ * long conversation or agent loop pays the full input price only once. Providers that cache
366
+ * automatically, such as OpenAI and Gemini, need no change and ignore this.
367
+ */
368
+ withPromptCache(enabled = true) {
369
+ this.options.promptCache = enabled;
370
+ return this;
371
+ }
351
372
  /**
352
373
  * Hook for confirming tool execution in "confirm" mode.
353
374
  * Return true to proceed, false to cancel the specific call. When multiple
@@ -387,6 +408,8 @@ export class Chat {
387
408
  /**
388
409
  * Ask the model a question
389
410
  */
411
+ // Typed by the chat's schema: response.data is the schema's type after
412
+ // withSchema(), and unknown (as before) when no schema is set.
390
413
  async ask(content, options) {
391
414
  const requestId = randomUUID();
392
415
  const state = {};
@@ -462,9 +485,9 @@ export class Chat {
462
485
  const messagesToUse = context.messages || [];
463
486
  const executeOptions = {
464
487
  model: this.model,
465
- messages: messagesToUse,
488
+ messages: windowToolResults(messagesToUse, this.options.keepToolResults),
466
489
  tools: this.options.tools,
467
- temperature: options?.temperature ?? this.options.temperature,
490
+ temperature: requestTemperature(this.provider, this.model, options?.temperature ?? this.options.temperature),
468
491
  max_tokens: options?.maxTokens ?? this.options.maxTokens ?? config.maxTokens,
469
492
  headers: { ...this.options.headers, ...options?.headers },
470
493
  response_format: responseFormat, // Pass to provider
@@ -473,6 +496,7 @@ export class Chat {
473
496
  requestTimeout: options?.requestTimeout ?? this.options.requestTimeout ?? config.requestTimeout,
474
497
  thinking: options?.thinking ?? this.options.thinking,
475
498
  prediction: options?.prediction ?? this.options.prediction,
499
+ promptCache: requestPromptCache(this.provider, this.model, this.options.promptCache),
476
500
  signal: options?.signal,
477
501
  ...this.options.params
478
502
  };
@@ -481,7 +505,7 @@ export class Chat {
481
505
  const trackUsage = (u) => {
482
506
  if (u) {
483
507
  if (u.cost === undefined) {
484
- const withCost = ModelRegistry.calculateCost(u, this.model, this.provider.id);
508
+ const withCost = ModelRegistry.calculateCost(u, this.provider.registryModel?.(this.model) ?? this.model, this.provider.id);
485
509
  u.cost = withCost.cost;
486
510
  u.input_cost = withCost.input_cost;
487
511
  u.output_cost = withCost.output_cost;
@@ -505,9 +529,13 @@ export class Chat {
505
529
  };
506
530
  // Start generation
507
531
  await runAllHandlers(newMessageHandlers);
532
+ let requestStarted = Date.now();
508
533
  let response = await this.executor.executeChat(executeOptions);
534
+ const firstLatency = Date.now() - requestStarted;
535
+ let totalLatency = firstLatency;
509
536
  trackUsage(response.usage);
510
537
  assistantMessage = new ChatResponseString(response.content ?? "", response.usage ?? { input_tokens: 0, output_tokens: 0, total_tokens: 0 }, this.model, this.provider.id, response.thinking, response.reasoning, response.tool_calls, response.finish_reason, this.options.schema, response.metadata, response.attachments);
538
+ assistantMessage.latency = firstLatency;
511
539
  // --- Content Policy Hooks (Output - Turn 1) ---
512
540
  assistantMessage = await runChainHandlers(afterResponseHandlers, assistantMessage);
513
541
  // Add to history (temporary, might be rolled back on retry)
@@ -520,7 +548,7 @@ export class Chat {
520
548
  if (!response.tool_calls || response.tool_calls.length === 0) {
521
549
  await runAllHandlers(endMessageHandlers, assistantMessage);
522
550
  }
523
- const maxToolCalls = options?.maxToolCalls ?? this.options.maxToolCalls ?? 5;
551
+ const maxToolCalls = options?.maxToolCalls ?? this.options.maxToolCalls ?? DEFAULT_MAX_TOOL_CALLS;
524
552
  let stepCount = 0;
525
553
  let haltTriggered = false;
526
554
  // Tool Calling Loop
@@ -530,7 +558,13 @@ export class Chat {
530
558
  }
531
559
  stepCount++;
532
560
  if (stepCount > maxToolCalls) {
533
- throw new Error(`[NodeLLM] Maximum tool execution calls (${maxToolCalls}) exceeded.`);
561
+ this.messages.push(...toolCallLimitResults(this.provider, response.tool_calls, maxToolCalls));
562
+ throw new ToolCallLimitError(maxToolCalls, totalUsage);
563
+ }
564
+ const maxCost = this.options.maxCost;
565
+ if (maxCost !== undefined && (totalUsage.cost ?? 0) >= maxCost) {
566
+ this.messages.push(...unrunToolCallResults(this.provider, response.tool_calls, `the cost limit ($${maxCost}) was reached`));
567
+ throw new CostLimitError(maxCost, totalUsage);
534
568
  }
535
569
  const runConcurrently = shouldRunToolCallsConcurrently(this.options.toolConcurrency, this.options.toolExecution, response.tool_calls.length);
536
570
  const outcomes = await executeToolCallOutcomes(response.tool_calls, {
@@ -585,11 +619,14 @@ export class Chat {
585
619
  }
586
620
  if (haltTriggered)
587
621
  break;
622
+ // Content policy hooks see every request in the loop, as they do when streaming.
623
+ const followUpMessages = await runChainHandlers(beforeRequestHandlers, windowToolResults([...this.systemMessages, ...this.messages], this.options.keepToolResults));
624
+ requestStarted = Date.now();
588
625
  response = await this.executor.executeChat({
589
626
  model: this.model,
590
- messages: [...this.systemMessages, ...this.messages],
627
+ messages: followUpMessages,
591
628
  tools: this.options.tools,
592
- temperature: options?.temperature ?? this.options.temperature,
629
+ temperature: requestTemperature(this.provider, this.model, options?.temperature ?? this.options.temperature),
593
630
  max_tokens: options?.maxTokens ?? this.options.maxTokens ?? config.maxTokens,
594
631
  headers: this.options.headers,
595
632
  response_format: responseFormat,
@@ -597,11 +634,15 @@ export class Chat {
597
634
  parallel_tool_calls: this.options.toolCalls === "one" || this.options.toolCalls === 1 ? false : undefined,
598
635
  requestTimeout: options?.requestTimeout ?? this.options.requestTimeout ?? config.requestTimeout,
599
636
  prediction: options?.prediction ?? this.options.prediction,
637
+ promptCache: requestPromptCache(this.provider, this.model, this.options.promptCache),
600
638
  signal: options?.signal,
601
639
  ...this.options.params
602
640
  });
641
+ const latency = Date.now() - requestStarted;
642
+ totalLatency += latency;
603
643
  trackUsage(response.usage);
604
644
  assistantMessage = new ChatResponseString(response.content ?? "", response.usage ?? { input_tokens: 0, output_tokens: 0, total_tokens: 0 }, this.model, this.provider.id, response.thinking, response.reasoning, response.tool_calls, response.finish_reason, this.options.schema, response.metadata, response.attachments);
645
+ assistantMessage.latency = latency;
605
646
  assistantMessage = await runChainHandlers(afterResponseHandlers, assistantMessage);
606
647
  this.messages.push({
607
648
  role: "assistant",
@@ -614,6 +655,8 @@ export class Chat {
614
655
  }
615
656
  }
616
657
  finalResponse = new ChatResponseString(assistantMessage.toString() || "", totalUsage, this.model, this.provider.id, assistantMessage.thinking, assistantMessage.reasoning, response.tool_calls, assistantMessage.finish_reason, this.options.schema, assistantMessage.metadata, assistantMessage.attachments);
658
+ // What ask() returns covers every request in it, so its latency is their total.
659
+ finalResponse.latency = totalLatency;
617
660
  // 5. onResponse Hook
618
661
  const requestDirective = await runMiddleware(this.middlewares, "onResponse", context, finalResponse);
619
662
  if (requestDirective && typeof requestDirective === "object") {
@@ -1,10 +1,10 @@
1
1
  import { Middleware } from "../types/Middleware.js";
2
2
  import { Message } from "./Message.js";
3
- import { ToolResolvable } from "./Tool.js";
3
+ import { ToolResolvable, ToolCall } from "./Tool.js";
4
4
  import { ContentPart } from "./Content.js";
5
5
  import { Schema } from "../schema/Schema.js";
6
6
  import { ChatResponseString } from "./ChatResponse.js";
7
- import { ToolExecutionMode } from "../constants.js";
7
+ import { ToolExecutionModeInput } from "../constants.js";
8
8
  import { ResponseFormat, ThinkingConfig, ToolChoice } from "../providers/Provider.js";
9
9
  export interface ChatOptions {
10
10
  systemPrompt?: string;
@@ -15,9 +15,9 @@ export interface ChatOptions {
15
15
  maxTokens?: number;
16
16
  onNewMessage?: () => void;
17
17
  onEndMessage?: (message: ChatResponseString) => void;
18
- onToolCallStart?: (toolCall: unknown) => void;
19
- onToolCallEnd?: (toolCall: unknown, result: unknown) => void;
20
- onToolCallError?: (toolCall: unknown, error: Error) => "STOP" | "CONTINUE" | "RETRY" | void | Promise<"STOP" | "CONTINUE" | "RETRY" | void>;
18
+ onToolCallStart?: (toolCall: ToolCall) => void;
19
+ onToolCallEnd?: (toolCall: ToolCall, result: unknown) => void;
20
+ onToolCallError?: (toolCall: ToolCall, error: Error) => "STOP" | "CONTINUE" | "RETRY" | void | Promise<"STOP" | "CONTINUE" | "RETRY" | void>;
21
21
  /**
22
22
  * Additional handlers registered via the fluent on*() methods. Each on*()
23
23
  * call appends here instead of overwriting the single onX field above, so
@@ -26,9 +26,9 @@ export interface ChatOptions {
26
26
  */
27
27
  onNewMessageHandlers?: Array<() => void>;
28
28
  onEndMessageHandlers?: Array<(message: ChatResponseString) => void>;
29
- onToolCallStartHandlers?: Array<(toolCall: unknown) => void>;
30
- onToolCallEndHandlers?: Array<(toolCall: unknown, result: unknown) => void>;
31
- onToolCallErrorHandlers?: Array<(toolCall: unknown, error: Error) => "STOP" | "CONTINUE" | "RETRY" | void | Promise<"STOP" | "CONTINUE" | "RETRY" | void>>;
29
+ onToolCallStartHandlers?: Array<(toolCall: ToolCall) => void>;
30
+ onToolCallEndHandlers?: Array<(toolCall: ToolCall, result: unknown) => void>;
31
+ onToolCallErrorHandlers?: Array<(toolCall: ToolCall, error: Error) => "STOP" | "CONTINUE" | "RETRY" | void | Promise<"STOP" | "CONTINUE" | "RETRY" | void>>;
32
32
  headers?: Record<string, string>;
33
33
  responseFormat?: ResponseFormat;
34
34
  thinking?: ThinkingConfig;
@@ -38,20 +38,37 @@ export interface ChatOptions {
38
38
  assumeModelExists?: boolean;
39
39
  provider?: string;
40
40
  maxToolCalls?: number;
41
+ /**
42
+ * Sends only the most recent N tool results in full; older ones are replaced with a short
43
+ * placeholder in each request (the chat's history keeps them). Keeps long tool loops, such as
44
+ * an agent reading many pages, from resending every earlier result on every request.
45
+ */
46
+ keepToolResults?: number;
47
+ /**
48
+ * The most an ask may spend, in US dollars. A tool loop that has spent this much stops before
49
+ * its next request and throws CostLimitError. It needs the model's pricing, so it does nothing
50
+ * for models without it.
51
+ */
52
+ maxCost?: number;
41
53
  maxCorrections?: number;
42
54
  requestTimeout?: number;
43
- toolExecution?: ToolExecutionMode;
55
+ toolExecution?: ToolExecutionModeInput;
44
56
  /**
45
57
  * When true, independent tool calls returned in the same turn are executed
46
58
  * concurrently instead of one at a time. Defaults to `config.toolConcurrency`.
47
59
  */
48
60
  toolConcurrency?: boolean;
61
+ /**
62
+ * Cache the repeated start of each request (instructions, tools and earlier turns) on providers
63
+ * that need asking to, such as Anthropic. Others cache automatically.
64
+ */
65
+ promptCache?: boolean;
49
66
  toolChoice?: ToolChoice;
50
67
  toolCalls?: "one" | "many" | number;
51
- onConfirmToolCall?: (toolCall: unknown) => Promise<boolean> | boolean;
68
+ onConfirmToolCall?: (toolCall: ToolCall) => Promise<boolean> | boolean;
52
69
  onBeforeRequest?: (messages: Message[]) => Promise<Message[] | void>;
53
70
  onAfterResponse?: (response: ChatResponseString) => Promise<ChatResponseString | void>;
54
- onConfirmToolCallHandlers?: Array<(toolCall: unknown) => Promise<boolean> | boolean>;
71
+ onConfirmToolCallHandlers?: Array<(toolCall: ToolCall) => Promise<boolean> | boolean>;
55
72
  onBeforeRequestHandlers?: Array<(messages: Message[]) => Promise<Message[] | void>>;
56
73
  onAfterResponseHandlers?: Array<(response: ChatResponseString) => Promise<ChatResponseString | void>>;
57
74
  }
@@ -1 +1 @@
1
- {"version":3,"file":"ChatOptions.d.ts","sourceRoot":"","sources":["../../src/chat/ChatOptions.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"ChatOptions.d.ts","sourceRoot":"","sources":["../../src/chat/ChatOptions.ts"],"names":[],"mappings":"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"}
@@ -18,6 +18,11 @@ export declare class ChatResponseString extends String {
18
18
  readonly attachments?: Attachment[] | undefined;
19
19
  private _cachedData;
20
20
  private _validationError;
21
+ /**
22
+ * How long the provider took to answer, in milliseconds: for one request in afterResponse hooks,
23
+ * and in total across an ask's requests on what ask() returns.
24
+ */
25
+ latency?: number;
21
26
  constructor(content: string, usage: Usage, model: string, provider: string, thinking?: ThinkingResult | undefined, reasoning?: string | null | undefined, tool_calls?: ToolCall[] | undefined, finish_reason?: string | null | undefined, schema?: Schema | undefined, metadata?: Record<string, unknown> | undefined, attachments?: Attachment[] | undefined);
22
27
  get finishReason(): string | null | undefined;
23
28
  get input_tokens(): number;
@@ -1 +1 @@
1
- {"version":3,"file":"ChatResponse.d.ts","sourceRoot":"","sources":["../../src/chat/ChatResponse.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,KAAK,EAAE,cAAc,EAAE,UAAU,EAAE,MAAM,0BAA0B,CAAC;AAC7E,OAAO,EAAE,QAAQ,EAAE,MAAM,WAAW,CAAC;AACrC,OAAO,EAAE,MAAM,EAAE,MAAM,qBAAqB,CAAC;AAI7C;;;GAGG;AACH,qBAAa,kBAAmB,SAAQ,MAAM;aAM1B,KAAK,EAAE,KAAK;aACZ,KAAK,EAAE,MAAM;aACb,QAAQ,EAAE,MAAM;aAChB,QAAQ,CAAC,EAAE,cAAc;aACzB,SAAS,CAAC,EAAE,MAAM,GAAG,IAAI;aACzB,UAAU,CAAC,EAAE,QAAQ,EAAE;aACvB,aAAa,CAAC,EAAE,MAAM,GAAG,IAAI;aAC7B,MAAM,CAAC,EAAE,MAAM;aACf,QAAQ,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC;aAClC,WAAW,CAAC,EAAE,UAAU,EAAE;IAd5C,OAAO,CAAC,WAAW,CAAsB;IACzC,OAAO,CAAC,gBAAgB,CAAsB;gBAG5C,OAAO,EAAE,MAAM,EACC,KAAK,EAAE,KAAK,EACZ,KAAK,EAAE,MAAM,EACb,QAAQ,EAAE,MAAM,EAChB,QAAQ,CAAC,EAAE,cAAc,YAAA,EACzB,SAAS,CAAC,EAAE,MAAM,GAAG,IAAI,YAAA,EACzB,UAAU,CAAC,EAAE,QAAQ,EAAE,YAAA,EACvB,aAAa,CAAC,EAAE,MAAM,GAAG,IAAI,YAAA,EAC7B,MAAM,CAAC,EAAE,MAAM,YAAA,EACf,QAAQ,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,YAAA,EAClC,WAAW,CAAC,EAAE,UAAU,EAAE,YAAA;IAK5C,IAAI,YAAY,8BAEf;IAED,IAAI,YAAY,WAEf;IACD,IAAI,aAAa,WAEhB;IACD,IAAI,YAAY,WAEf;IACD,IAAI,aAAa,uBAEhB;IACD,IAAI,IAAI,uBAEP;IACD,IAAI,UAAU,uBAEb;IACD,IAAI,WAAW,uBAEd;IAGD,IAAI,WAAW,WAEd;IACD,IAAI,YAAY,WAEf;IACD,IAAI,WAAW,WAEd;IACD,IAAI,YAAY,uBAEf;IAED,IAAI,OAAO,IAAI,MAAM,CAEpB;IAED,IAAI,QAAQ,IAAI,MAAM,CAErB;IAED;;;OAGG;IACH,IAAI,IAAI;;;;;;;;;;MAYP;IAED;;OAEG;IACH,IAAI,GAAG;;;;;;;;;;MAEN;IAED,QAAQ;IAIR;;OAEG;IACH,WAAW,CAAC,UAAU,EAAE,MAAM,GAAG,kBAAkB;IAgBnD;;OAEG;IACH,IAAI,MAAM,IAAI,OAAO,CAOpB;IAED;;;;OAIG;IACH,IAAI,IAAI,IAAI,OAAO,CAkBlB;IAED;;OAEG;IACH,IAAI,QAAQ,IAAI,OAAO,CAMtB;IAED;;OAEG;IACH,IAAI,OAAO,IAAI,OAAO,CAQrB;IAED;;OAEG;IACH,IAAI,eAAe,IAAI,KAAK,GAAG,IAAI,CAOlC;CACF"}
1
+ {"version":3,"file":"ChatResponse.d.ts","sourceRoot":"","sources":["../../src/chat/ChatResponse.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,KAAK,EAAE,cAAc,EAAE,UAAU,EAAE,MAAM,0BAA0B,CAAC;AAC7E,OAAO,EAAE,QAAQ,EAAE,MAAM,WAAW,CAAC;AACrC,OAAO,EAAE,MAAM,EAAE,MAAM,qBAAqB,CAAC;AAI7C;;;GAGG;AACH,qBAAa,kBAAmB,SAAQ,MAAM;aAY1B,KAAK,EAAE,KAAK;aACZ,KAAK,EAAE,MAAM;aACb,QAAQ,EAAE,MAAM;aAChB,QAAQ,CAAC,EAAE,cAAc;aACzB,SAAS,CAAC,EAAE,MAAM,GAAG,IAAI;aACzB,UAAU,CAAC,EAAE,QAAQ,EAAE;aACvB,aAAa,CAAC,EAAE,MAAM,GAAG,IAAI;aAC7B,MAAM,CAAC,EAAE,MAAM;aACf,QAAQ,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC;aAClC,WAAW,CAAC,EAAE,UAAU,EAAE;IApB5C,OAAO,CAAC,WAAW,CAAsB;IACzC,OAAO,CAAC,gBAAgB,CAAsB;IAE9C;;;OAGG;IACI,OAAO,CAAC,EAAE,MAAM,CAAC;gBAGtB,OAAO,EAAE,MAAM,EACC,KAAK,EAAE,KAAK,EACZ,KAAK,EAAE,MAAM,EACb,QAAQ,EAAE,MAAM,EAChB,QAAQ,CAAC,EAAE,cAAc,YAAA,EACzB,SAAS,CAAC,EAAE,MAAM,GAAG,IAAI,YAAA,EACzB,UAAU,CAAC,EAAE,QAAQ,EAAE,YAAA,EACvB,aAAa,CAAC,EAAE,MAAM,GAAG,IAAI,YAAA,EAC7B,MAAM,CAAC,EAAE,MAAM,YAAA,EACf,QAAQ,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,YAAA,EAClC,WAAW,CAAC,EAAE,UAAU,EAAE,YAAA;IAK5C,IAAI,YAAY,8BAEf;IAED,IAAI,YAAY,WAEf;IACD,IAAI,aAAa,WAEhB;IACD,IAAI,YAAY,WAEf;IACD,IAAI,aAAa,uBAEhB;IACD,IAAI,IAAI,uBAEP;IACD,IAAI,UAAU,uBAEb;IACD,IAAI,WAAW,uBAEd;IAGD,IAAI,WAAW,WAEd;IACD,IAAI,YAAY,WAEf;IACD,IAAI,WAAW,WAEd;IACD,IAAI,YAAY,uBAEf;IAED,IAAI,OAAO,IAAI,MAAM,CAEpB;IAED,IAAI,QAAQ,IAAI,MAAM,CAErB;IAED;;;OAGG;IACH,IAAI,IAAI;;;;;;;;;;MAYP;IAED;;OAEG;IACH,IAAI,GAAG;;;;;;;;;;MAEN;IAED,QAAQ;IAIR;;OAEG;IACH,WAAW,CAAC,UAAU,EAAE,MAAM,GAAG,kBAAkB;IAkBnD;;OAEG;IACH,IAAI,MAAM,IAAI,OAAO,CAOpB;IAED;;;;OAIG;IACH,IAAI,IAAI,IAAI,OAAO,CAmBlB;IAED;;OAEG;IACH,IAAI,QAAQ,IAAI,OAAO,CAMtB;IAED;;OAEG;IACH,IAAI,OAAO,IAAI,OAAO,CAQrB;IAED;;OAEG;IACH,IAAI,eAAe,IAAI,KAAK,GAAG,IAAI,CAOlC;CACF"}
@@ -1,5 +1,5 @@
1
1
  import { extractJson } from "../utils/json.js";
2
- import { z } from "zod";
2
+ import { isZodSchema } from "../schema/zod.js";
3
3
  /**
4
4
  * Enhanced string that includes token usage metadata.
5
5
  * Behaves like a regular string but has .usage and .input_tokens etc.
@@ -17,6 +17,11 @@ export class ChatResponseString extends String {
17
17
  attachments;
18
18
  _cachedData = undefined;
19
19
  _validationError = null;
20
+ /**
21
+ * How long the provider took to answer, in milliseconds: for one request in afterResponse hooks,
22
+ * and in total across an ask's requests on what ask() returns.
23
+ */
24
+ latency;
20
25
  constructor(content, usage, model, provider, thinking, reasoning, tool_calls, finish_reason, schema, metadata, attachments) {
21
26
  super(content);
22
27
  this.usage = usage;
@@ -103,7 +108,9 @@ export class ChatResponseString extends String {
103
108
  * Return a new ChatResponseString with modified content but preserved metadata.
104
109
  */
105
110
  withContent(newContent) {
106
- return new ChatResponseString(newContent, this.usage, this.model, this.provider, this.thinking, this.reasoning, this.tool_calls, this.finish_reason, this.schema, this.metadata, this.attachments);
111
+ const changed = new ChatResponseString(newContent, this.usage, this.model, this.provider, this.thinking, this.reasoning, this.tool_calls, this.finish_reason, this.schema, this.metadata, this.attachments);
112
+ changed.latency = this.latency;
113
+ return changed;
107
114
  }
108
115
  /**
109
116
  * Attempt to extract and parse the content as JSON.
@@ -128,9 +135,10 @@ export class ChatResponseString extends String {
128
135
  if (this._validationError)
129
136
  throw this._validationError;
130
137
  const json = this.parsed;
131
- if (this.schema && this.schema.definition.schema instanceof z.ZodType) {
138
+ const schema = this.schema?.definition.schema;
139
+ if (isZodSchema(schema)) {
132
140
  try {
133
- this._cachedData = this.schema.definition.schema.parse(json);
141
+ this._cachedData = schema.parse(json);
134
142
  return this._cachedData;
135
143
  }
136
144
  catch (e) {
@@ -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,EACL,WAAW,EAIZ,MAAM,cAAc,CAAC;AACtB,OAAO,EAAE,WAAW,EAAE,MAAM,kBAAkB,CAAC;AAC/C,OAAO,EAAE,QAAQ,EAAE,SAAS,EAAyB,MAAM,0BAA0B,CAAC;AAEtF,OAAO,EAAE,MAAM,EAAE,MAAM,wBAAwB,CAAC;AAGhD,OAAO,EAAE,UAAU,EAAE,MAAM,WAAW,CAAC;AAqBvC;;;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;IAiC5B,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;CAuZrF"}
1
+ {"version":3,"file":"ChatStream.d.ts","sourceRoot":"","sources":["../../src/chat/ChatStream.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,OAAO,EAAE,MAAM,cAAc,CAAC;AACvC,OAAO,EACL,WAAW,EAIZ,MAAM,cAAc,CAAC;AACtB,OAAO,EAAE,WAAW,EAAE,MAAM,kBAAkB,CAAC;AAC/C,OAAO,EAAE,QAAQ,EAAE,SAAS,EAAyB,MAAM,0BAA0B,CAAC;AAEtF,OAAO,EAAE,MAAM,EAAE,MAAM,wBAAwB,CAAC;AAGhD,OAAO,EAAE,UAAU,EAAE,MAAM,WAAW,CAAC;AA6BvC;;;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;IAiC5B,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;CAsarF"}
@@ -1,18 +1,22 @@
1
+ import { windowToolResults } from "./ToolResultWindow.js";
1
2
  import { isBinaryContent, formatMultimodalContent } from "./Content.js";
2
3
  import { ChatResponseString } from "./ChatResponse.js";
3
4
  import { Stream } from "../streaming/Stream.js";
4
5
  import { config } from "../config.js";
5
- import { ToolExecutionMode } from "../constants.js";
6
+ import { ToolExecutionMode, DEFAULT_MAX_TOOL_CALLS } from "../constants.js";
6
7
  import { FileLoader } from "../utils/FileLoader.js";
7
8
  import { toJsonSchema } from "../schema/to-json-schema.js";
8
9
  import { ChatValidator } from "./Validation.js";
9
10
  import { ToolHandler } from "./ToolHandler.js";
10
11
  import { logger } from "../utils/logger.js";
12
+ import { CostLimitError, ToolCallLimitError } from "../errors/index.js";
11
13
  import { ModelRegistry } from "../models/ModelRegistry.js";
12
14
  import { runMiddleware } from "../utils/middleware-runner.js";
13
15
  import { randomUUID } from "node:crypto";
14
- import { shouldRunToolCallsConcurrently, executeToolCallOutcomes } from "./ToolCallOutcome.js";
16
+ import { shouldRunToolCallsConcurrently, executeToolCallOutcomes, toolCallLimitResults, unrunToolCallResults } from "./ToolCallOutcome.js";
15
17
  import { collectHandlers, runAllHandlers, runDirectiveHandlers, runConfirmHandlers, runChainHandlers } from "../utils/handler-stacking.js";
18
+ import { requestTemperature } from "./Temperature.js";
19
+ import { requestPromptCache } from "./PromptCache.js";
16
20
  /**
17
21
  * Internal handler for chat streaming logic.
18
22
  * Wraps the provider's stream with side effects like history updates and events.
@@ -129,14 +133,14 @@ export class ChatStream {
129
133
  };
130
134
  }
131
135
  let isFirst = true;
132
- const maxToolCalls = options.maxToolCalls ?? 5;
136
+ const maxToolCalls = options.maxToolCalls ?? DEFAULT_MAX_TOOL_CALLS;
133
137
  let stepCount = 0;
134
138
  const totalUsage = { input_tokens: 0, output_tokens: 0, total_tokens: 0 };
135
139
  const trackUsage = (u) => {
136
140
  if (u) {
137
141
  // Fallback cost calculation if provider didn't return it
138
142
  if (u.cost === undefined) {
139
- const withCost = ModelRegistry.calculateCost(u, model, provider.id);
143
+ const withCost = ModelRegistry.calculateCost(u, provider.registryModel?.(model) ?? model, provider.id);
140
144
  u.cost = withCost.cost;
141
145
  u.input_cost = withCost.input_cost;
142
146
  u.output_cost = withCost.output_cost;
@@ -154,23 +158,19 @@ export class ChatStream {
154
158
  };
155
159
  let assistantResponse;
156
160
  while (true) {
157
- stepCount++;
158
- if (stepCount > maxToolCalls) {
159
- throw new Error(`[NodeLLM] Maximum tool execution calls (${maxToolCalls}) exceeded during streaming.`);
160
- }
161
161
  let fullContent = "";
162
162
  let fullReasoning = "";
163
163
  const thinking = { text: "" };
164
164
  let toolCalls;
165
165
  let currentTurnUsage;
166
166
  context.messages = [...systemMessages, ...messages];
167
- let requestMessages = context.messages; // Use up-to-date messages from context
167
+ let requestMessages = windowToolResults(context.messages, options.keepToolResults);
168
168
  requestMessages = await runChainHandlers(beforeRequestHandlers, requestMessages);
169
169
  const streamRequest = {
170
170
  model,
171
171
  messages: requestMessages,
172
172
  tools: options.tools,
173
- temperature: options.temperature,
173
+ temperature: requestTemperature(provider, model, options.temperature),
174
174
  max_tokens: options.maxTokens ?? config.maxTokens,
175
175
  response_format: responseFormat,
176
176
  headers: options.headers,
@@ -179,6 +179,7 @@ export class ChatStream {
179
179
  requestTimeout: options.requestTimeout ?? config.requestTimeout,
180
180
  thinking: options.thinking,
181
181
  prediction: options.prediction,
182
+ promptCache: requestPromptCache(provider, model, options.promptCache),
182
183
  signal: abortController.signal,
183
184
  ...options.params
184
185
  };
@@ -235,6 +236,15 @@ export class ChatStream {
235
236
  if (!ToolHandler.shouldExecuteTools(toolCalls, options.toolExecution)) {
236
237
  break;
237
238
  }
239
+ stepCount++;
240
+ if (stepCount > maxToolCalls) {
241
+ messages.push(...toolCallLimitResults(provider, toolCalls, maxToolCalls));
242
+ throw new ToolCallLimitError(maxToolCalls, totalUsage);
243
+ }
244
+ if (options.maxCost !== undefined && (totalUsage.cost ?? 0) >= options.maxCost) {
245
+ messages.push(...unrunToolCallResults(provider, toolCalls, `the cost limit ($${options.maxCost}) was reached`));
246
+ throw new CostLimitError(options.maxCost, totalUsage);
247
+ }
238
248
  const runConcurrently = shouldRunToolCallsConcurrently(options.toolConcurrency, options.toolExecution, toolCalls.length);
239
249
  const outcomes = await executeToolCallOutcomes(toolCalls, {
240
250
  ...options,
@@ -0,0 +1,7 @@
1
+ import { Provider } from "../providers/Provider.js";
2
+ /**
3
+ * Whether to ask the provider to cache the request. Only providers that declare
4
+ * `supportsPromptCaching` get the flag, so it never reaches another provider's request body.
5
+ */
6
+ export declare function requestPromptCache(provider: Provider, model: string, enabled: boolean | undefined): true | undefined;
7
+ //# sourceMappingURL=PromptCache.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"PromptCache.d.ts","sourceRoot":"","sources":["../../src/chat/PromptCache.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,QAAQ,EAAE,MAAM,0BAA0B,CAAC;AAEpD;;;GAGG;AACH,wBAAgB,kBAAkB,CAChC,QAAQ,EAAE,QAAQ,EAClB,KAAK,EAAE,MAAM,EACb,OAAO,EAAE,OAAO,GAAG,SAAS,GAC3B,IAAI,GAAG,SAAS,CAElB"}
@@ -0,0 +1,7 @@
1
+ /**
2
+ * Whether to ask the provider to cache the request. Only providers that declare
3
+ * `supportsPromptCaching` get the flag, so it never reaches another provider's request body.
4
+ */
5
+ export function requestPromptCache(provider, model, enabled) {
6
+ return enabled && provider.capabilities?.supportsPromptCaching?.(model) ? true : undefined;
7
+ }
@@ -0,0 +1,7 @@
1
+ import { Provider } from "../providers/Provider.js";
2
+ /**
3
+ * The temperature to send. Models that reject one (such as Claude Opus 4.7 and later) get none,
4
+ * so a chat or agent configured with a temperature keeps working when it moves to them.
5
+ */
6
+ export declare function requestTemperature(provider: Provider, model: string, temperature: number | undefined): number | undefined;
7
+ //# sourceMappingURL=Temperature.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"Temperature.d.ts","sourceRoot":"","sources":["../../src/chat/Temperature.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,QAAQ,EAAE,MAAM,0BAA0B,CAAC;AAKpD;;;GAGG;AACH,wBAAgB,kBAAkB,CAChC,QAAQ,EAAE,QAAQ,EAClB,KAAK,EAAE,MAAM,EACb,WAAW,EAAE,MAAM,GAAG,SAAS,GAC9B,MAAM,GAAG,SAAS,CASpB"}
@@ -0,0 +1,17 @@
1
+ import { logger } from "../utils/logger.js";
2
+ const warnedModels = new Set();
3
+ /**
4
+ * The temperature to send. Models that reject one (such as Claude Opus 4.7 and later) get none,
5
+ * so a chat or agent configured with a temperature keeps working when it moves to them.
6
+ */
7
+ export function requestTemperature(provider, model, temperature) {
8
+ if (temperature === undefined)
9
+ return undefined;
10
+ if (provider.capabilities?.supportsTemperature?.(model) !== false)
11
+ return temperature;
12
+ if (!warnedModels.has(model)) {
13
+ warnedModels.add(model);
14
+ logger.warn(`Model ${model} does not accept a temperature; sending the request without it.`);
15
+ }
16
+ return undefined;
17
+ }