@loopman/langchain-sdk 1.7.0 → 1.12.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (94) hide show
  1. package/README.md +78 -5
  2. package/dist/agents/loopman-agent.d.ts.map +1 -1
  3. package/dist/agents/loopman-agent.js +51 -92
  4. package/dist/agents/loopman-agent.js.map +1 -1
  5. package/dist/client/loopman-api.d.ts +19 -64
  6. package/dist/client/loopman-api.d.ts.map +1 -1
  7. package/dist/client/loopman-api.js +85 -248
  8. package/dist/client/loopman-api.js.map +1 -1
  9. package/dist/helpers/prompt-orchestrator.js +17 -17
  10. package/dist/helpers/prompt-orchestrator.js.map +1 -1
  11. package/dist/helpers/template-generator-static.d.ts +27 -0
  12. package/dist/helpers/template-generator-static.d.ts.map +1 -0
  13. package/dist/helpers/template-generator-static.js +52 -0
  14. package/dist/helpers/template-generator-static.js.map +1 -0
  15. package/dist/helpers/template-generator.d.ts +50 -0
  16. package/dist/helpers/template-generator.d.ts.map +1 -0
  17. package/dist/helpers/template-generator.js +85 -0
  18. package/dist/helpers/template-generator.js.map +1 -0
  19. package/dist/index.d.ts +6 -1
  20. package/dist/index.d.ts.map +1 -1
  21. package/dist/index.js +6 -0
  22. package/dist/index.js.map +1 -1
  23. package/dist/langgraph/helpers.d.ts +171 -0
  24. package/dist/langgraph/helpers.d.ts.map +1 -0
  25. package/dist/langgraph/helpers.js +216 -0
  26. package/dist/langgraph/helpers.js.map +1 -0
  27. package/dist/langgraph/index.d.ts +16 -0
  28. package/dist/langgraph/index.d.ts.map +1 -0
  29. package/dist/langgraph/index.js +17 -0
  30. package/dist/langgraph/index.js.map +1 -0
  31. package/dist/langgraph/loopman-conditional-edge.d.ts +58 -0
  32. package/dist/langgraph/loopman-conditional-edge.d.ts.map +1 -0
  33. package/dist/langgraph/loopman-conditional-edge.js +77 -0
  34. package/dist/langgraph/loopman-conditional-edge.js.map +1 -0
  35. package/dist/langgraph/loopman-context-node.d.ts +74 -0
  36. package/dist/langgraph/loopman-context-node.d.ts.map +1 -0
  37. package/dist/langgraph/loopman-context-node.js +143 -0
  38. package/dist/langgraph/loopman-context-node.js.map +1 -0
  39. package/dist/langgraph/loopman-validation-node.d.ts +119 -0
  40. package/dist/langgraph/loopman-validation-node.d.ts.map +1 -0
  41. package/dist/langgraph/loopman-validation-node.js +420 -0
  42. package/dist/langgraph/loopman-validation-node.js.map +1 -0
  43. package/dist/langgraph/types.d.ts +75 -0
  44. package/dist/langgraph/types.d.ts.map +1 -0
  45. package/dist/langgraph/types.js +74 -0
  46. package/dist/langgraph/types.js.map +1 -0
  47. package/dist/loopman-agent-wrapper.d.ts +18 -0
  48. package/dist/loopman-agent-wrapper.d.ts.map +1 -1
  49. package/dist/loopman-agent-wrapper.js +31 -21
  50. package/dist/loopman-agent-wrapper.js.map +1 -1
  51. package/dist/loopman-middleware.d.ts +0 -5
  52. package/dist/loopman-middleware.d.ts.map +1 -1
  53. package/dist/loopman-middleware.js +22 -23
  54. package/dist/loopman-middleware.js.map +1 -1
  55. package/dist/mcp/loopman-mcp-client.d.ts.map +1 -1
  56. package/dist/mcp/loopman-mcp-client.js +5 -0
  57. package/dist/mcp/loopman-mcp-client.js.map +1 -1
  58. package/dist/mcp/tool-registry.d.ts +7 -1
  59. package/dist/mcp/tool-registry.d.ts.map +1 -1
  60. package/dist/mcp/tool-registry.js +23 -16
  61. package/dist/mcp/tool-registry.js.map +1 -1
  62. package/dist/services/logger.service.d.ts.map +1 -1
  63. package/dist/services/logger.service.js +4 -12
  64. package/dist/services/logger.service.js.map +1 -1
  65. package/dist/services/loopman.service.d.ts +25 -11
  66. package/dist/services/loopman.service.d.ts.map +1 -1
  67. package/dist/services/loopman.service.js +74 -45
  68. package/dist/services/loopman.service.js.map +1 -1
  69. package/dist/services/polling.service.d.ts +7 -3
  70. package/dist/services/polling.service.d.ts.map +1 -1
  71. package/dist/services/polling.service.js +61 -47
  72. package/dist/services/polling.service.js.map +1 -1
  73. package/dist/templates.json +20 -0
  74. package/dist/types.d.ts +9 -35
  75. package/dist/types.d.ts.map +1 -1
  76. package/dist/types.js.map +1 -1
  77. package/examples/README.md +346 -0
  78. package/examples/templates/README.md +285 -0
  79. package/examples/templates/langchain-full-review/.env.example +3 -0
  80. package/examples/templates/langchain-full-review/README.md +165 -0
  81. package/examples/templates/langchain-full-review/index.ts +54 -0
  82. package/examples/templates/langchain-full-review/package.json +29 -0
  83. package/examples/templates/langchain-full-review/tsconfig.json +22 -0
  84. package/examples/templates/langchain-tool-validation/.env.example +3 -0
  85. package/examples/templates/langchain-tool-validation/README.md +137 -0
  86. package/examples/templates/langchain-tool-validation/index.ts +65 -0
  87. package/examples/templates/langchain-tool-validation/package.json +29 -0
  88. package/examples/templates/langchain-tool-validation/tsconfig.json +22 -0
  89. package/examples/templates/langgraph-hello-world/.env.example +3 -0
  90. package/examples/templates/langgraph-hello-world/README.md +71 -0
  91. package/examples/templates/langgraph-hello-world/index.ts +147 -0
  92. package/examples/templates/langgraph-hello-world/package.json +27 -0
  93. package/examples/templates/langgraph-hello-world/tsconfig.json +22 -0
  94. package/package.json +12 -7
