@astroanywhere/agent 0.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +76 -0
- package/README.md +178 -0
- package/dist/cli.d.ts +15 -0
- package/dist/cli.d.ts.map +1 -0
- package/dist/cli.js +401 -0
- package/dist/cli.js.map +1 -0
- package/dist/commands/index.d.ts +9 -0
- package/dist/commands/index.d.ts.map +1 -0
- package/dist/commands/index.js +9 -0
- package/dist/commands/index.js.map +1 -0
- package/dist/commands/mcp.d.ts +16 -0
- package/dist/commands/mcp.d.ts.map +1 -0
- package/dist/commands/mcp.js +19 -0
- package/dist/commands/mcp.js.map +1 -0
- package/dist/commands/setup.d.ts +20 -0
- package/dist/commands/setup.d.ts.map +1 -0
- package/dist/commands/setup.js +585 -0
- package/dist/commands/setup.js.map +1 -0
- package/dist/commands/start.d.ts +16 -0
- package/dist/commands/start.d.ts.map +1 -0
- package/dist/commands/start.js +638 -0
- package/dist/commands/start.js.map +1 -0
- package/dist/commands/status.d.ts +5 -0
- package/dist/commands/status.d.ts.map +1 -0
- package/dist/commands/status.js +63 -0
- package/dist/commands/status.js.map +1 -0
- package/dist/commands/stop.d.ts +5 -0
- package/dist/commands/stop.d.ts.map +1 -0
- package/dist/commands/stop.js +85 -0
- package/dist/commands/stop.js.map +1 -0
- package/dist/execution/direct-strategy.d.ts +18 -0
- package/dist/execution/direct-strategy.d.ts.map +1 -0
- package/dist/execution/direct-strategy.js +156 -0
- package/dist/execution/direct-strategy.js.map +1 -0
- package/dist/execution/docker-strategy.d.ts +26 -0
- package/dist/execution/docker-strategy.d.ts.map +1 -0
- package/dist/execution/docker-strategy.js +222 -0
- package/dist/execution/docker-strategy.js.map +1 -0
- package/dist/execution/index.d.ts +14 -0
- package/dist/execution/index.d.ts.map +1 -0
- package/dist/execution/index.js +13 -0
- package/dist/execution/index.js.map +1 -0
- package/dist/execution/kubernetes-exec-strategy.d.ts +23 -0
- package/dist/execution/kubernetes-exec-strategy.d.ts.map +1 -0
- package/dist/execution/kubernetes-exec-strategy.js +232 -0
- package/dist/execution/kubernetes-exec-strategy.js.map +1 -0
- package/dist/execution/registry.d.ts +41 -0
- package/dist/execution/registry.d.ts.map +1 -0
- package/dist/execution/registry.js +84 -0
- package/dist/execution/registry.js.map +1 -0
- package/dist/execution/slurm-strategy.d.ts +22 -0
- package/dist/execution/slurm-strategy.d.ts.map +1 -0
- package/dist/execution/slurm-strategy.js +219 -0
- package/dist/execution/slurm-strategy.js.map +1 -0
- package/dist/execution/types.d.ts +72 -0
- package/dist/execution/types.d.ts.map +1 -0
- package/dist/execution/types.js +10 -0
- package/dist/execution/types.js.map +1 -0
- package/dist/index.d.ts +22 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +22 -0
- package/dist/index.js.map +1 -0
- package/dist/lib/api-client.d.ts +35 -0
- package/dist/lib/api-client.d.ts.map +1 -0
- package/dist/lib/api-client.js +126 -0
- package/dist/lib/api-client.js.map +1 -0
- package/dist/lib/config.d.ts +174 -0
- package/dist/lib/config.d.ts.map +1 -0
- package/dist/lib/config.js +399 -0
- package/dist/lib/config.js.map +1 -0
- package/dist/lib/copy-worktree.d.ts +73 -0
- package/dist/lib/copy-worktree.d.ts.map +1 -0
- package/dist/lib/copy-worktree.js +374 -0
- package/dist/lib/copy-worktree.js.map +1 -0
- package/dist/lib/git-pr.d.ts +63 -0
- package/dist/lib/git-pr.d.ts.map +1 -0
- package/dist/lib/git-pr.js +224 -0
- package/dist/lib/git-pr.js.map +1 -0
- package/dist/lib/hardware-id.d.ts +25 -0
- package/dist/lib/hardware-id.d.ts.map +1 -0
- package/dist/lib/hardware-id.js +186 -0
- package/dist/lib/hardware-id.js.map +1 -0
- package/dist/lib/hpc-context.d.ts +35 -0
- package/dist/lib/hpc-context.d.ts.map +1 -0
- package/dist/lib/hpc-context.js +167 -0
- package/dist/lib/hpc-context.js.map +1 -0
- package/dist/lib/prompt-templates.d.ts +195 -0
- package/dist/lib/prompt-templates.d.ts.map +1 -0
- package/dist/lib/prompt-templates.js +353 -0
- package/dist/lib/prompt-templates.js.map +1 -0
- package/dist/lib/providers.d.ts +27 -0
- package/dist/lib/providers.d.ts.map +1 -0
- package/dist/lib/providers.js +372 -0
- package/dist/lib/providers.js.map +1 -0
- package/dist/lib/repo-context.d.ts +18 -0
- package/dist/lib/repo-context.d.ts.map +1 -0
- package/dist/lib/repo-context.js +61 -0
- package/dist/lib/repo-context.js.map +1 -0
- package/dist/lib/repo-utils.d.ts +35 -0
- package/dist/lib/repo-utils.d.ts.map +1 -0
- package/dist/lib/repo-utils.js +222 -0
- package/dist/lib/repo-utils.js.map +1 -0
- package/dist/lib/resources.d.ts +17 -0
- package/dist/lib/resources.d.ts.map +1 -0
- package/dist/lib/resources.js +227 -0
- package/dist/lib/resources.js.map +1 -0
- package/dist/lib/slurm-detect.d.ts +15 -0
- package/dist/lib/slurm-detect.d.ts.map +1 -0
- package/dist/lib/slurm-detect.js +148 -0
- package/dist/lib/slurm-detect.js.map +1 -0
- package/dist/lib/slurm-executor.d.ts +70 -0
- package/dist/lib/slurm-executor.d.ts.map +1 -0
- package/dist/lib/slurm-executor.js +402 -0
- package/dist/lib/slurm-executor.js.map +1 -0
- package/dist/lib/slurm-job-monitor.d.ts +52 -0
- package/dist/lib/slurm-job-monitor.d.ts.map +1 -0
- package/dist/lib/slurm-job-monitor.js +212 -0
- package/dist/lib/slurm-job-monitor.js.map +1 -0
- package/dist/lib/ssh-discovery.d.ts +17 -0
- package/dist/lib/ssh-discovery.d.ts.map +1 -0
- package/dist/lib/ssh-discovery.js +287 -0
- package/dist/lib/ssh-discovery.js.map +1 -0
- package/dist/lib/ssh-installer.d.ts +69 -0
- package/dist/lib/ssh-installer.d.ts.map +1 -0
- package/dist/lib/ssh-installer.js +230 -0
- package/dist/lib/ssh-installer.js.map +1 -0
- package/dist/lib/streaming-prompt.d.ts +48 -0
- package/dist/lib/streaming-prompt.d.ts.map +1 -0
- package/dist/lib/streaming-prompt.js +91 -0
- package/dist/lib/streaming-prompt.js.map +1 -0
- package/dist/lib/task-executor.d.ts +114 -0
- package/dist/lib/task-executor.d.ts.map +1 -0
- package/dist/lib/task-executor.js +753 -0
- package/dist/lib/task-executor.js.map +1 -0
- package/dist/lib/websocket-client.d.ts +200 -0
- package/dist/lib/websocket-client.d.ts.map +1 -0
- package/dist/lib/websocket-client.js +781 -0
- package/dist/lib/websocket-client.js.map +1 -0
- package/dist/lib/workdir-safety.d.ts +63 -0
- package/dist/lib/workdir-safety.d.ts.map +1 -0
- package/dist/lib/workdir-safety.js +247 -0
- package/dist/lib/workdir-safety.js.map +1 -0
- package/dist/lib/worktree-include.d.ts +14 -0
- package/dist/lib/worktree-include.d.ts.map +1 -0
- package/dist/lib/worktree-include.js +68 -0
- package/dist/lib/worktree-include.js.map +1 -0
- package/dist/lib/worktree-setup.d.ts +18 -0
- package/dist/lib/worktree-setup.d.ts.map +1 -0
- package/dist/lib/worktree-setup.js +60 -0
- package/dist/lib/worktree-setup.js.map +1 -0
- package/dist/lib/worktree.d.ts +37 -0
- package/dist/lib/worktree.d.ts.map +1 -0
- package/dist/lib/worktree.js +411 -0
- package/dist/lib/worktree.js.map +1 -0
- package/dist/mcp/index.d.ts +8 -0
- package/dist/mcp/index.d.ts.map +1 -0
- package/dist/mcp/index.js +8 -0
- package/dist/mcp/index.js.map +1 -0
- package/dist/mcp/server.d.ts +45 -0
- package/dist/mcp/server.d.ts.map +1 -0
- package/dist/mcp/server.js +153 -0
- package/dist/mcp/server.js.map +1 -0
- package/dist/mcp/session-bridge.d.ts +87 -0
- package/dist/mcp/session-bridge.d.ts.map +1 -0
- package/dist/mcp/session-bridge.js +317 -0
- package/dist/mcp/session-bridge.js.map +1 -0
- package/dist/mcp/tools.d.ts +70 -0
- package/dist/mcp/tools.d.ts.map +1 -0
- package/dist/mcp/tools.js +234 -0
- package/dist/mcp/tools.js.map +1 -0
- package/dist/mcp/types.d.ts +197 -0
- package/dist/mcp/types.d.ts.map +1 -0
- package/dist/mcp/types.js +16 -0
- package/dist/mcp/types.js.map +1 -0
- package/dist/providers/base-adapter.d.ts +56 -0
- package/dist/providers/base-adapter.d.ts.map +1 -0
- package/dist/providers/base-adapter.js +5 -0
- package/dist/providers/base-adapter.js.map +1 -0
- package/dist/providers/claude-code-adapter.d.ts +27 -0
- package/dist/providers/claude-code-adapter.d.ts.map +1 -0
- package/dist/providers/claude-code-adapter.js +298 -0
- package/dist/providers/claude-code-adapter.js.map +1 -0
- package/dist/providers/claude-sdk-adapter.d.ts +60 -0
- package/dist/providers/claude-sdk-adapter.d.ts.map +1 -0
- package/dist/providers/claude-sdk-adapter.js +632 -0
- package/dist/providers/claude-sdk-adapter.js.map +1 -0
- package/dist/providers/codex-adapter.d.ts +21 -0
- package/dist/providers/codex-adapter.d.ts.map +1 -0
- package/dist/providers/codex-adapter.js +197 -0
- package/dist/providers/codex-adapter.js.map +1 -0
- package/dist/providers/index.d.ts +26 -0
- package/dist/providers/index.d.ts.map +1 -0
- package/dist/providers/index.js +58 -0
- package/dist/providers/index.js.map +1 -0
- package/dist/providers/slurm-adapter.d.ts +26 -0
- package/dist/providers/slurm-adapter.d.ts.map +1 -0
- package/dist/providers/slurm-adapter.js +146 -0
- package/dist/providers/slurm-adapter.js.map +1 -0
- package/dist/types.d.ts +592 -0
- package/dist/types.d.ts.map +1 -0
- package/dist/types.js +5 -0
- package/dist/types.js.map +1 -0
- package/package.json +77 -0
|
@@ -0,0 +1,222 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Repo utilities for agent runner.
|
|
3
|
+
*
|
|
4
|
+
* Lightweight versions of the core repo setup logic (isGitRepo, getFileTree,
|
|
5
|
+
* getGitRemoteUrl) that run on remote machines. Skips .gitignore/CLAUDE.md
|
|
6
|
+
* generation since the repo already exists on the remote machine.
|
|
7
|
+
*/
|
|
8
|
+
import { execFileSync, execSync } from 'node:child_process';
|
|
9
|
+
import { existsSync, mkdirSync, readFileSync } from 'node:fs';
|
|
10
|
+
import { homedir } from 'node:os';
|
|
11
|
+
import { join } from 'node:path';
|
|
12
|
+
export function isGitRepo(dir) {
|
|
13
|
+
try {
|
|
14
|
+
execFileSync('git', ['rev-parse', '--show-toplevel'], {
|
|
15
|
+
cwd: dir,
|
|
16
|
+
encoding: 'utf-8',
|
|
17
|
+
timeout: 5_000,
|
|
18
|
+
stdio: 'pipe',
|
|
19
|
+
});
|
|
20
|
+
return true;
|
|
21
|
+
}
|
|
22
|
+
catch {
|
|
23
|
+
return false;
|
|
24
|
+
}
|
|
25
|
+
}
|
|
26
|
+
export function getFileTree(dir) {
|
|
27
|
+
if (!existsSync(dir))
|
|
28
|
+
return [];
|
|
29
|
+
try {
|
|
30
|
+
const output = execFileSync('git', ['ls-files'], {
|
|
31
|
+
cwd: dir,
|
|
32
|
+
encoding: 'utf-8',
|
|
33
|
+
timeout: 10_000,
|
|
34
|
+
maxBuffer: 5 * 1024 * 1024,
|
|
35
|
+
});
|
|
36
|
+
return output.trim().split('\n').filter(Boolean);
|
|
37
|
+
}
|
|
38
|
+
catch {
|
|
39
|
+
return [];
|
|
40
|
+
}
|
|
41
|
+
}
|
|
42
|
+
export function getGitRemoteUrl(dir) {
|
|
43
|
+
try {
|
|
44
|
+
const url = execFileSync('git', ['remote', 'get-url', 'origin'], {
|
|
45
|
+
cwd: dir,
|
|
46
|
+
encoding: 'utf-8',
|
|
47
|
+
timeout: 5_000,
|
|
48
|
+
stdio: 'pipe',
|
|
49
|
+
}).trim();
|
|
50
|
+
return url || undefined;
|
|
51
|
+
}
|
|
52
|
+
catch {
|
|
53
|
+
return undefined;
|
|
54
|
+
}
|
|
55
|
+
}
|
|
56
|
+
const KEY_FILE_CAP = 15_000;
|
|
57
|
+
const PKG_FILE_CAP = 5_000;
|
|
58
|
+
/**
|
|
59
|
+
* Read key files from a directory for plan generation context.
|
|
60
|
+
* Returns capped contents of CLAUDE.md, README.md, and package metadata.
|
|
61
|
+
*/
|
|
62
|
+
function readKeyFiles(dir) {
|
|
63
|
+
const result = {};
|
|
64
|
+
function readCapped(path, cap) {
|
|
65
|
+
if (!existsSync(path))
|
|
66
|
+
return undefined;
|
|
67
|
+
try {
|
|
68
|
+
const content = readFileSync(path, 'utf-8');
|
|
69
|
+
return content.length > cap ? content.slice(0, cap) + '\n\n[... truncated ...]' : content;
|
|
70
|
+
}
|
|
71
|
+
catch {
|
|
72
|
+
return undefined;
|
|
73
|
+
}
|
|
74
|
+
}
|
|
75
|
+
result.claudeMd = readCapped(join(dir, 'CLAUDE.md'), KEY_FILE_CAP);
|
|
76
|
+
result.readmeMd = readCapped(join(dir, 'README.md'), KEY_FILE_CAP) ?? readCapped(join(dir, 'readme.md'), KEY_FILE_CAP);
|
|
77
|
+
const packageFiles = ['package.json', 'pyproject.toml', 'Cargo.toml', 'go.mod'];
|
|
78
|
+
for (const pkg of packageFiles) {
|
|
79
|
+
const content = readCapped(join(dir, pkg), PKG_FILE_CAP);
|
|
80
|
+
if (content) {
|
|
81
|
+
result.packageInfo = `# ${pkg}\n${content}`;
|
|
82
|
+
break;
|
|
83
|
+
}
|
|
84
|
+
}
|
|
85
|
+
return result;
|
|
86
|
+
}
|
|
87
|
+
/**
|
|
88
|
+
* Extract repository name from a git URL.
|
|
89
|
+
* e.g., "git@github.com:user/repo.git" → "repo"
|
|
90
|
+
*/
|
|
91
|
+
function extractRepoName(url) {
|
|
92
|
+
const parts = url.split('/');
|
|
93
|
+
const last = parts[parts.length - 1];
|
|
94
|
+
return last.replace(/\.git$/, '') || 'repo';
|
|
95
|
+
}
|
|
96
|
+
/**
|
|
97
|
+
* Clone a git repository to the specified target directory.
|
|
98
|
+
* If already cloned, fetch latest. Returns the local path.
|
|
99
|
+
*
|
|
100
|
+
* SECURITY: Uses execFileSync with git arguments to prevent command injection
|
|
101
|
+
*/
|
|
102
|
+
function cloneRepository(repoUrl, targetDir) {
|
|
103
|
+
if (existsSync(join(targetDir, '.git'))) {
|
|
104
|
+
// Already cloned — fetch latest
|
|
105
|
+
try {
|
|
106
|
+
execFileSync('git', ['fetch', '--all'], {
|
|
107
|
+
cwd: targetDir,
|
|
108
|
+
stdio: 'ignore',
|
|
109
|
+
timeout: 30_000,
|
|
110
|
+
});
|
|
111
|
+
}
|
|
112
|
+
catch {
|
|
113
|
+
// Non-fatal: proceed with stale clone
|
|
114
|
+
}
|
|
115
|
+
}
|
|
116
|
+
else {
|
|
117
|
+
// Ensure parent directory exists
|
|
118
|
+
mkdirSync(join(targetDir, '..'), { recursive: true });
|
|
119
|
+
// Clone the repo using execFileSync to prevent command injection
|
|
120
|
+
execFileSync('git', ['clone', repoUrl, targetDir], {
|
|
121
|
+
stdio: 'ignore',
|
|
122
|
+
timeout: 120_000,
|
|
123
|
+
});
|
|
124
|
+
}
|
|
125
|
+
return targetDir;
|
|
126
|
+
}
|
|
127
|
+
/**
|
|
128
|
+
* Run repo setup locally on the agent runner's machine.
|
|
129
|
+
* Handles existing directories and cloning repos from URL.
|
|
130
|
+
*/
|
|
131
|
+
export function localRepoSetup(options) {
|
|
132
|
+
const { workingDirectory, repository, projectId } = options;
|
|
133
|
+
// Case 1: No directory and no repository — create a fresh project dir
|
|
134
|
+
if (!workingDirectory && !repository) {
|
|
135
|
+
if (!projectId) {
|
|
136
|
+
return { success: false, error: 'Project ID is required when creating a new directory' };
|
|
137
|
+
}
|
|
138
|
+
try {
|
|
139
|
+
const dir = join(homedir(), '.astro', 'projects', projectId);
|
|
140
|
+
mkdirSync(dir, { recursive: true });
|
|
141
|
+
execSync('git init', { cwd: dir, stdio: 'ignore' });
|
|
142
|
+
execSync('git config user.name "Astro Agent" || true', { cwd: dir, stdio: 'ignore' });
|
|
143
|
+
execSync('git config user.email "agent@astro.local" || true', { cwd: dir, stdio: 'ignore' });
|
|
144
|
+
const fileTree = getFileTree(dir);
|
|
145
|
+
return {
|
|
146
|
+
success: true,
|
|
147
|
+
workingDirectory: dir,
|
|
148
|
+
fileTree,
|
|
149
|
+
};
|
|
150
|
+
}
|
|
151
|
+
catch (error) {
|
|
152
|
+
return { success: false, error: `Failed to create project directory: ${error instanceof Error ? error.message : String(error)}` };
|
|
153
|
+
}
|
|
154
|
+
}
|
|
155
|
+
// If repo URL + working directory, clone into the working directory
|
|
156
|
+
if (repository && workingDirectory) {
|
|
157
|
+
try {
|
|
158
|
+
const repoName = extractRepoName(repository);
|
|
159
|
+
const cloneTarget = join(workingDirectory, repoName);
|
|
160
|
+
const clonedDir = cloneRepository(repository, cloneTarget);
|
|
161
|
+
const fileTree = getFileTree(clonedDir);
|
|
162
|
+
const keyFiles = readKeyFiles(clonedDir);
|
|
163
|
+
return {
|
|
164
|
+
success: true,
|
|
165
|
+
workingDirectory: clonedDir,
|
|
166
|
+
fileTree,
|
|
167
|
+
repository,
|
|
168
|
+
keyFiles,
|
|
169
|
+
};
|
|
170
|
+
}
|
|
171
|
+
catch (error) {
|
|
172
|
+
return { success: false, error: `Failed to clone repository: ${error instanceof Error ? error.message : String(error)}` };
|
|
173
|
+
}
|
|
174
|
+
}
|
|
175
|
+
// If only a repo URL is provided (no working directory) — error
|
|
176
|
+
if (repository && !workingDirectory) {
|
|
177
|
+
return {
|
|
178
|
+
success: false,
|
|
179
|
+
error: 'Working directory required for git URL projects. Specify a local folder where the repository will be cloned.',
|
|
180
|
+
};
|
|
181
|
+
}
|
|
182
|
+
if (workingDirectory) {
|
|
183
|
+
if (!existsSync(workingDirectory)) {
|
|
184
|
+
// Directory doesn't exist — create it (non-git, direct mode)
|
|
185
|
+
try {
|
|
186
|
+
mkdirSync(workingDirectory, { recursive: true });
|
|
187
|
+
}
|
|
188
|
+
catch (mkdirError) {
|
|
189
|
+
return { success: false, error: `Failed to create directory: ${mkdirError instanceof Error ? mkdirError.message : String(mkdirError)}` };
|
|
190
|
+
}
|
|
191
|
+
return {
|
|
192
|
+
success: true,
|
|
193
|
+
workingDirectory,
|
|
194
|
+
fileTree: [],
|
|
195
|
+
needsGitInit: true,
|
|
196
|
+
};
|
|
197
|
+
}
|
|
198
|
+
if (isGitRepo(workingDirectory)) {
|
|
199
|
+
const fileTree = getFileTree(workingDirectory);
|
|
200
|
+
const detectedRepo = getGitRemoteUrl(workingDirectory);
|
|
201
|
+
const keyFiles = readKeyFiles(workingDirectory);
|
|
202
|
+
return {
|
|
203
|
+
success: true,
|
|
204
|
+
workingDirectory,
|
|
205
|
+
fileTree,
|
|
206
|
+
repository: detectedRepo,
|
|
207
|
+
keyFiles,
|
|
208
|
+
};
|
|
209
|
+
}
|
|
210
|
+
// Not a git repo — direct mode (per WORKSPACE_V2)
|
|
211
|
+
const keyFiles = readKeyFiles(workingDirectory);
|
|
212
|
+
return {
|
|
213
|
+
success: true,
|
|
214
|
+
workingDirectory,
|
|
215
|
+
fileTree: [],
|
|
216
|
+
needsGitInit: true,
|
|
217
|
+
keyFiles,
|
|
218
|
+
};
|
|
219
|
+
}
|
|
220
|
+
return { success: false, error: 'Unexpected state' };
|
|
221
|
+
}
|
|
222
|
+
//# sourceMappingURL=repo-utils.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"repo-utils.js","sourceRoot":"","sources":["../../src/lib/repo-utils.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Machine resource detection and reporting
|
|
3
|
+
*/
|
|
4
|
+
import type { MachineResources } from '../types.js';
|
|
5
|
+
/**
|
|
6
|
+
* Get complete machine resource information
|
|
7
|
+
*/
|
|
8
|
+
export declare function getMachineResources(): Promise<MachineResources>;
|
|
9
|
+
/**
|
|
10
|
+
* Format bytes to human-readable string
|
|
11
|
+
*/
|
|
12
|
+
export declare function formatBytes(bytes: number): string;
|
|
13
|
+
/**
|
|
14
|
+
* Format resource summary for display
|
|
15
|
+
*/
|
|
16
|
+
export declare function formatResourceSummary(resources: MachineResources): string;
|
|
17
|
+
//# sourceMappingURL=resources.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"resources.d.ts","sourceRoot":"","sources":["../../src/lib/resources.ts"],"names":[],"mappings":"AAAA;;GAEG;AAKH,OAAO,KAAK,EAAE,gBAAgB,EAAgC,MAAM,aAAa,CAAC;AA2MlF;;GAEG;AACH,wBAAsB,mBAAmB,IAAI,OAAO,CAAC,gBAAgB,CAAC,CAWrE;AAED;;GAEG;AACH,wBAAgB,WAAW,CAAC,KAAK,EAAE,MAAM,GAAG,MAAM,CAWjD;AAED;;GAEG;AACH,wBAAgB,qBAAqB,CAAC,SAAS,EAAE,gBAAgB,GAAG,MAAM,CAiBzE"}
|
|
@@ -0,0 +1,227 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Machine resource detection and reporting
|
|
3
|
+
*/
|
|
4
|
+
import os from 'node:os';
|
|
5
|
+
import { exec } from 'node:child_process';
|
|
6
|
+
import { promisify } from 'node:util';
|
|
7
|
+
const execAsync = promisify(exec);
|
|
8
|
+
/**
|
|
9
|
+
* Get CPU information
|
|
10
|
+
*/
|
|
11
|
+
function getCpuInfo() {
|
|
12
|
+
const cpus = os.cpus();
|
|
13
|
+
const firstCpu = cpus[0];
|
|
14
|
+
const loadAvg = os.loadavg();
|
|
15
|
+
return {
|
|
16
|
+
model: firstCpu?.model ?? 'Unknown',
|
|
17
|
+
cores: cpus.length,
|
|
18
|
+
speed: firstCpu?.speed ?? 0,
|
|
19
|
+
loadAvg,
|
|
20
|
+
};
|
|
21
|
+
}
|
|
22
|
+
/**
|
|
23
|
+
* Get memory information
|
|
24
|
+
*
|
|
25
|
+
* On macOS, os.freemem() only counts truly free pages and ignores
|
|
26
|
+
* inactive/purgeable pages that the OS can reclaim instantly, causing
|
|
27
|
+
* memory to appear ~99% used. We parse vm_stat to get accurate numbers.
|
|
28
|
+
*/
|
|
29
|
+
async function getMemoryInfo() {
|
|
30
|
+
const total = os.totalmem();
|
|
31
|
+
if (process.platform === 'darwin') {
|
|
32
|
+
try {
|
|
33
|
+
const { stdout } = await execAsync('vm_stat', { timeout: 5000 });
|
|
34
|
+
const pageMatch = stdout.match(/page size of (\d+) bytes/);
|
|
35
|
+
const pageSize = pageMatch ? parseInt(pageMatch[1]) : 16384;
|
|
36
|
+
const parse = (label) => {
|
|
37
|
+
const match = stdout.match(new RegExp(`${label}:\\s+(\\d+)`));
|
|
38
|
+
return match ? parseInt(match[1]) * pageSize : 0;
|
|
39
|
+
};
|
|
40
|
+
const free = parse('Pages free');
|
|
41
|
+
const inactive = parse('Pages inactive');
|
|
42
|
+
const purgeable = parse('Pages purgeable');
|
|
43
|
+
// Available = free + inactive + purgeable (all reclaimable by the OS)
|
|
44
|
+
const available = free + inactive + purgeable;
|
|
45
|
+
const used = total - available;
|
|
46
|
+
const usedPercent = (used / total) * 100;
|
|
47
|
+
return { total, free: available, used, usedPercent };
|
|
48
|
+
}
|
|
49
|
+
catch {
|
|
50
|
+
// Fall through to os.freemem()
|
|
51
|
+
}
|
|
52
|
+
}
|
|
53
|
+
const free = os.freemem();
|
|
54
|
+
const used = total - free;
|
|
55
|
+
const usedPercent = (used / total) * 100;
|
|
56
|
+
return { total, free, used, usedPercent };
|
|
57
|
+
}
|
|
58
|
+
/**
|
|
59
|
+
* Parse nvidia-smi output to get GPU information
|
|
60
|
+
*/
|
|
61
|
+
function parseNvidiaSmiOutput(output) {
|
|
62
|
+
const gpus = [];
|
|
63
|
+
const lines = output.trim().split('\n');
|
|
64
|
+
for (const line of lines) {
|
|
65
|
+
const parts = line.split(', ');
|
|
66
|
+
if (parts.length >= 4) {
|
|
67
|
+
const [name, memoryTotal, memoryFree, utilization] = parts;
|
|
68
|
+
gpus.push({
|
|
69
|
+
name: name?.trim() ?? 'Unknown GPU',
|
|
70
|
+
vendor: 'NVIDIA',
|
|
71
|
+
memoryTotal: parseInt(memoryTotal ?? '0', 10) * 1024 * 1024, // MiB to bytes
|
|
72
|
+
memoryFree: parseInt(memoryFree ?? '0', 10) * 1024 * 1024,
|
|
73
|
+
utilization: parseInt(utilization ?? '0', 10),
|
|
74
|
+
});
|
|
75
|
+
}
|
|
76
|
+
}
|
|
77
|
+
return gpus;
|
|
78
|
+
}
|
|
79
|
+
/**
|
|
80
|
+
* Detect NVIDIA GPUs using nvidia-smi
|
|
81
|
+
*/
|
|
82
|
+
async function detectNvidiaGpus() {
|
|
83
|
+
try {
|
|
84
|
+
const { stdout } = await execAsync('nvidia-smi --query-gpu=name,memory.total,memory.free,utilization.gpu --format=csv,noheader,nounits', { timeout: 5000 });
|
|
85
|
+
return parseNvidiaSmiOutput(stdout);
|
|
86
|
+
}
|
|
87
|
+
catch {
|
|
88
|
+
// nvidia-smi not available or failed
|
|
89
|
+
return [];
|
|
90
|
+
}
|
|
91
|
+
}
|
|
92
|
+
/**
|
|
93
|
+
* Detect AMD GPUs using rocm-smi
|
|
94
|
+
*/
|
|
95
|
+
async function detectAmdGpus() {
|
|
96
|
+
try {
|
|
97
|
+
const { stdout } = await execAsync('rocm-smi --showproductname --showmeminfo vram --showuse', {
|
|
98
|
+
timeout: 5000,
|
|
99
|
+
});
|
|
100
|
+
// Parse rocm-smi output (format varies by version)
|
|
101
|
+
const gpus = [];
|
|
102
|
+
const lines = stdout.split('\n');
|
|
103
|
+
let currentGpu = { vendor: 'AMD' };
|
|
104
|
+
for (const line of lines) {
|
|
105
|
+
if (line.includes('GPU[')) {
|
|
106
|
+
if (currentGpu.name) {
|
|
107
|
+
gpus.push(currentGpu);
|
|
108
|
+
}
|
|
109
|
+
currentGpu = { vendor: 'AMD', memoryTotal: 0, memoryFree: 0, utilization: 0 };
|
|
110
|
+
}
|
|
111
|
+
if (line.includes('Card series:')) {
|
|
112
|
+
currentGpu.name = line.split(':')[1]?.trim() ?? 'AMD GPU';
|
|
113
|
+
}
|
|
114
|
+
if (line.includes('Total Memory')) {
|
|
115
|
+
const match = line.match(/(\d+)/);
|
|
116
|
+
if (match) {
|
|
117
|
+
currentGpu.memoryTotal = parseInt(match[1], 10) * 1024 * 1024;
|
|
118
|
+
}
|
|
119
|
+
}
|
|
120
|
+
if (line.includes('GPU use')) {
|
|
121
|
+
const match = line.match(/(\d+)/);
|
|
122
|
+
if (match) {
|
|
123
|
+
currentGpu.utilization = parseInt(match[1], 10);
|
|
124
|
+
}
|
|
125
|
+
}
|
|
126
|
+
}
|
|
127
|
+
if (currentGpu.name) {
|
|
128
|
+
gpus.push(currentGpu);
|
|
129
|
+
}
|
|
130
|
+
return gpus;
|
|
131
|
+
}
|
|
132
|
+
catch {
|
|
133
|
+
// rocm-smi not available or failed
|
|
134
|
+
return [];
|
|
135
|
+
}
|
|
136
|
+
}
|
|
137
|
+
/**
|
|
138
|
+
* Detect Apple Silicon GPUs (macOS only)
|
|
139
|
+
*/
|
|
140
|
+
async function detectAppleGpus() {
|
|
141
|
+
if (os.platform() !== 'darwin') {
|
|
142
|
+
return [];
|
|
143
|
+
}
|
|
144
|
+
try {
|
|
145
|
+
const { stdout } = await execAsync('system_profiler SPDisplaysDataType -json', {
|
|
146
|
+
timeout: 5000,
|
|
147
|
+
});
|
|
148
|
+
const data = JSON.parse(stdout);
|
|
149
|
+
const displays = data?.SPDisplaysDataType ?? [];
|
|
150
|
+
const gpus = [];
|
|
151
|
+
for (const display of displays) {
|
|
152
|
+
const gpuName = display.sppci_model ?? display._name ?? 'Apple GPU';
|
|
153
|
+
const vramMatch = display.spdisplays_vram?.match(/(\d+)/);
|
|
154
|
+
const vramMB = vramMatch ? parseInt(vramMatch[1], 10) : 0;
|
|
155
|
+
gpus.push({
|
|
156
|
+
name: gpuName,
|
|
157
|
+
vendor: 'Apple',
|
|
158
|
+
memoryTotal: vramMB * 1024 * 1024,
|
|
159
|
+
memoryFree: 0, // Not available on macOS
|
|
160
|
+
utilization: 0, // Not easily available
|
|
161
|
+
});
|
|
162
|
+
}
|
|
163
|
+
return gpus;
|
|
164
|
+
}
|
|
165
|
+
catch {
|
|
166
|
+
return [];
|
|
167
|
+
}
|
|
168
|
+
}
|
|
169
|
+
/**
|
|
170
|
+
* Detect all GPUs on the system
|
|
171
|
+
*/
|
|
172
|
+
async function getGpuInfo() {
|
|
173
|
+
// Try all GPU detection methods in parallel
|
|
174
|
+
const [nvidiaGpus, amdGpus, appleGpus] = await Promise.all([
|
|
175
|
+
detectNvidiaGpus(),
|
|
176
|
+
detectAmdGpus(),
|
|
177
|
+
detectAppleGpus(),
|
|
178
|
+
]);
|
|
179
|
+
return [...nvidiaGpus, ...amdGpus, ...appleGpus];
|
|
180
|
+
}
|
|
181
|
+
/**
|
|
182
|
+
* Get complete machine resource information
|
|
183
|
+
*/
|
|
184
|
+
export async function getMachineResources() {
|
|
185
|
+
const [gpu, memory] = await Promise.all([getGpuInfo(), getMemoryInfo()]);
|
|
186
|
+
return {
|
|
187
|
+
hostname: os.hostname(),
|
|
188
|
+
platform: os.platform(),
|
|
189
|
+
arch: os.arch(),
|
|
190
|
+
cpu: getCpuInfo(),
|
|
191
|
+
memory,
|
|
192
|
+
gpu,
|
|
193
|
+
};
|
|
194
|
+
}
|
|
195
|
+
/**
|
|
196
|
+
* Format bytes to human-readable string
|
|
197
|
+
*/
|
|
198
|
+
export function formatBytes(bytes) {
|
|
199
|
+
const units = ['B', 'KB', 'MB', 'GB', 'TB'];
|
|
200
|
+
let unitIndex = 0;
|
|
201
|
+
let size = bytes;
|
|
202
|
+
while (size >= 1024 && unitIndex < units.length - 1) {
|
|
203
|
+
size /= 1024;
|
|
204
|
+
unitIndex++;
|
|
205
|
+
}
|
|
206
|
+
return `${size.toFixed(1)} ${units[unitIndex]}`;
|
|
207
|
+
}
|
|
208
|
+
/**
|
|
209
|
+
* Format resource summary for display
|
|
210
|
+
*/
|
|
211
|
+
export function formatResourceSummary(resources) {
|
|
212
|
+
const lines = [];
|
|
213
|
+
lines.push(`Host: ${resources.hostname} (${resources.platform}/${resources.arch})`);
|
|
214
|
+
lines.push(`CPU: ${resources.cpu.model} (${resources.cpu.cores} cores @ ${resources.cpu.speed}MHz)`);
|
|
215
|
+
lines.push(`Memory: ${formatBytes(resources.memory.used)} / ${formatBytes(resources.memory.total)} (${resources.memory.usedPercent.toFixed(1)}% used)`);
|
|
216
|
+
if (resources.gpu.length > 0) {
|
|
217
|
+
for (const gpu of resources.gpu) {
|
|
218
|
+
const memUsed = gpu.memoryTotal - gpu.memoryFree;
|
|
219
|
+
lines.push(`GPU: ${gpu.name} - ${formatBytes(memUsed)} / ${formatBytes(gpu.memoryTotal)} (${gpu.utilization}% util)`);
|
|
220
|
+
}
|
|
221
|
+
}
|
|
222
|
+
else {
|
|
223
|
+
lines.push('GPU: None detected');
|
|
224
|
+
}
|
|
225
|
+
return lines.join('\n');
|
|
226
|
+
}
|
|
227
|
+
//# sourceMappingURL=resources.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"resources.js","sourceRoot":"","sources":["../../src/lib/resources.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,OAAO,EAAE,MAAM,SAAS,CAAC;AACzB,OAAO,EAAE,IAAI,EAAE,MAAM,oBAAoB,CAAC;AAC1C,OAAO,EAAE,SAAS,EAAE,MAAM,WAAW,CAAC;AAGtC,MAAM,SAAS,GAAG,SAAS,CAAC,IAAI,CAAC,CAAC;AAElC;;GAEG;AACH,SAAS,UAAU;IACjB,MAAM,IAAI,GAAG,EAAE,CAAC,IAAI,EAAE,CAAC;IACvB,MAAM,QAAQ,GAAG,IAAI,CAAC,CAAC,CAAC,CAAC;IACzB,MAAM,OAAO,GAAG,EAAE,CAAC,OAAO,EAAE,CAAC;IAE7B,OAAO;QACL,KAAK,EAAE,QAAQ,EAAE,KAAK,IAAI,SAAS;QACnC,KAAK,EAAE,IAAI,CAAC,MAAM;QAClB,KAAK,EAAE,QAAQ,EAAE,KAAK,IAAI,CAAC;QAC3B,OAAO;KACR,CAAC;AACJ,CAAC;AAED;;;;;;GAMG;AACH,KAAK,UAAU,aAAa;IAC1B,MAAM,KAAK,GAAG,EAAE,CAAC,QAAQ,EAAE,CAAC;IAE5B,IAAI,OAAO,CAAC,QAAQ,KAAK,QAAQ,EAAE,CAAC;QAClC,IAAI,CAAC;YACH,MAAM,EAAE,MAAM,EAAE,GAAG,MAAM,SAAS,CAAC,SAAS,EAAE,EAAE,OAAO,EAAE,IAAI,EAAE,CAAC,CAAC;YACjE,MAAM,SAAS,GAAG,MAAM,CAAC,KAAK,CAAC,0BAA0B,CAAC,CAAC;YAC3D,MAAM,QAAQ,GAAG,SAAS,CAAC,CAAC,CAAC,QAAQ,CAAC,SAAS,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,KAAK,CAAC;YAE5D,MAAM,KAAK,GAAG,CAAC,KAAa,EAAU,EAAE;gBACtC,MAAM,KAAK,GAAG,MAAM,CAAC,KAAK,CAAC,IAAI,MAAM,CAAC,GAAG,KAAK,aAAa,CAAC,CAAC,CAAC;gBAC9D,OAAO,KAAK,CAAC,CAAC,CAAC,QAAQ,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,GAAG,QAAQ,CAAC,CAAC,CAAC,CAAC,CAAC;YACnD,CAAC,CAAC;YAEF,MAAM,IAAI,GAAG,KAAK,CAAC,YAAY,CAAC,CAAC;YACjC,MAAM,QAAQ,GAAG,KAAK,CAAC,gBAAgB,CAAC,CAAC;YACzC,MAAM,SAAS,GAAG,KAAK,CAAC,iBAAiB,CAAC,CAAC;YAE3C,sEAAsE;YACtE,MAAM,SAAS,GAAG,IAAI,GAAG,QAAQ,GAAG,SAAS,CAAC;YAC9C,MAAM,IAAI,GAAG,KAAK,GAAG,SAAS,CAAC;YAC/B,MAAM,WAAW,GAAG,CAAC,IAAI,GAAG,KAAK,CAAC,GAAG,GAAG,CAAC;YAEzC,OAAO,EAAE,KAAK,EAAE,IAAI,EAAE,SAAS,EAAE,IAAI,EAAE,WAAW,EAAE,CAAC;QACvD,CAAC;QAAC,MAAM,CAAC;YACP,+BAA+B;QACjC,CAAC;IACH,CAAC;IAED,MAAM,IAAI,GAAG,EAAE,CAAC,OAAO,EAAE,CAAC;IAC1B,MAAM,IAAI,GAAG,KAAK,GAAG,IAAI,CAAC;IAC1B,MAAM,WAAW,GAAG,CAAC,IAAI,GAAG,KAAK,CAAC,GAAG,GAAG,CAAC;IAEzC,OAAO,EAAE,KAAK,EAAE,IAAI,EAAE,IAAI,EAAE,WAAW,EAAE,CAAC;AAC5C,CAAC;AAED;;GAEG;AACH,SAAS,oBAAoB,CAAC,MAAc;IAC1C,MAAM,IAAI,GAAc,EAAE,CAAC;IAC3B,MAAM,KAAK,GAAG,MAAM,CAAC,IAAI,EAAE,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC;IAExC,KAAK,MAAM,IAAI,IAAI,KAAK,EAAE,CAAC;QACzB,MAAM,KAAK,GAAG,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC;QAC/B,IAAI,KAAK,CAAC,MAAM,IAAI,CAAC,EAAE,CAAC;YACtB,MAAM,CAAC,IAAI,EAAE,WAAW,EAAE,UAAU,EAAE,WAAW,CAAC,GAAG,KAAK,CAAC;YAC3D,IAAI,CAAC,IAAI,CAAC;gBACR,IAAI,EAAE,IAAI,EAAE,IAAI,EAAE,IAAI,aAAa;gBACnC,MAAM,EAAE,QAAQ;gBAChB,WAAW,EAAE,QAAQ,CAAC,WAAW,IAAI,GAAG,EAAE,EAAE,CAAC,GAAG,IAAI,GAAG,IAAI,EAAE,eAAe;gBAC5E,UAAU,EAAE,QAAQ,CAAC,UAAU,IAAI,GAAG,EAAE,EAAE,CAAC,GAAG,IAAI,GAAG,IAAI;gBACzD,WAAW,EAAE,QAAQ,CAAC,WAAW,IAAI,GAAG,EAAE,EAAE,CAAC;aAC9C,CAAC,CAAC;QACL,CAAC;IACH,CAAC;IAED,OAAO,IAAI,CAAC;AACd,CAAC;AAED;;GAEG;AACH,KAAK,UAAU,gBAAgB;IAC7B,IAAI,CAAC;QACH,MAAM,EAAE,MAAM,EAAE,GAAG,MAAM,SAAS,CAChC,oGAAoG,EACpG,EAAE,OAAO,EAAE,IAAI,EAAE,CAClB,CAAC;QACF,OAAO,oBAAoB,CAAC,MAAM,CAAC,CAAC;IACtC,CAAC;IAAC,MAAM,CAAC;QACP,qCAAqC;QACrC,OAAO,EAAE,CAAC;IACZ,CAAC;AACH,CAAC;AAED;;GAEG;AACH,KAAK,UAAU,aAAa;IAC1B,IAAI,CAAC;QACH,MAAM,EAAE,MAAM,EAAE,GAAG,MAAM,SAAS,CAAC,yDAAyD,EAAE;YAC5F,OAAO,EAAE,IAAI;SACd,CAAC,CAAC;QAEH,mDAAmD;QACnD,MAAM,IAAI,GAAc,EAAE,CAAC;QAC3B,MAAM,KAAK,GAAG,MAAM,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC;QACjC,IAAI,UAAU,GAAqB,EAAE,MAAM,EAAE,KAAK,EAAE,CAAC;QAErD,KAAK,MAAM,IAAI,IAAI,KAAK,EAAE,CAAC;YACzB,IAAI,IAAI,CAAC,QAAQ,CAAC,MAAM,CAAC,EAAE,CAAC;gBAC1B,IAAI,UAAU,CAAC,IAAI,EAAE,CAAC;oBACpB,IAAI,CAAC,IAAI,CAAC,UAAqB,CAAC,CAAC;gBACnC,CAAC;gBACD,UAAU,GAAG,EAAE,MAAM,EAAE,KAAK,EAAE,WAAW,EAAE,CAAC,EAAE,UAAU,EAAE,CAAC,EAAE,WAAW,EAAE,CAAC,EAAE,CAAC;YAChF,CAAC;YACD,IAAI,IAAI,CAAC,QAAQ,CAAC,cAAc,CAAC,EAAE,CAAC;gBAClC,UAAU,CAAC,IAAI,GAAG,IAAI,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,EAAE,IAAI,EAAE,IAAI,SAAS,CAAC;YAC5D,CAAC;YACD,IAAI,IAAI,CAAC,QAAQ,CAAC,cAAc,CAAC,EAAE,CAAC;gBAClC,MAAM,KAAK,GAAG,IAAI,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC;gBAClC,IAAI,KAAK,EAAE,CAAC;oBACV,UAAU,CAAC,WAAW,GAAG,QAAQ,CAAC,KAAK,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,GAAG,IAAI,GAAG,IAAI,CAAC;gBAChE,CAAC;YACH,CAAC;YACD,IAAI,IAAI,CAAC,QAAQ,CAAC,SAAS,CAAC,EAAE,CAAC;gBAC7B,MAAM,KAAK,GAAG,IAAI,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC;gBAClC,IAAI,KAAK,EAAE,CAAC;oBACV,UAAU,CAAC,WAAW,GAAG,QAAQ,CAAC,KAAK,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC;gBAClD,CAAC;YACH,CAAC;QACH,CAAC;QAED,IAAI,UAAU,CAAC,IAAI,EAAE,CAAC;YACpB,IAAI,CAAC,IAAI,CAAC,UAAqB,CAAC,CAAC;QACnC,CAAC;QAED,OAAO,IAAI,CAAC;IACd,CAAC;IAAC,MAAM,CAAC;QACP,mCAAmC;QACnC,OAAO,EAAE,CAAC;IACZ,CAAC;AACH,CAAC;AAED;;GAEG;AACH,KAAK,UAAU,eAAe;IAC5B,IAAI,EAAE,CAAC,QAAQ,EAAE,KAAK,QAAQ,EAAE,CAAC;QAC/B,OAAO,EAAE,CAAC;IACZ,CAAC;IAED,IAAI,CAAC;QACH,MAAM,EAAE,MAAM,EAAE,GAAG,MAAM,SAAS,CAAC,0CAA0C,EAAE;YAC7E,OAAO,EAAE,IAAI;SACd,CAAC,CAAC;QAEH,MAAM,IAAI,GAAG,IAAI,CAAC,KAAK,CAAC,MAAM,CAAC,CAAC;QAChC,MAAM,QAAQ,GAAG,IAAI,EAAE,kBAAkB,IAAI,EAAE,CAAC;QAChD,MAAM,IAAI,GAAc,EAAE,CAAC;QAE3B,KAAK,MAAM,OAAO,IAAI,QAAQ,EAAE,CAAC;YAC/B,MAAM,OAAO,GAAG,OAAO,CAAC,WAAW,IAAI,OAAO,CAAC,KAAK,IAAI,WAAW,CAAC;YACpE,MAAM,SAAS,GAAG,OAAO,CAAC,eAAe,EAAE,KAAK,CAAC,OAAO,CAAC,CAAC;YAC1D,MAAM,MAAM,GAAG,SAAS,CAAC,CAAC,CAAC,QAAQ,CAAC,SAAS,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC;YAE1D,IAAI,CAAC,IAAI,CAAC;gBACR,IAAI,EAAE,OAAO;gBACb,MAAM,EAAE,OAAO;gBACf,WAAW,EAAE,MAAM,GAAG,IAAI,GAAG,IAAI;gBACjC,UAAU,EAAE,CAAC,EAAE,yBAAyB;gBACxC,WAAW,EAAE,CAAC,EAAE,uBAAuB;aACxC,CAAC,CAAC;QACL,CAAC;QAED,OAAO,IAAI,CAAC;IACd,CAAC;IAAC,MAAM,CAAC;QACP,OAAO,EAAE,CAAC;IACZ,CAAC;AACH,CAAC;AAED;;GAEG;AACH,KAAK,UAAU,UAAU;IACvB,4CAA4C;IAC5C,MAAM,CAAC,UAAU,EAAE,OAAO,EAAE,SAAS,CAAC,GAAG,MAAM,OAAO,CAAC,GAAG,CAAC;QACzD,gBAAgB,EAAE;QAClB,aAAa,EAAE;QACf,eAAe,EAAE;KAClB,CAAC,CAAC;IAEH,OAAO,CAAC,GAAG,UAAU,EAAE,GAAG,OAAO,EAAE,GAAG,SAAS,CAAC,CAAC;AACnD,CAAC;AAED;;GAEG;AACH,MAAM,CAAC,KAAK,UAAU,mBAAmB;IACvC,MAAM,CAAC,GAAG,EAAE,MAAM,CAAC,GAAG,MAAM,OAAO,CAAC,GAAG,CAAC,CAAC,UAAU,EAAE,EAAE,aAAa,EAAE,CAAC,CAAC,CAAC;IAEzE,OAAO;QACL,QAAQ,EAAE,EAAE,CAAC,QAAQ,EAAE;QACvB,QAAQ,EAAE,EAAE,CAAC,QAAQ,EAAE;QACvB,IAAI,EAAE,EAAE,CAAC,IAAI,EAAE;QACf,GAAG,EAAE,UAAU,EAAE;QACjB,MAAM;QACN,GAAG;KACJ,CAAC;AACJ,CAAC;AAED;;GAEG;AACH,MAAM,UAAU,WAAW,CAAC,KAAa;IACvC,MAAM,KAAK,GAAG,CAAC,GAAG,EAAE,IAAI,EAAE,IAAI,EAAE,IAAI,EAAE,IAAI,CAAC,CAAC;IAC5C,IAAI,SAAS,GAAG,CAAC,CAAC;IAClB,IAAI,IAAI,GAAG,KAAK,CAAC;IAEjB,OAAO,IAAI,IAAI,IAAI,IAAI,SAAS,GAAG,KAAK,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;QACpD,IAAI,IAAI,IAAI,CAAC;QACb,SAAS,EAAE,CAAC;IACd,CAAC;IAED,OAAO,GAAG,IAAI,CAAC,OAAO,CAAC,CAAC,CAAC,IAAI,KAAK,CAAC,SAAS,CAAC,EAAE,CAAC;AAClD,CAAC;AAED;;GAEG;AACH,MAAM,UAAU,qBAAqB,CAAC,SAA2B;IAC/D,MAAM,KAAK,GAAa,EAAE,CAAC;IAE3B,KAAK,CAAC,IAAI,CAAC,SAAS,SAAS,CAAC,QAAQ,KAAK,SAAS,CAAC,QAAQ,IAAI,SAAS,CAAC,IAAI,GAAG,CAAC,CAAC;IACpF,KAAK,CAAC,IAAI,CAAC,QAAQ,SAAS,CAAC,GAAG,CAAC,KAAK,KAAK,SAAS,CAAC,GAAG,CAAC,KAAK,YAAY,SAAS,CAAC,GAAG,CAAC,KAAK,MAAM,CAAC,CAAC;IACrG,KAAK,CAAC,IAAI,CAAC,WAAW,WAAW,CAAC,SAAS,CAAC,MAAM,CAAC,IAAI,CAAC,MAAM,WAAW,CAAC,SAAS,CAAC,MAAM,CAAC,KAAK,CAAC,KAAK,SAAS,CAAC,MAAM,CAAC,WAAW,CAAC,OAAO,CAAC,CAAC,CAAC,SAAS,CAAC,CAAC;IAExJ,IAAI,SAAS,CAAC,GAAG,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;QAC7B,KAAK,MAAM,GAAG,IAAI,SAAS,CAAC,GAAG,EAAE,CAAC;YAChC,MAAM,OAAO,GAAG,GAAG,CAAC,WAAW,GAAG,GAAG,CAAC,UAAU,CAAC;YACjD,KAAK,CAAC,IAAI,CAAC,QAAQ,GAAG,CAAC,IAAI,MAAM,WAAW,CAAC,OAAO,CAAC,MAAM,WAAW,CAAC,GAAG,CAAC,WAAW,CAAC,KAAK,GAAG,CAAC,WAAW,SAAS,CAAC,CAAC;QACxH,CAAC;IACH,CAAC;SAAM,CAAC;QACN,KAAK,CAAC,IAAI,CAAC,oBAAoB,CAAC,CAAC;IACnC,CAAC;IAED,OAAO,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;AAC1B,CAAC"}
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Slurm Detection
|
|
3
|
+
*
|
|
4
|
+
* Detects Slurm installation and gathers cluster information.
|
|
5
|
+
*/
|
|
6
|
+
import type { SlurmInfo, SlurmPartitionDetail } from '../types.js';
|
|
7
|
+
/**
|
|
8
|
+
* Detect Slurm and gather cluster information
|
|
9
|
+
*/
|
|
10
|
+
export declare function detectSlurm(): Promise<SlurmInfo>;
|
|
11
|
+
/**
|
|
12
|
+
* Get detailed partition info
|
|
13
|
+
*/
|
|
14
|
+
export declare function getPartitionInfo(): Promise<SlurmPartitionDetail[]>;
|
|
15
|
+
//# sourceMappingURL=slurm-detect.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"slurm-detect.d.ts","sourceRoot":"","sources":["../../src/lib/slurm-detect.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAIH,OAAO,KAAK,EAAE,SAAS,EAAE,oBAAoB,EAAE,MAAM,aAAa,CAAC;AAInE;;GAEG;AACH,wBAAsB,WAAW,IAAI,OAAO,CAAC,SAAS,CAAC,CAuGtD;AAED;;GAEG;AACH,wBAAsB,gBAAgB,IAAI,OAAO,CAAC,oBAAoB,EAAE,CAAC,CA0CxE"}
|
|
@@ -0,0 +1,148 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Slurm Detection
|
|
3
|
+
*
|
|
4
|
+
* Detects Slurm installation and gathers cluster information.
|
|
5
|
+
*/
|
|
6
|
+
import { execFile } from 'node:child_process';
|
|
7
|
+
import { promisify } from 'node:util';
|
|
8
|
+
const execFileAsync = promisify(execFile);
|
|
9
|
+
/**
|
|
10
|
+
* Detect Slurm and gather cluster information
|
|
11
|
+
*/
|
|
12
|
+
export async function detectSlurm() {
|
|
13
|
+
const info = {
|
|
14
|
+
available: false,
|
|
15
|
+
partitions: [],
|
|
16
|
+
accounts: [],
|
|
17
|
+
qosLevels: [],
|
|
18
|
+
};
|
|
19
|
+
// Check if sinfo is available
|
|
20
|
+
try {
|
|
21
|
+
await execFileAsync('which', ['sinfo'], { timeout: 5000 });
|
|
22
|
+
info.available = true;
|
|
23
|
+
}
|
|
24
|
+
catch {
|
|
25
|
+
return info;
|
|
26
|
+
}
|
|
27
|
+
// Get Slurm version
|
|
28
|
+
try {
|
|
29
|
+
const { stdout } = await execFileAsync('sinfo', ['--version'], { timeout: 5000 });
|
|
30
|
+
const match = stdout.match(/slurm\s+(\d+\.\d+\.\d+)/);
|
|
31
|
+
if (match) {
|
|
32
|
+
info.version = match[1];
|
|
33
|
+
}
|
|
34
|
+
}
|
|
35
|
+
catch {
|
|
36
|
+
// Version detection failed
|
|
37
|
+
}
|
|
38
|
+
// Get cluster name
|
|
39
|
+
try {
|
|
40
|
+
const { stdout: rawConfig } = await execFileAsync('scontrol', ['show', 'config'], { timeout: 10000 });
|
|
41
|
+
const stdout = rawConfig.split('\n').filter(l => l.includes('ClusterName')).join('\n');
|
|
42
|
+
const match = stdout.match(/ClusterName\s*=\s*(\S+)/);
|
|
43
|
+
if (match) {
|
|
44
|
+
info.clusterName = match[1];
|
|
45
|
+
}
|
|
46
|
+
}
|
|
47
|
+
catch {
|
|
48
|
+
// Cluster name detection failed
|
|
49
|
+
}
|
|
50
|
+
// Get partitions
|
|
51
|
+
try {
|
|
52
|
+
const { stdout } = await execFileAsync('sinfo', ['-h', '-o', '%P'], { timeout: 10000 });
|
|
53
|
+
info.partitions = stdout
|
|
54
|
+
.split('\n')
|
|
55
|
+
.map((line) => line.trim())
|
|
56
|
+
.filter((line) => line.length > 0)
|
|
57
|
+
.map((name) => {
|
|
58
|
+
const isDefault = name.endsWith('*');
|
|
59
|
+
const partitionName = name.replace('*', '');
|
|
60
|
+
if (isDefault) {
|
|
61
|
+
info.defaultPartition = partitionName;
|
|
62
|
+
}
|
|
63
|
+
return partitionName;
|
|
64
|
+
});
|
|
65
|
+
}
|
|
66
|
+
catch {
|
|
67
|
+
// Partition detection failed
|
|
68
|
+
}
|
|
69
|
+
// Get user accounts
|
|
70
|
+
try {
|
|
71
|
+
const username = process.env.USER || process.env.LOGNAME;
|
|
72
|
+
if (username && /^[a-zA-Z0-9._-]+$/.test(username)) {
|
|
73
|
+
const { stdout } = await execFileAsync('sacctmgr', ['-p', 'show', 'assoc', `user=${username}`, 'format=Account', '--noheader'], { timeout: 10000 });
|
|
74
|
+
info.accounts = [
|
|
75
|
+
...new Set(stdout
|
|
76
|
+
.split('\n')
|
|
77
|
+
.map((line) => line.split('|')[0]?.trim())
|
|
78
|
+
.filter((a) => !!a && a.length > 0)),
|
|
79
|
+
];
|
|
80
|
+
}
|
|
81
|
+
}
|
|
82
|
+
catch {
|
|
83
|
+
// Account detection failed
|
|
84
|
+
}
|
|
85
|
+
// Get QOS levels
|
|
86
|
+
try {
|
|
87
|
+
const username = process.env.USER || process.env.LOGNAME;
|
|
88
|
+
if (username && /^[a-zA-Z0-9._-]+$/.test(username)) {
|
|
89
|
+
const { stdout } = await execFileAsync('sacctmgr', ['-p', 'show', 'assoc', `user=${username}`, 'format=QOS', '--noheader'], { timeout: 10000 });
|
|
90
|
+
const qosSet = new Set();
|
|
91
|
+
stdout.split('\n').forEach((line) => {
|
|
92
|
+
const qos = line.split('|')[0]?.trim();
|
|
93
|
+
if (qos) {
|
|
94
|
+
qos.split(',').forEach((q) => {
|
|
95
|
+
if (q.trim())
|
|
96
|
+
qosSet.add(q.trim());
|
|
97
|
+
});
|
|
98
|
+
}
|
|
99
|
+
});
|
|
100
|
+
info.qosLevels = [...qosSet];
|
|
101
|
+
}
|
|
102
|
+
}
|
|
103
|
+
catch {
|
|
104
|
+
// QOS detection failed
|
|
105
|
+
}
|
|
106
|
+
return info;
|
|
107
|
+
}
|
|
108
|
+
/**
|
|
109
|
+
* Get detailed partition info
|
|
110
|
+
*/
|
|
111
|
+
export async function getPartitionInfo() {
|
|
112
|
+
try {
|
|
113
|
+
const { stdout } = await execFileAsync('sinfo', ['-h', '-o', '%P|%a|%l|%D|%T|%f'], { timeout: 10000 });
|
|
114
|
+
const partitionMap = new Map();
|
|
115
|
+
stdout.split('\n').forEach((line) => {
|
|
116
|
+
const parts = line.split('|');
|
|
117
|
+
if (parts.length < 6)
|
|
118
|
+
return;
|
|
119
|
+
const [partitionRaw, , maxTime, nodesCount, nodeState, features] = parts;
|
|
120
|
+
const isDefault = partitionRaw?.endsWith('*') || false;
|
|
121
|
+
const name = partitionRaw?.replace('*', '') || '';
|
|
122
|
+
if (!name)
|
|
123
|
+
return;
|
|
124
|
+
let partition = partitionMap.get(name);
|
|
125
|
+
if (!partition) {
|
|
126
|
+
partition = {
|
|
127
|
+
name,
|
|
128
|
+
isDefault,
|
|
129
|
+
totalNodes: 0,
|
|
130
|
+
availableNodes: 0,
|
|
131
|
+
maxTime: maxTime !== '(null)' ? maxTime : undefined,
|
|
132
|
+
features: features !== '(null)' ? features?.split(',') || [] : [],
|
|
133
|
+
};
|
|
134
|
+
partitionMap.set(name, partition);
|
|
135
|
+
}
|
|
136
|
+
const count = parseInt(nodesCount || '0') || 0;
|
|
137
|
+
partition.totalNodes += count;
|
|
138
|
+
if (nodeState === 'idle' || nodeState === 'mixed') {
|
|
139
|
+
partition.availableNodes += count;
|
|
140
|
+
}
|
|
141
|
+
});
|
|
142
|
+
return Array.from(partitionMap.values());
|
|
143
|
+
}
|
|
144
|
+
catch {
|
|
145
|
+
return [];
|
|
146
|
+
}
|
|
147
|
+
}
|
|
148
|
+
//# sourceMappingURL=slurm-detect.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"slurm-detect.js","sourceRoot":"","sources":["../../src/lib/slurm-detect.ts"],"names":[],"mappings":"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"}
|