@langchain/core 1.1.29 → 1.1.30

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 (110) hide show
  1. package/CHANGELOG.md +16 -0
  2. package/dist/language_models/base.cjs +1 -1
  3. package/dist/language_models/base.cjs.map +1 -1
  4. package/dist/language_models/base.d.cts +6 -0
  5. package/dist/language_models/base.d.cts.map +1 -1
  6. package/dist/language_models/base.d.ts +6 -0
  7. package/dist/language_models/base.d.ts.map +1 -1
  8. package/dist/language_models/base.js +1 -1
  9. package/dist/language_models/base.js.map +1 -1
  10. package/dist/language_models/chat_models.cjs +8 -23
  11. package/dist/language_models/chat_models.cjs.map +1 -1
  12. package/dist/language_models/chat_models.d.cts +6 -0
  13. package/dist/language_models/chat_models.d.cts.map +1 -1
  14. package/dist/language_models/chat_models.d.ts +6 -0
  15. package/dist/language_models/chat_models.d.ts.map +1 -1
  16. package/dist/language_models/chat_models.js +9 -24
  17. package/dist/language_models/chat_models.js.map +1 -1
  18. package/dist/language_models/structured_output.cjs +88 -0
  19. package/dist/language_models/structured_output.cjs.map +1 -0
  20. package/dist/language_models/structured_output.d.cts +46 -0
  21. package/dist/language_models/structured_output.d.cts.map +1 -0
  22. package/dist/language_models/structured_output.d.ts +50 -0
  23. package/dist/language_models/structured_output.d.ts.map +1 -0
  24. package/dist/language_models/structured_output.js +79 -0
  25. package/dist/language_models/structured_output.js.map +1 -0
  26. package/dist/load/import_map.cjs +8 -4
  27. package/dist/load/import_map.cjs.map +1 -1
  28. package/dist/load/import_map.js +8 -4
  29. package/dist/load/import_map.js.map +1 -1
  30. package/dist/messages/base.cjs.map +1 -1
  31. package/dist/messages/base.d.cts +2 -2
  32. package/dist/messages/base.d.cts.map +1 -1
  33. package/dist/messages/base.d.ts +2 -2
  34. package/dist/messages/base.d.ts.map +1 -1
  35. package/dist/messages/base.js.map +1 -1
  36. package/dist/output_parsers/index.cjs +4 -1
  37. package/dist/output_parsers/index.cjs.map +1 -1
  38. package/dist/output_parsers/index.d.cts +2 -1
  39. package/dist/output_parsers/index.d.ts +2 -1
  40. package/dist/output_parsers/index.js +4 -2
  41. package/dist/output_parsers/index.js.map +1 -1
  42. package/dist/output_parsers/openai_tools/index.d.cts +2 -2
  43. package/dist/output_parsers/openai_tools/index.d.ts +2 -2
  44. package/dist/output_parsers/openai_tools/json_output_tools_parsers.cjs +8 -1
  45. package/dist/output_parsers/openai_tools/json_output_tools_parsers.cjs.map +1 -1
  46. package/dist/output_parsers/openai_tools/json_output_tools_parsers.d.cts +6 -1
  47. package/dist/output_parsers/openai_tools/json_output_tools_parsers.d.cts.map +1 -1
  48. package/dist/output_parsers/openai_tools/json_output_tools_parsers.d.ts +6 -1
  49. package/dist/output_parsers/openai_tools/json_output_tools_parsers.d.ts.map +1 -1
  50. package/dist/output_parsers/openai_tools/json_output_tools_parsers.js +8 -1
  51. package/dist/output_parsers/openai_tools/json_output_tools_parsers.js.map +1 -1
  52. package/dist/output_parsers/standard_schema.cjs +40 -0
  53. package/dist/output_parsers/standard_schema.cjs.map +1 -0
  54. package/dist/output_parsers/standard_schema.d.cts +16 -0
  55. package/dist/output_parsers/standard_schema.d.cts.map +1 -0
  56. package/dist/output_parsers/standard_schema.d.ts +16 -0
  57. package/dist/output_parsers/standard_schema.d.ts.map +1 -0
  58. package/dist/output_parsers/standard_schema.js +40 -0
  59. package/dist/output_parsers/standard_schema.js.map +1 -0
  60. package/dist/utils/json_schema.cjs +3 -1
  61. package/dist/utils/json_schema.cjs.map +1 -1
  62. package/dist/utils/json_schema.d.cts +3 -2
  63. package/dist/utils/json_schema.d.cts.map +1 -1
  64. package/dist/utils/json_schema.d.ts +3 -2
  65. package/dist/utils/json_schema.d.ts.map +1 -1
  66. package/dist/utils/json_schema.js +3 -1
  67. package/dist/utils/json_schema.js.map +1 -1
  68. package/dist/utils/standard_schema.cjs +43 -0
  69. package/dist/utils/standard_schema.cjs.map +1 -0
  70. package/dist/utils/standard_schema.d.cts +27 -0
  71. package/dist/utils/standard_schema.d.cts.map +1 -0
  72. package/dist/utils/standard_schema.d.ts +27 -0
  73. package/dist/utils/standard_schema.d.ts.map +1 -0
  74. package/dist/utils/standard_schema.js +34 -0
  75. package/dist/utils/standard_schema.js.map +1 -0
  76. package/dist/utils/testing/fake_model_builder.cjs +174 -0
  77. package/dist/utils/testing/fake_model_builder.cjs.map +1 -0
  78. package/dist/utils/testing/fake_model_builder.d.cts +87 -0
  79. package/dist/utils/testing/fake_model_builder.d.cts.map +1 -0
  80. package/dist/utils/testing/fake_model_builder.d.ts +88 -0
  81. package/dist/utils/testing/fake_model_builder.d.ts.map +1 -0
  82. package/dist/utils/testing/fake_model_builder.js +174 -0
  83. package/dist/utils/testing/fake_model_builder.js.map +1 -0
  84. package/dist/utils/testing/index.cjs +4 -1
  85. package/dist/utils/testing/index.cjs.map +1 -1
  86. package/dist/utils/testing/index.d.cts +2 -1
  87. package/dist/utils/testing/index.d.ts +2 -1
  88. package/dist/utils/testing/index.js +4 -2
  89. package/dist/utils/testing/index.js.map +1 -1
  90. package/dist/utils/types/zod.cjs +1 -1
  91. package/dist/utils/types/zod.cjs.map +1 -1
  92. package/dist/utils/types/zod.d.cts +3 -2
  93. package/dist/utils/types/zod.d.cts.map +1 -1
  94. package/dist/utils/types/zod.d.ts +3 -2
  95. package/dist/utils/types/zod.d.ts.map +1 -1
  96. package/dist/utils/types/zod.js +1 -1
  97. package/dist/utils/types/zod.js.map +1 -1
  98. package/errors.cjs +1 -0
  99. package/errors.d.cts +1 -0
  100. package/errors.d.ts +1 -0
  101. package/errors.js +1 -0
  102. package/language_models/structured_output.cjs +1 -0
  103. package/language_models/structured_output.d.cts +1 -0
  104. package/language_models/structured_output.d.ts +1 -0
  105. package/language_models/structured_output.js +1 -0
  106. package/package.json +32 -5
  107. package/utils/standard_schema.cjs +1 -0
  108. package/utils/standard_schema.d.cts +1 -0
  109. package/utils/standard_schema.d.ts +1 -0
  110. package/utils/standard_schema.js +1 -0
