feat: add backend server and service modules

Includes HTTP server with auth, static file serving, and API routes.
Services cover GPU monitoring, quota checking, Gitea repo listing,
workspace management, agent task orchestration, and settings persistence.
This commit is contained in:
2026-05-15 11:12:30 +08:00
parent 4fdd41a05a
commit 673a5f9f62
10 changed files with 872 additions and 0 deletions

49
src/services/gpu.js Normal file
View File

@@ -0,0 +1,49 @@
import { runProcess } from '../process.js';
const NVIDIA_QUERY = [
'--query-gpu=index,name,memory.used,memory.total,utilization.gpu',
'--format=csv,noheader,nounits'
];
function parseGpuLine(line) {
const [index, name, memoryUsed, memoryTotal, utilization] = line.split(',').map((part) => part.trim());
return {
index: Number(index),
name,
memoryUsedMiB: Number(memoryUsed),
memoryTotalMiB: Number(memoryTotal),
gpuUtilizationPercent: Number(utilization)
};
}
export function parseNvidiaSmiCsv(output) {
return output
.split('\n')
.map((line) => line.trim())
.filter(Boolean)
.map(parseGpuLine)
.filter((gpu) => Number.isFinite(gpu.index));
}
export async function collectGpuStatus(config) {
const hosts = config.gpuHosts || [];
const checks = hosts.map(async (host) => {
const result = await runProcess('ssh', [
'-o', 'BatchMode=yes',
'-o', `ConnectTimeout=${Math.max(1, Math.ceil((config.sshTimeoutMs || 10000) / 1000))}`,
host,
'nvidia-smi',
...NVIDIA_QUERY
], { timeoutMs: config.sshTimeoutMs || 10000 });
return {
host,
ok: result.ok,
checkedAt: new Date().toISOString(),
gpus: result.ok ? parseNvidiaSmiCsv(result.stdout) : [],
error: result.ok ? null : result.stderr || result.stdout || 'Unable to query GPU status.'
};
});
return Promise.all(checks);
}