( sessionId: string, command: string[], workingDir?: string )
| 122 | * Execute a command in the container |
| 123 | */ |
| 124 | export async function execCommand( |
| 125 | sessionId: string, |
| 126 | command: string[], |
| 127 | workingDir?: string |
| 128 | ): Promise<{ stdout: string; stderr: string; exitCode: number }> { |
| 129 | const container = containerCache.get(sessionId); |
| 130 | if (!container) { |
| 131 | throw new Error(`No container found for session: ${sessionId}`); |
| 132 | } |
| 133 | |
| 134 | try { |
| 135 | logger.info('Executing command in container', { sessionId, command, workingDir }); |
| 136 | |
| 137 | const exec = await container.exec({ |
| 138 | Cmd: command, |
| 139 | AttachStdout: true, |
| 140 | AttachStderr: true, |
| 141 | WorkingDir: workingDir || '/workspace', |
| 142 | }); |
| 143 | |
| 144 | const stream = await exec.start({ hijack: true, stdin: false }); |
| 145 | |
| 146 | let stdout = ''; |
| 147 | let stderr = ''; |
| 148 | |
| 149 | await new Promise<void>((resolve, reject) => { |
| 150 | container.modem.demuxStream(stream, |
| 151 | { |
| 152 | write: (chunk: Buffer) => { stdout += chunk.toString(); }, |
| 153 | } as NodeJS.WritableStream, |
| 154 | { |
| 155 | write: (chunk: Buffer) => { stderr += chunk.toString(); }, |
| 156 | } as NodeJS.WritableStream |
| 157 | ); |
| 158 | |
| 159 | stream.on('end', () => resolve()); |
| 160 | stream.on('error', (err) => reject(err)); |
| 161 | }); |
| 162 | |
| 163 | const inspection = await exec.inspect(); |
| 164 | const exitCode = inspection.ExitCode || 0; |
| 165 | |
| 166 | logger.info('Command executed', { sessionId, exitCode, stdoutLength: stdout.length, stderrLength: stderr.length }); |
| 167 | |
| 168 | return { stdout, stderr, exitCode }; |
| 169 | } catch (error) { |
| 170 | logger.error('Failed to execute command', { sessionId, command, error }); |
| 171 | throw new Error(`Failed to execute command: ${error}`); |
| 172 | } |
| 173 | } |
| 174 | |
| 175 | /** |
| 176 | * Read a file from the container |
no outgoing calls
no test coverage detected