@vibecontrols/vibe-plugin-ssh 2026.416.1

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.
@@ -0,0 +1,154 @@
1
+ /**
2
+ * Remote terminal routes – start ttyd on a destination server via SSH,
3
+ * port-forward back to a local port on the agent, and serve it through
4
+ * the agent's existing terminal WebSocket proxy.
5
+ *
6
+ * Namespace: "ssh"
7
+ * Keys:
8
+ * "terminal-sessions" → JSON array of SSHTerminalSession objects
9
+ */
10
+ import { Elysia } from "elysia";
11
+ import type { HostServices, SSHTerminalSession } from "../types.js";
12
+ export declare function cleanupAllTerminals(): void;
13
+ export declare function getTerminalInfo(sessionId: string): {
14
+ url: string;
15
+ port: number;
16
+ pid: number;
17
+ } | null;
18
+ /** List all active terminal sessions (for the session provider shim). */
19
+ export declare function listTerminalSessions(): SSHTerminalSession[];
20
+ export declare function createRemoteTerminalRoutes(hostServices: HostServices): Elysia<"/api/ssh/terminal", {
21
+ decorator: {};
22
+ store: {};
23
+ derive: {};
24
+ resolve: {};
25
+ }, {
26
+ typebox: {};
27
+ error: {};
28
+ }, {
29
+ schema: {};
30
+ standaloneSchema: {};
31
+ macro: {};
32
+ macroFn: {};
33
+ parser: {};
34
+ response: {};
35
+ }, {
36
+ api: {
37
+ ssh: {
38
+ terminal: {
39
+ sessions: {
40
+ get: {
41
+ body: unknown;
42
+ params: {};
43
+ query: unknown;
44
+ headers: unknown;
45
+ response: {
46
+ 200: {
47
+ sessions: SSHTerminalSession[];
48
+ };
49
+ };
50
+ };
51
+ };
52
+ };
53
+ };
54
+ };
55
+ } & {
56
+ api: {
57
+ ssh: {
58
+ terminal: {
59
+ sessions: {
60
+ ":id": {
61
+ get: {
62
+ body: unknown;
63
+ params: {
64
+ id: string;
65
+ } & {};
66
+ query: unknown;
67
+ headers: unknown;
68
+ response: {
69
+ 200: {
70
+ error: string;
71
+ session?: undefined;
72
+ } | {
73
+ session: SSHTerminalSession;
74
+ error?: undefined;
75
+ };
76
+ 422: {
77
+ type: "validation";
78
+ on: string;
79
+ summary?: string;
80
+ message?: string;
81
+ found?: unknown;
82
+ property?: string;
83
+ expected?: string;
84
+ };
85
+ };
86
+ };
87
+ };
88
+ };
89
+ };
90
+ };
91
+ };
92
+ } & {
93
+ api: {
94
+ ssh: {
95
+ terminal: {
96
+ start: {
97
+ post: {
98
+ body: unknown;
99
+ params: {};
100
+ query: unknown;
101
+ headers: unknown;
102
+ response: {};
103
+ };
104
+ };
105
+ };
106
+ };
107
+ };
108
+ } & {
109
+ api: {
110
+ ssh: {
111
+ terminal: {
112
+ stop: {
113
+ post: {
114
+ body: unknown;
115
+ params: {};
116
+ query: unknown;
117
+ headers: unknown;
118
+ response: {
119
+ 200: {
120
+ error: string;
121
+ success?: undefined;
122
+ sessionId?: undefined;
123
+ details?: undefined;
124
+ } | {
125
+ success: boolean;
126
+ sessionId: string;
127
+ error?: undefined;
128
+ details?: undefined;
129
+ } | {
130
+ error: string;
131
+ details: string;
132
+ success?: undefined;
133
+ sessionId?: undefined;
134
+ };
135
+ };
136
+ };
137
+ };
138
+ };
139
+ };
140
+ };
141
+ }, {
142
+ derive: {};
143
+ resolve: {};
144
+ schema: {};
145
+ standaloneSchema: {};
146
+ response: {};
147
+ }, {
148
+ derive: {};
149
+ resolve: {};
150
+ schema: {};
151
+ standaloneSchema: {};
152
+ response: {};
153
+ }>;
154
+ //# sourceMappingURL=remote-terminal.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"remote-terminal.d.ts","sourceRoot":"","sources":["../../src/routes/remote-terminal.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AAEH,OAAO,EAAE,MAAM,EAAE,MAAM,QAAQ,CAAC;AAIhC,OAAO,KAAK,EACV,YAAY,EAEZ,kBAAkB,EAGnB,MAAM,aAAa,CAAC;AAsNrB,wBAAgB,mBAAmB,IAAI,IAAI,CAc1C;AAOD,wBAAgB,eAAe,CAC7B,SAAS,EAAE,MAAM,GAChB;IAAE,GAAG,EAAE,MAAM,CAAC;IAAC,IAAI,EAAE,MAAM,CAAC;IAAC,GAAG,EAAE,MAAM,CAAA;CAAE,GAAG,IAAI,CAQnD;AAED,yEAAyE;AACzE,wBAAgB,oBAAoB,IAAI,kBAAkB,EAAE,CAE3D;AAMD,wBAAgB,0BAA0B,CAAC,YAAY,EAAE,YAAY;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA6RpE"}
@@ -0,0 +1,437 @@
1
+ /**
2
+ * Remote terminal routes – start ttyd on a destination server via SSH,
3
+ * port-forward back to a local port on the agent, and serve it through
4
+ * the agent's existing terminal WebSocket proxy.
5
+ *
6
+ * Namespace: "ssh"
7
+ * Keys:
8
+ * "terminal-sessions" → JSON array of SSHTerminalSession objects
9
+ */
10
+ import { Elysia } from "elysia";
11
+ import { Client } from "ssh2";
12
+ import { createServer } from "node:net";
13
+ const activeTerminals = new Map();
14
+ // ---------------------------------------------------------------------------
15
+ // KV helpers
16
+ // ---------------------------------------------------------------------------
17
+ async function getConnectionById(storage, id) {
18
+ const raw = await storage.get("ssh", "connections");
19
+ if (!raw)
20
+ return undefined;
21
+ const all = JSON.parse(raw);
22
+ return all.find((c) => c.id === id);
23
+ }
24
+ async function persistSessions(storage) {
25
+ const sessions = Array.from(activeTerminals.values()).map((t) => t.session);
26
+ await storage.set("ssh", "terminal-sessions", JSON.stringify(sessions));
27
+ }
28
+ // ---------------------------------------------------------------------------
29
+ // SSH helpers
30
+ // ---------------------------------------------------------------------------
31
+ async function buildConnectConfig(conn) {
32
+ const cfg = {
33
+ host: conn.host,
34
+ port: conn.port,
35
+ username: conn.username,
36
+ };
37
+ if (conn.privateKeyPath) {
38
+ const file = Bun.file(conn.privateKeyPath);
39
+ cfg.privateKey = Buffer.from(await file.arrayBuffer());
40
+ }
41
+ else if (conn.password) {
42
+ cfg.password = conn.password;
43
+ }
44
+ return cfg;
45
+ }
46
+ function sshExec(client, command) {
47
+ return new Promise((resolve, reject) => {
48
+ client.exec(command, (err, stream) => {
49
+ if (err)
50
+ return reject(err);
51
+ let stdout = "";
52
+ let stderr = "";
53
+ stream.on("data", (data) => {
54
+ stdout += data.toString();
55
+ });
56
+ stream.stderr.on("data", (data) => {
57
+ stderr += data.toString();
58
+ });
59
+ stream.on("close", (code) => {
60
+ resolve({ stdout: stdout.trim(), stderr: stderr.trim(), code });
61
+ });
62
+ });
63
+ });
64
+ }
65
+ // ---------------------------------------------------------------------------
66
+ // Find a free port on the remote server
67
+ // ---------------------------------------------------------------------------
68
+ async function findFreeRemotePort(client, start = 7881, end = 8080) {
69
+ for (let port = start; port <= end; port++) {
70
+ const { code } = await sshExec(client, `ss -tlnp 2>/dev/null | grep -q ':${port} ' && echo taken || echo free`);
71
+ // If grep finds the port, code is 0 and output contains "taken".
72
+ // We just check the stdout text directly.
73
+ const { stdout } = await sshExec(client, `ss -tlnp 2>/dev/null | grep -q ':${port} ' && echo taken || echo free`);
74
+ if (stdout === "free")
75
+ return port;
76
+ }
77
+ throw new Error(`No free port found on remote server in range ${start}-${end}`);
78
+ }
79
+ // ---------------------------------------------------------------------------
80
+ // Find a free local port on the agent
81
+ // ---------------------------------------------------------------------------
82
+ function findFreeLocalPort(start = 7681, end = 7880) {
83
+ return new Promise((resolve, reject) => {
84
+ let current = start;
85
+ function tryPort() {
86
+ if (current > end) {
87
+ return reject(new Error(`No free local port found in range ${start}-${end}`));
88
+ }
89
+ // Check if any active terminal already uses this port
90
+ for (const [, t] of activeTerminals) {
91
+ if (t.session.localPort === current) {
92
+ current++;
93
+ return tryPort();
94
+ }
95
+ }
96
+ const srv = createServer();
97
+ srv.once("error", () => {
98
+ current++;
99
+ tryPort();
100
+ });
101
+ srv.once("listening", () => {
102
+ srv.close(() => resolve(current));
103
+ });
104
+ srv.listen(current, "127.0.0.1");
105
+ }
106
+ tryPort();
107
+ });
108
+ }
109
+ // ---------------------------------------------------------------------------
110
+ // Install ttyd on remote if missing
111
+ // ---------------------------------------------------------------------------
112
+ async function ensureTtydInstalled(client) {
113
+ const { code } = await sshExec(client, "which ttyd");
114
+ if (code === 0)
115
+ return true;
116
+ // Detect package manager and try to install
117
+ const { stdout: osRelease } = await sshExec(client, "cat /etc/os-release 2>/dev/null || echo unknown");
118
+ let installCmd;
119
+ if (osRelease.includes("debian") ||
120
+ osRelease.includes("ubuntu") ||
121
+ osRelease.includes("ID=debian") ||
122
+ osRelease.includes("ID=ubuntu")) {
123
+ installCmd =
124
+ "sudo apt-get update -qq && sudo apt-get install -y -qq ttyd 2>/dev/null";
125
+ }
126
+ else if (osRelease.includes("centos") ||
127
+ osRelease.includes("fedora") ||
128
+ osRelease.includes("rhel") ||
129
+ osRelease.includes("ID=centos") ||
130
+ osRelease.includes("ID=fedora")) {
131
+ installCmd = "sudo yum install -y -q ttyd 2>/dev/null";
132
+ }
133
+ else if (osRelease.includes("alpine") || osRelease.includes("ID=alpine")) {
134
+ installCmd = "sudo apk add --quiet ttyd 2>/dev/null";
135
+ }
136
+ else {
137
+ // Fallback: try downloading binary from GitHub
138
+ const { stdout: arch } = await sshExec(client, "uname -m");
139
+ const archMap = {
140
+ x86_64: "x86_64",
141
+ aarch64: "aarch64",
142
+ arm64: "aarch64",
143
+ };
144
+ const mappedArch = archMap[arch] || "x86_64";
145
+ installCmd = `curl -fsSL "https://github.com/tsl0922/ttyd/releases/latest/download/ttyd.${mappedArch}" -o /tmp/ttyd && chmod +x /tmp/ttyd && sudo mv /tmp/ttyd /usr/local/bin/ttyd`;
146
+ }
147
+ const result = await sshExec(client, installCmd);
148
+ if (result.code !== 0) {
149
+ // Try without sudo
150
+ const { code: retryCode } = await sshExec(client, installCmd.replace(/sudo /g, ""));
151
+ return retryCode === 0;
152
+ }
153
+ return true;
154
+ }
155
+ // ---------------------------------------------------------------------------
156
+ // Cleanup
157
+ // ---------------------------------------------------------------------------
158
+ export function cleanupAllTerminals() {
159
+ for (const [id, terminal] of activeTerminals) {
160
+ try {
161
+ if (terminal.sshTunnelProc)
162
+ terminal.sshTunnelProc.kill();
163
+ }
164
+ catch {
165
+ /* ignore */
166
+ }
167
+ try {
168
+ terminal.sshClient.end();
169
+ }
170
+ catch {
171
+ /* ignore */
172
+ }
173
+ activeTerminals.delete(id);
174
+ }
175
+ }
176
+ // ---------------------------------------------------------------------------
177
+ // Session provider shim – exposes getTerminalInfo() so the agent's terminal
178
+ // proxy at /terminal/:sessionId/ws can find and route to our forwarded port.
179
+ // ---------------------------------------------------------------------------
180
+ export function getTerminalInfo(sessionId) {
181
+ const terminal = activeTerminals.get(sessionId);
182
+ if (!terminal || terminal.session.status !== "active")
183
+ return null;
184
+ return {
185
+ url: `http://127.0.0.1:${terminal.session.localPort}`,
186
+ port: terminal.session.localPort,
187
+ pid: process.pid, // Agent's own PID – always alive while agent runs
188
+ };
189
+ }
190
+ /** List all active terminal sessions (for the session provider shim). */
191
+ export function listTerminalSessions() {
192
+ return Array.from(activeTerminals.values()).map((t) => t.session);
193
+ }
194
+ // ---------------------------------------------------------------------------
195
+ // Route factory
196
+ // ---------------------------------------------------------------------------
197
+ export function createRemoteTerminalRoutes(hostServices) {
198
+ const { storage, broadcast } = hostServices;
199
+ return (new Elysia({ prefix: "/api/ssh/terminal" })
200
+ // -----------------------------------------------------------------------
201
+ // GET /api/ssh/terminal/sessions — list active remote terminal sessions
202
+ // -----------------------------------------------------------------------
203
+ .get("/sessions", () => {
204
+ return { sessions: listTerminalSessions() };
205
+ })
206
+ // -----------------------------------------------------------------------
207
+ // GET /api/ssh/terminal/sessions/:id — get a specific session
208
+ // -----------------------------------------------------------------------
209
+ .get("/sessions/:id", ({ params, set }) => {
210
+ const terminal = activeTerminals.get(params.id);
211
+ if (!terminal) {
212
+ set.status = 404;
213
+ return { error: "Terminal session not found" };
214
+ }
215
+ return { session: terminal.session };
216
+ })
217
+ // -----------------------------------------------------------------------
218
+ // POST /api/ssh/terminal/start — start remote ttyd + SSH port forward
219
+ // -----------------------------------------------------------------------
220
+ .post("/start", async ({ body, set }) => {
221
+ const { connectionId, shell = "bash" } = body;
222
+ try {
223
+ // 1. Look up connection
224
+ const connConfig = await getConnectionById(storage, connectionId);
225
+ if (!connConfig) {
226
+ set.status = 404;
227
+ return { error: "SSH connection not found" };
228
+ }
229
+ const sessionId = globalThis.crypto.randomUUID();
230
+ const session = {
231
+ id: sessionId,
232
+ connectionId,
233
+ remotePort: 0,
234
+ localPort: 0,
235
+ remotePid: null,
236
+ shell,
237
+ status: "starting",
238
+ startedAt: new Date().toISOString(),
239
+ };
240
+ // 2. Establish SSH connection
241
+ const sshClient = new Client();
242
+ const connectConfig = await buildConnectConfig(connConfig);
243
+ return new Promise((resolve) => {
244
+ sshClient.on("error", (err) => {
245
+ session.status = "error";
246
+ session.error = err.message;
247
+ set.status = 500;
248
+ resolve({
249
+ error: "SSH connection failed",
250
+ details: err.message,
251
+ });
252
+ });
253
+ sshClient.on("ready", async () => {
254
+ try {
255
+ // 3. Ensure ttyd is installed on remote
256
+ const installed = await ensureTtydInstalled(sshClient);
257
+ if (!installed) {
258
+ sshClient.end();
259
+ session.status = "error";
260
+ session.error = "Failed to install ttyd on remote server";
261
+ set.status = 500;
262
+ return resolve({
263
+ error: "ttyd is not installed on the remote server and auto-install failed",
264
+ });
265
+ }
266
+ // 4. Find free remote port
267
+ const remotePort = await findFreeRemotePort(sshClient);
268
+ session.remotePort = remotePort;
269
+ // 5. Start ttyd on remote
270
+ const { stdout: pidOutput, code: startCode } = await sshExec(sshClient, `nohup ttyd --writable --port ${remotePort} ${shell} > /dev/null 2>&1 & echo $!`);
271
+ if (startCode !== 0 || !pidOutput) {
272
+ sshClient.end();
273
+ session.status = "error";
274
+ session.error = "Failed to start ttyd on remote";
275
+ set.status = 500;
276
+ return resolve({ error: "Failed to start ttyd on remote" });
277
+ }
278
+ const remotePid = parseInt(pidOutput, 10);
279
+ session.remotePid = remotePid;
280
+ // 6. Wait for ttyd to bind and verify it's listening
281
+ await new Promise((r) => setTimeout(r, 1500));
282
+ const { stdout: listenCheck } = await sshExec(sshClient, `ss -tlnp 2>/dev/null | grep ':${remotePort} ' || echo NOT_LISTENING`);
283
+ if (listenCheck.includes("NOT_LISTENING")) {
284
+ // ttyd may need more time
285
+ await new Promise((r) => setTimeout(r, 2000));
286
+ }
287
+ // 7. Allocate local port + create SSH port forward
288
+ // Uses a real `ssh -L` subprocess for the tunnel
289
+ // because ssh2's forwardOut + Bun has data piping
290
+ // issues with WebSocket-heavy protocols like ttyd.
291
+ const localPort = await findFreeLocalPort();
292
+ session.localPort = localPort;
293
+ try {
294
+ // Build ssh command args
295
+ const sshArgs = [
296
+ "-N", // No remote command
297
+ "-L",
298
+ `${localPort}:127.0.0.1:${remotePort}`,
299
+ "-o",
300
+ "StrictHostKeyChecking=accept-new",
301
+ "-o",
302
+ "ServerAliveInterval=30",
303
+ "-o",
304
+ "ExitOnForwardFailure=yes",
305
+ "-p",
306
+ String(connConfig.port),
307
+ ];
308
+ if (connConfig.privateKeyPath) {
309
+ sshArgs.push("-i", connConfig.privateKeyPath);
310
+ }
311
+ sshArgs.push(`${connConfig.username}@${connConfig.host}`);
312
+ const sshProc = Bun.spawn(["ssh", ...sshArgs], {
313
+ stdout: "ignore",
314
+ stderr: "pipe",
315
+ });
316
+ // Wait for the tunnel to be ready
317
+ await new Promise((r) => setTimeout(r, 2000));
318
+ // Verify the local port is listening
319
+ const checkSrv = createServer();
320
+ const portBound = await new Promise((res) => {
321
+ checkSrv.once("error", () => res(true)); // Port in use = tunnel working
322
+ checkSrv.once("listening", () => {
323
+ checkSrv.close();
324
+ res(false); // Port free = tunnel not ready
325
+ });
326
+ checkSrv.listen(localPort, "127.0.0.1");
327
+ });
328
+ if (!portBound) {
329
+ // Tunnel didn't bind yet, wait more
330
+ await new Promise((r) => setTimeout(r, 2000));
331
+ }
332
+ session.status = "active";
333
+ activeTerminals.set(sessionId, {
334
+ sshClient,
335
+ sshTunnelProc: sshProc,
336
+ session,
337
+ });
338
+ void persistSessions(storage);
339
+ if (broadcast) {
340
+ broadcast("ssh:terminal:started", {
341
+ sessionId,
342
+ connectionId,
343
+ localPort,
344
+ remotePort,
345
+ host: connConfig.host,
346
+ });
347
+ }
348
+ resolve({
349
+ sessionId,
350
+ connectionId,
351
+ localPort,
352
+ remotePort,
353
+ host: connConfig.host,
354
+ status: "active",
355
+ });
356
+ }
357
+ catch (bindErr) {
358
+ void sshExec(sshClient, `kill ${remotePid} 2>/dev/null`);
359
+ sshClient.end();
360
+ session.status = "error";
361
+ session.error =
362
+ bindErr instanceof Error
363
+ ? bindErr.message
364
+ : "Port bind failed";
365
+ set.status = 500;
366
+ resolve({
367
+ error: "Failed to bind local port",
368
+ details: session.error,
369
+ });
370
+ }
371
+ }
372
+ catch (err) {
373
+ sshClient.end();
374
+ session.status = "error";
375
+ session.error =
376
+ err instanceof Error ? err.message : "Unknown error";
377
+ set.status = 500;
378
+ resolve({
379
+ error: "Failed to start remote terminal",
380
+ details: session.error,
381
+ });
382
+ }
383
+ });
384
+ sshClient.connect(connectConfig);
385
+ });
386
+ }
387
+ catch (error) {
388
+ set.status = 500;
389
+ return {
390
+ error: "Failed to start remote terminal",
391
+ details: error instanceof Error ? error.message : "Unknown error",
392
+ };
393
+ }
394
+ })
395
+ // -----------------------------------------------------------------------
396
+ // POST /api/ssh/terminal/stop — stop a remote ttyd session
397
+ // -----------------------------------------------------------------------
398
+ .post("/stop", async ({ body, set }) => {
399
+ const { sessionId } = body;
400
+ const terminal = activeTerminals.get(sessionId);
401
+ if (!terminal) {
402
+ set.status = 404;
403
+ return { error: "Terminal session not found" };
404
+ }
405
+ try {
406
+ terminal.session.status = "stopping";
407
+ // Kill remote ttyd process
408
+ if (terminal.session.remotePid) {
409
+ await sshExec(terminal.sshClient, `kill ${terminal.session.remotePid} 2>/dev/null`).catch(() => { });
410
+ }
411
+ // Kill SSH tunnel subprocess
412
+ if (terminal.sshTunnelProc) {
413
+ terminal.sshTunnelProc.kill();
414
+ }
415
+ // Close SSH connection (used for exec commands)
416
+ terminal.sshClient.end();
417
+ terminal.session.status = "stopped";
418
+ activeTerminals.delete(sessionId);
419
+ void persistSessions(storage);
420
+ if (broadcast) {
421
+ broadcast("ssh:terminal:stopped", {
422
+ sessionId,
423
+ connectionId: terminal.session.connectionId,
424
+ });
425
+ }
426
+ return { success: true, sessionId };
427
+ }
428
+ catch (error) {
429
+ set.status = 500;
430
+ return {
431
+ error: "Failed to stop terminal session",
432
+ details: error instanceof Error ? error.message : "Unknown error",
433
+ };
434
+ }
435
+ }));
436
+ }
437
+ //# sourceMappingURL=remote-terminal.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"remote-terminal.js","sourceRoot":"","sources":["../../src/routes/remote-terminal.ts"],"names":[],"mappings":"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"}