@byfriends/kosong 0.1.0 → 0.2.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.
- package/dist/{anthropic-Dm_GqFgS.d.mts → anthropic-0CVG5rBE.d.mts} +1 -2
- package/dist/{provider-DiJKWMsQ.d.mts → errors-wlT14tC4.d.mts} +227 -2
- package/dist/{google-genai-hX0X6CF3.d.mts → google-genai-xKK8lI_R.d.mts} +1 -2
- package/dist/index.d.mts +66 -12
- package/dist/index.mjs +945 -21
- package/dist/{openai-common-08qin3UI.mjs → openai-common-Dl42y_vn.mjs} +27 -2
- package/dist/{openai-common-B6cK2ig3.d.mts → openai-common-DwkxUSyI.d.mts} +7 -3
- package/dist/{openai-responses-BxOwxtd3.d.mts → openai-responses-DZ9mQ5RA.d.mts} +2 -2
- package/dist/providers/anthropic.d.mts +1 -1
- package/dist/providers/anthropic.mjs +56 -68
- package/dist/providers/google-genai.d.mts +1 -1
- package/dist/providers/google-genai.mjs +1 -2
- package/dist/providers/openai-common.d.mts +1 -1
- package/dist/providers/openai-common.mjs +1 -1
- package/dist/providers/openai-responses.d.mts +1 -1
- package/dist/providers/openai-responses.mjs +21 -4
- package/dist/request-auth-BMXt8jRu.mjs +341 -0
- package/package.json +1 -11
- package/dist/capability-registry-CMBuEYcf.mjs +0 -161
- package/dist/chat-completions-stream-BuMu_xr9.mjs +0 -62
- package/dist/errors-DweKbIOf.d.mts +0 -42
- package/dist/openai-compat-CMrIk-ib.d.mts +0 -132
- package/dist/openai-compat-CWbwO4b7.mjs +0 -801
- package/dist/openai-legacy-B6CVfLlr.d.mts +0 -71
- package/dist/providers/openai-compat.d.mts +0 -2
- package/dist/providers/openai-compat.mjs +0 -2
- package/dist/providers/openai-legacy.d.mts +0 -2
- package/dist/providers/openai-legacy.mjs +0 -248
- 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.
|
|
3
|
+
"version": "0.2.0",
|
|
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 };
|