@juspay/neurolink 7.38.0 → 7.39.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/CHANGELOG.md +12 -0
- package/dist/hitl/hitlErrors.d.ts +38 -0
- package/dist/hitl/hitlErrors.js +54 -0
- package/dist/hitl/hitlManager.d.ts +100 -0
- package/dist/hitl/hitlManager.js +457 -0
- package/dist/hitl/index.d.ts +8 -0
- package/dist/hitl/index.js +9 -0
- package/dist/hitl/types.d.ts +196 -0
- package/dist/hitl/types.js +8 -0
- package/dist/lib/hitl/hitlErrors.d.ts +38 -0
- package/dist/lib/hitl/hitlErrors.js +54 -0
- package/dist/lib/hitl/hitlManager.d.ts +100 -0
- package/dist/lib/hitl/hitlManager.js +457 -0
- package/dist/lib/hitl/index.d.ts +8 -0
- package/dist/lib/hitl/index.js +9 -0
- package/dist/lib/hitl/types.d.ts +196 -0
- package/dist/lib/hitl/types.js +8 -0
- package/dist/lib/mcp/externalServerManager.d.ts +11 -0
- package/dist/lib/mcp/externalServerManager.js +69 -2
- package/dist/lib/mcp/toolRegistry.d.ts +11 -0
- package/dist/lib/mcp/toolRegistry.js +69 -3
- package/dist/lib/neurolink.d.ts +27 -0
- package/dist/lib/neurolink.js +146 -0
- package/dist/lib/providers/openAI.js +2 -2
- package/dist/mcp/externalServerManager.d.ts +11 -0
- package/dist/mcp/externalServerManager.js +69 -2
- package/dist/mcp/toolRegistry.d.ts +11 -0
- package/dist/mcp/toolRegistry.js +69 -3
- package/dist/neurolink.d.ts +27 -0
- package/dist/neurolink.js +146 -0
- package/dist/providers/openAI.js +2 -2
- package/package.json +2 -2
@@ -0,0 +1,457 @@
|
|
1
|
+
/**
|
2
|
+
* HITL (Human-in-the-Loop) Manager
|
3
|
+
*
|
4
|
+
* Central orchestrator for all HITL confirmation workflows.
|
5
|
+
* Manages user confirmation requests, timeouts, and argument modifications
|
6
|
+
* for enterprise-grade AI safety.
|
7
|
+
*/
|
8
|
+
import { EventEmitter } from "events";
|
9
|
+
import { randomUUID } from "crypto";
|
10
|
+
import { HITLTimeoutError, HITLConfigurationError } from "./hitlErrors.js";
|
11
|
+
import { logger } from "../utils/logger.js";
|
12
|
+
/**
|
13
|
+
* HITLManager - Central orchestrator for Human-in-the-Loop safety mechanisms
|
14
|
+
*
|
15
|
+
* Features:
|
16
|
+
* - Real-time user confirmation via events
|
17
|
+
* - Configurable dangerous action detection
|
18
|
+
* - Custom rule engine for complex scenarios
|
19
|
+
* - Argument modification support
|
20
|
+
* - Comprehensive audit logging
|
21
|
+
* - Timeout handling with cleanup
|
22
|
+
*/
|
23
|
+
export class HITLManager extends EventEmitter {
|
24
|
+
config;
|
25
|
+
pendingConfirmations = new Map();
|
26
|
+
statistics = {
|
27
|
+
totalRequests: 0,
|
28
|
+
pendingRequests: 0,
|
29
|
+
averageResponseTime: 0,
|
30
|
+
approvedRequests: 0,
|
31
|
+
rejectedRequests: 0,
|
32
|
+
timedOutRequests: 0,
|
33
|
+
};
|
34
|
+
constructor(config) {
|
35
|
+
super();
|
36
|
+
this.config = this.validateConfig(config);
|
37
|
+
this.setupEventHandlers();
|
38
|
+
}
|
39
|
+
/**
|
40
|
+
* Validate HITL configuration and apply defaults
|
41
|
+
*/
|
42
|
+
validateConfig(config) {
|
43
|
+
// Apply defaults for optional fields
|
44
|
+
const configWithDefaults = {
|
45
|
+
enabled: config.enabled,
|
46
|
+
dangerousActions: config.dangerousActions,
|
47
|
+
timeout: config.timeout ?? 30000, // Default: 30 seconds
|
48
|
+
confirmationMethod: config.confirmationMethod ?? "event", // Default: "event"
|
49
|
+
allowArgumentModification: config.allowArgumentModification ?? true, // Default: true
|
50
|
+
autoApproveOnTimeout: config.autoApproveOnTimeout ?? false, // Default: false (safe)
|
51
|
+
auditLogging: config.auditLogging ?? false, // Default: false
|
52
|
+
customRules: config.customRules ?? [], // Default: empty array
|
53
|
+
};
|
54
|
+
if (!configWithDefaults.enabled) {
|
55
|
+
return configWithDefaults; // If disabled, don't validate other fields
|
56
|
+
}
|
57
|
+
if (!Array.isArray(configWithDefaults.dangerousActions)) {
|
58
|
+
throw new HITLConfigurationError("dangerousActions must be an array of strings");
|
59
|
+
}
|
60
|
+
if (typeof configWithDefaults.timeout !== "number" ||
|
61
|
+
configWithDefaults.timeout <= 0) {
|
62
|
+
throw new HITLConfigurationError("timeout must be a positive number (milliseconds)");
|
63
|
+
}
|
64
|
+
if (configWithDefaults.confirmationMethod !== "event") {
|
65
|
+
throw new HITLConfigurationError("confirmationMethod must be 'event' (only supported method)");
|
66
|
+
}
|
67
|
+
if (typeof configWithDefaults.allowArgumentModification !== "boolean") {
|
68
|
+
throw new HITLConfigurationError("allowArgumentModification must be a boolean");
|
69
|
+
}
|
70
|
+
return configWithDefaults;
|
71
|
+
}
|
72
|
+
/**
|
73
|
+
* Check if a tool requires confirmation based on configuration
|
74
|
+
*/
|
75
|
+
requiresConfirmation(toolName, args) {
|
76
|
+
if (!this.config.enabled) {
|
77
|
+
return false;
|
78
|
+
}
|
79
|
+
// Check dangerous actions keywords
|
80
|
+
const lowerToolName = toolName.toLowerCase();
|
81
|
+
for (const action of this.config.dangerousActions) {
|
82
|
+
if (lowerToolName.includes(action.toLowerCase())) {
|
83
|
+
return true;
|
84
|
+
}
|
85
|
+
}
|
86
|
+
// Check custom rules
|
87
|
+
if (this.config.customRules) {
|
88
|
+
for (const rule of this.config.customRules) {
|
89
|
+
if (rule.requiresConfirmation) {
|
90
|
+
try {
|
91
|
+
if (rule.condition(toolName, args)) {
|
92
|
+
return true;
|
93
|
+
}
|
94
|
+
}
|
95
|
+
catch (error) {
|
96
|
+
// Log rule evaluation error but don't fail
|
97
|
+
this.logAuditEvent("rule-evaluation-error", {
|
98
|
+
ruleName: rule.name,
|
99
|
+
toolName,
|
100
|
+
error: error instanceof Error ? error.message : String(error),
|
101
|
+
});
|
102
|
+
}
|
103
|
+
}
|
104
|
+
}
|
105
|
+
}
|
106
|
+
return false;
|
107
|
+
}
|
108
|
+
/**
|
109
|
+
* Request confirmation for a tool execution
|
110
|
+
*/
|
111
|
+
async requestConfirmation(toolName, arguments_, context) {
|
112
|
+
const confirmationId = this.generateConfirmationId();
|
113
|
+
const startTime = Date.now();
|
114
|
+
// Update statistics
|
115
|
+
this.statistics.totalRequests++;
|
116
|
+
this.statistics.pendingRequests++;
|
117
|
+
return new Promise((resolve, reject) => {
|
118
|
+
// Set up timeout
|
119
|
+
const timeoutHandle = setTimeout(() => {
|
120
|
+
this.handleTimeout(confirmationId);
|
121
|
+
}, this.config.timeout);
|
122
|
+
// Store pending confirmation
|
123
|
+
const request = {
|
124
|
+
confirmationId,
|
125
|
+
toolName,
|
126
|
+
arguments: arguments_,
|
127
|
+
timestamp: startTime,
|
128
|
+
timeoutHandle,
|
129
|
+
resolve,
|
130
|
+
reject,
|
131
|
+
};
|
132
|
+
this.pendingConfirmations.set(confirmationId, request);
|
133
|
+
// Create confirmation request event
|
134
|
+
const requestEvent = {
|
135
|
+
type: "hitl:confirmation-request",
|
136
|
+
payload: {
|
137
|
+
confirmationId,
|
138
|
+
toolName,
|
139
|
+
serverId: context?.serverId,
|
140
|
+
actionType: this.generateActionDescription(toolName, arguments_),
|
141
|
+
arguments: arguments_,
|
142
|
+
metadata: {
|
143
|
+
timestamp: new Date(startTime).toISOString(),
|
144
|
+
sessionId: context?.sessionId,
|
145
|
+
userId: context?.userId,
|
146
|
+
dangerousKeywords: this.getTriggeredKeywords(toolName, arguments_),
|
147
|
+
},
|
148
|
+
timeoutMs: this.config.timeout,
|
149
|
+
allowModification: this.config.allowArgumentModification,
|
150
|
+
},
|
151
|
+
};
|
152
|
+
// Emit confirmation request event
|
153
|
+
this.emit("hitl:confirmation-request", requestEvent);
|
154
|
+
// Log audit trail if enabled
|
155
|
+
if (this.config.auditLogging) {
|
156
|
+
this.logAuditEvent("confirmation-requested", {
|
157
|
+
confirmationId,
|
158
|
+
toolName,
|
159
|
+
userId: context?.userId,
|
160
|
+
sessionId: context?.sessionId,
|
161
|
+
timestamp: startTime,
|
162
|
+
arguments: arguments_,
|
163
|
+
});
|
164
|
+
}
|
165
|
+
});
|
166
|
+
}
|
167
|
+
/**
|
168
|
+
* Process user response to confirmation request
|
169
|
+
*/
|
170
|
+
processUserResponse(confirmationId, response) {
|
171
|
+
const request = this.pendingConfirmations.get(confirmationId);
|
172
|
+
if (!request) {
|
173
|
+
logger.warn(`No pending confirmation found for ID: ${confirmationId}`);
|
174
|
+
return;
|
175
|
+
}
|
176
|
+
// Clear timeout
|
177
|
+
clearTimeout(request.timeoutHandle);
|
178
|
+
// Remove from pending
|
179
|
+
this.pendingConfirmations.delete(confirmationId);
|
180
|
+
this.statistics.pendingRequests--;
|
181
|
+
// Calculate response time
|
182
|
+
const responseTime = response.responseTime || Date.now() - request.timestamp;
|
183
|
+
// Update statistics
|
184
|
+
if (response.approved) {
|
185
|
+
this.statistics.approvedRequests++;
|
186
|
+
}
|
187
|
+
else {
|
188
|
+
this.statistics.rejectedRequests++;
|
189
|
+
}
|
190
|
+
// Update average response time
|
191
|
+
const totalResponses = this.statistics.approvedRequests + this.statistics.rejectedRequests;
|
192
|
+
this.statistics.averageResponseTime =
|
193
|
+
(this.statistics.averageResponseTime * (totalResponses - 1) +
|
194
|
+
responseTime) /
|
195
|
+
totalResponses;
|
196
|
+
// Create result
|
197
|
+
const result = {
|
198
|
+
approved: response.approved,
|
199
|
+
reason: response.reason,
|
200
|
+
modifiedArguments: response.modifiedArguments,
|
201
|
+
responseTime,
|
202
|
+
};
|
203
|
+
// Log audit trail if enabled
|
204
|
+
if (this.config.auditLogging) {
|
205
|
+
this.logAuditEvent(response.approved ? "confirmation-approved" : "confirmation-rejected", {
|
206
|
+
confirmationId,
|
207
|
+
toolName: request.toolName,
|
208
|
+
approved: response.approved,
|
209
|
+
reason: response.reason,
|
210
|
+
userId: response.userId,
|
211
|
+
responseTime,
|
212
|
+
arguments: request.arguments,
|
213
|
+
});
|
214
|
+
}
|
215
|
+
// Resolve the promise
|
216
|
+
request.resolve(result);
|
217
|
+
}
|
218
|
+
/**
|
219
|
+
* Handle confirmation timeout
|
220
|
+
*/
|
221
|
+
handleTimeout(confirmationId) {
|
222
|
+
const request = this.pendingConfirmations.get(confirmationId);
|
223
|
+
if (!request) {
|
224
|
+
return;
|
225
|
+
}
|
226
|
+
// Remove from pending
|
227
|
+
this.pendingConfirmations.delete(confirmationId);
|
228
|
+
this.statistics.pendingRequests--;
|
229
|
+
this.statistics.timedOutRequests++;
|
230
|
+
// Calculate response time (timeout duration)
|
231
|
+
const responseTime = Date.now() - request.timestamp;
|
232
|
+
// Check if auto-approve on timeout is enabled
|
233
|
+
const shouldAutoApprove = this.config.autoApproveOnTimeout === true;
|
234
|
+
// Log audit trail if enabled
|
235
|
+
if (this.config.auditLogging) {
|
236
|
+
this.logAuditEvent("confirmation-timeout", {
|
237
|
+
confirmationId,
|
238
|
+
toolName: request.toolName,
|
239
|
+
timeout: this.config.timeout,
|
240
|
+
arguments: request.arguments,
|
241
|
+
autoApproved: shouldAutoApprove,
|
242
|
+
});
|
243
|
+
}
|
244
|
+
// Create timeout event
|
245
|
+
const timeoutEvent = {
|
246
|
+
type: "hitl:timeout",
|
247
|
+
payload: {
|
248
|
+
confirmationId,
|
249
|
+
toolName: request.toolName,
|
250
|
+
timeout: this.config.timeout,
|
251
|
+
},
|
252
|
+
};
|
253
|
+
// Emit timeout event
|
254
|
+
this.emit("hitl:timeout", timeoutEvent);
|
255
|
+
if (shouldAutoApprove) {
|
256
|
+
// Auto-approve the request
|
257
|
+
this.statistics.approvedRequests++;
|
258
|
+
// Update average response time
|
259
|
+
const totalResponses = this.statistics.approvedRequests + this.statistics.rejectedRequests;
|
260
|
+
this.statistics.averageResponseTime =
|
261
|
+
(this.statistics.averageResponseTime * (totalResponses - 1) +
|
262
|
+
responseTime) /
|
263
|
+
totalResponses;
|
264
|
+
// Log auto-approval if enabled
|
265
|
+
if (this.config.auditLogging) {
|
266
|
+
this.logAuditEvent("confirmation-auto-approved", {
|
267
|
+
confirmationId,
|
268
|
+
toolName: request.toolName,
|
269
|
+
reason: "Auto-approved due to timeout",
|
270
|
+
responseTime,
|
271
|
+
arguments: request.arguments,
|
272
|
+
});
|
273
|
+
}
|
274
|
+
// Resolve with auto-approval
|
275
|
+
const result = {
|
276
|
+
approved: true,
|
277
|
+
reason: "Auto-approved due to timeout",
|
278
|
+
responseTime,
|
279
|
+
};
|
280
|
+
request.resolve(result);
|
281
|
+
}
|
282
|
+
else {
|
283
|
+
// Reject with timeout error (original behavior)
|
284
|
+
request.reject(new HITLTimeoutError(`Confirmation timeout for tool: ${request.toolName}`, confirmationId, this.config.timeout));
|
285
|
+
}
|
286
|
+
}
|
287
|
+
/**
|
288
|
+
* Set up event handlers for processing responses
|
289
|
+
*/
|
290
|
+
setupEventHandlers() {
|
291
|
+
this.on("hitl:confirmation-response", (event) => {
|
292
|
+
if (event.payload?.confirmationId) {
|
293
|
+
this.processUserResponse(event.payload.confirmationId, {
|
294
|
+
approved: event.payload.approved,
|
295
|
+
reason: event.payload.reason,
|
296
|
+
modifiedArguments: event.payload.modifiedArguments,
|
297
|
+
responseTime: event.payload.metadata?.responseTime,
|
298
|
+
userId: event.payload.metadata?.userId,
|
299
|
+
});
|
300
|
+
}
|
301
|
+
});
|
302
|
+
}
|
303
|
+
/**
|
304
|
+
* Generate unique confirmation ID
|
305
|
+
*/
|
306
|
+
generateConfirmationId() {
|
307
|
+
return `hitl-${Date.now()}-${randomUUID()}`;
|
308
|
+
}
|
309
|
+
/**
|
310
|
+
* Generate human-readable action description
|
311
|
+
*/
|
312
|
+
generateActionDescription(toolName, args) {
|
313
|
+
const lowerToolName = toolName.toLowerCase();
|
314
|
+
// Check for specific action types
|
315
|
+
if (lowerToolName.includes("delete")) {
|
316
|
+
return "Delete Operation";
|
317
|
+
}
|
318
|
+
if (lowerToolName.includes("remove")) {
|
319
|
+
return "Remove Operation";
|
320
|
+
}
|
321
|
+
if (lowerToolName.includes("update")) {
|
322
|
+
return "Update Operation";
|
323
|
+
}
|
324
|
+
if (lowerToolName.includes("create")) {
|
325
|
+
return "Create Operation";
|
326
|
+
}
|
327
|
+
if (lowerToolName.includes("drop")) {
|
328
|
+
return "Drop Operation";
|
329
|
+
}
|
330
|
+
if (lowerToolName.includes("truncate")) {
|
331
|
+
return "Truncate Operation";
|
332
|
+
}
|
333
|
+
if (lowerToolName.includes("restart")) {
|
334
|
+
return "Restart Operation";
|
335
|
+
}
|
336
|
+
if (lowerToolName.includes("stop")) {
|
337
|
+
return "Stop Operation";
|
338
|
+
}
|
339
|
+
if (lowerToolName.includes("kill")) {
|
340
|
+
return "Kill Operation";
|
341
|
+
}
|
342
|
+
// Check custom rules for custom messages
|
343
|
+
if (this.config.customRules) {
|
344
|
+
for (const rule of this.config.customRules) {
|
345
|
+
try {
|
346
|
+
if (rule.condition(toolName, args) && rule.customMessage) {
|
347
|
+
return rule.customMessage;
|
348
|
+
}
|
349
|
+
}
|
350
|
+
catch {
|
351
|
+
// Ignore rule evaluation errors
|
352
|
+
}
|
353
|
+
}
|
354
|
+
}
|
355
|
+
return `Execute ${toolName}`;
|
356
|
+
}
|
357
|
+
/**
|
358
|
+
* Get keywords that triggered HITL
|
359
|
+
*/
|
360
|
+
getTriggeredKeywords(toolName, args) {
|
361
|
+
const triggered = [];
|
362
|
+
const lowerToolName = toolName.toLowerCase();
|
363
|
+
// Check dangerous actions
|
364
|
+
for (const action of this.config.dangerousActions) {
|
365
|
+
if (lowerToolName.includes(action.toLowerCase())) {
|
366
|
+
triggered.push(action);
|
367
|
+
}
|
368
|
+
}
|
369
|
+
// Check custom rules
|
370
|
+
if (this.config.customRules) {
|
371
|
+
for (const rule of this.config.customRules) {
|
372
|
+
try {
|
373
|
+
if (rule.requiresConfirmation && rule.condition(toolName, args)) {
|
374
|
+
triggered.push(rule.name);
|
375
|
+
}
|
376
|
+
}
|
377
|
+
catch {
|
378
|
+
// Ignore rule evaluation errors
|
379
|
+
}
|
380
|
+
}
|
381
|
+
}
|
382
|
+
return triggered;
|
383
|
+
}
|
384
|
+
/**
|
385
|
+
* Log audit events for compliance and debugging
|
386
|
+
*/
|
387
|
+
logAuditEvent(eventType, data) {
|
388
|
+
const auditLog = {
|
389
|
+
timestamp: new Date().toISOString(),
|
390
|
+
eventType: eventType,
|
391
|
+
toolName: data.toolName,
|
392
|
+
userId: data.userId,
|
393
|
+
sessionId: data.sessionId,
|
394
|
+
arguments: data.arguments,
|
395
|
+
reason: data.reason,
|
396
|
+
responseTime: data.responseTime,
|
397
|
+
...data,
|
398
|
+
};
|
399
|
+
logger.info(`[HITL Audit] ${eventType}:`, auditLog);
|
400
|
+
// Emit audit event for external logging systems
|
401
|
+
this.emit("hitl:audit", auditLog);
|
402
|
+
}
|
403
|
+
/**
|
404
|
+
* Get current HITL usage statistics
|
405
|
+
*/
|
406
|
+
getStatistics() {
|
407
|
+
return { ...this.statistics };
|
408
|
+
}
|
409
|
+
/**
|
410
|
+
* Get current configuration
|
411
|
+
*/
|
412
|
+
getConfig() {
|
413
|
+
return { ...this.config };
|
414
|
+
}
|
415
|
+
/**
|
416
|
+
* Update configuration (for dynamic reconfiguration)
|
417
|
+
*/
|
418
|
+
updateConfig(newConfig) {
|
419
|
+
const updatedConfig = { ...this.config, ...newConfig };
|
420
|
+
this.config = this.validateConfig(updatedConfig);
|
421
|
+
if (this.config.auditLogging) {
|
422
|
+
this.logAuditEvent("configuration-updated", {
|
423
|
+
oldConfig: this.config,
|
424
|
+
newConfig: updatedConfig,
|
425
|
+
});
|
426
|
+
}
|
427
|
+
}
|
428
|
+
/**
|
429
|
+
* Clean up resources and reject pending confirmations
|
430
|
+
*/
|
431
|
+
cleanup() {
|
432
|
+
// Clear all pending confirmations
|
433
|
+
for (const [confirmationId, request] of this.pendingConfirmations) {
|
434
|
+
clearTimeout(request.timeoutHandle);
|
435
|
+
request.reject(new Error(`HITL cleanup: confirmation ${confirmationId} cancelled`));
|
436
|
+
}
|
437
|
+
this.pendingConfirmations.clear();
|
438
|
+
this.statistics.pendingRequests = 0;
|
439
|
+
if (this.config.auditLogging) {
|
440
|
+
this.logAuditEvent("manager-cleanup", {
|
441
|
+
clearedConfirmations: this.pendingConfirmations.size,
|
442
|
+
});
|
443
|
+
}
|
444
|
+
}
|
445
|
+
/**
|
446
|
+
* Check if manager is currently enabled
|
447
|
+
*/
|
448
|
+
isEnabled() {
|
449
|
+
return this.config.enabled;
|
450
|
+
}
|
451
|
+
/**
|
452
|
+
* Get count of pending confirmations
|
453
|
+
*/
|
454
|
+
getPendingCount() {
|
455
|
+
return this.pendingConfirmations.size;
|
456
|
+
}
|
457
|
+
}
|
@@ -0,0 +1,8 @@
|
|
1
|
+
/**
|
2
|
+
* HITL (Human-in-the-Loop) Module
|
3
|
+
*
|
4
|
+
* Simple barrel export for HITL components.
|
5
|
+
*/
|
6
|
+
export { HITLManager } from "./hitlManager.js";
|
7
|
+
export type { HITLConfig, HITLRule, ConfirmationRequest, ConfirmationResult, ConfirmationRequestEvent, ConfirmationResponseEvent, ConfirmationTimeoutEvent, HITLStatistics, HITLAuditLog, } from "./types.js";
|
8
|
+
export { HITLError, HITLUserRejectedError, HITLTimeoutError, HITLConfigurationError, } from "./hitlErrors.js";
|
@@ -0,0 +1,9 @@
|
|
1
|
+
/**
|
2
|
+
* HITL (Human-in-the-Loop) Module
|
3
|
+
*
|
4
|
+
* Simple barrel export for HITL components.
|
5
|
+
*/
|
6
|
+
// Core HITL Manager
|
7
|
+
export { HITLManager } from "./hitlManager.js";
|
8
|
+
// Error Classes
|
9
|
+
export { HITLError, HITLUserRejectedError, HITLTimeoutError, HITLConfigurationError, } from "./hitlErrors.js";
|
@@ -0,0 +1,196 @@
|
|
1
|
+
/**
|
2
|
+
* HITL (Human-in-the-Loop) Type Definitions
|
3
|
+
*
|
4
|
+
* Comprehensive TypeScript interfaces for the HITL safety system.
|
5
|
+
* These types ensure type safety and provide clear contracts for
|
6
|
+
* all HITL-related functionality.
|
7
|
+
*/
|
8
|
+
/**
|
9
|
+
* Core HITL configuration interface
|
10
|
+
* Controls how the HITL system behaves and what tools require confirmation
|
11
|
+
*/
|
12
|
+
export interface HITLConfig {
|
13
|
+
/** Master enable/disable switch for HITL functionality */
|
14
|
+
enabled: boolean;
|
15
|
+
/** Keywords that trigger HITL confirmation (e.g., "delete", "remove", "drop") */
|
16
|
+
dangerousActions: string[];
|
17
|
+
/** Timeout in milliseconds for user confirmation (default: 30000) */
|
18
|
+
timeout?: number;
|
19
|
+
/** Communication method - currently only "event" is supported (default: "event") */
|
20
|
+
confirmationMethod?: "event";
|
21
|
+
/** Whether users can modify tool arguments during approval (default: true) */
|
22
|
+
allowArgumentModification?: boolean;
|
23
|
+
/** Auto-approve requests when they timeout (default: false - rejects on timeout) */
|
24
|
+
autoApproveOnTimeout?: boolean;
|
25
|
+
/** Enable audit logging for compliance and debugging (default: false) */
|
26
|
+
auditLogging?: boolean;
|
27
|
+
/** Advanced custom rules for complex tool scenarios (default: []) */
|
28
|
+
customRules?: HITLRule[];
|
29
|
+
}
|
30
|
+
/**
|
31
|
+
* Custom rule for advanced HITL scenarios
|
32
|
+
* Allows enterprises to define complex conditions for when tools require confirmation
|
33
|
+
*/
|
34
|
+
export interface HITLRule {
|
35
|
+
/** Human-readable name for the rule */
|
36
|
+
name: string;
|
37
|
+
/** Function that determines if a tool requires confirmation */
|
38
|
+
condition: (toolName: string, args: unknown) => boolean;
|
39
|
+
/** Whether this rule requires confirmation when triggered */
|
40
|
+
requiresConfirmation: boolean;
|
41
|
+
/** Custom message to show users when this rule is triggered */
|
42
|
+
customMessage?: string;
|
43
|
+
}
|
44
|
+
/**
|
45
|
+
* Internal confirmation request tracking
|
46
|
+
* Used by HITLManager to track pending confirmations
|
47
|
+
*/
|
48
|
+
export interface ConfirmationRequest {
|
49
|
+
/** Unique identifier for this confirmation request */
|
50
|
+
confirmationId: string;
|
51
|
+
/** Name of the tool requiring confirmation */
|
52
|
+
toolName: string;
|
53
|
+
/** Arguments that will be passed to the tool */
|
54
|
+
arguments: unknown;
|
55
|
+
/** Timestamp when the request was created */
|
56
|
+
timestamp: number;
|
57
|
+
/** Timeout handle for cleanup */
|
58
|
+
timeoutHandle: NodeJS.Timeout;
|
59
|
+
/** Promise resolve function */
|
60
|
+
resolve: (result: ConfirmationResult) => void;
|
61
|
+
/** Promise reject function */
|
62
|
+
reject: (error: Error) => void;
|
63
|
+
}
|
64
|
+
/**
|
65
|
+
* Result of a confirmation request
|
66
|
+
* Contains user decision and potentially modified arguments
|
67
|
+
*/
|
68
|
+
export interface ConfirmationResult {
|
69
|
+
/** Whether the user approved the tool execution */
|
70
|
+
approved: boolean;
|
71
|
+
/** Optional reason for rejection (if approved is false) */
|
72
|
+
reason?: string;
|
73
|
+
/** User-modified arguments (if allowArgumentModification is enabled) */
|
74
|
+
modifiedArguments?: unknown;
|
75
|
+
/** Time taken for user to respond in milliseconds */
|
76
|
+
responseTime: number;
|
77
|
+
}
|
78
|
+
/**
|
79
|
+
* Event payload for confirmation requests
|
80
|
+
* Sent to frontends via EventEmitter when tool needs approval
|
81
|
+
*/
|
82
|
+
export interface ConfirmationRequestEvent {
|
83
|
+
type: "hitl:confirmation-request";
|
84
|
+
payload: {
|
85
|
+
/** Unique ID for tracking this request */
|
86
|
+
confirmationId: string;
|
87
|
+
/** Name of the tool requiring confirmation */
|
88
|
+
toolName: string;
|
89
|
+
/** MCP server ID (if this is an external tool) */
|
90
|
+
serverId?: string;
|
91
|
+
/** Human-readable description of the action */
|
92
|
+
actionType: string;
|
93
|
+
/** Tool parameters for user review */
|
94
|
+
arguments: unknown;
|
95
|
+
/** Additional metadata about the request */
|
96
|
+
metadata: {
|
97
|
+
/** ISO timestamp when request was created */
|
98
|
+
timestamp: string;
|
99
|
+
/** User session identifier */
|
100
|
+
sessionId?: string;
|
101
|
+
/** User identifier */
|
102
|
+
userId?: string;
|
103
|
+
/** Keywords that triggered HITL */
|
104
|
+
dangerousKeywords: string[];
|
105
|
+
};
|
106
|
+
/** Confirmation timeout in milliseconds */
|
107
|
+
timeoutMs: number;
|
108
|
+
/** Whether user can modify arguments */
|
109
|
+
allowModification: boolean;
|
110
|
+
};
|
111
|
+
}
|
112
|
+
/**
|
113
|
+
* Event payload for confirmation responses
|
114
|
+
* Sent from frontends back to HITLManager with user decision
|
115
|
+
*/
|
116
|
+
export interface ConfirmationResponseEvent {
|
117
|
+
type: "hitl:confirmation-response";
|
118
|
+
payload: {
|
119
|
+
/** Matching confirmation ID from the request */
|
120
|
+
confirmationId: string;
|
121
|
+
/** User's approval decision */
|
122
|
+
approved: boolean;
|
123
|
+
/** Optional reason for rejection */
|
124
|
+
reason?: string;
|
125
|
+
/** User-edited parameters (if modification allowed) */
|
126
|
+
modifiedArguments?: unknown;
|
127
|
+
/** Response metadata */
|
128
|
+
metadata: {
|
129
|
+
/** ISO timestamp when user responded */
|
130
|
+
timestamp: string;
|
131
|
+
/** Time taken to respond in milliseconds */
|
132
|
+
responseTime: number;
|
133
|
+
/** User who made the decision */
|
134
|
+
userId?: string;
|
135
|
+
};
|
136
|
+
};
|
137
|
+
}
|
138
|
+
/**
|
139
|
+
* Event payload for confirmation timeouts
|
140
|
+
* Emitted when user doesn't respond within timeout period
|
141
|
+
*/
|
142
|
+
export interface ConfirmationTimeoutEvent {
|
143
|
+
type: "hitl:timeout";
|
144
|
+
payload: {
|
145
|
+
/** Confirmation ID that timed out */
|
146
|
+
confirmationId: string;
|
147
|
+
/** Tool name that timed out */
|
148
|
+
toolName: string;
|
149
|
+
/** Timeout duration in milliseconds */
|
150
|
+
timeout: number;
|
151
|
+
};
|
152
|
+
}
|
153
|
+
/**
|
154
|
+
* HITL audit log entry
|
155
|
+
* Used for compliance and debugging purposes
|
156
|
+
*/
|
157
|
+
export interface HITLAuditLog {
|
158
|
+
/** ISO timestamp of the event */
|
159
|
+
timestamp: string;
|
160
|
+
/** Type of HITL event */
|
161
|
+
eventType: "confirmation-requested" | "confirmation-approved" | "confirmation-rejected" | "confirmation-timeout" | "confirmation-auto-approved";
|
162
|
+
/** Tool that was involved */
|
163
|
+
toolName: string;
|
164
|
+
/** User who made the decision (if applicable) */
|
165
|
+
userId?: string;
|
166
|
+
/** Session identifier */
|
167
|
+
sessionId?: string;
|
168
|
+
/** Tool arguments (may be sanitized for security) */
|
169
|
+
arguments: unknown;
|
170
|
+
/** Reason for rejection (if applicable) */
|
171
|
+
reason?: string;
|
172
|
+
/** IP address of the user (if available) */
|
173
|
+
ipAddress?: string;
|
174
|
+
/** User agent string (if available) */
|
175
|
+
userAgent?: string;
|
176
|
+
/** Response time in milliseconds (if applicable) */
|
177
|
+
responseTime?: number;
|
178
|
+
}
|
179
|
+
/**
|
180
|
+
* HITL statistics interface
|
181
|
+
* Provides metrics about HITL usage for monitoring
|
182
|
+
*/
|
183
|
+
export interface HITLStatistics {
|
184
|
+
/** Total number of confirmation requests made */
|
185
|
+
totalRequests: number;
|
186
|
+
/** Number of pending confirmations */
|
187
|
+
pendingRequests: number;
|
188
|
+
/** Average response time for user decisions */
|
189
|
+
averageResponseTime: number;
|
190
|
+
/** Number of approved requests */
|
191
|
+
approvedRequests: number;
|
192
|
+
/** Number of rejected requests */
|
193
|
+
rejectedRequests: number;
|
194
|
+
/** Number of timed out requests */
|
195
|
+
timedOutRequests: number;
|
196
|
+
}
|