@agent-relay/cloud 0.1.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/dist/api/admin.d.ts +8 -0
- package/dist/api/admin.d.ts.map +1 -0
- package/dist/api/admin.js +225 -0
- package/dist/api/admin.js.map +1 -0
- package/dist/api/auth.d.ts +20 -0
- package/dist/api/auth.d.ts.map +1 -0
- package/dist/api/auth.js +136 -0
- package/dist/api/auth.js.map +1 -0
- package/dist/api/billing.d.ts +7 -0
- package/dist/api/billing.d.ts.map +1 -0
- package/dist/api/billing.js +564 -0
- package/dist/api/billing.js.map +1 -0
- package/dist/api/cli-pty-runner.d.ts +53 -0
- package/dist/api/cli-pty-runner.d.ts.map +1 -0
- package/dist/api/cli-pty-runner.js +193 -0
- package/dist/api/cli-pty-runner.js.map +1 -0
- package/dist/api/codex-auth-helper.d.ts +21 -0
- package/dist/api/codex-auth-helper.d.ts.map +1 -0
- package/dist/api/codex-auth-helper.js +327 -0
- package/dist/api/codex-auth-helper.js.map +1 -0
- package/dist/api/consensus.d.ts +13 -0
- package/dist/api/consensus.d.ts.map +1 -0
- package/dist/api/consensus.js +261 -0
- package/dist/api/consensus.js.map +1 -0
- package/dist/api/coordinators.d.ts +8 -0
- package/dist/api/coordinators.d.ts.map +1 -0
- package/dist/api/coordinators.js +750 -0
- package/dist/api/coordinators.js.map +1 -0
- package/dist/api/daemons.d.ts +12 -0
- package/dist/api/daemons.d.ts.map +1 -0
- package/dist/api/daemons.js +535 -0
- package/dist/api/daemons.js.map +1 -0
- package/dist/api/generic-webhooks.d.ts +8 -0
- package/dist/api/generic-webhooks.d.ts.map +1 -0
- package/dist/api/generic-webhooks.js +129 -0
- package/dist/api/generic-webhooks.js.map +1 -0
- package/dist/api/git.d.ts +8 -0
- package/dist/api/git.d.ts.map +1 -0
- package/dist/api/git.js +269 -0
- package/dist/api/git.js.map +1 -0
- package/dist/api/github-app.d.ts +11 -0
- package/dist/api/github-app.d.ts.map +1 -0
- package/dist/api/github-app.js +223 -0
- package/dist/api/github-app.js.map +1 -0
- package/dist/api/middleware/planLimits.d.ts +43 -0
- package/dist/api/middleware/planLimits.d.ts.map +1 -0
- package/dist/api/middleware/planLimits.js +202 -0
- package/dist/api/middleware/planLimits.js.map +1 -0
- package/dist/api/monitoring.d.ts +11 -0
- package/dist/api/monitoring.d.ts.map +1 -0
- package/dist/api/monitoring.js +578 -0
- package/dist/api/monitoring.js.map +1 -0
- package/dist/api/nango-auth.d.ts +9 -0
- package/dist/api/nango-auth.d.ts.map +1 -0
- package/dist/api/nango-auth.js +674 -0
- package/dist/api/nango-auth.js.map +1 -0
- package/dist/api/onboarding.d.ts +15 -0
- package/dist/api/onboarding.d.ts.map +1 -0
- package/dist/api/onboarding.js +679 -0
- package/dist/api/onboarding.js.map +1 -0
- package/dist/api/policy.d.ts +8 -0
- package/dist/api/policy.d.ts.map +1 -0
- package/dist/api/policy.js +229 -0
- package/dist/api/policy.js.map +1 -0
- package/dist/api/provider-env.d.ts +14 -0
- package/dist/api/provider-env.d.ts.map +1 -0
- package/dist/api/provider-env.js +75 -0
- package/dist/api/provider-env.js.map +1 -0
- package/dist/api/providers.d.ts +7 -0
- package/dist/api/providers.d.ts.map +1 -0
- package/dist/api/providers.js +564 -0
- package/dist/api/providers.js.map +1 -0
- package/dist/api/repos.d.ts +8 -0
- package/dist/api/repos.d.ts.map +1 -0
- package/dist/api/repos.js +577 -0
- package/dist/api/repos.js.map +1 -0
- package/dist/api/sessions.d.ts +11 -0
- package/dist/api/sessions.d.ts.map +1 -0
- package/dist/api/sessions.js +302 -0
- package/dist/api/sessions.js.map +1 -0
- package/dist/api/teams.d.ts +7 -0
- package/dist/api/teams.d.ts.map +1 -0
- package/dist/api/teams.js +281 -0
- package/dist/api/teams.js.map +1 -0
- package/dist/api/test-helpers.d.ts +10 -0
- package/dist/api/test-helpers.d.ts.map +1 -0
- package/dist/api/test-helpers.js +745 -0
- package/dist/api/test-helpers.js.map +1 -0
- package/dist/api/usage.d.ts +7 -0
- package/dist/api/usage.d.ts.map +1 -0
- package/dist/api/usage.js +111 -0
- package/dist/api/usage.js.map +1 -0
- package/dist/api/webhooks.d.ts +8 -0
- package/dist/api/webhooks.d.ts.map +1 -0
- package/dist/api/webhooks.js +645 -0
- package/dist/api/webhooks.js.map +1 -0
- package/dist/api/workspaces.d.ts +25 -0
- package/dist/api/workspaces.d.ts.map +1 -0
- package/dist/api/workspaces.js +1799 -0
- package/dist/api/workspaces.js.map +1 -0
- package/dist/billing/index.d.ts +9 -0
- package/dist/billing/index.d.ts.map +1 -0
- package/dist/billing/index.js +9 -0
- package/dist/billing/index.js.map +1 -0
- package/dist/billing/plans.d.ts +39 -0
- package/dist/billing/plans.d.ts.map +1 -0
- package/dist/billing/plans.js +245 -0
- package/dist/billing/plans.js.map +1 -0
- package/dist/billing/service.d.ts +80 -0
- package/dist/billing/service.d.ts.map +1 -0
- package/dist/billing/service.js +388 -0
- package/dist/billing/service.js.map +1 -0
- package/dist/billing/types.d.ts +141 -0
- package/dist/billing/types.d.ts.map +1 -0
- package/dist/billing/types.js +7 -0
- package/dist/billing/types.js.map +1 -0
- package/dist/config.d.ts +5 -0
- package/dist/config.d.ts.map +1 -0
- package/dist/config.js +5 -0
- package/dist/config.js.map +1 -0
- package/dist/db/bulk-ingest.d.ts +89 -0
- package/dist/db/bulk-ingest.d.ts.map +1 -0
- package/dist/db/bulk-ingest.js +268 -0
- package/dist/db/bulk-ingest.js.map +1 -0
- package/dist/db/drizzle.d.ts +256 -0
- package/dist/db/drizzle.d.ts.map +1 -0
- package/dist/db/drizzle.js +1286 -0
- package/dist/db/drizzle.js.map +1 -0
- package/dist/db/index.d.ts +55 -0
- package/dist/db/index.d.ts.map +1 -0
- package/dist/db/index.js +68 -0
- package/dist/db/index.js.map +1 -0
- package/dist/db/schema.d.ts +4873 -0
- package/dist/db/schema.d.ts.map +1 -0
- package/dist/db/schema.js +620 -0
- package/dist/db/schema.js.map +1 -0
- package/dist/index.d.ts +11 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +38 -0
- package/dist/index.js.map +1 -0
- package/dist/provisioner/index.d.ts +207 -0
- package/dist/provisioner/index.d.ts.map +1 -0
- package/dist/provisioner/index.js +2114 -0
- package/dist/provisioner/index.js.map +1 -0
- package/dist/server.d.ts +17 -0
- package/dist/server.d.ts.map +1 -0
- package/dist/server.js +1924 -0
- package/dist/server.js.map +1 -0
- package/dist/services/auto-scaler.d.ts +152 -0
- package/dist/services/auto-scaler.d.ts.map +1 -0
- package/dist/services/auto-scaler.js +439 -0
- package/dist/services/auto-scaler.js.map +1 -0
- package/dist/services/capacity-manager.d.ts +148 -0
- package/dist/services/capacity-manager.d.ts.map +1 -0
- package/dist/services/capacity-manager.js +449 -0
- package/dist/services/capacity-manager.js.map +1 -0
- package/dist/services/ci-agent-spawner.d.ts +49 -0
- package/dist/services/ci-agent-spawner.d.ts.map +1 -0
- package/dist/services/ci-agent-spawner.js +373 -0
- package/dist/services/ci-agent-spawner.js.map +1 -0
- package/dist/services/cloud-message-bus.d.ts +28 -0
- package/dist/services/cloud-message-bus.d.ts.map +1 -0
- package/dist/services/cloud-message-bus.js +19 -0
- package/dist/services/cloud-message-bus.js.map +1 -0
- package/dist/services/compute-enforcement.d.ts +57 -0
- package/dist/services/compute-enforcement.d.ts.map +1 -0
- package/dist/services/compute-enforcement.js +175 -0
- package/dist/services/compute-enforcement.js.map +1 -0
- package/dist/services/coordinator.d.ts +62 -0
- package/dist/services/coordinator.d.ts.map +1 -0
- package/dist/services/coordinator.js +389 -0
- package/dist/services/coordinator.js.map +1 -0
- package/dist/services/index.d.ts +17 -0
- package/dist/services/index.d.ts.map +1 -0
- package/dist/services/index.js +25 -0
- package/dist/services/index.js.map +1 -0
- package/dist/services/intro-expiration.d.ts +60 -0
- package/dist/services/intro-expiration.d.ts.map +1 -0
- package/dist/services/intro-expiration.js +252 -0
- package/dist/services/intro-expiration.js.map +1 -0
- package/dist/services/mention-handler.d.ts +65 -0
- package/dist/services/mention-handler.d.ts.map +1 -0
- package/dist/services/mention-handler.js +405 -0
- package/dist/services/mention-handler.js.map +1 -0
- package/dist/services/nango.d.ts +201 -0
- package/dist/services/nango.d.ts.map +1 -0
- package/dist/services/nango.js +392 -0
- package/dist/services/nango.js.map +1 -0
- package/dist/services/persistence.d.ts +131 -0
- package/dist/services/persistence.d.ts.map +1 -0
- package/dist/services/persistence.js +200 -0
- package/dist/services/persistence.js.map +1 -0
- package/dist/services/planLimits.d.ts +147 -0
- package/dist/services/planLimits.d.ts.map +1 -0
- package/dist/services/planLimits.js +335 -0
- package/dist/services/planLimits.js.map +1 -0
- package/dist/services/presence-registry.d.ts +56 -0
- package/dist/services/presence-registry.d.ts.map +1 -0
- package/dist/services/presence-registry.js +91 -0
- package/dist/services/presence-registry.js.map +1 -0
- package/dist/services/scaling-orchestrator.d.ts +159 -0
- package/dist/services/scaling-orchestrator.d.ts.map +1 -0
- package/dist/services/scaling-orchestrator.js +502 -0
- package/dist/services/scaling-orchestrator.js.map +1 -0
- package/dist/services/scaling-policy.d.ts +121 -0
- package/dist/services/scaling-policy.d.ts.map +1 -0
- package/dist/services/scaling-policy.js +415 -0
- package/dist/services/scaling-policy.js.map +1 -0
- package/dist/services/ssh-security.d.ts +31 -0
- package/dist/services/ssh-security.d.ts.map +1 -0
- package/dist/services/ssh-security.js +63 -0
- package/dist/services/ssh-security.js.map +1 -0
- package/dist/services/workspace-keepalive.d.ts +76 -0
- package/dist/services/workspace-keepalive.d.ts.map +1 -0
- package/dist/services/workspace-keepalive.js +234 -0
- package/dist/services/workspace-keepalive.js.map +1 -0
- package/dist/shims/consensus.d.ts +23 -0
- package/dist/shims/consensus.d.ts.map +1 -0
- package/dist/shims/consensus.js +5 -0
- package/dist/shims/consensus.js.map +1 -0
- package/dist/webhooks/index.d.ts +24 -0
- package/dist/webhooks/index.d.ts.map +1 -0
- package/dist/webhooks/index.js +29 -0
- package/dist/webhooks/index.js.map +1 -0
- package/dist/webhooks/parsers/github.d.ts +8 -0
- package/dist/webhooks/parsers/github.d.ts.map +1 -0
- package/dist/webhooks/parsers/github.js +234 -0
- package/dist/webhooks/parsers/github.js.map +1 -0
- package/dist/webhooks/parsers/index.d.ts +23 -0
- package/dist/webhooks/parsers/index.d.ts.map +1 -0
- package/dist/webhooks/parsers/index.js +30 -0
- package/dist/webhooks/parsers/index.js.map +1 -0
- package/dist/webhooks/parsers/linear.d.ts +9 -0
- package/dist/webhooks/parsers/linear.d.ts.map +1 -0
- package/dist/webhooks/parsers/linear.js +258 -0
- package/dist/webhooks/parsers/linear.js.map +1 -0
- package/dist/webhooks/parsers/slack.d.ts +9 -0
- package/dist/webhooks/parsers/slack.d.ts.map +1 -0
- package/dist/webhooks/parsers/slack.js +214 -0
- package/dist/webhooks/parsers/slack.js.map +1 -0
- package/dist/webhooks/responders/github.d.ts +8 -0
- package/dist/webhooks/responders/github.d.ts.map +1 -0
- package/dist/webhooks/responders/github.js +73 -0
- package/dist/webhooks/responders/github.js.map +1 -0
- package/dist/webhooks/responders/index.d.ts +23 -0
- package/dist/webhooks/responders/index.d.ts.map +1 -0
- package/dist/webhooks/responders/index.js +30 -0
- package/dist/webhooks/responders/index.js.map +1 -0
- package/dist/webhooks/responders/linear.d.ts +9 -0
- package/dist/webhooks/responders/linear.d.ts.map +1 -0
- package/dist/webhooks/responders/linear.js +149 -0
- package/dist/webhooks/responders/linear.js.map +1 -0
- package/dist/webhooks/responders/slack.d.ts +20 -0
- package/dist/webhooks/responders/slack.d.ts.map +1 -0
- package/dist/webhooks/responders/slack.js +178 -0
- package/dist/webhooks/responders/slack.js.map +1 -0
- package/dist/webhooks/router.d.ts +25 -0
- package/dist/webhooks/router.d.ts.map +1 -0
- package/dist/webhooks/router.js +504 -0
- package/dist/webhooks/router.js.map +1 -0
- package/dist/webhooks/rules-engine.d.ts +24 -0
- package/dist/webhooks/rules-engine.d.ts.map +1 -0
- package/dist/webhooks/rules-engine.js +287 -0
- package/dist/webhooks/rules-engine.js.map +1 -0
- package/dist/webhooks/types.d.ts +186 -0
- package/dist/webhooks/types.d.ts.map +1 -0
- package/dist/webhooks/types.js +8 -0
- package/dist/webhooks/types.js.map +1 -0
- package/package.json +55 -0
|
@@ -0,0 +1,449 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Capacity Manager
|
|
3
|
+
*
|
|
4
|
+
* Tracks workspace capacity across the fleet and provides:
|
|
5
|
+
* - Real-time capacity metrics
|
|
6
|
+
* - Optimal agent placement recommendations
|
|
7
|
+
* - Load balancing decisions
|
|
8
|
+
* - Capacity forecasting based on trends
|
|
9
|
+
*
|
|
10
|
+
* Works with AutoScaler to determine when to provision new instances
|
|
11
|
+
* and with Coordinator to place agents optimally.
|
|
12
|
+
*/
|
|
13
|
+
import { EventEmitter } from 'events';
|
|
14
|
+
import { createClient } from 'redis';
|
|
15
|
+
const DEFAULT_CONFIG = {
|
|
16
|
+
healthCheckIntervalMs: 15000, // 15 seconds
|
|
17
|
+
staleThresholdMs: 60000, // 1 minute
|
|
18
|
+
memoryWeightFactor: 0.4,
|
|
19
|
+
agentWeightFactor: 0.4,
|
|
20
|
+
cpuWeightFactor: 0.2,
|
|
21
|
+
redisKeyPrefix: 'capacity:',
|
|
22
|
+
};
|
|
23
|
+
// Redis channels
|
|
24
|
+
const CHANNELS = {
|
|
25
|
+
CAPACITY_UPDATE: 'capacity:update',
|
|
26
|
+
PLACEMENT_REQUEST: 'capacity:placement',
|
|
27
|
+
};
|
|
28
|
+
export class CapacityManager extends EventEmitter {
|
|
29
|
+
config;
|
|
30
|
+
redis = null;
|
|
31
|
+
subscriber = null;
|
|
32
|
+
capacityMap = new Map();
|
|
33
|
+
userWorkspaces = new Map(); // userId -> workspaceIds
|
|
34
|
+
trendHistory = new Map();
|
|
35
|
+
healthCheckTimer = null;
|
|
36
|
+
constructor(config = {}) {
|
|
37
|
+
super();
|
|
38
|
+
this.config = { ...DEFAULT_CONFIG, ...config };
|
|
39
|
+
}
|
|
40
|
+
/**
|
|
41
|
+
* Initialize with Redis for cross-server sync
|
|
42
|
+
*/
|
|
43
|
+
async initialize(redisUrl) {
|
|
44
|
+
try {
|
|
45
|
+
this.redis = createClient({ url: redisUrl });
|
|
46
|
+
this.redis.on('error', (err) => this.emit('error', { context: 'redis', error: err }));
|
|
47
|
+
this.subscriber = createClient({ url: redisUrl });
|
|
48
|
+
this.subscriber.on('error', (err) => this.emit('error', { context: 'subscriber', error: err }));
|
|
49
|
+
await Promise.all([this.redis.connect(), this.subscriber.connect()]);
|
|
50
|
+
// Subscribe to capacity updates
|
|
51
|
+
await this.subscriber.subscribe(CHANNELS.CAPACITY_UPDATE, (message) => {
|
|
52
|
+
try {
|
|
53
|
+
const capacity = JSON.parse(message);
|
|
54
|
+
capacity.lastHeartbeat = new Date(capacity.lastHeartbeat);
|
|
55
|
+
capacity.lastMetricsUpdate = new Date(capacity.lastMetricsUpdate);
|
|
56
|
+
this.updateLocalCapacity(capacity);
|
|
57
|
+
}
|
|
58
|
+
catch (error) {
|
|
59
|
+
this.emit('error', { context: 'capacity_parse', error });
|
|
60
|
+
}
|
|
61
|
+
});
|
|
62
|
+
// Load existing capacity from Redis
|
|
63
|
+
await this.loadFromRedis();
|
|
64
|
+
// Start health check loop
|
|
65
|
+
this.startHealthCheckLoop();
|
|
66
|
+
this.emit('initialized');
|
|
67
|
+
}
|
|
68
|
+
catch (error) {
|
|
69
|
+
this.emit('error', error);
|
|
70
|
+
throw error;
|
|
71
|
+
}
|
|
72
|
+
}
|
|
73
|
+
/**
|
|
74
|
+
* Load capacity data from Redis
|
|
75
|
+
*/
|
|
76
|
+
async loadFromRedis() {
|
|
77
|
+
if (!this.redis)
|
|
78
|
+
return;
|
|
79
|
+
const keys = await this.redis.keys(`${this.config.redisKeyPrefix}workspace:*`);
|
|
80
|
+
for (const key of keys) {
|
|
81
|
+
const data = await this.redis.get(key);
|
|
82
|
+
if (data) {
|
|
83
|
+
try {
|
|
84
|
+
const capacity = JSON.parse(data);
|
|
85
|
+
capacity.lastHeartbeat = new Date(capacity.lastHeartbeat);
|
|
86
|
+
capacity.lastMetricsUpdate = new Date(capacity.lastMetricsUpdate);
|
|
87
|
+
this.updateLocalCapacity(capacity);
|
|
88
|
+
}
|
|
89
|
+
catch {
|
|
90
|
+
// Skip invalid entries
|
|
91
|
+
}
|
|
92
|
+
}
|
|
93
|
+
}
|
|
94
|
+
}
|
|
95
|
+
/**
|
|
96
|
+
* Update local capacity map
|
|
97
|
+
*/
|
|
98
|
+
updateLocalCapacity(capacity) {
|
|
99
|
+
this.capacityMap.set(capacity.workspaceId, capacity);
|
|
100
|
+
// Track user -> workspace mapping
|
|
101
|
+
let userWorkspaceSet = this.userWorkspaces.get(capacity.userId);
|
|
102
|
+
if (!userWorkspaceSet) {
|
|
103
|
+
userWorkspaceSet = new Set();
|
|
104
|
+
this.userWorkspaces.set(capacity.userId, userWorkspaceSet);
|
|
105
|
+
}
|
|
106
|
+
userWorkspaceSet.add(capacity.workspaceId);
|
|
107
|
+
// Update trend history
|
|
108
|
+
this.updateTrendHistory(capacity);
|
|
109
|
+
this.emit('capacity_updated', capacity);
|
|
110
|
+
}
|
|
111
|
+
/**
|
|
112
|
+
* Update trend history for forecasting
|
|
113
|
+
*/
|
|
114
|
+
updateTrendHistory(capacity) {
|
|
115
|
+
const key = capacity.workspaceId;
|
|
116
|
+
let history = this.trendHistory.get(key) || [];
|
|
117
|
+
history.push({
|
|
118
|
+
timestamp: new Date(),
|
|
119
|
+
agents: capacity.currentAgents,
|
|
120
|
+
memory: capacity.memoryUsedBytes,
|
|
121
|
+
});
|
|
122
|
+
// Keep only last 30 minutes of history
|
|
123
|
+
const cutoff = Date.now() - 30 * 60 * 1000;
|
|
124
|
+
history = history.filter((h) => h.timestamp.getTime() > cutoff);
|
|
125
|
+
this.trendHistory.set(key, history);
|
|
126
|
+
}
|
|
127
|
+
/**
|
|
128
|
+
* Report capacity from a workspace
|
|
129
|
+
*/
|
|
130
|
+
async reportCapacity(workspaceId, userId, metrics) {
|
|
131
|
+
const existing = this.capacityMap.get(workspaceId);
|
|
132
|
+
const capacity = {
|
|
133
|
+
workspaceId,
|
|
134
|
+
userId,
|
|
135
|
+
provider: metrics.provider || existing?.provider || 'unknown',
|
|
136
|
+
region: metrics.region || existing?.region || 'unknown',
|
|
137
|
+
currentAgents: metrics.currentAgents ?? existing?.currentAgents ?? 0,
|
|
138
|
+
maxAgents: metrics.maxAgents ?? existing?.maxAgents ?? 10,
|
|
139
|
+
memoryUsedBytes: metrics.memoryUsedBytes ?? existing?.memoryUsedBytes ?? 0,
|
|
140
|
+
memoryLimitBytes: metrics.memoryLimitBytes ?? existing?.memoryLimitBytes ?? 512 * 1024 * 1024,
|
|
141
|
+
cpuPercent: metrics.cpuPercent ?? existing?.cpuPercent ?? 0,
|
|
142
|
+
agentCapacityPercent: 0,
|
|
143
|
+
memoryCapacityPercent: 0,
|
|
144
|
+
overallHealthScore: 0,
|
|
145
|
+
lastHeartbeat: new Date(),
|
|
146
|
+
lastMetricsUpdate: new Date(),
|
|
147
|
+
};
|
|
148
|
+
// Calculate derived metrics
|
|
149
|
+
capacity.agentCapacityPercent = (capacity.currentAgents / capacity.maxAgents) * 100;
|
|
150
|
+
capacity.memoryCapacityPercent = (capacity.memoryUsedBytes / capacity.memoryLimitBytes) * 100;
|
|
151
|
+
capacity.overallHealthScore = this.calculateHealthScore(capacity);
|
|
152
|
+
// Update local map
|
|
153
|
+
this.updateLocalCapacity(capacity);
|
|
154
|
+
// Persist to Redis and broadcast
|
|
155
|
+
if (this.redis) {
|
|
156
|
+
const key = `${this.config.redisKeyPrefix}workspace:${workspaceId}`;
|
|
157
|
+
await this.redis.set(key, JSON.stringify(capacity), { EX: 300 }); // 5 min TTL
|
|
158
|
+
await this.redis.publish(CHANNELS.CAPACITY_UPDATE, JSON.stringify(capacity));
|
|
159
|
+
}
|
|
160
|
+
}
|
|
161
|
+
/**
|
|
162
|
+
* Calculate health score for a workspace (lower is healthier/better for placement)
|
|
163
|
+
*/
|
|
164
|
+
calculateHealthScore(capacity) {
|
|
165
|
+
const memoryScore = capacity.memoryCapacityPercent * this.config.memoryWeightFactor;
|
|
166
|
+
const agentScore = capacity.agentCapacityPercent * this.config.agentWeightFactor;
|
|
167
|
+
const cpuScore = capacity.cpuPercent * this.config.cpuWeightFactor;
|
|
168
|
+
return memoryScore + agentScore + cpuScore;
|
|
169
|
+
}
|
|
170
|
+
/**
|
|
171
|
+
* Get best workspace for placing a new agent
|
|
172
|
+
*/
|
|
173
|
+
recommendPlacement(userId, agentCount = 1) {
|
|
174
|
+
const userWorkspaceIds = this.userWorkspaces.get(userId);
|
|
175
|
+
if (!userWorkspaceIds || userWorkspaceIds.size === 0) {
|
|
176
|
+
return [];
|
|
177
|
+
}
|
|
178
|
+
const recommendations = [];
|
|
179
|
+
for (const workspaceId of userWorkspaceIds) {
|
|
180
|
+
const capacity = this.capacityMap.get(workspaceId);
|
|
181
|
+
if (!capacity)
|
|
182
|
+
continue;
|
|
183
|
+
// Skip stale workspaces
|
|
184
|
+
if (Date.now() - capacity.lastHeartbeat.getTime() > this.config.staleThresholdMs) {
|
|
185
|
+
continue;
|
|
186
|
+
}
|
|
187
|
+
// Check if workspace can accommodate new agents
|
|
188
|
+
const availableSlots = capacity.maxAgents - capacity.currentAgents;
|
|
189
|
+
if (availableSlots < agentCount) {
|
|
190
|
+
continue;
|
|
191
|
+
}
|
|
192
|
+
// Calculate estimated capacity after placement
|
|
193
|
+
const newAgentCount = capacity.currentAgents + agentCount;
|
|
194
|
+
const estimatedCapacityAfter = (newAgentCount / capacity.maxAgents) * 100;
|
|
195
|
+
// Calculate placement score (lower is better)
|
|
196
|
+
let score = capacity.overallHealthScore;
|
|
197
|
+
// Penalize workspaces that would be over 80% after placement
|
|
198
|
+
if (estimatedCapacityAfter > 80) {
|
|
199
|
+
score += (estimatedCapacityAfter - 80) * 2;
|
|
200
|
+
}
|
|
201
|
+
// Bonus for workspaces with room to grow
|
|
202
|
+
if (estimatedCapacityAfter < 50) {
|
|
203
|
+
score -= (50 - estimatedCapacityAfter) * 0.5;
|
|
204
|
+
}
|
|
205
|
+
const reason = this.getPlacementReason(capacity, estimatedCapacityAfter);
|
|
206
|
+
recommendations.push({
|
|
207
|
+
workspaceId,
|
|
208
|
+
score: Math.max(0, score),
|
|
209
|
+
reason,
|
|
210
|
+
estimatedCapacityAfter,
|
|
211
|
+
});
|
|
212
|
+
}
|
|
213
|
+
// Sort by score (lower is better)
|
|
214
|
+
return recommendations.sort((a, b) => a.score - b.score);
|
|
215
|
+
}
|
|
216
|
+
/**
|
|
217
|
+
* Generate human-readable placement reason
|
|
218
|
+
*/
|
|
219
|
+
getPlacementReason(capacity, estimatedAfter) {
|
|
220
|
+
if (capacity.overallHealthScore < 30) {
|
|
221
|
+
return 'Workspace is healthy with low utilization';
|
|
222
|
+
}
|
|
223
|
+
else if (capacity.overallHealthScore < 50) {
|
|
224
|
+
return 'Workspace has moderate load, good for placement';
|
|
225
|
+
}
|
|
226
|
+
else if (capacity.overallHealthScore < 70) {
|
|
227
|
+
return 'Workspace under load but can accommodate';
|
|
228
|
+
}
|
|
229
|
+
else {
|
|
230
|
+
return `Workspace at ${Math.round(estimatedAfter)}% capacity after placement`;
|
|
231
|
+
}
|
|
232
|
+
}
|
|
233
|
+
/**
|
|
234
|
+
* Get capacity snapshot for a user
|
|
235
|
+
*/
|
|
236
|
+
getCapacitySnapshot(userId) {
|
|
237
|
+
const userWorkspaceIds = this.userWorkspaces.get(userId);
|
|
238
|
+
if (!userWorkspaceIds || userWorkspaceIds.size === 0) {
|
|
239
|
+
return null;
|
|
240
|
+
}
|
|
241
|
+
const workspaces = [];
|
|
242
|
+
let totalAgents = 0;
|
|
243
|
+
let totalMaxAgents = 0;
|
|
244
|
+
let totalMemory = 0;
|
|
245
|
+
let totalMemoryLimit = 0;
|
|
246
|
+
let healthScoreSum = 0;
|
|
247
|
+
for (const workspaceId of userWorkspaceIds) {
|
|
248
|
+
const capacity = this.capacityMap.get(workspaceId);
|
|
249
|
+
if (capacity) {
|
|
250
|
+
workspaces.push(capacity);
|
|
251
|
+
totalAgents += capacity.currentAgents;
|
|
252
|
+
totalMaxAgents += capacity.maxAgents;
|
|
253
|
+
totalMemory += capacity.memoryUsedBytes;
|
|
254
|
+
totalMemoryLimit += capacity.memoryLimitBytes;
|
|
255
|
+
healthScoreSum += capacity.overallHealthScore;
|
|
256
|
+
}
|
|
257
|
+
}
|
|
258
|
+
return {
|
|
259
|
+
userId,
|
|
260
|
+
totalWorkspaces: workspaces.length,
|
|
261
|
+
totalAgents,
|
|
262
|
+
totalMaxAgents,
|
|
263
|
+
totalMemoryBytes: totalMemory,
|
|
264
|
+
totalMemoryLimitBytes: totalMemoryLimit,
|
|
265
|
+
averageHealthScore: workspaces.length > 0 ? healthScoreSum / workspaces.length : 0,
|
|
266
|
+
workspaces,
|
|
267
|
+
timestamp: new Date(),
|
|
268
|
+
};
|
|
269
|
+
}
|
|
270
|
+
/**
|
|
271
|
+
* Forecast capacity needs based on trends
|
|
272
|
+
*/
|
|
273
|
+
getCapacityForecast(userId) {
|
|
274
|
+
const snapshot = this.getCapacitySnapshot(userId);
|
|
275
|
+
if (!snapshot)
|
|
276
|
+
return null;
|
|
277
|
+
// Calculate aggregate trends
|
|
278
|
+
let totalAgentTrend = 0;
|
|
279
|
+
let totalMemoryTrend = 0;
|
|
280
|
+
let trendSamples = 0;
|
|
281
|
+
for (const workspace of snapshot.workspaces) {
|
|
282
|
+
const history = this.trendHistory.get(workspace.workspaceId);
|
|
283
|
+
if (!history || history.length < 2)
|
|
284
|
+
continue;
|
|
285
|
+
const oldest = history[0];
|
|
286
|
+
const newest = history[history.length - 1];
|
|
287
|
+
const timeSpanMinutes = (newest.timestamp.getTime() - oldest.timestamp.getTime()) / (1000 * 60);
|
|
288
|
+
if (timeSpanMinutes > 0) {
|
|
289
|
+
totalAgentTrend += (newest.agents - oldest.agents) / timeSpanMinutes;
|
|
290
|
+
totalMemoryTrend += (newest.memory - oldest.memory) / timeSpanMinutes;
|
|
291
|
+
trendSamples++;
|
|
292
|
+
}
|
|
293
|
+
}
|
|
294
|
+
// Average trends
|
|
295
|
+
const avgAgentTrend = trendSamples > 0 ? totalAgentTrend / trendSamples : 0;
|
|
296
|
+
const avgMemoryTrend = trendSamples > 0 ? totalMemoryTrend / trendSamples : 0;
|
|
297
|
+
// Project future state
|
|
298
|
+
const projectedAgents15Min = Math.max(0, snapshot.totalAgents + avgAgentTrend * 15);
|
|
299
|
+
const projectedAgents60Min = Math.max(0, snapshot.totalAgents + avgAgentTrend * 60);
|
|
300
|
+
// Check if we'll exceed capacity
|
|
301
|
+
const willExceedCapacity = projectedAgents60Min >= snapshot.totalMaxAgents * 0.9;
|
|
302
|
+
// Calculate time to capacity exhaustion
|
|
303
|
+
let timeToExhaustion;
|
|
304
|
+
if (avgAgentTrend > 0) {
|
|
305
|
+
const remainingSlots = snapshot.totalMaxAgents - snapshot.totalAgents;
|
|
306
|
+
timeToExhaustion = remainingSlots / avgAgentTrend;
|
|
307
|
+
}
|
|
308
|
+
// Generate recommendation
|
|
309
|
+
let recommendation = 'none';
|
|
310
|
+
if (snapshot.totalAgents >= snapshot.totalMaxAgents * 0.95) {
|
|
311
|
+
recommendation = 'critical';
|
|
312
|
+
}
|
|
313
|
+
else if (snapshot.totalAgents >= snapshot.totalMaxAgents * 0.85) {
|
|
314
|
+
recommendation = 'scale_now';
|
|
315
|
+
}
|
|
316
|
+
else if (willExceedCapacity || projectedAgents15Min >= snapshot.totalMaxAgents * 0.8) {
|
|
317
|
+
recommendation = 'scale_soon';
|
|
318
|
+
}
|
|
319
|
+
return {
|
|
320
|
+
userId,
|
|
321
|
+
currentAgents: snapshot.totalAgents,
|
|
322
|
+
projectedAgents15Min: Math.round(projectedAgents15Min),
|
|
323
|
+
projectedAgents60Min: Math.round(projectedAgents60Min),
|
|
324
|
+
memoryTrendPerMinute: avgMemoryTrend,
|
|
325
|
+
willExceedCapacity,
|
|
326
|
+
timeToCapacityExhaustion: timeToExhaustion,
|
|
327
|
+
recommendation,
|
|
328
|
+
};
|
|
329
|
+
}
|
|
330
|
+
/**
|
|
331
|
+
* Convert workspace metrics to capacity format
|
|
332
|
+
*/
|
|
333
|
+
fromWorkspaceMetrics(userId, metrics) {
|
|
334
|
+
return {
|
|
335
|
+
workspaceId: metrics.workspaceId,
|
|
336
|
+
userId,
|
|
337
|
+
currentAgents: metrics.agentCount,
|
|
338
|
+
memoryUsedBytes: metrics.totalMemoryBytes,
|
|
339
|
+
cpuPercent: metrics.cpuPercent,
|
|
340
|
+
};
|
|
341
|
+
}
|
|
342
|
+
/**
|
|
343
|
+
* Health check loop - detect stale workspaces
|
|
344
|
+
*/
|
|
345
|
+
startHealthCheckLoop() {
|
|
346
|
+
if (this.healthCheckTimer) {
|
|
347
|
+
clearInterval(this.healthCheckTimer);
|
|
348
|
+
}
|
|
349
|
+
this.healthCheckTimer = setInterval(() => {
|
|
350
|
+
const now = Date.now();
|
|
351
|
+
for (const [workspaceId, capacity] of this.capacityMap) {
|
|
352
|
+
if (now - capacity.lastHeartbeat.getTime() > this.config.staleThresholdMs) {
|
|
353
|
+
this.emit('workspace_stale', { workspaceId, lastHeartbeat: capacity.lastHeartbeat });
|
|
354
|
+
}
|
|
355
|
+
}
|
|
356
|
+
}, this.config.healthCheckIntervalMs);
|
|
357
|
+
}
|
|
358
|
+
/**
|
|
359
|
+
* Remove a workspace from tracking
|
|
360
|
+
*/
|
|
361
|
+
async removeWorkspace(workspaceId) {
|
|
362
|
+
const capacity = this.capacityMap.get(workspaceId);
|
|
363
|
+
if (capacity) {
|
|
364
|
+
this.capacityMap.delete(workspaceId);
|
|
365
|
+
this.trendHistory.delete(workspaceId);
|
|
366
|
+
const userWorkspaceSet = this.userWorkspaces.get(capacity.userId);
|
|
367
|
+
if (userWorkspaceSet) {
|
|
368
|
+
userWorkspaceSet.delete(workspaceId);
|
|
369
|
+
}
|
|
370
|
+
if (this.redis) {
|
|
371
|
+
await this.redis.del(`${this.config.redisKeyPrefix}workspace:${workspaceId}`);
|
|
372
|
+
}
|
|
373
|
+
this.emit('workspace_removed', workspaceId);
|
|
374
|
+
}
|
|
375
|
+
}
|
|
376
|
+
/**
|
|
377
|
+
* Get all workspaces for a user
|
|
378
|
+
*/
|
|
379
|
+
getUserWorkspaces(userId) {
|
|
380
|
+
const workspaceIds = this.userWorkspaces.get(userId);
|
|
381
|
+
if (!workspaceIds)
|
|
382
|
+
return [];
|
|
383
|
+
const workspaces = [];
|
|
384
|
+
for (const id of workspaceIds) {
|
|
385
|
+
const capacity = this.capacityMap.get(id);
|
|
386
|
+
if (capacity) {
|
|
387
|
+
workspaces.push(capacity);
|
|
388
|
+
}
|
|
389
|
+
}
|
|
390
|
+
return workspaces;
|
|
391
|
+
}
|
|
392
|
+
/**
|
|
393
|
+
* Get global capacity metrics
|
|
394
|
+
*/
|
|
395
|
+
getGlobalMetrics() {
|
|
396
|
+
let totalAgents = 0;
|
|
397
|
+
let totalMaxAgents = 0;
|
|
398
|
+
let utilizationSum = 0;
|
|
399
|
+
let staleCount = 0;
|
|
400
|
+
const now = Date.now();
|
|
401
|
+
for (const capacity of this.capacityMap.values()) {
|
|
402
|
+
totalAgents += capacity.currentAgents;
|
|
403
|
+
totalMaxAgents += capacity.maxAgents;
|
|
404
|
+
utilizationSum += capacity.overallHealthScore;
|
|
405
|
+
if (now - capacity.lastHeartbeat.getTime() > this.config.staleThresholdMs) {
|
|
406
|
+
staleCount++;
|
|
407
|
+
}
|
|
408
|
+
}
|
|
409
|
+
return {
|
|
410
|
+
totalWorkspaces: this.capacityMap.size,
|
|
411
|
+
totalAgents,
|
|
412
|
+
totalMaxAgents,
|
|
413
|
+
averageUtilization: this.capacityMap.size > 0 ? utilizationSum / this.capacityMap.size : 0,
|
|
414
|
+
staleWorkspaces: staleCount,
|
|
415
|
+
};
|
|
416
|
+
}
|
|
417
|
+
/**
|
|
418
|
+
* Clean shutdown
|
|
419
|
+
*/
|
|
420
|
+
async shutdown() {
|
|
421
|
+
if (this.healthCheckTimer) {
|
|
422
|
+
clearInterval(this.healthCheckTimer);
|
|
423
|
+
this.healthCheckTimer = null;
|
|
424
|
+
}
|
|
425
|
+
if (this.subscriber) {
|
|
426
|
+
await this.subscriber.unsubscribe();
|
|
427
|
+
await this.subscriber.quit();
|
|
428
|
+
this.subscriber = null;
|
|
429
|
+
}
|
|
430
|
+
if (this.redis) {
|
|
431
|
+
await this.redis.quit();
|
|
432
|
+
this.redis = null;
|
|
433
|
+
}
|
|
434
|
+
this.emit('shutdown');
|
|
435
|
+
}
|
|
436
|
+
}
|
|
437
|
+
// Singleton instance
|
|
438
|
+
let _capacityManager = null;
|
|
439
|
+
export function getCapacityManager() {
|
|
440
|
+
if (!_capacityManager) {
|
|
441
|
+
_capacityManager = new CapacityManager();
|
|
442
|
+
}
|
|
443
|
+
return _capacityManager;
|
|
444
|
+
}
|
|
445
|
+
export function createCapacityManager(config = {}) {
|
|
446
|
+
_capacityManager = new CapacityManager(config);
|
|
447
|
+
return _capacityManager;
|
|
448
|
+
}
|
|
449
|
+
//# sourceMappingURL=capacity-manager.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"capacity-manager.js","sourceRoot":"","sources":["../../src/services/capacity-manager.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* CI Agent Spawner Service
|
|
3
|
+
*
|
|
4
|
+
* Spawns agents to fix CI failures automatically.
|
|
5
|
+
* Called by the webhook handler when CI checks fail on PRs.
|
|
6
|
+
*
|
|
7
|
+
* Flow:
|
|
8
|
+
* 1. App posts acknowledgment comment on the PR
|
|
9
|
+
* 2. Finds a linked daemon for the repository
|
|
10
|
+
* 3. Queues spawn command for the daemon
|
|
11
|
+
* 4. Agent works and posts response comment
|
|
12
|
+
*/
|
|
13
|
+
import { CIFailureEvent } from '../db/index.js';
|
|
14
|
+
/**
|
|
15
|
+
* Spawn an agent to fix CI failures
|
|
16
|
+
*
|
|
17
|
+
* This function:
|
|
18
|
+
* 1. Finds the workspace for the repository
|
|
19
|
+
* 2. Posts acknowledgment comment
|
|
20
|
+
* 3. Creates a fix attempt record
|
|
21
|
+
* 4. Queues spawn command for a linked daemon
|
|
22
|
+
*
|
|
23
|
+
* @param failureEvent - The CI failure event from the database
|
|
24
|
+
*/
|
|
25
|
+
export declare function spawnCIFixAgent(failureEvent: CIFailureEvent): Promise<void>;
|
|
26
|
+
/**
|
|
27
|
+
* Notify an existing agent about a CI failure
|
|
28
|
+
*
|
|
29
|
+
* Used when an agent is already working on a PR and a new failure occurs.
|
|
30
|
+
*
|
|
31
|
+
* @param agentId - The ID of the existing agent
|
|
32
|
+
* @param failureEvent - The new CI failure event
|
|
33
|
+
*/
|
|
34
|
+
export declare function notifyAgentOfCIFailure(agentId: string, failureEvent: CIFailureEvent): Promise<void>;
|
|
35
|
+
/**
|
|
36
|
+
* Mark a fix attempt as complete
|
|
37
|
+
*
|
|
38
|
+
* Called when an agent reports completion (success or failure)
|
|
39
|
+
*/
|
|
40
|
+
export declare function completeFixAttempt(fixAttemptId: string, success: boolean, commitSha?: string, errorMessage?: string): Promise<void>;
|
|
41
|
+
/**
|
|
42
|
+
* Get failure history for a repository
|
|
43
|
+
*/
|
|
44
|
+
export declare function getFailureHistory(repository: string, limit?: number): Promise<CIFailureEvent[]>;
|
|
45
|
+
/**
|
|
46
|
+
* Get failure history for a specific PR
|
|
47
|
+
*/
|
|
48
|
+
export declare function getPRFailureHistory(repository: string, prNumber: number): Promise<CIFailureEvent[]>;
|
|
49
|
+
//# sourceMappingURL=ci-agent-spawner.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"ci-agent-spawner.d.ts","sourceRoot":"","sources":["../../src/services/ci-agent-spawner.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;GAWG;AAEH,OAAO,EAAM,cAAc,EAA4B,MAAM,gBAAgB,CAAC;AAgK9E;;;;;;;;;;GAUG;AACH,wBAAsB,eAAe,CAAC,YAAY,EAAE,cAAc,GAAG,OAAO,CAAC,IAAI,CAAC,CA4GjF;AA0ED;;;;;;;GAOG;AACH,wBAAsB,sBAAsB,CAC1C,OAAO,EAAE,MAAM,EACf,YAAY,EAAE,cAAc,GAC3B,OAAO,CAAC,IAAI,CAAC,CAkDf;AAED;;;;GAIG;AACH,wBAAsB,kBAAkB,CACtC,YAAY,EAAE,MAAM,EACpB,OAAO,EAAE,OAAO,EAChB,SAAS,CAAC,EAAE,MAAM,EAClB,YAAY,CAAC,EAAE,MAAM,GACpB,OAAO,CAAC,IAAI,CAAC,CAwCf;AAED;;GAEG;AACH,wBAAsB,iBAAiB,CACrC,UAAU,EAAE,MAAM,EAClB,KAAK,SAAK,GACT,OAAO,CAAC,cAAc,EAAE,CAAC,CAE3B;AAED;;GAEG;AACH,wBAAsB,mBAAmB,CACvC,UAAU,EAAE,MAAM,EAClB,QAAQ,EAAE,MAAM,GACf,OAAO,CAAC,cAAc,EAAE,CAAC,CAE3B"}
|