import type { MCPBridge } from '../bridge/MCPBridge.js'; import { VmSandboxManager } from './vm/VmSandboxManager.js'; import type { SandboxOptions, SandboxRuntime } from './types.js'; const ISOLATED_VM_NODE_MAJOR = 24; type InitializableSandboxRuntime = SandboxRuntime & { initialize(): Promise }; type IsolatedVmLoader = () => Promise<{ IVMSandboxManager: new ( bridge: MCPBridge, options: SandboxOptions, ) => InitializableSandboxRuntime; }>; const loadIsolatedVmManager: IsolatedVmLoader = () => import('./ivm/IVMSandboxManager.js'); export async function createSandboxManager( bridge: MCPBridge, options: SandboxOptions, ): Promise { if (shouldUseIsolatedVm()) { return createIsolatedVmSandboxWithFallback(bridge, options); } return new VmSandboxManager(bridge, options); } export async function createIsolatedVmSandboxWithFallback( bridge: MCPBridge, options: SandboxOptions, loadManager: IsolatedVmLoader = loadIsolatedVmManager, ): Promise { try { const { IVMSandboxManager } = await loadManager(); const manager = new IVMSandboxManager(bridge, options); await manager.initialize(); return manager; } catch (error) { options.logger?.warn?.( 'Failed to initialize isolated-vm sandbox, falling back to VM sandbox.', { error }, ); return new VmSandboxManager(bridge, options); } } export function shouldUseIsolatedVm( nodeVersion: string = process.versions.node, execArgv: readonly string[] = process.execArgv, forceVm: boolean = process.env.KUBE_MCP_FORCE_VM_SANDBOX === '1', ): boolean { if (forceVm) { return false; } const major = Number.parseInt(nodeVersion.split('.')[0] ?? '', 10); if (!Number.isFinite(major)) { return false; } return major === ISOLATED_VM_NODE_MAJOR && execArgv.includes('--no-node-snapshot'); }