{"version":3,"file":"sandboxBridge-D6RAncmy.mjs","names":[],"sources":["../src/services/sandboxBridge/index.ts"],"sourcesContent":["export const BRIDGE_FILE_NAME = 'sandbox-bridge.mjs';\nexport const BRIDGE_CONTAINER_PATH = `/opt/doompi/${BRIDGE_FILE_NAME}`;\nexport const BROKER_SOCKET_ENV = 'DOOMPI_BROKER_SOCKET';\nexport const BROKER_ADDRESS_ENV = 'DOOMPI_BROKER_ADDRESS';\n/** Hostname the engine maps to the host, used when the broker listens on TCP. */\nexport const BROKER_HOST_GATEWAY = 'host.docker.internal';\nexport const BROKER_PORT_ENV = 'DOOMPI_BROKER_PORT';\nexport const BROKER_PROVIDERS_ENV = 'DOOMPI_BROKER_PROVIDERS';\n/** Fixed inside the container, which has its own loopback namespace. */\nexport const BROKER_CONTAINER_PORT = 8317;\nexport const BROKER_SOCKET_CONTAINER_PATH = '/run/doompi/broker.sock';\n\n/**\n * Container-side forwarder from loopback TCP to the mounted broker socket.\n *\n * Provider SDKs issue ordinary HTTP through Node's global fetch, which cannot\n * address a unix socket, and on a virtual machine backed engine cannot reach\n * one at all. Forwarding raw bytes leaves every SDK unmodified whichever way\n * the broker listens. Wrapping the launcher rather than running as a separate\n * service ties the listener's lifetime to the session without an init process.\n */\nexport function sandboxBridgeSource(): string {\n  return [\n    \"import { spawn } from 'node:child_process';\",\n    \"import net from 'node:net';\",\n    '',\n    `const socketPath = process.env.${BROKER_SOCKET_ENV};`,\n    `const address = process.env.${BROKER_ADDRESS_ENV};`,\n    `const port = Number(process.env.${BROKER_PORT_ENV});`,\n    'const [command, ...args] = process.argv.slice(2);',\n    '',\n    'function startChild(whenDone) {',\n    \"  const child = spawn(command, args, { stdio: 'inherit' });\",\n    \"  child.on('exit', (code, signal) => whenDone(code ?? (signal ? 1 : 0)));\",\n    \"  child.on('error', (error) => {\",\n    '    process.stderr.write(`[doompi] sandbox bridge: ${error.message}\\\\n`);',\n    '    whenDone(127);',\n    '  });',\n    '}',\n    '',\n    'function dialBroker() {',\n    '  if (socketPath) return net.connect(socketPath);',\n    \"  const separator = address.lastIndexOf(':');\",\n    '  return net.connect(Number(address.slice(separator + 1)), address.slice(0, separator));',\n    '}',\n    '',\n    'if ((!socketPath && !address) || !Number.isInteger(port)) {',\n    '  startChild((code) => {',\n    '    process.exitCode = code;',\n    '  });',\n    '} else {',\n    '  const server = net.createServer((client) => {',\n    '    const upstream = dialBroker();',\n    \"    client.on('error', () => upstream.destroy());\",\n    \"    upstream.on('error', () => client.destroy());\",\n    '    client.pipe(upstream);',\n    '    upstream.pipe(client);',\n    '  });',\n    \"  server.listen(port, '127.0.0.1', () => {\",\n    '    startChild((code) => {',\n    '      server.close();',\n    '      process.exitCode = code;',\n    '    });',\n    '  });',\n    '}',\n    '',\n  ].join('\\n');\n}\n"],"mappings":";AAAA,MAAa,mBAAmB;AAChC,MAAa,wBAAwB,eAAe;AACpD,MAAa,oBAAoB;AACjC,MAAa,qBAAqB;;AAElC,MAAa,sBAAsB;AACnC,MAAa,kBAAkB;AAC/B,MAAa,uBAAuB;;AAEpC,MAAa,wBAAwB;AACrC,MAAa,+BAA+B;;;;;;;;;;AAW5C,SAAgB,sBAA8B;CAC5C,OAAO;EACL;EACA;EACA;EACA,kCAAkC,kBAAkB;EACpD,+BAA+B,mBAAmB;EAClD,mCAAmC,gBAAgB;EACnD;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;CACF,CAAC,CAAC,KAAK,IAAI;AACb"}