agent-relay 6.0.16 → 6.0.18

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 (63) hide show
  1. package/dist/index.cjs +111 -32
  2. package/dist/packages/cloud/src/api-client.d.ts +33 -0
  3. package/dist/packages/cloud/src/api-client.d.ts.map +1 -0
  4. package/dist/packages/cloud/src/api-client.js +123 -0
  5. package/dist/packages/cloud/src/api-client.js.map +1 -0
  6. package/dist/packages/cloud/src/auth.d.ts +13 -0
  7. package/dist/packages/cloud/src/auth.d.ts.map +1 -0
  8. package/dist/packages/cloud/src/auth.js +299 -0
  9. package/dist/packages/cloud/src/auth.js.map +1 -0
  10. package/dist/packages/cloud/src/connect.d.ts +45 -0
  11. package/dist/packages/cloud/src/connect.d.ts.map +1 -0
  12. package/dist/packages/cloud/src/connect.js +166 -0
  13. package/dist/packages/cloud/src/connect.js.map +1 -0
  14. package/dist/packages/cloud/src/index.d.ts +10 -0
  15. package/dist/packages/cloud/src/index.d.ts.map +1 -0
  16. package/dist/packages/cloud/src/index.js +10 -0
  17. package/dist/packages/cloud/src/index.js.map +1 -0
  18. package/dist/packages/cloud/src/lib/ssh-interactive.d.ts +70 -0
  19. package/dist/packages/cloud/src/lib/ssh-interactive.d.ts.map +1 -0
  20. package/dist/packages/cloud/src/lib/ssh-interactive.js +440 -0
  21. package/dist/packages/cloud/src/lib/ssh-interactive.js.map +1 -0
  22. package/dist/packages/cloud/src/lib/ssh-runtime.d.ts +35 -0
  23. package/dist/packages/cloud/src/lib/ssh-runtime.d.ts.map +1 -0
  24. package/dist/packages/cloud/src/lib/ssh-runtime.js +52 -0
  25. package/dist/packages/cloud/src/lib/ssh-runtime.js.map +1 -0
  26. package/dist/packages/cloud/src/proactive-runtime.d.ts +24 -0
  27. package/dist/packages/cloud/src/proactive-runtime.d.ts.map +1 -0
  28. package/dist/packages/cloud/src/proactive-runtime.js +315 -0
  29. package/dist/packages/cloud/src/proactive-runtime.js.map +1 -0
  30. package/dist/packages/cloud/src/types.d.ts +200 -0
  31. package/dist/packages/cloud/src/types.d.ts.map +1 -0
  32. package/dist/packages/cloud/src/types.js +12 -0
  33. package/dist/packages/cloud/src/types.js.map +1 -0
  34. package/dist/packages/cloud/src/workflows.d.ts +65 -0
  35. package/dist/packages/cloud/src/workflows.d.ts.map +1 -0
  36. package/dist/packages/cloud/src/workflows.js +892 -0
  37. package/dist/packages/cloud/src/workflows.js.map +1 -0
  38. package/dist/packages/cloud/src/workspaces.d.ts +11 -0
  39. package/dist/packages/cloud/src/workspaces.d.ts.map +1 -0
  40. package/dist/packages/cloud/src/workspaces.js +146 -0
  41. package/dist/packages/cloud/src/workspaces.js.map +1 -0
  42. package/dist/src/cli/bootstrap.d.ts +3 -1
  43. package/dist/src/cli/bootstrap.d.ts.map +1 -1
  44. package/dist/src/cli/bootstrap.js +17 -3
  45. package/dist/src/cli/bootstrap.js.map +1 -1
  46. package/dist/src/cli/commands/cloud.js +1 -1
  47. package/dist/src/cli/commands/cloud.js.map +1 -1
  48. package/dist/src/cli/commands/dlq.d.ts +20 -0
  49. package/dist/src/cli/commands/dlq.d.ts.map +1 -0
  50. package/dist/src/cli/commands/dlq.js +456 -0
  51. package/dist/src/cli/commands/dlq.js.map +1 -0
  52. package/dist/src/cli/commands/proactive-bootstrap.d.ts +10 -0
  53. package/dist/src/cli/commands/proactive-bootstrap.d.ts.map +1 -0
  54. package/dist/src/cli/commands/proactive-bootstrap.js +133 -0
  55. package/dist/src/cli/commands/proactive-bootstrap.js.map +1 -0
  56. package/dist/src/cli/commands/relay-runtime.d.ts +58 -0
  57. package/dist/src/cli/commands/relay-runtime.d.ts.map +1 -0
  58. package/dist/src/cli/commands/relay-runtime.js +484 -0
  59. package/dist/src/cli/commands/relay-runtime.js.map +1 -0
  60. package/dist/src/cli/commands/setup.d.ts.map +1 -1
  61. package/dist/src/cli/commands/setup.js +11 -9
  62. package/dist/src/cli/commands/setup.js.map +1 -1
  63. package/package.json +11 -10
