@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.
Files changed (203) hide show
  1. package/LICENSE +76 -0
  2. package/README.md +178 -0
  3. package/dist/cli.d.ts +15 -0
  4. package/dist/cli.d.ts.map +1 -0
  5. package/dist/cli.js +401 -0
  6. package/dist/cli.js.map +1 -0
  7. package/dist/commands/index.d.ts +9 -0
  8. package/dist/commands/index.d.ts.map +1 -0
  9. package/dist/commands/index.js +9 -0
  10. package/dist/commands/index.js.map +1 -0
  11. package/dist/commands/mcp.d.ts +16 -0
  12. package/dist/commands/mcp.d.ts.map +1 -0
  13. package/dist/commands/mcp.js +19 -0
  14. package/dist/commands/mcp.js.map +1 -0
  15. package/dist/commands/setup.d.ts +20 -0
  16. package/dist/commands/setup.d.ts.map +1 -0
  17. package/dist/commands/setup.js +585 -0
  18. package/dist/commands/setup.js.map +1 -0
  19. package/dist/commands/start.d.ts +16 -0
  20. package/dist/commands/start.d.ts.map +1 -0
  21. package/dist/commands/start.js +638 -0
  22. package/dist/commands/start.js.map +1 -0
  23. package/dist/commands/status.d.ts +5 -0
  24. package/dist/commands/status.d.ts.map +1 -0
  25. package/dist/commands/status.js +63 -0
  26. package/dist/commands/status.js.map +1 -0
  27. package/dist/commands/stop.d.ts +5 -0
  28. package/dist/commands/stop.d.ts.map +1 -0
  29. package/dist/commands/stop.js +85 -0
  30. package/dist/commands/stop.js.map +1 -0
  31. package/dist/execution/direct-strategy.d.ts +18 -0
  32. package/dist/execution/direct-strategy.d.ts.map +1 -0
  33. package/dist/execution/direct-strategy.js +156 -0
  34. package/dist/execution/direct-strategy.js.map +1 -0
  35. package/dist/execution/docker-strategy.d.ts +26 -0
  36. package/dist/execution/docker-strategy.d.ts.map +1 -0
  37. package/dist/execution/docker-strategy.js +222 -0
  38. package/dist/execution/docker-strategy.js.map +1 -0
  39. package/dist/execution/index.d.ts +14 -0
  40. package/dist/execution/index.d.ts.map +1 -0
  41. package/dist/execution/index.js +13 -0
  42. package/dist/execution/index.js.map +1 -0
  43. package/dist/execution/kubernetes-exec-strategy.d.ts +23 -0
  44. package/dist/execution/kubernetes-exec-strategy.d.ts.map +1 -0
  45. package/dist/execution/kubernetes-exec-strategy.js +232 -0
  46. package/dist/execution/kubernetes-exec-strategy.js.map +1 -0
  47. package/dist/execution/registry.d.ts +41 -0
  48. package/dist/execution/registry.d.ts.map +1 -0
  49. package/dist/execution/registry.js +84 -0
  50. package/dist/execution/registry.js.map +1 -0
  51. package/dist/execution/slurm-strategy.d.ts +22 -0
  52. package/dist/execution/slurm-strategy.d.ts.map +1 -0
  53. package/dist/execution/slurm-strategy.js +219 -0
  54. package/dist/execution/slurm-strategy.js.map +1 -0
  55. package/dist/execution/types.d.ts +72 -0
  56. package/dist/execution/types.d.ts.map +1 -0
  57. package/dist/execution/types.js +10 -0
  58. package/dist/execution/types.js.map +1 -0
  59. package/dist/index.d.ts +22 -0
  60. package/dist/index.d.ts.map +1 -0
  61. package/dist/index.js +22 -0
  62. package/dist/index.js.map +1 -0
  63. package/dist/lib/api-client.d.ts +35 -0
  64. package/dist/lib/api-client.d.ts.map +1 -0
  65. package/dist/lib/api-client.js +126 -0
  66. package/dist/lib/api-client.js.map +1 -0
  67. package/dist/lib/config.d.ts +174 -0
  68. package/dist/lib/config.d.ts.map +1 -0
  69. package/dist/lib/config.js +399 -0
  70. package/dist/lib/config.js.map +1 -0
  71. package/dist/lib/copy-worktree.d.ts +73 -0
  72. package/dist/lib/copy-worktree.d.ts.map +1 -0
  73. package/dist/lib/copy-worktree.js +374 -0
  74. package/dist/lib/copy-worktree.js.map +1 -0
  75. package/dist/lib/git-pr.d.ts +63 -0
  76. package/dist/lib/git-pr.d.ts.map +1 -0
  77. package/dist/lib/git-pr.js +224 -0
  78. package/dist/lib/git-pr.js.map +1 -0
  79. package/dist/lib/hardware-id.d.ts +25 -0
  80. package/dist/lib/hardware-id.d.ts.map +1 -0
  81. package/dist/lib/hardware-id.js +186 -0
  82. package/dist/lib/hardware-id.js.map +1 -0
  83. package/dist/lib/hpc-context.d.ts +35 -0
  84. package/dist/lib/hpc-context.d.ts.map +1 -0
  85. package/dist/lib/hpc-context.js +167 -0
  86. package/dist/lib/hpc-context.js.map +1 -0
  87. package/dist/lib/prompt-templates.d.ts +195 -0
  88. package/dist/lib/prompt-templates.d.ts.map +1 -0
  89. package/dist/lib/prompt-templates.js +353 -0
  90. package/dist/lib/prompt-templates.js.map +1 -0
  91. package/dist/lib/providers.d.ts +27 -0
  92. package/dist/lib/providers.d.ts.map +1 -0
  93. package/dist/lib/providers.js +372 -0
  94. package/dist/lib/providers.js.map +1 -0
  95. package/dist/lib/repo-context.d.ts +18 -0
  96. package/dist/lib/repo-context.d.ts.map +1 -0
  97. package/dist/lib/repo-context.js +61 -0
  98. package/dist/lib/repo-context.js.map +1 -0
  99. package/dist/lib/repo-utils.d.ts +35 -0
  100. package/dist/lib/repo-utils.d.ts.map +1 -0
  101. package/dist/lib/repo-utils.js +222 -0
  102. package/dist/lib/repo-utils.js.map +1 -0
  103. package/dist/lib/resources.d.ts +17 -0
  104. package/dist/lib/resources.d.ts.map +1 -0
  105. package/dist/lib/resources.js +227 -0
  106. package/dist/lib/resources.js.map +1 -0
  107. package/dist/lib/slurm-detect.d.ts +15 -0
  108. package/dist/lib/slurm-detect.d.ts.map +1 -0
  109. package/dist/lib/slurm-detect.js +148 -0
  110. package/dist/lib/slurm-detect.js.map +1 -0
  111. package/dist/lib/slurm-executor.d.ts +70 -0
  112. package/dist/lib/slurm-executor.d.ts.map +1 -0
  113. package/dist/lib/slurm-executor.js +402 -0
  114. package/dist/lib/slurm-executor.js.map +1 -0
  115. package/dist/lib/slurm-job-monitor.d.ts +52 -0
  116. package/dist/lib/slurm-job-monitor.d.ts.map +1 -0
  117. package/dist/lib/slurm-job-monitor.js +212 -0
  118. package/dist/lib/slurm-job-monitor.js.map +1 -0
  119. package/dist/lib/ssh-discovery.d.ts +17 -0
  120. package/dist/lib/ssh-discovery.d.ts.map +1 -0
  121. package/dist/lib/ssh-discovery.js +287 -0
  122. package/dist/lib/ssh-discovery.js.map +1 -0
  123. package/dist/lib/ssh-installer.d.ts +69 -0
  124. package/dist/lib/ssh-installer.d.ts.map +1 -0
  125. package/dist/lib/ssh-installer.js +230 -0
  126. package/dist/lib/ssh-installer.js.map +1 -0
  127. package/dist/lib/streaming-prompt.d.ts +48 -0
  128. package/dist/lib/streaming-prompt.d.ts.map +1 -0
  129. package/dist/lib/streaming-prompt.js +91 -0
  130. package/dist/lib/streaming-prompt.js.map +1 -0
  131. package/dist/lib/task-executor.d.ts +114 -0
  132. package/dist/lib/task-executor.d.ts.map +1 -0
  133. package/dist/lib/task-executor.js +753 -0
  134. package/dist/lib/task-executor.js.map +1 -0
  135. package/dist/lib/websocket-client.d.ts +200 -0
  136. package/dist/lib/websocket-client.d.ts.map +1 -0
  137. package/dist/lib/websocket-client.js +781 -0
  138. package/dist/lib/websocket-client.js.map +1 -0
  139. package/dist/lib/workdir-safety.d.ts +63 -0
  140. package/dist/lib/workdir-safety.d.ts.map +1 -0
  141. package/dist/lib/workdir-safety.js +247 -0
  142. package/dist/lib/workdir-safety.js.map +1 -0
  143. package/dist/lib/worktree-include.d.ts +14 -0
  144. package/dist/lib/worktree-include.d.ts.map +1 -0
  145. package/dist/lib/worktree-include.js +68 -0
  146. package/dist/lib/worktree-include.js.map +1 -0
  147. package/dist/lib/worktree-setup.d.ts +18 -0
  148. package/dist/lib/worktree-setup.d.ts.map +1 -0
  149. package/dist/lib/worktree-setup.js +60 -0
  150. package/dist/lib/worktree-setup.js.map +1 -0
  151. package/dist/lib/worktree.d.ts +37 -0
  152. package/dist/lib/worktree.d.ts.map +1 -0
  153. package/dist/lib/worktree.js +411 -0
  154. package/dist/lib/worktree.js.map +1 -0
  155. package/dist/mcp/index.d.ts +8 -0
  156. package/dist/mcp/index.d.ts.map +1 -0
  157. package/dist/mcp/index.js +8 -0
  158. package/dist/mcp/index.js.map +1 -0
  159. package/dist/mcp/server.d.ts +45 -0
  160. package/dist/mcp/server.d.ts.map +1 -0
  161. package/dist/mcp/server.js +153 -0
  162. package/dist/mcp/server.js.map +1 -0
  163. package/dist/mcp/session-bridge.d.ts +87 -0
  164. package/dist/mcp/session-bridge.d.ts.map +1 -0
  165. package/dist/mcp/session-bridge.js +317 -0
  166. package/dist/mcp/session-bridge.js.map +1 -0
  167. package/dist/mcp/tools.d.ts +70 -0
  168. package/dist/mcp/tools.d.ts.map +1 -0
  169. package/dist/mcp/tools.js +234 -0
  170. package/dist/mcp/tools.js.map +1 -0
  171. package/dist/mcp/types.d.ts +197 -0
  172. package/dist/mcp/types.d.ts.map +1 -0
  173. package/dist/mcp/types.js +16 -0
  174. package/dist/mcp/types.js.map +1 -0
  175. package/dist/providers/base-adapter.d.ts +56 -0
  176. package/dist/providers/base-adapter.d.ts.map +1 -0
  177. package/dist/providers/base-adapter.js +5 -0
  178. package/dist/providers/base-adapter.js.map +1 -0
  179. package/dist/providers/claude-code-adapter.d.ts +27 -0
  180. package/dist/providers/claude-code-adapter.d.ts.map +1 -0
  181. package/dist/providers/claude-code-adapter.js +298 -0
  182. package/dist/providers/claude-code-adapter.js.map +1 -0
  183. package/dist/providers/claude-sdk-adapter.d.ts +60 -0
  184. package/dist/providers/claude-sdk-adapter.d.ts.map +1 -0
  185. package/dist/providers/claude-sdk-adapter.js +632 -0
  186. package/dist/providers/claude-sdk-adapter.js.map +1 -0
  187. package/dist/providers/codex-adapter.d.ts +21 -0
  188. package/dist/providers/codex-adapter.d.ts.map +1 -0
  189. package/dist/providers/codex-adapter.js +197 -0
  190. package/dist/providers/codex-adapter.js.map +1 -0
  191. package/dist/providers/index.d.ts +26 -0
  192. package/dist/providers/index.d.ts.map +1 -0
  193. package/dist/providers/index.js +58 -0
  194. package/dist/providers/index.js.map +1 -0
  195. package/dist/providers/slurm-adapter.d.ts +26 -0
  196. package/dist/providers/slurm-adapter.d.ts.map +1 -0
  197. package/dist/providers/slurm-adapter.js +146 -0
  198. package/dist/providers/slurm-adapter.js.map +1 -0
  199. package/dist/types.d.ts +592 -0
  200. package/dist/types.d.ts.map +1 -0
  201. package/dist/types.js +5 -0
  202. package/dist/types.js.map +1 -0
  203. package/package.json +77 -0
