@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.
- package/README.md +72 -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/index.d.ts +3 -1
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +2 -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 +131 -0
- package/dist/langgraph/loopman-context-node.js.map +1 -0
- package/dist/langgraph/loopman-validation-node.d.ts +89 -0
- package/dist/langgraph/loopman-validation-node.d.ts.map +1 -0
- package/dist/langgraph/loopman-validation-node.js +297 -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/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 +15 -10
- package/dist/services/loopman.service.d.ts.map +1 -1
- package/dist/services/loopman.service.js +49 -37
- 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/types.d.ts +9 -35
- package/dist/types.d.ts.map +1 -1
- package/dist/types.js.map +1 -1
- package/package.json +6 -4
|
@@ -76,27 +76,20 @@ export class LoggerService {
|
|
|
76
76
|
* Log to console based on level and debug mode
|
|
77
77
|
*/
|
|
78
78
|
logToConsole(level, message, data) {
|
|
79
|
+
if (!this.config.debug) {
|
|
80
|
+
return;
|
|
81
|
+
}
|
|
79
82
|
const prefix = `[${this.config.source}]`;
|
|
80
83
|
const logData = data !== undefined ? data : "";
|
|
81
84
|
switch (level) {
|
|
82
85
|
case "debug":
|
|
83
|
-
// Debug only shown if debug mode is enabled
|
|
84
|
-
if (this.config.debug) {
|
|
85
|
-
console.log(prefix, message, logData);
|
|
86
|
-
}
|
|
87
|
-
break;
|
|
88
86
|
case "info":
|
|
89
|
-
|
|
90
|
-
if (this.config.debug) {
|
|
91
|
-
console.log(prefix, message, logData);
|
|
92
|
-
}
|
|
87
|
+
console.log(prefix, message, logData);
|
|
93
88
|
break;
|
|
94
89
|
case "warn":
|
|
95
|
-
// Warnings always shown
|
|
96
90
|
console.warn(prefix, message, logData);
|
|
97
91
|
break;
|
|
98
92
|
case "error":
|
|
99
|
-
// Errors always shown
|
|
100
93
|
console.error(prefix, message, logData);
|
|
101
94
|
break;
|
|
102
95
|
}
|
|
@@ -121,7 +114,6 @@ export class LoggerService {
|
|
|
121
114
|
const payload = {
|
|
122
115
|
comment: message,
|
|
123
116
|
category: "SDK_OPERATION",
|
|
124
|
-
workflowId: this.config.workflowId,
|
|
125
117
|
workflowIdentifier: this.config.workflowId,
|
|
126
118
|
executionIdentifier: this.config.executionId,
|
|
127
119
|
counter: 0,
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"logger.service.js","sourceRoot":"","sources":["../../src/services/logger.service.ts"],"names":[],"mappings":"AA6BA;;;;;;;;;;;;;;;;;;;;;;;GAuBG;AACH,MAAM,OAAO,aAAa;IAChB,MAAM,CAAe;IAE7B,YAAY,MAAoB;QAC9B,IAAI,CAAC,MAAM,GAAG;YACZ,KAAK,EAAE,KAAK;YACZ,gBAAgB,EAAE,IAAI;YACtB,GAAG,MAAM;SACV,CAAC;IACJ,CAAC;IAED;;OAEG;IACH,SAAS,CAAC,MAAc;QACtB,IAAI,CAAC,MAAM,CAAC,MAAM,GAAG,MAAM,CAAC;IAC9B,CAAC;IAED;;OAEG;IACH,KAAK,CAAC,OAAe,EAAE,IAAU;QAC/B,IAAI,CAAC,GAAG,CAAC,OAAO,EAAE,OAAO,EAAE,IAAI,CAAC,CAAC;IACnC,CAAC;IAED;;OAEG;IACH,IAAI,CAAC,OAAe,EAAE,IAAU;QAC9B,IAAI,CAAC,GAAG,CAAC,MAAM,EAAE,OAAO,EAAE,IAAI,CAAC,CAAC;IAClC,CAAC;IAED;;OAEG;IACH,IAAI,CAAC,OAAe,EAAE,IAAU;QAC9B,IAAI,CAAC,GAAG,CAAC,MAAM,EAAE,OAAO,EAAE,IAAI,CAAC,CAAC;IAClC,CAAC;IAED;;OAEG;IACH,KAAK,CAAC,OAAe,EAAE,IAAU;QAC/B,IAAI,CAAC,GAAG,CAAC,OAAO,EAAE,OAAO,EAAE,IAAI,CAAC,CAAC;IACnC,CAAC;IAED;;OAEG;IACK,GAAG,CAAC,KAAe,EAAE,OAAe,EAAE,IAAU;QACtD,kBAAkB;QAClB,IAAI,CAAC,YAAY,CAAC,KAAK,EAAE,OAAO,EAAE,IAAI,CAAC,CAAC;QAExC,gCAAgC;QAChC,IAAI,IAAI,CAAC,MAAM,CAAC,gBAAgB,IAAI,KAAK,KAAK,OAAO,EAAE,CAAC;YACtD,IAAI,CAAC,aAAa,CAAC,KAAK,EAAE,OAAO,EAAE,IAAI,CAAC,CAAC;QAC3C,CAAC;IACH,CAAC;IAED;;OAEG;IACK,YAAY,CAAC,KAAe,EAAE,OAAe,EAAE,IAAU;QAC/D,MAAM,MAAM,GAAG,IAAI,IAAI,CAAC,MAAM,CAAC,MAAM,GAAG,CAAC;QACzC,MAAM,OAAO,GAAG,IAAI,KAAK,SAAS,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC;QAE/C,QAAQ,KAAK,EAAE,CAAC;YACd,KAAK,OAAO
|
|
1
|
+
{"version":3,"file":"logger.service.js","sourceRoot":"","sources":["../../src/services/logger.service.ts"],"names":[],"mappings":"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"}
|
|
@@ -16,10 +16,6 @@ export declare class LoopmanService {
|
|
|
16
16
|
* @deprecated Use logger.info(), logger.warn(), etc. instead
|
|
17
17
|
*/
|
|
18
18
|
sendLog(level: "debug" | "info" | "warn" | "error", message: string): Promise<void>;
|
|
19
|
-
/**
|
|
20
|
-
* Get current user information
|
|
21
|
-
*/
|
|
22
|
-
getCurrentUser(): Promise<import("..").LoopmanUser>;
|
|
23
19
|
/**
|
|
24
20
|
* Get guidelines for the current workflow
|
|
25
21
|
* @param category - Optional category filter
|
|
@@ -27,10 +23,18 @@ export declare class LoopmanService {
|
|
|
27
23
|
*/
|
|
28
24
|
getGuidelines(category?: string): Promise<GuidelinesResponse>;
|
|
29
25
|
/**
|
|
30
|
-
* Get decision context
|
|
31
|
-
*
|
|
26
|
+
* Get decision context from a task's decisions
|
|
27
|
+
* This extracts decision history from a task response (from GET /api/v1/tasks/:id)
|
|
28
|
+
* @param task - Task response containing decisions array
|
|
29
|
+
* @returns Decision context formatted for the SDK
|
|
30
|
+
*/
|
|
31
|
+
getDecisionContextFromTask(task: LoopmanTaskResponse): DecisionContextResponse;
|
|
32
|
+
/**
|
|
33
|
+
* Maps task status to decision status format
|
|
34
|
+
* @param status - Task status from API
|
|
35
|
+
* @returns Decision status for SDK
|
|
32
36
|
*/
|
|
33
|
-
|
|
37
|
+
private mapTaskStatusToDecisionStatus;
|
|
34
38
|
/**
|
|
35
39
|
* Get workflow categories
|
|
36
40
|
* Returns available categories for guidelines in this workflow
|
|
@@ -43,7 +47,7 @@ export declare class LoopmanService {
|
|
|
43
47
|
*/
|
|
44
48
|
private convertToolArgsToInformation;
|
|
45
49
|
/**
|
|
46
|
-
* Create a task in Loopman for human review of a tool call
|
|
50
|
+
* Create or update a task in Loopman for human review of a tool call
|
|
47
51
|
* Maps tool call data to a task that humans can validate/reject/modify
|
|
48
52
|
*
|
|
49
53
|
* @param toolName - Name of the tool to be validated
|
|
@@ -54,9 +58,10 @@ export declare class LoopmanService {
|
|
|
54
58
|
* @param parentTaskId - Optional parent task ID to create hierarchical link
|
|
55
59
|
* @param proposedDecision - Optional proposed decision from parent task
|
|
56
60
|
* @param decisionReasoning - Optional decision reasoning from parent task
|
|
57
|
-
* @
|
|
61
|
+
* @param existingTaskId - Optional existing task ID to update (for NEEDS_CHANGES retries)
|
|
62
|
+
* @returns The created or updated task response from Loopman API
|
|
58
63
|
*/
|
|
59
|
-
createTaskForValidation(toolName: string, toolArgs: any, description?: string, toolCallId?: string, businessContext?: string, parentTaskId?: string, proposedDecision?: string, decisionReasoning?: string): Promise<LoopmanTaskResponse>;
|
|
64
|
+
createTaskForValidation(toolName: string, toolArgs: any, description?: string, toolCallId?: string, businessContext?: string, parentTaskId?: string, proposedDecision?: string, decisionReasoning?: string, existingTaskId?: string): Promise<LoopmanTaskResponse>;
|
|
60
65
|
/**
|
|
61
66
|
* Get the current status of a task
|
|
62
67
|
* @param taskId - The ID of the task to check
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"loopman.service.d.ts","sourceRoot":"","sources":["../../src/services/loopman.service.ts"],"names":[],"mappings":"AACA,OAAO,
|
|
1
|
+
{"version":3,"file":"loopman.service.d.ts","sourceRoot":"","sources":["../../src/services/loopman.service.ts"],"names":[],"mappings":"AACA,OAAO,EAGL,uBAAuB,EACvB,kBAAkB,EAClB,oBAAoB,EACpB,mBAAmB,EAEpB,MAAM,UAAU,CAAC;AAClB,OAAO,EAAE,aAAa,EAAE,MAAM,kBAAkB,CAAC;AACjD,OAAO,EAAE,cAAc,EAAE,KAAK,cAAc,EAAE,MAAM,mBAAmB,CAAC;AAExE;;;GAGG;AACH,qBAAa,cAAc;IACzB,OAAO,CAAC,SAAS,CAAmB;IACpC,OAAO,CAAC,MAAM,CAAuB;IAGrC,SAAgB,OAAO,EAAE,cAAc,CAAC;IACxC,SAAgB,MAAM,EAAE,aAAa,CAAC;gBAE1B,MAAM,EAAE,oBAAoB;IAqCxC;;;OAGG;IACG,OAAO,CACX,KAAK,EAAE,OAAO,GAAG,MAAM,GAAG,MAAM,GAAG,OAAO,EAC1C,OAAO,EAAE,MAAM,GACd,OAAO,CAAC,IAAI,CAAC;IAKhB;;;;OAIG;IACG,aAAa,CAAC,QAAQ,CAAC,EAAE,MAAM,GAAG,OAAO,CAAC,kBAAkB,CAAC;IAyBnE;;;;;OAKG;IACH,0BAA0B,CACxB,IAAI,EAAE,mBAAmB,GACxB,uBAAuB;IA2B1B;;;;OAIG;IACH,OAAO,CAAC,6BAA6B;IAgBrC;;;;OAIG;IACG,qBAAqB,IAAI,OAAO,CAAC,MAAM,EAAE,CAAC;IAqBhD;;;OAGG;IACH,OAAO,CAAC,4BAA4B;IAyDpC;;;;;;;;;;;;;;OAcG;IACG,uBAAuB,CAC3B,QAAQ,EAAE,MAAM,EAChB,QAAQ,EAAE,GAAG,EACb,WAAW,CAAC,EAAE,MAAM,EACpB,UAAU,CAAC,EAAE,MAAM,EACnB,eAAe,CAAC,EAAE,MAAM,EACxB,YAAY,CAAC,EAAE,MAAM,EACrB,gBAAgB,CAAC,EAAE,MAAM,EACzB,iBAAiB,CAAC,EAAE,MAAM,EAC1B,cAAc,CAAC,EAAE,MAAM,GACtB,OAAO,CAAC,mBAAmB,CAAC;IAyE/B;;;;OAIG;IACG,OAAO,CAAC,MAAM,EAAE,MAAM,GAAG,OAAO,CAAC,mBAAmB,CAAC;IAsB3D;;;OAGG;IACH,iBAAiB,CAAC,MAAM,EAAE,MAAM,EAAE,WAAW,CAAC,EAAE,WAAW,GAAG,cAAc;CAY7E"}
|
|
@@ -29,6 +29,8 @@ export class LoopmanService {
|
|
|
29
29
|
debug: this.config.debug,
|
|
30
30
|
enableRemoteLogs: true,
|
|
31
31
|
});
|
|
32
|
+
// Attach logger to API client (keeps the client silent unless debug is enabled)
|
|
33
|
+
this.apiClient.setLogger(this.logger, this.config.debug);
|
|
32
34
|
// Create polling service and inject a dedicated logger
|
|
33
35
|
this.polling = new PollingService(this.apiClient);
|
|
34
36
|
const pollingLogger = new LoggerService({
|
|
@@ -50,12 +52,6 @@ export class LoopmanService {
|
|
|
50
52
|
// Delegate to logger service
|
|
51
53
|
this.logger[level](message);
|
|
52
54
|
}
|
|
53
|
-
/**
|
|
54
|
-
* Get current user information
|
|
55
|
-
*/
|
|
56
|
-
async getCurrentUser() {
|
|
57
|
-
return await this.apiClient.getCurrentUser(this.config.apiKey);
|
|
58
|
-
}
|
|
59
55
|
/**
|
|
60
56
|
* Get guidelines for the current workflow
|
|
61
57
|
* @param category - Optional category filter
|
|
@@ -69,38 +65,56 @@ export class LoopmanService {
|
|
|
69
65
|
params.append("category", category);
|
|
70
66
|
}
|
|
71
67
|
const response = await this.apiClient.get(this.config.apiKey, `/api/v1/guidelines?${params.toString()}`);
|
|
72
|
-
|
|
73
|
-
console.log(`[LoopmanService] Retrieved ${response.guidelines.length} guidelines`);
|
|
74
|
-
}
|
|
68
|
+
this.logger.debug(`[LoopmanService] Retrieved ${response.guidelines.length} guidelines`);
|
|
75
69
|
return response;
|
|
76
70
|
}
|
|
77
71
|
catch (error) {
|
|
78
|
-
|
|
79
|
-
console.error("[LoopmanService] Failed to get guidelines:", error);
|
|
80
|
-
}
|
|
72
|
+
this.logger.warn("[LoopmanService] Failed to get guidelines", error);
|
|
81
73
|
// Return empty guidelines on error
|
|
82
74
|
return { guidelines: [] };
|
|
83
75
|
}
|
|
84
76
|
}
|
|
85
77
|
/**
|
|
86
|
-
* Get decision context
|
|
87
|
-
*
|
|
78
|
+
* Get decision context from a task's decisions
|
|
79
|
+
* This extracts decision history from a task response (from GET /api/v1/tasks/:id)
|
|
80
|
+
* @param task - Task response containing decisions array
|
|
81
|
+
* @returns Decision context formatted for the SDK
|
|
88
82
|
*/
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
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
|
|
83
|
+
getDecisionContextFromTask(task) {
|
|
84
|
+
if (!task.decisions || task.decisions.length === 0) {
|
|
85
|
+
this.logger.debug("[LoopmanService] No decisions found in task", {
|
|
86
|
+
taskId: task.id,
|
|
87
|
+
});
|
|
102
88
|
return { decisions: [] };
|
|
103
89
|
}
|
|
90
|
+
// Convert task decisions to DecisionContextEntry format
|
|
91
|
+
const decisions = task.decisions.map((decision) => ({
|
|
92
|
+
date: decision.createdAt,
|
|
93
|
+
userType: decision.user ? "USER" : "SYSTEM",
|
|
94
|
+
firstName: decision.user?.firstName,
|
|
95
|
+
lastName: decision.user?.lastName,
|
|
96
|
+
status: this.mapTaskStatusToDecisionStatus(decision.status),
|
|
97
|
+
comment: decision.comment,
|
|
98
|
+
}));
|
|
99
|
+
this.logger.debug(`[LoopmanService] Extracted ${decisions.length} decision(s) from task ${task.id}`);
|
|
100
|
+
return { decisions };
|
|
101
|
+
}
|
|
102
|
+
/**
|
|
103
|
+
* Maps task status to decision status format
|
|
104
|
+
* @param status - Task status from API
|
|
105
|
+
* @returns Decision status for SDK
|
|
106
|
+
*/
|
|
107
|
+
mapTaskStatusToDecisionStatus(status) {
|
|
108
|
+
// Map task statuses to decision statuses
|
|
109
|
+
const statusMap = {
|
|
110
|
+
PENDING: "PENDING",
|
|
111
|
+
APPROVED: "APPROVED",
|
|
112
|
+
REJECTED: "REJECTED",
|
|
113
|
+
NEEDS_CHANGES: "NEEDS_CHANGES",
|
|
114
|
+
CANCELLED: "CANCELLED",
|
|
115
|
+
EXPIRED: "EXPIRED",
|
|
116
|
+
};
|
|
117
|
+
return statusMap[status] || "PENDING";
|
|
104
118
|
}
|
|
105
119
|
/**
|
|
106
120
|
* Get workflow categories
|
|
@@ -110,15 +124,11 @@ export class LoopmanService {
|
|
|
110
124
|
async getWorkflowCategories() {
|
|
111
125
|
try {
|
|
112
126
|
const response = await this.apiClient.get(this.config.apiKey, `/api/v1/workflows/${this.config.workflowId}/categories`);
|
|
113
|
-
|
|
114
|
-
console.log(`[LoopmanService] Retrieved ${response.categories.length} categories`);
|
|
115
|
-
}
|
|
127
|
+
this.logger.debug(`[LoopmanService] Retrieved ${response.categories.length} categories`);
|
|
116
128
|
return response.categories;
|
|
117
129
|
}
|
|
118
130
|
catch (error) {
|
|
119
|
-
|
|
120
|
-
console.error("[LoopmanService] Failed to get workflow categories:", error);
|
|
121
|
-
}
|
|
131
|
+
this.logger.warn("[LoopmanService] Failed to get workflow categories", error);
|
|
122
132
|
return [];
|
|
123
133
|
}
|
|
124
134
|
}
|
|
@@ -171,7 +181,7 @@ export class LoopmanService {
|
|
|
171
181
|
return information;
|
|
172
182
|
}
|
|
173
183
|
/**
|
|
174
|
-
* Create a task in Loopman for human review of a tool call
|
|
184
|
+
* Create or update a task in Loopman for human review of a tool call
|
|
175
185
|
* Maps tool call data to a task that humans can validate/reject/modify
|
|
176
186
|
*
|
|
177
187
|
* @param toolName - Name of the tool to be validated
|
|
@@ -182,9 +192,10 @@ export class LoopmanService {
|
|
|
182
192
|
* @param parentTaskId - Optional parent task ID to create hierarchical link
|
|
183
193
|
* @param proposedDecision - Optional proposed decision from parent task
|
|
184
194
|
* @param decisionReasoning - Optional decision reasoning from parent task
|
|
185
|
-
* @
|
|
195
|
+
* @param existingTaskId - Optional existing task ID to update (for NEEDS_CHANGES retries)
|
|
196
|
+
* @returns The created or updated task response from Loopman API
|
|
186
197
|
*/
|
|
187
|
-
async createTaskForValidation(toolName, toolArgs, description, toolCallId, businessContext, parentTaskId, proposedDecision, decisionReasoning) {
|
|
198
|
+
async createTaskForValidation(toolName, toolArgs, description, toolCallId, businessContext, parentTaskId, proposedDecision, decisionReasoning, existingTaskId) {
|
|
188
199
|
try {
|
|
189
200
|
const timestamp = new Date().toISOString();
|
|
190
201
|
const externalReference = `${this.config.workflowId}-${this.config.executionId}-${toolName}-${Date.now()}`;
|
|
@@ -204,11 +215,11 @@ export class LoopmanService {
|
|
|
204
215
|
idempotencyKey = `${this.config.executionId}-${toolName}-${uniqueSuffix}`;
|
|
205
216
|
}
|
|
206
217
|
const payload = {
|
|
218
|
+
id: existingTaskId, // Include task ID for updates (upsert)
|
|
207
219
|
title: `Tool validation`,
|
|
208
220
|
description: description || `Validation required for tool: ${toolName}`,
|
|
209
221
|
workflowIdentifier: this.config.workflowId,
|
|
210
222
|
executionIdentifier: this.config.executionId,
|
|
211
|
-
channelId: this.config.channelId,
|
|
212
223
|
category: "tool-validation",
|
|
213
224
|
businessContext: businessContext, // Business explanation (from parent or current)
|
|
214
225
|
proposedDecision, // Inherited from parent task if available
|
|
@@ -224,6 +235,7 @@ export class LoopmanService {
|
|
|
224
235
|
priority: "MEDIUM",
|
|
225
236
|
externalReference,
|
|
226
237
|
idempotencyKey,
|
|
238
|
+
status: existingTaskId ? "PENDING" : undefined, // Reset status to PENDING on retry
|
|
227
239
|
};
|
|
228
240
|
this.logger.debug("[LoopmanService] Creating task for tool validation:", payload);
|
|
229
241
|
const taskResponse = await this.apiClient.post(this.config.apiKey, `/api/v1/tasks`, payload);
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"loopman.service.js","sourceRoot":"","sources":["../../src/services/loopman.service.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,gBAAgB,EAAE,MAAM,uBAAuB,CAAC;
|
|
1
|
+
{"version":3,"file":"loopman.service.js","sourceRoot":"","sources":["../../src/services/loopman.service.ts"],"names":[],"mappings":"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"}
|
|
@@ -28,7 +28,7 @@ export interface PollingOptions {
|
|
|
28
28
|
*/
|
|
29
29
|
export interface DecisionStatusResponse {
|
|
30
30
|
id: string;
|
|
31
|
-
status: "PENDING" | "VALIDATED" | "REFUSED" | "
|
|
31
|
+
status: "PENDING" | "VALIDATED" | "REFUSED" | "NEEDS_CHANGES" | "CANCELLED" | "EXPIRED";
|
|
32
32
|
feedback?: string;
|
|
33
33
|
modified_data?: any;
|
|
34
34
|
createdAt: string;
|
|
@@ -40,7 +40,7 @@ export interface DecisionStatusResponse {
|
|
|
40
40
|
*/
|
|
41
41
|
export interface PollingResult {
|
|
42
42
|
/** Decision status */
|
|
43
|
-
status: "VALIDATED" | "REFUSED" | "
|
|
43
|
+
status: "VALIDATED" | "REFUSED" | "NEEDS_CHANGES" | "CANCELLED" | "EXPIRED" | "ABORTED" | "TIMEOUT";
|
|
44
44
|
/** Decision ID */
|
|
45
45
|
taskId: string;
|
|
46
46
|
/** Elapsed time in milliseconds */
|
|
@@ -81,7 +81,7 @@ export declare class PollingService {
|
|
|
81
81
|
waitForDecision(options: PollingOptions): Promise<PollingResult>;
|
|
82
82
|
/**
|
|
83
83
|
* Check task status via API
|
|
84
|
-
*
|
|
84
|
+
* Fetches full task to get status and feedback
|
|
85
85
|
*/
|
|
86
86
|
private checkTaskStatus;
|
|
87
87
|
/**
|
|
@@ -103,6 +103,10 @@ export declare class PollingService {
|
|
|
103
103
|
* Uses /api/v1/tasks/:id/interruption endpoint (best effort - may not exist yet)
|
|
104
104
|
*/
|
|
105
105
|
private notifyInterruption;
|
|
106
|
+
/**
|
|
107
|
+
* Check if error is a 401 error (authentication error)
|
|
108
|
+
*/
|
|
109
|
+
private is401Error;
|
|
106
110
|
/**
|
|
107
111
|
* Check if error is a 500 error (server-side issue)
|
|
108
112
|
*/
|
|
@@ -1 +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,
|
|
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,eAAe,GACf,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,eAAe,GACf,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;IAyMtE;;;OAGG;YACW,eAAe;IAwG7B;;OAEG;IACH,OAAO,CAAC,6BAA6B;IAoBrC;;;OAGG;YACW,mBAAmB;IAsBjC;;;OAGG;YACW,kBAAkB;IAwBhC;;;OAGG;YACW,kBAAkB;IA+BhC;;OAEG;IACH,OAAO,CAAC,UAAU;IAclB;;OAEG;IACH,OAAO,CAAC,UAAU;IAUlB;;;OAGG;IACH,OAAO,CAAC,SAAS;IAMjB;;OAEG;IACH,OAAO,CAAC,KAAK;IAoBb;;OAEG;IACH,OAAO,CAAC,QAAQ;IAMhB;;OAEG;IACH,OAAO,CAAC,OAAO;IAMf;;OAEG;IACH,OAAO,CAAC,OAAO;IAMf;;OAEG;IACH,OAAO,CAAC,QAAQ;CAKjB"}
|
|
@@ -37,7 +37,7 @@ export class PollingService {
|
|
|
37
37
|
this.logger?.setTaskId(taskId);
|
|
38
38
|
// Store debug flag for this polling session
|
|
39
39
|
this.debug = options.debug ?? false;
|
|
40
|
-
this.logInfo("
|
|
40
|
+
this.logInfo("Starting polling for decision", {
|
|
41
41
|
taskId,
|
|
42
42
|
workflowId,
|
|
43
43
|
executionId,
|
|
@@ -55,14 +55,14 @@ export class PollingService {
|
|
|
55
55
|
while (Date.now() - startTime < timeoutMs) {
|
|
56
56
|
iterationCount++;
|
|
57
57
|
const elapsedTime = Date.now() - startTime;
|
|
58
|
-
this.logDebug(
|
|
58
|
+
this.logDebug(`Polling iteration #${iterationCount}`, {
|
|
59
59
|
taskId,
|
|
60
60
|
elapsedTime,
|
|
61
61
|
remainingTime: timeoutMs - elapsedTime,
|
|
62
62
|
});
|
|
63
63
|
// Check for abort signal
|
|
64
64
|
if (abortSignal?.aborted) {
|
|
65
|
-
this.logInfo("
|
|
65
|
+
this.logInfo("Polling aborted by signal", {
|
|
66
66
|
taskId,
|
|
67
67
|
iterationCount,
|
|
68
68
|
});
|
|
@@ -87,7 +87,7 @@ export class PollingService {
|
|
|
87
87
|
}
|
|
88
88
|
// Check if decision is resolved
|
|
89
89
|
if (statusResponse.status !== "PENDING") {
|
|
90
|
-
this.logInfo("
|
|
90
|
+
this.logInfo("Decision resolved", {
|
|
91
91
|
taskId,
|
|
92
92
|
status: statusResponse.status,
|
|
93
93
|
iterationCount,
|
|
@@ -106,7 +106,21 @@ export class PollingService {
|
|
|
106
106
|
}
|
|
107
107
|
catch (error) {
|
|
108
108
|
consecutiveErrors++;
|
|
109
|
-
this.logWarn(
|
|
109
|
+
this.logWarn(`Error in polling iteration #${iterationCount}`, error);
|
|
110
|
+
// Stop immediately on authentication errors (401) - not a temporary issue
|
|
111
|
+
if (this.is401Error(error)) {
|
|
112
|
+
this.logError("Authentication error (401), stopping polling", {
|
|
113
|
+
taskId,
|
|
114
|
+
error: error instanceof Error ? error.message : String(error),
|
|
115
|
+
});
|
|
116
|
+
await this.notifyInterruption(taskId, apiKey, "error", {
|
|
117
|
+
elapsedTime: Date.now() - startTime,
|
|
118
|
+
reason: "authentication_error",
|
|
119
|
+
error: error instanceof Error ? error.message : String(error),
|
|
120
|
+
});
|
|
121
|
+
await this.stopPollingSession(taskId, apiKey, "error");
|
|
122
|
+
throw new Error(`Authentication failed during polling for task ${taskId}: ${error instanceof Error ? error.message : String(error)}`);
|
|
123
|
+
}
|
|
110
124
|
// Ignore 500 errors (server issues are temporary)
|
|
111
125
|
if (this.is500Error(error)) {
|
|
112
126
|
this.logInfo("Server error 500, continuing polling", {
|
|
@@ -115,7 +129,7 @@ export class PollingService {
|
|
|
115
129
|
consecutiveErrors = 0; // Don't count 500 as critical error
|
|
116
130
|
}
|
|
117
131
|
else if (consecutiveErrors >= MAX_CONSECUTIVE_ERRORS) {
|
|
118
|
-
this.logWarn("
|
|
132
|
+
this.logWarn("Too many consecutive errors, stopping polling", {
|
|
119
133
|
consecutiveErrors,
|
|
120
134
|
taskId,
|
|
121
135
|
});
|
|
@@ -130,7 +144,7 @@ export class PollingService {
|
|
|
130
144
|
}
|
|
131
145
|
// Sleep with jitter before next iteration
|
|
132
146
|
const sleepMs = this.addJitter(pollingIntervalMs);
|
|
133
|
-
this.logDebug(
|
|
147
|
+
this.logDebug(`Sleeping for ${sleepMs}ms before next poll`, {
|
|
134
148
|
taskId,
|
|
135
149
|
});
|
|
136
150
|
try {
|
|
@@ -138,7 +152,7 @@ export class PollingService {
|
|
|
138
152
|
}
|
|
139
153
|
catch (error) {
|
|
140
154
|
if (error instanceof Error && error.message === "Sleep aborted") {
|
|
141
|
-
this.logInfo("
|
|
155
|
+
this.logInfo("Sleep interrupted by abort signal", {
|
|
142
156
|
taskId,
|
|
143
157
|
});
|
|
144
158
|
await this.notifyInterruption(taskId, apiKey, "aborted", {
|
|
@@ -158,7 +172,7 @@ export class PollingService {
|
|
|
158
172
|
}
|
|
159
173
|
}
|
|
160
174
|
// Timeout reached
|
|
161
|
-
this.logWarn("
|
|
175
|
+
this.logWarn("Polling timeout reached", {
|
|
162
176
|
taskId,
|
|
163
177
|
timeoutMs,
|
|
164
178
|
});
|
|
@@ -182,27 +196,27 @@ export class PollingService {
|
|
|
182
196
|
}
|
|
183
197
|
/**
|
|
184
198
|
* Check task status via API
|
|
185
|
-
*
|
|
199
|
+
* Fetches full task to get status and feedback
|
|
186
200
|
*/
|
|
187
201
|
async checkTaskStatus(taskId, workflowId, executionId, apiKey) {
|
|
188
|
-
this.logDebug("
|
|
189
|
-
//
|
|
190
|
-
const
|
|
191
|
-
const status = this.mapTaskStatusToDecisionStatus(
|
|
192
|
-
//
|
|
202
|
+
this.logDebug("Checking task status", { taskId });
|
|
203
|
+
// Fetch full task to get status and decisions
|
|
204
|
+
const fullTask = await this.apiClient.get(apiKey, `/api/v1/tasks/${taskId}`);
|
|
205
|
+
const status = this.mapTaskStatusToDecisionStatus(fullTask.status);
|
|
206
|
+
// Extract feedback if status is NEEDS_CHANGES
|
|
193
207
|
let feedback;
|
|
194
208
|
let modified_data;
|
|
195
|
-
if (status === "
|
|
196
|
-
this.logDebug("
|
|
197
|
-
|
|
198
|
-
// Extract feedback from all NEED_CHANGES decisions (there can be multiple iterations)
|
|
209
|
+
if (status === "NEEDS_CHANGES") {
|
|
210
|
+
this.logDebug("Status is NEEDS_CHANGES, extracting feedback from task", { taskId });
|
|
211
|
+
// Extract feedback from all NEEDS_CHANGES decisions (there can be multiple iterations)
|
|
199
212
|
if (fullTask.decisions &&
|
|
200
213
|
Array.isArray(fullTask.decisions) &&
|
|
201
214
|
fullTask.decisions.length > 0) {
|
|
202
|
-
// Filter
|
|
203
|
-
const needChangesDecisions = fullTask.decisions.filter((d) => d.status === "
|
|
215
|
+
// Filter NEEDS_CHANGES decisions (decisions are sorted by date desc)
|
|
216
|
+
const needChangesDecisions = fullTask.decisions.filter((d) => d.status === "NEEDS_CHANGES" ||
|
|
217
|
+
d.type === "NEEDS_CHANGES");
|
|
204
218
|
if (needChangesDecisions.length > 0) {
|
|
205
|
-
// Aggregate all feedback from
|
|
219
|
+
// Aggregate all feedback from NEEDS_CHANGES iterations with user names
|
|
206
220
|
const feedbacksWithUsers = needChangesDecisions
|
|
207
221
|
.map((d) => {
|
|
208
222
|
const comment = d.comment || d.feedback;
|
|
@@ -237,7 +251,7 @@ export class PollingService {
|
|
|
237
251
|
})
|
|
238
252
|
.join("\n\n");
|
|
239
253
|
}
|
|
240
|
-
// Use modified_data from the latest
|
|
254
|
+
// Use modified_data from the latest NEEDS_CHANGES
|
|
241
255
|
const latestNeedChanges = needChangesDecisions[0];
|
|
242
256
|
modified_data =
|
|
243
257
|
latestNeedChanges.modified_data || latestNeedChanges.modifiedData;
|
|
@@ -246,16 +260,14 @@ export class PollingService {
|
|
|
246
260
|
}
|
|
247
261
|
// Map task status response to decision status format
|
|
248
262
|
const mappedResponse = {
|
|
249
|
-
id:
|
|
263
|
+
id: fullTask.id || taskId,
|
|
250
264
|
status: status,
|
|
251
|
-
createdAt:
|
|
252
|
-
updatedAt:
|
|
253
|
-
feedback: feedback
|
|
254
|
-
modified_data: modified_data
|
|
255
|
-
statusResponse.modified_data ||
|
|
256
|
-
statusResponse.modifiedData,
|
|
265
|
+
createdAt: fullTask.createdAt || new Date().toISOString(),
|
|
266
|
+
updatedAt: fullTask.updatedAt || new Date().toISOString(),
|
|
267
|
+
feedback: feedback,
|
|
268
|
+
modified_data: modified_data,
|
|
257
269
|
};
|
|
258
|
-
this.logDebug("
|
|
270
|
+
this.logDebug("Status response received", {
|
|
259
271
|
taskId,
|
|
260
272
|
status: mappedResponse.status,
|
|
261
273
|
hasFeedback: !!mappedResponse.feedback,
|
|
@@ -272,7 +284,7 @@ export class PollingService {
|
|
|
272
284
|
case "REJECTED":
|
|
273
285
|
return "REFUSED";
|
|
274
286
|
case "NEEDS_CHANGES":
|
|
275
|
-
return "
|
|
287
|
+
return "NEEDS_CHANGES";
|
|
276
288
|
case "CANCELLED":
|
|
277
289
|
return "CANCELLED";
|
|
278
290
|
case "EXPIRED":
|
|
@@ -292,7 +304,7 @@ export class PollingService {
|
|
|
292
304
|
source: "loopman-langchain-sdk-typescript",
|
|
293
305
|
timestamp: new Date().toISOString(),
|
|
294
306
|
});
|
|
295
|
-
this.logDebug("
|
|
307
|
+
this.logDebug("Polling session started", { taskId });
|
|
296
308
|
}
|
|
297
309
|
catch (error) {
|
|
298
310
|
this.logWarn("Failed to start polling session", error);
|
|
@@ -309,7 +321,7 @@ export class PollingService {
|
|
|
309
321
|
reason,
|
|
310
322
|
timestamp: new Date().toISOString(),
|
|
311
323
|
});
|
|
312
|
-
this.logInfo("
|
|
324
|
+
this.logInfo("Polling session stopped", {
|
|
313
325
|
taskId,
|
|
314
326
|
reason,
|
|
315
327
|
});
|
|
@@ -332,7 +344,7 @@ export class PollingService {
|
|
|
332
344
|
timestamp: new Date().toISOString(),
|
|
333
345
|
},
|
|
334
346
|
});
|
|
335
|
-
this.logInfo("
|
|
347
|
+
this.logInfo("Interruption notified", {
|
|
336
348
|
taskId,
|
|
337
349
|
type,
|
|
338
350
|
});
|
|
@@ -342,6 +354,20 @@ export class PollingService {
|
|
|
342
354
|
// Non-critical - endpoint might not be implemented yet
|
|
343
355
|
}
|
|
344
356
|
}
|
|
357
|
+
/**
|
|
358
|
+
* Check if error is a 401 error (authentication error)
|
|
359
|
+
*/
|
|
360
|
+
is401Error(error) {
|
|
361
|
+
if (error instanceof Error) {
|
|
362
|
+
const message = error.message.toLowerCase();
|
|
363
|
+
return (message.includes("401") ||
|
|
364
|
+
message.includes("unauthorized") ||
|
|
365
|
+
message.includes("invalid or expired api key") ||
|
|
366
|
+
message.includes("invalid api key") ||
|
|
367
|
+
message.includes("authentication"));
|
|
368
|
+
}
|
|
369
|
+
return false;
|
|
370
|
+
}
|
|
345
371
|
/**
|
|
346
372
|
* Check if error is a 500 error (server-side issue)
|
|
347
373
|
*/
|
|
@@ -387,9 +413,6 @@ export class PollingService {
|
|
|
387
413
|
if (this.logger) {
|
|
388
414
|
this.logger.debug(message, data);
|
|
389
415
|
}
|
|
390
|
-
else if (this.debug) {
|
|
391
|
-
console.log("[PollingService]", message, data !== undefined ? data : "");
|
|
392
|
-
}
|
|
393
416
|
}
|
|
394
417
|
/**
|
|
395
418
|
* Log info message
|
|
@@ -398,9 +421,6 @@ export class PollingService {
|
|
|
398
421
|
if (this.logger) {
|
|
399
422
|
this.logger.info(message, data);
|
|
400
423
|
}
|
|
401
|
-
else if (this.debug) {
|
|
402
|
-
console.log("[PollingService]", message, data !== undefined ? data : "");
|
|
403
|
-
}
|
|
404
424
|
}
|
|
405
425
|
/**
|
|
406
426
|
* Log warning message
|
|
@@ -409,9 +429,6 @@ export class PollingService {
|
|
|
409
429
|
if (this.logger) {
|
|
410
430
|
this.logger.warn(message, data);
|
|
411
431
|
}
|
|
412
|
-
else {
|
|
413
|
-
console.warn("[PollingService]", message, data !== undefined ? data : "");
|
|
414
|
-
}
|
|
415
432
|
}
|
|
416
433
|
/**
|
|
417
434
|
* Log error message
|
|
@@ -420,9 +437,6 @@ export class PollingService {
|
|
|
420
437
|
if (this.logger) {
|
|
421
438
|
this.logger.error(message, data);
|
|
422
439
|
}
|
|
423
|
-
else {
|
|
424
|
-
console.error("[PollingService]", message, data !== undefined ? data : "");
|
|
425
|
-
}
|
|
426
440
|
}
|
|
427
441
|
}
|
|
428
442
|
//# sourceMappingURL=polling.service.js.map
|