@@ -0,0 +1,16 @@
1
+ /**
2
+ * LangGraph Integration for Loopman
3
+ *
4
+ * This module provides LangGraph nodes and utilities for integrating
5
+ * Human-in-the-Loop validation into your workflows.
6
+ */
7
+ export { LoopmanGraphState } from "./types";
8
+ export type { LoopmanGuideline, LoopmanDecision } from "./types";
9
+ export { createLoopmanValidationNode } from "./loopman-validation-node";
10
+ export type { LoopmanValidationNodeConfig } from "./loopman-validation-node";
11
+ export { createLoopmanConditionalEdge } from "./loopman-conditional-edge";
12
+ export { createLoopmanContextNode } from "./loopman-context-node";
13
+ export type { LoopmanContextNodeConfig } from "./loopman-context-node";
14
+ export { enrichSystemPrompt, formatGuidelines, formatDecisionContext, hasLoopmanContext, getCriticalGuidelines, getLatestDecision, } from "./helpers";
15
+ export type { EnrichSystemPromptOptions } from "./helpers";
16
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/langgraph/index.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAGH,OAAO,EAAE,iBAAiB,EAAE,MAAM,SAAS,CAAC;AAC5C,YAAY,EAAE,gBAAgB,EAAE,eAAe,EAAE,MAAM,SAAS,CAAC;AAGjE,OAAO,EAAE,2BAA2B,EAAE,MAAM,2BAA2B,CAAC;AACxE,YAAY,EAAE,2BAA2B,EAAE,MAAM,2BAA2B,CAAC;AAG7E,OAAO,EAAE,4BAA4B,EAAE,MAAM,4BAA4B,CAAC;AAG1E,OAAO,EAAE,wBAAwB,EAAE,MAAM,wBAAwB,CAAC;AAClE,YAAY,EAAE,wBAAwB,EAAE,MAAM,wBAAwB,CAAC;AAGvE,OAAO,EACL,kBAAkB,EAClB,gBAAgB,EAChB,qBAAqB,EACrB,iBAAiB,EACjB,qBAAqB,EACrB,iBAAiB,GAClB,MAAM,WAAW,CAAC;AACnB,YAAY,EAAE,yBAAyB,EAAE,MAAM,WAAW,CAAC"}
@@ -0,0 +1,17 @@
1
+ /**
2
+ * LangGraph Integration for Loopman
3
+ *
4
+ * This module provides LangGraph nodes and utilities for integrating
5
+ * Human-in-the-Loop validation into your workflows.
6
+ */
7
+ // Export types and state
8
+ export { LoopmanGraphState } from "./types";
9
+ // Export validation node
10
+ export { createLoopmanValidationNode } from "./loopman-validation-node";
11
+ // Export conditional edge
12
+ export { createLoopmanConditionalEdge } from "./loopman-conditional-edge";
13
+ // Export context node
14
+ export { createLoopmanContextNode } from "./loopman-context-node";
15
+ // Export helper functions
16
+ export { enrichSystemPrompt, formatGuidelines, formatDecisionContext, hasLoopmanContext, getCriticalGuidelines, getLatestDecision, } from "./helpers";
17
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/langgraph/index.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,yBAAyB;AACzB,OAAO,EAAE,iBAAiB,EAAE,MAAM,SAAS,CAAC;AAG5C,yBAAyB;AACzB,OAAO,EAAE,2BAA2B,EAAE,MAAM,2BAA2B,CAAC;AAGxE,0BAA0B;AAC1B,OAAO,EAAE,4BAA4B,EAAE,MAAM,4BAA4B,CAAC;AAE1E,sBAAsB;AACtB,OAAO,EAAE,wBAAwB,EAAE,MAAM,wBAAwB,CAAC;AAGlE,0BAA0B;AAC1B,OAAO,EACL,kBAAkB,EAClB,gBAAgB,EAChB,qBAAqB,EACrB,iBAAiB,EACjB,qBAAqB,EACrB,iBAAiB,GAClB,MAAM,WAAW,CAAC"}
@@ -0,0 +1,58 @@
1
+ /**
2
+ * Loopman Conditional Edge for LangGraph
3
+ *
4
+ * This conditional edge routes the workflow based on the Loopman task status
5
+ * after human validation.
6
+ */
7
+ /**
8
+ * Creates a conditional edge function for routing based on Loopman task status
9
+ *
10
+ * **Works with any state**: This function only reads `loopmanTaskStatus` from
11
+ * the state. You can use it with any custom state that includes this field.
12
+ *
13
+ * @param options - Optional configuration
14
+ * @param options.debug - Enable debug logging
15
+ * @returns Function that routes based on loopmanTaskStatus
16
+ *
17
+ * @example Basic usage
18
+ * ```typescript
19
+ * import { createLoopmanConditionalEdge } from "loopman-langchain-sdk";
20
+ * import { StateGraph, END } from "@langchain/langgraph";
21
+ *
22
+ * const workflow = new StateGraph(LoopmanGraphState)
23
+ * .addNode("agent", agentNode)
24
+ * .addNode("validation", validationNode)
25
+ * .addNode("tools", toolNode)
26
+ * .addConditionalEdges(
27
+ * "validation",
28
+ * createLoopmanConditionalEdge({ debug: true }),
29
+ * {
30
+ * execute: "tools", // APPROVED → execute tool
31
+ * rejected: END, // REJECTED → end workflow
32
+ * retry: "agent", // NEEDS_CHANGES → retry with feedback
33
+ * timeout: END, // TIMEOUT → end workflow
34
+ * error: END // ERROR → end workflow
35
+ * }
36
+ * );
37
+ * ```
38
+ *
39
+ * @example Custom routing
40
+ * ```typescript
41
+ * const workflow = new StateGraph(MyState)
42
+ * .addConditionalEdges(
43
+ * "validation",
44
+ * createLoopmanConditionalEdge(),
45
+ * {
46
+ * execute: "execute_action",
47
+ * rejected: "notify_rejection",
48
+ * retry: "agent_with_context",
49
+ * timeout: "handle_timeout",
50
+ * error: "handle_error",
51
+ * }
52
+ * );
53
+ * ```
54
+ */
55
+ export declare function createLoopmanConditionalEdge(options?: {
56
+ debug?: boolean;
57
+ }): (state: any) => string;
58
+ //# sourceMappingURL=loopman-conditional-edge.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"loopman-conditional-edge.d.ts","sourceRoot":"","sources":["../../src/langgraph/loopman-conditional-edge.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA+CG;AACH,wBAAgB,4BAA4B,CAAC,OAAO,CAAC,EAAE;IAAE,KAAK,CAAC,EAAE,OAAO,CAAA;CAAE,IAChE,OAAO,GAAG,KAAG,MAAM,CA0B5B"}
@@ -0,0 +1,77 @@
1
+ /**
2
+ * Loopman Conditional Edge for LangGraph
3
+ *
4
+ * This conditional edge routes the workflow based on the Loopman task status
5
+ * after human validation.
6
+ */
7
+ /**
8
+ * Creates a conditional edge function for routing based on Loopman task status
9
+ *
10
+ * **Works with any state**: This function only reads `loopmanTaskStatus` from
11
+ * the state. You can use it with any custom state that includes this field.
12
+ *
13
+ * @param options - Optional configuration
14
+ * @param options.debug - Enable debug logging
15
+ * @returns Function that routes based on loopmanTaskStatus
16
+ *
17
+ * @example Basic usage
18
+ * ```typescript
19
+ * import { createLoopmanConditionalEdge } from "loopman-langchain-sdk";
20
+ * import { StateGraph, END } from "@langchain/langgraph";
21
+ *
22
+ * const workflow = new StateGraph(LoopmanGraphState)
23
+ * .addNode("agent", agentNode)
24
+ * .addNode("validation", validationNode)
25
+ * .addNode("tools", toolNode)
26
+ * .addConditionalEdges(
27
+ * "validation",
28
+ * createLoopmanConditionalEdge({ debug: true }),
29
+ * {
30
+ * execute: "tools", // APPROVED → execute tool
31
+ * rejected: END, // REJECTED → end workflow
32
+ * retry: "agent", // NEEDS_CHANGES → retry with feedback
33
+ * timeout: END, // TIMEOUT → end workflow
34
+ * error: END // ERROR → end workflow
35
+ * }
36
+ * );
37
+ * ```
38
+ *
39
+ * @example Custom routing
40
+ * ```typescript
41
+ * const workflow = new StateGraph(MyState)
42
+ * .addConditionalEdges(
43
+ * "validation",
44
+ * createLoopmanConditionalEdge(),
45
+ * {
46
+ * execute: "execute_action",
47
+ * rejected: "notify_rejection",
48
+ * retry: "agent_with_context",
49
+ * timeout: "handle_timeout",
50
+ * error: "handle_error",
51
+ * }
52
+ * );
53
+ * ```
54
+ */
55
+ export function createLoopmanConditionalEdge(options) {
56
+ return (state) => {
57
+ const { loopmanTaskStatus } = state;
58
+ void options; // Debug logging intentionally omitted (library is silent by default)
59
+ switch (loopmanTaskStatus) {
60
+ case "APPROVED":
61
+ return "execute"; // Proceed to tool execution
62
+ case "REJECTED":
63
+ return "rejected"; // End workflow
64
+ case "NEEDS_CHANGES":
65
+ return "retry"; // Loop back to agent for correction
66
+ case "TIMEOUT":
67
+ return "timeout"; // Handle timeout case
68
+ case "PENDING":
69
+ // Should not happen after polling completes, but handle gracefully
70
+ return "timeout";
71
+ case "ERROR":
72
+ default:
73
+ return "error"; // Handle errors
74
+ }
75
+ };
76
+ }
77
+ //# sourceMappingURL=loopman-conditional-edge.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"loopman-conditional-edge.js","sourceRoot":"","sources":["../../src/langgraph/loopman-conditional-edge.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA+CG;AACH,MAAM,UAAU,4BAA4B,CAAC,OAA6B;IACxE,OAAO,CAAC,KAAU,EAAU,EAAE;QAC5B,MAAM,EAAE,iBAAiB,EAAE,GAAG,KAAK,CAAC;QACpC,KAAK,OAAO,CAAC,CAAC,qEAAqE;QAEnF,QAAQ,iBAAiB,EAAE,CAAC;YAC1B,KAAK,UAAU;gBACb,OAAO,SAAS,CAAC,CAAC,4BAA4B;YAEhD,KAAK,UAAU;gBACb,OAAO,UAAU,CAAC,CAAC,eAAe;YAEpC,KAAK,eAAe;gBAClB,OAAO,OAAO,CAAC,CAAC,oCAAoC;YAEtD,KAAK,SAAS;gBACZ,OAAO,SAAS,CAAC,CAAC,sBAAsB;YAE1C,KAAK,SAAS;gBACZ,mEAAmE;gBACnE,OAAO,SAAS,CAAC;YAEnB,KAAK,OAAO,CAAC;YACb;gBACE,OAAO,OAAO,CAAC,CAAC,gBAAgB;QACpC,CAAC;IACH,CAAC,CAAC;AACJ,CAAC"}
@@ -0,0 +1,74 @@
1
+ /**
2
+ * Loopman Context Enrichment Node for LangGraph
3
+ *
4
+ * This node fetches validation guidelines and historical decision context
5
+ * from Loopman API and adds them to the graph state.
6
+ */
7
+ /**
8
+ * Configuration for the Loopman context enrichment node
9
+ */
10
+ export interface LoopmanContextNodeConfig {
11
+ /** Loopman API key for authentication */
12
+ apiKey: string;
13
+ /** Workflow identifier */
14
+ workflowId: string;
15
+ /** Execution identifier (auto-generated if not provided) */
16
+ executionId?: string;
17
+ /** Category to filter guidelines (optional, use "none" for all) */
18
+ category?: string;
19
+ /** Whether to fetch guidelines (default: true) */
20
+ includeGuidelines?: boolean;
21
+ /** Whether to fetch decision history (default: true) */
22
+ includeDecisionHistory?: boolean;
23
+ /** Enable debug logging */
24
+ debug?: boolean;
25
+ }
26
+ /**
27
+ * Factory function to create a Loopman context enrichment node
28
+ *
29
+ * This node fetches validation guidelines and historical decision context
30
+ * from Loopman API and adds them to the graph state. This enriched context
31
+ * can then be used by agents to make better-informed decisions.
32
+ *
33
+ * **Works with any state**: This node only adds `guidelines` and `decisionContext`
34
+ * to your state. It doesn't require `LoopmanGraphState` - you can use your own
35
+ * custom state with any fields you want!
36
+ *
37
+ * @example With LoopmanGraphState
38
+ * ```typescript
39
+ * import { createLoopmanContextNode, LoopmanGraphState } from "loopman-langchain-sdk";
40
+ *
41
+ * const contextNode = createLoopmanContextNode({
42
+ * apiKey: process.env.LOOPMAN_API_KEY!,
43
+ * workflowId: "my-workflow",
44
+ * category: "email", // Optional category filter
45
+ * });
46
+ *
47
+ * const workflow = new StateGraph(LoopmanGraphState)
48
+ * .addNode("load_context", contextNode)
49
+ * .addNode("agent", agentNode)
50
+ * .addEdge(START, "load_context")
51
+ * .addEdge("load_context", "agent");
52
+ * ```
53
+ *
54
+ * @example With custom state
55
+ * ```typescript
56
+ * const MyCustomState = Annotation.Root({
57
+ * messages: Annotation<BaseMessage[]>({ ... }),
58
+ * myCustomField: Annotation<string>({ ... }),
59
+ * guidelines: Annotation<LoopmanGuideline[]>({ ... }), // Add Loopman fields
60
+ * decisionContext: Annotation<LoopmanDecision[]>({ ... }), // to your state
61
+ * });
62
+ *
63
+ * const contextNode = createLoopmanContextNode({
64
+ * apiKey: process.env.LOOPMAN_API_KEY!,
65
+ * workflowId: "my-workflow",
66
+ * });
67
+ *
68
+ * const workflow = new StateGraph(MyCustomState)
69
+ * .addNode("load_context", contextNode) // Works with custom state!
70
+ * .addNode("agent", agentNode);
71
+ * ```
72
+ */
73
+ export declare function createLoopmanContextNode(config: LoopmanContextNodeConfig): (state: any) => Promise<any>;
74
+ //# sourceMappingURL=loopman-context-node.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"loopman-context-node.d.ts","sourceRoot":"","sources":["../../src/langgraph/loopman-context-node.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAKH;;GAEG;AACH,MAAM,WAAW,wBAAwB;IACvC,yCAAyC;IACzC,MAAM,EAAE,MAAM,CAAC;IACf,0BAA0B;IAC1B,UAAU,EAAE,MAAM,CAAC;IACnB,4DAA4D;IAC5D,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,mEAAmE;IACnE,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,kDAAkD;IAClD,iBAAiB,CAAC,EAAE,OAAO,CAAC;IAC5B,wDAAwD;IACxD,sBAAsB,CAAC,EAAE,OAAO,CAAC;IACjC,2BAA2B;IAC3B,KAAK,CAAC,EAAE,OAAO,CAAC;CACjB;AAED;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA8CG;AACH,wBAAgB,wBAAwB,CAAC,MAAM,EAAE,wBAAwB,IAczD,OAAO,GAAG,KAAG,OAAO,CAAC,GAAG,CAAC,CAiHxC"}
@@ -0,0 +1,143 @@
1
+ /**
2
+ * Loopman Context Enrichment Node for LangGraph
3
+ *
4
+ * This node fetches validation guidelines and historical decision context
5
+ * from Loopman API and adds them to the graph state.
6
+ */
7
+ import { LoopmanService } from "../services/loopman.service";
8
+ /**
9
+ * Factory function to create a Loopman context enrichment node
10
+ *
11
+ * This node fetches validation guidelines and historical decision context
12
+ * from Loopman API and adds them to the graph state. This enriched context
13
+ * can then be used by agents to make better-informed decisions.
14
+ *
15
+ * **Works with any state**: This node only adds `guidelines` and `decisionContext`
16
+ * to your state. It doesn't require `LoopmanGraphState` - you can use your own
17
+ * custom state with any fields you want!
18
+ *
19
+ * @example With LoopmanGraphState
20
+ * ```typescript
21
+ * import { createLoopmanContextNode, LoopmanGraphState } from "loopman-langchain-sdk";
22
+ *
23
+ * const contextNode = createLoopmanContextNode({
24
+ * apiKey: process.env.LOOPMAN_API_KEY!,
25
+ * workflowId: "my-workflow",
26
+ * category: "email", // Optional category filter
27
+ * });
28
+ *
29
+ * const workflow = new StateGraph(LoopmanGraphState)
30
+ * .addNode("load_context", contextNode)
31
+ * .addNode("agent", agentNode)
32
+ * .addEdge(START, "load_context")
33
+ * .addEdge("load_context", "agent");
34
+ * ```
35
+ *
36
+ * @example With custom state
37
+ * ```typescript
38
+ * const MyCustomState = Annotation.Root({
39
+ * messages: Annotation<BaseMessage[]>({ ... }),
40
+ * myCustomField: Annotation<string>({ ... }),
41
+ * guidelines: Annotation<LoopmanGuideline[]>({ ... }), // Add Loopman fields
42
+ * decisionContext: Annotation<LoopmanDecision[]>({ ... }), // to your state
43
+ * });
44
+ *
45
+ * const contextNode = createLoopmanContextNode({
46
+ * apiKey: process.env.LOOPMAN_API_KEY!,
47
+ * workflowId: "my-workflow",
48
+ * });
49
+ *
50
+ * const workflow = new StateGraph(MyCustomState)
51
+ * .addNode("load_context", contextNode) // Works with custom state!
52
+ * .addNode("agent", agentNode);
53
+ * ```
54
+ */
55
+ export function createLoopmanContextNode(config) {
56
+ const loopmanService = new LoopmanService({
57
+ apiKey: config.apiKey,
58
+ workflowId: config.workflowId,
59
+ executionId: config.executionId || `exec-${Date.now()}`,
60
+ debug: config.debug,
61
+ });
62
+ const includeGuidelines = config.includeGuidelines ?? true;
63
+ const includeDecisionHistory = config.includeDecisionHistory ?? true;
64
+ const debug = config.debug ?? false;
65
+ const logger = loopmanService.logger;
66
+ const executionId = config.executionId || `exec-${Date.now()}`;
67
+ return async (state) => {
68
+ logger.debug("[LoopmanContextNode] Loading context...");
69
+ const updates = {};
70
+ // Fetch guidelines if requested
71
+ if (includeGuidelines) {
72
+ try {
73
+ logger.debug(`[LoopmanContextNode] Fetching guidelines via API (category: ${config.category || "all"})`);
74
+ const response = await loopmanService.getGuidelines(config.category || undefined);
75
+ // Convert API response to graph state format (lowercase severity)
76
+ updates.guidelines = response.guidelines.map((g) => ({
77
+ ruleId: g.ruleId,
78
+ description: g.description,
79
+ category: g.category,
80
+ severity: g.severity.toLowerCase(),
81
+ }));
82
+ logger.debug(`[LoopmanContextNode] Loaded ${response.guidelines.length} guideline(s) via API`, {
83
+ severities: response.guidelines.length > 0
84
+ ? response.guidelines.map((g) => g.severity)
85
+ : [],
86
+ });
87
+ }
88
+ catch (error) {
89
+ if (debug) {
90
+ logger.error(`[LoopmanContextNode] Failed to fetch guidelines via API: ${error.message}`);
91
+ }
92
+ // Continue execution with empty guidelines
93
+ updates.guidelines = [];
94
+ }
95
+ }
96
+ // Fetch decision context if requested
97
+ if (includeDecisionHistory) {
98
+ // Check if state contains a taskId - if so, we need to fetch from the task directly
99
+ const taskId = state.taskId;
100
+ if (taskId) {
101
+ logger.debug(`[LoopmanContextNode] TaskId found in state (${taskId}) - fetching task-specific decisions`);
102
+ try {
103
+ const task = await loopmanService.getTask(taskId);
104
+ const response = loopmanService.getDecisionContextFromTask(task);
105
+ updates.decisionContext = response.decisions;
106
+ logger.debug(`[LoopmanContextNode] Loaded ${response.decisions.length} decision(s) from task ${taskId}`, {
107
+ latest: response.decisions.length > 0
108
+ ? response.decisions[response.decisions.length - 1]
109
+ : null,
110
+ });
111
+ }
112
+ catch (error) {
113
+ if (debug) {
114
+ logger.error(`[LoopmanContextNode] Failed to fetch decisions from task: ${error.message}`);
115
+ }
116
+ updates.decisionContext = [];
117
+ }
118
+ }
119
+ else {
120
+ // No taskId: fetch execution-level decisions
121
+ try {
122
+ logger.debug(`[LoopmanContextNode] Fetching execution-level decisions (executionId: ${executionId})`);
123
+ const response = await loopmanService.getDecisionContext(executionId);
124
+ updates.decisionContext = response.decisions;
125
+ logger.debug(`[LoopmanContextNode] Loaded ${response.decisions.length} decision(s) for execution`, {
126
+ latest: response.decisions.length > 0
127
+ ? response.decisions[response.decisions.length - 1]
128
+ : null,
129
+ });
130
+ }
131
+ catch (error) {
132
+ if (debug) {
133
+ logger.error(`[LoopmanContextNode] Failed to fetch decision context: ${error.message}`);
134
+ }
135
+ updates.decisionContext = [];
136
+ }
137
+ }
138
+ }
139
+ logger.debug("[LoopmanContextNode] Context loaded successfully");
140
+ return updates;
141
+ };
142
+ }
143
+ //# sourceMappingURL=loopman-context-node.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"loopman-context-node.js","sourceRoot":"","sources":["../../src/langgraph/loopman-context-node.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,119 @@
1
+ /**
2
+ * Loopman Validation Node for LangGraph
3
+ *
4
+ * This node handles human-in-the-loop validation by:
5
+ * 1. Extracting tool calls from agent messages
6
+ * 2. Creating validation tasks in Loopman
7
+ * 3. Polling for human decisions
8
+ * 4. Enriching state with guidelines and decision context
9
+ */
10
+ import { TaskInformation } from "../types";
11
+ /**
12
+ * Configuration for Loopman validation node
13
+ */
14
+ export interface LoopmanValidationNodeConfig {
15
+ /** Loopman API key for authentication */
16
+ apiKey: string;
17
+ /** Workflow identifier */
18
+ workflowId: string;
19
+ /** Execution identifier (auto-generated if not provided) */
20
+ executionId?: string;
21
+ /** Category to filter guidelines (optional) */
22
+ category?: string;
23
+ /** Polling timeout in milliseconds (default: 5 minutes) */
24
+ timeout?: number;
25
+ /** Polling interval in milliseconds (default: 5 seconds) */
26
+ pollingInterval?: number;
27
+ /** Enable debug logging */
28
+ debug?: boolean;
29
+ /** Custom title for the task (default: "Tool validation") */
30
+ taskTitle?: string;
31
+ /** Custom message/description to display when creating task */
32
+ taskMessage?: string;
33
+ /** Custom function to extract tool call from message */
34
+ extractToolCall?: (messages: any[]) => {
35
+ name: string;
36
+ args: any;
37
+ id: string;
38
+ } | null;
39
+ /** Business context to include in the task (or function to extract from state) */
40
+ businessContext?: string | ((state: any) => string);
41
+ /** Proposed decision to include in the task (or function to extract from state) */
42
+ proposedDecision?: string | ((state: any) => string);
43
+ /** Decision reasoning to include in the task (or function to extract from state) */
44
+ decisionReasoning?: string | ((state: any) => string);
45
+ /** Whether to include full state in task information (default: false) */
46
+ includeFullState?: boolean;
47
+ /** Custom function to format state for task information (if not provided, uses JSON.stringify) */
48
+ formatState?: (state: any) => TaskInformation[];
49
+ }
50
+ /**
51
+ * Creates a Loopman validation node for LangGraph
52
+ *
53
+ * This node:
54
+ * 1. Extracts the tool call from the last AI message
55
+ * 2. Creates a Loopman task for human validation
56
+ * 3. Polls until human decision is received
57
+ * 4. Automatically enriches state with guidelines and decisionContext
58
+ *
59
+ * **Works with any state**: This node reads `messages` and `requiresValidation`
60
+ * from the state, and updates it with `loopmanTaskId`, `loopmanTaskStatus`,
61
+ * `guidelines`, and `decisionContext`. You can use your own custom state schema!
62
+ *
63
+ * **Context Enrichment**: After validation, this node automatically fetches
64
+ * and adds `guidelines` and `decisionContext` to the state, making them
65
+ * available for the agent on retry (NEEDS_CHANGES) or subsequent executions.
66
+ *
67
+ * **State Inclusion**: You can include the full agent state in the task information
68
+ * by setting `includeFullState: true`. This helps human reviewers understand the
69
+ * complete context of the decision. You can also provide custom formatters.
70
+ *
71
+ * **Decision Context**: You can provide business context, proposed decisions, and
72
+ * reasoning either as static strings or as functions that extract from the state.
73
+ *
74
+ * @example Basic usage with LoopmanGraphState
75
+ * ```typescript
76
+ * import { createLoopmanValidationNode, LoopmanGraphState } from "loopman-langchain-sdk";
77
+ *
78
+ * const loopmanNode = createLoopmanValidationNode({
79
+ * apiKey: process.env.LOOPMAN_API_KEY!,
80
+ * workflowId: "my-workflow",
81
+ * executionId: `exec-${Date.now()}`,
82
+ * timeout: 5 * 60 * 1000,
83
+ * pollingInterval: 5000,
84
+ * debug: true,
85
+ * taskTitle: "Email Validation", // Custom title
86
+ * taskMessage: "Please review this action" // Custom description
87
+ * });
88
+ *
89
+ * workflow.addNode("loopman_validation", loopmanNode);
90
+ * ```
91
+ *
92
+ * @example With full state and decision context
93
+ * ```typescript
94
+ * const loopmanNode = createLoopmanValidationNode({
95
+ * apiKey: process.env.LOOPMAN_API_KEY!,
96
+ * workflowId: "my-workflow",
97
+ * includeFullState: true, // Include all state in task information
98
+ * businessContext: (state) => `Processing user request: ${state.userQuery}`,
99
+ * proposedDecision: (state) => `Execute ${state.currentAction} on ${state.targetResource}`,
100
+ * decisionReasoning: (state) => state.reasoning || "No specific reasoning provided",
101
+ * });
102
+ * ```
103
+ *
104
+ * @example With custom state formatter
105
+ * ```typescript
106
+ * const loopmanNode = createLoopmanValidationNode({
107
+ * apiKey: process.env.LOOPMAN_API_KEY!,
108
+ * workflowId: "my-workflow",
109
+ * includeFullState: true,
110
+ * formatState: (state) => [
111
+ * { type: "text", label: "User", value: state.userId },
112
+ * { type: "text", label: "Action", value: state.action },
113
+ * { type: "bulletPoints", label: "Parameters", value: Object.keys(state.params) },
114
+ * ],
115
+ * });
116
+ * ```
117
+ */
118
+ export declare function createLoopmanValidationNode(config: LoopmanValidationNodeConfig): (state: any) => Promise<any>;
119
+ //# sourceMappingURL=loopman-validation-node.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"loopman-validation-node.d.ts","sourceRoot":"","sources":["../../src/langgraph/loopman-validation-node.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AAIH,OAAO,EAAE,eAAe,EAAE,MAAM,UAAU,CAAC;AAG3C;;GAEG;AACH,MAAM,WAAW,2BAA2B;IAC1C,yCAAyC;IACzC,MAAM,EAAE,MAAM,CAAC;IACf,0BAA0B;IAC1B,UAAU,EAAE,MAAM,CAAC;IACnB,4DAA4D;IAC5D,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,+CAA+C;IAC/C,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,2DAA2D;IAC3D,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,4DAA4D;IAC5D,eAAe,CAAC,EAAE,MAAM,CAAC;IACzB,2BAA2B;IAC3B,KAAK,CAAC,EAAE,OAAO,CAAC;IAChB,6DAA6D;IAC7D,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,+DAA+D;IAC/D,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,wDAAwD;IACxD,eAAe,CAAC,EAAE,CAAC,QAAQ,EAAE,GAAG,EAAE,KAAK;QACrC,IAAI,EAAE,MAAM,CAAC;QACb,IAAI,EAAE,GAAG,CAAC;QACV,EAAE,EAAE,MAAM,CAAC;KACZ,GAAG,IAAI,CAAC;IACT,kFAAkF;IAClF,eAAe,CAAC,EAAE,MAAM,GAAG,CAAC,CAAC,KAAK,EAAE,GAAG,KAAK,MAAM,CAAC,CAAC;IACpD,mFAAmF;IACnF,gBAAgB,CAAC,EAAE,MAAM,GAAG,CAAC,CAAC,KAAK,EAAE,GAAG,KAAK,MAAM,CAAC,CAAC;IACrD,oFAAoF;IACpF,iBAAiB,CAAC,EAAE,MAAM,GAAG,CAAC,CAAC,KAAK,EAAE,GAAG,KAAK,MAAM,CAAC,CAAC;IACtD,yEAAyE;IACzE,gBAAgB,CAAC,EAAE,OAAO,CAAC;IAC3B,kGAAkG;IAClG,WAAW,CAAC,EAAE,CAAC,KAAK,EAAE,GAAG,KAAK,eAAe,EAAE,CAAC;CACjD;AAED;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAmEG;AACH,wBAAgB,2BAA2B,CACzC,MAAM,EAAE,2BAA2B,IAerB,OAAO,GAAG,kBAmNzB"}