@@ -0,0 +1,70 @@
1
+ /**
2
+ * Slurm Executor
3
+ *
4
+ * Handles Slurm job submission and monitoring.
5
+ */
6
+ import type { SlurmInfo, SlurmJobStatus, SlurmJobConfig } from '../types.js';
7
+ export interface SlurmTaskInput {
8
+ taskId: string;
9
+ projectId: string;
10
+ nodeId: string;
11
+ title: string;
12
+ description: string;
13
+ workingDirectory?: string;
14
+ config?: SlurmJobConfig;
15
+ }
16
+ export interface SlurmExecuteOptions {
17
+ onStatus: (status: SlurmJobStatus) => void;
18
+ onOutput: (stream: 'stdout' | 'stderr', data: string) => void;
19
+ signal?: AbortSignal;
20
+ }
21
+ export interface SlurmExecuteResult {
22
+ status: string;
23
+ output?: string;
24
+ error?: string;
25
+ exitCode?: number;
26
+ slurmJobId?: string;
27
+ }
28
+ export declare class SlurmExecutor {
29
+ private slurmInfo;
30
+ private jobs;
31
+ private scriptDir;
32
+ constructor(slurmInfo: SlurmInfo);
33
+ /**
34
+ * Execute a task via Slurm
35
+ */
36
+ execute(task: SlurmTaskInput, options: SlurmExecuteOptions): Promise<SlurmExecuteResult>;
37
+ /**
38
+ * Cancel a task
39
+ */
40
+ cancel(taskId: string): Promise<boolean>;
41
+ /**
42
+ * Cancel all tasks
43
+ */
44
+ cancelAll(): Promise<void>;
45
+ /**
46
+ * Generate Slurm batch script
47
+ */
48
+ private generateScript;
49
+ /**
50
+ * Extract commands from task description
51
+ */
52
+ private extractCommands;
53
+ /**
54
+ * Submit job to Slurm
55
+ */
56
+ private submitJob;
57
+ /**
58
+ * Monitor job until completion
59
+ */
60
+ private monitorJob;
61
+ /**
62
+ * Get job status from squeue/sacct
63
+ */
64
+ private getJobStatus;
65
+ /**
66
+ * Sanitize job name for Slurm
67
+ */
68
+ private sanitizeName;
69
+ }
70
+ //# sourceMappingURL=slurm-executor.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"slurm-executor.d.ts","sourceRoot":"","sources":["../../src/lib/slurm-executor.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAOH,OAAO,KAAK,EAAE,SAAS,EAAE,cAAc,EAAE,cAAc,EAAE,MAAM,aAAa,CAAC;AAY7E,MAAM,WAAW,cAAc;IAC7B,MAAM,EAAE,MAAM,CAAC;IACf,SAAS,EAAE,MAAM,CAAC;IAClB,MAAM,EAAE,MAAM,CAAC;IACf,KAAK,EAAE,MAAM,CAAC;IACd,WAAW,EAAE,MAAM,CAAC;IACpB,gBAAgB,CAAC,EAAE,MAAM,CAAC;IAC1B,MAAM,CAAC,EAAE,cAAc,CAAC;CACzB;AAED,MAAM,WAAW,mBAAmB;IAClC,QAAQ,EAAE,CAAC,MAAM,EAAE,cAAc,KAAK,IAAI,CAAC;IAC3C,QAAQ,EAAE,CAAC,MAAM,EAAE,QAAQ,GAAG,QAAQ,EAAE,IAAI,EAAE,MAAM,KAAK,IAAI,CAAC;IAC9D,MAAM,CAAC,EAAE,WAAW,CAAC;CACtB;AAED,MAAM,WAAW,kBAAkB;IACjC,MAAM,EAAE,MAAM,CAAC;IACf,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,UAAU,CAAC,EAAE,MAAM,CAAC;CACrB;AAUD,qBAAa,aAAa;IAIZ,OAAO,CAAC,SAAS;IAH7B,OAAO,CAAC,IAAI,CAAiC;IAC7C,OAAO,CAAC,SAAS,CAAS;gBAEN,SAAS,EAAE,SAAS;IAOxC;;OAEG;IACG,OAAO,CAAC,IAAI,EAAE,cAAc,EAAE,OAAO,EAAE,mBAAmB,GAAG,OAAO,CAAC,kBAAkB,CAAC;IAqD9F;;OAEG;IACG,MAAM,CAAC,MAAM,EAAE,MAAM,GAAG,OAAO,CAAC,OAAO,CAAC;IAoB9C;;OAEG;IACG,SAAS,IAAI,OAAO,CAAC,IAAI,CAAC;IAMhC;;OAEG;IACH,OAAO,CAAC,cAAc;IA8FtB;;OAEG;IACH,OAAO,CAAC,eAAe;IAwCvB;;OAEG;YACW,SAAS;IAkBvB;;OAEG;YACW,UAAU;IAgGxB;;OAEG;YACW,YAAY;IAkD1B;;OAEG;IACH,OAAO,CAAC,YAAY;CAMrB"}
@@ -0,0 +1,402 @@
1
+ /**
2
+ * Slurm Executor
3
+ *
4
+ * Handles Slurm job submission and monitoring.
5
+ */
6
+ import { execFile } from 'node:child_process';
7
+ import { promisify } from 'node:util';
8
+ import * as fs from 'node:fs/promises';
9
+ import * as path from 'node:path';
10
+ import * as os from 'node:os';
11
+ const execFileAsync = promisify(execFile);
12
+ /** SLURM job IDs are numeric (optionally with array syntax like 12345_1). Validates and returns. */
13
+ function sanitizedSlurmJobId(id) {
14
+ if (!/^\d+(_\d+)?$/.test(id)) {
15
+ throw new Error(`Invalid SLURM job ID (possible command injection): ${id}`);
16
+ }
17
+ return id;
18
+ }
19
+ export class SlurmExecutor {
20
+ slurmInfo;
21
+ jobs = new Map();
22
+ scriptDir;
23
+ constructor(slurmInfo) {
24
+ this.slurmInfo = slurmInfo;
25
+ this.scriptDir = path.join(os.tmpdir(), 'astro-slurm-scripts');
26
+ fs.mkdir(this.scriptDir, { recursive: true }).catch(() => {
27
+ // Ignore if already exists
28
+ });
29
+ }
30
+ /**
31
+ * Execute a task via Slurm
32
+ */
33
+ async execute(task, options) {
34
+ // Check if already aborted
35
+ if (options.signal?.aborted) {
36
+ return { status: 'cancelled' };
37
+ }
38
+ const slurmConfig = task.config ?? {};
39
+ // Generate batch script
40
+ const script = this.generateScript(task, slurmConfig);
41
+ const scriptPath = path.join(this.scriptDir, `astro_${task.taskId}.sh`);
42
+ await fs.writeFile(scriptPath, script, { mode: 0o755 });
43
+ // Submit job
44
+ const submitResult = await this.submitJob(scriptPath);
45
+ if (!submitResult.success || !submitResult.jobId) {
46
+ return {
47
+ status: 'failed',
48
+ error: submitResult.error || 'Job submission failed',
49
+ };
50
+ }
51
+ const slurmJobId = submitResult.jobId;
52
+ // Set up output paths
53
+ const workdir = task.workingDirectory || process.cwd();
54
+ const outputPath = path.join(workdir, `astro_${task.taskId}_${slurmJobId}.out`);
55
+ const errorPath = path.join(workdir, `astro_${task.taskId}_${slurmJobId}.err`);
56
+ // Track the job
57
+ const tracker = {
58
+ taskId: task.taskId,
59
+ slurmJobId,
60
+ outputPath,
61
+ errorPath,
62
+ };
63
+ this.jobs.set(task.taskId, tracker);
64
+ // Wire abort signal to scancel
65
+ if (options.signal) {
66
+ const onAbort = () => {
67
+ this.cancel(task.taskId);
68
+ };
69
+ options.signal.addEventListener('abort', onAbort, { once: true });
70
+ }
71
+ // Monitor job
72
+ const result = await this.monitorJob(tracker, options);
73
+ return { ...result, slurmJobId };
74
+ }
75
+ /**
76
+ * Cancel a task
77
+ */
78
+ async cancel(taskId) {
79
+ const tracker = this.jobs.get(taskId);
80
+ if (!tracker)
81
+ return false;
82
+ // Stop watcher
83
+ if (tracker.watcher) {
84
+ clearInterval(tracker.watcher);
85
+ }
86
+ // Cancel Slurm job
87
+ try {
88
+ await execFileAsync('scancel', [sanitizedSlurmJobId(tracker.slurmJobId)], { timeout: 10000 });
89
+ }
90
+ catch {
91
+ // Failed to cancel — job may have already finished
92
+ }
93
+ this.jobs.delete(taskId);
94
+ return true;
95
+ }
96
+ /**
97
+ * Cancel all tasks
98
+ */
99
+ async cancelAll() {
100
+ for (const [taskId] of this.jobs) {
101
+ await this.cancel(taskId);
102
+ }
103
+ }
104
+ /**
105
+ * Generate Slurm batch script
106
+ */
107
+ generateScript(task, config) {
108
+ const lines = [];
109
+ lines.push('#!/bin/bash');
110
+ lines.push('');
111
+ // Job name
112
+ lines.push(`#SBATCH --job-name=astro_${this.sanitizeName(task.title)}`);
113
+ // Output files
114
+ const workdir = task.workingDirectory || '$HOME';
115
+ lines.push(`#SBATCH --output=${workdir}/astro_${task.taskId}_%j.out`);
116
+ lines.push(`#SBATCH --error=${workdir}/astro_${task.taskId}_%j.err`);
117
+ // Partition
118
+ if (config.partition) {
119
+ lines.push(`#SBATCH --partition=${config.partition}`);
120
+ }
121
+ else if (this.slurmInfo.defaultPartition) {
122
+ lines.push(`#SBATCH --partition=${this.slurmInfo.defaultPartition}`);
123
+ }
124
+ // Resources
125
+ if (config.nodes)
126
+ lines.push(`#SBATCH --nodes=${config.nodes}`);
127
+ if (config.ntasks)
128
+ lines.push(`#SBATCH --ntasks=${config.ntasks}`);
129
+ if (config.cpusPerTask)
130
+ lines.push(`#SBATCH --cpus-per-task=${config.cpusPerTask}`);
131
+ if (config.mem)
132
+ lines.push(`#SBATCH --mem=${config.mem}`);
133
+ // GPU
134
+ if (config.gpu) {
135
+ const gpuSpec = config.gpu.type
136
+ ? `${config.gpu.type}:${config.gpu.count}`
137
+ : config.gpu.count.toString();
138
+ lines.push(`#SBATCH --gres=gpu:${gpuSpec}`);
139
+ }
140
+ // Time limit
141
+ if (config.time) {
142
+ lines.push(`#SBATCH --time=${config.time}`);
143
+ }
144
+ else {
145
+ lines.push('#SBATCH --time=02:00:00'); // Default 2 hours
146
+ }
147
+ // QOS and account
148
+ if (config.qos)
149
+ lines.push(`#SBATCH --qos=${config.qos}`);
150
+ if (config.account) {
151
+ lines.push(`#SBATCH --account=${config.account}`);
152
+ }
153
+ else if (this.slurmInfo.accounts.length > 0) {
154
+ lines.push(`#SBATCH --account=${this.slurmInfo.accounts[0]}`);
155
+ }
156
+ lines.push('');
157
+ lines.push('# Exit on error');
158
+ lines.push('set -e');
159
+ lines.push('');
160
+ lines.push('# Job info');
161
+ lines.push('echo "=== Astro Job ==="');
162
+ lines.push('echo "Job ID: $SLURM_JOB_ID"');
163
+ lines.push('echo "Job Name: $SLURM_JOB_NAME"');
164
+ lines.push('echo "Node: $SLURMD_NODENAME"');
165
+ lines.push('echo "Start: $(date)"');
166
+ lines.push('echo "Working directory: $(pwd)"');
167
+ lines.push('echo "=================="');
168
+ lines.push('');
169
+ // Load modules
170
+ if (config.modules && config.modules.length > 0) {
171
+ lines.push('# Load modules');
172
+ for (const mod of config.modules) {
173
+ lines.push(`module load ${mod}`);
174
+ }
175
+ lines.push('');
176
+ }
177
+ // Environment variables (shell-escaped with single quotes)
178
+ lines.push('# Environment');
179
+ lines.push(`export ASTRO_TASK_ID='${shellEscape(task.taskId)}'`);
180
+ lines.push(`export ASTRO_PROJECT_ID='${shellEscape(task.projectId)}'`);
181
+ lines.push('');
182
+ // Extract and add commands from task description
183
+ lines.push('# Task commands');
184
+ const commands = this.extractCommands(task.description);
185
+ for (const cmd of commands) {
186
+ lines.push(cmd);
187
+ }
188
+ lines.push('');
189
+ lines.push('echo "=================="');
190
+ lines.push('echo "End: $(date)"');
191
+ lines.push('echo "Exit code: $?"');
192
+ return lines.join('\n');
193
+ }
194
+ /**
195
+ * Extract commands from task description
196
+ */
197
+ extractCommands(description) {
198
+ const commands = [];
199
+ // Look for code blocks
200
+ const codeBlockMatch = description.match(/```(?:bash|sh|shell)?\n([\s\S]*?)```/g);
201
+ if (codeBlockMatch) {
202
+ for (const block of codeBlockMatch) {
203
+ const code = block.replace(/```(?:bash|sh|shell)?\n?/, '').replace(/```$/, '').trim();
204
+ commands.push(code);
205
+ }
206
+ return commands;
207
+ }
208
+ // Look for command patterns in lines
209
+ const lines = description.split('\n');
210
+ for (const line of lines) {
211
+ const trimmed = line.trim();
212
+ if (!trimmed || trimmed.startsWith('#'))
213
+ continue;
214
+ if (trimmed.startsWith('python ') ||
215
+ trimmed.startsWith('python3 ') ||
216
+ trimmed.startsWith('Rscript ') ||
217
+ trimmed.startsWith('bash ') ||
218
+ trimmed.startsWith('./') ||
219
+ trimmed.startsWith('make ') ||
220
+ trimmed.match(/^\w+\s+/)) {
221
+ commands.push(trimmed);
222
+ }
223
+ }
224
+ if (commands.length === 0) {
225
+ commands.push(`# Task: ${description.substring(0, 200).replace(/\n/g, ' ')}`);
226
+ commands.push('echo "No explicit commands found. Task description stored above."');
227
+ }
228
+ return commands;
229
+ }
230
+ /**
231
+ * Submit job to Slurm
232
+ */
233
+ async submitJob(scriptPath) {
234
+ try {
235
+ const { stdout, stderr } = await execFileAsync('sbatch', [scriptPath], { timeout: 30000 });
236
+ const jobIdMatch = stdout.match(/Submitted batch job (\d+)/);
237
+ if (jobIdMatch) {
238
+ return { success: true, jobId: jobIdMatch[1] };
239
+ }
240
+ return { success: false, error: stderr || stdout || 'Unknown submission error' };
241
+ }
242
+ catch (error) {
243
+ return {
244
+ success: false,
245
+ error: error instanceof Error ? error.message : 'Submission failed',
246
+ };
247
+ }
248
+ }
249
+ /**
250
+ * Monitor job until completion
251
+ */
252
+ async monitorJob(tracker, options) {
253
+ return new Promise((resolve) => {
254
+ let lastOutputOffset = 0;
255
+ let lastErrorOffset = 0;
256
+ let lastState = '';
257
+ const checkJob = async () => {
258
+ // Check if aborted
259
+ if (options.signal?.aborted) {
260
+ if (tracker.watcher) {
261
+ clearInterval(tracker.watcher);
262
+ }
263
+ this.cancel(tracker.taskId);
264
+ resolve({ status: 'cancelled' });
265
+ return;
266
+ }
267
+ // Check job status
268
+ const status = await this.getJobStatus(tracker.slurmJobId);
269
+ if (status && status.state !== lastState) {
270
+ lastState = status.state;
271
+ options.onStatus(status);
272
+ }
273
+ // Stream stdout
274
+ try {
275
+ const stat = await fs.stat(tracker.outputPath);
276
+ if (stat.size > lastOutputOffset) {
277
+ const fd = await fs.open(tracker.outputPath, 'r');
278
+ const buffer = Buffer.alloc(stat.size - lastOutputOffset);
279
+ await fd.read(buffer, 0, buffer.length, lastOutputOffset);
280
+ await fd.close();
281
+ lastOutputOffset = stat.size;
282
+ const data = buffer.toString('utf-8');
283
+ if (data)
284
+ options.onOutput('stdout', data);
285
+ }
286
+ }
287
+ catch {
288
+ // File doesn't exist yet
289
+ }
290
+ // Stream stderr
291
+ try {
292
+ const stat = await fs.stat(tracker.errorPath);
293
+ if (stat.size > lastErrorOffset) {
294
+ const fd = await fs.open(tracker.errorPath, 'r');
295
+ const buffer = Buffer.alloc(stat.size - lastErrorOffset);
296
+ await fd.read(buffer, 0, buffer.length, lastErrorOffset);
297
+ await fd.close();
298
+ lastErrorOffset = stat.size;
299
+ const data = buffer.toString('utf-8');
300
+ if (data)
301
+ options.onOutput('stderr', data);
302
+ }
303
+ }
304
+ catch {
305
+ // File doesn't exist yet
306
+ }
307
+ // Check for completion
308
+ if (status && ['COMPLETED', 'FAILED', 'CANCELLED', 'TIMEOUT', 'NODE_FAIL', 'OUT_OF_MEMORY'].includes(status.state)) {
309
+ if (tracker.watcher) {
310
+ clearInterval(tracker.watcher);
311
+ }
312
+ this.jobs.delete(tracker.taskId);
313
+ // Read final output
314
+ let output = '';
315
+ try {
316
+ output = await fs.readFile(tracker.outputPath, 'utf-8');
317
+ }
318
+ catch {
319
+ // Ignore
320
+ }
321
+ let error = '';
322
+ try {
323
+ error = await fs.readFile(tracker.errorPath, 'utf-8');
324
+ }
325
+ catch {
326
+ // Ignore
327
+ }
328
+ resolve({
329
+ status: status.state === 'COMPLETED' && status.exitCode === 0 ? 'completed' : 'failed',
330
+ output,
331
+ error: error || (status.exitCode !== 0 ? `Exit code: ${status.exitCode}` : undefined),
332
+ exitCode: status.exitCode,
333
+ });
334
+ }
335
+ };
336
+ // Initial check
337
+ checkJob();
338
+ // Poll every 5 seconds
339
+ tracker.watcher = setInterval(checkJob, 5000);
340
+ });
341
+ }
342
+ /**
343
+ * Get job status from squeue/sacct
344
+ */
345
+ async getJobStatus(jobId) {
346
+ const safeJobId = sanitizedSlurmJobId(jobId);
347
+ // Try squeue first (for running jobs)
348
+ try {
349
+ const { stdout } = await execFileAsync('squeue', ['-j', safeJobId, '-h', '-o', '%T|%r|%N|%e'], { timeout: 10000 });
350
+ const trimmed = stdout.trim();
351
+ if (trimmed) {
352
+ const [state, stateReason, nodeList] = trimmed.split('|');
353
+ return {
354
+ jobId,
355
+ state: state || 'UNKNOWN',
356
+ stateReason: stateReason !== '(null)' ? stateReason : undefined,
357
+ nodeList: nodeList !== '(null)' ? nodeList : undefined,
358
+ };
359
+ }
360
+ }
361
+ catch {
362
+ // Job not in queue, check sacct
363
+ }
364
+ // Try sacct (for completed jobs)
365
+ try {
366
+ const { stdout } = await execFileAsync('sacct', ['-j', safeJobId, '--parsable2', '--noheader', '-o', 'State,ExitCode,NodeList'], { timeout: 10000 });
367
+ const lines = stdout.trim().split('\n');
368
+ const mainLine = lines.find((l) => !l.includes('.'));
369
+ if (mainLine) {
370
+ const [state, exitCodeRaw, nodeList] = mainLine.split('|');
371
+ let exitCode;
372
+ if (exitCodeRaw && exitCodeRaw.includes(':')) {
373
+ exitCode = parseInt(exitCodeRaw.split(':')[0]);
374
+ }
375
+ return {
376
+ jobId,
377
+ state: state?.split(' ')[0] || 'UNKNOWN',
378
+ nodeList: nodeList || undefined,
379
+ exitCode,
380
+ };
381
+ }
382
+ }
383
+ catch {
384
+ // sacct failed
385
+ }
386
+ return null;
387
+ }
388
+ /**
389
+ * Sanitize job name for Slurm
390
+ */
391
+ sanitizeName(name) {
392
+ return name
393
+ .replace(/[^a-zA-Z0-9_-]/g, '_')
394
+ .replace(/_+/g, '_')
395
+ .substring(0, 40);
396
+ }
397
+ }
398
+ /** Shell-escape a string by replacing single quotes with '\'' */
399
+ function shellEscape(value) {
400
+ return value.replace(/'/g, "'\\''");
401
+ }
402
+ //# sourceMappingURL=slurm-executor.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"slurm-executor.js","sourceRoot":"","sources":["../../src/lib/slurm-executor.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH,OAAO,EAAE,QAAQ,EAAE,MAAM,oBAAoB,CAAC;AAC9C,OAAO,EAAE,SAAS,EAAE,MAAM,WAAW,CAAC;AACtC,OAAO,KAAK,EAAE,MAAM,kBAAkB,CAAC;AACvC,OAAO,KAAK,IAAI,MAAM,WAAW,CAAC;AAClC,OAAO,KAAK,EAAE,MAAM,SAAS,CAAC;AAG9B,MAAM,aAAa,GAAG,SAAS,CAAC,QAAQ,CAAC,CAAC;AAE1C,oGAAoG;AACpG,SAAS,mBAAmB,CAAC,EAAU;IACrC,IAAI,CAAC,cAAc,CAAC,IAAI,CAAC,EAAE,CAAC,EAAE,CAAC;QAC7B,MAAM,IAAI,KAAK,CAAC,sDAAsD,EAAE,EAAE,CAAC,CAAC;IAC9E,CAAC;IACD,OAAO,EAAE,CAAC;AACZ,CAAC;AAkCD,MAAM,OAAO,aAAa;IAIJ;IAHZ,IAAI,GAAG,IAAI,GAAG,EAAsB,CAAC;IACrC,SAAS,CAAS;IAE1B,YAAoB,SAAoB;QAApB,cAAS,GAAT,SAAS,CAAW;QACtC,IAAI,CAAC,SAAS,GAAG,IAAI,CAAC,IAAI,CAAC,EAAE,CAAC,MAAM,EAAE,EAAE,qBAAqB,CAAC,CAAC;QAC/D,EAAE,CAAC,KAAK,CAAC,IAAI,CAAC,SAAS,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,CAAC,CAAC,KAAK,CAAC,GAAG,EAAE;YACvD,2BAA2B;QAC7B,CAAC,CAAC,CAAC;IACL,CAAC;IAED;;OAEG;IACH,KAAK,CAAC,OAAO,CAAC,IAAoB,EAAE,OAA4B;QAC9D,2BAA2B;QAC3B,IAAI,OAAO,CAAC,MAAM,EAAE,OAAO,EAAE,CAAC;YAC5B,OAAO,EAAE,MAAM,EAAE,WAAW,EAAE,CAAC;QACjC,CAAC;QAED,MAAM,WAAW,GAAG,IAAI,CAAC,MAAM,IAAI,EAAE,CAAC;QAEtC,wBAAwB;QACxB,MAAM,MAAM,GAAG,IAAI,CAAC,cAAc,CAAC,IAAI,EAAE,WAAW,CAAC,CAAC;QACtD,MAAM,UAAU,GAAG,IAAI,CAAC,IAAI,CAAC,IAAI,CAAC,SAAS,EAAE,SAAS,IAAI,CAAC,MAAM,KAAK,CAAC,CAAC;QAExE,MAAM,EAAE,CAAC,SAAS,CAAC,UAAU,EAAE,MAAM,EAAE,EAAE,IAAI,EAAE,KAAK,EAAE,CAAC,CAAC;QAExD,aAAa;QACb,MAAM,YAAY,GAAG,MAAM,IAAI,CAAC,SAAS,CAAC,UAAU,CAAC,CAAC;QAEtD,IAAI,CAAC,YAAY,CAAC,OAAO,IAAI,CAAC,YAAY,CAAC,KAAK,EAAE,CAAC;YACjD,OAAO;gBACL,MAAM,EAAE,QAAQ;gBAChB,KAAK,EAAE,YAAY,CAAC,KAAK,IAAI,uBAAuB;aACrD,CAAC;QACJ,CAAC;QAED,MAAM,UAAU,GAAG,YAAY,CAAC,KAAK,CAAC;QAEtC,sBAAsB;QACtB,MAAM,OAAO,GAAG,IAAI,CAAC,gBAAgB,IAAI,OAAO,CAAC,GAAG,EAAE,CAAC;QACvD,MAAM,UAAU,GAAG,IAAI,CAAC,IAAI,CAAC,OAAO,EAAE,SAAS,IAAI,CAAC,MAAM,IAAI,UAAU,MAAM,CAAC,CAAC;QAChF,MAAM,SAAS,GAAG,IAAI,CAAC,IAAI,CAAC,OAAO,EAAE,SAAS,IAAI,CAAC,MAAM,IAAI,UAAU,MAAM,CAAC,CAAC;QAE/E,gBAAgB;QAChB,MAAM,OAAO,GAAe;YAC1B,MAAM,EAAE,IAAI,CAAC,MAAM;YACnB,UAAU;YACV,UAAU;YACV,SAAS;SACV,CAAC;QACF,IAAI,CAAC,IAAI,CAAC,GAAG,CAAC,IAAI,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;QAEpC,+BAA+B;QAC/B,IAAI,OAAO,CAAC,MAAM,EAAE,CAAC;YACnB,MAAM,OAAO,GAAG,GAAG,EAAE;gBACnB,IAAI,CAAC,MAAM,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC;YAC3B,CAAC,CAAC;YACF,OAAO,CAAC,MAAM,CAAC,gBAAgB,CAAC,OAAO,EAAE,OAAO,EAAE,EAAE,IAAI,EAAE,IAAI,EAAE,CAAC,CAAC;QACpE,CAAC;QAED,cAAc;QACd,MAAM,MAAM,GAAG,MAAM,IAAI,CAAC,UAAU,CAAC,OAAO,EAAE,OAAO,CAAC,CAAC;QACvD,OAAO,EAAE,GAAG,MAAM,EAAE,UAAU,EAAE,CAAC;IACnC,CAAC;IAED;;OAEG;IACH,KAAK,CAAC,MAAM,CAAC,MAAc;QACzB,MAAM,OAAO,GAAG,IAAI,CAAC,IAAI,CAAC,GAAG,CAAC,MAAM,CAAC,CAAC;QACtC,IAAI,CAAC,OAAO;YAAE,OAAO,KAAK,CAAC;QAE3B,eAAe;QACf,IAAI,OAAO,CAAC,OAAO,EAAE,CAAC;YACpB,aAAa,CAAC,OAAO,CAAC,OAAO,CAAC,CAAC;QACjC,CAAC;QAED,mBAAmB;QACnB,IAAI,CAAC;YACH,MAAM,aAAa,CAAC,SAAS,EAAE,CAAC,mBAAmB,CAAC,OAAO,CAAC,UAAU,CAAC,CAAC,EAAE,EAAE,OAAO,EAAE,KAAK,EAAE,CAAC,CAAC;QAChG,CAAC;QAAC,MAAM,CAAC;YACP,mDAAmD;QACrD,CAAC;QAED,IAAI,CAAC,IAAI,CAAC,MAAM,CAAC,MAAM,CAAC,CAAC;QACzB,OAAO,IAAI,CAAC;IACd,CAAC;IAED;;OAEG;IACH,KAAK,CAAC,SAAS;QACb,KAAK,MAAM,CAAC,MAAM,CAAC,IAAI,IAAI,CAAC,IAAI,EAAE,CAAC;YACjC,MAAM,IAAI,CAAC,MAAM,CAAC,MAAM,CAAC,CAAC;QAC5B,CAAC;IACH,CAAC;IAED;;OAEG;IACK,cAAc,CAAC,IAAoB,EAAE,MAAsB;QACjE,MAAM,KAAK,GAAa,EAAE,CAAC;QAE3B,KAAK,CAAC,IAAI,CAAC,aAAa,CAAC,CAAC;QAC1B,KAAK,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC;QAEf,WAAW;QACX,KAAK,CAAC,IAAI,CAAC,4BAA4B,IAAI,CAAC,YAAY,CAAC,IAAI,CAAC,KAAK,CAAC,EAAE,CAAC,CAAC;QAExE,eAAe;QACf,MAAM,OAAO,GAAG,IAAI,CAAC,gBAAgB,IAAI,OAAO,CAAC;QACjD,KAAK,CAAC,IAAI,CAAC,oBAAoB,OAAO,UAAU,IAAI,CAAC,MAAM,SAAS,CAAC,CAAC;QACtE,KAAK,CAAC,IAAI,CAAC,mBAAmB,OAAO,UAAU,IAAI,CAAC,MAAM,SAAS,CAAC,CAAC;QAErE,YAAY;QACZ,IAAI,MAAM,CAAC,SAAS,EAAE,CAAC;YACrB,KAAK,CAAC,IAAI,CAAC,uBAAuB,MAAM,CAAC,SAAS,EAAE,CAAC,CAAC;QACxD,CAAC;aAAM,IAAI,IAAI,CAAC,SAAS,CAAC,gBAAgB,EAAE,CAAC;YAC3C,KAAK,CAAC,IAAI,CAAC,uBAAuB,IAAI,CAAC,SAAS,CAAC,gBAAgB,EAAE,CAAC,CAAC;QACvE,CAAC;QAED,YAAY;QACZ,IAAI,MAAM,CAAC,KAAK;YAAE,KAAK,CAAC,IAAI,CAAC,mBAAmB,MAAM,CAAC,KAAK,EAAE,CAAC,CAAC;QAChE,IAAI,MAAM,CAAC,MAAM;YAAE,KAAK,CAAC,IAAI,CAAC,oBAAoB,MAAM,CAAC,MAAM,EAAE,CAAC,CAAC;QACnE,IAAI,MAAM,CAAC,WAAW;YAAE,KAAK,CAAC,IAAI,CAAC,2BAA2B,MAAM,CAAC,WAAW,EAAE,CAAC,CAAC;QACpF,IAAI,MAAM,CAAC,GAAG;YAAE,KAAK,CAAC,IAAI,CAAC,iBAAiB,MAAM,CAAC,GAAG,EAAE,CAAC,CAAC;QAE1D,MAAM;QACN,IAAI,MAAM,CAAC,GAAG,EAAE,CAAC;YACf,MAAM,OAAO,GAAG,MAAM,CAAC,GAAG,CAAC,IAAI;gBAC7B,CAAC,CAAC,GAAG,MAAM,CAAC,GAAG,CAAC,IAAI,IAAI,MAAM,CAAC,GAAG,CAAC,KAAK,EAAE;gBAC1C,CAAC,CAAC,MAAM,CAAC,GAAG,CAAC,KAAK,CAAC,QAAQ,EAAE,CAAC;YAChC,KAAK,CAAC,IAAI,CAAC,sBAAsB,OAAO,EAAE,CAAC,CAAC;QAC9C,CAAC;QAED,aAAa;QACb,IAAI,MAAM,CAAC,IAAI,EAAE,CAAC;YAChB,KAAK,CAAC,IAAI,CAAC,kBAAkB,MAAM,CAAC,IAAI,EAAE,CAAC,CAAC;QAC9C,CAAC;aAAM,CAAC;YACN,KAAK,CAAC,IAAI,CAAC,yBAAyB,CAAC,CAAC,CAAC,kBAAkB;QAC3D,CAAC;QAED,kBAAkB;QAClB,IAAI,MAAM,CAAC,GAAG;YAAE,KAAK,CAAC,IAAI,CAAC,iBAAiB,MAAM,CAAC,GAAG,EAAE,CAAC,CAAC;QAC1D,IAAI,MAAM,CAAC,OAAO,EAAE,CAAC;YACnB,KAAK,CAAC,IAAI,CAAC,qBAAqB,MAAM,CAAC,OAAO,EAAE,CAAC,CAAC;QACpD,CAAC;aAAM,IAAI,IAAI,CAAC,SAAS,CAAC,QAAQ,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;YAC9C,KAAK,CAAC,IAAI,CAAC,qBAAqB,IAAI,CAAC,SAAS,CAAC,QAAQ,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC;QAChE,CAAC;QAED,KAAK,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC;QACf,KAAK,CAAC,IAAI,CAAC,iBAAiB,CAAC,CAAC;QAC9B,KAAK,CAAC,IAAI,CAAC,QAAQ,CAAC,CAAC;QACrB,KAAK,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC;QACf,KAAK,CAAC,IAAI,CAAC,YAAY,CAAC,CAAC;QACzB,KAAK,CAAC,IAAI,CAAC,0BAA0B,CAAC,CAAC;QACvC,KAAK,CAAC,IAAI,CAAC,8BAA8B,CAAC,CAAC;QAC3C,KAAK,CAAC,IAAI,CAAC,kCAAkC,CAAC,CAAC;QAC/C,KAAK,CAAC,IAAI,CAAC,+BAA+B,CAAC,CAAC;QAC5C,KAAK,CAAC,IAAI,CAAC,uBAAuB,CAAC,CAAC;QACpC,KAAK,CAAC,IAAI,CAAC,kCAAkC,CAAC,CAAC;QAC/C,KAAK,CAAC,IAAI,CAAC,2BAA2B,CAAC,CAAC;QACxC,KAAK,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC;QAEf,eAAe;QACf,IAAI,MAAM,CAAC,OAAO,IAAI,MAAM,CAAC,OAAO,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;YAChD,KAAK,CAAC,IAAI,CAAC,gBAAgB,CAAC,CAAC;YAC7B,KAAK,MAAM,GAAG,IAAI,MAAM,CAAC,OAAO,EAAE,CAAC;gBACjC,KAAK,CAAC,IAAI,CAAC,eAAe,GAAG,EAAE,CAAC,CAAC;YACnC,CAAC;YACD,KAAK,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC;QACjB,CAAC;QAED,2DAA2D;QAC3D,KAAK,CAAC,IAAI,CAAC,eAAe,CAAC,CAAC;QAC5B,KAAK,CAAC,IAAI,CAAC,yBAAyB,WAAW,CAAC,IAAI,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC;QACjE,KAAK,CAAC,IAAI,CAAC,4BAA4B,WAAW,CAAC,IAAI,CAAC,SAAS,CAAC,GAAG,CAAC,CAAC;QACvE,KAAK,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC;QAEf,iDAAiD;QACjD,KAAK,CAAC,IAAI,CAAC,iBAAiB,CAAC,CAAC;QAC9B,MAAM,QAAQ,GAAG,IAAI,CAAC,eAAe,CAAC,IAAI,CAAC,WAAW,CAAC,CAAC;QACxD,KAAK,MAAM,GAAG,IAAI,QAAQ,EAAE,CAAC;YAC3B,KAAK,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;QAClB,CAAC;QAED,KAAK,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC;QACf,KAAK,CAAC,IAAI,CAAC,2BAA2B,CAAC,CAAC;QACxC,KAAK,CAAC,IAAI,CAAC,qBAAqB,CAAC,CAAC;QAClC,KAAK,CAAC,IAAI,CAAC,sBAAsB,CAAC,CAAC;QAEnC,OAAO,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;IAC1B,CAAC;IAED;;OAEG;IACK,eAAe,CAAC,WAAmB;QACzC,MAAM,QAAQ,GAAa,EAAE,CAAC;QAE9B,uBAAuB;QACvB,MAAM,cAAc,GAAG,WAAW,CAAC,KAAK,CAAC,uCAAuC,CAAC,CAAC;QAClF,IAAI,cAAc,EAAE,CAAC;YACnB,KAAK,MAAM,KAAK,IAAI,cAAc,EAAE,CAAC;gBACnC,MAAM,IAAI,GAAG,KAAK,CAAC,OAAO,CAAC,0BAA0B,EAAE,EAAE,CAAC,CAAC,OAAO,CAAC,MAAM,EAAE,EAAE,CAAC,CAAC,IAAI,EAAE,CAAC;gBACtF,QAAQ,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;YACtB,CAAC;YACD,OAAO,QAAQ,CAAC;QAClB,CAAC;QAED,qCAAqC;QACrC,MAAM,KAAK,GAAG,WAAW,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC;QACtC,KAAK,MAAM,IAAI,IAAI,KAAK,EAAE,CAAC;YACzB,MAAM,OAAO,GAAG,IAAI,CAAC,IAAI,EAAE,CAAC;YAC5B,IAAI,CAAC,OAAO,IAAI,OAAO,CAAC,UAAU,CAAC,GAAG,CAAC;gBAAE,SAAS;YAElD,IACE,OAAO,CAAC,UAAU,CAAC,SAAS,CAAC;gBAC7B,OAAO,CAAC,UAAU,CAAC,UAAU,CAAC;gBAC9B,OAAO,CAAC,UAAU,CAAC,UAAU,CAAC;gBAC9B,OAAO,CAAC,UAAU,CAAC,OAAO,CAAC;gBAC3B,OAAO,CAAC,UAAU,CAAC,IAAI,CAAC;gBACxB,OAAO,CAAC,UAAU,CAAC,OAAO,CAAC;gBAC3B,OAAO,CAAC,KAAK,CAAC,SAAS,CAAC,EACxB,CAAC;gBACD,QAAQ,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC;YACzB,CAAC;QACH,CAAC;QAED,IAAI,QAAQ,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;YAC1B,QAAQ,CAAC,IAAI,CAAC,WAAW,WAAW,CAAC,SAAS,CAAC,CAAC,EAAE,GAAG,CAAC,CAAC,OAAO,CAAC,KAAK,EAAE,GAAG,CAAC,EAAE,CAAC,CAAC;YAC9E,QAAQ,CAAC,IAAI,CAAC,mEAAmE,CAAC,CAAC;QACrF,CAAC;QAED,OAAO,QAAQ,CAAC;IAClB,CAAC;IAED;;OAEG;IACK,KAAK,CAAC,SAAS,CAAC,UAAkB;QACxC,IAAI,CAAC;YACH,MAAM,EAAE,MAAM,EAAE,MAAM,EAAE,GAAG,MAAM,aAAa,CAAC,QAAQ,EAAE,CAAC,UAAU,CAAC,EAAE,EAAE,OAAO,EAAE,KAAK,EAAE,CAAC,CAAC;YAE3F,MAAM,UAAU,GAAG,MAAM,CAAC,KAAK,CAAC,2BAA2B,CAAC,CAAC;YAC7D,IAAI,UAAU,EAAE,CAAC;gBACf,OAAO,EAAE,OAAO,EAAE,IAAI,EAAE,KAAK,EAAE,UAAU,CAAC,CAAC,CAAC,EAAE,CAAC;YACjD,CAAC;YAED,OAAO,EAAE,OAAO,EAAE,KAAK,EAAE,KAAK,EAAE,MAAM,IAAI,MAAM,IAAI,0BAA0B,EAAE,CAAC;QACnF,CAAC;QAAC,OAAO,KAAK,EAAE,CAAC;YACf,OAAO;gBACL,OAAO,EAAE,KAAK;gBACd,KAAK,EAAE,KAAK,YAAY,KAAK,CAAC,CAAC,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC,CAAC,mBAAmB;aACpE,CAAC;QACJ,CAAC;IACH,CAAC;IAED;;OAEG;IACK,KAAK,CAAC,UAAU,CAAC,OAAmB,EAAE,OAA4B;QACxE,OAAO,IAAI,OAAO,CAAC,CAAC,OAAO,EAAE,EAAE;YAC7B,IAAI,gBAAgB,GAAG,CAAC,CAAC;YACzB,IAAI,eAAe,GAAG,CAAC,CAAC;YACxB,IAAI,SAAS,GAAG,EAAE,CAAC;YAEnB,MAAM,QAAQ,GAAG,KAAK,IAAI,EAAE;gBAC1B,mBAAmB;gBACnB,IAAI,OAAO,CAAC,MAAM,EAAE,OAAO,EAAE,CAAC;oBAC5B,IAAI,OAAO,CAAC,OAAO,EAAE,CAAC;wBACpB,aAAa,CAAC,OAAO,CAAC,OAAO,CAAC,CAAC;oBACjC,CAAC;oBACD,IAAI,CAAC,MAAM,CAAC,OAAO,CAAC,MAAM,CAAC,CAAC;oBAC5B,OAAO,CAAC,EAAE,MAAM,EAAE,WAAW,EAAE,CAAC,CAAC;oBACjC,OAAO;gBACT,CAAC;gBAED,mBAAmB;gBACnB,MAAM,MAAM,GAAG,MAAM,IAAI,CAAC,YAAY,CAAC,OAAO,CAAC,UAAU,CAAC,CAAC;gBAE3D,IAAI,MAAM,IAAI,MAAM,CAAC,KAAK,KAAK,SAAS,EAAE,CAAC;oBACzC,SAAS,GAAG,MAAM,CAAC,KAAK,CAAC;oBACzB,OAAO,CAAC,QAAQ,CAAC,MAAM,CAAC,CAAC;gBAC3B,CAAC;gBAED,gBAAgB;gBAChB,IAAI,CAAC;oBACH,MAAM,IAAI,GAAG,MAAM,EAAE,CAAC,IAAI,CAAC,OAAO,CAAC,UAAU,CAAC,CAAC;oBAC/C,IAAI,IAAI,CAAC,IAAI,GAAG,gBAAgB,EAAE,CAAC;wBACjC,MAAM,EAAE,GAAG,MAAM,EAAE,CAAC,IAAI,CAAC,OAAO,CAAC,UAAU,EAAE,GAAG,CAAC,CAAC;wBAClD,MAAM,MAAM,GAAG,MAAM,CAAC,KAAK,CAAC,IAAI,CAAC,IAAI,GAAG,gBAAgB,CAAC,CAAC;wBAC1D,MAAM,EAAE,CAAC,IAAI,CAAC,MAAM,EAAE,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,gBAAgB,CAAC,CAAC;wBAC1D,MAAM,EAAE,CAAC,KAAK,EAAE,CAAC;wBACjB,gBAAgB,GAAG,IAAI,CAAC,IAAI,CAAC;wBAC7B,MAAM,IAAI,GAAG,MAAM,CAAC,QAAQ,CAAC,OAAO,CAAC,CAAC;wBACtC,IAAI,IAAI;4BAAE,OAAO,CAAC,QAAQ,CAAC,QAAQ,EAAE,IAAI,CAAC,CAAC;oBAC7C,CAAC;gBACH,CAAC;gBAAC,MAAM,CAAC;oBACP,yBAAyB;gBAC3B,CAAC;gBAED,gBAAgB;gBAChB,IAAI,CAAC;oBACH,MAAM,IAAI,GAAG,MAAM,EAAE,CAAC,IAAI,CAAC,OAAO,CAAC,SAAS,CAAC,CAAC;oBAC9C,IAAI,IAAI,CAAC,IAAI,GAAG,eAAe,EAAE,CAAC;wBAChC,MAAM,EAAE,GAAG,MAAM,EAAE,CAAC,IAAI,CAAC,OAAO,CAAC,SAAS,EAAE,GAAG,CAAC,CAAC;wBACjD,MAAM,MAAM,GAAG,MAAM,CAAC,KAAK,CAAC,IAAI,CAAC,IAAI,GAAG,eAAe,CAAC,CAAC;wBACzD,MAAM,EAAE,CAAC,IAAI,CAAC,MAAM,EAAE,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,eAAe,CAAC,CAAC;wBACzD,MAAM,EAAE,CAAC,KAAK,EAAE,CAAC;wBACjB,eAAe,GAAG,IAAI,CAAC,IAAI,CAAC;wBAC5B,MAAM,IAAI,GAAG,MAAM,CAAC,QAAQ,CAAC,OAAO,CAAC,CAAC;wBACtC,IAAI,IAAI;4BAAE,OAAO,CAAC,QAAQ,CAAC,QAAQ,EAAE,IAAI,CAAC,CAAC;oBAC7C,CAAC;gBACH,CAAC;gBAAC,MAAM,CAAC;oBACP,yBAAyB;gBAC3B,CAAC;gBAED,uBAAuB;gBACvB,IAAI,MAAM,IAAI,CAAC,WAAW,EAAE,QAAQ,EAAE,WAAW,EAAE,SAAS,EAAE,WAAW,EAAE,eAAe,CAAC,CAAC,QAAQ,CAAC,MAAM,CAAC,KAAK,CAAC,EAAE,CAAC;oBACnH,IAAI,OAAO,CAAC,OAAO,EAAE,CAAC;wBACpB,aAAa,CAAC,OAAO,CAAC,OAAO,CAAC,CAAC;oBACjC,CAAC;oBACD,IAAI,CAAC,IAAI,CAAC,MAAM,CAAC,OAAO,CAAC,MAAM,CAAC,CAAC;oBAEjC,oBAAoB;oBACpB,IAAI,MAAM,GAAG,EAAE,CAAC;oBAChB,IAAI,CAAC;wBACH,MAAM,GAAG,MAAM,EAAE,CAAC,QAAQ,CAAC,OAAO,CAAC,UAAU,EAAE,OAAO,CAAC,CAAC;oBAC1D,CAAC;oBAAC,MAAM,CAAC;wBACP,SAAS;oBACX,CAAC;oBAED,IAAI,KAAK,GAAG,EAAE,CAAC;oBACf,IAAI,CAAC;wBACH,KAAK,GAAG,MAAM,EAAE,CAAC,QAAQ,CAAC,OAAO,CAAC,SAAS,EAAE,OAAO,CAAC,CAAC;oBACxD,CAAC;oBAAC,MAAM,CAAC;wBACP,SAAS;oBACX,CAAC;oBAED,OAAO,CAAC;wBACN,MAAM,EAAE,MAAM,CAAC,KAAK,KAAK,WAAW,IAAI,MAAM,CAAC,QAAQ,KAAK,CAAC,CAAC,CAAC,CAAC,WAAW,CAAC,CAAC,CAAC,QAAQ;wBACtF,MAAM;wBACN,KAAK,EAAE,KAAK,IAAI,CAAC,MAAM,CAAC,QAAQ,KAAK,CAAC,CAAC,CAAC,CAAC,cAAc,MAAM,CAAC,QAAQ,EAAE,CAAC,CAAC,CAAC,SAAS,CAAC;wBACrF,QAAQ,EAAE,MAAM,CAAC,QAAQ;qBAC1B,CAAC,CAAC;gBACL,CAAC;YACH,CAAC,CAAC;YAEF,gBAAgB;YAChB,QAAQ,EAAE,CAAC;YAEX,uBAAuB;YACvB,OAAO,CAAC,OAAO,GAAG,WAAW,CAAC,QAAQ,EAAE,IAAI,CAAC,CAAC;QAChD,CAAC,CAAC,CAAC;IACL,CAAC;IAED;;OAEG;IACK,KAAK,CAAC,YAAY,CAAC,KAAa;QACtC,MAAM,SAAS,GAAG,mBAAmB,CAAC,KAAK,CAAC,CAAC;QAC7C,sCAAsC;QACtC,IAAI,CAAC;YACH,MAAM,EAAE,MAAM,EAAE,GAAG,MAAM,aAAa,CACpC,QAAQ,EAAE,CAAC,IAAI,EAAE,SAAS,EAAE,IAAI,EAAE,IAAI,EAAE,aAAa,CAAC,EACtD,EAAE,OAAO,EAAE,KAAK,EAAE,CACnB,CAAC;YACF,MAAM,OAAO,GAAG,MAAM,CAAC,IAAI,EAAE,CAAC;YAC9B,IAAI,OAAO,EAAE,CAAC;gBACZ,MAAM,CAAC,KAAK,EAAE,WAAW,EAAE,QAAQ,CAAC,GAAG,OAAO,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC;gBAC1D,OAAO;oBACL,KAAK;oBACL,KAAK,EAAE,KAAK,IAAI,SAAS;oBACzB,WAAW,EAAE,WAAW,KAAK,QAAQ,CAAC,CAAC,CAAC,WAAW,CAAC,CAAC,CAAC,SAAS;oBAC/D,QAAQ,EAAE,QAAQ,KAAK,QAAQ,CAAC,CAAC,CAAC,QAAQ,CAAC,CAAC,CAAC,SAAS;iBACvD,CAAC;YACJ,CAAC;QACH,CAAC;QAAC,MAAM,CAAC;YACP,gCAAgC;QAClC,CAAC;QAED,iCAAiC;QACjC,IAAI,CAAC;YACH,MAAM,EAAE,MAAM,EAAE,GAAG,MAAM,aAAa,CACpC,OAAO,EAAE,CAAC,IAAI,EAAE,SAAS,EAAE,aAAa,EAAE,YAAY,EAAE,IAAI,EAAE,yBAAyB,CAAC,EACxF,EAAE,OAAO,EAAE,KAAK,EAAE,CACnB,CAAC;YACF,MAAM,KAAK,GAAG,MAAM,CAAC,IAAI,EAAE,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC;YACxC,MAAM,QAAQ,GAAG,KAAK,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,CAAC,QAAQ,CAAC,GAAG,CAAC,CAAC,CAAC;YACrD,IAAI,QAAQ,EAAE,CAAC;gBACb,MAAM,CAAC,KAAK,EAAE,WAAW,EAAE,QAAQ,CAAC,GAAG,QAAQ,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC;gBAC3D,IAAI,QAA4B,CAAC;gBACjC,IAAI,WAAW,IAAI,WAAW,CAAC,QAAQ,CAAC,GAAG,CAAC,EAAE,CAAC;oBAC7C,QAAQ,GAAG,QAAQ,CAAC,WAAW,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC;gBACjD,CAAC;gBACD,OAAO;oBACL,KAAK;oBACL,KAAK,EAAE,KAAK,EAAE,KAAK,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,IAAI,SAAS;oBACxC,QAAQ,EAAE,QAAQ,IAAI,SAAS;oBAC/B,QAAQ;iBACT,CAAC;YACJ,CAAC;QACH,CAAC;QAAC,MAAM,CAAC;YACP,eAAe;QACjB,CAAC;QAED,OAAO,IAAI,CAAC;IACd,CAAC;IAED;;OAEG;IACK,YAAY,CAAC,IAAY;QAC/B,OAAO,IAAI;aACR,OAAO,CAAC,iBAAiB,EAAE,GAAG,CAAC;aAC/B,OAAO,CAAC,KAAK,EAAE,GAAG,CAAC;aACnB,SAAS,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC;IACtB,CAAC;CACF;AAED,iEAAiE;AACjE,SAAS,WAAW,CAAC,KAAa;IAChC,OAAO,KAAK,CAAC,OAAO,CAAC,IAAI,EAAE,OAAO,CAAC,CAAC;AACtC,CAAC"}
@@ -0,0 +1,52 @@
1
+ /**
2
+ * Slurm Job Monitor
3
+ *
4
+ * Background poller that tracks submitted Slurm batch jobs (sbatch).
5
+ * Monitors job status via sacct and streams updates through the
6
+ * existing WebSocket relay protocol.
7
+ */
8
+ import type { WebSocketClient } from './websocket-client.js';
9
+ export declare class SlurmJobMonitor {
10
+ private jobs;
11
+ private pollInterval;
12
+ private wsClient;
13
+ private pollIntervalMs;
14
+ constructor(wsClient: WebSocketClient, pollIntervalMs?: number);
15
+ /**
16
+ * Track a submitted Slurm job
17
+ */
18
+ trackJob(slurmJobId: string, executionId: string, nodeId: string, outputPath?: string): void;
19
+ /**
20
+ * Stop tracking a job
21
+ */
22
+ untrackJob(slurmJobId: string): void;
23
+ /**
24
+ * Check if any jobs are being tracked
25
+ */
26
+ hasTrackedJobs(): boolean;
27
+ /**
28
+ * Get tracked job IDs for a given execution
29
+ */
30
+ getJobsForExecution(executionId: string): string[];
31
+ /**
32
+ * Start the polling loop
33
+ */
34
+ start(): void;
35
+ /**
36
+ * Stop the polling loop
37
+ */
38
+ stop(): void;
39
+ /**
40
+ * Poll all tracked jobs
41
+ */
42
+ private pollAll;
43
+ /**
44
+ * Poll a single job's status via sacct
45
+ */
46
+ private pollJob;
47
+ /**
48
+ * Stream new output from the job's output file
49
+ */
50
+ private streamOutput;
51
+ }
52
+ //# sourceMappingURL=slurm-job-monitor.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"slurm-job-monitor.d.ts","sourceRoot":"","sources":["../../src/lib/slurm-job-monitor.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAMH,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,uBAAuB,CAAC;AA+B7D,qBAAa,eAAe;IAC1B,OAAO,CAAC,IAAI,CAAiC;IAC7C,OAAO,CAAC,YAAY,CAA+C;IACnE,OAAO,CAAC,QAAQ,CAAkB;IAClC,OAAO,CAAC,cAAc,CAAS;gBAEnB,QAAQ,EAAE,eAAe,EAAE,cAAc,SAAS;IAK9D;;OAEG;IACH,QAAQ,CACN,UAAU,EAAE,MAAM,EAClB,WAAW,EAAE,MAAM,EACnB,MAAM,EAAE,MAAM,EACd,UAAU,CAAC,EAAE,MAAM,GAClB,IAAI;IAkBP;;OAEG;IACH,UAAU,CAAC,UAAU,EAAE,MAAM,GAAG,IAAI;IAOpC;;OAEG;IACH,cAAc,IAAI,OAAO;IAIzB;;OAEG;IACH,mBAAmB,CAAC,WAAW,EAAE,MAAM,GAAG,MAAM,EAAE;IAMlD;;OAEG;IACH,KAAK,IAAI,IAAI;IAcb;;OAEG;IACH,IAAI,IAAI,IAAI;IAQZ;;OAEG;YACW,OAAO;IAUrB;;OAEG;YACW,OAAO;IAyErB;;OAEG;YACW,YAAY;CA+B3B"}