@@ -0,0 +1,174 @@
1
+ const require_base = require('../../messages/base.cjs');
2
+ const require_ai = require('../../messages/ai.cjs');
3
+ const require_base$1 = require('../../runnables/base.cjs');
4
+ require('../../messages/index.cjs');
5
+ const require_language_models_chat_models = require('../../language_models/chat_models.cjs');
6
+
7
+ //#region src/utils/testing/fake_model_builder.ts
8
+ function deriveContent(messages) {
9
+ return messages.map((m) => m.text).filter(Boolean).join("-");
10
+ }
11
+ let idCounter = 0;
12
+ function nextToolCallId() {
13
+ idCounter += 1;
14
+ return `fake_tc_${idCounter}`;
15
+ }
16
+ /**
17
+ * A fake chat model for testing, created via {@link fakeModel}.
18
+ *
19
+ * Queue responses with `.respond()` and `.respondWithTools()`, then
20
+ * pass the instance directly wherever a chat model is expected.
21
+ *
22
+ * Each builder method queues a model response consumed in order per `invoke()`:
23
+ *
24
+ * `.respond(entry)` — enqueue a `BaseMessage`, `Error`, or factory function.
25
+ *
26
+ * `.respondWithTools(toolCalls[])` — enqueue an `AIMessage` with the given
27
+ * tool calls. Content is derived from the input messages automatically.
28
+ *
29
+ * Both can be mixed freely in one chain. When all queued responses are
30
+ * consumed, further invocations throw.
31
+ *
32
+ * Additional configuration:
33
+ * - `.alwaysThrow(error)` — every call throws (overrides the queue)
34
+ * - `.structuredResponse(value)` — value returned by `withStructuredOutput()`
35
+ *
36
+ * The model records all invocations in `.calls` / `.callCount`.
37
+ */
38
+ var FakeBuiltModel = class FakeBuiltModel extends require_language_models_chat_models.BaseChatModel {
39
+ queue = [];
40
+ _alwaysThrowError;
41
+ _structuredResponseValue;
42
+ _tools = [];
43
+ _callIndex = 0;
44
+ _calls = [];
45
+ get calls() {
46
+ return this._calls;
47
+ }
48
+ get callCount() {
49
+ return this._calls.length;
50
+ }
51
+ constructor() {
52
+ super({});
53
+ }
54
+ _llmType() {
55
+ return "fake-model-builder";
56
+ }
57
+ _combineLLMOutput() {
58
+ return [];
59
+ }
60
+ respond(entry) {
61
+ if (typeof entry === "function") this.queue.push({
62
+ kind: "factory",
63
+ factory: entry
64
+ });
65
+ else if (require_base.BaseMessage.isInstance(entry)) this.queue.push({
66
+ kind: "message",
67
+ message: entry
68
+ });
69
+ else this.queue.push({
70
+ kind: "error",
71
+ error: entry
72
+ });
73
+ return this;
74
+ }
75
+ respondWithTools(toolCalls) {
76
+ this.queue.push({
77
+ kind: "toolCalls",
78
+ toolCalls: toolCalls.map((tc) => ({
79
+ name: tc.name,
80
+ args: tc.args,
81
+ id: tc.id ?? nextToolCallId(),
82
+ type: "tool_call"
83
+ }))
84
+ });
85
+ return this;
86
+ }
87
+ alwaysThrow(error) {
88
+ this._alwaysThrowError = error;
89
+ return this;
90
+ }
91
+ structuredResponse(value) {
92
+ this._structuredResponseValue = value;
93
+ return this;
94
+ }
95
+ bindTools(tools) {
96
+ const merged = [...this._tools, ...tools];
97
+ const next = new FakeBuiltModel();
98
+ next.queue = this.queue;
99
+ next._alwaysThrowError = this._alwaysThrowError;
100
+ next._structuredResponseValue = this._structuredResponseValue;
101
+ next._tools = merged;
102
+ next._calls = this._calls;
103
+ next._callIndex = this._callIndex;
104
+ return next.withConfig({});
105
+ }
106
+ withStructuredOutput(_params, _config) {
107
+ const { _structuredResponseValue } = this;
108
+ return require_base$1.RunnableLambda.from(async () => {
109
+ return _structuredResponseValue;
110
+ });
111
+ }
112
+ async _generate(messages, options, _runManager) {
113
+ this._calls.push({
114
+ messages: [...messages],
115
+ options
116
+ });
117
+ const currentCallIndex = this._callIndex;
118
+ this._callIndex += 1;
119
+ if (this._alwaysThrowError) throw this._alwaysThrowError;
120
+ const entry = this.queue[currentCallIndex];
121
+ if (!entry) throw new Error(`FakeModel: no response queued for invocation ${currentCallIndex} (${this.queue.length} total queued).`);
122
+ if (entry.kind === "error") throw entry.error;
123
+ if (entry.kind === "factory") {
124
+ const result = entry.factory(messages);
125
+ if (!require_base.BaseMessage.isInstance(result)) throw result;
126
+ return { generations: [{
127
+ text: "",
128
+ message: result
129
+ }] };
130
+ }
131
+ if (entry.kind === "message") return { generations: [{
132
+ text: "",
133
+ message: entry.message
134
+ }] };
135
+ const content = deriveContent(messages);
136
+ return {
137
+ generations: [{
138
+ text: content,
139
+ message: new require_ai.AIMessage({
140
+ content,
141
+ id: currentCallIndex.toString(),
142
+ tool_calls: entry.toolCalls.length > 0 ? entry.toolCalls.map((tc) => ({
143
+ ...tc,
144
+ type: "tool_call"
145
+ })) : void 0
146
+ })
147
+ }],
148
+ llmOutput: {}
149
+ };
150
+ }
151
+ };
152
+ /**
153
+ * Creates a fake chat model for testing.
154
+ *
155
+ * @example
156
+ * ```typescript
157
+ * const model = fakeModel()
158
+ * .respondWithTools([{ name: "search", args: { query: "weather" } }])
159
+ * .respond(new AIMessage("Sunny and warm."));
160
+ *
161
+ * const r1 = await model.invoke([new HumanMessage("What's the weather?")]);
162
+ * // r1.tool_calls[0].name === "search"
163
+ *
164
+ * const r2 = await model.invoke([new HumanMessage("Thanks")]);
165
+ * // r2.content === "Sunny and warm."
166
+ * ```
167
+ */
168
+ function fakeModel() {
169
+ return new FakeBuiltModel();
170
+ }
171
+
172
+ //#endregion
173
+ exports.fakeModel = fakeModel;
174
+ //# sourceMappingURL=fake_model_builder.cjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"fake_model_builder.cjs","names":["BaseChatModel","BaseMessage","RunnableLambda","AIMessage"],"sources":["../../../src/utils/testing/fake_model_builder.ts"],"sourcesContent":["/* eslint-disable @typescript-eslint/no-explicit-any */\nimport { CallbackManagerForLLMRun } from \"../../callbacks/manager.js\";\nimport {\n BaseChatModel,\n BaseChatModelCallOptions,\n} from \"../../language_models/chat_models.js\";\nimport {\n BaseLanguageModelInput,\n StructuredOutputMethodOptions,\n StructuredOutputMethodParams,\n} from \"../../language_models/base.js\";\nimport { BaseMessage, AIMessage } from \"../../messages/index.js\";\nimport type { ToolCall } from \"../../messages/tool.js\";\nimport type { ChatResult } from \"../../outputs.js\";\nimport { Runnable, RunnableLambda } from \"../../runnables/base.js\";\nimport { StructuredTool } from \"../../tools/index.js\";\nimport type { InteropZodType } from \"../types/zod.js\";\nimport type { ToolSpec } from \"./chat_models.js\";\n\ntype ResponseFactory = (messages: BaseMessage[]) => BaseMessage | Error;\n\ntype QueueEntry =\n | { kind: \"message\"; message: BaseMessage }\n | { kind: \"toolCalls\"; toolCalls: ToolCall[] }\n | { kind: \"error\"; error: Error }\n | { kind: \"factory\"; factory: ResponseFactory };\n\ninterface FakeModelCall {\n messages: BaseMessage[];\n options: any;\n}\n\nfunction deriveContent(messages: BaseMessage[]): string {\n return messages\n .map((m) => m.text)\n .filter(Boolean)\n .join(\"-\");\n}\n\nlet idCounter = 0;\nfunction nextToolCallId(): string {\n idCounter += 1;\n return `fake_tc_${idCounter}`;\n}\n\n/**\n * A fake chat model for testing, created via {@link fakeModel}.\n *\n * Queue responses with `.respond()` and `.respondWithTools()`, then\n * pass the instance directly wherever a chat model is expected.\n *\n * Each builder method queues a model response consumed in order per `invoke()`:\n *\n * `.respond(entry)` — enqueue a `BaseMessage`, `Error`, or factory function.\n *\n * `.respondWithTools(toolCalls[])` — enqueue an `AIMessage` with the given\n * tool calls. Content is derived from the input messages automatically.\n *\n * Both can be mixed freely in one chain. When all queued responses are\n * consumed, further invocations throw.\n *\n * Additional configuration:\n * - `.alwaysThrow(error)` — every call throws (overrides the queue)\n * - `.structuredResponse(value)` — value returned by `withStructuredOutput()`\n *\n * The model records all invocations in `.calls` / `.callCount`.\n */\nclass FakeBuiltModel extends BaseChatModel {\n private queue: QueueEntry[] = [];\n\n private _alwaysThrowError: Error | undefined;\n\n private _structuredResponseValue: any;\n\n private _tools: (StructuredTool | ToolSpec)[] = [];\n\n private _callIndex = 0;\n\n private _calls: FakeModelCall[] = [];\n\n get calls(): FakeModelCall[] {\n return this._calls;\n }\n\n get callCount(): number {\n return this._calls.length;\n }\n\n constructor() {\n super({});\n }\n\n _llmType(): string {\n return \"fake-model-builder\";\n }\n\n _combineLLMOutput() {\n return [];\n }\n\n respond(entry: BaseMessage | Error | ResponseFactory): this {\n if (typeof entry === \"function\") {\n this.queue.push({ kind: \"factory\", factory: entry });\n } else if (BaseMessage.isInstance(entry)) {\n this.queue.push({ kind: \"message\", message: entry });\n } else {\n this.queue.push({ kind: \"error\", error: entry });\n }\n return this;\n }\n\n respondWithTools(\n toolCalls: Array<{ name: string; args: Record<string, any>; id?: string }>\n ): this {\n this.queue.push({\n kind: \"toolCalls\",\n toolCalls: toolCalls.map((tc) => ({\n name: tc.name,\n args: tc.args,\n id: tc.id ?? nextToolCallId(),\n type: \"tool_call\" as const,\n })),\n });\n return this;\n }\n\n alwaysThrow(error: Error): this {\n this._alwaysThrowError = error;\n return this;\n }\n\n structuredResponse(value: Record<string, any>): this {\n this._structuredResponseValue = value;\n return this;\n }\n\n bindTools(tools: (StructuredTool | ToolSpec)[]) {\n const merged = [...this._tools, ...tools];\n const next = new FakeBuiltModel();\n next.queue = this.queue;\n next._alwaysThrowError = this._alwaysThrowError;\n next._structuredResponseValue = this._structuredResponseValue;\n next._tools = merged;\n next._calls = this._calls;\n next._callIndex = this._callIndex;\n\n return next.withConfig({} as BaseChatModelCallOptions);\n }\n\n withStructuredOutput<\n RunOutput extends Record<string, any> = Record<string, any>,\n >(\n _params:\n | StructuredOutputMethodParams<RunOutput, boolean>\n | InteropZodType<RunOutput>\n | Record<string, any>,\n _config?: StructuredOutputMethodOptions<boolean>\n ):\n | Runnable<BaseLanguageModelInput, RunOutput>\n | Runnable<\n BaseLanguageModelInput,\n { raw: BaseMessage; parsed: RunOutput }\n > {\n const { _structuredResponseValue } = this;\n return RunnableLambda.from(async () => {\n return _structuredResponseValue as RunOutput;\n }) as Runnable;\n }\n\n async _generate(\n messages: BaseMessage[],\n options?: this[\"ParsedCallOptions\"],\n _runManager?: CallbackManagerForLLMRun\n ): Promise<ChatResult> {\n this._calls.push({ messages: [...messages], options });\n\n const currentCallIndex = this._callIndex;\n this._callIndex += 1;\n\n if (this._alwaysThrowError) {\n throw this._alwaysThrowError;\n }\n\n const entry = this.queue[currentCallIndex];\n if (!entry) {\n throw new Error(\n `FakeModel: no response queued for invocation ${currentCallIndex} (${this.queue.length} total queued).`\n );\n }\n\n if (entry.kind === \"error\") {\n throw entry.error;\n }\n\n if (entry.kind === \"factory\") {\n const result = entry.factory(messages);\n if (!BaseMessage.isInstance(result)) {\n throw result;\n }\n return {\n generations: [{ text: \"\", message: result }],\n };\n }\n\n if (entry.kind === \"message\") {\n return {\n generations: [{ text: \"\", message: entry.message }],\n };\n }\n\n const content = deriveContent(messages);\n const message = new AIMessage({\n content,\n id: currentCallIndex.toString(),\n tool_calls:\n entry.toolCalls.length > 0\n ? entry.toolCalls.map((tc) => ({\n ...tc,\n type: \"tool_call\" as const,\n }))\n : undefined,\n });\n\n return {\n generations: [{ text: content, message }],\n llmOutput: {},\n };\n }\n}\n\n/**\n * Creates a fake chat model for testing.\n *\n * @example\n * ```typescript\n * const model = fakeModel()\n * .respondWithTools([{ name: \"search\", args: { query: \"weather\" } }])\n * .respond(new AIMessage(\"Sunny and warm.\"));\n *\n * const r1 = await model.invoke([new HumanMessage(\"What's the weather?\")]);\n * // r1.tool_calls[0].name === \"search\"\n *\n * const r2 = await model.invoke([new HumanMessage(\"Thanks\")]);\n * // r2.content === \"Sunny and warm.\"\n * ```\n */\nexport function fakeModel(): FakeBuiltModel {\n return new FakeBuiltModel();\n}\n"],"mappings":"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"}
@@ -0,0 +1,87 @@
1
+ import { BaseMessage } from "../../messages/base.cjs";
2
+ import { AIMessageChunk } from "../../messages/ai.cjs";
3
+ import { MessageStructure, MessageToolSet } from "../../messages/message.cjs";
4
+ import { ChatResult } from "../../outputs.cjs";
5
+ import { InteropZodType } from "../types/zod.cjs";
6
+ import { CallbackManagerForLLMRun } from "../../callbacks/manager.cjs";
7
+ import { Runnable } from "../../runnables/base.cjs";
8
+ import { BaseLanguageModelInput, StructuredOutputMethodOptions, StructuredOutputMethodParams } from "../../language_models/base.cjs";
9
+ import { StructuredTool } from "../../tools/index.cjs";
10
+ import { BaseChatModel, BaseChatModelCallOptions } from "../../language_models/chat_models.cjs";
11
+ import { ToolSpec } from "./chat_models.cjs";
12
+
13
+ //#region src/utils/testing/fake_model_builder.d.ts
14
+ type ResponseFactory = (messages: BaseMessage[]) => BaseMessage | Error;
15
+ interface FakeModelCall {
16
+ messages: BaseMessage[];
17
+ options: any;
18
+ }
19
+ /**
20
+ * A fake chat model for testing, created via {@link fakeModel}.
21
+ *
22
+ * Queue responses with `.respond()` and `.respondWithTools()`, then
23
+ * pass the instance directly wherever a chat model is expected.
24
+ *
25
+ * Each builder method queues a model response consumed in order per `invoke()`:
26
+ *
27
+ * `.respond(entry)` — enqueue a `BaseMessage`, `Error`, or factory function.
28
+ *
29
+ * `.respondWithTools(toolCalls[])` — enqueue an `AIMessage` with the given
30
+ * tool calls. Content is derived from the input messages automatically.
31
+ *
32
+ * Both can be mixed freely in one chain. When all queued responses are
33
+ * consumed, further invocations throw.
34
+ *
35
+ * Additional configuration:
36
+ * - `.alwaysThrow(error)` — every call throws (overrides the queue)
37
+ * - `.structuredResponse(value)` — value returned by `withStructuredOutput()`
38
+ *
39
+ * The model records all invocations in `.calls` / `.callCount`.
40
+ */
41
+ declare class FakeBuiltModel extends BaseChatModel {
42
+ private queue;
43
+ private _alwaysThrowError;
44
+ private _structuredResponseValue;
45
+ private _tools;
46
+ private _callIndex;
47
+ private _calls;
48
+ get calls(): FakeModelCall[];
49
+ get callCount(): number;
50
+ constructor();
51
+ _llmType(): string;
52
+ _combineLLMOutput(): never[];
53
+ respond(entry: BaseMessage | Error | ResponseFactory): this;
54
+ respondWithTools(toolCalls: Array<{
55
+ name: string;
56
+ args: Record<string, any>;
57
+ id?: string;
58
+ }>): this;
59
+ alwaysThrow(error: Error): this;
60
+ structuredResponse(value: Record<string, any>): this;
61
+ bindTools(tools: (StructuredTool | ToolSpec)[]): Runnable<BaseLanguageModelInput, AIMessageChunk<MessageStructure<MessageToolSet>>, BaseChatModelCallOptions>;
62
+ withStructuredOutput<RunOutput extends Record<string, any> = Record<string, any>>(_params: StructuredOutputMethodParams<RunOutput, boolean> | InteropZodType<RunOutput> | Record<string, any>, _config?: StructuredOutputMethodOptions<boolean>): Runnable<BaseLanguageModelInput, RunOutput> | Runnable<BaseLanguageModelInput, {
63
+ raw: BaseMessage;
64
+ parsed: RunOutput;
65
+ }>;
66
+ _generate(messages: BaseMessage[], options?: this["ParsedCallOptions"], _runManager?: CallbackManagerForLLMRun): Promise<ChatResult>;
67
+ }
68
+ /**
69
+ * Creates a fake chat model for testing.
70
+ *
71
+ * @example
72
+ * ```typescript
73
+ * const model = fakeModel()
74
+ * .respondWithTools([{ name: "search", args: { query: "weather" } }])
75
+ * .respond(new AIMessage("Sunny and warm."));
76
+ *
77
+ * const r1 = await model.invoke([new HumanMessage("What's the weather?")]);
78
+ * // r1.tool_calls[0].name === "search"
79
+ *
80
+ * const r2 = await model.invoke([new HumanMessage("Thanks")]);
81
+ * // r2.content === "Sunny and warm."
82
+ * ```
83
+ */
84
+ declare function fakeModel(): FakeBuiltModel;
85
+ //#endregion
86
+ export { fakeModel };
87
+ //# sourceMappingURL=fake_model_builder.d.cts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"fake_model_builder.d.cts","names":[],"sources":["../../../src/utils/testing/fake_model_builder.ts"],"mappings":";;;;;;;;;;;;;KAmBK,eAAA,IAAmB,QAAA,EAAU,WAAA,OAAkB,WAAA,GAAc,KAAA;AAAA,UAQxD,aAAA;EACR,QAAA,EAAU,WAAA;EACV,OAAA;AAAA;;;;;;;;;;;;;;AAVqE;;;;;;;;;cAgDjE,cAAA,SAAuB,aAAA;EAAA,QACnB,KAAA;EAAA,QAEA,iBAAA;EAAA,QAEA,wBAAA;EAAA,QAEA,MAAA;EAAA,QAEA,UAAA;EAAA,QAEA,MAAA;EAAA,IAEJ,KAAA,CAAA,GAAS,aAAA;EAAA,IAIT,SAAA,CAAA;EAIJ,WAAA,CAAA;EAIA,QAAA,CAAA;EAIA,iBAAA,CAAA;EAIA,OAAA,CAAQ,KAAA,EAAO,WAAA,GAAc,KAAA,GAAQ,eAAA;EAWrC,gBAAA,CACE,SAAA,EAAW,KAAA;IAAQ,IAAA;IAAc,IAAA,EAAM,MAAA;IAAqB,EAAA;EAAA;EAc9D,WAAA,CAAY,KAAA,EAAO,KAAA;EAKnB,kBAAA,CAAmB,KAAA,EAAO,MAAA;EAK1B,SAAA,CAAU,KAAA,GAAQ,cAAA,GAAiB,QAAA,MAAW,QAAA,CAAA,sBAAA,EAAA,cAAA,CAAA,gBAAA,CAAA,cAAA,IAAA,wBAAA;EAa9C,oBAAA,mBACoB,MAAA,gBAAsB,MAAA,cAAA,CAExC,OAAA,EACI,4BAAA,CAA6B,SAAA,aAC7B,cAAA,CAAe,SAAA,IACf,MAAA,eACJ,OAAA,GAAU,6BAAA,YAER,QAAA,CAAS,sBAAA,EAAwB,SAAA,IACjC,QAAA,CACE,sBAAA;IACE,GAAA,EAAK,WAAA;IAAa,MAAA,EAAQ,SAAA;EAAA;EAQ5B,SAAA,CACJ,QAAA,EAAU,WAAA,IACV,OAAA,8BACA,WAAA,GAAc,wBAAA,GACb,OAAA,CAAQ,UAAA;AAAA;;;;;;;;;;;;;;;;;iBAyEG,SAAA,CAAA,GAAa,cAAA"}
@@ -0,0 +1,88 @@
1
+ import { BaseMessage } from "../../messages/base.js";
2
+ import { AIMessageChunk } from "../../messages/ai.js";
3
+ import { MessageStructure, MessageToolSet } from "../../messages/message.js";
4
+ import { ChatResult } from "../../outputs.js";
5
+ import { InteropZodType } from "../types/zod.js";
6
+ import { CallbackManagerForLLMRun } from "../../callbacks/manager.js";
7
+ import { Runnable } from "../../runnables/base.js";
8
+ import { BaseLanguageModelInput, StructuredOutputMethodOptions, StructuredOutputMethodParams } from "../../language_models/base.js";
9
+ import "../../messages/index.js";
10
+ import { StructuredTool } from "../../tools/index.js";
11
+ import { BaseChatModel, BaseChatModelCallOptions } from "../../language_models/chat_models.js";
12
+ import { ToolSpec } from "./chat_models.js";
13
+
14
+ //#region src/utils/testing/fake_model_builder.d.ts
15
+ type ResponseFactory = (messages: BaseMessage[]) => BaseMessage | Error;
16
+ interface FakeModelCall {
17
+ messages: BaseMessage[];
18
+ options: any;
19
+ }
20
+ /**
21
+ * A fake chat model for testing, created via {@link fakeModel}.
22
+ *
23
+ * Queue responses with `.respond()` and `.respondWithTools()`, then
24
+ * pass the instance directly wherever a chat model is expected.
25
+ *
26
+ * Each builder method queues a model response consumed in order per `invoke()`:
27
+ *
28
+ * `.respond(entry)` — enqueue a `BaseMessage`, `Error`, or factory function.
29
+ *
30
+ * `.respondWithTools(toolCalls[])` — enqueue an `AIMessage` with the given
31
+ * tool calls. Content is derived from the input messages automatically.
32
+ *
33
+ * Both can be mixed freely in one chain. When all queued responses are
34
+ * consumed, further invocations throw.
35
+ *
36
+ * Additional configuration:
37
+ * - `.alwaysThrow(error)` — every call throws (overrides the queue)
38
+ * - `.structuredResponse(value)` — value returned by `withStructuredOutput()`
39
+ *
40
+ * The model records all invocations in `.calls` / `.callCount`.
41
+ */
42
+ declare class FakeBuiltModel extends BaseChatModel {
43
+ private queue;
44
+ private _alwaysThrowError;
45
+ private _structuredResponseValue;
46
+ private _tools;
47
+ private _callIndex;
48
+ private _calls;
49
+ get calls(): FakeModelCall[];
50
+ get callCount(): number;
51
+ constructor();
52
+ _llmType(): string;
53
+ _combineLLMOutput(): never[];
54
+ respond(entry: BaseMessage | Error | ResponseFactory): this;
55
+ respondWithTools(toolCalls: Array<{
56
+ name: string;
57
+ args: Record<string, any>;
58
+ id?: string;
59
+ }>): this;
60
+ alwaysThrow(error: Error): this;
61
+ structuredResponse(value: Record<string, any>): this;
62
+ bindTools(tools: (StructuredTool | ToolSpec)[]): Runnable<BaseLanguageModelInput, AIMessageChunk<MessageStructure<MessageToolSet>>, BaseChatModelCallOptions>;
63
+ withStructuredOutput<RunOutput extends Record<string, any> = Record<string, any>>(_params: StructuredOutputMethodParams<RunOutput, boolean> | InteropZodType<RunOutput> | Record<string, any>, _config?: StructuredOutputMethodOptions<boolean>): Runnable<BaseLanguageModelInput, RunOutput> | Runnable<BaseLanguageModelInput, {
64
+ raw: BaseMessage;
65
+ parsed: RunOutput;
66
+ }>;
67
+ _generate(messages: BaseMessage[], options?: this["ParsedCallOptions"], _runManager?: CallbackManagerForLLMRun): Promise<ChatResult>;
68
+ }
69
+ /**
70
+ * Creates a fake chat model for testing.
71
+ *
72
+ * @example
73
+ * ```typescript
74
+ * const model = fakeModel()
75
+ * .respondWithTools([{ name: "search", args: { query: "weather" } }])
76
+ * .respond(new AIMessage("Sunny and warm."));
77
+ *
78
+ * const r1 = await model.invoke([new HumanMessage("What's the weather?")]);
79
+ * // r1.tool_calls[0].name === "search"
80
+ *
81
+ * const r2 = await model.invoke([new HumanMessage("Thanks")]);
82
+ * // r2.content === "Sunny and warm."
83
+ * ```
84
+ */
85
+ declare function fakeModel(): FakeBuiltModel;
86
+ //#endregion
87
+ export { fakeModel };
88
+ //# sourceMappingURL=fake_model_builder.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"fake_model_builder.d.ts","names":[],"sources":["../../../src/utils/testing/fake_model_builder.ts"],"mappings":";;;;;;;;;;;;;;KAmBK,eAAA,IAAmB,QAAA,EAAU,WAAA,OAAkB,WAAA,GAAc,KAAA;AAAA,UAQxD,aAAA;EACR,QAAA,EAAU,WAAA;EACV,OAAA;AAAA;AAZ+C;;;;;;;;;;;;;;AAEsB;;;;;;;;AAFtB,cAkD3C,cAAA,SAAuB,aAAA;EAAA,QACnB,KAAA;EAAA,QAEA,iBAAA;EAAA,QAEA,wBAAA;EAAA,QAEA,MAAA;EAAA,QAEA,UAAA;EAAA,QAEA,MAAA;EAAA,IAEJ,KAAA,CAAA,GAAS,aAAA;EAAA,IAIT,SAAA,CAAA;EAIJ,WAAA,CAAA;EAIA,QAAA,CAAA;EAIA,iBAAA,CAAA;EAIA,OAAA,CAAQ,KAAA,EAAO,WAAA,GAAc,KAAA,GAAQ,eAAA;EAWrC,gBAAA,CACE,SAAA,EAAW,KAAA;IAAQ,IAAA;IAAc,IAAA,EAAM,MAAA;IAAqB,EAAA;EAAA;EAc9D,WAAA,CAAY,KAAA,EAAO,KAAA;EAKnB,kBAAA,CAAmB,KAAA,EAAO,MAAA;EAK1B,SAAA,CAAU,KAAA,GAAQ,cAAA,GAAiB,QAAA,MAAW,QAAA,CAAA,sBAAA,EAAA,cAAA,CAAA,gBAAA,CAAA,cAAA,IAAA,wBAAA;EAa9C,oBAAA,mBACoB,MAAA,gBAAsB,MAAA,cAAA,CAExC,OAAA,EACI,4BAAA,CAA6B,SAAA,aAC7B,cAAA,CAAe,SAAA,IACf,MAAA,eACJ,OAAA,GAAU,6BAAA,YAER,QAAA,CAAS,sBAAA,EAAwB,SAAA,IACjC,QAAA,CACE,sBAAA;IACE,GAAA,EAAK,WAAA;IAAa,MAAA,EAAQ,SAAA;EAAA;EAQ5B,SAAA,CACJ,QAAA,EAAU,WAAA,IACV,OAAA,8BACA,WAAA,GAAc,wBAAA,GACb,OAAA,CAAQ,UAAA;AAAA;;;;;;;;;;;;;;;;;iBAyEG,SAAA,CAAA,GAAa,cAAA"}
@@ -0,0 +1,174 @@
1
+ import { BaseMessage } from "../../messages/base.js";
2
+ import { AIMessage } from "../../messages/ai.js";
3
+ import { RunnableLambda } from "../../runnables/base.js";
4
+ import "../../messages/index.js";
5
+ import { BaseChatModel } from "../../language_models/chat_models.js";
6
+
7
+ //#region src/utils/testing/fake_model_builder.ts
8
+ function deriveContent(messages) {
9
+ return messages.map((m) => m.text).filter(Boolean).join("-");
10
+ }
11
+ let idCounter = 0;
12
+ function nextToolCallId() {
13
+ idCounter += 1;
14
+ return `fake_tc_${idCounter}`;
15
+ }
16
+ /**
17
+ * A fake chat model for testing, created via {@link fakeModel}.
18
+ *
19
+ * Queue responses with `.respond()` and `.respondWithTools()`, then
20
+ * pass the instance directly wherever a chat model is expected.
21
+ *
22
+ * Each builder method queues a model response consumed in order per `invoke()`:
23
+ *
24
+ * `.respond(entry)` — enqueue a `BaseMessage`, `Error`, or factory function.
25
+ *
26
+ * `.respondWithTools(toolCalls[])` — enqueue an `AIMessage` with the given
27
+ * tool calls. Content is derived from the input messages automatically.
28
+ *
29
+ * Both can be mixed freely in one chain. When all queued responses are
30
+ * consumed, further invocations throw.
31
+ *
32
+ * Additional configuration:
33
+ * - `.alwaysThrow(error)` — every call throws (overrides the queue)
34
+ * - `.structuredResponse(value)` — value returned by `withStructuredOutput()`
35
+ *
36
+ * The model records all invocations in `.calls` / `.callCount`.
37
+ */
38
+ var FakeBuiltModel = class FakeBuiltModel extends BaseChatModel {
39
+ queue = [];
40
+ _alwaysThrowError;
41
+ _structuredResponseValue;
42
+ _tools = [];
43
+ _callIndex = 0;
44
+ _calls = [];
45
+ get calls() {
46
+ return this._calls;
47
+ }
48
+ get callCount() {
49
+ return this._calls.length;
50
+ }
51
+ constructor() {
52
+ super({});
53
+ }
54
+ _llmType() {
55
+ return "fake-model-builder";
56
+ }
57
+ _combineLLMOutput() {
58
+ return [];
59
+ }
60
+ respond(entry) {
61
+ if (typeof entry === "function") this.queue.push({
62
+ kind: "factory",
63
+ factory: entry
64
+ });
65
+ else if (BaseMessage.isInstance(entry)) this.queue.push({
66
+ kind: "message",
67
+ message: entry
68
+ });
69
+ else this.queue.push({
70
+ kind: "error",
71
+ error: entry
72
+ });
73
+ return this;
74
+ }
75
+ respondWithTools(toolCalls) {
76
+ this.queue.push({
77
+ kind: "toolCalls",
78
+ toolCalls: toolCalls.map((tc) => ({
79
+ name: tc.name,
80
+ args: tc.args,
81
+ id: tc.id ?? nextToolCallId(),
82
+ type: "tool_call"
83
+ }))
84
+ });
85
+ return this;
86
+ }
87
+ alwaysThrow(error) {
88
+ this._alwaysThrowError = error;
89
+ return this;
90
+ }
91
+ structuredResponse(value) {
92
+ this._structuredResponseValue = value;
93
+ return this;
94
+ }
95
+ bindTools(tools) {
96
+ const merged = [...this._tools, ...tools];
97
+ const next = new FakeBuiltModel();
98
+ next.queue = this.queue;
99
+ next._alwaysThrowError = this._alwaysThrowError;
100
+ next._structuredResponseValue = this._structuredResponseValue;
101
+ next._tools = merged;
102
+ next._calls = this._calls;
103
+ next._callIndex = this._callIndex;
104
+ return next.withConfig({});
105
+ }
106
+ withStructuredOutput(_params, _config) {
107
+ const { _structuredResponseValue } = this;
108
+ return RunnableLambda.from(async () => {
109
+ return _structuredResponseValue;
110
+ });
111
+ }
112
+ async _generate(messages, options, _runManager) {
113
+ this._calls.push({
114
+ messages: [...messages],
115
+ options
116
+ });
117
+ const currentCallIndex = this._callIndex;
118
+ this._callIndex += 1;
119
+ if (this._alwaysThrowError) throw this._alwaysThrowError;
120
+ const entry = this.queue[currentCallIndex];
121
+ if (!entry) throw new Error(`FakeModel: no response queued for invocation ${currentCallIndex} (${this.queue.length} total queued).`);
122
+ if (entry.kind === "error") throw entry.error;
123
+ if (entry.kind === "factory") {
124
+ const result = entry.factory(messages);
125
+ if (!BaseMessage.isInstance(result)) throw result;
126
+ return { generations: [{
127
+ text: "",
128
+ message: result
129
+ }] };
130
+ }
131
+ if (entry.kind === "message") return { generations: [{
132
+ text: "",
133
+ message: entry.message
134
+ }] };
135
+ const content = deriveContent(messages);
136
+ return {
137
+ generations: [{
138
+ text: content,
139
+ message: new AIMessage({
140
+ content,
141
+ id: currentCallIndex.toString(),
142
+ tool_calls: entry.toolCalls.length > 0 ? entry.toolCalls.map((tc) => ({
143
+ ...tc,
144
+ type: "tool_call"
145
+ })) : void 0
146
+ })
147
+ }],
148
+ llmOutput: {}
149
+ };
150
+ }
151
+ };
152
+ /**
153
+ * Creates a fake chat model for testing.
154
+ *
155
+ * @example
156
+ * ```typescript
157
+ * const model = fakeModel()
158
+ * .respondWithTools([{ name: "search", args: { query: "weather" } }])
159
+ * .respond(new AIMessage("Sunny and warm."));
160
+ *
161
+ * const r1 = await model.invoke([new HumanMessage("What's the weather?")]);
162
+ * // r1.tool_calls[0].name === "search"
163
+ *
164
+ * const r2 = await model.invoke([new HumanMessage("Thanks")]);
165
+ * // r2.content === "Sunny and warm."
166
+ * ```
167
+ */
168
+ function fakeModel() {
169
+ return new FakeBuiltModel();
170
+ }
171
+
172
+ //#endregion
173
+ export { fakeModel };
174
+ //# sourceMappingURL=fake_model_builder.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"fake_model_builder.js","names":[],"sources":["../../../src/utils/testing/fake_model_builder.ts"],"sourcesContent":["/* eslint-disable @typescript-eslint/no-explicit-any */\nimport { CallbackManagerForLLMRun } from \"../../callbacks/manager.js\";\nimport {\n BaseChatModel,\n BaseChatModelCallOptions,\n} from \"../../language_models/chat_models.js\";\nimport {\n BaseLanguageModelInput,\n StructuredOutputMethodOptions,\n StructuredOutputMethodParams,\n} from \"../../language_models/base.js\";\nimport { BaseMessage, AIMessage } from \"../../messages/index.js\";\nimport type { ToolCall } from \"../../messages/tool.js\";\nimport type { ChatResult } from \"../../outputs.js\";\nimport { Runnable, RunnableLambda } from \"../../runnables/base.js\";\nimport { StructuredTool } from \"../../tools/index.js\";\nimport type { InteropZodType } from \"../types/zod.js\";\nimport type { ToolSpec } from \"./chat_models.js\";\n\ntype ResponseFactory = (messages: BaseMessage[]) => BaseMessage | Error;\n\ntype QueueEntry =\n | { kind: \"message\"; message: BaseMessage }\n | { kind: \"toolCalls\"; toolCalls: ToolCall[] }\n | { kind: \"error\"; error: Error }\n | { kind: \"factory\"; factory: ResponseFactory };\n\ninterface FakeModelCall {\n messages: BaseMessage[];\n options: any;\n}\n\nfunction deriveContent(messages: BaseMessage[]): string {\n return messages\n .map((m) => m.text)\n .filter(Boolean)\n .join(\"-\");\n}\n\nlet idCounter = 0;\nfunction nextToolCallId(): string {\n idCounter += 1;\n return `fake_tc_${idCounter}`;\n}\n\n/**\n * A fake chat model for testing, created via {@link fakeModel}.\n *\n * Queue responses with `.respond()` and `.respondWithTools()`, then\n * pass the instance directly wherever a chat model is expected.\n *\n * Each builder method queues a model response consumed in order per `invoke()`:\n *\n * `.respond(entry)` — enqueue a `BaseMessage`, `Error`, or factory function.\n *\n * `.respondWithTools(toolCalls[])` — enqueue an `AIMessage` with the given\n * tool calls. Content is derived from the input messages automatically.\n *\n * Both can be mixed freely in one chain. When all queued responses are\n * consumed, further invocations throw.\n *\n * Additional configuration:\n * - `.alwaysThrow(error)` — every call throws (overrides the queue)\n * - `.structuredResponse(value)` — value returned by `withStructuredOutput()`\n *\n * The model records all invocations in `.calls` / `.callCount`.\n */\nclass FakeBuiltModel extends BaseChatModel {\n private queue: QueueEntry[] = [];\n\n private _alwaysThrowError: Error | undefined;\n\n private _structuredResponseValue: any;\n\n private _tools: (StructuredTool | ToolSpec)[] = [];\n\n private _callIndex = 0;\n\n private _calls: FakeModelCall[] = [];\n\n get calls(): FakeModelCall[] {\n return this._calls;\n }\n\n get callCount(): number {\n return this._calls.length;\n }\n\n constructor() {\n super({});\n }\n\n _llmType(): string {\n return \"fake-model-builder\";\n }\n\n _combineLLMOutput() {\n return [];\n }\n\n respond(entry: BaseMessage | Error | ResponseFactory): this {\n if (typeof entry === \"function\") {\n this.queue.push({ kind: \"factory\", factory: entry });\n } else if (BaseMessage.isInstance(entry)) {\n this.queue.push({ kind: \"message\", message: entry });\n } else {\n this.queue.push({ kind: \"error\", error: entry });\n }\n return this;\n }\n\n respondWithTools(\n toolCalls: Array<{ name: string; args: Record<string, any>; id?: string }>\n ): this {\n this.queue.push({\n kind: \"toolCalls\",\n toolCalls: toolCalls.map((tc) => ({\n name: tc.name,\n args: tc.args,\n id: tc.id ?? nextToolCallId(),\n type: \"tool_call\" as const,\n })),\n });\n return this;\n }\n\n alwaysThrow(error: Error): this {\n this._alwaysThrowError = error;\n return this;\n }\n\n structuredResponse(value: Record<string, any>): this {\n this._structuredResponseValue = value;\n return this;\n }\n\n bindTools(tools: (StructuredTool | ToolSpec)[]) {\n const merged = [...this._tools, ...tools];\n const next = new FakeBuiltModel();\n next.queue = this.queue;\n next._alwaysThrowError = this._alwaysThrowError;\n next._structuredResponseValue = this._structuredResponseValue;\n next._tools = merged;\n next._calls = this._calls;\n next._callIndex = this._callIndex;\n\n return next.withConfig({} as BaseChatModelCallOptions);\n }\n\n withStructuredOutput<\n RunOutput extends Record<string, any> = Record<string, any>,\n >(\n _params:\n | StructuredOutputMethodParams<RunOutput, boolean>\n | InteropZodType<RunOutput>\n | Record<string, any>,\n _config?: StructuredOutputMethodOptions<boolean>\n ):\n | Runnable<BaseLanguageModelInput, RunOutput>\n | Runnable<\n BaseLanguageModelInput,\n { raw: BaseMessage; parsed: RunOutput }\n > {\n const { _structuredResponseValue } = this;\n return RunnableLambda.from(async () => {\n return _structuredResponseValue as RunOutput;\n }) as Runnable;\n }\n\n async _generate(\n messages: BaseMessage[],\n options?: this[\"ParsedCallOptions\"],\n _runManager?: CallbackManagerForLLMRun\n ): Promise<ChatResult> {\n this._calls.push({ messages: [...messages], options });\n\n const currentCallIndex = this._callIndex;\n this._callIndex += 1;\n\n if (this._alwaysThrowError) {\n throw this._alwaysThrowError;\n }\n\n const entry = this.queue[currentCallIndex];\n if (!entry) {\n throw new Error(\n `FakeModel: no response queued for invocation ${currentCallIndex} (${this.queue.length} total queued).`\n );\n }\n\n if (entry.kind === \"error\") {\n throw entry.error;\n }\n\n if (entry.kind === \"factory\") {\n const result = entry.factory(messages);\n if (!BaseMessage.isInstance(result)) {\n throw result;\n }\n return {\n generations: [{ text: \"\", message: result }],\n };\n }\n\n if (entry.kind === \"message\") {\n return {\n generations: [{ text: \"\", message: entry.message }],\n };\n }\n\n const content = deriveContent(messages);\n const message = new AIMessage({\n content,\n id: currentCallIndex.toString(),\n tool_calls:\n entry.toolCalls.length > 0\n ? entry.toolCalls.map((tc) => ({\n ...tc,\n type: \"tool_call\" as const,\n }))\n : undefined,\n });\n\n return {\n generations: [{ text: content, message }],\n llmOutput: {},\n };\n }\n}\n\n/**\n * Creates a fake chat model for testing.\n *\n * @example\n * ```typescript\n * const model = fakeModel()\n * .respondWithTools([{ name: \"search\", args: { query: \"weather\" } }])\n * .respond(new AIMessage(\"Sunny and warm.\"));\n *\n * const r1 = await model.invoke([new HumanMessage(\"What's the weather?\")]);\n * // r1.tool_calls[0].name === \"search\"\n *\n * const r2 = await model.invoke([new HumanMessage(\"Thanks\")]);\n * // r2.content === \"Sunny and warm.\"\n * ```\n */\nexport function fakeModel(): FakeBuiltModel {\n return new FakeBuiltModel();\n}\n"],"mappings":"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"}
@@ -10,6 +10,7 @@ const require_runnables = require('./runnables.cjs');
10
10
  const require_tools = require('./tools.cjs');
