| 222 | let codeCellActive = false; |
| 223 | |
| 224 | export async function executeCodeCell( |
| 225 | input: ExecuteCodeCellInput, |
| 226 | ): Promise<CodeModeExecutionResult> { |
| 227 | if (input.signal?.aborted) throw input.signal.reason ?? abortError(); |
| 228 | return new Promise<CodeModeExecutionResult>((resolve, reject) => { |
| 229 | const entry: QueuedCodeCell = { input, resolve, reject }; |
| 230 | if (codeCellActive) { |
| 231 | if (queuedCodeCell) { |
| 232 | resolve({ |
| 233 | ok: false, |
| 234 | error: { kind: 'limit_exceeded', message: 'Code Mode execution queue is full' }, |
| 235 | toolCalls: [], |
| 236 | }); |
| 237 | return; |
| 238 | } |
| 239 | const onAbort = () => { |
| 240 | if (queuedCodeCell !== entry) return; |
| 241 | queuedCodeCell = undefined; |
| 242 | reject(input.signal?.reason ?? abortError()); |
| 243 | }; |
| 244 | entry.onAbort = onAbort; |
| 245 | input.signal?.addEventListener('abort', onAbort, { once: true }); |
| 246 | queuedCodeCell = entry; |
| 247 | return; |
| 248 | } |
| 249 | codeCellActive = true; |
| 250 | runCodeCell(entry); |
| 251 | }); |
| 252 | } |
| 253 | |
| 254 | function runCodeCell(entry: QueuedCodeCell): void { |
| 255 | if (entry.onAbort) entry.input.signal?.removeEventListener('abort', entry.onAbort); |