UNPKG

langchain

Version:
1 lines 8.17 kB
{"version":3,"file":"middleware.cjs","names":["RunnableCallable","getHookConstraint","derivePrivateState"],"sources":["../../../src/agents/nodes/middleware.ts"],"sourcesContent":["/* oxlint-disable @typescript-eslint/no-explicit-any */\nimport { LangGraphRunnableConfig, Command } from \"@langchain/langgraph\";\nimport {\n getInteropZodObjectShape,\n interopParse,\n isInteropZodObject,\n} from \"@langchain/core/utils/types\";\n\nimport { RunnableCallable, RunnableCallableArgs } from \"../RunnableCallable.js\";\nimport type { JumpToTarget } from \"../constants.js\";\nimport type { Runtime } from \"../runtime.js\";\nimport type {\n AnyAgentMiddleware,\n MiddlewareResult,\n} from \"../middleware/types.js\";\nimport { derivePrivateState } from \"./utils.js\";\nimport { getHookConstraint } from \"../middleware/utils.js\";\n\n/**\n * Named class for context objects to provide better error messages\n */\nclass AgentContext {}\nclass AgentRuntime {}\n\ntype NodeOutput<TStateSchema extends Record<string, any>> =\n | TStateSchema\n | Command<any, TStateSchema, string>\n | { jumpTo?: JumpToTarget };\n\nexport abstract class MiddlewareNode<\n TStateSchema extends Record<string, any>,\n TContextSchema extends Record<string, any>,\n> extends RunnableCallable<TStateSchema, NodeOutput<TStateSchema>> {\n abstract middleware: AnyAgentMiddleware;\n\n constructor(\n fields: RunnableCallableArgs<TStateSchema, NodeOutput<TStateSchema>>\n ) {\n super(fields);\n }\n\n abstract runHook(\n state: TStateSchema,\n config?: Runtime<TContextSchema>\n ): Promise<MiddlewareResult<TStateSchema>> | MiddlewareResult<TStateSchema>;\n\n async invokeMiddleware(\n invokeState: TStateSchema,\n config?: LangGraphRunnableConfig\n ): Promise<NodeOutput<TStateSchema>> {\n /**\n * Filter context based on middleware's contextSchema\n */\n let filteredContext = {} as TContextSchema;\n /**\n * Parse context using middleware's contextSchema to apply defaults and validation\n */\n if (\n this.middleware.contextSchema &&\n isInteropZodObject(this.middleware.contextSchema)\n ) {\n /**\n * Extract only the fields relevant to this middleware's schema\n */\n const schemaShape = getInteropZodObjectShape(\n this.middleware.contextSchema\n );\n if (schemaShape) {\n const relevantContext: Record<string, unknown> = {};\n const invokeContext = config?.context || {};\n for (const key of Object.keys(schemaShape)) {\n if (key in invokeContext) {\n relevantContext[key] = invokeContext[key];\n }\n }\n /**\n * Parse to apply defaults and validation, even if relevantContext is empty\n * This will throw if required fields are missing and no defaults exist\n */\n filteredContext = interopParse(\n this.middleware.contextSchema,\n relevantContext\n ) as TContextSchema;\n }\n }\n\n const state: TStateSchema = {\n ...invokeState,\n /**\n * don't overwrite possible outdated messages from other middleware nodes\n */\n messages: invokeState.messages,\n };\n\n const runtime: Runtime<TContextSchema> = {\n context: filteredContext,\n store: config?.store,\n configurable: config?.configurable,\n writer: config?.writer,\n interrupt: config?.interrupt,\n signal: config?.signal,\n };\n\n const result = await this.runHook(\n state,\n /**\n * assign runtime and context values into empty named class\n * instances to create a better error message.\n */\n Object.freeze(\n Object.assign(new AgentRuntime(), {\n ...runtime,\n context: Object.freeze(\n Object.assign(new AgentContext(), filteredContext)\n ),\n })\n )\n );\n\n /**\n * If result is undefined, the hook made no state changes — return\n * only the jumpTo sentinel so we don't re-emit every input key as\n * a state update.\n */\n if (!result) {\n return { jumpTo: undefined };\n }\n\n /**\n * Verify that the jump target is allowed for the middleware\n */\n let jumpToConstraint: JumpToTarget[] | undefined;\n let constraint: string | undefined;\n\n if (this.name?.startsWith(\"BeforeAgentNode_\")) {\n jumpToConstraint = getHookConstraint(this.middleware.beforeAgent);\n constraint = \"beforeAgent.canJumpTo\";\n } else if (this.name?.startsWith(\"BeforeModelNode_\")) {\n jumpToConstraint = getHookConstraint(this.middleware.beforeModel);\n constraint = \"beforeModel.canJumpTo\";\n } else if (this.name?.startsWith(\"AfterAgentNode_\")) {\n jumpToConstraint = getHookConstraint(this.middleware.afterAgent);\n constraint = \"afterAgent.canJumpTo\";\n } else if (this.name?.startsWith(\"AfterModelNode_\")) {\n jumpToConstraint = getHookConstraint(this.middleware.afterModel);\n constraint = \"afterModel.canJumpTo\";\n }\n\n if (\n typeof result.jumpTo === \"string\" &&\n !jumpToConstraint?.includes(result.jumpTo as JumpToTarget)\n ) {\n const suggestion =\n jumpToConstraint && jumpToConstraint.length > 0\n ? `must be one of: ${jumpToConstraint?.join(\", \")}.`\n : constraint\n ? `no ${constraint} defined in middleware ${this.middleware.name}`\n : \"\";\n throw new Error(`Invalid jump target: ${result.jumpTo}, ${suggestion}.`);\n }\n\n /**\n * If result is a control action, handle it\n */\n if (typeof result === \"object\" && \"type\" in result) {\n // Handle control actions\n if (result.type === \"terminate\") {\n if (result.error) {\n throw result.error;\n }\n return {\n ...state,\n ...(result.result || {}),\n jumpTo: result.jumpTo,\n };\n }\n\n throw new Error(`Invalid control action: ${JSON.stringify(result)}`);\n }\n\n /**\n * If result is a state update, merge it with current state\n */\n return { ...state, ...result, jumpTo: result.jumpTo };\n }\n\n get nodeOptions() {\n return {\n input: derivePrivateState(this.middleware.stateSchema),\n };\n }\n}\n"],"mappings":";;;;;;;;;AAqBA,IAAM,eAAN,MAAmB;AACnB,IAAM,eAAN,MAAmB;AAOnB,IAAsB,iBAAtB,cAGUA,yBAAAA,iBAAyD;CAGjE,YACE,QACA;AACA,QAAM,OAAO;;CAQf,MAAM,iBACJ,aACA,QACmC;;;;EAInC,IAAI,kBAAkB,EAAE;;;;AAIxB,MACE,KAAK,WAAW,kBAAA,GAAA,4BAAA,oBACG,KAAK,WAAW,cAAc,EACjD;;;;GAIA,MAAM,eAAA,GAAA,4BAAA,0BACJ,KAAK,WAAW,cACjB;AACD,OAAI,aAAa;IACf,MAAM,kBAA2C,EAAE;IACnD,MAAM,gBAAgB,QAAQ,WAAW,EAAE;AAC3C,SAAK,MAAM,OAAO,OAAO,KAAK,YAAY,CACxC,KAAI,OAAO,cACT,iBAAgB,OAAO,cAAc;;;;;AAOzC,uBAAA,GAAA,4BAAA,cACE,KAAK,WAAW,eAChB,gBACD;;;EAIL,MAAM,QAAsB;GAC1B,GAAG;;;;GAIH,UAAU,YAAY;GACvB;EAED,MAAM,UAAmC;GACvC,SAAS;GACT,OAAO,QAAQ;GACf,cAAc,QAAQ;GACtB,QAAQ,QAAQ;GAChB,WAAW,QAAQ;GACnB,QAAQ,QAAQ;GACjB;EAED,MAAM,SAAS,MAAM,KAAK;GACxB;;;;;GAKA,OAAO,OACL,OAAO,OAAO,IAAI,cAAc,EAAE;IAChC,GAAG;IACH,SAAS,OAAO,OACd,OAAO,OAAO,IAAI,cAAc,EAAE,gBAAgB,CACnD;IACF,CAAC,CACH;GACF;;;;;;AAOD,MAAI,CAAC,OACH,QAAO,EAAE,QAAQ,KAAA,GAAW;;;;EAM9B,IAAI;EACJ,IAAI;AAEJ,MAAI,KAAK,MAAM,WAAW,mBAAmB,EAAE;AAC7C,sBAAmBC,gBAAAA,kBAAkB,KAAK,WAAW,YAAY;AACjE,gBAAa;aACJ,KAAK,MAAM,WAAW,mBAAmB,EAAE;AACpD,sBAAmBA,gBAAAA,kBAAkB,KAAK,WAAW,YAAY;AACjE,gBAAa;aACJ,KAAK,MAAM,WAAW,kBAAkB,EAAE;AACnD,sBAAmBA,gBAAAA,kBAAkB,KAAK,WAAW,WAAW;AAChE,gBAAa;aACJ,KAAK,MAAM,WAAW,kBAAkB,EAAE;AACnD,sBAAmBA,gBAAAA,kBAAkB,KAAK,WAAW,WAAW;AAChE,gBAAa;;AAGf,MACE,OAAO,OAAO,WAAW,YACzB,CAAC,kBAAkB,SAAS,OAAO,OAAuB,EAC1D;GACA,MAAM,aACJ,oBAAoB,iBAAiB,SAAS,IAC1C,mBAAmB,kBAAkB,KAAK,KAAK,CAAC,KAChD,aACE,MAAM,WAAW,yBAAyB,KAAK,WAAW,SAC1D;AACR,SAAM,IAAI,MAAM,wBAAwB,OAAO,OAAO,IAAI,WAAW,GAAG;;;;;AAM1E,MAAI,OAAO,WAAW,YAAY,UAAU,QAAQ;AAElD,OAAI,OAAO,SAAS,aAAa;AAC/B,QAAI,OAAO,MACT,OAAM,OAAO;AAEf,WAAO;KACL,GAAG;KACH,GAAI,OAAO,UAAU,EAAE;KACvB,QAAQ,OAAO;KAChB;;AAGH,SAAM,IAAI,MAAM,2BAA2B,KAAK,UAAU,OAAO,GAAG;;;;;AAMtE,SAAO;GAAE,GAAG;GAAO,GAAG;GAAQ,QAAQ,OAAO;GAAQ;;CAGvD,IAAI,cAAc;AAChB,SAAO,EACL,OAAOC,cAAAA,mBAAmB,KAAK,WAAW,YAAY,EACvD"}