@langchain/core 0.2.15 → 0.2.17

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 (103) hide show
  1. package/caches.cjs +1 -1
  2. package/caches.d.cts +1 -1
  3. package/caches.d.ts +1 -1
  4. package/caches.js +1 -1
  5. package/callbacks/dispatch/web.cjs +1 -0
  6. package/callbacks/dispatch/web.d.cts +1 -0
  7. package/callbacks/dispatch/web.d.ts +1 -0
  8. package/callbacks/dispatch/web.js +1 -0
  9. package/callbacks/dispatch.cjs +1 -0
  10. package/callbacks/dispatch.d.cts +1 -0
  11. package/callbacks/dispatch.d.ts +1 -0
  12. package/callbacks/dispatch.js +1 -0
  13. package/dist/{caches.cjs → caches/base.cjs} +6 -6
  14. package/dist/{caches.d.ts → caches/base.d.ts} +7 -7
  15. package/dist/{caches.js → caches/base.js} +6 -6
  16. package/dist/caches/tests/in_memory_cache.test.d.ts +1 -0
  17. package/dist/caches/tests/in_memory_cache.test.js +33 -0
  18. package/dist/callbacks/base.cjs +8 -0
  19. package/dist/callbacks/base.d.ts +16 -10
  20. package/dist/callbacks/base.js +8 -0
  21. package/dist/callbacks/dispatch/index.cjs +49 -0
  22. package/dist/callbacks/dispatch/index.d.ts +35 -0
  23. package/dist/callbacks/dispatch/index.js +45 -0
  24. package/dist/callbacks/dispatch/web.cjs +61 -0
  25. package/dist/callbacks/dispatch/web.d.ts +32 -0
  26. package/dist/callbacks/dispatch/web.js +57 -0
  27. package/dist/callbacks/manager.cjs +20 -0
  28. package/dist/callbacks/manager.d.ts +2 -1
  29. package/dist/callbacks/manager.js +20 -0
  30. package/dist/language_models/base.cjs +4 -4
  31. package/dist/language_models/base.d.ts +2 -2
  32. package/dist/language_models/base.js +1 -1
  33. package/dist/language_models/chat_models.d.ts +22 -5
  34. package/dist/language_models/llms.d.ts +1 -1
  35. package/dist/language_models/tests/chat_models.test.js +33 -0
  36. package/dist/load/import_map.cjs +2 -2
  37. package/dist/load/import_map.d.ts +2 -2
  38. package/dist/load/import_map.js +2 -2
  39. package/dist/messages/ai.cjs +19 -0
  40. package/dist/messages/ai.d.ts +2 -0
  41. package/dist/messages/ai.js +19 -0
  42. package/dist/messages/base.cjs +95 -5
  43. package/dist/messages/base.d.ts +5 -1
  44. package/dist/messages/base.js +93 -4
  45. package/dist/messages/chat.cjs +12 -0
  46. package/dist/messages/chat.d.ts +2 -0
  47. package/dist/messages/chat.js +12 -0
  48. package/dist/messages/index.cjs +1 -0
  49. package/dist/messages/index.d.ts +2 -1
  50. package/dist/messages/index.js +1 -0
  51. package/dist/messages/modifier.cjs +35 -0
  52. package/dist/messages/modifier.d.ts +19 -0
  53. package/dist/messages/modifier.js +31 -0
  54. package/dist/messages/tests/base_message.test.js +134 -2
  55. package/dist/messages/tests/message_utils.test.js +54 -2
  56. package/dist/messages/tool.cjs +45 -0
  57. package/dist/messages/tool.d.ts +29 -0
  58. package/dist/messages/tool.js +46 -1
  59. package/dist/messages/transformers.cjs +6 -0
  60. package/dist/messages/transformers.d.ts +3 -2
  61. package/dist/messages/transformers.js +6 -0
  62. package/dist/messages/utils.cjs +5 -1
  63. package/dist/messages/utils.js +5 -1
  64. package/dist/output_parsers/openai_tools/json_output_tools_parsers.cjs +2 -0
  65. package/dist/output_parsers/openai_tools/json_output_tools_parsers.js +2 -0
  66. package/dist/runnables/base.cjs +104 -1
  67. package/dist/runnables/base.d.ts +50 -0
  68. package/dist/runnables/base.js +101 -0
  69. package/dist/runnables/index.cjs +2 -1
  70. package/dist/runnables/index.d.ts +1 -1
  71. package/dist/runnables/index.js +1 -1
  72. package/dist/runnables/tests/runnable_stream_events.test.js +1 -1
  73. package/dist/runnables/tests/runnable_stream_events_v2.test.js +106 -1
  74. package/dist/runnables/tests/runnable_tools.test.d.ts +1 -0
  75. package/dist/runnables/tests/runnable_tools.test.js +149 -0
  76. package/dist/{tools.cjs → tools/index.cjs} +135 -47
  77. package/dist/{tools.d.ts → tools/index.d.ts} +76 -47
  78. package/dist/{tools.js → tools/index.js} +134 -45
  79. package/dist/tools/tests/tools.test.d.ts +1 -0
  80. package/dist/tools/tests/tools.test.js +85 -0
  81. package/dist/tools/utils.cjs +28 -0
  82. package/dist/tools/utils.d.ts +11 -0
  83. package/dist/tools/utils.js +23 -0
  84. package/dist/tracers/base.cjs +1 -0
  85. package/dist/tracers/base.d.ts +1 -1
  86. package/dist/tracers/base.js +1 -0
  87. package/dist/tracers/event_stream.cjs +15 -0
  88. package/dist/tracers/event_stream.d.ts +1 -0
  89. package/dist/tracers/event_stream.js +15 -0
  90. package/dist/types/zod.cjs +2 -0
  91. package/dist/types/zod.d.ts +2 -0
  92. package/dist/types/zod.js +1 -0
  93. package/dist/utils/function_calling.cjs +38 -10
  94. package/dist/utils/function_calling.d.ts +32 -11
  95. package/dist/utils/function_calling.js +36 -9
  96. package/dist/utils/testing/index.cjs +10 -3
  97. package/dist/utils/testing/index.d.ts +1 -1
  98. package/dist/utils/testing/index.js +9 -2
  99. package/package.json +28 -1
  100. package/tools.cjs +1 -1
  101. package/tools.d.cts +1 -1
  102. package/tools.d.ts +1 -1
  103. package/tools.js +1 -1