11
11
  const require_tracers = require('./tracers.cjs');
12
12
  const require_vectorstores = require('./vectorstores.cjs');
13
+ const require_fake_model_builder = require('./fake_model_builder.cjs');
13
14
 
14
15
  //#region src/utils/testing/index.ts
15
16
  var testing_exports = /* @__PURE__ */ require_runtime.__exportAll({
@@ -28,7 +29,8 @@ var testing_exports = /* @__PURE__ */ require_runtime.__exportAll({
28
29
  FakeTracer: () => require_message_history.FakeTracer,
29
30
  FakeVectorStore: () => require_vectorstores.FakeVectorStore,
30
31
  SingleRunExtractor: () => require_tracers.SingleRunExtractor,
31
- SyntheticEmbeddings: () => require_embeddings.SyntheticEmbeddings
32
+ SyntheticEmbeddings: () => require_embeddings.SyntheticEmbeddings,
33
+ fakeModel: () => require_fake_model_builder.fakeModel
32
34
  });
33
35
 
34
36
  //#endregion
@@ -48,6 +50,7 @@ exports.FakeTracer = require_message_history.FakeTracer;
48
50
  exports.FakeVectorStore = require_vectorstores.FakeVectorStore;
49
51
  exports.SingleRunExtractor = require_tracers.SingleRunExtractor;
50
52
  exports.SyntheticEmbeddings = require_embeddings.SyntheticEmbeddings;
53
+ exports.fakeModel = require_fake_model_builder.fakeModel;
51
54
  Object.defineProperty(exports, 'testing_exports', {
52
55
  enumerable: true,
53
56
  get: function () {
@@ -1 +1 @@
1
- {"version":3,"file":"index.cjs","names":[],"sources":["../../../src/utils/testing/index.ts"],"sourcesContent":["export * from \"./chat_models.js\";\nexport * from \"./embeddings.js\";\nexport * from \"./llms.js\";\nexport * from \"./message_history.js\";\nexport * from \"./output_parsers.js\";\nexport * from \"./retrievers.js\";\nexport * from \"./runnables.js\";\nexport * from \"./tools.js\";\nexport * from \"./tracers.js\";\nexport * from \"./vectorstores.js\";\n"],"mappings":""}
1
+ {"version":3,"file":"index.cjs","names":[],"sources":["../../../src/utils/testing/index.ts"],"sourcesContent":["export * from \"./chat_models.js\";\nexport * from \"./embeddings.js\";\nexport * from \"./llms.js\";\nexport * from \"./message_history.js\";\nexport * from \"./output_parsers.js\";\nexport * from \"./retrievers.js\";\nexport * from \"./runnables.js\";\nexport * from \"./tools.js\";\nexport * from \"./tracers.js\";\nexport * from \"./vectorstores.js\";\nexport { fakeModel } from \"./fake_model_builder.js\";\n"],"mappings":""}
@@ -8,4 +8,5 @@ import { FakeRunnable } from "./runnables.cjs";
8
8
  import { FakeTool, FakeToolParams } from "./tools.cjs";
9
9
  import { SingleRunExtractor } from "./tracers.cjs";
10
10
  import { FakeVectorStore, FakeVectorStoreArgs } from "./vectorstores.cjs";
11
- export { FakeChatInput, FakeChatMessageHistory, FakeChatModel, FakeEmbeddings, FakeLLM, FakeListChatMessageHistory, FakeListChatModel, FakeListChatModelCallOptions, FakeRetriever, FakeRunnable, FakeSplitIntoListParser, FakeStreamingChatModel, FakeStreamingChatModelCallOptions, FakeStreamingChatModelFields, FakeStreamingLLM, FakeTool, FakeToolParams, FakeTracer, FakeVectorStore, FakeVectorStoreArgs, SingleRunExtractor, SyntheticEmbeddings, ToolSpec };
11
+ import { fakeModel } from "./fake_model_builder.cjs";
12
+ export { FakeChatInput, FakeChatMessageHistory, FakeChatModel, FakeEmbeddings, FakeLLM, FakeListChatMessageHistory, FakeListChatModel, FakeListChatModelCallOptions, FakeRetriever, FakeRunnable, FakeSplitIntoListParser, FakeStreamingChatModel, FakeStreamingChatModelCallOptions, FakeStreamingChatModelFields, FakeStreamingLLM, FakeTool, FakeToolParams, FakeTracer, FakeVectorStore, FakeVectorStoreArgs, SingleRunExtractor, SyntheticEmbeddings, ToolSpec, fakeModel };
@@ -8,4 +8,5 @@ import { FakeRunnable } from "./runnables.js";
8
8
  import { FakeTool, FakeToolParams } from "./tools.js";
9
9
  import { SingleRunExtractor } from "./tracers.js";
10
10
  import { FakeVectorStore, FakeVectorStoreArgs } from "./vectorstores.js";
11
- export { FakeChatInput, FakeChatMessageHistory, FakeChatModel, FakeEmbeddings, FakeLLM, FakeListChatMessageHistory, FakeListChatModel, FakeListChatModelCallOptions, FakeRetriever, FakeRunnable, FakeSplitIntoListParser, FakeStreamingChatModel, FakeStreamingChatModelCallOptions, FakeStreamingChatModelFields, FakeStreamingLLM, FakeTool, FakeToolParams, FakeTracer, FakeVectorStore, FakeVectorStoreArgs, SingleRunExtractor, SyntheticEmbeddings, ToolSpec };
11
+ import { fakeModel } from "./fake_model_builder.js";
12
+ export { FakeChatInput, FakeChatMessageHistory, FakeChatModel, FakeEmbeddings, FakeLLM, FakeListChatMessageHistory, FakeListChatModel, FakeListChatModelCallOptions, FakeRetriever, FakeRunnable, FakeSplitIntoListParser, FakeStreamingChatModel, FakeStreamingChatModelCallOptions, FakeStreamingChatModelFields, FakeStreamingLLM, FakeTool, FakeToolParams, FakeTracer, FakeVectorStore, FakeVectorStoreArgs, SingleRunExtractor, SyntheticEmbeddings, ToolSpec, fakeModel };
@@ -9,6 +9,7 @@ import { FakeRunnable } from "./runnables.js";
9
9
  import { FakeTool } from "./tools.js";
10
10
  import { SingleRunExtractor } from "./tracers.js";
11
11
  import { FakeVectorStore } from "./vectorstores.js";
12
+ import { fakeModel } from "./fake_model_builder.js";
12
13
 
13
14
  //#region src/utils/testing/index.ts
14
15
  var testing_exports = /* @__PURE__ */ __exportAll({
@@ -27,9 +28,10 @@ var testing_exports = /* @__PURE__ */ __exportAll({
27
28
  FakeTracer: () => FakeTracer,
28
29
  FakeVectorStore: () => FakeVectorStore,
29
30
  SingleRunExtractor: () => SingleRunExtractor,
30
- SyntheticEmbeddings: () => SyntheticEmbeddings
31
+ SyntheticEmbeddings: () => SyntheticEmbeddings,
32
+ fakeModel: () => fakeModel
31
33
  });
32
34
 
33
35
  //#endregion
34
- export { FakeChatMessageHistory, FakeChatModel, FakeEmbeddings, FakeLLM, FakeListChatMessageHistory, FakeListChatModel, FakeRetriever, FakeRunnable, FakeSplitIntoListParser, FakeStreamingChatModel, FakeStreamingLLM, FakeTool, FakeTracer, FakeVectorStore, SingleRunExtractor, SyntheticEmbeddings, testing_exports };
36
+ export { FakeChatMessageHistory, FakeChatModel, FakeEmbeddings, FakeLLM, FakeListChatMessageHistory, FakeListChatModel, FakeRetriever, FakeRunnable, FakeSplitIntoListParser, FakeStreamingChatModel, FakeStreamingLLM, FakeTool, FakeTracer, FakeVectorStore, SingleRunExtractor, SyntheticEmbeddings, fakeModel, testing_exports };
35
37
  //# sourceMappingURL=index.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","names":[],"sources":["../../../src/utils/testing/index.ts"],"sourcesContent":["export * from \"./chat_models.js\";\nexport * from \"./embeddings.js\";\nexport * from \"./llms.js\";\nexport * from \"./message_history.js\";\nexport * from \"./output_parsers.js\";\nexport * from \"./retrievers.js\";\nexport * from \"./runnables.js\";\nexport * from \"./tools.js\";\nexport * from \"./tracers.js\";\nexport * from \"./vectorstores.js\";\n"],"mappings":""}
1
+ {"version":3,"file":"index.js","names":[],"sources":["../../../src/utils/testing/index.ts"],"sourcesContent":["export * from \"./chat_models.js\";\nexport * from \"./embeddings.js\";\nexport * from \"./llms.js\";\nexport * from \"./message_history.js\";\nexport * from \"./output_parsers.js\";\nexport * from \"./retrievers.js\";\nexport * from \"./runnables.js\";\nexport * from \"./tools.js\";\nexport * from \"./tracers.js\";\nexport * from \"./vectorstores.js\";\nexport { fakeModel } from \"./fake_model_builder.js\";\n"],"mappings":""}