@standardagents/builder 0.11.4 → 0.11.6

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.
@@ -2721,6 +2721,8 @@ var init_ToolExecutor = __esm({
2721
2721
  parentMessageId: toolMessageId,
2722
2722
  // Set depth one level deeper than parent
2723
2723
  depth: state.depth + 1,
2724
+ // Extend promptPath with the sub-prompt name
2725
+ promptPath: [...state.promptPath, promptDef.name],
2724
2726
  // Additional messages to inject
2725
2727
  extraMessages
2726
2728
  }, true);
@@ -2749,7 +2751,7 @@ var init_ToolExecutor = __esm({
2749
2751
  reader.releaseLock();
2750
2752
  }
2751
2753
  const childToolMessagesResult = await state.storage.sql.exec(
2752
- `SELECT id, content, tool_status, tool_call_id FROM messages WHERE parent_id = ? AND role = 'tool'`,
2754
+ `SELECT id, content, tool_status, tool_call_id, name FROM messages WHERE parent_id = ? AND role = 'tool'`,
2753
2755
  toolMessageId
2754
2756
  );
2755
2757
  const childToolRows = childToolMessagesResult.toArray();
@@ -2781,33 +2783,64 @@ var init_ToolExecutor = __esm({
2781
2783
  if (toolResponseOptions.include_text_response && textContent) {
2782
2784
  responseParts.push(textContent);
2783
2785
  }
2784
- if (toolResponseOptions.include_tool_calls || toolResponseOptions.include_errors) {
2785
- const childAssistantMessagesResult = await state.storage.sql.exec(
2786
- `SELECT id, tool_calls FROM messages WHERE parent_id = ? AND role = 'assistant' AND tool_calls IS NOT NULL`,
2787
- toolMessageId
2788
- );
2789
- const childAssistantRows = childAssistantMessagesResult.toArray();
2790
- const toolCallsSummary = [];
2791
- if (toolResponseOptions.include_tool_calls && childAssistantRows.length > 0) {
2792
- for (const row of childAssistantRows) {
2793
- const toolCalls = JSON.parse(row.tool_calls);
2794
- for (const tc of toolCalls) {
2795
- toolCallsSummary.push(
2796
- `Tool Call: ${tc.function.name}(${tc.function.arguments})`
2797
- );
2798
- }
2799
- }
2800
- }
2786
+ if (overallStatus === "error") {
2787
+ const failedTools = [];
2788
+ const successfulToolNames = [];
2801
2789
  for (const row of childToolRows) {
2802
- const isError = row.content?.startsWith("Error: ");
2803
- if (isError && toolResponseOptions.include_errors || !isError && toolResponseOptions.include_tool_calls) {
2804
- toolCallsSummary.push(`Tool Response: ${row.content}`);
2790
+ const toolName = row.name || "unknown_tool";
2791
+ const isError = row.tool_status === "error";
2792
+ if (isError) {
2793
+ failedTools.push({
2794
+ name: toolName,
2795
+ content: row.content
2796
+ });
2797
+ } else {
2798
+ successfulToolNames.push(toolName);
2805
2799
  }
2806
2800
  }
2807
- if (toolCallsSummary.length > 0) {
2808
- responseParts.push(
2809
- "Tool Executions:\n" + toolCallsSummary.join("\n")
2801
+ if (toolResponseOptions.include_errors && failedTools.length > 0) {
2802
+ const errorLines = failedTools.map((tool2) => {
2803
+ let errorMsg = tool2.content;
2804
+ if (errorMsg.startsWith("Failed to execute tool: ")) {
2805
+ errorMsg = errorMsg.substring("Failed to execute tool: ".length);
2806
+ }
2807
+ return ` ${tool2.name}: ${errorMsg}`;
2808
+ });
2809
+ responseParts.push(`Sub-prompt failed with ${failedTools.length} error(s):
2810
+ ${errorLines.join("\n")}`);
2811
+ }
2812
+ if (toolResponseOptions.include_tool_calls && successfulToolNames.length > 0) {
2813
+ responseParts.push(`Completed successfully: ${successfulToolNames.join(", ")}`);
2814
+ }
2815
+ } else {
2816
+ if (toolResponseOptions.include_tool_calls || toolResponseOptions.include_errors) {
2817
+ const childAssistantMessagesResult = await state.storage.sql.exec(
2818
+ `SELECT id, tool_calls FROM messages WHERE parent_id = ? AND role = 'assistant' AND tool_calls IS NOT NULL`,
2819
+ toolMessageId
2810
2820
  );
2821
+ const childAssistantRows = childAssistantMessagesResult.toArray();
2822
+ const toolCallsSummary = [];
2823
+ if (toolResponseOptions.include_tool_calls && childAssistantRows.length > 0) {
2824
+ for (const row of childAssistantRows) {
2825
+ const toolCalls = JSON.parse(row.tool_calls);
2826
+ for (const tc of toolCalls) {
2827
+ toolCallsSummary.push(
2828
+ `Tool Call: ${tc.function.name}(${tc.function.arguments})`
2829
+ );
2830
+ }
2831
+ }
2832
+ }
2833
+ for (const row of childToolRows) {
2834
+ const isError = row.content?.startsWith("Error: ");
2835
+ if (isError && toolResponseOptions.include_errors || !isError && toolResponseOptions.include_tool_calls) {
2836
+ toolCallsSummary.push(`Tool Response: ${row.content}`);
2837
+ }
2838
+ }
2839
+ if (toolCallsSummary.length > 0) {
2840
+ responseParts.push(
2841
+ "Tool Executions:\n" + toolCallsSummary.join("\n")
2842
+ );
2843
+ }
2811
2844
  }
2812
2845
  }
2813
2846
  const finalResponse = responseParts.length > 0 ? responseParts.join("\n\n") : "Prompt executed successfully";
@@ -4767,6 +4800,8 @@ var init_FlowEngine = __esm({
4767
4800
  parentMessageId: stateInput.parentMessageId,
4768
4801
  depth: stateInput.depth ?? 0,
4769
4802
  // Default to 0 for top-level prompts
4803
+ // Initialize promptPath from input or create new path with current prompt name
4804
+ promptPath: stateInput.promptPath ?? [sideAPrompt.name],
4770
4805
  pendingMessageId: stateInput.pendingMessageId,
4771
4806
  abortController: stateInput.abortController,
4772
4807
  allowedTools: stateInput.allowedTools,
@@ -4970,6 +5005,7 @@ var init_FlowEngine = __esm({
4970
5005
  state.extraMessages = [];
4971
5006
  state.currentSide = "a";
4972
5007
  state.prompt = state.prompts.sideA;
5008
+ state.promptPath = [sideAPrompt.name];
4973
5009
  state.pendingHandoff = void 0;
4974
5010
  state.emitTelemetry?.({
4975
5011
  type: "agent_handoff",
@@ -7215,6 +7251,9 @@ var init_ThreadStateImpl = __esm({
7215
7251
  metadata: void 0
7216
7252
  }));
7217
7253
  }
7254
+ get promptPath() {
7255
+ return this._flowState.promptPath;
7256
+ }
7218
7257
  forceTurn(side) {
7219
7258
  this._flowState.forcedNextSide = side === "a" ? "side_a" : "side_b";
7220
7259
  }
@@ -20350,6 +20389,546 @@ async function fetchGenerationMetadata(apiKey, generationId, baseUrl = "https://
20350
20389
  }
20351
20390
  return null;
20352
20391
  }
20392
+ function transformChatContentPart(part) {
20393
+ if (part.type === "text") {
20394
+ return { type: "text", text: part.text };
20395
+ }
20396
+ if (part.type === "image") {
20397
+ const data = part.data || "";
20398
+ const imageUrl = data.startsWith("data:") ? data : `data:${part.mediaType || "image/png"};base64,${data}`;
20399
+ return {
20400
+ type: "image_url",
20401
+ image_url: {
20402
+ url: imageUrl,
20403
+ detail: part.detail || "auto"
20404
+ }
20405
+ };
20406
+ }
20407
+ if (part.type === "image_url") {
20408
+ return {
20409
+ type: "image_url",
20410
+ image_url: {
20411
+ url: part.image_url?.url || "",
20412
+ detail: part.image_url?.detail || "auto"
20413
+ }
20414
+ };
20415
+ }
20416
+ return {
20417
+ type: "text",
20418
+ text: `[File: ${part.filename || "file"}]`
20419
+ };
20420
+ }
20421
+ function transformChatMessageContent(content) {
20422
+ if (typeof content === "string") {
20423
+ return content;
20424
+ }
20425
+ return content.map(transformChatContentPart);
20426
+ }
20427
+ function transformChatSystemMessage(msg) {
20428
+ return {
20429
+ role: "system",
20430
+ content: msg.content
20431
+ };
20432
+ }
20433
+ function transformChatUserMessage(msg) {
20434
+ return {
20435
+ role: "user",
20436
+ content: transformChatMessageContent(msg.content)
20437
+ };
20438
+ }
20439
+ function transformChatAssistantMessage(msg) {
20440
+ const message = {
20441
+ role: "assistant",
20442
+ content: msg.content || null
20443
+ };
20444
+ if (msg.toolCalls && msg.toolCalls.length > 0) {
20445
+ message.tool_calls = msg.toolCalls.map((tc) => ({
20446
+ id: tc.id,
20447
+ type: "function",
20448
+ function: {
20449
+ name: tc.name,
20450
+ arguments: typeof tc.arguments === "string" ? tc.arguments : JSON.stringify(tc.arguments)
20451
+ }
20452
+ }));
20453
+ }
20454
+ return message;
20455
+ }
20456
+ function transformChatToolMessage(msg) {
20457
+ let output;
20458
+ if (typeof msg.content === "string") {
20459
+ output = msg.content;
20460
+ } else if ("type" in msg.content) {
20461
+ if (msg.content.type === "text") {
20462
+ output = msg.content.text;
20463
+ } else if (msg.content.type === "error") {
20464
+ output = `Error: ${msg.content.error}`;
20465
+ } else {
20466
+ output = JSON.stringify(msg.content);
20467
+ }
20468
+ } else {
20469
+ output = JSON.stringify(msg.content);
20470
+ }
20471
+ const imageAttachments = msg.attachments?.filter((a) => a.type === "image" && a.data) || [];
20472
+ const toolMessage = {
20473
+ role: "tool",
20474
+ tool_call_id: msg.toolCallId,
20475
+ content: output || (imageAttachments.length > 0 ? "Success" : "")
20476
+ };
20477
+ if (imageAttachments.length === 0) {
20478
+ return { toolMessage };
20479
+ }
20480
+ const imageContent = [];
20481
+ const toolName = msg.toolName || "the tool";
20482
+ const isSingle = imageAttachments.length === 1;
20483
+ const descriptor = isSingle ? "the file" : `${imageAttachments.length} files`;
20484
+ const verb = isSingle ? "is" : "are";
20485
+ imageContent.push({
20486
+ type: "text",
20487
+ text: `Here ${verb} ${descriptor} from ${toolName}:`
20488
+ });
20489
+ for (const attachment of imageAttachments) {
20490
+ const attachmentData = attachment.data || "";
20491
+ const imageData = attachmentData.startsWith("data:") ? attachmentData : `data:${attachment.mediaType || "image/png"};base64,${attachmentData}`;
20492
+ imageContent.push({
20493
+ type: "image_url",
20494
+ image_url: {
20495
+ url: imageData,
20496
+ detail: "auto"
20497
+ }
20498
+ });
20499
+ }
20500
+ const syntheticUserMessage = {
20501
+ role: "user",
20502
+ content: imageContent
20503
+ };
20504
+ return { toolMessage, syntheticUserMessage };
20505
+ }
20506
+ function transformChatMessages(messages) {
20507
+ const result = [];
20508
+ for (const msg of messages) {
20509
+ switch (msg.role) {
20510
+ case "system":
20511
+ result.push(transformChatSystemMessage(msg));
20512
+ break;
20513
+ case "user":
20514
+ result.push(transformChatUserMessage(msg));
20515
+ break;
20516
+ case "assistant":
20517
+ result.push(transformChatAssistantMessage(msg));
20518
+ break;
20519
+ case "tool": {
20520
+ const { toolMessage, syntheticUserMessage } = transformChatToolMessage(msg);
20521
+ result.push(toolMessage);
20522
+ if (syntheticUserMessage) {
20523
+ result.push(syntheticUserMessage);
20524
+ }
20525
+ break;
20526
+ }
20527
+ }
20528
+ }
20529
+ return result;
20530
+ }
20531
+ function transformChatTool(tool2) {
20532
+ const inputParams = tool2.function.parameters;
20533
+ let parameters;
20534
+ if (inputParams && typeof inputParams === "object") {
20535
+ parameters = {
20536
+ ...inputParams,
20537
+ additionalProperties: false
20538
+ };
20539
+ } else {
20540
+ parameters = {
20541
+ type: "object",
20542
+ properties: {},
20543
+ required: [],
20544
+ additionalProperties: false
20545
+ };
20546
+ }
20547
+ return {
20548
+ type: "function",
20549
+ function: {
20550
+ name: tool2.function.name,
20551
+ description: tool2.function.description || void 0,
20552
+ parameters,
20553
+ strict: true
20554
+ }
20555
+ };
20556
+ }
20557
+ function transformChatTools(tools) {
20558
+ return tools.map(transformChatTool);
20559
+ }
20560
+ function transformChatToolChoice(choice) {
20561
+ if (choice === "auto") {
20562
+ return "auto";
20563
+ }
20564
+ if (choice === "none") {
20565
+ return "none";
20566
+ }
20567
+ if (choice === "required") {
20568
+ return "required";
20569
+ }
20570
+ if (typeof choice === "object" && "name" in choice) {
20571
+ return { type: "function", function: { name: choice.name } };
20572
+ }
20573
+ return void 0;
20574
+ }
20575
+ function mapChatFinishReason(finishReason) {
20576
+ switch (finishReason) {
20577
+ case "stop":
20578
+ return "stop";
20579
+ case "tool_calls":
20580
+ return "tool_calls";
20581
+ case "length":
20582
+ return "length";
20583
+ case "content_filter":
20584
+ return "content_filter";
20585
+ case "error":
20586
+ return "error";
20587
+ default:
20588
+ return "stop";
20589
+ }
20590
+ }
20591
+ function extractChatToolCalls(toolCalls) {
20592
+ if (!toolCalls || toolCalls.length === 0) {
20593
+ return void 0;
20594
+ }
20595
+ return toolCalls.map((tc) => {
20596
+ let parsedArgs = {};
20597
+ try {
20598
+ parsedArgs = tc.function.arguments ? JSON.parse(tc.function.arguments) : {};
20599
+ } catch {
20600
+ }
20601
+ return {
20602
+ id: tc.id,
20603
+ name: tc.function.name,
20604
+ arguments: parsedArgs
20605
+ };
20606
+ });
20607
+ }
20608
+ function transformChatUsage(usage, actualProvider) {
20609
+ if (!usage) {
20610
+ return {
20611
+ promptTokens: 0,
20612
+ completionTokens: 0,
20613
+ totalTokens: 0
20614
+ };
20615
+ }
20616
+ const promptTokens = usage.native_tokens_prompt || usage.prompt_tokens || 0;
20617
+ const completionTokens = usage.native_tokens_completion || usage.completion_tokens || 0;
20618
+ const totalTokens = usage.total_tokens || promptTokens + completionTokens;
20619
+ return {
20620
+ promptTokens,
20621
+ completionTokens,
20622
+ totalTokens,
20623
+ reasoningTokens: usage.completion_tokens_details?.reasoning_tokens,
20624
+ cachedTokens: usage.prompt_tokens_details?.cached_tokens,
20625
+ cost: usage.cost,
20626
+ provider: actualProvider
20627
+ };
20628
+ }
20629
+ function extractImageFromUrl(url, index) {
20630
+ if (url.startsWith("data:")) {
20631
+ const match2 = url.match(/^data:([^;]+);base64,(.+)$/);
20632
+ if (match2) {
20633
+ return {
20634
+ id: `image_${index}`,
20635
+ data: match2[2],
20636
+ // base64 data without prefix
20637
+ mediaType: match2[1]
20638
+ };
20639
+ }
20640
+ return {
20641
+ id: `image_${index}`,
20642
+ data: url,
20643
+ mediaType: "image/png"
20644
+ };
20645
+ }
20646
+ return {
20647
+ id: `image_${index}`,
20648
+ data: url,
20649
+ mediaType: "image/png"
20650
+ // Default; actual type unknown without fetching
20651
+ };
20652
+ }
20653
+ function extractChatImages(images) {
20654
+ if (!images || images.length === 0) {
20655
+ return void 0;
20656
+ }
20657
+ return images.map((img, index) => extractImageFromUrl(img.image_url.url, index));
20658
+ }
20659
+ function transformChatResponse(response) {
20660
+ const choice = response.choices?.[0];
20661
+ const message = choice?.message;
20662
+ const content = message?.content || null;
20663
+ const toolCalls = extractChatToolCalls(message?.tool_calls);
20664
+ const images = extractChatImages(message?.images);
20665
+ const actualProvider = response.model?.split("/")[0] || void 0;
20666
+ return {
20667
+ content,
20668
+ toolCalls,
20669
+ images,
20670
+ finishReason: mapChatFinishReason(choice?.finish_reason),
20671
+ usage: transformChatUsage(response.usage, actualProvider),
20672
+ metadata: {
20673
+ model: response.model,
20674
+ provider: "openrouter",
20675
+ actualProvider,
20676
+ requestId: response.id
20677
+ }
20678
+ };
20679
+ }
20680
+ function createChatStreamState() {
20681
+ return {
20682
+ content: "",
20683
+ toolCalls: /* @__PURE__ */ new Map(),
20684
+ images: [],
20685
+ reasoningContent: "",
20686
+ hasContent: false,
20687
+ hasReasoning: false,
20688
+ finishReason: null
20689
+ };
20690
+ }
20691
+ function processChatStreamChunk(chunk, state) {
20692
+ const chunks = [];
20693
+ const choice = chunk.choices?.[0];
20694
+ const delta = choice?.delta;
20695
+ if (!delta && !choice?.finish_reason && !chunk.usage) {
20696
+ return chunks;
20697
+ }
20698
+ if (delta?.content) {
20699
+ state.hasContent = true;
20700
+ state.content += delta.content;
20701
+ chunks.push({ type: "content-delta", delta: delta.content });
20702
+ }
20703
+ if (delta?.reasoning_content) {
20704
+ state.hasReasoning = true;
20705
+ state.reasoningContent += delta.reasoning_content;
20706
+ chunks.push({ type: "reasoning-delta", delta: delta.reasoning_content });
20707
+ }
20708
+ if (delta?.tool_calls) {
20709
+ for (const tc of delta.tool_calls) {
20710
+ const index = tc.index;
20711
+ const existing = state.toolCalls.get(index);
20712
+ if (tc.id && tc.function?.name) {
20713
+ state.toolCalls.set(index, {
20714
+ id: tc.id,
20715
+ name: tc.function.name,
20716
+ arguments: tc.function.arguments || ""
20717
+ });
20718
+ chunks.push({
20719
+ type: "tool-call-start",
20720
+ id: tc.id,
20721
+ name: tc.function.name
20722
+ });
20723
+ } else if (existing && tc.function?.arguments) {
20724
+ existing.arguments += tc.function.arguments;
20725
+ chunks.push({
20726
+ type: "tool-call-delta",
20727
+ id: existing.id,
20728
+ argumentsDelta: tc.function.arguments
20729
+ });
20730
+ }
20731
+ }
20732
+ }
20733
+ if (delta?.images && delta.images.length > 0) {
20734
+ for (const img of delta.images) {
20735
+ const index = state.images.length;
20736
+ const providerImage = extractImageFromUrl(img.image_url.url, index);
20737
+ state.images.push(providerImage);
20738
+ chunks.push({
20739
+ type: "image-done",
20740
+ index,
20741
+ image: providerImage
20742
+ });
20743
+ }
20744
+ }
20745
+ if (choice?.finish_reason) {
20746
+ state.finishReason = choice.finish_reason;
20747
+ if (state.hasContent) {
20748
+ chunks.push({ type: "content-done" });
20749
+ }
20750
+ if (state.hasReasoning) {
20751
+ chunks.push({ type: "reasoning-done" });
20752
+ }
20753
+ for (const tc of state.toolCalls.values()) {
20754
+ let parsedArgs = {};
20755
+ try {
20756
+ parsedArgs = tc.arguments ? JSON.parse(tc.arguments) : {};
20757
+ } catch {
20758
+ }
20759
+ chunks.push({
20760
+ type: "tool-call-done",
20761
+ id: tc.id,
20762
+ arguments: parsedArgs
20763
+ });
20764
+ }
20765
+ }
20766
+ if (chunk.usage) {
20767
+ const actualProvider = chunk.model?.split("/")[0] || void 0;
20768
+ chunks.push({
20769
+ type: "finish",
20770
+ finishReason: mapChatFinishReason(state.finishReason),
20771
+ usage: transformChatUsage(chunk.usage, actualProvider),
20772
+ responseId: chunk.id
20773
+ });
20774
+ }
20775
+ return chunks;
20776
+ }
20777
+ function parseChatStreamEvent(jsonStr) {
20778
+ try {
20779
+ return JSON.parse(jsonStr);
20780
+ } catch {
20781
+ return null;
20782
+ }
20783
+ }
20784
+ async function* parseChatSSEStream(response, state) {
20785
+ const reader = response.body?.getReader();
20786
+ if (!reader) {
20787
+ throw new Error("No response body");
20788
+ }
20789
+ const decoder = new TextDecoder();
20790
+ let buffer = "";
20791
+ try {
20792
+ while (true) {
20793
+ const { done, value } = await reader.read();
20794
+ if (done) break;
20795
+ buffer += decoder.decode(value, { stream: true });
20796
+ const lines = buffer.split("\n");
20797
+ buffer = lines.pop() || "";
20798
+ for (const line of lines) {
20799
+ const trimmed = line.trim();
20800
+ if (!trimmed || trimmed.startsWith(":")) continue;
20801
+ if (trimmed.startsWith("data: ")) {
20802
+ const data = trimmed.slice(6);
20803
+ if (data === "[DONE]") continue;
20804
+ const chunk = parseChatStreamEvent(data);
20805
+ if (chunk) {
20806
+ const providerChunks = processChatStreamChunk(chunk, state);
20807
+ for (const c of providerChunks) {
20808
+ yield c;
20809
+ }
20810
+ }
20811
+ }
20812
+ }
20813
+ }
20814
+ if (buffer.trim()) {
20815
+ const trimmed = buffer.trim();
20816
+ if (trimmed.startsWith("data: ")) {
20817
+ const data = trimmed.slice(6);
20818
+ if (data !== "[DONE]") {
20819
+ const chunk = parseChatStreamEvent(data);
20820
+ if (chunk) {
20821
+ const providerChunks = processChatStreamChunk(chunk, state);
20822
+ for (const c of providerChunks) {
20823
+ yield c;
20824
+ }
20825
+ }
20826
+ }
20827
+ }
20828
+ }
20829
+ if (state.finishReason && !state.toolCalls.size) {
20830
+ }
20831
+ } finally {
20832
+ reader.releaseLock();
20833
+ }
20834
+ }
20835
+ function buildChatParams(request) {
20836
+ const messages = transformChatMessages(request.messages);
20837
+ const params = {
20838
+ model: request.model,
20839
+ messages
20840
+ };
20841
+ if (request.tools && request.tools.length > 0) {
20842
+ params.tools = transformChatTools(request.tools);
20843
+ const toolChoice = transformChatToolChoice(request.toolChoice);
20844
+ if (toolChoice !== void 0) {
20845
+ params.tool_choice = toolChoice;
20846
+ }
20847
+ if (request.parallelToolCalls !== void 0) {
20848
+ params.parallel_tool_calls = request.parallelToolCalls;
20849
+ }
20850
+ }
20851
+ if (request.maxOutputTokens !== void 0) {
20852
+ params.max_tokens = request.maxOutputTokens;
20853
+ }
20854
+ if (request.temperature !== void 0) {
20855
+ params.temperature = request.temperature;
20856
+ }
20857
+ if (request.topP !== void 0) {
20858
+ params.top_p = request.topP;
20859
+ }
20860
+ if (request.reasoning?.level !== void 0) {
20861
+ const effortMap = {
20862
+ 10: "minimal",
20863
+ 33: "low",
20864
+ 66: "medium",
20865
+ 100: "high"
20866
+ };
20867
+ const effort = effortMap[request.reasoning.level];
20868
+ if (effort) {
20869
+ params.reasoning = { effort };
20870
+ }
20871
+ }
20872
+ if (request.responseFormat) {
20873
+ if (request.responseFormat.type === "json") {
20874
+ if (request.responseFormat.schema) {
20875
+ params.response_format = {
20876
+ type: "json_schema",
20877
+ json_schema: {
20878
+ name: "response",
20879
+ schema: request.responseFormat.schema,
20880
+ strict: true
20881
+ }
20882
+ };
20883
+ } else {
20884
+ params.response_format = { type: "json_object" };
20885
+ }
20886
+ }
20887
+ }
20888
+ if (request.providerOptions) {
20889
+ const { _metadata, ...safeOptions } = request.providerOptions;
20890
+ Object.assign(params, safeOptions);
20891
+ }
20892
+ return params;
20893
+ }
20894
+ function createChatErrorChunk(error, code) {
20895
+ return { type: "error", error, code };
20896
+ }
20897
+ function isBase64Like22(str) {
20898
+ if (str.startsWith("data:")) return true;
20899
+ if (str.length > 200) {
20900
+ const base64Pattern = /^[A-Za-z0-9+/]+=*$/;
20901
+ return base64Pattern.test(str.substring(0, 200));
20902
+ }
20903
+ return false;
20904
+ }
20905
+ function truncateBase64String22(str, maxLength = 50) {
20906
+ if (str.length <= maxLength) return str;
20907
+ const preview = str.substring(0, maxLength);
20908
+ return `${preview}...[truncated, ${str.length.toLocaleString()} chars]`;
20909
+ }
20910
+ function truncateChatBase64(obj, maxLength = 50) {
20911
+ if (obj === null || obj === void 0) {
20912
+ return obj;
20913
+ }
20914
+ if (typeof obj === "string") {
20915
+ if (isBase64Like22(obj)) {
20916
+ return truncateBase64String22(obj, maxLength);
20917
+ }
20918
+ return obj;
20919
+ }
20920
+ if (Array.isArray(obj)) {
20921
+ return obj.map((item) => truncateChatBase64(item, maxLength));
20922
+ }
20923
+ if (typeof obj === "object") {
20924
+ const result = {};
20925
+ for (const [key, value] of Object.entries(obj)) {
20926
+ result[key] = truncateChatBase64(value, maxLength);
20927
+ }
20928
+ return result;
20929
+ }
20930
+ return obj;
20931
+ }
20353
20932
  function svgToDataUri2(svg) {
20354
20933
  const encoded = encodeURIComponent(svg).replace(/'/g, "%27").replace(/"/g, "%22");
20355
20934
  return `data:image/svg+xml,${encoded}`;
@@ -20481,6 +21060,17 @@ var init_dist2 = __esm({
20481
21060
  constructor(config) {
20482
21061
  this.config = config;
20483
21062
  }
21063
+ /**
21064
+ * Determine which API to use for a request.
21065
+ * Checks request-level providerOptions first, then falls back to config.
21066
+ * Defaults to Chat Completions (stable API).
21067
+ */
21068
+ getApiMode(request) {
21069
+ if (request?.providerOptions?.useResponsesApi === true) {
21070
+ return "responses";
21071
+ }
21072
+ return "chat";
21073
+ }
20484
21074
  async getClient() {
20485
21075
  if (!this.client) {
20486
21076
  const { OpenRouter: OpenRouter2 } = await Promise.resolve().then(() => (init_esm(), esm_exports));
@@ -20617,6 +21207,53 @@ var init_dist2 = __esm({
20617
21207
  // Generation Methods
20618
21208
  // ============================================================================
20619
21209
  async generate(request) {
21210
+ const apiMode = this.getApiMode(request);
21211
+ if (apiMode === "responses") {
21212
+ return this.generateWithResponses(request);
21213
+ }
21214
+ return this.generateWithChat(request);
21215
+ }
21216
+ /**
21217
+ * Generate using the Chat Completions API (default).
21218
+ */
21219
+ async generateWithChat(request) {
21220
+ const apiKey = this.config.apiKey;
21221
+ const baseUrl = this.config.baseUrl || "https://openrouter.ai/api/v1";
21222
+ try {
21223
+ const params = buildChatParams(request);
21224
+ if (this.config.providers && this.config.providers.length > 0) {
21225
+ params.provider = { only: this.config.providers };
21226
+ }
21227
+ const response = await fetch(`${baseUrl}/chat/completions`, {
21228
+ method: "POST",
21229
+ headers: {
21230
+ "Content-Type": "application/json",
21231
+ "Authorization": `Bearer ${apiKey}`
21232
+ },
21233
+ body: JSON.stringify(params),
21234
+ signal: request.signal
21235
+ });
21236
+ if (!response.ok) {
21237
+ const errorText = await response.text();
21238
+ let errorMessage = `OpenRouter API error: ${response.status}`;
21239
+ try {
21240
+ const errorJson = JSON.parse(errorText);
21241
+ errorMessage = errorJson.error?.message || errorJson.message || errorMessage;
21242
+ } catch {
21243
+ errorMessage = errorText || errorMessage;
21244
+ }
21245
+ throw new ProviderError(errorMessage, "invalid_request", response.status);
21246
+ }
21247
+ const data = await response.json();
21248
+ return transformChatResponse(data);
21249
+ } catch (error) {
21250
+ throw this.toProviderError(error);
21251
+ }
21252
+ }
21253
+ /**
21254
+ * Generate using the Responses API (beta).
21255
+ */
21256
+ async generateWithResponses(request) {
20620
21257
  const client = await this.getClient();
20621
21258
  try {
20622
21259
  const params = buildCreateParams2(request);
@@ -20633,6 +21270,87 @@ var init_dist2 = __esm({
20633
21270
  }
20634
21271
  }
20635
21272
  async stream(request) {
21273
+ const apiMode = this.getApiMode(request);
21274
+ if (apiMode === "responses") {
21275
+ return this.streamWithResponses(request);
21276
+ }
21277
+ return this.streamWithChat(request);
21278
+ }
21279
+ /**
21280
+ * Stream using the Chat Completions API (default).
21281
+ */
21282
+ async streamWithChat(request) {
21283
+ const self = this;
21284
+ const apiKey = this.config.apiKey;
21285
+ const baseUrl = this.config.baseUrl || "https://openrouter.ai/api/v1";
21286
+ try {
21287
+ const params = buildChatParams(request);
21288
+ if (this.config.providers && this.config.providers.length > 0) {
21289
+ params.provider = { only: this.config.providers };
21290
+ }
21291
+ const response = await fetch(`${baseUrl}/chat/completions`, {
21292
+ method: "POST",
21293
+ headers: {
21294
+ "Content-Type": "application/json",
21295
+ "Authorization": `Bearer ${apiKey}`
21296
+ },
21297
+ body: JSON.stringify({
21298
+ ...params,
21299
+ stream: true,
21300
+ stream_options: { include_usage: true }
21301
+ }),
21302
+ signal: request.signal
21303
+ });
21304
+ if (!response.ok) {
21305
+ const errorText = await response.text();
21306
+ let errorMessage = `OpenRouter API error: ${response.status}`;
21307
+ try {
21308
+ const errorJson = JSON.parse(errorText);
21309
+ errorMessage = errorJson.error?.message || errorJson.message || errorMessage;
21310
+ } catch {
21311
+ errorMessage = errorText || errorMessage;
21312
+ }
21313
+ throw new ProviderError(errorMessage, "invalid_request", response.status);
21314
+ }
21315
+ return {
21316
+ async *[Symbol.asyncIterator]() {
21317
+ const state = createChatStreamState();
21318
+ let finishChunk = null;
21319
+ let responseId = null;
21320
+ try {
21321
+ for await (const chunk of parseChatSSEStream(response, state)) {
21322
+ if (chunk.type === "finish") {
21323
+ finishChunk = chunk;
21324
+ responseId = chunk.responseId || null;
21325
+ } else {
21326
+ yield chunk;
21327
+ }
21328
+ }
21329
+ if (finishChunk) {
21330
+ const finishWithMeta = {
21331
+ ...finishChunk,
21332
+ _asyncMetadata: responseId ? {
21333
+ generationId: responseId,
21334
+ apiKey,
21335
+ baseUrl
21336
+ } : void 0
21337
+ };
21338
+ yield finishWithMeta;
21339
+ }
21340
+ } catch (error) {
21341
+ const providerError = self.toProviderError(error);
21342
+ yield createChatErrorChunk(providerError.message, providerError.code);
21343
+ }
21344
+ }
21345
+ };
21346
+ } catch (error) {
21347
+ throw this.toProviderError(error);
21348
+ }
21349
+ }
21350
+ /**
21351
+ * Stream using the Responses API (beta).
21352
+ */
21353
+ async streamWithResponses(request) {
20636
21354
  const self = this;
20637
21355
  const apiKey = this.config.apiKey;
20638
21356
  const baseUrl = this.config.baseUrl || "https://openrouter.ai/api/v1";
@@ -20765,19 +21483,33 @@ var init_dist2 = __esm({
20765
21483
  // Inspection
20766
21484
  // ============================================================================
20767
21485
  /**
20768
- * Transform a ProviderRequest to OpenRouter Responses API format for inspection.
21486
+ * Transform a ProviderRequest to the appropriate API format for inspection.
20769
21487
  * Returns the exact request body that would be sent to OpenRouter, with base64 data truncated.
20770
21488
  */
20771
21489
  async inspectRequest(request) {
20772
- const params = buildCreateParams2(request);
21490
+ const apiMode = this.getApiMode(request);
21491
+ if (apiMode === "responses") {
21492
+ const params2 = buildCreateParams2(request);
21493
+ if (this.config.providers && this.config.providers.length > 0) {
21494
+ params2.provider = { only: this.config.providers };
21495
+ }
21496
+ return {
21497
+ body: truncateBase642(params2),
21498
+ messagesPath: "input",
21499
+ metadata: {
21500
+ endpoint: "https://openrouter.ai/api/v1/responses"
21501
+ }
21502
+ };
21503
+ }
21504
+ const params = buildChatParams(request);
20773
21505
  if (this.config.providers && this.config.providers.length > 0) {
20774
21506
  params.provider = { only: this.config.providers };
20775
21507
  }
20776
21508
  return {
20777
- body: truncateBase642(params),
20778
- messagesPath: "input",
21509
+ body: truncateChatBase64(params),
21510
+ messagesPath: "messages",
20779
21511
  metadata: {
20780
- endpoint: "https://openrouter.ai/api/v1/responses"
21512
+ endpoint: "https://openrouter.ai/api/v1/chat/completions"
20781
21513
  }
20782
21514
  };
20783
21515
  }
@@ -20846,7 +21578,17 @@ var init_dist2 = __esm({
20846
21578
  }).passthrough();
20847
21579
  openrouterProviderOptions = z.object({
20848
21580
  /** Provider routing configuration */
20849
- provider: providerRoutingSchema.optional()
21581
+ provider: providerRoutingSchema.optional(),
21582
+ /**
21583
+ * Use OpenRouter's Responses API (beta) instead of the Chat Completions API.
21584
+ *
21585
+ * By default, the provider uses the stable Chat Completions API.
21586
+ * Set this to true to use the Responses API which has some additional
21587
+ * features but may be less stable.
21588
+ *
21589
+ * @default false
21590
+ */
21591
+ useResponsesApi: z.boolean().optional()
20850
21592
  }).passthrough();
20851
21593
  openrouter = Object.assign(
20852
21594
  (config) => new OpenRouterProvider(config),