@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,84 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Execution Strategy Registry
|
|
3
|
+
*
|
|
4
|
+
* Manages all available execution strategies. Provides detection, lookup,
|
|
5
|
+
* and listing of strategies.
|
|
6
|
+
*/
|
|
7
|
+
import { DirectStrategy } from './direct-strategy.js';
|
|
8
|
+
import { SlurmStrategy } from './slurm-strategy.js';
|
|
9
|
+
import { DockerStrategy } from './docker-strategy.js';
|
|
10
|
+
import { K8sExecStrategy } from './kubernetes-exec-strategy.js';
|
|
11
|
+
export class ExecutionStrategyRegistry {
|
|
12
|
+
strategies = new Map();
|
|
13
|
+
detectionResults = new Map();
|
|
14
|
+
detected = false;
|
|
15
|
+
/**
|
|
16
|
+
* Detect all strategies in parallel.
|
|
17
|
+
* Instantiates each strategy, calls detect(), and stores available ones.
|
|
18
|
+
*/
|
|
19
|
+
async detectAll() {
|
|
20
|
+
const allStrategies = [
|
|
21
|
+
new DirectStrategy(),
|
|
22
|
+
new SlurmStrategy(),
|
|
23
|
+
new DockerStrategy(),
|
|
24
|
+
new K8sExecStrategy(),
|
|
25
|
+
];
|
|
26
|
+
const results = await Promise.allSettled(allStrategies.map(async (strategy) => {
|
|
27
|
+
const detection = await strategy.detect();
|
|
28
|
+
// Always register the strategy instance so it can be retrieved
|
|
29
|
+
this.strategies.set(strategy.id, strategy);
|
|
30
|
+
const info = {
|
|
31
|
+
id: strategy.id,
|
|
32
|
+
name: strategy.name,
|
|
33
|
+
available: detection.available,
|
|
34
|
+
version: detection.version,
|
|
35
|
+
metadata: detection.metadata,
|
|
36
|
+
};
|
|
37
|
+
this.detectionResults.set(strategy.id, info);
|
|
38
|
+
return info;
|
|
39
|
+
}));
|
|
40
|
+
this.detected = true;
|
|
41
|
+
return results
|
|
42
|
+
.filter((r) => r.status === 'fulfilled')
|
|
43
|
+
.map((r) => r.value);
|
|
44
|
+
}
|
|
45
|
+
/**
|
|
46
|
+
* Get a specific strategy by ID.
|
|
47
|
+
* Returns null if the strategy hasn't been detected or isn't registered.
|
|
48
|
+
*/
|
|
49
|
+
get(id) {
|
|
50
|
+
return this.strategies.get(id) ?? null;
|
|
51
|
+
}
|
|
52
|
+
/**
|
|
53
|
+
* Get the default strategy (always DirectStrategy).
|
|
54
|
+
*/
|
|
55
|
+
getDefault() {
|
|
56
|
+
let direct = this.strategies.get('direct');
|
|
57
|
+
if (!direct) {
|
|
58
|
+
direct = new DirectStrategy();
|
|
59
|
+
this.strategies.set('direct', direct);
|
|
60
|
+
}
|
|
61
|
+
return direct;
|
|
62
|
+
}
|
|
63
|
+
/**
|
|
64
|
+
* List all detected strategies (available and unavailable).
|
|
65
|
+
*/
|
|
66
|
+
listAll() {
|
|
67
|
+
return Array.from(this.detectionResults.values());
|
|
68
|
+
}
|
|
69
|
+
/**
|
|
70
|
+
* List only available strategies.
|
|
71
|
+
*/
|
|
72
|
+
listAvailable() {
|
|
73
|
+
return Array.from(this.detectionResults.values()).filter((s) => s.available);
|
|
74
|
+
}
|
|
75
|
+
/**
|
|
76
|
+
* Check if detection has been run.
|
|
77
|
+
*/
|
|
78
|
+
isDetected() {
|
|
79
|
+
return this.detected;
|
|
80
|
+
}
|
|
81
|
+
}
|
|
82
|
+
/** Singleton registry instance */
|
|
83
|
+
export const executionStrategyRegistry = new ExecutionStrategyRegistry();
|
|
84
|
+
//# sourceMappingURL=registry.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"registry.js","sourceRoot":"","sources":["../../src/execution/registry.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAGH,OAAO,EAAE,cAAc,EAAE,MAAM,sBAAsB,CAAC;AACtD,OAAO,EAAE,aAAa,EAAE,MAAM,qBAAqB,CAAC;AACpD,OAAO,EAAE,cAAc,EAAE,MAAM,sBAAsB,CAAC;AACtD,OAAO,EAAE,eAAe,EAAE,MAAM,+BAA+B,CAAC;AAEhE,MAAM,OAAO,yBAAyB;IAC5B,UAAU,GAAG,IAAI,GAAG,EAA4C,CAAC;IACjE,gBAAgB,GAAG,IAAI,GAAG,EAAgD,CAAC;IAC3E,QAAQ,GAAG,KAAK,CAAC;IAEzB;;;OAGG;IACH,KAAK,CAAC,SAAS;QACb,MAAM,aAAa,GAAwB;YACzC,IAAI,cAAc,EAAE;YACpB,IAAI,aAAa,EAAE;YACnB,IAAI,cAAc,EAAE;YACpB,IAAI,eAAe,EAAE;SACtB,CAAC;QAEF,MAAM,OAAO,GAAG,MAAM,OAAO,CAAC,UAAU,CACtC,aAAa,CAAC,GAAG,CAAC,KAAK,EAAE,QAAQ,EAAkC,EAAE;YACnE,MAAM,SAAS,GAAG,MAAM,QAAQ,CAAC,MAAM,EAAE,CAAC;YAE1C,+DAA+D;YAC/D,IAAI,CAAC,UAAU,CAAC,GAAG,CAAC,QAAQ,CAAC,EAAE,EAAE,QAAQ,CAAC,CAAC;YAE3C,MAAM,IAAI,GAA0B;gBAClC,EAAE,EAAE,QAAQ,CAAC,EAAE;gBACf,IAAI,EAAE,QAAQ,CAAC,IAAI;gBACnB,SAAS,EAAE,SAAS,CAAC,SAAS;gBAC9B,OAAO,EAAE,SAAS,CAAC,OAAO;gBAC1B,QAAQ,EAAE,SAAS,CAAC,QAAQ;aAC7B,CAAC;YAEF,IAAI,CAAC,gBAAgB,CAAC,GAAG,CAAC,QAAQ,CAAC,EAAE,EAAE,IAAI,CAAC,CAAC;YAC7C,OAAO,IAAI,CAAC;QACd,CAAC,CAAC,CACH,CAAC;QAEF,IAAI,CAAC,QAAQ,GAAG,IAAI,CAAC;QAErB,OAAO,OAAO;aACX,MAAM,CAAC,CAAC,CAAC,EAAsD,EAAE,CAAC,CAAC,CAAC,MAAM,KAAK,WAAW,CAAC;aAC3F,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC;IACzB,CAAC;IAED;;;OAGG;IACH,GAAG,CAAC,EAAyB;QAC3B,OAAO,IAAI,CAAC,UAAU,CAAC,GAAG,CAAC,EAAE,CAAC,IAAI,IAAI,CAAC;IACzC,CAAC;IAED;;OAEG;IACH,UAAU;QACR,IAAI,MAAM,GAAG,IAAI,CAAC,UAAU,CAAC,GAAG,CAAC,QAAQ,CAAC,CAAC;QAC3C,IAAI,CAAC,MAAM,EAAE,CAAC;YACZ,MAAM,GAAG,IAAI,cAAc,EAAE,CAAC;YAC9B,IAAI,CAAC,UAAU,CAAC,GAAG,CAAC,QAAQ,EAAE,MAAM,CAAC,CAAC;QACxC,CAAC;QACD,OAAO,MAAM,CAAC;IAChB,CAAC;IAED;;OAEG;IACH,OAAO;QACL,OAAO,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,gBAAgB,CAAC,MAAM,EAAE,CAAC,CAAC;IACpD,CAAC;IAED;;OAEG;IACH,aAAa;QACX,OAAO,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,gBAAgB,CAAC,MAAM,EAAE,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,SAAS,CAAC,CAAC;IAC/E,CAAC;IAED;;OAEG;IACH,UAAU;QACR,OAAO,IAAI,CAAC,QAAQ,CAAC;IACvB,CAAC;CACF;AAED,kCAAkC;AAClC,MAAM,CAAC,MAAM,yBAAyB,GAAG,IAAI,yBAAyB,EAAE,CAAC"}
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* SLURM Execution Strategy
|
|
3
|
+
*
|
|
4
|
+
* Wraps existing lib/slurm-detect.ts, lib/slurm-executor.ts, and lib/hpc-context.ts.
|
|
5
|
+
* Does not duplicate logic — delegates to the proven SLURM modules.
|
|
6
|
+
*/
|
|
7
|
+
import type { ExecutionStrategy, ExecutionSpec, ExecutionCallbacks, ExecutionResult, ExecutionStrategyDetection, ExecutionJobStatus } from './types.js';
|
|
8
|
+
export declare class SlurmStrategy implements ExecutionStrategy {
|
|
9
|
+
readonly id: "slurm";
|
|
10
|
+
readonly name = "SLURM HPC";
|
|
11
|
+
readonly isAsync = true;
|
|
12
|
+
private slurmInfo;
|
|
13
|
+
private executor;
|
|
14
|
+
/** Maps jobId → slurmJobId */
|
|
15
|
+
private jobMap;
|
|
16
|
+
detect(): Promise<ExecutionStrategyDetection>;
|
|
17
|
+
buildContext(): Promise<string>;
|
|
18
|
+
execute(spec: ExecutionSpec, callbacks: ExecutionCallbacks, signal: AbortSignal): Promise<ExecutionResult>;
|
|
19
|
+
cancel(jobId: string): Promise<void>;
|
|
20
|
+
getStatus(jobId: string): Promise<ExecutionJobStatus | null>;
|
|
21
|
+
}
|
|
22
|
+
//# sourceMappingURL=slurm-strategy.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"slurm-strategy.d.ts","sourceRoot":"","sources":["../../src/execution/slurm-strategy.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAQH,OAAO,KAAK,EACV,iBAAiB,EACjB,aAAa,EACb,kBAAkB,EAClB,eAAe,EACf,0BAA0B,EAC1B,kBAAkB,EACnB,MAAM,YAAY,CAAC;AAIpB,qBAAa,aAAc,YAAW,iBAAiB;IACrD,QAAQ,CAAC,EAAE,EAAG,OAAO,CAAU;IAC/B,QAAQ,CAAC,IAAI,eAAe;IAC5B,QAAQ,CAAC,OAAO,QAAQ;IAExB,OAAO,CAAC,SAAS,CAA0B;IAC3C,OAAO,CAAC,QAAQ,CAA8B;IAC9C,8BAA8B;IAC9B,OAAO,CAAC,MAAM,CAA6B;IAErC,MAAM,IAAI,OAAO,CAAC,0BAA0B,CAAC;IAwB7C,YAAY,IAAI,OAAO,CAAC,MAAM,CAAC;IAK/B,OAAO,CACX,IAAI,EAAE,aAAa,EACnB,SAAS,EAAE,kBAAkB,EAC7B,MAAM,EAAE,WAAW,GAClB,OAAO,CAAC,eAAe,CAAC;IA2FrB,MAAM,CAAC,KAAK,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;IAkBpC,SAAS,CAAC,KAAK,EAAE,MAAM,GAAG,OAAO,CAAC,kBAAkB,GAAG,IAAI,CAAC;CAqDnE"}
|
|
@@ -0,0 +1,219 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* SLURM Execution Strategy
|
|
3
|
+
*
|
|
4
|
+
* Wraps existing lib/slurm-detect.ts, lib/slurm-executor.ts, and lib/hpc-context.ts.
|
|
5
|
+
* Does not duplicate logic — delegates to the proven SLURM modules.
|
|
6
|
+
*/
|
|
7
|
+
import { exec } from 'node:child_process';
|
|
8
|
+
import { promisify } from 'node:util';
|
|
9
|
+
import { detectSlurm } from '../lib/slurm-detect.js';
|
|
10
|
+
import { SlurmExecutor } from '../lib/slurm-executor.js';
|
|
11
|
+
import { buildHpcContext } from '../lib/hpc-context.js';
|
|
12
|
+
const execAsync = promisify(exec);
|
|
13
|
+
export class SlurmStrategy {
|
|
14
|
+
id = 'slurm';
|
|
15
|
+
name = 'SLURM HPC';
|
|
16
|
+
isAsync = true;
|
|
17
|
+
slurmInfo = null;
|
|
18
|
+
executor = null;
|
|
19
|
+
/** Maps jobId → slurmJobId */
|
|
20
|
+
jobMap = new Map();
|
|
21
|
+
async detect() {
|
|
22
|
+
try {
|
|
23
|
+
this.slurmInfo = await detectSlurm();
|
|
24
|
+
if (!this.slurmInfo.available) {
|
|
25
|
+
return { available: false };
|
|
26
|
+
}
|
|
27
|
+
return {
|
|
28
|
+
available: true,
|
|
29
|
+
version: this.slurmInfo.version,
|
|
30
|
+
metadata: {
|
|
31
|
+
clusterName: this.slurmInfo.clusterName,
|
|
32
|
+
partitions: this.slurmInfo.partitions,
|
|
33
|
+
defaultPartition: this.slurmInfo.defaultPartition,
|
|
34
|
+
accounts: this.slurmInfo.accounts,
|
|
35
|
+
qosLevels: this.slurmInfo.qosLevels,
|
|
36
|
+
},
|
|
37
|
+
};
|
|
38
|
+
}
|
|
39
|
+
catch {
|
|
40
|
+
return { available: false };
|
|
41
|
+
}
|
|
42
|
+
}
|
|
43
|
+
async buildContext() {
|
|
44
|
+
const hpcContext = await buildHpcContext();
|
|
45
|
+
return hpcContext.contextString;
|
|
46
|
+
}
|
|
47
|
+
async execute(spec, callbacks, signal) {
|
|
48
|
+
if (signal.aborted) {
|
|
49
|
+
return { status: 'cancelled' };
|
|
50
|
+
}
|
|
51
|
+
// Ensure detection has run
|
|
52
|
+
if (!this.slurmInfo?.available) {
|
|
53
|
+
const detection = await this.detect();
|
|
54
|
+
if (!detection.available || !this.slurmInfo) {
|
|
55
|
+
return {
|
|
56
|
+
status: 'failed',
|
|
57
|
+
error: 'SLURM is not available on this machine',
|
|
58
|
+
};
|
|
59
|
+
}
|
|
60
|
+
}
|
|
61
|
+
if (!this.executor) {
|
|
62
|
+
this.executor = new SlurmExecutor(this.slurmInfo);
|
|
63
|
+
}
|
|
64
|
+
// Parse slurm config from spec.options
|
|
65
|
+
const slurmConfig = {};
|
|
66
|
+
const opts = spec.options ?? {};
|
|
67
|
+
if (opts.partition)
|
|
68
|
+
slurmConfig.partition = String(opts.partition);
|
|
69
|
+
if (opts.nodes)
|
|
70
|
+
slurmConfig.nodes = Number(opts.nodes);
|
|
71
|
+
if (opts.ntasks)
|
|
72
|
+
slurmConfig.ntasks = Number(opts.ntasks);
|
|
73
|
+
if (opts.cpusPerTask)
|
|
74
|
+
slurmConfig.cpusPerTask = Number(opts.cpusPerTask);
|
|
75
|
+
if (opts.mem)
|
|
76
|
+
slurmConfig.mem = String(opts.mem);
|
|
77
|
+
if (opts.time)
|
|
78
|
+
slurmConfig.time = String(opts.time);
|
|
79
|
+
if (opts.qos)
|
|
80
|
+
slurmConfig.qos = String(opts.qos);
|
|
81
|
+
if (opts.account)
|
|
82
|
+
slurmConfig.account = String(opts.account);
|
|
83
|
+
if (opts.modules)
|
|
84
|
+
slurmConfig.modules = opts.modules;
|
|
85
|
+
if (opts.gpu)
|
|
86
|
+
slurmConfig.gpu = opts.gpu;
|
|
87
|
+
const command = typeof spec.command === 'string' ? spec.command : spec.command.join(' ');
|
|
88
|
+
const slurmTask = {
|
|
89
|
+
taskId: spec.jobId,
|
|
90
|
+
projectId: opts.projectId || 'unknown',
|
|
91
|
+
nodeId: opts.nodeId || 'unknown',
|
|
92
|
+
title: command.substring(0, 80),
|
|
93
|
+
description: command,
|
|
94
|
+
workingDirectory: spec.cwd,
|
|
95
|
+
config: slurmConfig,
|
|
96
|
+
};
|
|
97
|
+
try {
|
|
98
|
+
const result = await this.executor.execute(slurmTask, {
|
|
99
|
+
onStatus: (jobStatus) => {
|
|
100
|
+
const stateMap = {
|
|
101
|
+
'PENDING': 'Job pending in queue',
|
|
102
|
+
'RUNNING': 'Job running',
|
|
103
|
+
'COMPLETING': 'Job completing',
|
|
104
|
+
'COMPLETED': 'Job completed',
|
|
105
|
+
'FAILED': 'Job failed',
|
|
106
|
+
'CANCELLED': 'Job cancelled',
|
|
107
|
+
'TIMEOUT': 'Job timed out',
|
|
108
|
+
};
|
|
109
|
+
const message = stateMap[jobStatus.state] || `Job state: ${jobStatus.state}`;
|
|
110
|
+
const progress = jobStatus.state === 'RUNNING' ? 50 : jobStatus.state === 'COMPLETING' ? 90 : undefined;
|
|
111
|
+
callbacks.onStatus(jobStatus.state, progress, message);
|
|
112
|
+
},
|
|
113
|
+
onOutput: (stream, data) => {
|
|
114
|
+
if (stream === 'stdout') {
|
|
115
|
+
callbacks.onStdout(data);
|
|
116
|
+
}
|
|
117
|
+
else {
|
|
118
|
+
callbacks.onStderr(data);
|
|
119
|
+
}
|
|
120
|
+
},
|
|
121
|
+
signal,
|
|
122
|
+
});
|
|
123
|
+
if (result.slurmJobId) {
|
|
124
|
+
this.jobMap.set(spec.jobId, result.slurmJobId);
|
|
125
|
+
}
|
|
126
|
+
return {
|
|
127
|
+
status: result.status === 'completed' ? 'completed' : result.status === 'cancelled' ? 'cancelled' : 'failed',
|
|
128
|
+
exitCode: result.exitCode,
|
|
129
|
+
output: result.output,
|
|
130
|
+
error: result.error,
|
|
131
|
+
externalJobId: result.slurmJobId,
|
|
132
|
+
};
|
|
133
|
+
}
|
|
134
|
+
catch (error) {
|
|
135
|
+
return {
|
|
136
|
+
status: 'failed',
|
|
137
|
+
error: error instanceof Error ? error.message : String(error),
|
|
138
|
+
};
|
|
139
|
+
}
|
|
140
|
+
}
|
|
141
|
+
async cancel(jobId) {
|
|
142
|
+
// Try executor's cancel (by taskId)
|
|
143
|
+
if (this.executor) {
|
|
144
|
+
await this.executor.cancel(jobId);
|
|
145
|
+
}
|
|
146
|
+
// Also try scancel with the slurm job ID
|
|
147
|
+
const slurmJobId = this.jobMap.get(jobId);
|
|
148
|
+
if (slurmJobId) {
|
|
149
|
+
try {
|
|
150
|
+
await execAsync(`scancel ${sanitizedSlurmJobId(slurmJobId)}`, { timeout: 10000 });
|
|
151
|
+
}
|
|
152
|
+
catch {
|
|
153
|
+
// Job may have already finished
|
|
154
|
+
}
|
|
155
|
+
this.jobMap.delete(jobId);
|
|
156
|
+
}
|
|
157
|
+
}
|
|
158
|
+
async getStatus(jobId) {
|
|
159
|
+
const slurmJobId = this.jobMap.get(jobId);
|
|
160
|
+
if (!slurmJobId)
|
|
161
|
+
return null;
|
|
162
|
+
const safeJobId = sanitizedSlurmJobId(slurmJobId);
|
|
163
|
+
// Try squeue first (running jobs)
|
|
164
|
+
try {
|
|
165
|
+
const { stdout } = await execAsync(`squeue -j ${safeJobId} -h -o "%T|%r" 2>/dev/null`, { timeout: 10000 });
|
|
166
|
+
const trimmed = stdout.trim();
|
|
167
|
+
if (trimmed) {
|
|
168
|
+
const [state, reason] = trimmed.split('|');
|
|
169
|
+
return {
|
|
170
|
+
jobId,
|
|
171
|
+
externalJobId: slurmJobId,
|
|
172
|
+
state: state || 'UNKNOWN',
|
|
173
|
+
message: reason !== '(null)' ? reason : undefined,
|
|
174
|
+
};
|
|
175
|
+
}
|
|
176
|
+
}
|
|
177
|
+
catch {
|
|
178
|
+
// Not in queue
|
|
179
|
+
}
|
|
180
|
+
// Try sacct (completed jobs)
|
|
181
|
+
try {
|
|
182
|
+
const { stdout } = await execAsync(`sacct -j ${safeJobId} --parsable2 --noheader -o State,ExitCode 2>/dev/null`, { timeout: 10000 });
|
|
183
|
+
const lines = stdout.trim().split('\n');
|
|
184
|
+
const mainLine = lines.find((l) => !l.includes('.'));
|
|
185
|
+
if (mainLine) {
|
|
186
|
+
const [state, exitCodeRaw] = mainLine.split('|');
|
|
187
|
+
let exitCode;
|
|
188
|
+
if (exitCodeRaw?.includes(':')) {
|
|
189
|
+
exitCode = parseInt(exitCodeRaw.split(':')[0]);
|
|
190
|
+
}
|
|
191
|
+
return {
|
|
192
|
+
jobId,
|
|
193
|
+
externalJobId: slurmJobId,
|
|
194
|
+
state: state?.split(' ')[0] || 'UNKNOWN',
|
|
195
|
+
exitCode,
|
|
196
|
+
};
|
|
197
|
+
}
|
|
198
|
+
}
|
|
199
|
+
catch {
|
|
200
|
+
// sacct failed
|
|
201
|
+
}
|
|
202
|
+
return null;
|
|
203
|
+
}
|
|
204
|
+
}
|
|
205
|
+
// ============================================================================
|
|
206
|
+
// Input Validation
|
|
207
|
+
// ============================================================================
|
|
208
|
+
/** SLURM job IDs are always numeric (optionally with array syntax like 12345_1) */
|
|
209
|
+
function isValidSlurmJobId(id) {
|
|
210
|
+
return /^\d+(_\d+)?$/.test(id);
|
|
211
|
+
}
|
|
212
|
+
/** Validate and return a safe SLURM job ID, or throw. Prevents command injection. */
|
|
213
|
+
function sanitizedSlurmJobId(id) {
|
|
214
|
+
if (!isValidSlurmJobId(id)) {
|
|
215
|
+
throw new Error(`Invalid SLURM job ID (possible command injection): ${id}`);
|
|
216
|
+
}
|
|
217
|
+
return id;
|
|
218
|
+
}
|
|
219
|
+
//# sourceMappingURL=slurm-strategy.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"slurm-strategy.js","sourceRoot":"","sources":["../../src/execution/slurm-strategy.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,72 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Execution Strategy Types
|
|
3
|
+
*
|
|
4
|
+
* Core interfaces for the execution strategy abstraction. Execution strategies
|
|
5
|
+
* are orthogonal to agent models (Claude, Codex): a strategy defines HOW a
|
|
6
|
+
* command runs (direct spawn, SLURM batch, Docker container, K8s pod),
|
|
7
|
+
* while a provider defines WHAT reasons about the task.
|
|
8
|
+
*/
|
|
9
|
+
export type ExecutionStrategyType = 'direct' | 'slurm' | 'docker' | 'k8s-exec';
|
|
10
|
+
export interface ExecutionStrategy {
|
|
11
|
+
/** Unique strategy identifier */
|
|
12
|
+
readonly id: ExecutionStrategyType;
|
|
13
|
+
/** Human-readable name */
|
|
14
|
+
readonly name: string;
|
|
15
|
+
/** True for submit-and-monitor strategies (SLURM) */
|
|
16
|
+
readonly isAsync: boolean;
|
|
17
|
+
/** Capability 1: Detection — probe environment for availability and metadata */
|
|
18
|
+
detect(): Promise<ExecutionStrategyDetection>;
|
|
19
|
+
/** Capability 2: Context injection — optional prompt prefix for AI awareness */
|
|
20
|
+
buildContext?(): Promise<string>;
|
|
21
|
+
/** Capability 3: Job submission — execute a command with streaming callbacks */
|
|
22
|
+
execute(spec: ExecutionSpec, callbacks: ExecutionCallbacks, signal: AbortSignal): Promise<ExecutionResult>;
|
|
23
|
+
/** Capability 4+5: Cancel a running/queued job */
|
|
24
|
+
cancel(jobId: string): Promise<void>;
|
|
25
|
+
/** Capability 4+5: Get current status of a job */
|
|
26
|
+
getStatus(jobId: string): Promise<ExecutionJobStatus | null>;
|
|
27
|
+
}
|
|
28
|
+
export interface ExecutionStrategyDetection {
|
|
29
|
+
available: boolean;
|
|
30
|
+
version?: string;
|
|
31
|
+
/** Strategy-specific metadata: partitions, namespaces, clouds, etc. */
|
|
32
|
+
metadata?: Record<string, unknown>;
|
|
33
|
+
}
|
|
34
|
+
export interface ExecutionSpec {
|
|
35
|
+
jobId: string;
|
|
36
|
+
command: string | string[];
|
|
37
|
+
cwd: string;
|
|
38
|
+
env?: Record<string, string>;
|
|
39
|
+
timeout?: number;
|
|
40
|
+
/** Strategy-specific options: partition, image, pod, cloud, etc. */
|
|
41
|
+
options?: Record<string, unknown>;
|
|
42
|
+
}
|
|
43
|
+
export interface ExecutionCallbacks {
|
|
44
|
+
onStdout(data: string): void;
|
|
45
|
+
onStderr(data: string): void;
|
|
46
|
+
onStatus(status: string, progress?: number, message?: string): void;
|
|
47
|
+
}
|
|
48
|
+
export interface ExecutionResult {
|
|
49
|
+
status: 'completed' | 'failed' | 'cancelled' | 'timeout';
|
|
50
|
+
exitCode?: number;
|
|
51
|
+
output?: string;
|
|
52
|
+
error?: string;
|
|
53
|
+
/** External job ID: SLURM job ID, container ID, pod name, sky cluster */
|
|
54
|
+
externalJobId?: string;
|
|
55
|
+
}
|
|
56
|
+
export interface ExecutionJobStatus {
|
|
57
|
+
jobId: string;
|
|
58
|
+
externalJobId: string;
|
|
59
|
+
state: string;
|
|
60
|
+
progress?: number;
|
|
61
|
+
message?: string;
|
|
62
|
+
startedAt?: string;
|
|
63
|
+
exitCode?: number;
|
|
64
|
+
}
|
|
65
|
+
export interface ExecutionStrategyInfo {
|
|
66
|
+
id: ExecutionStrategyType;
|
|
67
|
+
name: string;
|
|
68
|
+
available: boolean;
|
|
69
|
+
version?: string;
|
|
70
|
+
metadata?: Record<string, unknown>;
|
|
71
|
+
}
|
|
72
|
+
//# sourceMappingURL=types.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../src/execution/types.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAMH,MAAM,MAAM,qBAAqB,GAAG,QAAQ,GAAG,OAAO,GAAG,QAAQ,GAAG,UAAU,CAAC;AAM/E,MAAM,WAAW,iBAAiB;IAChC,iCAAiC;IACjC,QAAQ,CAAC,EAAE,EAAE,qBAAqB,CAAC;IAEnC,0BAA0B;IAC1B,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IAEtB,qDAAqD;IACrD,QAAQ,CAAC,OAAO,EAAE,OAAO,CAAC;IAE1B,gFAAgF;IAChF,MAAM,IAAI,OAAO,CAAC,0BAA0B,CAAC,CAAC;IAE9C,gFAAgF;IAChF,YAAY,CAAC,IAAI,OAAO,CAAC,MAAM,CAAC,CAAC;IAEjC,gFAAgF;IAChF,OAAO,CAAC,IAAI,EAAE,aAAa,EAAE,SAAS,EAAE,kBAAkB,EAAE,MAAM,EAAE,WAAW,GAAG,OAAO,CAAC,eAAe,CAAC,CAAC;IAE3G,kDAAkD;IAClD,MAAM,CAAC,KAAK,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;IAErC,kDAAkD;IAClD,SAAS,CAAC,KAAK,EAAE,MAAM,GAAG,OAAO,CAAC,kBAAkB,GAAG,IAAI,CAAC,CAAC;CAC9D;AAMD,MAAM,WAAW,0BAA0B;IACzC,SAAS,EAAE,OAAO,CAAC;IACnB,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,uEAAuE;IACvE,QAAQ,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;CACpC;AAMD,MAAM,WAAW,aAAa;IAC5B,KAAK,EAAE,MAAM,CAAC;IACd,OAAO,EAAE,MAAM,GAAG,MAAM,EAAE,CAAC;IAC3B,GAAG,EAAE,MAAM,CAAC;IACZ,GAAG,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IAC7B,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,oEAAoE;IACpE,OAAO,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;CACnC;AAED,MAAM,WAAW,kBAAkB;IACjC,QAAQ,CAAC,IAAI,EAAE,MAAM,GAAG,IAAI,CAAC;IAC7B,QAAQ,CAAC,IAAI,EAAE,MAAM,GAAG,IAAI,CAAC;IAC7B,QAAQ,CAAC,MAAM,EAAE,MAAM,EAAE,QAAQ,CAAC,EAAE,MAAM,EAAE,OAAO,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;CACrE;AAMD,MAAM,WAAW,eAAe;IAC9B,MAAM,EAAE,WAAW,GAAG,QAAQ,GAAG,WAAW,GAAG,SAAS,CAAC;IACzD,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,yEAAyE;IACzE,aAAa,CAAC,EAAE,MAAM,CAAC;CACxB;AAMD,MAAM,WAAW,kBAAkB;IACjC,KAAK,EAAE,MAAM,CAAC;IACd,aAAa,EAAE,MAAM,CAAC;IACtB,KAAK,EAAE,MAAM,CAAC;IACd,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,QAAQ,CAAC,EAAE,MAAM,CAAC;CACnB;AAMD,MAAM,WAAW,qBAAqB;IACpC,EAAE,EAAE,qBAAqB,CAAC;IAC1B,IAAI,EAAE,MAAM,CAAC;IACb,SAAS,EAAE,OAAO,CAAC;IACnB,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,QAAQ,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;CACpC"}
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Execution Strategy Types
|
|
3
|
+
*
|
|
4
|
+
* Core interfaces for the execution strategy abstraction. Execution strategies
|
|
5
|
+
* are orthogonal to agent models (Claude, Codex): a strategy defines HOW a
|
|
6
|
+
* command runs (direct spawn, SLURM batch, Docker container, K8s pod),
|
|
7
|
+
* while a provider defines WHAT reasons about the task.
|
|
8
|
+
*/
|
|
9
|
+
export {};
|
|
10
|
+
//# sourceMappingURL=types.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"types.js","sourceRoot":"","sources":["../../src/execution/types.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG"}
|
package/dist/index.d.ts
ADDED
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Astro Agent Runner
|
|
3
|
+
*
|
|
4
|
+
* Lightweight agent runner for local, remote, and HPC environments.
|
|
5
|
+
* Exports the public API for programmatic use.
|
|
6
|
+
*/
|
|
7
|
+
export type { ProviderType, ProviderInfo, ProviderCapabilities, MachineResources, CpuInfo, MemoryInfo, GpuInfo, Task, TaskResult, TaskStatus, TaskArtifact, WSMessage, WSMessageType, RunnerConfig, StoredConfig, SSHHost, DiscoveredHost, DeviceAuthRequest, DeviceAuthResult, RunnerEvent, RunnerEventHandler, SlurmInfo, SlurmPartitionDetail, SlurmJobStatus, SlurmJobConfig, } from './types.js';
|
|
8
|
+
export { getMachineResources, formatBytes, formatResourceSummary } from './lib/resources.js';
|
|
9
|
+
export { detectProviders, getProvider, isProviderAvailable, formatProviderInfo, formatProvidersSummary } from './lib/providers.js';
|
|
10
|
+
export { discoverRemoteHosts, formatDiscoveredHosts, buildSSHCommand } from './lib/ssh-discovery.js';
|
|
11
|
+
export { WebSocketClient, type WebSocketClientOptions } from './lib/websocket-client.js';
|
|
12
|
+
export { TaskExecutor, type TaskExecutorOptions } from './lib/task-executor.js';
|
|
13
|
+
export { config, ConfigManager } from './lib/config.js';
|
|
14
|
+
export { detectSlurm, getPartitionInfo } from './lib/slurm-detect.js';
|
|
15
|
+
export { SlurmExecutor } from './lib/slurm-executor.js';
|
|
16
|
+
export type { SlurmTaskInput, SlurmExecuteOptions, SlurmExecuteResult } from './lib/slurm-executor.js';
|
|
17
|
+
export { createProviderAdapter, getAvailableAdapters } from './providers/index.js';
|
|
18
|
+
export type { ProviderAdapter, TaskOutputStream, ProviderStatus } from './providers/base-adapter.js';
|
|
19
|
+
export { ClaudeCodeAdapter } from './providers/claude-code-adapter.js';
|
|
20
|
+
export { CodexAdapter } from './providers/codex-adapter.js';
|
|
21
|
+
export { SlurmAdapter } from './providers/slurm-adapter.js';
|
|
22
|
+
//# sourceMappingURL=index.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAGH,YAAY,EACV,YAAY,EACZ,YAAY,EACZ,oBAAoB,EACpB,gBAAgB,EAChB,OAAO,EACP,UAAU,EACV,OAAO,EACP,IAAI,EACJ,UAAU,EACV,UAAU,EACV,YAAY,EACZ,SAAS,EACT,aAAa,EACb,YAAY,EACZ,YAAY,EACZ,OAAO,EACP,cAAc,EACd,iBAAiB,EACjB,gBAAgB,EAChB,WAAW,EACX,kBAAkB,EAClB,SAAS,EACT,oBAAoB,EACpB,cAAc,EACd,cAAc,GACf,MAAM,YAAY,CAAC;AAGpB,OAAO,EAAE,mBAAmB,EAAE,WAAW,EAAE,qBAAqB,EAAE,MAAM,oBAAoB,CAAC;AAC7F,OAAO,EAAE,eAAe,EAAE,WAAW,EAAE,mBAAmB,EAAE,kBAAkB,EAAE,sBAAsB,EAAE,MAAM,oBAAoB,CAAC;AACnI,OAAO,EAAE,mBAAmB,EAAE,qBAAqB,EAAE,eAAe,EAAE,MAAM,wBAAwB,CAAC;AACrG,OAAO,EAAE,eAAe,EAAE,KAAK,sBAAsB,EAAE,MAAM,2BAA2B,CAAC;AACzF,OAAO,EAAE,YAAY,EAAE,KAAK,mBAAmB,EAAE,MAAM,wBAAwB,CAAC;AAChF,OAAO,EAAE,MAAM,EAAE,aAAa,EAAE,MAAM,iBAAiB,CAAC;AAGxD,OAAO,EAAE,WAAW,EAAE,gBAAgB,EAAE,MAAM,uBAAuB,CAAC;AACtE,OAAO,EAAE,aAAa,EAAE,MAAM,yBAAyB,CAAC;AACxD,YAAY,EAAE,cAAc,EAAE,mBAAmB,EAAE,kBAAkB,EAAE,MAAM,yBAAyB,CAAC;AAGvG,OAAO,EAAE,qBAAqB,EAAE,oBAAoB,EAAE,MAAM,sBAAsB,CAAC;AACnF,YAAY,EAAE,eAAe,EAAE,gBAAgB,EAAE,cAAc,EAAE,MAAM,6BAA6B,CAAC;AACrG,OAAO,EAAE,iBAAiB,EAAE,MAAM,oCAAoC,CAAC;AACvE,OAAO,EAAE,YAAY,EAAE,MAAM,8BAA8B,CAAC;AAC5D,OAAO,EAAE,YAAY,EAAE,MAAM,8BAA8B,CAAC"}
|
package/dist/index.js
ADDED
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Astro Agent Runner
|
|
3
|
+
*
|
|
4
|
+
* Lightweight agent runner for local, remote, and HPC environments.
|
|
5
|
+
* Exports the public API for programmatic use.
|
|
6
|
+
*/
|
|
7
|
+
// Library exports
|
|
8
|
+
export { getMachineResources, formatBytes, formatResourceSummary } from './lib/resources.js';
|
|
9
|
+
export { detectProviders, getProvider, isProviderAvailable, formatProviderInfo, formatProvidersSummary } from './lib/providers.js';
|
|
10
|
+
export { discoverRemoteHosts, formatDiscoveredHosts, buildSSHCommand } from './lib/ssh-discovery.js';
|
|
11
|
+
export { WebSocketClient } from './lib/websocket-client.js';
|
|
12
|
+
export { TaskExecutor } from './lib/task-executor.js';
|
|
13
|
+
export { config, ConfigManager } from './lib/config.js';
|
|
14
|
+
// Slurm lib
|
|
15
|
+
export { detectSlurm, getPartitionInfo } from './lib/slurm-detect.js';
|
|
16
|
+
export { SlurmExecutor } from './lib/slurm-executor.js';
|
|
17
|
+
// Provider adapters
|
|
18
|
+
export { createProviderAdapter, getAvailableAdapters } from './providers/index.js';
|
|
19
|
+
export { ClaudeCodeAdapter } from './providers/claude-code-adapter.js';
|
|
20
|
+
export { CodexAdapter } from './providers/codex-adapter.js';
|
|
21
|
+
export { SlurmAdapter } from './providers/slurm-adapter.js';
|
|
22
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AA+BH,kBAAkB;AAClB,OAAO,EAAE,mBAAmB,EAAE,WAAW,EAAE,qBAAqB,EAAE,MAAM,oBAAoB,CAAC;AAC7F,OAAO,EAAE,eAAe,EAAE,WAAW,EAAE,mBAAmB,EAAE,kBAAkB,EAAE,sBAAsB,EAAE,MAAM,oBAAoB,CAAC;AACnI,OAAO,EAAE,mBAAmB,EAAE,qBAAqB,EAAE,eAAe,EAAE,MAAM,wBAAwB,CAAC;AACrG,OAAO,EAAE,eAAe,EAA+B,MAAM,2BAA2B,CAAC;AACzF,OAAO,EAAE,YAAY,EAA4B,MAAM,wBAAwB,CAAC;AAChF,OAAO,EAAE,MAAM,EAAE,aAAa,EAAE,MAAM,iBAAiB,CAAC;AAExD,YAAY;AACZ,OAAO,EAAE,WAAW,EAAE,gBAAgB,EAAE,MAAM,uBAAuB,CAAC;AACtE,OAAO,EAAE,aAAa,EAAE,MAAM,yBAAyB,CAAC;AAGxD,oBAAoB;AACpB,OAAO,EAAE,qBAAqB,EAAE,oBAAoB,EAAE,MAAM,sBAAsB,CAAC;AAEnF,OAAO,EAAE,iBAAiB,EAAE,MAAM,oCAAoC,CAAC;AACvE,OAAO,EAAE,YAAY,EAAE,MAAM,8BAA8B,CAAC;AAC5D,OAAO,EAAE,YAAY,EAAE,MAAM,8BAA8B,CAAC"}
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* HTTP client for device auth using native fetch (Node 18+)
|
|
3
|
+
*/
|
|
4
|
+
import type { DeviceAuthServerResponse, DeviceTokenServerResponse, MachineRegisterResponse } from '../types.js';
|
|
5
|
+
export type DeviceAuthErrorCode = 'network' | 'timeout' | 'denied' | 'expired' | 'server_error';
|
|
6
|
+
export declare class DeviceAuthApiError extends Error {
|
|
7
|
+
readonly code: DeviceAuthErrorCode;
|
|
8
|
+
readonly statusCode?: number | undefined;
|
|
9
|
+
constructor(message: string, code: DeviceAuthErrorCode, statusCode?: number | undefined);
|
|
10
|
+
}
|
|
11
|
+
/**
|
|
12
|
+
* Request a device authorization code from the backend.
|
|
13
|
+
* POST /api/device/authorize
|
|
14
|
+
*/
|
|
15
|
+
export declare function requestDeviceCode(apiUrl: string, machineInfo: {
|
|
16
|
+
hostname: string;
|
|
17
|
+
platform: string;
|
|
18
|
+
}): Promise<DeviceAuthServerResponse>;
|
|
19
|
+
/**
|
|
20
|
+
* Poll the backend until the user authorizes (or denies/expires).
|
|
21
|
+
* POST /api/device/token
|
|
22
|
+
*
|
|
23
|
+
* Handles RFC 8628 states:
|
|
24
|
+
* authorization_pending → keep polling
|
|
25
|
+
* slow_down → increase interval +5s
|
|
26
|
+
* access_denied → throw
|
|
27
|
+
* expired_token → throw
|
|
28
|
+
*/
|
|
29
|
+
export declare function pollForToken(apiUrl: string, userCode: string, intervalSec: number, timeoutSec: number): Promise<DeviceTokenServerResponse>;
|
|
30
|
+
/**
|
|
31
|
+
* Register an authenticated machine with the backend.
|
|
32
|
+
* POST /api/device/register (Bearer token)
|
|
33
|
+
*/
|
|
34
|
+
export declare function registerMachine(apiUrl: string, accessToken: string, machineInfo: Record<string, unknown>): Promise<MachineRegisterResponse>;
|
|
35
|
+
//# sourceMappingURL=api-client.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"api-client.d.ts","sourceRoot":"","sources":["../../src/lib/api-client.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,OAAO,KAAK,EACV,wBAAwB,EACxB,yBAAyB,EAEzB,uBAAuB,EACxB,MAAM,aAAa,CAAC;AAMrB,MAAM,MAAM,mBAAmB,GAAG,SAAS,GAAG,SAAS,GAAG,QAAQ,GAAG,SAAS,GAAG,cAAc,CAAC;AAEhG,qBAAa,kBAAmB,SAAQ,KAAK;aAGzB,IAAI,EAAE,mBAAmB;aACzB,UAAU,CAAC,EAAE,MAAM;gBAFnC,OAAO,EAAE,MAAM,EACC,IAAI,EAAE,mBAAmB,EACzB,UAAU,CAAC,EAAE,MAAM,YAAA;CAKtC;AAMD;;;GAGG;AACH,wBAAsB,iBAAiB,CACrC,MAAM,EAAE,MAAM,EACd,WAAW,EAAE;IAAE,QAAQ,EAAE,MAAM,CAAC;IAAC,QAAQ,EAAE,MAAM,CAAA;CAAE,GAClD,OAAO,CAAC,wBAAwB,CAAC,CA4BnC;AAED;;;;;;;;;GASG;AACH,wBAAsB,YAAY,CAChC,MAAM,EAAE,MAAM,EACd,QAAQ,EAAE,MAAM,EAChB,WAAW,EAAE,MAAM,EACnB,UAAU,EAAE,MAAM,GACjB,OAAO,CAAC,yBAAyB,CAAC,CAsDpC;AAED;;;GAGG;AACH,wBAAsB,eAAe,CACnC,MAAM,EAAE,MAAM,EACd,WAAW,EAAE,MAAM,EACnB,WAAW,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GACnC,OAAO,CAAC,uBAAuB,CAAC,CA4BlC"}
|