@deslop/workbench 0.0.360 → 0.0.381

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 (157) hide show
  1. package/dist/anthropic-C02QVQ9u.mjs +6313 -0
  2. package/dist/azure-openai-responses-CUFLNwdy.mjs +207 -0
  3. package/dist/client/assets/{(home)-DVKAaI4b.js → (home)-BL3S5BVq.js} +1 -1
  4. package/dist/client/assets/-workbench-terminal-YB9hQXjr.js +145 -0
  5. package/dist/client/assets/agent-BmwIVlVZ.js +1 -0
  6. package/dist/client/assets/agent-CE67X_hb.js +2 -0
  7. package/dist/client/assets/{arc-CuHXSNPr.js → arc-BjSQqbzd.js} +1 -1
  8. package/dist/client/assets/architectureDiagram-3BPJPVTR-CTWT1AFv.js +36 -0
  9. package/dist/client/assets/{blockDiagram-GPEHLZMM-D3jiL-uN.js → blockDiagram-GPEHLZMM-CISQUfO9.js} +1 -1
  10. package/dist/client/assets/{c4Diagram-AAUBKEIU-bA47L7u8.js → c4Diagram-AAUBKEIU-Ct3OGD9a.js} +1 -1
  11. package/dist/client/assets/channel-S3CdaK6m.js +1 -0
  12. package/dist/client/assets/{chunk-2J33WTMH-optplvap.js → chunk-2J33WTMH-BUMgKaV6.js} +1 -1
  13. package/dist/client/assets/{chunk-3OPIFGDE-k7mTnOn5.js → chunk-3OPIFGDE-BlIdNnu8.js} +1 -1
  14. package/dist/client/assets/{chunk-4BX2VUAB-Co5qfYem.js → chunk-4BX2VUAB-CiBu5cRv.js} +1 -1
  15. package/dist/client/assets/{chunk-55IACEB6-7AWIUH7L.js → chunk-55IACEB6-nU8KvKB3.js} +1 -1
  16. package/dist/client/assets/{chunk-5ZQYHXKU-Bub4jU0C.js → chunk-5ZQYHXKU-DbN9DSns.js} +1 -1
  17. package/dist/client/assets/{chunk-727SXJPM-DcofuxtV.js → chunk-727SXJPM-DkPu5ecB.js} +2 -2
  18. package/dist/client/assets/{chunk-AQP2D5EJ-CBwGmuY5.js → chunk-AQP2D5EJ-B8lrSg7a.js} +1 -1
  19. package/dist/client/assets/{chunk-BSJP7CBP-BInTsaMb.js → chunk-BSJP7CBP-C450xCVa.js} +1 -1
  20. package/dist/client/assets/{chunk-CSCIHK7Q-BTHSw3Fl.js → chunk-CSCIHK7Q-DoGVP1BZ.js} +2 -2
  21. package/dist/client/assets/{chunk-FMBD7UC4-BQD4ioRx.js → chunk-FMBD7UC4-cqorOok8.js} +1 -1
  22. package/dist/client/assets/{chunk-KSCS5N6A-CUDSaUx0.js → chunk-KSCS5N6A-dbmnxO_p.js} +1 -1
  23. package/dist/client/assets/{chunk-L5ZTLDWV-D0-tvK0S.js → chunk-L5ZTLDWV-D9P-YjsA.js} +1 -1
  24. package/dist/client/assets/{chunk-LZXEDZCA-BkJ5xlLM.js → chunk-LZXEDZCA-BdVT_AWc.js} +2 -2
  25. package/dist/client/assets/{chunk-ND2GUHAM-COdW9HuZ.js → chunk-ND2GUHAM-CmHIi1wD.js} +1 -1
  26. package/dist/client/assets/{chunk-NZK2D7GU-Byrnkfto.js → chunk-NZK2D7GU-hkTOm2qR.js} +1 -1
  27. package/dist/client/assets/{chunk-O5CBEL6O-C_CProRX.js → chunk-O5CBEL6O-D1fDxsSH.js} +1 -1
  28. package/dist/client/assets/chunk-QZHKN3VN-BS_CF_l3.js +1 -0
  29. package/dist/client/assets/chunk-WU5MYG2G-CtG2KJlt.js +1 -0
  30. package/dist/client/assets/{chunk-XPW4576I-DWr3727k.js → chunk-XPW4576I-BjBK3ctW.js} +2 -2
  31. package/dist/client/assets/classDiagram-4FO5ZUOK-BdTSUdNF.js +1 -0
  32. package/dist/client/assets/classDiagram-v2-Q7XG4LA2-BdTSUdNF.js +1 -0
  33. package/dist/client/assets/compiler-runtime-CLAvuQ-D.js +1 -0
  34. package/dist/client/assets/cose-bilkent-S5V4N54A-BGt2II16.js +1 -0
  35. package/dist/client/assets/{cytoscape.esm-FqbQrHcz.js → cytoscape.esm-Kic9WIU3.js} +2 -2
  36. package/dist/client/assets/{dagre-BM42HDAG-Bwiv8kFL.js → dagre-BM42HDAG-CN7Tha00.js} +1 -1
  37. package/dist/client/assets/{diagram-2AECGRRQ-BY9KXQPi.js → diagram-2AECGRRQ-DnobmroZ.js} +1 -1
  38. package/dist/client/assets/{diagram-5GNKFQAL-C-jmG8LL.js → diagram-5GNKFQAL-D6NqAeoi.js} +1 -1
  39. package/dist/client/assets/{diagram-KO2AKTUF-qDHWGr5P.js → diagram-KO2AKTUF-y8QX4vEL.js} +1 -1
  40. package/dist/client/assets/{diagram-LMA3HP47-Dg8zuIuL.js → diagram-LMA3HP47-DAEPoAHp.js} +1 -1
  41. package/dist/client/assets/{diagram-OG6HWLK6-DupmLmKo.js → diagram-OG6HWLK6-B3KiYvxM.js} +1 -1
  42. package/dist/client/assets/dialog-B0kBnYwI.js +153 -0
  43. package/dist/client/assets/diff-BP9B4x7R.js +2 -0
  44. package/dist/client/assets/diff-OmMK6IL0.js +221 -0
  45. package/dist/client/assets/dist-D9sYb5Oa.js +1 -0
  46. package/dist/client/assets/{erDiagram-TEJ5UH35-DcYoMsDA.js → erDiagram-TEJ5UH35-CbzdEpkS.js} +1 -1
  47. package/dist/client/assets/external-link-D7Q28KpR.js +1 -0
  48. package/dist/client/assets/fallbacks-DwGmG_0c.js +16 -0
  49. package/dist/client/assets/{flowDiagram-I6XJVG4X-xLfWiyaL.js → flowDiagram-I6XJVG4X-C2H7PQev.js} +1 -1
  50. package/dist/client/assets/ganttDiagram-6RSMTGT7-BZql2QFP.js +292 -0
  51. package/dist/client/assets/{gitGraphDiagram-PVQCEYII-DE7nmb1q.js → gitGraphDiagram-PVQCEYII-d2_5HIIo.js} +1 -1
  52. package/dist/client/assets/{index-D1icept3.js → index-Cc-cDoXa.js} +4 -4
  53. package/dist/client/assets/index-DT_QSnKQ.css +2 -0
  54. package/dist/client/assets/{infoDiagram-5YYISTIA-CUzdfhph.js → infoDiagram-5YYISTIA-DaDFMb3D.js} +1 -1
  55. package/dist/client/assets/input-CEh4Uy0l.js +1 -0
  56. package/dist/client/assets/{ishikawaDiagram-YF4QCWOH-D3h5fT3O.js → ishikawaDiagram-YF4QCWOH-7tWPtPSR.js} +1 -1
  57. package/dist/client/assets/{journeyDiagram-JHISSGLW-DXqP7IZk.js → journeyDiagram-JHISSGLW-CYDeiigr.js} +1 -1
  58. package/dist/client/assets/{kanban-definition-UN3LZRKU-BBdz3OGi.js → kanban-definition-UN3LZRKU-BFoF4JfY.js} +3 -3
  59. package/dist/client/assets/{katex-Vhh-h91d.js → katex-CddkPoXu.js} +1 -1
  60. package/dist/client/assets/{line-D2nnU070.js → line-CcJ0IOWh.js} +1 -1
  61. package/dist/client/assets/{linear-BifnMVyn.js → linear-Ct8JHF0c.js} +1 -1
  62. package/dist/client/assets/mermaid-parser.core-CKHoAf1J.js +2 -2
  63. package/dist/client/assets/{mindmap-definition-RKZ34NQL-BAbACAeS.js → mindmap-definition-RKZ34NQL-DTgZ_Z5F.js} +1 -1
  64. package/dist/client/assets/{pieDiagram-4H26LBE5-YjWBEaV3.js → pieDiagram-4H26LBE5-BmpbjVUG.js} +1 -1
  65. package/dist/client/assets/pierre-dark-vibrant-D4RhcSIK.js +1 -0
  66. package/dist/client/assets/pierre-light-vibrant-B76X7i5Y.js +1 -0
  67. package/dist/client/assets/portless-4_iTgOr5.js +1 -0
  68. package/dist/client/assets/portless-qyhmpSUj.js +2 -0
  69. package/dist/client/assets/{quadrantDiagram-W4KKPZXB-0qpR8bhI.js → quadrantDiagram-W4KKPZXB-BncnX7WL.js} +1 -1
  70. package/dist/client/assets/{requirementDiagram-4Y6WPE33-UxrH60_h.js → requirementDiagram-4Y6WPE33-C4viwYDb.js} +1 -1
  71. package/dist/client/assets/resizable-A9BpOcmt.js +1 -0
  72. package/dist/client/assets/route-Da0uHKH9.js +45 -0
  73. package/dist/client/assets/route-ULg8h9n0.js +2 -0
  74. package/dist/client/assets/run-CCCofwDU.js +2 -0
  75. package/dist/client/assets/run-D7w-8aQA.js +1 -0
  76. package/dist/client/assets/{sankeyDiagram-5OEKKPKP-CtfCq9EV.js → sankeyDiagram-5OEKKPKP-cs1kWOqp.js} +1 -1
  77. package/dist/client/assets/{sequenceDiagram-3UESZ5HK-BgLwmDnV.js → sequenceDiagram-3UESZ5HK-D7Bj1Dg6.js} +1 -1
  78. package/dist/client/assets/sonner-DgKrvTU1.js +1 -0
  79. package/dist/client/assets/src-DzxfdEt6.js +1 -0
  80. package/dist/client/assets/state-_2CmL5IM.js +2 -0
  81. package/dist/client/assets/{stateDiagram-AJRCARHV--lvnWH2s.js → stateDiagram-AJRCARHV-xBL-crbl.js} +1 -1
  82. package/dist/client/assets/stateDiagram-v2-BHNVJYJU-ZbAyaVmU.js +1 -0
  83. package/dist/client/assets/terminal-DJ8tjXNh.js +1 -0
  84. package/dist/client/assets/terminal-Dx10AUUW.js +2 -0
  85. package/dist/client/assets/{timeline-definition-PNZ67QCA-BbIMEZmJ.js → timeline-definition-PNZ67QCA-Bs3JkoMQ.js} +2 -2
  86. package/dist/client/assets/triangle-alert-cDPYgb7f.js +1 -0
  87. package/dist/client/assets/{vennDiagram-CIIHVFJN-ClrNZ6mc.js → vennDiagram-CIIHVFJN-D25dPloy.js} +1 -1
  88. package/dist/client/assets/{wardleyDiagram-YWT4CUSO-B104yVOC.js → wardleyDiagram-YWT4CUSO-B7X6xZZ7.js} +1 -1
  89. package/dist/client/assets/{xychartDiagram-2RQKCTM6-BBRSu-ZO.js → xychartDiagram-2RQKCTM6-Cgc-2R8L.js} +1 -1
  90. package/dist/client/index.html +13 -14
  91. package/dist/completionchunk-DDfxP5hO.mjs +5196 -0
  92. package/dist/dist-CsBDFjO2.mjs +1163 -0
  93. package/dist/{execAsync-BeHTdVKh.mjs → execAsync-B-b5b4hb.mjs} +2 -2
  94. package/dist/from-DGwFTZmN.mjs +3845 -0
  95. package/dist/{getMachineId-bsd-8V0SSHI2.mjs → getMachineId-bsd-C-aUDBo5.mjs} +4 -3
  96. package/dist/{getMachineId-darwin-fwMRmXNE.mjs → getMachineId-darwin-CQg0u9gI.mjs} +4 -3
  97. package/dist/{getMachineId-linux-BglPdw6k.mjs → getMachineId-linux-DQmpbzHz.mjs} +3 -2
  98. package/dist/{getMachineId-unsupported-B6r8oWEG.mjs → getMachineId-unsupported-BT4Te_jg.mjs} +3 -2
  99. package/dist/{getMachineId-win-Bvbq3C3K.mjs → getMachineId-win-zoUdci1a.mjs} +4 -3
  100. package/dist/github-copilot-headers-B--aVYl2.mjs +39 -0
  101. package/dist/google-DHtiCcEt.mjs +348 -0
  102. package/dist/google-shared-BT0mQb3v.mjs +25358 -0
  103. package/dist/google-vertex-CRkz0MgQ.mjs +391 -0
  104. package/dist/hash-CDrrQIkY.mjs +17 -0
  105. package/dist/headers-m19bM8_9.mjs +9 -0
  106. package/dist/mistral-DXtHhhUc.mjs +36806 -0
  107. package/dist/multipart-parser-6y-zJbR0.mjs +295 -0
  108. package/dist/openai-CUH8rb7p.mjs +6671 -0
  109. package/dist/openai-codex-responses-BSLixEC8.mjs +1081 -0
  110. package/dist/openai-completions-CE-LDmL4.mjs +735 -0
  111. package/dist/openai-prompt-cache-6hf3xB_x.mjs +9 -0
  112. package/dist/openai-responses-41QiypX_.mjs +217 -0
  113. package/dist/openai-responses-shared-BAoGGIxP.mjs +415 -0
  114. package/dist/openrouter-CDq1vETJ.mjs +125 -0
  115. package/dist/otel-ugdFQeJO.mjs +23177 -0
  116. package/dist/photon_rs-D6BNoOSO.mjs +4253 -0
  117. package/dist/rolldown-runtime-EQORzF3F.mjs +38 -0
  118. package/dist/sanitize-unicode-CPcy0g31.mjs +27 -0
  119. package/dist/server.js +247457 -56643
  120. package/dist/src-BHoXDvRK.mjs +1178 -0
  121. package/dist/transform-messages-CUKh2_5w.mjs +188 -0
  122. package/package.json +4 -3
  123. package/dist/client/assets/-workbench-terminal-CoufoT41.js +0 -145
  124. package/dist/client/assets/agent-B0AsYIb3.js +0 -2
  125. package/dist/client/assets/agent-DCVbbaGs.js +0 -1
  126. package/dist/client/assets/architectureDiagram-3BPJPVTR-hs4IN-ZW.js +0 -36
  127. package/dist/client/assets/button-Dz6Az3h_.js +0 -16
  128. package/dist/client/assets/channel-CHiC1IgU.js +0 -1
  129. package/dist/client/assets/chunk-QZHKN3VN-SFi3gsXX.js +0 -1
  130. package/dist/client/assets/chunk-WU5MYG2G-OzrGGim9.js +0 -1
  131. package/dist/client/assets/classDiagram-4FO5ZUOK-DvZGz7Ek.js +0 -1
  132. package/dist/client/assets/classDiagram-v2-Q7XG4LA2-DvZGz7Ek.js +0 -1
  133. package/dist/client/assets/compiler-runtime-rGeCHUuX.js +0 -1
  134. package/dist/client/assets/cose-bilkent-S5V4N54A-BzitJXTQ.js +0 -1
  135. package/dist/client/assets/diff-BqnMP7Ys.js +0 -217
  136. package/dist/client/assets/diff-CLnQZZVT.js +0 -2
  137. package/dist/client/assets/dist-lRkD-JPF.js +0 -1
  138. package/dist/client/assets/external-link-DPI4TAq4.js +0 -1
  139. package/dist/client/assets/fallbacks-uU4M5NOw.js +0 -1
  140. package/dist/client/assets/ganttDiagram-6RSMTGT7-hA3inn7u.js +0 -292
  141. package/dist/client/assets/index-DNWcrdqu.css +0 -2
  142. package/dist/client/assets/input-group-1-P7Y_75.js +0 -153
  143. package/dist/client/assets/loader-circle-BxillczB.js +0 -1
  144. package/dist/client/assets/portless-ClPWjTC4.js +0 -1
  145. package/dist/client/assets/portless-QJD7ZmA9.js +0 -2
  146. package/dist/client/assets/resizable-BaJ5ba6-.js +0 -1
  147. package/dist/client/assets/route-C-L2dkin.js +0 -45
  148. package/dist/client/assets/route-b5JXfzPO.js +0 -2
  149. package/dist/client/assets/run-C7DiKMnt.js +0 -1
  150. package/dist/client/assets/run-Dt91HvlA.js +0 -2
  151. package/dist/client/assets/src-oaGqIoNi.js +0 -1
  152. package/dist/client/assets/state-CVjPP5QG.js +0 -2
  153. package/dist/client/assets/stateDiagram-v2-BHNVJYJU-BggoNPhO.js +0 -1
  154. package/dist/client/assets/terminal-C4sv4xT5.js +0 -2
  155. package/dist/client/assets/terminal-kxE_eoTZ.js +0 -1
  156. package/dist/client/assets/triangle-alert-CTEZG9zF.js +0 -1
  157. /package/dist/client/assets/{chunk-QTnfLwEv.js → rolldown-runtime-QTnfLwEv.js} +0 -0
