summaryrefslogtreecommitdiffhomepage
path: root/packages/openai-stream/src/provider.ts
diff options
context:
space:
mode:
Diffstat (limited to 'packages/openai-stream/src/provider.ts')
-rw-r--r--packages/openai-stream/src/provider.ts113
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 } : {}),
+ }),
+ };
}