@standardagents/builder 0.11.4 → 0.11.5

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.
@@ -20350,6 +20350,546 @@ async function fetchGenerationMetadata(apiKey, generationId, baseUrl = "https://
20350
20350
  }
20351
20351
  return null;
20352
20352
  }
20353
+ function transformChatContentPart(part) {
20354
+ if (part.type === "text") {
20355
+ return { type: "text", text: part.text };
20356
+ }
20357
+ if (part.type === "image") {
20358
+ const data = part.data || "";
20359
+ const imageUrl = data.startsWith("data:") ? data : `data:${part.mediaType || "image/png"};base64,${data}`;
20360
+ return {
20361
+ type: "image_url",
20362
+ image_url: {
20363
+ url: imageUrl,
20364
+ detail: part.detail || "auto"
20365
+ }
20366
+ };
20367
+ }
20368
+ if (part.type === "image_url") {
20369
+ return {
20370
+ type: "image_url",
20371
+ image_url: {
20372
+ url: part.image_url?.url || "",
20373
+ detail: part.image_url?.detail || "auto"
20374
+ }
20375
+ };
20376
+ }
20377
+ return {
20378
+ type: "text",
20379
+ text: `[File: ${part.filename || "file"}]`
20380
+ };
20381
+ }
20382
+ function transformChatMessageContent(content) {
20383
+ if (typeof content === "string") {
20384
+ return content;
20385
+ }
20386
+ return content.map(transformChatContentPart);
20387
+ }
20388
+ function transformChatSystemMessage(msg) {
20389
+ return {
20390
+ role: "system",
20391
+ content: msg.content
20392
+ };
20393
+ }
20394
+ function transformChatUserMessage(msg) {
20395
+ return {
20396
+ role: "user",
20397
+ content: transformChatMessageContent(msg.content)
20398
+ };
20399
+ }
20400
+ function transformChatAssistantMessage(msg) {
20401
+ const message = {
20402
+ role: "assistant",
20403
+ content: msg.content || null
20404
+ };
20405
+ if (msg.toolCalls && msg.toolCalls.length > 0) {
20406
+ message.tool_calls = msg.toolCalls.map((tc) => ({
20407
+ id: tc.id,
20408
+ type: "function",
20409
+ function: {
20410
+ name: tc.name,
20411
+ arguments: typeof tc.arguments === "string" ? tc.arguments : JSON.stringify(tc.arguments)
20412
+ }
20413
+ }));
20414
+ }
20415
+ return message;
20416
+ }
20417
+ function transformChatToolMessage(msg) {
20418
+ let output;
20419
+ if (typeof msg.content === "string") {
20420
+ output = msg.content;
20421
+ } else if ("type" in msg.content) {
20422
+ if (msg.content.type === "text") {
20423
+ output = msg.content.text;
20424
+ } else if (msg.content.type === "error") {
20425
+ output = `Error: ${msg.content.error}`;
20426
+ } else {
20427
+ output = JSON.stringify(msg.content);
20428
+ }
20429
+ } else {
20430
+ output = JSON.stringify(msg.content);
20431
+ }
20432
+ const imageAttachments = msg.attachments?.filter((a) => a.type === "image" && a.data) || [];
20433
+ const toolMessage = {
20434
+ role: "tool",
20435
+ tool_call_id: msg.toolCallId,
20436
+ content: output || (imageAttachments.length > 0 ? "Success" : "")
20437
+ };
20438
+ if (imageAttachments.length === 0) {
20439
+ return { toolMessage };
20440
+ }
20441
+ const imageContent = [];
20442
+ const toolName = msg.toolName || "the tool";
20443
+ const isSingle = imageAttachments.length === 1;
20444
+ const descriptor = isSingle ? "the file" : `${imageAttachments.length} files`;
20445
+ const verb = isSingle ? "is" : "are";
20446
+ imageContent.push({
20447
+ type: "text",
20448
+ text: `Here ${verb} ${descriptor} from ${toolName}:`
20449
+ });
20450
+ for (const attachment of imageAttachments) {
20451
+ const attachmentData = attachment.data || "";
20452
+ const imageData = attachmentData.startsWith("data:") ? attachmentData : `data:${attachment.mediaType || "image/png"};base64,${attachmentData}`;
20453
+ imageContent.push({
20454
+ type: "image_url",
20455
+ image_url: {
20456
+ url: imageData,
20457
+ detail: "auto"
20458
+ }
20459
+ });
20460
+ }
20461
+ const syntheticUserMessage = {
20462
+ role: "user",
20463
+ content: imageContent
20464
+ };
20465
+ return { toolMessage, syntheticUserMessage };
20466
+ }
20467
+ function transformChatMessages(messages) {
20468
+ const result = [];
20469
+ for (const msg of messages) {
20470
+ switch (msg.role) {
20471
+ case "system":
20472
+ result.push(transformChatSystemMessage(msg));
20473
+ break;
20474
+ case "user":
20475
+ result.push(transformChatUserMessage(msg));
20476
+ break;
20477
+ case "assistant":
20478
+ result.push(transformChatAssistantMessage(msg));
20479
+ break;
20480
+ case "tool": {
20481
+ const { toolMessage, syntheticUserMessage } = transformChatToolMessage(msg);
20482
+ result.push(toolMessage);
20483
+ if (syntheticUserMessage) {
20484
+ result.push(syntheticUserMessage);
20485
+ }
20486
+ break;
20487
+ }
20488
+ }
20489
+ }
20490
+ return result;
20491
+ }
20492
+ function transformChatTool(tool2) {
20493
+ const inputParams = tool2.function.parameters;
20494
+ let parameters;
20495
+ if (inputParams && typeof inputParams === "object") {
20496
+ parameters = {
20497
+ ...inputParams,
20498
+ additionalProperties: false
20499
+ };
20500
+ } else {
20501
+ parameters = {
20502
+ type: "object",
20503
+ properties: {},
20504
+ required: [],
20505
+ additionalProperties: false
20506
+ };
20507
+ }
20508
+ return {
20509
+ type: "function",
20510
+ function: {
20511
+ name: tool2.function.name,
20512
+ description: tool2.function.description || void 0,
20513
+ parameters,
20514
+ strict: true
20515
+ }
20516
+ };
20517
+ }
20518
+ function transformChatTools(tools) {
20519
+ return tools.map(transformChatTool);
20520
+ }
20521
+ function transformChatToolChoice(choice) {
20522
+ if (choice === "auto") {
20523
+ return "auto";
20524
+ }
20525
+ if (choice === "none") {
20526
+ return "none";
20527
+ }
20528
+ if (choice === "required") {
20529
+ return "required";
20530
+ }
20531
+ if (typeof choice === "object" && "name" in choice) {
20532
+ return { type: "function", function: { name: choice.name } };
20533
+ }
20534
+ return void 0;
20535
+ }
20536
+ function mapChatFinishReason(finishReason) {
20537
+ switch (finishReason) {
20538
+ case "stop":
20539
+ return "stop";
20540
+ case "tool_calls":
20541
+ return "tool_calls";
20542
+ case "length":
20543
+ return "length";
20544
+ case "content_filter":
20545
+ return "content_filter";
20546
+ case "error":
20547
+ return "error";
20548
+ default:
20549
+ return "stop";
20550
+ }
20551
+ }
20552
+ function extractChatToolCalls(toolCalls) {
20553
+ if (!toolCalls || toolCalls.length === 0) {
20554
+ return void 0;
20555
+ }
20556
+ return toolCalls.map((tc) => {
20557
+ let parsedArgs = {};
20558
+ try {
20559
+ parsedArgs = tc.function.arguments ? JSON.parse(tc.function.arguments) : {};
20560
+ } catch {
20561
+ }
20562
+ return {
20563
+ id: tc.id,
20564
+ name: tc.function.name,
20565
+ arguments: parsedArgs
20566
+ };
20567
+ });
20568
+ }
20569
+ function transformChatUsage(usage, actualProvider) {
20570
+ if (!usage) {
20571
+ return {
20572
+ promptTokens: 0,
20573
+ completionTokens: 0,
20574
+ totalTokens: 0
20575
+ };
20576
+ }
20577
+ const promptTokens = usage.native_tokens_prompt || usage.prompt_tokens || 0;
20578
+ const completionTokens = usage.native_tokens_completion || usage.completion_tokens || 0;
20579
+ const totalTokens = usage.total_tokens || promptTokens + completionTokens;
20580
+ return {
20581
+ promptTokens,
20582
+ completionTokens,
20583
+ totalTokens,
20584
+ reasoningTokens: usage.completion_tokens_details?.reasoning_tokens,
20585
+ cachedTokens: usage.prompt_tokens_details?.cached_tokens,
20586
+ cost: usage.cost,
20587
+ provider: actualProvider
20588
+ };
20589
+ }
20590
+ function extractImageFromUrl(url, index) {
20591
+ if (url.startsWith("data:")) {
20592
+ const match2 = url.match(/^data:([^;]+);base64,(.+)$/);
20593
+ if (match2) {
20594
+ return {
20595
+ id: `image_${index}`,
20596
+ data: match2[2],
20597
+ // base64 data without prefix
20598
+ mediaType: match2[1]
20599
+ };
20600
+ }
20601
+ return {
20602
+ id: `image_${index}`,
20603
+ data: url,
20604
+ mediaType: "image/png"
20605
+ };
20606
+ }
20607
+ return {
20608
+ id: `image_${index}`,
20609
+ data: url,
20610
+ mediaType: "image/png"
20611
+ // Default; actual type unknown without fetching
20612
+ };
20613
+ }
20614
+ function extractChatImages(images) {
20615
+ if (!images || images.length === 0) {
20616
+ return void 0;
20617
+ }
20618
+ return images.map((img, index) => extractImageFromUrl(img.image_url.url, index));
20619
+ }
20620
+ function transformChatResponse(response) {
20621
+ const choice = response.choices?.[0];
20622
+ const message = choice?.message;
20623
+ const content = message?.content || null;
20624
+ const toolCalls = extractChatToolCalls(message?.tool_calls);
20625
+ const images = extractChatImages(message?.images);
20626
+ const actualProvider = response.model?.split("/")[0] || void 0;
20627
+ return {
20628
+ content,
20629
+ toolCalls,
20630
+ images,
20631
+ finishReason: mapChatFinishReason(choice?.finish_reason),
20632
+ usage: transformChatUsage(response.usage, actualProvider),
20633
+ metadata: {
20634
+ model: response.model,
20635
+ provider: "openrouter",
20636
+ actualProvider,
20637
+ requestId: response.id
20638
+ }
20639
+ };
20640
+ }
20641
+ function createChatStreamState() {
20642
+ return {
20643
+ content: "",
20644
+ toolCalls: /* @__PURE__ */ new Map(),
20645
+ images: [],
20646
+ reasoningContent: "",
20647
+ hasContent: false,
20648
+ hasReasoning: false,
20649
+ finishReason: null
20650
+ };
20651
+ }
20652
+ function processChatStreamChunk(chunk, state) {
20653
+ const chunks = [];
20654
+ const choice = chunk.choices?.[0];
20655
+ const delta = choice?.delta;
20656
+ if (!delta && !choice?.finish_reason && !chunk.usage) {
20657
+ return chunks;
20658
+ }
20659
+ if (delta?.content) {
20660
+ state.hasContent = true;
20661
+ state.content += delta.content;
20662
+ chunks.push({ type: "content-delta", delta: delta.content });
20663
+ }
20664
+ if (delta?.reasoning_content) {
20665
+ state.hasReasoning = true;
20666
+ state.reasoningContent += delta.reasoning_content;
20667
+ chunks.push({ type: "reasoning-delta", delta: delta.reasoning_content });
20668
+ }
20669
+ if (delta?.tool_calls) {
20670
+ for (const tc of delta.tool_calls) {
20671
+ const index = tc.index;
20672
+ const existing = state.toolCalls.get(index);
20673
+ if (tc.id && tc.function?.name) {
20674
+ state.toolCalls.set(index, {
20675
+ id: tc.id,
20676
+ name: tc.function.name,
20677
+ arguments: tc.function.arguments || ""
20678
+ });
20679
+ chunks.push({
20680
+ type: "tool-call-start",
20681
+ id: tc.id,
20682
+ name: tc.function.name
20683
+ });
20684
+ } else if (existing && tc.function?.arguments) {
20685
+ existing.arguments += tc.function.arguments;
20686
+ chunks.push({
20687
+ type: "tool-call-delta",
20688
+ id: existing.id,
20689
+ argumentsDelta: tc.function.arguments
20690
+ });
20691
+ }
20692
+ }
20693
+ }
20694
+ if (delta?.images && delta.images.length > 0) {
20695
+ for (const img of delta.images) {
20696
+ const index = state.images.length;
20697
+ const providerImage = extractImageFromUrl(img.image_url.url, index);
20698
+ state.images.push(providerImage);
20699
+ chunks.push({
20700
+ type: "image-done",
20701
+ index,
20702
+ image: providerImage
20703
+ });
20704
+ }
20705
+ }
20706
+ if (choice?.finish_reason) {
20707
+ state.finishReason = choice.finish_reason;
20708
+ if (state.hasContent) {
20709
+ chunks.push({ type: "content-done" });
20710
+ }
20711
+ if (state.hasReasoning) {
20712
+ chunks.push({ type: "reasoning-done" });
20713
+ }
20714
+ for (const tc of state.toolCalls.values()) {
20715
+ let parsedArgs = {};
20716
+ try {
20717
+ parsedArgs = tc.arguments ? JSON.parse(tc.arguments) : {};
20718
+ } catch {
20719
+ }
20720
+ chunks.push({
20721
+ type: "tool-call-done",
20722
+ id: tc.id,
20723
+ arguments: parsedArgs
20724
+ });
20725
+ }
20726
+ }
20727
+ if (chunk.usage) {
20728
+ const actualProvider = chunk.model?.split("/")[0] || void 0;
20729
+ chunks.push({
20730
+ type: "finish",
20731
+ finishReason: mapChatFinishReason(state.finishReason),
20732
+ usage: transformChatUsage(chunk.usage, actualProvider),
20733
+ responseId: chunk.id
20734
+ });
20735
+ }
20736
+ return chunks;
20737
+ }
20738
+ function parseChatStreamEvent(jsonStr) {
20739
+ try {
20740
+ return JSON.parse(jsonStr);
20741
+ } catch {
20742
+ return null;
20743
+ }
20744
+ }
20745
+ async function* parseChatSSEStream(response, state) {
20746
+ const reader = response.body?.getReader();
20747
+ if (!reader) {
20748
+ throw new Error("No response body");
20749
+ }
20750
+ const decoder = new TextDecoder();
20751
+ let buffer = "";
20752
+ try {
20753
+ while (true) {
20754
+ const { done, value } = await reader.read();
20755
+ if (done) break;
20756
+ buffer += decoder.decode(value, { stream: true });
20757
+ const lines = buffer.split("\n");
20758
+ buffer = lines.pop() || "";
20759
+ for (const line of lines) {
20760
+ const trimmed = line.trim();
20761
+ if (!trimmed || trimmed.startsWith(":")) continue;
20762
+ if (trimmed.startsWith("data: ")) {
20763
+ const data = trimmed.slice(6);
20764
+ if (data === "[DONE]") continue;
20765
+ const chunk = parseChatStreamEvent(data);
20766
+ if (chunk) {
20767
+ const providerChunks = processChatStreamChunk(chunk, state);
20768
+ for (const c of providerChunks) {
20769
+ yield c;
20770
+ }
20771
+ }
20772
+ }
20773
+ }
20774
+ }
20775
+ if (buffer.trim()) {
20776
+ const trimmed = buffer.trim();
20777
+ if (trimmed.startsWith("data: ")) {
20778
+ const data = trimmed.slice(6);
20779
+ if (data !== "[DONE]") {
20780
+ const chunk = parseChatStreamEvent(data);
20781
+ if (chunk) {
20782
+ const providerChunks = processChatStreamChunk(chunk, state);
20783
+ for (const c of providerChunks) {
20784
+ yield c;
20785
+ }
20786
+ }
20787
+ }
20788
+ }
20789
+ }
20790
+ if (state.finishReason && !state.toolCalls.size) {
20791
+ }
20792
+ } finally {
20793
+ reader.releaseLock();
20794
+ }
20795
+ }
20796
+ function buildChatParams(request) {
20797
+ const messages = transformChatMessages(request.messages);
20798
+ const params = {
20799
+ model: request.model,
20800
+ messages
20801
+ };
20802
+ if (request.tools && request.tools.length > 0) {
20803
+ params.tools = transformChatTools(request.tools);
20804
+ const toolChoice = transformChatToolChoice(request.toolChoice);
20805
+ if (toolChoice !== void 0) {
20806
+ params.tool_choice = toolChoice;
20807
+ }
20808
+ if (request.parallelToolCalls !== void 0) {
20809
+ params.parallel_tool_calls = request.parallelToolCalls;
20810
+ }
20811
+ }
20812
+ if (request.maxOutputTokens !== void 0) {
20813
+ params.max_tokens = request.maxOutputTokens;
20814
+ }
20815
+ if (request.temperature !== void 0) {
20816
+ params.temperature = request.temperature;
20817
+ }
20818
+ if (request.topP !== void 0) {
20819
+ params.top_p = request.topP;
20820
+ }
20821
+ if (request.reasoning?.level !== void 0) {
20822
+ const effortMap = {
20823
+ 10: "minimal",
20824
+ 33: "low",
20825
+ 66: "medium",
20826
+ 100: "high"
20827
+ };
20828
+ const effort = effortMap[request.reasoning.level];
20829
+ if (effort) {
20830
+ params.reasoning = { effort };
20831
+ }
20832
+ }
20833
+ if (request.responseFormat) {
20834
+ if (request.responseFormat.type === "json") {
20835
+ if (request.responseFormat.schema) {
20836
+ params.response_format = {
20837
+ type: "json_schema",
20838
+ json_schema: {
20839
+ name: "response",
20840
+ schema: request.responseFormat.schema,
20841
+ strict: true
20842
+ }
20843
+ };
20844
+ } else {
20845
+ params.response_format = { type: "json_object" };
20846
+ }
20847
+ }
20848
+ }
20849
+ if (request.providerOptions) {
20850
+ const { _metadata, ...safeOptions } = request.providerOptions;
20851
+ Object.assign(params, safeOptions);
20852
+ }
20853
+ return params;
20854
+ }
20855
+ function createChatErrorChunk(error, code) {
20856
+ return { type: "error", error, code };
20857
+ }
20858
+ function isBase64Like22(str) {
20859
+ if (str.startsWith("data:")) return true;
20860
+ if (str.length > 200) {
20861
+ const base64Pattern = /^[A-Za-z0-9+/]+=*$/;
20862
+ return base64Pattern.test(str.substring(0, 200));
20863
+ }
20864
+ return false;
20865
+ }
20866
+ function truncateBase64String22(str, maxLength = 50) {
20867
+ if (str.length <= maxLength) return str;
20868
+ const preview = str.substring(0, maxLength);
20869
+ return `${preview}...[truncated, ${str.length.toLocaleString()} chars]`;
20870
+ }
20871
+ function truncateChatBase64(obj, maxLength = 50) {
20872
+ if (obj === null || obj === void 0) {
20873
+ return obj;
20874
+ }
20875
+ if (typeof obj === "string") {
20876
+ if (isBase64Like22(obj)) {
20877
+ return truncateBase64String22(obj, maxLength);
20878
+ }
20879
+ return obj;
20880
+ }
20881
+ if (Array.isArray(obj)) {
20882
+ return obj.map((item) => truncateChatBase64(item, maxLength));
20883
+ }
20884
+ if (typeof obj === "object") {
20885
+ const result = {};
20886
+ for (const [key, value] of Object.entries(obj)) {
20887
+ result[key] = truncateChatBase64(value, maxLength);
20888
+ }
20889
+ return result;
20890
+ }
20891
+ return obj;
20892
+ }
20353
20893
  function svgToDataUri2(svg) {
20354
20894
  const encoded = encodeURIComponent(svg).replace(/'/g, "%27").replace(/"/g, "%22");
20355
20895
  return `data:image/svg+xml,${encoded}`;
@@ -20481,6 +21021,17 @@ var init_dist2 = __esm({
20481
21021
  constructor(config) {
20482
21022
  this.config = config;
20483
21023
  }
21024
+ /**
21025
+ * Determine which API to use for a request.
21026
+ * Checks request-level providerOptions first, then falls back to config.
21027
+ * Defaults to Chat Completions (stable API).
21028
+ */
21029
+ getApiMode(request) {
21030
+ if (request?.providerOptions?.useResponsesApi === true) {
21031
+ return "responses";
21032
+ }
21033
+ return "chat";
21034
+ }
20484
21035
  async getClient() {
20485
21036
  if (!this.client) {
20486
21037
  const { OpenRouter: OpenRouter2 } = await Promise.resolve().then(() => (init_esm(), esm_exports));
@@ -20617,6 +21168,53 @@ var init_dist2 = __esm({
20617
21168
  // Generation Methods
20618
21169
  // ============================================================================
20619
21170
  async generate(request) {
21171
+ const apiMode = this.getApiMode(request);
21172
+ if (apiMode === "responses") {
21173
+ return this.generateWithResponses(request);
21174
+ }
21175
+ return this.generateWithChat(request);
21176
+ }
21177
+ /**
21178
+ * Generate using the Chat Completions API (default).
21179
+ */
21180
+ async generateWithChat(request) {
21181
+ const apiKey = this.config.apiKey;
21182
+ const baseUrl = this.config.baseUrl || "https://openrouter.ai/api/v1";
21183
+ try {
21184
+ const params = buildChatParams(request);
21185
+ if (this.config.providers && this.config.providers.length > 0) {
21186
+ params.provider = { only: this.config.providers };
21187
+ }
21188
+ const response = await fetch(`${baseUrl}/chat/completions`, {
21189
+ method: "POST",
21190
+ headers: {
21191
+ "Content-Type": "application/json",
21192
+ "Authorization": `Bearer ${apiKey}`
21193
+ },
21194
+ body: JSON.stringify(params),
21195
+ signal: request.signal
21196
+ });
21197
+ if (!response.ok) {
21198
+ const errorText = await response.text();
21199
+ let errorMessage = `OpenRouter API error: ${response.status}`;
21200
+ try {
21201
+ const errorJson = JSON.parse(errorText);
21202
+ errorMessage = errorJson.error?.message || errorJson.message || errorMessage;
21203
+ } catch {
21204
+ errorMessage = errorText || errorMessage;
21205
+ }
21206
+ throw new ProviderError(errorMessage, "invalid_request", response.status);
21207
+ }
21208
+ const data = await response.json();
21209
+ return transformChatResponse(data);
21210
+ } catch (error) {
21211
+ throw this.toProviderError(error);
21212
+ }
21213
+ }
21214
+ /**
21215
+ * Generate using the Responses API (beta).
21216
+ */
21217
+ async generateWithResponses(request) {
20620
21218
  const client = await this.getClient();
20621
21219
  try {
20622
21220
  const params = buildCreateParams2(request);
@@ -20633,6 +21231,87 @@ var init_dist2 = __esm({
20633
21231
  }
20634
21232
  }
20635
21233
  async stream(request) {
21234
+ const apiMode = this.getApiMode(request);
21235
+ if (apiMode === "responses") {
21236
+ return this.streamWithResponses(request);
21237
+ }
21238
+ return this.streamWithChat(request);
21239
+ }
21240
+ /**
21241
+ * Stream using the Chat Completions API (default).
21242
+ */
21243
+ async streamWithChat(request) {
21244
+ const self = this;
21245
+ const apiKey = this.config.apiKey;
21246
+ const baseUrl = this.config.baseUrl || "https://openrouter.ai/api/v1";
21247
+ try {
21248
+ const params = buildChatParams(request);
21249
+ if (this.config.providers && this.config.providers.length > 0) {
21250
+ params.provider = { only: this.config.providers };
21251
+ }
21252
+ const response = await fetch(`${baseUrl}/chat/completions`, {
21253
+ method: "POST",
21254
+ headers: {
21255
+ "Content-Type": "application/json",
21256
+ "Authorization": `Bearer ${apiKey}`
21257
+ },
21258
+ body: JSON.stringify({
21259
+ ...params,
21260
+ stream: true,
21261
+ stream_options: { include_usage: true }
21262
+ }),
21263
+ signal: request.signal
21264
+ });
21265
+ if (!response.ok) {
21266
+ const errorText = await response.text();
21267
+ let errorMessage = `OpenRouter API error: ${response.status}`;
21268
+ try {
21269
+ const errorJson = JSON.parse(errorText);
21270
+ errorMessage = errorJson.error?.message || errorJson.message || errorMessage;
21271
+ } catch {
21272
+ errorMessage = errorText || errorMessage;
21273
+ }
21274
+ throw new ProviderError(errorMessage, "invalid_request", response.status);
21275
+ }
21276
+ return {
21277
+ async *[Symbol.asyncIterator]() {
21278
+ const state = createChatStreamState();
21279
+ let finishChunk = null;
21280
+ let responseId = null;
21281
+ try {
21282
+ for await (const chunk of parseChatSSEStream(response, state)) {
21283
+ if (chunk.type === "finish") {
21284
+ finishChunk = chunk;
21285
+ responseId = chunk.responseId || null;
21286
+ } else {
21287
+ yield chunk;
21288
+ }
21289
+ }
21290
+ if (finishChunk) {
21291
+ const finishWithMeta = {
21292
+ ...finishChunk,
21293
+ _asyncMetadata: responseId ? {
21294
+ generationId: responseId,
21295
+ apiKey,
21296
+ baseUrl
21297
+ } : void 0
21298
+ };
21299
+ yield finishWithMeta;
21300
+ }
21301
+ } catch (error) {
21302
+ const providerError = self.toProviderError(error);
21303
+ yield createChatErrorChunk(providerError.message, providerError.code);
21304
+ }
21305
+ }
21306
+ };
21307
+ } catch (error) {
21308
+ throw this.toProviderError(error);
21309
+ }
21310
+ }
21311
+ /**
21312
+ * Stream using the Responses API (beta).
21313
+ */
21314
+ async streamWithResponses(request) {
20636
21315
  const self = this;
20637
21316
  const apiKey = this.config.apiKey;
20638
21317
  const baseUrl = this.config.baseUrl || "https://openrouter.ai/api/v1";
@@ -20765,19 +21444,33 @@ var init_dist2 = __esm({
20765
21444
  // Inspection
20766
21445
  // ============================================================================
20767
21446
  /**
20768
- * Transform a ProviderRequest to OpenRouter Responses API format for inspection.
21447
+ * Transform a ProviderRequest to the appropriate API format for inspection.
20769
21448
  * Returns the exact request body that would be sent to OpenRouter, with base64 data truncated.
20770
21449
  */
20771
21450
  async inspectRequest(request) {
20772
- const params = buildCreateParams2(request);
21451
+ const apiMode = this.getApiMode(request);
21452
+ if (apiMode === "responses") {
21453
+ const params2 = buildCreateParams2(request);
21454
+ if (this.config.providers && this.config.providers.length > 0) {
21455
+ params2.provider = { only: this.config.providers };
21456
+ }
21457
+ return {
21458
+ body: truncateBase642(params2),
21459
+ messagesPath: "input",
21460
+ metadata: {
21461
+ endpoint: "https://openrouter.ai/api/v1/responses"
21462
+ }
21463
+ };
21464
+ }
21465
+ const params = buildChatParams(request);
20773
21466
  if (this.config.providers && this.config.providers.length > 0) {
20774
21467
  params.provider = { only: this.config.providers };
20775
21468
  }
20776
21469
  return {
20777
- body: truncateBase642(params),
20778
- messagesPath: "input",
21470
+ body: truncateChatBase64(params),
21471
+ messagesPath: "messages",
20779
21472
  metadata: {
20780
- endpoint: "https://openrouter.ai/api/v1/responses"
21473
+ endpoint: "https://openrouter.ai/api/v1/chat/completions"
20781
21474
  }
20782
21475
  };
20783
21476
  }
@@ -20846,7 +21539,17 @@ var init_dist2 = __esm({
20846
21539
  }).passthrough();
20847
21540
  openrouterProviderOptions = z.object({
20848
21541
  /** Provider routing configuration */
20849
- provider: providerRoutingSchema.optional()
21542
+ provider: providerRoutingSchema.optional(),
21543
+ /**
21544
+ * Use OpenRouter's Responses API (beta) instead of the Chat Completions API.
21545
+ *
21546
+ * By default, the provider uses the stable Chat Completions API.
21547
+ * Set this to true to use the Responses API which has some additional
21548
+ * features but may be less stable.
21549
+ *
21550
+ * @default false
21551
+ */
21552
+ useResponsesApi: z.boolean().optional()
20850
21553
  }).passthrough();
20851
21554
  openrouter = Object.assign(
20852
21555
  (config) => new OpenRouterProvider(config),