sub-agents-mcp 0.1.2

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 (75) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +265 -0
  3. package/dist/agents/AgentManager.d.ts +58 -0
  4. package/dist/agents/AgentManager.d.ts.map +1 -0
  5. package/dist/agents/AgentManager.js +182 -0
  6. package/dist/agents/AgentManager.js.map +1 -0
  7. package/dist/config/ServerConfig.d.ts +34 -0
  8. package/dist/config/ServerConfig.d.ts.map +1 -0
  9. package/dist/config/ServerConfig.js +54 -0
  10. package/dist/config/ServerConfig.js.map +1 -0
  11. package/dist/execution/AgentExecutor.d.ts +114 -0
  12. package/dist/execution/AgentExecutor.d.ts.map +1 -0
  13. package/dist/execution/AgentExecutor.js +234 -0
  14. package/dist/execution/AgentExecutor.js.map +1 -0
  15. package/dist/execution/ExecutionLimits.d.ts +141 -0
  16. package/dist/execution/ExecutionLimits.d.ts.map +1 -0
  17. package/dist/execution/ExecutionLimits.js +231 -0
  18. package/dist/execution/ExecutionLimits.js.map +1 -0
  19. package/dist/execution/McpRequestTimeout.d.ts +166 -0
  20. package/dist/execution/McpRequestTimeout.d.ts.map +1 -0
  21. package/dist/execution/McpRequestTimeout.js +278 -0
  22. package/dist/execution/McpRequestTimeout.js.map +1 -0
  23. package/dist/execution/PromptController.d.ts +92 -0
  24. package/dist/execution/PromptController.d.ts.map +1 -0
  25. package/dist/execution/PromptController.js +130 -0
  26. package/dist/execution/PromptController.js.map +1 -0
  27. package/dist/execution/StreamProcessor.d.ts +23 -0
  28. package/dist/execution/StreamProcessor.d.ts.map +1 -0
  29. package/dist/execution/StreamProcessor.js +51 -0
  30. package/dist/execution/StreamProcessor.js.map +1 -0
  31. package/dist/execution/TimeoutManager.d.ts +159 -0
  32. package/dist/execution/TimeoutManager.d.ts.map +1 -0
  33. package/dist/execution/TimeoutManager.js +283 -0
  34. package/dist/execution/TimeoutManager.js.map +1 -0
  35. package/dist/index.d.ts +10 -0
  36. package/dist/index.d.ts.map +1 -0
  37. package/dist/index.js +51 -0
  38. package/dist/index.js.map +1 -0
  39. package/dist/resources/AgentResources.d.ts +104 -0
  40. package/dist/resources/AgentResources.d.ts.map +1 -0
  41. package/dist/resources/AgentResources.js +315 -0
  42. package/dist/resources/AgentResources.js.map +1 -0
  43. package/dist/server/McpServer.d.ts +138 -0
  44. package/dist/server/McpServer.d.ts.map +1 -0
  45. package/dist/server/McpServer.js +373 -0
  46. package/dist/server/McpServer.js.map +1 -0
  47. package/dist/tools/RunAgentTool.d.ts +140 -0
  48. package/dist/tools/RunAgentTool.d.ts.map +1 -0
  49. package/dist/tools/RunAgentTool.js +371 -0
  50. package/dist/tools/RunAgentTool.js.map +1 -0
  51. package/dist/types/AgentDefinition.d.ts +33 -0
  52. package/dist/types/AgentDefinition.d.ts.map +1 -0
  53. package/dist/types/AgentDefinition.js +3 -0
  54. package/dist/types/AgentDefinition.js.map +1 -0
  55. package/dist/types/ExecutionParams.d.ts +48 -0
  56. package/dist/types/ExecutionParams.d.ts.map +1 -0
  57. package/dist/types/ExecutionParams.js +3 -0
  58. package/dist/types/ExecutionParams.js.map +1 -0
  59. package/dist/types/ServerConfig.d.ts +39 -0
  60. package/dist/types/ServerConfig.d.ts.map +1 -0
  61. package/dist/types/ServerConfig.js +3 -0
  62. package/dist/types/ServerConfig.js.map +1 -0
  63. package/dist/types/index.d.ts +19 -0
  64. package/dist/types/index.d.ts.map +1 -0
  65. package/dist/types/index.js +3 -0
  66. package/dist/types/index.js.map +1 -0
  67. package/dist/utils/ErrorHandler.d.ts +86 -0
  68. package/dist/utils/ErrorHandler.d.ts.map +1 -0
  69. package/dist/utils/ErrorHandler.js +99 -0
  70. package/dist/utils/ErrorHandler.js.map +1 -0
  71. package/dist/utils/Logger.d.ts +99 -0
  72. package/dist/utils/Logger.d.ts.map +1 -0
  73. package/dist/utils/Logger.js +151 -0
  74. package/dist/utils/Logger.js.map +1 -0
  75. package/package.json +92 -0