@@ -11,14 +11,40 @@ export function mergeContent(firstContent, secondContent) {
11
11
  // If both are arrays
12
12
  }
13
13
  else if (Array.isArray(secondContent)) {
14
- return [...firstContent, ...secondContent];
15
- // If the first content is a list and second is a string
14
+ return (_mergeLists(firstContent, secondContent) ?? [
15
+ ...firstContent,
16
+ ...secondContent,
17
+ ]);
16
18
  }
17
19
  else {
18
20
  // Otherwise, add the second content as a new element of the list
19
21
  return [...firstContent, { type: "text", text: secondContent }];
20
22
  }
21
23
  }
24
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
25
+ function stringifyWithDepthLimit(obj, depthLimit) {
26
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
27
+ function helper(obj, currentDepth) {
28
+ if (typeof obj !== "object" || obj === null || obj === undefined) {
29
+ return obj;
30
+ }
31
+ if (currentDepth >= depthLimit) {
32
+ if (Array.isArray(obj)) {
33
+ return "[Array]";
34
+ }
35
+ return "[Object]";
36
+ }
37
+ if (Array.isArray(obj)) {
38
+ return obj.map((item) => helper(item, currentDepth + 1));
39
+ }
40
+ const result = {};
41
+ for (const key of Object.keys(obj)) {
42
+ result[key] = helper(obj[key], currentDepth + 1);
43
+ }
44
+ return result;
45
+ }
46
+ return JSON.stringify(helper(obj, 0), null, 2);
47
+ }
22
48
  /**
23
49
  * Base class for all types of messages in a conversation. It includes
24
50
  * properties like `content`, `name`, and `additional_kwargs`. It also
@@ -123,6 +149,32 @@ export class BaseMessage extends Serializable {
123
149
  .kwargs,
124
150
  };
125
151
  }
152
+ static lc_name() {
153
+ return "BaseMessage";
154
+ }
155
+ // Can't be protected for silly reasons
156
+ get _printableFields() {
157
+ return {
158
+ id: this.id,
159
+ content: this.content,
160
+ name: this.name,
161
+ additional_kwargs: this.additional_kwargs,
162
+ response_metadata: this.response_metadata,
163
+ };
164
+ }
165
+ get [Symbol.toStringTag]() {
166
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
167
+ return this.constructor.lc_name();
168
+ }
169
+ // Override the default behavior of console.log
170
+ [Symbol.for("nodejs.util.inspect.custom")](depth) {
171
+ if (depth === null) {
172
+ return this;
173
+ }
174
+ const printable = stringifyWithDepthLimit(this._printableFields, Math.max(4, depth));
175
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
176
+ return `${this.constructor.lc_name()} ${printable}`;
177
+ }
126
178
  }
127
179
  export function isOpenAIToolCallArray(value) {
128
180
  return (Array.isArray(value) &&
@@ -148,9 +200,13 @@ right
148
200
  throw new Error(`field[${key}] already exists in the message chunk, but with a different type.`);
149
201
  }
150
202
  else if (typeof merged[key] === "string") {
151
- merged[key] = merged[key] + value;
203
+ if (key === "type") {
204
+ // Do not merge 'type' fields
205
+ continue;
206
+ }
207
+ merged[key] += value;
152
208
  }
153
- else if (!Array.isArray(merged[key]) && typeof merged[key] === "object") {
209
+ else if (typeof merged[key] === "object" && !Array.isArray(merged[key])) {
154
210
  merged[key] = _mergeDicts(merged[key], value);
155
211
  }
156
212
  else if (Array.isArray(merged[key])) {
@@ -187,6 +243,12 @@ export function _mergeLists(left, right) {
187
243
  merged.push(item);
188
244
  }
189
245
  }
246
+ else if (typeof item === "object" &&
247
+ "text" in item &&
248
+ item.text === "") {
249
+ // No-op - skip empty text blocks
250
+ continue;
251
+ }
190
252
  else {
191
253
  merged.push(item);
192
254
  }
@@ -194,6 +256,33 @@ export function _mergeLists(left, right) {
194
256
  return merged;
195
257
  }
196
258
  }
259
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
260
+ export function _mergeObj(left, right) {
261
+ if (!left && !right) {
262
+ throw new Error("Cannot merge two undefined objects.");
263
+ }
264
+ if (!left || !right) {
265
+ return left || right;
266
+ }
267
+ else if (typeof left !== typeof right) {
268
+ throw new Error(`Cannot merge objects of different types.\nLeft ${typeof left}\nRight ${typeof right}`);
269
+ }
270
+ else if (typeof left === "string" && typeof right === "string") {
271
+ return (left + right);
272
+ }
273
+ else if (Array.isArray(left) && Array.isArray(right)) {
274
+ return _mergeLists(left, right);
275
+ }
276
+ else if (typeof left === "object" && typeof right === "object") {
277
+ return _mergeDicts(left, right);
278
+ }
279
+ else if (left === right) {
280
+ return left;
281
+ }
282
+ else {
283
+ throw new Error(`Can not merge objects of different types.\nLeft ${left}\nRight ${right}`);
284
+ }
285
+ }
197
286
  /**
198
287
  * Represents a chunk of a message, which can be concatenated with other
199
288
  * message chunks. It includes a method `_merge_kwargs_dict()` for merging
@@ -32,6 +32,12 @@ class ChatMessage extends base_js_1.BaseMessage {
32
32
  static isInstance(message) {
33
33
  return message._getType() === "generic";
34
34
  }
35
+ get _printableFields() {
36
+ return {
37
+ ...super._printableFields,
38
+ role: this.role,
39
+ };
40
+ }
35
41
  }
36
42
  exports.ChatMessage = ChatMessage;
37
43
  /**
@@ -68,5 +74,11 @@ class ChatMessageChunk extends base_js_1.BaseMessageChunk {
68
74
  id: this.id ?? chunk.id,
69
75
  });
70
76
  }
77
+ get _printableFields() {
78
+ return {
79
+ ...super._printableFields,
80
+ role: this.role,
81
+ };
82
+ }
71
83
  }
72
84
  exports.ChatMessageChunk = ChatMessageChunk;
@@ -13,6 +13,7 @@ export declare class ChatMessage extends BaseMessage implements ChatMessageField
13
13
  constructor(fields: ChatMessageFieldsWithRole);
14
14
  _getType(): MessageType;
15
15
  static isInstance(message: BaseMessage): message is ChatMessage;
16
+ get _printableFields(): Record<string, unknown>;
16
17
  }
17
18
  /**
18
19
  * Represents a chunk of a chat message, which can be concatenated with
@@ -25,4 +26,5 @@ export declare class ChatMessageChunk extends BaseMessageChunk {
25
26
  constructor(fields: ChatMessageFieldsWithRole);
26
27
  _getType(): MessageType;
27
28
  concat(chunk: ChatMessageChunk): ChatMessageChunk;
29
+ get _printableFields(): Record<string, unknown>;
28
30
  }
@@ -29,6 +29,12 @@ export class ChatMessage extends BaseMessage {
29
29
  static isInstance(message) {
30
30
  return message._getType() === "generic";
31
31
  }
32
+ get _printableFields() {
33
+ return {
34
+ ...super._printableFields,
35
+ role: this.role,
36
+ };
37
+ }
32
38
  }
33
39
  /**
34
40
  * Represents a chunk of a chat message, which can be concatenated with
@@ -64,4 +70,10 @@ export class ChatMessageChunk extends BaseMessageChunk {
64
70
  id: this.id ?? chunk.id,
65
71
  });
66
72
  }
73
+ get _printableFields() {
74
+ return {
75
+ ...super._printableFields,
76
+ role: this.role,
77
+ };
78
+ }
67
79
  }
@@ -23,6 +23,7 @@ __exportStar(require("./human.cjs"), exports);
23
23
  __exportStar(require("./system.cjs"), exports);
24
24
  __exportStar(require("./utils.cjs"), exports);
25
25
  __exportStar(require("./transformers.cjs"), exports);
26
+ __exportStar(require("./modifier.cjs"), exports);
26
27
  // TODO: Use a star export when we deprecate the
27
28
  // existing "ToolCall" type in "base.js".
28
29
  var tool_js_1 = require("./tool.cjs");
@@ -6,4 +6,5 @@ export * from "./human.js";
6
6
  export * from "./system.js";
7
7
  export * from "./utils.js";
8
8
  export * from "./transformers.js";
9
- export { type ToolMessageFieldsWithToolCallId, ToolMessage, ToolMessageChunk, } from "./tool.js";
9
+ export * from "./modifier.js";
10
+ export { type ToolMessageFieldsWithToolCallId, ToolMessage, ToolMessageChunk, type InvalidToolCall, } from "./tool.js";
@@ -6,6 +6,7 @@ export * from "./human.js";
6
6
  export * from "./system.js";
7
7
  export * from "./utils.js";
8
8
  export * from "./transformers.js";
9
+ export * from "./modifier.js";
9
10
  // TODO: Use a star export when we deprecate the
10
11
  // existing "ToolCall" type in "base.js".
11
12
  export { ToolMessage, ToolMessageChunk, } from "./tool.js";
@@ -0,0 +1,35 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.RemoveMessage = void 0;
4
+ const base_js_1 = require("./base.cjs");
5
+ /**
6
+ * Message responsible for deleting other messages.
7
+ */
8
+ class RemoveMessage extends base_js_1.BaseMessage {
9
+ constructor(fields) {
10
+ super({
11
+ ...fields,
12
+ content: "",
13
+ });
14
+ /**
15
+ * The ID of the message to remove.
16
+ */
17
+ Object.defineProperty(this, "id", {
18
+ enumerable: true,
19
+ configurable: true,
20
+ writable: true,
21
+ value: void 0
22
+ });
23
+ this.id = fields.id;
24
+ }
25
+ _getType() {
26
+ return "remove";
27
+ }
28
+ get _printableFields() {
29
+ return {
30
+ ...super._printableFields,
31
+ id: this.id,
32
+ };
33
+ }
34
+ }
35
+ exports.RemoveMessage = RemoveMessage;
@@ -0,0 +1,19 @@
1
+ import { BaseMessage, BaseMessageFields, MessageType } from "./base.js";
2
+ export interface RemoveMessageFields extends Omit<BaseMessageFields, "content"> {
3
+ /**
4
+ * The ID of the message to remove.
5
+ */
6
+ id: string;
7
+ }
8
+ /**
9
+ * Message responsible for deleting other messages.
10
+ */
11
+ export declare class RemoveMessage extends BaseMessage {
12
+ /**
13
+ * The ID of the message to remove.
14
+ */
15
+ id: string;
16
+ constructor(fields: RemoveMessageFields);
17
+ _getType(): MessageType;
18
+ get _printableFields(): Record<string, unknown>;
19
+ }
@@ -0,0 +1,31 @@
1
+ import { BaseMessage } from "./base.js";
2
+ /**
3
+ * Message responsible for deleting other messages.
4
+ */
5
+ export class RemoveMessage extends BaseMessage {
6
+ constructor(fields) {
7
+ super({
8
+ ...fields,
9
+ content: "",
10
+ });
11
+ /**
12
+ * The ID of the message to remove.
13
+ */
14
+ Object.defineProperty(this, "id", {
15
+ enumerable: true,
16
+ configurable: true,
17
+ writable: true,
18
+ value: void 0
19
+ });
20
+ this.id = fields.id;
21
+ }
22
+ _getType() {
23
+ return "remove";
24
+ }
25
+ get _printableFields() {
26
+ return {
27
+ ...super._printableFields,
28
+ id: this.id,
29
+ };
30
+ }
31
+ }
@@ -1,6 +1,6 @@
1
- import { test } from "@jest/globals";
1
+ import { test, describe, it, expect } from "@jest/globals";
2
2
  import { ChatPromptTemplate } from "../../prompts/chat.js";
