@yourgpt/llm-sdk 2.1.8 → 2.1.10-alpha.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.
Files changed (51) hide show
  1. package/dist/adapters/index.d.mts +38 -4
  2. package/dist/adapters/index.d.ts +38 -4
  3. package/dist/adapters/index.js +318 -8
  4. package/dist/adapters/index.mjs +318 -8
  5. package/dist/{base-iGi9Va6Z.d.ts → base-DN1EfKnE.d.mts} +2 -1
  6. package/dist/{base-D-U61JaB.d.mts → base-DuUNxtVg.d.ts} +2 -1
  7. package/dist/fallback/index.d.mts +4 -4
  8. package/dist/fallback/index.d.ts +4 -4
  9. package/dist/index.d.mts +7 -7
  10. package/dist/index.d.ts +7 -7
  11. package/dist/index.js +43 -23
  12. package/dist/index.mjs +43 -23
  13. package/dist/providers/anthropic/index.d.mts +3 -3
  14. package/dist/providers/anthropic/index.d.ts +3 -3
  15. package/dist/providers/anthropic/index.js +17 -0
  16. package/dist/providers/anthropic/index.mjs +17 -0
  17. package/dist/providers/azure/index.d.mts +3 -3
  18. package/dist/providers/azure/index.d.ts +3 -3
  19. package/dist/providers/fireworks/index.d.mts +1 -1
  20. package/dist/providers/fireworks/index.d.ts +1 -1
  21. package/dist/providers/google/index.d.mts +3 -3
  22. package/dist/providers/google/index.d.ts +3 -3
  23. package/dist/providers/google/index.js +311 -8
  24. package/dist/providers/google/index.mjs +311 -8
  25. package/dist/providers/ollama/index.d.mts +4 -4
  26. package/dist/providers/ollama/index.d.ts +4 -4
  27. package/dist/providers/openai/index.d.mts +3 -3
  28. package/dist/providers/openai/index.d.ts +3 -3
  29. package/dist/providers/openai/index.js +321 -8
  30. package/dist/providers/openai/index.mjs +321 -8
  31. package/dist/providers/openrouter/index.d.mts +7 -3
  32. package/dist/providers/openrouter/index.d.ts +7 -3
  33. package/dist/providers/openrouter/index.js +601 -11
  34. package/dist/providers/openrouter/index.mjs +601 -11
  35. package/dist/providers/togetherai/index.d.mts +61 -2
  36. package/dist/providers/togetherai/index.d.ts +61 -2
  37. package/dist/providers/togetherai/index.js +1030 -2
  38. package/dist/providers/togetherai/index.mjs +1029 -2
  39. package/dist/providers/xai/index.d.mts +3 -3
  40. package/dist/providers/xai/index.d.ts +3 -3
  41. package/dist/providers/xai/index.js +311 -8
  42. package/dist/providers/xai/index.mjs +311 -8
  43. package/dist/{types-D4YfrQJR.d.mts → types-BNCmlJMs.d.mts} +1 -1
  44. package/dist/{types-DRqxMIjF.d.mts → types-CMMQ8s2O.d.mts} +1 -1
  45. package/dist/{types-CR8mi9I0.d.ts → types-CMvvDo-E.d.mts} +12 -1
  46. package/dist/{types-CR8mi9I0.d.mts → types-CMvvDo-E.d.ts} +12 -1
  47. package/dist/{types-BctsnC3g.d.ts → types-DhktekQ3.d.ts} +1 -1
  48. package/dist/{types-38yolWJn.d.ts → types-Pj-vpmoT.d.ts} +1 -1
  49. package/dist/yourgpt/index.d.mts +1 -1
  50. package/dist/yourgpt/index.d.ts +1 -1
  51. package/package.json +1 -1
@@ -23,7 +23,12 @@ function togetherai(modelId, options = {}) {
23
23
  supportsThinking: false,
24
24
  supportsPDF: false,
25
25
  maxTokens: 131072,
26
- supportedImageTypes: ["image/png", "image/jpeg", "image/gif", "image/webp"]
26
+ supportedImageTypes: [
27
+ "image/png",
28
+ "image/jpeg",
29
+ "image/gif",
30
+ "image/webp"
31
+ ]
27
32
  },
28
33
  async doGenerate(params) {
29
34
  const client2 = await getClient();
@@ -199,7 +204,1030 @@ function formatMessages(messages) {
199
204
  });
200
205
  }
201
206
 
