@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.
- package/dist/auth/GeminiCodeAssistProjectResolver.cjs +6 -5
- package/dist/auth/GeminiCodeAssistProjectResolver.js +4 -3
- package/dist/{chunk-SU2GCLAC.cjs → chunk-3Q6Z6JTO.cjs} +124 -16
- package/dist/chunk-3Z5BQZFM.cjs +52 -0
- package/dist/{chunk-4VAVYUZS.cjs → chunk-4XMYPW46.cjs} +9 -9
- package/dist/{chunk-S4WBV25P.js → chunk-6QZGDLL4.js} +106 -23
- package/dist/{chunk-C72S6TTV.cjs → chunk-7FEBOPJO.cjs} +5 -4
- package/dist/{chunk-TIER4SUC.js → chunk-BODMAL6G.js} +119 -11
- package/dist/{chunk-DKPXN34V.cjs → chunk-CGKLE6IW.cjs} +145 -30
- package/dist/{chunk-XK5CIRMQ.js → chunk-D3TDKWRP.js} +60 -2
- package/dist/{chunk-RSJ3TWJQ.cjs → chunk-DDMRUL76.cjs} +5 -5
- package/dist/{chunk-QYTT6GE3.js → chunk-FH2P4OCD.js} +124 -9
- package/dist/{chunk-Z7LUNECE.js → chunk-IB3FDI4O.js} +5 -4
- package/dist/{chunk-7Y47UCF2.js → chunk-IFXJ2BG7.js} +5 -38
- package/dist/{chunk-C7PSERMH.js → chunk-IWQAX3CS.js} +1 -1
- package/dist/{chunk-YGXJGRFI.cjs → chunk-JWVTXXPX.cjs} +106 -23
- package/dist/{chunk-7YN22L2H.cjs → chunk-K52THW2C.cjs} +5 -5
- package/dist/{chunk-Z7Y2NPHY.js → chunk-MFZ5437A.js} +1 -1
- package/dist/{chunk-VPBAUQ2M.js → chunk-OQWKZCXP.js} +15 -8
- package/dist/{chunk-OCEUVQHW.cjs → chunk-PG7PS2NN.cjs} +61 -3
- package/dist/chunk-SYQF7OIR.js +52 -0
- package/dist/{chunk-E3UCVHLP.cjs → chunk-UNWKG6EI.cjs} +5 -38
- package/dist/{chunk-RGTR7CIO.cjs → chunk-ZCIQ3L3R.cjs} +19 -12
- package/dist/completion/CompletionService.cjs +13 -12
- package/dist/completion/CompletionService.js +12 -11
- package/dist/completion.cjs +13 -12
- package/dist/completion.js +12 -11
- package/dist/index.cjs +15 -14
- package/dist/index.js +14 -13
- package/dist/outbound-api/auditCapture.cjs +2 -2
- package/dist/outbound-api/auditCapture.d.cts +5 -3
- package/dist/outbound-api/auditCapture.d.ts +5 -3
- package/dist/outbound-api/auditCapture.js +1 -1
- package/dist/outbound-api.cjs +13 -12
- package/dist/outbound-api.js +12 -11
- package/dist/pipeline/upstreamFetch.cjs +3 -2
- package/dist/pipeline/upstreamFetch.d.cts +6 -0
- package/dist/pipeline/upstreamFetch.d.ts +6 -0
- package/dist/pipeline/upstreamFetch.js +2 -1
- package/dist/pipeline/upstreamTrace.cjs +14 -0
- package/dist/pipeline/upstreamTrace.d.cts +85 -0
- package/dist/pipeline/upstreamTrace.d.ts +85 -0
- package/dist/pipeline/upstreamTrace.js +14 -0
- package/dist/provider-proxy/ProviderProxy.cjs +13 -12
- package/dist/provider-proxy/ProviderProxy.js +12 -11
- package/dist/provider-proxy/ingress/providerProxyShared.cjs +15 -12
- package/dist/provider-proxy/ingress/providerProxyShared.d.cts +17 -1
- package/dist/provider-proxy/ingress/providerProxyShared.d.ts +17 -1
- package/dist/provider-proxy/ingress/providerProxyShared.js +14 -11
- package/dist/provider-proxy.cjs +13 -12
- package/dist/provider-proxy.js +12 -11
- package/dist/transformer/transformers/AnthropicTransformer.cjs +2 -2
- package/dist/transformer/transformers/AnthropicTransformer.js +1 -1
- package/dist/transformer/transformers/GeminiCodeAssistTransformer.cjs +3 -3
- package/dist/transformer/transformers/GeminiCodeAssistTransformer.js +2 -2
- package/dist/transformer/transformers/GeminiTransformer.cjs +3 -3
- package/dist/transformer/transformers/GeminiTransformer.js +2 -2
- package/dist/transformer/transformers/OpenAIResponseTransformer.cjs +2 -2
- package/dist/transformer/transformers/OpenAIResponseTransformer.js +1 -1
- package/dist/transformer/transformers/OpenCodeGoTransformer.cjs +2 -2
- package/dist/transformer/transformers/OpenCodeGoTransformer.js +1 -1
- package/dist/transformer/transformers.cjs +9 -9
- package/dist/transformer/transformers.js +9 -9
- package/dist/transformer.cjs +11 -11
- package/dist/transformer.js +10 -10
- package/package.json +1 -1
- package/dist/{chunk-FTQ7IQUC.js → chunk-C6OV7GCC.js} +8 -8
|
@@ -45,10 +45,12 @@ var OpenAIResponseTransformer = class {
|
|
|
45
45
|
if (msg.role === "assistant" && msg.tool_calls?.length) {
|
|
46
46
|
input.push(entry);
|
|
47
47
|
for (const tc of msg.tool_calls) {
|
|
48
|
+
const callId = tc.id;
|
|
49
|
+
const itemId = callId.startsWith("fc_") ? callId : `fc_${callId.replace(/^(call_|fc_)/, "")}`;
|
|
48
50
|
input.push({
|
|
49
51
|
type: "function_call",
|
|
50
|
-
id:
|
|
51
|
-
call_id:
|
|
52
|
+
id: itemId,
|
|
53
|
+
call_id: callId,
|
|
52
54
|
name: tc.function.name,
|
|
53
55
|
arguments: tc.function.arguments
|
|
54
56
|
});
|
|
@@ -61,7 +63,11 @@ var OpenAIResponseTransformer = class {
|
|
|
61
63
|
const body = {
|
|
62
64
|
model: request.model,
|
|
63
65
|
input,
|
|
64
|
-
stream:
|
|
66
|
+
// codex's backend REQUIRES `stream:true` (it 400s with "Stream must be
|
|
67
|
+
// set to true" otherwise). Always force it; a non-streaming CLIENT is
|
|
68
|
+
// served by aggregating the SSE upstream of the wire (the ingress buffers
|
|
69
|
+
// it into a single message), not by asking codex for a non-streaming reply.
|
|
70
|
+
stream: true,
|
|
65
71
|
// `store:false` is required by the codex backend and accepted by the
|
|
66
72
|
// public Responses API (which defaults to store:true). Always set it so
|
|
67
73
|
// codex relays (no discoverable url token) work without configuration.
|
|
@@ -335,6 +341,7 @@ function convertResponseApiStreamToOpenAI(responseApiStream) {
|
|
|
335
341
|
const messageId = `chatcmpl-${Date.now()}`;
|
|
336
342
|
let model = "unknown";
|
|
337
343
|
let hasEmittedRole = false;
|
|
344
|
+
let hasToolCalls = false;
|
|
338
345
|
const safeEnqueue = (str) => {
|
|
339
346
|
if (!isClosed) {
|
|
340
347
|
try {
|
|
@@ -391,6 +398,42 @@ function convertResponseApiStreamToOpenAI(responseApiStream) {
|
|
|
391
398
|
}]);
|
|
392
399
|
}
|
|
393
400
|
break;
|
|
401
|
+
case "response.output_item.added": {
|
|
402
|
+
const item = event.item;
|
|
403
|
+
if (item?.type !== "function_call") break;
|
|
404
|
+
if (!hasEmittedRole) {
|
|
405
|
+
emitChunk([{ index: 0, delta: { role: "assistant", content: null }, finish_reason: null }]);
|
|
406
|
+
hasEmittedRole = true;
|
|
407
|
+
}
|
|
408
|
+
hasToolCalls = true;
|
|
409
|
+
emitChunk([{
|
|
410
|
+
index: 0,
|
|
411
|
+
delta: {
|
|
412
|
+
tool_calls: [{
|
|
413
|
+
index: event.output_index ?? 0,
|
|
414
|
+
id: item.call_id,
|
|
415
|
+
type: "function",
|
|
416
|
+
function: { name: item.name, arguments: "" }
|
|
417
|
+
}]
|
|
418
|
+
},
|
|
419
|
+
finish_reason: null
|
|
420
|
+
}]);
|
|
421
|
+
break;
|
|
422
|
+
}
|
|
423
|
+
case "response.function_call_arguments.delta": {
|
|
424
|
+
hasToolCalls = true;
|
|
425
|
+
emitChunk([{
|
|
426
|
+
index: 0,
|
|
427
|
+
delta: {
|
|
428
|
+
tool_calls: [{
|
|
429
|
+
index: event.output_index ?? 0,
|
|
430
|
+
function: { arguments: event.delta ?? "" }
|
|
431
|
+
}]
|
|
432
|
+
},
|
|
433
|
+
finish_reason: null
|
|
434
|
+
}]);
|
|
435
|
+
break;
|
|
436
|
+
}
|
|
394
437
|
case "response.completed": {
|
|
395
438
|
const resp = event.response;
|
|
396
439
|
const respUsage = resp?.usage;
|
|
@@ -399,7 +442,7 @@ function convertResponseApiStreamToOpenAI(responseApiStream) {
|
|
|
399
442
|
completion_tokens: respUsage.output_tokens || 0,
|
|
400
443
|
total_tokens: (respUsage.input_tokens || 0) + (respUsage.output_tokens || 0)
|
|
401
444
|
} : void 0;
|
|
402
|
-
emitChunk([{ index: 0, delta: {}, finish_reason: "stop" }], usage);
|
|
445
|
+
emitChunk([{ index: 0, delta: {}, finish_reason: hasToolCalls ? "tool_calls" : "stop" }], usage);
|
|
403
446
|
safeEnqueue("data: [DONE]\n\n");
|
|
404
447
|
break;
|
|
405
448
|
}
|
|
@@ -442,6 +485,9 @@ function convertOpenAIStreamToResponseApi(openaiStream) {
|
|
|
442
485
|
let accumulatedContent = "";
|
|
443
486
|
let model = "unknown";
|
|
444
487
|
const responseId = `resp_${Date.now()}`;
|
|
488
|
+
const toolCalls = /* @__PURE__ */ new Map();
|
|
489
|
+
const toolOutputIndex = /* @__PURE__ */ new Map();
|
|
490
|
+
let nextOutputIndex = 1;
|
|
445
491
|
const safeEnqueue = (str) => {
|
|
446
492
|
if (!isClosed) {
|
|
447
493
|
try {
|
|
@@ -487,21 +533,83 @@ function convertOpenAIStreamToResponseApi(openaiStream) {
|
|
|
487
533
|
delta: choice.delta.thinking.content
|
|
488
534
|
});
|
|
489
535
|
}
|
|
536
|
+
if (choice.delta?.tool_calls) {
|
|
537
|
+
for (const tc of choice.delta.tool_calls) {
|
|
538
|
+
const tcIndex = typeof tc["index"] === "number" ? tc["index"] : 0;
|
|
539
|
+
const func = tc["function"] ?? {};
|
|
540
|
+
let entry = toolCalls.get(tcIndex);
|
|
541
|
+
if (!entry) {
|
|
542
|
+
const callId = typeof tc["id"] === "string" ? tc["id"] : `call_${Date.now()}_${tcIndex}`;
|
|
543
|
+
const name = typeof func["name"] === "string" ? func["name"] : "";
|
|
544
|
+
entry = { callId, name, arguments: "" };
|
|
545
|
+
toolCalls.set(tcIndex, entry);
|
|
546
|
+
const outIdx = nextOutputIndex++;
|
|
547
|
+
toolOutputIndex.set(tcIndex, outIdx);
|
|
548
|
+
const itemId = callId.startsWith("fc_") ? callId : `fc_${callId.replace(/^(call_|fc_)/, "")}`;
|
|
549
|
+
emitEvent({
|
|
550
|
+
type: "response.output_item.added",
|
|
551
|
+
output_index: outIdx,
|
|
552
|
+
item: {
|
|
553
|
+
id: itemId,
|
|
554
|
+
type: "function_call",
|
|
555
|
+
status: "in_progress",
|
|
556
|
+
call_id: callId,
|
|
557
|
+
name,
|
|
558
|
+
arguments: ""
|
|
559
|
+
}
|
|
560
|
+
});
|
|
561
|
+
}
|
|
562
|
+
const argsFragment = typeof func["arguments"] === "string" ? func["arguments"] : "";
|
|
563
|
+
if (argsFragment) {
|
|
564
|
+
entry.arguments += argsFragment;
|
|
565
|
+
emitEvent({
|
|
566
|
+
type: "response.function_call_arguments.delta",
|
|
567
|
+
output_index: toolOutputIndex.get(tcIndex),
|
|
568
|
+
delta: argsFragment
|
|
569
|
+
});
|
|
570
|
+
}
|
|
571
|
+
}
|
|
572
|
+
}
|
|
490
573
|
if (choice.finish_reason) {
|
|
491
574
|
emitEvent({ type: "response.output_text.done", text: accumulatedContent });
|
|
575
|
+
const output = [];
|
|
576
|
+
if (accumulatedContent) {
|
|
577
|
+
output.push({
|
|
578
|
+
type: "message",
|
|
579
|
+
role: "assistant",
|
|
580
|
+
content: [{ type: "output_text", text: accumulatedContent }]
|
|
581
|
+
});
|
|
582
|
+
}
|
|
583
|
+
for (const [tcIndex, entry] of toolCalls) {
|
|
584
|
+
const itemId = entry.callId.startsWith("fc_") ? entry.callId : `fc_${entry.callId.replace(/^(call_|fc_)/, "")}`;
|
|
585
|
+
output.push({
|
|
586
|
+
id: itemId,
|
|
587
|
+
type: "function_call",
|
|
588
|
+
status: "completed",
|
|
589
|
+
call_id: entry.callId,
|
|
590
|
+
name: entry.name,
|
|
591
|
+
arguments: entry.arguments
|
|
592
|
+
});
|
|
593
|
+
emitEvent({
|
|
594
|
+
type: "response.output_item.done",
|
|
595
|
+
output_index: toolOutputIndex.get(tcIndex),
|
|
596
|
+
item: {
|
|
597
|
+
id: itemId,
|
|
598
|
+
type: "function_call",
|
|
599
|
+
status: "completed",
|
|
600
|
+
call_id: entry.callId,
|
|
601
|
+
name: entry.name,
|
|
602
|
+
arguments: entry.arguments
|
|
603
|
+
}
|
|
604
|
+
});
|
|
605
|
+
}
|
|
492
606
|
emitEvent({
|
|
493
607
|
type: "response.completed",
|
|
494
608
|
response: {
|
|
495
609
|
id: responseId,
|
|
496
610
|
status: "completed",
|
|
497
611
|
model,
|
|
498
|
-
output
|
|
499
|
-
{
|
|
500
|
-
type: "message",
|
|
501
|
-
role: "assistant",
|
|
502
|
-
content: [{ type: "output_text", text: accumulatedContent }]
|
|
503
|
-
}
|
|
504
|
-
],
|
|
612
|
+
output,
|
|
505
613
|
usage: chunk.usage ? {
|
|
506
614
|
input_tokens: chunk.usage.prompt_tokens || 0,
|
|
507
615
|
output_tokens: chunk.usage.completion_tokens || 0,
|
|
@@ -3,16 +3,16 @@
|
|
|
3
3
|
var _chunkHQP3K7PUcjs = require('./chunk-HQP3K7PU.cjs');
|
|
4
4
|
|
|
5
5
|
|
|
6
|
-
var
|
|
6
|
+
var _chunk46ZIFWYGcjs = require('./chunk-46ZIFWYG.cjs');
|
|
7
7
|
|
|
8
8
|
|
|
9
|
-
var
|
|
9
|
+
var _chunk4XMYPW46cjs = require('./chunk-4XMYPW46.cjs');
|
|
10
10
|
|
|
11
11
|
|
|
12
|
-
var
|
|
12
|
+
var _chunkK52THW2Ccjs = require('./chunk-K52THW2C.cjs');
|
|
13
13
|
|
|
14
14
|
|
|
15
|
-
var
|
|
15
|
+
var _chunk3Q6Z6JTOcjs = require('./chunk-3Q6Z6JTO.cjs');
|
|
16
16
|
|
|
17
17
|
|
|
18
18
|
var _chunkGBHYAGX3cjs = require('./chunk-GBHYAGX3.cjs');
|
|
@@ -80,14 +80,14 @@ var _chunkVACWOIREcjs = require('./chunk-VACWOIRE.cjs');
|
|
|
80
80
|
var _chunkA2YMUCBTcjs = require('./chunk-A2YMUCBT.cjs');
|
|
81
81
|
|
|
82
82
|
|
|
83
|
-
var
|
|
83
|
+
var _chunkUNWKG6EIcjs = require('./chunk-UNWKG6EI.cjs');
|
|
84
84
|
|
|
85
85
|
|
|
86
86
|
|
|
87
87
|
var _chunkSUEGJ75Dcjs = require('./chunk-SUEGJ75D.cjs');
|
|
88
88
|
|
|
89
89
|
|
|
90
|
-
var
|
|
90
|
+
var _chunkPG7PS2NNcjs = require('./chunk-PG7PS2NN.cjs');
|
|
91
91
|
|
|
92
92
|
|
|
93
93
|
var _chunkJMJBSACDcjs = require('./chunk-JMJBSACD.cjs');
|
|
@@ -517,17 +517,17 @@ function getSharedExecutor() {
|
|
|
517
517
|
}
|
|
518
518
|
var sharedResponses = null;
|
|
519
519
|
function getResponsesEndpointTransformer() {
|
|
520
|
-
if (!sharedResponses) sharedResponses = new (0,
|
|
520
|
+
if (!sharedResponses) sharedResponses = new (0, _chunk3Q6Z6JTOcjs.OpenAIResponseTransformer)();
|
|
521
521
|
return sharedResponses;
|
|
522
522
|
}
|
|
523
523
|
var sharedAnthropic = null;
|
|
524
524
|
function getAnthropicEndpointTransformer() {
|
|
525
|
-
if (!sharedAnthropic) sharedAnthropic = new (0,
|
|
525
|
+
if (!sharedAnthropic) sharedAnthropic = new (0, _chunk4XMYPW46cjs.AnthropicTransformer)();
|
|
526
526
|
return sharedAnthropic;
|
|
527
527
|
}
|
|
528
528
|
var sharedGemini = null;
|
|
529
529
|
function getGeminiEndpointTransformer() {
|
|
530
|
-
if (!sharedGemini) sharedGemini = new (0,
|
|
530
|
+
if (!sharedGemini) sharedGemini = new (0, _chunkK52THW2Ccjs.GeminiTransformer)();
|
|
531
531
|
return sharedGemini;
|
|
532
532
|
}
|
|
533
533
|
function readBody(req) {
|
|
@@ -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 (e7) {
|
|
674
|
+
continue;
|
|
675
|
+
}
|
|
676
|
+
switch (ev["type"]) {
|
|
677
|
+
case "message_start": {
|
|
678
|
+
const m = _nullishCoalesce(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 = _nullishCoalesce(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 = _nullishCoalesce(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 = _nullishCoalesce(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 (e8) {
|
|
729
|
+
input = {};
|
|
730
|
+
}
|
|
731
|
+
return { type: "tool_use", id: _nullishCoalesce(blk.id, () => ( "")), name: _nullishCoalesce(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" });
|
|
@@ -816,7 +905,7 @@ async function runPipeline(anthropicBody, plan, reportSelection) {
|
|
|
816
905
|
},
|
|
817
906
|
fetchFn: (url, headers, body) => {
|
|
818
907
|
console.info(`[ProviderProxy:anthropic] -> ${url} model=${resolvedModel} stream=${isStream}`);
|
|
819
|
-
return
|
|
908
|
+
return _chunkPG7PS2NNcjs.fetchUpstream.call(void 0,
|
|
820
909
|
url,
|
|
821
910
|
{ method: "POST", headers, body: JSON.stringify(body) },
|
|
822
911
|
{ providerId: proxyProviderId(plan), accountId: proxyAccountId }
|
|
@@ -859,7 +948,7 @@ async function runSubscriptionSameFormatFetch(rawBody, plan, reportSelection, op
|
|
|
859
948
|
console.info(
|
|
860
949
|
`[ProviderProxy:anthropic] (subscription same-format) -> ${plan.upstreamUrl} model=${outboundModel} stream=${plan.isStream}`
|
|
861
950
|
);
|
|
862
|
-
const response = await
|
|
951
|
+
const response = await _chunkPG7PS2NNcjs.fetchUpstream.call(void 0,
|
|
863
952
|
plan.upstreamUrl,
|
|
864
953
|
{ method: "POST", headers, body: outboundBody },
|
|
865
954
|
{ providerId: proxyProviderId(plan), accountId: proxyAccountId }
|
|
@@ -875,7 +964,7 @@ function rewriteBodyModel(rawBody, model) {
|
|
|
875
964
|
if (!parsed || typeof parsed !== "object" || Array.isArray(parsed)) return rawBody;
|
|
876
965
|
parsed.model = model;
|
|
877
966
|
return JSON.stringify(parsed);
|
|
878
|
-
} catch (
|
|
967
|
+
} catch (e9) {
|
|
879
968
|
return rawBody;
|
|
880
969
|
}
|
|
881
970
|
}
|
|
@@ -903,7 +992,7 @@ async function readBoundedBody(response, max = 2048) {
|
|
|
903
992
|
try {
|
|
904
993
|
const text = await response.clone().text();
|
|
905
994
|
return text.slice(0, max);
|
|
906
|
-
} catch (
|
|
995
|
+
} catch (e10) {
|
|
907
996
|
return void 0;
|
|
908
997
|
}
|
|
909
998
|
}
|
|
@@ -1014,7 +1103,7 @@ async function handleAnthropicMessagesByo(res, rawBody, route, deps, options = {
|
|
|
1014
1103
|
let anthropicBody;
|
|
1015
1104
|
try {
|
|
1016
1105
|
anthropicBody = JSON.parse(rawBody);
|
|
1017
|
-
} catch (
|
|
1106
|
+
} catch (e11) {
|
|
1018
1107
|
writeError(res, 400, "Invalid JSON in request body");
|
|
1019
1108
|
return;
|
|
1020
1109
|
}
|
|
@@ -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
|
|
1118
|
+
const upstreamResponse = providerResponse.response;
|
|
1119
|
+
const upstreamSse = (_nullishCoalesce(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,
|
|
@@ -1111,7 +1214,7 @@ async function runSameFormatFetch(bodyToSend, plan, options, keyOverride) {
|
|
|
1111
1214
|
_chunkGBHYAGX3cjs.injectExtendedContextBeta.call(void 0, headers, resolvedModel, _nullishCoalesce(extendedContextEnabled, () => ( false)));
|
|
1112
1215
|
const url = _chunkA2YMUCBTcjs.buildProviderApiUrl.call(void 0, provider, { model: resolvedModel, stream: isStream });
|
|
1113
1216
|
console.info(`[ProviderProxy:anthropic] (same-format) -> ${url} model=${resolvedModel} stream=${isStream}`);
|
|
1114
|
-
const response = await
|
|
1217
|
+
const response = await _chunkPG7PS2NNcjs.fetchUpstream.call(void 0,
|
|
1115
1218
|
url,
|
|
1116
1219
|
{ method: "POST", headers, body: bodyToSend },
|
|
1117
1220
|
{ providerId: "byo" }
|
|
@@ -1123,7 +1226,7 @@ function resolveSameFormatBody(anthropicBody, rawBody, plan) {
|
|
|
1123
1226
|
try {
|
|
1124
1227
|
const m = JSON.parse(rawBody).model;
|
|
1125
1228
|
originalModel = typeof m === "string" ? m : void 0;
|
|
1126
|
-
} catch (
|
|
1229
|
+
} catch (e12) {
|
|
1127
1230
|
originalModel = void 0;
|
|
1128
1231
|
}
|
|
1129
1232
|
return plan.resolvedModel !== originalModel ? JSON.stringify(anthropicBody) : rawBody;
|
|
@@ -1223,7 +1326,7 @@ function recordGeminiNonStreamUsage(recorder, bodyText, attribution) {
|
|
|
1223
1326
|
usage: tapped,
|
|
1224
1327
|
rawUsage: parsed.usageMetadata
|
|
1225
1328
|
});
|
|
1226
|
-
} catch (
|
|
1329
|
+
} catch (e13) {
|
|
1227
1330
|
}
|
|
1228
1331
|
}
|
|
1229
1332
|
|
|
@@ -1247,7 +1350,7 @@ async function handleGeminiGenerateContentRequest(res, rawBody, url, route, deps
|
|
|
1247
1350
|
let geminiBody;
|
|
1248
1351
|
try {
|
|
1249
1352
|
geminiBody = JSON.parse(rawBody);
|
|
1250
|
-
} catch (
|
|
1353
|
+
} catch (e14) {
|
|
1251
1354
|
writeError(res, 400, "Invalid JSON in request body");
|
|
1252
1355
|
return;
|
|
1253
1356
|
}
|
|
@@ -1346,7 +1449,7 @@ async function runPipeline2(geminiBody, plan) {
|
|
|
1346
1449
|
},
|
|
1347
1450
|
fetchFn: (url, headers, body) => {
|
|
1348
1451
|
console.log(`[ProviderProxy:gemini] -> ${url} model=${resolvedModel} stream=${isStream}`);
|
|
1349
|
-
return
|
|
1452
|
+
return _chunkPG7PS2NNcjs.fetchUpstream.call(void 0,
|
|
1350
1453
|
url,
|
|
1351
1454
|
{ method: "POST", headers, body: JSON.stringify(body) },
|
|
1352
1455
|
{ providerId: "byo" }
|
|
@@ -1408,7 +1511,7 @@ function recordChatCompletionsNonStreamUsage(recorder, bodyText, attribution) {
|
|
|
1408
1511
|
usage: tapped,
|
|
1409
1512
|
rawUsage: parsed.usage
|
|
1410
1513
|
});
|
|
1411
|
-
} catch (
|
|
1514
|
+
} catch (e15) {
|
|
1412
1515
|
}
|
|
1413
1516
|
}
|
|
1414
1517
|
|
|
@@ -1424,7 +1527,7 @@ async function handleOpenAIChatRequest(res, rawBody, route, deps) {
|
|
|
1424
1527
|
let chatBody;
|
|
1425
1528
|
try {
|
|
1426
1529
|
chatBody = JSON.parse(rawBody);
|
|
1427
|
-
} catch (
|
|
1530
|
+
} catch (e16) {
|
|
1428
1531
|
writeError(res, 400, "Invalid JSON in request body");
|
|
1429
1532
|
return;
|
|
1430
1533
|
}
|
|
@@ -1569,7 +1672,7 @@ async function runPipeline3(chatBody, plan) {
|
|
|
1569
1672
|
},
|
|
1570
1673
|
fetchFn: (url, headers, body) => {
|
|
1571
1674
|
console.log(`[ProviderProxy:chat] -> ${url} model=${resolvedModel} stream=${isStream}`);
|
|
1572
|
-
return
|
|
1675
|
+
return _chunkPG7PS2NNcjs.fetchUpstream.call(void 0,
|
|
1573
1676
|
url,
|
|
1574
1677
|
{ method: "POST", headers, body: JSON.stringify(body) },
|
|
1575
1678
|
{ providerId: plan.proxyProviderId, accountId: proxyAccountId }
|
|
@@ -1642,7 +1745,7 @@ function recordResponsesNonStreamUsage(recorder, bodyText, attribution) {
|
|
|
1642
1745
|
usage: tapped,
|
|
1643
1746
|
rawUsage: parsed.usage
|
|
1644
1747
|
});
|
|
1645
|
-
} catch (
|
|
1748
|
+
} catch (e17) {
|
|
1646
1749
|
}
|
|
1647
1750
|
}
|
|
1648
1751
|
|
|
@@ -1656,7 +1759,7 @@ async function handleOpenAIResponsesRequest(res, rawBody, route, deps) {
|
|
|
1656
1759
|
let responsesBody;
|
|
1657
1760
|
try {
|
|
1658
1761
|
responsesBody = JSON.parse(rawBody);
|
|
1659
|
-
} catch (
|
|
1762
|
+
} catch (e18) {
|
|
1660
1763
|
writeError(res, 400, "Invalid JSON in request body");
|
|
1661
1764
|
return;
|
|
1662
1765
|
}
|
|
@@ -1815,7 +1918,7 @@ async function runPipeline4(responsesBody, plan) {
|
|
|
1815
1918
|
},
|
|
1816
1919
|
fetchFn: (url, headers, body) => {
|
|
1817
1920
|
console.log(`[ProviderProxy:responses] -> ${url} model=${resolvedModel} stream=${isStream}`);
|
|
1818
|
-
return
|
|
1921
|
+
return _chunkPG7PS2NNcjs.fetchUpstream.call(void 0,
|
|
1819
1922
|
url,
|
|
1820
1923
|
{ method: "POST", headers, body: JSON.stringify(body) },
|
|
1821
1924
|
{ providerId: plan.proxyProviderId, accountId: proxyAccountId }
|
|
@@ -3096,7 +3199,7 @@ async function handleVoucherRedeem(req, res, deps, voucherEnabled, redeemLimiter
|
|
|
3096
3199
|
let code;
|
|
3097
3200
|
try {
|
|
3098
3201
|
code = raw ? JSON.parse(raw)["code"] : void 0;
|
|
3099
|
-
} catch (
|
|
3202
|
+
} catch (e19) {
|
|
3100
3203
|
writeErr(res, 400, "Invalid JSON in request body");
|
|
3101
3204
|
return;
|
|
3102
3205
|
}
|
|
@@ -3255,7 +3358,7 @@ function shimAuthHeader(req, routeToken) {
|
|
|
3255
3358
|
}
|
|
3256
3359
|
async function handleOutboundRequest(req, res, deps, config, rateLimiter, serialQueue, concurrencyGate, redeemLimiter, redeemMutex) {
|
|
3257
3360
|
const now = Date.now();
|
|
3258
|
-
const audit =
|
|
3361
|
+
const audit = _chunkUNWKG6EIcjs.beginAuditCapture.call(void 0, req, res, now);
|
|
3259
3362
|
const billing = _chunkAPYG5QD7cjs.beginBillingCapture.call(void 0, req, res, now);
|
|
3260
3363
|
const presented = extractPresentedKey(req);
|
|
3261
3364
|
const verification = await verifyKey(deps.db, presented, now);
|
|
@@ -3366,7 +3469,7 @@ async function handleOutboundRequest(req, res, deps, config, rateLimiter, serial
|
|
|
3366
3469
|
let parsedBody = {};
|
|
3367
3470
|
try {
|
|
3368
3471
|
parsedBody = rawBody ? JSON.parse(rawBody) : {};
|
|
3369
|
-
} catch (
|
|
3472
|
+
} catch (e20) {
|
|
3370
3473
|
writeJsonError(res, 400, "Invalid JSON in request body");
|
|
3371
3474
|
return;
|
|
3372
3475
|
}
|
|
@@ -3595,6 +3698,7 @@ var OutboundApiServer = (_class11 = 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) {
|
|
@@ -5967,4 +6081,5 @@ ${description}`;
|
|
|
5967
6081
|
|
|
5968
6082
|
|
|
5969
6083
|
|
|
5970
|
-
|
|
6084
|
+
|
|
6085
|
+
exports.CompletionService = CompletionService; exports.register = register; exports.emit = emit; exports.attach = attach; exports.release = release; exports.convertMessageToOpenAI = convertMessageToOpenAI; exports.convertMessageToAnthropic = convertMessageToAnthropic; exports.convertMessageToGemini = convertMessageToGemini; exports.getOpenRouterProviderConfig = getOpenRouterProviderConfig; exports.addOpenRouterProviderToRequest = addOpenRouterProviderToRequest; exports.DEFAULT_ROUTE_IDLE_MS = DEFAULT_ROUTE_IDLE_MS; exports.ProviderProxyRouteMap = ProviderProxyRouteMap; exports.getSharedExecutor = getSharedExecutor; exports.getResponsesEndpointTransformer = getResponsesEndpointTransformer; exports.getAnthropicEndpointTransformer = getAnthropicEndpointTransformer; exports.getGeminiEndpointTransformer = getGeminiEndpointTransformer; exports.readBody = readBody; exports.relayResponse = relayResponse; exports.aggregateAnthropicSseToJsonBody = aggregateAnthropicSseToJsonBody; exports.writeError = writeError; exports.resolvePoolBoundKey = resolvePoolBoundKey; exports.extractRouteToken = extractRouteToken; exports.isLoopbackAddress = isLoopbackAddress; exports.ProviderProxy = ProviderProxy; exports.getProviderProxy = getProviderProxy; exports.__resetProviderProxyForTests = __resetProviderProxyForTests; exports.KeyedMutex = KeyedMutex; exports.OUTBOUND_API_SERVER_CONFIG_KEY = OUTBOUND_API_SERVER_CONFIG_KEY; exports.DEFAULT_USER_MESSAGE_QUEUE = DEFAULT_USER_MESSAGE_QUEUE; exports.DEFAULT_CONCURRENCY_QUEUE = DEFAULT_CONCURRENCY_QUEUE; exports.DEFAULT_ACCOUNT_PROBE = DEFAULT_ACCOUNT_PROBE; exports.normalizeAccountProbe = normalizeAccountProbe; exports.normalizeAudit = normalizeAudit; exports.normalizeBilling = normalizeBilling; exports.DEFAULT_FINGERPRINT = DEFAULT_FINGERPRINT; exports.normalizeFingerprint = normalizeFingerprint; exports.normalizeVoucher = normalizeVoucher; exports.normalizeProxyConfig = normalizeProxyConfig; exports.normalizeProxySegment = normalizeProxySegment; exports.normalizeWebhookDestination = normalizeWebhookDestination; exports.normalizeWebhookSegment = normalizeWebhookSegment; exports.normalizeQueueSegments = normalizeQueueSegments; exports.normalizePrefixTargets = normalizePrefixTargets; exports.defaultServerConfig = defaultServerConfig; exports.normalizeServerConfig = normalizeServerConfig; exports.loadServerConfig = loadServerConfig; exports.saveServerConfig = saveServerConfig; exports.mergeServerConfig = mergeServerConfig; exports.computeKeyExpiry = computeKeyExpiry; exports.checkKeyQuota = checkKeyQuota; exports.randomBase62 = randomBase62; exports.hashKey = hashKey; exports.createNamedKey = createNamedKey; exports.verifyKey = verifyKey; exports.verifyPresentedKey = verifyPresentedKey; exports.ConcurrencyQueueFullError = ConcurrencyQueueFullError; exports.ConcurrencyWaitTimeoutError = ConcurrencyWaitTimeoutError; exports.ConcurrencyWaitCancelledError = ConcurrencyWaitCancelledError; exports.isConcurrencyRejection = isConcurrencyRejection; exports.OutboundConcurrencyGate = OutboundConcurrencyGate; exports.OutboundRateLimiter = OutboundRateLimiter; exports.isUserMessageRequest = isUserMessageRequest; exports.SerialQueueTimeoutError = SerialQueueTimeoutError; exports.isSerialQueueTimeout = isSerialQueueTimeout; exports.UserMessageSerialQueue = UserMessageSerialQueue; exports.generateVoucherCode = generateVoucherCode; exports.hashVoucherCode = hashVoucherCode; exports.voucherCodePrefix = voucherCodePrefix; exports.newVoucherId = newVoucherId; exports.computeVoucherGrant = computeVoucherGrant; exports.toVoucherInfo = toVoucherInfo; exports.isRedeemRequest = isRedeemRequest; exports.handleVoucherRedeem = handleVoucherRedeem; exports.DEFAULT_OUTBOUND_PORT = DEFAULT_OUTBOUND_PORT; exports.OutboundApiConfigError = OutboundApiConfigError; exports.OutboundApiServer = OutboundApiServer; exports.formatUrls = formatUrls; exports.startOfLocalDay = startOfLocalDay; exports.startOfLocalWeek = startOfLocalWeek; exports.KeySpendTracker = KeySpendTracker; exports.getOutboundApiServer = getOutboundApiServer; exports.__resetOutboundApiServerForTests = __resetOutboundApiServerForTests;
|
|
@@ -1,3 +1,9 @@
|
|
|
1
|
+
import {
|
|
2
|
+
getUpstreamTracePath,
|
|
3
|
+
redactHeaders,
|
|
4
|
+
writeUpstreamTrace
|
|
5
|
+
} from "./chunk-SYQF7OIR.js";
|
|
6
|
+
|
|
1
7
|
// src/pipeline/upstreamFetch.ts
|
|
2
8
|
import { Agent, buildConnector, ProxyAgent } from "undici";
|
|
3
9
|
import { SocksClient } from "socks";
|
|
@@ -95,8 +101,60 @@ function resolveUpstreamDispatcher(ctx) {
|
|
|
95
101
|
}
|
|
96
102
|
function fetchUpstream(url, init, ctx) {
|
|
97
103
|
const dispatcher = resolveUpstreamDispatcher({ ...ctx ?? {}, url });
|
|
98
|
-
|
|
99
|
-
|
|
104
|
+
const doFetch = dispatcher ? () => fetch(url, { ...init, dispatcher }) : () => fetch(url, init);
|
|
105
|
+
const tracePath = getUpstreamTracePath();
|
|
106
|
+
if (!tracePath || !ctx?.providerId) return doFetch();
|
|
107
|
+
const startedAt = Date.now();
|
|
108
|
+
const method = typeof init.method === "string" ? init.method : "GET";
|
|
109
|
+
const requestHeaders = redactHeaders(
|
|
110
|
+
init.headers
|
|
111
|
+
);
|
|
112
|
+
const requestBody = typeof init.body === "string" ? init.body : null;
|
|
113
|
+
const providerId = ctx.providerId;
|
|
114
|
+
const accountId = ctx.accountId;
|
|
115
|
+
return doFetch().then((res) => {
|
|
116
|
+
const clone = res.clone();
|
|
117
|
+
const status = res.status;
|
|
118
|
+
const statusText = res.statusText;
|
|
119
|
+
const responseHeaders = redactHeaders(res.headers);
|
|
120
|
+
void clone.text().then((body) => {
|
|
121
|
+
writeUpstreamTrace({
|
|
122
|
+
ts: startedAt,
|
|
123
|
+
durationMs: Date.now() - startedAt,
|
|
124
|
+
providerId,
|
|
125
|
+
accountId,
|
|
126
|
+
url,
|
|
127
|
+
method,
|
|
128
|
+
requestHeaders,
|
|
129
|
+
requestBody,
|
|
130
|
+
status,
|
|
131
|
+
statusText,
|
|
132
|
+
responseHeaders,
|
|
133
|
+
responseBody: body,
|
|
134
|
+
responseBytes: Buffer.byteLength(body, "utf8")
|
|
135
|
+
});
|
|
136
|
+
}).catch(() => {
|
|
137
|
+
});
|
|
138
|
+
return res;
|
|
139
|
+
}).catch((err) => {
|
|
140
|
+
const msg = err instanceof Error ? err.message : String(err);
|
|
141
|
+
writeUpstreamTrace({
|
|
142
|
+
ts: startedAt,
|
|
143
|
+
durationMs: Date.now() - startedAt,
|
|
144
|
+
providerId,
|
|
145
|
+
accountId,
|
|
146
|
+
url,
|
|
147
|
+
method,
|
|
148
|
+
requestHeaders,
|
|
149
|
+
requestBody,
|
|
150
|
+
status: 0,
|
|
151
|
+
statusText: "",
|
|
152
|
+
responseHeaders: {},
|
|
153
|
+
responseBody: `<UPSTREAM FETCH ERROR: ${msg}>`,
|
|
154
|
+
responseBytes: 0
|
|
155
|
+
});
|
|
156
|
+
throw err;
|
|
157
|
+
});
|
|
100
158
|
}
|
|
101
159
|
function __resetUpstreamProxyForTests() {
|
|
102
160
|
resolver = null;
|