@omnicross/core 0.1.4 → 0.1.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.
Files changed (67) hide show
  1. package/dist/auth/GeminiCodeAssistProjectResolver.cjs +6 -5
  2. package/dist/auth/GeminiCodeAssistProjectResolver.js +4 -3
  3. package/dist/{chunk-SU2GCLAC.cjs → chunk-3Q6Z6JTO.cjs} +124 -16
  4. package/dist/chunk-3Z5BQZFM.cjs +52 -0
  5. package/dist/{chunk-4VAVYUZS.cjs → chunk-4XMYPW46.cjs} +9 -9
  6. package/dist/{chunk-S4WBV25P.js → chunk-6QZGDLL4.js} +106 -23
  7. package/dist/{chunk-C72S6TTV.cjs → chunk-7FEBOPJO.cjs} +5 -4
  8. package/dist/{chunk-TIER4SUC.js → chunk-BODMAL6G.js} +119 -11
  9. package/dist/{chunk-DKPXN34V.cjs → chunk-CGKLE6IW.cjs} +145 -30
  10. package/dist/{chunk-XK5CIRMQ.js → chunk-D3TDKWRP.js} +60 -2
  11. package/dist/{chunk-RSJ3TWJQ.cjs → chunk-DDMRUL76.cjs} +5 -5
  12. package/dist/{chunk-QYTT6GE3.js → chunk-FH2P4OCD.js} +124 -9
  13. package/dist/{chunk-Z7LUNECE.js → chunk-IB3FDI4O.js} +5 -4
  14. package/dist/{chunk-7Y47UCF2.js → chunk-IFXJ2BG7.js} +5 -38
  15. package/dist/{chunk-C7PSERMH.js → chunk-IWQAX3CS.js} +1 -1
  16. package/dist/{chunk-YGXJGRFI.cjs → chunk-JWVTXXPX.cjs} +106 -23
  17. package/dist/{chunk-7YN22L2H.cjs → chunk-K52THW2C.cjs} +5 -5
  18. package/dist/{chunk-Z7Y2NPHY.js → chunk-MFZ5437A.js} +1 -1
  19. package/dist/{chunk-VPBAUQ2M.js → chunk-OQWKZCXP.js} +15 -8
  20. package/dist/{chunk-OCEUVQHW.cjs → chunk-PG7PS2NN.cjs} +61 -3
  21. package/dist/chunk-SYQF7OIR.js +52 -0
  22. package/dist/{chunk-E3UCVHLP.cjs → chunk-UNWKG6EI.cjs} +5 -38
  23. package/dist/{chunk-RGTR7CIO.cjs → chunk-ZCIQ3L3R.cjs} +19 -12
  24. package/dist/completion/CompletionService.cjs +13 -12
  25. package/dist/completion/CompletionService.js +12 -11
  26. package/dist/completion.cjs +13 -12
  27. package/dist/completion.js +12 -11
  28. package/dist/index.cjs +15 -14
  29. package/dist/index.js +14 -13
  30. package/dist/outbound-api/auditCapture.cjs +2 -2
  31. package/dist/outbound-api/auditCapture.d.cts +5 -3
  32. package/dist/outbound-api/auditCapture.d.ts +5 -3
  33. package/dist/outbound-api/auditCapture.js +1 -1
  34. package/dist/outbound-api.cjs +13 -12
  35. package/dist/outbound-api.js +12 -11
  36. package/dist/pipeline/upstreamFetch.cjs +3 -2
  37. package/dist/pipeline/upstreamFetch.d.cts +6 -0
  38. package/dist/pipeline/upstreamFetch.d.ts +6 -0
  39. package/dist/pipeline/upstreamFetch.js +2 -1
  40. package/dist/pipeline/upstreamTrace.cjs +14 -0
  41. package/dist/pipeline/upstreamTrace.d.cts +85 -0
  42. package/dist/pipeline/upstreamTrace.d.ts +85 -0
  43. package/dist/pipeline/upstreamTrace.js +14 -0
  44. package/dist/provider-proxy/ProviderProxy.cjs +13 -12
  45. package/dist/provider-proxy/ProviderProxy.js +12 -11
  46. package/dist/provider-proxy/ingress/providerProxyShared.cjs +15 -12
  47. package/dist/provider-proxy/ingress/providerProxyShared.d.cts +17 -1
  48. package/dist/provider-proxy/ingress/providerProxyShared.d.ts +17 -1
  49. package/dist/provider-proxy/ingress/providerProxyShared.js +14 -11
  50. package/dist/provider-proxy.cjs +13 -12
  51. package/dist/provider-proxy.js +12 -11
  52. package/dist/transformer/transformers/AnthropicTransformer.cjs +2 -2
  53. package/dist/transformer/transformers/AnthropicTransformer.js +1 -1
  54. package/dist/transformer/transformers/GeminiCodeAssistTransformer.cjs +3 -3
  55. package/dist/transformer/transformers/GeminiCodeAssistTransformer.js +2 -2
  56. package/dist/transformer/transformers/GeminiTransformer.cjs +3 -3
  57. package/dist/transformer/transformers/GeminiTransformer.js +2 -2
  58. package/dist/transformer/transformers/OpenAIResponseTransformer.cjs +2 -2
  59. package/dist/transformer/transformers/OpenAIResponseTransformer.js +1 -1
  60. package/dist/transformer/transformers/OpenCodeGoTransformer.cjs +2 -2
  61. package/dist/transformer/transformers/OpenCodeGoTransformer.js +1 -1
  62. package/dist/transformer/transformers.cjs +9 -9
  63. package/dist/transformer/transformers.js +9 -9
  64. package/dist/transformer.cjs +11 -11
  65. package/dist/transformer.js +10 -10
  66. package/package.json +1 -1
  67. package/dist/{chunk-FTQ7IQUC.js → chunk-C6OV7GCC.js} +8 -8
