(endpoint: AIEndpoint)
| 109 | } |
| 110 | |
| 111 | async function fetchOpenAIModels(endpoint: AIEndpoint): Promise<string[]> { |
| 112 | const requestUrl = buildProviderModelsUrl( |
| 113 | endpoint.provider, |
| 114 | endpoint.baseUrl, |
| 115 | endpoint.apiKey, |
| 116 | endpoint.useExactRequestUrl, |
| 117 | ); |
| 118 | if (!requestUrl) return []; |
| 119 | logAIEndpointDebug("request", endpoint, { |
| 120 | action: "fetch-models", |
| 121 | method: "GET", |
| 122 | requestUrl, |
| 123 | }); |
| 124 | const response = await fetch(requestUrl, { |
| 125 | headers: { Authorization: `Bearer ${endpoint.apiKey}` }, |
| 126 | }); |
| 127 | if (!response.ok) { |
| 128 | const errorBody = await response.text(); |
| 129 | logAIEndpointDebug("error", endpoint, { |
| 130 | action: "fetch-models", |
| 131 | method: "GET", |
| 132 | requestUrl, |
| 133 | status: response.status, |
| 134 | statusText: response.statusText, |
| 135 | contentType: response.headers.get("content-type"), |
| 136 | responseLength: errorBody.length, |
| 137 | responseBodyPreview: summarizeDebugText(errorBody), |
| 138 | }); |
| 139 | throw new Error(`Failed to fetch models: ${response.status} ${response.statusText}`); |
| 140 | } |
| 141 | const rawBody = await response.text(); |
| 142 | let data: { data?: Array<{ id: string }> }; |
| 143 | |
| 144 | try { |
| 145 | data = JSON.parse(rawBody); |
| 146 | } catch { |
| 147 | logAIEndpointDebug("error", endpoint, { |
| 148 | action: "fetch-models", |
| 149 | method: "GET", |
| 150 | requestUrl, |
| 151 | status: response.status, |
| 152 | statusText: response.statusText, |
| 153 | contentType: response.headers.get("content-type"), |
| 154 | responseLength: rawBody.length, |
| 155 | responseBodyPreview: summarizeDebugText(rawBody), |
| 156 | }); |
| 157 | throw new Error( |
| 158 | "The endpoint did not return JSON. Check whether the base URL points to the API root instead of a console page.", |
| 159 | ); |
| 160 | } |
| 161 | |
| 162 | if (!Array.isArray(data.data)) { |
| 163 | logAIEndpointDebug("error", endpoint, { |
| 164 | action: "fetch-models", |
| 165 | method: "GET", |
| 166 | requestUrl, |
| 167 | status: response.status, |
| 168 | statusText: response.statusText, |
no test coverage detected