diff options
Diffstat (limited to 'packages/openai-stream/src/provider.ts')
| -rw-r--r-- | packages/openai-stream/src/provider.ts | 113 |
1 files changed, 61 insertions, 52 deletions
diff --git a/packages/openai-stream/src/provider.ts b/packages/openai-stream/src/provider.ts index c13d60e..9a9369f 100644 --- a/packages/openai-stream/src/provider.ts +++ b/packages/openai-stream/src/provider.ts @@ -1,12 +1,14 @@ import type { - ApiKeyCredentials, - ChatMessage, - ModelInfo, - ProviderContract, - ProviderStreamOptions, - ToolContract, + ApiKeyCredentials, + ChatMessage, + ModelInfo, + ProviderContract, + ProviderStreamOptions, + ProviderUsage, + ToolContract, } from "@dispatch/kernel"; import type { FetchLike } from "@dispatch/trace-replay"; +import { getUsage as fetchUsage } from "./getUsage.js"; import { listModels as fetchModels } from "./listModels.js"; import { streamChat } from "./stream.js"; @@ -19,55 +21,62 @@ import { streamChat } from "./stream.js"; */ export interface CreateOpenAICompatProviderOpts { - readonly credentials: ApiKeyCredentials; - readonly model: string; - /** Provider id (was hardcoded "openai-compat"). Stamped on the ProviderContract.id - * + used in listModels error labels. */ - readonly id: string; - /** - * Internal injectable fetch — used by tests and replay mode. - * When absent, falls back to globalThis.fetch (production default). - */ - readonly fetchFn?: FetchLike; - /** - * Optional hook a provider extension uses to add provider-specific body fields (e.g. - * `reasoning_effort`) before the request is sent. Receives the body built so far + - * the ProviderStreamOptions; returns ADDITIONAL fields to merge (or the full body). - * Default (absent): no extra fields. Generic — the library names no feature. - */ - readonly transformBody?: ( - body: Record<string, unknown>, - opts: ProviderStreamOptions, - ) => Record<string, unknown>; + readonly credentials: ApiKeyCredentials; + readonly model: string; + /** Provider id (was hardcoded "openai-compat"). Stamped on the ProviderContract.id + * + used in listModels error labels. */ + readonly id: string; + /** + * Internal injectable fetch — used by tests and replay mode. + * When absent, falls back to globalThis.fetch (production default). + */ + readonly fetchFn?: FetchLike; + /** + * Optional hook a provider extension uses to add provider-specific body fields (e.g. + * `reasoning_effort`) before the request is sent. Receives the body built so far + + * the ProviderStreamOptions; returns ADDITIONAL fields to merge (or the full body). + * Default (absent): no extra fields. Generic — the library names no feature. + */ + readonly transformBody?: ( + body: Record<string, unknown>, + opts: ProviderStreamOptions, + ) => Record<string, unknown>; } export function createOpenAICompatProvider(opts: CreateOpenAICompatProviderOpts): ProviderContract { - const baseURL = opts.credentials.baseURL ?? "https://opencode.ai/zen/go/v1"; - const apiKey = opts.credentials.apiKey; - const fetchFn = opts.fetchFn; - const transformBody = opts.transformBody; + const baseURL = opts.credentials.baseURL ?? "https://opencode.ai/zen/go/v1"; + const apiKey = opts.credentials.apiKey; + const fetchFn = opts.fetchFn; + const transformBody = opts.transformBody; - const streamConfig = { - baseURL, - apiKey, - model: opts.model, - ...(fetchFn !== undefined ? { fetchFn } : {}), - ...(transformBody !== undefined ? { transformBody } : {}), - }; + const streamConfig = { + baseURL, + apiKey, + model: opts.model, + ...(fetchFn !== undefined ? { fetchFn } : {}), + ...(transformBody !== undefined ? { transformBody } : {}), + }; - return { - id: opts.id, - stream: ( - messages: readonly ChatMessage[], - tools: readonly ToolContract[], - streamOpts?: ProviderStreamOptions, - ) => streamChat(streamConfig, messages, tools, streamOpts), - listModels: (): Promise<readonly ModelInfo[]> => - fetchModels({ - baseURL, - apiKey, - providerId: opts.id, - ...(fetchFn !== undefined ? { fetchFn } : {}), - }), - }; + return { + id: opts.id, + stream: ( + messages: readonly ChatMessage[], + tools: readonly ToolContract[], + streamOpts?: ProviderStreamOptions, + ) => streamChat(streamConfig, messages, tools, streamOpts), + listModels: (): Promise<readonly ModelInfo[]> => + fetchModels({ + baseURL, + apiKey, + providerId: opts.id, + ...(fetchFn !== undefined ? { fetchFn } : {}), + }), + getUsage: (): Promise<ProviderUsage | undefined> => + fetchUsage({ + baseURL, + apiKey, + providerId: opts.id, + ...(fetchFn !== undefined ? { fetchFn } : {}), + }), + }; } |