@@ -0,0 +1 @@
1
+ {"version":3,"file":"ssh-interactive.d.ts","sourceRoot":"","sources":["../../../../../packages/cloud/src/lib/ssh-interactive.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAIH,OAAO,EAAqC,KAAK,YAAY,EAAE,MAAM,qCAAqC,CAAC;AAC3G,OAAO,EAAqD,KAAK,cAAc,EAAE,MAAM,kBAAkB,CAAC;AAI1G,MAAM,WAAW,iBAAiB;IAChC,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,EAAE,MAAM,CAAC;IACb,QAAQ,EAAE,MAAM,CAAC;CAClB;AAED,MAAM,WAAW,yBAAyB;IACxC,GAAG,EAAE,iBAAiB,CAAC;IACvB,aAAa,EAAE,MAAM,CAAC;IACtB,eAAe,EAAE,MAAM,EAAE,CAAC;IAC1B,aAAa,EAAE,YAAY,EAAE,CAAC;IAC9B,SAAS,EAAE,MAAM,CAAC;IAClB,EAAE,EAAE;QAAE,GAAG,EAAE,CAAC,GAAG,IAAI,EAAE,OAAO,EAAE,KAAK,IAAI,CAAC;QAAC,KAAK,EAAE,CAAC,GAAG,IAAI,EAAE,OAAO,EAAE,KAAK,IAAI,CAAA;KAAE,CAAC;IAC/E,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,OAAO,CAAC,EAAE,OAAO,CAAC,cAAc,CAAC,CAAC;CACnC;AAED,MAAM,WAAW,wBAAwB;IACvC,QAAQ,EAAE,MAAM,GAAG,IAAI,CAAC;IACxB,UAAU,EAAE,MAAM,GAAG,IAAI,CAAC;IAC1B,YAAY,EAAE,OAAO,CAAC;CACvB;AAsDD;;;;;;;;;;;;;;;GAeG;AACH,wBAAgB,qBAAqB,CAAC,OAAO,EAAE,MAAM,GAAG,MAAM,CAG7D;AAED;;;;;;;;;;GAUG;AACH,wBAAgB,wBAAwB,CAAC,OAAO,EAAE,MAAM,GAAG,MAAM,CAGhE;AAED;;;;;;GAMG;AACH,wBAAsB,qBAAqB,CACzC,OAAO,EAAE,yBAAyB,GACjC,OAAO,CAAC,wBAAwB,CAAC,CAyXnC"}
@@ -0,0 +1,440 @@
1
+ /**
2
+ * SSH Interactive Session — reusable SSH+PTY runner.
3
+ *
4
+ * Powers both `agent-relay auth <provider>` and `agent-relay cloud connect <provider>`,
5
+ * and is published from `@agent-relay/cloud` so other CLIs can drive the same flow.
6
+ */
7
+ import { createServer } from 'node:net';
8
+ import { spawn as spawnProcess } from 'node:child_process';
9
+ import { stripAnsiCodes, findMatchingError } from '@agent-relay/config/cli-auth-config';
10
+ import { loadSSH2, createAskpassScript, buildSystemSshArgs } from './ssh-runtime.js';
11
+ // ── Debug (env-gated) ────────────────────────────────────────────────────────
12
+ const DEBUG = process.env.AGENT_RELAY_DEBUG_SSH === '1';
13
+ function dbg(event, fields = {}) {
14
+ if (!DEBUG)
15
+ return;
16
+ const ts = new Date().toISOString();
17
+ const parts = Object.entries(fields)
18
+ .map(([k, v]) => `${k}=${typeof v === 'string' ? JSON.stringify(v) : v}`)
19
+ .join(' ');
20
+ process.stderr.write(`[ssh-debug ${ts}] ${event}${parts ? ' ' + parts : ''}\n`);
21
+ }
22
+ // ── Helpers ──────────────────────────────────────────────────────────────────
23
+ const color = {
24
+ cyan: (s) => `\x1b[36m${s}\x1b[0m`,
25
+ green: (s) => `\x1b[32m${s}\x1b[0m`,
26
+ yellow: (s) => `\x1b[33m${s}\x1b[0m`,
27
+ red: (s) => `\x1b[31m${s}\x1b[0m`,
28
+ dim: (s) => `\x1b[2m${s}\x1b[0m`,
29
+ };
30
+ function getSshErrorMessage(host, port, err) {
31
+ if (err.message.includes('Authentication')) {
32
+ return 'SSH authentication failed.';
33
+ }
34
+ if (err.message.includes('ECONNREFUSED')) {
35
+ return `Cannot connect to SSH server at ${host}:${port}. Is the workspace running and SSH enabled?`;
36
+ }
37
+ if (err.message.includes('ENOTFOUND') || err.message.includes('getaddrinfo')) {
38
+ return `Cannot resolve hostname: ${host}. Check network connectivity.`;
39
+ }
40
+ if (err.message.includes('ETIMEDOUT')) {
41
+ return `Connection timed out to ${host}:${port}. Is the workspace running?`;
42
+ }
43
+ return `SSH error: ${err.message}`;
44
+ }
45
+ // ── Main function ────────────────────────────────────────────────────────────
46
+ const DEFAULT_RUNTIME = {
47
+ loadSSH2,
48
+ createAskpassScript,
49
+ buildSystemSshArgs,
50
+ spawnProcess,
51
+ createServer,
52
+ setTimeout,
53
+ };
54
+ /**
55
+ * Format a remote command for execution inside an ssh2 shell() PTY.
56
+ *
57
+ * Wraps the command in `exec sh -c '…'` so the PTY closes cleanly when the
58
+ * target CLI exits (no shell-teardown race with a TUI's alt-screen flush)
59
+ * while still letting `sh` parse leading prefix assignments like
60
+ * `PATH=/foo/bin claude`. A bare `exec PATH=… claude` does not work in zsh
61
+ * because zsh's exec builtin treats `PATH=…` as the command name instead of
62
+ * a prefix assignment.
63
+ *
64
+ * We intentionally use `shell()` rather than `exec(cmd, { pty })` because
65
+ * Daytona's sandbox sshd only populates the full login-shell environment
66
+ * (including nvm-managed PATH entries where `claude` / `codex` actually live)
67
+ * for interactive shell sessions. An `exec` channel with a PTY gets a
68
+ * stripped-down environment and the target CLI fails to start silently.
69
+ */
70
+ export function formatShellInvocation(command) {
71
+ const escaped = command.replace(/'/g, `'\\''`);
72
+ return `exec sh -c '${escaped}'\n`;
73
+ }
74
+ /**
75
+ * Wrap the remote command with a visible checkpoint so the user sees proof
76
+ * the ssh pipeline reached the sandbox before the provider CLI takes over
77
+ * the terminal. Without this, claude/codex enter alt-screen immediately and
78
+ * the user sees zero output — indistinguishable from a hang.
79
+ *
80
+ * The printf runs before the exec that launches the provider CLI, so the
81
+ * user gets one visible line ("launching provider CLI…") right before
82
+ * alt-screen engages. When the provider CLI later exits and the alt-screen
83
+ * tears down, this line remains in scrollback as a breadcrumb.
84
+ */
85
+ export function wrapWithLaunchCheckpoint(command) {
86
+ // Escape single quotes for inclusion in the printf argument.
87
+ return `printf '\\033[2m[agent-relay] launching provider CLI…\\033[0m\\n' >&2; ${command}`;
88
+ }
89
+ /**
90
+ * Run an interactive SSH session with PTY.
91
+ *
92
+ * Connects via ssh2 (if available) or falls back to system ssh,
93
+ * sets up a local port tunnel, and runs the remote command in a PTY.
94
+ * Monitors output for success/error patterns.
95
+ */
96
+ export async function runInteractiveSession(options) {
97
+ const { ssh, successPatterns, errorPatterns, timeoutMs, io, tunnelPort = 1455 } = options;
98
+ const runtime = { ...DEFAULT_RUNTIME, ...options.runtime };
99
+ // Wrap the remote command with a visible checkpoint so the user sees proof
100
+ // the ssh pipeline is alive before the provider CLI enters alt-screen.
101
+ const remoteCommand = wrapWithLaunchCheckpoint(options.remoteCommand);
102
+ const ssh2 = await runtime.loadSSH2();
103
+ io.log(color.yellow('Starting interactive authentication...'));
104
+ io.log(color.dim(`Transport: ${ssh2 ? 'ssh2 (bundled)' : 'system ssh (fallback)'}`));
105
+ io.log(color.dim('The provider CLI may take 5-15s to render its first screen after connecting.'));
106
+ io.log(color.dim('A welcome / theme picker may appear before the sign-in step. Follow the on-screen prompts.'));
107
+ io.log(color.dim('Wait for the CLI to render before pressing Ctrl+C.'));
108
+ io.log('');
109
+ let execResult = null;
110
+ let execError = null;
111
+ if (ssh2) {
112
+ const { Client } = ssh2;
113
+ const sshClient = new Client();
114
+ let sshReady = false;
115
+ const tunnel = { server: null };
116
+ const sshReadyPromise = new Promise((resolve, reject) => {
117
+ sshClient.on('ready', () => {
118
+ sshReady = true;
119
+ tunnel.server = runtime.createServer((localSocket) => {
120
+ sshClient.forwardOut('127.0.0.1', tunnelPort, 'localhost', tunnelPort, (err, stream) => {
121
+ if (err) {
122
+ localSocket.end();
123
+ return;
124
+ }
125
+ localSocket.pipe(stream).pipe(localSocket);
126
+ });
127
+ });
128
+ tunnel.server.on('error', (err) => {
129
+ if (err.code === 'EADDRINUSE') {
130
+ io.log(color.dim(`Note: Port ${tunnelPort} in use, OAuth callbacks may not work.`));
131
+ }
132
+ resolve();
133
+ });
134
+ tunnel.server.listen(tunnelPort, '127.0.0.1', () => {
135
+ resolve();
136
+ });
137
+ });
138
+ sshClient.on('error', (err) => {
139
+ reject(new Error(getSshErrorMessage(ssh.host, ssh.port, err)));
140
+ });
141
+ sshClient.on('close', () => {
142
+ if (!sshReady) {
143
+ reject(new Error(`SSH connection to ${ssh.host}:${ssh.port} closed unexpectedly.`));
144
+ }
145
+ });
146
+ });
147
+ try {
148
+ sshClient.connect({
149
+ host: ssh.host,
150
+ port: ssh.port,
151
+ username: ssh.user,
152
+ password: ssh.password,
153
+ readyTimeout: 10000,
154
+ hostVerifier: () => true,
155
+ });
156
+ await Promise.race([
157
+ sshReadyPromise,
158
+ new Promise((_, reject) => runtime.setTimeout(() => reject(new Error('SSH connection timeout')), 15000)),
159
+ ]);
160
+ }
161
+ catch (err) {
162
+ io.error(color.red(`Failed to connect via SSH: ${err instanceof Error ? err.message : String(err)}`));
163
+ if (tunnel.server)
164
+ tunnel.server.close();
165
+ sshClient.end();
166
+ throw err;
167
+ }
168
+ const execInteractive = async (command, commandTimeoutMs) => await new Promise((resolve, reject) => {
169
+ const cols = process.stdout.columns || 80;
170
+ const rows = process.stdout.rows || 24;
171
+ const term = process.env.TERM || 'xterm-256color';
172
+ dbg('shell-request', { term, cols, rows });
173
+ // Use shell() so the remote side sources its login-shell init files
174
+ // (/etc/profile, ~/.zprofile, nvm setup, …). Daytona's sandbox image
175
+ // populates the nvm-managed PATH (/usr/local/share/nvm/current/bin)
176
+ // from those init files, and without them the target CLIs (claude,
177
+ // codex) are not on PATH and fail to start silently. An exec channel
178
+ // with `{ pty }` was tried and produced zero output for this reason.
179
+ sshClient.shell({ term, cols, rows }, (err, stream) => {
180
+ if (err) {
181
+ dbg('shell-error', { message: err.message });
182
+ return reject(err);
183
+ }
184
+ dbg('shell-opened');
185
+ let exitCode = null;
186
+ let exitSignal = null;
187
+ let authDetected = false;
188
+ let outputBuffer = '';
189
+ // Gate pattern matching so shell MOTD (e.g. "Last logged in …")
190
+ // does not trigger the broad `/logged\s*in/i` success pattern
191
+ // before the target CLI has even started.
192
+ let patternMatchingEnabled = false;
193
+ // Track whether we've drawn the dim "waiting" hint so we can clear
194
+ // it the moment the remote CLI starts producing real output.
195
+ let hintVisible = false;
196
+ const stdin = process.stdin;
197
+ const stdout = process.stdout;
198
+ const stderr = process.stderr;
199
+ const wasRaw = stdin.isRaw ?? false;
200
+ const onStdinData = (data) => {
201
+ if (authDetected && (data[0] === 0x1b || data[0] === 0x03)) {
202
+ cleanup();
203
+ clearTimeout(timer);
204
+ try {
205
+ stream.close();
206
+ }
207
+ catch {
208
+ // ignore
209
+ }
210
+ return;
211
+ }
212
+ stream.write(data);
213
+ };
214
+ const cleanup = () => {
215
+ stdin.off('data', onStdinData);
216
+ stdout.off('resize', onResize);
217
+ try {
218
+ stdin.setRawMode?.(wasRaw);
219
+ }
220
+ catch {
221
+ // ignore
222
+ }
223
+ stdin.pause();
224
+ };
225
+ const closeOnAuthSuccess = () => {
226
+ authDetected = true;
227
+ stdout.write('\n');
228
+ stdout.write(color.green(' ✓ Authentication successful!') + '\n');
229
+ stdout.write(color.dim(' Press Escape or Ctrl+C to exit.') + '\n');
230
+ stdout.write('\n');
231
+ };
232
+ let totalBytes = 0;
233
+ let firstByteAt = null;
234
+ const sessionStart = Date.now();
235
+ stream.on('data', (data) => {
236
+ totalBytes += data.length;
237
+ if (firstByteAt === null) {
238
+ firstByteAt = Date.now();
239
+ dbg('first-byte', {
240
+ elapsedMs: firstByteAt - sessionStart,
241
+ bytes: data.length,
242
+ preview: data.toString('utf8').slice(0, 120),
243
+ });
244
+ if (hintVisible) {
245
+ // Clear the dim "waiting" hint line before the remote CLI
246
+ // paints its own UI. \r moves to col 0, \x1b[2K clears the
247
+ // line, so the subsequent bytes (including any alt-screen
248
+ // switch) render from a known-clean state.
249
+ stdout.write('\r\x1b[2K');
250
+ hintVisible = false;
251
+ }
252
+ }
253
+ else if (DEBUG) {
254
+ dbg('data-out', { bytes: data.length, totalBytes });
255
+ }
256
+ stdout.write(data);
257
+ outputBuffer += data.toString();
258
+ if (outputBuffer.length > 8192) {
259
+ outputBuffer = outputBuffer.slice(-8192);
260
+ }
261
+ if (patternMatchingEnabled && !authDetected && successPatterns.length > 0) {
262
+ const clean = stripAnsiCodes(outputBuffer);
263
+ for (const pattern of successPatterns) {
264
+ if (pattern.test(clean)) {
265
+ closeOnAuthSuccess();
266
+ break;
267
+ }
268
+ }
269
+ }
270
+ if (patternMatchingEnabled && !authDetected && errorPatterns.length > 0) {
271
+ const matched = findMatchingError(outputBuffer, errorPatterns);
272
+ if (matched) {
273
+ clearTimeout(timer);
274
+ cleanup();
275
+ try {
276
+ stream.close();
277
+ }
278
+ catch {
279
+ // ignore
280
+ }
281
+ reject(new Error(matched.message + (matched.hint ? ` ${matched.hint}` : '')));
282
+ }
283
+ }
284
+ });
285
+ stream.stderr.on('data', (data) => {
286
+ dbg('stderr-out', { bytes: data.length });
287
+ stderr.write(data);
288
+ });
289
+ const onResize = () => {
290
+ try {
291
+ stream.setWindow(stdout.rows || 24, stdout.columns || 80, 0, 0);
292
+ }
293
+ catch {
294
+ // ignore
295
+ }
296
+ };
297
+ stream.on('exit', (code, signal) => {
298
+ dbg('stream-exit', { code, signal });
299
+ if (typeof code === 'number')
300
+ exitCode = code;
301
+ if (typeof signal === 'string')
302
+ exitSignal = signal;
303
+ });
304
+ stream.on('close', () => {
305
+ dbg('stream-close', {
306
+ totalBytes,
307
+ firstByteAt: firstByteAt !== null ? firstByteAt - sessionStart : null,
308
+ exitCode,
309
+ exitSignal,
310
+ authDetected,
311
+ });
312
+ clearTimeout(timer);
313
+ cleanup();
314
+ if (totalBytes === 0 && !authDetected) {
315
+ io.log('');
316
+ io.error(color.red('No output received from the remote auth command before the session closed.'));
317
+ io.error(color.dim(' This usually means the remote CLI failed to start. Re-run with AGENT_RELAY_DEBUG_SSH=1 for details.'));
318
+ }
319
+ resolve({ exitCode, exitSignal, authDetected });
320
+ });
321
+ stream.on('error', (streamErr) => {
322
+ dbg('stream-error', {
323
+ message: streamErr instanceof Error ? streamErr.message : String(streamErr),
324
+ });
325
+ clearTimeout(timer);
326
+ cleanup();
327
+ reject(streamErr instanceof Error ? streamErr : new Error(String(streamErr)));
328
+ });
329
+ stdout.on('resize', onResize);
330
+ stdin.on('data', onStdinData);
331
+ try {
332
+ stdin.setRawMode?.(true);
333
+ }
334
+ catch {
335
+ // ignore
336
+ }
337
+ stdin.resume();
338
+ const timer = runtime.setTimeout(() => {
339
+ cleanup();
340
+ try {
341
+ stream.close();
342
+ }
343
+ catch {
344
+ // ignore
345
+ }
346
+ reject(new Error(`Authentication timed out after ${Math.floor(commandTimeoutMs / 1000)}s`));
347
+ }, commandTimeoutMs);
348
+ const invocation = formatShellInvocation(command);
349
+ dbg('shell-write', { bytes: invocation.length, preview: invocation.slice(0, 200) });
350
+ stream.write(invocation);
351
+ // Reset the output buffer so pattern matching only considers output
352
+ // produced by the command we just wrote, not the shell's MOTD.
353
+ outputBuffer = '';
354
+ patternMatchingEnabled = true;
355
+ // Show a single-line dim hint so the user can see something is
356
+ // happening while the remote shell starts. As soon as the first
357
+ // byte comes back from the target CLI, we clear this line (see
358
+ // stream.on('data')) and hand the terminal over to the remote.
359
+ stdout.write(color.dim(' Waiting for provider CLI to launch…'));
360
+ hintVisible = true;
361
+ });
362
+ });
363
+ try {
364
+ execResult = await execInteractive(remoteCommand, timeoutMs);
365
+ }
366
+ catch (err) {
367
+ execError = err instanceof Error ? err : new Error(String(err));
368
+ io.log('');
369
+ io.error(color.red(`Remote auth command failed: ${execError.message}`));
370
+ }
371
+ finally {
372
+ if (tunnel.server)
373
+ tunnel.server.close();
374
+ sshClient.end();
375
+ }
376
+ }
377
+ else {
378
+ // Fallback: system ssh
379
+ const askpassPath = runtime.createAskpassScript(ssh.password);
380
+ try {
381
+ const sshArgs = runtime.buildSystemSshArgs({
382
+ host: ssh.host,
383
+ port: ssh.port,
384
+ username: ssh.user,
385
+ localPort: tunnelPort,
386
+ remotePort: tunnelPort,
387
+ });
388
+ sshArgs.push('-tt');
389
+ sshArgs.push(`${ssh.user}@${ssh.host}`);
390
+ sshArgs.push(remoteCommand);
391
+ const child = runtime.spawnProcess('ssh', sshArgs, {
392
+ stdio: 'inherit',
393
+ env: {
394
+ ...process.env,
395
+ SSH_ASKPASS: askpassPath,
396
+ SSH_ASKPASS_REQUIRE: 'force',
397
+ DISPLAY: process.env.DISPLAY || ':0',
398
+ },
399
+ });
400
+ execResult = await new Promise((resolve) => {
401
+ child.on('exit', (code, signal) => {
402
+ resolve({
403
+ exitCode: code,
404
+ exitSignal: signal ? String(signal) : null,
405
+ authDetected: code === 0,
406
+ });
407
+ });
408
+ child.on('error', (err) => {
409
+ io.error(color.red(`Failed to launch ssh: ${err.message}`));
410
+ resolve({ exitCode: 1, exitSignal: null, authDetected: false });
411
+ });
412
+ });
413
+ }
414
+ catch (err) {
415
+ execError = err instanceof Error ? err : new Error(String(err));
416
+ io.log('');
417
+ io.error(color.red(`SSH error: ${execError.message}`));
418
+ }
419
+ finally {
420
+ try {
421
+ const fs = await import('node:fs');
422
+ fs.unlinkSync(askpassPath);
423
+ }
424
+ catch {
425
+ // ignore
426
+ }
427
+ }
428
+ }
429
+ // Authentication is only considered successful when the interactive session
430
+ // reported a positive pattern match. A shell exit code of 0 is NOT trusted:
431
+ // zsh stays alive after a failed `exec` in interactive mode, and a user
432
+ // closing the session with Ctrl+D produces exit 0 even though nothing was
433
+ // authenticated. Callers currently always supply `successPatterns`.
434
+ return {
435
+ exitCode: execError ? 1 : (execResult?.exitCode ?? null),
436
+ exitSignal: execResult?.exitSignal ?? null,
437
+ authDetected: execError === null && execResult?.authDetected === true,
438
+ };
439
+ }
440
+ //# sourceMappingURL=ssh-interactive.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"ssh-interactive.js","sourceRoot":"","sources":["../../../../../packages/cloud/src/lib/ssh-interactive.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,35 @@
1
+ import { spawn as spawnProcess } from 'node:child_process';
2
+ import { createServer } from 'node:net';
3
+ export interface AuthSshRuntime {
4
+ fetch: typeof fetch;
5
+ loadSSH2: () => Promise<typeof import('ssh2') | null>;
6
+ createAskpassScript: (password: string) => string;
7
+ buildSystemSshArgs: (options: {
8
+ host: string;
9
+ port: number;
10
+ username: string;
11
+ localPort?: number;
12
+ remotePort?: number;
13
+ }) => string[];
14
+ spawnProcess: typeof spawnProcess;
15
+ createServer: typeof createServer;
16
+ setTimeout: typeof setTimeout;
17
+ }
18
+ export declare function loadSSH2(): Promise<typeof import('ssh2') | null>;
19
+ /**
20
+ * Create a temporary SSH_ASKPASS helper script that echoes the given password.
21
+ * Returns the script path. Caller must clean up.
22
+ */
23
+ export declare function createAskpassScript(password: string): string;
24
+ /**
25
+ * Build SSH args common to both auth and connect commands.
26
+ */
27
+ export declare function buildSystemSshArgs(options: {
28
+ host: string;
29
+ port: number;
30
+ username: string;
31
+ localPort?: number;
32
+ remotePort?: number;
33
+ }): string[];
34
+ export declare const DEFAULT_SSH_RUNTIME: AuthSshRuntime;
35
+ //# sourceMappingURL=ssh-runtime.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"ssh-runtime.d.ts","sourceRoot":"","sources":["../../../../../packages/cloud/src/lib/ssh-runtime.ts"],"names":[],"mappings":"AAGA,OAAO,EAAE,KAAK,IAAI,YAAY,EAAE,MAAM,oBAAoB,CAAC;AAC3D,OAAO,EAAE,YAAY,EAAE,MAAM,UAAU,CAAC;AAExC,MAAM,WAAW,cAAc;IAC7B,KAAK,EAAE,OAAO,KAAK,CAAC;IACpB,QAAQ,EAAE,MAAM,OAAO,CAAC,cAAc,MAAM,CAAC,GAAG,IAAI,CAAC,CAAC;IACtD,mBAAmB,EAAE,CAAC,QAAQ,EAAE,MAAM,KAAK,MAAM,CAAC;IAClD,kBAAkB,EAAE,CAAC,OAAO,EAAE;QAC5B,IAAI,EAAE,MAAM,CAAC;QACb,IAAI,EAAE,MAAM,CAAC;QACb,QAAQ,EAAE,MAAM,CAAC;QACjB,SAAS,CAAC,EAAE,MAAM,CAAC;QACnB,UAAU,CAAC,EAAE,MAAM,CAAC;KACrB,KAAK,MAAM,EAAE,CAAC;IACf,YAAY,EAAE,OAAO,YAAY,CAAC;IAClC,YAAY,EAAE,OAAO,YAAY,CAAC;IAClC,UAAU,EAAE,OAAO,UAAU,CAAC;CAC/B;AAED,wBAAsB,QAAQ,IAAI,OAAO,CAAC,cAAc,MAAM,CAAC,GAAG,IAAI,CAAC,CAMtE;AAED;;;GAGG;AACH,wBAAgB,mBAAmB,CAAC,QAAQ,EAAE,MAAM,GAAG,MAAM,CAK5D;AAED;;GAEG;AACH,wBAAgB,kBAAkB,CAAC,OAAO,EAAE;IAC1C,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,EAAE,MAAM,CAAC;IACb,QAAQ,EAAE,MAAM,CAAC;IACjB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,UAAU,CAAC,EAAE,MAAM,CAAC;CACrB,GAAG,MAAM,EAAE,CAeX;AAED,eAAO,MAAM,mBAAmB,EAAE,cAQjC,CAAC"}
@@ -0,0 +1,52 @@
1
+ import fs from 'node:fs';
2
+ import path from 'node:path';
3
+ import { tmpdir } from 'node:os';
4
+ import { spawn as spawnProcess } from 'node:child_process';
5
+ import { createServer } from 'node:net';
6
+ export async function loadSSH2() {
7
+ try {
8
+ return await import('ssh2');
9
+ }
10
+ catch {
11
+ return null;
12
+ }
13
+ }
14
+ /**
15
+ * Create a temporary SSH_ASKPASS helper script that echoes the given password.
16
+ * Returns the script path. Caller must clean up.
17
+ */
18
+ export function createAskpassScript(password) {
19
+ const askpassPath = path.join(tmpdir(), `ar-askpass-${process.pid}-${Date.now()}`);
20
+ const escaped = password.replace(/'/g, "'\"'\"'");
21
+ fs.writeFileSync(askpassPath, `#!/bin/sh\nprintf '%s\\n' '${escaped}'\n`, { mode: 0o700 });
22
+ return askpassPath;
23
+ }
24
+ /**
25
+ * Build SSH args common to both auth and connect commands.
26
+ */
27
+ export function buildSystemSshArgs(options) {
28
+ const args = [
29
+ '-o',
30
+ 'StrictHostKeyChecking=no',
31
+ '-o',
32
+ 'UserKnownHostsFile=/dev/null',
33
+ '-o',
34
+ 'LogLevel=ERROR',
35
+ '-p',
36
+ String(options.port),
37
+ ];
38
+ if (options.localPort && options.remotePort) {
39
+ args.push('-L', `${options.localPort}:localhost:${options.remotePort}`);
40
+ }
41
+ return args;
42
+ }
43
+ export const DEFAULT_SSH_RUNTIME = {
44
+ fetch: (input, init) => fetch(input, init),
45
+ loadSSH2,
46
+ createAskpassScript,
47
+ buildSystemSshArgs,
48
+ spawnProcess,
49
+ createServer,
50
+ setTimeout,
51
+ };
52
+ //# sourceMappingURL=ssh-runtime.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"ssh-runtime.js","sourceRoot":"","sources":["../../../../../packages/cloud/src/lib/ssh-runtime.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,SAAS,CAAC;AACzB,OAAO,IAAI,MAAM,WAAW,CAAC;AAC7B,OAAO,EAAE,MAAM,EAAE,MAAM,SAAS,CAAC;AACjC,OAAO,EAAE,KAAK,IAAI,YAAY,EAAE,MAAM,oBAAoB,CAAC;AAC3D,OAAO,EAAE,YAAY,EAAE,MAAM,UAAU,CAAC;AAkBxC,MAAM,CAAC,KAAK,UAAU,QAAQ;IAC5B,IAAI,CAAC;QACH,OAAO,MAAM,MAAM,CAAC,MAAM,CAAC,CAAC;IAC9B,CAAC;IAAC,MAAM,CAAC;QACP,OAAO,IAAI,CAAC;IACd,CAAC;AACH,CAAC;AAED;;;GAGG;AACH,MAAM,UAAU,mBAAmB,CAAC,QAAgB;IAClD,MAAM,WAAW,GAAG,IAAI,CAAC,IAAI,CAAC,MAAM,EAAE,EAAE,cAAc,OAAO,CAAC,GAAG,IAAI,IAAI,CAAC,GAAG,EAAE,EAAE,CAAC,CAAC;IACnF,MAAM,OAAO,GAAG,QAAQ,CAAC,OAAO,CAAC,IAAI,EAAE,SAAS,CAAC,CAAC;IAClD,EAAE,CAAC,aAAa,CAAC,WAAW,EAAE,8BAA8B,OAAO,KAAK,EAAE,EAAE,IAAI,EAAE,KAAK,EAAE,CAAC,CAAC;IAC3F,OAAO,WAAW,CAAC;AACrB,CAAC;AAED;;GAEG;AACH,MAAM,UAAU,kBAAkB,CAAC,OAMlC;IACC,MAAM,IAAI,GAAG;QACX,IAAI;QACJ,0BAA0B;QAC1B,IAAI;QACJ,8BAA8B;QAC9B,IAAI;QACJ,gBAAgB;QAChB,IAAI;QACJ,MAAM,CAAC,OAAO,CAAC,IAAI,CAAC;KACrB,CAAC;IACF,IAAI,OAAO,CAAC,SAAS,IAAI,OAAO,CAAC,UAAU,EAAE,CAAC;QAC5C,IAAI,CAAC,IAAI,CAAC,IAAI,EAAE,GAAG,OAAO,CAAC,SAAS,cAAc,OAAO,CAAC,UAAU,EAAE,CAAC,CAAC;IAC1E,CAAC;IACD,OAAO,IAAI,CAAC;AACd,CAAC;AAED,MAAM,CAAC,MAAM,mBAAmB,GAAmB;IACjD,KAAK,EAAE,CAAC,KAAkC,EAAE,IAAkC,EAAE,EAAE,CAAC,KAAK,CAAC,KAAK,EAAE,IAAI,CAAC;IACrG,QAAQ;IACR,mBAAmB;IACnB,kBAAkB;IAClB,YAAY;IACZ,YAAY;IACZ,UAAU;CACX,CAAC"}
@@ -0,0 +1,24 @@
1
+ import { type ProactiveAgentRecord, type ProactiveDeploymentResponse, type WorkspaceSecretRecord } from './types.js';
2
+ type ClientOptions = {
3
+ apiUrl?: string;
4
+ };
5
+ type DeployOptions = ClientOptions & {
6
+ name?: string;
7
+ watch?: boolean;
8
+ };
9
+ type DeployInput = {
10
+ entrypoint: string;
11
+ source: string;
12
+ };
13
+ type SecretOptions = ClientOptions & {
14
+ workspace: string;
15
+ };
16
+ export declare function deployProactiveAgent(input: DeployInput, options?: DeployOptions): Promise<ProactiveDeploymentResponse>;
17
+ export declare function listProactiveAgents(options?: ClientOptions): Promise<ProactiveAgentRecord[]>;
18
+ export declare function inspectProactiveAgent(agentId: string, options?: ClientOptions): Promise<ProactiveAgentRecord>;
19
+ export declare function undeployProactiveAgent(agentId: string, options?: ClientOptions): Promise<ProactiveAgentRecord>;
20
+ export declare function createWorkspaceSecret(name: string, value: string, options: SecretOptions): Promise<WorkspaceSecretRecord>;
21
+ export declare function getWorkspaceSecret(name: string, options: SecretOptions): Promise<WorkspaceSecretRecord>;
22
+ export declare function deleteWorkspaceSecret(name: string, options: SecretOptions): Promise<WorkspaceSecretRecord>;
23
+ export {};
24
+ //# sourceMappingURL=proactive-runtime.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"proactive-runtime.d.ts","sourceRoot":"","sources":["../../../../packages/cloud/src/proactive-runtime.ts"],"names":[],"mappings":"AACA,OAAO,EAEL,KAAK,oBAAoB,EACzB,KAAK,2BAA2B,EAChC,KAAK,qBAAqB,EAC3B,MAAM,YAAY,CAAC;AAEpB,KAAK,aAAa,GAAG;IACnB,MAAM,CAAC,EAAE,MAAM,CAAC;CACjB,CAAC;AAEF,KAAK,aAAa,GAAG,aAAa,GAAG;IACnC,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,KAAK,CAAC,EAAE,OAAO,CAAC;CACjB,CAAC;AAEF,KAAK,WAAW,GAAG;IACjB,UAAU,EAAE,MAAM,CAAC;IACnB,MAAM,EAAE,MAAM,CAAC;CAChB,CAAC;AAEF,KAAK,aAAa,GAAG,aAAa,GAAG;IACnC,SAAS,EAAE,MAAM,CAAC;CACnB,CAAC;AAkJF,wBAAsB,oBAAoB,CACxC,KAAK,EAAE,WAAW,EAClB,OAAO,GAAE,aAAkB,GAC1B,OAAO,CAAC,2BAA2B,CAAC,CAmCtC;AAED,wBAAsB,mBAAmB,CAAC,OAAO,GAAE,aAAkB,GAAG,OAAO,CAAC,oBAAoB,EAAE,CAAC,CAiBtG;AAED,wBAAsB,qBAAqB,CACzC,OAAO,EAAE,MAAM,EACf,OAAO,GAAE,aAAkB,GAC1B,OAAO,CAAC,oBAAoB,CAAC,CAqC/B;AAED,wBAAsB,sBAAsB,CAC1C,OAAO,EAAE,MAAM,EACf,OAAO,GAAE,aAAkB,GAC1B,OAAO,CAAC,oBAAoB,CAAC,CA4B/B;AAED,wBAAsB,qBAAqB,CACzC,IAAI,EAAE,MAAM,EACZ,KAAK,EAAE,MAAM,EACb,OAAO,EAAE,aAAa,GACrB,OAAO,CAAC,qBAAqB,CAAC,CAgChC;AAED,wBAAsB,kBAAkB,CACtC,IAAI,EAAE,MAAM,EACZ,OAAO,EAAE,aAAa,GACrB,OAAO,CAAC,qBAAqB,CAAC,CAgChC;AAED,wBAAsB,qBAAqB,CACzC,IAAI,EAAE,MAAM,EACZ,OAAO,EAAE,aAAa,GACrB,OAAO,CAAC,qBAAqB,CAAC,CAmChC"}