openvibe 0.63.2 → 0.63.3
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 +81 -0
- package/README.md +39 -0
- package/README_CN.md +1 -1
- package/dist/cli/args.d.ts +3 -1
- package/dist/cli/args.d.ts.map +1 -1
- package/dist/cli/args.js +22 -2
- package/dist/cli/args.js.map +1 -1
- package/dist/core/agent-session.d.ts.map +1 -1
- package/dist/core/agent-session.js +5 -3
- package/dist/core/agent-session.js.map +1 -1
- package/dist/core/companion/executor/bash-executor.d.ts +30 -0
- package/dist/core/companion/executor/bash-executor.d.ts.map +1 -0
- package/dist/core/companion/executor/bash-executor.js +105 -0
- package/dist/core/companion/executor/bash-executor.js.map +1 -0
- package/dist/core/companion/executor/code-executor.d.ts +33 -0
- package/dist/core/companion/executor/code-executor.d.ts.map +1 -0
- package/dist/core/companion/executor/code-executor.js +144 -0
- package/dist/core/companion/executor/code-executor.js.map +1 -0
- package/dist/core/companion/executor/resource-monitor.d.ts +55 -0
- package/dist/core/companion/executor/resource-monitor.d.ts.map +1 -0
- package/dist/core/companion/executor/resource-monitor.js +141 -0
- package/dist/core/companion/executor/resource-monitor.js.map +1 -0
- package/dist/core/companion/http-server.d.ts +92 -0
- package/dist/core/companion/http-server.d.ts.map +1 -0
- package/dist/core/companion/http-server.js +229 -0
- package/dist/core/companion/http-server.js.map +1 -0
- package/dist/core/companion/index.d.ts +29 -0
- package/dist/core/companion/index.d.ts.map +1 -0
- package/dist/core/companion/index.js +48 -0
- package/dist/core/companion/index.js.map +1 -0
- package/dist/core/companion/scheduler/resource-scheduler.d.ts +82 -0
- package/dist/core/companion/scheduler/resource-scheduler.d.ts.map +1 -0
- package/dist/core/companion/scheduler/resource-scheduler.js +333 -0
- package/dist/core/companion/scheduler/resource-scheduler.js.map +1 -0
- package/dist/core/companion/scheduler/workers/base-worker.d.ts +87 -0
- package/dist/core/companion/scheduler/workers/base-worker.d.ts.map +1 -0
- package/dist/core/companion/scheduler/workers/base-worker.js +70 -0
- package/dist/core/companion/scheduler/workers/base-worker.js.map +1 -0
- package/dist/core/companion/scheduler/workers/cpu-worker.d.ts +12 -0
- package/dist/core/companion/scheduler/workers/cpu-worker.d.ts.map +1 -0
- package/dist/core/companion/scheduler/workers/cpu-worker.js +134 -0
- package/dist/core/companion/scheduler/workers/cpu-worker.js.map +1 -0
- package/dist/core/companion/scheduler/workers/gpu-worker.d.ts +16 -0
- package/dist/core/companion/scheduler/workers/gpu-worker.d.ts.map +1 -0
- package/dist/core/companion/scheduler/workers/gpu-worker.js +167 -0
- package/dist/core/companion/scheduler/workers/gpu-worker.js.map +1 -0
- package/dist/core/companion/scheduler/workers/index.d.ts +6 -0
- package/dist/core/companion/scheduler/workers/index.d.ts.map +1 -0
- package/dist/core/companion/scheduler/workers/index.js +6 -0
- package/dist/core/companion/scheduler/workers/index.js.map +1 -0
- package/dist/core/companion/scheduler/workers/io-worker.d.ts +17 -0
- package/dist/core/companion/scheduler/workers/io-worker.d.ts.map +1 -0
- package/dist/core/companion/scheduler/workers/io-worker.js +197 -0
- package/dist/core/companion/scheduler/workers/io-worker.js.map +1 -0
- package/dist/core/companion/scheduler/workers/network-worker.d.ts +13 -0
- package/dist/core/companion/scheduler/workers/network-worker.d.ts.map +1 -0
- package/dist/core/companion/scheduler/workers/network-worker.js +167 -0
- package/dist/core/companion/scheduler/workers/network-worker.js.map +1 -0
- package/dist/core/companion/security/security-manager.d.ts +50 -0
- package/dist/core/companion/security/security-manager.d.ts.map +1 -0
- package/dist/core/companion/security/security-manager.js +102 -0
- package/dist/core/companion/security/security-manager.js.map +1 -0
- package/dist/core/hybrid-cloud/extension.d.ts +8 -0
- package/dist/core/hybrid-cloud/extension.d.ts.map +1 -0
- package/dist/core/hybrid-cloud/extension.js +64 -0
- package/dist/core/hybrid-cloud/extension.js.map +1 -0
- package/dist/core/hybrid-cloud/index.d.ts +98 -0
- package/dist/core/hybrid-cloud/index.d.ts.map +1 -0
- package/dist/core/hybrid-cloud/index.js +211 -0
- package/dist/core/hybrid-cloud/index.js.map +1 -0
- package/dist/core/keybindings.d.ts +1 -1
- package/dist/core/keybindings.d.ts.map +1 -1
- package/dist/core/keybindings.js +3 -1
- package/dist/core/keybindings.js.map +1 -1
- package/dist/core/package-manager.d.ts.map +1 -1
- package/dist/core/package-manager.js +6 -1
- package/dist/core/package-manager.js.map +1 -1
- package/dist/core/settings-manager.d.ts +13 -0
- package/dist/core/settings-manager.d.ts.map +1 -1
- package/dist/core/settings-manager.js +35 -0
- package/dist/core/settings-manager.js.map +1 -1
- package/dist/core/slash-commands.d.ts.map +1 -1
- package/dist/core/slash-commands.js +7 -0
- package/dist/core/slash-commands.js.map +1 -1
- package/dist/core/system-prompt.d.ts.map +1 -1
- package/dist/core/system-prompt.js +46 -0
- package/dist/core/system-prompt.js.map +1 -1
- package/dist/core/todo-manager.d.ts +32 -0
- package/dist/core/todo-manager.d.ts.map +1 -0
- package/dist/core/todo-manager.js +117 -0
- package/dist/core/todo-manager.js.map +1 -0
- package/dist/core/tools/batch-write.d.ts +42 -0
- package/dist/core/tools/batch-write.d.ts.map +1 -0
- package/dist/core/tools/batch-write.js +267 -0
- package/dist/core/tools/batch-write.js.map +1 -0
- package/dist/core/tools/edit.d.ts.map +1 -1
- package/dist/core/tools/edit.js +10 -2
- package/dist/core/tools/edit.js.map +1 -1
- package/dist/core/tools/fast-executor.d.ts +6 -1
- package/dist/core/tools/fast-executor.d.ts.map +1 -1
- package/dist/core/tools/fast-executor.js +83 -4
- package/dist/core/tools/fast-executor.js.map +1 -1
- package/dist/core/tools/index.d.ts +141 -0
- package/dist/core/tools/index.d.ts.map +1 -1
- package/dist/core/tools/index.js +30 -0
- package/dist/core/tools/index.js.map +1 -1
- package/dist/core/tools/todo.d.ts +47 -0
- package/dist/core/tools/todo.d.ts.map +1 -0
- package/dist/core/tools/todo.js +212 -0
- package/dist/core/tools/todo.js.map +1 -0
- package/dist/core/tools/unified.d.ts +121 -0
- package/dist/core/tools/unified.d.ts.map +1 -0
- package/dist/core/tools/unified.js +481 -0
- package/dist/core/tools/unified.js.map +1 -0
- package/dist/core/tools/write.d.ts +1 -1
- package/dist/core/tools/write.d.ts.map +1 -1
- package/dist/core/tools/write.js +20 -5
- package/dist/core/tools/write.js.map +1 -1
- package/dist/main.d.ts.map +1 -1
- package/dist/main.js +63 -1
- package/dist/main.js.map +1 -1
- package/dist/modes/index.d.ts +2 -0
- package/dist/modes/index.d.ts.map +1 -1
- package/dist/modes/index.js +2 -0
- package/dist/modes/index.js.map +1 -1
- package/dist/modes/interactive/components/index.d.ts +1 -0
- package/dist/modes/interactive/components/index.d.ts.map +1 -1
- package/dist/modes/interactive/components/index.js +1 -0
- package/dist/modes/interactive/components/index.js.map +1 -1
- package/dist/modes/interactive/components/todo-display.d.ts +9 -0
- package/dist/modes/interactive/components/todo-display.d.ts.map +1 -0
- package/dist/modes/interactive/components/todo-display.js +60 -0
- package/dist/modes/interactive/components/todo-display.js.map +1 -0
- package/dist/modes/interactive/interactive-mode.d.ts +8 -0
- package/dist/modes/interactive/interactive-mode.d.ts.map +1 -1
- package/dist/modes/interactive/interactive-mode.js +151 -0
- package/dist/modes/interactive/interactive-mode.js.map +1 -1
- package/dist/modes/plan-mode.d.ts +14 -0
- package/dist/modes/plan-mode.d.ts.map +1 -0
- package/dist/modes/plan-mode.js +107 -0
- package/dist/modes/plan-mode.js.map +1 -0
- package/dist/modes/spec-mode.d.ts +16 -0
- package/dist/modes/spec-mode.d.ts.map +1 -0
- package/dist/modes/spec-mode.js +186 -0
- package/dist/modes/spec-mode.js.map +1 -0
- package/dist/utils/version-check.d.ts.map +1 -1
- package/dist/utils/version-check.js +2 -2
- package/dist/utils/version-check.js.map +1 -1
- package/docs/HYBRID_CLOUD_README.md +188 -0
- package/docs/hybrid-architecture-design.md +317 -0
- package/docs/todo.md +71 -0
- package/examples/extensions/custom-provider-anthropic/package-lock.json +2 -2
- package/examples/extensions/custom-provider-anthropic/package.json +1 -1
- package/examples/extensions/custom-provider-gitlab-duo/package.json +1 -1
- package/examples/extensions/custom-provider-qwen-cli/package.json +1 -1
- package/examples/extensions/with-deps/package-lock.json +2 -2
- package/examples/extensions/with-deps/package.json +1 -1
- package/package.json +4 -4
|
@@ -0,0 +1,333 @@
|
|
|
1
|
+
import { EventEmitter } from "events";
|
|
2
|
+
import { ResourceMonitor } from "../executor/resource-monitor.js";
|
|
3
|
+
import { CPUWorker, GPUWorker, IOWorker, NetworkWorker, } from "./workers/index.js";
|
|
4
|
+
const PRIORITY_WEIGHTS = {
|
|
5
|
+
critical: 100,
|
|
6
|
+
high: 75,
|
|
7
|
+
medium: 50,
|
|
8
|
+
low: 25,
|
|
9
|
+
};
|
|
10
|
+
const TASK_TYPE_WORKER_MAP = {
|
|
11
|
+
render: ["gpu", "cpu"],
|
|
12
|
+
io_heavy: ["io", "cpu"],
|
|
13
|
+
cpu_intensive: ["cpu"],
|
|
14
|
+
network: ["network"],
|
|
15
|
+
script: ["cpu", "io"],
|
|
16
|
+
bash: ["cpu"],
|
|
17
|
+
code: ["cpu", "gpu"],
|
|
18
|
+
};
|
|
19
|
+
export class ResourceScheduler extends EventEmitter {
|
|
20
|
+
config;
|
|
21
|
+
resourceMonitor;
|
|
22
|
+
workers = new Map();
|
|
23
|
+
taskQueue = [];
|
|
24
|
+
runningTasks = new Map();
|
|
25
|
+
taskCounter = 0;
|
|
26
|
+
stats = {
|
|
27
|
+
totalTasks: 0,
|
|
28
|
+
completedTasks: 0,
|
|
29
|
+
failedTasks: 0,
|
|
30
|
+
queuedTasks: 0,
|
|
31
|
+
runningTasks: 0,
|
|
32
|
+
averageWaitTime: 0,
|
|
33
|
+
averageExecutionTime: 0,
|
|
34
|
+
};
|
|
35
|
+
isProcessing = false;
|
|
36
|
+
processInterval;
|
|
37
|
+
constructor(config = {}) {
|
|
38
|
+
super();
|
|
39
|
+
this.config = {
|
|
40
|
+
maxConcurrentTasks: config.maxConcurrentTasks ?? 8,
|
|
41
|
+
enableGPU: config.enableGPU ?? true,
|
|
42
|
+
maxCPUWorkers: config.maxCPUWorkers ?? 4,
|
|
43
|
+
maxGPUWorkers: config.maxGPUWorkers ?? 2,
|
|
44
|
+
maxIOWorkers: config.maxIOWorkers ?? 2,
|
|
45
|
+
maxNetworkWorkers: config.maxNetworkWorkers ?? 2,
|
|
46
|
+
taskTimeout: config.taskTimeout ?? 300000,
|
|
47
|
+
priorityBoost: config.priorityBoost ?? true,
|
|
48
|
+
};
|
|
49
|
+
this.resourceMonitor = new ResourceMonitor();
|
|
50
|
+
this.initializeWorkers();
|
|
51
|
+
}
|
|
52
|
+
initializeWorkers() {
|
|
53
|
+
for (let i = 0; i < this.config.maxCPUWorkers; i++) {
|
|
54
|
+
const worker = new CPUWorker(`cpu_${i}`);
|
|
55
|
+
this.workers.set(worker.id, worker);
|
|
56
|
+
}
|
|
57
|
+
if (this.config.enableGPU) {
|
|
58
|
+
for (let i = 0; i < this.config.maxGPUWorkers; i++) {
|
|
59
|
+
const worker = new GPUWorker(`gpu_${i}`);
|
|
60
|
+
if (worker.capabilities.hasGpu) {
|
|
61
|
+
this.workers.set(worker.id, worker);
|
|
62
|
+
}
|
|
63
|
+
}
|
|
64
|
+
}
|
|
65
|
+
for (let i = 0; i < this.config.maxIOWorkers; i++) {
|
|
66
|
+
const worker = new IOWorker(`io_${i}`);
|
|
67
|
+
this.workers.set(worker.id, worker);
|
|
68
|
+
}
|
|
69
|
+
for (let i = 0; i < this.config.maxNetworkWorkers; i++) {
|
|
70
|
+
const worker = new NetworkWorker(`net_${i}`);
|
|
71
|
+
this.workers.set(worker.id, worker);
|
|
72
|
+
}
|
|
73
|
+
}
|
|
74
|
+
dispatch(taskType, payload, requirements) {
|
|
75
|
+
const task = this.createTask(taskType, payload, requirements);
|
|
76
|
+
return this.submitTask(task);
|
|
77
|
+
}
|
|
78
|
+
submit(task) {
|
|
79
|
+
const fullTask = this.createTask(task.type, task.payload, task.requirements);
|
|
80
|
+
fullTask.priority = task.priority;
|
|
81
|
+
fullTask.metadata = task.metadata;
|
|
82
|
+
return this.submitTask(fullTask);
|
|
83
|
+
}
|
|
84
|
+
createTask(type, payload, requirements) {
|
|
85
|
+
this.taskCounter++;
|
|
86
|
+
return {
|
|
87
|
+
id: `task_${Date.now()}_${this.taskCounter}`,
|
|
88
|
+
type,
|
|
89
|
+
priority: "medium",
|
|
90
|
+
status: "pending",
|
|
91
|
+
payload,
|
|
92
|
+
requirements,
|
|
93
|
+
createdAt: new Date(),
|
|
94
|
+
};
|
|
95
|
+
}
|
|
96
|
+
submitTask(task) {
|
|
97
|
+
return new Promise((resolve, reject) => {
|
|
98
|
+
const queuedTask = {
|
|
99
|
+
task,
|
|
100
|
+
resolve,
|
|
101
|
+
reject,
|
|
102
|
+
addedAt: new Date(),
|
|
103
|
+
};
|
|
104
|
+
this.taskQueue.push(queuedTask);
|
|
105
|
+
this.stats.totalTasks++;
|
|
106
|
+
this.stats.queuedTasks = this.taskQueue.length;
|
|
107
|
+
this.sortQueue();
|
|
108
|
+
this.emit("taskQueued", task);
|
|
109
|
+
this.processQueue();
|
|
110
|
+
});
|
|
111
|
+
}
|
|
112
|
+
sortQueue() {
|
|
113
|
+
if (!this.config.priorityBoost) {
|
|
114
|
+
return;
|
|
115
|
+
}
|
|
116
|
+
this.taskQueue.sort((a, b) => {
|
|
117
|
+
const priorityDiff = PRIORITY_WEIGHTS[b.task.priority] - PRIORITY_WEIGHTS[a.task.priority];
|
|
118
|
+
if (priorityDiff !== 0) {
|
|
119
|
+
return priorityDiff;
|
|
120
|
+
}
|
|
121
|
+
return a.addedAt.getTime() - b.addedAt.getTime();
|
|
122
|
+
});
|
|
123
|
+
}
|
|
124
|
+
processQueue() {
|
|
125
|
+
if (this.isProcessing) {
|
|
126
|
+
return;
|
|
127
|
+
}
|
|
128
|
+
this.isProcessing = true;
|
|
129
|
+
this.doProcessQueue();
|
|
130
|
+
}
|
|
131
|
+
async doProcessQueue() {
|
|
132
|
+
while (this.taskQueue.length > 0 && this.runningTasks.size < this.config.maxConcurrentTasks) {
|
|
133
|
+
const queuedTask = this.selectNextTask();
|
|
134
|
+
if (!queuedTask) {
|
|
135
|
+
break;
|
|
136
|
+
}
|
|
137
|
+
this.executeTask(queuedTask);
|
|
138
|
+
}
|
|
139
|
+
this.isProcessing = false;
|
|
140
|
+
this.stats.queuedTasks = this.taskQueue.length;
|
|
141
|
+
this.stats.runningTasks = this.runningTasks.size;
|
|
142
|
+
}
|
|
143
|
+
selectNextTask() {
|
|
144
|
+
for (const queuedTask of this.taskQueue) {
|
|
145
|
+
const worker = this.selectWorker(queuedTask.task);
|
|
146
|
+
if (worker) {
|
|
147
|
+
const index = this.taskQueue.indexOf(queuedTask);
|
|
148
|
+
this.taskQueue.splice(index, 1);
|
|
149
|
+
return queuedTask;
|
|
150
|
+
}
|
|
151
|
+
}
|
|
152
|
+
return null;
|
|
153
|
+
}
|
|
154
|
+
selectWorker(task) {
|
|
155
|
+
const preferredTypes = TASK_TYPE_WORKER_MAP[task.type] || ["cpu"];
|
|
156
|
+
const candidates = [];
|
|
157
|
+
for (const [, worker] of this.workers) {
|
|
158
|
+
if (!worker.canHandle(task)) {
|
|
159
|
+
continue;
|
|
160
|
+
}
|
|
161
|
+
const typeIndex = preferredTypes.indexOf(worker.type);
|
|
162
|
+
if (typeIndex === -1 && !preferredTypes.includes(worker.type)) {
|
|
163
|
+
continue;
|
|
164
|
+
}
|
|
165
|
+
const info = worker.getInfo();
|
|
166
|
+
let score = 100;
|
|
167
|
+
if (typeIndex === 0) {
|
|
168
|
+
score += 50;
|
|
169
|
+
}
|
|
170
|
+
score += info.stats.tasksCompleted;
|
|
171
|
+
candidates.push({ worker, score });
|
|
172
|
+
}
|
|
173
|
+
if (candidates.length === 0) {
|
|
174
|
+
return null;
|
|
175
|
+
}
|
|
176
|
+
candidates.sort((a, b) => b.score - a.score);
|
|
177
|
+
return candidates[0].worker;
|
|
178
|
+
}
|
|
179
|
+
async executeTask(queuedTask) {
|
|
180
|
+
const { task } = queuedTask;
|
|
181
|
+
const worker = this.selectWorker(task);
|
|
182
|
+
if (!worker) {
|
|
183
|
+
queuedTask.reject(new Error("No available worker for task"));
|
|
184
|
+
this.stats.failedTasks++;
|
|
185
|
+
this.emit("taskFailed", task);
|
|
186
|
+
return;
|
|
187
|
+
}
|
|
188
|
+
this.runningTasks.set(task.id, queuedTask);
|
|
189
|
+
task.status = "running";
|
|
190
|
+
task.startedAt = new Date();
|
|
191
|
+
const waitTime = Date.now() - queuedTask.addedAt.getTime();
|
|
192
|
+
this.updateAverageWaitTime(waitTime);
|
|
193
|
+
this.emit("taskStarted", task);
|
|
194
|
+
const controller = new AbortController();
|
|
195
|
+
const timeoutId = setTimeout(() => controller.abort(), task.requirements?.maxExecutionTimeMs || this.config.taskTimeout);
|
|
196
|
+
try {
|
|
197
|
+
const startTime = Date.now();
|
|
198
|
+
const result = await worker.execute(task, controller.signal);
|
|
199
|
+
const executionTime = Date.now() - startTime;
|
|
200
|
+
task.status = result.success ? "completed" : "failed";
|
|
201
|
+
task.completedAt = new Date();
|
|
202
|
+
task.result = result;
|
|
203
|
+
this.updateAverageExecutionTime(executionTime);
|
|
204
|
+
if (result.success) {
|
|
205
|
+
this.stats.completedTasks++;
|
|
206
|
+
this.emit("taskCompleted", task);
|
|
207
|
+
}
|
|
208
|
+
else {
|
|
209
|
+
this.stats.failedTasks++;
|
|
210
|
+
this.emit("taskFailed", task);
|
|
211
|
+
}
|
|
212
|
+
queuedTask.resolve(result);
|
|
213
|
+
}
|
|
214
|
+
catch (error) {
|
|
215
|
+
task.status = "failed";
|
|
216
|
+
task.completedAt = new Date();
|
|
217
|
+
task.result = {
|
|
218
|
+
success: false,
|
|
219
|
+
error: error instanceof Error ? error.message : String(error),
|
|
220
|
+
errorCode: "EXECUTION_ERROR",
|
|
221
|
+
};
|
|
222
|
+
this.stats.failedTasks++;
|
|
223
|
+
this.emit("taskFailed", task);
|
|
224
|
+
queuedTask.reject(error instanceof Error ? error : new Error(String(error)));
|
|
225
|
+
}
|
|
226
|
+
finally {
|
|
227
|
+
clearTimeout(timeoutId);
|
|
228
|
+
this.runningTasks.delete(task.id);
|
|
229
|
+
this.stats.runningTasks = this.runningTasks.size;
|
|
230
|
+
this.processQueue();
|
|
231
|
+
}
|
|
232
|
+
}
|
|
233
|
+
updateAverageWaitTime(waitTime) {
|
|
234
|
+
const total = this.stats.completedTasks + this.stats.failedTasks;
|
|
235
|
+
this.stats.averageWaitTime = (this.stats.averageWaitTime * (total - 1) + waitTime) / total;
|
|
236
|
+
}
|
|
237
|
+
updateAverageExecutionTime(executionTime) {
|
|
238
|
+
const total = this.stats.completedTasks + this.stats.failedTasks;
|
|
239
|
+
this.stats.averageExecutionTime = (this.stats.averageExecutionTime * (total - 1) + executionTime) / total;
|
|
240
|
+
}
|
|
241
|
+
getResourceStatus() {
|
|
242
|
+
const baseStatus = this.resourceMonitor.getStatus();
|
|
243
|
+
const workers = Array.from(this.workers.values()).map((w) => w.getInfo());
|
|
244
|
+
const gpuWorkers = workers.filter((w) => w.type === "gpu" && w.capabilities.hasGpu);
|
|
245
|
+
const gpuStatus = gpuWorkers.length > 0
|
|
246
|
+
? {
|
|
247
|
+
available: true,
|
|
248
|
+
deviceCount: gpuWorkers.length,
|
|
249
|
+
devices: gpuWorkers.map((w) => ({
|
|
250
|
+
name: w.capabilities.gpuName || "Unknown",
|
|
251
|
+
memoryMb: w.capabilities.gpuMemoryMb || 0,
|
|
252
|
+
utilization: w.status === "busy" ? 100 : 0,
|
|
253
|
+
})),
|
|
254
|
+
}
|
|
255
|
+
: undefined;
|
|
256
|
+
return {
|
|
257
|
+
cpu: baseStatus.cpu,
|
|
258
|
+
memory: baseStatus.memory,
|
|
259
|
+
gpu: gpuStatus,
|
|
260
|
+
workers,
|
|
261
|
+
queueLength: this.taskQueue.length,
|
|
262
|
+
runningTasks: this.runningTasks.size,
|
|
263
|
+
};
|
|
264
|
+
}
|
|
265
|
+
getStats() {
|
|
266
|
+
return { ...this.stats };
|
|
267
|
+
}
|
|
268
|
+
getQueue() {
|
|
269
|
+
return this.taskQueue.map((qt) => qt.task);
|
|
270
|
+
}
|
|
271
|
+
cancelTask(taskId) {
|
|
272
|
+
const index = this.taskQueue.findIndex((qt) => qt.task.id === taskId);
|
|
273
|
+
if (index !== -1) {
|
|
274
|
+
const [removed] = this.taskQueue.splice(index, 1);
|
|
275
|
+
removed.task.status = "cancelled";
|
|
276
|
+
removed.reject(new Error("Task cancelled"));
|
|
277
|
+
this.stats.queuedTasks = this.taskQueue.length;
|
|
278
|
+
this.emit("taskCancelled", removed.task);
|
|
279
|
+
return true;
|
|
280
|
+
}
|
|
281
|
+
return false;
|
|
282
|
+
}
|
|
283
|
+
getWorkerInfo() {
|
|
284
|
+
return Array.from(this.workers.values()).map((w) => w.getInfo());
|
|
285
|
+
}
|
|
286
|
+
addWorker(worker) {
|
|
287
|
+
this.workers.set(worker.id, worker);
|
|
288
|
+
this.emit("workerAdded", worker.getInfo());
|
|
289
|
+
}
|
|
290
|
+
removeWorker(workerId) {
|
|
291
|
+
const worker = this.workers.get(workerId);
|
|
292
|
+
if (worker) {
|
|
293
|
+
worker.setOffline();
|
|
294
|
+
this.workers.delete(workerId);
|
|
295
|
+
this.emit("workerRemoved", workerId);
|
|
296
|
+
return true;
|
|
297
|
+
}
|
|
298
|
+
return false;
|
|
299
|
+
}
|
|
300
|
+
start() {
|
|
301
|
+
if (this.processInterval) {
|
|
302
|
+
return;
|
|
303
|
+
}
|
|
304
|
+
this.processInterval = setInterval(() => {
|
|
305
|
+
this.processQueue();
|
|
306
|
+
}, 100);
|
|
307
|
+
this.emit("started");
|
|
308
|
+
}
|
|
309
|
+
stop() {
|
|
310
|
+
if (this.processInterval) {
|
|
311
|
+
clearInterval(this.processInterval);
|
|
312
|
+
this.processInterval = undefined;
|
|
313
|
+
}
|
|
314
|
+
for (const queuedTask of this.taskQueue) {
|
|
315
|
+
queuedTask.reject(new Error("Scheduler stopped"));
|
|
316
|
+
}
|
|
317
|
+
this.taskQueue = [];
|
|
318
|
+
this.emit("stopped");
|
|
319
|
+
}
|
|
320
|
+
shutdown() {
|
|
321
|
+
this.stop();
|
|
322
|
+
for (const [_taskId, queuedTask] of this.runningTasks) {
|
|
323
|
+
queuedTask.reject(new Error("Scheduler shutdown"));
|
|
324
|
+
}
|
|
325
|
+
this.runningTasks.clear();
|
|
326
|
+
for (const worker of this.workers.values()) {
|
|
327
|
+
worker.setOffline();
|
|
328
|
+
}
|
|
329
|
+
this.workers.clear();
|
|
330
|
+
this.emit("shutdown");
|
|
331
|
+
}
|
|
332
|
+
}
|
|
333
|
+
//# sourceMappingURL=resource-scheduler.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"resource-scheduler.js","sourceRoot":"","sources":["../../../../src/core/companion/scheduler/resource-scheduler.ts"],"names":[],"mappings":"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","sourcesContent":["import { EventEmitter } from \"events\";\nimport { ResourceMonitor } from \"../executor/resource-monitor.js\";\nimport {\n\ttype BaseWorker,\n\tCPUWorker,\n\tGPUWorker,\n\tIOWorker,\n\tNetworkWorker,\n\ttype ScheduledTask,\n\ttype TaskPayload,\n\ttype TaskPriority,\n\ttype TaskRequirements,\n\ttype TaskResult,\n\ttype TaskType,\n\ttype WorkerInfo,\n} from \"./workers/index.js\";\n\nexport interface ResourceSchedulerConfig {\n\tmaxConcurrentTasks?: number;\n\tenableGPU?: boolean;\n\tmaxCPUWorkers?: number;\n\tmaxGPUWorkers?: number;\n\tmaxIOWorkers?: number;\n\tmaxNetworkWorkers?: number;\n\ttaskTimeout?: number;\n\tpriorityBoost?: boolean;\n}\n\nexport interface SchedulerStats {\n\ttotalTasks: number;\n\tcompletedTasks: number;\n\tfailedTasks: number;\n\tqueuedTasks: number;\n\trunningTasks: number;\n\taverageWaitTime: number;\n\taverageExecutionTime: number;\n}\n\nexport interface ResourceStatus {\n\tcpu: {\n\t\tcoreCount: number;\n\t\tusagePercent: number;\n\t\tavailableCores: number;\n\t};\n\tmemory: {\n\t\ttotalMb: number;\n\t\tusedMb: number;\n\t\tfreeMb: number;\n\t\tusagePercent: number;\n\t};\n\tgpu?: {\n\t\tavailable: boolean;\n\t\tdeviceCount: number;\n\t\tdevices: Array<{\n\t\t\tname: string;\n\t\t\tmemoryMb: number;\n\t\t\tutilization: number;\n\t\t}>;\n\t};\n\tworkers: WorkerInfo[];\n\tqueueLength: number;\n\trunningTasks: number;\n}\n\ninterface QueuedTask {\n\ttask: ScheduledTask;\n\tresolve: (result: TaskResult) => void;\n\treject: (error: Error) => void;\n\taddedAt: Date;\n}\n\nconst PRIORITY_WEIGHTS: Record<TaskPriority, number> = {\n\tcritical: 100,\n\thigh: 75,\n\tmedium: 50,\n\tlow: 25,\n};\n\nconst TASK_TYPE_WORKER_MAP: Record<TaskType, string[]> = {\n\trender: [\"gpu\", \"cpu\"],\n\tio_heavy: [\"io\", \"cpu\"],\n\tcpu_intensive: [\"cpu\"],\n\tnetwork: [\"network\"],\n\tscript: [\"cpu\", \"io\"],\n\tbash: [\"cpu\"],\n\tcode: [\"cpu\", \"gpu\"],\n};\n\nexport class ResourceScheduler extends EventEmitter {\n\tprivate config: Required<ResourceSchedulerConfig>;\n\tprivate resourceMonitor: ResourceMonitor;\n\tprivate workers: Map<string, BaseWorker> = new Map();\n\tprivate taskQueue: QueuedTask[] = [];\n\tprivate runningTasks: Map<string, QueuedTask> = new Map();\n\tprivate taskCounter = 0;\n\tprivate stats: SchedulerStats = {\n\t\ttotalTasks: 0,\n\t\tcompletedTasks: 0,\n\t\tfailedTasks: 0,\n\t\tqueuedTasks: 0,\n\t\trunningTasks: 0,\n\t\taverageWaitTime: 0,\n\t\taverageExecutionTime: 0,\n\t};\n\tprivate isProcessing = false;\n\tprivate processInterval?: NodeJS.Timeout;\n\n\tconstructor(config: ResourceSchedulerConfig = {}) {\n\t\tsuper();\n\t\tthis.config = {\n\t\t\tmaxConcurrentTasks: config.maxConcurrentTasks ?? 8,\n\t\t\tenableGPU: config.enableGPU ?? true,\n\t\t\tmaxCPUWorkers: config.maxCPUWorkers ?? 4,\n\t\t\tmaxGPUWorkers: config.maxGPUWorkers ?? 2,\n\t\t\tmaxIOWorkers: config.maxIOWorkers ?? 2,\n\t\t\tmaxNetworkWorkers: config.maxNetworkWorkers ?? 2,\n\t\t\ttaskTimeout: config.taskTimeout ?? 300000,\n\t\t\tpriorityBoost: config.priorityBoost ?? true,\n\t\t};\n\t\tthis.resourceMonitor = new ResourceMonitor();\n\t\tthis.initializeWorkers();\n\t}\n\n\tprivate initializeWorkers(): void {\n\t\tfor (let i = 0; i < this.config.maxCPUWorkers; i++) {\n\t\t\tconst worker = new CPUWorker(`cpu_${i}`);\n\t\t\tthis.workers.set(worker.id, worker);\n\t\t}\n\n\t\tif (this.config.enableGPU) {\n\t\t\tfor (let i = 0; i < this.config.maxGPUWorkers; i++) {\n\t\t\t\tconst worker = new GPUWorker(`gpu_${i}`);\n\t\t\t\tif (worker.capabilities.hasGpu) {\n\t\t\t\t\tthis.workers.set(worker.id, worker);\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\tfor (let i = 0; i < this.config.maxIOWorkers; i++) {\n\t\t\tconst worker = new IOWorker(`io_${i}`);\n\t\t\tthis.workers.set(worker.id, worker);\n\t\t}\n\n\t\tfor (let i = 0; i < this.config.maxNetworkWorkers; i++) {\n\t\t\tconst worker = new NetworkWorker(`net_${i}`);\n\t\t\tthis.workers.set(worker.id, worker);\n\t\t}\n\t}\n\n\tdispatch(taskType: TaskType, payload: TaskPayload, requirements?: TaskRequirements): Promise<TaskResult> {\n\t\tconst task = this.createTask(taskType, payload, requirements);\n\t\treturn this.submitTask(task);\n\t}\n\n\tsubmit(task: Omit<ScheduledTask, \"id\" | \"createdAt\" | \"status\">): Promise<TaskResult> {\n\t\tconst fullTask = this.createTask(task.type, task.payload, task.requirements);\n\t\tfullTask.priority = task.priority;\n\t\tfullTask.metadata = task.metadata;\n\t\treturn this.submitTask(fullTask);\n\t}\n\n\tprivate createTask(type: TaskType, payload: TaskPayload, requirements?: TaskRequirements): ScheduledTask {\n\t\tthis.taskCounter++;\n\t\treturn {\n\t\t\tid: `task_${Date.now()}_${this.taskCounter}`,\n\t\t\ttype,\n\t\t\tpriority: \"medium\",\n\t\t\tstatus: \"pending\",\n\t\t\tpayload,\n\t\t\trequirements,\n\t\t\tcreatedAt: new Date(),\n\t\t};\n\t}\n\n\tprivate submitTask(task: ScheduledTask): Promise<TaskResult> {\n\t\treturn new Promise((resolve, reject) => {\n\t\t\tconst queuedTask: QueuedTask = {\n\t\t\t\ttask,\n\t\t\t\tresolve,\n\t\t\t\treject,\n\t\t\t\taddedAt: new Date(),\n\t\t\t};\n\n\t\t\tthis.taskQueue.push(queuedTask);\n\t\t\tthis.stats.totalTasks++;\n\t\t\tthis.stats.queuedTasks = this.taskQueue.length;\n\n\t\t\tthis.sortQueue();\n\t\t\tthis.emit(\"taskQueued\", task);\n\t\t\tthis.processQueue();\n\t\t});\n\t}\n\n\tprivate sortQueue(): void {\n\t\tif (!this.config.priorityBoost) {\n\t\t\treturn;\n\t\t}\n\n\t\tthis.taskQueue.sort((a, b) => {\n\t\t\tconst priorityDiff = PRIORITY_WEIGHTS[b.task.priority] - PRIORITY_WEIGHTS[a.task.priority];\n\t\t\tif (priorityDiff !== 0) {\n\t\t\t\treturn priorityDiff;\n\t\t\t}\n\t\t\treturn a.addedAt.getTime() - b.addedAt.getTime();\n\t\t});\n\t}\n\n\tprivate processQueue(): void {\n\t\tif (this.isProcessing) {\n\t\t\treturn;\n\t\t}\n\n\t\tthis.isProcessing = true;\n\t\tthis.doProcessQueue();\n\t}\n\n\tprivate async doProcessQueue(): Promise<void> {\n\t\twhile (this.taskQueue.length > 0 && this.runningTasks.size < this.config.maxConcurrentTasks) {\n\t\t\tconst queuedTask = this.selectNextTask();\n\t\t\tif (!queuedTask) {\n\t\t\t\tbreak;\n\t\t\t}\n\n\t\t\tthis.executeTask(queuedTask);\n\t\t}\n\n\t\tthis.isProcessing = false;\n\t\tthis.stats.queuedTasks = this.taskQueue.length;\n\t\tthis.stats.runningTasks = this.runningTasks.size;\n\t}\n\n\tprivate selectNextTask(): QueuedTask | null {\n\t\tfor (const queuedTask of this.taskQueue) {\n\t\t\tconst worker = this.selectWorker(queuedTask.task);\n\t\t\tif (worker) {\n\t\t\t\tconst index = this.taskQueue.indexOf(queuedTask);\n\t\t\t\tthis.taskQueue.splice(index, 1);\n\t\t\t\treturn queuedTask;\n\t\t\t}\n\t\t}\n\t\treturn null;\n\t}\n\n\tprivate selectWorker(task: ScheduledTask): BaseWorker | null {\n\t\tconst preferredTypes = TASK_TYPE_WORKER_MAP[task.type] || [\"cpu\"];\n\t\tconst candidates: Array<{ worker: BaseWorker; score: number }> = [];\n\n\t\tfor (const [, worker] of this.workers) {\n\t\t\tif (!worker.canHandle(task)) {\n\t\t\t\tcontinue;\n\t\t\t}\n\n\t\t\tconst typeIndex = preferredTypes.indexOf(worker.type);\n\t\t\tif (typeIndex === -1 && !preferredTypes.includes(worker.type)) {\n\t\t\t\tcontinue;\n\t\t\t}\n\n\t\t\tconst info = worker.getInfo();\n\t\t\tlet score = 100;\n\n\t\t\tif (typeIndex === 0) {\n\t\t\t\tscore += 50;\n\t\t\t}\n\n\t\t\tscore += info.stats.tasksCompleted;\n\n\t\t\tcandidates.push({ worker, score });\n\t\t}\n\n\t\tif (candidates.length === 0) {\n\t\t\treturn null;\n\t\t}\n\n\t\tcandidates.sort((a, b) => b.score - a.score);\n\t\treturn candidates[0].worker;\n\t}\n\n\tprivate async executeTask(queuedTask: QueuedTask): Promise<void> {\n\t\tconst { task } = queuedTask;\n\t\tconst worker = this.selectWorker(task);\n\n\t\tif (!worker) {\n\t\t\tqueuedTask.reject(new Error(\"No available worker for task\"));\n\t\t\tthis.stats.failedTasks++;\n\t\t\tthis.emit(\"taskFailed\", task);\n\t\t\treturn;\n\t\t}\n\n\t\tthis.runningTasks.set(task.id, queuedTask);\n\t\ttask.status = \"running\";\n\t\ttask.startedAt = new Date();\n\n\t\tconst waitTime = Date.now() - queuedTask.addedAt.getTime();\n\t\tthis.updateAverageWaitTime(waitTime);\n\n\t\tthis.emit(\"taskStarted\", task);\n\n\t\tconst controller = new AbortController();\n\t\tconst timeoutId = setTimeout(\n\t\t\t() => controller.abort(),\n\t\t\ttask.requirements?.maxExecutionTimeMs || this.config.taskTimeout,\n\t\t);\n\n\t\ttry {\n\t\t\tconst startTime = Date.now();\n\t\t\tconst result = await worker.execute(task, controller.signal);\n\t\t\tconst executionTime = Date.now() - startTime;\n\n\t\t\ttask.status = result.success ? \"completed\" : \"failed\";\n\t\t\ttask.completedAt = new Date();\n\t\t\ttask.result = result;\n\n\t\t\tthis.updateAverageExecutionTime(executionTime);\n\n\t\t\tif (result.success) {\n\t\t\t\tthis.stats.completedTasks++;\n\t\t\t\tthis.emit(\"taskCompleted\", task);\n\t\t\t} else {\n\t\t\t\tthis.stats.failedTasks++;\n\t\t\t\tthis.emit(\"taskFailed\", task);\n\t\t\t}\n\n\t\t\tqueuedTask.resolve(result);\n\t\t} catch (error) {\n\t\t\ttask.status = \"failed\";\n\t\t\ttask.completedAt = new Date();\n\t\t\ttask.result = {\n\t\t\t\tsuccess: false,\n\t\t\t\terror: error instanceof Error ? error.message : String(error),\n\t\t\t\terrorCode: \"EXECUTION_ERROR\",\n\t\t\t};\n\n\t\t\tthis.stats.failedTasks++;\n\t\t\tthis.emit(\"taskFailed\", task);\n\t\t\tqueuedTask.reject(error instanceof Error ? error : new Error(String(error)));\n\t\t} finally {\n\t\t\tclearTimeout(timeoutId);\n\t\t\tthis.runningTasks.delete(task.id);\n\t\t\tthis.stats.runningTasks = this.runningTasks.size;\n\t\t\tthis.processQueue();\n\t\t}\n\t}\n\n\tprivate updateAverageWaitTime(waitTime: number): void {\n\t\tconst total = this.stats.completedTasks + this.stats.failedTasks;\n\t\tthis.stats.averageWaitTime = (this.stats.averageWaitTime * (total - 1) + waitTime) / total;\n\t}\n\n\tprivate updateAverageExecutionTime(executionTime: number): void {\n\t\tconst total = this.stats.completedTasks + this.stats.failedTasks;\n\t\tthis.stats.averageExecutionTime = (this.stats.averageExecutionTime * (total - 1) + executionTime) / total;\n\t}\n\n\tgetResourceStatus(): ResourceStatus {\n\t\tconst baseStatus = this.resourceMonitor.getStatus();\n\t\tconst workers = Array.from(this.workers.values()).map((w) => w.getInfo());\n\n\t\tconst gpuWorkers = workers.filter((w) => w.type === \"gpu\" && w.capabilities.hasGpu);\n\t\tconst gpuStatus =\n\t\t\tgpuWorkers.length > 0\n\t\t\t\t? {\n\t\t\t\t\t\tavailable: true,\n\t\t\t\t\t\tdeviceCount: gpuWorkers.length,\n\t\t\t\t\t\tdevices: gpuWorkers.map((w) => ({\n\t\t\t\t\t\t\tname: w.capabilities.gpuName || \"Unknown\",\n\t\t\t\t\t\t\tmemoryMb: w.capabilities.gpuMemoryMb || 0,\n\t\t\t\t\t\t\tutilization: w.status === \"busy\" ? 100 : 0,\n\t\t\t\t\t\t})),\n\t\t\t\t\t}\n\t\t\t\t: undefined;\n\n\t\treturn {\n\t\t\tcpu: baseStatus.cpu,\n\t\t\tmemory: baseStatus.memory,\n\t\t\tgpu: gpuStatus,\n\t\t\tworkers,\n\t\t\tqueueLength: this.taskQueue.length,\n\t\t\trunningTasks: this.runningTasks.size,\n\t\t};\n\t}\n\n\tgetStats(): SchedulerStats {\n\t\treturn { ...this.stats };\n\t}\n\n\tgetQueue(): ScheduledTask[] {\n\t\treturn this.taskQueue.map((qt) => qt.task);\n\t}\n\n\tcancelTask(taskId: string): boolean {\n\t\tconst index = this.taskQueue.findIndex((qt) => qt.task.id === taskId);\n\t\tif (index !== -1) {\n\t\t\tconst [removed] = this.taskQueue.splice(index, 1);\n\t\t\tremoved.task.status = \"cancelled\";\n\t\t\tremoved.reject(new Error(\"Task cancelled\"));\n\t\t\tthis.stats.queuedTasks = this.taskQueue.length;\n\t\t\tthis.emit(\"taskCancelled\", removed.task);\n\t\t\treturn true;\n\t\t}\n\t\treturn false;\n\t}\n\n\tgetWorkerInfo(): WorkerInfo[] {\n\t\treturn Array.from(this.workers.values()).map((w) => w.getInfo());\n\t}\n\n\taddWorker(worker: BaseWorker): void {\n\t\tthis.workers.set(worker.id, worker);\n\t\tthis.emit(\"workerAdded\", worker.getInfo());\n\t}\n\n\tremoveWorker(workerId: string): boolean {\n\t\tconst worker = this.workers.get(workerId);\n\t\tif (worker) {\n\t\t\tworker.setOffline();\n\t\t\tthis.workers.delete(workerId);\n\t\t\tthis.emit(\"workerRemoved\", workerId);\n\t\t\treturn true;\n\t\t}\n\t\treturn false;\n\t}\n\n\tstart(): void {\n\t\tif (this.processInterval) {\n\t\t\treturn;\n\t\t}\n\n\t\tthis.processInterval = setInterval(() => {\n\t\t\tthis.processQueue();\n\t\t}, 100);\n\n\t\tthis.emit(\"started\");\n\t}\n\n\tstop(): void {\n\t\tif (this.processInterval) {\n\t\t\tclearInterval(this.processInterval);\n\t\t\tthis.processInterval = undefined;\n\t\t}\n\n\t\tfor (const queuedTask of this.taskQueue) {\n\t\t\tqueuedTask.reject(new Error(\"Scheduler stopped\"));\n\t\t}\n\t\tthis.taskQueue = [];\n\n\t\tthis.emit(\"stopped\");\n\t}\n\n\tshutdown(): void {\n\t\tthis.stop();\n\n\t\tfor (const [_taskId, queuedTask] of this.runningTasks) {\n\t\t\tqueuedTask.reject(new Error(\"Scheduler shutdown\"));\n\t\t}\n\t\tthis.runningTasks.clear();\n\n\t\tfor (const worker of this.workers.values()) {\n\t\t\tworker.setOffline();\n\t\t}\n\t\tthis.workers.clear();\n\n\t\tthis.emit(\"shutdown\");\n\t}\n}\n"]}
|
|
@@ -0,0 +1,87 @@
|
|
|
1
|
+
export interface TaskResult {
|
|
2
|
+
success: boolean;
|
|
3
|
+
exitCode?: number;
|
|
4
|
+
stdout?: string;
|
|
5
|
+
stderr?: string;
|
|
6
|
+
output?: string;
|
|
7
|
+
error?: string;
|
|
8
|
+
errorCode?: string;
|
|
9
|
+
metrics?: {
|
|
10
|
+
executionTimeMs: number;
|
|
11
|
+
memoryPeakMb: number;
|
|
12
|
+
cpuTimeMs: number;
|
|
13
|
+
};
|
|
14
|
+
}
|
|
15
|
+
export type TaskType = "render" | "io_heavy" | "cpu_intensive" | "network" | "script" | "bash" | "code";
|
|
16
|
+
export type TaskPriority = "low" | "medium" | "high" | "critical";
|
|
17
|
+
export type TaskStatus = "pending" | "queued" | "running" | "completed" | "failed" | "cancelled";
|
|
18
|
+
export interface ScheduledTask {
|
|
19
|
+
id: string;
|
|
20
|
+
type: TaskType;
|
|
21
|
+
priority: TaskPriority;
|
|
22
|
+
status: TaskStatus;
|
|
23
|
+
payload: TaskPayload;
|
|
24
|
+
requirements?: TaskRequirements;
|
|
25
|
+
createdAt: Date;
|
|
26
|
+
startedAt?: Date;
|
|
27
|
+
completedAt?: Date;
|
|
28
|
+
result?: TaskResult;
|
|
29
|
+
metadata?: Record<string, unknown>;
|
|
30
|
+
}
|
|
31
|
+
export interface TaskPayload {
|
|
32
|
+
command?: string;
|
|
33
|
+
args?: string[];
|
|
34
|
+
code?: string;
|
|
35
|
+
language?: string;
|
|
36
|
+
workingDir?: string;
|
|
37
|
+
env?: Record<string, string>;
|
|
38
|
+
data?: unknown;
|
|
39
|
+
}
|
|
40
|
+
export interface TaskRequirements {
|
|
41
|
+
minCpuCores?: number;
|
|
42
|
+
minMemoryMb?: number;
|
|
43
|
+
minGpuMemoryMb?: number;
|
|
44
|
+
requiresGpu?: boolean;
|
|
45
|
+
maxExecutionTimeMs?: number;
|
|
46
|
+
networkAccess?: boolean;
|
|
47
|
+
fileWriteAccess?: boolean;
|
|
48
|
+
}
|
|
49
|
+
export interface WorkerCapabilities {
|
|
50
|
+
cpuCores: number;
|
|
51
|
+
memoryMb: number;
|
|
52
|
+
hasGpu: boolean;
|
|
53
|
+
gpuMemoryMb?: number;
|
|
54
|
+
gpuName?: string;
|
|
55
|
+
supportsTypes: TaskType[];
|
|
56
|
+
}
|
|
57
|
+
export interface WorkerStats {
|
|
58
|
+
tasksCompleted: number;
|
|
59
|
+
tasksFailed: number;
|
|
60
|
+
totalExecutionTimeMs: number;
|
|
61
|
+
averageExecutionTimeMs: number;
|
|
62
|
+
lastTaskAt?: Date;
|
|
63
|
+
}
|
|
64
|
+
export interface WorkerInfo {
|
|
65
|
+
id: string;
|
|
66
|
+
type: string;
|
|
67
|
+
status: "idle" | "busy" | "offline";
|
|
68
|
+
capabilities: WorkerCapabilities;
|
|
69
|
+
stats: WorkerStats;
|
|
70
|
+
currentTask?: string;
|
|
71
|
+
}
|
|
72
|
+
export declare abstract class BaseWorker {
|
|
73
|
+
abstract readonly id: string;
|
|
74
|
+
abstract readonly type: string;
|
|
75
|
+
abstract readonly capabilities: WorkerCapabilities;
|
|
76
|
+
protected status: "idle" | "busy" | "offline";
|
|
77
|
+
protected currentTaskId?: string;
|
|
78
|
+
protected stats: WorkerStats;
|
|
79
|
+
getInfo(): WorkerInfo;
|
|
80
|
+
canHandle(task: ScheduledTask): boolean;
|
|
81
|
+
abstract execute(task: ScheduledTask, signal?: AbortSignal): Promise<TaskResult>;
|
|
82
|
+
protected markBusy(taskId: string): void;
|
|
83
|
+
protected markIdle(): void;
|
|
84
|
+
protected updateStats(executionTimeMs: number, success: boolean): void;
|
|
85
|
+
setOffline(): void;
|
|
86
|
+
}
|
|
87
|
+
//# sourceMappingURL=base-worker.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"base-worker.d.ts","sourceRoot":"","sources":["../../../../../src/core/companion/scheduler/workers/base-worker.ts"],"names":[],"mappings":"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","sourcesContent":["export interface TaskResult {\n\tsuccess: boolean;\n\texitCode?: number;\n\tstdout?: string;\n\tstderr?: string;\n\toutput?: string;\n\terror?: string;\n\terrorCode?: string;\n\tmetrics?: {\n\t\texecutionTimeMs: number;\n\t\tmemoryPeakMb: number;\n\t\tcpuTimeMs: number;\n\t};\n}\n\nexport type TaskType = \"render\" | \"io_heavy\" | \"cpu_intensive\" | \"network\" | \"script\" | \"bash\" | \"code\";\n\nexport type TaskPriority = \"low\" | \"medium\" | \"high\" | \"critical\";\n\nexport type TaskStatus = \"pending\" | \"queued\" | \"running\" | \"completed\" | \"failed\" | \"cancelled\";\n\nexport interface ScheduledTask {\n\tid: string;\n\ttype: TaskType;\n\tpriority: TaskPriority;\n\tstatus: TaskStatus;\n\tpayload: TaskPayload;\n\trequirements?: TaskRequirements;\n\tcreatedAt: Date;\n\tstartedAt?: Date;\n\tcompletedAt?: Date;\n\tresult?: TaskResult;\n\tmetadata?: Record<string, unknown>;\n}\n\nexport interface TaskPayload {\n\tcommand?: string;\n\targs?: string[];\n\tcode?: string;\n\tlanguage?: string;\n\tworkingDir?: string;\n\tenv?: Record<string, string>;\n\tdata?: unknown;\n}\n\nexport interface TaskRequirements {\n\tminCpuCores?: number;\n\tminMemoryMb?: number;\n\tminGpuMemoryMb?: number;\n\trequiresGpu?: boolean;\n\tmaxExecutionTimeMs?: number;\n\tnetworkAccess?: boolean;\n\tfileWriteAccess?: boolean;\n}\n\nexport interface WorkerCapabilities {\n\tcpuCores: number;\n\tmemoryMb: number;\n\thasGpu: boolean;\n\tgpuMemoryMb?: number;\n\tgpuName?: string;\n\tsupportsTypes: TaskType[];\n}\n\nexport interface WorkerStats {\n\ttasksCompleted: number;\n\ttasksFailed: number;\n\ttotalExecutionTimeMs: number;\n\taverageExecutionTimeMs: number;\n\tlastTaskAt?: Date;\n}\n\nexport interface WorkerInfo {\n\tid: string;\n\ttype: string;\n\tstatus: \"idle\" | \"busy\" | \"offline\";\n\tcapabilities: WorkerCapabilities;\n\tstats: WorkerStats;\n\tcurrentTask?: string;\n}\n\nexport abstract class BaseWorker {\n\tabstract readonly id: string;\n\tabstract readonly type: string;\n\tabstract readonly capabilities: WorkerCapabilities;\n\n\tprotected status: \"idle\" | \"busy\" | \"offline\" = \"idle\";\n\tprotected currentTaskId?: string;\n\tprotected stats: WorkerStats = {\n\t\ttasksCompleted: 0,\n\t\ttasksFailed: 0,\n\t\ttotalExecutionTimeMs: 0,\n\t\taverageExecutionTimeMs: 0,\n\t};\n\n\tgetInfo(): WorkerInfo {\n\t\treturn {\n\t\t\tid: this.id,\n\t\t\ttype: this.type,\n\t\t\tstatus: this.status,\n\t\t\tcapabilities: this.capabilities,\n\t\t\tstats: { ...this.stats },\n\t\t\tcurrentTask: this.currentTaskId,\n\t\t};\n\t}\n\n\tcanHandle(task: ScheduledTask): boolean {\n\t\tif (this.status !== \"idle\") {\n\t\t\treturn false;\n\t\t}\n\n\t\tif (!this.capabilities.supportsTypes.includes(task.type)) {\n\t\t\treturn false;\n\t\t}\n\n\t\tconst req = task.requirements;\n\t\tif (!req) {\n\t\t\treturn true;\n\t\t}\n\n\t\tif (req.minCpuCores && req.minCpuCores > this.capabilities.cpuCores) {\n\t\t\treturn false;\n\t\t}\n\n\t\tif (req.minMemoryMb && req.minMemoryMb > this.capabilities.memoryMb) {\n\t\t\treturn false;\n\t\t}\n\n\t\tif (req.requiresGpu && !this.capabilities.hasGpu) {\n\t\t\treturn false;\n\t\t}\n\n\t\tif (req.minGpuMemoryMb && this.capabilities.gpuMemoryMb && req.minGpuMemoryMb > this.capabilities.gpuMemoryMb) {\n\t\t\treturn false;\n\t\t}\n\n\t\treturn true;\n\t}\n\n\tabstract execute(task: ScheduledTask, signal?: AbortSignal): Promise<TaskResult>;\n\n\tprotected markBusy(taskId: string): void {\n\t\tthis.status = \"busy\";\n\t\tthis.currentTaskId = taskId;\n\t}\n\n\tprotected markIdle(): void {\n\t\tthis.status = \"idle\";\n\t\tthis.currentTaskId = undefined;\n\t}\n\n\tprotected updateStats(executionTimeMs: number, success: boolean): void {\n\t\tif (success) {\n\t\t\tthis.stats.tasksCompleted++;\n\t\t} else {\n\t\t\tthis.stats.tasksFailed++;\n\t\t}\n\n\t\tthis.stats.totalExecutionTimeMs += executionTimeMs;\n\t\tthis.stats.averageExecutionTimeMs =\n\t\t\tthis.stats.totalExecutionTimeMs / (this.stats.tasksCompleted + this.stats.tasksFailed);\n\t\tthis.stats.lastTaskAt = new Date();\n\t}\n\n\tsetOffline(): void {\n\t\tthis.status = \"offline\";\n\t\tthis.currentTaskId = undefined;\n\t}\n}\n"]}
|
|
@@ -0,0 +1,70 @@
|
|
|
1
|
+
export class BaseWorker {
|
|
2
|
+
status = "idle";
|
|
3
|
+
currentTaskId;
|
|
4
|
+
stats = {
|
|
5
|
+
tasksCompleted: 0,
|
|
6
|
+
tasksFailed: 0,
|
|
7
|
+
totalExecutionTimeMs: 0,
|
|
8
|
+
averageExecutionTimeMs: 0,
|
|
9
|
+
};
|
|
10
|
+
getInfo() {
|
|
11
|
+
return {
|
|
12
|
+
id: this.id,
|
|
13
|
+
type: this.type,
|
|
14
|
+
status: this.status,
|
|
15
|
+
capabilities: this.capabilities,
|
|
16
|
+
stats: { ...this.stats },
|
|
17
|
+
currentTask: this.currentTaskId,
|
|
18
|
+
};
|
|
19
|
+
}
|
|
20
|
+
canHandle(task) {
|
|
21
|
+
if (this.status !== "idle") {
|
|
22
|
+
return false;
|
|
23
|
+
}
|
|
24
|
+
if (!this.capabilities.supportsTypes.includes(task.type)) {
|
|
25
|
+
return false;
|
|
26
|
+
}
|
|
27
|
+
const req = task.requirements;
|
|
28
|
+
if (!req) {
|
|
29
|
+
return true;
|
|
30
|
+
}
|
|
31
|
+
if (req.minCpuCores && req.minCpuCores > this.capabilities.cpuCores) {
|
|
32
|
+
return false;
|
|
33
|
+
}
|
|
34
|
+
if (req.minMemoryMb && req.minMemoryMb > this.capabilities.memoryMb) {
|
|
35
|
+
return false;
|
|
36
|
+
}
|
|
37
|
+
if (req.requiresGpu && !this.capabilities.hasGpu) {
|
|
38
|
+
return false;
|
|
39
|
+
}
|
|
40
|
+
if (req.minGpuMemoryMb && this.capabilities.gpuMemoryMb && req.minGpuMemoryMb > this.capabilities.gpuMemoryMb) {
|
|
41
|
+
return false;
|
|
42
|
+
}
|
|
43
|
+
return true;
|
|
44
|
+
}
|
|
45
|
+
markBusy(taskId) {
|
|
46
|
+
this.status = "busy";
|
|
47
|
+
this.currentTaskId = taskId;
|
|
48
|
+
}
|
|
49
|
+
markIdle() {
|
|
50
|
+
this.status = "idle";
|
|
51
|
+
this.currentTaskId = undefined;
|
|
52
|
+
}
|
|
53
|
+
updateStats(executionTimeMs, success) {
|
|
54
|
+
if (success) {
|
|
55
|
+
this.stats.tasksCompleted++;
|
|
56
|
+
}
|
|
57
|
+
else {
|
|
58
|
+
this.stats.tasksFailed++;
|
|
59
|
+
}
|
|
60
|
+
this.stats.totalExecutionTimeMs += executionTimeMs;
|
|
61
|
+
this.stats.averageExecutionTimeMs =
|
|
62
|
+
this.stats.totalExecutionTimeMs / (this.stats.tasksCompleted + this.stats.tasksFailed);
|
|
63
|
+
this.stats.lastTaskAt = new Date();
|
|
64
|
+
}
|
|
65
|
+
setOffline() {
|
|
66
|
+
this.status = "offline";
|
|
67
|
+
this.currentTaskId = undefined;
|
|
68
|
+
}
|
|
69
|
+
}
|
|
70
|
+
//# sourceMappingURL=base-worker.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"base-worker.js","sourceRoot":"","sources":["../../../../../src/core/companion/scheduler/workers/base-worker.ts"],"names":[],"mappings":"AAiFA,MAAM,OAAgB,UAAU;IAKrB,MAAM,GAAgC,MAAM,CAAC;IAC7C,aAAa,CAAU;IACvB,KAAK,GAAgB;QAC9B,cAAc,EAAE,CAAC;QACjB,WAAW,EAAE,CAAC;QACd,oBAAoB,EAAE,CAAC;QACvB,sBAAsB,EAAE,CAAC;KACzB,CAAC;IAEF,OAAO,GAAe;QACrB,OAAO;YACN,EAAE,EAAE,IAAI,CAAC,EAAE;YACX,IAAI,EAAE,IAAI,CAAC,IAAI;YACf,MAAM,EAAE,IAAI,CAAC,MAAM;YACnB,YAAY,EAAE,IAAI,CAAC,YAAY;YAC/B,KAAK,EAAE,EAAE,GAAG,IAAI,CAAC,KAAK,EAAE;YACxB,WAAW,EAAE,IAAI,CAAC,aAAa;SAC/B,CAAC;IAAA,CACF;IAED,SAAS,CAAC,IAAmB,EAAW;QACvC,IAAI,IAAI,CAAC,MAAM,KAAK,MAAM,EAAE,CAAC;YAC5B,OAAO,KAAK,CAAC;QACd,CAAC;QAED,IAAI,CAAC,IAAI,CAAC,YAAY,CAAC,aAAa,CAAC,QAAQ,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE,CAAC;YAC1D,OAAO,KAAK,CAAC;QACd,CAAC;QAED,MAAM,GAAG,GAAG,IAAI,CAAC,YAAY,CAAC;QAC9B,IAAI,CAAC,GAAG,EAAE,CAAC;YACV,OAAO,IAAI,CAAC;QACb,CAAC;QAED,IAAI,GAAG,CAAC,WAAW,IAAI,GAAG,CAAC,WAAW,GAAG,IAAI,CAAC,YAAY,CAAC,QAAQ,EAAE,CAAC;YACrE,OAAO,KAAK,CAAC;QACd,CAAC;QAED,IAAI,GAAG,CAAC,WAAW,IAAI,GAAG,CAAC,WAAW,GAAG,IAAI,CAAC,YAAY,CAAC,QAAQ,EAAE,CAAC;YACrE,OAAO,KAAK,CAAC;QACd,CAAC;QAED,IAAI,GAAG,CAAC,WAAW,IAAI,CAAC,IAAI,CAAC,YAAY,CAAC,MAAM,EAAE,CAAC;YAClD,OAAO,KAAK,CAAC;QACd,CAAC;QAED,IAAI,GAAG,CAAC,cAAc,IAAI,IAAI,CAAC,YAAY,CAAC,WAAW,IAAI,GAAG,CAAC,cAAc,GAAG,IAAI,CAAC,YAAY,CAAC,WAAW,EAAE,CAAC;YAC/G,OAAO,KAAK,CAAC;QACd,CAAC;QAED,OAAO,IAAI,CAAC;IAAA,CACZ;IAIS,QAAQ,CAAC,MAAc,EAAQ;QACxC,IAAI,CAAC,MAAM,GAAG,MAAM,CAAC;QACrB,IAAI,CAAC,aAAa,GAAG,MAAM,CAAC;IAAA,CAC5B;IAES,QAAQ,GAAS;QAC1B,IAAI,CAAC,MAAM,GAAG,MAAM,CAAC;QACrB,IAAI,CAAC,aAAa,GAAG,SAAS,CAAC;IAAA,CAC/B;IAES,WAAW,CAAC,eAAuB,EAAE,OAAgB,EAAQ;QACtE,IAAI,OAAO,EAAE,CAAC;YACb,IAAI,CAAC,KAAK,CAAC,cAAc,EAAE,CAAC;QAC7B,CAAC;aAAM,CAAC;YACP,IAAI,CAAC,KAAK,CAAC,WAAW,EAAE,CAAC;QAC1B,CAAC;QAED,IAAI,CAAC,KAAK,CAAC,oBAAoB,IAAI,eAAe,CAAC;QACnD,IAAI,CAAC,KAAK,CAAC,sBAAsB;YAChC,IAAI,CAAC,KAAK,CAAC,oBAAoB,GAAG,CAAC,IAAI,CAAC,KAAK,CAAC,cAAc,GAAG,IAAI,CAAC,KAAK,CAAC,WAAW,CAAC,CAAC;QACxF,IAAI,CAAC,KAAK,CAAC,UAAU,GAAG,IAAI,IAAI,EAAE,CAAC;IAAA,CACnC;IAED,UAAU,GAAS;QAClB,IAAI,CAAC,MAAM,GAAG,SAAS,CAAC;QACxB,IAAI,CAAC,aAAa,GAAG,SAAS,CAAC;IAAA,CAC/B;CACD","sourcesContent":["export interface TaskResult {\n\tsuccess: boolean;\n\texitCode?: number;\n\tstdout?: string;\n\tstderr?: string;\n\toutput?: string;\n\terror?: string;\n\terrorCode?: string;\n\tmetrics?: {\n\t\texecutionTimeMs: number;\n\t\tmemoryPeakMb: number;\n\t\tcpuTimeMs: number;\n\t};\n}\n\nexport type TaskType = \"render\" | \"io_heavy\" | \"cpu_intensive\" | \"network\" | \"script\" | \"bash\" | \"code\";\n\nexport type TaskPriority = \"low\" | \"medium\" | \"high\" | \"critical\";\n\nexport type TaskStatus = \"pending\" | \"queued\" | \"running\" | \"completed\" | \"failed\" | \"cancelled\";\n\nexport interface ScheduledTask {\n\tid: string;\n\ttype: TaskType;\n\tpriority: TaskPriority;\n\tstatus: TaskStatus;\n\tpayload: TaskPayload;\n\trequirements?: TaskRequirements;\n\tcreatedAt: Date;\n\tstartedAt?: Date;\n\tcompletedAt?: Date;\n\tresult?: TaskResult;\n\tmetadata?: Record<string, unknown>;\n}\n\nexport interface TaskPayload {\n\tcommand?: string;\n\targs?: string[];\n\tcode?: string;\n\tlanguage?: string;\n\tworkingDir?: string;\n\tenv?: Record<string, string>;\n\tdata?: unknown;\n}\n\nexport interface TaskRequirements {\n\tminCpuCores?: number;\n\tminMemoryMb?: number;\n\tminGpuMemoryMb?: number;\n\trequiresGpu?: boolean;\n\tmaxExecutionTimeMs?: number;\n\tnetworkAccess?: boolean;\n\tfileWriteAccess?: boolean;\n}\n\nexport interface WorkerCapabilities {\n\tcpuCores: number;\n\tmemoryMb: number;\n\thasGpu: boolean;\n\tgpuMemoryMb?: number;\n\tgpuName?: string;\n\tsupportsTypes: TaskType[];\n}\n\nexport interface WorkerStats {\n\ttasksCompleted: number;\n\ttasksFailed: number;\n\ttotalExecutionTimeMs: number;\n\taverageExecutionTimeMs: number;\n\tlastTaskAt?: Date;\n}\n\nexport interface WorkerInfo {\n\tid: string;\n\ttype: string;\n\tstatus: \"idle\" | \"busy\" | \"offline\";\n\tcapabilities: WorkerCapabilities;\n\tstats: WorkerStats;\n\tcurrentTask?: string;\n}\n\nexport abstract class BaseWorker {\n\tabstract readonly id: string;\n\tabstract readonly type: string;\n\tabstract readonly capabilities: WorkerCapabilities;\n\n\tprotected status: \"idle\" | \"busy\" | \"offline\" = \"idle\";\n\tprotected currentTaskId?: string;\n\tprotected stats: WorkerStats = {\n\t\ttasksCompleted: 0,\n\t\ttasksFailed: 0,\n\t\ttotalExecutionTimeMs: 0,\n\t\taverageExecutionTimeMs: 0,\n\t};\n\n\tgetInfo(): WorkerInfo {\n\t\treturn {\n\t\t\tid: this.id,\n\t\t\ttype: this.type,\n\t\t\tstatus: this.status,\n\t\t\tcapabilities: this.capabilities,\n\t\t\tstats: { ...this.stats },\n\t\t\tcurrentTask: this.currentTaskId,\n\t\t};\n\t}\n\n\tcanHandle(task: ScheduledTask): boolean {\n\t\tif (this.status !== \"idle\") {\n\t\t\treturn false;\n\t\t}\n\n\t\tif (!this.capabilities.supportsTypes.includes(task.type)) {\n\t\t\treturn false;\n\t\t}\n\n\t\tconst req = task.requirements;\n\t\tif (!req) {\n\t\t\treturn true;\n\t\t}\n\n\t\tif (req.minCpuCores && req.minCpuCores > this.capabilities.cpuCores) {\n\t\t\treturn false;\n\t\t}\n\n\t\tif (req.minMemoryMb && req.minMemoryMb > this.capabilities.memoryMb) {\n\t\t\treturn false;\n\t\t}\n\n\t\tif (req.requiresGpu && !this.capabilities.hasGpu) {\n\t\t\treturn false;\n\t\t}\n\n\t\tif (req.minGpuMemoryMb && this.capabilities.gpuMemoryMb && req.minGpuMemoryMb > this.capabilities.gpuMemoryMb) {\n\t\t\treturn false;\n\t\t}\n\n\t\treturn true;\n\t}\n\n\tabstract execute(task: ScheduledTask, signal?: AbortSignal): Promise<TaskResult>;\n\n\tprotected markBusy(taskId: string): void {\n\t\tthis.status = \"busy\";\n\t\tthis.currentTaskId = taskId;\n\t}\n\n\tprotected markIdle(): void {\n\t\tthis.status = \"idle\";\n\t\tthis.currentTaskId = undefined;\n\t}\n\n\tprotected updateStats(executionTimeMs: number, success: boolean): void {\n\t\tif (success) {\n\t\t\tthis.stats.tasksCompleted++;\n\t\t} else {\n\t\t\tthis.stats.tasksFailed++;\n\t\t}\n\n\t\tthis.stats.totalExecutionTimeMs += executionTimeMs;\n\t\tthis.stats.averageExecutionTimeMs =\n\t\t\tthis.stats.totalExecutionTimeMs / (this.stats.tasksCompleted + this.stats.tasksFailed);\n\t\tthis.stats.lastTaskAt = new Date();\n\t}\n\n\tsetOffline(): void {\n\t\tthis.status = \"offline\";\n\t\tthis.currentTaskId = undefined;\n\t}\n}\n"]}
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
import { BaseWorker, type ScheduledTask, type TaskResult, type WorkerCapabilities } from "./base-worker.js";
|
|
2
|
+
export declare class CPUWorker extends BaseWorker {
|
|
3
|
+
readonly id: string;
|
|
4
|
+
readonly type = "cpu";
|
|
5
|
+
readonly capabilities: WorkerCapabilities;
|
|
6
|
+
constructor(id?: string);
|
|
7
|
+
execute(task: ScheduledTask, signal?: AbortSignal): Promise<TaskResult>;
|
|
8
|
+
private executeBash;
|
|
9
|
+
private executeCode;
|
|
10
|
+
private executeCPUTask;
|
|
11
|
+
}
|
|
12
|
+
//# sourceMappingURL=cpu-worker.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"cpu-worker.d.ts","sourceRoot":"","sources":["../../../../../src/core/companion/scheduler/workers/cpu-worker.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,UAAU,EAAE,KAAK,aAAa,EAAE,KAAK,UAAU,EAAE,KAAK,kBAAkB,EAAE,MAAM,kBAAkB,CAAC;AAE5G,qBAAa,SAAU,SAAQ,UAAU;IACxC,QAAQ,CAAC,EAAE,EAAE,MAAM,CAAC;IACpB,QAAQ,CAAC,IAAI,SAAS;IACtB,QAAQ,CAAC,YAAY,EAAE,kBAAkB,CAAC;IAE1C,YAAY,EAAE,CAAC,EAAE,MAAM,EAStB;IAEK,OAAO,CAAC,IAAI,EAAE,aAAa,EAAE,MAAM,CAAC,EAAE,WAAW,GAAG,OAAO,CAAC,UAAU,CAAC,CA6B5E;IAED,OAAO,CAAC,WAAW;YAqDL,WAAW;YAyCX,cAAc;CAU5B","sourcesContent":["import { spawn } from \"child_process\";\nimport { cpus, totalmem } from \"os\";\nimport { BaseWorker, type ScheduledTask, type TaskResult, type WorkerCapabilities } from \"./base-worker.js\";\n\nexport class CPUWorker extends BaseWorker {\n\treadonly id: string;\n\treadonly type = \"cpu\";\n\treadonly capabilities: WorkerCapabilities;\n\n\tconstructor(id?: string) {\n\t\tsuper();\n\t\tthis.id = id || `cpu_${Date.now()}_${Math.random().toString(36).substr(2, 6)}`;\n\t\tthis.capabilities = {\n\t\t\tcpuCores: cpus().length,\n\t\t\tmemoryMb: Math.floor(totalmem() / (1024 * 1024)),\n\t\t\thasGpu: false,\n\t\t\tsupportsTypes: [\"cpu_intensive\", \"code\", \"script\", \"bash\"],\n\t\t};\n\t}\n\n\tasync execute(task: ScheduledTask, signal?: AbortSignal): Promise<TaskResult> {\n\t\tthis.markBusy(task.id);\n\t\tconst startTime = Date.now();\n\n\t\ttry {\n\t\t\tlet result: TaskResult;\n\n\t\t\tif (task.type === \"bash\" || task.type === \"script\") {\n\t\t\t\tresult = await this.executeBash(task, signal);\n\t\t\t} else if (task.type === \"code\") {\n\t\t\t\tresult = await this.executeCode(task, signal);\n\t\t\t} else {\n\t\t\t\tresult = await this.executeCPUTask(task, signal);\n\t\t\t}\n\n\t\t\tconst executionTime = Date.now() - startTime;\n\t\t\tthis.updateStats(executionTime, result.success);\n\t\t\treturn result;\n\t\t} catch (error) {\n\t\t\tconst executionTime = Date.now() - startTime;\n\t\t\tthis.updateStats(executionTime, false);\n\t\t\treturn {\n\t\t\t\tsuccess: false,\n\t\t\t\terror: error instanceof Error ? error.message : String(error),\n\t\t\t\terrorCode: \"EXECUTION_ERROR\",\n\t\t\t};\n\t\t} finally {\n\t\t\tthis.markIdle();\n\t\t}\n\t}\n\n\tprivate executeBash(task: ScheduledTask, signal?: AbortSignal): Promise<TaskResult> {\n\t\treturn new Promise((resolve) => {\n\t\t\tconst stdout: Buffer[] = [];\n\t\t\tconst stderr: Buffer[] = [];\n\t\t\tconst payload = task.payload;\n\n\t\t\tconst child = spawn(payload.command || \"bash\", payload.args || [], {\n\t\t\t\tcwd: payload.workingDir,\n\t\t\t\tenv: { ...process.env, ...payload.env },\n\t\t\t\tstdio: [\"ignore\", \"pipe\", \"pipe\"],\n\t\t\t});\n\n\t\t\tconst timeout = task.requirements?.maxExecutionTimeMs || 300000;\n\t\t\tconst timeoutId = setTimeout(() => {\n\t\t\t\tchild.kill(\"SIGTERM\");\n\t\t\t}, timeout);\n\n\t\t\tconst onAbort = () => {\n\t\t\t\tchild.kill(\"SIGTERM\");\n\t\t\t};\n\n\t\t\tsignal?.addEventListener(\"abort\", onAbort);\n\n\t\t\tchild.stdout?.on(\"data\", (data: Buffer) => stdout.push(data));\n\t\t\tchild.stderr?.on(\"data\", (data: Buffer) => stderr.push(data));\n\n\t\t\tchild.on(\"close\", (code) => {\n\t\t\t\tclearTimeout(timeoutId);\n\t\t\t\tsignal?.removeEventListener(\"abort\", onAbort);\n\n\t\t\t\tresolve({\n\t\t\t\t\tsuccess: code === 0,\n\t\t\t\t\texitCode: code || 0,\n\t\t\t\t\tstdout: Buffer.concat(stdout).toString(),\n\t\t\t\t\tstderr: Buffer.concat(stderr).toString(),\n\t\t\t\t});\n\t\t\t});\n\n\t\t\tchild.on(\"error\", (error) => {\n\t\t\t\tclearTimeout(timeoutId);\n\t\t\t\tsignal?.removeEventListener(\"abort\", onAbort);\n\n\t\t\t\tresolve({\n\t\t\t\t\tsuccess: false,\n\t\t\t\t\tstdout: Buffer.concat(stdout).toString(),\n\t\t\t\t\tstderr: Buffer.concat(stderr).toString(),\n\t\t\t\t\terror: error.message,\n\t\t\t\t\terrorCode: \"SPAWN_ERROR\",\n\t\t\t\t});\n\t\t\t});\n\t\t});\n\t}\n\n\tprivate async executeCode(task: ScheduledTask, signal?: AbortSignal): Promise<TaskResult> {\n\t\tconst payload = task.payload;\n\t\tconst language = payload.language?.toLowerCase() || \"python\";\n\n\t\tlet command: string;\n\t\tlet args: string[];\n\n\t\tswitch (language) {\n\t\t\tcase \"python\":\n\t\t\tcase \"py\":\n\t\t\t\tcommand = \"python3\";\n\t\t\t\targs = [\"-c\", payload.code || \"\"];\n\t\t\t\tbreak;\n\t\t\tcase \"javascript\":\n\t\t\tcase \"js\":\n\t\t\tcase \"node\":\n\t\t\t\tcommand = \"node\";\n\t\t\t\targs = [\"-e\", payload.code || \"\"];\n\t\t\t\tbreak;\n\t\t\tcase \"typescript\":\n\t\t\tcase \"ts\":\n\t\t\t\tcommand = \"npx\";\n\t\t\t\targs = [\"tsx\", \"-e\", payload.code || \"\"];\n\t\t\t\tbreak;\n\t\t\tdefault:\n\t\t\t\treturn {\n\t\t\t\t\tsuccess: false,\n\t\t\t\t\terror: `Unsupported language: ${language}`,\n\t\t\t\t\terrorCode: \"UNSUPPORTED_LANGUAGE\",\n\t\t\t\t};\n\t\t}\n\n\t\treturn this.executeBash(\n\t\t\t{\n\t\t\t\t...task,\n\t\t\t\tpayload: { ...payload, command, args },\n\t\t\t},\n\t\t\tsignal,\n\t\t);\n\t}\n\n\tprivate async executeCPUTask(task: ScheduledTask, signal?: AbortSignal): Promise<TaskResult> {\n\t\treturn this.executeBash(\n\t\t\t{\n\t\t\t\t...task,\n\t\t\t\ttype: \"bash\",\n\t\t\t\tpayload: task.payload,\n\t\t\t},\n\t\t\tsignal,\n\t\t);\n\t}\n}\n"]}
|