@byfriends/kosong 0.1.0 → 0.2.1

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.
Files changed (29) hide show
  1. package/dist/{anthropic-Dm_GqFgS.d.mts → anthropic-0CVG5rBE.d.mts} +1 -2
  2. package/dist/{provider-DiJKWMsQ.d.mts → errors-wlT14tC4.d.mts} +227 -2
  3. package/dist/{google-genai-hX0X6CF3.d.mts → google-genai-xKK8lI_R.d.mts} +1 -2
  4. package/dist/index.d.mts +66 -12
  5. package/dist/index.mjs +945 -21
  6. package/dist/{openai-common-08qin3UI.mjs → openai-common-Dl42y_vn.mjs} +27 -2
  7. package/dist/{openai-common-B6cK2ig3.d.mts → openai-common-DwkxUSyI.d.mts} +7 -3
  8. package/dist/{openai-responses-BxOwxtd3.d.mts → openai-responses-DZ9mQ5RA.d.mts} +2 -2
  9. package/dist/providers/anthropic.d.mts +1 -1
  10. package/dist/providers/anthropic.mjs +56 -68
  11. package/dist/providers/google-genai.d.mts +1 -1
  12. package/dist/providers/google-genai.mjs +1 -2
  13. package/dist/providers/openai-common.d.mts +1 -1
  14. package/dist/providers/openai-common.mjs +1 -1
  15. package/dist/providers/openai-responses.d.mts +1 -1
  16. package/dist/providers/openai-responses.mjs +21 -4
  17. package/dist/request-auth-BMXt8jRu.mjs +341 -0
  18. package/package.json +1 -11
  19. package/dist/capability-registry-CMBuEYcf.mjs +0 -161
  20. package/dist/chat-completions-stream-BuMu_xr9.mjs +0 -62
  21. package/dist/errors-DweKbIOf.d.mts +0 -42
  22. package/dist/openai-compat-CMrIk-ib.d.mts +0 -132
  23. package/dist/openai-compat-CWbwO4b7.mjs +0 -801
  24. package/dist/openai-legacy-B6CVfLlr.d.mts +0 -71
  25. package/dist/providers/openai-compat.d.mts +0 -2
  26. package/dist/providers/openai-compat.mjs +0 -2
  27. package/dist/providers/openai-legacy.d.mts +0 -2
  28. package/dist/providers/openai-legacy.mjs +0 -248
  29. package/dist/request-auth-DCWSyCKI.mjs +0 -63
