| 268 | |
| 269 | // Streaming helpers |
| 270 | function sseStream( |
| 271 | gen: AsyncGenerator<string>, |
| 272 | status = 200, |
| 273 | ): Response { |
| 274 | const stream = new ReadableStream({ |
| 275 | async start(ctrl) { |
| 276 | try { |
| 277 | for await (const chunk of gen) { |
| 278 | ctrl.enqueue(new TextEncoder().encode(chunk)); |
| 279 | } |
| 280 | ctrl.close(); |
| 281 | } catch (e) { |
| 282 | ctrl.error(e); |
| 283 | } |
| 284 | }, |
| 285 | }); |
| 286 | return new Response(stream, { |
| 287 | status, |
| 288 | headers: { |
| 289 | "Content-Type": "text/event-stream", |
| 290 | "Cache-Control": "no-cache", |
| 291 | "Connection": "keep-alive", |
| 292 | }, |
| 293 | }); |
| 294 | } |
| 295 | |
| 296 | // Stream generators |
| 297 | async function* retoolStreamGenerator( |