@langchain/langgraph 0.0.11 → 0.0.13

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 (134) hide show
  1. package/dist/channels/any_value.cjs +57 -0
  2. package/dist/channels/any_value.d.ts +16 -0
  3. package/dist/channels/any_value.js +53 -0
  4. package/dist/channels/base.cjs +19 -28
  5. package/dist/channels/base.d.ts +13 -19
  6. package/dist/channels/base.js +17 -24
  7. package/dist/channels/binop.cjs +4 -3
  8. package/dist/channels/binop.d.ts +1 -1
  9. package/dist/channels/binop.js +3 -2
  10. package/dist/channels/dynamic_barrier_value.cjs +88 -0
  11. package/dist/channels/dynamic_barrier_value.d.ts +26 -0
  12. package/dist/channels/dynamic_barrier_value.js +84 -0
  13. package/dist/channels/ephemeral_value.cjs +64 -0
  14. package/dist/channels/ephemeral_value.d.ts +14 -0
  15. package/dist/channels/ephemeral_value.js +60 -0
  16. package/dist/channels/index.cjs +1 -3
  17. package/dist/channels/index.d.ts +1 -1
  18. package/dist/channels/index.js +1 -1
  19. package/dist/channels/last_value.cjs +11 -5
  20. package/dist/channels/last_value.d.ts +5 -1
  21. package/dist/channels/last_value.js +9 -3
  22. package/dist/channels/named_barrier_value.cjs +71 -0
  23. package/dist/channels/named_barrier_value.d.ts +18 -0
  24. package/dist/channels/named_barrier_value.js +66 -0
  25. package/dist/channels/topic.cjs +5 -3
  26. package/dist/channels/topic.d.ts +3 -3
  27. package/dist/channels/topic.js +5 -3
  28. package/dist/checkpoint/base.cjs +30 -12
  29. package/dist/checkpoint/base.d.ts +39 -22
  30. package/dist/checkpoint/base.js +28 -11
  31. package/dist/checkpoint/id.cjs +40 -0
  32. package/dist/checkpoint/id.d.ts +2 -0
  33. package/dist/checkpoint/id.js +35 -0
  34. package/dist/checkpoint/index.cjs +2 -2
  35. package/dist/checkpoint/index.d.ts +2 -2
  36. package/dist/checkpoint/index.js +2 -2
  37. package/dist/checkpoint/memory.cjs +63 -49
  38. package/dist/checkpoint/memory.d.ts +7 -10
  39. package/dist/checkpoint/memory.js +62 -47
  40. package/dist/checkpoint/sqlite.cjs +170 -0
  41. package/dist/checkpoint/sqlite.d.ts +14 -0
  42. package/dist/checkpoint/sqlite.js +163 -0
  43. package/dist/constants.cjs +3 -1
  44. package/dist/constants.d.ts +2 -0
  45. package/dist/constants.js +2 -0
  46. package/dist/errors.cjs +31 -0
  47. package/dist/errors.d.ts +12 -0
  48. package/dist/errors.js +24 -0
  49. package/dist/graph/graph.cjs +234 -96
  50. package/dist/graph/graph.d.ts +52 -23
  51. package/dist/graph/graph.js +233 -97
  52. package/dist/graph/index.cjs +2 -2
  53. package/dist/graph/index.d.ts +2 -2
  54. package/dist/graph/index.js +2 -2
  55. package/dist/graph/message.cjs +4 -3
  56. package/dist/graph/message.d.ts +4 -1
  57. package/dist/graph/message.js +4 -3
  58. package/dist/graph/state.cjs +237 -102
  59. package/dist/graph/state.d.ts +41 -18
  60. package/dist/graph/state.js +238 -104
  61. package/dist/index.cjs +6 -2
  62. package/dist/index.d.ts +3 -2
  63. package/dist/index.js +2 -1
  64. package/dist/prebuilt/agent_executor.cjs +22 -36
  65. package/dist/prebuilt/agent_executor.d.ts +7 -10
  66. package/dist/prebuilt/agent_executor.js +23 -37
  67. package/dist/prebuilt/chat_agent_executor.cjs +13 -13
  68. package/dist/prebuilt/chat_agent_executor.d.ts +3 -1
  69. package/dist/prebuilt/chat_agent_executor.js +15 -15
  70. package/dist/prebuilt/index.cjs +4 -1
  71. package/dist/prebuilt/index.d.ts +1 -0
  72. package/dist/prebuilt/index.js +1 -0
  73. package/dist/prebuilt/tool_node.cjs +59 -0
  74. package/dist/prebuilt/tool_node.d.ts +17 -0
  75. package/dist/prebuilt/tool_node.js +54 -0
  76. package/dist/pregel/debug.cjs +6 -8
  77. package/dist/pregel/debug.d.ts +2 -2
  78. package/dist/pregel/debug.js +5 -7
  79. package/dist/pregel/index.cjs +406 -236
  80. package/dist/pregel/index.d.ts +77 -41
  81. package/dist/pregel/index.js +408 -241
  82. package/dist/pregel/io.cjs +117 -30
  83. package/dist/pregel/io.d.ts +11 -3
  84. package/dist/pregel/io.js +111 -28
  85. package/dist/pregel/read.cjs +126 -46
  86. package/dist/pregel/read.d.ts +27 -18
  87. package/dist/pregel/read.js +125 -45
  88. package/dist/pregel/types.cjs +2 -0
  89. package/dist/pregel/types.d.ts +32 -0
  90. package/dist/pregel/types.js +1 -0
  91. package/dist/pregel/validate.cjs +58 -51
  92. package/dist/pregel/validate.d.ts +14 -13
  93. package/dist/pregel/validate.js +56 -50
  94. package/dist/pregel/write.cjs +46 -30
  95. package/dist/pregel/write.d.ts +18 -8
  96. package/dist/pregel/write.js +45 -29
  97. package/dist/serde/base.cjs +2 -0
  98. package/dist/serde/base.d.ts +4 -0
  99. package/dist/serde/base.js +1 -0
  100. package/dist/setup/async_local_storage.cjs +2 -2
  101. package/dist/setup/async_local_storage.js +1 -1
  102. package/dist/tests/channels.test.d.ts +1 -0
  103. package/dist/tests/channels.test.js +151 -0
  104. package/dist/tests/chatbot.int.test.d.ts +1 -0
  105. package/dist/tests/chatbot.int.test.js +61 -0
  106. package/dist/tests/checkpoints.test.d.ts +1 -0
  107. package/dist/tests/checkpoints.test.js +190 -0
  108. package/dist/tests/graph.test.d.ts +1 -0
  109. package/dist/tests/graph.test.js +15 -0
  110. package/dist/tests/prebuilt.int.test.d.ts +1 -0
  111. package/dist/tests/prebuilt.int.test.js +101 -0
  112. package/dist/tests/prebuilt.test.d.ts +1 -0
  113. package/dist/tests/prebuilt.test.js +195 -0
  114. package/dist/tests/pregel.io.test.d.ts +1 -0
  115. package/dist/tests/pregel.io.test.js +332 -0
  116. package/dist/tests/pregel.read.test.d.ts +1 -0
  117. package/dist/tests/pregel.read.test.js +109 -0
  118. package/dist/tests/pregel.test.d.ts +1 -0
  119. package/dist/tests/pregel.test.js +1879 -0
  120. package/dist/tests/pregel.validate.test.d.ts +1 -0
  121. package/dist/tests/pregel.validate.test.js +198 -0
  122. package/dist/tests/pregel.write.test.d.ts +1 -0
  123. package/dist/tests/pregel.write.test.js +44 -0
  124. package/dist/tests/tracing.int.test.d.ts +1 -0
  125. package/dist/tests/tracing.int.test.js +449 -0
  126. package/dist/tests/utils.d.ts +22 -0
  127. package/dist/tests/utils.js +76 -0
  128. package/dist/utils.cjs +74 -0
  129. package/dist/utils.d.ts +18 -0
  130. package/dist/utils.js +70 -0
  131. package/package.json +12 -8
  132. package/dist/pregel/reserved.cjs +0 -6
  133. package/dist/pregel/reserved.d.ts +0 -3
  134. package/dist/pregel/reserved.js +0 -3
