@byfriends/kosong 0.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,161 @@
1
+ import { A as createUserMessage, C as TextPart, D as VideoURLPart, E as ToolCallPart, F as mergeInPlace, M as isContentPart, N as isToolCall, O as createAssistantMessage, P as isToolCallPart, S as StreamedMessagePart, T as ToolCall, _ as AudioURLPart, a as StreamedMessage, b as Message, c as TokenUsage, d as grandTotal, f as inputTotal, g as isUnknownCapability, h as UNKNOWN_CAPABILITY, i as ProviderRequestAuth, j as extractText, k as createToolMessage, l as addUsage, m as ModelCapability, n as FinishReason, o as ThinkingEffort, p as Tool, r as GenerateOptions, s as VideoUploadInput, t as ChatProvider, u as emptyUsage, v as ContentPart, w as ThinkPart, x as Role, y as ImageURLPart } from "./provider-DiJKWMsQ.mjs";
2
+ import { a as APITimeoutError, i as APIStatusError, n as APIContextOverflowError, o as ChatProviderError, r as APIEmptyResponseError, t as APIConnectionError } from "./errors-DweKbIOf.mjs";
3
+ import { n as AnthropicOptions } from "./anthropic-Dm_GqFgS.mjs";
4
+ import { r as GoogleGenAIOptions } from "./google-genai-hX0X6CF3.mjs";
5
+ import { i as OpenAICompatOptions } from "./openai-compat-CMrIk-ib.mjs";
6
+ import { r as OpenAILegacyOptions } from "./openai-legacy-B6CVfLlr.mjs";
7
+ import { r as OpenAIResponsesOptions } from "./openai-responses-BxOwxtd3.mjs";
8
+
9
+ //#region src/providers/index.d.ts
10
+ type ProviderConfig = ({
11
+ type: 'anthropic';
12
+ } & AnthropicOptions) | ({
13
+ type: 'openai';
14
+ } & OpenAILegacyOptions) | ({
15
+ type: 'openai-compat';
16
+ } & OpenAICompatOptions) | ({
17
+ type: 'google-genai';
18
+ } & GoogleGenAIOptions) | ({
19
+ type: 'openai_responses';
20
+ } & OpenAIResponsesOptions) | ({
21
+ type: 'vertexai';
22
+ } & GoogleGenAIOptions);
23
+ type ProviderType = ProviderConfig['type'];
24
+ declare function createProvider(config: ProviderConfig): ChatProvider;
25
+ //#endregion
26
+ //#region src/catalog.d.ts
27
+ /**
28
+ * models.dev-style catalog: a public map of provider/model metadata. Callers
29
+ * consume a snapshot of this shape to populate provider + model configuration
30
+ * without hand-writing context windows or capabilities.
31
+ */
32
+ interface CatalogModelEntry {
33
+ readonly id?: string;
34
+ readonly name?: string;
35
+ readonly family?: string;
36
+ readonly limit?: {
37
+ readonly context?: number;
38
+ readonly output?: number;
39
+ };
40
+ readonly tool_call?: boolean;
41
+ readonly reasoning?: boolean;
42
+ readonly interleaved?: boolean | {
43
+ readonly field?: string;
44
+ };
45
+ readonly modalities?: {
46
+ readonly input?: readonly string[];
47
+ readonly output?: readonly string[];
48
+ };
49
+ }
50
+ interface CatalogProviderEntry {
51
+ readonly id?: string;
52
+ readonly name?: string;
53
+ /** Base URL for the provider; may be empty (some SDKs hardcode it). */
54
+ readonly api?: string;
55
+ /** Env var names carrying credentials — surfaced as a hint by callers. */
56
+ readonly env?: readonly string[];
57
+ /** models.dev SDK package id; used to infer the wire type when `type` is absent. */
58
+ readonly npm?: string;
59
+ /** Explicit wire type extension; inferred from `npm`/`id` when absent. */
60
+ readonly type?: string;
61
+ readonly models?: Record<string, CatalogModelEntry>;
62
+ }
63
+ /** Top-level catalog: `{ [providerId]: ProviderEntry }` (e.g. models.dev/api.json). */
64
+ type Catalog = Record<string, CatalogProviderEntry>;
65
+ /** A normalized catalog model: identity plus its {@link ModelCapability}. */
66
+ interface CatalogModel {
67
+ readonly id: string;
68
+ readonly name?: string;
69
+ readonly maxOutputSize?: number;
70
+ readonly reasoningKey?: string;
71
+ readonly capability: ModelCapability;
72
+ }
73
+ /**
74
+ * Resolves a catalog provider entry to a supported wire type. Honors an
75
+ * explicit `type`, otherwise infers from `npm`/`id`. Unknown providers return
76
+ * `undefined` so callers can omit them instead of writing an invalid config.
77
+ */
78
+ declare function inferWireType(entry: CatalogProviderEntry): ProviderType | undefined;
79
+ /**
80
+ * Resolves the base URL to store for a catalog provider, adapting the catalog's
81
+ * `api` to the wire's SDK convention.
82
+ *
83
+ * models.dev `api` URLs are written for the SDK named in `npm` (e.g.
84
+ * `@ai-sdk/anthropic`), whose base already includes the `/v1` version segment.
85
+ * We route the `anthropic` wire through the official `@anthropic-ai/sdk`, which
86
+ * appends `/v1/messages` itself — so a catalog `api` ending in `/v1` would POST
87
+ * to `/v1/v1/messages` (404). Strip the trailing `/v1` for anthropic. OpenAI
88
+ * family SDKs append `/chat/completions` to a `/v1` base, so those pass through.
89
+ */
90
+ declare function catalogBaseUrl(entry: CatalogProviderEntry, wire: ProviderType): string | undefined;
91
+ /** Normalizes one catalog model entry into a {@link CatalogModel}; skips invalid entries. */
92
+ declare function catalogModelToCapability(model: CatalogModelEntry): CatalogModel | undefined;
93
+ /** Extracts the valid, normalized models from a catalog provider entry. */
94
+ declare function catalogProviderModels(entry: CatalogProviderEntry): CatalogModel[];
95
+ //#endregion
96
+ //#region src/generate.d.ts
97
+ /**
98
+ * The result of a single {@link generate} call.
99
+ *
100
+ * Contains the fully-assembled assistant {@link message}, an optional
101
+ * provider-assigned {@link id}, and token {@link usage} statistics.
102
+ */
103
+ interface GenerateResult {
104
+ /** Provider-assigned response identifier, or `null` if unavailable. */
105
+ readonly id: string | null;
106
+ /** The fully-assembled assistant message with merged content parts and tool calls. */
107
+ readonly message: Message;
108
+ /** Token usage for this generation, or `null` if not reported. */
109
+ readonly usage: TokenUsage | null;
110
+ /**
111
+ * Normalized finish reason reported by the provider, or `null` if no
112
+ * finish_reason was emitted (for example, the stream was interrupted
113
+ * before the final event).
114
+ */
115
+ readonly finishReason: FinishReason | null;
116
+ /**
117
+ * Raw provider-specific finish_reason string preserved verbatim.
118
+ * `null` if the provider did not emit one.
119
+ */
120
+ readonly rawFinishReason: string | null;
121
+ }
122
+ interface GenerateCallbacks {
123
+ onMessagePart?: (part: StreamedMessagePart) => void | Promise<void>;
124
+ /**
125
+ * Fires once per fully-assembled tool call after the stream drains, in the
126
+ * order tool calls appear in the final assistant message.
127
+ *
128
+ * Tool calls are deliberately deferred until after the stream completes:
129
+ * parallel-tool-call streams may interleave argument deltas across calls
130
+ * (e.g. tc0-header → tc1-header → tc0-args → tc1-args), so firing mid-stream
131
+ * would dispatch a tool with half-parsed arguments and trigger toolParseError.
132
+ */
133
+ onToolCall?: (toolCall: ToolCall) => void | Promise<void>;
134
+ }
135
+ /**
136
+ * Generate one assistant message by streaming from the given provider.
137
+ *
138
+ * Parts of the message are streamed and merged: consecutive compatible parts
139
+ * (e.g. TextPart + TextPart, ToolCall + ToolCallPart) are merged in-place so
140
+ * the returned message always contains fully-assembled parts.
141
+ *
142
+ * **Tool call completion** is inferred from merge boundaries (a non-merging
143
+ * next part flushes the pending tool call into `message.toolCalls`) and from
144
+ * stream end. Provider adapters translate native "done" signals into this
145
+ * unified form; the generate loop never sees a separate done event.
146
+ *
147
+ * @param provider - The chat provider to generate from.
148
+ * @param systemPrompt - System-level instruction prepended to the request.
149
+ * @param tools - Tool definitions the model may invoke.
150
+ * @param history - The conversation history sent as context.
151
+ * @param callbacks - Optional streaming callbacks.
152
+ * @param options - Optional per-call settings (e.g. an {@link AbortSignal}).
153
+ *
154
+ * @throws {DOMException} with name `"AbortError"` when `options.signal` is
155
+ * aborted before or during streaming.
156
+ * @throws {APIEmptyResponseError} when the response contains no content and
157
+ * no tool calls, or only thinking content without any text or tool calls.
158
+ */
159
+ declare function generate(provider: ChatProvider, systemPrompt: string, tools: Tool[], history: Message[], callbacks?: GenerateCallbacks, options?: GenerateOptions): Promise<GenerateResult>;
160
+ //#endregion
161
+ export { APIConnectionError, APIContextOverflowError, APIEmptyResponseError, APIStatusError, APITimeoutError, type AudioURLPart, type Catalog, type CatalogModel, type CatalogModelEntry, type CatalogProviderEntry, ChatProvider, ChatProviderError, type ContentPart, FinishReason, type GenerateCallbacks, GenerateOptions, type GenerateResult, type ImageURLPart, type Message, type ModelCapability, type ProviderConfig, ProviderRequestAuth, type ProviderType, type Role, StreamedMessage, type StreamedMessagePart, type TextPart, type ThinkPart, ThinkingEffort, type TokenUsage, type Tool, type ToolCall, type ToolCallPart, UNKNOWN_CAPABILITY, type VideoURLPart, VideoUploadInput, addUsage, catalogBaseUrl, catalogModelToCapability, catalogProviderModels, createAssistantMessage, createProvider, createToolMessage, createUserMessage, emptyUsage, extractText, generate, grandTotal, inferWireType, inputTotal, isContentPart, isToolCall, isToolCallPart, isUnknownCapability, mergeInPlace };
package/dist/index.mjs ADDED
@@ -0,0 +1,287 @@
1
+ import { _ as mergeInPlace, d as createToolMessage, f as createUserMessage, g as isToolCallPart, h as isToolCall, m as isContentPart, p as extractText, u as createAssistantMessage } from "./openai-common-08qin3UI.mjs";
2
+ import { a as APITimeoutError, i as APIStatusError, n as APIContextOverflowError, o as ChatProviderError, r as APIEmptyResponseError, t as APIConnectionError } from "./errors-WFxxzL1B.mjs";
3
+ import { a as isUnknownCapability, i as UNKNOWN_CAPABILITY } from "./request-auth-DCWSyCKI.mjs";
4
+ import { AnthropicChatProvider } from "./providers/anthropic.mjs";
5
+ import { GoogleGenAIChatProvider } from "./providers/google-genai.mjs";
6
+ import { t as OpenAICompatChatProvider } from "./openai-compat-CWbwO4b7.mjs";
7
+ import { OpenAILegacyChatProvider } from "./providers/openai-legacy.mjs";
8
+ import { OpenAIResponsesChatProvider } from "./providers/openai-responses.mjs";
9
+ //#region src/providers/index.ts
10
+ function createProvider(config) {
11
+ switch (config.type) {
12
+ case "anthropic": return new AnthropicChatProvider(config);
13
+ case "openai": return new OpenAILegacyChatProvider(config);
14
+ case "openai-compat": return new OpenAICompatChatProvider(config);
15
+ case "google-genai": return new GoogleGenAIChatProvider(config);
16
+ case "openai_responses": return new OpenAIResponsesChatProvider(config);
17
+ case "vertexai": return new GoogleGenAIChatProvider(config);
18
+ default: throw new Error(`Unknown provider type: ${String(config)}`);
19
+ }
20
+ }
21
+ //#endregion
22
+ //#region src/catalog.ts
23
+ const KNOWN_WIRE_TYPES = [
24
+ "anthropic",
25
+ "openai",
26
+ "openai-compat",
27
+ "google-genai",
28
+ "openai_responses",
29
+ "vertexai"
30
+ ];
31
+ function isWireType(value) {
32
+ return typeof value === "string" && KNOWN_WIRE_TYPES.includes(value);
33
+ }
34
+ function hasEmbeddingMarker(value) {
35
+ if (value === void 0) return false;
36
+ const lower = value.toLowerCase();
37
+ return lower.includes("embedding") || /(?:^|[-_/])embed(?:$|[-_/])/.test(lower);
38
+ }
39
+ function isUsableChatModel(model) {
40
+ const outputModalities = model.modalities?.output;
41
+ if (outputModalities !== void 0 && !outputModalities.includes("text")) return false;
42
+ return !hasEmbeddingMarker(model.family) && !hasEmbeddingMarker(model.id) && !hasEmbeddingMarker(model.name);
43
+ }
44
+ /**
45
+ * Resolves a catalog provider entry to a supported wire type. Honors an
46
+ * explicit `type`, otherwise infers from `npm`/`id`. Unknown providers return
47
+ * `undefined` so callers can omit them instead of writing an invalid config.
48
+ */
49
+ function inferWireType(entry) {
50
+ if (isWireType(entry.type)) return entry.type;
51
+ const npm = (entry.npm ?? "").toLowerCase();
52
+ const id = (entry.id ?? "").toLowerCase();
53
+ if (npm.includes("anthropic") || id.includes("anthropic") || id.includes("claude")) return "anthropic";
54
+ if (id.includes("vertex")) return "vertexai";
55
+ if (npm.includes("google") || id.includes("google") || id.includes("gemini")) return "google-genai";
56
+ if (npm.includes("openai") || id.includes("openai")) return "openai";
57
+ }
58
+ /**
59
+ * Resolves the base URL to store for a catalog provider, adapting the catalog's
60
+ * `api` to the wire's SDK convention.
61
+ *
62
+ * models.dev `api` URLs are written for the SDK named in `npm` (e.g.
63
+ * `@ai-sdk/anthropic`), whose base already includes the `/v1` version segment.
64
+ * We route the `anthropic` wire through the official `@anthropic-ai/sdk`, which
65
+ * appends `/v1/messages` itself — so a catalog `api` ending in `/v1` would POST
66
+ * to `/v1/v1/messages` (404). Strip the trailing `/v1` for anthropic. OpenAI
67
+ * family SDKs append `/chat/completions` to a `/v1` base, so those pass through.
68
+ */
69
+ function catalogBaseUrl(entry, wire) {
70
+ const api = entry.api;
71
+ if (typeof api !== "string" || api.length === 0) return void 0;
72
+ if (wire === "anthropic") return api.replace(/\/v1\/?$/, "");
73
+ return api;
74
+ }
75
+ /** Normalizes one catalog model entry into a {@link CatalogModel}; skips invalid entries. */
76
+ function catalogModelToCapability(model) {
77
+ if (typeof model.id !== "string" || model.id.length === 0) return void 0;
78
+ const context = model.limit?.context;
79
+ if (typeof context !== "number" || !Number.isInteger(context) || context <= 0) return void 0;
80
+ if (!isUsableChatModel(model)) return void 0;
81
+ const inputs = model.modalities?.input ?? [];
82
+ const output = model.limit?.output;
83
+ return {
84
+ id: model.id,
85
+ name: typeof model.name === "string" && model.name.length > 0 ? model.name : void 0,
86
+ maxOutputSize: typeof output === "number" && output > 0 ? output : void 0,
87
+ reasoningKey: catalogReasoningKey(model.interleaved),
88
+ capability: {
89
+ image_in: inputs.includes("image"),
90
+ video_in: inputs.includes("video"),
91
+ audio_in: inputs.includes("audio"),
92
+ thinking: Boolean(model.reasoning),
93
+ tool_use: model.tool_call ?? true,
94
+ max_context_tokens: context
95
+ }
96
+ };
97
+ }
98
+ function catalogReasoningKey(interleaved) {
99
+ if (interleaved === true) return "reasoning_content";
100
+ if (typeof interleaved !== "object" || interleaved === null) return void 0;
101
+ const field = interleaved.field?.trim();
102
+ return field !== void 0 && field.length > 0 ? field : void 0;
103
+ }
104
+ /** Extracts the valid, normalized models from a catalog provider entry. */
105
+ function catalogProviderModels(entry) {
106
+ const models = entry.models ?? {};
107
+ return Object.values(models).map((model) => catalogModelToCapability(model)).filter((model) => model !== void 0);
108
+ }
109
+ //#endregion
110
+ //#region src/generate.ts
111
+ /**
112
+ * Generate one assistant message by streaming from the given provider.
113
+ *
114
+ * Parts of the message are streamed and merged: consecutive compatible parts
115
+ * (e.g. TextPart + TextPart, ToolCall + ToolCallPart) are merged in-place so
116
+ * the returned message always contains fully-assembled parts.
117
+ *
118
+ * **Tool call completion** is inferred from merge boundaries (a non-merging
119
+ * next part flushes the pending tool call into `message.toolCalls`) and from
120
+ * stream end. Provider adapters translate native "done" signals into this
121
+ * unified form; the generate loop never sees a separate done event.
122
+ *
123
+ * @param provider - The chat provider to generate from.
124
+ * @param systemPrompt - System-level instruction prepended to the request.
125
+ * @param tools - Tool definitions the model may invoke.
126
+ * @param history - The conversation history sent as context.
127
+ * @param callbacks - Optional streaming callbacks.
128
+ * @param options - Optional per-call settings (e.g. an {@link AbortSignal}).
129
+ *
130
+ * @throws {DOMException} with name `"AbortError"` when `options.signal` is
131
+ * aborted before or during streaming.
132
+ * @throws {APIEmptyResponseError} when the response contains no content and
133
+ * no tool calls, or only thinking content without any text or tool calls.
134
+ */
135
+ async function generate(provider, systemPrompt, tools, history, callbacks, options) {
136
+ const message = {
137
+ role: "assistant",
138
+ content: [],
139
+ toolCalls: []
140
+ };
141
+ let pendingPart = null;
142
+ const toolCallIndexMap = /* @__PURE__ */ new Map();
143
+ if (options?.signal?.aborted) throwAbortError();
144
+ const stream = await provider.generate(systemPrompt, tools, history, options);
145
+ await throwIfAborted(options?.signal, stream);
146
+ for await (const part of stream) {
147
+ await throwIfAborted(options?.signal, stream);
148
+ if (callbacks?.onMessagePart !== void 0) {
149
+ await callbacks.onMessagePart(deepCopyPart(part));
150
+ await throwIfAborted(options?.signal, stream);
151
+ }
152
+ if (isToolCallPart(part) && part.index !== void 0 && !isPendingToolCallAtIndex(pendingPart, part.index)) {
153
+ const arrayIdx = toolCallIndexMap.get(part.index);
154
+ if (arrayIdx !== void 0) {
155
+ const target = message.toolCalls[arrayIdx];
156
+ if (target !== void 0 && part.argumentsPart !== null) target.arguments = target.arguments === null ? part.argumentsPart : target.arguments + part.argumentsPart;
157
+ continue;
158
+ }
159
+ }
160
+ if (pendingPart === null) pendingPart = part;
161
+ else if (!mergeInPlace(pendingPart, part)) {
162
+ flushPart(message, pendingPart, toolCallIndexMap);
163
+ pendingPart = part;
164
+ }
165
+ }
166
+ await throwIfAborted(options?.signal, stream);
167
+ if (pendingPart !== null) flushPart(message, pendingPart, toolCallIndexMap);
168
+ if (message.content.length === 0 && message.toolCalls.length === 0) throw new APIEmptyResponseError(`The API returned an empty response (no content, no tool calls). Provider: ${provider.name}, model: ${provider.modelName}`);
169
+ const hasThink = message.content.some((p) => p.type === "think");
170
+ const hasText = message.content.some((p) => p.type === "text" && p.text.trim().length > 0);
171
+ const hasToolCalls = message.toolCalls.length > 0;
172
+ if (hasThink && !hasText && !hasToolCalls) throw new APIEmptyResponseError(`The API returned a response containing only thinking content without any text or tool calls. This usually indicates the stream was interrupted or the output token budget was exhausted during reasoning. Provider: ${provider.name}, model: ${provider.modelName}`);
173
+ if (callbacks?.onToolCall !== void 0) for (const toolCall of message.toolCalls) {
174
+ await throwIfAborted(options?.signal, stream);
175
+ await callbacks.onToolCall(toolCall);
176
+ }
177
+ return {
178
+ id: stream.id,
179
+ message,
180
+ usage: stream.usage,
181
+ finishReason: stream.finishReason,
182
+ rawFinishReason: stream.rawFinishReason
183
+ };
184
+ }
185
+ function throwAbortError() {
186
+ throw new DOMException("The operation was aborted.", "AbortError");
187
+ }
188
+ async function cancelStream(stream) {
189
+ const cancelable = stream;
190
+ try {
191
+ await cancelable.cancel?.();
192
+ } catch {}
193
+ try {
194
+ await cancelable.return?.();
195
+ } catch {}
196
+ }
197
+ async function throwIfAborted(signal, stream) {
198
+ if (!signal?.aborted) return;
199
+ if (stream !== void 0) await cancelStream(stream);
200
+ throwAbortError();
201
+ }
202
+ /** True when `pending` is a ToolCall whose _streamIndex equals `index`. */
203
+ function isPendingToolCallAtIndex(pending, index) {
204
+ return pending !== null && isToolCall(pending) && pending._streamIndex === index;
205
+ }
206
+ /**
207
+ * Append a fully-merged part to the message.
208
+ *
209
+ * - ContentPart -> message.content
210
+ * - ToolCall -> message.toolCalls (the `_streamIndex` routing key is
211
+ * registered in the map and stripped before storage).
212
+ * - ToolCallPart -> ignored (orphaned delta without a matching pending call)
213
+ */
214
+ function flushPart(message, part, toolCallIndexMap) {
215
+ if (isContentPart(part)) {
216
+ message.content.push(part);
217
+ return;
218
+ }
219
+ if (isToolCall(part)) {
220
+ const streamIndex = part._streamIndex;
221
+ const stored = {
222
+ type: "function",
223
+ id: part.id,
224
+ name: part.name,
225
+ arguments: part.arguments,
226
+ extras: part.extras
227
+ };
228
+ const ordinal = message.toolCalls.length;
229
+ message.toolCalls.push(stored);
230
+ if (streamIndex !== void 0) toolCallIndexMap.set(streamIndex, ordinal);
231
+ }
232
+ }
233
+ /**
234
+ * Produce a shallow-ish copy of a StreamedMessagePart.
235
+ *
236
+ * This is intentionally minimal: we only need isolation for the mutable
237
+ * string fields that `mergeInPlace` mutates (text, think, arguments).
238
+ */
239
+ function deepCopyPart(part) {
240
+ return structuredClone(part);
241
+ }
242
+ //#endregion
243
+ //#region src/usage.ts
244
+ /**
245
+ * Compute total input tokens (other + cache read + cache creation).
246
+ */
247
+ function inputTotal(usage) {
248
+ return usage.inputOther + usage.inputCacheRead + usage.inputCacheCreation;
249
+ }
250
+ /**
251
+ * Compute grand total tokens (input total + output).
252
+ */
253
+ function grandTotal(usage) {
254
+ return inputTotal(usage) + usage.output;
255
+ }
256
+ /**
257
+ * Create a zero-valued TokenUsage.
258
+ */
259
+ function emptyUsage() {
260
+ return {
261
+ inputOther: 0,
262
+ output: 0,
263
+ inputCacheRead: 0,
264
+ inputCacheCreation: 0
265
+ };
266
+ }
267
+ /**
268
+ * Sum two TokenUsage values.
269
+ */
270
+ function addUsage(a, b) {
271
+ return {
272
+ inputOther: a.inputOther + b.inputOther,
273
+ output: a.output + b.output,
274
+ inputCacheRead: a.inputCacheRead + b.inputCacheRead,
275
+ inputCacheCreation: a.inputCacheCreation + b.inputCacheCreation
276
+ };
277
+ }
278
+ //#endregion
279
+ //#region src/index.ts
280
+ /**
281
+ * Concrete provider adapters stay off the root barrel because their SDK type
282
+ * graphs pollute downstream declaration bundles. Import them from subpaths:
283
+ * `@byfriends/kosong/providers/openai-compat`,
284
+ * `@byfriends/kosong/providers/openai-legacy`, etc.
285
+ */
286
+ //#endregion
287
+ export { APIConnectionError, APIContextOverflowError, APIEmptyResponseError, APIStatusError, APITimeoutError, ChatProviderError, UNKNOWN_CAPABILITY, addUsage, catalogBaseUrl, catalogModelToCapability, catalogProviderModels, createAssistantMessage, createProvider, createToolMessage, createUserMessage, emptyUsage, extractText, generate, grandTotal, inferWireType, inputTotal, isContentPart, isToolCall, isToolCallPart, isUnknownCapability, mergeInPlace };