@loopman/langchain-sdk 1.0.9

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 (55) hide show
  1. package/LICENSE +374 -0
  2. package/README.md +594 -0
  3. package/dist/agents/loopman-agent.d.ts +29 -0
  4. package/dist/agents/loopman-agent.d.ts.map +1 -0
  5. package/dist/agents/loopman-agent.js +441 -0
  6. package/dist/agents/loopman-agent.js.map +1 -0
  7. package/dist/client/loopman-api.d.ts +123 -0
  8. package/dist/client/loopman-api.d.ts.map +1 -0
  9. package/dist/client/loopman-api.js +407 -0
  10. package/dist/client/loopman-api.js.map +1 -0
  11. package/dist/helpers/prompt-orchestrator.d.ts +12 -0
  12. package/dist/helpers/prompt-orchestrator.d.ts.map +1 -0
  13. package/dist/helpers/prompt-orchestrator.js +133 -0
  14. package/dist/helpers/prompt-orchestrator.js.map +1 -0
  15. package/dist/index.d.ts +17 -0
  16. package/dist/index.d.ts.map +1 -0
  17. package/dist/index.js +22 -0
  18. package/dist/index.js.map +1 -0
  19. package/dist/loopman-agent-wrapper.d.ts +70 -0
  20. package/dist/loopman-agent-wrapper.d.ts.map +1 -0
  21. package/dist/loopman-agent-wrapper.js +157 -0
  22. package/dist/loopman-agent-wrapper.js.map +1 -0
  23. package/dist/loopman-middleware.d.ts +78 -0
  24. package/dist/loopman-middleware.d.ts.map +1 -0
  25. package/dist/loopman-middleware.js +367 -0
  26. package/dist/loopman-middleware.js.map +1 -0
  27. package/dist/mcp/loopman-mcp-client.d.ts +17 -0
  28. package/dist/mcp/loopman-mcp-client.d.ts.map +1 -0
  29. package/dist/mcp/loopman-mcp-client.js +76 -0
  30. package/dist/mcp/loopman-mcp-client.js.map +1 -0
  31. package/dist/mcp/tool-registry.d.ts +29 -0
  32. package/dist/mcp/tool-registry.d.ts.map +1 -0
  33. package/dist/mcp/tool-registry.js +143 -0
  34. package/dist/mcp/tool-registry.js.map +1 -0
  35. package/dist/services/index.d.ts +12 -0
  36. package/dist/services/index.d.ts.map +1 -0
  37. package/dist/services/index.js +9 -0
  38. package/dist/services/index.js.map +1 -0
  39. package/dist/services/logger.service.d.ts +107 -0
  40. package/dist/services/logger.service.d.ts.map +1 -0
  41. package/dist/services/logger.service.js +173 -0
  42. package/dist/services/logger.service.js.map +1 -0
  43. package/dist/services/loopman.service.d.ts +72 -0
  44. package/dist/services/loopman.service.d.ts.map +1 -0
  45. package/dist/services/loopman.service.js +271 -0
  46. package/dist/services/loopman.service.js.map +1 -0
  47. package/dist/services/polling.service.d.ts +136 -0
  48. package/dist/services/polling.service.d.ts.map +1 -0
  49. package/dist/services/polling.service.js +428 -0
  50. package/dist/services/polling.service.js.map +1 -0
  51. package/dist/types.d.ts +242 -0
  52. package/dist/types.d.ts.map +1 -0
  53. package/dist/types.js +35 -0
  54. package/dist/types.js.map +1 -0
  55. package/package.json +58 -0
