feat(api): integrate createLoggingFetch into all OpenAI-client providers

Addresses Daniel's review feedback to wire createLoggingFetch into other
providers that use the OpenAI client.

Providers updated:
- base-openai-compatible-provider.ts
- openai.ts (including Azure AI Inference and Azure OpenAI)
- openai-native.ts
- lm-studio.ts
- huggingface.ts
- xai.ts
- requesty.ts
- router-provider.ts
- qwen-code.ts

OpenRouter was already implemented as the reference.
This commit is contained in:
Hannes Rudolph 2025-12-18 16:38:03 -07:00 committed by daniel-lxs
parent 85b23f6d95
commit 0ae6ba7aa8
No known key found for this signature in database
GPG key ID: 21C74479048B3AA6
12 changed files with 28 additions and 4 deletions

View file

@ -116,6 +116,7 @@ describe("OpenAiHandler", () => {
"User-Agent": `RooCode/${Package.version}`,
},
timeout: expect.any(Number),
fetch: expect.any(Function),
})
})
})

View file

@ -69,6 +69,7 @@ describe("RequestyHandler", () => {
"X-Title": "Roo Code",
"User-Agent": `RooCode/${Package.version}`,
},
fetch: expect.any(Function),
})
})
@ -84,6 +85,7 @@ describe("RequestyHandler", () => {
"X-Title": "Roo Code",
"User-Agent": `RooCode/${Package.version}`,
},
fetch: expect.any(Function),
})
})

View file

@ -100,6 +100,7 @@ describe("VercelAiGatewayHandler", () => {
"X-Title": "Roo Code",
"User-Agent": expect.stringContaining("RooCode/"),
}),
fetch: expect.any(Function),
})
})

View file

@ -14,7 +14,7 @@ import { BaseProvider } from "./base-provider"
import { handleOpenAIError } from "./utils/openai-error-handler"
import { calculateApiCostOpenAI } from "../../shared/cost"
import { getApiRequestTimeout } from "./utils/timeout-config"
import { withLogging, ApiLogger } from "../core/logging"
import { withLogging, ApiLogger, createLoggingFetch } from "../core/logging"
type BaseOpenAiCompatibleProviderOptions<ModelName extends string> = ApiHandlerOptions & {
providerName: string
@ -65,6 +65,7 @@ export abstract class BaseOpenAiCompatibleProvider<ModelName extends string>
apiKey: this.options.apiKey,
defaultHeaders: DEFAULT_HEADERS,
timeout: getApiRequestTimeout(),
fetch: createLoggingFetch(this._providerName),
})
}

View file

@ -9,6 +9,7 @@ import { DEFAULT_HEADERS } from "./constants"
import { BaseProvider } from "./base-provider"
import { getHuggingFaceModels, getCachedHuggingFaceModels } from "./fetchers/huggingface"
import { handleOpenAIError } from "./utils/openai-error-handler"
import { createLoggingFetch } from "../core/logging"
export class HuggingFaceHandler extends BaseProvider implements SingleCompletionHandler {
private client: OpenAI
@ -31,6 +32,7 @@ export class HuggingFaceHandler extends BaseProvider implements SingleCompletion
baseURL: "https://router.huggingface.co/v1",
apiKey: this.options.huggingFaceApiKey,
defaultHeaders: DEFAULT_HEADERS,
fetch: createLoggingFetch(this.providerName),
})
// Try to get cached models first

View file

@ -17,6 +17,7 @@ import type { SingleCompletionHandler, ApiHandlerCreateMessageMetadata } from ".
import { getModelsFromCache } from "./fetchers/modelCache"
import { getApiRequestTimeout } from "./utils/timeout-config"
import { handleOpenAIError } from "./utils/openai-error-handler"
import { createLoggingFetch } from "../core/logging"
export class LmStudioHandler extends BaseProvider implements SingleCompletionHandler {
protected options: ApiHandlerOptions
@ -37,6 +38,7 @@ export class LmStudioHandler extends BaseProvider implements SingleCompletionHan
baseURL: (this.options.lmStudioBaseUrl || "http://localhost:1234") + "/v1",
apiKey: apiKey,
timeout: getApiRequestTimeout(),
fetch: createLoggingFetch(this.providerName),
})
}

View file

