Stream the agent's chunks to the response as NDJSON, one object per line.
( req: IncomingMessage, res: ServerResponse, resolveAdapter: (input: ResolveAdapterInput) => AnyTextAdapter, )
| 162 | |
| 163 | /** Stream the agent's chunks to the response as NDJSON, one object per line. */ |
| 164 | async function handleRun( |
| 165 | req: IncomingMessage, |
| 166 | res: ServerResponse, |
| 167 | resolveAdapter: (input: ResolveAdapterInput) => AnyTextAdapter, |
| 168 | ): Promise<void> { |
| 169 | const parsed: unknown = JSON.parse(await readBody(req)) |
| 170 | const request = parseContainerRunRequest(parsed) |
| 171 | res.writeHead(200, { |
| 172 | 'content-type': 'application/x-ndjson', |
| 173 | 'cache-control': 'no-cache', |
| 174 | }) |
| 175 | // The DO appends each line to its durable run-log; here we are the producer, |
| 176 | // so we surface a mid-stream failure as a terminal RUN_ERROR line the DO will |
| 177 | // append + finish on, never a silently truncated stream. |
| 178 | try { |
| 179 | for await (const chunk of runAgent(request, resolveAdapter)) { |
| 180 | res.write(`${JSON.stringify(chunk)}\n`) |
| 181 | } |
| 182 | } catch (error) { |
| 183 | const message = error instanceof Error ? error.message : String(error) |
| 184 | res.write(`${JSON.stringify({ type: EventType.RUN_ERROR, message })}\n`) |
| 185 | } finally { |
| 186 | res.end() |
| 187 | } |
| 188 | } |
| 189 | |
| 190 | /** |
| 191 | * Start the in-container harness runner: a `node:http` server with `GET /health` |
no test coverage detected