@@ -0,0 +1,735 @@
1
+ #!/usr/bin/env -S node --max-old-space-size=16384 --heapsnapshot-near-heap-limit=3 --report-on-fatalerror
2
+ import { Ir as calculateCost, Lr as clampThinkingLevel, Rr as getProviderEnvValue, Vr as registerApiProvider, jr as parseStreamingJson, zr as AssistantMessageEventStream } from "./server.js";
3
+ import { t as headersToRecord } from "./headers-m19bM8_9.mjs";
4
+ import { t as sanitizeSurrogates } from "./sanitize-unicode-CPcy0g31.mjs";
5
+ import { i as resolveCloudflareBaseUrl, n as hasCopilotVisionInput, r as isCloudflareProvider, t as buildCopilotDynamicHeaders } from "./github-copilot-headers-B--aVYl2.mjs";
6
+ import { r as buildBaseOptions, t as transformMessages } from "./transform-messages-CUKh2_5w.mjs";
7
+ import { n as OpenAI } from "./openai-CUH8rb7p.mjs";
8
+ import { t as clampOpenAIPromptCacheKey } from "./openai-prompt-cache-6hf3xB_x.mjs";
9
+ //#region ../../node_modules/.pnpm/@earendil-works+pi-ai@0.79.8_@modelcontextprotocol+sdk@1.29.0_zod@4.4.3__ws@8.21.0_zod@4.4.3/node_modules/@earendil-works/pi-ai/dist/providers/openai-completions.js
10
+ /**
11
+ * Check if conversation messages contain tool calls or tool results.
12
+ * This is needed because Anthropic (via proxy) requires the tools param
13
+ * to be present when messages include tool_calls or tool role messages.
14
+ */
15
+ function hasToolHistory(messages) {
16
+ for (const msg of messages) {
17
+ if (msg.role === "toolResult") return true;
18
+ if (msg.role === "assistant") {
19
+ if (msg.content.some((block) => block.type === "toolCall")) return true;
20
+ }
21
+ }
22
+ return false;
23
+ }
24
+ function isTextContentBlock(block) {
25
+ return block.type === "text";
26
+ }
27
+ function isThinkingContentBlock(block) {
28
+ return block.type === "thinking";
29
+ }
30
+ function isToolCallBlock(block) {
31
+ return block.type === "toolCall";
32
+ }
33
+ function isImageContentBlock(block) {
34
+ return block.type === "image";
35
+ }
36
+ function resolveCacheRetention(cacheRetention, env) {
37
+ if (cacheRetention) return cacheRetention;
38
+ if (getProviderEnvValue("PI_CACHE_RETENTION", env) === "long") return "long";
39
+ return "short";
40
+ }
41
+ const streamOpenAICompletions = (model, context, options) => {
42
+ const stream = new AssistantMessageEventStream();
43
+ (async () => {
44
+ const output = {
45
+ role: "assistant",
46
+ content: [],
47
+ api: model.api,
48
+ provider: model.provider,
49
+ model: model.id,
50
+ usage: {
51
+ input: 0,
52
+ output: 0,
53
+ cacheRead: 0,
54
+ cacheWrite: 0,
55
+ totalTokens: 0,
56
+ cost: {
57
+ input: 0,
58
+ output: 0,
59
+ cacheRead: 0,
60
+ cacheWrite: 0,
61
+ total: 0
62
+ }
63
+ },
64
+ stopReason: "stop",
65
+ timestamp: Date.now()
66
+ };
67
+ try {
68
+ const apiKey = options?.apiKey;
69
+ if (!apiKey) throw new Error(`No API key for provider: ${model.provider}`);
70
+ const compat = getCompat(model);
71
+ const cacheRetention = resolveCacheRetention(options?.cacheRetention, options?.env);
72
+ const cacheSessionId = cacheRetention === "none" ? void 0 : options?.sessionId;
73
+ const client = createClient(model, context, apiKey, options?.headers, cacheSessionId, compat, options?.env);
74
+ let params = buildParams(model, context, options, compat, cacheRetention);
75
+ const nextParams = await options?.onPayload?.(params, model);
76
+ if (nextParams !== void 0) params = nextParams;
77
+ const requestOptions = {
78
+ ...options?.signal ? { signal: options.signal } : {},
79
+ ...options?.timeoutMs !== void 0 ? { timeout: options.timeoutMs } : {},
80
+ maxRetries: options?.maxRetries ?? 0
81
+ };
82
+ const { data: openaiStream, response } = await client.chat.completions.create(params, requestOptions).withResponse();
83
+ await options?.onResponse?.({
84
+ status: response.status,
85
+ headers: headersToRecord(response.headers)
86
+ }, model);
87
+ stream.push({
88
+ type: "start",
89
+ partial: output
90
+ });
91
+ let textBlock = null;
92
+ let thinkingBlock = null;
93
+ let hasFinishReason = false;
94
+ const toolCallBlocksByIndex = /* @__PURE__ */ new Map();
95
+ const toolCallBlocksById = /* @__PURE__ */ new Map();
96
+ const blocks = output.content;
97
+ const getContentIndex = (block) => blocks.indexOf(block);
98
+ const finishBlock = (block) => {
99
+ const contentIndex = getContentIndex(block);
100
+ if (contentIndex === -1) return;
101
+ if (block.type === "text") stream.push({
102
+ type: "text_end",
103
+ contentIndex,
104
+ content: block.text,
105
+ partial: output
106
+ });
107
+ else if (block.type === "thinking") stream.push({
108
+ type: "thinking_end",
109
+ contentIndex,
110
+ content: block.thinking,
111
+ partial: output
112
+ });
113
+ else if (block.type === "toolCall") {
114
+ block.arguments = parseStreamingJson(block.partialArgs);
115
+ delete block.partialArgs;
116
+ delete block.streamIndex;
117
+ stream.push({
118
+ type: "toolcall_end",
119
+ contentIndex,
120
+ toolCall: block,
121
+ partial: output
122
+ });
123
+ }
124
+ };
125
+ const ensureTextBlock = () => {
126
+ if (!textBlock) {
127
+ textBlock = {
128
+ type: "text",
129
+ text: ""
130
+ };
131
+ blocks.push(textBlock);
132
+ stream.push({
133
+ type: "text_start",
134
+ contentIndex: getContentIndex(textBlock),
135
+ partial: output
136
+ });
137
+ }
138
+ return textBlock;
139
+ };
140
+ const ensureThinkingBlock = (thinkingSignature) => {
141
+ if (!thinkingBlock) {
142
+ thinkingBlock = {
143
+ type: "thinking",
144
+ thinking: "",
145
+ thinkingSignature
146
+ };
147
+ blocks.push(thinkingBlock);
148
+ stream.push({
149
+ type: "thinking_start",
150
+ contentIndex: getContentIndex(thinkingBlock),
151
+ partial: output
152
+ });
153
+ }
154
+ return thinkingBlock;
155
+ };
156
+ const ensureToolCallBlock = (toolCall) => {
157
+ const streamIndex = typeof toolCall.index === "number" ? toolCall.index : void 0;
158
+ let block = streamIndex !== void 0 ? toolCallBlocksByIndex.get(streamIndex) : void 0;
159
+ if (!block && toolCall.id) block = toolCallBlocksById.get(toolCall.id);
160
+ if (!block) {
161
+ block = {
162
+ type: "toolCall",
163
+ id: toolCall.id || "",
164
+ name: toolCall.function?.name || "",
165
+ arguments: {},
166
+ partialArgs: "",
167
+ streamIndex
168
+ };
169
+ if (streamIndex !== void 0) toolCallBlocksByIndex.set(streamIndex, block);
170
+ if (toolCall.id) toolCallBlocksById.set(toolCall.id, block);
171
+ blocks.push(block);
172
+ stream.push({
173
+ type: "toolcall_start",
174
+ contentIndex: getContentIndex(block),
175
+ partial: output
176
+ });
177
+ }
178
+ if (streamIndex !== void 0 && block.streamIndex === void 0) {
179
+ block.streamIndex = streamIndex;
180
+ toolCallBlocksByIndex.set(streamIndex, block);
181
+ }
182
+ if (toolCall.id) toolCallBlocksById.set(toolCall.id, block);
183
+ return block;
184
+ };
185
+ for await (const chunk of openaiStream) {
186
+ if (!chunk || typeof chunk !== "object") continue;
187
+ output.responseId ||= chunk.id;
188
+ if (typeof chunk.model === "string" && chunk.model.length > 0 && chunk.model !== model.id) output.responseModel ||= chunk.model;
189
+ if (chunk.usage) output.usage = parseChunkUsage(chunk.usage, model);
190
+ const choice = Array.isArray(chunk.choices) ? chunk.choices[0] : void 0;
191
+ if (!choice) continue;
192
+ if (!chunk.usage && choice.usage) output.usage = parseChunkUsage(choice.usage, model);
193
+ if (choice.finish_reason) {
194
+ const finishReasonResult = mapStopReason(choice.finish_reason);
195
+ output.stopReason = finishReasonResult.stopReason;
196
+ if (finishReasonResult.errorMessage) output.errorMessage = finishReasonResult.errorMessage;
197
+ hasFinishReason = true;
198
+ }
199
+ if (choice.delta) {
200
+ if (choice.delta.content !== null && choice.delta.content !== void 0 && choice.delta.content.length > 0) {
201
+ const block = ensureTextBlock();
202
+ block.text += choice.delta.content;
203
+ stream.push({
204
+ type: "text_delta",
205
+ contentIndex: getContentIndex(block),
206
+ delta: choice.delta.content,
207
+ partial: output
208
+ });
209
+ }
210
+ const reasoningFields = [
211
+ "reasoning_content",
212
+ "reasoning",
213
+ "reasoning_text"
214
+ ];
215
+ const deltaFields = choice.delta;
216
+ let foundReasoningField = null;
217
+ for (const field of reasoningFields) {
218
+ const value = deltaFields[field];
219
+ if (typeof value === "string" && value.length > 0) {
220
+ foundReasoningField = field;
221
+ break;
222
+ }
223
+ }
224
+ if (foundReasoningField) {
225
+ const delta = deltaFields[foundReasoningField];
226
+ if (typeof delta === "string" && delta.length > 0) {
227
+ const block = ensureThinkingBlock(model.provider === "opencode-go" && foundReasoningField === "reasoning" ? "reasoning_content" : foundReasoningField);
228
+ block.thinking += delta;
229
+ stream.push({
230
+ type: "thinking_delta",
231
+ contentIndex: getContentIndex(block),
232
+ delta,
233
+ partial: output
234
+ });
235
+ }
236
+ }
237
+ if (choice?.delta?.tool_calls) for (const toolCall of choice.delta.tool_calls) {
238
+ const block = ensureToolCallBlock(toolCall);
239
+ if (!block.id && toolCall.id) {
240
+ block.id = toolCall.id;
241
+ toolCallBlocksById.set(toolCall.id, block);
242
+ }
243
+ if (!block.name && toolCall.function?.name) block.name = toolCall.function.name;
244
+ let delta = "";
245
+ if (toolCall.function?.arguments) {
246
+ delta = toolCall.function.arguments;
247
+ block.partialArgs = (block.partialArgs ?? "") + toolCall.function.arguments;
248
+ block.arguments = parseStreamingJson(block.partialArgs);
249
+ }
250
+ stream.push({
251
+ type: "toolcall_delta",
252
+ contentIndex: getContentIndex(block),
253
+ delta,
254
+ partial: output
255
+ });
256
+ }
257
+ const reasoningDetails = choice.delta.reasoning_details;
258
+ if (reasoningDetails && Array.isArray(reasoningDetails)) {
259
+ for (const detail of reasoningDetails) if (detail.type === "reasoning.encrypted" && detail.id && detail.data) {
260
+ const matchingToolCall = output.content.find((b) => b.type === "toolCall" && b.id === detail.id);
261
+ if (matchingToolCall) matchingToolCall.thoughtSignature = JSON.stringify(detail);
262
+ }
263
+ }
264
+ }
265
+ }
266
+ for (const block of blocks) finishBlock(block);
267
+ if (options?.signal?.aborted) throw new Error("Request was aborted");
268
+ if (output.stopReason === "aborted") throw new Error("Request was aborted");
269
+ if (output.stopReason === "error") throw new Error(output.errorMessage || "Provider returned an error stop reason");
270
+ if (!hasFinishReason) throw new Error("Stream ended without finish_reason");
271
+ stream.push({
272
+ type: "done",
273
+ reason: output.stopReason,
274
+ message: output
275
+ });
276
+ stream.end();
277
+ } catch (error) {
278
+ for (const block of output.content) {
279
+ delete block.index;
280
+ delete block.partialArgs;
281
+ delete block.streamIndex;
282
+ }
283
+ output.stopReason = options?.signal?.aborted ? "aborted" : "error";
284
+ output.errorMessage = error instanceof Error ? error.message : JSON.stringify(error);
285
+ const rawMetadata = error?.error?.metadata?.raw;
286
+ if (rawMetadata) output.errorMessage += `\n${rawMetadata}`;
287
+ stream.push({
288
+ type: "error",
289
+ reason: output.stopReason,
290
+ error: output
291
+ });
292
+ stream.end();
293
+ }
294
+ })();
295
+ return stream;
296
+ };
297
+ const streamSimpleOpenAICompletions = (model, context, options) => {
298
+ const apiKey = options?.apiKey;
299
+ if (!apiKey) throw new Error(`No API key for provider: ${model.provider}`);
300
+ const base = buildBaseOptions(model, options, apiKey);
301
+ const clampedReasoning = options?.reasoning ? clampThinkingLevel(model, options.reasoning) : void 0;
302
+ const reasoningEffort = clampedReasoning === "off" ? void 0 : clampedReasoning;
303
+ const toolChoice = options?.toolChoice;
304
+ return streamOpenAICompletions(model, context, {
305
+ ...base,
306
+ reasoningEffort,
307
+ toolChoice
308
+ });
309
+ };
310
+ function register() {
311
+ registerApiProvider({
312
+ api: "openai-completions",
313
+ stream: streamOpenAICompletions,
314
+ streamSimple: streamSimpleOpenAICompletions
315
+ });
316
+ }
317
+ function createClient(model, context, apiKey, optionsHeaders, sessionId, compat = getCompat(model), env) {
318
+ const headers = { ...model.headers };
319
+ if (model.provider === "github-copilot") {
320
+ const hasImages = hasCopilotVisionInput(context.messages);
321
+ const copilotHeaders = buildCopilotDynamicHeaders({
322
+ messages: context.messages,
323
+ hasImages
324
+ });
325
+ Object.assign(headers, copilotHeaders);
326
+ }
327
+ if (sessionId && compat.sendSessionAffinityHeaders) {
328
+ headers.session_id = sessionId;
329
+ headers["x-client-request-id"] = sessionId;
330
+ headers["x-session-affinity"] = sessionId;
331
+ }
332
+ if (optionsHeaders) Object.assign(headers, optionsHeaders);
333
+ const defaultHeaders = model.provider === "cloudflare-ai-gateway" ? {
334
+ ...headers,
335
+ Authorization: headers.Authorization ?? null,
336
+ "cf-aig-authorization": `Bearer ${apiKey}`
337
+ } : headers;
338
+ return new OpenAI({
339
+ apiKey,
340
+ baseURL: isCloudflareProvider(model.provider) ? resolveCloudflareBaseUrl(model, env) : model.baseUrl,
341
+ dangerouslyAllowBrowser: true,
342
+ defaultHeaders
343
+ });
344
+ }
345
+ function buildParams(model, context, options, compat = getCompat(model), cacheRetention = resolveCacheRetention(options?.cacheRetention, options?.env)) {
346
+ const messages = convertMessages(model, context, compat);
347
+ const cacheControl = getCompatCacheControl(compat, cacheRetention);
348
+ const params = {
349
+ model: model.id,
350
+ messages,
351
+ stream: true,
352
+ prompt_cache_key: model.baseUrl.includes("api.openai.com") && cacheRetention !== "none" || cacheRetention === "long" && compat.supportsLongCacheRetention ? clampOpenAIPromptCacheKey(options?.sessionId) : void 0,
353
+ prompt_cache_retention: cacheRetention === "long" && compat.supportsLongCacheRetention ? "24h" : void 0
354
+ };
355
+ if (compat.supportsUsageInStreaming !== false) params.stream_options = { include_usage: true };
356
+ if (compat.supportsStore) params.store = false;
357
+ if (options?.maxTokens) if (compat.maxTokensField === "max_tokens") params.max_tokens = options.maxTokens;
358
+ else params.max_completion_tokens = options.maxTokens;
359
+ if (options?.temperature !== void 0) params.temperature = options.temperature;
360
+ if (context.tools && context.tools.length > 0) {
361
+ params.tools = convertTools(context.tools, compat);
362
+ if (compat.zaiToolStream) params.tool_stream = true;
363
+ } else if (hasToolHistory(context.messages)) params.tools = [];
364
+ if (cacheControl) applyAnthropicCacheControl(messages, params.tools, cacheControl);
365
+ if (options?.toolChoice) params.tool_choice = options.toolChoice;
366
+ if (compat.thinkingFormat === "zai" && model.reasoning) {
367
+ const zaiParams = params;
368
+ zaiParams.thinking = { type: options?.reasoningEffort ? "enabled" : "disabled" };
369
+ if (options?.reasoningEffort && compat.supportsReasoningEffort) {
370
+ const mappedEffort = model.thinkingLevelMap?.[options.reasoningEffort];
371
+ const effort = mappedEffort === void 0 ? options.reasoningEffort : mappedEffort;
372
+ if (typeof effort === "string") zaiParams.reasoning_effort = effort;
373
+ }
374
+ } else if (compat.thinkingFormat === "qwen" && model.reasoning) params.enable_thinking = !!options?.reasoningEffort;
375
+ else if (compat.thinkingFormat === "qwen-chat-template" && model.reasoning) params.chat_template_kwargs = {
376
+ enable_thinking: !!options?.reasoningEffort,
377
+ preserve_thinking: true
378
+ };
379
+ else if (compat.thinkingFormat === "deepseek" && model.reasoning) {
380
+ if (options?.reasoningEffort) params.thinking = { type: "enabled" };
381
+ else if (model.thinkingLevelMap?.off !== null) params.thinking = { type: "disabled" };
382
+ if (options?.reasoningEffort && compat.supportsReasoningEffort) params.reasoning_effort = model.thinkingLevelMap?.[options.reasoningEffort] ?? options.reasoningEffort;
383
+ } else if (compat.thinkingFormat === "openrouter" && model.reasoning) {
384
+ const openRouterParams = params;
385
+ if (options?.reasoningEffort) openRouterParams.reasoning = { effort: model.thinkingLevelMap?.[options.reasoningEffort] ?? options.reasoningEffort };
386
+ else if (model.thinkingLevelMap?.off !== null) openRouterParams.reasoning = { effort: model.thinkingLevelMap?.off ?? "none" };
387
+ } else if (compat.thinkingFormat === "ant-ling" && model.reasoning && options?.reasoningEffort) {
388
+ const effort = model.thinkingLevelMap?.[options.reasoningEffort];
389
+ if (typeof effort === "string") params.reasoning = { effort };
390
+ } else if (compat.thinkingFormat === "together" && model.reasoning) {
391
+ const togetherParams = params;
392
+ togetherParams.reasoning = { enabled: !!options?.reasoningEffort };
393
+ if (options?.reasoningEffort && compat.supportsReasoningEffort) togetherParams.reasoning_effort = model.thinkingLevelMap?.[options.reasoningEffort] ?? options.reasoningEffort;
394
+ } else if (compat.thinkingFormat === "string-thinking" && model.reasoning) {
395
+ const stringThinkingParams = params;
396
+ if (options?.reasoningEffort) stringThinkingParams.thinking = model.thinkingLevelMap?.[options.reasoningEffort] ?? options.reasoningEffort;
397
+ else if (model.thinkingLevelMap?.off !== null) stringThinkingParams.thinking = model.thinkingLevelMap?.off ?? "none";
398
+ } else if (options?.reasoningEffort && model.reasoning && compat.supportsReasoningEffort) params.reasoning_effort = model.thinkingLevelMap?.[options.reasoningEffort] ?? options.reasoningEffort;
399
+ else if (!options?.reasoningEffort && model.reasoning && compat.supportsReasoningEffort) {
400
+ const offValue = model.thinkingLevelMap?.off;
401
+ if (typeof offValue === "string") params.reasoning_effort = offValue;
402
+ }
403
+ if (model.compat?.openRouterRouting) params.provider = model.compat.openRouterRouting;
404
+ if (model.baseUrl.includes("ai-gateway.vercel.sh") && model.compat?.vercelGatewayRouting) {
405
+ const routing = model.compat.vercelGatewayRouting;
406
+ if (routing.only || routing.order) {
407
+ const gatewayOptions = {};
408
+ if (routing.only) gatewayOptions.only = routing.only;
409
+ if (routing.order) gatewayOptions.order = routing.order;
410
+ params.providerOptions = { gateway: gatewayOptions };
411
+ }
412
+ }
413
+ return params;
414
+ }
415
+ function getCompatCacheControl(compat, cacheRetention) {
416
+ if (compat.cacheControlFormat !== "anthropic" || cacheRetention === "none") return;
417
+ const ttl = cacheRetention === "long" && compat.supportsLongCacheRetention ? "1h" : void 0;
418
+ return {
419
+ type: "ephemeral",
420
+ ...ttl ? { ttl } : {}
421
+ };
422
+ }
423
+ function applyAnthropicCacheControl(messages, tools, cacheControl) {
424
+ addCacheControlToSystemPrompt(messages, cacheControl);
425
+ addCacheControlToLastTool(tools, cacheControl);
426
+ addCacheControlToLastConversationMessage(messages, cacheControl);
427
+ }
428
+ function addCacheControlToSystemPrompt(messages, cacheControl) {
429
+ for (const message of messages) if (message.role === "system" || message.role === "developer") {
430
+ addCacheControlToInstructionMessage(message, cacheControl);
431
+ return;
432
+ }
433
+ }
434
+ function addCacheControlToLastConversationMessage(messages, cacheControl) {
435
+ for (let i = messages.length - 1; i >= 0; i--) {
436
+ const message = messages[i];
437
+ if (message.role === "user" || message.role === "assistant") {
438
+ if (addCacheControlToMessage(message, cacheControl)) return;
439
+ }
440
+ }
441
+ }
442
+ function addCacheControlToLastTool(tools, cacheControl) {
443
+ if (!tools || tools.length === 0) return;
444
+ const lastTool = tools[tools.length - 1];
445
+ lastTool.cache_control = cacheControl;
446
+ }
447
+ function addCacheControlToInstructionMessage(message, cacheControl) {
448
+ return addCacheControlToTextContent(message, cacheControl);
449
+ }
450
+ function addCacheControlToMessage(message, cacheControl) {
451
+ if (message.role === "user" || message.role === "assistant") return addCacheControlToTextContent(message, cacheControl);
452
+ return false;
453
+ }
454
+ function addCacheControlToTextContent(message, cacheControl) {
455
+ const content = message.content;
456
+ if (typeof content === "string") {
457
+ if (content.length === 0) return false;
458
+ message.content = [{
459
+ type: "text",
460
+ text: content,
461
+ cache_control: cacheControl
462
+ }];
463
+ return true;
464
+ }
465
+ if (!Array.isArray(content)) return false;
466
+ for (let i = content.length - 1; i >= 0; i--) {
467
+ const part = content[i];
468
+ if (part?.type === "text") {
469
+ const textPart = part;
470
+ textPart.cache_control = cacheControl;
471
+ return true;
472
+ }
473
+ }
474
+ return false;
475
+ }
476
+ function convertMessages(model, context, compat) {
477
+ const params = [];
478
+ const normalizeToolCallId = (id) => {
479
+ if (id.includes("|")) {
480
+ const [callId] = id.split("|");
481
+ return callId.replace(/[^a-zA-Z0-9_-]/g, "_").slice(0, 40);
482
+ }
483
+ if (model.provider === "openai") return id.length > 40 ? id.slice(0, 40) : id;
484
+ return id;
485
+ };
486
+ const transformedMessages = transformMessages(context.messages, model, (id) => normalizeToolCallId(id));
487
+ if (context.systemPrompt) {
488
+ const role = model.reasoning && compat.supportsDeveloperRole ? "developer" : "system";
489
+ params.push({
490
+ role,
491
+ content: sanitizeSurrogates(context.systemPrompt)
492
+ });
493
+ }
494
+ let lastRole = null;
495
+ for (let i = 0; i < transformedMessages.length; i++) {
496
+ const msg = transformedMessages[i];
497
+ if (compat.requiresAssistantAfterToolResult && lastRole === "toolResult" && msg.role === "user") params.push({
498
+ role: "assistant",
499
+ content: "I have processed the tool results."
500
+ });
501
+ if (msg.role === "user") if (typeof msg.content === "string") params.push({
502
+ role: "user",
503
+ content: sanitizeSurrogates(msg.content)
504
+ });
505
+ else {
506
+ const content = msg.content.map((item) => {
507
+ if (item.type === "text") return {
508
+ type: "text",
509
+ text: sanitizeSurrogates(item.text)
510
+ };
511
+ else return {
512
+ type: "image_url",
513
+ image_url: { url: `data:${item.mimeType};base64,${item.data}` }
514
+ };
515
+ });
516
+ if (content.length === 0) continue;
517
+ params.push({
518
+ role: "user",
519
+ content
520
+ });
521
+ }
522
+ else if (msg.role === "assistant") {
523
+ const assistantMsg = {
524
+ role: "assistant",
525
+ content: compat.requiresAssistantAfterToolResult ? "" : null
526
+ };
527
+ const assistantTextParts = msg.content.filter(isTextContentBlock).filter((block) => block.text.trim().length > 0).map((block) => ({
528
+ type: "text",
529
+ text: sanitizeSurrogates(block.text)
530
+ }));
531
+ const assistantText = assistantTextParts.map((part) => part.text).join("");
532
+ const nonEmptyThinkingBlocks = msg.content.filter(isThinkingContentBlock).filter((block) => block.thinking.trim().length > 0);
533
+ if (nonEmptyThinkingBlocks.length > 0) if (compat.requiresThinkingAsText) assistantMsg.content = [{
534
+ type: "text",
535
+ text: nonEmptyThinkingBlocks.map((block) => sanitizeSurrogates(block.thinking)).join("\n\n")
536
+ }, ...assistantTextParts];
537
+ else {
538
+ if (assistantText.length > 0) assistantMsg.content = assistantText;
539
+ let signature = nonEmptyThinkingBlocks[0].thinkingSignature;
540
+ if (model.provider === "opencode-go" && signature === "reasoning") signature = "reasoning_content";
541
+ if (signature && signature.length > 0) assistantMsg[signature] = nonEmptyThinkingBlocks.map((block) => block.thinking).join("\n");
542
+ }
543
+ else if (assistantText.length > 0) assistantMsg.content = assistantText;
544
+ const toolCalls = msg.content.filter(isToolCallBlock);
545
+ if (toolCalls.length > 0) {
546
+ assistantMsg.tool_calls = toolCalls.map((tc) => ({
547
+ id: tc.id,
548
+ type: "function",
549
+ function: {
550
+ name: tc.name,
551
+ arguments: JSON.stringify(tc.arguments)
552
+ }
553
+ }));
554
+ const reasoningDetails = toolCalls.filter((tc) => tc.thoughtSignature).map((tc) => {
555
+ try {
556
+ return JSON.parse(tc.thoughtSignature);
557
+ } catch {
558
+ return null;
559
+ }
560
+ }).filter(Boolean);
561
+ if (reasoningDetails.length > 0) assistantMsg.reasoning_details = reasoningDetails;
562
+ }
563
+ if (compat.requiresReasoningContentOnAssistantMessages && model.reasoning && assistantMsg.reasoning_content === void 0) assistantMsg.reasoning_content = "";
564
+ const content = assistantMsg.content;
565
+ if (!(content !== null && content !== void 0 && (typeof content === "string" ? content.length > 0 : content.length > 0)) && !assistantMsg.tool_calls) continue;
566
+ params.push(assistantMsg);
567
+ } else if (msg.role === "toolResult") {
568
+ const imageBlocks = [];
569
+ let j = i;
570
+ for (; j < transformedMessages.length && transformedMessages[j].role === "toolResult"; j++) {
571
+ const toolMsg = transformedMessages[j];
572
+ const textResult = toolMsg.content.filter(isTextContentBlock).map((block) => block.text).join("\n");
573
+ const hasImages = toolMsg.content.some((c) => c.type === "image");
574
+ const toolResultMsg = {
575
+ role: "tool",
576
+ content: sanitizeSurrogates(textResult.length > 0 ? textResult : "(see attached image)"),
577
+ tool_call_id: toolMsg.toolCallId
578
+ };
579
+ if (compat.requiresToolResultName && toolMsg.toolName) toolResultMsg.name = toolMsg.toolName;
580
+ params.push(toolResultMsg);
581
+ if (hasImages && model.input.includes("image")) {
582
+ for (const block of toolMsg.content) if (isImageContentBlock(block)) imageBlocks.push({
583
+ type: "image_url",
584
+ image_url: { url: `data:${block.mimeType};base64,${block.data}` }
585
+ });
586
+ }
587
+ }
588
+ i = j - 1;
589
+ if (imageBlocks.length > 0) {
590
+ if (compat.requiresAssistantAfterToolResult) params.push({
591
+ role: "assistant",
592
+ content: "I have processed the tool results."
593
+ });
594
+ params.push({
595
+ role: "user",
596
+ content: [{
597
+ type: "text",
598
+ text: "Attached image(s) from tool result:"
599
+ }, ...imageBlocks]
600
+ });
601
+ lastRole = "user";
602
+ } else lastRole = "toolResult";
603
+ continue;
604
+ }
605
+ lastRole = msg.role;
606
+ }
607
+ return params;
608
+ }
609
+ function convertTools(tools, compat) {
610
+ return tools.map((tool) => ({
611
+ type: "function",
612
+ function: {
613
+ name: tool.name,
614
+ description: tool.description,
615
+ parameters: tool.parameters,
616
+ ...compat.supportsStrictMode !== false && { strict: false }
617
+ }
618
+ }));
619
+ }
620
+ function parseChunkUsage(rawUsage, model) {
621
+ const promptTokens = rawUsage.prompt_tokens || 0;
622
+ const cacheReadTokens = rawUsage.prompt_tokens_details?.cached_tokens ?? rawUsage.prompt_cache_hit_tokens ?? 0;
623
+ const cacheWriteTokens = rawUsage.prompt_tokens_details?.cache_write_tokens || 0;
624
+ const input = Math.max(0, promptTokens - cacheReadTokens - cacheWriteTokens);
625
+ const outputTokens = rawUsage.completion_tokens || 0;
626
+ const usage = {
627
+ input,
628
+ output: outputTokens,
629
+ cacheRead: cacheReadTokens,
630
+ cacheWrite: cacheWriteTokens,
631
+ totalTokens: input + outputTokens + cacheReadTokens + cacheWriteTokens,
632
+ cost: {
633
+ input: 0,
634
+ output: 0,
635
+ cacheRead: 0,
636
+ cacheWrite: 0,
637
+ total: 0
638
+ }
639
+ };
640
+ calculateCost(model, usage);
641
+ return usage;
642
+ }
643
+ function mapStopReason(reason) {
644
+ if (reason === null) return { stopReason: "stop" };
645
+ switch (reason) {
646
+ case "stop":
647
+ case "end": return { stopReason: "stop" };
648
+ case "length": return { stopReason: "length" };
649
+ case "function_call":
650
+ case "tool_calls": return { stopReason: "toolUse" };
651
+ case "content_filter": return {
652
+ stopReason: "error",
653
+ errorMessage: "Provider finish_reason: content_filter"
654
+ };
655
+ case "network_error": return {
656
+ stopReason: "error",
657
+ errorMessage: "Provider finish_reason: network_error"
658
+ };
659
+ default: return {
660
+ stopReason: "error",
661
+ errorMessage: `Provider finish_reason: ${reason}`
662
+ };
663
+ }
664
+ }
665
+ /**
666
+ * Detect compatibility settings from provider and baseUrl for known providers.
667
+ * Provider takes precedence over URL-based detection since it's explicitly configured.
668
+ * Returns a fully resolved OpenAICompletionsCompat object with all fields set.
669
+ */
670
+ function detectCompat(model) {
671
+ const provider = model.provider;
672
+ const baseUrl = model.baseUrl;
673
+ const isZai = provider === "zai" || provider === "zai-coding-cn" || baseUrl.includes("api.z.ai") || baseUrl.includes("open.bigmodel.cn");
674
+ const isTogether = provider === "together" || baseUrl.includes("api.together.ai") || baseUrl.includes("api.together.xyz");
675
+ const isMoonshot = provider === "moonshotai" || provider === "moonshotai-cn" || baseUrl.includes("api.moonshot.");
676
+ const isOpenRouter = provider === "openrouter" || baseUrl.includes("openrouter.ai");
677
+ const isCloudflareWorkersAI = provider === "cloudflare-workers-ai" || baseUrl.includes("api.cloudflare.com");
678
+ const isCloudflareAiGateway = provider === "cloudflare-ai-gateway" || baseUrl.includes("gateway.ai.cloudflare.com");
679
+ const isNvidia = provider === "nvidia" || baseUrl.includes("integrate.api.nvidia.com");
680
+ const isAntLing = provider === "ant-ling" || baseUrl.includes("api.ant-ling.com");
681
+ const isNonStandard = isNvidia || provider === "cerebras" || baseUrl.includes("cerebras.ai") || provider === "xai" || baseUrl.includes("api.x.ai") || isTogether || baseUrl.includes("chutes.ai") || baseUrl.includes("deepseek.com") || isZai || isMoonshot || provider === "opencode" || baseUrl.includes("opencode.ai") || isCloudflareWorkersAI || isCloudflareAiGateway || isAntLing;
682
+ const useMaxTokens = baseUrl.includes("chutes.ai") || isMoonshot || isCloudflareAiGateway || isTogether || isNvidia || isAntLing;
683
+ const isGrok = provider === "xai" || baseUrl.includes("api.x.ai");
684
+ const isDeepSeek = provider === "deepseek" || baseUrl.includes("deepseek.com");
685
+ const isOpenRouterDeveloperRoleModel = isOpenRouter && (model.id.startsWith("anthropic/") || model.id.startsWith("openai/"));
686
+ const cacheControlFormat = provider === "openrouter" && model.id.startsWith("anthropic/") ? "anthropic" : void 0;
687
+ return {
688
+ supportsStore: !isNonStandard,
689
+ supportsDeveloperRole: isOpenRouterDeveloperRoleModel || !isNonStandard && !isOpenRouter,
690
+ supportsReasoningEffort: !isGrok && !isZai && !isMoonshot && !isTogether && !isCloudflareAiGateway && !isNvidia && !isAntLing,
691
+ supportsUsageInStreaming: true,
692
+ maxTokensField: useMaxTokens ? "max_tokens" : "max_completion_tokens",
693
+ requiresToolResultName: false,
694
+ requiresAssistantAfterToolResult: false,
695
+ requiresThinkingAsText: false,
696
+ requiresReasoningContentOnAssistantMessages: isDeepSeek,
697
+ thinkingFormat: isDeepSeek ? "deepseek" : isZai ? "zai" : isTogether ? "together" : isAntLing ? "ant-ling" : isOpenRouter ? "openrouter" : "openai",
698
+ openRouterRouting: {},
699
+ vercelGatewayRouting: {},
700
+ zaiToolStream: false,
701
+ supportsStrictMode: !isMoonshot && !isTogether && !isCloudflareAiGateway && !isNvidia,
702
+ cacheControlFormat,
703
+ sendSessionAffinityHeaders: false,
704
+ supportsLongCacheRetention: !(isTogether || isCloudflareWorkersAI || isCloudflareAiGateway || isNvidia || isAntLing)
705
+ };
706
+ }
707
+ /**
708
+ * Get resolved compatibility settings for a model.
709
+ * Uses explicit model.compat if provided, otherwise auto-detects from provider/URL.
710
+ */
711
+ function getCompat(model) {
712
+ const detected = detectCompat(model);
713
+ if (!model.compat) return detected;
714
+ return {
715
+ supportsStore: model.compat.supportsStore ?? detected.supportsStore,
716
+ supportsDeveloperRole: model.compat.supportsDeveloperRole ?? detected.supportsDeveloperRole,
717
+ supportsReasoningEffort: model.compat.supportsReasoningEffort ?? detected.supportsReasoningEffort,
718
+ supportsUsageInStreaming: model.compat.supportsUsageInStreaming ?? detected.supportsUsageInStreaming,
719
+ maxTokensField: model.compat.maxTokensField ?? detected.maxTokensField,
720
+ requiresToolResultName: model.compat.requiresToolResultName ?? detected.requiresToolResultName,
721
+ requiresAssistantAfterToolResult: model.compat.requiresAssistantAfterToolResult ?? detected.requiresAssistantAfterToolResult,
722
+ requiresThinkingAsText: model.compat.requiresThinkingAsText ?? detected.requiresThinkingAsText,
723
+ requiresReasoningContentOnAssistantMessages: model.compat.requiresReasoningContentOnAssistantMessages ?? detected.requiresReasoningContentOnAssistantMessages,
724
+ thinkingFormat: model.compat.thinkingFormat ?? detected.thinkingFormat,
725
+ openRouterRouting: model.compat.openRouterRouting ?? {},
726
+ vercelGatewayRouting: model.compat.vercelGatewayRouting ?? detected.vercelGatewayRouting,
727
+ zaiToolStream: model.compat.zaiToolStream ?? detected.zaiToolStream,
728
+ supportsStrictMode: model.compat.supportsStrictMode ?? detected.supportsStrictMode,
729
+ cacheControlFormat: model.compat.cacheControlFormat ?? detected.cacheControlFormat,
730
+ sendSessionAffinityHeaders: model.compat.sendSessionAffinityHeaders ?? detected.sendSessionAffinityHeaders,
731
+ supportsLongCacheRetention: model.compat.supportsLongCacheRetention ?? detected.supportsLongCacheRetention
732
+ };
733
+ }
734
+ //#endregion
735
+ export { convertMessages, register, streamOpenAICompletions, streamSimpleOpenAICompletions };