@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,623 @@
1
+ import { c as thinkingEffortToReasoningEffort, n as convertOpenAIError, p as extractText, s as reasoningEffortToThinkingEffort } from "../openai-common-08qin3UI.mjs";
2
+ import { o as ChatProviderError } from "../errors-WFxxzL1B.mjs";
3
+ import { n as requireProviderApiKey, r as resolveAuthBackedClient, t as mergeRequestHeaders } from "../request-auth-DCWSyCKI.mjs";
4
+ import { a as usesOpenAIResponsesDeveloperRole, i as getOpenAIResponsesModelCapability } from "../capability-registry-CMBuEYcf.mjs";
5
+ import OpenAI from "openai";
6
+ //#region src/providers/openai-responses.ts
7
+ /**
8
+ * Normalize the Responses API status / incomplete_details into the unified
9
+ * {@link FinishReason} enum.
10
+ *
11
+ * Note: the Responses API has no `tool_calls`-style status. When a response
12
+ * completes with `function_call` items inline the status is still
13
+ * `'completed'`; callers detect tool calls via `message.toolCalls.length`,
14
+ * not via finishReason.
15
+ */
16
+ function normalizeResponsesFinishReason(status, incompleteReason) {
17
+ if (status === null || status === void 0) return {
18
+ finishReason: null,
19
+ rawFinishReason: null
20
+ };
21
+ if (status === "completed") return {
22
+ finishReason: "completed",
23
+ rawFinishReason: "completed"
24
+ };
25
+ if (status === "incomplete") {
26
+ if (incompleteReason === "max_output_tokens") return {
27
+ finishReason: "truncated",
28
+ rawFinishReason: "max_output_tokens"
29
+ };
30
+ if (incompleteReason === "content_filter") return {
31
+ finishReason: "filtered",
32
+ rawFinishReason: "content_filter"
33
+ };
34
+ return {
35
+ finishReason: "other",
36
+ rawFinishReason: incompleteReason ?? "incomplete"
37
+ };
38
+ }
39
+ if (status === "failed") return {
40
+ finishReason: "other",
41
+ rawFinishReason: "failed"
42
+ };
43
+ return {
44
+ finishReason: null,
45
+ rawFinishReason: null
46
+ };
47
+ }
48
+ function asRawObject(value) {
49
+ if (value === null || typeof value !== "object" || Array.isArray(value)) return null;
50
+ return value;
51
+ }
52
+ function readStringField(object, key) {
53
+ const value = object[key];
54
+ return typeof value === "string" ? value : void 0;
55
+ }
56
+ function readNullableStringField(object, key) {
57
+ const value = object[key];
58
+ if (value === null) return null;
59
+ return typeof value === "string" ? value : void 0;
60
+ }
61
+ function readNumberField(object, key) {
62
+ const value = object[key];
63
+ return typeof value === "number" ? value : void 0;
64
+ }
65
+ function readObjectField(object, key) {
66
+ return asRawObject(object[key]) ?? void 0;
67
+ }
68
+ function readObjectArrayField(object, key) {
69
+ const value = object[key];
70
+ if (!Array.isArray(value)) return void 0;
71
+ return value.flatMap((item) => {
72
+ const objectItem = asRawObject(item);
73
+ return objectItem === null ? [] : [objectItem];
74
+ });
75
+ }
76
+ function failResponsesDecode(context, detail) {
77
+ throw new ChatProviderError(`OpenAI Responses decode error: ${context} ${detail}`);
78
+ }
79
+ function requireStringField(object, key, context) {
80
+ const value = readStringField(object, key);
81
+ if (value === void 0) failResponsesDecode(`${context}.${key}`, "must be a string.");
82
+ return value;
83
+ }
84
+ function requireObjectField(object, key, context) {
85
+ const value = readObjectField(object, key);
86
+ if (value === void 0) failResponsesDecode(`${context}.${key}`, "must be an object.");
87
+ return value;
88
+ }
89
+ function readResponseOutputItem(value, context) {
90
+ const item = asRawObject(value);
91
+ if (item === null) failResponsesDecode(context, "must be an object.");
92
+ const type = requireStringField(item, "type", context);
93
+ if (type === "message") return {
94
+ type,
95
+ content: readObjectArrayField(item, "content") ?? []
96
+ };
97
+ if (type === "function_call") return {
98
+ type,
99
+ itemId: readStringField(item, "id"),
100
+ callId: readStringField(item, "call_id"),
101
+ name: readStringField(item, "name"),
102
+ arguments: readNullableStringField(item, "arguments")
103
+ };
104
+ if (type === "reasoning") return {
105
+ type,
106
+ encryptedContent: readStringField(item, "encrypted_content"),
107
+ summary: readObjectArrayField(item, "summary") ?? []
108
+ };
109
+ return { type: "other" };
110
+ }
111
+ function responseStreamIndex(itemId, outputIndex) {
112
+ return itemId ?? outputIndex;
113
+ }
114
+ function formatResponseStreamIndex(streamIndex) {
115
+ return streamIndex === void 0 ? "<unindexed>" : String(streamIndex);
116
+ }
117
+ function requireFunctionCallName(item) {
118
+ if (item.name === void 0) throw new ChatProviderError("OpenAI Responses function_call item is missing a name.");
119
+ return item.name;
120
+ }
121
+ function functionCallId(callId) {
122
+ return callId === void 0 || callId.length === 0 ? crypto.randomUUID() : callId;
123
+ }
124
+ function formatResponsesErrorEvent(code, message, param) {
125
+ return `${code ?? "unknown"}: ${message}${param === null ? "" : ` (param: ${param})`}`;
126
+ }
127
+ function formatResponsesFailedResponse(response) {
128
+ const error = readObjectField(response, "error");
129
+ if (error !== void 0) return `${readNullableStringField(error, "code") ?? "unknown"}: ${readStringField(error, "message") ?? "no message"}`;
130
+ const incompleteDetails = readObjectField(response, "incomplete_details");
131
+ const reason = incompleteDetails === void 0 ? void 0 : readStringField(incompleteDetails, "reason");
132
+ return reason === void 0 ? "Unknown error (no error details in response)" : `incomplete: ${reason}`;
133
+ }
134
+ function contentPartsToInputItems(parts) {
135
+ const items = [];
136
+ for (const part of parts) switch (part.type) {
137
+ case "text":
138
+ if (part.text) items.push({
139
+ type: "input_text",
140
+ text: part.text
141
+ });
142
+ break;
143
+ case "image_url":
144
+ items.push({
145
+ type: "input_image",
146
+ detail: "auto",
147
+ image_url: part.imageUrl.url
148
+ });
149
+ break;
150
+ case "audio_url": {
151
+ const mapped = mapAudioUrlToInputItem(part.audioUrl.url);
152
+ if (mapped !== null) items.push(mapped);
153
+ break;
154
+ }
155
+ case "think":
156
+ case "video_url": break;
157
+ }
158
+ return items;
159
+ }
160
+ function contentPartsToOutputItems(parts) {
161
+ const items = [];
162
+ for (const part of parts) if (part.type === "text" && part.text) items.push({
163
+ type: "output_text",
164
+ text: part.text,
165
+ annotations: []
166
+ });
167
+ return items;
168
+ }
169
+ function messageContentToFunctionOutputItems(content) {
170
+ const items = [];
171
+ for (const part of content) switch (part.type) {
172
+ case "text":
173
+ if (part.text) items.push({
174
+ type: "input_text",
175
+ text: part.text
176
+ });
177
+ break;
178
+ case "image_url":
179
+ items.push({
180
+ type: "input_image",
181
+ image_url: part.imageUrl.url
182
+ });
183
+ break;
184
+ case "audio_url": {
185
+ const mapped = mapAudioUrlToInputItem(part.audioUrl.url);
186
+ if (mapped !== null) items.push(mapped);
187
+ break;
188
+ }
189
+ case "think":
190
+ case "video_url": break;
191
+ }
192
+ return items;
193
+ }
194
+ function mapAudioUrlToInputItem(url) {
195
+ if (url.startsWith("data:audio/")) try {
196
+ const parts = url.split(",", 2);
197
+ if (parts.length !== 2 || parts[0] === void 0 || parts[1] === void 0) return null;
198
+ const header = parts[0];
199
+ const b64 = parts[1];
200
+ const subtypePart = header.split("/")[1];
201
+ if (subtypePart === void 0) return null;
202
+ const [subtypeHead = ""] = subtypePart.split(";");
203
+ const subtype = subtypeHead.toLowerCase();
204
+ const ext = subtype === "mp3" || subtype === "mpeg" ? "mp3" : subtype === "wav" ? "wav" : null;
205
+ if (ext === null) return null;
206
+ return {
207
+ type: "input_file",
208
+ file_data: b64,
209
+ filename: `inline.${ext}`
210
+ };
211
+ } catch {
212
+ return null;
213
+ }
214
+ if (url.startsWith("http://") || url.startsWith("https://")) return {
215
+ type: "input_file",
216
+ file_url: url
217
+ };
218
+ return null;
219
+ }
220
+ function convertMessage(message, modelName, toolMessageConversion) {
221
+ let role = message.role;
222
+ if (usesOpenAIResponsesDeveloperRole(modelName) && role === "system") role = "developer";
223
+ if (role === "tool") return [{
224
+ call_id: message.toolCallId ?? "",
225
+ output: toolMessageConversion === "extract_text" ? extractText(message) : messageContentToFunctionOutputItems(message.content),
226
+ type: "function_call_output"
227
+ }];
228
+ const result = [];
229
+ if (message.content.length > 0) {
230
+ const pendingParts = [];
231
+ const flushPendingParts = () => {
232
+ if (pendingParts.length === 0) return;
233
+ if (role === "assistant") result.push({
234
+ content: contentPartsToOutputItems(pendingParts),
235
+ role,
236
+ type: "message"
237
+ });
238
+ else result.push({
239
+ content: contentPartsToInputItems(pendingParts),
240
+ role,
241
+ type: "message"
242
+ });
243
+ pendingParts.length = 0;
244
+ };
245
+ let i = 0;
246
+ const n = message.content.length;
247
+ while (i < n) {
248
+ const part = message.content[i];
249
+ if (part === void 0) break;
250
+ if (part.type === "think") {
251
+ flushPendingParts();
252
+ const encryptedValue = part.encrypted;
253
+ const summaries = [{
254
+ type: "summary_text",
255
+ text: part.think || ""
256
+ }];
257
+ i += 1;
258
+ while (i < n) {
259
+ const nextPart = message.content[i];
260
+ if (nextPart === void 0) break;
261
+ if (nextPart.type !== "think") break;
262
+ if (nextPart.encrypted !== encryptedValue) break;
263
+ summaries.push({
264
+ type: "summary_text",
265
+ text: nextPart.think || ""
266
+ });
267
+ i += 1;
268
+ }
269
+ result.push({
270
+ summary: summaries,
271
+ type: "reasoning",
272
+ encrypted_content: encryptedValue
273
+ });
274
+ } else {
275
+ pendingParts.push(part);
276
+ i += 1;
277
+ }
278
+ }
279
+ flushPendingParts();
280
+ }
281
+ for (const toolCall of message.toolCalls) result.push({
282
+ arguments: toolCall.arguments ?? "{}",
283
+ call_id: toolCall.id,
284
+ name: toolCall.name,
285
+ type: "function_call"
286
+ });
287
+ return result;
288
+ }
289
+ function convertTool(tool) {
290
+ return {
291
+ type: "function",
292
+ name: tool.name,
293
+ description: tool.description,
294
+ parameters: tool.parameters,
295
+ strict: false
296
+ };
297
+ }
298
+ var OpenAIResponsesStreamedMessage = class {
299
+ _id = null;
300
+ _usage = null;
301
+ _finishReason = null;
302
+ _rawFinishReason = null;
303
+ _iter;
304
+ constructor(response, isStream) {
305
+ if (isStream) this._iter = this._convertStreamResponse(response);
306
+ else this._iter = this._convertNonStreamResponse(response);
307
+ }
308
+ get id() {
309
+ return this._id;
310
+ }
311
+ get usage() {
312
+ return this._usage;
313
+ }
314
+ get finishReason() {
315
+ return this._finishReason;
316
+ }
317
+ get rawFinishReason() {
318
+ return this._rawFinishReason;
319
+ }
320
+ async *[Symbol.asyncIterator]() {
321
+ yield* this._iter;
322
+ }
323
+ _captureFinishReasonFromResponse(response) {
324
+ const status = readNullableStringField(response, "status");
325
+ const incomplete = readObjectField(response, "incomplete_details");
326
+ const normalized = normalizeResponsesFinishReason(status, incomplete ? readStringField(incomplete, "reason") : null);
327
+ this._finishReason = normalized.finishReason;
328
+ this._rawFinishReason = normalized.rawFinishReason;
329
+ }
330
+ _extractUsage(usage) {
331
+ const inputTokens = readNumberField(usage, "input_tokens") ?? 0;
332
+ const outputTokens = readNumberField(usage, "output_tokens") ?? 0;
333
+ const details = readObjectField(usage, "input_tokens_details");
334
+ const cached = details ? readNumberField(details, "cached_tokens") ?? 0 : 0;
335
+ this._usage = {
336
+ inputOther: inputTokens - cached,
337
+ output: outputTokens,
338
+ inputCacheRead: cached,
339
+ inputCacheCreation: 0
340
+ };
341
+ }
342
+ async *_convertNonStreamResponse(response) {
343
+ this._id = readStringField(response, "id") ?? null;
344
+ const usage = readObjectField(response, "usage");
345
+ if (usage !== void 0) this._extractUsage(usage);
346
+ this._captureFinishReasonFromResponse(response);
347
+ const output = readObjectArrayField(response, "output");
348
+ if (output === void 0) return;
349
+ for (const item of output) {
350
+ const outputItem = readResponseOutputItem(item, "response.output item");
351
+ if (outputItem.type === "message") {
352
+ for (const contentItem of outputItem.content) if (contentItem["type"] === "output_text") {
353
+ const text = readStringField(contentItem, "text");
354
+ if (text !== void 0) yield {
355
+ type: "text",
356
+ text
357
+ };
358
+ }
359
+ } else if (outputItem.type === "function_call") yield {
360
+ type: "function",
361
+ id: functionCallId(outputItem.callId),
362
+ name: requireFunctionCallName(outputItem),
363
+ arguments: outputItem.arguments ?? null
364
+ };
365
+ else if (outputItem.type === "reasoning") for (const summary of outputItem.summary) {
366
+ const text = readStringField(summary, "text");
367
+ if (text === void 0) continue;
368
+ const thinkPart = {
369
+ type: "think",
370
+ think: text
371
+ };
372
+ if (outputItem.encryptedContent !== void 0) thinkPart.encrypted = outputItem.encryptedContent;
373
+ yield thinkPart;
374
+ }
375
+ }
376
+ }
377
+ async *_convertStreamResponse(response) {
378
+ const functionCallArgumentsByIndex = /* @__PURE__ */ new Map();
379
+ let unindexedFunctionCallArguments;
380
+ const hasFunctionCallArguments = (streamIndex) => streamIndex === void 0 ? unindexedFunctionCallArguments !== void 0 : functionCallArgumentsByIndex.has(streamIndex);
381
+ const getFunctionCallArguments = (streamIndex) => streamIndex === void 0 ? unindexedFunctionCallArguments : functionCallArgumentsByIndex.get(streamIndex);
382
+ const setFunctionCallArguments = (streamIndex, argumentsValue) => {
383
+ if (streamIndex === void 0) unindexedFunctionCallArguments = argumentsValue;
384
+ else functionCallArgumentsByIndex.set(streamIndex, argumentsValue);
385
+ };
386
+ const appendFunctionCallArguments = (streamIndex, argumentsPart, context) => {
387
+ if (!hasFunctionCallArguments(streamIndex)) failResponsesDecode(context, `received function-call arguments for unknown stream index ${formatResponseStreamIndex(streamIndex)}.`);
388
+ setFunctionCallArguments(streamIndex, getFunctionCallArguments(streamIndex) + argumentsPart);
389
+ };
390
+ const yieldFinalArgumentsSuffix = function* (streamIndex, finalArguments, context) {
391
+ if (!hasFunctionCallArguments(streamIndex)) failResponsesDecode(context, `received final function-call arguments for unknown stream index ${formatResponseStreamIndex(streamIndex)}.`);
392
+ const accumulatedArguments = getFunctionCallArguments(streamIndex);
393
+ if (finalArguments === accumulatedArguments) return;
394
+ if (!finalArguments.startsWith(accumulatedArguments)) throw new ChatProviderError(`OpenAI Responses final function-call arguments for stream index ${formatResponseStreamIndex(streamIndex)} do not match the streamed argument deltas.`);
395
+ const suffix = finalArguments.slice(accumulatedArguments.length);
396
+ setFunctionCallArguments(streamIndex, finalArguments);
397
+ if (suffix.length === 0) return;
398
+ const part = {
399
+ type: "tool_call_part",
400
+ argumentsPart: suffix
401
+ };
402
+ if (streamIndex !== void 0) part.index = streamIndex;
403
+ yield part;
404
+ };
405
+ try {
406
+ for await (const chunk of response) {
407
+ const type = requireStringField(chunk, "type", "stream event");
408
+ switch (type) {
409
+ case "response.output_text.delta":
410
+ yield {
411
+ type: "text",
412
+ text: requireStringField(chunk, "delta", type)
413
+ };
414
+ break;
415
+ case "response.created":
416
+ case "response.in_progress": {
417
+ const respId = readStringField(requireObjectField(chunk, "response", type), "id");
418
+ if (respId !== void 0) this._id = respId;
419
+ break;
420
+ }
421
+ case "response.output_item.added": {
422
+ const item = readResponseOutputItem(chunk["item"], `${type}.item`);
423
+ const outputIndex = readNumberField(chunk, "output_index");
424
+ if (item.type === "function_call") {
425
+ const streamIndex = responseStreamIndex(item.itemId, outputIndex);
426
+ setFunctionCallArguments(streamIndex, item.arguments ?? "");
427
+ const tc = {
428
+ type: "function",
429
+ id: functionCallId(item.callId),
430
+ name: requireFunctionCallName(item),
431
+ arguments: item.arguments ?? null
432
+ };
433
+ if (streamIndex !== void 0) tc._streamIndex = streamIndex;
434
+ yield tc;
435
+ }
436
+ break;
437
+ }
438
+ case "response.output_item.done": {
439
+ const item = readResponseOutputItem(chunk["item"], `${type}.item`);
440
+ const outputIndex = readNumberField(chunk, "output_index");
441
+ if (item.type === "reasoning") {
442
+ const thinkPart = {
443
+ type: "think",
444
+ think: ""
445
+ };
446
+ if (item.encryptedContent !== void 0) thinkPart.encrypted = item.encryptedContent;
447
+ yield thinkPart;
448
+ } else if (item.type === "function_call" && typeof item.arguments === "string") yield* yieldFinalArgumentsSuffix(responseStreamIndex(item.itemId, outputIndex), item.arguments, type);
449
+ break;
450
+ }
451
+ case "response.function_call_arguments.delta": {
452
+ const streamIndex = responseStreamIndex(readStringField(chunk, "item_id"), readNumberField(chunk, "output_index"));
453
+ const argumentsPart = requireStringField(chunk, "delta", type);
454
+ const part = {
455
+ type: "tool_call_part",
456
+ argumentsPart
457
+ };
458
+ appendFunctionCallArguments(streamIndex, argumentsPart, type);
459
+ if (streamIndex !== void 0) part.index = streamIndex;
460
+ yield part;
461
+ break;
462
+ }
463
+ case "response.function_call_arguments.done": {
464
+ const functionArguments = requireStringField(chunk, "arguments", type);
465
+ yield* yieldFinalArgumentsSuffix(responseStreamIndex(readStringField(chunk, "item_id"), readNumberField(chunk, "output_index")), functionArguments, type);
466
+ break;
467
+ }
468
+ case "response.reasoning_summary_part.added":
469
+ yield {
470
+ type: "think",
471
+ think: ""
472
+ };
473
+ break;
474
+ case "response.reasoning_summary_text.delta":
475
+ yield {
476
+ type: "think",
477
+ think: requireStringField(chunk, "delta", type)
478
+ };
479
+ break;
480
+ case "response.completed":
481
+ case "response.incomplete": {
482
+ const responseObject = requireObjectField(chunk, "response", type);
483
+ const respId = readStringField(responseObject, "id");
484
+ if (respId !== void 0) this._id = respId;
485
+ const usage = readObjectField(responseObject, "usage");
486
+ if (usage !== void 0) this._extractUsage(usage);
487
+ this._captureFinishReasonFromResponse(responseObject);
488
+ break;
489
+ }
490
+ case "error": {
491
+ const message = requireStringField(chunk, "message", type);
492
+ throw new ChatProviderError(`OpenAI Responses stream error: ${formatResponsesErrorEvent(readNullableStringField(chunk, "code") ?? null, message, readNullableStringField(chunk, "param") ?? null)}`);
493
+ }
494
+ case "response.failed": throw new ChatProviderError(`OpenAI Responses response.failed: ${formatResponsesFailedResponse(requireObjectField(chunk, "response", type))}`);
495
+ default: break;
496
+ }
497
+ }
498
+ } catch (error) {
499
+ throw convertOpenAIError(error);
500
+ }
501
+ }
502
+ };
503
+ var OpenAIResponsesChatProvider = class {
504
+ name = "openai-responses";
505
+ _model;
506
+ _stream;
507
+ _apiKey;
508
+ _baseUrl;
509
+ _defaultHeaders;
510
+ _generationKwargs;
511
+ _toolMessageConversion;
512
+ _client;
513
+ _httpClient;
514
+ _clientFactory;
515
+ constructor(options) {
516
+ const apiKey = options.apiKey ?? process.env["OPENAI_API_KEY"];
517
+ this._apiKey = apiKey === void 0 || apiKey.length === 0 ? void 0 : apiKey;
518
+ this._baseUrl = options.baseUrl ?? "https://api.openai.com/v1";
519
+ this._defaultHeaders = options.defaultHeaders;
520
+ this._model = options.model;
521
+ this._stream = true;
522
+ this._generationKwargs = {};
523
+ this._toolMessageConversion = options.toolMessageConversion ?? null;
524
+ this._httpClient = options.httpClient;
525
+ this._clientFactory = options.clientFactory;
526
+ if (options.maxOutputTokens !== void 0) this._generationKwargs.max_output_tokens = options.maxOutputTokens;
527
+ this._client = this._apiKey === void 0 ? void 0 : this._buildClient(this._apiKey);
528
+ }
529
+ get modelName() {
530
+ return this._model;
531
+ }
532
+ get thinkingEffort() {
533
+ return reasoningEffortToThinkingEffort(this._generationKwargs.reasoning_effort);
534
+ }
535
+ get modelParameters() {
536
+ return {
537
+ model: this._model,
538
+ baseUrl: this._baseUrl,
539
+ ...this._generationKwargs
540
+ };
541
+ }
542
+ getCapability(model) {
543
+ return getOpenAIResponsesModelCapability(model ?? this._model);
544
+ }
545
+ async generate(systemPrompt, tools, history, options) {
546
+ const input = [];
547
+ if (systemPrompt) {
548
+ const sysItem = {
549
+ role: "system",
550
+ content: systemPrompt
551
+ };
552
+ if (usesOpenAIResponsesDeveloperRole(this._model)) sysItem["role"] = "developer";
553
+ input.push(sysItem);
554
+ }
555
+ for (const msg of history) input.push(...convertMessage(msg, this._model, this._toolMessageConversion));
556
+ const kwargs = { ...this._generationKwargs };
557
+ const reasoningEffort = kwargs["reasoning_effort"];
558
+ delete kwargs["reasoning_effort"];
559
+ if (reasoningEffort !== void 0) {
560
+ kwargs["reasoning"] = {
561
+ effort: reasoningEffort,
562
+ summary: "auto"
563
+ };
564
+ kwargs["include"] = ["reasoning.encrypted_content"];
565
+ }
566
+ for (const key of Object.keys(kwargs)) if (kwargs[key] === void 0) delete kwargs[key];
567
+ try {
568
+ const client = this._createClient(options?.auth);
569
+ const createParams = {
570
+ model: this._model,
571
+ input,
572
+ tools: tools.map((t) => convertTool(t)),
573
+ store: false,
574
+ stream: this._stream,
575
+ ...kwargs
576
+ };
577
+ if (!("responses" in client) || typeof client.responses?.create !== "function") throw new Error("OpenAI SDK version does not support Responses API. Upgrade to >=4.x with responses support.");
578
+ return new OpenAIResponsesStreamedMessage(await client.responses.create(createParams, options?.signal ? { signal: options.signal } : void 0), this._stream);
579
+ } catch (error) {
580
+ throw convertOpenAIError(error);
581
+ }
582
+ }
583
+ withThinking(effort) {
584
+ const reasoningEffort = thinkingEffortToReasoningEffort(effort);
585
+ const clone = this._clone();
586
+ clone._generationKwargs = {
587
+ ...clone._generationKwargs,
588
+ reasoning_effort: reasoningEffort
589
+ };
590
+ return clone;
591
+ }
592
+ withGenerationKwargs(kwargs) {
593
+ const clone = this._clone();
594
+ clone._generationKwargs = {
595
+ ...clone._generationKwargs,
596
+ ...kwargs
597
+ };
598
+ return clone;
599
+ }
600
+ _clone() {
601
+ const clone = Object.assign(Object.create(Object.getPrototypeOf(this)), this);
602
+ clone._generationKwargs = { ...this._generationKwargs };
603
+ return clone;
604
+ }
605
+ _createClient(auth) {
606
+ return resolveAuthBackedClient({
607
+ cachedClient: this._client,
608
+ clientFactory: this._clientFactory
609
+ }, auth, (a) => this._buildClient(requireProviderApiKey("OpenAIResponsesChatProvider", a, this._apiKey), a));
610
+ }
611
+ _buildClient(apiKey, auth) {
612
+ const clientOpts = {
613
+ apiKey,
614
+ baseURL: this._baseUrl
615
+ };
616
+ const defaultHeaders = mergeRequestHeaders(this._defaultHeaders, auth?.headers);
617
+ if (defaultHeaders !== void 0) clientOpts["defaultHeaders"] = defaultHeaders;
618
+ if (this._httpClient !== void 0) clientOpts["httpClient"] = this._httpClient;
619
+ return new OpenAI(clientOpts);
620
+ }
621
+ };
622
+ //#endregion
623
+ export { OpenAIResponsesChatProvider, OpenAIResponsesStreamedMessage };
@@ -0,0 +1,63 @@
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
+ max_context_tokens: 0
16
+ }, UNKNOWN_CAPABILITY_MARKER, { value: true }));
17
+ function isUnknownCapability(capability) {
18
+ if (capability === UNKNOWN_CAPABILITY) return true;
19
+ if (capability[UNKNOWN_CAPABILITY_MARKER] === true) return true;
20
+ return !capability.image_in && !capability.video_in && !capability.audio_in && !capability.thinking && !capability.tool_use && capability.max_context_tokens === 0;
21
+ }
22
+ //#endregion
23
+ //#region src/providers/request-auth.ts
24
+ function requireProviderApiKey(providerName, auth, defaultApiKey) {
25
+ const apiKey = auth?.apiKey ?? defaultApiKey;
26
+ 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.`);
27
+ return apiKey;
28
+ }
29
+ function mergeRequestHeaders(defaultHeaders, requestHeaders) {
30
+ const merged = {};
31
+ if (defaultHeaders !== void 0) Object.assign(merged, defaultHeaders);
32
+ if (requestHeaders !== void 0) Object.assign(merged, requestHeaders);
33
+ return Object.keys(merged).length > 0 ? merged : void 0;
34
+ }
35
+ /**
36
+ * Resolve the SDK client to use for a single provider request, applying the
37
+ * standard precedence shared by every provider adapter:
38
+ *
39
+ * 1. If a `clientFactory` was supplied, delegate to it (it receives the
40
+ * per-request {@link ProviderRequestAuth}, defaulting to `{}`).
41
+ * 2. Otherwise, if no per-request auth is needed AND a constructor-time
42
+ * client was cached, reuse the cached instance.
43
+ * 3. Otherwise, call `build(auth)` to construct a fresh client for this
44
+ * request — typically using `requireProviderApiKey` plus
45
+ * `mergeRequestHeaders`.
46
+ *
47
+ * Note: when per-request `auth` is provided (e.g. an OAuth bearer token
48
+ * resolved immediately before each call), step 3 fires and a brand-new SDK
49
+ * client is constructed per request. This is intentional — it keeps short-lived
50
+ * credentials out of any long-lived shared state and avoids racing concurrent
51
+ * requests on a mutable client. The trade-off is that connection-pool / keep-
52
+ * alive state inside the SDK client isn't reused across requests on the OAuth
53
+ * path. For the current agent-CLI workload (one LLM call per turn step) this
54
+ * is fine; if a future host needs high-throughput per-request auth, the
55
+ * obvious optimization is a small LRU keyed on `(apiKey, headers digest)`.
56
+ */
57
+ function resolveAuthBackedClient(state, auth, build) {
58
+ if (state.clientFactory !== void 0) return state.clientFactory(auth ?? {});
59
+ if (auth === void 0 && state.cachedClient !== void 0) return state.cachedClient;
60
+ return build(auth);
61
+ }
62
+ //#endregion
63
+ export { isUnknownCapability as a, UNKNOWN_CAPABILITY as i, requireProviderApiKey as n, resolveAuthBackedClient as r, mergeRequestHeaders as t };