@@ -0,0 +1,190 @@
1
+ import { describe, it, expect } from "@jest/globals";
2
+ import { deepCopy } from "../checkpoint/base.js";
3
+ import { MemorySaver } from "../checkpoint/memory.js";
4
+ import { SqliteSaver } from "../checkpoint/sqlite.js";
5
+ import { convert1to6, uuid6 } from "../checkpoint/id.js";
6
+ const checkpoint1 = {
7
+ v: 1,
8
+ id: uuid6(-1),
9
+ ts: "2024-04-19T17:19:07.952Z",
10
+ channel_values: {
11
+ someKey1: "someValue1",
12
+ },
13
+ channel_versions: {
14
+ someKey2: 1,
15
+ },
16
+ versions_seen: {
17
+ someKey3: {
18
+ someKey4: 1,
19
+ },
20
+ },
21
+ };
22
+ const checkpoint2 = {
23
+ v: 1,
24
+ id: uuid6(1),
25
+ ts: "2024-04-20T17:19:07.952Z",
26
+ channel_values: {
27
+ someKey1: "someValue2",
28
+ },
29
+ channel_versions: {
30
+ someKey2: 2,
31
+ },
32
+ versions_seen: {
33
+ someKey3: {
34
+ someKey4: 2,
35
+ },
36
+ },
37
+ };
38
+ describe("Base", () => {
39
+ it("should deep copy a simple object", () => {
40
+ const obj = { a: 1, b: { c: 2 } };
41
+ const copiedObj = deepCopy(obj);
42
+ // Check if the copied object is equal to the original object
43
+ expect(copiedObj).toEqual(obj);
44
+ // Check if the copied object is not the same object reference as the original object
45
+ expect(copiedObj).not.toBe(obj);
46
+ // Check if the nested object is also deep copied
47
+ expect(copiedObj.b).toEqual(obj.b);
48
+ expect(copiedObj.b).not.toBe(obj.b);
49
+ });
50
+ it("should deep copy an array", () => {
51
+ const arr = [1, 2, 3];
52
+ const copiedArr = deepCopy(arr);
53
+ // Check if the copied array is equal to the original array
54
+ expect(copiedArr).toEqual(arr);
55
+ });
56
+ it("should deep copy an array of objects", () => {
57
+ const arr = [{ a: 1 }, { b: 2 }];
58
+ const copiedArr = deepCopy(arr);
59
+ // Check if the copied array is equal to the original array
60
+ expect(copiedArr).toEqual(arr);
61
+ // Check if the copied array is not the same array reference as the original array
62
+ expect(copiedArr).not.toBe(arr);
63
+ // Check if the nested objects in the array are also deep copied
64
+ expect(copiedArr[0]).toEqual(arr[0]);
65
+ expect(copiedArr[0]).not.toBe(arr[0]);
66
+ });
67
+ });
68
+ describe("MemorySaver", () => {
69
+ it("should save and retrieve checkpoints correctly", async () => {
70
+ const memorySaver = new MemorySaver();
71
+ // save checkpoint
72
+ const runnableConfig = await memorySaver.put({ configurable: { thread_id: "1" } }, checkpoint1, { source: "update", step: -1 });
73
+ expect(runnableConfig).toEqual({
74
+ configurable: {
75
+ thread_id: "1",
76
+ checkpoint_id: checkpoint1.id,
77
+ },
78
+ });
79
+ // get checkpoint tuple
80
+ const checkpointTuple = await memorySaver.getTuple({
81
+ configurable: { thread_id: "1" },
82
+ });
83
+ expect(checkpointTuple?.config).toEqual({
84
+ configurable: {
85
+ thread_id: "1",
86
+ checkpoint_id: checkpoint1.id,
87
+ },
88
+ });
89
+ expect(checkpointTuple?.checkpoint).toEqual(checkpoint1);
90
+ // save another checkpoint
91
+ await memorySaver.put({ configurable: { thread_id: "1" } }, checkpoint2, {
92
+ source: "update",
93
+ step: -1,
94
+ });
95
+ // list checkpoints
96
+ const checkpointTupleGenerator = await memorySaver.list({
97
+ configurable: { thread_id: "1" },
98
+ });
99
+ const checkpointTuples = [];
100
+ for await (const checkpoint of checkpointTupleGenerator) {
101
+ checkpointTuples.push(checkpoint);
102
+ }
103
+ expect(checkpointTuples.length).toBe(2);
104
+ const checkpointTuple1 = checkpointTuples[0];
105
+ const checkpointTuple2 = checkpointTuples[1];
106
+ expect(checkpointTuple1.checkpoint.ts).toBe("2024-04-20T17:19:07.952Z");
107
+ expect(checkpointTuple2.checkpoint.ts).toBe("2024-04-19T17:19:07.952Z");
108
+ });
109
+ });
110
+ describe("SqliteSaver", () => {
111
+ it("should save and retrieve checkpoints correctly", async () => {
112
+ const sqliteSaver = SqliteSaver.fromConnString(":memory:");
113
+ // get undefined checkpoint
114
+ const undefinedCheckpoint = await sqliteSaver.getTuple({
115
+ configurable: { thread_id: "1" },
116
+ });
117
+ expect(undefinedCheckpoint).toBeUndefined();
118
+ // save first checkpoint
119
+ const runnableConfig = await sqliteSaver.put({ configurable: { thread_id: "1" } }, checkpoint1, { source: "update", step: -1 });
120
+ expect(runnableConfig).toEqual({
121
+ configurable: {
122
+ thread_id: "1",
123
+ checkpoint_id: checkpoint1.id,
124
+ },
125
+ });
126
+ // get first checkpoint tuple
127
+ const firstCheckpointTuple = await sqliteSaver.getTuple({
128
+ configurable: { thread_id: "1" },
129
+ });
130
+ expect(firstCheckpointTuple?.config).toEqual({
131
+ configurable: {
132
+ thread_id: "1",
133
+ checkpoint_id: checkpoint1.id,
134
+ },
135
+ });
136
+ expect(firstCheckpointTuple?.checkpoint).toEqual(checkpoint1);
137
+ expect(firstCheckpointTuple?.parentConfig).toBeUndefined();
138
+ // save second checkpoint
139
+ await sqliteSaver.put({
140
+ configurable: {
141
+ thread_id: "1",
142
+ checkpoint_id: "2024-04-18T17:19:07.952Z",
143
+ },
144
+ }, checkpoint2, { source: "update", step: -1 });
145
+ // verify that parentTs is set and retrieved correctly for second checkpoint
146
+ const secondCheckpointTuple = await sqliteSaver.getTuple({
147
+ configurable: { thread_id: "1" },
148
+ });
149
+ expect(secondCheckpointTuple?.parentConfig).toEqual({
150
+ configurable: {
151
+ thread_id: "1",
152
+ checkpoint_id: "2024-04-18T17:19:07.952Z",
153
+ },
154
+ });
155
+ // list checkpoints
156
+ const checkpointTupleGenerator = await sqliteSaver.list({
157
+ configurable: { thread_id: "1" },
158
+ });
159
+ const checkpointTuples = [];
160
+ for await (const checkpoint of checkpointTupleGenerator) {
161
+ checkpointTuples.push(checkpoint);
162
+ }
163
+ expect(checkpointTuples.length).toBe(2);
164
+ const checkpointTuple1 = checkpointTuples[0];
165
+ const checkpointTuple2 = checkpointTuples[1];
166
+ expect(checkpointTuple1.checkpoint.ts).toBe("2024-04-20T17:19:07.952Z");
167
+ expect(checkpointTuple2.checkpoint.ts).toBe("2024-04-19T17:19:07.952Z");
168
+ });
169
+ });
170
+ describe("id", () => {
171
+ it("should convert uuid1 to uuid6", () => {
172
+ const regex = /^[0-9a-f]{8}-[0-9a-f]{4}-6[0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12}$/;
173
+ // [UUIDv1, UUIDv6]
174
+ const cases = [
175
+ [
176
+ "5714f720-1268-11e7-a24b-96d95aa38c32",
177
+ "1e712685-714f-6720-a24b-96d95aa38c32",
178
+ ],
179
+ [
180
+ "68f820c0-1268-11e7-a24b-671acd892c6a",
181
+ "1e712686-8f82-60c0-a24b-671acd892c6a",
182
+ ],
183
+ ];
184
+ cases.forEach(([v1, v6]) => {
185
+ const converted = convert1to6(v1);
186
+ expect(converted).toBe(v6);
187
+ expect(converted).toMatch(regex);
188
+ });
189
+ });
190
+ });
@@ -0,0 +1 @@
1
+ export {};
@@ -0,0 +1,15 @@
1
+ import { describe, it, expect } from "@jest/globals";
2
+ import { StateGraph } from "../graph/state.js";
3
+ describe("State", () => {
4
+ it("should validate a new node key correctly ", () => {
5
+ const stateGraph = new StateGraph({
6
+ channels: { existingStateAttributeKey: null },
7
+ });
8
+ expect(() => {
9
+ stateGraph.addNode("existingStateAttributeKey", (_) => ({}));
10
+ }).toThrow("existingStateAttributeKey");
11
+ expect(() => {
12
+ stateGraph.addNode("newNodeKey", (_) => ({}));
13
+ }).not.toThrow();
14
+ });
15
+ });
@@ -0,0 +1 @@
1
+ export {};
@@ -0,0 +1,101 @@
1
+ /* eslint-disable no-process-env */
2
+ import { it, beforeAll, describe, expect } from "@jest/globals";
3
+ import { Tool } from "@langchain/core/tools";
4
+ import { ChatOpenAI } from "@langchain/openai";
5
+ import { HumanMessage } from "@langchain/core/messages";
6
+ import { END } from "../index.js";
7
+ import { createFunctionCallingExecutor } from "../prebuilt/index.js";
8
+ // Tracing slows down the tests
9
+ beforeAll(() => {
10
+ process.env.LANGCHAIN_TRACING_V2 = "false";
11
+ process.env.LANGCHAIN_ENDPOINT = "";
12
+ process.env.LANGCHAIN_API_KEY = "";
13
+ process.env.LANGCHAIN_PROJECT = "";
14
+ });
15
+ describe("createFunctionCallingExecutor", () => {
16
+ it("can call a function", async () => {
17
+ const weatherResponse = `Not too cold, not too hot 😎`;
18
+ const model = new ChatOpenAI();
19
+ class SanFranciscoWeatherTool extends Tool {
20
+ constructor() {
21
+ super();
22
+ Object.defineProperty(this, "name", {
23
+ enumerable: true,
24
+ configurable: true,
25
+ writable: true,
26
+ value: "current_weather"
27
+ });
28
+ Object.defineProperty(this, "description", {
29
+ enumerable: true,
30
+ configurable: true,
31
+ writable: true,
32
+ value: "Get the current weather report for San Francisco, CA"
33
+ });
34
+ }
35
+ async _call(_) {
36
+ return weatherResponse;
37
+ }
38
+ }
39
+ const tools = [new SanFranciscoWeatherTool()];
40
+ const functionsAgentExecutor = createFunctionCallingExecutor({
41
+ model,
42
+ tools,
43
+ });
44
+ const response = await functionsAgentExecutor.invoke({
45
+ messages: [new HumanMessage("What's the weather like in SF?")],
46
+ });
47
+ console.log(response);
48
+ // It needs at least one human message, one AI and one function message.
49
+ expect(response.messages.length > 3).toBe(true);
50
+ const firstFunctionMessage = response.messages.find((message) => message._getType() === "function");
51
+ expect(firstFunctionMessage).toBeDefined();
52
+ expect(firstFunctionMessage?.content).toBe(weatherResponse);
53
+ });
54
+ it("can stream a function", async () => {
55
+ const weatherResponse = `Not too cold, not too hot 😎`;
56
+ const model = new ChatOpenAI({
57
+ streaming: true,
58
+ });
59
+ class SanFranciscoWeatherTool extends Tool {
60
+ constructor() {
61
+ super();
62
+ Object.defineProperty(this, "name", {
63
+ enumerable: true,
64
+ configurable: true,
65
+ writable: true,
66
+ value: "current_weather"
67
+ });
68
+ Object.defineProperty(this, "description", {
69
+ enumerable: true,
70
+ configurable: true,
71
+ writable: true,
72
+ value: "Get the current weather report for San Francisco, CA"
73
+ });
74
+ }
75
+ async _call(_) {
76
+ return weatherResponse;
77
+ }
78
+ }
79
+ const tools = [new SanFranciscoWeatherTool()];
80
+ const functionsAgentExecutor = createFunctionCallingExecutor({
81
+ model,
82
+ tools,
83
+ });
84
+ const stream = await functionsAgentExecutor.stream({
85
+ messages: [new HumanMessage("What's the weather like in SF?")],
86
+ });
87
+ const fullResponse = [];
88
+ for await (const item of stream) {
89
+ console.log(item);
90
+ console.log("-----\n");
91
+ fullResponse.push(item);
92
+ }
93
+ // Needs at least 3 llm calls, plus one `__end__` call.
94
+ expect(fullResponse.length >= 4).toBe(true);
95
+ const endMessage = fullResponse[fullResponse.length - 1];
96
+ expect(END in endMessage).toBe(true);
97
+ expect(endMessage[END].messages.length > 0).toBe(true);
98
+ const functionCall = endMessage[END].messages.find((message) => message._getType() === "function");
99
+ expect(functionCall.content).toBe(weatherResponse);
100
+ });
101
+ });
@@ -0,0 +1 @@
1
+ export {};
@@ -0,0 +1,195 @@
1
+ /* eslint-disable no-process-env */
2
+ import { it, expect, beforeAll, describe } from "@jest/globals";
3
+ import { PromptTemplate } from "@langchain/core/prompts";
4
+ import { FakeStreamingLLM } from "@langchain/core/utils/testing";
5
+ import { Tool } from "@langchain/core/tools";
6
+ import { createAgentExecutor } from "../prebuilt/index.js";
7
+ // Tracing slows down the tests
8
+ beforeAll(() => {
9
+ process.env.LANGCHAIN_TRACING_V2 = "false";
10
+ process.env.LANGCHAIN_ENDPOINT = "";
11
+ process.env.LANGCHAIN_ENDPOINT = "";
12
+ process.env.LANGCHAIN_API_KEY = "";
13
+ process.env.LANGCHAIN_PROJECT = "";
14
+ });
15
+ describe("PreBuilt", () => {
16
+ class SearchAPI extends Tool {
17
+ constructor() {
18
+ super();
19
+ Object.defineProperty(this, "name", {
20
+ enumerable: true,
21
+ configurable: true,
22
+ writable: true,
23
+ value: "search_api"
24
+ });
25
+ Object.defineProperty(this, "description", {
26
+ enumerable: true,
27
+ configurable: true,
28
+ writable: true,
29
+ value: "A simple API that returns the input string."
30
+ });
31
+ }
32
+ async _call(query) {
33
+ return `result for ${query}`;
34
+ }
35
+ }
36
+ const tools = [new SearchAPI()];
37
+ it("Can invoke createAgentExecutor", async () => {
38
+ const prompt = PromptTemplate.fromTemplate("Hello!");
39
+ const llm = new FakeStreamingLLM({
40
+ responses: [
41
+ "tool:search_api:query",
42
+ "tool:search_api:another",
43
+ "finish:answer",
44
+ ],
45
+ });
46
+ const agentParser = (input) => {
47
+ if (input.startsWith("finish")) {
48
+ const answer = input.split(":")[1];
49
+ return {
50
+ returnValues: { answer },
51
+ log: input,
52
+ };
53
+ }
54
+ const [, toolName, toolInput] = input.split(":");
55
+ return {
56
+ tool: toolName,
57
+ toolInput,
58
+ log: input,
59
+ };
60
+ };
61
+ const agent = prompt.pipe(llm).pipe(agentParser);
62
+ const agentExecutor = createAgentExecutor({
63
+ agentRunnable: agent,
64
+ tools,
65
+ });
66
+ const result = await agentExecutor.invoke({
67
+ input: "what is the weather in sf?",
68
+ });
69
+ expect(result).toEqual({
70
+ input: "what is the weather in sf?",
71
+ agentOutcome: {
72
+ returnValues: {
73
+ answer: "answer",
74
+ },
75
+ log: "finish:answer",
76
+ },
77
+ steps: [
78
+ {
79
+ action: {
80
+ tool: "search_api",
81
+ toolInput: "query",
82
+ log: "tool:search_api:query",
83
+ },
84
+ observation: "result for query",
85
+ },
86
+ {
87
+ action: {
88
+ tool: "search_api",
89
+ toolInput: "another",
90
+ log: "tool:search_api:another",
91
+ },
92
+ observation: "result for another",
93
+ },
94
+ ],
95
+ });
96
+ });
97
+ it("Can stream createAgentExecutor", async () => {
98
+ const prompt = PromptTemplate.fromTemplate("Hello!");
99
+ const llm = new FakeStreamingLLM({
100
+ responses: [
101
+ "tool:search_api:query",
102
+ "tool:search_api:another",
103
+ "finish:answer",
104
+ ],
105
+ });
106
+ const agentParser = (input) => {
107
+ if (input.startsWith("finish")) {
108
+ const answer = input.split(":")[1];
109
+ return {
110
+ returnValues: { answer },
111
+ log: input,
112
+ };
113
+ }
114
+ const [, toolName, toolInput] = input.split(":");
115
+ return {
116
+ tool: toolName,
117
+ toolInput,
118
+ log: input,
119
+ };
120
+ };
121
+ const agent = prompt.pipe(llm).pipe(agentParser);
122
+ const agentExecutor = createAgentExecutor({
123
+ agentRunnable: agent,
124
+ tools,
125
+ });
126
+ const stream = agentExecutor.stream({
127
+ input: "what is the weather in sf?",
128
+ });
129
+ const fullResponse = [];
130
+ for await (const item of await stream) {
131
+ fullResponse.push(item);
132
+ }
133
+ expect(fullResponse.length > 3).toBe(true);
134
+ const allAgentMessages = fullResponse.filter((res) => "agent" in res);
135
+ expect(allAgentMessages.length >= 3).toBe(true);
136
+ expect(fullResponse).toEqual([
137
+ {
138
+ agent: {
139
+ agentOutcome: {
140
+ log: "tool:search_api:query",
141
+ tool: "search_api",
142
+ toolInput: "query",
143
+ },
144
+ },
145
+ },
146
+ {
147
+ action: {
148
+ steps: [
149
+ {
150
+ action: {
151
+ log: "tool:search_api:query",
152
+ tool: "search_api",
153
+ toolInput: "query",
154
+ },
155
+ observation: "result for query",
156
+ },
157
+ ],
158
+ },
159
+ },
160
+ {
161
+ agent: {
162
+ agentOutcome: {
163
+ log: "tool:search_api:another",
164
+ tool: "search_api",
165
+ toolInput: "another",
166
+ },
167
+ },
168
+ },
169
+ {
170
+ action: {
171
+ steps: [
172
+ {
173
+ action: {
174
+ log: "tool:search_api:another",
175
+ tool: "search_api",
176
+ toolInput: "another",
177
+ },
178
+ observation: "result for another",
179
+ },
180
+ ],
181
+ },
182
+ },
183
+ {
184
+ agent: {
185
+ agentOutcome: {
186
+ log: "finish:answer",
187
+ returnValues: {
188
+ answer: "answer",
189
+ },
190
+ },
191
+ },
192
+ },
193
+ ]);
194
+ });
195
+ });
@@ -0,0 +1 @@
1
+ export {};