202
- exports.createTogetherAI = togetherai;
207
+ // src/core/utils.ts
208
+ function generateId(prefix = "id") {
209
+ return `${prefix}_${Date.now()}_${Math.random().toString(36).substring(2, 9)}`;
210
+ }
211
+ function generateMessageId() {
212
+ return generateId("msg");
213
+ }
214
+ function generateToolCallId() {
215
+ return generateId("call");
216
+ }
217
+
218
+ // src/adapters/base.ts
219
+ function stringifyForDebug(value) {
220
+ return JSON.stringify(
221
+ value,
222
+ (_key, currentValue) => {
223
+ if (typeof currentValue === "bigint") {
224
+ return currentValue.toString();
225
+ }
226
+ if (currentValue instanceof Error) {
227
+ return {
228
+ name: currentValue.name,
229
+ message: currentValue.message,
230
+ stack: currentValue.stack
231
+ };
232
+ }
233
+ return currentValue;
234
+ },
235
+ 2
236
+ );
237
+ }
238
+ function logProviderPayload(provider, label, payload, enabled) {
239
+ if (!enabled) {
240
+ return;
241
+ }
242
+ if (label.toLowerCase().includes("stream ")) {
243
+ return;
244
+ }
245
+ try {
246
+ console.log(
247
+ `[llm-sdk:${provider}] ${label}
248
+ ${stringifyForDebug(payload)}`
249
+ );
250
+ } catch (error) {
251
+ console.log(
252
+ `[llm-sdk:${provider}] ${label} (failed to stringify payload)`,
253
+ error
254
+ );
255
+ }
256
+ }
257
+ function parameterToJsonSchema(param) {
258
+ const schema = {
259
+ type: param.type
260
+ };
261
+ if (param.description) {
262
+ schema.description = param.description;
263
+ }
264
+ if (param.enum) {
265
+ schema.enum = param.enum;
266
+ }
267
+ if (param.type === "array" && param.items) {
268
+ schema.items = parameterToJsonSchema(
269
+ param.items
270
+ );
271
+ }
272
+ if (param.type === "object" && param.properties) {
273
+ schema.properties = Object.fromEntries(
274
+ Object.entries(param.properties).map(([key, prop]) => [
275
+ key,
276
+ parameterToJsonSchema(
277
+ prop
278
+ )
279
+ ])
280
+ );
281
+ schema.additionalProperties = false;
282
+ }
283
+ return schema;
284
+ }
285
+ function normalizeObjectJsonSchema(schema) {
286
+ if (!schema || typeof schema !== "object") {
287
+ return {
288
+ type: "object",
289
+ properties: {},
290
+ required: [],
291
+ additionalProperties: false
292
+ };
293
+ }
294
+ const normalized = { ...schema };
295
+ const type = normalized.type;
296
+ if (type === "object") {
297
+ const properties = normalized.properties && typeof normalized.properties === "object" && !Array.isArray(normalized.properties) ? normalized.properties : {};
298
+ normalized.properties = Object.fromEntries(
299
+ Object.entries(properties).map(([key, value]) => [
300
+ key,
301
+ normalizeObjectJsonSchema(value)
302
+ ])
303
+ );
304
+ const propertyKeys = Object.keys(properties);
305
+ const required = Array.isArray(normalized.required) ? normalized.required.filter(
306
+ (value) => typeof value === "string"
307
+ ) : [];
308
+ normalized.required = Array.from(/* @__PURE__ */ new Set([...required, ...propertyKeys]));
309
+ if (normalized.additionalProperties === void 0) {
310
+ normalized.additionalProperties = false;
311
+ }
312
+ } else if (type === "array" && normalized.items && typeof normalized.items === "object") {
313
+ normalized.items = normalizeObjectJsonSchema(
314
+ normalized.items
315
+ );
316
+ }
317
+ return normalized;
318
+ }
319
+ function formatTools(actions) {
320
+ return actions.map((action) => ({
321
+ type: "function",
322
+ function: {
323
+ name: action.name,
324
+ description: action.description,
325
+ parameters: {
326
+ type: "object",
327
+ properties: action.parameters ? Object.fromEntries(
328
+ Object.entries(action.parameters).map(([key, param]) => [
329
+ key,
330
+ parameterToJsonSchema(param)
331
+ ])
332
+ ) : {},
333
+ required: action.parameters ? Object.entries(action.parameters).filter(([, param]) => param.required).map(([key]) => key) : [],
334
+ additionalProperties: false
335
+ }
336
+ }
337
+ }));
338
+ }
339
+ function hasImageAttachments(message) {
340
+ const attachments = message.metadata?.attachments;
341
+ return attachments?.some((a) => a.type === "image") ?? false;
342
+ }
343
+ function attachmentToOpenAIImage(attachment) {
344
+ if (attachment.type !== "image") return null;
345
+ let imageUrl;
346
+ if (attachment.url) {
347
+ imageUrl = attachment.url;
348
+ } else if (attachment.data) {
349
+ imageUrl = attachment.data.startsWith("data:") ? attachment.data : `data:${attachment.mimeType || "image/png"};base64,${attachment.data}`;
350
+ } else {
351
+ return null;
352
+ }
353
+ return {
354
+ type: "image_url",
355
+ image_url: {
356
+ url: imageUrl,
357
+ detail: "auto"
358
+ }
359
+ };
360
+ }
361
+ function messageToOpenAIContent(message) {
362
+ const attachments = message.metadata?.attachments;
363
+ const content = message.content ?? "";
364
+ if (!hasImageAttachments(message)) {
365
+ return content;
366
+ }
367
+ const blocks = [];
368
+ if (content) {
369
+ blocks.push({ type: "text", text: content });
370
+ }
371
+ if (attachments) {
372
+ for (const attachment of attachments) {
373
+ const imageBlock = attachmentToOpenAIImage(attachment);
374
+ if (imageBlock) {
375
+ blocks.push(imageBlock);
376
+ }
377
+ }
378
+ }
379
+ return blocks;
380
+ }
381
+ function formatMessagesForOpenAI(messages, systemPrompt) {
382
+ const formatted = [];
383
+ if (systemPrompt) {
384
+ formatted.push({ role: "system", content: systemPrompt });
385
+ }
386
+ for (const msg of messages) {
387
+ if (msg.role === "system") {
388
+ formatted.push({ role: "system", content: msg.content ?? "" });
389
+ } else if (msg.role === "user") {
390
+ formatted.push({
391
+ role: "user",
392
+ content: messageToOpenAIContent(msg)
393
+ });
394
+ } else if (msg.role === "assistant") {
395
+ const hasToolCalls = msg.tool_calls && msg.tool_calls.length > 0;
396
+ const assistantMsg = {
397
+ role: "assistant",
398
+ // Gemini/xAI (OpenAI-compatible) reject content: "" on assistant messages with tool_calls
399
+ content: hasToolCalls ? msg.content || null : msg.content
400
+ };
401
+ if (hasToolCalls) {
402
+ assistantMsg.tool_calls = msg.tool_calls;
403
+ }
404
+ formatted.push(assistantMsg);
405
+ } else if (msg.role === "tool" && msg.tool_call_id) {
406
+ formatted.push({
407
+ role: "tool",
408
+ content: msg.content ?? "",
409
+ tool_call_id: msg.tool_call_id
410
+ });
411
+ }
412
+ }
413
+ return formatted;
414
+ }
415
+
416
+ // src/adapters/openai.ts
417
+ var OpenAIAdapter = class _OpenAIAdapter {
418
+ constructor(config) {
419
+ this.config = config;
420
+ this.model = config.model || "gpt-4o";
421
+ this.provider = _OpenAIAdapter.resolveProviderName(config.baseUrl);
422
+ }
423
+ static resolveProviderName(baseUrl) {
424
+ if (!baseUrl) return "openai";
425
+ if (baseUrl.includes("generativelanguage.googleapis.com")) return "google";
426
+ if (baseUrl.includes("x.ai")) return "xai";
427
+ if (baseUrl.includes("azure")) return "azure";
428
+ if (baseUrl.includes("openrouter.ai")) return "openrouter";
429
+ return "openai";
430
+ }
431
+ async getClient() {
432
+ if (!this.client) {
433
+ const { default: OpenAI } = await import('openai');
434
+ this.client = new OpenAI({
435
+ apiKey: this.config.apiKey,
436
+ baseURL: this.config.baseUrl
437
+ });
438
+ }
439
+ return this.client;
440
+ }
441
+ shouldUseResponsesApi(request) {
442
+ return request.providerToolOptions?.openai?.nativeToolSearch?.enabled === true && request.providerToolOptions.openai.nativeToolSearch.useResponsesApi !== false && Array.isArray(request.toolDefinitions) && request.toolDefinitions.length > 0;
443
+ }
444
+ buildResponsesInput(request) {
445
+ const sourceMessages = request.rawMessages && request.rawMessages.length > 0 ? request.rawMessages : formatMessagesForOpenAI(request.messages, void 0);
446
+ const input = [];
447
+ for (const message of sourceMessages) {
448
+ if (message.role === "system") {
449
+ continue;
450
+ }
451
+ if (message.role === "assistant") {
452
+ const content = typeof message.content === "string" ? message.content : Array.isArray(message.content) ? message.content : message.content ? JSON.stringify(message.content) : "";
453
+ if (content) {
454
+ input.push({
455
+ type: "message",
456
+ role: "assistant",
457
+ content
458
+ });
459
+ }
460
+ const toolCalls = Array.isArray(message.tool_calls) ? message.tool_calls : [];
461
+ for (const toolCall of toolCalls) {
462
+ input.push({
463
+ type: "function_call",
464
+ call_id: toolCall.id,
465
+ name: toolCall.function?.name,
466
+ arguments: toolCall.function?.arguments ?? "{}"
467
+ });
468
+ }
469
+ continue;
470
+ }
471
+ if (message.role === "tool") {
472
+ input.push({
473
+ type: "function_call_output",
474
+ call_id: message.tool_call_id,
475
+ output: typeof message.content === "string" ? message.content : JSON.stringify(message.content ?? null)
476
+ });
477
+ continue;
478
+ }
479
+ input.push({
480
+ type: "message",
481
+ role: message.role === "developer" ? "developer" : "user",
482
+ content: typeof message.content === "string" ? message.content : Array.isArray(message.content) ? message.content : JSON.stringify(message.content ?? "")
483
+ });
484
+ }
485
+ return input;
486
+ }
487
+ buildResponsesTools(tools) {
488
+ const nativeTools = tools.filter((tool) => tool.available !== false).map((tool) => ({
489
+ type: "function",
490
+ name: tool.name,
491
+ description: tool.description,
492
+ parameters: normalizeObjectJsonSchema(
493
+ tool.inputSchema ?? {
494
+ type: "object",
495
+ properties: {},
496
+ required: []
497
+ }
498
+ ),
499
+ strict: true,
500
+ defer_loading: tool.deferLoading === true
501
+ }));
502
+ return [{ type: "tool_search" }, ...nativeTools];
503
+ }
504
+ parseResponsesResult(response) {
505
+ const content = typeof response?.output_text === "string" ? response.output_text : "";
506
+ const toolCalls = Array.isArray(response?.output) ? response.output.filter((item) => item?.type === "function_call").map((item) => ({
507
+ id: item.call_id ?? item.id ?? generateToolCallId(),
508
+ name: item.name,
509
+ args: (() => {
510
+ try {
511
+ return JSON.parse(item.arguments ?? "{}");
512
+ } catch {
513
+ return {};
514
+ }
515
+ })()
516
+ })) : [];
517
+ return {
518
+ content,
519
+ toolCalls,
520
+ usage: response?.usage ? {
521
+ promptTokens: response.usage.input_tokens ?? 0,
522
+ completionTokens: response.usage.output_tokens ?? 0,
523
+ totalTokens: response.usage.total_tokens ?? (response.usage.input_tokens ?? 0) + (response.usage.output_tokens ?? 0)
524
+ } : void 0,
525
+ rawResponse: response
526
+ };
527
+ }
528
+ /**
529
+ * OpenAI reasoning models on OpenRouter (o1/o3/o4/gpt-5 family) hide their
530
+ * reasoning content on the chat-completions endpoint. To surface reasoning
531
+ * SUMMARIES (not raw CoT, which OpenAI never exposes) we have to use the
532
+ * Responses API, which streams `response.reasoning_summary_text.delta` events.
533
+ *
534
+ * Match by prefix on the OpenRouter model id. Excludes openai/gpt-4o,
535
+ * openai/gpt-4.1, openai/chatgpt-* — those continue on chat-completions.
536
+ */
537
+ isOpenAIReasoningModelOnOpenRouter(activeModel) {
538
+ if (this.provider !== "openrouter") return false;
539
+ return activeModel.startsWith("openai/o1") || activeModel.startsWith("openai/o3") || activeModel.startsWith("openai/o4") || activeModel.startsWith("openai/gpt-5");
540
+ }
541
+ /**
542
+ * Convert ActionDefinition[] (the chat-completions tool shape used by the
543
+ * adapter) to the Responses API tool shape.
544
+ */
545
+ buildResponsesToolsFromActions(actions) {
546
+ if (!actions || actions.length === 0) return void 0;
547
+ const formatted = formatTools(actions);
548
+ return formatted.map((t) => ({
549
+ type: "function",
550
+ name: t.function.name,
551
+ description: t.function.description,
552
+ parameters: t.function.parameters
553
+ }));
554
+ }
555
+ /**
556
+ * Streaming Responses API path for OpenAI reasoning models on OpenRouter.
557
+ *
558
+ * Maps Responses API SSE events back to the same StreamEvent shapes the
559
+ * chat-completions path emits, so downstream consumers (processChunk.ts,
560
+ * frontend tool handlers, plan approval, specialist delegations) see
561
+ * identical events regardless of which path produced them.
562
+ *
563
+ * response.reasoning_summary_text.delta → thinking:start (once) + thinking:delta
564
+ * response.output_text.delta → message:delta
565
+ * response.output_item.added (function_call) → action:start (queued buffer)
566
+ * response.function_call_arguments.delta → action:args (progressive)
567
+ * response.output_item.done (function_call) → final action:args + action:end
568
+ * response.completed → message:end + done(usage)
569
+ * response.error → error
570
+ */
571
+ async *streamWithResponsesAPI(request, activeModel, messageId) {
572
+ const client = await this.getClient();
573
+ const maxTokensValue = request.config?.maxTokens ?? this.config.maxTokens;
574
+ const payload = {
575
+ model: activeModel,
576
+ input: this.buildResponsesInput(request),
577
+ stream: true,
578
+ reasoning: {
579
+ effort: request.config?.reasoningEffort ?? "medium",
580
+ summary: "auto"
581
+ }
582
+ };
583
+ if (request.systemPrompt) payload.instructions = request.systemPrompt;
584
+ if (typeof maxTokensValue === "number")
585
+ payload.max_output_tokens = maxTokensValue;
586
+ const tools = this.buildResponsesToolsFromActions(request.actions);
587
+ if (tools && tools.length > 0) payload.tools = tools;
588
+ logProviderPayload(
589
+ "openai",
590
+ "responses-api request payload",
591
+ payload,
592
+ request.debug
593
+ );
594
+ let stream;
595
+ try {
596
+ stream = await client.responses.create(payload);
597
+ } catch (error) {
598
+ yield {
599
+ type: "error",
600
+ message: error instanceof Error ? error.message : "Unknown error",
601
+ code: "OPENAI_RESPONSES_ERROR"
602
+ };
603
+ return;
604
+ }
605
+ const toolBuffers = /* @__PURE__ */ new Map();
606
+ const itemIdToCallId = /* @__PURE__ */ new Map();
607
+ let usage;
608
+ let reasoningStarted = false;
609
+ let textStarted = false;
610
+ let finishEmitted = false;
611
+ const resolveCallId = (evt) => {
612
+ if (evt?.call_id) return evt.call_id;
613
+ if (evt?.item_id) return itemIdToCallId.get(evt.item_id) ?? evt.item_id;
614
+ if (evt?.item?.call_id) return evt.item.call_id;
615
+ if (evt?.item?.id) return evt.item.id;
616
+ return "";
617
+ };
618
+ try {
619
+ for await (const evt of stream) {
620
+ logProviderPayload(
621
+ "openai",
622
+ "responses-api stream chunk",
623
+ evt,
624
+ request.debug
625
+ );
626
+ if (request.signal?.aborted) break;
627
+ const t = evt?.type ?? "";
628
+ if (t === "response.reasoning_summary_text.delta") {
629
+ const delta = evt.delta ?? "";
630
+ if (!delta) continue;
631
+ if (!reasoningStarted) {
632
+ yield { type: "thinking:start" };
633
+ reasoningStarted = true;
634
+ }
635
+ yield { type: "thinking:delta", content: delta };
636
+ continue;
637
+ }
638
+ if (t === "response.reasoning_summary_text.done" || t === "response.reasoning.done") {
639
+ continue;
640
+ }
641
+ if (t === "response.output_text.delta") {
642
+ const text = evt.delta ?? "";
643
+ if (!text) continue;
644
+ if (reasoningStarted && !textStarted) {
645
+ yield { type: "thinking:end" };
646
+ textStarted = true;
647
+ }
648
+ yield { type: "message:delta", content: text };
649
+ continue;
650
+ }
651
+ if (t === "response.output_item.added") {
652
+ const item = evt.item;
653
+ if (item?.type === "function_call") {
654
+ const callId = item.call_id ?? item.id ?? "";
655
+ const itemId = item.id ?? callId;
656
+ if (callId) {
657
+ if (itemId && itemId !== callId) {
658
+ itemIdToCallId.set(itemId, callId);
659
+ }
660
+ if (!toolBuffers.has(callId)) {
661
+ toolBuffers.set(callId, {
662
+ id: callId,
663
+ name: item.name ?? "",
664
+ arguments: item.arguments ?? "",
665
+ emittedStart: false
666
+ });
667
+ }
668
+ const buf = toolBuffers.get(callId);
669
+ if (buf.name && !buf.emittedStart) {
670
+ yield { type: "action:start", id: buf.id, name: buf.name };
671
+ buf.emittedStart = true;
672
+ }
673
+ }
674
+ }
675
+ continue;
676
+ }
677
+ if (t === "response.function_call_arguments.delta") {
678
+ const callId = resolveCallId(evt);
679
+ const delta = evt.delta ?? "";
680
+ if (!callId || !delta) continue;
681
+ let buf = toolBuffers.get(callId);
682
+ if (!buf) {
683
+ buf = { id: callId, name: "", arguments: "", emittedStart: false };
684
+ toolBuffers.set(callId, buf);
685
+ }
686
+ buf.arguments += delta;
687
+ if (buf.emittedStart) {
688
+ yield {
689
+ type: "action:args",
690
+ id: buf.id,
691
+ args: buf.arguments
692
+ };
693
+ }
694
+ continue;
695
+ }
696
+ if (t === "response.output_item.done") {
697
+ const item = evt.item;
698
+ if (item?.type === "function_call") {
699
+ const callId = item.call_id ?? item.id ?? "";
700
+ const buf = toolBuffers.get(callId);
701
+ const name = buf?.name || item.name || "";
702
+ const argsStr = buf?.arguments || item.arguments || "{}";
703
+ if (callId && name) {
704
+ if (!buf?.emittedStart) {
705
+ yield { type: "action:start", id: callId, name };
706
+ }
707
+ yield {
708
+ type: "action:args",
709
+ id: callId,
710
+ args: argsStr
711
+ };
712
+ yield {
713
+ type: "action:end",
714
+ id: callId,
715
+ name
716
+ };
717
+ }
718
+ toolBuffers.delete(callId);
719
+ }
720
+ continue;
721
+ }
722
+ if (t === "response.completed") {
723
+ const u = evt.response?.usage;
724
+ if (u) {
725
+ usage = {
726
+ prompt_tokens: u.input_tokens ?? 0,
727
+ completion_tokens: u.output_tokens ?? 0,
728
+ total_tokens: u.total_tokens ?? (u.input_tokens ?? 0) + (u.output_tokens ?? 0)
729
+ };
730
+ }
731
+ for (const buf of toolBuffers.values()) {
732
+ if (!buf.id || !buf.name) continue;
733
+ if (!buf.emittedStart) {
734
+ yield { type: "action:start", id: buf.id, name: buf.name };
735
+ }
736
+ yield {
737
+ type: "action:args",
738
+ id: buf.id,
739
+ args: buf.arguments || "{}"
740
+ };
741
+ yield { type: "action:end", id: buf.id, name: buf.name };
742
+ }
743
+ toolBuffers.clear();
744
+ if (reasoningStarted && !textStarted) {
745
+ yield { type: "thinking:end" };
746
+ }
747
+ yield { type: "message:end" };
748
+ yield { type: "done", usage };
749
+ finishEmitted = true;
750
+ continue;
751
+ }
752
+ if (t === "response.error" || t === "error") {
753
+ const msg = evt.error?.message || evt.message || "Responses API error";
754
+ yield {
755
+ type: "error",
756
+ message: msg,
757
+ code: "OPENAI_RESPONSES_ERROR"
758
+ };
759
+ return;
760
+ }
761
+ }
762
+ } catch (error) {
763
+ yield {
764
+ type: "error",
765
+ message: error instanceof Error ? error.message : "Unknown error",
766
+ code: "OPENAI_RESPONSES_ERROR"
767
+ };
768
+ return;
769
+ }
770
+ if (!finishEmitted) {
771
+ if (reasoningStarted && !textStarted) {
772
+ yield { type: "thinking:end" };
773
+ }
774
+ yield { type: "message:end" };
775
+ yield { type: "done", usage };
776
+ }
777
+ }
778
+ async completeWithResponses(request) {
779
+ const client = await this.getClient();
780
+ const openaiToolOptions = request.providerToolOptions?.openai;
781
+ const payload = {
782
+ model: request.config?.model || this.model,
783
+ instructions: request.systemPrompt,
784
+ input: this.buildResponsesInput(request),
785
+ tools: this.buildResponsesTools(request.toolDefinitions ?? []),
786
+ tool_choice: openaiToolOptions?.toolChoice === "required" ? "required" : openaiToolOptions?.toolChoice === "auto" ? "auto" : void 0,
787
+ parallel_tool_calls: openaiToolOptions?.parallelToolCalls,
788
+ temperature: request.config?.temperature ?? this.config.temperature,
789
+ max_output_tokens: request.config?.maxTokens ?? this.config.maxTokens,
790
+ stream: false
791
+ };
792
+ logProviderPayload("openai", "request payload", payload, request.debug);
793
+ const response = await client.responses.create(payload);
794
+ logProviderPayload("openai", "response payload", response, request.debug);
795
+ return this.parseResponsesResult(response);
796
+ }
797
+ async *stream(request) {
798
+ if (this.shouldUseResponsesApi(request)) {
799
+ const messageId2 = generateMessageId();
800
+ yield { type: "message:start", id: messageId2 };
801
+ try {
802
+ const result = await this.completeWithResponses(request);
803
+ if (result.content) {
804
+ yield { type: "message:delta", content: result.content };
805
+ }
806
+ for (const toolCall of result.toolCalls) {
807
+ yield {
808
+ type: "action:start",
809
+ id: toolCall.id,
810
+ name: toolCall.name
811
+ };
812
+ yield {
813
+ type: "action:args",
814
+ id: toolCall.id,
815
+ args: JSON.stringify(toolCall.args)
816
+ };
817
+ }
818
+ yield { type: "message:end" };
819
+ yield {
820
+ type: "done",
821
+ usage: result.usage ? {
822
+ prompt_tokens: result.usage.promptTokens,
823
+ completion_tokens: result.usage.completionTokens,
824
+ total_tokens: result.usage.totalTokens
825
+ } : void 0
826
+ };
827
+ return;
828
+ } catch (error) {
829
+ yield {
830
+ type: "error",
831
+ message: error instanceof Error ? error.message : "Unknown error",
832
+ code: "OPENAI_RESPONSES_ERROR"
833
+ };
834
+ return;
835
+ }
836
+ }
837
+ const client = await this.getClient();
838
+ let messages;
839
+ if (request.rawMessages && request.rawMessages.length > 0) {
840
+ const processedMessages = request.rawMessages.map((msg) => {
841
+ if (msg.role === "assistant" && Array.isArray(msg.tool_calls) && msg.tool_calls.length > 0 && msg.content === "") {
842
+ return { ...msg, content: null };
843
+ }
844
+ const hasAttachments = msg.attachments && Array.isArray(msg.attachments) && msg.attachments.length > 0;
845
+ if (hasAttachments) {
846
+ const content = [];
847
+ if (msg.content) {
848
+ content.push({ type: "text", text: msg.content });
849
+ }
850
+ for (const attachment of msg.attachments) {
851
+ if (attachment.type === "image") {
852
+ let imageUrl;
853
+ if (attachment.url) {
854
+ imageUrl = attachment.url;
855
+ } else if (attachment.data) {
856
+ imageUrl = attachment.data.startsWith("data:") ? attachment.data : `data:${attachment.mimeType || "image/png"};base64,${attachment.data}`;
857
+ } else {
858
+ continue;
859
+ }
860
+ content.push({
861
+ type: "image_url",
862
+ image_url: { url: imageUrl, detail: "auto" }
863
+ });
864
+ }
865
+ }
866
+ return { ...msg, content, attachments: void 0 };
867
+ }
868
+ return msg;
869
+ });
870
+ if (request.systemPrompt) {
871
+ const hasSystem = processedMessages.some((m) => m.role === "system");
872
+ if (!hasSystem) {
873
+ messages = [
874
+ { role: "system", content: request.systemPrompt },
875
+ ...processedMessages
876
+ ];
877
+ } else {
878
+ messages = processedMessages;
879
+ }
880
+ } else {
881
+ messages = processedMessages;
882
+ }
883
+ } else {
884
+ messages = formatMessagesForOpenAI(
885
+ request.messages,
886
+ request.systemPrompt
887
+ );
888
+ }
889
+ const tools = request.actions?.length ? formatTools(request.actions) : [];
890
+ const webSearchConfig = request.webSearch ?? this.config.webSearch;
891
+ if (webSearchConfig) {
892
+ const webSearchTool = {
893
+ type: "web_search_preview"
894
+ };
895
+ const wsConfig = typeof webSearchConfig === "object" ? webSearchConfig : {};
896
+ if (wsConfig.userLocation) {
897
+ webSearchTool.search_context_size = "medium";
898
+ }
899
+ tools.push(webSearchTool);
900
+ }
901
+ const messageId = generateMessageId();
902
+ yield { type: "message:start", id: messageId };
903
+ try {
904
+ const openaiToolOptions = request.providerToolOptions?.openai;
905
+ const toolChoice = openaiToolOptions?.toolChoice && typeof openaiToolOptions.toolChoice === "object" ? {
906
+ type: "function",
907
+ function: {
908
+ name: openaiToolOptions.toolChoice.name
909
+ }
910
+ } : openaiToolOptions?.toolChoice;
911
+ const isOpenRouter = this.provider === "openrouter";
912
+ const activeModel = request.config?.model || this.model;
913
+ const modelSlug = activeModel.replace("openai/", "");
914
+ const isOSeries = /^o[1-9]/.test(modelSlug);
915
+ const isOpenAIOnOpenRouter = isOpenRouter && activeModel.startsWith("openai/");
916
+ if (!this.config.disableThinking && this.isOpenAIReasoningModelOnOpenRouter(activeModel)) {
917
+ yield* this.streamWithResponsesAPI(request, activeModel, messageId);
918
+ return;
919
+ }
920
+ const maxTokensValue = request.config?.maxTokens ?? this.config.maxTokens;
921
+ const payload = {
922
+ model: activeModel,
923
+ messages,
924
+ tools: tools.length > 0 ? tools : void 0,
925
+ tool_choice: tools.length > 0 ? toolChoice : void 0,
926
+ parallel_tool_calls: tools.length > 0 ? openaiToolOptions?.parallelToolCalls : void 0,
927
+ stream: true,
928
+ stream_options: { include_usage: true },
929
+ // o-series: use max_completion_tokens + reasoning_effort, no temperature
930
+ // regular models: use max_tokens + temperature
931
+ ...isOSeries ? {
932
+ max_completion_tokens: maxTokensValue,
933
+ reasoning_effort: request.config?.reasoningEffort ?? "medium"
934
+ } : {
935
+ temperature: request.config?.temperature ?? this.config.temperature,
936
+ max_tokens: maxTokensValue
937
+ },
938
+ // Non-OpenAI OpenRouter models support OR's reasoning/include_reasoning params.
939
+ // When disableThinking=true we must explicitly send include_reasoning:false because
940
+ // models like Qwen3 and DeepSeek-R1 reason by default even without the reasoning param.
941
+ ...isOpenRouter && !isOpenAIOnOpenRouter ? this.config.disableThinking ? { include_reasoning: false } : { reasoning: { max_tokens: 8e3 }, include_reasoning: true } : {}
942
+ };
943
+ logProviderPayload("openai", "request payload", payload, request.debug);
944
+ const stream = await client.chat.completions.create(payload);
945
+ let currentToolCall = null;
946
+ const collectedCitations = [];
947
+ let citationIndex = 0;
948
+ let usage;
949
+ let adapterReasoningStarted = false;
950
+ for await (const chunk of stream) {
951
+ logProviderPayload("openai", "stream chunk", chunk, request.debug);
952
+ if (request.signal?.aborted) {
953
+ break;
954
+ }
955
+ const delta = chunk.choices[0]?.delta;
956
+ const choice = chunk.choices[0];
957
+ if (delta?.content) {
958
+ yield { type: "message:delta", content: delta.content };
959
+ }
960
+ if (isOpenRouter) {
961
+ const rc = delta?.reasoning_content ?? delta?.reasoning ?? null;
962
+ if (rc) {
963
+ const rcText = typeof rc === "string" ? rc : Array.isArray(rc) && rc[0]?.text ? rc[0].text : "";
964
+ if (rcText) {
965
+ if (!adapterReasoningStarted) {
966
+ yield { type: "thinking:start" };
967
+ adapterReasoningStarted = true;
968
+ }
969
+ yield { type: "thinking:delta", content: rcText };
970
+ }
971
+ } else if (adapterReasoningStarted && (delta?.content || choice?.finish_reason)) {
972
+ yield { type: "thinking:end" };
973
+ adapterReasoningStarted = false;
974
+ }
975
+ }
976
+ const annotations = delta?.annotations;
977
+ if (annotations && annotations.length > 0) {
978
+ for (const annotation of annotations) {
979
+ if (annotation.type === "url_citation" && annotation.url_citation?.url) {
980
+ citationIndex++;
981
+ const url = annotation.url_citation.url;
982
+ const domain = extractDomain(url);
983
+ collectedCitations.push({
984
+ index: citationIndex,
985
+ url,
986
+ title: annotation.url_citation.title || domain,
987
+ domain,
988
+ favicon: domain ? `https://www.google.com/s2/favicons?domain=${domain}&sz=32` : void 0
989
+ });
990
+ }
991
+ }
992
+ }
993
+ if (delta?.tool_calls) {
994
+ for (const toolCall of delta.tool_calls) {
995
+ if (toolCall.id) {
996
+ if (currentToolCall) {
997
+ yield {
998
+ type: "action:args",
999
+ id: currentToolCall.id,
1000
+ args: currentToolCall.arguments
1001
+ };
1002
+ yield {
1003
+ type: "action:end",
1004
+ id: currentToolCall.id,
1005
+ name: currentToolCall.name
1006
+ };
1007
+ }
1008
+ const tcExtraContent = toolCall.extra_content;
1009
+ currentToolCall = {
1010
+ id: toolCall.id,
1011
+ name: toolCall.function?.name || "",
1012
+ arguments: toolCall.function?.arguments || "",
1013
+ ...tcExtraContent ? { extra_content: tcExtraContent } : {}
1014
+ };
1015
+ yield {
1016
+ type: "action:start",
1017
+ id: currentToolCall.id,
1018
+ name: currentToolCall.name,
1019
+ ...currentToolCall.extra_content ? { extra_content: currentToolCall.extra_content } : {}
1020
+ };
1021
+ } else if (currentToolCall && toolCall.function?.arguments) {
1022
+ currentToolCall.arguments += toolCall.function.arguments;
1023
+ yield {
1024
+ type: "action:args",
1025
+ id: currentToolCall.id,
1026
+ args: currentToolCall.arguments
1027
+ };
1028
+ }
1029
+ }
1030
+ }
1031
+ if (chunk.usage) {
1032
+ usage = {
1033
+ prompt_tokens: chunk.usage.prompt_tokens,
1034
+ completion_tokens: chunk.usage.completion_tokens,
1035
+ total_tokens: chunk.usage.total_tokens
1036
+ };
1037
+ }
1038
+ if (choice?.finish_reason) {
1039
+ if (currentToolCall) {
1040
+ yield {
1041
+ type: "action:args",
1042
+ id: currentToolCall.id,
1043
+ args: currentToolCall.arguments
1044
+ };
1045
+ yield {
1046
+ type: "action:end",
1047
+ id: currentToolCall.id,
1048
+ name: currentToolCall.name
1049
+ };
1050
+ currentToolCall = null;
1051
+ }
1052
+ }
1053
+ }
1054
+ if (collectedCitations.length > 0) {
1055
+ const uniqueCitations = deduplicateCitations(collectedCitations);
1056
+ yield { type: "citation", citations: uniqueCitations };
1057
+ }
1058
+ yield { type: "message:end" };
1059
+ yield { type: "done", usage };
1060
+ } catch (error) {
1061
+ yield {
1062
+ type: "error",
1063
+ message: error instanceof Error ? error.message : "Unknown error",
1064
+ code: `${this.provider.toUpperCase()}_ERROR`
1065
+ };
1066
+ }
1067
+ }
1068
+ async complete(request) {
1069
+ if (this.shouldUseResponsesApi(request)) {
1070
+ return this.completeWithResponses(request);
1071
+ }
1072
+ const client = await this.getClient();
1073
+ let messages;
1074
+ if (request.rawMessages && request.rawMessages.length > 0) {
1075
+ const sanitized = request.rawMessages.map((msg) => {
1076
+ if (msg.role === "assistant" && Array.isArray(msg.tool_calls) && msg.tool_calls.length > 0 && msg.content === "") {
1077
+ return { ...msg, content: null };
1078
+ }
1079
+ return msg;
1080
+ });
1081
+ if (request.systemPrompt && !sanitized.some((message2) => message2.role === "system")) {
1082
+ messages = [
1083
+ { role: "system", content: request.systemPrompt },
1084
+ ...sanitized
1085
+ ];
1086
+ } else {
1087
+ messages = sanitized;
1088
+ }
1089
+ } else {
1090
+ messages = formatMessagesForOpenAI(
1091
+ request.messages,
1092
+ request.systemPrompt
1093
+ );
1094
+ }
1095
+ const tools = request.actions?.length ? formatTools(request.actions) : [];
1096
+ const openaiToolOptions = request.providerToolOptions?.openai;
1097
+ const toolChoice = openaiToolOptions?.toolChoice && typeof openaiToolOptions.toolChoice === "object" ? {
1098
+ type: "function",
1099
+ function: {
1100
+ name: openaiToolOptions.toolChoice.name
1101
+ }
1102
+ } : openaiToolOptions?.toolChoice;
1103
+ const activeModel2 = request.config?.model || this.model;
1104
+ const modelSlug2 = activeModel2.replace("openai/", "");
1105
+ const isOSeries2 = /^o[1-9]/.test(modelSlug2);
1106
+ const maxTokensValue2 = request.config?.maxTokens ?? this.config.maxTokens;
1107
+ const payload = {
1108
+ model: activeModel2,
1109
+ messages,
1110
+ tools: tools.length > 0 ? tools : void 0,
1111
+ tool_choice: tools.length > 0 ? toolChoice : void 0,
1112
+ parallel_tool_calls: tools.length > 0 ? openaiToolOptions?.parallelToolCalls : void 0,
1113
+ stream: false,
1114
+ ...isOSeries2 ? {
1115
+ max_completion_tokens: maxTokensValue2,
1116
+ reasoning_effort: request.config?.reasoningEffort ?? "medium"
1117
+ } : {
1118
+ temperature: request.config?.temperature ?? this.config.temperature,
1119
+ max_tokens: maxTokensValue2
1120
+ }
1121
+ };
1122
+ logProviderPayload("openai", "request payload", payload, request.debug);
1123
+ const response = await client.chat.completions.create(payload);
1124
+ logProviderPayload("openai", "response payload", response, request.debug);
1125
+ const choice = response.choices?.[0];
1126
+ const message = choice?.message;
1127
+ return {
1128
+ content: message?.content ?? "",
1129
+ toolCalls: message?.tool_calls?.map((toolCall) => ({
1130
+ id: toolCall.id ?? generateToolCallId(),
1131
+ name: toolCall.function?.name ?? "",
1132
+ args: (() => {
1133
+ try {
1134
+ return JSON.parse(toolCall.function?.arguments ?? "{}");
1135
+ } catch {
1136
+ return {};
1137
+ }
1138
+ })(),
1139
+ ...toolCall.extra_content ? { extra_content: toolCall.extra_content } : {}
1140
+ })) ?? [],
1141
+ usage: response.usage ? {
1142
+ promptTokens: response.usage.prompt_tokens,
1143
+ completionTokens: response.usage.completion_tokens,
1144
+ totalTokens: response.usage.total_tokens
1145
+ } : void 0,
1146
+ rawResponse: response
1147
+ };
1148
+ }
1149
+ };
1150
+ function extractDomain(url) {
1151
+ try {
1152
+ const parsed = new URL(url);
1153
+ return parsed.hostname;
1154
+ } catch {
1155
+ return "";
1156
+ }
1157
+ }
1158
+ function deduplicateCitations(citations) {
1159
+ const seen = /* @__PURE__ */ new Map();
1160
+ let index = 0;
1161
+ for (const citation of citations) {
1162
+ if (!seen.has(citation.url)) {
1163
+ index++;
1164
+ seen.set(citation.url, { ...citation, index });
1165
+ }
1166
+ }
1167
+ return Array.from(seen.values());
1168
+ }
1169
+ function createOpenAIAdapter(config) {
1170
+ return new OpenAIAdapter(config);
1171
+ }
1172
+
1173
+ // src/providers/types.ts
1174
+ function createCallableProvider(providerFn, properties) {
1175
+ Object.defineProperty(providerFn, "name", {
1176
+ value: properties.name,
1177
+ writable: false,
1178
+ configurable: true
1179
+ });
1180
+ Object.assign(providerFn, {
1181
+ supportedModels: properties.supportedModels,
1182
+ languageModel: providerFn,
1183
+ getCapabilities: properties.getCapabilities,
1184
+ embeddingModel: properties.embeddingModel
1185
+ });
1186
+ return providerFn;
1187
+ }
1188
+
1189
+ // src/providers/togetherai/index.ts
1190
+ var DEFAULT_CAPABILITIES = {
1191
+ vision: true,
1192
+ tools: true,
1193
+ jsonMode: true,
1194
+ maxTokens: 131072
1195
+ };
1196
+ function createTogetherAI(config = {}) {
1197
+ const apiKey = config.apiKey ?? process.env.TOGETHER_API_KEY ?? "";
1198
+ const baseUrl = config.baseUrl ?? "https://api.together.xyz/v1";
1199
+ const providerFn = (modelId) => {
1200
+ return createOpenAIAdapter({
1201
+ apiKey,
1202
+ model: modelId,
1203
+ baseUrl
1204
+ });
1205
+ };
1206
+ const getCapabilities = (_modelId) => {
1207
+ return {
1208
+ supportsVision: DEFAULT_CAPABILITIES.vision,
1209
+ supportsTools: DEFAULT_CAPABILITIES.tools,
1210
+ supportsThinking: false,
1211
+ supportsStreaming: true,
1212
+ supportsPDF: false,
1213
+ supportsAudio: false,
1214
+ supportsVideo: false,
1215
+ maxTokens: DEFAULT_CAPABILITIES.maxTokens,
1216
+ supportedImageTypes: ["image/png", "image/jpeg", "image/gif", "image/webp"] ,
1217
+ supportsJsonMode: DEFAULT_CAPABILITIES.jsonMode,
1218
+ supportsSystemMessages: true
1219
+ };
1220
+ };
1221
+ return createCallableProvider(providerFn, {
1222
+ name: "togetherai",
1223
+ supportedModels: [],
1224
+ getCapabilities
1225
+ });
1226
+ }
1227
+ var createTogetherAIProvider = createTogetherAI;
1228
+
1229
+ exports.createTogetherAI = createTogetherAI;
1230
+ exports.createTogetherAIProvider = createTogetherAIProvider;
203
1231
  exports.togetherai = togetherai;
204
1232
  //# sourceMappingURL=index.js.map
205
1233
  //# sourceMappingURL=index.js.map