@loopman/langchain-sdk 1.7.0 → 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,171 @@
1
+ /**
2
+ * Helper functions for LangGraph integration with Loopman
3
+ */
4
+ import type { LoopmanDecision, LoopmanGuideline } from "./types";
5
+ /**
6
+ * Configuration for enriching system prompts
7
+ */
8
+ export interface EnrichSystemPromptOptions {
9
+ /** Whether to include guidelines (default: true) */
10
+ includeGuidelines?: boolean;
11
+ /** Whether to include decision context (default: true) */
12
+ includeDecisionContext?: boolean;
13
+ /** Maximum number of historical decisions to show (default: 3) */
14
+ maxDecisions?: number;
15
+ /** Custom header for guidelines section */
16
+ guidelinesHeader?: string;
17
+ /** Custom header for decision context section */
18
+ decisionContextHeader?: string;
19
+ }
20
+ /**
21
+ * Enriches a system prompt with Loopman guidelines and decision context
22
+ *
23
+ * This helper function automatically formats and appends validation guidelines
24
+ * and historical decision context to your agent's system prompt.
25
+ *
26
+ * **Works with any state**: This function accepts any state object and only
27
+ * checks for `guidelines` and `decisionContext` properties. You don't need
28
+ * to use `LoopmanGraphState` - it works with your custom state too!
29
+ *
30
+ * @param basePrompt - The base system prompt to enrich
31
+ * @param state - Any state object (checks for guidelines and decisionContext)
32
+ * @param options - Optional configuration for formatting
33
+ * @returns Enriched system prompt with Loopman context
34
+ *
35
+ * @example With LoopmanGraphState
36
+ * ```typescript
37
+ * async function agentNode(state: typeof LoopmanGraphState.State) {
38
+ * const systemPrompt = enrichSystemPrompt(
39
+ * "You are a helpful email assistant.",
40
+ * state // Pass entire state, extracts what it needs
41
+ * );
42
+ *
43
+ * const response = await model.invoke([
44
+ * { role: "system", content: systemPrompt },
45
+ * ...messages,
46
+ * ]);
47
+ *
48
+ * return { messages: [response] };
49
+ * }
50
+ * ```
51
+ *
52
+ * @example With custom state
53
+ * ```typescript
54
+ * const MyCustomState = Annotation.Root({
55
+ * messages: Annotation<BaseMessage[]>({ ... }),
56
+ * myCustomField: Annotation<string>({ ... }),
57
+ * guidelines: Annotation<LoopmanGuideline[]>({ ... }), // Optional Loopman field
58
+ * decisionContext: Annotation<LoopmanDecision[]>({ ... }), // Optional Loopman field
59
+ * });
60
+ *
61
+ * async function agentNode(state: typeof MyCustomState.State) {
62
+ * // Works seamlessly with custom state!
63
+ * const systemPrompt = enrichSystemPrompt(
64
+ * "You are a helpful assistant.",
65
+ * state
66
+ * );
67
+ *
68
+ * return { messages: [response] };
69
+ * }
70
+ * ```
71
+ *
72
+ * @example With custom options
73
+ * ```typescript
74
+ * const systemPrompt = enrichSystemPrompt(
75
+ * "You are a helpful assistant.",
76
+ * state,
77
+ * {
78
+ * maxDecisions: 5,
79
+ * guidelinesHeader: "📋 Company Policies",
80
+ * includeDecisionContext: false, // Skip decision history
81
+ * }
82
+ * );
83
+ * ```
84
+ */
85
+ export declare function enrichSystemPrompt(basePrompt: string, state: any, // Accept any state object
86
+ options?: EnrichSystemPromptOptions): string;
87
+ /**
88
+ * Formats guidelines as a structured string for logging or display
89
+ *
90
+ * @param guidelines - Array of Loopman guidelines
91
+ * @returns Formatted string representation of guidelines
92
+ *
93
+ * @example
94
+ * ```typescript
95
+ * const formatted = formatGuidelines(state.guidelines);
96
+ * console.log(formatted);
97
+ * // Output:
98
+ * // 📋 3 Guideline(s):
99
+ * // - [CRITICAL] Never send emails without approval
100
+ * // - [MAJOR] Always validate email addresses
101
+ * // - [MINOR] Include signature in all emails
102
+ * ```
103
+ */
104
+ export declare function formatGuidelines(guidelines: LoopmanGuideline[]): string;
105
+ /**
106
+ * Formats decision context as a structured string for logging or display
107
+ *
108
+ * @param decisions - Array of Loopman decisions
109
+ * @param maxDecisions - Maximum number of decisions to show (default: all)
110
+ * @returns Formatted string representation of decision history
111
+ *
112
+ * @example
113
+ * ```typescript
114
+ * const formatted = formatDecisionContext(state.decisionContext, 3);
115
+ * console.log(formatted);
116
+ * // Output:
117
+ * // 📜 3 Recent Decision(s):
118
+ * // - APPROVED by USER: "Looks good"
119
+ * // - NEEDS_CHANGES by USER: "Fix the subject line"
120
+ * // - APPROVED by USER
121
+ * ```
122
+ */
123
+ export declare function formatDecisionContext(decisions: LoopmanDecision[], maxDecisions?: number): string;
124
+ /**
125
+ * Checks if the state contains any Loopman context (guidelines or decisions)
126
+ *
127
+ * Works with any state object - simply checks for the presence of
128
+ * `guidelines` or `decisionContext` properties.
129
+ *
130
+ * @param state - Any state object (checks for guidelines and decisionContext)
131
+ * @returns True if state has guidelines or decision context
132
+ *
133
+ * @example
134
+ * ```typescript
135
+ * if (hasLoopmanContext(state)) {
136
+ * console.log("Using Loopman context for enhanced decision-making");
137
+ * }
138
+ * ```
139
+ */
140
+ export declare function hasLoopmanContext(state: any): boolean;
141
+ /**
142
+ * Extracts critical guidelines from a list
143
+ *
144
+ * @param guidelines - Array of Loopman guidelines
145
+ * @returns Array containing only critical severity guidelines
146
+ *
147
+ * @example
148
+ * ```typescript
149
+ * const criticalGuidelines = getCriticalGuidelines(state.guidelines);
150
+ * if (criticalGuidelines.length > 0) {
151
+ * console.warn(`${criticalGuidelines.length} critical guideline(s) must be followed!`);
152
+ * }
153
+ * ```
154
+ */
155
+ export declare function getCriticalGuidelines(guidelines: LoopmanGuideline[]): LoopmanGuideline[];
156
+ /**
157
+ * Gets the latest decision from decision context
158
+ *
159
+ * @param decisions - Array of Loopman decisions
160
+ * @returns The most recent decision, or null if empty
161
+ *
162
+ * @example
163
+ * ```typescript
164
+ * const latestDecision = getLatestDecision(state.decisionContext);
165
+ * if (latestDecision?.status === "NEEDS_CHANGES") {
166
+ * console.log("Previous attempt needs changes:", latestDecision.comment);
167
+ * }
168
+ * ```
169
+ */
170
+ export declare function getLatestDecision(decisions: LoopmanDecision[]): LoopmanDecision | null;
171
+ //# sourceMappingURL=helpers.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"helpers.d.ts","sourceRoot":"","sources":["../../src/langgraph/helpers.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,OAAO,KAAK,EAAE,eAAe,EAAE,gBAAgB,EAAE,MAAM,SAAS,CAAC;AAEjE;;GAEG;AACH,MAAM,WAAW,yBAAyB;IACxC,oDAAoD;IACpD,iBAAiB,CAAC,EAAE,OAAO,CAAC;IAC5B,0DAA0D;IAC1D,sBAAsB,CAAC,EAAE,OAAO,CAAC;IACjC,kEAAkE;IAClE,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,2CAA2C;IAC3C,gBAAgB,CAAC,EAAE,MAAM,CAAC;IAC1B,iDAAiD;IACjD,qBAAqB,CAAC,EAAE,MAAM,CAAC;CAChC;AAED;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAgEG;AACH,wBAAgB,kBAAkB,CAChC,UAAU,EAAE,MAAM,EAClB,KAAK,EAAE,GAAG,EAAE,0BAA0B;AACtC,OAAO,GAAE,yBAA8B,GACtC,MAAM,CAwCR;AAED;;;;;;;;;;;;;;;;GAgBG;AACH,wBAAgB,gBAAgB,CAAC,UAAU,EAAE,gBAAgB,EAAE,GAAG,MAAM,CAUvE;AAED;;;;;;;;;;;;;;;;;GAiBG;AACH,wBAAgB,qBAAqB,CACnC,SAAS,EAAE,eAAe,EAAE,EAC5B,YAAY,CAAC,EAAE,MAAM,GACpB,MAAM,CAkBR;AAED;;;;;;;;;;;;;;;GAeG;AACH,wBAAgB,iBAAiB,CAAC,KAAK,EAAE,GAAG,GAAG,OAAO,CAKrD;AAED;;;;;;;;;;;;;GAaG;AACH,wBAAgB,qBAAqB,CACnC,UAAU,EAAE,gBAAgB,EAAE,GAC7B,gBAAgB,EAAE,CAEpB;AAED;;;;;;;;;;;;;GAaG;AACH,wBAAgB,iBAAiB,CAC/B,SAAS,EAAE,eAAe,EAAE,GAC3B,eAAe,GAAG,IAAI,CAKxB"}
@@ -0,0 +1,216 @@
1
+ /**
2
+ * Helper functions for LangGraph integration with Loopman
3
+ */
4
+ /**
5
+ * Enriches a system prompt with Loopman guidelines and decision context
6
+ *
7
+ * This helper function automatically formats and appends validation guidelines
8
+ * and historical decision context to your agent's system prompt.
9
+ *
10
+ * **Works with any state**: This function accepts any state object and only
11
+ * checks for `guidelines` and `decisionContext` properties. You don't need
12
+ * to use `LoopmanGraphState` - it works with your custom state too!
13
+ *
14
+ * @param basePrompt - The base system prompt to enrich
15
+ * @param state - Any state object (checks for guidelines and decisionContext)
16
+ * @param options - Optional configuration for formatting
17
+ * @returns Enriched system prompt with Loopman context
18
+ *
19
+ * @example With LoopmanGraphState
20
+ * ```typescript
21
+ * async function agentNode(state: typeof LoopmanGraphState.State) {
22
+ * const systemPrompt = enrichSystemPrompt(
23
+ * "You are a helpful email assistant.",
24
+ * state // Pass entire state, extracts what it needs
25
+ * );
26
+ *
27
+ * const response = await model.invoke([
28
+ * { role: "system", content: systemPrompt },
29
+ * ...messages,
30
+ * ]);
31
+ *
32
+ * return { messages: [response] };
33
+ * }
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[]>({ ... }), // Optional Loopman field
42
+ * decisionContext: Annotation<LoopmanDecision[]>({ ... }), // Optional Loopman field
43
+ * });
44
+ *
45
+ * async function agentNode(state: typeof MyCustomState.State) {
46
+ * // Works seamlessly with custom state!
47
+ * const systemPrompt = enrichSystemPrompt(
48
+ * "You are a helpful assistant.",
49
+ * state
50
+ * );
51
+ *
52
+ * return { messages: [response] };
53
+ * }
54
+ * ```
55
+ *
56
+ * @example With custom options
57
+ * ```typescript
58
+ * const systemPrompt = enrichSystemPrompt(
59
+ * "You are a helpful assistant.",
60
+ * state,
61
+ * {
62
+ * maxDecisions: 5,
63
+ * guidelinesHeader: "📋 Company Policies",
64
+ * includeDecisionContext: false, // Skip decision history
65
+ * }
66
+ * );
67
+ * ```
68
+ */
69
+ export function enrichSystemPrompt(basePrompt, state, // Accept any state object
70
+ options = {}) {
71
+ const { includeGuidelines = true, includeDecisionContext = true, maxDecisions = 3, guidelinesHeader = "**Guidelines**", decisionContextHeader = "**Previous Decisions**", } = options;
72
+ let enrichedPrompt = basePrompt;
73
+ // Add guidelines if available and enabled
74
+ if (includeGuidelines && state.guidelines && state.guidelines.length > 0) {
75
+ enrichedPrompt += `\n\n${guidelinesHeader}:\n`;
76
+ state.guidelines.forEach((g) => {
77
+ enrichedPrompt += `- [${g.severity.toUpperCase()}] ${g.description}\n`;
78
+ });
79
+ }
80
+ // Add decision context if available and enabled
81
+ if (includeDecisionContext &&
82
+ state.decisionContext &&
83
+ state.decisionContext.length > 0) {
84
+ enrichedPrompt += `\n\n${decisionContextHeader}:\n`;
85
+ // Show only the most recent N decisions
86
+ const recentDecisions = state.decisionContext.slice(-maxDecisions);
87
+ recentDecisions.forEach((d) => {
88
+ enrichedPrompt += `- ${d.status} by ${d.userType}`;
89
+ if (d.comment) {
90
+ enrichedPrompt += `: "${d.comment}"`;
91
+ }
92
+ enrichedPrompt += "\n";
93
+ });
94
+ }
95
+ return enrichedPrompt;
96
+ }
97
+ /**
98
+ * Formats guidelines as a structured string for logging or display
99
+ *
100
+ * @param guidelines - Array of Loopman guidelines
101
+ * @returns Formatted string representation of guidelines
102
+ *
103
+ * @example
104
+ * ```typescript
105
+ * const formatted = formatGuidelines(state.guidelines);
106
+ * console.log(formatted);
107
+ * // Output:
108
+ * // 📋 3 Guideline(s):
109
+ * // - [CRITICAL] Never send emails without approval
110
+ * // - [MAJOR] Always validate email addresses
111
+ * // - [MINOR] Include signature in all emails
112
+ * ```
113
+ */
114
+ export function formatGuidelines(guidelines) {
115
+ if (!guidelines || guidelines.length === 0) {
116
+ return "No guidelines available";
117
+ }
118
+ let output = `${guidelines.length} Guideline(s):\n`;
119
+ guidelines.forEach((g) => {
120
+ output += ` - [${g.severity.toUpperCase()}] ${g.description}\n`;
121
+ });
122
+ return output.trim();
123
+ }
124
+ /**
125
+ * Formats decision context as a structured string for logging or display
126
+ *
127
+ * @param decisions - Array of Loopman decisions
128
+ * @param maxDecisions - Maximum number of decisions to show (default: all)
129
+ * @returns Formatted string representation of decision history
130
+ *
131
+ * @example
132
+ * ```typescript
133
+ * const formatted = formatDecisionContext(state.decisionContext, 3);
134
+ * console.log(formatted);
135
+ * // Output:
136
+ * // 📜 3 Recent Decision(s):
137
+ * // - APPROVED by USER: "Looks good"
138
+ * // - NEEDS_CHANGES by USER: "Fix the subject line"
139
+ * // - APPROVED by USER
140
+ * ```
141
+ */
142
+ export function formatDecisionContext(decisions, maxDecisions) {
143
+ if (!decisions || decisions.length === 0) {
144
+ return "No decision history available";
145
+ }
146
+ const displayDecisions = maxDecisions
147
+ ? decisions.slice(-maxDecisions)
148
+ : decisions;
149
+ let output = `${displayDecisions.length} Recent Decision(s):\n`;
150
+ displayDecisions.forEach((d) => {
151
+ output += ` - ${d.status} by ${d.userType}`;
152
+ if (d.comment) {
153
+ output += `: "${d.comment}"`;
154
+ }
155
+ output += "\n";
156
+ });
157
+ return output.trim();
158
+ }
159
+ /**
160
+ * Checks if the state contains any Loopman context (guidelines or decisions)
161
+ *
162
+ * Works with any state object - simply checks for the presence of
163
+ * `guidelines` or `decisionContext` properties.
164
+ *
165
+ * @param state - Any state object (checks for guidelines and decisionContext)
166
+ * @returns True if state has guidelines or decision context
167
+ *
168
+ * @example
169
+ * ```typescript
170
+ * if (hasLoopmanContext(state)) {
171
+ * console.log("Using Loopman context for enhanced decision-making");
172
+ * }
173
+ * ```
174
+ */
175
+ export function hasLoopmanContext(state) {
176
+ return ((state.guidelines && state.guidelines.length > 0) ||
177
+ (state.decisionContext && state.decisionContext.length > 0));
178
+ }
179
+ /**
180
+ * Extracts critical guidelines from a list
181
+ *
182
+ * @param guidelines - Array of Loopman guidelines
183
+ * @returns Array containing only critical severity guidelines
184
+ *
185
+ * @example
186
+ * ```typescript
187
+ * const criticalGuidelines = getCriticalGuidelines(state.guidelines);
188
+ * if (criticalGuidelines.length > 0) {
189
+ * console.warn(`${criticalGuidelines.length} critical guideline(s) must be followed!`);
190
+ * }
191
+ * ```
192
+ */
193
+ export function getCriticalGuidelines(guidelines) {
194
+ return guidelines.filter((g) => g.severity === "critical");
195
+ }
196
+ /**
197
+ * Gets the latest decision from decision context
198
+ *
199
+ * @param decisions - Array of Loopman decisions
200
+ * @returns The most recent decision, or null if empty
201
+ *
202
+ * @example
203
+ * ```typescript
204
+ * const latestDecision = getLatestDecision(state.decisionContext);
205
+ * if (latestDecision?.status === "NEEDS_CHANGES") {
206
+ * console.log("Previous attempt needs changes:", latestDecision.comment);
207
+ * }
208
+ * ```
209
+ */
210
+ export function getLatestDecision(decisions) {
211
+ if (!decisions || decisions.length === 0) {
212
+ return null;
213
+ }
214
+ return decisions[decisions.length - 1];
215
+ }
216
+ //# sourceMappingURL=helpers.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"helpers.js","sourceRoot":"","sources":["../../src/langgraph/helpers.ts"],"names":[],"mappings":"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"}
@@ -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 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 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,IAazD,OAAO,GAAG,KAAG,OAAO,CAAC,GAAG,CAAC,CAoGxC"}