@loopman/langchain-sdk 1.0.9 → 1.8.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 (65) hide show
  1. package/README.md +72 -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/index.d.ts +3 -1
  12. package/dist/index.d.ts.map +1 -1
  13. package/dist/index.js +2 -0
  14. package/dist/index.js.map +1 -1
  15. package/dist/langgraph/helpers.d.ts +171 -0
  16. package/dist/langgraph/helpers.d.ts.map +1 -0
  17. package/dist/langgraph/helpers.js +216 -0
  18. package/dist/langgraph/helpers.js.map +1 -0
  19. package/dist/langgraph/index.d.ts +16 -0
  20. package/dist/langgraph/index.d.ts.map +1 -0
  21. package/dist/langgraph/index.js +17 -0
  22. package/dist/langgraph/index.js.map +1 -0
  23. package/dist/langgraph/loopman-conditional-edge.d.ts +58 -0
  24. package/dist/langgraph/loopman-conditional-edge.d.ts.map +1 -0
  25. package/dist/langgraph/loopman-conditional-edge.js +77 -0
  26. package/dist/langgraph/loopman-conditional-edge.js.map +1 -0
  27. package/dist/langgraph/loopman-context-node.d.ts +74 -0
  28. package/dist/langgraph/loopman-context-node.d.ts.map +1 -0
  29. package/dist/langgraph/loopman-context-node.js +131 -0
  30. package/dist/langgraph/loopman-context-node.js.map +1 -0
  31. package/dist/langgraph/loopman-validation-node.d.ts +89 -0
  32. package/dist/langgraph/loopman-validation-node.d.ts.map +1 -0
  33. package/dist/langgraph/loopman-validation-node.js +297 -0
  34. package/dist/langgraph/loopman-validation-node.js.map +1 -0
  35. package/dist/langgraph/types.d.ts +75 -0
  36. package/dist/langgraph/types.d.ts.map +1 -0
  37. package/dist/langgraph/types.js +74 -0
  38. package/dist/langgraph/types.js.map +1 -0
  39. package/dist/loopman-agent-wrapper.d.ts +18 -0
  40. package/dist/loopman-agent-wrapper.d.ts.map +1 -1
  41. package/dist/loopman-agent-wrapper.js +31 -21
  42. package/dist/loopman-agent-wrapper.js.map +1 -1
  43. package/dist/loopman-middleware.d.ts +0 -5
  44. package/dist/loopman-middleware.d.ts.map +1 -1
  45. package/dist/loopman-middleware.js +22 -23
  46. package/dist/loopman-middleware.js.map +1 -1
  47. package/dist/mcp/tool-registry.d.ts +7 -1
  48. package/dist/mcp/tool-registry.d.ts.map +1 -1
  49. package/dist/mcp/tool-registry.js +23 -16
  50. package/dist/mcp/tool-registry.js.map +1 -1
  51. package/dist/services/logger.service.d.ts.map +1 -1
  52. package/dist/services/logger.service.js +4 -12
  53. package/dist/services/logger.service.js.map +1 -1
  54. package/dist/services/loopman.service.d.ts +15 -10
  55. package/dist/services/loopman.service.d.ts.map +1 -1
  56. package/dist/services/loopman.service.js +49 -37
  57. package/dist/services/loopman.service.js.map +1 -1
  58. package/dist/services/polling.service.d.ts +7 -3
  59. package/dist/services/polling.service.d.ts.map +1 -1
  60. package/dist/services/polling.service.js +61 -47
  61. package/dist/services/polling.service.js.map +1 -1
  62. package/dist/types.d.ts +9 -35
  63. package/dist/types.d.ts.map +1 -1
  64. package/dist/types.js.map +1 -1
  65. package/package.json +6 -4
