langchain 1.0.0-alpha.3 → 1.0.0-alpha.5
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/dist/agents/ReactAgent.cjs +1 -1
- package/dist/agents/ReactAgent.cjs.map +1 -1
- package/dist/agents/ReactAgent.d.cts +3 -3
- package/dist/agents/ReactAgent.d.cts.map +1 -1
- package/dist/agents/ReactAgent.d.ts +3 -3
- package/dist/agents/ReactAgent.d.ts.map +1 -1
- package/dist/agents/ReactAgent.js +2 -2
- package/dist/agents/ReactAgent.js.map +1 -1
- package/dist/agents/RunnableCallable.cjs +5 -0
- package/dist/agents/RunnableCallable.cjs.map +1 -1
- package/dist/agents/RunnableCallable.d.cts +2 -0
- package/dist/agents/RunnableCallable.d.cts.map +1 -1
- package/dist/agents/RunnableCallable.d.ts +2 -0
- package/dist/agents/RunnableCallable.d.ts.map +1 -1
- package/dist/agents/RunnableCallable.js +5 -0
- package/dist/agents/RunnableCallable.js.map +1 -1
- package/dist/agents/annotation.cjs +2 -2
- package/dist/agents/annotation.cjs.map +1 -1
- package/dist/agents/annotation.d.cts +4 -4
- package/dist/agents/annotation.d.cts.map +1 -1
- package/dist/agents/annotation.d.ts +3 -3
- package/dist/agents/annotation.d.ts.map +1 -1
- package/dist/agents/annotation.js +2 -2
- package/dist/agents/annotation.js.map +1 -1
- package/dist/agents/createAgent.cjs +10 -0
- package/dist/agents/createAgent.cjs.map +1 -0
- package/dist/agents/createAgent.js +10 -0
- package/dist/agents/createAgent.js.map +1 -0
- package/dist/agents/errors.cjs +1 -1
- package/dist/agents/errors.cjs.map +1 -1
- package/dist/agents/errors.js +1 -1
- package/dist/agents/errors.js.map +1 -1
- package/dist/agents/index.cjs +23 -4
- package/dist/agents/index.cjs.map +1 -1
- package/dist/agents/index.d.cts +96 -33
- package/dist/agents/index.d.cts.map +1 -1
- package/dist/agents/index.d.ts +96 -33
- package/dist/agents/index.d.ts.map +1 -1
- package/dist/agents/index.js +23 -4
- package/dist/agents/index.js.map +1 -1
- package/dist/agents/middlewareAgent/ReactAgent.cjs +255 -0
- package/dist/agents/middlewareAgent/ReactAgent.cjs.map +1 -0
- package/dist/agents/middlewareAgent/ReactAgent.d.cts +68 -0
- package/dist/agents/middlewareAgent/ReactAgent.d.cts.map +1 -0
- package/dist/agents/middlewareAgent/ReactAgent.d.ts +68 -0
- package/dist/agents/middlewareAgent/ReactAgent.d.ts.map +1 -0
- package/dist/agents/middlewareAgent/ReactAgent.js +254 -0
- package/dist/agents/middlewareAgent/ReactAgent.js.map +1 -0
- package/dist/agents/middlewareAgent/annotation.cjs +39 -0
- package/dist/agents/middlewareAgent/annotation.cjs.map +1 -0
- package/dist/agents/middlewareAgent/annotation.js +38 -0
- package/dist/agents/middlewareAgent/annotation.js.map +1 -0
- package/dist/agents/middlewareAgent/index.cjs +11 -0
- package/dist/agents/middlewareAgent/index.cjs.map +1 -0
- package/dist/agents/middlewareAgent/index.js +11 -0
- package/dist/agents/middlewareAgent/index.js.map +1 -0
- package/dist/agents/middlewareAgent/middleware.cjs +47 -0
- package/dist/agents/middlewareAgent/middleware.cjs.map +1 -0
- package/dist/agents/middlewareAgent/middleware.d.cts +46 -0
- package/dist/agents/middlewareAgent/middleware.d.cts.map +1 -0
- package/dist/agents/middlewareAgent/middleware.d.ts +46 -0
- package/dist/agents/middlewareAgent/middleware.d.ts.map +1 -0
- package/dist/agents/middlewareAgent/middleware.js +46 -0
- package/dist/agents/middlewareAgent/middleware.js.map +1 -0
- package/dist/agents/middlewareAgent/middlewares/hitl.cjs +235 -0
- package/dist/agents/middlewareAgent/middlewares/hitl.cjs.map +1 -0
- package/dist/agents/middlewareAgent/middlewares/hitl.d.cts +199 -0
- package/dist/agents/middlewareAgent/middlewares/hitl.d.cts.map +1 -0
- package/dist/agents/middlewareAgent/middlewares/hitl.d.ts +199 -0
- package/dist/agents/middlewareAgent/middlewares/hitl.d.ts.map +1 -0
- package/dist/agents/middlewareAgent/middlewares/hitl.js +234 -0
- package/dist/agents/middlewareAgent/middlewares/hitl.js.map +1 -0
- package/dist/agents/middlewareAgent/middlewares/index.cjs +8 -0
- package/dist/agents/middlewareAgent/middlewares/index.d.cts +4 -0
- package/dist/agents/middlewareAgent/middlewares/index.d.ts +4 -0
- package/dist/agents/middlewareAgent/middlewares/index.js +5 -0
- package/dist/agents/middlewareAgent/middlewares/promptCaching.cjs +153 -0
- package/dist/agents/middlewareAgent/middlewares/promptCaching.cjs.map +1 -0
- package/dist/agents/middlewareAgent/middlewares/promptCaching.d.cts +152 -0
- package/dist/agents/middlewareAgent/middlewares/promptCaching.d.cts.map +1 -0
- package/dist/agents/middlewareAgent/middlewares/promptCaching.d.ts +152 -0
- package/dist/agents/middlewareAgent/middlewares/promptCaching.d.ts.map +1 -0
- package/dist/agents/middlewareAgent/middlewares/promptCaching.js +152 -0
- package/dist/agents/middlewareAgent/middlewares/promptCaching.js.map +1 -0
- package/dist/agents/middlewareAgent/middlewares/summarization.cjs +262 -0
- package/dist/agents/middlewareAgent/middlewares/summarization.cjs.map +1 -0
- package/dist/agents/middlewareAgent/middlewares/summarization.d.cts +89 -0
- package/dist/agents/middlewareAgent/middlewares/summarization.d.cts.map +1 -0
- package/dist/agents/middlewareAgent/middlewares/summarization.d.ts +89 -0
- package/dist/agents/middlewareAgent/middlewares/summarization.d.ts.map +1 -0
- package/dist/agents/middlewareAgent/middlewares/summarization.js +260 -0
- package/dist/agents/middlewareAgent/middlewares/summarization.js.map +1 -0
- package/dist/agents/middlewareAgent/nodes/AfterModalNode.cjs +29 -0
- package/dist/agents/middlewareAgent/nodes/AfterModalNode.cjs.map +1 -0
- package/dist/agents/middlewareAgent/nodes/AfterModalNode.js +29 -0
- package/dist/agents/middlewareAgent/nodes/AfterModalNode.js.map +1 -0
- package/dist/agents/middlewareAgent/nodes/AgentNode.cjs +332 -0
- package/dist/agents/middlewareAgent/nodes/AgentNode.cjs.map +1 -0
- package/dist/agents/middlewareAgent/nodes/AgentNode.js +331 -0
- package/dist/agents/middlewareAgent/nodes/AgentNode.js.map +1 -0
- package/dist/agents/middlewareAgent/nodes/BeforeModalNode.cjs +27 -0
- package/dist/agents/middlewareAgent/nodes/BeforeModalNode.cjs.map +1 -0
- package/dist/agents/middlewareAgent/nodes/BeforeModalNode.js +27 -0
- package/dist/agents/middlewareAgent/nodes/BeforeModalNode.js.map +1 -0
- package/dist/agents/middlewareAgent/nodes/middleware.cjs +73 -0
- package/dist/agents/middlewareAgent/nodes/middleware.cjs.map +1 -0
- package/dist/agents/middlewareAgent/nodes/middleware.js +73 -0
- package/dist/agents/middlewareAgent/nodes/middleware.js.map +1 -0
- package/dist/agents/middlewareAgent/nodes/utils.cjs +74 -0
- package/dist/agents/middlewareAgent/nodes/utils.cjs.map +1 -0
- package/dist/agents/middlewareAgent/nodes/utils.js +70 -0
- package/dist/agents/middlewareAgent/nodes/utils.js.map +1 -0
- package/dist/agents/middlewareAgent/types.d.cts +393 -0
- package/dist/agents/middlewareAgent/types.d.cts.map +1 -0
- package/dist/agents/middlewareAgent/types.d.ts +393 -0
- package/dist/agents/middlewareAgent/types.d.ts.map +1 -0
- package/dist/agents/nodes/AgentNode.cjs.map +1 -1
- package/dist/agents/nodes/AgentNode.js.map +1 -1
- package/dist/agents/nodes/ToolNode.cjs +1 -1
- package/dist/agents/nodes/ToolNode.cjs.map +1 -1
- package/dist/agents/nodes/ToolNode.d.cts +4 -4
- package/dist/agents/nodes/ToolNode.d.cts.map +1 -1
- package/dist/agents/nodes/ToolNode.d.ts +1 -1
- package/dist/agents/nodes/ToolNode.d.ts.map +1 -1
- package/dist/agents/nodes/ToolNode.js +1 -1
- package/dist/agents/nodes/ToolNode.js.map +1 -1
- package/dist/agents/responses.cjs +1 -1
- package/dist/agents/responses.cjs.map +1 -1
- package/dist/agents/responses.d.cts +1 -1
- package/dist/agents/responses.d.cts.map +1 -1
- package/dist/agents/responses.d.ts +1 -1
- package/dist/agents/responses.d.ts.map +1 -1
- package/dist/agents/responses.js +1 -1
- package/dist/agents/responses.js.map +1 -1
- package/dist/agents/types.d.cts +12 -12
- package/dist/agents/types.d.cts.map +1 -1
- package/dist/agents/types.d.ts +8 -8
- package/dist/agents/types.d.ts.map +1 -1
- package/dist/agents/utils.cjs +1 -1
- package/dist/agents/utils.cjs.map +1 -1
- package/dist/agents/utils.js +1 -1
- package/dist/agents/utils.js.map +1 -1
- package/dist/agents/withAgentName.cjs +1 -1
- package/dist/agents/withAgentName.cjs.map +1 -1
- package/dist/agents/withAgentName.js +1 -1
- package/dist/agents/withAgentName.js.map +1 -1
- package/dist/chains/api/api_chain.d.cts +1 -1
- package/dist/chains/base.d.cts +1 -1
- package/dist/chains/combine_docs_chain.d.cts +1 -1
- package/dist/chains/combine_documents/stuff.d.cts +1 -1
- package/dist/chains/conversational_retrieval_chain.d.cts +1 -1
- package/dist/chains/graph_qa/cypher.d.cts +1 -1
- package/dist/chains/history_aware_retriever.d.cts +2 -2
- package/dist/chains/llm_chain.d.cts +3 -3
- package/dist/chains/openai_functions/base.d.cts +3 -3
- package/dist/chains/openai_functions/openapi.d.cts +1 -1
- package/dist/chains/openai_functions/structured_output.d.cts +3 -3
- package/dist/chains/openai_functions/tagging.d.cts +1 -1
- package/dist/chains/query_constructor/index.cjs +1 -1
- package/dist/chains/query_constructor/index.d.cts +2 -2
- package/dist/chains/query_constructor/index.d.ts +1 -1
- package/dist/chains/query_constructor/index.js +1 -1
- package/dist/chains/question_answering/load.d.ts +2 -2
- package/dist/chains/question_answering/load.d.ts.map +1 -1
- package/dist/chains/retrieval.d.cts +1 -1
- package/dist/chains/router/llm_router.d.cts +1 -1
- package/dist/chains/router/multi_prompt.cjs +1 -1
- package/dist/chains/router/multi_prompt.js +1 -1
- package/dist/chains/router/multi_retrieval_qa.cjs +1 -1
- package/dist/chains/router/multi_retrieval_qa.js +1 -1
- package/dist/chains/sql_db/sql_db_chain.d.cts +2 -2
- package/dist/chains/summarization/load.d.ts +2 -2
- package/dist/chains/summarization/load.d.ts.map +1 -1
- package/dist/chat_models/universal.d.cts +3 -3
- package/dist/evaluation/agents/trajectory.d.cts +3 -3
- package/dist/evaluation/agents/trajectory.d.ts.map +1 -1
- package/dist/evaluation/comparison/pairwise.d.cts +1 -1
- package/dist/evaluation/comparison/pairwise.d.ts.map +1 -1
- package/dist/evaluation/criteria/criteria.d.cts +1 -1
- package/dist/evaluation/qa/eval_chain.d.cts +1 -1
- package/dist/index.cjs +5 -2
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +6 -5
- package/dist/index.d.ts +4 -3
- package/dist/index.js +5 -3
- package/dist/index.js.map +1 -1
- package/dist/load/import_map.cjs +1 -1
- package/dist/load/import_map.js +1 -1
- package/dist/memory/summary.d.cts +1 -1
- package/dist/output_parsers/fix.d.cts +1 -1
- package/dist/output_parsers/http_response.d.cts +1 -1
- package/dist/output_parsers/structured.cjs +1 -1
- package/dist/output_parsers/structured.d.cts +2 -2
- package/dist/output_parsers/structured.d.ts +1 -1
- package/dist/output_parsers/structured.js +1 -1
- package/dist/tools/fs.d.cts +1 -1
- package/dist/tools/json.d.cts +1 -1
- package/dist/tools/retriever.d.cts +1 -1
- package/dist/tools/vectorstore.d.cts +1 -1
- package/dist/tools/webbrowser.d.cts +1 -1
- package/package.json +14 -3
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
import { AgentBuiltInState, AgentMiddleware, Controls, MiddlewareResult, ModelRequest, Runtime } from "./types.js";
|
|
2
|
+
import { z } from "zod";
|
|
3
|
+
|
|
4
|
+
//#region src/agents/middlewareAgent/middleware.d.ts
|
|
5
|
+
|
|
6
|
+
/**
|
|
7
|
+
* Creates a middleware instance with automatic schema inference.
|
|
8
|
+
*
|
|
9
|
+
* @param config - Middleware configuration
|
|
10
|
+
* @param config.name - The name of the middleware
|
|
11
|
+
* @param config.stateSchema - The schema of the middleware state
|
|
12
|
+
* @param config.contextSchema - The schema of the middleware context
|
|
13
|
+
* @param config.prepareModelRequest - The function to prepare the model request
|
|
14
|
+
* @param config.beforeModel - The function to run before the model call
|
|
15
|
+
* @param config.afterModel - The function to run after the model call
|
|
16
|
+
* @returns A middleware instance
|
|
17
|
+
*
|
|
18
|
+
* @example
|
|
19
|
+
* ```ts
|
|
20
|
+
* const authMiddleware = createMiddleware({
|
|
21
|
+
* name: "AuthMiddleware",
|
|
22
|
+
* stateSchema: z.object({
|
|
23
|
+
* isAuthenticated: z.boolean().default(false),
|
|
24
|
+
* }),
|
|
25
|
+
* contextSchema: z.object({
|
|
26
|
+
* userId: z.string(),
|
|
27
|
+
* }),
|
|
28
|
+
* beforeModel: async (state, runtime, controls) => {
|
|
29
|
+
* if (!state.isAuthenticated) {
|
|
30
|
+
* return controls.terminate(new Error("Not authenticated"));
|
|
31
|
+
* }
|
|
32
|
+
* },
|
|
33
|
+
* });
|
|
34
|
+
* ```
|
|
35
|
+
*/
|
|
36
|
+
declare function createMiddleware<TSchema extends z.ZodObject<any> | undefined = undefined, TContextSchema extends z.ZodObject<any> | undefined = undefined>(config: {
|
|
37
|
+
name: string;
|
|
38
|
+
stateSchema?: TSchema;
|
|
39
|
+
contextSchema?: TContextSchema;
|
|
40
|
+
prepareModelRequest?: (options: ModelRequest, state: (TSchema extends z.ZodObject<any> ? z.infer<TSchema> : {}) & AgentBuiltInState, runtime: Runtime<TContextSchema extends z.ZodObject<any> ? z.infer<TContextSchema> : {}>) => Promise<ModelRequest | void> | ModelRequest | void;
|
|
41
|
+
beforeModel?: (state: (TSchema extends z.ZodObject<any> ? z.infer<TSchema> : {}) & AgentBuiltInState, runtime: Runtime<TContextSchema extends z.ZodObject<any> ? z.infer<TContextSchema> : {}>, controls: Controls<(TSchema extends z.ZodObject<any> ? z.infer<TSchema> : {}) & AgentBuiltInState>) => Promise<MiddlewareResult<Partial<TSchema extends z.ZodObject<any> ? z.infer<TSchema> : {}>>> | MiddlewareResult<Partial<TSchema extends z.ZodObject<any> ? z.infer<TSchema> : {}>>;
|
|
42
|
+
afterModel?: (state: (TSchema extends z.ZodObject<any> ? z.infer<TSchema> : {}) & AgentBuiltInState, runtime: Runtime<TContextSchema extends z.ZodObject<any> ? z.infer<TContextSchema> : {}>, controls: Controls<(TSchema extends z.ZodObject<any> ? z.infer<TSchema> : {}) & AgentBuiltInState>) => Promise<MiddlewareResult<Partial<TSchema extends z.ZodObject<any> ? z.infer<TSchema> : {}>>> | MiddlewareResult<Partial<TSchema extends z.ZodObject<any> ? z.infer<TSchema> : {}>>;
|
|
43
|
+
}): AgentMiddleware<TSchema, TContextSchema, any>;
|
|
44
|
+
//#endregion
|
|
45
|
+
export { createMiddleware };
|
|
46
|
+
//# sourceMappingURL=middleware.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"middleware.d.ts","names":["z","AgentMiddleware","Runtime","Controls","MiddlewareResult","AgentBuiltInState","ModelRequest","createMiddleware","ZodObject","TSchema","TContextSchema","infer","Promise","Partial"],"sources":["../../../src/agents/middlewareAgent/middleware.d.ts"],"sourcesContent":["/* eslint-disable @typescript-eslint/ban-types */\nimport { z } from \"zod\";\nimport type { AgentMiddleware, Runtime, Controls, MiddlewareResult, AgentBuiltInState, ModelRequest } from \"./types.js\";\n/**\n * Creates a middleware instance with automatic schema inference.\n *\n * @param config - Middleware configuration\n * @param config.name - The name of the middleware\n * @param config.stateSchema - The schema of the middleware state\n * @param config.contextSchema - The schema of the middleware context\n * @param config.prepareModelRequest - The function to prepare the model request\n * @param config.beforeModel - The function to run before the model call\n * @param config.afterModel - The function to run after the model call\n * @returns A middleware instance\n *\n * @example\n * ```ts\n * const authMiddleware = createMiddleware({\n * name: \"AuthMiddleware\",\n * stateSchema: z.object({\n * isAuthenticated: z.boolean().default(false),\n * }),\n * contextSchema: z.object({\n * userId: z.string(),\n * }),\n * beforeModel: async (state, runtime, controls) => {\n * if (!state.isAuthenticated) {\n * return controls.terminate(new Error(\"Not authenticated\"));\n * }\n * },\n * });\n * ```\n */\nexport declare function createMiddleware<TSchema extends z.ZodObject<any> | undefined = undefined, TContextSchema extends z.ZodObject<any> | undefined = undefined>(config: {\n name: string;\n stateSchema?: TSchema;\n contextSchema?: TContextSchema;\n prepareModelRequest?: (options: ModelRequest, state: (TSchema extends z.ZodObject<any> ? z.infer<TSchema> : {}) & AgentBuiltInState, runtime: Runtime<TContextSchema extends z.ZodObject<any> ? z.infer<TContextSchema> : {}>) => Promise<ModelRequest | void> | ModelRequest | void;\n beforeModel?: (state: (TSchema extends z.ZodObject<any> ? z.infer<TSchema> : {}) & AgentBuiltInState, runtime: Runtime<TContextSchema extends z.ZodObject<any> ? z.infer<TContextSchema> : {}>, controls: Controls<(TSchema extends z.ZodObject<any> ? z.infer<TSchema> : {}) & AgentBuiltInState>) => Promise<MiddlewareResult<Partial<TSchema extends z.ZodObject<any> ? z.infer<TSchema> : {}>>> | MiddlewareResult<Partial<TSchema extends z.ZodObject<any> ? z.infer<TSchema> : {}>>;\n afterModel?: (state: (TSchema extends z.ZodObject<any> ? z.infer<TSchema> : {}) & AgentBuiltInState, runtime: Runtime<TContextSchema extends z.ZodObject<any> ? z.infer<TContextSchema> : {}>, controls: Controls<(TSchema extends z.ZodObject<any> ? z.infer<TSchema> : {}) & AgentBuiltInState>) => Promise<MiddlewareResult<Partial<TSchema extends z.ZodObject<any> ? z.infer<TSchema> : {}>>> | MiddlewareResult<Partial<TSchema extends z.ZodObject<any> ? z.infer<TSchema> : {}>>;\n}): AgentMiddleware<TSchema, TContextSchema, any>;\n"],"mappings":";;;;;;AAiCA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAKmHE,iBAL3FK,gBAK2FL,CAAAA,gBAL1DF,CAAAA,CAAEQ,SAKwDN,CAAAA,GAAAA,CAAAA,GAAAA,SAAAA,GAAAA,SAAAA,EAAAA,uBALOF,CAAAA,CAAEQ,SAKTN,CAAAA,GAAAA,CAAAA,GAAAA,SAAAA,GAAAA,SAAAA,CAAAA,CAAAA,MAAAA,EAAAA;EAAO,IAA8FO,EAAAA,MAAAA;EAAO,WAAWD,CAAAA,EAHxNC,OAGwND;EAAS,aAAgBC,CAAAA,EAF/OC,cAE+OD;EAAO,mBAAbE,CAAAA,EAAAA,CAAAA,OAAAA,EADzNL,YACyNK,EAAAA,KAAAA,EAAAA,CADnMF,OACmME,SADnLX,CAAAA,CAAEQ,SACiLG,CAAAA,GAAAA,CAAAA,GADhKX,CAAAA,CAAEW,KAC8JA,CADxJF,OACwJE,CAAAA,GAAAA,CAAAA,CAAAA,CAAAA,GADvIN,iBACuIM,EAAAA,OAAAA,EAD3GT,OAC2GS,CADnGD,cACmGC,SAD5EX,CAAAA,CAAEQ,SAC0EG,CAAAA,GAAAA,CAAAA,GADzDX,CAAAA,CAAEW,KACuDA,CADjDD,cACiDC,CAAAA,GAAAA,CAAAA,CAAAA,CAAAA,EAAAA,GADvBC,OACuBD,CADfL,YACeK,GAAAA,IAAAA,CAAAA,GADQL,YACRK,GAAAA,IAAAA;EAAK,WAAkBN,CAAAA,EAAAA,CAAAA,KAAAA,EAAAA,CAAzPI,OAAyPJ,SAAzOL,CAAAA,CAAEQ,SAAuOH,CAAAA,GAAAA,CAAAA,GAAtNL,CAAAA,CAAEW,KAAoNN,CAA9MI,OAA8MJ,CAAAA,GAAAA,CAAAA,CAAAA,CAAAA,GAA7LA,iBAA6LA,EAAAA,OAAAA,EAAjKH,OAAiKG,CAAzJK,cAAyJL,SAAlIL,CAAAA,CAAEQ,SAAgIH,CAAAA,GAAAA,CAAAA,GAA/GL,CAAAA,CAAEW,KAA6GN,CAAvGK,cAAuGL,CAAAA,GAAAA,CAAAA,CAAAA,CAAAA,EAAAA,QAAAA,EAAtEF,QAAsEE,CAAAA,CAA5DI,OAA4DJ,SAA5CL,CAAAA,CAAEQ,SAA0CH,CAAAA,GAAAA,CAAAA,GAAzBL,CAAAA,CAAEW,KAAuBN,CAAjBI,OAAiBJ,CAAAA,GAAAA,CAAAA,CAAAA,CAAAA,GAAAA,iBAAAA,CAAAA,EAAAA,GAAuBO,OAAvBP,CAA+BD,gBAA/BC,CAAgDQ,OAAhDR,CAAwDI,OAAxDJ,SAAwEL,CAAAA,CAAEQ,SAA1EH,CAAAA,GAAAA,CAAAA,GAA2FL,CAAAA,CAAEW,KAA7FN,CAAmGI,OAAnGJ,CAAAA,GAAAA,CAAAA,CAAAA,CAAAA,CAAAA,CAAAA,GAAsHD,gBAAtHC,CAAuIQ,OAAvIR,CAA+II,OAA/IJ,SAA+JL,CAAAA,CAAEQ,SAAjKH,CAAAA,GAAAA,CAAAA,GAAkLL,CAAAA,CAAEW,KAApLN,CAA0LI,OAA1LJ,CAAAA,GAAAA,CAAAA,CAAAA,CAAAA,CAAAA;EAAiB,UAAvFF,CAAAA,EAAAA,CAAAA,KAAAA,EAAAA,CACpLM,OADoLN,SACpKH,CAAAA,CAAEQ,SADkKL,CAAAA,GAAAA,CAAAA,GACjJH,CAAAA,CAAEW,KAD+IR,CACzIM,OADyIN,CAAAA,GAAAA,CAAAA,CAAAA,CAAAA,GACxHE,iBADwHF,EAAAA,OAAAA,EAC5FD,OAD4FC,CACpFO,cADoFP,SAC7DH,CAAAA,CAAEQ,SAD2DL,CAAAA,GAAAA,CAAAA,GAC1CH,CAAAA,CAAEW,KADwCR,CAClCO,cADkCP,CAAAA,GAAAA,CAAAA,CAAAA,CAAAA,EAAAA,QAAAA,EACDA,QADCA,CAAAA,CACSM,OADTN,SACyBH,CAAAA,CAAEQ,SAD3BL,CAAAA,GAAAA,CAAAA,GAC4CH,CAAAA,CAAEW,KAD9CR,CACoDM,OADpDN,CAAAA,GAAAA,CAAAA,CAAAA,CAAAA,GACqEE,iBADrEF,CAAAA,EAAAA,GAC4FS,OAD5FT,CACoGC,gBADpGD,CACqHU,OADrHV,CAC6HM,OAD7HN,SAC6IH,CAAAA,CAAEQ,SAD/IL,CAAAA,GAAAA,CAAAA,GACgKH,CAAAA,CAAEW,KADlKR,CACwKM,OADxKN,CAAAA,GAAAA,CAAAA,CAAAA,CAAAA,CAAAA,CAAAA,GAC2LC,gBAD3LD,CAC4MU,OAD5MV,CACoNM,OADpNN,SACoOH,CAAAA,CAAEQ,SADtOL,CAAAA,GAAAA,CAAAA,GACuPH,CAAAA,CAAEW,KADzPR,CAC+PM,OAD/PN,CAAAA,GAAAA,CAAAA,CAAAA,CAAAA,CAAAA;CAAQ,CAAA,EAElNF,eAFwUQ,CAExTA,OAFwTA,EAE/SC,cAF+SD,EAAAA,GAAAA,CAAAA"}
|
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
//#region src/agents/middlewareAgent/middleware.ts
|
|
2
|
+
/**
|
|
3
|
+
* Creates a middleware instance with automatic schema inference.
|
|
4
|
+
*
|
|
5
|
+
* @param config - Middleware configuration
|
|
6
|
+
* @param config.name - The name of the middleware
|
|
7
|
+
* @param config.stateSchema - The schema of the middleware state
|
|
8
|
+
* @param config.contextSchema - The schema of the middleware context
|
|
9
|
+
* @param config.prepareModelRequest - The function to prepare the model request
|
|
10
|
+
* @param config.beforeModel - The function to run before the model call
|
|
11
|
+
* @param config.afterModel - The function to run after the model call
|
|
12
|
+
* @returns A middleware instance
|
|
13
|
+
*
|
|
14
|
+
* @example
|
|
15
|
+
* ```ts
|
|
16
|
+
* const authMiddleware = createMiddleware({
|
|
17
|
+
* name: "AuthMiddleware",
|
|
18
|
+
* stateSchema: z.object({
|
|
19
|
+
* isAuthenticated: z.boolean().default(false),
|
|
20
|
+
* }),
|
|
21
|
+
* contextSchema: z.object({
|
|
22
|
+
* userId: z.string(),
|
|
23
|
+
* }),
|
|
24
|
+
* beforeModel: async (state, runtime, controls) => {
|
|
25
|
+
* if (!state.isAuthenticated) {
|
|
26
|
+
* return controls.terminate(new Error("Not authenticated"));
|
|
27
|
+
* }
|
|
28
|
+
* },
|
|
29
|
+
* });
|
|
30
|
+
* ```
|
|
31
|
+
*/
|
|
32
|
+
function createMiddleware(config) {
|
|
33
|
+
const middleware = {
|
|
34
|
+
name: config.name,
|
|
35
|
+
stateSchema: config.stateSchema,
|
|
36
|
+
contextSchema: config.contextSchema
|
|
37
|
+
};
|
|
38
|
+
if (config.prepareModelRequest) middleware.prepareModelRequest = async (options, state, runtime) => Promise.resolve(config.prepareModelRequest(options, state, runtime));
|
|
39
|
+
if (config.beforeModel) middleware.beforeModel = async (state, runtime, controls) => Promise.resolve(config.beforeModel(state, runtime, controls));
|
|
40
|
+
if (config.afterModel) middleware.afterModel = async (state, runtime, controls) => Promise.resolve(config.afterModel(state, runtime, controls));
|
|
41
|
+
return middleware;
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
//#endregion
|
|
45
|
+
export { createMiddleware };
|
|
46
|
+
//# sourceMappingURL=middleware.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"middleware.js","names":["config: {\n name: string;\n stateSchema?: TSchema;\n contextSchema?: TContextSchema;\n prepareModelRequest?: (\n options: ModelRequest,\n state: (TSchema extends z.ZodObject<any> ? z.infer<TSchema> : {}) &\n AgentBuiltInState,\n runtime: Runtime<\n TContextSchema extends z.ZodObject<any> ? z.infer<TContextSchema> : {}\n >\n ) => Promise<ModelRequest | void> | ModelRequest | void;\n beforeModel?: (\n state: (TSchema extends z.ZodObject<any> ? z.infer<TSchema> : {}) &\n AgentBuiltInState,\n runtime: Runtime<\n TContextSchema extends z.ZodObject<any> ? z.infer<TContextSchema> : {}\n >,\n controls: Controls<\n (TSchema extends z.ZodObject<any> ? z.infer<TSchema> : {}) &\n AgentBuiltInState\n >\n ) =>\n | Promise<\n MiddlewareResult<\n Partial<TSchema extends z.ZodObject<any> ? z.infer<TSchema> : {}>\n >\n >\n | MiddlewareResult<\n Partial<TSchema extends z.ZodObject<any> ? z.infer<TSchema> : {}>\n >;\n afterModel?: (\n state: (TSchema extends z.ZodObject<any> ? z.infer<TSchema> : {}) &\n AgentBuiltInState,\n runtime: Runtime<\n TContextSchema extends z.ZodObject<any> ? z.infer<TContextSchema> : {}\n >,\n controls: Controls<\n (TSchema extends z.ZodObject<any> ? z.infer<TSchema> : {}) &\n AgentBuiltInState\n >\n ) =>\n | Promise<\n MiddlewareResult<\n Partial<TSchema extends z.ZodObject<any> ? z.infer<TSchema> : {}>\n >\n >\n | MiddlewareResult<\n Partial<TSchema extends z.ZodObject<any> ? z.infer<TSchema> : {}>\n >;\n}","middleware: AgentMiddleware<TSchema, TContextSchema, any>"],"sources":["../../../src/agents/middlewareAgent/middleware.ts"],"sourcesContent":["/* eslint-disable @typescript-eslint/ban-types */\nimport { z } from \"zod\";\nimport type {\n AgentMiddleware,\n Runtime,\n Controls,\n MiddlewareResult,\n AgentBuiltInState,\n ModelRequest,\n} from \"./types.js\";\n\n/**\n * Creates a middleware instance with automatic schema inference.\n *\n * @param config - Middleware configuration\n * @param config.name - The name of the middleware\n * @param config.stateSchema - The schema of the middleware state\n * @param config.contextSchema - The schema of the middleware context\n * @param config.prepareModelRequest - The function to prepare the model request\n * @param config.beforeModel - The function to run before the model call\n * @param config.afterModel - The function to run after the model call\n * @returns A middleware instance\n *\n * @example\n * ```ts\n * const authMiddleware = createMiddleware({\n * name: \"AuthMiddleware\",\n * stateSchema: z.object({\n * isAuthenticated: z.boolean().default(false),\n * }),\n * contextSchema: z.object({\n * userId: z.string(),\n * }),\n * beforeModel: async (state, runtime, controls) => {\n * if (!state.isAuthenticated) {\n * return controls.terminate(new Error(\"Not authenticated\"));\n * }\n * },\n * });\n * ```\n */\nexport function createMiddleware<\n TSchema extends z.ZodObject<any> | undefined = undefined,\n TContextSchema extends z.ZodObject<any> | undefined = undefined\n>(config: {\n name: string;\n stateSchema?: TSchema;\n contextSchema?: TContextSchema;\n prepareModelRequest?: (\n options: ModelRequest,\n state: (TSchema extends z.ZodObject<any> ? z.infer<TSchema> : {}) &\n AgentBuiltInState,\n runtime: Runtime<\n TContextSchema extends z.ZodObject<any> ? z.infer<TContextSchema> : {}\n >\n ) => Promise<ModelRequest | void> | ModelRequest | void;\n beforeModel?: (\n state: (TSchema extends z.ZodObject<any> ? z.infer<TSchema> : {}) &\n AgentBuiltInState,\n runtime: Runtime<\n TContextSchema extends z.ZodObject<any> ? z.infer<TContextSchema> : {}\n >,\n controls: Controls<\n (TSchema extends z.ZodObject<any> ? z.infer<TSchema> : {}) &\n AgentBuiltInState\n >\n ) =>\n | Promise<\n MiddlewareResult<\n Partial<TSchema extends z.ZodObject<any> ? z.infer<TSchema> : {}>\n >\n >\n | MiddlewareResult<\n Partial<TSchema extends z.ZodObject<any> ? z.infer<TSchema> : {}>\n >;\n afterModel?: (\n state: (TSchema extends z.ZodObject<any> ? z.infer<TSchema> : {}) &\n AgentBuiltInState,\n runtime: Runtime<\n TContextSchema extends z.ZodObject<any> ? z.infer<TContextSchema> : {}\n >,\n controls: Controls<\n (TSchema extends z.ZodObject<any> ? z.infer<TSchema> : {}) &\n AgentBuiltInState\n >\n ) =>\n | Promise<\n MiddlewareResult<\n Partial<TSchema extends z.ZodObject<any> ? z.infer<TSchema> : {}>\n >\n >\n | MiddlewareResult<\n Partial<TSchema extends z.ZodObject<any> ? z.infer<TSchema> : {}>\n >;\n}): AgentMiddleware<TSchema, TContextSchema, any> {\n const middleware: AgentMiddleware<TSchema, TContextSchema, any> = {\n name: config.name,\n stateSchema: config.stateSchema,\n contextSchema: config.contextSchema,\n };\n\n if (config.prepareModelRequest) {\n middleware.prepareModelRequest = async (options, state, runtime) =>\n Promise.resolve(config.prepareModelRequest!(options, state, runtime));\n }\n\n if (config.beforeModel) {\n middleware.beforeModel = async (state, runtime, controls) =>\n Promise.resolve(config.beforeModel!(state, runtime, controls));\n }\n\n if (config.afterModel) {\n middleware.afterModel = async (state, runtime, controls) =>\n Promise.resolve(config.afterModel!(state, runtime, controls));\n }\n\n return middleware;\n}\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAyCA,SAAgB,iBAGdA,QAkDgD;CAChD,MAAMC,aAA4D;EAChE,MAAM,OAAO;EACb,aAAa,OAAO;EACpB,eAAe,OAAO;CACvB;AAED,KAAI,OAAO,qBACT,WAAW,sBAAsB,OAAO,SAAS,OAAO,YACtD,QAAQ,QAAQ,OAAO,oBAAqB,SAAS,OAAO,QAAQ,CAAC;AAGzE,KAAI,OAAO,aACT,WAAW,cAAc,OAAO,OAAO,SAAS,aAC9C,QAAQ,QAAQ,OAAO,YAAa,OAAO,SAAS,SAAS,CAAC;AAGlE,KAAI,OAAO,YACT,WAAW,aAAa,OAAO,OAAO,SAAS,aAC7C,QAAQ,QAAQ,OAAO,WAAY,OAAO,SAAS,SAAS,CAAC;AAGjE,QAAO;AACR"}
|
|
@@ -0,0 +1,235 @@
|
|
|
1
|
+
const require_rolldown_runtime = require('../../../_virtual/rolldown_runtime.cjs');
|
|
2
|
+
const require_middleware = require('../middleware.cjs');
|
|
3
|
+
const __langchain_core_messages = require_rolldown_runtime.__toESM(require("@langchain/core/messages"));
|
|
4
|
+
const __langchain_langgraph = require_rolldown_runtime.__toESM(require("@langchain/langgraph"));
|
|
5
|
+
const zod = require_rolldown_runtime.__toESM(require("zod"));
|
|
6
|
+
const uuid = require_rolldown_runtime.__toESM(require("uuid"));
|
|
7
|
+
|
|
8
|
+
//#region src/agents/middlewareAgent/middlewares/hitl.ts
|
|
9
|
+
const contextSchema = zod.z.object({
|
|
10
|
+
toolConfigs: zod.z.record(zod.z.object({
|
|
11
|
+
requireApproval: zod.z.boolean().optional(),
|
|
12
|
+
description: zod.z.string().optional()
|
|
13
|
+
})).default({}),
|
|
14
|
+
messagePrefix: zod.z.string().default("Tool execution requires approval")
|
|
15
|
+
});
|
|
16
|
+
/**
|
|
17
|
+
* Creates a Human-in-the-Loop (HITL) middleware for tool approval and oversight.
|
|
18
|
+
*
|
|
19
|
+
* This middleware intercepts tool calls made by an AI agent and provides human oversight
|
|
20
|
+
* capabilities before execution. It enables selective approval workflows where certain tools
|
|
21
|
+
* require human intervention while others can execute automatically.
|
|
22
|
+
*
|
|
23
|
+
* ## Features
|
|
24
|
+
*
|
|
25
|
+
* - **Selective Tool Approval**: Configure which tools require human approval
|
|
26
|
+
* - **Multiple Response Types**: Accept, edit, ignore, or manually respond to tool calls
|
|
27
|
+
* - **Asynchronous Workflow**: Uses LangGraph's interrupt mechanism for non-blocking approval
|
|
28
|
+
* - **Custom Approval Messages**: Provide context-specific descriptions for approval requests
|
|
29
|
+
*
|
|
30
|
+
* ## Response Types
|
|
31
|
+
*
|
|
32
|
+
* When a tool requires approval, the human operator can respond with:
|
|
33
|
+
* - `accept`: Execute the tool with original arguments
|
|
34
|
+
* - `edit`: Modify the tool arguments before execution
|
|
35
|
+
* - `ignore`: Skip the tool and terminate the agent
|
|
36
|
+
* - `response`: Provide a manual response instead of executing the tool
|
|
37
|
+
*
|
|
38
|
+
* @param options - Configuration options for the middleware
|
|
39
|
+
* @param options.toolConfigs - Per-tool configuration mapping tool names to their settings
|
|
40
|
+
* @param options.toolConfigs[toolName].requireApproval - Whether the tool requires human approval
|
|
41
|
+
* @param options.toolConfigs[toolName].description - Custom approval message for the tool
|
|
42
|
+
* @param options.messagePrefix - Default prefix for approval messages (default: "Tool execution requires approval")
|
|
43
|
+
*
|
|
44
|
+
* @returns A middleware instance that can be passed to `createAgent`
|
|
45
|
+
*
|
|
46
|
+
* @example
|
|
47
|
+
* Basic usage with selective tool approval
|
|
48
|
+
* ```typescript
|
|
49
|
+
* import { humanInTheLoopMiddleware } from "langchain/middleware";
|
|
50
|
+
* import { createAgent } from "langchain";
|
|
51
|
+
*
|
|
52
|
+
* const hitlMiddleware = humanInTheLoopMiddleware({
|
|
53
|
+
* toolConfigs: {
|
|
54
|
+
* "write_file": {
|
|
55
|
+
* requireApproval: true,
|
|
56
|
+
* description: "⚠️ File write operation requires approval"
|
|
57
|
+
* },
|
|
58
|
+
* "read_file": {
|
|
59
|
+
* requireApproval: false // Safe operation, no approval needed
|
|
60
|
+
* }
|
|
61
|
+
* }
|
|
62
|
+
* });
|
|
63
|
+
*
|
|
64
|
+
* const agent = createAgent({
|
|
65
|
+
* model: "openai:gpt-4",
|
|
66
|
+
* tools: [writeFileTool, readFileTool],
|
|
67
|
+
* middlewares: [hitlMiddleware]
|
|
68
|
+
* });
|
|
69
|
+
* ```
|
|
70
|
+
*
|
|
71
|
+
* @example
|
|
72
|
+
* Handling approval requests
|
|
73
|
+
* ```typescript
|
|
74
|
+
* import { Command } from "@langchain/langgraph";
|
|
75
|
+
*
|
|
76
|
+
* // Initial agent invocation
|
|
77
|
+
* const result = await agent.invoke({
|
|
78
|
+
* messages: [new HumanMessage("Write 'Hello' to output.txt")]
|
|
79
|
+
* }, config);
|
|
80
|
+
*
|
|
81
|
+
* // Check if agent is paused for approval
|
|
82
|
+
* const state = await agent.graph.getState(config);
|
|
83
|
+
* if (state.next?.length > 0) {
|
|
84
|
+
* // Get interrupt details
|
|
85
|
+
* const task = state.tasks?.[0];
|
|
86
|
+
* const requests = task?.interrupts?.[0]?.value;
|
|
87
|
+
*
|
|
88
|
+
* // Show tool call details to user
|
|
89
|
+
* console.log("Tool:", requests[0].action);
|
|
90
|
+
* console.log("Args:", requests[0].args);
|
|
91
|
+
*
|
|
92
|
+
* // Resume with approval
|
|
93
|
+
* await agent.invoke(
|
|
94
|
+
* new Command({ resume: [{ type: "accept" }] }),
|
|
95
|
+
* config
|
|
96
|
+
* );
|
|
97
|
+
* }
|
|
98
|
+
* ```
|
|
99
|
+
*
|
|
100
|
+
* @example
|
|
101
|
+
* Different response types
|
|
102
|
+
* ```typescript
|
|
103
|
+
* // Accept the tool call as-is
|
|
104
|
+
* new Command({ resume: [{ type: "accept" }] })
|
|
105
|
+
*
|
|
106
|
+
* // Edit the tool arguments
|
|
107
|
+
* new Command({
|
|
108
|
+
* resume: [{
|
|
109
|
+
* type: "edit",
|
|
110
|
+
* args: { action: "write_file", args: { filename: "safe.txt", content: "Modified" } }
|
|
111
|
+
* }]
|
|
112
|
+
* })
|
|
113
|
+
*
|
|
114
|
+
* // Skip tool and terminate agent
|
|
115
|
+
* new Command({ resume: [{ type: "ignore" }] })
|
|
116
|
+
*
|
|
117
|
+
* // Provide manual response
|
|
118
|
+
* new Command({
|
|
119
|
+
* resume: [{
|
|
120
|
+
* type: "response",
|
|
121
|
+
* args: "File operation not allowed in demo mode"
|
|
122
|
+
* }]
|
|
123
|
+
* })
|
|
124
|
+
* ```
|
|
125
|
+
*
|
|
126
|
+
* @example
|
|
127
|
+
* Production use case with database operations
|
|
128
|
+
* ```typescript
|
|
129
|
+
* const hitlMiddleware = humanInTheLoopMiddleware({
|
|
130
|
+
* toolConfigs: {
|
|
131
|
+
* "execute_sql": {
|
|
132
|
+
* requireApproval: true,
|
|
133
|
+
* description: "🚨 SQL query requires DBA approval\nPlease review for safety and performance"
|
|
134
|
+
* },
|
|
135
|
+
* "read_schema": {
|
|
136
|
+
* requireApproval: false // Reading metadata is safe
|
|
137
|
+
* },
|
|
138
|
+
* "delete_records": {
|
|
139
|
+
* requireApproval: true,
|
|
140
|
+
* description: "⛔ DESTRUCTIVE OPERATION - Requires manager approval"
|
|
141
|
+
* }
|
|
142
|
+
* },
|
|
143
|
+
* messagePrefix: "Database operation pending approval"
|
|
144
|
+
* });
|
|
145
|
+
* ```
|
|
146
|
+
*
|
|
147
|
+
* @remarks
|
|
148
|
+
* - Tool calls are processed in the order they appear in the AI message
|
|
149
|
+
* - Auto-approved tools execute immediately without interruption
|
|
150
|
+
* - Multiple tools requiring approval are bundled into a single interrupt
|
|
151
|
+
* - The middleware operates in the `afterModel` phase, intercepting before tool execution
|
|
152
|
+
* - Requires a checkpointer to maintain state across interruptions
|
|
153
|
+
*
|
|
154
|
+
* @see {@link createAgent} for agent creation
|
|
155
|
+
* @see {@link Command} for resuming interrupted execution
|
|
156
|
+
* @public
|
|
157
|
+
*/
|
|
158
|
+
function humanInTheLoopMiddleware(options = {}) {
|
|
159
|
+
return require_middleware.createMiddleware({
|
|
160
|
+
name: "HumanInTheLoopMiddleware",
|
|
161
|
+
contextSchema,
|
|
162
|
+
afterModel: async (state, runtime, controls) => {
|
|
163
|
+
const config = {
|
|
164
|
+
...contextSchema.parse(options),
|
|
165
|
+
...runtime.context
|
|
166
|
+
};
|
|
167
|
+
const { messages } = state;
|
|
168
|
+
if (!messages.length) return;
|
|
169
|
+
const lastMessage = messages[messages.length - 1];
|
|
170
|
+
if (!(0, __langchain_core_messages.isAIMessage)(lastMessage) || !lastMessage.tool_calls?.length) return;
|
|
171
|
+
const interruptToolCalls = [];
|
|
172
|
+
const autoApprovedToolCalls = [];
|
|
173
|
+
for (const toolCall of lastMessage.tool_calls) {
|
|
174
|
+
const normalizedToolCall = {
|
|
175
|
+
id: toolCall.id || (0, uuid.v4)(),
|
|
176
|
+
name: toolCall.name,
|
|
177
|
+
args: toolCall.args
|
|
178
|
+
};
|
|
179
|
+
const toolConfig = config.toolConfigs[normalizedToolCall.name];
|
|
180
|
+
if (toolConfig?.requireApproval) interruptToolCalls.push(normalizedToolCall);
|
|
181
|
+
else autoApprovedToolCalls.push(normalizedToolCall);
|
|
182
|
+
}
|
|
183
|
+
if (!interruptToolCalls.length) return;
|
|
184
|
+
const approvedToolCalls = [...autoApprovedToolCalls];
|
|
185
|
+
const requests = interruptToolCalls.map((toolCall) => {
|
|
186
|
+
const toolConfig = config.toolConfigs[toolCall.name];
|
|
187
|
+
const description = toolConfig?.description || `${config.messagePrefix}\n\nTool: ${toolCall.name}\nArgs: ${JSON.stringify(toolCall.args, null, 2)}`;
|
|
188
|
+
return {
|
|
189
|
+
action: toolCall.name,
|
|
190
|
+
args: toolCall.args,
|
|
191
|
+
toolCallId: toolCall.id,
|
|
192
|
+
description
|
|
193
|
+
};
|
|
194
|
+
});
|
|
195
|
+
const responses = await (0, __langchain_langgraph.interrupt)(requests);
|
|
196
|
+
for (let i = 0; i < responses.length; i++) {
|
|
197
|
+
const response = responses[i];
|
|
198
|
+
const toolCall = interruptToolCalls[i];
|
|
199
|
+
switch (response.type) {
|
|
200
|
+
case "accept":
|
|
201
|
+
approvedToolCalls.push(toolCall);
|
|
202
|
+
break;
|
|
203
|
+
case "edit":
|
|
204
|
+
if (response.args && typeof response.args === "object" && "args" in response.args) approvedToolCalls.push({
|
|
205
|
+
...toolCall,
|
|
206
|
+
args: response.args.args
|
|
207
|
+
});
|
|
208
|
+
break;
|
|
209
|
+
case "ignore": return controls.terminate();
|
|
210
|
+
case "response": {
|
|
211
|
+
const toolMessage = new __langchain_core_messages.ToolMessage({
|
|
212
|
+
content: typeof response.args === "string" ? response.args : "",
|
|
213
|
+
tool_call_id: toolCall.id
|
|
214
|
+
});
|
|
215
|
+
return {
|
|
216
|
+
messages: [...state.messages, toolMessage],
|
|
217
|
+
jump_to: "model"
|
|
218
|
+
};
|
|
219
|
+
}
|
|
220
|
+
default: throw new Error(`Unknown response type: ${response.type}`);
|
|
221
|
+
}
|
|
222
|
+
}
|
|
223
|
+
const updatedMessage = new __langchain_core_messages.AIMessage({
|
|
224
|
+
content: lastMessage.content,
|
|
225
|
+
tool_calls: approvedToolCalls,
|
|
226
|
+
id: lastMessage.id
|
|
227
|
+
});
|
|
228
|
+
return { messages: [...state.messages.slice(0, -1), updatedMessage] };
|
|
229
|
+
}
|
|
230
|
+
});
|
|
231
|
+
}
|
|
232
|
+
|
|
233
|
+
//#endregion
|
|
234
|
+
exports.humanInTheLoopMiddleware = humanInTheLoopMiddleware;
|
|
235
|
+
//# sourceMappingURL=hitl.cjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"hitl.cjs","names":["z","options: z.input<typeof contextSchema>","createMiddleware","interruptToolCalls: ToolCall[]","autoApprovedToolCalls: ToolCall[]","normalizedToolCall: ToolCall","requests: ToolApprovalRequest[]","ToolMessage","AIMessage"],"sources":["../../../../src/agents/middlewareAgent/middlewares/hitl.ts"],"sourcesContent":["import { z } from \"zod\";\nimport { v4 as uuid } from \"uuid\";\nimport { AIMessage, ToolMessage, isAIMessage } from \"@langchain/core/messages\";\nimport { interrupt } from \"@langchain/langgraph\";\n\nimport { createMiddleware } from \"../middleware.js\";\nimport type { ToolCall } from \"../types.js\";\nimport { HumanResponse } from \"../../interrupt.js\";\n\n/**\n * Interrupt request for tool approval\n */\ninterface ToolApprovalRequest {\n action: string;\n args: Record<string, any>;\n toolCallId: string;\n description?: string;\n}\n\nconst contextSchema = z.object({\n toolConfigs: z\n .record(\n z.object({\n requireApproval: z.boolean().optional(),\n description: z.string().optional(),\n })\n )\n .default({}),\n messagePrefix: z.string().default(\"Tool execution requires approval\"),\n});\n\n/**\n * Creates a Human-in-the-Loop (HITL) middleware for tool approval and oversight.\n *\n * This middleware intercepts tool calls made by an AI agent and provides human oversight\n * capabilities before execution. It enables selective approval workflows where certain tools\n * require human intervention while others can execute automatically.\n *\n * ## Features\n *\n * - **Selective Tool Approval**: Configure which tools require human approval\n * - **Multiple Response Types**: Accept, edit, ignore, or manually respond to tool calls\n * - **Asynchronous Workflow**: Uses LangGraph's interrupt mechanism for non-blocking approval\n * - **Custom Approval Messages**: Provide context-specific descriptions for approval requests\n *\n * ## Response Types\n *\n * When a tool requires approval, the human operator can respond with:\n * - `accept`: Execute the tool with original arguments\n * - `edit`: Modify the tool arguments before execution\n * - `ignore`: Skip the tool and terminate the agent\n * - `response`: Provide a manual response instead of executing the tool\n *\n * @param options - Configuration options for the middleware\n * @param options.toolConfigs - Per-tool configuration mapping tool names to their settings\n * @param options.toolConfigs[toolName].requireApproval - Whether the tool requires human approval\n * @param options.toolConfigs[toolName].description - Custom approval message for the tool\n * @param options.messagePrefix - Default prefix for approval messages (default: \"Tool execution requires approval\")\n *\n * @returns A middleware instance that can be passed to `createAgent`\n *\n * @example\n * Basic usage with selective tool approval\n * ```typescript\n * import { humanInTheLoopMiddleware } from \"langchain/middleware\";\n * import { createAgent } from \"langchain\";\n *\n * const hitlMiddleware = humanInTheLoopMiddleware({\n * toolConfigs: {\n * \"write_file\": {\n * requireApproval: true,\n * description: \"⚠️ File write operation requires approval\"\n * },\n * \"read_file\": {\n * requireApproval: false // Safe operation, no approval needed\n * }\n * }\n * });\n *\n * const agent = createAgent({\n * model: \"openai:gpt-4\",\n * tools: [writeFileTool, readFileTool],\n * middlewares: [hitlMiddleware]\n * });\n * ```\n *\n * @example\n * Handling approval requests\n * ```typescript\n * import { Command } from \"@langchain/langgraph\";\n *\n * // Initial agent invocation\n * const result = await agent.invoke({\n * messages: [new HumanMessage(\"Write 'Hello' to output.txt\")]\n * }, config);\n *\n * // Check if agent is paused for approval\n * const state = await agent.graph.getState(config);\n * if (state.next?.length > 0) {\n * // Get interrupt details\n * const task = state.tasks?.[0];\n * const requests = task?.interrupts?.[0]?.value;\n *\n * // Show tool call details to user\n * console.log(\"Tool:\", requests[0].action);\n * console.log(\"Args:\", requests[0].args);\n *\n * // Resume with approval\n * await agent.invoke(\n * new Command({ resume: [{ type: \"accept\" }] }),\n * config\n * );\n * }\n * ```\n *\n * @example\n * Different response types\n * ```typescript\n * // Accept the tool call as-is\n * new Command({ resume: [{ type: \"accept\" }] })\n *\n * // Edit the tool arguments\n * new Command({\n * resume: [{\n * type: \"edit\",\n * args: { action: \"write_file\", args: { filename: \"safe.txt\", content: \"Modified\" } }\n * }]\n * })\n *\n * // Skip tool and terminate agent\n * new Command({ resume: [{ type: \"ignore\" }] })\n *\n * // Provide manual response\n * new Command({\n * resume: [{\n * type: \"response\",\n * args: \"File operation not allowed in demo mode\"\n * }]\n * })\n * ```\n *\n * @example\n * Production use case with database operations\n * ```typescript\n * const hitlMiddleware = humanInTheLoopMiddleware({\n * toolConfigs: {\n * \"execute_sql\": {\n * requireApproval: true,\n * description: \"🚨 SQL query requires DBA approval\\nPlease review for safety and performance\"\n * },\n * \"read_schema\": {\n * requireApproval: false // Reading metadata is safe\n * },\n * \"delete_records\": {\n * requireApproval: true,\n * description: \"⛔ DESTRUCTIVE OPERATION - Requires manager approval\"\n * }\n * },\n * messagePrefix: \"Database operation pending approval\"\n * });\n * ```\n *\n * @remarks\n * - Tool calls are processed in the order they appear in the AI message\n * - Auto-approved tools execute immediately without interruption\n * - Multiple tools requiring approval are bundled into a single interrupt\n * - The middleware operates in the `afterModel` phase, intercepting before tool execution\n * - Requires a checkpointer to maintain state across interruptions\n *\n * @see {@link createAgent} for agent creation\n * @see {@link Command} for resuming interrupted execution\n * @public\n */\nexport function humanInTheLoopMiddleware(\n options: z.input<typeof contextSchema> = {}\n) {\n return createMiddleware({\n name: \"HumanInTheLoopMiddleware\",\n contextSchema,\n afterModel: async (state, runtime, controls) => {\n const config = { ...contextSchema.parse(options), ...runtime.context };\n const { messages } = state;\n\n if (!messages.length) {\n return;\n }\n\n const lastMessage = messages[messages.length - 1];\n\n // Check if it's an AI message with tool calls\n if (!isAIMessage(lastMessage) || !lastMessage.tool_calls?.length) {\n return;\n }\n\n // Separate tool calls that need interrupts from those that don't\n const interruptToolCalls: ToolCall[] = [];\n const autoApprovedToolCalls: ToolCall[] = [];\n\n for (const toolCall of lastMessage.tool_calls) {\n // Ensure tool call has an ID\n const normalizedToolCall: ToolCall = {\n id: toolCall.id || uuid(),\n name: toolCall.name,\n args: toolCall.args,\n };\n\n const toolConfig = config.toolConfigs[normalizedToolCall.name];\n\n if (toolConfig?.requireApproval) {\n interruptToolCalls.push(normalizedToolCall);\n } else {\n autoApprovedToolCalls.push(normalizedToolCall);\n }\n }\n\n // If no interrupts needed, return early\n if (!interruptToolCalls.length) {\n return;\n }\n\n const approvedToolCalls = [...autoApprovedToolCalls];\n\n // Process tool calls that need interrupts\n const requests: ToolApprovalRequest[] = interruptToolCalls.map(\n (toolCall) => {\n const toolConfig = config.toolConfigs[toolCall.name];\n const description =\n toolConfig?.description ||\n `${config.messagePrefix}\\n\\nTool: ${\n toolCall.name\n }\\nArgs: ${JSON.stringify(toolCall.args, null, 2)}`;\n\n return {\n action: toolCall.name,\n args: toolCall.args,\n toolCallId: toolCall.id,\n description,\n };\n }\n );\n\n // Interrupt and wait for human responses\n const responses = (await interrupt(requests)) as HumanResponse[];\n\n // Process responses\n for (let i = 0; i < responses.length; i++) {\n const response = responses[i];\n const toolCall = interruptToolCalls[i];\n\n switch (response.type) {\n case \"accept\":\n approvedToolCalls.push(toolCall);\n break;\n\n case \"edit\":\n // For edit, args is an ActionRequest with updated args\n if (\n response.args &&\n typeof response.args === \"object\" &&\n \"args\" in response.args\n ) {\n approvedToolCalls.push({\n ...toolCall,\n args: (\n response.args as { action: string; args: Record<string, any> }\n ).args,\n });\n }\n break;\n\n case \"ignore\":\n // Skip to end - terminate the agent\n return controls.terminate();\n\n case \"response\": {\n // Return manual tool response and jump back to model\n // For response, args is a string\n const toolMessage = new ToolMessage({\n content: typeof response.args === \"string\" ? response.args : \"\",\n tool_call_id: toolCall.id,\n });\n return {\n messages: [...state.messages, toolMessage],\n jump_to: \"model\",\n };\n }\n default:\n throw new Error(`Unknown response type: ${(response as any).type}`);\n }\n }\n\n // Update the last message with approved tool calls\n const updatedMessage = new AIMessage({\n content: lastMessage.content,\n tool_calls: approvedToolCalls,\n id: lastMessage.id,\n });\n\n // Replace the last message with the updated one\n return {\n messages: [...state.messages.slice(0, -1), updatedMessage],\n };\n },\n });\n}\n"],"mappings":";;;;;;;;AAmBA,MAAM,gBAAgBA,MAAE,OAAO;CAC7B,aAAaA,MACV,OACCA,MAAE,OAAO;EACP,iBAAiBA,MAAE,SAAS,CAAC,UAAU;EACvC,aAAaA,MAAE,QAAQ,CAAC,UAAU;CACnC,EAAC,CACH,CACA,QAAQ,CAAE,EAAC;CACd,eAAeA,MAAE,QAAQ,CAAC,QAAQ,mCAAmC;AACtE,EAAC;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAgJF,SAAgB,yBACdC,UAAyC,CAAE,GAC3C;AACA,QAAOC,oCAAiB;EACtB,MAAM;EACN;EACA,YAAY,OAAO,OAAO,SAAS,aAAa;GAC9C,MAAM,SAAS;IAAE,GAAG,cAAc,MAAM,QAAQ;IAAE,GAAG,QAAQ;GAAS;GACtE,MAAM,EAAE,UAAU,GAAG;AAErB,OAAI,CAAC,SAAS,OACZ;GAGF,MAAM,cAAc,SAAS,SAAS,SAAS;AAG/C,OAAI,4CAAa,YAAY,IAAI,CAAC,YAAY,YAAY,OACxD;GAIF,MAAMC,qBAAiC,CAAE;GACzC,MAAMC,wBAAoC,CAAE;AAE5C,QAAK,MAAM,YAAY,YAAY,YAAY;IAE7C,MAAMC,qBAA+B;KACnC,IAAI,SAAS,oBAAY;KACzB,MAAM,SAAS;KACf,MAAM,SAAS;IAChB;IAED,MAAM,aAAa,OAAO,YAAY,mBAAmB;AAEzD,QAAI,YAAY,iBACd,mBAAmB,KAAK,mBAAmB;SAE3C,sBAAsB,KAAK,mBAAmB;GAEjD;AAGD,OAAI,CAAC,mBAAmB,OACtB;GAGF,MAAM,oBAAoB,CAAC,GAAG,qBAAsB;GAGpD,MAAMC,WAAkC,mBAAmB,IACzD,CAAC,aAAa;IACZ,MAAM,aAAa,OAAO,YAAY,SAAS;IAC/C,MAAM,cACJ,YAAY,eACZ,GAAG,OAAO,cAAc,UAAU,EAChC,SAAS,KACV,QAAQ,EAAE,KAAK,UAAU,SAAS,MAAM,MAAM,EAAE,EAAE;AAErD,WAAO;KACL,QAAQ,SAAS;KACjB,MAAM,SAAS;KACf,YAAY,SAAS;KACrB;IACD;GACF,EACF;GAGD,MAAM,YAAa,2CAAgB,SAAS;AAG5C,QAAK,IAAI,IAAI,GAAG,IAAI,UAAU,QAAQ,KAAK;IACzC,MAAM,WAAW,UAAU;IAC3B,MAAM,WAAW,mBAAmB;AAEpC,YAAQ,SAAS,MAAjB;KACE,KAAK;MACH,kBAAkB,KAAK,SAAS;AAChC;KAEF,KAAK;AAEH,UACE,SAAS,QACT,OAAO,SAAS,SAAS,YACzB,UAAU,SAAS,MAEnB,kBAAkB,KAAK;OACrB,GAAG;OACH,MACE,SAAS,KACT;MACH,EAAC;AAEJ;KAEF,KAAK,SAEH,QAAO,SAAS,WAAW;KAE7B,KAAK,YAAY;MAGf,MAAM,cAAc,IAAIC,sCAAY;OAClC,SAAS,OAAO,SAAS,SAAS,WAAW,SAAS,OAAO;OAC7D,cAAc,SAAS;MACxB;AACD,aAAO;OACL,UAAU,CAAC,GAAG,MAAM,UAAU,WAAY;OAC1C,SAAS;MACV;KACF;KACD,QACE,OAAM,IAAI,MAAM,CAAC,uBAAuB,EAAG,SAAiB,MAAM;IACrE;GACF;GAGD,MAAM,iBAAiB,IAAIC,oCAAU;IACnC,SAAS,YAAY;IACrB,YAAY;IACZ,IAAI,YAAY;GACjB;AAGD,UAAO,EACL,UAAU,CAAC,GAAG,MAAM,SAAS,MAAM,GAAG,GAAG,EAAE,cAAe,EAC3D;EACF;CACF,EAAC;AACH"}
|
|
@@ -0,0 +1,199 @@
|
|
|
1
|
+
import { AgentMiddleware } from "../types.cjs";
|
|
2
|
+
import { z } from "zod";
|
|
3
|
+
|
|
4
|
+
//#region src/agents/middlewareAgent/middlewares/hitl.d.ts
|
|
5
|
+
declare const contextSchema: z.ZodObject<{
|
|
6
|
+
toolConfigs: z.ZodDefault<z.ZodRecord<z.ZodString, z.ZodObject<{
|
|
7
|
+
requireApproval: z.ZodOptional<z.ZodBoolean>;
|
|
8
|
+
description: z.ZodOptional<z.ZodString>;
|
|
9
|
+
}, "strip", z.ZodTypeAny, {
|
|
10
|
+
requireApproval?: boolean | undefined;
|
|
11
|
+
description?: string | undefined;
|
|
12
|
+
}, {
|
|
13
|
+
requireApproval?: boolean | undefined;
|
|
14
|
+
description?: string | undefined;
|
|
15
|
+
}>>>;
|
|
16
|
+
messagePrefix: z.ZodDefault<z.ZodString>;
|
|
17
|
+
}, "strip", z.ZodTypeAny, {
|
|
18
|
+
toolConfigs: Record<string, {
|
|
19
|
+
requireApproval?: boolean | undefined;
|
|
20
|
+
description?: string | undefined;
|
|
21
|
+
}>;
|
|
22
|
+
messagePrefix: string;
|
|
23
|
+
}, {
|
|
24
|
+
toolConfigs?: Record<string, {
|
|
25
|
+
requireApproval?: boolean | undefined;
|
|
26
|
+
description?: string | undefined;
|
|
27
|
+
}> | undefined;
|
|
28
|
+
messagePrefix?: string | undefined;
|
|
29
|
+
}>;
|
|
30
|
+
/**
|
|
31
|
+
* Creates a Human-in-the-Loop (HITL) middleware for tool approval and oversight.
|
|
32
|
+
*
|
|
33
|
+
* This middleware intercepts tool calls made by an AI agent and provides human oversight
|
|
34
|
+
* capabilities before execution. It enables selective approval workflows where certain tools
|
|
35
|
+
* require human intervention while others can execute automatically.
|
|
36
|
+
*
|
|
37
|
+
* ## Features
|
|
38
|
+
*
|
|
39
|
+
* - **Selective Tool Approval**: Configure which tools require human approval
|
|
40
|
+
* - **Multiple Response Types**: Accept, edit, ignore, or manually respond to tool calls
|
|
41
|
+
* - **Asynchronous Workflow**: Uses LangGraph's interrupt mechanism for non-blocking approval
|
|
42
|
+
* - **Custom Approval Messages**: Provide context-specific descriptions for approval requests
|
|
43
|
+
*
|
|
44
|
+
* ## Response Types
|
|
45
|
+
*
|
|
46
|
+
* When a tool requires approval, the human operator can respond with:
|
|
47
|
+
* - `accept`: Execute the tool with original arguments
|
|
48
|
+
* - `edit`: Modify the tool arguments before execution
|
|
49
|
+
* - `ignore`: Skip the tool and terminate the agent
|
|
50
|
+
* - `response`: Provide a manual response instead of executing the tool
|
|
51
|
+
*
|
|
52
|
+
* @param options - Configuration options for the middleware
|
|
53
|
+
* @param options.toolConfigs - Per-tool configuration mapping tool names to their settings
|
|
54
|
+
* @param options.toolConfigs[toolName].requireApproval - Whether the tool requires human approval
|
|
55
|
+
* @param options.toolConfigs[toolName].description - Custom approval message for the tool
|
|
56
|
+
* @param options.messagePrefix - Default prefix for approval messages (default: "Tool execution requires approval")
|
|
57
|
+
*
|
|
58
|
+
* @returns A middleware instance that can be passed to `createAgent`
|
|
59
|
+
*
|
|
60
|
+
* @example
|
|
61
|
+
* Basic usage with selective tool approval
|
|
62
|
+
* ```typescript
|
|
63
|
+
* import { humanInTheLoopMiddleware } from "langchain/middleware";
|
|
64
|
+
* import { createAgent } from "langchain";
|
|
65
|
+
*
|
|
66
|
+
* const hitlMiddleware = humanInTheLoopMiddleware({
|
|
67
|
+
* toolConfigs: {
|
|
68
|
+
* "write_file": {
|
|
69
|
+
* requireApproval: true,
|
|
70
|
+
* description: "⚠️ File write operation requires approval"
|
|
71
|
+
* },
|
|
72
|
+
* "read_file": {
|
|
73
|
+
* requireApproval: false // Safe operation, no approval needed
|
|
74
|
+
* }
|
|
75
|
+
* }
|
|
76
|
+
* });
|
|
77
|
+
*
|
|
78
|
+
* const agent = createAgent({
|
|
79
|
+
* model: "openai:gpt-4",
|
|
80
|
+
* tools: [writeFileTool, readFileTool],
|
|
81
|
+
* middlewares: [hitlMiddleware]
|
|
82
|
+
* });
|
|
83
|
+
* ```
|
|
84
|
+
*
|
|
85
|
+
* @example
|
|
86
|
+
* Handling approval requests
|
|
87
|
+
* ```typescript
|
|
88
|
+
* import { Command } from "@langchain/langgraph";
|
|
89
|
+
*
|
|
90
|
+
* // Initial agent invocation
|
|
91
|
+
* const result = await agent.invoke({
|
|
92
|
+
* messages: [new HumanMessage("Write 'Hello' to output.txt")]
|
|
93
|
+
* }, config);
|
|
94
|
+
*
|
|
95
|
+
* // Check if agent is paused for approval
|
|
96
|
+
* const state = await agent.graph.getState(config);
|
|
97
|
+
* if (state.next?.length > 0) {
|
|
98
|
+
* // Get interrupt details
|
|
99
|
+
* const task = state.tasks?.[0];
|
|
100
|
+
* const requests = task?.interrupts?.[0]?.value;
|
|
101
|
+
*
|
|
102
|
+
* // Show tool call details to user
|
|
103
|
+
* console.log("Tool:", requests[0].action);
|
|
104
|
+
* console.log("Args:", requests[0].args);
|
|
105
|
+
*
|
|
106
|
+
* // Resume with approval
|
|
107
|
+
* await agent.invoke(
|
|
108
|
+
* new Command({ resume: [{ type: "accept" }] }),
|
|
109
|
+
* config
|
|
110
|
+
* );
|
|
111
|
+
* }
|
|
112
|
+
* ```
|
|
113
|
+
*
|
|
114
|
+
* @example
|
|
115
|
+
* Different response types
|
|
116
|
+
* ```typescript
|
|
117
|
+
* // Accept the tool call as-is
|
|
118
|
+
* new Command({ resume: [{ type: "accept" }] })
|
|
119
|
+
*
|
|
120
|
+
* // Edit the tool arguments
|
|
121
|
+
* new Command({
|
|
122
|
+
* resume: [{
|
|
123
|
+
* type: "edit",
|
|
124
|
+
* args: { action: "write_file", args: { filename: "safe.txt", content: "Modified" } }
|
|
125
|
+
* }]
|
|
126
|
+
* })
|
|
127
|
+
*
|
|
128
|
+
* // Skip tool and terminate agent
|
|
129
|
+
* new Command({ resume: [{ type: "ignore" }] })
|
|
130
|
+
*
|
|
131
|
+
* // Provide manual response
|
|
132
|
+
* new Command({
|
|
133
|
+
* resume: [{
|
|
134
|
+
* type: "response",
|
|
135
|
+
* args: "File operation not allowed in demo mode"
|
|
136
|
+
* }]
|
|
137
|
+
* })
|
|
138
|
+
* ```
|
|
139
|
+
*
|
|
140
|
+
* @example
|
|
141
|
+
* Production use case with database operations
|
|
142
|
+
* ```typescript
|
|
143
|
+
* const hitlMiddleware = humanInTheLoopMiddleware({
|
|
144
|
+
* toolConfigs: {
|
|
145
|
+
* "execute_sql": {
|
|
146
|
+
* requireApproval: true,
|
|
147
|
+
* description: "🚨 SQL query requires DBA approval\nPlease review for safety and performance"
|
|
148
|
+
* },
|
|
149
|
+
* "read_schema": {
|
|
150
|
+
* requireApproval: false // Reading metadata is safe
|
|
151
|
+
* },
|
|
152
|
+
* "delete_records": {
|
|
153
|
+
* requireApproval: true,
|
|
154
|
+
* description: "⛔ DESTRUCTIVE OPERATION - Requires manager approval"
|
|
155
|
+
* }
|
|
156
|
+
* },
|
|
157
|
+
* messagePrefix: "Database operation pending approval"
|
|
158
|
+
* });
|
|
159
|
+
* ```
|
|
160
|
+
*
|
|
161
|
+
* @remarks
|
|
162
|
+
* - Tool calls are processed in the order they appear in the AI message
|
|
163
|
+
* - Auto-approved tools execute immediately without interruption
|
|
164
|
+
* - Multiple tools requiring approval are bundled into a single interrupt
|
|
165
|
+
* - The middleware operates in the `afterModel` phase, intercepting before tool execution
|
|
166
|
+
* - Requires a checkpointer to maintain state across interruptions
|
|
167
|
+
*
|
|
168
|
+
* @see {@link createAgent} for agent creation
|
|
169
|
+
* @see {@link Command} for resuming interrupted execution
|
|
170
|
+
* @public
|
|
171
|
+
*/
|
|
172
|
+
declare function humanInTheLoopMiddleware(options?: z.input<typeof contextSchema>): AgentMiddleware<undefined, z.ZodObject<{
|
|
173
|
+
toolConfigs: z.ZodDefault<z.ZodRecord<z.ZodString, z.ZodObject<{
|
|
174
|
+
requireApproval: z.ZodOptional<z.ZodBoolean>;
|
|
175
|
+
description: z.ZodOptional<z.ZodString>;
|
|
176
|
+
}, "strip", z.ZodTypeAny, {
|
|
177
|
+
requireApproval?: boolean | undefined;
|
|
178
|
+
description?: string | undefined;
|
|
179
|
+
}, {
|
|
180
|
+
requireApproval?: boolean | undefined;
|
|
181
|
+
description?: string | undefined;
|
|
182
|
+
}>>>;
|
|
183
|
+
messagePrefix: z.ZodDefault<z.ZodString>;
|
|
184
|
+
}, "strip", z.ZodTypeAny, {
|
|
185
|
+
toolConfigs: Record<string, {
|
|
186
|
+
requireApproval?: boolean | undefined;
|
|
187
|
+
description?: string | undefined;
|
|
188
|
+
}>;
|
|
189
|
+
messagePrefix: string;
|
|
190
|
+
}, {
|
|
191
|
+
toolConfigs?: Record<string, {
|
|
192
|
+
requireApproval?: boolean | undefined;
|
|
193
|
+
description?: string | undefined;
|
|
194
|
+
}> | undefined;
|
|
195
|
+
messagePrefix?: string | undefined;
|
|
196
|
+
}>, any>;
|
|
197
|
+
//#endregion
|
|
198
|
+
export { humanInTheLoopMiddleware };
|
|
199
|
+
//# sourceMappingURL=hitl.d.cts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"hitl.d.cts","names":["z","contextSchema","ZodString","ZodBoolean","ZodOptional","ZodTypeAny","ZodObject","ZodRecord","ZodDefault","Record","humanInTheLoopMiddleware","input","___types_js1","AgentMiddleware"],"sources":["../../../../src/agents/middlewareAgent/middlewares/hitl.d.ts"],"sourcesContent":["import { z } from \"zod\";\ndeclare const contextSchema: z.ZodObject<{\n toolConfigs: z.ZodDefault<z.ZodRecord<z.ZodString, z.ZodObject<{\n requireApproval: z.ZodOptional<z.ZodBoolean>;\n description: z.ZodOptional<z.ZodString>;\n }, \"strip\", z.ZodTypeAny, {\n requireApproval?: boolean | undefined;\n description?: string | undefined;\n }, {\n requireApproval?: boolean | undefined;\n description?: string | undefined;\n }>>>;\n messagePrefix: z.ZodDefault<z.ZodString>;\n}, \"strip\", z.ZodTypeAny, {\n toolConfigs: Record<string, {\n requireApproval?: boolean | undefined;\n description?: string | undefined;\n }>;\n messagePrefix: string;\n}, {\n toolConfigs?: Record<string, {\n requireApproval?: boolean | undefined;\n description?: string | undefined;\n }> | undefined;\n messagePrefix?: string | undefined;\n}>;\n/**\n * Creates a Human-in-the-Loop (HITL) middleware for tool approval and oversight.\n *\n * This middleware intercepts tool calls made by an AI agent and provides human oversight\n * capabilities before execution. It enables selective approval workflows where certain tools\n * require human intervention while others can execute automatically.\n *\n * ## Features\n *\n * - **Selective Tool Approval**: Configure which tools require human approval\n * - **Multiple Response Types**: Accept, edit, ignore, or manually respond to tool calls\n * - **Asynchronous Workflow**: Uses LangGraph's interrupt mechanism for non-blocking approval\n * - **Custom Approval Messages**: Provide context-specific descriptions for approval requests\n *\n * ## Response Types\n *\n * When a tool requires approval, the human operator can respond with:\n * - `accept`: Execute the tool with original arguments\n * - `edit`: Modify the tool arguments before execution\n * - `ignore`: Skip the tool and terminate the agent\n * - `response`: Provide a manual response instead of executing the tool\n *\n * @param options - Configuration options for the middleware\n * @param options.toolConfigs - Per-tool configuration mapping tool names to their settings\n * @param options.toolConfigs[toolName].requireApproval - Whether the tool requires human approval\n * @param options.toolConfigs[toolName].description - Custom approval message for the tool\n * @param options.messagePrefix - Default prefix for approval messages (default: \"Tool execution requires approval\")\n *\n * @returns A middleware instance that can be passed to `createAgent`\n *\n * @example\n * Basic usage with selective tool approval\n * ```typescript\n * import { humanInTheLoopMiddleware } from \"langchain/middleware\";\n * import { createAgent } from \"langchain\";\n *\n * const hitlMiddleware = humanInTheLoopMiddleware({\n * toolConfigs: {\n * \"write_file\": {\n * requireApproval: true,\n * description: \"⚠️ File write operation requires approval\"\n * },\n * \"read_file\": {\n * requireApproval: false // Safe operation, no approval needed\n * }\n * }\n * });\n *\n * const agent = createAgent({\n * model: \"openai:gpt-4\",\n * tools: [writeFileTool, readFileTool],\n * middlewares: [hitlMiddleware]\n * });\n * ```\n *\n * @example\n * Handling approval requests\n * ```typescript\n * import { Command } from \"@langchain/langgraph\";\n *\n * // Initial agent invocation\n * const result = await agent.invoke({\n * messages: [new HumanMessage(\"Write 'Hello' to output.txt\")]\n * }, config);\n *\n * // Check if agent is paused for approval\n * const state = await agent.graph.getState(config);\n * if (state.next?.length > 0) {\n * // Get interrupt details\n * const task = state.tasks?.[0];\n * const requests = task?.interrupts?.[0]?.value;\n *\n * // Show tool call details to user\n * console.log(\"Tool:\", requests[0].action);\n * console.log(\"Args:\", requests[0].args);\n *\n * // Resume with approval\n * await agent.invoke(\n * new Command({ resume: [{ type: \"accept\" }] }),\n * config\n * );\n * }\n * ```\n *\n * @example\n * Different response types\n * ```typescript\n * // Accept the tool call as-is\n * new Command({ resume: [{ type: \"accept\" }] })\n *\n * // Edit the tool arguments\n * new Command({\n * resume: [{\n * type: \"edit\",\n * args: { action: \"write_file\", args: { filename: \"safe.txt\", content: \"Modified\" } }\n * }]\n * })\n *\n * // Skip tool and terminate agent\n * new Command({ resume: [{ type: \"ignore\" }] })\n *\n * // Provide manual response\n * new Command({\n * resume: [{\n * type: \"response\",\n * args: \"File operation not allowed in demo mode\"\n * }]\n * })\n * ```\n *\n * @example\n * Production use case with database operations\n * ```typescript\n * const hitlMiddleware = humanInTheLoopMiddleware({\n * toolConfigs: {\n * \"execute_sql\": {\n * requireApproval: true,\n * description: \"🚨 SQL query requires DBA approval\\nPlease review for safety and performance\"\n * },\n * \"read_schema\": {\n * requireApproval: false // Reading metadata is safe\n * },\n * \"delete_records\": {\n * requireApproval: true,\n * description: \"⛔ DESTRUCTIVE OPERATION - Requires manager approval\"\n * }\n * },\n * messagePrefix: \"Database operation pending approval\"\n * });\n * ```\n *\n * @remarks\n * - Tool calls are processed in the order they appear in the AI message\n * - Auto-approved tools execute immediately without interruption\n * - Multiple tools requiring approval are bundled into a single interrupt\n * - The middleware operates in the `afterModel` phase, intercepting before tool execution\n * - Requires a checkpointer to maintain state across interruptions\n *\n * @see {@link createAgent} for agent creation\n * @see {@link Command} for resuming interrupted execution\n * @public\n */\nexport declare function humanInTheLoopMiddleware(options?: z.input<typeof contextSchema>): import(\"../types.js\").AgentMiddleware<undefined, z.ZodObject<{\n toolConfigs: z.ZodDefault<z.ZodRecord<z.ZodString, z.ZodObject<{\n requireApproval: z.ZodOptional<z.ZodBoolean>;\n description: z.ZodOptional<z.ZodString>;\n }, \"strip\", z.ZodTypeAny, {\n requireApproval?: boolean | undefined;\n description?: string | undefined;\n }, {\n requireApproval?: boolean | undefined;\n description?: string | undefined;\n }>>>;\n messagePrefix: z.ZodDefault<z.ZodString>;\n}, \"strip\", z.ZodTypeAny, {\n toolConfigs: Record<string, {\n requireApproval?: boolean | undefined;\n description?: string | undefined;\n }>;\n messagePrefix: string;\n}, {\n toolConfigs?: Record<string, {\n requireApproval?: boolean | undefined;\n description?: string | undefined;\n }> | undefined;\n messagePrefix?: string | undefined;\n}>, any>;\nexport {};\n"],"mappings":";;;;cACcC,eAAeD,CAAAA,CAAEM;eACdN,CAAAA,CAAEQ,WAAWR,CAAAA,CAAEO,UAAUP,CAAAA,CAAEE,WAAWF,CAAAA,CAAEM;qBAChCN,CAAAA,CAAEI,YAAYJ,CAAAA,CAAEG;IAF3BF,WAAAA,EAGOD,CAAAA,CAAEI,WAqBrB,CArBiCJ,CAAAA,CAAEE,SAqBnC,CAAA;EAAA,CAAA,EAAA,OAAA,EApBcF,CAAAA,CAAEK,UAoBhB,EAAA;IAvBwCL,eAAEE,CAAAA,EAAAA,OAAAA,GAAAA,SAAAA;IACLF,WAAEG,CAAAA,EAAAA,MAAAA,GAAAA,SAAAA;EAAU,CAAA,EAA1BH;IACUA,eAAEE,CAAAA,EAAAA,OAAAA,GAAAA,SAAAA;IAAhBF,WAAEI,CAAAA,EAAAA,MAAAA,GAAAA,SAAAA;EAAW,CAAA,CAAA,CAClBJ,CAAAA;EAAY,aAH6BM,EAUtCN,CAAAA,CAAEQ,UAVoCF,CAUzBN,CAAAA,CAAEE,SAVuBI,CAAAA;CAAS,EAAA,OAAlCC,EAWpBP,CAAAA,CAAEK,UAXkBE,EAAAA;EAAS,WAAtBC,EAYFC,MAZED,CAAAA,MAAAA,EAAAA;IAUaR,eAAEE,CAAAA,EAAAA,OAAAA,GAAAA,SAAAA;IAAfF,WAAEQ,CAAAA,EAAAA,MAAAA,GAAAA,SAAAA;EAAU,CAAA,CAAA;EACP,aACPC,EAAAA,MAAAA;CAAM,EAAA;EAMC,WAnBOH,CAAAA,EAmBbG,MAnBaH,CAAAA,MAAAA,EAAAA;IAAS,eAAA,CAAA,EAAA,OAAA,GAAA,SAAA;IAuKhBI,WAAAA,CAAAA,EAAAA,MAAAA,GAAwB,SAAA;EAAA,CAAA,CAAA,GAAA,SAAA;EAAA,aAA0BT,CAAAA,EAAAA,MAAAA,GAAAA,SAAAA;CAAa,CAAA;;;;;;;;;;;;;;;;;AAAyC;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;iBAAxGS,wBAAAA,WAAmCV,CAAAA,CAAEW,aAAaV,iBAA6E,2BAAXD,CAAAA,CAAEM;eAC7HN,CAAAA,CAAEQ,WAAWR,CAAAA,CAAEO,UAAUP,CAAAA,CAAEE,WAAWF,CAAAA,CAAEM;qBAChCN,CAAAA,CAAEI,YAAYJ,CAAAA,CAAEG;iBACpBH,CAAAA,CAAEI,YAAYJ,CAAAA,CAAEE;cACrBF,CAAAA,CAAEK;;;;;;;iBAOCL,CAAAA,CAAEQ,WAAWR,CAAAA,CAAEE;YACtBF,CAAAA,CAAEK;eACGI;;;;;;gBAMCA"}
|