@ -23,7 +23,7 @@ import { ApiStream, ApiStreamUsageChunk } from "../transform/stream"
import { getModelParams } from "../transform/model-params"
import { BaseProvider } from "./base-provider"
import { withLogging, ApiLogger } from "../core/logging"
import { withLogging, ApiLogger, createLoggingFetch } from "../core/logging"
import type { SingleCompletionHandler, ApiHandlerCreateMessageMetadata } from "../index"
export type OpenAiNativeModel = ReturnType<OpenAiNativeHandler["getModel"]>
@ -71,7 +71,11 @@ export class OpenAiNativeHandler extends BaseProvider implements SingleCompletio
this.options.enableResponsesReasoningSummary = true
}
const apiKey = this.options.openAiNativeApiKey ?? "not-provided"
this.client = new OpenAI({ baseURL: this.options.openAiNativeBaseUrl, apiKey })
this.client = new OpenAI({
baseURL: this.options.openAiNativeBaseUrl,
apiKey,
fetch: createLoggingFetch(this.providerName),
})
}
private normalizeUsage(usage: any, model: OpenAiNativeModel): ApiStreamUsageChunk | undefined {

View file

@ -22,7 +22,7 @@ import { getModelParams } from "../transform/model-params"
import { DEFAULT_HEADERS } from "./constants"
import { BaseProvider } from "./base-provider"
import { withLogging, ApiLogger } from "../core/logging"
import { withLogging, ApiLogger, createLoggingFetch } from "../core/logging"
import type { SingleCompletionHandler, ApiHandlerCreateMessageMetadata } from "../index"
import { getApiRequestTimeout } from "./utils/timeout-config"
import { handleOpenAIError } from "./utils/openai-error-handler"
@ -63,6 +63,7 @@ export class OpenAiHandler extends BaseProvider implements SingleCompletionHandl
defaultHeaders: headers,
defaultQuery: { "api-version": this.options.azureApiVersion || "2024-05-01-preview" },
timeout,
fetch: createLoggingFetch(this.providerName),
})
} else if (isAzureOpenAi) {
// Azure API shape slightly differs from the core API shape:
@ -73,6 +74,7 @@ export class OpenAiHandler extends BaseProvider implements SingleCompletionHandl
apiVersion: this.options.azureApiVersion || azureOpenAiDefaultApiVersion,
defaultHeaders: headers,
timeout,
fetch: createLoggingFetch(this.providerName),
})
} else {
this.client = new OpenAI({
@ -80,6 +82,7 @@ export class OpenAiHandler extends BaseProvider implements SingleCompletionHandl
apiKey,
defaultHeaders: headers,
timeout,
fetch: createLoggingFetch(this.providerName),
})
}
}

View file

@ -15,6 +15,7 @@ import { ApiStream } from "../transform/stream"
import { BaseProvider } from "./base-provider"
import type { SingleCompletionHandler, ApiHandlerCreateMessageMetadata } from "../index"
import { createLoggingFetch } from "../core/logging"
const QWEN_OAUTH_BASE_URL = "https://chat.qwen.ai"
const QWEN_OAUTH_TOKEN_ENDPOINT = `${QWEN_OAUTH_BASE_URL}/api/v1/oauth2/token`
@ -69,6 +70,7 @@ export class QwenCodeHandler extends BaseProvider implements SingleCompletionHan
this.client = new OpenAI({
apiKey: "dummy-key-will-be-replaced",
baseURL: "https://dashscope.aliyuncs.com/compatible-mode/v1",
fetch: createLoggingFetch("QwenCode"),
})
}
return this.client

View file

@ -25,6 +25,7 @@ import type { SingleCompletionHandler, ApiHandlerCreateMessageMetadata } from ".
import { toRequestyServiceUrl } from "../../shared/utils/requesty"
import { handleOpenAIError } from "./utils/openai-error-handler"
import { applyRouterToolPreferences } from "./utils/router-tool-preferences"
import { createLoggingFetch } from "../core/logging"
// Requesty usage includes an extra field for Anthropic use cases.
// Safely cast the prompt token details section to the appropriate structure.
@ -78,6 +79,7 @@ export class RequestyHandler extends BaseProvider implements SingleCompletionHan
baseURL: this.baseURL,
apiKey: apiKey,
defaultHeaders: DEFAULT_HEADERS,
fetch: createLoggingFetch(this.providerName),
})
}

View file

@ -6,6 +6,7 @@ import { ApiHandlerOptions, RouterName, ModelRecord } from "../../shared/api"
import { BaseProvider } from "./base-provider"
import { getModels, getModelsFromCache } from "./fetchers/modelCache"
import { createLoggingFetch } from "../core/logging"
import { DEFAULT_HEADERS } from "./constants"
@ -52,6 +53,7 @@ export abstract class RouterProvider extends BaseProvider {
...DEFAULT_HEADERS,
...(options.openAiHeaders || {}),
},
fetch: createLoggingFetch(name),
})
}

View file

@ -15,6 +15,7 @@ import { DEFAULT_HEADERS } from "./constants"
import { BaseProvider } from "./base-provider"
import type { SingleCompletionHandler, ApiHandlerCreateMessageMetadata } from "../index"
import { handleOpenAIError } from "./utils/openai-error-handler"
import { createLoggingFetch } from "../core/logging"
const XAI_DEFAULT_TEMPERATURE = 0
@ -36,6 +37,7 @@ export class XAIHandler extends BaseProvider implements SingleCompletionHandler
baseURL: "https://api.x.ai/v1",
apiKey: apiKey,
defaultHeaders: DEFAULT_HEADERS,
fetch: createLoggingFetch(this.providerName),
})
}