@@ -0,0 +1,271 @@
1
+ import { LoopmanApiClient } from "../client/loopman-api";
2
+ import { LoggerService } from "./logger.service";
3
+ import { PollingService } from "./polling.service";
4
+ /**
5
+ * Service to interact with Loopman Backoffice API
6
+ * Handles logs, decisions, and polling
7
+ */
8
+ export class LoopmanService {
9
+ apiClient;
10
+ config;
11
+ // Expose services for direct access
12
+ polling;
13
+ logger;
14
+ constructor(config) {
15
+ this.config = {
16
+ timeout: 5 * 60 * 1000, // 5 minutes
17
+ pollingInterval: 5000, // 5 seconds
18
+ debug: false,
19
+ ...config,
20
+ };
21
+ this.apiClient = new LoopmanApiClient({ apiKey: config.apiKey });
22
+ // Create logger service
23
+ this.logger = new LoggerService({
24
+ apiClient: this.apiClient,
25
+ apiKey: this.config.apiKey,
26
+ workflowId: this.config.workflowId,
27
+ executionId: this.config.executionId,
28
+ source: "LoopmanService",
29
+ debug: this.config.debug,
30
+ enableRemoteLogs: true,
31
+ });
32
+ // Create polling service and inject a dedicated logger
33
+ this.polling = new PollingService(this.apiClient);
34
+ const pollingLogger = new LoggerService({
35
+ apiClient: this.apiClient,
36
+ apiKey: this.config.apiKey,
37
+ workflowId: this.config.workflowId,
38
+ executionId: this.config.executionId,
39
+ source: "PollingService",
40
+ debug: this.config.debug,
41
+ enableRemoteLogs: true,
42
+ });
43
+ this.polling.setLogger(pollingLogger);
44
+ }
45
+ /**
46
+ * Send a log to Loopman API
47
+ * @deprecated Use logger.info(), logger.warn(), etc. instead
48
+ */
49
+ async sendLog(level, message) {
50
+ // Delegate to logger service
51
+ this.logger[level](message);
52
+ }
53
+ /**
54
+ * Get current user information
55
+ */
56
+ async getCurrentUser() {
57
+ return await this.apiClient.getCurrentUser(this.config.apiKey);
58
+ }
59
+ /**
60
+ * Get guidelines for the current workflow
61
+ * @param category - Optional category filter
62
+ * @returns Guidelines response with list of guidelines
63
+ */
64
+ async getGuidelines(category) {
65
+ try {
66
+ const params = new URLSearchParams();
67
+ params.append("workflow_external_id", this.config.workflowId);
68
+ if (category) {
69
+ params.append("category", category);
70
+ }
71
+ const response = await this.apiClient.get(this.config.apiKey, `/api/v1/guidelines?${params.toString()}`);
72
+ if (this.config.debug) {
73
+ console.log(`[LoopmanService] Retrieved ${response.guidelines.length} guidelines`);
74
+ }
75
+ return response;
76
+ }
77
+ catch (error) {
78
+ if (this.config.debug) {
79
+ console.error("[LoopmanService] Failed to get guidelines:", error);
80
+ }
81
+ // Return empty guidelines on error
82
+ return { guidelines: [] };
83
+ }
84
+ }
85
+ /**
86
+ * Get decision context (history of decisions) for the current workflow execution
87
+ * @returns Decision context with history of previous decisions
88
+ */
89
+ async getDecisionContext() {
90
+ try {
91
+ const response = await this.apiClient.get(this.config.apiKey, `/api/v1/workflows/${this.config.workflowId}/executions/${this.config.executionId}/decisions`);
92
+ if (this.config.debug) {
93
+ console.log(`[LoopmanService] Retrieved ${response.decisions.length} decisions in context`);
94
+ }
95
+ return response;
96
+ }
97
+ catch (error) {
98
+ if (this.config.debug) {
99
+ console.error("[LoopmanService] Failed to get decision context:", error);
100
+ }
101
+ // Return empty decisions on error
102
+ return { decisions: [] };
103
+ }
104
+ }
105
+ /**
106
+ * Get workflow categories
107
+ * Returns available categories for guidelines in this workflow
108
+ * @returns Array of category names
109
+ */
110
+ async getWorkflowCategories() {
111
+ try {
112
+ const response = await this.apiClient.get(this.config.apiKey, `/api/v1/workflows/${this.config.workflowId}/categories`);
113
+ if (this.config.debug) {
114
+ console.log(`[LoopmanService] Retrieved ${response.categories.length} categories`);
115
+ }
116
+ return response.categories;
117
+ }
118
+ catch (error) {
119
+ if (this.config.debug) {
120
+ console.error("[LoopmanService] Failed to get workflow categories:", error);
121
+ }
122
+ return [];
123
+ }
124
+ }
125
+ /**
126
+ * Convert tool arguments to structured information items
127
+ * Formats tool parameters for human-readable display in Loopman UI
128
+ */
129
+ convertToolArgsToInformation(toolName, toolArgs) {
130
+ const information = [];
131
+ information.push({
132
+ type: "text",
133
+ label: `Tool`,
134
+ value: toolName,
135
+ });
136
+ if (!toolArgs || typeof toolArgs !== "object") {
137
+ return information;
138
+ }
139
+ // Iterate through tool arguments and create information items
140
+ for (const [key, value] of Object.entries(toolArgs)) {
141
+ if (value === null || value === undefined) {
142
+ continue;
143
+ }
144
+ const label = key.charAt(0).toUpperCase() + key.slice(1).replace(/_/g, " ");
145
+ // Detect URLs
146
+ if (typeof value === "string" &&
147
+ (value.startsWith("http://") || value.startsWith("https://"))) {
148
+ information.push({
149
+ type: "url",
150
+ label: `${label} URL`,
151
+ value: value,
152
+ });
153
+ }
154
+ // Detect arrays (convert to bullet points)
155
+ else if (Array.isArray(value)) {
156
+ information.push({
157
+ type: "bulletPoints",
158
+ label: label,
159
+ value: value.map(String),
160
+ });
161
+ }
162
+ // Text values
163
+ else {
164
+ information.push({
165
+ type: "text",
166
+ label: label,
167
+ value: String(value),
168
+ });
169
+ }
170
+ }
171
+ return information;
172
+ }
173
+ /**
174
+ * Create a task in Loopman for human review of a tool call
175
+ * Maps tool call data to a task that humans can validate/reject/modify
176
+ *
177
+ * @param toolName - Name of the tool to be validated
178
+ * @param toolArgs - Arguments for the tool call
179
+ * @param description - Optional description of the action
180
+ * @param toolCallId - Optional unique ID from LangChain tool call
181
+ * @param businessContext - Optional business context explaining the action
182
+ * @param parentTaskId - Optional parent task ID to create hierarchical link
183
+ * @param proposedDecision - Optional proposed decision from parent task
184
+ * @param decisionReasoning - Optional decision reasoning from parent task
185
+ * @returns The created task response from Loopman API
186
+ */
187
+ async createTaskForValidation(toolName, toolArgs, description, toolCallId, businessContext, parentTaskId, proposedDecision, decisionReasoning) {
188
+ try {
189
+ const timestamp = new Date().toISOString();
190
+ const externalReference = `${this.config.workflowId}-${this.config.executionId}-${toolName}-${Date.now()}`;
191
+ // Generate idempotency key based on execution, tool call, and unique call ID
192
+ // This prevents duplicate tasks while allowing multiple calls with same args
193
+ let idempotencyKey;
194
+ if (toolCallId) {
195
+ // Use tool_call_id from LangChain for uniqueness (preferred)
196
+ idempotencyKey = `${this.config.executionId}-${toolName}-${toolCallId}`;
197
+ }
198
+ else {
199
+ // Fallback: hash of args + timestamp for uniqueness
200
+ const argsHash = JSON.stringify(toolArgs);
201
+ const uniqueSuffix = `${Date.now()}-${Buffer.from(argsHash)
202
+ .toString("base64")
203
+ .slice(0, 20)}`;
204
+ idempotencyKey = `${this.config.executionId}-${toolName}-${uniqueSuffix}`;
205
+ }
206
+ const payload = {
207
+ title: `Tool validation`,
208
+ description: description || `Validation required for tool: ${toolName}`,
209
+ workflowIdentifier: this.config.workflowId,
210
+ executionIdentifier: this.config.executionId,
211
+ channelId: this.config.channelId,
212
+ category: "tool-validation",
213
+ businessContext: businessContext, // Business explanation (from parent or current)
214
+ proposedDecision, // Inherited from parent task if available
215
+ decisionReasoning, // Inherited from parent task if available
216
+ metadata: {
217
+ source: "loopman-langchain-sdk-typescript",
218
+ timestamp,
219
+ toolName,
220
+ toolArgs,
221
+ parentTaskId, // Link to parent reflection task
222
+ },
223
+ information: this.convertToolArgsToInformation(toolName, toolArgs),
224
+ priority: "MEDIUM",
225
+ externalReference,
226
+ idempotencyKey,
227
+ };
228
+ this.logger.debug("[LoopmanService] Creating task for tool validation:", payload);
229
+ const taskResponse = await this.apiClient.post(this.config.apiKey, `/api/v1/tasks`, payload);
230
+ this.logger.debug(`[LoopmanService] Task created with ID: ${taskResponse.id}`, { status: taskResponse.status });
231
+ return taskResponse;
232
+ }
233
+ catch (error) {
234
+ this.logger.error("[LoopmanService] Failed to create task:", error);
235
+ throw new Error(`Failed to create task in Loopman: ${error instanceof Error ? error.message : String(error)}`);
236
+ }
237
+ }
238
+ /**
239
+ * Get the current status of a task
240
+ * @param taskId - The ID of the task to check
241
+ * @returns The task response from Loopman API
242
+ */
243
+ async getTask(taskId) {
244
+ try {
245
+ const taskResponse = await this.apiClient.get(this.config.apiKey, `/api/v1/tasks/${taskId}`);
246
+ this.logger.debug(`[LoopmanService] Task ${taskId} status: ${taskResponse.status}`);
247
+ return taskResponse;
248
+ }
249
+ catch (error) {
250
+ this.logger.error("[LoopmanService] Failed to get task:", error);
251
+ throw new Error(`Failed to get task from Loopman: ${error instanceof Error ? error.message : String(error)}`);
252
+ }
253
+ }
254
+ /**
255
+ * Get polling options with current configuration
256
+ * Helper method to construct PollingOptions for direct PollingService usage
257
+ */
258
+ getPollingOptions(taskId, abortSignal) {
259
+ return {
260
+ taskId,
261
+ workflowId: this.config.workflowId,
262
+ executionId: this.config.executionId,
263
+ apiKey: this.config.apiKey,
264
+ timeoutMs: this.config.timeout,
265
+ pollingIntervalMs: this.config.pollingInterval,
266
+ abortSignal,
267
+ debug: this.config.debug,
268
+ };
269
+ }
270
+ }
271
+ //# sourceMappingURL=loopman.service.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"loopman.service.js","sourceRoot":"","sources":["../../src/services/loopman.service.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,136 @@
1
+ import { LoopmanApiClient } from "../client/loopman-api";
2
+ import { LoggerService } from "./logger.service";
3
+ /**
4
+ * Polling options for decision monitoring
5
+ */
6
+ export interface PollingOptions {
7
+ /** Decision ID to poll for */
8
+ taskId: string;
9
+ /** Workflow ID */
10
+ workflowId: string;
11
+ /** Execution ID */
12
+ executionId: string;
13
+ /** API key for authentication */
14
+ apiKey: string;
15
+ /** Timeout in milliseconds (default: 5 minutes) */
16
+ timeoutMs?: number;
17
+ /** Base polling interval in milliseconds (default: 5000) */
18
+ pollingIntervalMs?: number;
19
+ /** Abort signal for cancellation */
20
+ abortSignal?: AbortSignal;
21
+ /** Enable debug logging */
22
+ debug?: boolean;
23
+ /** Callback for status updates */
24
+ onStatusUpdate?: (status: string, iteration: number) => void;
25
+ }
26
+ /**
27
+ * Decision status response from API
28
+ */
29
+ export interface DecisionStatusResponse {
30
+ id: string;
31
+ status: "PENDING" | "VALIDATED" | "REFUSED" | "NEED_CHANGES" | "CANCELLED" | "EXPIRED";
32
+ feedback?: string;
33
+ modified_data?: any;
34
+ createdAt: string;
35
+ updatedAt: string;
36
+ [key: string]: any;
37
+ }
38
+ /**
39
+ * Polling result with final decision
40
+ */
41
+ export interface PollingResult {
42
+ /** Decision status */
43
+ status: "VALIDATED" | "REFUSED" | "NEED_CHANGES" | "CANCELLED" | "EXPIRED" | "ABORTED" | "TIMEOUT";
44
+ /** Decision ID */
45
+ taskId: string;
46
+ /** Elapsed time in milliseconds */
47
+ elapsedTime: number;
48
+ /** Number of polling iterations */
49
+ iterations: number;
50
+ /** Full decision data */
51
+ data?: DecisionStatusResponse;
52
+ }
53
+ /**
54
+ * Service for polling decision status and waiting for human review
55
+ *
56
+ * Inspired by the Python SDK PollingService with improvements:
57
+ * - Session management (start/stop polling)
58
+ * - Interruption notifications to backend
59
+ * - Jitter in polling intervals (±20%)
60
+ * - Graceful handling of 500 errors
61
+ * - Consecutive error tracking
62
+ * - AbortSignal support for cancellation
63
+ * - Progress callbacks
64
+ * - Centralized logging with LoggerService
65
+ */
66
+ export declare class PollingService {
67
+ private apiClient;
68
+ private logger;
69
+ private debug;
70
+ constructor(apiClient: LoopmanApiClient);
71
+ /**
72
+ * Set logger for this polling service
73
+ * Called by LoopmanService to inject the logger
74
+ */
75
+ setLogger(logger: LoggerService): void;
76
+ /**
77
+ * Wait for a human decision on a specific decision
78
+ * @param options Polling options
79
+ * @returns Polling result with final decision
80
+ */
81
+ waitForDecision(options: PollingOptions): Promise<PollingResult>;
82
+ /**
83
+ * Check task status via API
84
+ * Uses the simplified /api/v1/tasks/:id/status endpoint
85
+ */
86
+ private checkTaskStatus;
87
+ /**
88
+ * Map task status from API to decision status
89
+ */
90
+ private mapTaskStatusToDecisionStatus;
91
+ /**
92
+ * Start polling session on backend
93
+ * Uses the simplified /api/v1/tasks/:id/polling/start endpoint
94
+ */
95
+ private startPollingSession;
96
+ /**
97
+ * Stop polling session on backend
98
+ * Uses the simplified /api/v1/tasks/:id/polling/stop endpoint
99
+ */
100
+ private stopPollingSession;
101
+ /**
102
+ * Notify backend about workflow interruption
103
+ * Uses /api/v1/tasks/:id/interruption endpoint (best effort - may not exist yet)
104
+ */
105
+ private notifyInterruption;
106
+ /**
107
+ * Check if error is a 500 error (server-side issue)
108
+ */
109
+ private is500Error;
110
+ /**
111
+ * Add jitter to polling interval (±20%)
112
+ * This helps distribute load on the server when multiple clients are polling
113
+ */
114
+ private addJitter;
115
+ /**
116
+ * Sleep with optional abort signal support
117
+ */
118
+ private sleep;
119
+ /**
120
+ * Log debug message
121
+ */
122
+ private logDebug;
123
+ /**
124
+ * Log info message
125
+ */
126
+ private logInfo;
127
+ /**
128
+ * Log warning message
129
+ */
130
+ private logWarn;
131
+ /**
132
+ * Log error message
133
+ */
134
+ private logError;
135
+ }
136
+ //# sourceMappingURL=polling.service.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"polling.service.d.ts","sourceRoot":"","sources":["../../src/services/polling.service.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,gBAAgB,EAAE,MAAM,uBAAuB,CAAC;AACzD,OAAO,EAAE,aAAa,EAAE,MAAM,kBAAkB,CAAC;AAEjD;;GAEG;AACH,MAAM,WAAW,cAAc;IAC7B,8BAA8B;IAC9B,MAAM,EAAE,MAAM,CAAC;IACf,kBAAkB;IAClB,UAAU,EAAE,MAAM,CAAC;IACnB,mBAAmB;IACnB,WAAW,EAAE,MAAM,CAAC;IACpB,iCAAiC;IACjC,MAAM,EAAE,MAAM,CAAC;IACf,mDAAmD;IACnD,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,4DAA4D;IAC5D,iBAAiB,CAAC,EAAE,MAAM,CAAC;IAC3B,oCAAoC;IACpC,WAAW,CAAC,EAAE,WAAW,CAAC;IAC1B,2BAA2B;IAC3B,KAAK,CAAC,EAAE,OAAO,CAAC;IAChB,kCAAkC;IAClC,cAAc,CAAC,EAAE,CAAC,MAAM,EAAE,MAAM,EAAE,SAAS,EAAE,MAAM,KAAK,IAAI,CAAC;CAC9D;AAED;;GAEG;AACH,MAAM,WAAW,sBAAsB;IACrC,EAAE,EAAE,MAAM,CAAC;IACX,MAAM,EACF,SAAS,GACT,WAAW,GACX,SAAS,GACT,cAAc,GACd,WAAW,GACX,SAAS,CAAC;IACd,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,aAAa,CAAC,EAAE,GAAG,CAAC;IACpB,SAAS,EAAE,MAAM,CAAC;IAClB,SAAS,EAAE,MAAM,CAAC;IAClB,CAAC,GAAG,EAAE,MAAM,GAAG,GAAG,CAAC;CACpB;AAED;;GAEG;AACH,MAAM,WAAW,aAAa;IAC5B,sBAAsB;IACtB,MAAM,EACF,WAAW,GACX,SAAS,GACT,cAAc,GACd,WAAW,GACX,SAAS,GACT,SAAS,GACT,SAAS,CAAC;IACd,kBAAkB;IAClB,MAAM,EAAE,MAAM,CAAC;IACf,mCAAmC;IACnC,WAAW,EAAE,MAAM,CAAC;IACpB,mCAAmC;IACnC,UAAU,EAAE,MAAM,CAAC;IACnB,yBAAyB;IACzB,IAAI,CAAC,EAAE,sBAAsB,CAAC;CAC/B;AAED;;;;;;;;;;;;GAYG;AACH,qBAAa,cAAc;IACzB,OAAO,CAAC,SAAS,CAAmB;IACpC,OAAO,CAAC,MAAM,CAA8B;IAC5C,OAAO,CAAC,KAAK,CAAkB;gBAEnB,SAAS,EAAE,gBAAgB;IAIvC;;;OAGG;IACH,SAAS,CAAC,MAAM,EAAE,aAAa,GAAG,IAAI;IAItC;;;;OAIG;IACG,eAAe,CAAC,OAAO,EAAE,cAAc,GAAG,OAAO,CAAC,aAAa,CAAC;IAsLtE;;;OAGG;YACW,eAAe;IA8G7B;;OAEG;IACH,OAAO,CAAC,6BAA6B;IAoBrC;;;OAGG;YACW,mBAAmB;IAsBjC;;;OAGG;YACW,kBAAkB;IAwBhC;;;OAGG;YACW,kBAAkB;IA+BhC;;OAEG;IACH,OAAO,CAAC,UAAU;IAUlB;;;OAGG;IACH,OAAO,CAAC,SAAS;IAMjB;;OAEG;IACH,OAAO,CAAC,KAAK;IAoBb;;OAEG;IACH,OAAO,CAAC,QAAQ;IAQhB;;OAEG;IACH,OAAO,CAAC,OAAO;IAQf;;OAEG;IACH,OAAO,CAAC,OAAO;IAQf;;OAEG;IACH,OAAO,CAAC,QAAQ;CAWjB"}