@@ -0,0 +1,341 @@
1
+ import { o as ChatProviderError } from "./errors-WFxxzL1B.mjs";
2
+ //#region src/capability.ts
3
+ const UNKNOWN_CAPABILITY_MARKER = Symbol.for("byf.kosong.UNKNOWN_CAPABILITY");
4
+ /**
5
+ * Shared read-only default returned when a provider has not catalogued a
6
+ * given model. Frozen so accidental mutation at one call site cannot leak
7
+ * into another.
8
+ */
9
+ const UNKNOWN_CAPABILITY = Object.freeze(Object.defineProperty({
10
+ image_in: false,
11
+ video_in: false,
12
+ audio_in: false,
13
+ thinking: false,
14
+ tool_use: false,
15
+ thinking_effort: false,
16
+ thinking_xhigh: false,
17
+ thinking_max: false,
18
+ max_context_tokens: 0
19
+ }, UNKNOWN_CAPABILITY_MARKER, { value: true }));
20
+ function isUnknownCapability(capability) {
21
+ if (capability === UNKNOWN_CAPABILITY) return true;
22
+ if (capability[UNKNOWN_CAPABILITY_MARKER] === true) return true;
23
+ return !capability.image_in && !capability.video_in && !capability.audio_in && !capability.thinking && !capability.tool_use && !capability.thinking_effort && !capability.thinking_xhigh && !capability.thinking_max && capability.max_context_tokens === 0;
24
+ }
25
+ //#endregion
26
+ //#region src/providers/capability-registry.ts
27
+ const CACHE_CAPABILITY = Object.freeze({
28
+ strategy: "explicit-block",
29
+ maxCacheableBlocks: 4,
30
+ supportedScopes: [
31
+ "global",
32
+ "project",
33
+ "session",
34
+ "none"
35
+ ]
36
+ });
37
+ const OPENAI_CACHE_CAPABILITY = Object.freeze({
38
+ strategy: "prompt-cache-key",
39
+ supportedScopes: ["global"]
40
+ });
41
+ const NO_CACHE_CAPABILITY = Object.freeze({
42
+ strategy: "none",
43
+ supportedScopes: []
44
+ });
45
+ const OPENAI_RESPONSES_DEVELOPER_ROLE_MODELS = new Set([
46
+ "gpt-4.1",
47
+ "gpt-4.1-mini",
48
+ "gpt-4.1-nano",
49
+ "gpt-5-codex",
50
+ "o1",
51
+ "o1-mini",
52
+ "o1-pro",
53
+ "o3",
54
+ "o3-mini",
55
+ "o3-pro",
56
+ "o4-mini"
57
+ ]);
58
+ const OPENAI_VISION_TOOL_PREFIXES = [
59
+ "gpt-4o",
60
+ "gpt-4-turbo",
61
+ "gpt-4.1",
62
+ "gpt-4.5"
63
+ ];
64
+ const CLAUDE_3_PREFIXES = [
65
+ "claude-3-",
66
+ "claude-3.5-",
67
+ "claude-3.7-"
68
+ ];
69
+ const CLAUDE_4_PREFIXES = [
70
+ "claude-opus-4",
71
+ "claude-sonnet-4",
72
+ "claude-haiku-4"
73
+ ];
74
+ const GEMINI_CATALOGUED_PREFIXES = [
75
+ "gemini-1.5-pro",
76
+ "gemini-1.5-flash",
77
+ "gemini-2.0-flash",
78
+ "gemini-2.0-pro",
79
+ "gemini-2.5-pro",
80
+ "gemini-2.5-flash"
81
+ ];
82
+ const OPENAI_REASONING_CAPABILITY = Object.freeze({
83
+ image_in: false,
84
+ video_in: false,
85
+ audio_in: false,
86
+ thinking: true,
87
+ tool_use: true,
88
+ thinking_effort: true,
89
+ thinking_xhigh: false,
90
+ thinking_max: false,
91
+ max_context_tokens: 0,
92
+ cache: OPENAI_CACHE_CAPABILITY
93
+ });
94
+ const OPENAI_REASONING_XHIGH_CAPABILITY = Object.freeze({
95
+ image_in: false,
96
+ video_in: false,
97
+ audio_in: false,
98
+ thinking: true,
99
+ tool_use: true,
100
+ thinking_effort: true,
101
+ thinking_xhigh: true,
102
+ thinking_max: false,
103
+ max_context_tokens: 0,
104
+ cache: OPENAI_CACHE_CAPABILITY
105
+ });
106
+ const OPENAI_VISION_TOOL_CAPABILITY = Object.freeze({
107
+ image_in: true,
108
+ video_in: false,
109
+ audio_in: false,
110
+ thinking: false,
111
+ tool_use: true,
112
+ thinking_effort: false,
113
+ thinking_xhigh: false,
114
+ thinking_max: false,
115
+ max_context_tokens: 0,
116
+ cache: OPENAI_CACHE_CAPABILITY
117
+ });
118
+ const OPENAI_TEXT_TOOL_CAPABILITY = Object.freeze({
119
+ image_in: false,
120
+ video_in: false,
121
+ audio_in: false,
122
+ thinking: false,
123
+ tool_use: true,
124
+ thinking_effort: false,
125
+ thinking_xhigh: false,
126
+ thinking_max: false,
127
+ max_context_tokens: 0,
128
+ cache: OPENAI_CACHE_CAPABILITY
129
+ });
130
+ const ANTHROPIC_VISION_TOOL_CAPABILITY = Object.freeze({
131
+ image_in: true,
132
+ video_in: false,
133
+ audio_in: false,
134
+ thinking: false,
135
+ tool_use: true,
136
+ thinking_effort: false,
137
+ thinking_xhigh: false,
138
+ thinking_max: false,
139
+ max_context_tokens: 0,
140
+ cache: CACHE_CAPABILITY
141
+ });
142
+ const ANTHROPIC_THINKING_VISION_TOOL_CAPABILITY = Object.freeze({
143
+ image_in: true,
144
+ video_in: false,
145
+ audio_in: false,
146
+ thinking: true,
147
+ tool_use: true,
148
+ thinking_effort: true,
149
+ thinking_xhigh: false,
150
+ thinking_max: true,
151
+ max_context_tokens: 0,
152
+ cache: CACHE_CAPABILITY
153
+ });
154
+ const ANTHROPIC_THINKING_XHIGH_VISION_TOOL_CAPABILITY = Object.freeze({
155
+ image_in: true,
156
+ video_in: false,
157
+ audio_in: false,
158
+ thinking: true,
159
+ tool_use: true,
160
+ thinking_effort: true,
161
+ thinking_xhigh: true,
162
+ thinking_max: true,
163
+ max_context_tokens: 0,
164
+ cache: CACHE_CAPABILITY
165
+ });
166
+ const GEMINI_MULTIMODAL_TOOL_CAPABILITY = Object.freeze({
167
+ image_in: true,
168
+ video_in: true,
169
+ audio_in: true,
170
+ thinking: false,
171
+ tool_use: true,
172
+ thinking_effort: false,
173
+ thinking_xhigh: false,
174
+ thinking_max: false,
175
+ max_context_tokens: 0,
176
+ cache: NO_CACHE_CAPABILITY
177
+ });
178
+ const GEMINI_THINKING_MULTIMODAL_TOOL_CAPABILITY = Object.freeze({
179
+ image_in: true,
180
+ video_in: true,
181
+ audio_in: true,
182
+ thinking: true,
183
+ tool_use: true,
184
+ thinking_effort: false,
185
+ thinking_xhigh: false,
186
+ thinking_max: false,
187
+ max_context_tokens: 0,
188
+ cache: NO_CACHE_CAPABILITY
189
+ });
190
+ const OPENAI_LEGACY_CAPABILITY_CATALOG = [
191
+ {
192
+ matches: isOpenAIGpt5ReasoningModel,
193
+ capability: OPENAI_REASONING_XHIGH_CAPABILITY
194
+ },
195
+ {
196
+ matches: isOpenAIReasoningModel,
197
+ capability: OPENAI_REASONING_CAPABILITY
198
+ },
199
+ {
200
+ matches: (name) => hasPrefix(name, OPENAI_VISION_TOOL_PREFIXES),
201
+ capability: OPENAI_VISION_TOOL_CAPABILITY
202
+ },
203
+ {
204
+ matches: (name) => name.startsWith("gpt-3.5-turbo"),
205
+ capability: OPENAI_TEXT_TOOL_CAPABILITY
206
+ }
207
+ ];
208
+ const OPENAI_RESPONSES_CAPABILITY_CATALOG = [
209
+ {
210
+ matches: isOpenAIGpt5ReasoningModel,
211
+ capability: OPENAI_REASONING_XHIGH_CAPABILITY
212
+ },
213
+ {
214
+ matches: isOpenAIReasoningModel,
215
+ capability: OPENAI_REASONING_CAPABILITY
216
+ },
217
+ {
218
+ matches: (name) => hasPrefix(name, OPENAI_VISION_TOOL_PREFIXES),
219
+ capability: OPENAI_VISION_TOOL_CAPABILITY
220
+ }
221
+ ];
222
+ const ANTHROPIC_CAPABILITY_CATALOG = [
223
+ {
224
+ matches: (name) => hasPrefix(name, CLAUDE_3_PREFIXES),
225
+ capability: ANTHROPIC_VISION_TOOL_CAPABILITY
226
+ },
227
+ {
228
+ matches: isClaudeOpus47Or48,
229
+ capability: ANTHROPIC_THINKING_XHIGH_VISION_TOOL_CAPABILITY
230
+ },
231
+ {
232
+ matches: (name) => hasPrefix(name, CLAUDE_4_PREFIXES),
233
+ capability: ANTHROPIC_THINKING_VISION_TOOL_CAPABILITY
234
+ }
235
+ ];
236
+ function normalizeModelName(modelName) {
237
+ return modelName.toLowerCase();
238
+ }
239
+ function hasPrefix(modelName, prefixes) {
240
+ return prefixes.some((prefix) => modelName.startsWith(prefix));
241
+ }
242
+ function isOpenAIReasoningModel(modelName) {
243
+ return /^o\d/.test(modelName);
244
+ }
245
+ function isOpenAIGpt5ReasoningModel(modelName) {
246
+ return modelName.startsWith("gpt-5");
247
+ }
248
+ function isClaudeOpus47Or48(modelName) {
249
+ return /claude-opus-4-[78]/.test(modelName);
250
+ }
251
+ function capabilityFromCatalog(modelName, catalog) {
252
+ const normalized = normalizeModelName(modelName);
253
+ for (const entry of catalog) if (entry.matches(normalized)) return entry.capability;
254
+ return UNKNOWN_CAPABILITY;
255
+ }
256
+ function getOpenAILegacyModelCapability(modelName) {
257
+ const capability = capabilityFromCatalog(modelName, OPENAI_LEGACY_CAPABILITY_CATALOG);
258
+ if (!capability.cache) return {
259
+ ...capability,
260
+ cache: OPENAI_CACHE_CAPABILITY
261
+ };
262
+ return capability;
263
+ }
264
+ function getOpenAIResponsesModelCapability(modelName) {
265
+ return capabilityFromCatalog(modelName, OPENAI_RESPONSES_CAPABILITY_CATALOG);
266
+ }
267
+ function getAnthropicModelCapability(modelName) {
268
+ return capabilityFromCatalog(modelName, ANTHROPIC_CAPABILITY_CATALOG);
269
+ }
270
+ function getGoogleGenAIModelCapability(modelName) {
271
+ const normalized = normalizeModelName(modelName);
272
+ if (!normalized.startsWith("gemini-")) return UNKNOWN_CAPABILITY;
273
+ if (!hasPrefix(normalized, GEMINI_CATALOGUED_PREFIXES)) return UNKNOWN_CAPABILITY;
274
+ if (normalized.startsWith("gemini-2.5-") || normalized.includes("thinking")) return GEMINI_THINKING_MULTIMODAL_TOOL_CAPABILITY;
275
+ return GEMINI_MULTIMODAL_TOOL_CAPABILITY;
276
+ }
277
+ /**
278
+ * Tries all provider-specific capability registries and returns the first
279
+ * non-UNKNOWN match. Used when the provider context is unknown (e.g., catalog
280
+ * enrichment) to fill in accurate thinking capability flags.
281
+ */
282
+ function resolveCapabilityFromRegistry(modelName) {
283
+ const registries = [
284
+ getAnthropicModelCapability,
285
+ getOpenAIResponsesModelCapability,
286
+ getOpenAILegacyModelCapability,
287
+ getGoogleGenAIModelCapability
288
+ ];
289
+ for (const fn of registries) {
290
+ const cap = fn(modelName);
291
+ if (!isUnknownCapability(cap)) return cap;
292
+ }
293
+ }
294
+ function usesOpenAIResponsesDeveloperRole(modelName) {
295
+ const normalized = normalizeModelName(modelName);
296
+ if (OPENAI_RESPONSES_DEVELOPER_ROLE_MODELS.has(normalized)) return true;
297
+ for (const cataloguedModel of OPENAI_RESPONSES_DEVELOPER_ROLE_MODELS) if (normalized.startsWith(cataloguedModel + "-")) return true;
298
+ return false;
299
+ }
300
+ //#endregion
301
+ //#region src/providers/request-auth.ts
302
+ function requireProviderApiKey(providerName, auth, defaultApiKey) {
303
+ const apiKey = auth?.apiKey ?? defaultApiKey;
304
+ if (apiKey === void 0 || apiKey.length === 0) throw new ChatProviderError(`${providerName}: apiKey is required. Provide it via the constructor options, the provider's API-key environment variable, options.auth.apiKey on each request, or an OAuth login.`);
305
+ return apiKey;
306
+ }
307
+ function mergeRequestHeaders(defaultHeaders, requestHeaders) {
308
+ const merged = {};
309
+ if (defaultHeaders !== void 0) Object.assign(merged, defaultHeaders);
310
+ if (requestHeaders !== void 0) Object.assign(merged, requestHeaders);
311
+ return Object.keys(merged).length > 0 ? merged : void 0;
312
+ }
313
+ /**
314
+ * Resolve the SDK client to use for a single provider request, applying the
315
+ * standard precedence shared by every provider adapter:
316
+ *
317
+ * 1. If a `clientFactory` was supplied, delegate to it (it receives the
318
+ * per-request {@link ProviderRequestAuth}, defaulting to `{}`).
319
+ * 2. Otherwise, if no per-request auth is needed AND a constructor-time
320
+ * client was cached, reuse the cached instance.
321
+ * 3. Otherwise, call `build(auth)` to construct a fresh client for this
322
+ * request — typically using `requireProviderApiKey` plus
323
+ * `mergeRequestHeaders`.
324
+ *
325
+ * Note: when per-request `auth` is provided (e.g. an OAuth bearer token
326
+ * resolved immediately before each call), step 3 fires and a brand-new SDK
327
+ * client is constructed per request. This is intentional — it keeps short-lived
328
+ * credentials out of any long-lived shared state and avoids racing concurrent
329
+ * requests on a mutable client. The trade-off is that connection-pool / keep-
330
+ * alive state inside the SDK client isn't reused across requests on the OAuth
331
+ * path. For the current agent-CLI workload (one LLM call per turn step) this
332
+ * is fine; if a future host needs high-throughput per-request auth, the
333
+ * obvious optimization is a small LRU keyed on `(apiKey, headers digest)`.
334
+ */
335
+ function resolveAuthBackedClient(state, auth, build) {
336
+ if (state.clientFactory !== void 0) return state.clientFactory(auth ?? {});
337
+ if (auth === void 0 && state.cachedClient !== void 0) return state.cachedClient;
338
+ return build(auth);
339
+ }
340
+ //#endregion
341
+ export { getGoogleGenAIModelCapability as a, resolveCapabilityFromRegistry as c, isUnknownCapability as d, getAnthropicModelCapability as i, usesOpenAIResponsesDeveloperRole as l, requireProviderApiKey as n, getOpenAILegacyModelCapability as o, resolveAuthBackedClient as r, getOpenAIResponsesModelCapability as s, mergeRequestHeaders as t, UNKNOWN_CAPABILITY as u };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@byfriends/kosong",
3
- "version": "0.1.0",
3
+ "version": "0.2.1",
4
4
  "description": "LLM and provider abstraction layer for BYF",
