(
input: Parameters<typeof fetch>[0],
init?: Parameters<typeof fetch>[1]
)
| 1807 | |
| 1808 | const baseFetch = getProviderFetch(providerConfig); |
| 1809 | const copilotFetchFn = async ( |
| 1810 | input: Parameters<typeof fetch>[0], |
| 1811 | init?: Parameters<typeof fetch>[1] |
| 1812 | ) => { |
| 1813 | const headers = new Headers(input instanceof Request ? input.headers : undefined); |
| 1814 | if (init?.headers) { |
| 1815 | for (const [key, value] of new Headers(init.headers).entries()) { |
| 1816 | headers.set(key, value); |
| 1817 | } |
| 1818 | } |
| 1819 | headers.set("Authorization", `Bearer ${resolvedApiKey ?? ""}`); |
| 1820 | headers.set("Openai-Intent", "conversation-edits"); |
| 1821 | |
| 1822 | const urlString = getFetchInputUrl(input); |
| 1823 | |
| 1824 | const method = ( |
| 1825 | init?.method ?? (input instanceof Request ? input.method : "GET") |
| 1826 | ).toUpperCase(); |
| 1827 | // normalizeCodexResponsesBody() applies only to the stock OpenAI provider's |
| 1828 | // /v1/responses path (used by Codex OAuth). The custom CopilotResponsesLanguageModel |
| 1829 | // posts directly to /responses, intentionally bypassing this normalization. |
| 1830 | const isResponsesRequest = /\/v1\/responses(\?|$)/.test(urlString); |
| 1831 | |
| 1832 | let nextInit: Parameters<typeof fetch>[1] = { ...init, headers }; |
| 1833 | |
| 1834 | // Resolve request body text for billing classification. |
| 1835 | // Standard AI SDK path: init.body is a JSON string. |
| 1836 | // Request object path: clone + read body text so the original stream |
| 1837 | // remains intact for the real network request. |
| 1838 | let originalBodyText: string | undefined; |
| 1839 | if (typeof init?.body === "string") { |
| 1840 | originalBodyText = init.body; |
| 1841 | } else if (input instanceof Request) { |
| 1842 | try { |
| 1843 | originalBodyText = await input.clone().text(); |
| 1844 | } catch { |
| 1845 | // Fall back to undefined so classifyCopilotInitiator defaults to "user". |
| 1846 | } |
| 1847 | } |
| 1848 | |
| 1849 | if (typeof originalBodyText === "string" && method === "POST" && isResponsesRequest) { |
| 1850 | try { |
| 1851 | const normalizedBody = normalizeCodexResponsesBody(originalBodyText); |
| 1852 | headers.delete("content-length"); |
| 1853 | nextInit = { |
| 1854 | ...nextInit, |
| 1855 | headers, |
| 1856 | body: normalizedBody, |
| 1857 | }; |
| 1858 | } catch { |
| 1859 | // If body isn't JSON, keep the original request body for Copilot. |
| 1860 | } |
| 1861 | } |
| 1862 | |
| 1863 | // GitHub Copilot uses X-Initiator to determine premium request billing. |
| 1864 | // "user" = consumes a premium request; "agent" = free (tool/agent work). |
| 1865 | // If the caller explicitly marked this as agent-initiated (e.g., sub-agent, |
| 1866 | // compaction, internal utility), skip the heuristic and always use "agent". |
nothing calls this directly
no test coverage detected