@grackle-ai/server 0.35.0 → 0.36.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/dist/adapter-manager.d.ts +1 -1
- package/dist/adapter-manager.d.ts.map +1 -1
- package/dist/adapters/codespace.d.ts +1 -1
- package/dist/adapters/codespace.d.ts.map +1 -1
- package/dist/adapters/codespace.js +7 -2
- package/dist/adapters/codespace.js.map +1 -1
- package/dist/adapters/docker.d.ts +1 -1
- package/dist/adapters/docker.d.ts.map +1 -1
- package/dist/adapters/docker.js +8 -3
- package/dist/adapters/docker.js.map +1 -1
- package/dist/adapters/local.d.ts +1 -1
- package/dist/adapters/local.d.ts.map +1 -1
- package/dist/adapters/local.js +1 -1
- package/dist/adapters/local.js.map +1 -1
- package/dist/adapters/ssh.d.ts +1 -1
- package/dist/adapters/ssh.d.ts.map +1 -1
- package/dist/adapters/ssh.js +6 -2
- package/dist/adapters/ssh.js.map +1 -1
- package/dist/grpc-service.d.ts.map +1 -1
- package/dist/grpc-service.js +8 -1
- package/dist/grpc-service.js.map +1 -1
- package/dist/index.js +1 -1
- package/dist/index.js.map +1 -1
- package/dist/ws-bridge.js +1 -1
- package/dist/ws-bridge.js.map +1 -1
- package/package.json +5 -4
- package/dist/adapters/adapter.d.ts +0 -50
- package/dist/adapters/adapter.d.ts.map +0 -1
- package/dist/adapters/adapter.js +0 -24
- package/dist/adapters/adapter.js.map +0 -1
- package/dist/adapters/powerline-transport.d.ts +0 -7
- package/dist/adapters/powerline-transport.d.ts.map +0 -1
- package/dist/adapters/powerline-transport.js +0 -22
- package/dist/adapters/powerline-transport.js.map +0 -1
- package/dist/adapters/remote-adapter-utils.d.ts +0 -161
- package/dist/adapters/remote-adapter-utils.d.ts.map +0 -1
- package/dist/adapters/remote-adapter-utils.js +0 -598
- package/dist/adapters/remote-adapter-utils.js.map +0 -1
|
@@ -1,598 +0,0 @@
|
|
|
1
|
-
import { DEFAULT_POWERLINE_PORT } from "@grackle-ai/common";
|
|
2
|
-
import { createPowerLineClient } from "./powerline-transport.js";
|
|
3
|
-
import { findFreePort } from "../utils/ports.js";
|
|
4
|
-
import { sleep } from "../utils/sleep.js";
|
|
5
|
-
import { logger } from "../logger.js";
|
|
6
|
-
import { spawn } from "node:child_process";
|
|
7
|
-
import { createConnection } from "node:net";
|
|
8
|
-
import { join, resolve } from "node:path";
|
|
9
|
-
import { existsSync, readFileSync } from "node:fs";
|
|
10
|
-
import { getCredentialProviders } from "../credential-providers.js";
|
|
11
|
-
// ─── Constants ──────────────────────────────────────────────
|
|
12
|
-
/** Timeout for `npm install` on the remote host. */
|
|
13
|
-
const BOOTSTRAP_NPM_INSTALL_TIMEOUT_MS = 120_000;
|
|
14
|
-
/** Default timeout for remote command execution. */
|
|
15
|
-
const REMOTE_EXEC_DEFAULT_TIMEOUT_MS = 60_000;
|
|
16
|
-
/** Delay between gRPC connect-with-retry attempts. */
|
|
17
|
-
const CONNECT_RETRY_DELAY_MS = 1_500;
|
|
18
|
-
/** Maximum number of gRPC connect-with-retry attempts. */
|
|
19
|
-
const CONNECT_MAX_RETRIES = 10;
|
|
20
|
-
/** Delay between port availability polls. */
|
|
21
|
-
const TUNNEL_PORT_POLL_DELAY_MS = 500;
|
|
22
|
-
/** Maximum number of port availability polls. */
|
|
23
|
-
const TUNNEL_PORT_POLL_MAX_ATTEMPTS = 20;
|
|
24
|
-
/** Wait after starting the remote PowerLine process before verifying. */
|
|
25
|
-
const POWERLINE_STARTUP_DELAY_MS = 2_000;
|
|
26
|
-
/** Grace period before sending SIGKILL to a tunnel process. */
|
|
27
|
-
const TUNNEL_KILL_GRACE_MS = 1_000;
|
|
28
|
-
/** Timeout for the initial SSH connectivity test. */
|
|
29
|
-
const SSH_CONNECTIVITY_TIMEOUT_MS = 15_000;
|
|
30
|
-
/** Remote directory where PowerLine artifacts are installed. Uses $HOME (not ~) so it expands inside double-quoted shell strings. */
|
|
31
|
-
const REMOTE_POWERLINE_DIRECTORY = "$HOME/.grackle/powerline";
|
|
32
|
-
// ─── Dev vs Production Mode ─────────────────────────────────
|
|
33
|
-
/**
|
|
34
|
-
* Check if we are running from a monorepo source checkout.
|
|
35
|
-
* We detect this by checking for `rush.json` at the repo root,
|
|
36
|
-
* computed relative to this file's compiled location (packages/server/dist/adapters → 4 levels up).
|
|
37
|
-
* The old approach (checking for a sibling powerline dist) would false-positive when
|
|
38
|
-
* `@grackle-ai/powerline` is installed alongside the server in node_modules.
|
|
39
|
-
*/
|
|
40
|
-
export function isDevMode() {
|
|
41
|
-
const repoRoot = resolve(import.meta.dirname, "../../../../");
|
|
42
|
-
return existsSync(join(repoRoot, "rush.json"));
|
|
43
|
-
}
|
|
44
|
-
/**
|
|
45
|
-
* Read the lockstep version from the server's own package.json.
|
|
46
|
-
* import.meta.dirname = dist/adapters, so ../../package.json = server's package.json.
|
|
47
|
-
*/
|
|
48
|
-
function getPackageVersion() {
|
|
49
|
-
const packageJsonPath = resolve(import.meta.dirname, "../../package.json");
|
|
50
|
-
const pkg = JSON.parse(readFileSync(packageJsonPath, "utf8"));
|
|
51
|
-
return pkg.version;
|
|
52
|
-
}
|
|
53
|
-
const tunnelMap = new Map();
|
|
54
|
-
/** Register an active tunnel for an environment, closing any existing tunnel first. */
|
|
55
|
-
export function registerTunnel(environmentId, state) {
|
|
56
|
-
const existing = tunnelMap.get(environmentId);
|
|
57
|
-
if (existing) {
|
|
58
|
-
existing.tunnel.close().catch((err) => {
|
|
59
|
-
logger.warn({ err, environmentId }, "Failed to close existing tunnel before registering new one");
|
|
60
|
-
});
|
|
61
|
-
if (existing.reverseTunnel) {
|
|
62
|
-
existing.reverseTunnel.close().catch((err) => {
|
|
63
|
-
logger.warn({ err, environmentId }, "Failed to close existing reverse tunnel before registering new one");
|
|
64
|
-
});
|
|
65
|
-
}
|
|
66
|
-
}
|
|
67
|
-
tunnelMap.set(environmentId, state);
|
|
68
|
-
}
|
|
69
|
-
/** Get the tunnel state for an environment. */
|
|
70
|
-
export function getTunnel(environmentId) {
|
|
71
|
-
return tunnelMap.get(environmentId);
|
|
72
|
-
}
|
|
73
|
-
/** Close and unregister the tunnel(s) for an environment. */
|
|
74
|
-
export async function closeTunnel(environmentId) {
|
|
75
|
-
const state = tunnelMap.get(environmentId);
|
|
76
|
-
if (state) {
|
|
77
|
-
await state.tunnel.close();
|
|
78
|
-
if (state.reverseTunnel) {
|
|
79
|
-
await state.reverseTunnel.close();
|
|
80
|
-
}
|
|
81
|
-
tunnelMap.delete(environmentId);
|
|
82
|
-
}
|
|
83
|
-
}
|
|
84
|
-
/** Close all active tunnels (called during server shutdown). */
|
|
85
|
-
export async function closeAllTunnels() {
|
|
86
|
-
const ids = [...tunnelMap.keys()];
|
|
87
|
-
for (const id of ids) {
|
|
88
|
-
try {
|
|
89
|
-
await closeTunnel(id);
|
|
90
|
-
}
|
|
91
|
-
catch (err) {
|
|
92
|
-
logger.error({ environmentId: id, err }, "Failed to close tunnel during shutdown");
|
|
93
|
-
}
|
|
94
|
-
}
|
|
95
|
-
}
|
|
96
|
-
// ─── Tunnel Process Base ────────────────────────────────────
|
|
97
|
-
/**
|
|
98
|
-
* Base class for tunnels backed by a long-lived child process.
|
|
99
|
-
* Subclasses provide the command and arguments to spawn.
|
|
100
|
-
*/
|
|
101
|
-
export class ProcessTunnel {
|
|
102
|
-
localPort;
|
|
103
|
-
process;
|
|
104
|
-
constructor(localPort) {
|
|
105
|
-
this.localPort = localPort;
|
|
106
|
-
}
|
|
107
|
-
/** Open the tunnel by spawning the background process. */
|
|
108
|
-
async open() {
|
|
109
|
-
const { command, args } = this.spawnArgs();
|
|
110
|
-
logger.info({ command, args }, "Opening tunnel");
|
|
111
|
-
this.process = spawn(command, args, {
|
|
112
|
-
stdio: ["ignore", "ignore", "pipe"],
|
|
113
|
-
detached: false,
|
|
114
|
-
});
|
|
115
|
-
this.process.on("error", (err) => {
|
|
116
|
-
logger.error({ err }, "Tunnel process error");
|
|
117
|
-
});
|
|
118
|
-
this.process.stderr?.on("data", (data) => {
|
|
119
|
-
logger.debug({ stderr: data.toString() }, "Tunnel stderr");
|
|
120
|
-
});
|
|
121
|
-
// Wait for the local port to become reachable. Kill the process if it fails.
|
|
122
|
-
try {
|
|
123
|
-
await waitForLocalPort(this.localPort);
|
|
124
|
-
}
|
|
125
|
-
catch (err) {
|
|
126
|
-
await this.close();
|
|
127
|
-
throw err;
|
|
128
|
-
}
|
|
129
|
-
}
|
|
130
|
-
/** Close the tunnel by killing the background process. */
|
|
131
|
-
async close() {
|
|
132
|
-
if (this.process?.exitCode !== null) {
|
|
133
|
-
return;
|
|
134
|
-
}
|
|
135
|
-
this.process.kill("SIGTERM");
|
|
136
|
-
await sleep(TUNNEL_KILL_GRACE_MS);
|
|
137
|
-
// eslint-disable-next-line @typescript-eslint/no-unnecessary-condition -- exitCode may change after SIGTERM + sleep
|
|
138
|
-
if (this.process.exitCode === null) {
|
|
139
|
-
this.process.kill("SIGKILL");
|
|
140
|
-
}
|
|
141
|
-
this.process = undefined;
|
|
142
|
-
}
|
|
143
|
-
/** Return true if the tunnel process is still running. */
|
|
144
|
-
isAlive() {
|
|
145
|
-
return this.process?.exitCode === null;
|
|
146
|
-
}
|
|
147
|
-
}
|
|
148
|
-
// ─── Bootstrap PowerLine ────────────────────────────────────
|
|
149
|
-
/** Regex for valid POSIX environment variable names. */
|
|
150
|
-
const ENV_VAR_NAME_PATTERN = /^[A-Za-z_][A-Za-z0-9_]*$/;
|
|
151
|
-
/**
|
|
152
|
-
* Escape a value for safe use inside a shell single-quoted string.
|
|
153
|
-
* Replaces each `'` with `'\''` (end quote, escaped quote, start quote).
|
|
154
|
-
*/
|
|
155
|
-
function shellEscape(value) {
|
|
156
|
-
return value.replace(/'/g, "'\\''");
|
|
157
|
-
}
|
|
158
|
-
/**
|
|
159
|
-
* Build the list of env-file lines for the PowerLine process.
|
|
160
|
-
* Pure helper used by both {@link writeRemoteEnvFile} and {@link startRemotePowerLine}.
|
|
161
|
-
*/
|
|
162
|
-
function writeRemoteEnvFileLines(powerlineToken, extraEnv) {
|
|
163
|
-
const envLines = [];
|
|
164
|
-
if (powerlineToken) {
|
|
165
|
-
envLines.push(`export GRACKLE_POWERLINE_TOKEN='${shellEscape(powerlineToken)}'`);
|
|
166
|
-
}
|
|
167
|
-
if (extraEnv) {
|
|
168
|
-
for (const [key, value] of Object.entries(extraEnv)) {
|
|
169
|
-
if (!ENV_VAR_NAME_PATTERN.test(key)) {
|
|
170
|
-
logger.warn({ key }, "Skipping invalid env var name");
|
|
171
|
-
continue;
|
|
172
|
-
}
|
|
173
|
-
envLines.push(`export ${key}='${shellEscape(value)}'`);
|
|
174
|
-
}
|
|
175
|
-
}
|
|
176
|
-
return envLines;
|
|
177
|
-
}
|
|
178
|
-
/**
|
|
179
|
-
* Write the environment variable file to the remote PowerLine directory.
|
|
180
|
-
* Used during both initial bootstrap and reconnect (tokens may have rotated).
|
|
181
|
-
*/
|
|
182
|
-
export async function writeRemoteEnvFile(executor, powerlineToken, extraEnv) {
|
|
183
|
-
const envLines = writeRemoteEnvFileLines(powerlineToken, extraEnv);
|
|
184
|
-
if (envLines.length === 0) {
|
|
185
|
-
return;
|
|
186
|
-
}
|
|
187
|
-
const envFileContent = envLines.join("\n") + "\n";
|
|
188
|
-
const envFileContentBase64 = Buffer.from(envFileContent, "utf8").toString("base64");
|
|
189
|
-
await executor.exec(`cd ${REMOTE_POWERLINE_DIRECTORY} && node -e "require('fs').writeFileSync('.env.sh',Buffer.from(process.argv[1],'base64').toString('utf8'))" '${shellEscape(envFileContentBase64)}'`, { timeout: REMOTE_EXEC_DEFAULT_TIMEOUT_MS });
|
|
190
|
-
await executor.exec(`chmod 600 ${REMOTE_POWERLINE_DIRECTORY}/.env.sh`, { timeout: REMOTE_EXEC_DEFAULT_TIMEOUT_MS });
|
|
191
|
-
}
|
|
192
|
-
/** Node.js one-liner that probes the PowerLine port and exits 0/1. */
|
|
193
|
-
const PROBE_SCRIPT = `node -e "const s=require('net').createConnection(${DEFAULT_POWERLINE_PORT},'127.0.0.1');`
|
|
194
|
-
+ `s.on('connect',()=>{s.destroy();process.exit(0)});`
|
|
195
|
-
+ `s.on('error',()=>process.exit(1))"`;
|
|
196
|
-
/**
|
|
197
|
-
* Probe whether the remote PowerLine is listening on its port.
|
|
198
|
-
* Throws if the port is not reachable.
|
|
199
|
-
*/
|
|
200
|
-
export async function probeRemotePowerLine(executor) {
|
|
201
|
-
await executor.exec(PROBE_SCRIPT, { timeout: REMOTE_EXEC_DEFAULT_TIMEOUT_MS });
|
|
202
|
-
}
|
|
203
|
-
/**
|
|
204
|
-
* Node.js one-liner that spawns a fully detached child process.
|
|
205
|
-
*
|
|
206
|
-
* Uses `child_process.spawn()` with `detached: true` and `unref()` so the
|
|
207
|
-
* parent Node process exits immediately. This is the only reliable way to
|
|
208
|
-
* background a process through `gh codespace ssh` — the relay waits for EOF
|
|
209
|
-
* on all inherited FDs, and even `nohup ... < /dev/null > log 2>&1 &` leaves
|
|
210
|
-
* the SSH session hanging because the bash subshell created by `&` holds
|
|
211
|
-
* references to the SSH transport's pipes.
|
|
212
|
-
*
|
|
213
|
-
* Takes three positional arguments (passed by bash, allowing `$HOME` / `$WD`
|
|
214
|
-
* expansion): argv[1] = entryPoint, argv[2] = pidFilePath, argv[3] = logFile.
|
|
215
|
-
* Uses `process.cwd()` as the working directory (caller must `cd` first).
|
|
216
|
-
*/
|
|
217
|
-
/** Validate and build the node one-liner that spawns a fully detached PowerLine process. */
|
|
218
|
-
function buildSpawnScript(host) {
|
|
219
|
-
if (host && !/^[\d.a-zA-Z:]+$/.test(host)) {
|
|
220
|
-
throw new Error(`Invalid host address: ${host}`);
|
|
221
|
-
}
|
|
222
|
-
const hostArg = host ? `,'--host=${host}'` : "";
|
|
223
|
-
return (`node -e "`
|
|
224
|
-
+ `const fs=require('fs');`
|
|
225
|
-
+ `const {spawn}=require('child_process');`
|
|
226
|
-
+ `const out=fs.openSync(process.argv[3],'w');`
|
|
227
|
-
+ `const c=spawn('node',[process.argv[1],'--port=${DEFAULT_POWERLINE_PORT}'${hostArg}],`
|
|
228
|
-
+ `{cwd:process.cwd(),detached:true,stdio:['ignore',out,out]});`
|
|
229
|
-
+ `fs.writeFileSync(process.argv[2],String(c.pid));`
|
|
230
|
-
+ `c.unref();"`);
|
|
231
|
-
}
|
|
232
|
-
/**
|
|
233
|
-
* Ensure the remote PowerLine process is running.
|
|
234
|
-
*
|
|
235
|
-
* Batches env-var write, process start, and port probe into a **single SSH
|
|
236
|
-
* call** to minimize per-call latency (each `gh codespace ssh` round trip
|
|
237
|
-
* takes ~10-15 s through GitHub's relay).
|
|
238
|
-
*
|
|
239
|
-
* Uses Node's `spawn({ detached: true })` to properly daemonize the
|
|
240
|
-
* PowerLine process, avoiding the SSH-hanging issue where `nohup ... &`
|
|
241
|
-
* keeps the session alive through GitHub's codespace relay.
|
|
242
|
-
*
|
|
243
|
-
* When `probeFirst` is true the script begins with a TCP port check and
|
|
244
|
-
* returns immediately if PowerLine is already listening, combining the
|
|
245
|
-
* "is it alive?" check and the "start if not" logic into one SSH call.
|
|
246
|
-
*
|
|
247
|
-
* This is the "restart" middle path — it assumes code is already installed
|
|
248
|
-
* and skips npm install, git checks, and artifact copies.
|
|
249
|
-
*/
|
|
250
|
-
export async function startRemotePowerLine(executor, powerlineToken, options = {}) {
|
|
251
|
-
const { extraEnv, workingDirectory, host, autoDetectWorkspace, probeFirst } = options;
|
|
252
|
-
// Validate workingDirectory to prevent shell injection — must be an absolute POSIX path
|
|
253
|
-
if (workingDirectory && !/^\/[\w./-]+$/.test(workingDirectory)) {
|
|
254
|
-
throw new Error(`Invalid working directory: ${workingDirectory}`);
|
|
255
|
-
}
|
|
256
|
-
const envLines = writeRemoteEnvFileLines(powerlineToken, extraEnv);
|
|
257
|
-
const devMode = isDevMode();
|
|
258
|
-
const entryPoint = devMode
|
|
259
|
-
? "dist/index.js"
|
|
260
|
-
: "node_modules/@grackle-ai/powerline/dist/index.js";
|
|
261
|
-
const absoluteEntryPoint = `${REMOTE_POWERLINE_DIRECTORY}/${entryPoint}`;
|
|
262
|
-
const logFilePath = "$HOME/.grackle/powerline.log";
|
|
263
|
-
const pidFilePath = `${REMOTE_POWERLINE_DIRECTORY}/powerline.pid`;
|
|
264
|
-
// Build a compound script that runs in a single SSH call:
|
|
265
|
-
// 0. (Optional) Probe — exit early if already listening
|
|
266
|
-
// 1. Write env file (base64 → file)
|
|
267
|
-
// 2. Detect working directory (optional)
|
|
268
|
-
// 3. Source env + spawn PowerLine (detached, exits immediately)
|
|
269
|
-
// 4. Brief sleep + probe
|
|
270
|
-
const parts = [];
|
|
271
|
-
// 0. Early-exit probe (saves work when PowerLine is already running).
|
|
272
|
-
// Uses `; ` (not `&&`) to separate from the start logic so that a
|
|
273
|
-
// failed probe doesn't short-circuit the rest of the script.
|
|
274
|
-
// `exit 0` exits the top-level bash -c, not a subshell.
|
|
275
|
-
let probeFirstPrefix = "";
|
|
276
|
-
if (probeFirst) {
|
|
277
|
-
probeFirstPrefix = `${PROBE_SCRIPT} && echo "__PL_ALIVE__" && exit 0; `;
|
|
278
|
-
}
|
|
279
|
-
// 1. Env file
|
|
280
|
-
if (envLines.length > 0) {
|
|
281
|
-
const envFileContent = envLines.join("\n") + "\n";
|
|
282
|
-
const envFileContentBase64 = Buffer.from(envFileContent, "utf8").toString("base64");
|
|
283
|
-
parts.push(`cd ${REMOTE_POWERLINE_DIRECTORY}`
|
|
284
|
-
+ ` && node -e "require('fs').writeFileSync('.env.sh',Buffer.from(process.argv[1],'base64').toString('utf8'))"`
|
|
285
|
-
+ ` '${shellEscape(envFileContentBase64)}'`
|
|
286
|
-
+ ` && chmod 600 .env.sh`);
|
|
287
|
-
}
|
|
288
|
-
// 2. Working directory
|
|
289
|
-
let startDirExpr;
|
|
290
|
-
if (workingDirectory) {
|
|
291
|
-
startDirExpr = workingDirectory;
|
|
292
|
-
}
|
|
293
|
-
else if (autoDetectWorkspace) {
|
|
294
|
-
// Detect /workspaces/*/ inline; fall back to PowerLine directory.
|
|
295
|
-
// Use ${WD:-default} so the exit code is always 0 ([ -z ] && ... would
|
|
296
|
-
// return 1 when WD is set, breaking the && chain).
|
|
297
|
-
parts.push(`WD=$(ls -d /workspaces/*/ 2>/dev/null | head -1 | sed "s/\\/$//");`
|
|
298
|
-
+ ` WD=\${WD:-${REMOTE_POWERLINE_DIRECTORY}}`);
|
|
299
|
-
startDirExpr = "$WD";
|
|
300
|
-
}
|
|
301
|
-
else {
|
|
302
|
-
startDirExpr = REMOTE_POWERLINE_DIRECTORY;
|
|
303
|
-
}
|
|
304
|
-
// 3. Source env vars and spawn PowerLine as a detached process.
|
|
305
|
-
// Paths are passed as bash arguments (not embedded in the Node script)
|
|
306
|
-
// so that shell variables like $HOME and $WD are expanded by bash.
|
|
307
|
-
// The spawn script exits immediately — no SSH hanging.
|
|
308
|
-
const sourceEnv = envLines.length > 0
|
|
309
|
-
? `. ${REMOTE_POWERLINE_DIRECTORY}/.env.sh && `
|
|
310
|
-
: "";
|
|
311
|
-
parts.push(`cd "${startDirExpr}" && ${sourceEnv}`
|
|
312
|
-
+ `${buildSpawnScript(host)} "${absoluteEntryPoint}" "${pidFilePath}" "${logFilePath}"`);
|
|
313
|
-
// 4. Probe (after a brief pause for the port to bind)
|
|
314
|
-
parts.push(`sleep ${POWERLINE_STARTUP_DELAY_MS / 1000} && ${PROBE_SCRIPT}`);
|
|
315
|
-
const compoundScript = probeFirstPrefix + parts.join(" && ");
|
|
316
|
-
try {
|
|
317
|
-
const stdout = await executor.exec(`bash -c '${shellEscape(compoundScript)}'`, { timeout: REMOTE_EXEC_DEFAULT_TIMEOUT_MS });
|
|
318
|
-
if (probeFirst && stdout.includes("__PL_ALIVE__")) {
|
|
319
|
-
logger.info("Remote PowerLine was already running on port %d", DEFAULT_POWERLINE_PORT);
|
|
320
|
-
return { alreadyRunning: true };
|
|
321
|
-
}
|
|
322
|
-
logger.info("Remote PowerLine is listening on port %d", DEFAULT_POWERLINE_PORT);
|
|
323
|
-
return { alreadyRunning: false };
|
|
324
|
-
}
|
|
325
|
-
catch (err) {
|
|
326
|
-
const detail = err instanceof Error ? err.message : String(err);
|
|
327
|
-
logger.info("Failed to start remote PowerLine: %s", detail);
|
|
328
|
-
throw new Error(`PowerLine process died immediately after starting. Check ~/.grackle/powerline.log on the remote host. Cause: ${detail}`);
|
|
329
|
-
}
|
|
330
|
-
}
|
|
331
|
-
/**
|
|
332
|
-
* Bootstrap the PowerLine on a remote host via the given executor.
|
|
333
|
-
* Yields progress events for each stage of the process.
|
|
334
|
-
* @param extraEnv - Additional env vars to forward (from adapter config).
|
|
335
|
-
*/
|
|
336
|
-
export async function* bootstrapPowerLine(executor, powerlineToken, extraEnv, workingDirectory, host) {
|
|
337
|
-
// 1. Check Node.js (PowerLine requires >= 22)
|
|
338
|
-
yield { stage: "bootstrapping", message: "Checking Node.js on remote host...", progress: 0.10 };
|
|
339
|
-
try {
|
|
340
|
-
const nodeVersionOutput = await executor.exec("node --version", { timeout: SSH_CONNECTIVITY_TIMEOUT_MS });
|
|
341
|
-
const nodeVersion = String(nodeVersionOutput).trim();
|
|
342
|
-
logger.info({ nodeVersion }, "Remote Node.js version");
|
|
343
|
-
const versionMatch = nodeVersion.match(/^v?(\d+)\./);
|
|
344
|
-
if (!versionMatch) {
|
|
345
|
-
throw new Error(`Unable to parse Node.js version "${nodeVersion}" on remote host. Install Node.js >= 22 and try again.`);
|
|
346
|
-
}
|
|
347
|
-
const majorVersion = parseInt(versionMatch[1], 10);
|
|
348
|
-
if (isNaN(majorVersion) || majorVersion < 22) {
|
|
349
|
-
throw new Error(`Unsupported Node.js version "${nodeVersion}" on remote host. PowerLine requires Node.js >= 22.`);
|
|
350
|
-
}
|
|
351
|
-
}
|
|
352
|
-
catch (error) {
|
|
353
|
-
if (error instanceof Error
|
|
354
|
-
&& (error.message.startsWith("Unable to parse Node.js version")
|
|
355
|
-
|| error.message.startsWith("Unsupported Node.js version"))) {
|
|
356
|
-
throw error;
|
|
357
|
-
}
|
|
358
|
-
throw new Error("Node.js is not installed or not accessible on the remote host. Install Node.js >= 22 and try again.");
|
|
359
|
-
}
|
|
360
|
-
// 2. Check git
|
|
361
|
-
yield { stage: "bootstrapping", message: "Checking git on remote host...", progress: 0.15 };
|
|
362
|
-
try {
|
|
363
|
-
await executor.exec("git --version", { timeout: SSH_CONNECTIVITY_TIMEOUT_MS });
|
|
364
|
-
}
|
|
365
|
-
catch {
|
|
366
|
-
throw new Error("git is not installed on the remote host. Install git and try again.");
|
|
367
|
-
}
|
|
368
|
-
// 2.5. Capture GITHUB_TOKEN from remote host for git push connectivity.
|
|
369
|
-
// In GitHub Codespaces, GITHUB_TOKEN is injected by the platform but is NOT
|
|
370
|
-
// available via `printenv` in SSH sessions. It lives in a shared env file at
|
|
371
|
-
// /workspaces/.codespaces/shared/.env (format: GITHUB_TOKEN=ghu_...).
|
|
372
|
-
// Fall back to printenv for non-codespace environments (e.g. SSH with real shells).
|
|
373
|
-
// Only performed when the GitHub credential provider is enabled, so that users
|
|
374
|
-
// who have disabled it do not receive injected tokens.
|
|
375
|
-
let enrichedExtraEnv = extraEnv;
|
|
376
|
-
const hasLocalToken = process.env.GITHUB_TOKEN || process.env.GH_TOKEN;
|
|
377
|
-
const hasAdapterToken = extraEnv?.GITHUB_TOKEN || extraEnv?.GH_TOKEN;
|
|
378
|
-
const githubProviderEnabled = getCredentialProviders().github === "on";
|
|
379
|
-
if (githubProviderEnabled && !hasLocalToken && !hasAdapterToken) {
|
|
380
|
-
try {
|
|
381
|
-
const remoteToken = (await executor.exec(`(grep -m1 '^GITHUB_TOKEN=' /workspaces/.codespaces/shared/.env 2>/dev/null | cut -d= -f2- || grep -m1 '^GH_TOKEN=' /workspaces/.codespaces/shared/.env 2>/dev/null | cut -d= -f2- || printenv GITHUB_TOKEN 2>/dev/null || printenv GH_TOKEN 2>/dev/null || true)`, { timeout: SSH_CONNECTIVITY_TIMEOUT_MS })).trim();
|
|
382
|
-
if (remoteToken) {
|
|
383
|
-
enrichedExtraEnv = { ...extraEnv, GITHUB_TOKEN: remoteToken };
|
|
384
|
-
logger.info("Captured GITHUB_TOKEN from remote host for agent git operations");
|
|
385
|
-
}
|
|
386
|
-
}
|
|
387
|
-
catch {
|
|
388
|
-
logger.debug("Could not read GITHUB_TOKEN from remote host");
|
|
389
|
-
}
|
|
390
|
-
}
|
|
391
|
-
// 3. Install PowerLine — dev mode (copy artifacts) vs production (npm install)
|
|
392
|
-
const devMode = isDevMode();
|
|
393
|
-
if (devMode) {
|
|
394
|
-
// ── Dev mode: copy local monorepo artifacts ──
|
|
395
|
-
yield { stage: "bootstrapping", message: "Creating remote directories...", progress: 0.20 };
|
|
396
|
-
await executor.exec(`mkdir -p ${REMOTE_POWERLINE_DIRECTORY}/node_modules/@grackle-ai/common`, { timeout: REMOTE_EXEC_DEFAULT_TIMEOUT_MS });
|
|
397
|
-
// Resolve local artifact paths relative to server's built location.
|
|
398
|
-
// import.meta.dirname = packages/server/dist/adapters → up 3 levels → packages/
|
|
399
|
-
const serverDistDir = resolve(import.meta.dirname);
|
|
400
|
-
const commonPackageDir = resolve(serverDistDir, "../../../common");
|
|
401
|
-
const powerlinePackageDir = resolve(serverDistDir, "../../../powerline");
|
|
402
|
-
const mcpPackageDir = resolve(serverDistDir, "../../../mcp");
|
|
403
|
-
yield { stage: "bootstrapping", message: "Copying PowerLine artifacts...", progress: 0.25 };
|
|
404
|
-
await executor.copyTo(join(powerlinePackageDir, "dist"), `${REMOTE_POWERLINE_DIRECTORY}/dist`);
|
|
405
|
-
await executor.copyTo(join(powerlinePackageDir, "package.json"), `${REMOTE_POWERLINE_DIRECTORY}/package.json`);
|
|
406
|
-
// Collect non-workspace deps from @grackle-ai/common and @grackle-ai/mcp
|
|
407
|
-
// so we can merge them into powerline's package.json before a single npm install.
|
|
408
|
-
const extraDeps = {};
|
|
409
|
-
for (const dir of [commonPackageDir, mcpPackageDir]) {
|
|
410
|
-
const pkg = JSON.parse(readFileSync(join(dir, "package.json"), "utf8"));
|
|
411
|
-
for (const [k, v] of Object.entries(pkg.dependencies || {})) {
|
|
412
|
-
if (!k.startsWith("@grackle-ai/")) {
|
|
413
|
-
extraDeps[k] = v;
|
|
414
|
-
}
|
|
415
|
-
}
|
|
416
|
-
}
|
|
417
|
-
// Strip @grackle-ai/* workspace deps, merge in common/mcp deps, then npm install once.
|
|
418
|
-
yield { stage: "bootstrapping", message: "Installing dependencies on remote host...", progress: 0.40 };
|
|
419
|
-
const extraDepsJson = JSON.stringify(extraDeps).replace(/'/g, "'\\''");
|
|
420
|
-
await executor.exec(`cd ${REMOTE_POWERLINE_DIRECTORY} && node -e "`
|
|
421
|
-
+ `const p=JSON.parse(require('fs').readFileSync('package.json','utf8'));`
|
|
422
|
-
+ `for(const k of Object.keys(p.dependencies||{})){if(k.startsWith('@grackle-ai/'))delete p.dependencies[k];}`
|
|
423
|
-
+ `for(const k of Object.keys(p.devDependencies||{})){if(k.startsWith('@grackle-ai/'))delete p.devDependencies[k];}`
|
|
424
|
-
+ `Object.assign(p.dependencies||{},JSON.parse(process.argv[1]));`
|
|
425
|
-
+ `require('fs').writeFileSync('package.json',JSON.stringify(p,null,2));" '${extraDepsJson}'`, { timeout: REMOTE_EXEC_DEFAULT_TIMEOUT_MS });
|
|
426
|
-
await executor.exec(`cd ${REMOTE_POWERLINE_DIRECTORY} && npm install --omit=dev --legacy-peer-deps --registry=https://registry.npmjs.org`, { timeout: BOOTSTRAP_NPM_INSTALL_TIMEOUT_MS });
|
|
427
|
-
// Copy @grackle-ai/* packages AFTER all npm installs (npm wipes unmanaged dirs)
|
|
428
|
-
for (const [name, dir] of [["common", commonPackageDir], ["mcp", mcpPackageDir]]) {
|
|
429
|
-
const remotePkgDir = `${REMOTE_POWERLINE_DIRECTORY}/node_modules/@grackle-ai/${name}`;
|
|
430
|
-
yield { stage: "bootstrapping", message: `Copying @grackle-ai/${name}...`, progress: name === "common" ? 0.57 : 0.59 };
|
|
431
|
-
await executor.exec(`mkdir -p ${remotePkgDir}`, { timeout: REMOTE_EXEC_DEFAULT_TIMEOUT_MS });
|
|
432
|
-
await executor.copyTo(join(dir, "dist"), `${remotePkgDir}/dist`);
|
|
433
|
-
await executor.copyTo(join(dir, "package.json"), `${remotePkgDir}/package.json`);
|
|
434
|
-
}
|
|
435
|
-
}
|
|
436
|
-
else {
|
|
437
|
-
// ── Production mode: npm install from registry ──
|
|
438
|
-
const version = getPackageVersion();
|
|
439
|
-
yield { stage: "bootstrapping", message: "Creating remote directories...", progress: 0.20 };
|
|
440
|
-
await executor.exec(`mkdir -p ${REMOTE_POWERLINE_DIRECTORY}`, { timeout: REMOTE_EXEC_DEFAULT_TIMEOUT_MS });
|
|
441
|
-
yield { stage: "bootstrapping", message: `Installing @grackle-ai/powerline@${version}...`, progress: 0.25 };
|
|
442
|
-
await executor.exec(`cd ${REMOTE_POWERLINE_DIRECTORY} && npm init -y && npm install @grackle-ai/powerline@${version} --omit=dev --legacy-peer-deps --registry=https://registry.npmjs.org`, { timeout: BOOTSTRAP_NPM_INSTALL_TIMEOUT_MS });
|
|
443
|
-
}
|
|
444
|
-
logger.info({ devMode }, "PowerLine bootstrap mode");
|
|
445
|
-
// 4. Configure git credential helper so agents can push to GitHub.
|
|
446
|
-
// Writes a small shell script that provides GITHUB_TOKEN (from PowerLine's env)
|
|
447
|
-
// as the password for HTTPS git operations. Stored in the PowerLine directory
|
|
448
|
-
// so destroy() cleans it up.
|
|
449
|
-
yield { stage: "bootstrapping", message: "Configuring git credentials...", progress: 0.56 };
|
|
450
|
-
try {
|
|
451
|
-
const credHelperScript = '#!/bin/sh\ntest "$1" = get || exit 0\necho "username=x-access-token"\necho "password=${GITHUB_TOKEN:-$GH_TOKEN}"\n';
|
|
452
|
-
const credHelperBase64 = Buffer.from(credHelperScript, "utf8").toString("base64");
|
|
453
|
-
const credHelperPath = `${REMOTE_POWERLINE_DIRECTORY}/git-credential-github.sh`;
|
|
454
|
-
await executor.exec(`node -e "require('fs').writeFileSync(process.argv[1],Buffer.from(process.argv[2],'base64').toString('utf8'),{mode:0o755})" `
|
|
455
|
-
+ `"${credHelperPath}" '${credHelperBase64}'`
|
|
456
|
-
+ ` && git config --global credential.helper "${credHelperPath}"`, { timeout: REMOTE_EXEC_DEFAULT_TIMEOUT_MS });
|
|
457
|
-
logger.info("Git credential helper configured at %s", credHelperPath);
|
|
458
|
-
}
|
|
459
|
-
catch (err) {
|
|
460
|
-
logger.warn({ err }, "Failed to configure git credential helper (agents may be unable to push)");
|
|
461
|
-
}
|
|
462
|
-
// 5. Kill any existing PowerLine process on the port (with fallbacks)
|
|
463
|
-
yield { stage: "bootstrapping", message: "Stopping any existing PowerLine process...", progress: 0.60 };
|
|
464
|
-
try {
|
|
465
|
-
await executor.exec(buildRemoteKillCommand(), { timeout: REMOTE_EXEC_DEFAULT_TIMEOUT_MS });
|
|
466
|
-
await sleep(1_000);
|
|
467
|
-
}
|
|
468
|
-
catch {
|
|
469
|
-
// Ignore — no process to kill
|
|
470
|
-
}
|
|
471
|
-
// 6–8. Write env vars, start process, wait, verify
|
|
472
|
-
yield { stage: "bootstrapping", message: "Starting PowerLine on remote host...", progress: 0.65 };
|
|
473
|
-
await startRemotePowerLine(executor, powerlineToken, { extraEnv: enrichedExtraEnv, workingDirectory, host });
|
|
474
|
-
yield { stage: "bootstrapping", message: "PowerLine is running on remote host", progress: 0.75 };
|
|
475
|
-
}
|
|
476
|
-
// ─── Connect Through Tunnel ────────────────────────────────
|
|
477
|
-
/**
|
|
478
|
-
* Connect to a PowerLine through a local tunnel port, retrying until the gRPC
|
|
479
|
-
* service responds to a ping.
|
|
480
|
-
*/
|
|
481
|
-
export async function connectThroughTunnel(environmentId, localPort, powerlineToken) {
|
|
482
|
-
const client = createPowerLineClient(`http://127.0.0.1:${localPort}`, powerlineToken);
|
|
483
|
-
let lastError;
|
|
484
|
-
for (let attempt = 0; attempt < CONNECT_MAX_RETRIES; attempt++) {
|
|
485
|
-
try {
|
|
486
|
-
await client.ping({});
|
|
487
|
-
return { client, environmentId, port: localPort };
|
|
488
|
-
}
|
|
489
|
-
catch (err) {
|
|
490
|
-
lastError = err;
|
|
491
|
-
await sleep(CONNECT_RETRY_DELAY_MS);
|
|
492
|
-
}
|
|
493
|
-
}
|
|
494
|
-
// Clean up the tunnel so we don't leak background processes on connect failure
|
|
495
|
-
try {
|
|
496
|
-
await closeTunnel(environmentId);
|
|
497
|
-
}
|
|
498
|
-
catch (err) {
|
|
499
|
-
logger.error({ environmentId, err }, "Failed to close tunnel after connect failure");
|
|
500
|
-
}
|
|
501
|
-
throw new Error(`Could not reach PowerLine after ${CONNECT_MAX_RETRIES} attempts: ${lastError instanceof Error ? lastError.message : String(lastError)}`);
|
|
502
|
-
}
|
|
503
|
-
// ─── Wait for Local Port ────────────────────────────────────
|
|
504
|
-
/**
|
|
505
|
-
* Poll until a TCP connection can be established on localhost at the given port.
|
|
506
|
-
* Used to wait for a tunnel process to begin accepting connections.
|
|
507
|
-
*/
|
|
508
|
-
export async function waitForLocalPort(port) {
|
|
509
|
-
for (let attempt = 0; attempt < TUNNEL_PORT_POLL_MAX_ATTEMPTS; attempt++) {
|
|
510
|
-
const reachable = await new Promise((resolve) => {
|
|
511
|
-
const socket = createConnection({ host: "127.0.0.1", port });
|
|
512
|
-
socket.once("connect", () => {
|
|
513
|
-
socket.destroy();
|
|
514
|
-
resolve(true);
|
|
515
|
-
});
|
|
516
|
-
socket.once("error", () => {
|
|
517
|
-
socket.destroy();
|
|
518
|
-
resolve(false);
|
|
519
|
-
});
|
|
520
|
-
});
|
|
521
|
-
if (reachable) {
|
|
522
|
-
return;
|
|
523
|
-
}
|
|
524
|
-
await sleep(TUNNEL_PORT_POLL_DELAY_MS);
|
|
525
|
-
}
|
|
526
|
-
throw new Error(`Local port ${port} did not become reachable after ${TUNNEL_PORT_POLL_MAX_ATTEMPTS} attempts`);
|
|
527
|
-
}
|
|
528
|
-
// ─── Remote Process Kill ────────────────────────────────────
|
|
529
|
-
/**
|
|
530
|
-
* Build a shell command that kills the remote PowerLine process.
|
|
531
|
-
* Prefers killing by tracked PID (written at startup) to avoid terminating
|
|
532
|
-
* unrelated services on the same port. Falls back to port-based kill.
|
|
533
|
-
*/
|
|
534
|
-
export function buildRemoteKillCommand() {
|
|
535
|
-
const pidfile = `${REMOTE_POWERLINE_DIRECTORY}/powerline.pid`;
|
|
536
|
-
// Try pidfile-based kill first (safe — only kills what we started)
|
|
537
|
-
const pidfileKill = [
|
|
538
|
-
`[ -f "${pidfile}" ]`,
|
|
539
|
-
`PID=$(cat "${pidfile}" 2>/dev/null)`,
|
|
540
|
-
`[ -n "$PID" ]`,
|
|
541
|
-
`kill "$PID" 2>/dev/null`,
|
|
542
|
-
`rm -f "${pidfile}"`,
|
|
543
|
-
].join(" && ");
|
|
544
|
-
// Fallback: port-based kill (for upgrades from before pidfile support)
|
|
545
|
-
const portKill = `fuser -k ${DEFAULT_POWERLINE_PORT}/tcp 2>/dev/null`
|
|
546
|
-
+ ` || lsof -ti:${DEFAULT_POWERLINE_PORT} | xargs kill 2>/dev/null`
|
|
547
|
-
+ ` || pkill -f "powerline.*${DEFAULT_POWERLINE_PORT}" 2>/dev/null`;
|
|
548
|
-
return `(${pidfileKill}) || (${portKill}) || true`;
|
|
549
|
-
}
|
|
550
|
-
// ─── Shared Adapter Operations ──────────────────────────────
|
|
551
|
-
/**
|
|
552
|
-
* Stop the remote PowerLine process and close the tunnel.
|
|
553
|
-
* Shared by SSH and Codespace adapters.
|
|
554
|
-
*/
|
|
555
|
-
export async function remoteStop(environmentId, executor) {
|
|
556
|
-
try {
|
|
557
|
-
await executor.exec(buildRemoteKillCommand());
|
|
558
|
-
}
|
|
559
|
-
catch (err) {
|
|
560
|
-
logger.debug({ environmentId, err }, "Failed to kill remote PowerLine (may already be stopped)");
|
|
561
|
-
}
|
|
562
|
-
await closeTunnel(environmentId);
|
|
563
|
-
}
|
|
564
|
-
/**
|
|
565
|
-
* Stop the remote PowerLine, remove artifacts, and close the tunnel.
|
|
566
|
-
* Shared by SSH and Codespace adapters.
|
|
567
|
-
*/
|
|
568
|
-
export async function remoteDestroy(environmentId, executor) {
|
|
569
|
-
try {
|
|
570
|
-
await executor.exec(`${buildRemoteKillCommand()}; `
|
|
571
|
-
+ 'CRED="$HOME/.claude/.credentials.json"; '
|
|
572
|
-
+ `if [ -L "$CRED" ]; then case "$(readlink "$CRED" 2>/dev/null)" in ${REMOTE_POWERLINE_DIRECTORY}/*) rm -f "$CRED";; esac; fi; `
|
|
573
|
-
+ `HELPER="$(git config --global credential.helper 2>/dev/null || true)"; `
|
|
574
|
-
+ `case "$HELPER" in ${REMOTE_POWERLINE_DIRECTORY}/*) git config --global --unset credential.helper 2>/dev/null || true;; esac; `
|
|
575
|
-
+ `rm -rf ${REMOTE_POWERLINE_DIRECTORY}`);
|
|
576
|
-
}
|
|
577
|
-
catch (err) {
|
|
578
|
-
logger.debug({ environmentId, err }, "Failed to clean up remote PowerLine artifacts");
|
|
579
|
-
}
|
|
580
|
-
await closeTunnel(environmentId);
|
|
581
|
-
}
|
|
582
|
-
/** Check that the tunnel is alive and the PowerLine responds to a ping. */
|
|
583
|
-
export async function remoteHealthCheck(connection) {
|
|
584
|
-
const state = getTunnel(connection.environmentId);
|
|
585
|
-
if (!state?.tunnel.isAlive()) {
|
|
586
|
-
return false;
|
|
587
|
-
}
|
|
588
|
-
try {
|
|
589
|
-
await connection.client.ping({});
|
|
590
|
-
return true;
|
|
591
|
-
}
|
|
592
|
-
catch {
|
|
593
|
-
return false;
|
|
594
|
-
}
|
|
595
|
-
}
|
|
596
|
-
// ─── Exports for Adapter Use ────────────────────────────────
|
|
597
|
-
export { findFreePort, REMOTE_POWERLINE_DIRECTORY, SSH_CONNECTIVITY_TIMEOUT_MS, REMOTE_EXEC_DEFAULT_TIMEOUT_MS };
|
|
598
|
-
//# sourceMappingURL=remote-adapter-utils.js.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"remote-adapter-utils.js","sourceRoot":"","sources":["../../src/adapters/remote-adapter-utils.ts"],"names":[],"mappings":"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"}
|