@@ -3,7 +3,7 @@
3
3
 
4
4
 
5
5
 
6
- var _chunkYGXJGRFIcjs = require('./chunk-YGXJGRFI.cjs');
6
+ var _chunkJWVTXXPXcjs = require('./chunk-JWVTXXPX.cjs');
7
7
 
8
8
  // src/transformer/transformers/GeminiCodeAssistTransformer.ts
9
9
  var DEFAULT_CODE_ASSIST_ENDPOINT = "https://cloudcode-pa.googleapis.com";
@@ -117,7 +117,7 @@ var GeminiCodeAssistTransformer = (_class = class {constructor() { _class.protot
117
117
  * openaiResponsesIngress). `undefined` is the valid fresh free-tier value.
118
118
  */
119
119
  async transformRequestIn(request, provider, _context) {
120
- const inner = _chunkYGXJGRFIcjs.buildRequestBody.call(void 0, request);
120
+ const inner = _chunkJWVTXXPXcjs.buildRequestBody.call(void 0, request);
121
121
  const envelope = {
122
122
  model: request.model,
123
123
  project: provider.geminiProject,
@@ -147,7 +147,7 @@ var GeminiCodeAssistTransformer = (_class = class {constructor() { _class.protot
147
147
  if (inner && typeof inner === "object" && !("model" in inner) && "model" in r) {
148
148
  inner.model = r.model;
149
149
  }
150
- return _chunkYGXJGRFIcjs.transformRequestOut.call(void 0, inner);
150
+ return _chunkJWVTXXPXcjs.transformRequestOut.call(void 0, inner);
151
151
  }
152
152
  /**
153
153
  * Code Assist response → OpenAI-compatible. PEEL the `.response` envelope from
@@ -155,7 +155,7 @@ var GeminiCodeAssistTransformer = (_class = class {constructor() { _class.protot
155
155
  */
156
156
  async transformResponseOut(response, _context) {
157
157
  const unwrapped = await unwrapCodeAssistResponse(response);
158
- return _chunkYGXJGRFIcjs.transformResponseOut.call(void 0, unwrapped, this.name, this.logger);
158
+ return _chunkJWVTXXPXcjs.transformResponseOut.call(void 0, unwrapped, this.name, this.logger);
159
159
  }
160
160
  /**
161
161
  * OpenAI-compatible response → Code Assist (endpoint-encode parity). Re-wraps
@@ -164,7 +164,7 @@ var GeminiCodeAssistTransformer = (_class = class {constructor() { _class.protot
164
164
  * `transformResponseOut`'s peel.
165
165
  */
166
166
  async transformResponseIn(response, _context) {
167
- const geminiResponse = await _chunkYGXJGRFIcjs.transformResponseIn.call(void 0, response, this.logger);
167
+ const geminiResponse = await _chunkJWVTXXPXcjs.transformResponseIn.call(void 0, response, this.logger);
168
168
  const contentType = _nullishCoalesce(geminiResponse.headers.get("Content-Type"), () => ( ""));
169
169
  if (contentType.includes("text/event-stream")) {
170
170
  return geminiResponse;
@@ -1,18 +1,18 @@
1
1
  import {
2
2
  streamSSEResponse
3
3
  } from "./chunk-VVEHS2LI.js";
4
+ import {
5
+ TransformerChainExecutor
6
+ } from "./chunk-G2UTNSGU.js";
4
7
  import {
5
8
  AnthropicTransformer
6
- } from "./chunk-FTQ7IQUC.js";
9
+ } from "./chunk-C6OV7GCC.js";
7
10
  import {
8
11
  GeminiTransformer
9
- } from "./chunk-C7PSERMH.js";
12
+ } from "./chunk-IWQAX3CS.js";
10
13
  import {
11
14
  OpenAIResponseTransformer
12
- } from "./chunk-TIER4SUC.js";
13
- import {
14
- TransformerChainExecutor
15
- } from "./chunk-G2UTNSGU.js";
15
+ } from "./chunk-BODMAL6G.js";
16
16
  import {
17
17
  injectExtendedContextBeta
18
18
  } from "./chunk-MZNPGW5Q.js";
@@ -80,14 +80,14 @@ import {
80
80
  } from "./chunk-H5JUT3KV.js";
81
81
  import {
82
82
  beginAuditCapture
83
- } from "./chunk-7Y47UCF2.js";
83
+ } from "./chunk-IFXJ2BG7.js";
84
84
  import {
85
85
  convertAnthropicToOpenAI,
86
86
  convertOpenAIToAnthropic
87
87
  } from "./chunk-5ZQBEOMD.js";
88
88
  import {
89
89
  fetchUpstream
90
- } from "./chunk-XK5CIRMQ.js";
90
+ } from "./chunk-D3TDKWRP.js";
91
91
  import {
92
92
  applyAugmentation
93
93
  } from "./chunk-Y7FO65VT.js";
@@ -651,6 +651,95 @@ async function relayResponse(res, providerResponse, isStream, rewriteModel) {
651
651
  res.end(clientText);
652
652
  return bodyText;
653
653
  }
654
+ async function aggregateAnthropicSseToJsonBody(response, rewriteModel) {
655
+ const text = await response.text();
656
+ const message = {
657
+ type: "message",
658
+ role: "assistant",
659
+ content: [],
660
+ stop_reason: null,
661
+ stop_sequence: null,
662
+ usage: {}
663
+ };
664
+ const blocks = /* @__PURE__ */ new Map();
665
+ for (const raw of text.split("\n")) {
666
+ const line = raw.trim();
667
+ if (!line.startsWith("data:")) continue;
668
+ const payload = line.slice(5).trim();
669
+ if (!payload || payload === "[DONE]") continue;
670
+ let ev;
671
+ try {
672
+ ev = JSON.parse(payload);
673
+ } catch {
674
+ continue;
675
+ }
676
+ switch (ev["type"]) {
677
+ case "message_start": {
678
+ const m = ev["message"] ?? {};
679
+ if (typeof m["id"] === "string") message["id"] = m["id"];
680
+ if (typeof m["model"] === "string") message["model"] = m["model"];
681
+ if (m["usage"]) message["usage"] = { ...m["usage"] };
682
+ break;
683
+ }
684
+ case "content_block_start": {
685
+ const idx = Number(ev["index"]);
686
+ const cb = ev["content_block"] ?? {};
687
+ blocks.set(idx, {
688
+ type: typeof cb["type"] === "string" ? cb["type"] : "text",
689
+ text: typeof cb["text"] === "string" ? cb["text"] : "",
690
+ id: typeof cb["id"] === "string" ? cb["id"] : void 0,
691
+ name: typeof cb["name"] === "string" ? cb["name"] : void 0,
692
+ inputJson: ""
693
+ });
694
+ break;
695
+ }
696
+ case "content_block_delta": {
697
+ const b = blocks.get(Number(ev["index"]));
698
+ if (!b) break;
699
+ const d = ev["delta"] ?? {};
700
+ if (d["type"] === "text_delta" && typeof d["text"] === "string") b.text += d["text"];
701
+ else if (d["type"] === "input_json_delta" && typeof d["partial_json"] === "string")
702
+ b.inputJson += d["partial_json"];
703
+ else if (d["type"] === "thinking_delta" && typeof d["thinking"] === "string")
704
+ b.text += d["thinking"];
705
+ else if (d["type"] === "signature_delta" && typeof d["signature"] === "string")
706
+ b.signature = (b.signature || "") + d["signature"];
707
+ break;
708
+ }
709
+ case "message_delta": {
710
+ const d = ev["delta"] ?? {};
711
+ if (d["stop_reason"] !== void 0) message["stop_reason"] = d["stop_reason"];
712
+ if (d["stop_sequence"] !== void 0) message["stop_sequence"] = d["stop_sequence"];
713
+ if (ev["usage"])
714
+ message["usage"] = { ...message["usage"], ...ev["usage"] };
715
+ break;
716
+ }
717
+ default:
718
+ break;
719
+ }
720
+ }
721
+ message["content"] = [...blocks.keys()].sort((a, b) => a - b).map((idx) => {
722
+ const blk = blocks.get(idx);
723
+ if (!blk) return void 0;
724
+ if (blk.type === "tool_use") {
725
+ let input = {};
726
+ try {
727
+ input = blk.inputJson ? JSON.parse(blk.inputJson) : {};
728
+ } catch {
729
+ input = {};
730
+ }
731
+ return { type: "tool_use", id: blk.id ?? "", name: blk.name ?? "", input };
732
+ }
733
+ if (blk.type === "thinking") {
734
+ const out = { type: "thinking", thinking: blk.text };
735
+ if (blk.signature) out.signature = blk.signature;
736
+ return out;
737
+ }
738
+ return { type: blk.type || "text", text: blk.text };
739
+ }).filter((b) => b !== void 0);
740
+ if (rewriteModel) message["model"] = rewriteModel;
741
+ return JSON.stringify(message);
742
+ }
654
743
  function writeError(res, status, message) {
655
744
  if (res.headersSent) return;
656
745
  res.writeHead(status, { "Content-Type": "application/json" });
@@ -1026,7 +1115,21 @@ async function handleAnthropicMessagesByo(res, rawBody, route, deps, options = {
1026
1115
  if (!plan) return;
1027
1116
  anthropicBody.model = plan.resolvedModel;
1028
1117
  const providerResponse = route.authMode === "subscription" ? await runPipelineWithSubscriptionRetry(anthropicBody, rawBody, plan, route, deps, options) : await runPipelineWithPoolReporting(anthropicBody, rawBody, plan, options);
1029
- const bodyText = await relayResponse(res, providerResponse.response, isStream, route.requestedModel);
1118
+ const upstreamResponse = providerResponse.response;
1119
+ const upstreamSse = (upstreamResponse.headers.get("content-type") ?? "").includes(
1120
+ "text/event-stream"
1121
+ );
1122
+ let bodyText;
1123
+ if (!isStream && upstreamSse) {
1124
+ bodyText = await aggregateAnthropicSseToJsonBody(upstreamResponse, route.requestedModel);
1125
+ res.writeHead(
1126
+ upstreamResponse.status && upstreamResponse.status >= 100 ? upstreamResponse.status : 200,
1127
+ { "Content-Type": "application/json" }
1128
+ );
1129
+ res.end(bodyText);
1130
+ } else {
1131
+ bodyText = await relayResponse(res, upstreamResponse, isStream, route.requestedModel);
1132
+ }
1030
1133
  if (bodyText && deps.usageRecorder) {
1031
1134
  recordAnthropicNonStreamUsage(deps.usageRecorder, bodyText, {
1032
1135
  sessionId: route.sessionId,
@@ -3595,6 +3698,7 @@ var OutboundApiServer = class {
3595
3698
  }
3596
3699
  /** Per-request handler. Auth is enforced on EVERY request (incl. loopback). */
3597
3700
  onRequest(req, res) {
3701
+ if (req.url) req.url = normalizeDoubledEndpointPath(req.url);
3598
3702
  if (this.deps.healthReportProvider && this.tryServeHealth(req, res)) return;
3599
3703
  handleOutboundRequest(
3600
3704
  req,
@@ -3717,6 +3821,16 @@ function firstLanIPv4() {
3717
3821
  }
3718
3822
  return null;
3719
3823
  }
3824
+ function normalizeDoubledEndpointPath(url) {
3825
+ const queryIdx = url.indexOf("?");
3826
+ const path = queryIdx === -1 ? url : url.slice(0, queryIdx);
3827
+ const query = queryIdx === -1 ? "" : url.slice(queryIdx);
3828
+ const collapsed = path.replace(
3829
+ /^(.*?)(\/v1\/(?:messages|responses|chat\/completions))\2$/,
3830
+ "$1$2"
3831
+ );
3832
+ return collapsed + query;
3833
+ }
3720
3834
 
3721
3835
  // src/outbound-api/keySpendTracker.ts
3722
3836
  function startOfLocalDay(ts) {
@@ -5904,6 +6018,7 @@ export {
5904
6018
  getGeminiEndpointTransformer,
5905
6019
  readBody,
5906
6020
  relayResponse,
6021
+ aggregateAnthropicSseToJsonBody,
5907
6022
  writeError,
5908
6023
  resolvePoolBoundKey,
5909
6024
  extractRouteToken,
@@ -15,10 +15,11 @@ var OpenCodeGoTransformer = class {
15
15
  async transformRequestIn(request, _provider, _context) {
16
16
  const messages = request.messages.map((m) => {
17
17
  const content = m.content;
18
- if (Array.isArray(content) && content.length === 1 && content[0]?.type === "text") {
19
- return { ...m, content: content[0].text };
20
- }
21
- return m;
18
+ const normalizedContent = Array.isArray(content) && content.length === 1 && content[0]?.type === "text" ? content[0].text : content;
19
+ const out2 = { role: m.role, content: normalizedContent };
20
+ if (m.tool_calls) out2.tool_calls = m.tool_calls;
21
+ if (m.tool_call_id) out2.tool_call_id = m.tool_call_id;
22
+ return out2;
22
23
  });
23
24
  const out = {
24
25
  model: request.model,
@@ -11,11 +11,6 @@ import {
11
11
 
12
12
  // src/outbound-api/auditCapture.ts
13
13
  import { randomUUID } from "crypto";
14
- function isStreamingContentType(res) {
15
- const ct = res.getHeader("content-type");
16
- const value = Array.isArray(ct) ? ct.join(";") : String(ct ?? "");
17
- return value.toLowerCase().includes("text/event-stream");
18
- }
19
14
  function resolveClientIp(req, trustForwardedFor) {
20
15
  if (trustForwardedFor) {
21
16
  const xff = req.headers["x-forwarded-for"];
@@ -27,18 +22,11 @@ function resolveClientIp(req, trustForwardedFor) {
27
22
  }
28
23
  return req.socket?.remoteAddress ?? void 0;
29
24
  }
30
- function truncateToBytes(text, maxBytes) {
31
- const buf = Buffer.from(text, "utf8");
32
- if (buf.length <= maxBytes) return text;
33
- return buf.subarray(0, maxBytes).toString("utf8");
34
- }
35
25
  function beginAuditCapture(req, res, now) {
36
26
  const config = getAuditCaptureConfig();
37
27
  if (!config) return null;
38
28
  let rawRequestBody;
39
29
  const responseChunks = [];
40
- let responseBytes = 0;
41
- let streamDetected = false;
42
30
  let finished = false;
43
31
  const ctx = {
44
32
  setRequestBody(raw) {
@@ -46,19 +34,9 @@ function beginAuditCapture(req, res, now) {
46
34
  }
47
35
  };
48
36
  if (config.captureBodies) {
49
- installResponseCapture(res, config.maxBodyBytes, {
37
+ installResponseCapture(res, {
50
38
  push(chunk) {
51
- responseBytes += chunk.length;
52
39
  responseChunks.push(chunk);
53
- },
54
- get bytes() {
55
- return responseBytes;
56
- },
57
- markStream() {
58
- streamDetected = true;
59
- },
60
- get isStream() {
61
- return streamDetected;
62
40
  }
63
41
  });
64
42
  }
@@ -92,9 +70,9 @@ function beginAuditCapture(req, res, now) {
92
70
  if (ctx.error) record.error = redactAuditText(ctx.error);
93
71
  if (config.captureBodies) {
94
72
  if (rawRequestBody != null && rawRequestBody.length > 0) {
95
- record.requestBody = redactAuditText(truncateToBytes(rawRequestBody, config.maxBodyBytes));
73
+ record.requestBody = redactAuditText(rawRequestBody);
96
74
  }
97
- if (!streamDetected && responseChunks.length > 0) {
75
+ if (responseChunks.length > 0) {
98
76
  const body = Buffer.concat(responseChunks).toString("utf8");
99
77
  record.responseBody = redactAuditText(body);
100
78
  }
@@ -106,24 +84,13 @@ function beginAuditCapture(req, res, now) {
106
84
  res.once("close", finalize);
107
85
  return ctx;
108
86
  }
109
- function installResponseCapture(res, maxBodyBytes, sink) {
110
- let contentTypeChecked = false;
87
+ function installResponseCapture(res, sink) {
111
88
  const capture = (chunk) => {
112
- if (sink.isStream) return;
113
- if (!contentTypeChecked) {
114
- contentTypeChecked = true;
115
- if (isStreamingContentType(res)) {
116
- sink.markStream();
117
- return;
118
- }
119
- }
120
- if (sink.bytes >= maxBodyBytes) return;
121
89
  let buf = null;
122
90
  if (Buffer.isBuffer(chunk)) buf = chunk;
123
91
  else if (typeof chunk === "string") buf = Buffer.from(chunk, "utf8");
124
92
  if (!buf || buf.length === 0) return;
125
- const remaining = maxBodyBytes - sink.bytes;
126
- sink.push(buf.length > remaining ? buf.subarray(0, remaining) : buf);
93
+ sink.push(buf);
127
94
  };
128
95
  const originalWrite = res.write.bind(res);
129
96
  const originalEnd = res.end.bind(res);
@@ -3,7 +3,7 @@ import {
3
3
  transformRequestOut,
4
4
  transformResponseIn,
5
5
  transformResponseOut
6
- } from "./chunk-S4WBV25P.js";
6
+ } from "./chunk-6QZGDLL4.js";
7
7
 
8
8
  // src/transformer/transformers/GeminiTransformer.ts
9
9
  var GeminiTransformer = class {
@@ -321,6 +321,7 @@ function handleStreamResponse(response, providerName, logger) {
321
321
  let pendingContent = "";
322
322
  let contentIndex = 0;
323
323
  let toolCallIndex = -1;
324
+ let textBuffered = false;
324
325
  const stream = new ReadableStream({
325
326
  async start(controller) {
326
327
  const reader = response.body.getReader();
@@ -338,6 +339,7 @@ function handleStreamResponse(response, providerName, logger) {
338
339
  }
339
340
  const candidate = chunk.candidates[0];
340
341
  const parts = _optionalChain([candidate, 'access', _59 => _59.content, 'optionalAccess', _60 => _60.parts]) || [];
342
+ textBuffered = false;
341
343
  parts.filter((part) => part.text && part.thought === true).forEach((part) => {
342
344
  hasThinkingContent = true;
343
345
  const thinkingChunk = createChunk({
@@ -415,7 +417,7 @@ function handleStreamResponse(response, providerName, logger) {
415
417
  if (hasThinkingContent && textContent && !signatureSent) {
416
418
  if (_optionalChain([chunk, 'access', _70 => _70.modelVersion, 'optionalAccess', _71 => _71.includes, 'call', _72 => _72("3")])) {
417
419
  pendingContent += textContent;
418
- return;
420
+ textBuffered = true;
419
421
  } else {
420
422
  const signatureChunk = createChunk({
421
423
  responseId: chunk.responseId,
@@ -433,7 +435,7 @@ function handleStreamResponse(response, providerName, logger) {
433
435
  signatureSent = true;
434
436
  }
435
437
  }
436
- if (textContent) {
438
+ if (textContent && !textBuffered) {
437
439
  if (!pendingContent) contentIndex++;
438
440
  const contentChunk = createChunk({
439
441
  responseId: chunk.responseId,
@@ -854,35 +856,116 @@ function transformRequestOut(request) {
854
856
  tool_choice: toolChoice
855
857
  };
856
858
  if (Array.isArray(contents)) {
859
+ const toolCallIdsByName = /* @__PURE__ */ new Map();
857
860
  for (const content of contents) {
858
861
  if (typeof content === "string") {
859
- unifiedRequest.messages.push({
860
- role: "user",
861
- content
862
- });
863
- } else if ("text" in content && typeof content.text === "string") {
862
+ unifiedRequest.messages.push({ role: "user", content });
863
+ continue;
864
+ }
865
+ if (content && typeof content === "object" && "text" in content && typeof content.text === "string" && !("parts" in content)) {
864
866
  unifiedRequest.messages.push({
865
867
  role: "user",
866
868
  content: content.text || null
867
869
  });
868
- } else if ("role" in content && content.role === "user") {
869
- const geminiContent = content;
870
- unifiedRequest.messages.push({
871
- role: "user",
872
- content: _optionalChain([geminiContent, 'access', _122 => _122.parts, 'optionalAccess', _123 => _123.map, 'call', _124 => _124((part) => ({
873
- type: "text",
874
- text: part.text || ""
875
- }))]) || []
876
- });
877
- } else if (content.role === "model") {
870
+ continue;
871
+ }
872
+ if (!content || typeof content !== "object" || !("role" in content)) {
873
+ continue;
874
+ }
875
+ const geminiContent = content;
876
+ const isModel = geminiContent.role === "model";
877
+ const role = isModel ? "assistant" : "user";
878
+ const parts = _nullishCoalesce(geminiContent.parts, () => ( []));
879
+ const functionResponses = [];
880
+ const functionCalls = [];
881
+ const textParts = [];
882
+ const contentParts = [];
883
+ let thinkingText = "";
884
+ let signature;
885
+ for (const part of parts) {
886
+ if ("thoughtSignature" in part) {
887
+ signature = part.thoughtSignature;
888
+ }
889
+ if ("functionResponse" in part) {
890
+ functionResponses.push(part);
891
+ } else if ("functionCall" in part) {
892
+ functionCalls.push(part);
893
+ } else if ("inlineData" in part || "file_data" in part) {
894
+ const inline = part.inlineData;
895
+ const fileData = part.file_data;
896
+ if (_optionalChain([inline, 'optionalAccess', _122 => _122.data])) {
897
+ const mime = inline.mime_type || "image/png";
898
+ contentParts.push({
899
+ type: "image_url",
900
+ image_url: { url: `data:${mime};base64,${inline.data}` },
901
+ media_type: mime
902
+ });
903
+ } else if (_optionalChain([fileData, 'optionalAccess', _123 => _123.file_uri])) {
904
+ contentParts.push({
905
+ type: "image_url",
906
+ image_url: { url: fileData.file_uri },
907
+ media_type: fileData.mime_type
908
+ });
909
+ }
910
+ } else if ("text" in part) {
911
+ if (part.thought === true) {
912
+ thinkingText += _nullishCoalesce(part.text, () => ( ""));
913
+ } else {
914
+ textParts.push(part);
915
+ }
916
+ }
917
+ }
918
+ for (const fr of functionResponses) {
919
+ const fnName = _nullishCoalesce(fr.functionResponse.name, () => ( ""));
920
+ const queue = toolCallIdsByName.get(fnName);
921
+ const id = queue && queue.length > 0 ? queue.shift() : `tool_${Math.random().toString(36).substring(2, 15)}`;
922
+ const response = fr.functionResponse.response;
923
+ const result = _optionalChain([response, 'optionalAccess', _124 => _124.result]);
924
+ const toolContent = typeof result === "string" ? result : result !== void 0 ? JSON.stringify(result) : response !== void 0 ? JSON.stringify(response) : "";
878
925
  unifiedRequest.messages.push({
879
- role: "assistant",
880
- content: _optionalChain([content, 'access', _125 => _125.parts, 'optionalAccess', _126 => _126.map, 'call', _127 => _127((part) => ({
881
- type: "text",
882
- text: part.text || ""
883
- }))]) || []
926
+ role: "tool",
927
+ tool_call_id: id,
928
+ content: toolContent
884
929
  });
885
930
  }
931
+ const toolCalls = functionCalls.map((p) => {
932
+ const id = p.functionCall.id || `tool_${Math.random().toString(36).substring(2, 15)}`;
933
+ if (p.functionCall.name) {
934
+ const arr = _nullishCoalesce(toolCallIdsByName.get(p.functionCall.name), () => ( []));
935
+ arr.push(id);
936
+ toolCallIdsByName.set(p.functionCall.name, arr);
937
+ }
938
+ return {
939
+ id,
940
+ type: "function",
941
+ function: {
942
+ name: p.functionCall.name,
943
+ arguments: JSON.stringify(_nullishCoalesce(p.functionCall.args, () => ( {})))
944
+ }
945
+ };
946
+ });
947
+ const onlyToolResults = functionResponses.length > 0 && textParts.length === 0 && functionCalls.length === 0 && contentParts.length === 0 && !thinkingText && !signature;
948
+ if (onlyToolResults) continue;
949
+ let messageContent;
950
+ if (contentParts.length > 0) {
951
+ messageContent = [
952
+ ...textParts.map((p) => ({ type: "text", text: p.text })),
953
+ ...contentParts
954
+ ];
955
+ } else {
956
+ messageContent = textParts.map((p) => p.text).join("\n") || null;
957
+ }
958
+ const message = {
959
+ role,
960
+ content: messageContent
961
+ };
962
+ if (toolCalls.length > 0) {
963
+ message.tool_calls = toolCalls;
964
+ }
965
+ if (signature || thinkingText) {
966
+ message.thinking = { content: thinkingText || "", signature };
967
+ }
968
+ unifiedRequest.messages.push(message);
886
969
  }
887
970
  }
888
971
  if (Array.isArray(tools)) {
@@ -895,7 +978,7 @@ function transformRequestOut(request) {
895
978
  function: {
896
979
  name: funcDecl.name,
897
980
  description: _nullishCoalesce(funcDecl.description, () => ( "")),
898
- parameters: _nullishCoalesce(funcDecl.parameters, () => ( {}))
981
+ parameters: _nullishCoalesce(_nullishCoalesce(funcDecl.parameters, () => ( funcDecl.parametersJsonSchema)), () => ( {}))
899
982
  }
900
983
  });
901
984
  }
@@ -3,7 +3,7 @@
3
3
 
4
4
 
5
5
 
6
- var _chunkYGXJGRFIcjs = require('./chunk-YGXJGRFI.cjs');
6
+ var _chunkJWVTXXPXcjs = require('./chunk-JWVTXXPX.cjs');
7
7
 
8
8
  // src/transformer/transformers/GeminiTransformer.ts
9
9
  var GeminiTransformer = (_class = class {
@@ -44,7 +44,7 @@ var GeminiTransformer = (_class = class {
44
44
  * Also builds the correct URL for the Gemini API
45
45
  */
46
46
  async transformRequestIn(request, provider, _context) {
47
- const body = _chunkYGXJGRFIcjs.buildRequestBody.call(void 0, request);
47
+ const body = _chunkJWVTXXPXcjs.buildRequestBody.call(void 0, request);
48
48
  const action = request.stream ? "streamGenerateContent?alt=sse" : "generateContent";
49
49
  const url = new URL(`./${request.model}:${action}`, provider.baseUrl);
50
50
  const headers = {};
@@ -65,20 +65,20 @@ var GeminiTransformer = (_class = class {
65
65
  * (For requests coming into the Gemini endpoint)
66
66
  */
67
67
  async transformRequestOut(request, _context) {
68
- return _chunkYGXJGRFIcjs.transformRequestOut.call(void 0, request);
68
+ return _chunkJWVTXXPXcjs.transformRequestOut.call(void 0, request);
69
69
  }
70
70
  /**
71
71
  * Transform Gemini response to OpenAI-compatible format
72
72
  */
73
73
  async transformResponseOut(response, _context) {
74
- return _chunkYGXJGRFIcjs.transformResponseOut.call(void 0, response, this.name, this.logger);
74
+ return _chunkJWVTXXPXcjs.transformResponseOut.call(void 0, response, this.name, this.logger);
75
75
  }
76
76
  /**
77
77
  * Transform OpenAI-compatible response back to Gemini format
78
78
  * (For endpoint mode — returning Gemini-format responses to the client)
79
79
  */
80
80
  async transformResponseIn(response, _context) {
81
- return _chunkYGXJGRFIcjs.transformResponseIn.call(void 0, response, this.logger);
81
+ return _chunkJWVTXXPXcjs.transformResponseIn.call(void 0, response, this.logger);
82
82
  }
83
83
  }, _class.__initStatic(), _class);
84
84
 
@@ -3,7 +3,7 @@ import {
3
3
  transformRequestOut,
4
4
  transformResponseIn,
5
5
  transformResponseOut
6
- } from "./chunk-S4WBV25P.js";
6
+ } from "./chunk-6QZGDLL4.js";
7
7
 
8
8
  // src/transformer/transformers/GeminiCodeAssistTransformer.ts
9
9
  var DEFAULT_CODE_ASSIST_ENDPOINT = "https://cloudcode-pa.googleapis.com";
@@ -1,21 +1,21 @@
1
+ import {
2
+ OpenCodeGoTransformer
3
+ } from "./chunk-IB3FDI4O.js";
1
4
  import {
2
5
  ReasoningTransformer
3
6
  } from "./chunk-ZJZAOKI7.js";
4
7
  import {
5
8
  AnthropicTransformer
6
- } from "./chunk-FTQ7IQUC.js";
9
+ } from "./chunk-C6OV7GCC.js";
7
10
  import {
8
11
  GeminiTransformer
9
- } from "./chunk-C7PSERMH.js";
12
+ } from "./chunk-IWQAX3CS.js";
10
13
  import {
11
14
  OpenAIResponseTransformer
12
- } from "./chunk-TIER4SUC.js";
13
- import {
14
- OpenCodeGoTransformer
15
- } from "./chunk-Z7LUNECE.js";
15
+ } from "./chunk-BODMAL6G.js";
16
16
  import {
17
17
  GeminiCodeAssistTransformer
18
- } from "./chunk-Z7Y2NPHY.js";
18
+ } from "./chunk-MFZ5437A.js";
19
19
 
20
20
  // src/transformer/transformers/DeepseekTransformer.ts
21
21
  var DeepseekTransformer = class {
@@ -32,7 +32,14 @@ var DeepseekTransformer = class {
32
32
  this.logger?.debug("DeepSeek: Limiting max_tokens from %d to 8192", request.max_tokens);
33
33
  request.max_tokens = 8192;
34
34
  }
35
- return request;
35
+ const sanitizedMessages = (request.messages ?? []).map((m) => {
36
+ const out = { role: m.role };
37
+ if (m.content !== void 0) out.content = m.content;
38
+ if (m.tool_calls) out.tool_calls = m.tool_calls;
39
+ if (m.tool_call_id) out.tool_call_id = m.tool_call_id;
40
+ return out;
41
+ });
42
+ return { ...request, messages: sanitizedMessages };
36
43
  }
37
44
  /**
38
45
  * Transform response: convert reasoning_content to thinking blocks