UNPKG

consortium

Version:

Remote control and session sharing CLI for AI coding agents

123 lines (120 loc) • 3.2 kB
import { Socket, Server } from 'net'; import { M as MaybeConsumableWritableStream } from './writable-C9MDBwYu.mjs'; import { P as PushReadableStream, a as tryClose } from './consumable-GBIKq8FA.mjs'; import './utils-CoFf4cMv.mjs'; function nodeSocketToConnection(socket) { socket.setNoDelay(true); const closed = new Promise((resolve) => { socket.on("close", resolve); }); return { readable: new PushReadableStream((controller) => { socket.on("data", async (data) => { if (controller.abortSignal.aborted) { return; } socket.pause(); await controller.enqueue(data); socket.resume(); }); socket.on("end", () => { tryClose(controller); }); }), writable: new MaybeConsumableWritableStream({ write: (chunk) => { return new Promise((resolve, reject) => { socket.write(chunk, (err) => { if (err) { reject(err); } else { resolve(); } }); }); } }), get closed() { return closed; }, close() { socket.end(); } }; } class AdbServerNodeTcpConnector { spec; #listeners = /* @__PURE__ */ new Map(); constructor(spec) { this.spec = spec; } async connect({ unref, signal } = { unref: false }) { const socket = new Socket({ signal }); if (unref) { socket.unref(); } socket.connect(this.spec); await new Promise((resolve, reject) => { socket.once("connect", resolve); socket.once("error", reject); }); return nodeSocketToConnection(socket); } async addReverseTunnel(handler, address) { const server = new Server(async (socket) => { const connection = nodeSocketToConnection(socket); try { await handler({ service: address, readable: connection.readable, writable: connection.writable, get closed() { return connection.closed; }, async close() { await connection.close(); } }); } catch { socket.end(); } }); if (address) { const url = new URL(address); if (url.protocol === "tcp:") { server.listen(Number.parseInt(url.port, 10), url.hostname); } else if (url.protocol === "unix:") { server.listen(url.pathname); } else { throw new TypeError(`Unsupported protocol ${url.protocol}`); } } else { server.listen(); } await new Promise((resolve, reject) => { server.on("listening", () => resolve()); server.on("error", (e) => reject(e)); }); if (!address) { const info = server.address(); address = `tcp:${info.port}`; } this.#listeners.set(address, server); return address; } removeReverseTunnel(address) { const server = this.#listeners.get(address); if (!server) { return; } server.close(); this.#listeners.delete(address); } clearReverseTunnels() { for (const server of this.#listeners.values()) { server.close(); } this.#listeners.clear(); } } export { AdbServerNodeTcpConnector };