@blackms/aistack 1.5.0 → 1.5.1
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 +30 -3
- package/dist/agents/index.d.ts +1 -1
- package/dist/agents/index.d.ts.map +1 -1
- package/dist/agents/index.js +1 -1
- package/dist/agents/index.js.map +1 -1
- package/dist/agents/spawner.d.ts +12 -0
- package/dist/agents/spawner.d.ts.map +1 -1
- package/dist/agents/spawner.js +108 -0
- package/dist/agents/spawner.js.map +1 -1
- package/dist/integrations/slack.d.ts +3 -0
- package/dist/integrations/slack.d.ts.map +1 -1
- package/dist/integrations/slack.js +40 -0
- package/dist/integrations/slack.js.map +1 -1
- package/dist/memory/sqlite-store.d.ts +64 -1
- package/dist/memory/sqlite-store.d.ts.map +1 -1
- package/dist/memory/sqlite-store.js +293 -0
- package/dist/memory/sqlite-store.js.map +1 -1
- package/dist/monitoring/metrics.d.ts.map +1 -1
- package/dist/monitoring/metrics.js +8 -0
- package/dist/monitoring/metrics.js.map +1 -1
- package/dist/monitoring/resource-exhaustion-service.d.ts +121 -0
- package/dist/monitoring/resource-exhaustion-service.d.ts.map +1 -0
- package/dist/monitoring/resource-exhaustion-service.js +499 -0
- package/dist/monitoring/resource-exhaustion-service.js.map +1 -0
- package/dist/types.d.ts +56 -0
- package/dist/types.d.ts.map +1 -1
- package/dist/types.js.map +1 -1
- package/dist/utils/config.d.ts.map +1 -1
- package/dist/utils/config.js +19 -0
- package/dist/utils/config.js.map +1 -1
- package/dist/web/routes/agents.d.ts.map +1 -1
- package/dist/web/routes/agents.js +134 -1
- package/dist/web/routes/agents.js.map +1 -1
- package/dist/web/routes/system.d.ts.map +1 -1
- package/dist/web/routes/system.js +49 -0
- package/dist/web/routes/system.js.map +1 -1
- package/package.json +1 -1
|
@@ -0,0 +1,121 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Resource Exhaustion Service - monitors and prevents runaway agents
|
|
3
|
+
*/
|
|
4
|
+
import type { SQLiteStore } from '../memory/sqlite-store.js';
|
|
5
|
+
import type { AgentResourceMetrics, ResourceExhaustionConfig, ResourceExhaustionPhase, ResourceExhaustionEvent, DeliverableType, DeliverableCheckpoint } from '../types.js';
|
|
6
|
+
export interface ResourceExhaustionMetricsSummary {
|
|
7
|
+
totalAgentsTracked: number;
|
|
8
|
+
agentsByPhase: Record<ResourceExhaustionPhase, number>;
|
|
9
|
+
pausedAgents: number;
|
|
10
|
+
totalWarnings: number;
|
|
11
|
+
totalInterventions: number;
|
|
12
|
+
totalTerminations: number;
|
|
13
|
+
recentEvents: ResourceExhaustionEvent[];
|
|
14
|
+
}
|
|
15
|
+
/**
|
|
16
|
+
* Service for tracking and managing agent resource consumption
|
|
17
|
+
*/
|
|
18
|
+
export declare class ResourceExhaustionService {
|
|
19
|
+
private store;
|
|
20
|
+
private config;
|
|
21
|
+
private metricsCache;
|
|
22
|
+
private checkInterval;
|
|
23
|
+
private pauseCallbacks;
|
|
24
|
+
private agentTypes;
|
|
25
|
+
constructor(store: SQLiteStore, config: ResourceExhaustionConfig);
|
|
26
|
+
/**
|
|
27
|
+
* Check if the service is enabled
|
|
28
|
+
*/
|
|
29
|
+
isEnabled(): boolean;
|
|
30
|
+
/**
|
|
31
|
+
* Get current configuration
|
|
32
|
+
*/
|
|
33
|
+
getConfig(): ResourceExhaustionConfig;
|
|
34
|
+
/**
|
|
35
|
+
* Initialize tracking for a new agent
|
|
36
|
+
*/
|
|
37
|
+
initializeAgent(agentId: string, agentType: string): AgentResourceMetrics;
|
|
38
|
+
/**
|
|
39
|
+
* Record a file operation
|
|
40
|
+
*/
|
|
41
|
+
recordFileOperation(agentId: string, op: 'read' | 'write' | 'modify'): void;
|
|
42
|
+
/**
|
|
43
|
+
* Record an API call
|
|
44
|
+
*/
|
|
45
|
+
recordApiCall(agentId: string, tokens?: number): void;
|
|
46
|
+
/**
|
|
47
|
+
* Record a subtask spawn
|
|
48
|
+
*/
|
|
49
|
+
recordSubtaskSpawn(agentId: string): void;
|
|
50
|
+
/**
|
|
51
|
+
* Record a deliverable checkpoint
|
|
52
|
+
*/
|
|
53
|
+
recordDeliverable(agentId: string, type: DeliverableType, description?: string, artifacts?: string[]): DeliverableCheckpoint;
|
|
54
|
+
/**
|
|
55
|
+
* Evaluate agent's current phase based on resource consumption
|
|
56
|
+
*/
|
|
57
|
+
evaluateAgent(agentId: string): ResourceExhaustionPhase;
|
|
58
|
+
/**
|
|
59
|
+
* Check all active agents
|
|
60
|
+
*/
|
|
61
|
+
checkAllAgents(): void;
|
|
62
|
+
/**
|
|
63
|
+
* Pause an agent
|
|
64
|
+
*/
|
|
65
|
+
pauseAgent(agentId: string, reason: string): Promise<boolean>;
|
|
66
|
+
/**
|
|
67
|
+
* Resume a paused agent
|
|
68
|
+
*/
|
|
69
|
+
resumeAgent(agentId: string): boolean;
|
|
70
|
+
/**
|
|
71
|
+
* Check if an agent is paused
|
|
72
|
+
*/
|
|
73
|
+
isAgentPaused(agentId: string): boolean;
|
|
74
|
+
/**
|
|
75
|
+
* Terminate an agent due to resource exhaustion
|
|
76
|
+
*/
|
|
77
|
+
terminateAgent(agentId: string, reason: string): boolean;
|
|
78
|
+
/**
|
|
79
|
+
* Wait for an agent to be unpaused (returns true if resumed, false if terminated)
|
|
80
|
+
*/
|
|
81
|
+
waitForResume(agentId: string): Promise<boolean>;
|
|
82
|
+
/**
|
|
83
|
+
* Get metrics for a specific agent
|
|
84
|
+
*/
|
|
85
|
+
getAgentMetrics(agentId: string): AgentResourceMetrics | null;
|
|
86
|
+
/**
|
|
87
|
+
* Get a summary of resource exhaustion metrics
|
|
88
|
+
*/
|
|
89
|
+
getResourceMetrics(since?: Date): ResourceExhaustionMetricsSummary;
|
|
90
|
+
/**
|
|
91
|
+
* Get recent events
|
|
92
|
+
*/
|
|
93
|
+
getRecentEvents(limit?: number): ResourceExhaustionEvent[];
|
|
94
|
+
/**
|
|
95
|
+
* Start the background monitoring interval
|
|
96
|
+
*/
|
|
97
|
+
start(): void;
|
|
98
|
+
/**
|
|
99
|
+
* Stop the background monitoring
|
|
100
|
+
*/
|
|
101
|
+
stop(): void;
|
|
102
|
+
/**
|
|
103
|
+
* Clean up tracking for an agent
|
|
104
|
+
*/
|
|
105
|
+
cleanupAgent(agentId: string): void;
|
|
106
|
+
private getOrCreateMetrics;
|
|
107
|
+
private updateMetrics;
|
|
108
|
+
private getTotalFilesAccessed;
|
|
109
|
+
private getPausedAgentCount;
|
|
110
|
+
private loadMetricsFromDatabase;
|
|
111
|
+
private handlePhaseTransition;
|
|
112
|
+
}
|
|
113
|
+
/**
|
|
114
|
+
* Get or create the ResourceExhaustionService singleton
|
|
115
|
+
*/
|
|
116
|
+
export declare function getResourceExhaustionService(store: SQLiteStore, config: ResourceExhaustionConfig, forceNew?: boolean): ResourceExhaustionService;
|
|
117
|
+
/**
|
|
118
|
+
* Reset the singleton (for testing)
|
|
119
|
+
*/
|
|
120
|
+
export declare function resetResourceExhaustionService(): void;
|
|
121
|
+
//# sourceMappingURL=resource-exhaustion-service.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"resource-exhaustion-service.d.ts","sourceRoot":"","sources":["../../src/monitoring/resource-exhaustion-service.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,499 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Resource Exhaustion Service - monitors and prevents runaway agents
|
|
3
|
+
*/
|
|
4
|
+
import { randomUUID } from 'node:crypto';
|
|
5
|
+
import { logger } from '../utils/logger.js';
|
|
6
|
+
import { getMetricsCollector } from './metrics.js';
|
|
7
|
+
const log = logger.child('resource-exhaustion');
|
|
8
|
+
/**
|
|
9
|
+
* Service for tracking and managing agent resource consumption
|
|
10
|
+
*/
|
|
11
|
+
export class ResourceExhaustionService {
|
|
12
|
+
store;
|
|
13
|
+
config;
|
|
14
|
+
metricsCache = new Map();
|
|
15
|
+
checkInterval = null;
|
|
16
|
+
pauseCallbacks = new Map();
|
|
17
|
+
agentTypes = new Map(); // agentId -> agentType
|
|
18
|
+
constructor(store, config) {
|
|
19
|
+
this.store = store;
|
|
20
|
+
this.config = config;
|
|
21
|
+
// Load existing metrics from database on startup
|
|
22
|
+
if (this.isEnabled()) {
|
|
23
|
+
this.loadMetricsFromDatabase();
|
|
24
|
+
}
|
|
25
|
+
}
|
|
26
|
+
/**
|
|
27
|
+
* Check if the service is enabled
|
|
28
|
+
*/
|
|
29
|
+
isEnabled() {
|
|
30
|
+
return this.config.enabled;
|
|
31
|
+
}
|
|
32
|
+
/**
|
|
33
|
+
* Get current configuration
|
|
34
|
+
*/
|
|
35
|
+
getConfig() {
|
|
36
|
+
return { ...this.config };
|
|
37
|
+
}
|
|
38
|
+
/**
|
|
39
|
+
* Initialize tracking for a new agent
|
|
40
|
+
*/
|
|
41
|
+
initializeAgent(agentId, agentType) {
|
|
42
|
+
const now = new Date();
|
|
43
|
+
const metrics = {
|
|
44
|
+
agentId,
|
|
45
|
+
filesRead: 0,
|
|
46
|
+
filesWritten: 0,
|
|
47
|
+
filesModified: 0,
|
|
48
|
+
apiCallsCount: 0,
|
|
49
|
+
subtasksSpawned: 0,
|
|
50
|
+
tokensConsumed: 0,
|
|
51
|
+
startedAt: now,
|
|
52
|
+
lastDeliverableAt: null,
|
|
53
|
+
lastActivityAt: now,
|
|
54
|
+
phase: 'normal',
|
|
55
|
+
pausedAt: null,
|
|
56
|
+
pauseReason: null,
|
|
57
|
+
};
|
|
58
|
+
this.metricsCache.set(agentId, metrics);
|
|
59
|
+
this.agentTypes.set(agentId, agentType);
|
|
60
|
+
// Persist to database
|
|
61
|
+
this.store.saveAgentResourceMetrics(metrics);
|
|
62
|
+
log.debug('Initialized agent resource tracking', { agentId, agentType });
|
|
63
|
+
return metrics;
|
|
64
|
+
}
|
|
65
|
+
/**
|
|
66
|
+
* Record a file operation
|
|
67
|
+
*/
|
|
68
|
+
recordFileOperation(agentId, op) {
|
|
69
|
+
if (!this.isEnabled())
|
|
70
|
+
return;
|
|
71
|
+
const metrics = this.getOrCreateMetrics(agentId);
|
|
72
|
+
if (!metrics)
|
|
73
|
+
return;
|
|
74
|
+
switch (op) {
|
|
75
|
+
case 'read':
|
|
76
|
+
metrics.filesRead++;
|
|
77
|
+
break;
|
|
78
|
+
case 'write':
|
|
79
|
+
metrics.filesWritten++;
|
|
80
|
+
break;
|
|
81
|
+
case 'modify':
|
|
82
|
+
metrics.filesModified++;
|
|
83
|
+
break;
|
|
84
|
+
}
|
|
85
|
+
metrics.lastActivityAt = new Date();
|
|
86
|
+
this.updateMetrics(agentId, metrics);
|
|
87
|
+
// Update Prometheus metrics
|
|
88
|
+
const collector = getMetricsCollector();
|
|
89
|
+
collector.observeHistogram('agent_files_accessed', this.getTotalFilesAccessed(metrics));
|
|
90
|
+
}
|
|
91
|
+
/**
|
|
92
|
+
* Record an API call
|
|
93
|
+
*/
|
|
94
|
+
recordApiCall(agentId, tokens) {
|
|
95
|
+
if (!this.isEnabled())
|
|
96
|
+
return;
|
|
97
|
+
const metrics = this.getOrCreateMetrics(agentId);
|
|
98
|
+
if (!metrics)
|
|
99
|
+
return;
|
|
100
|
+
metrics.apiCallsCount++;
|
|
101
|
+
if (tokens) {
|
|
102
|
+
metrics.tokensConsumed += tokens;
|
|
103
|
+
}
|
|
104
|
+
metrics.lastActivityAt = new Date();
|
|
105
|
+
this.updateMetrics(agentId, metrics);
|
|
106
|
+
// Update Prometheus metrics
|
|
107
|
+
const collector = getMetricsCollector();
|
|
108
|
+
collector.observeHistogram('agent_api_calls', metrics.apiCallsCount);
|
|
109
|
+
if (tokens) {
|
|
110
|
+
collector.observeHistogram('agent_tokens_consumed', metrics.tokensConsumed);
|
|
111
|
+
}
|
|
112
|
+
}
|
|
113
|
+
/**
|
|
114
|
+
* Record a subtask spawn
|
|
115
|
+
*/
|
|
116
|
+
recordSubtaskSpawn(agentId) {
|
|
117
|
+
if (!this.isEnabled())
|
|
118
|
+
return;
|
|
119
|
+
const metrics = this.getOrCreateMetrics(agentId);
|
|
120
|
+
if (!metrics)
|
|
121
|
+
return;
|
|
122
|
+
metrics.subtasksSpawned++;
|
|
123
|
+
metrics.lastActivityAt = new Date();
|
|
124
|
+
this.updateMetrics(agentId, metrics);
|
|
125
|
+
}
|
|
126
|
+
/**
|
|
127
|
+
* Record a deliverable checkpoint
|
|
128
|
+
*/
|
|
129
|
+
recordDeliverable(agentId, type, description, artifacts) {
|
|
130
|
+
const metrics = this.getOrCreateMetrics(agentId);
|
|
131
|
+
const now = new Date();
|
|
132
|
+
// Create checkpoint
|
|
133
|
+
const checkpoint = this.store.createDeliverableCheckpoint({
|
|
134
|
+
id: randomUUID(),
|
|
135
|
+
agentId,
|
|
136
|
+
type,
|
|
137
|
+
description,
|
|
138
|
+
artifacts,
|
|
139
|
+
});
|
|
140
|
+
// Update metrics
|
|
141
|
+
if (metrics) {
|
|
142
|
+
metrics.lastDeliverableAt = now;
|
|
143
|
+
metrics.lastActivityAt = now;
|
|
144
|
+
// Reset phase to normal if we were in warning
|
|
145
|
+
if (metrics.phase === 'warning') {
|
|
146
|
+
metrics.phase = 'normal';
|
|
147
|
+
}
|
|
148
|
+
this.updateMetrics(agentId, metrics);
|
|
149
|
+
}
|
|
150
|
+
log.info('Recorded deliverable checkpoint', { agentId, type, description });
|
|
151
|
+
return checkpoint;
|
|
152
|
+
}
|
|
153
|
+
/**
|
|
154
|
+
* Evaluate agent's current phase based on resource consumption
|
|
155
|
+
*/
|
|
156
|
+
evaluateAgent(agentId) {
|
|
157
|
+
if (!this.isEnabled())
|
|
158
|
+
return 'normal';
|
|
159
|
+
const metrics = this.metricsCache.get(agentId);
|
|
160
|
+
if (!metrics)
|
|
161
|
+
return 'normal';
|
|
162
|
+
const thresholds = this.config.thresholds;
|
|
163
|
+
const warningPercent = this.config.warningThresholdPercent;
|
|
164
|
+
// Check each threshold
|
|
165
|
+
const checks = [
|
|
166
|
+
{ key: 'maxFilesAccessed', value: this.getTotalFilesAccessed(metrics), max: thresholds.maxFilesAccessed },
|
|
167
|
+
{ key: 'maxApiCalls', value: metrics.apiCallsCount, max: thresholds.maxApiCalls },
|
|
168
|
+
{ key: 'maxSubtasksSpawned', value: metrics.subtasksSpawned, max: thresholds.maxSubtasksSpawned },
|
|
169
|
+
{ key: 'maxTokensConsumed', value: metrics.tokensConsumed, max: thresholds.maxTokensConsumed },
|
|
170
|
+
];
|
|
171
|
+
// Check time without deliverable
|
|
172
|
+
const timeSinceDeliverable = metrics.lastDeliverableAt
|
|
173
|
+
? Date.now() - metrics.lastDeliverableAt.getTime()
|
|
174
|
+
: Date.now() - metrics.startedAt.getTime();
|
|
175
|
+
checks.push({
|
|
176
|
+
key: 'maxTimeWithoutDeliverableMs',
|
|
177
|
+
value: timeSinceDeliverable,
|
|
178
|
+
max: thresholds.maxTimeWithoutDeliverableMs,
|
|
179
|
+
});
|
|
180
|
+
// Determine phase based on highest threshold breach
|
|
181
|
+
let newPhase = 'normal';
|
|
182
|
+
let triggeredBy = null;
|
|
183
|
+
for (const check of checks) {
|
|
184
|
+
const ratio = check.value / check.max;
|
|
185
|
+
if (ratio >= 1) {
|
|
186
|
+
// Exceeded threshold - intervention (upgrade from warning or normal)
|
|
187
|
+
if (newPhase === 'normal' || newPhase === 'warning') {
|
|
188
|
+
newPhase = 'intervention';
|
|
189
|
+
triggeredBy = check.key;
|
|
190
|
+
}
|
|
191
|
+
}
|
|
192
|
+
else if (ratio >= warningPercent) {
|
|
193
|
+
// Warning threshold (only upgrade from normal)
|
|
194
|
+
if (newPhase === 'normal') {
|
|
195
|
+
newPhase = 'warning';
|
|
196
|
+
triggeredBy = check.key;
|
|
197
|
+
}
|
|
198
|
+
}
|
|
199
|
+
}
|
|
200
|
+
// Handle phase transition
|
|
201
|
+
if (newPhase !== metrics.phase) {
|
|
202
|
+
this.handlePhaseTransition(agentId, metrics.phase, newPhase, triggeredBy);
|
|
203
|
+
metrics.phase = newPhase;
|
|
204
|
+
this.updateMetrics(agentId, metrics);
|
|
205
|
+
}
|
|
206
|
+
return newPhase;
|
|
207
|
+
}
|
|
208
|
+
/**
|
|
209
|
+
* Check all active agents
|
|
210
|
+
*/
|
|
211
|
+
checkAllAgents() {
|
|
212
|
+
if (!this.isEnabled())
|
|
213
|
+
return;
|
|
214
|
+
for (const agentId of this.metricsCache.keys()) {
|
|
215
|
+
this.evaluateAgent(agentId);
|
|
216
|
+
}
|
|
217
|
+
}
|
|
218
|
+
/**
|
|
219
|
+
* Pause an agent
|
|
220
|
+
*/
|
|
221
|
+
async pauseAgent(agentId, reason) {
|
|
222
|
+
const metrics = this.metricsCache.get(agentId);
|
|
223
|
+
if (!metrics)
|
|
224
|
+
return false;
|
|
225
|
+
metrics.pausedAt = new Date();
|
|
226
|
+
metrics.pauseReason = reason;
|
|
227
|
+
this.updateMetrics(agentId, metrics);
|
|
228
|
+
// Update Prometheus metrics
|
|
229
|
+
const collector = getMetricsCollector();
|
|
230
|
+
collector.setGauge('agents_paused_current', this.getPausedAgentCount());
|
|
231
|
+
log.info('Agent paused', { agentId, reason });
|
|
232
|
+
// If there's a pending callback (agent waiting to execute), resolve it with false
|
|
233
|
+
const callback = this.pauseCallbacks.get(agentId);
|
|
234
|
+
if (callback) {
|
|
235
|
+
callback(false);
|
|
236
|
+
this.pauseCallbacks.delete(agentId);
|
|
237
|
+
}
|
|
238
|
+
return true;
|
|
239
|
+
}
|
|
240
|
+
/**
|
|
241
|
+
* Resume a paused agent
|
|
242
|
+
*/
|
|
243
|
+
resumeAgent(agentId) {
|
|
244
|
+
const metrics = this.metricsCache.get(agentId);
|
|
245
|
+
if (!metrics || !metrics.pausedAt)
|
|
246
|
+
return false;
|
|
247
|
+
metrics.pausedAt = null;
|
|
248
|
+
metrics.pauseReason = null;
|
|
249
|
+
// Reset phase to warning if it was at intervention
|
|
250
|
+
if (metrics.phase === 'intervention') {
|
|
251
|
+
metrics.phase = 'warning';
|
|
252
|
+
}
|
|
253
|
+
this.updateMetrics(agentId, metrics);
|
|
254
|
+
// Update Prometheus metrics
|
|
255
|
+
const collector = getMetricsCollector();
|
|
256
|
+
collector.setGauge('agents_paused_current', this.getPausedAgentCount());
|
|
257
|
+
log.info('Agent resumed', { agentId });
|
|
258
|
+
return true;
|
|
259
|
+
}
|
|
260
|
+
/**
|
|
261
|
+
* Check if an agent is paused
|
|
262
|
+
*/
|
|
263
|
+
isAgentPaused(agentId) {
|
|
264
|
+
const metrics = this.metricsCache.get(agentId);
|
|
265
|
+
return metrics?.pausedAt !== null;
|
|
266
|
+
}
|
|
267
|
+
/**
|
|
268
|
+
* Terminate an agent due to resource exhaustion
|
|
269
|
+
*/
|
|
270
|
+
terminateAgent(agentId, reason) {
|
|
271
|
+
const metrics = this.metricsCache.get(agentId);
|
|
272
|
+
if (!metrics)
|
|
273
|
+
return false;
|
|
274
|
+
// Trigger termination phase transition
|
|
275
|
+
this.handlePhaseTransition(agentId, metrics.phase, 'termination', 'maxTimeWithoutDeliverableMs');
|
|
276
|
+
metrics.phase = 'termination';
|
|
277
|
+
this.updateMetrics(agentId, metrics);
|
|
278
|
+
log.info('Agent terminated', { agentId, reason });
|
|
279
|
+
return true;
|
|
280
|
+
}
|
|
281
|
+
/**
|
|
282
|
+
* Wait for an agent to be unpaused (returns true if resumed, false if terminated)
|
|
283
|
+
*/
|
|
284
|
+
async waitForResume(agentId) {
|
|
285
|
+
return new Promise((resolve) => {
|
|
286
|
+
this.pauseCallbacks.set(agentId, resolve);
|
|
287
|
+
});
|
|
288
|
+
}
|
|
289
|
+
/**
|
|
290
|
+
* Get metrics for a specific agent
|
|
291
|
+
*/
|
|
292
|
+
getAgentMetrics(agentId) {
|
|
293
|
+
return this.metricsCache.get(agentId) ?? null;
|
|
294
|
+
}
|
|
295
|
+
/**
|
|
296
|
+
* Get a summary of resource exhaustion metrics
|
|
297
|
+
*/
|
|
298
|
+
getResourceMetrics(since) {
|
|
299
|
+
const dbMetrics = this.store.getResourceExhaustionMetrics(since);
|
|
300
|
+
const events = this.store.getResourceExhaustionEvents({ limit: 10, since });
|
|
301
|
+
const agentsByPhase = {
|
|
302
|
+
normal: 0,
|
|
303
|
+
warning: 0,
|
|
304
|
+
intervention: 0,
|
|
305
|
+
termination: 0,
|
|
306
|
+
};
|
|
307
|
+
for (const metrics of this.metricsCache.values()) {
|
|
308
|
+
agentsByPhase[metrics.phase]++;
|
|
309
|
+
}
|
|
310
|
+
return {
|
|
311
|
+
totalAgentsTracked: this.metricsCache.size,
|
|
312
|
+
agentsByPhase,
|
|
313
|
+
pausedAgents: this.getPausedAgentCount(),
|
|
314
|
+
totalWarnings: dbMetrics.warningCount,
|
|
315
|
+
totalInterventions: dbMetrics.interventionCount,
|
|
316
|
+
totalTerminations: dbMetrics.terminationCount,
|
|
317
|
+
recentEvents: events,
|
|
318
|
+
};
|
|
319
|
+
}
|
|
320
|
+
/**
|
|
321
|
+
* Get recent events
|
|
322
|
+
*/
|
|
323
|
+
getRecentEvents(limit = 10) {
|
|
324
|
+
return this.store.getResourceExhaustionEvents({ limit });
|
|
325
|
+
}
|
|
326
|
+
/**
|
|
327
|
+
* Start the background monitoring interval
|
|
328
|
+
*/
|
|
329
|
+
start() {
|
|
330
|
+
if (!this.isEnabled() || this.checkInterval)
|
|
331
|
+
return;
|
|
332
|
+
this.checkInterval = setInterval(() => {
|
|
333
|
+
this.checkAllAgents();
|
|
334
|
+
}, this.config.checkIntervalMs);
|
|
335
|
+
log.info('Resource exhaustion monitoring started', {
|
|
336
|
+
checkIntervalMs: this.config.checkIntervalMs,
|
|
337
|
+
});
|
|
338
|
+
}
|
|
339
|
+
/**
|
|
340
|
+
* Stop the background monitoring
|
|
341
|
+
*/
|
|
342
|
+
stop() {
|
|
343
|
+
if (this.checkInterval) {
|
|
344
|
+
clearInterval(this.checkInterval);
|
|
345
|
+
this.checkInterval = null;
|
|
346
|
+
log.info('Resource exhaustion monitoring stopped');
|
|
347
|
+
}
|
|
348
|
+
}
|
|
349
|
+
/**
|
|
350
|
+
* Clean up tracking for an agent
|
|
351
|
+
*/
|
|
352
|
+
cleanupAgent(agentId) {
|
|
353
|
+
const metrics = this.metricsCache.get(agentId);
|
|
354
|
+
// Update final histograms before cleanup
|
|
355
|
+
if (metrics) {
|
|
356
|
+
const collector = getMetricsCollector();
|
|
357
|
+
collector.observeHistogram('agent_files_accessed', this.getTotalFilesAccessed(metrics));
|
|
358
|
+
collector.observeHistogram('agent_api_calls', metrics.apiCallsCount);
|
|
359
|
+
collector.observeHistogram('agent_tokens_consumed', metrics.tokensConsumed);
|
|
360
|
+
}
|
|
361
|
+
this.metricsCache.delete(agentId);
|
|
362
|
+
this.agentTypes.delete(agentId);
|
|
363
|
+
this.pauseCallbacks.delete(agentId);
|
|
364
|
+
// Clean up from database
|
|
365
|
+
this.store.deleteAgentResourceMetrics(agentId);
|
|
366
|
+
this.store.deleteDeliverableCheckpoints(agentId);
|
|
367
|
+
log.debug('Cleaned up agent resource tracking', { agentId });
|
|
368
|
+
}
|
|
369
|
+
// Private methods
|
|
370
|
+
getOrCreateMetrics(agentId) {
|
|
371
|
+
let metrics = this.metricsCache.get(agentId);
|
|
372
|
+
if (!metrics) {
|
|
373
|
+
// Try to load from database
|
|
374
|
+
metrics = this.store.getAgentResourceMetrics(agentId) ?? undefined;
|
|
375
|
+
if (metrics) {
|
|
376
|
+
this.metricsCache.set(agentId, metrics);
|
|
377
|
+
}
|
|
378
|
+
}
|
|
379
|
+
return metrics ?? null;
|
|
380
|
+
}
|
|
381
|
+
updateMetrics(agentId, metrics) {
|
|
382
|
+
this.metricsCache.set(agentId, metrics);
|
|
383
|
+
this.store.saveAgentResourceMetrics(metrics);
|
|
384
|
+
}
|
|
385
|
+
getTotalFilesAccessed(metrics) {
|
|
386
|
+
return metrics.filesRead + metrics.filesWritten + metrics.filesModified;
|
|
387
|
+
}
|
|
388
|
+
getPausedAgentCount() {
|
|
389
|
+
let count = 0;
|
|
390
|
+
for (const metrics of this.metricsCache.values()) {
|
|
391
|
+
if (metrics.pausedAt !== null) {
|
|
392
|
+
count++;
|
|
393
|
+
}
|
|
394
|
+
}
|
|
395
|
+
return count;
|
|
396
|
+
}
|
|
397
|
+
loadMetricsFromDatabase() {
|
|
398
|
+
const savedMetrics = this.store.listAgentResourceMetrics();
|
|
399
|
+
for (const metrics of savedMetrics) {
|
|
400
|
+
this.metricsCache.set(metrics.agentId, metrics);
|
|
401
|
+
}
|
|
402
|
+
log.debug('Loaded metrics from database', { count: savedMetrics.length });
|
|
403
|
+
}
|
|
404
|
+
handlePhaseTransition(agentId, oldPhase, newPhase, triggeredBy) {
|
|
405
|
+
const metrics = this.metricsCache.get(agentId);
|
|
406
|
+
if (!metrics)
|
|
407
|
+
return;
|
|
408
|
+
const agentType = this.agentTypes.get(agentId) ?? 'unknown';
|
|
409
|
+
let action = 'allowed';
|
|
410
|
+
// Update Prometheus metrics
|
|
411
|
+
const collector = getMetricsCollector();
|
|
412
|
+
if (newPhase === 'warning') {
|
|
413
|
+
action = 'warned';
|
|
414
|
+
collector.incrementCounter('resource_exhaustion_warnings_total');
|
|
415
|
+
log.warn('Agent approaching resource limits', {
|
|
416
|
+
agentId,
|
|
417
|
+
agentType,
|
|
418
|
+
triggeredBy,
|
|
419
|
+
phase: newPhase,
|
|
420
|
+
});
|
|
421
|
+
}
|
|
422
|
+
else if (newPhase === 'intervention') {
|
|
423
|
+
action = 'paused';
|
|
424
|
+
collector.incrementCounter('resource_exhaustion_interventions_total');
|
|
425
|
+
log.error('Agent exceeded resource limits', {
|
|
426
|
+
agentId,
|
|
427
|
+
agentType,
|
|
428
|
+
triggeredBy,
|
|
429
|
+
phase: newPhase,
|
|
430
|
+
});
|
|
431
|
+
// Auto-pause if configured
|
|
432
|
+
if (this.config.pauseOnIntervention) {
|
|
433
|
+
this.pauseAgent(agentId, `Resource threshold exceeded: ${triggeredBy}`);
|
|
434
|
+
}
|
|
435
|
+
}
|
|
436
|
+
else if (newPhase === 'termination') {
|
|
437
|
+
action = 'terminated';
|
|
438
|
+
collector.incrementCounter('resource_exhaustion_terminations_total');
|
|
439
|
+
log.error('Agent terminated due to resource exhaustion', {
|
|
440
|
+
agentId,
|
|
441
|
+
agentType,
|
|
442
|
+
triggeredBy,
|
|
443
|
+
phase: newPhase,
|
|
444
|
+
});
|
|
445
|
+
}
|
|
446
|
+
// Log event to database
|
|
447
|
+
const event = {
|
|
448
|
+
id: randomUUID(),
|
|
449
|
+
agentId,
|
|
450
|
+
agentType,
|
|
451
|
+
phase: newPhase,
|
|
452
|
+
actionTaken: action,
|
|
453
|
+
metrics: { ...metrics },
|
|
454
|
+
thresholds: { ...this.config.thresholds },
|
|
455
|
+
triggeredBy,
|
|
456
|
+
createdAt: new Date(),
|
|
457
|
+
};
|
|
458
|
+
this.store.saveResourceExhaustionEvent(event);
|
|
459
|
+
}
|
|
460
|
+
}
|
|
461
|
+
// Singleton management
|
|
462
|
+
let instance = null;
|
|
463
|
+
let lastConfig = null;
|
|
464
|
+
/**
|
|
465
|
+
* Get or create the ResourceExhaustionService singleton
|
|
466
|
+
*/
|
|
467
|
+
export function getResourceExhaustionService(store, config, forceNew = false) {
|
|
468
|
+
// Check if config has changed
|
|
469
|
+
const configChanged = lastConfig !== null && (lastConfig.enabled !== config.enabled ||
|
|
470
|
+
lastConfig.warningThresholdPercent !== config.warningThresholdPercent ||
|
|
471
|
+
lastConfig.checkIntervalMs !== config.checkIntervalMs ||
|
|
472
|
+
lastConfig.autoTerminate !== config.autoTerminate ||
|
|
473
|
+
lastConfig.pauseOnIntervention !== config.pauseOnIntervention ||
|
|
474
|
+
JSON.stringify(lastConfig.thresholds) !== JSON.stringify(config.thresholds));
|
|
475
|
+
if (!instance || forceNew || configChanged) {
|
|
476
|
+
// Stop existing instance if any
|
|
477
|
+
if (instance) {
|
|
478
|
+
instance.stop();
|
|
479
|
+
}
|
|
480
|
+
instance = new ResourceExhaustionService(store, config);
|
|
481
|
+
lastConfig = { ...config };
|
|
482
|
+
// Start monitoring if enabled
|
|
483
|
+
if (config.enabled) {
|
|
484
|
+
instance.start();
|
|
485
|
+
}
|
|
486
|
+
}
|
|
487
|
+
return instance;
|
|
488
|
+
}
|
|
489
|
+
/**
|
|
490
|
+
* Reset the singleton (for testing)
|
|
491
|
+
*/
|
|
492
|
+
export function resetResourceExhaustionService() {
|
|
493
|
+
if (instance) {
|
|
494
|
+
instance.stop();
|
|
495
|
+
instance = null;
|
|
496
|
+
}
|
|
497
|
+
lastConfig = null;
|
|
498
|
+
}
|
|
499
|
+
//# sourceMappingURL=resource-exhaustion-service.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"resource-exhaustion-service.js","sourceRoot":"","sources":["../../src/monitoring/resource-exhaustion-service.ts"],"names":[],"mappings":"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"}
|