(kind: 'code' | 'shell' | 'doc' | 'pi')
| 108 | } |
| 109 | |
| 110 | async function createE2BSandbox(kind: 'code' | 'shell' | 'doc' | 'pi'): Promise<E2BSandbox> { |
| 111 | const apiKey = env.E2B_API_KEY |
| 112 | if (!apiKey) { |
| 113 | throw new Error('E2B_API_KEY is required when E2B is enabled') |
| 114 | } |
| 115 | |
| 116 | // Document generation uses a dedicated template (python-pptx/docx/openpyxl/ |
| 117 | // reportlab + fonts); shell/code execution use the general shell template. |
| 118 | // Doc fails closed: never run LLM-authored Python in E2B's default template |
| 119 | // (which is not vetted for this) just because the doc template id is unset. |
| 120 | if (kind === 'doc' && !env.MOTHERSHIP_E2B_DOC_TEMPLATE_ID) { |
| 121 | throw new Error('Document compiler not configured (MOTHERSHIP_E2B_DOC_TEMPLATE_ID is unset)') |
| 122 | } |
| 123 | // Pi fails closed for the same reason: the coding agent needs the Pi CLI + git |
| 124 | // baked into a vetted template, never E2B's default image. |
| 125 | if (kind === 'pi' && !env.E2B_PI_TEMPLATE_ID) { |
| 126 | throw new Error('Pi cloud agent not configured (E2B_PI_TEMPLATE_ID is unset)') |
| 127 | } |
| 128 | |
| 129 | const templateName = |
| 130 | kind === 'doc' |
| 131 | ? env.MOTHERSHIP_E2B_DOC_TEMPLATE_ID |
| 132 | : kind === 'pi' |
| 133 | ? env.E2B_PI_TEMPLATE_ID |
| 134 | : env.MOTHERSHIP_E2B_TEMPLATE_ID |
| 135 | logger.info('Creating E2B sandbox', { |
| 136 | kind, |
| 137 | template: templateName || '(default)', |
| 138 | }) |
| 139 | const { Sandbox } = await import('@e2b/code-interpreter') |
| 140 | return templateName ? Sandbox.create(templateName, { apiKey }) : Sandbox.create({ apiKey }) |
| 141 | } |
| 142 | |
| 143 | function shouldReadSandboxPathAsBase64(outputSandboxPath: string): boolean { |
| 144 | const ext = outputSandboxPath.slice(outputSandboxPath.lastIndexOf('.')).toLowerCase() |
no test coverage detected