(
options: TextOptions<TProviderOptions>,
)
| 62 | } |
| 63 | |
| 64 | async *chatStream( |
| 65 | options: TextOptions<TProviderOptions>, |
| 66 | ): AsyncIterable<StreamChunk> { |
| 67 | // Track tool call metadata by unique ID |
| 68 | // Responses API streams tool calls with deltas — first chunk has ID/name, |
| 69 | // subsequent chunks only have args. |
| 70 | // We assign our own indices as we encounter unique tool call IDs. |
| 71 | const toolCallMetadata = new Map< |
| 72 | string, |
| 73 | { |
| 74 | index: number |
| 75 | name: string |
| 76 | started: boolean |
| 77 | // Set once TOOL_CALL_END has been emitted (via args.done or the |
| 78 | // output_item.done backfill) so the two paths don't double-emit. |
| 79 | ended?: boolean |
| 80 | // Set when args.done arrives before TOOL_CALL_START could fire |
| 81 | // (output_item.added lacked a name). output_item.done picks these |
| 82 | // up to emit the missing END. Allow explicit `undefined` so the |
| 83 | // emission paths can re-clear the slot after handing it off. |
| 84 | pendingArguments?: string |
| 85 | } |
| 86 | >() |
| 87 | |
| 88 | // AG-UI lifecycle tracking |
| 89 | const aguiState = { |
| 90 | runId: generateId(this.name), |
| 91 | threadId: options.threadId ?? generateId(this.name), |
| 92 | messageId: generateId(this.name), |
| 93 | hasEmittedRunStarted: false, |
| 94 | } |
| 95 | |
| 96 | try { |
| 97 | // mapOptionsToRequest can throw on caller-side validation failures |
| 98 | // (empty user content, unsupported parts, webSearchTool() rejection in |
| 99 | // the OpenRouter override). Keep it inside the try so those failures |
| 100 | // surface as RUN_ERROR events instead of iterator throws. |
| 101 | const requestParams = this.mapOptionsToRequest(options) |
| 102 | options.logger.request( |
| 103 | `activity=chat provider=${this.name} model=${this.model} messages=${options.messages.length} tools=${options.tools?.length ?? 0} stream=true`, |
| 104 | { provider: this.name, model: this.model }, |
| 105 | ) |
| 106 | const response = await this.client.responses.create( |
| 107 | { |
| 108 | ...requestParams, |
| 109 | stream: true, |
| 110 | }, |
| 111 | extractRequestOptions(options.request), |
| 112 | ) |
| 113 | |
| 114 | yield* this.processStreamChunks( |
| 115 | response, |
| 116 | toolCallMetadata, |
| 117 | options, |
| 118 | aguiState, |
| 119 | ) |
| 120 | } catch (error: unknown) { |
| 121 | // Narrow before logging: raw SDK errors can carry request metadata |
nothing calls this directly
no test coverage detected