@@ -0,0 +1,231 @@
1
+ "use strict";
2
+ /**
3
+ * Execution limits configuration and enforcement for agent execution.
4
+ *
5
+ * Provides configurable limits for resource usage including memory, concurrency,
6
+ * execution time, and output size to ensure system stability and prevent abuse.
7
+ */
8
+ Object.defineProperty(exports, "__esModule", { value: true });
9
+ exports.ExecutionLimits = exports.DEFAULT_EXECUTION_LIMITS = void 0;
10
+ const ErrorHandler_1 = require("../utils/ErrorHandler");
11
+ /**
12
+ * Default execution limits configuration.
13
+ */
14
+ exports.DEFAULT_EXECUTION_LIMITS = {
15
+ maxConcurrentExecutions: 5,
16
+ maxMemoryUsageMB: 100,
17
+ maxOutputSizeBytes: 1024 * 1024, // 1MB
18
+ maxExecutionTimeMs: 90000, // 90 seconds
19
+ enableResourceMonitoring: true,
20
+ };
21
+ /**
22
+ * Execution limits enforcer for resource constraint management.
23
+ *
24
+ * Monitors and enforces limits on concurrent executions, memory usage,
25
+ * output size, and execution time to prevent resource exhaustion.
26
+ */
27
+ class ExecutionLimits {
28
+ /**
29
+ * Creates a new ExecutionLimits instance.
30
+ *
31
+ * @param config - Execution limits configuration (uses defaults if not provided)
32
+ */
33
+ constructor(config = {}) {
34
+ this.activeExecutions = new Set();
35
+ this.config = { ...exports.DEFAULT_EXECUTION_LIMITS, ...config };
36
+ }
37
+ /**
38
+ * Checks if a new execution can be started within limits.
39
+ *
40
+ * @param executionId - Unique identifier for the execution
41
+ * @throws {ResourceLimitError} When concurrent execution limit is exceeded
42
+ */
43
+ checkConcurrencyLimit(executionId) {
44
+ if (this.activeExecutions.size >= this.config.maxConcurrentExecutions) {
45
+ throw new ErrorHandler_1.ResourceLimitError(`Maximum concurrent executions exceeded: ${this.config.maxConcurrentExecutions}`, 'CONCURRENCY_LIMIT_EXCEEDED', 'concurrency', this.config.maxConcurrentExecutions, {
46
+ operation: 'concurrency_check',
47
+ metadata: { executionId, currentCount: this.activeExecutions.size },
48
+ });
49
+ }
50
+ }
51
+ /**
52
+ * Registers a new execution as active.
53
+ *
54
+ * @param executionId - Unique identifier for the execution
55
+ */
56
+ registerExecution(executionId) {
57
+ this.checkConcurrencyLimit(executionId);
58
+ this.activeExecutions.add(executionId);
59
+ }
60
+ /**
61
+ * Unregisters an execution as completed.
62
+ *
63
+ * @param executionId - Unique identifier for the execution
64
+ */
65
+ unregisterExecution(executionId) {
66
+ this.activeExecutions.delete(executionId);
67
+ }
68
+ /**
69
+ * Checks if memory usage is within limits.
70
+ *
71
+ * @param memoryUsageMB - Current memory usage in MB
72
+ * @throws {ResourceLimitError} When memory limit is exceeded
73
+ */
74
+ checkMemoryLimit(memoryUsageMB) {
75
+ if (memoryUsageMB > this.config.maxMemoryUsageMB) {
76
+ throw new ErrorHandler_1.ResourceLimitError(`Memory usage exceeded: ${memoryUsageMB}MB > ${this.config.maxMemoryUsageMB}MB`, 'MEMORY_LIMIT_EXCEEDED', 'memory', this.config.maxMemoryUsageMB);
77
+ }
78
+ }
79
+ /**
80
+ * Checks if output size is within limits.
81
+ *
82
+ * @param outputSizeBytes - Current output size in bytes
83
+ * @throws {ResourceLimitError} When output size limit is exceeded
84
+ */
85
+ checkOutputSizeLimit(outputSizeBytes) {
86
+ if (outputSizeBytes > this.config.maxOutputSizeBytes) {
87
+ throw new ErrorHandler_1.ResourceLimitError(`Output size exceeded: ${outputSizeBytes} bytes > ${this.config.maxOutputSizeBytes} bytes`, 'OUTPUT_SIZE_LIMIT_EXCEEDED', 'output_size', this.config.maxOutputSizeBytes);
88
+ }
89
+ }
90
+ /**
91
+ * Gets current resource usage statistics.
92
+ *
93
+ * @param currentMemoryMB - Current memory usage in MB
94
+ * @param currentOutputBytes - Current output size in bytes
95
+ * @param executionTimeMs - Current execution time in milliseconds
96
+ * @returns Resource usage statistics
97
+ */
98
+ getResourceUsage(currentMemoryMB = 0, currentOutputBytes = 0, executionTimeMs = 0) {
99
+ return {
100
+ memoryUsageMB: currentMemoryMB,
101
+ activeExecutions: this.activeExecutions.size,
102
+ outputSizeBytes: currentOutputBytes,
103
+ executionTimeMs,
104
+ };
105
+ }
106
+ /**
107
+ * Gets the current configuration.
108
+ *
109
+ * @returns Execution limits configuration
110
+ */
111
+ getConfig() {
112
+ return { ...this.config };
113
+ }
114
+ /**
115
+ * Gets the number of active executions.
116
+ *
117
+ * @returns Number of active executions
118
+ */
119
+ getActiveExecutionCount() {
120
+ return this.activeExecutions.size;
121
+ }
122
+ /**
123
+ * Checks if resource monitoring is enabled.
124
+ *
125
+ * @returns True if resource monitoring is enabled
126
+ */
127
+ isResourceMonitoringEnabled() {
128
+ return this.config.enableResourceMonitoring;
129
+ }
130
+ /**
131
+ * Gets adaptive resource limits based on current system state.
132
+ *
133
+ * @param systemMemoryMB - Current available system memory in MB
134
+ * @param systemLoad - Current system load (0-1)
135
+ * @returns Adjusted execution limits configuration
136
+ */
137
+ getAdaptiveLimits(systemMemoryMB, systemLoad = 0.5) {
138
+ const baseLimits = this.getConfig();
139
+ // Adjust limits based on available system resources
140
+ const memoryMultiplier = Math.min(systemMemoryMB / 1000, 2); // Scale up to 2x for high memory systems
141
+ const loadMultiplier = Math.max(1 - systemLoad, 0.3); // Reduce limits under high load
142
+ return {
143
+ ...baseLimits,
144
+ maxConcurrentExecutions: Math.max(Math.floor(baseLimits.maxConcurrentExecutions * loadMultiplier), 1),
145
+ maxMemoryUsageMB: Math.floor(baseLimits.maxMemoryUsageMB * memoryMultiplier),
146
+ maxExecutionTimeMs: systemLoad > 0.8
147
+ ? Math.floor(baseLimits.maxExecutionTimeMs * 1.5) // More time under high load
148
+ : baseLimits.maxExecutionTimeMs,
149
+ };
150
+ }
151
+ /**
152
+ * Monitors resource usage and suggests optimizations.
153
+ *
154
+ * @param currentUsage - Current resource usage
155
+ * @returns Resource optimization suggestions
156
+ */
157
+ analyzeResourceUsage(currentUsage) {
158
+ const config = this.getConfig();
159
+ const recommendations = [];
160
+ let severity = 'low';
161
+ let shouldThrottle = false;
162
+ // Analyze concurrency
163
+ const concurrencyUtilization = currentUsage.activeExecutions / config.maxConcurrentExecutions;
164
+ if (concurrencyUtilization > 0.8) {
165
+ recommendations.push('High concurrency utilization detected - consider queuing new requests');
166
+ severity = 'medium';
167
+ shouldThrottle = true;
168
+ }
169
+ // Analyze memory usage
170
+ const memoryUtilization = currentUsage.memoryUsageMB / config.maxMemoryUsageMB;
171
+ if (memoryUtilization > 0.9) {
172
+ recommendations.push('Memory usage approaching limit - consider reducing concurrent executions');
173
+ severity = 'high';
174
+ shouldThrottle = true;
175
+ }
176
+ else if (memoryUtilization > 0.7) {
177
+ recommendations.push('Memory usage elevated - monitor closely');
178
+ if (severity === 'low')
179
+ severity = 'medium';
180
+ }
181
+ // Analyze output size trends
182
+ const outputUtilization = currentUsage.outputSizeBytes / config.maxOutputSizeBytes;
183
+ if (outputUtilization > 0.8) {
184
+ recommendations.push('Output size approaching limit - consider using spawn method for large outputs');
185
+ if (severity === 'low')
186
+ severity = 'medium';
187
+ }
188
+ // Analyze execution time
189
+ if (currentUsage.executionTimeMs > config.maxExecutionTimeMs * 0.8) {
190
+ recommendations.push('Execution time approaching timeout - consider optimizing agent performance');
191
+ if (severity === 'low')
192
+ severity = 'medium';
193
+ }
194
+ return {
195
+ recommendations,
196
+ severity,
197
+ shouldThrottle,
198
+ };
199
+ }
200
+ /**
201
+ * Creates execution limits optimized for specific operation types.
202
+ *
203
+ * @param operationType - Type of operation (light, standard, heavy)
204
+ * @returns Optimized execution limits configuration
205
+ */
206
+ createOptimizedConfig(operationType) {
207
+ const baseLimits = exports.DEFAULT_EXECUTION_LIMITS;
208
+ switch (operationType) {
209
+ case 'light':
210
+ return {
211
+ ...baseLimits,
212
+ maxConcurrentExecutions: baseLimits.maxConcurrentExecutions * 2,
213
+ maxMemoryUsageMB: baseLimits.maxMemoryUsageMB * 0.5,
214
+ maxExecutionTimeMs: baseLimits.maxExecutionTimeMs * 0.5,
215
+ maxOutputSizeBytes: baseLimits.maxOutputSizeBytes * 0.5,
216
+ };
217
+ case 'heavy':
218
+ return {
219
+ ...baseLimits,
220
+ maxConcurrentExecutions: Math.max(baseLimits.maxConcurrentExecutions * 0.5, 1),
221
+ maxMemoryUsageMB: baseLimits.maxMemoryUsageMB * 2,
222
+ maxExecutionTimeMs: baseLimits.maxExecutionTimeMs * 2,
223
+ maxOutputSizeBytes: baseLimits.maxOutputSizeBytes * 2,
224
+ };
225
+ default: // standard
226
+ return baseLimits;
227
+ }
228
+ }
229
+ }
230
+ exports.ExecutionLimits = ExecutionLimits;
231
+ //# sourceMappingURL=ExecutionLimits.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"ExecutionLimits.js","sourceRoot":"","sources":["../../src/execution/ExecutionLimits.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,166 @@
1
+ import { Logger } from '../utils/Logger';
2
+ /**
3
+ * Configuration for MCP request timeout management
4
+ * Following MCP specification recommendations for handling long-running LLM operations
5
+ */
6
+ export interface McpTimeoutConfig {
7
+ /**
8
+ * Default timeout for MCP requests in milliseconds
9
+ * Considering LLM processing characteristics, set to 2 minutes by default
10
+ */
11
+ defaultTimeoutMs: number;
12
+ /**
13
+ * Maximum absolute timeout in milliseconds
14
+ * Prevents infinite waiting even with progress updates (5 minutes by default)
15
+ */
16
+ maxTimeoutMs: number;
17
+ /**
18
+ * Whether to reset timeout when progress notification is received
19
+ * Recommended by MCP specification for long-running operations
20
+ */
21
+ progressResetEnabled: boolean;
22
+ /**
23
+ * Warning threshold in milliseconds
24
+ * Sends progress notification to improve UX (1 minute by default)
25
+ */
26
+ warningThresholdMs: number;
27
+ /**
28
+ * Enable debug logging for timeout operations
29
+ */
30
+ enableDebugLogging: boolean;
31
+ }
32
+ /**
33
+ * Default timeout configuration for MCP requests
34
+ * Based on MCP best practices and LLM operation characteristics
35
+ */
36
+ export declare const DEFAULT_MCP_TIMEOUT_CONFIG: McpTimeoutConfig;
37
+ /**
38
+ * Progress notification data for MCP requests
39
+ */
40
+ export interface ProgressNotification {
41
+ requestId: string;
42
+ message: string;
43
+ percentage?: number;
44
+ timestamp: number;
45
+ }
46
+ /**
47
+ * Timeout context for tracking request execution
48
+ */
49
+ export interface TimeoutContext {
50
+ requestId: string;
51
+ startTime: number;
52
+ currentTimeout: NodeJS.Timeout | null;
53
+ warningTimeout: NodeJS.Timeout | null;
54
+ maxTimeout: NodeJS.Timeout | null;
55
+ progressCount: number;
56
+ lastProgressTime: number;
57
+ isCompleted: boolean;
58
+ isCancelled: boolean;
59
+ onTimeout?: TimeoutCallback;
60
+ onProgress?: ProgressCallback;
61
+ }
62
+ /**
63
+ * Callback for handling timeout events
64
+ */
65
+ export type TimeoutCallback = (context: TimeoutContext) => void;
66
+ /**
67
+ * Callback for sending progress notifications
68
+ */
69
+ export type ProgressCallback = (notification: ProgressNotification) => void;
70
+ /**
71
+ * McpRequestTimeout manages timeout behavior for MCP server requests
72
+ * Implements MCP specification recommendations for handling long-running operations
73
+ *
74
+ * This class handles AI -> MCP level timeouts, separate from MCP -> AI (AgentExecutor) timeouts
75
+ * Following MCP best practices:
76
+ * - Progressive timeout with reset on progress
77
+ * - Maximum absolute timeout enforcement
78
+ * - Progress notifications for better UX
79
+ * - Graceful cancellation support
80
+ */
81
+ export declare class McpRequestTimeout {
82
+ private readonly config;
83
+ private readonly logger;
84
+ private readonly contexts;
85
+ /**
86
+ * Creates a new McpRequestTimeout instance
87
+ *
88
+ * @param config - Optional timeout configuration
89
+ * @param logger - Optional logger instance
90
+ */
91
+ constructor(config?: Partial<McpTimeoutConfig>, logger?: Logger);
92
+ /**
93
+ * Start timeout tracking for a request
94
+ *
95
+ * @param requestId - Unique request identifier
96
+ * @param onTimeout - Callback when timeout occurs
97
+ * @param onProgress - Optional callback for progress notifications
98
+ * @returns TimeoutContext for the request
99
+ */
100
+ startTimeout(requestId: string, onTimeout: TimeoutCallback, onProgress?: ProgressCallback): TimeoutContext;
101
+ /**
102
+ * Report progress and optionally reset timeout
103
+ * Following MCP specification: MAY reset timeout on progress, but enforce maximum
104
+ *
105
+ * @param requestId - Request identifier
106
+ * @param message - Progress message
107
+ * @param percentage - Optional completion percentage
108
+ */
109
+ reportProgress(requestId: string, message: string, percentage?: number): void;
110
+ /**
111
+ * Mark request as completed and clear timeouts
112
+ *
113
+ * @param requestId - Request identifier
114
+ */
115
+ complete(requestId: string): void;
116
+ /**
117
+ * Cancel request and clear timeouts
118
+ * Following MCP specification for cancellation
119
+ *
120
+ * @param requestId - Request identifier
121
+ * @param reason - Cancellation reason
122
+ */
123
+ cancel(requestId: string, reason: string): void;
124
+ /**
125
+ * Clear timeout for a request
126
+ *
127
+ * @param requestId - Request identifier
128
+ */
129
+ clearTimeout(requestId: string): void;
130
+ /**
131
+ * Check if request has timed out
132
+ *
133
+ * @param requestId - Request identifier
134
+ * @returns true if timed out
135
+ */
136
+ hasTimedOut(requestId: string): boolean;
137
+ /**
138
+ * Get timeout statistics for monitoring
139
+ *
140
+ * @returns Current timeout statistics
141
+ */
142
+ getStats(): {
143
+ activeRequests: number;
144
+ averageProgressCount: number;
145
+ longestRunningMs: number;
146
+ };
147
+ /**
148
+ * Handle timeout event
149
+ *
150
+ * @private
151
+ */
152
+ private handleTimeout;
153
+ /**
154
+ * Send progress notification
155
+ *
156
+ * @private
157
+ */
158
+ private sendProgressNotification;
159
+ /**
160
+ * Clear all timeouts for a context
161
+ *
162
+ * @private
163
+ */
164
+ private clearTimeouts;
165
+ }
166
+ //# sourceMappingURL=McpRequestTimeout.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"McpRequestTimeout.d.ts","sourceRoot":"","sources":["../../src/execution/McpRequestTimeout.ts"],"names":[],"mappings":"AAAA,OAAO,EAAiB,MAAM,EAAE,MAAM,kBAAkB,CAAA;AAExD;;;GAGG;AACH,MAAM,WAAW,gBAAgB;IAC/B;;;OAGG;IACH,gBAAgB,EAAE,MAAM,CAAA;IAExB;;;OAGG;IACH,YAAY,EAAE,MAAM,CAAA;IAEpB;;;OAGG;IACH,oBAAoB,EAAE,OAAO,CAAA;IAE7B;;;OAGG;IACH,kBAAkB,EAAE,MAAM,CAAA;IAE1B;;OAEG;IACH,kBAAkB,EAAE,OAAO,CAAA;CAC5B;AAED;;;GAGG;AACH,eAAO,MAAM,0BAA0B,EAAE,gBAMxC,CAAA;AAED;;GAEG;AACH,MAAM,WAAW,oBAAoB;IACnC,SAAS,EAAE,MAAM,CAAA;IACjB,OAAO,EAAE,MAAM,CAAA;IACf,UAAU,CAAC,EAAE,MAAM,CAAA;IACnB,SAAS,EAAE,MAAM,CAAA;CAClB;AAED;;GAEG;AACH,MAAM,WAAW,cAAc;IAC7B,SAAS,EAAE,MAAM,CAAA;IACjB,SAAS,EAAE,MAAM,CAAA;IACjB,cAAc,EAAE,MAAM,CAAC,OAAO,GAAG,IAAI,CAAA;IACrC,cAAc,EAAE,MAAM,CAAC,OAAO,GAAG,IAAI,CAAA;IACrC,UAAU,EAAE,MAAM,CAAC,OAAO,GAAG,IAAI,CAAA;IACjC,aAAa,EAAE,MAAM,CAAA;IACrB,gBAAgB,EAAE,MAAM,CAAA;IACxB,WAAW,EAAE,OAAO,CAAA;IACpB,WAAW,EAAE,OAAO,CAAA;IACpB,SAAS,CAAC,EAAE,eAAe,CAAA;IAC3B,UAAU,CAAC,EAAE,gBAAgB,CAAA;CAC9B;AAED;;GAEG;AACH,MAAM,MAAM,eAAe,GAAG,CAAC,OAAO,EAAE,cAAc,KAAK,IAAI,CAAA;AAE/D;;GAEG;AACH,MAAM,MAAM,gBAAgB,GAAG,CAAC,YAAY,EAAE,oBAAoB,KAAK,IAAI,CAAA;AAE3E;;;;;;;;;;GAUG;AACH,qBAAa,iBAAiB;IAC5B,OAAO,CAAC,QAAQ,CAAC,MAAM,CAAkB;IACzC,OAAO,CAAC,QAAQ,CAAC,MAAM,CAAQ;IAC/B,OAAO,CAAC,QAAQ,CAAC,QAAQ,CAAyC;IAElE;;;;;OAKG;gBACS,MAAM,CAAC,EAAE,OAAO,CAAC,gBAAgB,CAAC,EAAE,MAAM,CAAC,EAAE,MAAM;IAK/D;;;;;;;OAOG;IACH,YAAY,CACV,SAAS,EAAE,MAAM,EACjB,SAAS,EAAE,eAAe,EAC1B,UAAU,CAAC,EAAE,gBAAgB,GAC5B,cAAc;IA+DjB;;;;;;;OAOG;IACH,cAAc,CAAC,SAAS,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,EAAE,UAAU,CAAC,EAAE,MAAM,GAAG,IAAI;IA4C7E;;;;OAIG;IACH,QAAQ,CAAC,SAAS,EAAE,MAAM,GAAG,IAAI;IAmBjC;;;;;;OAMG;IACH,MAAM,CAAC,SAAS,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,GAAG,IAAI;IAkB/C;;;;OAIG;IACH,YAAY,CAAC,SAAS,EAAE,MAAM,GAAG,IAAI;IAQrC;;;;;OAKG;IACH,WAAW,CAAC,SAAS,EAAE,MAAM,GAAG,OAAO;IAUvC;;;;OAIG;IACH,QAAQ,IAAI;QACV,cAAc,EAAE,MAAM,CAAA;QACtB,oBAAoB,EAAE,MAAM,CAAA;QAC5B,gBAAgB,EAAE,MAAM,CAAA;KACzB;IAoBD;;;;OAIG;IACH,OAAO,CAAC,aAAa;IAcrB;;;;OAIG;IACH,OAAO,CAAC,wBAAwB;IAchC;;;;OAIG;IACH,OAAO,CAAC,aAAa;CActB"}
@@ -0,0 +1,278 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.McpRequestTimeout = exports.DEFAULT_MCP_TIMEOUT_CONFIG = void 0;
4
+ const Logger_1 = require("../utils/Logger");
5
+ /**
6
+ * Default timeout configuration for MCP requests
7
+ * Based on MCP best practices and LLM operation characteristics
8
+ */
9
+ exports.DEFAULT_MCP_TIMEOUT_CONFIG = {
10
+ defaultTimeoutMs: 360000, // 6 minutes - considering complex agent operations
11
+ maxTimeoutMs: 660000, // 11 minutes - absolute maximum for AI->MCP
12
+ progressResetEnabled: true,
13
+ warningThresholdMs: 60000, // 1 minute - send progress notification
14
+ enableDebugLogging: false,
15
+ };
16
+ /**
17
+ * McpRequestTimeout manages timeout behavior for MCP server requests
18
+ * Implements MCP specification recommendations for handling long-running operations
19
+ *
20
+ * This class handles AI -> MCP level timeouts, separate from MCP -> AI (AgentExecutor) timeouts
21
+ * Following MCP best practices:
22
+ * - Progressive timeout with reset on progress
23
+ * - Maximum absolute timeout enforcement
24
+ * - Progress notifications for better UX
25
+ * - Graceful cancellation support
26
+ */
27
+ class McpRequestTimeout {
28
+ /**
29
+ * Creates a new McpRequestTimeout instance
30
+ *
31
+ * @param config - Optional timeout configuration
32
+ * @param logger - Optional logger instance
33
+ */
34
+ constructor(config, logger) {
35
+ this.contexts = new Map();
36
+ this.config = { ...exports.DEFAULT_MCP_TIMEOUT_CONFIG, ...config };
37
+ this.logger = logger || new Logger_1.Logger(process.env['LOG_LEVEL'] || 'info');
38
+ }
39
+ /**
40
+ * Start timeout tracking for a request
41
+ *
42
+ * @param requestId - Unique request identifier
43
+ * @param onTimeout - Callback when timeout occurs
44
+ * @param onProgress - Optional callback for progress notifications
45
+ * @returns TimeoutContext for the request
46
+ */
47
+ startTimeout(requestId, onTimeout, onProgress) {
48
+ // Clear any existing timeout for this request
49
+ this.clearTimeout(requestId);
50
+ const context = {
51
+ requestId,
52
+ startTime: Date.now(),
53
+ currentTimeout: null,
54
+ warningTimeout: null,
55
+ maxTimeout: null,
56
+ progressCount: 0,
57
+ lastProgressTime: Date.now(),
58
+ isCompleted: false,
59
+ isCancelled: false,
60
+ onTimeout,
61
+ ...(onProgress && { onProgress }),
62
+ };
63
+ // Set warning timeout (for progress notification)
64
+ if (onProgress && this.config.warningThresholdMs > 0) {
65
+ context.warningTimeout = setTimeout(() => {
66
+ if (!context.isCompleted && !context.isCancelled) {
67
+ this.sendProgressNotification(context, onProgress, 'Processing is taking longer than expected');
68
+ }
69
+ }, this.config.warningThresholdMs);
70
+ }
71
+ // Set default timeout
72
+ context.currentTimeout = setTimeout(() => {
73
+ if (!context.isCompleted && !context.isCancelled) {
74
+ this.handleTimeout(context, onTimeout);
75
+ }
76
+ }, this.config.defaultTimeoutMs);
77
+ // Set maximum absolute timeout (cannot be reset)
78
+ context.maxTimeout = setTimeout(() => {
79
+ if (!context.isCompleted && !context.isCancelled) {
80
+ this.logger.warn('Maximum timeout reached, forcing termination', {
81
+ requestId,
82
+ elapsedMs: Date.now() - context.startTime,
83
+ maxTimeoutMs: this.config.maxTimeoutMs,
84
+ });
85
+ this.handleTimeout(context, onTimeout);
86
+ }
87
+ }, this.config.maxTimeoutMs);
88
+ this.contexts.set(requestId, context);
89
+ if (this.config.enableDebugLogging) {
90
+ this.logger.debug('Timeout tracking started', {
91
+ requestId,
92
+ defaultTimeoutMs: this.config.defaultTimeoutMs,
93
+ maxTimeoutMs: this.config.maxTimeoutMs,
94
+ });
95
+ }
96
+ return context;
97
+ }
98
+ /**
99
+ * Report progress and optionally reset timeout
100
+ * Following MCP specification: MAY reset timeout on progress, but enforce maximum
101
+ *
102
+ * @param requestId - Request identifier
103
+ * @param message - Progress message
104
+ * @param percentage - Optional completion percentage
105
+ */
106
+ reportProgress(requestId, message, percentage) {
107
+ const context = this.contexts.get(requestId);
108
+ if (!context || context.isCompleted || context.isCancelled) {
109
+ return;
110
+ }
111
+ context.progressCount++;
112
+ context.lastProgressTime = Date.now();
113
+ if (this.config.enableDebugLogging) {
114
+ this.logger.debug('Progress reported', {
115
+ requestId,
116
+ message,
117
+ percentage,
118
+ progressCount: context.progressCount,
119
+ elapsedMs: Date.now() - context.startTime,
120
+ });
121
+ }
122
+ // Reset timeout if enabled (but maximum timeout remains)
123
+ if (this.config.progressResetEnabled && context.currentTimeout) {
124
+ clearTimeout(context.currentTimeout);
125
+ // Calculate remaining time before max timeout
126
+ const elapsedMs = Date.now() - context.startTime;
127
+ const remainingMs = this.config.maxTimeoutMs - elapsedMs;
128
+ const newTimeoutMs = Math.min(this.config.defaultTimeoutMs, remainingMs);
129
+ if (newTimeoutMs > 0 && context.onTimeout) {
130
+ context.currentTimeout = setTimeout(() => {
131
+ if (!context.isCompleted && !context.isCancelled) {
132
+ this.handleTimeout(context, context.onTimeout);
133
+ }
134
+ }, newTimeoutMs);
135
+ this.logger.info('Timeout reset due to progress', {
136
+ requestId,
137
+ newTimeoutMs,
138
+ remainingBeforeMaxMs: remainingMs,
139
+ });
140
+ }
141
+ }
142
+ }
143
+ /**
144
+ * Mark request as completed and clear timeouts
145
+ *
146
+ * @param requestId - Request identifier
147
+ */
148
+ complete(requestId) {
149
+ const context = this.contexts.get(requestId);
150
+ if (!context) {
151
+ return;
152
+ }
153
+ context.isCompleted = true;
154
+ this.clearTimeouts(context);
155
+ const totalTime = Date.now() - context.startTime;
156
+ this.logger.info('Request completed within timeout', {
157
+ requestId,
158
+ totalTimeMs: totalTime,
159
+ progressCount: context.progressCount,
160
+ });
161
+ this.contexts.delete(requestId);
162
+ }
163
+ /**
164
+ * Cancel request and clear timeouts
165
+ * Following MCP specification for cancellation
166
+ *
167
+ * @param requestId - Request identifier
168
+ * @param reason - Cancellation reason
169
+ */
170
+ cancel(requestId, reason) {
171
+ const context = this.contexts.get(requestId);
172
+ if (!context) {
173
+ return;
174
+ }
175
+ context.isCancelled = true;
176
+ this.clearTimeouts(context);
177
+ this.logger.info('Request cancelled', {
178
+ requestId,
179
+ reason,
180
+ elapsedMs: Date.now() - context.startTime,
181
+ });
182
+ this.contexts.delete(requestId);
183
+ }
184
+ /**
185
+ * Clear timeout for a request
186
+ *
187
+ * @param requestId - Request identifier
188
+ */
189
+ clearTimeout(requestId) {
190
+ const context = this.contexts.get(requestId);
191
+ if (context) {
192
+ this.clearTimeouts(context);
193
+ this.contexts.delete(requestId);
194
+ }
195
+ }
196
+ /**
197
+ * Check if request has timed out
198
+ *
199
+ * @param requestId - Request identifier
200
+ * @returns true if timed out
201
+ */
202
+ hasTimedOut(requestId) {
203
+ const context = this.contexts.get(requestId);
204
+ if (!context) {
205
+ return false;
206
+ }
207
+ const elapsedMs = Date.now() - context.startTime;
208
+ return elapsedMs >= this.config.maxTimeoutMs;
209
+ }
210
+ /**
211
+ * Get timeout statistics for monitoring
212
+ *
213
+ * @returns Current timeout statistics
214
+ */
215
+ getStats() {
216
+ const activeContexts = Array.from(this.contexts.values()).filter((c) => !c.isCompleted && !c.isCancelled);
217
+ const now = Date.now();
218
+ const longestRunningMs = activeContexts.reduce((max, c) => Math.max(max, now - c.startTime), 0);
219
+ const averageProgressCount = activeContexts.length > 0
220
+ ? activeContexts.reduce((sum, c) => sum + c.progressCount, 0) / activeContexts.length
221
+ : 0;
222
+ return {
223
+ activeRequests: activeContexts.length,
224
+ averageProgressCount,
225
+ longestRunningMs,
226
+ };
227
+ }
228
+ /**
229
+ * Handle timeout event
230
+ *
231
+ * @private
232
+ */
233
+ handleTimeout(context, onTimeout) {
234
+ const elapsedMs = Date.now() - context.startTime;
235
+ this.logger.warn('Request timeout occurred', {
236
+ requestId: context.requestId,
237
+ elapsedMs,
238
+ progressCount: context.progressCount,
239
+ lastProgressMs: Date.now() - context.lastProgressTime,
240
+ });
241
+ onTimeout(context);
242
+ this.clearTimeouts(context);
243
+ }
244
+ /**
245
+ * Send progress notification
246
+ *
247
+ * @private
248
+ */
249
+ sendProgressNotification(context, onProgress, message) {
250
+ const notification = {
251
+ requestId: context.requestId,
252
+ message,
253
+ timestamp: Date.now(),
254
+ };
255
+ onProgress(notification);
256
+ }
257
+ /**
258
+ * Clear all timeouts for a context
259
+ *
260
+ * @private
261
+ */
262
+ clearTimeouts(context) {
263
+ if (context.currentTimeout) {
264
+ clearTimeout(context.currentTimeout);
265
+ context.currentTimeout = null;
266
+ }
267
+ if (context.warningTimeout) {
268
+ clearTimeout(context.warningTimeout);
269
+ context.warningTimeout = null;
270
+ }
271
+ if (context.maxTimeout) {
272
+ clearTimeout(context.maxTimeout);
273
+ context.maxTimeout = null;
274
+ }
275
+ }
276
+ }
277
+ exports.McpRequestTimeout = McpRequestTimeout;
278
+ //# sourceMappingURL=McpRequestTimeout.js.map