@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,212 @@
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 { execFile } from 'node:child_process';
9
+ import { promisify } from 'node:util';
10
+ import { open, stat } from 'node:fs/promises';
11
+ import { readFile } from 'node:fs/promises';
12
+ const execFileAsync = promisify(execFile);
13
+ /** SLURM job IDs are numeric (optionally with array syntax like 12345_1). Validates and returns. */
14
+ function sanitizedSlurmJobId(id) {
15
+ if (!/^\d+(_\d+)?$/.test(id)) {
16
+ throw new Error(`Invalid SLURM job ID (possible command injection): ${id}`);
17
+ }
18
+ return id;
19
+ }
20
+ /** Terminal Slurm states */
21
+ const TERMINAL_STATES = new Set([
22
+ 'COMPLETED', 'FAILED', 'CANCELLED', 'TIMEOUT',
23
+ 'PREEMPTED', 'NODE_FAIL', 'OUT_OF_MEMORY',
24
+ ]);
25
+ export class SlurmJobMonitor {
26
+ jobs = new Map();
27
+ pollInterval = null;
28
+ wsClient;
29
+ pollIntervalMs;
30
+ constructor(wsClient, pollIntervalMs = 30_000) {
31
+ this.wsClient = wsClient;
32
+ this.pollIntervalMs = pollIntervalMs;
33
+ }
34
+ /**
35
+ * Track a submitted Slurm job
36
+ */
37
+ trackJob(slurmJobId, executionId, nodeId, outputPath) {
38
+ console.log(`[slurm-monitor] Tracking job ${slurmJobId} for task ${executionId}`);
39
+ this.jobs.set(slurmJobId, {
40
+ slurmJobId,
41
+ executionId,
42
+ nodeId,
43
+ outputPath,
44
+ lastOutputOffset: 0,
45
+ stdoutSequence: 0,
46
+ trackingSince: new Date(),
47
+ });
48
+ // Start polling if not already running
49
+ if (!this.pollInterval) {
50
+ this.start();
51
+ }
52
+ }
53
+ /**
54
+ * Stop tracking a job
55
+ */
56
+ untrackJob(slurmJobId) {
57
+ this.jobs.delete(slurmJobId);
58
+ if (this.jobs.size === 0) {
59
+ this.stop();
60
+ }
61
+ }
62
+ /**
63
+ * Check if any jobs are being tracked
64
+ */
65
+ hasTrackedJobs() {
66
+ return this.jobs.size > 0;
67
+ }
68
+ /**
69
+ * Get tracked job IDs for a given execution
70
+ */
71
+ getJobsForExecution(executionId) {
72
+ return Array.from(this.jobs.values())
73
+ .filter((j) => j.executionId === executionId)
74
+ .map((j) => j.slurmJobId);
75
+ }
76
+ /**
77
+ * Start the polling loop
78
+ */
79
+ start() {
80
+ if (this.pollInterval)
81
+ return;
82
+ console.log(`[slurm-monitor] Starting poll loop (${this.pollIntervalMs}ms)`);
83
+ // Immediate first poll so we don't wait a full interval before checking
84
+ this.pollAll().catch((err) => {
85
+ console.error('[slurm-monitor] Poll error:', err);
86
+ });
87
+ this.pollInterval = setInterval(() => {
88
+ this.pollAll().catch((err) => {
89
+ console.error('[slurm-monitor] Poll error:', err);
90
+ });
91
+ }, this.pollIntervalMs);
92
+ }
93
+ /**
94
+ * Stop the polling loop
95
+ */
96
+ stop() {
97
+ if (this.pollInterval) {
98
+ clearInterval(this.pollInterval);
99
+ this.pollInterval = null;
100
+ console.log('[slurm-monitor] Stopped poll loop');
101
+ }
102
+ }
103
+ /**
104
+ * Poll all tracked jobs
105
+ */
106
+ async pollAll() {
107
+ for (const [jobId, job] of this.jobs) {
108
+ try {
109
+ await this.pollJob(job);
110
+ }
111
+ catch (err) {
112
+ console.error(`[slurm-monitor] Error polling job ${jobId}:`, err);
113
+ }
114
+ }
115
+ }
116
+ /**
117
+ * Poll a single job's status via sacct
118
+ */
119
+ async pollJob(job) {
120
+ const { slurmJobId, executionId } = job;
121
+ let state = 'UNKNOWN';
122
+ let exitCode;
123
+ let elapsed;
124
+ try {
125
+ const { stdout } = await execFileAsync('sacct', ['-j', sanitizedSlurmJobId(slurmJobId), '--format=State,ExitCode,Elapsed', '-n', '-P'], { timeout: 10_000 });
126
+ // sacct can return multiple lines (job + job.batch steps)
127
+ // Take the first line (main job)
128
+ const firstLine = stdout.trim().split('\n')[0];
129
+ if (firstLine) {
130
+ const parts = firstLine.split('|');
131
+ state = (parts[0] || 'UNKNOWN').replace(/\+$/, ''); // Remove trailing + from CANCELLED+
132
+ const exitParts = (parts[1] || '').split(':');
133
+ exitCode = parseInt(exitParts[0]) || undefined;
134
+ elapsed = parts[2] || undefined;
135
+ }
136
+ }
137
+ catch {
138
+ // sacct not available or job not yet visible
139
+ return;
140
+ }
141
+ // Report state changes
142
+ if (state !== job.lastState) {
143
+ job.lastState = state;
144
+ if (TERMINAL_STATES.has(state)) {
145
+ // Job finished — send result
146
+ const isSuccess = state === 'COMPLETED' && (!exitCode || exitCode === 0);
147
+ // Try to read final output
148
+ let output;
149
+ if (job.outputPath) {
150
+ try {
151
+ output = await readFile(job.outputPath, 'utf-8');
152
+ }
153
+ catch {
154
+ // Output file not accessible
155
+ }
156
+ }
157
+ const result = {
158
+ taskId: executionId,
159
+ status: isSuccess ? 'completed' : 'failed',
160
+ exitCode: exitCode ?? (isSuccess ? 0 : 1),
161
+ output: output || `Slurm job ${slurmJobId}: ${state}${elapsed ? ` (${elapsed})` : ''}`,
162
+ error: isSuccess ? undefined : `Slurm job ${state}`,
163
+ completedAt: new Date().toISOString(),
164
+ };
165
+ this.wsClient.sendTaskResult(result);
166
+ console.log(`[slurm-monitor] Job ${slurmJobId} terminal: ${state}`);
167
+ this.untrackJob(slurmJobId);
168
+ }
169
+ else {
170
+ // Non-terminal state change — send progress
171
+ const progress = state === 'RUNNING' ? 50 : state === 'PENDING' ? 10 : 25;
172
+ const message = `Slurm job ${slurmJobId}: ${state}${elapsed ? ` (${elapsed})` : ''}`;
173
+ this.wsClient.sendTaskStatus(executionId, 'running', progress, message);
174
+ }
175
+ }
176
+ // Stream output file content if running
177
+ if (state === 'RUNNING' && job.outputPath) {
178
+ await this.streamOutput(job);
179
+ }
180
+ }
181
+ /**
182
+ * Stream new output from the job's output file
183
+ */
184
+ async streamOutput(job) {
185
+ if (!job.outputPath)
186
+ return;
187
+ try {
188
+ const fileStat = await stat(job.outputPath);
189
+ if (fileStat.size <= job.lastOutputOffset)
190
+ return;
191
+ // Read only the new bytes to avoid byte/character offset mismatch
192
+ const bytesToRead = fileStat.size - job.lastOutputOffset;
193
+ const fd = await open(job.outputPath, 'r');
194
+ try {
195
+ const buffer = Buffer.alloc(bytesToRead);
196
+ await fd.read(buffer, 0, bytesToRead, job.lastOutputOffset);
197
+ job.lastOutputOffset = fileStat.size;
198
+ const newContent = buffer.toString('utf-8');
199
+ if (newContent.length > 0) {
200
+ this.wsClient.sendTaskOutput(job.executionId, 'stdout', newContent, job.stdoutSequence++);
201
+ }
202
+ }
203
+ finally {
204
+ await fd.close();
205
+ }
206
+ }
207
+ catch {
208
+ // File not yet created or not accessible
209
+ }
210
+ }
211
+ }
212
+ //# sourceMappingURL=slurm-job-monitor.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"slurm-job-monitor.js","sourceRoot":"","sources":["../../src/lib/slurm-job-monitor.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,17 @@
1
+ /**
2
+ * SSH config discovery for remote host detection
3
+ */
4
+ import type { DiscoveredHost } from '../types.js';
5
+ /**
6
+ * Discover all remote hosts from various sources
7
+ */
8
+ export declare function discoverRemoteHosts(): Promise<DiscoveredHost[]>;
9
+ /**
10
+ * Format discovered hosts for display
11
+ */
12
+ export declare function formatDiscoveredHosts(hosts: DiscoveredHost[]): string;
13
+ /**
14
+ * Build SSH command for connecting to a host
15
+ */
16
+ export declare function buildSSHCommand(host: DiscoveredHost, command?: string): string;
17
+ //# sourceMappingURL=ssh-discovery.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"ssh-discovery.d.ts","sourceRoot":"","sources":["../../src/lib/ssh-discovery.ts"],"names":[],"mappings":"AAAA;;GAEG;AAKH,OAAO,KAAK,EAAW,cAAc,EAAE,MAAM,aAAa,CAAC;AA2N3D;;GAEG;AACH,wBAAsB,mBAAmB,IAAI,OAAO,CAAC,cAAc,EAAE,CAAC,CAmDrE;AAED;;GAEG;AACH,wBAAgB,qBAAqB,CAAC,KAAK,EAAE,cAAc,EAAE,GAAG,MAAM,CAsCrE;AAED;;GAEG;AACH,wBAAgB,eAAe,CAAC,IAAI,EAAE,cAAc,EAAE,OAAO,CAAC,EAAE,MAAM,GAAG,MAAM,CAuB9E"}
@@ -0,0 +1,287 @@
1
+ /**
2
+ * SSH config discovery for remote host detection
3
+ */
4
+ import { readFile } from 'node:fs/promises';
5
+ import { join } from 'node:path';
6
+ import { homedir } from 'node:os';
7
+ /**
8
+ * Parse SSH config file and extract host configurations
9
+ */
10
+ async function parseSSHConfig() {
11
+ const sshConfigPath = join(homedir(), '.ssh', 'config');
12
+ console.log(`[ssh-discovery] Parsing SSH config from: ${sshConfigPath}`);
13
+ try {
14
+ const content = await readFile(sshConfigPath, 'utf-8');
15
+ const hosts = [];
16
+ let currentHost = null;
17
+ let skippedCount = 0;
18
+ for (const line of content.split('\n')) {
19
+ const trimmed = line.trim();
20
+ // Skip comments and empty lines
21
+ if (!trimmed || trimmed.startsWith('#')) {
22
+ continue;
23
+ }
24
+ // Parse key-value pair
25
+ const match = trimmed.match(/^(\S+)\s+(.+)$/);
26
+ if (!match)
27
+ continue;
28
+ const [, key, value] = match;
29
+ const keyLower = key?.toLowerCase();
30
+ if (keyLower === 'host') {
31
+ // Save previous host if exists
32
+ if (currentHost) {
33
+ hosts.push(currentHost);
34
+ console.log(`[ssh-discovery] ✓ Added host: ${currentHost.name} (${currentHost.hostname})`);
35
+ }
36
+ const hostPattern = value?.trim() ?? '';
37
+ // Skip wildcard patterns and local-only patterns
38
+ if (hostPattern.includes('*') ||
39
+ hostPattern === 'localhost' ||
40
+ hostPattern === '127.0.0.1') {
41
+ console.log(`[ssh-discovery] ⊗ Skipped pattern/localhost: ${hostPattern}`);
42
+ skippedCount++;
43
+ currentHost = null;
44
+ continue;
45
+ }
46
+ currentHost = {
47
+ name: hostPattern,
48
+ hostname: hostPattern, // Default to the host alias
49
+ };
50
+ }
51
+ else if (currentHost && value) {
52
+ switch (keyLower) {
53
+ case 'hostname':
54
+ currentHost.hostname = value.trim();
55
+ break;
56
+ case 'user':
57
+ currentHost.user = value.trim();
58
+ break;
59
+ case 'port':
60
+ currentHost.port = parseInt(value.trim(), 10);
61
+ break;
62
+ case 'identityfile':
63
+ currentHost.identityFile = value.trim().replace('~', homedir());
64
+ break;
65
+ case 'proxyjump':
66
+ currentHost.proxyJump = value.trim();
67
+ break;
68
+ }
69
+ }
70
+ }
71
+ // Don't forget the last host
72
+ if (currentHost) {
73
+ hosts.push(currentHost);
74
+ console.log(`[ssh-discovery] ✓ Added host: ${currentHost.name} (${currentHost.hostname})`);
75
+ }
76
+ console.log(`[ssh-discovery] Parsed ${hosts.length} valid hosts (skipped ${skippedCount} wildcards/localhost)`);
77
+ return hosts;
78
+ }
79
+ catch (error) {
80
+ // SSH config doesn't exist or can't be read
81
+ if (error.code === 'ENOENT') {
82
+ console.log(`[ssh-discovery] No SSH config file found at ${sshConfigPath}`);
83
+ return [];
84
+ }
85
+ console.error(`[ssh-discovery] Error reading SSH config:`, error);
86
+ throw error;
87
+ }
88
+ }
89
+ /**
90
+ * Discover VS Code Remote SSH tunnel configurations
91
+ */
92
+ async function discoverVSCodeTunnels() {
93
+ const hosts = [];
94
+ // VS Code stores remote configurations in different locations based on platform
95
+ const vscodeConfigPaths = [
96
+ join(homedir(), '.vscode-server', 'data', 'Machine', 'settings.json'),
97
+ join(homedir(), '.vscode', 'globalStorage', 'ms-vscode-remote.remote-ssh', 'hosts.json'),
98
+ join(homedir(), 'Library', 'Application Support', 'Code', 'User', 'globalStorage', 'ms-vscode-remote.remote-ssh', 'hosts.json'),
99
+ join(homedir(), '.config', 'Code', 'User', 'globalStorage', 'ms-vscode-remote.remote-ssh', 'hosts.json'),
100
+ ];
101
+ for (const configPath of vscodeConfigPaths) {
102
+ try {
103
+ const content = await readFile(configPath, 'utf-8');
104
+ const config = JSON.parse(content);
105
+ // Handle different VS Code config formats
106
+ if (Array.isArray(config)) {
107
+ for (const entry of config) {
108
+ if (entry.host && entry.hostName) {
109
+ hosts.push({
110
+ name: entry.host,
111
+ hostname: entry.hostName,
112
+ user: entry.user,
113
+ port: entry.port,
114
+ identityFile: entry.identityFile,
115
+ });
116
+ }
117
+ }
118
+ }
119
+ else if (config.remote?.SSH?.remotePlatform) {
120
+ // Newer VS Code format
121
+ for (const hostName of Object.keys(config.remote.SSH.remotePlatform)) {
122
+ if (!hosts.some((h) => h.name === hostName)) {
123
+ hosts.push({
124
+ name: hostName,
125
+ hostname: hostName,
126
+ });
127
+ }
128
+ }
129
+ }
130
+ }
131
+ catch {
132
+ // Config doesn't exist or is invalid, continue to next path
133
+ continue;
134
+ }
135
+ }
136
+ return hosts;
137
+ }
138
+ /**
139
+ * Parse known_hosts file to find additional hosts
140
+ */
141
+ async function parseKnownHosts() {
142
+ const knownHostsPath = join(homedir(), '.ssh', 'known_hosts');
143
+ try {
144
+ const content = await readFile(knownHostsPath, 'utf-8');
145
+ const hostnames = new Set();
146
+ for (const line of content.split('\n')) {
147
+ if (!line.trim() || line.startsWith('#')) {
148
+ continue;
149
+ }
150
+ // Known hosts format: hostname[,hostname,...] keytype key [comment]
151
+ const hostPart = line.split(' ')[0];
152
+ if (!hostPart) {
153
+ continue;
154
+ }
155
+ // Split by comma for multiple hostnames on same line
156
+ for (let hostname of hostPart.split(',')) {
157
+ // Remove port if present (e.g., [hostname]:port)
158
+ hostname = hostname.replace(/^\[(.+)\]:\d+$/, '$1');
159
+ // Skip IP addresses and localhost
160
+ if (hostname.match(/^\d+\.\d+\.\d+\.\d+$/) ||
161
+ hostname === 'localhost' ||
162
+ hostname === '127.0.0.1') {
163
+ continue;
164
+ }
165
+ // Skip hashed hostnames (start with |)
166
+ if (hostname.startsWith('|')) {
167
+ continue;
168
+ }
169
+ hostnames.add(hostname);
170
+ }
171
+ }
172
+ return Array.from(hostnames);
173
+ }
174
+ catch {
175
+ return [];
176
+ }
177
+ }
178
+ /**
179
+ * Discover all remote hosts from various sources
180
+ */
181
+ export async function discoverRemoteHosts() {
182
+ console.log('[ssh-discovery] Starting remote host discovery...');
183
+ const discovered = [];
184
+ const seenHosts = new Set();
185
+ // Parse SSH config (highest priority)
186
+ console.log('[ssh-discovery] 1/3 Checking SSH config (~/.ssh/config)...');
187
+ const sshHosts = await parseSSHConfig();
188
+ for (const host of sshHosts) {
189
+ seenHosts.add(host.name);
190
+ discovered.push({
191
+ ...host,
192
+ source: 'ssh-config',
193
+ });
194
+ }
195
+ console.log(`[ssh-discovery] Found ${sshHosts.length} hosts from SSH config`);
196
+ // Discover VS Code tunnels
197
+ console.log('[ssh-discovery] 2/3 Checking VS Code Remote SSH...');
198
+ const vscodeTunnels = await discoverVSCodeTunnels();
199
+ for (const host of vscodeTunnels) {
200
+ if (!seenHosts.has(host.name)) {
201
+ seenHosts.add(host.name);
202
+ discovered.push({
203
+ ...host,
204
+ source: 'vscode-tunnel',
205
+ });
206
+ }
207
+ }
208
+ console.log(`[ssh-discovery] Found ${vscodeTunnels.length} unique VS Code hosts`);
209
+ // Parse known_hosts (lowest priority - just suggests hostnames)
210
+ console.log('[ssh-discovery] 3/3 Checking known_hosts...');
211
+ const knownHostnames = await parseKnownHosts();
212
+ let knownHostsAdded = 0;
213
+ for (const hostname of knownHostnames) {
214
+ if (!seenHosts.has(hostname)) {
215
+ seenHosts.add(hostname);
216
+ discovered.push({
217
+ name: hostname,
218
+ hostname,
219
+ source: 'known-hosts',
220
+ });
221
+ knownHostsAdded++;
222
+ }
223
+ }
224
+ console.log(`[ssh-discovery] Found ${knownHostsAdded} unique hosts from known_hosts`);
225
+ console.log(`[ssh-discovery] Discovery complete: ${discovered.length} total unique hosts`);
226
+ return discovered;
227
+ }
228
+ /**
229
+ * Format discovered hosts for display
230
+ */
231
+ export function formatDiscoveredHosts(hosts) {
232
+ if (hosts.length === 0) {
233
+ return 'No remote hosts discovered.';
234
+ }
235
+ const lines = ['Discovered Remote Hosts:', ''];
236
+ // Group by source
237
+ const bySource = new Map();
238
+ for (const host of hosts) {
239
+ const existing = bySource.get(host.source) ?? [];
240
+ existing.push(host);
241
+ bySource.set(host.source, existing);
242
+ }
243
+ const sourceLabels = {
244
+ 'ssh-config': 'From SSH config (~/.ssh/config):',
245
+ 'vscode-tunnel': 'From VS Code Remote SSH:',
246
+ 'known-hosts': 'From known hosts:',
247
+ };
248
+ for (const [source, sourceHosts] of bySource) {
249
+ lines.push(` ${sourceLabels[source] ?? source}`);
250
+ for (const host of sourceHosts) {
251
+ const details = [];
252
+ if (host.user)
253
+ details.push(`user: ${host.user}`);
254
+ if (host.port && host.port !== 22)
255
+ details.push(`port: ${host.port}`);
256
+ if (host.proxyJump)
257
+ details.push(`via: ${host.proxyJump}`);
258
+ const detailStr = details.length > 0 ? ` (${details.join(', ')})` : '';
259
+ const targetStr = host.hostname !== host.name ? ` → ${host.hostname}` : '';
260
+ lines.push(` • ${host.name}${targetStr}${detailStr}`);
261
+ }
262
+ lines.push('');
263
+ }
264
+ return lines.join('\n');
265
+ }
266
+ /**
267
+ * Build SSH command for connecting to a host
268
+ */
269
+ export function buildSSHCommand(host, command) {
270
+ const parts = ['ssh'];
271
+ if (host.port && host.port !== 22) {
272
+ parts.push('-p', String(host.port));
273
+ }
274
+ if (host.identityFile) {
275
+ parts.push('-i', host.identityFile);
276
+ }
277
+ if (host.proxyJump) {
278
+ parts.push('-J', host.proxyJump);
279
+ }
280
+ const target = host.user ? `${host.user}@${host.hostname}` : host.hostname;
281
+ parts.push(target);
282
+ if (command) {
283
+ parts.push(command);
284
+ }
285
+ return parts.join(' ');
286
+ }
287
+ //# sourceMappingURL=ssh-discovery.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"ssh-discovery.js","sourceRoot":"","sources":["../../src/lib/ssh-discovery.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,69 @@
1
+ /**
2
+ * Remote SSH installation utilities for local dev.
3
+ *
4
+ * Packs the agent-runner locally, SCPs it to the target host,
5
+ * installs via npm, and pushes pre-provisioned tokens so the
6
+ * remote host skips its own device auth entirely.
7
+ */
8
+ import type { DiscoveredHost } from '../types.js';
9
+ /**
10
+ * Detect the LAN IP of this machine so remote hosts can reach the dev server.
11
+ * Returns the first non-internal IPv4 address found.
12
+ */
13
+ export declare function detectLocalIP(): string;
14
+ /**
15
+ * SSH to a host and check whether Node.js ≥ 18 is available.
16
+ * Returns { available, version } or throws on SSH failure.
17
+ */
18
+ export declare function checkRemoteNode(host: DiscoveredHost): Promise<{
19
+ available: boolean;
20
+ version: string | null;
21
+ }>;
22
+ export interface InstallOptions {
23
+ host: DiscoveredHost;
24
+ apiUrl: string;
25
+ relayUrl: string;
26
+ accessToken: string;
27
+ refreshToken: string;
28
+ wsToken: string;
29
+ machineId: string;
30
+ }
31
+ /**
32
+ * Pack the local agent-runner, SCP it to the remote host, install, and configure.
33
+ *
34
+ * Steps:
35
+ * 1. `npm pack` in the agent-runner directory → tarball
36
+ * 2. `scp` tarball to remote ~/
37
+ * 3. `ssh npm install -g <tarball>` on remote
38
+ * 4. `ssh astro-agent setup --non-interactive --skip-auth` on remote
39
+ * 5. Push tokens via `ssh astro-agent config --set` commands
40
+ */
41
+ export declare function packAndInstall(opts: InstallOptions, onProgress?: (msg: string) => void): Promise<void>;
42
+ export declare function buildSshArgs(host: DiscoveredHost, command: string): string[];
43
+ export declare function sshExec(host: DiscoveredHost, command: string): Promise<{
44
+ stdout: string;
45
+ stderr: string;
46
+ }>;
47
+ export interface StartRemoteOptions {
48
+ maxTasks?: number;
49
+ logLevel?: string;
50
+ preserveWorktrees?: boolean;
51
+ }
52
+ export interface RemoteStartResult {
53
+ host: DiscoveredHost;
54
+ success: boolean;
55
+ message: string;
56
+ alreadyRunning?: boolean;
57
+ }
58
+ /**
59
+ * Start agent runners on remote hosts.
60
+ *
61
+ * For each host:
62
+ * 1. Check if an agent is already running (pgrep)
63
+ * 2. Start via nohup + disown
64
+ * 3. Verify after 2s with pgrep
65
+ *
66
+ * One failure does not block others.
67
+ */
68
+ export declare function startRemoteAgents(hosts: DiscoveredHost[], options?: StartRemoteOptions, onProgress?: (host: string, msg: string) => void): Promise<RemoteStartResult[]>;
69
+ //# sourceMappingURL=ssh-installer.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"ssh-installer.d.ts","sourceRoot":"","sources":["../../src/lib/ssh-installer.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAOH,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,aAAa,CAAC;AAQlD;;;GAGG;AACH,wBAAgB,aAAa,IAAI,MAAM,CAatC;AAMD;;;GAGG;AACH,wBAAsB,eAAe,CACnC,IAAI,EAAE,cAAc,GACnB,OAAO,CAAC;IAAE,SAAS,EAAE,OAAO,CAAC;IAAC,OAAO,EAAE,MAAM,GAAG,IAAI,CAAA;CAAE,CAAC,CASzD;AAMD,MAAM,WAAW,cAAc;IAC7B,IAAI,EAAE,cAAc,CAAC;IACrB,MAAM,EAAE,MAAM,CAAC;IACf,QAAQ,EAAE,MAAM,CAAC;IACjB,WAAW,EAAE,MAAM,CAAC;IACpB,YAAY,EAAE,MAAM,CAAC;IACrB,OAAO,EAAE,MAAM,CAAC;IAChB,SAAS,EAAE,MAAM,CAAC;CACnB;AAED;;;;;;;;;GASG;AACH,wBAAsB,cAAc,CAClC,IAAI,EAAE,cAAc,EACpB,UAAU,CAAC,EAAE,CAAC,GAAG,EAAE,MAAM,KAAK,IAAI,GACjC,OAAO,CAAC,IAAI,CAAC,CAkEf;AAMD,wBAAgB,YAAY,CAAC,IAAI,EAAE,cAAc,EAAE,OAAO,EAAE,MAAM,GAAG,MAAM,EAAE,CAoB5E;AAuBD,wBAAsB,OAAO,CAC3B,IAAI,EAAE,cAAc,EACpB,OAAO,EAAE,MAAM,GACd,OAAO,CAAC;IAAE,MAAM,EAAE,MAAM,CAAC;IAAC,MAAM,EAAE,MAAM,CAAA;CAAE,CAAC,CAG7C;AAMD,MAAM,WAAW,kBAAkB;IACjC,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,iBAAiB,CAAC,EAAE,OAAO,CAAC;CAC7B;AAED,MAAM,WAAW,iBAAiB;IAChC,IAAI,EAAE,cAAc,CAAC;IACrB,OAAO,EAAE,OAAO,CAAC;IACjB,OAAO,EAAE,MAAM,CAAC;IAChB,cAAc,CAAC,EAAE,OAAO,CAAC;CAC1B;AAED;;;;;;;;;GASG;AACH,wBAAsB,iBAAiB,CACrC,KAAK,EAAE,cAAc,EAAE,EACvB,OAAO,GAAE,kBAAuB,EAChC,UAAU,CAAC,EAAE,CAAC,IAAI,EAAE,MAAM,EAAE,GAAG,EAAE,MAAM,KAAK,IAAI,GAC/C,OAAO,CAAC,iBAAiB,EAAE,CAAC,CA8D9B"}