3
- import { HumanMessage, AIMessage, ToolMessage } from "../index.js";
3
+ import { HumanMessage, AIMessage, ToolMessage, ToolMessageChunk, AIMessageChunk, } from "../index.js";
4
4
  import { load } from "../../load/index.js";
5
5
  test("Test ChatPromptTemplate can format OpenAI content image messages", async () => {
6
6
  const message = new HumanMessage({
@@ -111,3 +111,135 @@ test("Deserialisation and serialisation of messages with ID", async () => {
111
111
  expect(deserialized).toEqual(message);
112
112
  expect(deserialized.id).toBe(messageId);
113
113
  });
114
+ test("Can concat artifact (string) of ToolMessageChunk", () => {
115
+ const rawOutputOne = "Hello";
116
+ const rawOutputTwo = " world";
117
+ const chunk1 = new ToolMessageChunk({
118
+ content: "Hello",
119
+ tool_call_id: "1",
120
+ artifact: rawOutputOne,
121
+ });
122
+ const chunk2 = new ToolMessageChunk({
123
+ content: " world",
124
+ tool_call_id: "1",
125
+ artifact: rawOutputTwo,
126
+ });
127
+ const concated = chunk1.concat(chunk2);
128
+ expect(concated.artifact).toBe(`${rawOutputOne}${rawOutputTwo}`);
129
+ });
130
+ test("Can concat artifact (array) of ToolMessageChunk", () => {
131
+ const rawOutputOne = ["Hello", " world"];
132
+ const rawOutputTwo = ["!!"];
133
+ const chunk1 = new ToolMessageChunk({
134
+ content: "Hello",
135
+ tool_call_id: "1",
136
+ artifact: rawOutputOne,
137
+ });
138
+ const chunk2 = new ToolMessageChunk({
139
+ content: " world",
140
+ tool_call_id: "1",
141
+ artifact: rawOutputTwo,
142
+ });
143
+ const concated = chunk1.concat(chunk2);
144
+ expect(concated.artifact).toEqual(["Hello", " world", "!!"]);
145
+ });
146
+ test("Can concat artifact (object) of ToolMessageChunk", () => {
147
+ const rawOutputOne = {
148
+ foo: "bar",
149
+ };
150
+ const rawOutputTwo = {
151
+ bar: "baz",
152
+ };
153
+ const chunk1 = new ToolMessageChunk({
154
+ content: "Hello",
155
+ tool_call_id: "1",
156
+ artifact: rawOutputOne,
157
+ });
158
+ const chunk2 = new ToolMessageChunk({
159
+ content: " world",
160
+ tool_call_id: "1",
161
+ artifact: rawOutputTwo,
162
+ });
163
+ const concated = chunk1.concat(chunk2);
164
+ expect(concated.artifact).toEqual({
165
+ foo: "bar",
166
+ bar: "baz",
167
+ });
168
+ });
169
+ describe("Complex AIMessageChunk concat", () => {
170
+ it("concatenates content arrays of strings", () => {
171
+ expect(new AIMessageChunk({
172
+ content: [{ type: "text", text: "I am" }],
173
+ id: "ai4",
174
+ }).concat(new AIMessageChunk({ content: [{ type: "text", text: " indeed." }] }))).toEqual(new AIMessageChunk({
175
+ id: "ai4",
176
+ content: [
177
+ { type: "text", text: "I am" },
178
+ { type: "text", text: " indeed." },
179
+ ],
180
+ }));
181
+ });
182
+ it("concatenates mixed content arrays", () => {
183
+ expect(new AIMessageChunk({
184
+ content: [{ index: 0, type: "text", text: "I am" }],
185
+ }).concat(new AIMessageChunk({ content: [{ type: "text", text: " indeed." }] }))).toEqual(new AIMessageChunk({
186
+ content: [
187
+ { index: 0, type: "text", text: "I am" },
188
+ { type: "text", text: " indeed." },
189
+ ],
190
+ }));
191
+ });
192
+ it("merges content arrays with same index", () => {
193
+ expect(new AIMessageChunk({ content: [{ index: 0, text: "I am" }] }).concat(new AIMessageChunk({ content: [{ index: 0, text: " indeed." }] }))).toEqual(new AIMessageChunk({ content: [{ index: 0, text: "I am indeed." }] }));
194
+ });
195
+ it("does not merge when one chunk is missing an index", () => {
196
+ expect(new AIMessageChunk({ content: [{ index: 0, text: "I am" }] }).concat(new AIMessageChunk({ content: [{ text: " indeed." }] }))).toEqual(new AIMessageChunk({
197
+ content: [{ index: 0, text: "I am" }, { text: " indeed." }],
198
+ }));
199
+ });
200
+ it("does not create a holey array when there's a gap between indexes", () => {
201
+ expect(new AIMessageChunk({ content: [{ index: 0, text: "I am" }] }).concat(new AIMessageChunk({ content: [{ index: 2, text: " indeed." }] }))).toEqual(new AIMessageChunk({
202
+ content: [
203
+ { index: 0, text: "I am" },
204
+ { index: 2, text: " indeed." },
205
+ ],
206
+ }));
207
+ });
208
+ it("does not merge content arrays with separate indexes", () => {
209
+ expect(new AIMessageChunk({ content: [{ index: 0, text: "I am" }] }).concat(new AIMessageChunk({ content: [{ index: 1, text: " indeed." }] }))).toEqual(new AIMessageChunk({
210
+ content: [
211
+ { index: 0, text: "I am" },
212
+ { index: 1, text: " indeed." },
213
+ ],
214
+ }));
215
+ });
216
+ it("merges content arrays with same index and type", () => {
217
+ expect(new AIMessageChunk({
218
+ content: [{ index: 0, text: "I am", type: "text_block" }],
219
+ }).concat(new AIMessageChunk({
220
+ content: [{ index: 0, text: " indeed.", type: "text_block" }],
221
+ }))).toEqual(new AIMessageChunk({
222
+ content: [{ index: 0, text: "I am indeed.", type: "text_block" }],
223
+ }));
224
+ });
225
+ it("merges content arrays with same index and different types without updating type", () => {
226
+ expect(new AIMessageChunk({
227
+ content: [{ index: 0, text: "I am", type: "text_block" }],
228
+ }).concat(new AIMessageChunk({
229
+ content: [{ index: 0, text: " indeed.", type: "text_block_delta" }],
230
+ }))).toEqual(new AIMessageChunk({
231
+ content: [{ index: 0, text: "I am indeed.", type: "text_block" }],
232
+ }));
233
+ });
234
+ it("concatenates empty string content and merges other fields", () => {
235
+ expect(new AIMessageChunk({
236
+ content: [{ index: 0, type: "text", text: "I am" }],
237
+ }).concat(new AIMessageChunk({
238
+ content: [{ type: "text", text: "" }],
239
+ response_metadata: { extra: "value" },
240
+ }))).toEqual(new AIMessageChunk({
241
+ content: [{ index: 0, type: "text", text: "I am" }],
242
+ response_metadata: { extra: "value" },
243
+ }));
244
+ });
245
+ });
@@ -3,6 +3,7 @@ import { filterMessages, mergeMessageRuns, trimMessages, } from "../transformers
3
3
  import { AIMessage } from "../ai.js";
4
4
  import { HumanMessage } from "../human.js";
5
5
  import { SystemMessage } from "../system.js";
6
+ import { getBufferString } from "../utils.js";
6
7
  describe("filterMessage", () => {
7
8
  const getMessages = () => [
8
9
  new SystemMessage("you're a good assistant."),
@@ -97,8 +98,8 @@ describe("mergeMessageRuns", () => {
97
98
  { type: "text", text: "my favorite dish is lasagna" },
98
99
  ],
99
100
  tool_calls: [
100
- { name: "blah_tool", args: { x: 2 }, id: "123" },
101
- { name: "blah_tool", args: { x: -10 }, id: "456" },
101
+ { name: "blah_tool", args: { x: 2 }, id: "123", type: "tool_call" },
102
+ { name: "blah_tool", args: { x: -10 }, id: "456", type: "tool_call" },
102
103
  ],
103
104
  id: "baz",
104
105
  }),
@@ -380,3 +381,54 @@ describe("trimMessages can trim", () => {
380
381
  expect(typeof trimmedMessages.func).toBe("function");
381
382
  });
382
383
  });
384
+ test("getBufferString can handle complex messages", () => {
385
+ const messageArr1 = [new HumanMessage("Hello there!")];
386
+ const messageArr2 = [
387
+ new AIMessage({
388
+ content: [
389
+ {
390
+ type: "text",
391
+ text: "Hello there!",
392
+ },
393
+ ],
394
+ }),
395
+ ];
396
+ const messageArr3 = [
397
+ new HumanMessage({
398
+ content: [
399
+ {
400
+ type: "image_url",
401
+ image_url: {
402
+ url: "https://example.com/image.jpg",
403
+ },
404
+ },
405
+ {
406
+ type: "image_url",
407
+ image_url: "https://example.com/image.jpg",
408
+ },
409
+ ],
410
+ }),
411
+ ];
412
+ const bufferString1 = getBufferString(messageArr1);
413
+ expect(bufferString1).toBe("Human: Hello there!");
414
+ const bufferString2 = getBufferString(messageArr2);
415
+ expect(bufferString2).toBe(`AI: ${JSON.stringify([
416
+ {
417
+ type: "text",
418
+ text: "Hello there!",
419
+ },
420
+ ], null, 2)}`);
421
+ const bufferString3 = getBufferString(messageArr3);
422
+ expect(bufferString3).toBe(`Human: ${JSON.stringify([
423
+ {
424
+ type: "image_url",
425
+ image_url: {
426
+ url: "https://example.com/image.jpg",
427
+ },
428
+ },
429
+ {
430
+ type: "image_url",
431
+ image_url: "https://example.com/image.jpg",
432
+ },
433
+ ], null, 2)}`);
434
+ });
@@ -25,7 +25,22 @@ class ToolMessage extends base_js_1.BaseMessage {
25
25
  writable: true,
26
26
  value: void 0
27
27
  });
28
+ /**
29
+ * Artifact of the Tool execution which is not meant to be sent to the model.
30
+ *
31
+ * Should only be specified if it is different from the message content, e.g. if only
32
+ * a subset of the full tool output is being passed as message content but the full
33
+ * output is needed in other parts of the code.
34
+ */
35
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
36
+ Object.defineProperty(this, "artifact", {
37
+ enumerable: true,
38
+ configurable: true,
39
+ writable: true,
40
+ value: void 0
41
+ });
28
42
  this.tool_call_id = fields.tool_call_id;
43
+ this.artifact = fields.artifact;
29
44
  }
30
45
  _getType() {
31
46
  return "tool";
@@ -33,6 +48,13 @@ class ToolMessage extends base_js_1.BaseMessage {
33
48
  static isInstance(message) {
34
49
  return message._getType() === "tool";
35
50
  }
51
+ get _printableFields() {
52
+ return {
53
+ ...super._printableFields,
54
+ tool_call_id: this.tool_call_id,
55
+ artifact: this.artifact,
56
+ };
57
+ }
36
58
  }
37
59
  exports.ToolMessage = ToolMessage;
38
60
  /**
@@ -48,7 +70,22 @@ class ToolMessageChunk extends base_js_1.BaseMessageChunk {
48
70
  writable: true,
49
71
  value: void 0
50
72
  });
73
+ /**
74
+ * Artifact of the Tool execution which is not meant to be sent to the model.
75
+ *
76
+ * Should only be specified if it is different from the message content, e.g. if only
77
+ * a subset of the full tool output is being passed as message content but the full
78
+ * output is needed in other parts of the code.
79
+ */
80
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
81
+ Object.defineProperty(this, "artifact", {
82
+ enumerable: true,
83
+ configurable: true,
84
+ writable: true,
85
+ value: void 0
86
+ });
51
87
  this.tool_call_id = fields.tool_call_id;
88
+ this.artifact = fields.artifact;
52
89
  }
53
90
  static lc_name() {
54
91
  return "ToolMessageChunk";
@@ -61,10 +98,18 @@ class ToolMessageChunk extends base_js_1.BaseMessageChunk {
61
98
  content: (0, base_js_1.mergeContent)(this.content, chunk.content),
62
99
  additional_kwargs: (0, base_js_1._mergeDicts)(this.additional_kwargs, chunk.additional_kwargs),
63
100
  response_metadata: (0, base_js_1._mergeDicts)(this.response_metadata, chunk.response_metadata),
101
+ artifact: (0, base_js_1._mergeObj)(this.artifact, chunk.artifact),
64
102
  tool_call_id: this.tool_call_id,
65
103
  id: this.id ?? chunk.id,
66
104
  });
67
105
  }
106
+ get _printableFields() {
107
+ return {
108
+ ...super._printableFields,
109
+ tool_call_id: this.tool_call_id,
110
+ artifact: this.artifact,
111
+ };
112
+ }
68
113
  }
69
114
  exports.ToolMessageChunk = ToolMessageChunk;
70
115
  function defaultToolCallParser(