@@ -0,0 +1,131 @@
1
+ /**
2
+ * Loopman Context Enrichment Node for LangGraph
3
+ *
4
+ * This node fetches validation guidelines and historical decision context
5
+ * from Loopman 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 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
+ return async (state) => {
67
+ logger.debug("[LoopmanContextNode] Loading context...");
68
+ const updates = {};
69
+ // Fetch guidelines if requested
70
+ if (includeGuidelines) {
71
+ try {
72
+ logger.debug(`[LoopmanContextNode] Fetching guidelines (category: ${config.category || "all"})`);
73
+ const response = await loopmanService.getGuidelines(config.category || undefined);
74
+ // Convert API response to graph state format (lowercase severity)
75
+ updates.guidelines = response.guidelines.map((g) => ({
76
+ ruleId: g.ruleId,
77
+ description: g.description,
78
+ category: g.category,
79
+ severity: g.severity.toLowerCase(),
80
+ }));
81
+ logger.debug(`[LoopmanContextNode] Loaded ${response.guidelines.length} guideline(s)`, {
82
+ severities: response.guidelines.length > 0
83
+ ? response.guidelines.map((g) => g.severity)
84
+ : [],
85
+ });
86
+ }
87
+ catch (error) {
88
+ if (debug) {
89
+ logger.error(`[LoopmanContextNode] Failed to fetch guidelines: ${error.message}`);
90
+ }
91
+ // Continue execution with empty guidelines
92
+ updates.guidelines = [];
93
+ }
94
+ }
95
+ // Fetch decision context if requested
96
+ // Note: Decision context requires a taskId to fetch decisions from that task
97
+ // If you need decision history, pass the taskId in the state
98
+ if (includeDecisionHistory) {
99
+ try {
100
+ logger.debug(`[LoopmanContextNode] Decision history requested (executionId: ${config.executionId || "auto-generated"})`);
101
+ // Check if state contains a taskId to fetch decisions from
102
+ const taskId = state.taskId;
103
+ if (taskId) {
104
+ logger.debug(`[LoopmanContextNode] Fetching task ${taskId} to get decisions`);
105
+ const task = await loopmanService.getTask(taskId);
106
+ const response = loopmanService.getDecisionContextFromTask(task);
107
+ updates.decisionContext = response.decisions;
108
+ logger.debug(`[LoopmanContextNode] Loaded ${response.decisions.length} decision(s) from task ${taskId}`, {
109
+ latest: response.decisions.length > 0
110
+ ? response.decisions[response.decisions.length - 1]
111
+ : null,
112
+ });
113
+ }
114
+ else {
115
+ logger.debug("[LoopmanContextNode] No taskId in state - skipping decision history");
116
+ updates.decisionContext = [];
117
+ }
118
+ }
119
+ catch (error) {
120
+ if (debug) {
121
+ logger.error(`[LoopmanContextNode] Failed to fetch decision context: ${error.message}`);
122
+ }
123
+ // Continue execution with empty decision context
124
+ updates.decisionContext = [];
125
+ }
126
+ }
127
+ logger.debug("[LoopmanContextNode] Context loaded successfully");
128
+ return updates;
129
+ };
130
+ }
131
+ //# 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,89 @@
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
+ /**
11
+ * Configuration for Loopman validation node
12
+ */
13
+ export interface LoopmanValidationNodeConfig {
14
+ /** Loopman API key for authentication */
15
+ apiKey: string;
16
+ /** Workflow identifier */
17
+ workflowId: string;
18
+ /** Execution identifier (auto-generated if not provided) */
19
+ executionId?: string;
20
+ /** Category to filter guidelines (optional) */
21
+ category?: string;
22
+ /** Polling timeout in milliseconds (default: 5 minutes) */
23
+ timeout?: number;
24
+ /** Polling interval in milliseconds (default: 5 seconds) */
25
+ pollingInterval?: number;
26
+ /** Enable debug logging */
27
+ debug?: boolean;
28
+ /** Custom message to display when creating task */
29
+ taskMessage?: string;
30
+ /** Custom function to extract tool call from message */
31
+ extractToolCall?: (messages: any[]) => {
32
+ name: string;
33
+ args: any;
34
+ id: string;
35
+ } | null;
36
+ }
37
+ /**
38
+ * Creates a Loopman validation node for LangGraph
39
+ *
40
+ * This node:
41
+ * 1. Extracts the tool call from the last AI message
42
+ * 2. Creates a Loopman task for human validation
43
+ * 3. Polls until human decision is received
44
+ * 4. Automatically enriches state with guidelines and decisionContext
45
+ *
46
+ * **Works with any state**: This node reads `messages` and `requiresValidation`
47
+ * from the state, and updates it with `loopmanTaskId`, `loopmanTaskStatus`,
48
+ * `guidelines`, and `decisionContext`. You can use your own custom state schema!
49
+ *
50
+ * **Context Enrichment**: After validation, this node automatically fetches
51
+ * and adds `guidelines` and `decisionContext` to the state, making them
52
+ * available for the agent on retry (NEEDS_CHANGES) or subsequent executions.
53
+ *
54
+ * @example With LoopmanGraphState
55
+ * ```typescript
56
+ * import { createLoopmanValidationNode, LoopmanGraphState } from "loopman-langchain-sdk";
57
+ *
58
+ * const loopmanNode = createLoopmanValidationNode({
59
+ * apiKey: process.env.LOOPMAN_API_KEY!,
60
+ * workflowId: "my-workflow",
61
+ * executionId: `exec-${Date.now()}`,
62
+ * timeout: 5 * 60 * 1000,
63
+ * pollingInterval: 5000,
64
+ * debug: true,
65
+ * taskMessage: "Please review this action"
66
+ * });
67
+ *
68
+ * workflow.addNode("loopman_validation", loopmanNode);
69
+ * ```
70
+ *
71
+ * @example With custom state
72
+ * ```typescript
73
+ * const MyCustomState = Annotation.Root({
74
+ * messages: Annotation<BaseMessage[]>({ ... }),
75
+ * requiresValidation: Annotation<boolean>({ ... }),
76
+ * loopmanTaskId: Annotation<string | null>({ ... }),
77
+ * loopmanTaskStatus: Annotation<string | null>({ ... }),
78
+ * guidelines: Annotation<LoopmanGuideline[]>({ ... }),
79
+ * decisionContext: Annotation<LoopmanDecision[]>({ ... }),
80
+ * // ... your custom fields
81
+ * });
82
+ *
83
+ * const loopmanNode = createLoopmanValidationNode({ ... });
84
+ * const workflow = new StateGraph(MyCustomState)
85
+ * .addNode("validation", loopmanNode); // Works!
86
+ * ```
87
+ */
88
+ export declare function createLoopmanValidationNode(config: LoopmanValidationNodeConfig): (state: any) => Promise<any>;
89
+ //# 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;AAMH;;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,mDAAmD;IACnD,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;CACV;AAED;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAkDG;AACH,wBAAgB,2BAA2B,CACzC,MAAM,EAAE,2BAA2B,IAYrB,OAAO,GAAG,kBAkLzB"}
@@ -0,0 +1,297 @@
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 { ToolMessage } from "@langchain/core/messages";
11
+ import { LoopmanService } from "../services/loopman.service";
12
+ import { createLoopmanContextNode } from "./loopman-context-node";
13
+ /**
14
+ * Creates a Loopman validation node for LangGraph
15
+ *
16
+ * This node:
17
+ * 1. Extracts the tool call from the last AI message
18
+ * 2. Creates a Loopman task for human validation
19
+ * 3. Polls until human decision is received
20
+ * 4. Automatically enriches state with guidelines and decisionContext
21
+ *
22
+ * **Works with any state**: This node reads `messages` and `requiresValidation`
23
+ * from the state, and updates it with `loopmanTaskId`, `loopmanTaskStatus`,
24
+ * `guidelines`, and `decisionContext`. You can use your own custom state schema!
25
+ *
26
+ * **Context Enrichment**: After validation, this node automatically fetches
27
+ * and adds `guidelines` and `decisionContext` to the state, making them
28
+ * available for the agent on retry (NEEDS_CHANGES) or subsequent executions.
29
+ *
30
+ * @example With LoopmanGraphState
31
+ * ```typescript
32
+ * import { createLoopmanValidationNode, LoopmanGraphState } from "loopman-langchain-sdk";
33
+ *
34
+ * const loopmanNode = createLoopmanValidationNode({
35
+ * apiKey: process.env.LOOPMAN_API_KEY!,
36
+ * workflowId: "my-workflow",
37
+ * executionId: `exec-${Date.now()}`,
38
+ * timeout: 5 * 60 * 1000,
39
+ * pollingInterval: 5000,
40
+ * debug: true,
41
+ * taskMessage: "Please review this action"
42
+ * });
43
+ *
44
+ * workflow.addNode("loopman_validation", loopmanNode);
45
+ * ```
46
+ *
47
+ * @example With custom state
48
+ * ```typescript
49
+ * const MyCustomState = Annotation.Root({
50
+ * messages: Annotation<BaseMessage[]>({ ... }),
51
+ * requiresValidation: Annotation<boolean>({ ... }),
52
+ * loopmanTaskId: Annotation<string | null>({ ... }),
53
+ * loopmanTaskStatus: Annotation<string | null>({ ... }),
54
+ * guidelines: Annotation<LoopmanGuideline[]>({ ... }),
55
+ * decisionContext: Annotation<LoopmanDecision[]>({ ... }),
56
+ * // ... your custom fields
57
+ * });
58
+ *
59
+ * const loopmanNode = createLoopmanValidationNode({ ... });
60
+ * const workflow = new StateGraph(MyCustomState)
61
+ * .addNode("validation", loopmanNode); // Works!
62
+ * ```
63
+ */
64
+ export function createLoopmanValidationNode(config) {
65
+ // Create LoopmanService instance with the provided configuration
66
+ const loopmanService = new LoopmanService({
67
+ apiKey: config.apiKey,
68
+ workflowId: config.workflowId,
69
+ executionId: config.executionId || `exec-${Date.now()}`,
70
+ timeout: config.timeout,
71
+ pollingInterval: config.pollingInterval,
72
+ debug: config.debug,
73
+ });
74
+ return async (state) => {
75
+ const { messages, requiresValidation, loopmanTaskId } = state;
76
+ const { debug } = config;
77
+ const logger = loopmanService.logger;
78
+ // Skip if validation not required
79
+ if (!requiresValidation) {
80
+ logger.debug("[LoopmanNode] Validation not required, skipping");
81
+ return {};
82
+ }
83
+ // Extract tool call from last message
84
+ const lastMessage = messages[messages.length - 1];
85
+ const toolCall = config.extractToolCall
86
+ ? config.extractToolCall(messages)
87
+ : extractDefaultToolCall(lastMessage);
88
+ if (!toolCall) {
89
+ logger.warn("[LoopmanNode] No tool call found, skipping");
90
+ return { requiresValidation: false };
91
+ }
92
+ // Step 1: Check if we're retrying an existing task (NEEDS_CHANGES scenario)
93
+ const isRetry = !!loopmanTaskId;
94
+ if (isRetry) {
95
+ logger.debug("[LoopmanNode] Updating existing validation task", {
96
+ taskId: loopmanTaskId,
97
+ tool: toolCall.name,
98
+ args: toolCall.args,
99
+ });
100
+ }
101
+ else {
102
+ logger.debug("[LoopmanNode] Creating validation task", {
103
+ tool: toolCall.name,
104
+ args: toolCall.args,
105
+ });
106
+ }
107
+ // Step 2: Create or update task in Loopman
108
+ const taskMessage = config.taskMessage || `Validation required for tool: ${toolCall.name}`;
109
+ try {
110
+ const task = await loopmanService.createTaskForValidation(toolCall.name, toolCall.args, taskMessage, toolCall.id, undefined, // businessContext
111
+ undefined, // parentTaskId
112
+ undefined, // proposedDecision
113
+ undefined, // decisionReasoning
114
+ isRetry ? loopmanTaskId : undefined // existingTaskId for retry
115
+ );
116
+ logger.debug("[LoopmanNode] Task created, polling for human decision", {
117
+ taskId: task.id,
118
+ });
119
+ // Step 2: Poll for human decision
120
+ const pollingResult = await loopmanService.polling.waitForDecision(loopmanService.getPollingOptions(task.id));
121
+ logger.debug("[LoopmanNode] Polling result", {
122
+ status: pollingResult.status,
123
+ });
124
+ // Step 3: Handle timeout/abort
125
+ if (pollingResult.status === "TIMEOUT") {
126
+ return {
127
+ loopmanTaskId: task.id,
128
+ loopmanTaskStatus: "TIMEOUT",
129
+ requiresValidation: false,
130
+ messages: [
131
+ new ToolMessage({
132
+ content: "Human validation timeout - task was not reviewed in time",
133
+ tool_call_id: toolCall.id,
134
+ }),
135
+ ],
136
+ };
137
+ }
138
+ if (pollingResult.status === "ABORTED") {
139
+ return {
140
+ loopmanTaskId: task.id,
141
+ loopmanTaskStatus: "ABORTED",
142
+ requiresValidation: false,
143
+ };
144
+ }
145
+ // Step 4: Get final task with decision
146
+ const finalTask = await loopmanService.getTask(task.id);
147
+ const latestDecision = finalTask.decisions?.[0];
148
+ const feedback = latestDecision?.comment || null;
149
+ if (debug) {
150
+ logger.debug("[LoopmanNode] Human decision received", {
151
+ status: finalTask.status,
152
+ feedback,
153
+ });
154
+ }
155
+ // Step 5: Fetch enriched context only if NEEDS_CHANGES
156
+ // This optimizes API calls by loading guidelines and decisions only when needed
157
+ let contextUpdates = {};
158
+ if (finalTask.status === "NEEDS_CHANGES") {
159
+ logger.debug("[LoopmanNode] Status is NEEDS_CHANGES - loading context for retry");
160
+ try {
161
+ // Use the context node to load guidelines and decisions
162
+ const contextNode = createLoopmanContextNode({
163
+ apiKey: config.apiKey,
164
+ workflowId: config.workflowId,
165
+ executionId: config.executionId,
166
+ category: config.category,
167
+ includeGuidelines: true,
168
+ includeDecisionHistory: true,
169
+ debug,
170
+ });
171
+ // Add taskId to state so context node can fetch decisions
172
+ const stateWithTaskId = { ...state, taskId: finalTask.id };
173
+ contextUpdates = await contextNode(stateWithTaskId);
174
+ if (debug) {
175
+ const guidelinesCount = contextUpdates.guidelines?.length || 0;
176
+ const decisionsCount = contextUpdates.decisionContext?.length || 0;
177
+ logger.debug("[LoopmanNode] Context loaded", {
178
+ guidelinesCount,
179
+ decisionsCount,
180
+ });
181
+ }
182
+ }
183
+ catch (error) {
184
+ logger.warn(`[LoopmanNode] Failed to load context: ${error.message} (continuing without)`);
185
+ // Continue without context if loading fails
186
+ contextUpdates = {};
187
+ }
188
+ }
189
+ else if (debug) {
190
+ logger.debug(`[LoopmanNode] Status is ${finalTask.status} - skipping context loading`);
191
+ }
192
+ // Step 6: Return state update with enriched context (only if NEEDS_CHANGES)
193
+ return {
194
+ loopmanTaskId: task.id,
195
+ loopmanTaskStatus: finalTask.status,
196
+ requiresValidation: false, // Reset flag
197
+ ...contextUpdates, // Add guidelines and decisionContext if loaded
198
+ messages: buildDecisionMessages(finalTask.status, feedback, toolCall.id),
199
+ };
200
+ }
201
+ catch (error) {
202
+ if (debug) {
203
+ logger.error("[LoopmanNode] Error during validation", error.message);
204
+ }
205
+ return {
206
+ loopmanTaskStatus: "ERROR",
207
+ requiresValidation: false,
208
+ messages: [
209
+ new ToolMessage({
210
+ content: `Error during validation: ${error.message}`,
211
+ tool_call_id: toolCall.id,
212
+ }),
213
+ ],
214
+ };
215
+ }
216
+ };
217
+ }
218
+ // ============================================================================
219
+ // Helper Functions
220
+ // ============================================================================
221
+ /**
222
+ * Extracts tool call from a message
223
+ */
224
+ function extractDefaultToolCall(message) {
225
+ if (!message)
226
+ return null;
227
+ // Handle AIMessage with tool_calls
228
+ if (message.tool_calls && message.tool_calls.length > 0) {
229
+ const tc = message.tool_calls[0];
230
+ return {
231
+ name: tc.name,
232
+ args: tc.args,
233
+ id: tc.id || `call_${Date.now()}`,
234
+ };
235
+ }
236
+ // Handle raw message with toolCalls
237
+ if (message.toolCalls && message.toolCalls.length > 0) {
238
+ const tc = message.toolCalls[0];
239
+ return {
240
+ name: tc.name,
241
+ args: tc.args,
242
+ id: tc.id || `call_${Date.now()}`,
243
+ };
244
+ }
245
+ return null;
246
+ }
247
+ /**
248
+ * Builds messages to add to state based on decision
249
+ */
250
+ function buildDecisionMessages(status, feedback, toolCallId) {
251
+ switch (status) {
252
+ case "APPROVED":
253
+ return [
254
+ new ToolMessage({
255
+ content: feedback
256
+ ? `Approved by human reviewer. Feedback: "${feedback}"`
257
+ : "Approved by human reviewer. Proceed with execution.",
258
+ tool_call_id: toolCallId,
259
+ }),
260
+ ];
261
+ case "REJECTED":
262
+ return [
263
+ new ToolMessage({
264
+ content: feedback
265
+ ? `Rejected by human reviewer. Reason: "${feedback}"`
266
+ : "Rejected by human reviewer. Action cannot be executed.",
267
+ tool_call_id: toolCallId,
268
+ }),
269
+ ];
270
+ case "NEEDS_CHANGES":
271
+ return [
272
+ new ToolMessage({
273
+ content: feedback
274
+ ? `Changes requested by human reviewer: "${feedback}"`
275
+ : "Changes requested by human reviewer. Please revise your approach.",
276
+ tool_call_id: toolCallId,
277
+ }),
278
+ ];
279
+ case "TIMEOUT":
280
+ return [
281
+ new ToolMessage({
282
+ content: "Human validation timeout - task was not reviewed in time",
283
+ tool_call_id: toolCallId,
284
+ }),
285
+ ];
286
+ case "PENDING":
287
+ case "ERROR":
288
+ default:
289
+ return [
290
+ new ToolMessage({
291
+ content: `Validation status: ${status}`,
292
+ tool_call_id: toolCallId,
293
+ }),
294
+ ];
295
+ }
296
+ }
297
+ //# sourceMappingURL=loopman-validation-node.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"loopman-validation-node.js","sourceRoot":"","sources":["../../src/langgraph/loopman-validation-node.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,75 @@
1
+ /**
2
+ * Common types and state definition for LangGraph integration
3
+ */
4
+ /**
5
+ * Guideline from Loopman API
6
+ */
7
+ export interface LoopmanGuideline {
8
+ ruleId: string;
9
+ description: string;
10
+ category?: string | null;
11
+ severity: "critical" | "major" | "minor";
12
+ }
13
+ /**
14
+ * Decision from Loopman decision context
15
+ */
16
+ export interface LoopmanDecision {
17
+ date: string;
18
+ userType: "USER" | "SYSTEM";
19
+ status: "PENDING" | "APPROVED" | "REJECTED" | "NEEDS_CHANGES";
20
+ comment?: string;
21
+ firstName?: string;
22
+ lastName?: string;
23
+ }
24
+ /**
25
+ * State definition for LangGraph with Loopman integration
26
+ *
27
+ * This state includes all fields needed for Loopman's Human-in-the-Loop
28
+ * validation and context enrichment features. You can also use your own
29
+ * custom state by including only the fields you need.
30
+ *
31
+ * @example Basic usage
32
+ * ```typescript
33
+ * const workflow = new StateGraph(LoopmanGraphState)
34
+ * .addNode("agent", agentNode)
35
+ * .addNode("validation", validationNode);
36
+ * ```
37
+ *
38
+ * @example Custom state
39
+ * ```typescript
40
+ * const MyState = Annotation.Root({
41
+ * messages: Annotation<BaseMessage[]>({ ... }),
42
+ * myCustomField: Annotation<string>({ ... }),
43
+ * // Add only Loopman fields you need:
44
+ * guidelines: Annotation<LoopmanGuideline[]>({ ... }),
45
+ * requiresValidation: Annotation<boolean>({ ... }),
46
+ * });
47
+ * ```
48
+ */
49
+ export declare const LoopmanGraphState: import("@langchain/langgraph").AnnotationRoot<{
50
+ /**
51
+ * Messages in the conversation
52
+ */
53
+ messages: import("@langchain/langgraph").BinaryOperatorAggregate<any[], any[]>;
54
+ /**
55
+ * ID of the Loopman task awaiting validation
56
+ */
57
+ loopmanTaskId: import("@langchain/langgraph").BinaryOperatorAggregate<string | null, string | null>;
58
+ /**
59
+ * Status of the Loopman task (APPROVED, REJECTED, NEEDS_CHANGES, etc.)
60
+ */
61
+ loopmanTaskStatus: import("@langchain/langgraph").BinaryOperatorAggregate<string | null, string | null>;
62
+ /**
63
+ * Flag indicating if the current action requires validation
64
+ */
65
+ requiresValidation: import("@langchain/langgraph").BinaryOperatorAggregate<boolean, boolean>;
66
+ /**
67
+ * Validation guidelines for the workflow
68
+ */
69
+ guidelines: import("@langchain/langgraph").BinaryOperatorAggregate<LoopmanGuideline[], LoopmanGuideline[]>;
70
+ /**
71
+ * Historical decision context from previous human reviews
72
+ */
73
+ decisionContext: import("@langchain/langgraph").BinaryOperatorAggregate<LoopmanDecision[], LoopmanDecision[]>;
74
+ }>;
75
+ //# sourceMappingURL=types.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../src/langgraph/types.ts"],"names":[],"mappings":"AAAA;;GAEG;AAIH;;GAEG;AACH,MAAM,WAAW,gBAAgB;IAC/B,MAAM,EAAE,MAAM,CAAC;IACf,WAAW,EAAE,MAAM,CAAC;IACpB,QAAQ,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IACzB,QAAQ,EAAE,UAAU,GAAG,OAAO,GAAG,OAAO,CAAC;CAC1C;AAED;;GAEG;AACH,MAAM,WAAW,eAAe;IAC9B,IAAI,EAAE,MAAM,CAAC;IACb,QAAQ,EAAE,MAAM,GAAG,QAAQ,CAAC;IAC5B,MAAM,EAAE,SAAS,GAAG,UAAU,GAAG,UAAU,GAAG,eAAe,CAAC;IAC9D,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,QAAQ,CAAC,EAAE,MAAM,CAAC;CACnB;AAED;;;;;;;;;;;;;;;;;;;;;;;;GAwBG;AACH,eAAO,MAAM,iBAAiB;IAC5B;;OAEG;;IAMH;;OAEG;;IAMH;;OAEG;;IAMH;;OAEG;;IAMH;;OAEG;;IAMH;;OAEG;;EAKH,CAAC"}