aiservermanager 0.1.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +31 -0
- package/backend/dist/di/container.js +80 -0
- package/backend/dist/di/container.js.map +1 -0
- package/backend/dist/di/types.js +18 -0
- package/backend/dist/di/types.js.map +1 -0
- package/backend/dist/files/validatePassword.ps1 +10 -0
- package/backend/dist/files/wmiGpuQuery.ps1 +15 -0
- package/backend/dist/helpers/ExecTools.js +101 -0
- package/backend/dist/helpers/ExecTools.js.map +1 -0
- package/backend/dist/index.js +51 -0
- package/backend/dist/index.js.map +1 -0
- package/backend/dist/middleware/authMiddleware.js +32 -0
- package/backend/dist/middleware/authMiddleware.js.map +1 -0
- package/backend/dist/models/GpuInfo.js +3 -0
- package/backend/dist/models/GpuInfo.js.map +1 -0
- package/backend/dist/models/ServiceConfig.js +46 -0
- package/backend/dist/models/ServiceConfig.js.map +1 -0
- package/backend/dist/models/ServiceStatus.js +3 -0
- package/backend/dist/models/ServiceStatus.js.map +1 -0
- package/backend/dist/routes/authRoutes.js +46 -0
- package/backend/dist/routes/authRoutes.js.map +1 -0
- package/backend/dist/routes/gpuRoutes.js +35 -0
- package/backend/dist/routes/gpuRoutes.js.map +1 -0
- package/backend/dist/routes/serviceRoutes.js +206 -0
- package/backend/dist/routes/serviceRoutes.js.map +1 -0
- package/backend/dist/routes/systemRoutes.js +64 -0
- package/backend/dist/routes/systemRoutes.js.map +1 -0
- package/backend/dist/services/auth/linuxPasswordVerifier.js +74 -0
- package/backend/dist/services/auth/linuxPasswordVerifier.js.map +1 -0
- package/backend/dist/services/auth/passwordVerifier.js +3 -0
- package/backend/dist/services/auth/passwordVerifier.js.map +1 -0
- package/backend/dist/services/auth/windowsPasswordVerifier.js +73 -0
- package/backend/dist/services/auth/windowsPasswordVerifier.js.map +1 -0
- package/backend/dist/services/authService.js +240 -0
- package/backend/dist/services/authService.js.map +1 -0
- package/backend/dist/services/configManager.js +96 -0
- package/backend/dist/services/configManager.js.map +1 -0
- package/backend/dist/services/controllers/systemctlController.js +287 -0
- package/backend/dist/services/controllers/systemctlController.js.map +1 -0
- package/backend/dist/services/controllers/windowsServiceController.js +201 -0
- package/backend/dist/services/controllers/windowsServiceController.js.map +1 -0
- package/backend/dist/services/detectors/amdLinuxDetector.js +127 -0
- package/backend/dist/services/detectors/amdLinuxDetector.js.map +1 -0
- package/backend/dist/services/detectors/gpuDetector.js +3 -0
- package/backend/dist/services/detectors/gpuDetector.js.map +1 -0
- package/backend/dist/services/detectors/nvidiaSmiDetector.js +67 -0
- package/backend/dist/services/detectors/nvidiaSmiDetector.js.map +1 -0
- package/backend/dist/services/detectors/wmiDetector.js +125 -0
- package/backend/dist/services/detectors/wmiDetector.js.map +1 -0
- package/backend/dist/services/enrichers/gpuEnricher.js +3 -0
- package/backend/dist/services/enrichers/gpuEnricher.js.map +1 -0
- package/backend/dist/services/enrichers/lspciEnricher.js +92 -0
- package/backend/dist/services/enrichers/lspciEnricher.js.map +1 -0
- package/backend/dist/services/enrichers/vulkanEnricher.js +57 -0
- package/backend/dist/services/enrichers/vulkanEnricher.js.map +1 -0
- package/backend/dist/services/gpuService.js +108 -0
- package/backend/dist/services/gpuService.js.map +1 -0
- package/backend/dist/services/helpers/gpuDedup.js +46 -0
- package/backend/dist/services/helpers/gpuDedup.js.map +1 -0
- package/backend/dist/services/helpers/gpuEngineNames.js +22 -0
- package/backend/dist/services/helpers/gpuEngineNames.js.map +1 -0
- package/backend/dist/services/llamaAutocompleteService.js +277 -0
- package/backend/dist/services/llamaAutocompleteService.js.map +1 -0
- package/backend/dist/services/managedServicesController.js +72 -0
- package/backend/dist/services/managedServicesController.js.map +1 -0
- package/backend/dist/services/managedServicesManager.js +91 -0
- package/backend/dist/services/managedServicesManager.js.map +1 -0
- package/backend/dist/services/probes/amdLinuxUsageProbe.js +109 -0
- package/backend/dist/services/probes/amdLinuxUsageProbe.js.map +1 -0
- package/backend/dist/services/probes/gpuUsageProbe.js +3 -0
- package/backend/dist/services/probes/gpuUsageProbe.js.map +1 -0
- package/backend/dist/services/probes/nvidiaSmiUsageProbe.js +67 -0
- package/backend/dist/services/probes/nvidiaSmiUsageProbe.js.map +1 -0
- package/backend/dist/services/providers/systemInfoLinuxProvider.js +188 -0
- package/backend/dist/services/providers/systemInfoLinuxProvider.js.map +1 -0
- package/backend/dist/services/providers/systemInfoWindowsProvider.js +101 -0
- package/backend/dist/services/providers/systemInfoWindowsProvider.js.map +1 -0
- package/backend/dist/services/serviceConfigController.js +116 -0
- package/backend/dist/services/serviceConfigController.js.map +1 -0
- package/backend/dist/services/serviceController.js +3 -0
- package/backend/dist/services/serviceController.js.map +1 -0
- package/backend/dist/services/serviceManager.js +157 -0
- package/backend/dist/services/serviceManager.js.map +1 -0
- package/backend/dist/services/systemInfoProvider.js +3 -0
- package/backend/dist/services/systemInfoProvider.js.map +1 -0
- package/backend/dist/services/systemService.js +42 -0
- package/backend/dist/services/systemService.js.map +1 -0
- package/backend/public/browser/chunk-34LU6STA.js +1 -0
- package/backend/public/browser/chunk-JGNPKRLU.js +4 -0
- package/backend/public/browser/favicon.svg +11 -0
- package/backend/public/browser/index.html +15 -0
- package/backend/public/browser/main-MUMQYBNS.js +5579 -0
- package/backend/public/browser/polyfills-5CFQRCPP.js +2 -0
- package/backend/public/browser/styles-QBUDNRKH.css +1 -0
- package/bin/aiservermanager.js +2 -0
- package/package.json +45 -0
|
@@ -0,0 +1,201 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.WindowsServiceController = void 0;
|
|
4
|
+
const ExecTools_1 = require("../../helpers/ExecTools");
|
|
5
|
+
/** Manage Windows services via sc.exe. */
|
|
6
|
+
class WindowsServiceController {
|
|
7
|
+
static SC = "sc.exe";
|
|
8
|
+
_isAdmin = null;
|
|
9
|
+
async isAvailable() {
|
|
10
|
+
return process.platform === "win32";
|
|
11
|
+
}
|
|
12
|
+
/** Check if the current process is running as Administrator. */
|
|
13
|
+
async checkIsAdmin() {
|
|
14
|
+
if (this._isAdmin !== null)
|
|
15
|
+
return this._isAdmin;
|
|
16
|
+
const { stdout } = await ExecTools_1.ExecTools.safeExec("[bool]([Security.Principal.WindowsPrincipal]" +
|
|
17
|
+
"[Security.Principal.WindowsIdentity]::GetCurrent())" +
|
|
18
|
+
".IsInRole([Security.Principal.WindowsBuiltInRole]::Administrator)");
|
|
19
|
+
this._isAdmin = stdout.trim().toUpperCase() === "TRUE";
|
|
20
|
+
return this._isAdmin;
|
|
21
|
+
}
|
|
22
|
+
async getStatus(name) {
|
|
23
|
+
// sc.exe queryex gives STATE (RUNNING/STOPPED), START_TYPE (AUTO/DEMAND/DISABLED)
|
|
24
|
+
const { stdout, stderr } = await ExecTools_1.ExecTools.safeExec(`${WindowsServiceController.SC} queryex "${name}"`);
|
|
25
|
+
const lines = stdout.split("\n");
|
|
26
|
+
let running = false;
|
|
27
|
+
let enabled = false;
|
|
28
|
+
let pid;
|
|
29
|
+
let foundState = false;
|
|
30
|
+
for (const line of lines) {
|
|
31
|
+
const trimmed = line.trim();
|
|
32
|
+
// STATE line: " STATE: 4 RUNNING" or " STATE: 1 STOPPED"
|
|
33
|
+
if (trimmed.startsWith("STATE:")) {
|
|
34
|
+
foundState = true;
|
|
35
|
+
const parts = trimmed.split(/\s+/);
|
|
36
|
+
const state = parts[parts.length - 1]?.toUpperCase();
|
|
37
|
+
running = state === "RUNNING";
|
|
38
|
+
}
|
|
39
|
+
// START_TYPE line: " START_TYPE: 2 AUTO_START"
|
|
40
|
+
if (trimmed.startsWith("START_TYPE:")) {
|
|
41
|
+
const parts = trimmed.split(/\s+/);
|
|
42
|
+
const startType = parts[parts.length - 1]?.toUpperCase();
|
|
43
|
+
enabled = startType !== "DISABLED";
|
|
44
|
+
}
|
|
45
|
+
// PID line: " PID: 1234"
|
|
46
|
+
if (trimmed.startsWith("PID:")) {
|
|
47
|
+
const pidStr = trimmed.split(/\s+/)[1];
|
|
48
|
+
if (pidStr) {
|
|
49
|
+
pid = parseInt(pidStr, 10);
|
|
50
|
+
}
|
|
51
|
+
}
|
|
52
|
+
}
|
|
53
|
+
// Fallback: if sc.exe query failed (service not found), check with Get-Service
|
|
54
|
+
if (!foundState) {
|
|
55
|
+
const psResult = await ExecTools_1.ExecTools.safeExec(`Get-Service "${name}" -ErrorAction SilentlyContinue | Select-Object -ExpandProperty Status`);
|
|
56
|
+
const status = psResult.stdout.trim().toUpperCase();
|
|
57
|
+
if (status) {
|
|
58
|
+
running = status === "RUNNING";
|
|
59
|
+
foundState = true;
|
|
60
|
+
}
|
|
61
|
+
if (foundState) {
|
|
62
|
+
const startModeResult = await ExecTools_1.ExecTools.safeExec(`Get-Service "${name}" -ErrorAction SilentlyContinue | Select-Object -ExpandProperty StartType`);
|
|
63
|
+
const startMode = startModeResult.stdout.trim().toUpperCase();
|
|
64
|
+
if (startMode) {
|
|
65
|
+
enabled = startMode !== "DISABLED";
|
|
66
|
+
}
|
|
67
|
+
}
|
|
68
|
+
}
|
|
69
|
+
if (!foundState) {
|
|
70
|
+
const errorMsg = stderr.trim() ? `Service "${name}" not found: ${stderr.trim()}` : `Service "${name}" not found`;
|
|
71
|
+
return { name, running: false, enabled: false, installed: false, error: errorMsg };
|
|
72
|
+
}
|
|
73
|
+
return { name, running, enabled, installed: true, pid };
|
|
74
|
+
}
|
|
75
|
+
async perform(name, action) {
|
|
76
|
+
const SC = WindowsServiceController.SC;
|
|
77
|
+
let cmd;
|
|
78
|
+
switch (action) {
|
|
79
|
+
case "start":
|
|
80
|
+
cmd = `${SC} start "${name}"`;
|
|
81
|
+
break;
|
|
82
|
+
case "stop":
|
|
83
|
+
cmd = `${SC} stop "${name}"`;
|
|
84
|
+
break;
|
|
85
|
+
case "enable":
|
|
86
|
+
cmd = `${SC} config "${name}" start= auto`;
|
|
87
|
+
break;
|
|
88
|
+
case "disable":
|
|
89
|
+
cmd = `${SC} config "${name}" start= disabled`;
|
|
90
|
+
break;
|
|
91
|
+
default:
|
|
92
|
+
throw new Error(`Unknown action: ${action}`);
|
|
93
|
+
}
|
|
94
|
+
const result = await ExecTools_1.ExecTools.safeExecWithCode(cmd);
|
|
95
|
+
if (result.exitCode !== 0) {
|
|
96
|
+
return {
|
|
97
|
+
name,
|
|
98
|
+
running: false,
|
|
99
|
+
enabled: false,
|
|
100
|
+
installed: true,
|
|
101
|
+
error: `${SC} ${action} failed (code ${result.exitCode}): ${result.stderr.trim() || result.stdout.trim()}`,
|
|
102
|
+
};
|
|
103
|
+
}
|
|
104
|
+
// After start/stop, give the service a moment to transition
|
|
105
|
+
if (action === "start" || action === "stop") {
|
|
106
|
+
await new Promise((resolve) => setTimeout(resolve, 1000));
|
|
107
|
+
}
|
|
108
|
+
const status = await this.getStatus(name);
|
|
109
|
+
// After "start", verify the service is actually running
|
|
110
|
+
if (action === "start" && !status.running && !status.error) {
|
|
111
|
+
status.error = `sc.exe start returned success, but "${name}" is not running`;
|
|
112
|
+
}
|
|
113
|
+
return status;
|
|
114
|
+
}
|
|
115
|
+
async install(name, execStart) {
|
|
116
|
+
const SC = WindowsServiceController.SC;
|
|
117
|
+
const isAdmin = await this.checkIsAdmin();
|
|
118
|
+
if (!isAdmin) {
|
|
119
|
+
return {
|
|
120
|
+
name,
|
|
121
|
+
running: false,
|
|
122
|
+
enabled: false,
|
|
123
|
+
installed: false,
|
|
124
|
+
error: "Server is not running as Administrator. Restart with elevated privileges to install system services.",
|
|
125
|
+
};
|
|
126
|
+
}
|
|
127
|
+
// sc.exe create with demand start (disabled) — install only, no auto-start
|
|
128
|
+
const createResult = await ExecTools_1.ExecTools.safeExecWithCode(`${SC} create "${name}" binPath= "${execStart}" start= demand`);
|
|
129
|
+
if (createResult.exitCode !== 0) {
|
|
130
|
+
// Service may already exist — try sc.exe config to update
|
|
131
|
+
const configResult = await ExecTools_1.ExecTools.safeExecWithCode(`${SC} config "${name}" binPath= "${execStart}" start= demand`);
|
|
132
|
+
if (configResult.exitCode !== 0) {
|
|
133
|
+
return {
|
|
134
|
+
name,
|
|
135
|
+
running: false,
|
|
136
|
+
enabled: false,
|
|
137
|
+
installed: false,
|
|
138
|
+
error: `Failed to install service: ${configResult.stderr.trim()}`,
|
|
139
|
+
};
|
|
140
|
+
}
|
|
141
|
+
return this.getStatus(name);
|
|
142
|
+
}
|
|
143
|
+
return this.getStatus(name);
|
|
144
|
+
}
|
|
145
|
+
async installAndEnable(name, execStart) {
|
|
146
|
+
const status = await this.install(name, execStart);
|
|
147
|
+
if (status.error)
|
|
148
|
+
return status;
|
|
149
|
+
// Enable (set to auto start)
|
|
150
|
+
const enableResult = await ExecTools_1.ExecTools.safeExecWithCode(`${WindowsServiceController.SC} config "${name}" start= auto`);
|
|
151
|
+
if (enableResult.exitCode !== 0) {
|
|
152
|
+
return {
|
|
153
|
+
name,
|
|
154
|
+
running: false,
|
|
155
|
+
enabled: false,
|
|
156
|
+
installed: true,
|
|
157
|
+
error: `sc.exe config start=auto failed: ${enableResult.stderr.trim()}`,
|
|
158
|
+
};
|
|
159
|
+
}
|
|
160
|
+
return this.getStatus(name);
|
|
161
|
+
}
|
|
162
|
+
async uninstall(name) {
|
|
163
|
+
const SC = WindowsServiceController.SC;
|
|
164
|
+
// Stop the service (best-effort)
|
|
165
|
+
const stopResult = await ExecTools_1.ExecTools.safeExecWithCode(`${SC} stop "${name}"`);
|
|
166
|
+
if (stopResult.exitCode === 0) {
|
|
167
|
+
// Wait until the service is actually stopped (sc.exe stop is async)
|
|
168
|
+
for (let i = 0; i < 10; i++) {
|
|
169
|
+
await new Promise((resolve) => setTimeout(resolve, 1000));
|
|
170
|
+
const status = await this.getStatus(name);
|
|
171
|
+
if (!status.running)
|
|
172
|
+
break;
|
|
173
|
+
}
|
|
174
|
+
}
|
|
175
|
+
// Delete the service
|
|
176
|
+
const deleteResult = await ExecTools_1.ExecTools.safeExecWithCode(`${SC} delete "${name}"`);
|
|
177
|
+
if (deleteResult.exitCode !== 0) {
|
|
178
|
+
return {
|
|
179
|
+
ok: false,
|
|
180
|
+
error: `sc.exe delete failed (code ${deleteResult.exitCode}): ${deleteResult.stderr.trim() || deleteResult.stdout.trim()}`,
|
|
181
|
+
};
|
|
182
|
+
}
|
|
183
|
+
return { ok: true };
|
|
184
|
+
}
|
|
185
|
+
async listAvailable() {
|
|
186
|
+
const { stdout } = await ExecTools_1.ExecTools.safeExec("Get-Service | Select-Object -ExpandProperty Name");
|
|
187
|
+
const names = [];
|
|
188
|
+
for (const line of stdout.split("\n")) {
|
|
189
|
+
const name = line.trim();
|
|
190
|
+
if (!name)
|
|
191
|
+
continue;
|
|
192
|
+
names.push(name);
|
|
193
|
+
}
|
|
194
|
+
return names.sort();
|
|
195
|
+
}
|
|
196
|
+
async getJournal(_name, _count = 100) {
|
|
197
|
+
return { error: "Journal retrieval is not supported on Windows. Use Linux with systemd." };
|
|
198
|
+
}
|
|
199
|
+
}
|
|
200
|
+
exports.WindowsServiceController = WindowsServiceController;
|
|
201
|
+
//# sourceMappingURL=windowsServiceController.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"windowsServiceController.js","sourceRoot":"","sources":["../../../src/services/controllers/windowsServiceController.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,127 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) {
|
|
3
|
+
var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
|
|
4
|
+
if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
|
|
5
|
+
else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
|
|
6
|
+
return c > 3 && r && Object.defineProperty(target, key, r), r;
|
|
7
|
+
};
|
|
8
|
+
var __metadata = (this && this.__metadata) || function (k, v) {
|
|
9
|
+
if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v);
|
|
10
|
+
};
|
|
11
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
12
|
+
exports.AmdLinuxDetector = void 0;
|
|
13
|
+
const inversify_1 = require("inversify");
|
|
14
|
+
const ExecTools_1 = require("../../helpers/ExecTools");
|
|
15
|
+
/**
|
|
16
|
+
* Detect AMD GPUs on Linux using `rocm-smi`.
|
|
17
|
+
* Returns only static info: index, name, vramTotal, pciBusId.
|
|
18
|
+
* Dynamic metrics (usage, temperature, vramUsed) are delegated to AmdLinuxUsageProbe.
|
|
19
|
+
*
|
|
20
|
+
* Commands (rocm-smi 6.x compatible):
|
|
21
|
+
* --showproductname --json → product name
|
|
22
|
+
* --showmeminfo vram --json → VRAM total
|
|
23
|
+
* --showbus --json → PCI bus ID
|
|
24
|
+
*/
|
|
25
|
+
let AmdLinuxDetector = class AmdLinuxDetector {
|
|
26
|
+
availableCache = null;
|
|
27
|
+
constructor() {
|
|
28
|
+
if (process.platform !== "linux") {
|
|
29
|
+
this.availableCache = false;
|
|
30
|
+
}
|
|
31
|
+
}
|
|
32
|
+
async isAvailable() {
|
|
33
|
+
if (this.availableCache !== null)
|
|
34
|
+
return this.availableCache;
|
|
35
|
+
const result = await ExecTools_1.ExecTools.safeExec("rocm-smi --showproductname --json", { timeout: 5000 });
|
|
36
|
+
const available = result.stdout.trim().length > 0;
|
|
37
|
+
if (available) {
|
|
38
|
+
this.availableCache = true;
|
|
39
|
+
}
|
|
40
|
+
return available;
|
|
41
|
+
}
|
|
42
|
+
async detect() {
|
|
43
|
+
const results = await Promise.all([
|
|
44
|
+
ExecTools_1.ExecTools.safeExec("rocm-smi --showproductname --json", { timeout: 10000 }),
|
|
45
|
+
ExecTools_1.ExecTools.safeExec("rocm-smi --showmeminfo vram --json", { timeout: 10000 }),
|
|
46
|
+
ExecTools_1.ExecTools.safeExec("rocm-smi --showbus --json", { timeout: 10000 }),
|
|
47
|
+
]);
|
|
48
|
+
if (!results[0].stdout.trim())
|
|
49
|
+
return [];
|
|
50
|
+
const productData = this.parseJson(results[0].stdout);
|
|
51
|
+
if (!productData)
|
|
52
|
+
return [];
|
|
53
|
+
const cardKeys = this.getCardKeys(productData);
|
|
54
|
+
if (cardKeys.length === 0)
|
|
55
|
+
return [];
|
|
56
|
+
const memData = this.parseJson(results[1].stdout);
|
|
57
|
+
const busData = this.parseJson(results[2].stdout);
|
|
58
|
+
const gpus = [];
|
|
59
|
+
for (let i = 0; i < cardKeys.length; i++) {
|
|
60
|
+
const key = cardKeys[i];
|
|
61
|
+
gpus.push(this.parseCard(i, key, productData, memData, busData));
|
|
62
|
+
}
|
|
63
|
+
return gpus;
|
|
64
|
+
}
|
|
65
|
+
parseJson(raw) {
|
|
66
|
+
try {
|
|
67
|
+
return JSON.parse(raw.trim());
|
|
68
|
+
}
|
|
69
|
+
catch {
|
|
70
|
+
return null;
|
|
71
|
+
}
|
|
72
|
+
}
|
|
73
|
+
getCardKeys(data) {
|
|
74
|
+
return Object.keys(data)
|
|
75
|
+
.filter((k) => k.startsWith("card"))
|
|
76
|
+
.sort((a, b) => {
|
|
77
|
+
const numA = parseInt(a.replace("card", ""), 10);
|
|
78
|
+
const numB = parseInt(b.replace("card", ""), 10);
|
|
79
|
+
return numA - numB;
|
|
80
|
+
});
|
|
81
|
+
}
|
|
82
|
+
parseCard(index, cardKey, productData, memData, busData) {
|
|
83
|
+
const gpu = {
|
|
84
|
+
index,
|
|
85
|
+
vendor: "AMD",
|
|
86
|
+
brand: "RADEON",
|
|
87
|
+
name: `AMD GPU ${index}`,
|
|
88
|
+
engineCudaName: "",
|
|
89
|
+
engineRocmName: "",
|
|
90
|
+
engineVulkanName: "",
|
|
91
|
+
vramTotal: 0,
|
|
92
|
+
pciBusId: "",
|
|
93
|
+
};
|
|
94
|
+
// Product name
|
|
95
|
+
const cardInfo = productData[cardKey];
|
|
96
|
+
if (cardInfo?.["Card Series"]) {
|
|
97
|
+
gpu.name = String(cardInfo["Card Series"]);
|
|
98
|
+
}
|
|
99
|
+
// VRAM total (bytes → GB)
|
|
100
|
+
if (memData) {
|
|
101
|
+
const memCard = memData[cardKey];
|
|
102
|
+
const totalBytes = memCard?.["VRAM Total Memory (B)"];
|
|
103
|
+
if (totalBytes !== undefined) {
|
|
104
|
+
gpu.vramTotal = parseFloat(String(totalBytes)) / 1024 ** 3;
|
|
105
|
+
}
|
|
106
|
+
}
|
|
107
|
+
// PCI Bus — strip "0000:" domain prefix to match lspci format
|
|
108
|
+
if (busData) {
|
|
109
|
+
const busCard = busData[cardKey];
|
|
110
|
+
const pciBus = busCard?.["PCI Bus"];
|
|
111
|
+
if (pciBus !== undefined) {
|
|
112
|
+
let bus = String(pciBus).toUpperCase();
|
|
113
|
+
if (bus.startsWith("0000:")) {
|
|
114
|
+
bus = bus.slice(5);
|
|
115
|
+
}
|
|
116
|
+
gpu.pciBusId = bus;
|
|
117
|
+
}
|
|
118
|
+
}
|
|
119
|
+
return gpu;
|
|
120
|
+
}
|
|
121
|
+
};
|
|
122
|
+
exports.AmdLinuxDetector = AmdLinuxDetector;
|
|
123
|
+
exports.AmdLinuxDetector = AmdLinuxDetector = __decorate([
|
|
124
|
+
(0, inversify_1.injectable)(),
|
|
125
|
+
__metadata("design:paramtypes", [])
|
|
126
|
+
], AmdLinuxDetector);
|
|
127
|
+
//# sourceMappingURL=amdLinuxDetector.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"amdLinuxDetector.js","sourceRoot":"","sources":["../../../src/services/detectors/amdLinuxDetector.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"gpuDetector.js","sourceRoot":"","sources":["../../../src/services/detectors/gpuDetector.ts"],"names":[],"mappings":""}
|
|
@@ -0,0 +1,67 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) {
|
|
3
|
+
var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
|
|
4
|
+
if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
|
|
5
|
+
else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
|
|
6
|
+
return c > 3 && r && Object.defineProperty(target, key, r), r;
|
|
7
|
+
};
|
|
8
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
9
|
+
exports.NvidiaSmiDetector = void 0;
|
|
10
|
+
const inversify_1 = require("inversify");
|
|
11
|
+
const ExecTools_1 = require("../../helpers/ExecTools");
|
|
12
|
+
/**
|
|
13
|
+
* Detect NVIDIA GPUs using `nvidia-smi`.
|
|
14
|
+
* Returns only static info: index, name, vramTotal, pciBusId.
|
|
15
|
+
* Dynamic metrics (usage, temperature, vramUsed) are delegated to NvidiaSmiUsageProbe.
|
|
16
|
+
*/
|
|
17
|
+
let NvidiaSmiDetector = class NvidiaSmiDetector {
|
|
18
|
+
availableCache = null;
|
|
19
|
+
async isAvailable() {
|
|
20
|
+
if (this.availableCache !== null)
|
|
21
|
+
return this.availableCache;
|
|
22
|
+
const result = await ExecTools_1.ExecTools.safeExec("nvidia-smi --query-gpu=index --format=csv,noheader,nounits", {
|
|
23
|
+
timeout: 5000,
|
|
24
|
+
});
|
|
25
|
+
const available = result.stdout.trim().length > 0;
|
|
26
|
+
if (available) {
|
|
27
|
+
this.availableCache = true;
|
|
28
|
+
}
|
|
29
|
+
return available;
|
|
30
|
+
}
|
|
31
|
+
async detect() {
|
|
32
|
+
const result = await ExecTools_1.ExecTools.safeExec("nvidia-smi --query-gpu=index,name,memory.total,pci.bus_id --format=csv,noheader,nounits", { timeout: 10000 });
|
|
33
|
+
if (!result.stdout.trim())
|
|
34
|
+
return [];
|
|
35
|
+
return this.parseCsv(result.stdout);
|
|
36
|
+
}
|
|
37
|
+
parseCsv(raw) {
|
|
38
|
+
const gpus = [];
|
|
39
|
+
for (const line of raw.trim().split("\n")) {
|
|
40
|
+
const parts = line.split(",").map((s) => s.trim());
|
|
41
|
+
if (parts.length < 4)
|
|
42
|
+
continue;
|
|
43
|
+
const name = parts[1];
|
|
44
|
+
const vramTotalMiB = parseFloat(parts[2]);
|
|
45
|
+
let busId = parts[3];
|
|
46
|
+
// Normalize: strip PCI domain prefix (e.g. "0000:" on Linux or "00000000:" on Windows)
|
|
47
|
+
busId = busId.replace(/^0+:/, "");
|
|
48
|
+
gpus.push({
|
|
49
|
+
index: parseInt(parts[0], 10),
|
|
50
|
+
vendor: "NVIDIA",
|
|
51
|
+
brand: "NVIDIA",
|
|
52
|
+
name,
|
|
53
|
+
engineCudaName: "",
|
|
54
|
+
engineRocmName: "",
|
|
55
|
+
engineVulkanName: "",
|
|
56
|
+
vramTotal: Math.round(vramTotalMiB / 1024),
|
|
57
|
+
pciBusId: busId,
|
|
58
|
+
});
|
|
59
|
+
}
|
|
60
|
+
return gpus;
|
|
61
|
+
}
|
|
62
|
+
};
|
|
63
|
+
exports.NvidiaSmiDetector = NvidiaSmiDetector;
|
|
64
|
+
exports.NvidiaSmiDetector = NvidiaSmiDetector = __decorate([
|
|
65
|
+
(0, inversify_1.injectable)()
|
|
66
|
+
], NvidiaSmiDetector);
|
|
67
|
+
//# sourceMappingURL=nvidiaSmiDetector.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"nvidiaSmiDetector.js","sourceRoot":"","sources":["../../../src/services/detectors/nvidiaSmiDetector.ts"],"names":[],"mappings":";;;;;;;;;AAAA,yCAAuC;AAEvC,uDAAoD;AAGpD;;;;GAIG;AAEI,IAAM,iBAAiB,GAAvB,MAAM,iBAAiB;IACpB,cAAc,GAAmB,IAAI,CAAC;IAE9C,KAAK,CAAC,WAAW;QACf,IAAI,IAAI,CAAC,cAAc,KAAK,IAAI;YAAE,OAAO,IAAI,CAAC,cAAc,CAAC;QAE7D,MAAM,MAAM,GAAG,MAAM,qBAAS,CAAC,QAAQ,CAAC,4DAA4D,EAAE;YACpG,OAAO,EAAE,IAAI;SACd,CAAC,CAAC;QACH,MAAM,SAAS,GAAG,MAAM,CAAC,MAAM,CAAC,IAAI,EAAE,CAAC,MAAM,GAAG,CAAC,CAAC;QAClD,IAAI,SAAS,EAAE,CAAC;YACd,IAAI,CAAC,cAAc,GAAG,IAAI,CAAC;QAC7B,CAAC;QACD,OAAO,SAAS,CAAC;IACnB,CAAC;IAED,KAAK,CAAC,MAAM;QACV,MAAM,MAAM,GAAG,MAAM,qBAAS,CAAC,QAAQ,CACrC,yFAAyF,EACzF,EAAE,OAAO,EAAE,KAAK,EAAE,CACnB,CAAC;QAEF,IAAI,CAAC,MAAM,CAAC,MAAM,CAAC,IAAI,EAAE;YAAE,OAAO,EAAE,CAAC;QAErC,OAAO,IAAI,CAAC,QAAQ,CAAC,MAAM,CAAC,MAAM,CAAC,CAAC;IACtC,CAAC;IAEO,QAAQ,CAAC,GAAW;QAC1B,MAAM,IAAI,GAAc,EAAE,CAAC;QAE3B,KAAK,MAAM,IAAI,IAAI,GAAG,CAAC,IAAI,EAAE,CAAC,KAAK,CAAC,IAAI,CAAC,EAAE,CAAC;YAC1C,MAAM,KAAK,GAAG,IAAI,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,IAAI,EAAE,CAAC,CAAC;YACnD,IAAI,KAAK,CAAC,MAAM,GAAG,CAAC;gBAAE,SAAS;YAE/B,MAAM,IAAI,GAAG,KAAK,CAAC,CAAC,CAAC,CAAC;YACtB,MAAM,YAAY,GAAG,UAAU,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,CAAC;YAC1C,IAAI,KAAK,GAAG,KAAK,CAAC,CAAC,CAAC,CAAC;YAErB,uFAAuF;YACvF,KAAK,GAAG,KAAK,CAAC,OAAO,CAAC,MAAM,EAAE,EAAE,CAAC,CAAC;YAElC,IAAI,CAAC,IAAI,CAAC;gBACR,KAAK,EAAE,QAAQ,CAAC,KAAK,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC;gBAC7B,MAAM,EAAE,QAAQ;gBAChB,KAAK,EAAE,QAAQ;gBACf,IAAI;gBACJ,cAAc,EAAE,EAAE;gBAClB,cAAc,EAAE,EAAE;gBAClB,gBAAgB,EAAE,EAAE;gBACpB,SAAS,EAAE,IAAI,CAAC,KAAK,CAAC,YAAY,GAAG,IAAI,CAAC;gBAC1C,QAAQ,EAAE,KAAK;aAChB,CAAC,CAAC;QACL,CAAC;QAED,OAAO,IAAI,CAAC;IACd,CAAC;CACF,CAAA;AAxDY,8CAAiB;4BAAjB,iBAAiB;IAD7B,IAAA,sBAAU,GAAE;GACA,iBAAiB,CAwD7B"}
|
|
@@ -0,0 +1,125 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
3
|
+
if (k2 === undefined) k2 = k;
|
|
4
|
+
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
5
|
+
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
6
|
+
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
7
|
+
}
|
|
8
|
+
Object.defineProperty(o, k2, desc);
|
|
9
|
+
}) : (function(o, m, k, k2) {
|
|
10
|
+
if (k2 === undefined) k2 = k;
|
|
11
|
+
o[k2] = m[k];
|
|
12
|
+
}));
|
|
13
|
+
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
|
|
14
|
+
Object.defineProperty(o, "default", { enumerable: true, value: v });
|
|
15
|
+
}) : function(o, v) {
|
|
16
|
+
o["default"] = v;
|
|
17
|
+
});
|
|
18
|
+
var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) {
|
|
19
|
+
var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
|
|
20
|
+
if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
|
|
21
|
+
else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
|
|
22
|
+
return c > 3 && r && Object.defineProperty(target, key, r), r;
|
|
23
|
+
};
|
|
24
|
+
var __importStar = (this && this.__importStar) || (function () {
|
|
25
|
+
var ownKeys = function(o) {
|
|
26
|
+
ownKeys = Object.getOwnPropertyNames || function (o) {
|
|
27
|
+
var ar = [];
|
|
28
|
+
for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
|
|
29
|
+
return ar;
|
|
30
|
+
};
|
|
31
|
+
return ownKeys(o);
|
|
32
|
+
};
|
|
33
|
+
return function (mod) {
|
|
34
|
+
if (mod && mod.__esModule) return mod;
|
|
35
|
+
var result = {};
|
|
36
|
+
if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
|
|
37
|
+
__setModuleDefault(result, mod);
|
|
38
|
+
return result;
|
|
39
|
+
};
|
|
40
|
+
})();
|
|
41
|
+
var __metadata = (this && this.__metadata) || function (k, v) {
|
|
42
|
+
if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v);
|
|
43
|
+
};
|
|
44
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
45
|
+
exports.WmiDetector = void 0;
|
|
46
|
+
const inversify_1 = require("inversify");
|
|
47
|
+
const path = __importStar(require("path"));
|
|
48
|
+
const ExecTools_1 = require("../../helpers/ExecTools");
|
|
49
|
+
/**
|
|
50
|
+
* Detect GPUs on Windows using PowerShell WMI (Win32_VideoController).
|
|
51
|
+
* Supports all vendors — NVIDIA, AMD, Intel.
|
|
52
|
+
* PCI bus ID is read from the Windows registry (LocationInformation) to match
|
|
53
|
+
* the format produced by nvidia-smi (e.g. "01:00.0"), enabling correct dedup.
|
|
54
|
+
*/
|
|
55
|
+
let WmiDetector = class WmiDetector {
|
|
56
|
+
scriptPath = path.resolve(__dirname, "../../../files/wmiGpuQuery.ps1");
|
|
57
|
+
availableCache = null;
|
|
58
|
+
constructor() {
|
|
59
|
+
if (process.platform !== "win32") {
|
|
60
|
+
this.availableCache = false;
|
|
61
|
+
}
|
|
62
|
+
}
|
|
63
|
+
async isAvailable() {
|
|
64
|
+
if (this.availableCache !== null)
|
|
65
|
+
return this.availableCache;
|
|
66
|
+
const result = await ExecTools_1.ExecTools.safeExec("Get-CimInstance -ClassName Win32_VideoController | Select-Object -First 1 | ConvertTo-Json", { timeout: 8000 });
|
|
67
|
+
const available = result.stdout.trim().length > 0;
|
|
68
|
+
if (available) {
|
|
69
|
+
this.availableCache = true;
|
|
70
|
+
}
|
|
71
|
+
return available;
|
|
72
|
+
}
|
|
73
|
+
async detect() {
|
|
74
|
+
const result = await ExecTools_1.ExecTools.safeExecPs1(this.scriptPath, { timeout: 15000 });
|
|
75
|
+
if (!result.stdout.trim())
|
|
76
|
+
return [];
|
|
77
|
+
return this.parseJson(result.stdout);
|
|
78
|
+
}
|
|
79
|
+
parseJson(raw) {
|
|
80
|
+
try {
|
|
81
|
+
const items = Array.isArray(JSON.parse(raw)) ? JSON.parse(raw) : [JSON.parse(raw)];
|
|
82
|
+
return items.map((item, idx) => {
|
|
83
|
+
const data = item;
|
|
84
|
+
const name = data.name ?? "Unknown GPU";
|
|
85
|
+
const vramBytes = parseInt(data.vram ?? data.AdapterRAM ?? "0", 10);
|
|
86
|
+
return {
|
|
87
|
+
index: idx,
|
|
88
|
+
vendor: classifyVendor(name),
|
|
89
|
+
brand: resolveBrand(name),
|
|
90
|
+
name,
|
|
91
|
+
engineCudaName: "",
|
|
92
|
+
engineRocmName: "",
|
|
93
|
+
engineVulkanName: "",
|
|
94
|
+
vramTotal: Math.round(vramBytes / (1024 * 1024 * 1024)),
|
|
95
|
+
pciBusId: data.pci ?? data.PNPDeviceID ?? "",
|
|
96
|
+
};
|
|
97
|
+
});
|
|
98
|
+
}
|
|
99
|
+
catch {
|
|
100
|
+
return [];
|
|
101
|
+
}
|
|
102
|
+
}
|
|
103
|
+
};
|
|
104
|
+
exports.WmiDetector = WmiDetector;
|
|
105
|
+
exports.WmiDetector = WmiDetector = __decorate([
|
|
106
|
+
(0, inversify_1.injectable)(),
|
|
107
|
+
__metadata("design:paramtypes", [])
|
|
108
|
+
], WmiDetector);
|
|
109
|
+
function classifyVendor(name) {
|
|
110
|
+
const upper = name.toUpperCase();
|
|
111
|
+
if (upper.includes("NVIDIA"))
|
|
112
|
+
return "NVIDIA";
|
|
113
|
+
if (upper.includes("AMD") || upper.includes("RADEON"))
|
|
114
|
+
return "AMD";
|
|
115
|
+
if (upper.includes("INTEL"))
|
|
116
|
+
return "Intel";
|
|
117
|
+
return "Unknown";
|
|
118
|
+
}
|
|
119
|
+
function resolveBrand(name) {
|
|
120
|
+
const upper = name.toUpperCase();
|
|
121
|
+
if (upper.includes("AMD") || upper.includes("RADEON"))
|
|
122
|
+
return "RADEON";
|
|
123
|
+
return classifyVendor(name);
|
|
124
|
+
}
|
|
125
|
+
//# sourceMappingURL=wmiDetector.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"wmiDetector.js","sourceRoot":"","sources":["../../../src/services/detectors/wmiDetector.ts"],"names":[],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAAA,yCAAuC;AACvC,2CAA6B;AAE7B,uDAAoD;AAGpD;;;;;GAKG;AAEI,IAAM,WAAW,GAAjB,MAAM,WAAW;IACL,UAAU,GAAG,IAAI,CAAC,OAAO,CAAC,SAAS,EAAE,gCAAgC,CAAC,CAAC;IAChF,cAAc,GAAmB,IAAI,CAAC;IAE9C;QACE,IAAI,OAAO,CAAC,QAAQ,KAAK,OAAO,EAAE,CAAC;YACjC,IAAI,CAAC,cAAc,GAAG,KAAK,CAAC;QAC9B,CAAC;IACH,CAAC;IAED,KAAK,CAAC,WAAW;QACf,IAAI,IAAI,CAAC,cAAc,KAAK,IAAI;YAAE,OAAO,IAAI,CAAC,cAAc,CAAC;QAE7D,MAAM,MAAM,GAAG,MAAM,qBAAS,CAAC,QAAQ,CACrC,4FAA4F,EAC5F,EAAE,OAAO,EAAE,IAAI,EAAE,CAClB,CAAC;QACF,MAAM,SAAS,GAAG,MAAM,CAAC,MAAM,CAAC,IAAI,EAAE,CAAC,MAAM,GAAG,CAAC,CAAC;QAClD,IAAI,SAAS,EAAE,CAAC;YACd,IAAI,CAAC,cAAc,GAAG,IAAI,CAAC;QAC7B,CAAC;QACD,OAAO,SAAS,CAAC;IACnB,CAAC;IAED,KAAK,CAAC,MAAM;QACV,MAAM,MAAM,GAAG,MAAM,qBAAS,CAAC,WAAW,CAAC,IAAI,CAAC,UAAU,EAAE,EAAE,OAAO,EAAE,KAAK,EAAE,CAAC,CAAC;QAChF,IAAI,CAAC,MAAM,CAAC,MAAM,CAAC,IAAI,EAAE;YAAE,OAAO,EAAE,CAAC;QAErC,OAAO,IAAI,CAAC,SAAS,CAAC,MAAM,CAAC,MAAM,CAAC,CAAC;IACvC,CAAC;IAEO,SAAS,CAAC,GAAW;QAC3B,IAAI,CAAC;YACH,MAAM,KAAK,GAAc,KAAK,CAAC,OAAO,CAAC,IAAI,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,CAAC;YAE9F,OAAO,KAAK,CAAC,GAAG,CAAC,CAAC,IAAI,EAAE,GAAG,EAAE,EAAE;gBAC7B,MAAM,IAAI,GAAG,IAA+B,CAAC;gBAC7C,MAAM,IAAI,GAAI,IAAI,CAAC,IAAe,IAAI,aAAa,CAAC;gBACpD,MAAM,SAAS,GAAG,QAAQ,CAAE,IAAI,CAAC,IAAe,IAAK,IAAI,CAAC,UAAqB,IAAI,GAAG,EAAE,EAAE,CAAC,CAAC;gBAE5F,OAAO;oBACL,KAAK,EAAE,GAAG;oBACV,MAAM,EAAE,cAAc,CAAC,IAAI,CAAC;oBAC5B,KAAK,EAAE,YAAY,CAAC,IAAI,CAAC;oBACzB,IAAI;oBACJ,cAAc,EAAE,EAAE;oBAClB,cAAc,EAAE,EAAE;oBAClB,gBAAgB,EAAE,EAAE;oBACpB,SAAS,EAAE,IAAI,CAAC,KAAK,CAAC,SAAS,GAAG,CAAC,IAAI,GAAG,IAAI,GAAG,IAAI,CAAC,CAAC;oBACvD,QAAQ,EAAG,IAAI,CAAC,GAAc,IAAK,IAAI,CAAC,WAAsB,IAAI,EAAE;iBACrE,CAAC;YACJ,CAAC,CAAC,CAAC;QACL,CAAC;QAAC,MAAM,CAAC;YACP,OAAO,EAAE,CAAC;QACZ,CAAC;IACH,CAAC;CACF,CAAA;AAxDY,kCAAW;sBAAX,WAAW;IADvB,IAAA,sBAAU,GAAE;;GACA,WAAW,CAwDvB;AAED,SAAS,cAAc,CAAC,IAAY;IAClC,MAAM,KAAK,GAAG,IAAI,CAAC,WAAW,EAAE,CAAC;IACjC,IAAI,KAAK,CAAC,QAAQ,CAAC,QAAQ,CAAC;QAAE,OAAO,QAAQ,CAAC;IAC9C,IAAI,KAAK,CAAC,QAAQ,CAAC,KAAK,CAAC,IAAI,KAAK,CAAC,QAAQ,CAAC,QAAQ,CAAC;QAAE,OAAO,KAAK,CAAC;IACpE,IAAI,KAAK,CAAC,QAAQ,CAAC,OAAO,CAAC;QAAE,OAAO,OAAO,CAAC;IAC5C,OAAO,SAAS,CAAC;AACnB,CAAC;AAED,SAAS,YAAY,CAAC,IAAY;IAChC,MAAM,KAAK,GAAG,IAAI,CAAC,WAAW,EAAE,CAAC;IACjC,IAAI,KAAK,CAAC,QAAQ,CAAC,KAAK,CAAC,IAAI,KAAK,CAAC,QAAQ,CAAC,QAAQ,CAAC;QAAE,OAAO,QAAQ,CAAC;IACvE,OAAO,cAAc,CAAC,IAAI,CAAC,CAAC;AAC9B,CAAC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"gpuEnricher.js","sourceRoot":"","sources":["../../../src/services/enrichers/gpuEnricher.ts"],"names":[],"mappings":""}
|