langchain 1.2.19 → 1.2.20
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.
- package/CHANGELOG.md +21 -0
- package/dist/agents/middleware/llmToolSelector.d.ts +4 -4
- package/dist/agents/middleware/llmToolSelector.d.ts.map +1 -1
- package/dist/agents/middleware/summarization.d.ts +8 -8
- package/dist/agents/middleware/summarization.d.ts.map +1 -1
- package/dist/agents/middleware/types.cjs.map +1 -1
- package/dist/agents/middleware/types.d.cts +1 -1
- package/dist/agents/middleware/types.d.cts.map +1 -1
- package/dist/agents/middleware/types.d.ts +1 -1
- package/dist/agents/middleware/types.d.ts.map +1 -1
- package/dist/agents/middleware/types.js.map +1 -1
- package/dist/agents/middleware/utils.cjs +20 -3
- package/dist/agents/middleware/utils.cjs.map +1 -1
- package/dist/agents/middleware/utils.d.cts +8 -2
- package/dist/agents/middleware/utils.d.cts.map +1 -1
- package/dist/agents/middleware/utils.d.ts +8 -2
- package/dist/agents/middleware/utils.d.ts.map +1 -1
- package/dist/agents/middleware/utils.js +20 -3
- package/dist/agents/middleware/utils.js.map +1 -1
- package/dist/agents/nodes/AgentNode.cjs +86 -51
- package/dist/agents/nodes/AgentNode.cjs.map +1 -1
- package/dist/agents/nodes/AgentNode.js +87 -52
- package/dist/agents/nodes/AgentNode.js.map +1 -1
- package/dist/agents/nodes/middleware.cjs +4 -5
- package/dist/agents/nodes/middleware.cjs.map +1 -1
- package/dist/agents/nodes/middleware.js +4 -5
- package/dist/agents/nodes/middleware.js.map +1 -1
- package/package.json +5 -5
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"utils.cjs","names":["messages: BaseMessage[]","textContent: string","AIMessage","ToolMessage","hook:\n | BeforeAgentHook\n | BeforeModelHook\n | AfterAgentHook\n | AfterModelHook\n | undefined","arg: BeforeAgentHook | BeforeModelHook | AfterAgentHook | AfterModelHook","ms: number","config: {\n backoffFactor: number;\n initialDelayMs: number;\n maxDelayMs: number;\n jitter: boolean;\n }","retryNumber: number","delay: number"],"sources":["../../../src/agents/middleware/utils.ts"],"sourcesContent":["import {\n AIMessage,\n ToolMessage,\n type BaseMessage,\n} from \"@langchain/core/messages\";\nimport {\n AfterModelHook,\n AfterAgentHook,\n BeforeAgentHook,\n BeforeModelHook,\n} from \"./types.js\";\nimport { JumpToTarget } from \"../constants.js\";\n\n/**\n * Default token counter that approximates based on character count
|
|
1
|
+
{"version":3,"file":"utils.cjs","names":["messages: BaseMessage[]","tools?: Array<Record<string, any>> | null","textContent: string","AIMessage","ToolMessage","hook:\n | BeforeAgentHook\n | BeforeModelHook\n | AfterAgentHook\n | AfterModelHook\n | undefined","arg: BeforeAgentHook | BeforeModelHook | AfterAgentHook | AfterModelHook","ms: number","config: {\n backoffFactor: number;\n initialDelayMs: number;\n maxDelayMs: number;\n jitter: boolean;\n }","retryNumber: number","delay: number"],"sources":["../../../src/agents/middleware/utils.ts"],"sourcesContent":["import {\n AIMessage,\n ToolMessage,\n type BaseMessage,\n} from \"@langchain/core/messages\";\nimport { isLangChainTool } from \"@langchain/core/tools\";\nimport { convertToOpenAITool } from \"@langchain/core/utils/function_calling\";\nimport {\n AfterModelHook,\n AfterAgentHook,\n BeforeAgentHook,\n BeforeModelHook,\n} from \"./types.js\";\nimport { JumpToTarget } from \"../constants.js\";\n\n/**\n * Default token counter that approximates based on character count.\n *\n * If tools are provided, the token count also includes stringified tool schemas.\n *\n * @param messages Messages to count tokens for\n * @param tools Optional list of tools to include in the token count. Each tool\n * can be either a LangChain tool instance or a dict representing a tool schema.\n * LangChain tool instances are converted to OpenAI tool format before counting.\n * @returns Approximate token count\n */\nexport function countTokensApproximately(\n messages: BaseMessage[],\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n tools?: Array<Record<string, any>> | null\n): number {\n const charsPerToken = 4;\n let totalChars = 0;\n\n // Count tokens for tools if provided\n if (tools && tools.length > 0) {\n let toolsChars = 0;\n for (const tool of tools) {\n const toolDict = isLangChainTool(tool) ? convertToOpenAITool(tool) : tool;\n toolsChars += JSON.stringify(toolDict).length;\n }\n totalChars += toolsChars;\n }\n\n for (const msg of messages) {\n let textContent: string;\n if (typeof msg.content === \"string\") {\n textContent = msg.content;\n } else if (Array.isArray(msg.content)) {\n textContent = msg.content\n .map((item) => {\n if (typeof item === \"string\") return item;\n if (item.type === \"text\" && \"text\" in item) return item.text;\n return \"\";\n })\n .join(\"\");\n } else {\n textContent = \"\";\n }\n\n if (\n AIMessage.isInstance(msg) &&\n Array.isArray(msg.tool_calls) &&\n msg.tool_calls.length > 0\n ) {\n textContent += JSON.stringify(msg.tool_calls);\n }\n\n if (ToolMessage.isInstance(msg)) {\n textContent += msg.tool_call_id ?? \"\";\n }\n\n totalChars += textContent.length;\n }\n // Approximate 1 token = 4 characters\n return Math.ceil(totalChars / charsPerToken);\n}\n\nexport function getHookConstraint(\n hook:\n | BeforeAgentHook\n | BeforeModelHook\n | AfterAgentHook\n | AfterModelHook\n | undefined\n): JumpToTarget[] | undefined {\n if (!hook || typeof hook === \"function\") {\n return undefined;\n }\n return hook.canJumpTo;\n}\n\nexport function getHookFunction(\n arg: BeforeAgentHook | BeforeModelHook | AfterAgentHook | AfterModelHook\n) {\n if (typeof arg === \"function\") {\n return arg;\n }\n return arg.hook;\n}\n\n/**\n * Sleep for the specified number of milliseconds.\n */\nexport function sleep(ms: number): Promise<void> {\n return new Promise((resolve) => setTimeout(resolve, ms));\n}\n\n/**\n * Calculate delay for a retry attempt with exponential backoff and jitter.\n *\n * @param retryNumber - The retry attempt number (0-indexed)\n * @param config - Configuration for backoff calculation\n * @returns Delay in milliseconds before next retry\n *\n * @internal Exported for testing purposes\n */\nexport function calculateRetryDelay(\n config: {\n backoffFactor: number;\n initialDelayMs: number;\n maxDelayMs: number;\n jitter: boolean;\n },\n retryNumber: number\n): number {\n const { backoffFactor, initialDelayMs, maxDelayMs, jitter } = config;\n\n let delay: number;\n if (backoffFactor === 0.0) {\n delay = initialDelayMs;\n } else {\n delay = initialDelayMs * backoffFactor ** retryNumber;\n }\n\n // Cap at maxDelayMs\n delay = Math.min(delay, maxDelayMs);\n\n if (jitter && delay > 0) {\n const jitterAmount = delay * 0.25;\n delay = delay + (Math.random() * 2 - 1) * jitterAmount;\n // Ensure delay is not negative after jitter\n delay = Math.max(0, delay);\n }\n\n return delay;\n}\n"],"mappings":";;;;;;;;;;;;;;;;;AA0BA,SAAgB,yBACdA,UAEAC,OACQ;CACR,MAAM,gBAAgB;CACtB,IAAI,aAAa;AAGjB,KAAI,SAAS,MAAM,SAAS,GAAG;EAC7B,IAAI,aAAa;AACjB,OAAK,MAAM,QAAQ,OAAO;GACxB,MAAM,uDAA2B,KAAK,oEAAuB,KAAK,GAAG;GACrE,cAAc,KAAK,UAAU,SAAS,CAAC;EACxC;EACD,cAAc;CACf;AAED,MAAK,MAAM,OAAO,UAAU;EAC1B,IAAIC;AACJ,MAAI,OAAO,IAAI,YAAY,UACzB,cAAc,IAAI;WACT,MAAM,QAAQ,IAAI,QAAQ,EACnC,cAAc,IAAI,QACf,IAAI,CAAC,SAAS;AACb,OAAI,OAAO,SAAS,SAAU,QAAO;AACrC,OAAI,KAAK,SAAS,UAAU,UAAU,KAAM,QAAO,KAAK;AACxD,UAAO;EACR,EAAC,CACD,KAAK,GAAG;OAEX,cAAc;AAGhB,MACEC,oCAAU,WAAW,IAAI,IACzB,MAAM,QAAQ,IAAI,WAAW,IAC7B,IAAI,WAAW,SAAS,GAExB,eAAe,KAAK,UAAU,IAAI,WAAW;AAG/C,MAAIC,sCAAY,WAAW,IAAI,EAC7B,eAAe,IAAI,gBAAgB;EAGrC,cAAc,YAAY;CAC3B;AAED,QAAO,KAAK,KAAK,aAAa,cAAc;AAC7C;AAED,SAAgB,kBACdC,MAM4B;AAC5B,KAAI,CAAC,QAAQ,OAAO,SAAS,WAC3B,QAAO;AAET,QAAO,KAAK;AACb;AAED,SAAgB,gBACdC,KACA;AACA,KAAI,OAAO,QAAQ,WACjB,QAAO;AAET,QAAO,IAAI;AACZ;;;;AAKD,SAAgB,MAAMC,IAA2B;AAC/C,QAAO,IAAI,QAAQ,CAAC,YAAY,WAAW,SAAS,GAAG;AACxD;;;;;;;;;;AAWD,SAAgB,oBACdC,QAMAC,aACQ;CACR,MAAM,EAAE,eAAe,gBAAgB,YAAY,QAAQ,GAAG;CAE9D,IAAIC;AACJ,KAAI,kBAAkB,GACpB,QAAQ;MAER,QAAQ,iBAAiB,iBAAiB;CAI5C,QAAQ,KAAK,IAAI,OAAO,WAAW;AAEnC,KAAI,UAAU,QAAQ,GAAG;EACvB,MAAM,eAAe,QAAQ;EAC7B,QAAQ,SAAS,KAAK,QAAQ,GAAG,IAAI,KAAK;EAE1C,QAAQ,KAAK,IAAI,GAAG,MAAM;CAC3B;AAED,QAAO;AACR"}
|
|
@@ -3,11 +3,17 @@ import { BaseMessage } from "@langchain/core/messages";
|
|
|
3
3
|
//#region src/agents/middleware/utils.d.ts
|
|
4
4
|
|
|
5
5
|
/**
|
|
6
|
-
* Default token counter that approximates based on character count
|
|
6
|
+
* Default token counter that approximates based on character count.
|
|
7
|
+
*
|
|
8
|
+
* If tools are provided, the token count also includes stringified tool schemas.
|
|
9
|
+
*
|
|
7
10
|
* @param messages Messages to count tokens for
|
|
11
|
+
* @param tools Optional list of tools to include in the token count. Each tool
|
|
12
|
+
* can be either a LangChain tool instance or a dict representing a tool schema.
|
|
13
|
+
* LangChain tool instances are converted to OpenAI tool format before counting.
|
|
8
14
|
* @returns Approximate token count
|
|
9
15
|
*/
|
|
10
|
-
declare function countTokensApproximately(messages: BaseMessage[]): number;
|
|
16
|
+
declare function countTokensApproximately(messages: BaseMessage[], tools?: Array<Record<string, any>> | null): number;
|
|
11
17
|
//#endregion
|
|
12
18
|
export { countTokensApproximately };
|
|
13
19
|
//# sourceMappingURL=utils.d.cts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"utils.d.cts","names":["__types_js0","BaseMessage","AfterModelHook","AfterAgentHook","BeforeAgentHook","BeforeModelHook","JumpToTarget","countTokensApproximately","getHookConstraint","getHookFunction","___runtime_js0","AgentBuiltInState","Runtime","Partial","MiddlewareResult","Promise","sleep","calculateRetryDelay"],"sources":["../../../src/agents/middleware/utils.d.ts"],"sourcesContent":["import { type BaseMessage } from \"@langchain/core/messages\";\nimport { AfterModelHook, AfterAgentHook, BeforeAgentHook, BeforeModelHook } from \"./types.js\";\nimport { JumpToTarget } from \"../constants.js\";\n/**\n * Default token counter that approximates based on character count
|
|
1
|
+
{"version":3,"file":"utils.d.cts","names":["__types_js0","BaseMessage","AfterModelHook","AfterAgentHook","BeforeAgentHook","BeforeModelHook","JumpToTarget","countTokensApproximately","Record","Array","getHookConstraint","getHookFunction","___runtime_js0","AgentBuiltInState","Runtime","Partial","MiddlewareResult","Promise","sleep","calculateRetryDelay"],"sources":["../../../src/agents/middleware/utils.d.ts"],"sourcesContent":["import { type BaseMessage } from \"@langchain/core/messages\";\nimport { AfterModelHook, AfterAgentHook, BeforeAgentHook, BeforeModelHook } from \"./types.js\";\nimport { JumpToTarget } from \"../constants.js\";\n/**\n * Default token counter that approximates based on character count.\n *\n * If tools are provided, the token count also includes stringified tool schemas.\n *\n * @param messages Messages to count tokens for\n * @param tools Optional list of tools to include in the token count. Each tool\n * can be either a LangChain tool instance or a dict representing a tool schema.\n * LangChain tool instances are converted to OpenAI tool format before counting.\n * @returns Approximate token count\n */\nexport declare function countTokensApproximately(messages: BaseMessage[], tools?: Array<Record<string, any>> | null): number;\nexport declare function getHookConstraint(hook: BeforeAgentHook | BeforeModelHook | AfterAgentHook | AfterModelHook | undefined): JumpToTarget[] | undefined;\nexport declare function getHookFunction(arg: BeforeAgentHook | BeforeModelHook | AfterAgentHook | AfterModelHook): ((state: import(\"../runtime.js\").AgentBuiltInState, runtime: import(\"../runtime.js\").Runtime<unknown>) => Promise<import(\"./types.js\").MiddlewareResult<Partial<import(\"../runtime.js\").AgentBuiltInState>>> | import(\"./types.js\").MiddlewareResult<Partial<import(\"../runtime.js\").AgentBuiltInState>>) | ((state: import(\"../runtime.js\").AgentBuiltInState, runtime: import(\"../runtime.js\").Runtime<unknown>) => Promise<import(\"./types.js\").MiddlewareResult<Partial<import(\"../runtime.js\").AgentBuiltInState>>> | import(\"./types.js\").MiddlewareResult<Partial<import(\"../runtime.js\").AgentBuiltInState>>) | ((state: import(\"../runtime.js\").AgentBuiltInState, runtime: import(\"../runtime.js\").Runtime<unknown>) => Promise<import(\"./types.js\").MiddlewareResult<Partial<import(\"../runtime.js\").AgentBuiltInState>>> | import(\"./types.js\").MiddlewareResult<Partial<import(\"../runtime.js\").AgentBuiltInState>>) | ((state: import(\"../runtime.js\").AgentBuiltInState, runtime: import(\"../runtime.js\").Runtime<unknown>) => Promise<import(\"./types.js\").MiddlewareResult<Partial<import(\"../runtime.js\").AgentBuiltInState>>> | import(\"./types.js\").MiddlewareResult<Partial<import(\"../runtime.js\").AgentBuiltInState>>);\n/**\n * Sleep for the specified number of milliseconds.\n */\nexport declare function sleep(ms: number): Promise<void>;\n/**\n * Calculate delay for a retry attempt with exponential backoff and jitter.\n *\n * @param retryNumber - The retry attempt number (0-indexed)\n * @param config - Configuration for backoff calculation\n * @returns Delay in milliseconds before next retry\n *\n * @internal Exported for testing purposes\n */\nexport declare function calculateRetryDelay(config: {\n backoffFactor: number;\n initialDelayMs: number;\n maxDelayMs: number;\n jitter: boolean;\n}, retryNumber: number): number;\n//# sourceMappingURL=utils.d.ts.map"],"mappings":";;;;AAcA;;;;AAAuF;;;;;;;iBAA/DO,wBAAAA,WAAmCN,uBAAuBQ,MAAMD"}
|
|
@@ -5,11 +5,17 @@ import { BaseMessage } from "@langchain/core/messages";
|
|
|
5
5
|
//#region src/agents/middleware/utils.d.ts
|
|
6
6
|
|
|
7
7
|
/**
|
|
8
|
-
* Default token counter that approximates based on character count
|
|
8
|
+
* Default token counter that approximates based on character count.
|
|
9
|
+
*
|
|
10
|
+
* If tools are provided, the token count also includes stringified tool schemas.
|
|
11
|
+
*
|
|
9
12
|
* @param messages Messages to count tokens for
|
|
13
|
+
* @param tools Optional list of tools to include in the token count. Each tool
|
|
14
|
+
* can be either a LangChain tool instance or a dict representing a tool schema.
|
|
15
|
+
* LangChain tool instances are converted to OpenAI tool format before counting.
|
|
10
16
|
* @returns Approximate token count
|
|
11
17
|
*/
|
|
12
|
-
declare function countTokensApproximately(messages: BaseMessage[]): number;
|
|
18
|
+
declare function countTokensApproximately(messages: BaseMessage[], tools?: Array<Record<string, any>> | null): number;
|
|
13
19
|
//#endregion
|
|
14
20
|
export { countTokensApproximately };
|
|
15
21
|
//# sourceMappingURL=utils.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"utils.d.ts","names":["__types_js0","BaseMessage","AfterModelHook","AfterAgentHook","BeforeAgentHook","BeforeModelHook","JumpToTarget","countTokensApproximately","getHookConstraint","getHookFunction","___runtime_js0","AgentBuiltInState","Runtime","Partial","MiddlewareResult","Promise","sleep","calculateRetryDelay"],"sources":["../../../src/agents/middleware/utils.d.ts"],"sourcesContent":["import { type BaseMessage } from \"@langchain/core/messages\";\nimport { AfterModelHook, AfterAgentHook, BeforeAgentHook, BeforeModelHook } from \"./types.js\";\nimport { JumpToTarget } from \"../constants.js\";\n/**\n * Default token counter that approximates based on character count
|
|
1
|
+
{"version":3,"file":"utils.d.ts","names":["__types_js0","BaseMessage","AfterModelHook","AfterAgentHook","BeforeAgentHook","BeforeModelHook","JumpToTarget","countTokensApproximately","Record","Array","getHookConstraint","getHookFunction","___runtime_js0","AgentBuiltInState","Runtime","Partial","MiddlewareResult","Promise","sleep","calculateRetryDelay"],"sources":["../../../src/agents/middleware/utils.d.ts"],"sourcesContent":["import { type BaseMessage } from \"@langchain/core/messages\";\nimport { AfterModelHook, AfterAgentHook, BeforeAgentHook, BeforeModelHook } from \"./types.js\";\nimport { JumpToTarget } from \"../constants.js\";\n/**\n * Default token counter that approximates based on character count.\n *\n * If tools are provided, the token count also includes stringified tool schemas.\n *\n * @param messages Messages to count tokens for\n * @param tools Optional list of tools to include in the token count. Each tool\n * can be either a LangChain tool instance or a dict representing a tool schema.\n * LangChain tool instances are converted to OpenAI tool format before counting.\n * @returns Approximate token count\n */\nexport declare function countTokensApproximately(messages: BaseMessage[], tools?: Array<Record<string, any>> | null): number;\nexport declare function getHookConstraint(hook: BeforeAgentHook | BeforeModelHook | AfterAgentHook | AfterModelHook | undefined): JumpToTarget[] | undefined;\nexport declare function getHookFunction(arg: BeforeAgentHook | BeforeModelHook | AfterAgentHook | AfterModelHook): ((state: import(\"../runtime.js\").AgentBuiltInState, runtime: import(\"../runtime.js\").Runtime<unknown>) => Promise<import(\"./types.js\").MiddlewareResult<Partial<import(\"../runtime.js\").AgentBuiltInState>>> | import(\"./types.js\").MiddlewareResult<Partial<import(\"../runtime.js\").AgentBuiltInState>>) | ((state: import(\"../runtime.js\").AgentBuiltInState, runtime: import(\"../runtime.js\").Runtime<unknown>) => Promise<import(\"./types.js\").MiddlewareResult<Partial<import(\"../runtime.js\").AgentBuiltInState>>> | import(\"./types.js\").MiddlewareResult<Partial<import(\"../runtime.js\").AgentBuiltInState>>) | ((state: import(\"../runtime.js\").AgentBuiltInState, runtime: import(\"../runtime.js\").Runtime<unknown>) => Promise<import(\"./types.js\").MiddlewareResult<Partial<import(\"../runtime.js\").AgentBuiltInState>>> | import(\"./types.js\").MiddlewareResult<Partial<import(\"../runtime.js\").AgentBuiltInState>>) | ((state: import(\"../runtime.js\").AgentBuiltInState, runtime: import(\"../runtime.js\").Runtime<unknown>) => Promise<import(\"./types.js\").MiddlewareResult<Partial<import(\"../runtime.js\").AgentBuiltInState>>> | import(\"./types.js\").MiddlewareResult<Partial<import(\"../runtime.js\").AgentBuiltInState>>);\n/**\n * Sleep for the specified number of milliseconds.\n */\nexport declare function sleep(ms: number): Promise<void>;\n/**\n * Calculate delay for a retry attempt with exponential backoff and jitter.\n *\n * @param retryNumber - The retry attempt number (0-indexed)\n * @param config - Configuration for backoff calculation\n * @returns Delay in milliseconds before next retry\n *\n * @internal Exported for testing purposes\n */\nexport declare function calculateRetryDelay(config: {\n backoffFactor: number;\n initialDelayMs: number;\n maxDelayMs: number;\n jitter: boolean;\n}, retryNumber: number): number;\n//# sourceMappingURL=utils.d.ts.map"],"mappings":";;;;;;;;AAcA;;;;AAAuF;;;;;iBAA/DO,wBAAAA,WAAmCN,uBAAuBQ,MAAMD"}
|
|
@@ -1,13 +1,30 @@
|
|
|
1
1
|
import { AIMessage, ToolMessage } from "@langchain/core/messages";
|
|
2
|
+
import { isLangChainTool } from "@langchain/core/tools";
|
|
3
|
+
import { convertToOpenAITool } from "@langchain/core/utils/function_calling";
|
|
2
4
|
|
|
3
5
|
//#region src/agents/middleware/utils.ts
|
|
4
6
|
/**
|
|
5
|
-
* Default token counter that approximates based on character count
|
|
7
|
+
* Default token counter that approximates based on character count.
|
|
8
|
+
*
|
|
9
|
+
* If tools are provided, the token count also includes stringified tool schemas.
|
|
10
|
+
*
|
|
6
11
|
* @param messages Messages to count tokens for
|
|
12
|
+
* @param tools Optional list of tools to include in the token count. Each tool
|
|
13
|
+
* can be either a LangChain tool instance or a dict representing a tool schema.
|
|
14
|
+
* LangChain tool instances are converted to OpenAI tool format before counting.
|
|
7
15
|
* @returns Approximate token count
|
|
8
16
|
*/
|
|
9
|
-
function countTokensApproximately(messages) {
|
|
17
|
+
function countTokensApproximately(messages, tools) {
|
|
18
|
+
const charsPerToken = 4;
|
|
10
19
|
let totalChars = 0;
|
|
20
|
+
if (tools && tools.length > 0) {
|
|
21
|
+
let toolsChars = 0;
|
|
22
|
+
for (const tool$1 of tools) {
|
|
23
|
+
const toolDict = isLangChainTool(tool$1) ? convertToOpenAITool(tool$1) : tool$1;
|
|
24
|
+
toolsChars += JSON.stringify(toolDict).length;
|
|
25
|
+
}
|
|
26
|
+
totalChars += toolsChars;
|
|
27
|
+
}
|
|
11
28
|
for (const msg of messages) {
|
|
12
29
|
let textContent;
|
|
13
30
|
if (typeof msg.content === "string") textContent = msg.content;
|
|
@@ -21,7 +38,7 @@ function countTokensApproximately(messages) {
|
|
|
21
38
|
if (ToolMessage.isInstance(msg)) textContent += msg.tool_call_id ?? "";
|
|
22
39
|
totalChars += textContent.length;
|
|
23
40
|
}
|
|
24
|
-
return Math.ceil(totalChars /
|
|
41
|
+
return Math.ceil(totalChars / charsPerToken);
|
|
25
42
|
}
|
|
26
43
|
function getHookConstraint(hook) {
|
|
27
44
|
if (!hook || typeof hook === "function") return void 0;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"utils.js","names":["messages: BaseMessage[]","textContent: string","hook:\n | BeforeAgentHook\n | BeforeModelHook\n | AfterAgentHook\n | AfterModelHook\n | undefined","arg: BeforeAgentHook | BeforeModelHook | AfterAgentHook | AfterModelHook","ms: number","config: {\n backoffFactor: number;\n initialDelayMs: number;\n maxDelayMs: number;\n jitter: boolean;\n }","retryNumber: number","delay: number"],"sources":["../../../src/agents/middleware/utils.ts"],"sourcesContent":["import {\n AIMessage,\n ToolMessage,\n type BaseMessage,\n} from \"@langchain/core/messages\";\nimport {\n AfterModelHook,\n AfterAgentHook,\n BeforeAgentHook,\n BeforeModelHook,\n} from \"./types.js\";\nimport { JumpToTarget } from \"../constants.js\";\n\n/**\n * Default token counter that approximates based on character count
|
|
1
|
+
{"version":3,"file":"utils.js","names":["messages: BaseMessage[]","tools?: Array<Record<string, any>> | null","tool","textContent: string","hook:\n | BeforeAgentHook\n | BeforeModelHook\n | AfterAgentHook\n | AfterModelHook\n | undefined","arg: BeforeAgentHook | BeforeModelHook | AfterAgentHook | AfterModelHook","ms: number","config: {\n backoffFactor: number;\n initialDelayMs: number;\n maxDelayMs: number;\n jitter: boolean;\n }","retryNumber: number","delay: number"],"sources":["../../../src/agents/middleware/utils.ts"],"sourcesContent":["import {\n AIMessage,\n ToolMessage,\n type BaseMessage,\n} from \"@langchain/core/messages\";\nimport { isLangChainTool } from \"@langchain/core/tools\";\nimport { convertToOpenAITool } from \"@langchain/core/utils/function_calling\";\nimport {\n AfterModelHook,\n AfterAgentHook,\n BeforeAgentHook,\n BeforeModelHook,\n} from \"./types.js\";\nimport { JumpToTarget } from \"../constants.js\";\n\n/**\n * Default token counter that approximates based on character count.\n *\n * If tools are provided, the token count also includes stringified tool schemas.\n *\n * @param messages Messages to count tokens for\n * @param tools Optional list of tools to include in the token count. Each tool\n * can be either a LangChain tool instance or a dict representing a tool schema.\n * LangChain tool instances are converted to OpenAI tool format before counting.\n * @returns Approximate token count\n */\nexport function countTokensApproximately(\n messages: BaseMessage[],\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n tools?: Array<Record<string, any>> | null\n): number {\n const charsPerToken = 4;\n let totalChars = 0;\n\n // Count tokens for tools if provided\n if (tools && tools.length > 0) {\n let toolsChars = 0;\n for (const tool of tools) {\n const toolDict = isLangChainTool(tool) ? convertToOpenAITool(tool) : tool;\n toolsChars += JSON.stringify(toolDict).length;\n }\n totalChars += toolsChars;\n }\n\n for (const msg of messages) {\n let textContent: string;\n if (typeof msg.content === \"string\") {\n textContent = msg.content;\n } else if (Array.isArray(msg.content)) {\n textContent = msg.content\n .map((item) => {\n if (typeof item === \"string\") return item;\n if (item.type === \"text\" && \"text\" in item) return item.text;\n return \"\";\n })\n .join(\"\");\n } else {\n textContent = \"\";\n }\n\n if (\n AIMessage.isInstance(msg) &&\n Array.isArray(msg.tool_calls) &&\n msg.tool_calls.length > 0\n ) {\n textContent += JSON.stringify(msg.tool_calls);\n }\n\n if (ToolMessage.isInstance(msg)) {\n textContent += msg.tool_call_id ?? \"\";\n }\n\n totalChars += textContent.length;\n }\n // Approximate 1 token = 4 characters\n return Math.ceil(totalChars / charsPerToken);\n}\n\nexport function getHookConstraint(\n hook:\n | BeforeAgentHook\n | BeforeModelHook\n | AfterAgentHook\n | AfterModelHook\n | undefined\n): JumpToTarget[] | undefined {\n if (!hook || typeof hook === \"function\") {\n return undefined;\n }\n return hook.canJumpTo;\n}\n\nexport function getHookFunction(\n arg: BeforeAgentHook | BeforeModelHook | AfterAgentHook | AfterModelHook\n) {\n if (typeof arg === \"function\") {\n return arg;\n }\n return arg.hook;\n}\n\n/**\n * Sleep for the specified number of milliseconds.\n */\nexport function sleep(ms: number): Promise<void> {\n return new Promise((resolve) => setTimeout(resolve, ms));\n}\n\n/**\n * Calculate delay for a retry attempt with exponential backoff and jitter.\n *\n * @param retryNumber - The retry attempt number (0-indexed)\n * @param config - Configuration for backoff calculation\n * @returns Delay in milliseconds before next retry\n *\n * @internal Exported for testing purposes\n */\nexport function calculateRetryDelay(\n config: {\n backoffFactor: number;\n initialDelayMs: number;\n maxDelayMs: number;\n jitter: boolean;\n },\n retryNumber: number\n): number {\n const { backoffFactor, initialDelayMs, maxDelayMs, jitter } = config;\n\n let delay: number;\n if (backoffFactor === 0.0) {\n delay = initialDelayMs;\n } else {\n delay = initialDelayMs * backoffFactor ** retryNumber;\n }\n\n // Cap at maxDelayMs\n delay = Math.min(delay, maxDelayMs);\n\n if (jitter && delay > 0) {\n const jitterAmount = delay * 0.25;\n delay = delay + (Math.random() * 2 - 1) * jitterAmount;\n // Ensure delay is not negative after jitter\n delay = Math.max(0, delay);\n }\n\n return delay;\n}\n"],"mappings":";;;;;;;;;;;;;;;;AA0BA,SAAgB,yBACdA,UAEAC,OACQ;CACR,MAAM,gBAAgB;CACtB,IAAI,aAAa;AAGjB,KAAI,SAAS,MAAM,SAAS,GAAG;EAC7B,IAAI,aAAa;AACjB,OAAK,MAAMC,UAAQ,OAAO;GACxB,MAAM,WAAW,gBAAgBA,OAAK,GAAG,oBAAoBA,OAAK,GAAGA;GACrE,cAAc,KAAK,UAAU,SAAS,CAAC;EACxC;EACD,cAAc;CACf;AAED,MAAK,MAAM,OAAO,UAAU;EAC1B,IAAIC;AACJ,MAAI,OAAO,IAAI,YAAY,UACzB,cAAc,IAAI;WACT,MAAM,QAAQ,IAAI,QAAQ,EACnC,cAAc,IAAI,QACf,IAAI,CAAC,SAAS;AACb,OAAI,OAAO,SAAS,SAAU,QAAO;AACrC,OAAI,KAAK,SAAS,UAAU,UAAU,KAAM,QAAO,KAAK;AACxD,UAAO;EACR,EAAC,CACD,KAAK,GAAG;OAEX,cAAc;AAGhB,MACE,UAAU,WAAW,IAAI,IACzB,MAAM,QAAQ,IAAI,WAAW,IAC7B,IAAI,WAAW,SAAS,GAExB,eAAe,KAAK,UAAU,IAAI,WAAW;AAG/C,MAAI,YAAY,WAAW,IAAI,EAC7B,eAAe,IAAI,gBAAgB;EAGrC,cAAc,YAAY;CAC3B;AAED,QAAO,KAAK,KAAK,aAAa,cAAc;AAC7C;AAED,SAAgB,kBACdC,MAM4B;AAC5B,KAAI,CAAC,QAAQ,OAAO,SAAS,WAC3B,QAAO;AAET,QAAO,KAAK;AACb;AAED,SAAgB,gBACdC,KACA;AACA,KAAI,OAAO,QAAQ,WACjB,QAAO;AAET,QAAO,IAAI;AACZ;;;;AAKD,SAAgB,MAAMC,IAA2B;AAC/C,QAAO,IAAI,QAAQ,CAAC,YAAY,WAAW,SAAS,GAAG;AACxD;;;;;;;;;;AAWD,SAAgB,oBACdC,QAMAC,aACQ;CACR,MAAM,EAAE,eAAe,gBAAgB,YAAY,QAAQ,GAAG;CAE9D,IAAIC;AACJ,KAAI,kBAAkB,GACpB,QAAQ;MAER,QAAQ,iBAAiB,iBAAiB;CAI5C,QAAQ,KAAK,IAAI,OAAO,WAAW;AAEnC,KAAI,UAAU,QAAQ,GAAG;EACvB,MAAM,eAAe,QAAQ;EAC7B,QAAQ,SAAS,KAAK,QAAQ,GAAG,IAAI,KAAK;EAE1C,QAAQ,KAAK,IAAI,GAAG,MAAM;CAC3B;AAED,QAAO;AACR"}
|
|
@@ -18,7 +18,7 @@ const __langchain_core_utils_types = require_rolldown_runtime.__toESM(require("@
|
|
|
18
18
|
* @returns True if the response is an internal model response, false otherwise.
|
|
19
19
|
*/
|
|
20
20
|
function isInternalModelResponse(response) {
|
|
21
|
-
return __langchain_core_messages.AIMessage.isInstance(response) || typeof response === "object" && response !== null && "structuredResponse" in response && "messages" in response;
|
|
21
|
+
return __langchain_core_messages.AIMessage.isInstance(response) || (0, __langchain_langgraph.isCommand)(response) || typeof response === "object" && response !== null && "structuredResponse" in response && "messages" in response;
|
|
22
22
|
}
|
|
23
23
|
/**
|
|
24
24
|
* The name of the agent node in the state graph.
|
|
@@ -27,7 +27,6 @@ const AGENT_NODE_NAME = "model_request";
|
|
|
27
27
|
var AgentNode = class extends require_RunnableCallable.RunnableCallable {
|
|
28
28
|
#options;
|
|
29
29
|
#systemMessage;
|
|
30
|
-
#currentSystemMessage;
|
|
31
30
|
constructor(options) {
|
|
32
31
|
super({
|
|
33
32
|
name: options.name ?? "model",
|
|
@@ -76,31 +75,35 @@ var AgentNode = class extends require_RunnableCallable.RunnableCallable {
|
|
|
76
75
|
* If so, we should generate structured response (if needed) and stop
|
|
77
76
|
*/
|
|
78
77
|
const lastMessage = state.messages.at(-1);
|
|
79
|
-
if (lastMessage && __langchain_core_messages.ToolMessage.isInstance(lastMessage) && lastMessage.name && this.#options.shouldReturnDirect.has(lastMessage.name))
|
|
80
|
-
|
|
81
|
-
* return directly without invoking the model again
|
|
82
|
-
*/
|
|
83
|
-
return { messages: [] };
|
|
84
|
-
const response = await this.#invokeModel(state, config);
|
|
78
|
+
if (lastMessage && __langchain_core_messages.ToolMessage.isInstance(lastMessage) && lastMessage.name && this.#options.shouldReturnDirect.has(lastMessage.name)) return [new __langchain_langgraph.Command({ update: { messages: [] } })];
|
|
79
|
+
const { response, lastAiMessage, collectedCommands } = await this.#invokeModel(state, config);
|
|
85
80
|
/**
|
|
86
|
-
*
|
|
81
|
+
* structuredResponse — return as a plain state update dict (not a Command)
|
|
82
|
+
* because the structuredResponse channel uses UntrackedValue(guard=true)
|
|
83
|
+
* which only allows a single write per step.
|
|
87
84
|
*/
|
|
88
|
-
if ("structuredResponse" in response)
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
85
|
+
if (typeof response === "object" && response !== null && "structuredResponse" in response && "messages" in response) {
|
|
86
|
+
const { structuredResponse, messages } = response;
|
|
87
|
+
return {
|
|
88
|
+
messages: [...state.messages, ...messages],
|
|
89
|
+
structuredResponse
|
|
90
|
+
};
|
|
91
|
+
}
|
|
92
|
+
const commands = [];
|
|
93
|
+
const aiMessage = __langchain_core_messages.AIMessage.isInstance(response) ? response : lastAiMessage;
|
|
94
|
+
if (aiMessage) {
|
|
95
|
+
aiMessage.name = this.name;
|
|
96
|
+
aiMessage.lc_kwargs.name = this.name;
|
|
97
|
+
if (this.#areMoreStepsNeeded(state, aiMessage)) commands.push(new __langchain_langgraph.Command({ update: { messages: [new __langchain_core_messages.AIMessage({
|
|
98
|
+
content: "Sorry, need more steps to process this request.",
|
|
99
|
+
name: this.name,
|
|
100
|
+
id: aiMessage.id
|
|
101
|
+
})] } }));
|
|
102
|
+
else commands.push(new __langchain_langgraph.Command({ update: { messages: [aiMessage] } }));
|
|
103
|
+
}
|
|
104
|
+
if ((0, __langchain_langgraph.isCommand)(response) && !collectedCommands.includes(response)) commands.push(response);
|
|
105
|
+
commands.push(...collectedCommands);
|
|
106
|
+
return commands;
|
|
104
107
|
}
|
|
105
108
|
/**
|
|
106
109
|
* Derive the model from the options.
|
|
@@ -117,6 +120,18 @@ var AgentNode = class extends require_RunnableCallable.RunnableCallable {
|
|
|
117
120
|
const model = await this.#deriveModel();
|
|
118
121
|
const lgConfig = config;
|
|
119
122
|
/**
|
|
123
|
+
* Create a local variable for current system message to avoid concurrency issues
|
|
124
|
+
* Each invocation gets its own copy
|
|
125
|
+
*/
|
|
126
|
+
let currentSystemMessage = this.#systemMessage;
|
|
127
|
+
/**
|
|
128
|
+
* Shared tracking state for AIMessage and Command collection.
|
|
129
|
+
* lastAiMessage tracks the effective AIMessage through the middleware chain.
|
|
130
|
+
* collectedCommands accumulates Commands returned by middleware (not base handler).
|
|
131
|
+
*/
|
|
132
|
+
let lastAiMessage = null;
|
|
133
|
+
const collectedCommands = [];
|
|
134
|
+
/**
|
|
120
135
|
* Create the base handler that performs the actual model invocation
|
|
121
136
|
*/
|
|
122
137
|
const baseHandler = async (request) => {
|
|
@@ -129,38 +144,39 @@ var AgentNode = class extends require_RunnableCallable.RunnableCallable {
|
|
|
129
144
|
/**
|
|
130
145
|
* prepend the system message to the messages if it is not empty
|
|
131
146
|
*/
|
|
132
|
-
const messages = [...
|
|
147
|
+
const messages = [...currentSystemMessage.text === "" ? [] : [currentSystemMessage], ...request.messages];
|
|
133
148
|
const signal = require_utils$1.mergeAbortSignals(this.#options.signal, config.signal);
|
|
134
|
-
const response = await (0, __langchain_core_runnables.raceWithSignal)(modelWithTools.invoke(messages, {
|
|
149
|
+
const response$1 = await (0, __langchain_core_runnables.raceWithSignal)(modelWithTools.invoke(messages, {
|
|
135
150
|
...config,
|
|
136
151
|
signal
|
|
137
152
|
}), signal);
|
|
153
|
+
lastAiMessage = response$1;
|
|
138
154
|
/**
|
|
139
155
|
* if the user requests a native schema output, try to parse the response
|
|
140
156
|
* and return the structured response if it is valid
|
|
141
157
|
*/
|
|
142
158
|
if (structuredResponseFormat?.type === "native") {
|
|
143
|
-
const structuredResponse = structuredResponseFormat.strategy.parse(response);
|
|
159
|
+
const structuredResponse = structuredResponseFormat.strategy.parse(response$1);
|
|
144
160
|
if (structuredResponse) return {
|
|
145
161
|
structuredResponse,
|
|
146
|
-
messages: [response]
|
|
162
|
+
messages: [response$1]
|
|
147
163
|
};
|
|
148
|
-
return response;
|
|
164
|
+
return response$1;
|
|
149
165
|
}
|
|
150
|
-
if (!structuredResponseFormat || !response.tool_calls) return response;
|
|
151
|
-
const toolCalls = response.tool_calls.filter((call) => call.name in structuredResponseFormat.tools);
|
|
166
|
+
if (!structuredResponseFormat || !response$1.tool_calls) return response$1;
|
|
167
|
+
const toolCalls = response$1.tool_calls.filter((call) => call.name in structuredResponseFormat.tools);
|
|
152
168
|
/**
|
|
153
169
|
* if there were not structured tool calls, we can return the response
|
|
154
170
|
*/
|
|
155
|
-
if (toolCalls.length === 0) return response;
|
|
171
|
+
if (toolCalls.length === 0) return response$1;
|
|
156
172
|
/**
|
|
157
173
|
* if there were multiple structured tool calls, we should throw an error as this
|
|
158
174
|
* scenario is not defined/supported.
|
|
159
175
|
*/
|
|
160
|
-
if (toolCalls.length > 1) return this.#handleMultipleStructuredOutputs(response, toolCalls, structuredResponseFormat);
|
|
176
|
+
if (toolCalls.length > 1) return this.#handleMultipleStructuredOutputs(response$1, toolCalls, structuredResponseFormat);
|
|
161
177
|
const toolStrategy = structuredResponseFormat.tools[toolCalls[0].name];
|
|
162
178
|
const toolMessageContent = toolStrategy?.options?.toolMessageContent;
|
|
163
|
-
return this.#handleSingleStructuredOutput(response, toolCalls[0], structuredResponseFormat, toolMessageContent ?? options.lastMessage);
|
|
179
|
+
return this.#handleSingleStructuredOutput(response$1, toolCalls[0], structuredResponseFormat, toolMessageContent ?? options.lastMessage);
|
|
164
180
|
};
|
|
165
181
|
const wrapperMiddleware = this.#options.wrapModelCallHookMiddleware ?? [];
|
|
166
182
|
let wrappedHandler = baseHandler;
|
|
@@ -217,43 +233,53 @@ var AgentNode = class extends require_RunnableCallable.RunnableCallable {
|
|
|
217
233
|
const invalidTools = modifiedTools.filter((tool) => require_utils.isClientTool(tool) && this.#options.toolClasses.every((t) => t !== tool));
|
|
218
234
|
if (invalidTools.length > 0) throw new Error(`You have modified a tool in "wrapModelCall" hook of middleware "${currentMiddleware.name}": ${invalidTools.map((tool) => tool.name).join(", ")}. This is not supported.`);
|
|
219
235
|
let normalizedReq = req;
|
|
220
|
-
const hasSystemPromptChanged = req.systemPrompt !==
|
|
221
|
-
const hasSystemMessageChanged = req.systemMessage !==
|
|
236
|
+
const hasSystemPromptChanged = req.systemPrompt !== currentSystemMessage.text;
|
|
237
|
+
const hasSystemMessageChanged = req.systemMessage !== currentSystemMessage;
|
|
222
238
|
if (hasSystemPromptChanged && hasSystemMessageChanged) throw new Error("Cannot change both systemPrompt and systemMessage in the same request.");
|
|
223
239
|
/**
|
|
224
240
|
* Check if systemPrompt is a string was changed, if so create a new SystemMessage
|
|
225
241
|
*/
|
|
226
242
|
if (hasSystemPromptChanged) {
|
|
227
|
-
|
|
243
|
+
currentSystemMessage = new __langchain_core_messages.SystemMessage({ content: [{
|
|
228
244
|
type: "text",
|
|
229
245
|
text: req.systemPrompt
|
|
230
246
|
}] });
|
|
231
247
|
normalizedReq = {
|
|
232
248
|
...req,
|
|
233
|
-
systemPrompt:
|
|
234
|
-
systemMessage:
|
|
249
|
+
systemPrompt: currentSystemMessage.text,
|
|
250
|
+
systemMessage: currentSystemMessage
|
|
235
251
|
};
|
|
236
252
|
}
|
|
237
253
|
/**
|
|
238
254
|
* If the systemMessage was changed, update the current system message
|
|
239
255
|
*/
|
|
240
256
|
if (hasSystemMessageChanged) {
|
|
241
|
-
|
|
257
|
+
currentSystemMessage = new __langchain_core_messages.SystemMessage({ ...req.systemMessage });
|
|
242
258
|
normalizedReq = {
|
|
243
259
|
...req,
|
|
244
|
-
systemPrompt:
|
|
245
|
-
systemMessage:
|
|
260
|
+
systemPrompt: currentSystemMessage.text,
|
|
261
|
+
systemMessage: currentSystemMessage
|
|
246
262
|
};
|
|
247
263
|
}
|
|
248
|
-
|
|
264
|
+
const innerHandlerResult = await innerHandler(normalizedReq);
|
|
265
|
+
/**
|
|
266
|
+
* Normalize Commands so middleware always sees AIMessage from handler().
|
|
267
|
+
* When an inner middleware returns a Command, substitute the tracked
|
|
268
|
+
* lastAiMessage. The raw Command is still captured in innerHandlerResult
|
|
269
|
+
* for the framework's Command collection.
|
|
270
|
+
*/
|
|
271
|
+
if ((0, __langchain_langgraph.isCommand)(innerHandlerResult) && lastAiMessage) return lastAiMessage;
|
|
272
|
+
return innerHandlerResult;
|
|
249
273
|
};
|
|
250
274
|
if (!currentMiddleware.wrapModelCall) return handlerWithValidation(requestWithStateAndRuntime);
|
|
251
275
|
try {
|
|
252
276
|
const middlewareResponse = await currentMiddleware.wrapModelCall(requestWithStateAndRuntime, handlerWithValidation);
|
|
253
277
|
/**
|
|
254
|
-
* Validate that this specific middleware returned a valid
|
|
278
|
+
* Validate that this specific middleware returned a valid response
|
|
255
279
|
*/
|
|
256
|
-
if (!isInternalModelResponse(middlewareResponse)) throw new Error(`Invalid response from "wrapModelCall" in middleware "${currentMiddleware.name}": expected AIMessage, got ${typeof middlewareResponse}`);
|
|
280
|
+
if (!isInternalModelResponse(middlewareResponse)) throw new Error(`Invalid response from "wrapModelCall" in middleware "${currentMiddleware.name}": expected AIMessage or Command, got ${typeof middlewareResponse}`);
|
|
281
|
+
if (__langchain_core_messages.AIMessage.isInstance(middlewareResponse)) lastAiMessage = middlewareResponse;
|
|
282
|
+
else if ((0, __langchain_langgraph.isCommand)(middlewareResponse)) collectedCommands.push(middlewareResponse);
|
|
257
283
|
return middlewareResponse;
|
|
258
284
|
} catch (error) {
|
|
259
285
|
throw require_errors.MiddlewareError.wrap(error, currentMiddleware.name);
|
|
@@ -266,11 +292,11 @@ var AgentNode = class extends require_RunnableCallable.RunnableCallable {
|
|
|
266
292
|
* Reset current system prompt to initial state and convert to string using .text getter
|
|
267
293
|
* for backwards compatibility with ModelRequest
|
|
268
294
|
*/
|
|
269
|
-
|
|
295
|
+
currentSystemMessage = this.#systemMessage;
|
|
270
296
|
const initialRequest = {
|
|
271
297
|
model,
|
|
272
|
-
systemPrompt:
|
|
273
|
-
systemMessage:
|
|
298
|
+
systemPrompt: currentSystemMessage?.text,
|
|
299
|
+
systemMessage: currentSystemMessage,
|
|
274
300
|
messages: state.messages,
|
|
275
301
|
tools: this.#options.toolClasses,
|
|
276
302
|
state,
|
|
@@ -281,7 +307,12 @@ var AgentNode = class extends require_RunnableCallable.RunnableCallable {
|
|
|
281
307
|
signal: lgConfig.signal
|
|
282
308
|
})
|
|
283
309
|
};
|
|
284
|
-
|
|
310
|
+
const response = await wrappedHandler(initialRequest);
|
|
311
|
+
return {
|
|
312
|
+
response,
|
|
313
|
+
lastAiMessage,
|
|
314
|
+
collectedCommands
|
|
315
|
+
};
|
|
285
316
|
}
|
|
286
317
|
/**
|
|
287
318
|
* If the model returns multiple structured outputs, we need to handle it.
|
|
@@ -439,9 +470,13 @@ var AgentNode = class extends require_RunnableCallable.RunnableCallable {
|
|
|
439
470
|
const modelRunnable = this.#options.includeAgentName === "inline" ? require_withAgentName.withAgentName(modelWithTools, this.#options.includeAgentName) : modelWithTools;
|
|
440
471
|
return modelRunnable;
|
|
441
472
|
}
|
|
473
|
+
/**
|
|
474
|
+
* Returns internal bookkeeping state for StateManager, not graph output.
|
|
475
|
+
* The return shape differs from the node's output type (Command).
|
|
476
|
+
*/
|
|
442
477
|
getState() {
|
|
443
478
|
const state = super.getState();
|
|
444
|
-
const origState = state && !(
|
|
479
|
+
const origState = state && !(0, __langchain_langgraph.isCommand)(state) ? state : {};
|
|
445
480
|
return {
|
|
446
481
|
messages: [],
|
|
447
482
|
...origState
|