@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.
- package/README.md +78 -5
- package/dist/agents/loopman-agent.d.ts.map +1 -1
- package/dist/agents/loopman-agent.js +51 -92
- package/dist/agents/loopman-agent.js.map +1 -1
- package/dist/client/loopman-api.d.ts +19 -64
- package/dist/client/loopman-api.d.ts.map +1 -1
- package/dist/client/loopman-api.js +85 -248
- package/dist/client/loopman-api.js.map +1 -1
- package/dist/helpers/prompt-orchestrator.js +17 -17
- package/dist/helpers/prompt-orchestrator.js.map +1 -1
- package/dist/helpers/template-generator-static.d.ts +27 -0
- package/dist/helpers/template-generator-static.d.ts.map +1 -0
- package/dist/helpers/template-generator-static.js +52 -0
- package/dist/helpers/template-generator-static.js.map +1 -0
- package/dist/helpers/template-generator.d.ts +50 -0
- package/dist/helpers/template-generator.d.ts.map +1 -0
- package/dist/helpers/template-generator.js +85 -0
- package/dist/helpers/template-generator.js.map +1 -0
- package/dist/index.d.ts +6 -1
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +6 -0
- package/dist/index.js.map +1 -1
- package/dist/langgraph/helpers.d.ts +171 -0
- package/dist/langgraph/helpers.d.ts.map +1 -0
- package/dist/langgraph/helpers.js +216 -0
- package/dist/langgraph/helpers.js.map +1 -0
- package/dist/langgraph/index.d.ts +16 -0
- package/dist/langgraph/index.d.ts.map +1 -0
- package/dist/langgraph/index.js +17 -0
- package/dist/langgraph/index.js.map +1 -0
- package/dist/langgraph/loopman-conditional-edge.d.ts +58 -0
- package/dist/langgraph/loopman-conditional-edge.d.ts.map +1 -0
- package/dist/langgraph/loopman-conditional-edge.js +77 -0
- package/dist/langgraph/loopman-conditional-edge.js.map +1 -0
- package/dist/langgraph/loopman-context-node.d.ts +74 -0
- package/dist/langgraph/loopman-context-node.d.ts.map +1 -0
- package/dist/langgraph/loopman-context-node.js +143 -0
- package/dist/langgraph/loopman-context-node.js.map +1 -0
- package/dist/langgraph/loopman-validation-node.d.ts +119 -0
- package/dist/langgraph/loopman-validation-node.d.ts.map +1 -0
- package/dist/langgraph/loopman-validation-node.js +420 -0
- package/dist/langgraph/loopman-validation-node.js.map +1 -0
- package/dist/langgraph/types.d.ts +75 -0
- package/dist/langgraph/types.d.ts.map +1 -0
- package/dist/langgraph/types.js +74 -0
- package/dist/langgraph/types.js.map +1 -0
- package/dist/loopman-agent-wrapper.d.ts +18 -0
- package/dist/loopman-agent-wrapper.d.ts.map +1 -1
- package/dist/loopman-agent-wrapper.js +31 -21
- package/dist/loopman-agent-wrapper.js.map +1 -1
- package/dist/loopman-middleware.d.ts +0 -5
- package/dist/loopman-middleware.d.ts.map +1 -1
- package/dist/loopman-middleware.js +22 -23
- package/dist/loopman-middleware.js.map +1 -1
- package/dist/mcp/loopman-mcp-client.d.ts.map +1 -1
- package/dist/mcp/loopman-mcp-client.js +5 -0
- package/dist/mcp/loopman-mcp-client.js.map +1 -1
- package/dist/mcp/tool-registry.d.ts +7 -1
- package/dist/mcp/tool-registry.d.ts.map +1 -1
- package/dist/mcp/tool-registry.js +23 -16
- package/dist/mcp/tool-registry.js.map +1 -1
- package/dist/services/logger.service.d.ts.map +1 -1
- package/dist/services/logger.service.js +4 -12
- package/dist/services/logger.service.js.map +1 -1
- package/dist/services/loopman.service.d.ts +25 -11
- package/dist/services/loopman.service.d.ts.map +1 -1
- package/dist/services/loopman.service.js +74 -45
- package/dist/services/loopman.service.js.map +1 -1
- package/dist/services/polling.service.d.ts +7 -3
- package/dist/services/polling.service.d.ts.map +1 -1
- package/dist/services/polling.service.js +61 -47
- package/dist/services/polling.service.js.map +1 -1
- package/dist/templates.json +20 -0
- package/dist/types.d.ts +9 -35
- package/dist/types.d.ts.map +1 -1
- package/dist/types.js.map +1 -1
- package/examples/README.md +346 -0
- package/examples/templates/README.md +285 -0
- package/examples/templates/langchain-full-review/.env.example +3 -0
- package/examples/templates/langchain-full-review/README.md +165 -0
- package/examples/templates/langchain-full-review/index.ts +54 -0
- package/examples/templates/langchain-full-review/package.json +29 -0
- package/examples/templates/langchain-full-review/tsconfig.json +22 -0
- package/examples/templates/langchain-tool-validation/.env.example +3 -0
- package/examples/templates/langchain-tool-validation/README.md +137 -0
- package/examples/templates/langchain-tool-validation/index.ts +65 -0
- package/examples/templates/langchain-tool-validation/package.json +29 -0
- package/examples/templates/langchain-tool-validation/tsconfig.json +22 -0
- package/examples/templates/langgraph-hello-world/.env.example +3 -0
- package/examples/templates/langgraph-hello-world/README.md +71 -0
- package/examples/templates/langgraph-hello-world/index.ts +147 -0
- package/examples/templates/langgraph-hello-world/package.json +27 -0
- package/examples/templates/langgraph-hello-world/tsconfig.json +22 -0
- package/package.json +12 -7
|
@@ -0,0 +1,420 @@
|
|
|
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
|
+
* **State Inclusion**: You can include the full agent state in the task information
|
|
31
|
+
* by setting `includeFullState: true`. This helps human reviewers understand the
|
|
32
|
+
* complete context of the decision. You can also provide custom formatters.
|
|
33
|
+
*
|
|
34
|
+
* **Decision Context**: You can provide business context, proposed decisions, and
|
|
35
|
+
* reasoning either as static strings or as functions that extract from the state.
|
|
36
|
+
*
|
|
37
|
+
* @example Basic usage with LoopmanGraphState
|
|
38
|
+
* ```typescript
|
|
39
|
+
* import { createLoopmanValidationNode, LoopmanGraphState } from "loopman-langchain-sdk";
|
|
40
|
+
*
|
|
41
|
+
* const loopmanNode = createLoopmanValidationNode({
|
|
42
|
+
* apiKey: process.env.LOOPMAN_API_KEY!,
|
|
43
|
+
* workflowId: "my-workflow",
|
|
44
|
+
* executionId: `exec-${Date.now()}`,
|
|
45
|
+
* timeout: 5 * 60 * 1000,
|
|
46
|
+
* pollingInterval: 5000,
|
|
47
|
+
* debug: true,
|
|
48
|
+
* taskTitle: "Email Validation", // Custom title
|
|
49
|
+
* taskMessage: "Please review this action" // Custom description
|
|
50
|
+
* });
|
|
51
|
+
*
|
|
52
|
+
* workflow.addNode("loopman_validation", loopmanNode);
|
|
53
|
+
* ```
|
|
54
|
+
*
|
|
55
|
+
* @example With full state and decision context
|
|
56
|
+
* ```typescript
|
|
57
|
+
* const loopmanNode = createLoopmanValidationNode({
|
|
58
|
+
* apiKey: process.env.LOOPMAN_API_KEY!,
|
|
59
|
+
* workflowId: "my-workflow",
|
|
60
|
+
* includeFullState: true, // Include all state in task information
|
|
61
|
+
* businessContext: (state) => `Processing user request: ${state.userQuery}`,
|
|
62
|
+
* proposedDecision: (state) => `Execute ${state.currentAction} on ${state.targetResource}`,
|
|
63
|
+
* decisionReasoning: (state) => state.reasoning || "No specific reasoning provided",
|
|
64
|
+
* });
|
|
65
|
+
* ```
|
|
66
|
+
*
|
|
67
|
+
* @example With custom state formatter
|
|
68
|
+
* ```typescript
|
|
69
|
+
* const loopmanNode = createLoopmanValidationNode({
|
|
70
|
+
* apiKey: process.env.LOOPMAN_API_KEY!,
|
|
71
|
+
* workflowId: "my-workflow",
|
|
72
|
+
* includeFullState: true,
|
|
73
|
+
* formatState: (state) => [
|
|
74
|
+
* { type: "text", label: "User", value: state.userId },
|
|
75
|
+
* { type: "text", label: "Action", value: state.action },
|
|
76
|
+
* { type: "bulletPoints", label: "Parameters", value: Object.keys(state.params) },
|
|
77
|
+
* ],
|
|
78
|
+
* });
|
|
79
|
+
* ```
|
|
80
|
+
*/
|
|
81
|
+
export function createLoopmanValidationNode(config) {
|
|
82
|
+
// Generate executionId once for this validation node instance
|
|
83
|
+
const executionId = config.executionId || `exec-${Date.now()}`;
|
|
84
|
+
// Create LoopmanService instance with the provided configuration
|
|
85
|
+
const loopmanService = new LoopmanService({
|
|
86
|
+
apiKey: config.apiKey,
|
|
87
|
+
workflowId: config.workflowId,
|
|
88
|
+
executionId: executionId,
|
|
89
|
+
timeout: config.timeout,
|
|
90
|
+
pollingInterval: config.pollingInterval,
|
|
91
|
+
debug: config.debug,
|
|
92
|
+
});
|
|
93
|
+
return async (state) => {
|
|
94
|
+
const { messages, requiresValidation, loopmanTaskId } = state;
|
|
95
|
+
const { debug } = config;
|
|
96
|
+
const logger = loopmanService.logger;
|
|
97
|
+
// Skip if validation not required
|
|
98
|
+
if (!requiresValidation) {
|
|
99
|
+
logger.debug("[LoopmanNode] Validation not required, skipping");
|
|
100
|
+
return {};
|
|
101
|
+
}
|
|
102
|
+
// Extract tool call from last message
|
|
103
|
+
const lastMessage = messages[messages.length - 1];
|
|
104
|
+
const toolCall = config.extractToolCall
|
|
105
|
+
? config.extractToolCall(messages)
|
|
106
|
+
: extractDefaultToolCall(lastMessage);
|
|
107
|
+
if (!toolCall) {
|
|
108
|
+
logger.warn("[LoopmanNode] No tool call found, skipping");
|
|
109
|
+
return { requiresValidation: false };
|
|
110
|
+
}
|
|
111
|
+
// Step 1: Check if we're retrying an existing task (NEEDS_CHANGES scenario)
|
|
112
|
+
const isRetry = !!loopmanTaskId;
|
|
113
|
+
if (isRetry) {
|
|
114
|
+
logger.debug("[LoopmanNode] Updating existing validation task", {
|
|
115
|
+
taskId: loopmanTaskId,
|
|
116
|
+
tool: toolCall.name,
|
|
117
|
+
args: toolCall.args,
|
|
118
|
+
});
|
|
119
|
+
}
|
|
120
|
+
else {
|
|
121
|
+
logger.debug("[LoopmanNode] Creating validation task", {
|
|
122
|
+
tool: toolCall.name,
|
|
123
|
+
args: toolCall.args,
|
|
124
|
+
});
|
|
125
|
+
}
|
|
126
|
+
// Step 2: Create or update task in Loopman
|
|
127
|
+
const taskTitle = config.taskTitle || "Tool validation";
|
|
128
|
+
const taskMessage = config.taskMessage || `Validation required for tool: ${toolCall.name}`;
|
|
129
|
+
// Extract businessContext, proposedDecision, and decisionReasoning
|
|
130
|
+
const businessContext = typeof config.businessContext === "function"
|
|
131
|
+
? config.businessContext(state)
|
|
132
|
+
: config.businessContext;
|
|
133
|
+
const proposedDecision = typeof config.proposedDecision === "function"
|
|
134
|
+
? config.proposedDecision(state)
|
|
135
|
+
: config.proposedDecision;
|
|
136
|
+
const decisionReasoning = typeof config.decisionReasoning === "function"
|
|
137
|
+
? config.decisionReasoning(state)
|
|
138
|
+
: config.decisionReasoning;
|
|
139
|
+
// Prepare additional information from state if configured
|
|
140
|
+
let additionalInformation;
|
|
141
|
+
if (config.includeFullState) {
|
|
142
|
+
if (config.formatState) {
|
|
143
|
+
additionalInformation = config.formatState(state);
|
|
144
|
+
}
|
|
145
|
+
else {
|
|
146
|
+
additionalInformation = convertStateToInformation(state);
|
|
147
|
+
}
|
|
148
|
+
logger.debug("[LoopmanNode] Including full state in task information", {
|
|
149
|
+
informationCount: additionalInformation.length,
|
|
150
|
+
});
|
|
151
|
+
}
|
|
152
|
+
try {
|
|
153
|
+
const task = await loopmanService.createTaskForValidation(toolCall.name, toolCall.args, taskMessage, toolCall.id, businessContext, undefined, // parentTaskId
|
|
154
|
+
proposedDecision, decisionReasoning, isRetry ? loopmanTaskId : undefined, // existingTaskId for retry
|
|
155
|
+
additionalInformation, // Additional information from state
|
|
156
|
+
taskTitle // Custom title
|
|
157
|
+
);
|
|
158
|
+
logger.debug("[LoopmanNode] Task created, polling for human decision", {
|
|
159
|
+
taskId: task.id,
|
|
160
|
+
});
|
|
161
|
+
// Step 2: Poll for human decision
|
|
162
|
+
const pollingResult = await loopmanService.polling.waitForDecision(loopmanService.getPollingOptions(task.id));
|
|
163
|
+
logger.debug("[LoopmanNode] Polling result", {
|
|
164
|
+
status: pollingResult.status,
|
|
165
|
+
});
|
|
166
|
+
// Step 3: Handle timeout/abort
|
|
167
|
+
if (pollingResult.status === "TIMEOUT") {
|
|
168
|
+
return {
|
|
169
|
+
loopmanTaskId: task.id,
|
|
170
|
+
loopmanTaskStatus: "TIMEOUT",
|
|
171
|
+
requiresValidation: false,
|
|
172
|
+
messages: [
|
|
173
|
+
new ToolMessage({
|
|
174
|
+
content: "Human validation timeout - task was not reviewed in time",
|
|
175
|
+
tool_call_id: toolCall.id,
|
|
176
|
+
}),
|
|
177
|
+
],
|
|
178
|
+
};
|
|
179
|
+
}
|
|
180
|
+
if (pollingResult.status === "ABORTED") {
|
|
181
|
+
return {
|
|
182
|
+
loopmanTaskId: task.id,
|
|
183
|
+
loopmanTaskStatus: "ABORTED",
|
|
184
|
+
requiresValidation: false,
|
|
185
|
+
};
|
|
186
|
+
}
|
|
187
|
+
// Step 4: Get final task with decision
|
|
188
|
+
const finalTask = await loopmanService.getTask(task.id);
|
|
189
|
+
const latestDecision = finalTask.decisions?.[0];
|
|
190
|
+
const feedback = latestDecision?.comment || null;
|
|
191
|
+
if (debug) {
|
|
192
|
+
logger.debug("[LoopmanNode] Human decision received", {
|
|
193
|
+
status: finalTask.status,
|
|
194
|
+
feedback,
|
|
195
|
+
});
|
|
196
|
+
}
|
|
197
|
+
// Step 5: Fetch enriched context only if NEEDS_CHANGES
|
|
198
|
+
// This optimizes API calls by loading guidelines and decisions only when needed
|
|
199
|
+
let contextUpdates = {};
|
|
200
|
+
if (finalTask.status === "NEEDS_CHANGES") {
|
|
201
|
+
logger.debug("[LoopmanNode] Status is NEEDS_CHANGES - loading context for retry");
|
|
202
|
+
try {
|
|
203
|
+
// Use the context node to load guidelines and decisions
|
|
204
|
+
// IMPORTANT: Use the same executionId that was used to create the task
|
|
205
|
+
const contextNode = createLoopmanContextNode({
|
|
206
|
+
apiKey: config.apiKey,
|
|
207
|
+
workflowId: config.workflowId,
|
|
208
|
+
executionId: executionId, // Use the executionId from this node instance
|
|
209
|
+
category: config.category,
|
|
210
|
+
includeGuidelines: true,
|
|
211
|
+
includeDecisionHistory: true,
|
|
212
|
+
debug,
|
|
213
|
+
});
|
|
214
|
+
// Add taskId to state so context node can fetch decisions
|
|
215
|
+
const stateWithTaskId = { ...state, taskId: finalTask.id };
|
|
216
|
+
contextUpdates = await contextNode(stateWithTaskId);
|
|
217
|
+
if (debug) {
|
|
218
|
+
const guidelinesCount = contextUpdates.guidelines?.length || 0;
|
|
219
|
+
const decisionsCount = contextUpdates.decisionContext?.length || 0;
|
|
220
|
+
logger.debug("[LoopmanNode] Context loaded", {
|
|
221
|
+
guidelinesCount,
|
|
222
|
+
decisionsCount,
|
|
223
|
+
});
|
|
224
|
+
}
|
|
225
|
+
}
|
|
226
|
+
catch (error) {
|
|
227
|
+
logger.warn(`[LoopmanNode] Failed to load context: ${error.message} (continuing without)`);
|
|
228
|
+
// Continue without context if loading fails
|
|
229
|
+
contextUpdates = {};
|
|
230
|
+
}
|
|
231
|
+
}
|
|
232
|
+
else if (debug) {
|
|
233
|
+
logger.debug(`[LoopmanNode] Status is ${finalTask.status} - skipping context loading`);
|
|
234
|
+
}
|
|
235
|
+
// Step 6: Return state update with enriched context (only if NEEDS_CHANGES)
|
|
236
|
+
return {
|
|
237
|
+
loopmanTaskId: task.id,
|
|
238
|
+
loopmanTaskStatus: finalTask.status,
|
|
239
|
+
requiresValidation: false, // Reset flag
|
|
240
|
+
...contextUpdates, // Add guidelines and decisionContext if loaded
|
|
241
|
+
messages: buildDecisionMessages(finalTask.status, feedback, toolCall.id),
|
|
242
|
+
};
|
|
243
|
+
}
|
|
244
|
+
catch (error) {
|
|
245
|
+
if (debug) {
|
|
246
|
+
logger.error("[LoopmanNode] Error during validation", error.message);
|
|
247
|
+
}
|
|
248
|
+
return {
|
|
249
|
+
loopmanTaskStatus: "ERROR",
|
|
250
|
+
requiresValidation: false,
|
|
251
|
+
messages: [
|
|
252
|
+
new ToolMessage({
|
|
253
|
+
content: `Error during validation: ${error.message}`,
|
|
254
|
+
tool_call_id: toolCall.id,
|
|
255
|
+
}),
|
|
256
|
+
],
|
|
257
|
+
};
|
|
258
|
+
}
|
|
259
|
+
};
|
|
260
|
+
}
|
|
261
|
+
// ============================================================================
|
|
262
|
+
// Helper Functions
|
|
263
|
+
// ============================================================================
|
|
264
|
+
/**
|
|
265
|
+
* Converts state to TaskInformation array for display in Loopman UI
|
|
266
|
+
* Excludes messages array and large objects to keep information readable
|
|
267
|
+
*/
|
|
268
|
+
function convertStateToInformation(state) {
|
|
269
|
+
const information = [];
|
|
270
|
+
// Add a header indicating this is the full state
|
|
271
|
+
information.push({
|
|
272
|
+
type: "text",
|
|
273
|
+
label: "Full State",
|
|
274
|
+
value: "Complete agent state snapshot",
|
|
275
|
+
});
|
|
276
|
+
// Iterate through state properties
|
|
277
|
+
for (const [key, value] of Object.entries(state)) {
|
|
278
|
+
// Skip messages array (too verbose)
|
|
279
|
+
if (key === "messages") {
|
|
280
|
+
continue;
|
|
281
|
+
}
|
|
282
|
+
// Skip null/undefined values
|
|
283
|
+
if (value === null || value === undefined) {
|
|
284
|
+
continue;
|
|
285
|
+
}
|
|
286
|
+
const label = key.charAt(0).toUpperCase() + key.slice(1).replace(/_/g, " ");
|
|
287
|
+
// Handle different value types
|
|
288
|
+
if (typeof value === "string") {
|
|
289
|
+
// Detect URLs
|
|
290
|
+
if (value.startsWith("http://") || value.startsWith("https://")) {
|
|
291
|
+
information.push({
|
|
292
|
+
type: "url",
|
|
293
|
+
label: `${label} URL`,
|
|
294
|
+
value: value,
|
|
295
|
+
});
|
|
296
|
+
}
|
|
297
|
+
else {
|
|
298
|
+
information.push({
|
|
299
|
+
type: "text",
|
|
300
|
+
label: label,
|
|
301
|
+
value: value,
|
|
302
|
+
});
|
|
303
|
+
}
|
|
304
|
+
}
|
|
305
|
+
else if (typeof value === "boolean" || typeof value === "number") {
|
|
306
|
+
information.push({
|
|
307
|
+
type: "text",
|
|
308
|
+
label: label,
|
|
309
|
+
value: String(value),
|
|
310
|
+
});
|
|
311
|
+
}
|
|
312
|
+
else if (Array.isArray(value)) {
|
|
313
|
+
// For arrays, check if they're simple values or complex objects
|
|
314
|
+
if (value.length === 0) {
|
|
315
|
+
continue; // Skip empty arrays
|
|
316
|
+
}
|
|
317
|
+
if (typeof value[0] === "string" || typeof value[0] === "number") {
|
|
318
|
+
information.push({
|
|
319
|
+
type: "bulletPoints",
|
|
320
|
+
label: label,
|
|
321
|
+
value: value.map(String),
|
|
322
|
+
});
|
|
323
|
+
}
|
|
324
|
+
else {
|
|
325
|
+
// Complex objects - stringify them
|
|
326
|
+
information.push({
|
|
327
|
+
type: "text",
|
|
328
|
+
label: label,
|
|
329
|
+
value: JSON.stringify(value, null, 2),
|
|
330
|
+
});
|
|
331
|
+
}
|
|
332
|
+
}
|
|
333
|
+
else if (typeof value === "object") {
|
|
334
|
+
// Complex objects - stringify them
|
|
335
|
+
information.push({
|
|
336
|
+
type: "text",
|
|
337
|
+
label: label,
|
|
338
|
+
value: JSON.stringify(value, null, 2),
|
|
339
|
+
});
|
|
340
|
+
}
|
|
341
|
+
}
|
|
342
|
+
return information;
|
|
343
|
+
}
|
|
344
|
+
/**
|
|
345
|
+
* Extracts tool call from a message
|
|
346
|
+
*/
|
|
347
|
+
function extractDefaultToolCall(message) {
|
|
348
|
+
if (!message)
|
|
349
|
+
return null;
|
|
350
|
+
// Handle AIMessage with tool_calls
|
|
351
|
+
if (message.tool_calls && message.tool_calls.length > 0) {
|
|
352
|
+
const tc = message.tool_calls[0];
|
|
353
|
+
return {
|
|
354
|
+
name: tc.name,
|
|
355
|
+
args: tc.args,
|
|
356
|
+
id: tc.id || `call_${Date.now()}`,
|
|
357
|
+
};
|
|
358
|
+
}
|
|
359
|
+
// Handle raw message with toolCalls
|
|
360
|
+
if (message.toolCalls && message.toolCalls.length > 0) {
|
|
361
|
+
const tc = message.toolCalls[0];
|
|
362
|
+
return {
|
|
363
|
+
name: tc.name,
|
|
364
|
+
args: tc.args,
|
|
365
|
+
id: tc.id || `call_${Date.now()}`,
|
|
366
|
+
};
|
|
367
|
+
}
|
|
368
|
+
return null;
|
|
369
|
+
}
|
|
370
|
+
/**
|
|
371
|
+
* Builds messages to add to state based on decision
|
|
372
|
+
*/
|
|
373
|
+
function buildDecisionMessages(status, feedback, toolCallId) {
|
|
374
|
+
switch (status) {
|
|
375
|
+
case "APPROVED":
|
|
376
|
+
return [
|
|
377
|
+
new ToolMessage({
|
|
378
|
+
content: feedback
|
|
379
|
+
? `Approved by human reviewer. Feedback: "${feedback}"`
|
|
380
|
+
: "Approved by human reviewer. Proceed with execution.",
|
|
381
|
+
tool_call_id: toolCallId,
|
|
382
|
+
}),
|
|
383
|
+
];
|
|
384
|
+
case "REJECTED":
|
|
385
|
+
return [
|
|
386
|
+
new ToolMessage({
|
|
387
|
+
content: feedback
|
|
388
|
+
? `Rejected by human reviewer. Reason: "${feedback}"`
|
|
389
|
+
: "Rejected by human reviewer. Action cannot be executed.",
|
|
390
|
+
tool_call_id: toolCallId,
|
|
391
|
+
}),
|
|
392
|
+
];
|
|
393
|
+
case "NEEDS_CHANGES":
|
|
394
|
+
return [
|
|
395
|
+
new ToolMessage({
|
|
396
|
+
content: feedback
|
|
397
|
+
? `Changes requested by human reviewer: "${feedback}"`
|
|
398
|
+
: "Changes requested by human reviewer. Please revise your approach.",
|
|
399
|
+
tool_call_id: toolCallId,
|
|
400
|
+
}),
|
|
401
|
+
];
|
|
402
|
+
case "TIMEOUT":
|
|
403
|
+
return [
|
|
404
|
+
new ToolMessage({
|
|
405
|
+
content: "Human validation timeout - task was not reviewed in time",
|
|
406
|
+
tool_call_id: toolCallId,
|
|
407
|
+
}),
|
|
408
|
+
];
|
|
409
|
+
case "PENDING":
|
|
410
|
+
case "ERROR":
|
|
411
|
+
default:
|
|
412
|
+
return [
|
|
413
|
+
new ToolMessage({
|
|
414
|
+
content: `Validation status: ${status}`,
|
|
415
|
+
tool_call_id: toolCallId,
|
|
416
|
+
}),
|
|
417
|
+
];
|
|
418
|
+
}
|
|
419
|
+
}
|
|
420
|
+
//# 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"}
|
|
@@ -0,0 +1,74 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Common types and state definition for LangGraph integration
|
|
3
|
+
*/
|
|
4
|
+
import { Annotation } from "@langchain/langgraph";
|
|
5
|
+
/**
|
|
6
|
+
* State definition for LangGraph with Loopman integration
|
|
7
|
+
*
|
|
8
|
+
* This state includes all fields needed for Loopman's Human-in-the-Loop
|
|
9
|
+
* validation and context enrichment features. You can also use your own
|
|
10
|
+
* custom state by including only the fields you need.
|
|
11
|
+
*
|
|
12
|
+
* @example Basic usage
|
|
13
|
+
* ```typescript
|
|
14
|
+
* const workflow = new StateGraph(LoopmanGraphState)
|
|
15
|
+
* .addNode("agent", agentNode)
|
|
16
|
+
* .addNode("validation", validationNode);
|
|
17
|
+
* ```
|
|
18
|
+
*
|
|
19
|
+
* @example Custom state
|
|
20
|
+
* ```typescript
|
|
21
|
+
* const MyState = Annotation.Root({
|
|
22
|
+
* messages: Annotation<BaseMessage[]>({ ... }),
|
|
23
|
+
* myCustomField: Annotation<string>({ ... }),
|
|
24
|
+
* // Add only Loopman fields you need:
|
|
25
|
+
* guidelines: Annotation<LoopmanGuideline[]>({ ... }),
|
|
26
|
+
* requiresValidation: Annotation<boolean>({ ... }),
|
|
27
|
+
* });
|
|
28
|
+
* ```
|
|
29
|
+
*/
|
|
30
|
+
export const LoopmanGraphState = Annotation.Root({
|
|
31
|
+
/**
|
|
32
|
+
* Messages in the conversation
|
|
33
|
+
*/
|
|
34
|
+
messages: Annotation({
|
|
35
|
+
reducer: (x, y) => x.concat(y),
|
|
36
|
+
default: () => [],
|
|
37
|
+
}),
|
|
38
|
+
/**
|
|
39
|
+
* ID of the Loopman task awaiting validation
|
|
40
|
+
*/
|
|
41
|
+
loopmanTaskId: Annotation({
|
|
42
|
+
reducer: (x, y) => y ?? x,
|
|
43
|
+
default: () => null,
|
|
44
|
+
}),
|
|
45
|
+
/**
|
|
46
|
+
* Status of the Loopman task (APPROVED, REJECTED, NEEDS_CHANGES, etc.)
|
|
47
|
+
*/
|
|
48
|
+
loopmanTaskStatus: Annotation({
|
|
49
|
+
reducer: (x, y) => y ?? x,
|
|
50
|
+
default: () => null,
|
|
51
|
+
}),
|
|
52
|
+
/**
|
|
53
|
+
* Flag indicating if the current action requires validation
|
|
54
|
+
*/
|
|
55
|
+
requiresValidation: Annotation({
|
|
56
|
+
reducer: (x, y) => y ?? x,
|
|
57
|
+
default: () => false,
|
|
58
|
+
}),
|
|
59
|
+
/**
|
|
60
|
+
* Validation guidelines for the workflow
|
|
61
|
+
*/
|
|
62
|
+
guidelines: Annotation({
|
|
63
|
+
reducer: (x, y) => y ?? x,
|
|
64
|
+
default: () => [],
|
|
65
|
+
}),
|
|
66
|
+
/**
|
|
67
|
+
* Historical decision context from previous human reviews
|
|
68
|
+
*/
|
|
69
|
+
decisionContext: Annotation({
|
|
70
|
+
reducer: (x, y) => y ?? x,
|
|
71
|
+
default: () => [],
|
|
72
|
+
}),
|
|
73
|
+
});
|
|
74
|
+
//# sourceMappingURL=types.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"types.js","sourceRoot":"","sources":["../../src/langgraph/types.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,OAAO,EAAE,UAAU,EAAE,MAAM,sBAAsB,CAAC;AAwBlD;;;;;;;;;;;;;;;;;;;;;;;;GAwBG;AACH,MAAM,CAAC,MAAM,iBAAiB,GAAG,UAAU,CAAC,IAAI,CAAC;IAC/C;;OAEG;IACH,QAAQ,EAAE,UAAU,CAAQ;QAC1B,OAAO,EAAE,CAAC,CAAC,EAAE,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC;QAC9B,OAAO,EAAE,GAAG,EAAE,CAAC,EAAE;KAClB,CAAC;IAEF;;OAEG;IACH,aAAa,EAAE,UAAU,CAAgB;QACvC,OAAO,EAAE,CAAC,CAAC,EAAE,CAAC,EAAE,EAAE,CAAC,CAAC,IAAI,CAAC;QACzB,OAAO,EAAE,GAAG,EAAE,CAAC,IAAI;KACpB,CAAC;IAEF;;OAEG;IACH,iBAAiB,EAAE,UAAU,CAAgB;QAC3C,OAAO,EAAE,CAAC,CAAC,EAAE,CAAC,EAAE,EAAE,CAAC,CAAC,IAAI,CAAC;QACzB,OAAO,EAAE,GAAG,EAAE,CAAC,IAAI;KACpB,CAAC;IAEF;;OAEG;IACH,kBAAkB,EAAE,UAAU,CAAU;QACtC,OAAO,EAAE,CAAC,CAAC,EAAE,CAAC,EAAE,EAAE,CAAC,CAAC,IAAI,CAAC;QACzB,OAAO,EAAE,GAAG,EAAE,CAAC,KAAK;KACrB,CAAC;IAEF;;OAEG;IACH,UAAU,EAAE,UAAU,CAAqB;QACzC,OAAO,EAAE,CAAC,CAAC,EAAE,CAAC,EAAE,EAAE,CAAC,CAAC,IAAI,CAAC;QACzB,OAAO,EAAE,GAAG,EAAE,CAAC,EAAE;KAClB,CAAC;IAEF;;OAEG;IACH,eAAe,EAAE,UAAU,CAAoB;QAC7C,OAAO,EAAE,CAAC,CAAC,EAAE,CAAC,EAAE,EAAE,CAAC,CAAC,IAAI,CAAC;QACzB,OAAO,EAAE,GAAG,EAAE,CAAC,EAAE;KAClB,CAAC;CACH,CAAC,CAAC"}
|
|
@@ -23,6 +23,12 @@ import { RunnableConfig } from "@langchain/core/runnables";
|
|
|
23
23
|
export declare function invokeWithRetry(agent: any, input: any, config?: RunnableConfig, options?: {
|
|
24
24
|
maxRetries?: number;
|
|
25
25
|
debug?: boolean;
|
|
26
|
+
logger?: {
|
|
27
|
+
debug: (message: string, data?: any) => void;
|
|
28
|
+
info: (message: string, data?: any) => void;
|
|
29
|
+
warn: (message: string, data?: any) => void;
|
|
30
|
+
error: (message: string, data?: any) => void;
|
|
31
|
+
};
|
|
26
32
|
}): Promise<any>;
|
|
27
33
|
/**
|
|
28
34
|
* Helper function to stream a LangChain agent with automatic retry on human feedback
|
|
@@ -52,6 +58,12 @@ export declare function invokeWithRetry(agent: any, input: any, config?: Runnabl
|
|
|
52
58
|
export declare function streamWithRetry(agent: any, input: any, config?: RunnableConfig, options?: {
|
|
53
59
|
maxRetries?: number;
|
|
54
60
|
debug?: boolean;
|
|
61
|
+
logger?: {
|
|
62
|
+
debug: (message: string, data?: any) => void;
|
|
63
|
+
info: (message: string, data?: any) => void;
|
|
64
|
+
warn: (message: string, data?: any) => void;
|
|
65
|
+
error: (message: string, data?: any) => void;
|
|
66
|
+
};
|
|
55
67
|
}): AsyncGenerator<any, void, unknown>;
|
|
56
68
|
/**
|
|
57
69
|
* DEPRECATED: Use `invokeWithRetry()` instead for more explicit control
|
|
@@ -66,5 +78,11 @@ export declare function streamWithRetry(agent: any, input: any, config?: Runnabl
|
|
|
66
78
|
export declare function createLoopmanAgent(agent: any, options?: {
|
|
67
79
|
maxRetries?: number;
|
|
68
80
|
debug?: boolean;
|
|
81
|
+
logger?: {
|
|
82
|
+
debug: (message: string, data?: any) => void;
|
|
83
|
+
info: (message: string, data?: any) => void;
|
|
84
|
+
warn: (message: string, data?: any) => void;
|
|
85
|
+
error: (message: string, data?: any) => void;
|
|
86
|
+
};
|
|
69
87
|
}): any;
|
|
70
88
|
//# sourceMappingURL=loopman-agent-wrapper.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"loopman-agent-wrapper.d.ts","sourceRoot":"","sources":["../src/loopman-agent-wrapper.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,cAAc,EAAE,MAAM,2BAA2B,CAAC;AAE3D;;;;;;;;;;;;;;;;;;;;GAoBG;AACH,wBAAsB,eAAe,CACnC,KAAK,EAAE,GAAG,EACV,KAAK,EAAE,GAAG,EACV,MAAM,CAAC,EAAE,cAAc,EACvB,OAAO,CAAC,EAAE;IACR,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,KAAK,CAAC,EAAE,OAAO,CAAC;
|
|
1
|
+
{"version":3,"file":"loopman-agent-wrapper.d.ts","sourceRoot":"","sources":["../src/loopman-agent-wrapper.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,cAAc,EAAE,MAAM,2BAA2B,CAAC;AAE3D;;;;;;;;;;;;;;;;;;;;GAoBG;AACH,wBAAsB,eAAe,CACnC,KAAK,EAAE,GAAG,EACV,KAAK,EAAE,GAAG,EACV,MAAM,CAAC,EAAE,cAAc,EACvB,OAAO,CAAC,EAAE;IACR,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,KAAK,CAAC,EAAE,OAAO,CAAC;IAChB,MAAM,CAAC,EAAE;QACP,KAAK,EAAE,CAAC,OAAO,EAAE,MAAM,EAAE,IAAI,CAAC,EAAE,GAAG,KAAK,IAAI,CAAC;QAC7C,IAAI,EAAE,CAAC,OAAO,EAAE,MAAM,EAAE,IAAI,CAAC,EAAE,GAAG,KAAK,IAAI,CAAC;QAC5C,IAAI,EAAE,CAAC,OAAO,EAAE,MAAM,EAAE,IAAI,CAAC,EAAE,GAAG,KAAK,IAAI,CAAC;QAC5C,KAAK,EAAE,CAAC,OAAO,EAAE,MAAM,EAAE,IAAI,CAAC,EAAE,GAAG,KAAK,IAAI,CAAC;KAC9C,CAAC;CACH,GACA,OAAO,CAAC,GAAG,CAAC,CA+Dd;AAED;;;;;;;;;;;;;;;;;;;;;;;;GAwBG;AACH,wBAAuB,eAAe,CACpC,KAAK,EAAE,GAAG,EACV,KAAK,EAAE,GAAG,EACV,MAAM,CAAC,EAAE,cAAc,EACvB,OAAO,CAAC,EAAE;IACR,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,KAAK,CAAC,EAAE,OAAO,CAAC;IAChB,MAAM,CAAC,EAAE;QACP,KAAK,EAAE,CAAC,OAAO,EAAE,MAAM,EAAE,IAAI,CAAC,EAAE,GAAG,KAAK,IAAI,CAAC;QAC7C,IAAI,EAAE,CAAC,OAAO,EAAE,MAAM,EAAE,IAAI,CAAC,EAAE,GAAG,KAAK,IAAI,CAAC;QAC5C,IAAI,EAAE,CAAC,OAAO,EAAE,MAAM,EAAE,IAAI,CAAC,EAAE,GAAG,KAAK,IAAI,CAAC;QAC5C,KAAK,EAAE,CAAC,OAAO,EAAE,MAAM,EAAE,IAAI,CAAC,EAAE,GAAG,KAAK,IAAI,CAAC;KAC9C,CAAC;CACH,GACA,cAAc,CAAC,GAAG,EAAE,IAAI,EAAE,OAAO,CAAC,CAkEpC;AAED;;;;;;;;;GASG;AACH,wBAAgB,kBAAkB,CAChC,KAAK,EAAE,GAAG,EACV,OAAO,CAAC,EAAE;IACR,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,KAAK,CAAC,EAAE,OAAO,CAAC;IAChB,MAAM,CAAC,EAAE;QACP,KAAK,EAAE,CAAC,OAAO,EAAE,MAAM,EAAE,IAAI,CAAC,EAAE,GAAG,KAAK,IAAI,CAAC;QAC7C,IAAI,EAAE,CAAC,OAAO,EAAE,MAAM,EAAE,IAAI,CAAC,EAAE,GAAG,KAAK,IAAI,CAAC;QAC5C,IAAI,EAAE,CAAC,OAAO,EAAE,MAAM,EAAE,IAAI,CAAC,EAAE,GAAG,KAAK,IAAI,CAAC;QAC5C,KAAK,EAAE,CAAC,OAAO,EAAE,MAAM,EAAE,IAAI,CAAC,EAAE,GAAG,KAAK,IAAI,CAAC;KAC9C,CAAC;CACH,OAcF"}
|