5
5
  "license": "Proprietary",
6
6
  "author": "ByronFinn",
@@ -35,16 +35,6 @@
35
35
  "import": "./dist/index.mjs",
36
36
  "default": "./dist/index.mjs"
37
37
  },
38
- "./providers/openai-compat": {
39
- "types": "./dist/providers/openai-compat.d.mts",
40
- "import": "./dist/providers/openai-compat.mjs",
41
- "default": "./dist/providers/openai-compat.mjs"
42
- },
43
- "./providers/openai-legacy": {
44
- "types": "./dist/providers/openai-legacy.d.mts",
45
- "import": "./dist/providers/openai-legacy.mjs",
46
- "default": "./dist/providers/openai-legacy.mjs"
47
- },
48
38
  "./providers/openai-responses": {
49
39
  "types": "./dist/providers/openai-responses.d.mts",
50
40
  "import": "./dist/providers/openai-responses.mjs",
@@ -1,161 +0,0 @@
1
- import { i as UNKNOWN_CAPABILITY } from "./request-auth-DCWSyCKI.mjs";
2
- //#region src/providers/capability-registry.ts
3
- const OPENAI_RESPONSES_DEVELOPER_ROLE_MODELS = new Set([
4
- "gpt-4.1",
5
- "gpt-4.1-mini",
6
- "gpt-4.1-nano",
7
- "gpt-5-codex",
8
- "o1",
9
- "o1-mini",
10
- "o1-pro",
11
- "o3",
12
- "o3-mini",
13
- "o3-pro",
14
- "o4-mini"
15
- ]);
16
- const OPENAI_VISION_TOOL_PREFIXES = [
17
- "gpt-4o",
18
- "gpt-4-turbo",
19
- "gpt-4.1",
20
- "gpt-4.5"
21
- ];
22
- const CLAUDE_3_PREFIXES = [
23
- "claude-3-",
24
- "claude-3.5-",
25
- "claude-3.7-"
26
- ];
27
- const CLAUDE_4_PREFIXES = [
28
- "claude-opus-4",
29
- "claude-sonnet-4",
30
- "claude-haiku-4"
31
- ];
32
- const GEMINI_CATALOGUED_PREFIXES = [
33
- "gemini-1.5-pro",
34
- "gemini-1.5-flash",
35
- "gemini-2.0-flash",
36
- "gemini-2.0-pro",
37
- "gemini-2.5-pro",
38
- "gemini-2.5-flash"
39
- ];
40
- const OPENAI_REASONING_CAPABILITY = Object.freeze({
41
- image_in: false,
42
- video_in: false,
43
- audio_in: false,
44
- thinking: true,
45
- tool_use: true,
46
- max_context_tokens: 0
47
- });
48
- const OPENAI_VISION_TOOL_CAPABILITY = Object.freeze({
49
- image_in: true,
50
- video_in: false,
51
- audio_in: false,
52
- thinking: false,
53
- tool_use: true,
54
- max_context_tokens: 0
55
- });
56
- const OPENAI_TEXT_TOOL_CAPABILITY = Object.freeze({
57
- image_in: false,
58
- video_in: false,
59
- audio_in: false,
60
- thinking: false,
61
- tool_use: true,
62
- max_context_tokens: 0
63
- });
64
- const ANTHROPIC_VISION_TOOL_CAPABILITY = Object.freeze({
65
- image_in: true,
66
- video_in: false,
67
- audio_in: false,
68
- thinking: false,
69
- tool_use: true,
70
- max_context_tokens: 0
71
- });
72
- const ANTHROPIC_THINKING_VISION_TOOL_CAPABILITY = Object.freeze({
73
- image_in: true,
74
- video_in: false,
75
- audio_in: false,
76
- thinking: true,
77
- tool_use: true,
78
- max_context_tokens: 0
79
- });
80
- const GEMINI_MULTIMODAL_TOOL_CAPABILITY = Object.freeze({
81
- image_in: true,
82
- video_in: true,
83
- audio_in: true,
84
- thinking: false,
85
- tool_use: true,
86
- max_context_tokens: 0
87
- });
88
- const GEMINI_THINKING_MULTIMODAL_TOOL_CAPABILITY = Object.freeze({
89
- image_in: true,
90
- video_in: true,
91
- audio_in: true,
92
- thinking: true,
93
- tool_use: true,
94
- max_context_tokens: 0
95
- });
96
- const OPENAI_LEGACY_CAPABILITY_CATALOG = [
97
- {
98
- matches: isOpenAIReasoningModel,
99
- capability: OPENAI_REASONING_CAPABILITY
100
- },
101
- {
102
- matches: (name) => hasPrefix(name, OPENAI_VISION_TOOL_PREFIXES),
103
- capability: OPENAI_VISION_TOOL_CAPABILITY
104
- },
105
- {
106
- matches: (name) => name.startsWith("gpt-3.5-turbo"),
107
- capability: OPENAI_TEXT_TOOL_CAPABILITY
108
- }
109
- ];
110
- const OPENAI_RESPONSES_CAPABILITY_CATALOG = [{
111
- matches: isOpenAIReasoningModel,
112
- capability: OPENAI_REASONING_CAPABILITY
113
- }, {
114
- matches: (name) => hasPrefix(name, OPENAI_VISION_TOOL_PREFIXES),
115
- capability: OPENAI_VISION_TOOL_CAPABILITY
116
- }];
117
- const ANTHROPIC_CAPABILITY_CATALOG = [{
118
- matches: (name) => hasPrefix(name, CLAUDE_3_PREFIXES),
119
- capability: ANTHROPIC_VISION_TOOL_CAPABILITY
120
- }, {
121
- matches: (name) => hasPrefix(name, CLAUDE_4_PREFIXES),
122
- capability: ANTHROPIC_THINKING_VISION_TOOL_CAPABILITY
123
- }];
124
- function normalizeModelName(modelName) {
125
- return modelName.toLowerCase();
126
- }
127
- function hasPrefix(modelName, prefixes) {
128
- return prefixes.some((prefix) => modelName.startsWith(prefix));
129
- }
130
- function isOpenAIReasoningModel(modelName) {
131
- return /^o\d/.test(modelName);
132
- }
133
- function capabilityFromCatalog(modelName, catalog) {
134
- const normalized = normalizeModelName(modelName);
135
- for (const entry of catalog) if (entry.matches(normalized)) return entry.capability;
136
- return UNKNOWN_CAPABILITY;
137
- }
138
- function getOpenAILegacyModelCapability(modelName) {
139
- return capabilityFromCatalog(modelName, OPENAI_LEGACY_CAPABILITY_CATALOG);
140
- }
141
- function getOpenAIResponsesModelCapability(modelName) {
142
- return capabilityFromCatalog(modelName, OPENAI_RESPONSES_CAPABILITY_CATALOG);
143
- }
144
- function getAnthropicModelCapability(modelName) {
145
- return capabilityFromCatalog(modelName, ANTHROPIC_CAPABILITY_CATALOG);
146
- }
147
- function getGoogleGenAIModelCapability(modelName) {
148
- const normalized = normalizeModelName(modelName);
149
- if (!normalized.startsWith("gemini-")) return UNKNOWN_CAPABILITY;
150
- if (!hasPrefix(normalized, GEMINI_CATALOGUED_PREFIXES)) return UNKNOWN_CAPABILITY;
151
- if (normalized.startsWith("gemini-2.5-") || normalized.includes("thinking")) return GEMINI_THINKING_MULTIMODAL_TOOL_CAPABILITY;
152
- return GEMINI_MULTIMODAL_TOOL_CAPABILITY;
153
- }
154
- function usesOpenAIResponsesDeveloperRole(modelName) {
155
- const normalized = normalizeModelName(modelName);
156
- if (OPENAI_RESPONSES_DEVELOPER_ROLE_MODELS.has(normalized)) return true;
157
- for (const cataloguedModel of OPENAI_RESPONSES_DEVELOPER_ROLE_MODELS) if (normalized.startsWith(cataloguedModel + "-")) return true;
158
- return false;
159
- }
160
- //#endregion
161
- export { usesOpenAIResponsesDeveloperRole as a, getOpenAIResponsesModelCapability as i, getGoogleGenAIModelCapability as n, getOpenAILegacyModelCapability as r, getAnthropicModelCapability as t };
@@ -1,62 +0,0 @@
1
- //#region src/providers/chat-completions-stream.ts
2
- /**
3
- * Convert an OpenAI Chat Completions-style streamed tool-call delta into the
4
- * normalized kosong stream part protocol.
5
- *
6
- * OpenAI-compatible providers may emit argument chunks before the function name
7
- * for a stream index. Buffer those early argument chunks until the first named
8
- * header arrives, then emit subsequent chunks as indexed `tool_call_part`s so
9
- * the shared generate loop can route interleaved parallel calls.
10
- */
11
- function convertChatCompletionStreamToolCall(toolCall, bufferedByIndex) {
12
- if (toolCall.function === void 0 || toolCall.function === null) return [];
13
- const streamIndex = toolCall.index;
14
- const functionName = toolCall.function.name;
15
- const functionArguments = toolCall.function.arguments;
16
- const hasConcreteName = typeof functionName === "string" && functionName.length > 0;
17
- const hasArguments = typeof functionArguments === "string" && functionArguments.length > 0;
18
- if (streamIndex === void 0) {
19
- if (hasConcreteName) return [{
20
- type: "function",
21
- id: toolCall.id ?? crypto.randomUUID(),
22
- name: functionName,
23
- arguments: functionArguments ?? null
24
- }];
25
- if (hasArguments) return [{
26
- type: "tool_call_part",
27
- argumentsPart: functionArguments
28
- }];
29
- return [];
30
- }
31
- const buffered = bufferedByIndex.get(streamIndex) ?? {
32
- arguments: "",
33
- emitted: false
34
- };
35
- if (toolCall.id !== void 0) buffered.id = toolCall.id;
36
- if (!buffered.emitted) {
37
- if (!hasConcreteName) {
38
- if (hasArguments) buffered.arguments += functionArguments;
39
- bufferedByIndex.set(streamIndex, buffered);
40
- return [];
41
- }
42
- buffered.emitted = true;
43
- const initialArguments = buffered.arguments.length > 0 ? buffered.arguments + (functionArguments ?? "") : functionArguments ?? null;
44
- buffered.arguments = "";
45
- bufferedByIndex.set(streamIndex, buffered);
46
- return [{
47
- type: "function",
48
- id: buffered.id ?? toolCall.id ?? crypto.randomUUID(),
49
- name: functionName,
50
- arguments: initialArguments,
51
- _streamIndex: streamIndex
52
- }];
53
- }
54
- if (!hasArguments) return [];
55
- return [{
56
- type: "tool_call_part",
57
- argumentsPart: functionArguments,
58
- index: streamIndex
59
- }];
60
- }
61
- //#endregion
62
- export { convertChatCompletionStreamToolCall as t };
@@ -1,42 +0,0 @@
1
- //#region src/errors.d.ts
2
- /**
3
- * Base error for all chat provider errors.
4
- */
5
- declare class ChatProviderError extends Error {
6
- constructor(message: string);
7
- }
8
- /**
9
- * Network-level connection failure.
10
- */
11
- declare class APIConnectionError extends ChatProviderError {
12
- constructor(message: string);
13
- }
14
- /**
15
- * Request timed out.
16
- */
17
- declare class APITimeoutError extends ChatProviderError {
18
- constructor(message: string);
19
- }
20
- /**
21
- * HTTP status error from the API.
22
- */
23
- declare class APIStatusError extends ChatProviderError {
24
- readonly statusCode: number;
25
- readonly requestId: string | null;
26
- constructor(statusCode: number, message: string, requestId?: string | null);
27
- }
28
- /**
29
- * HTTP status error that specifically means the request exceeded the model
30
- * context window.
31
- */
32
- declare class APIContextOverflowError extends APIStatusError {
33
- constructor(statusCode: number, message: string, requestId?: string | null);
34
- }
35
- /**
36
- * The API returned an empty response (no content, no tool calls).
37
- */
38
- declare class APIEmptyResponseError extends ChatProviderError {
39
- constructor(message: string);
40
- }
41
- //#endregion
42
- export { APITimeoutError as a, APIStatusError as i, APIContextOverflowError as n, ChatProviderError as o, APIEmptyResponseError as r, APIConnectionError as t };