@omnicross/core 0.1.3 → 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/LICENSE +21 -21
- package/NOTICE +57 -57
- package/README.md +15 -15
- package/dist/auth/GeminiCodeAssistProjectResolver.cjs +6 -5
- package/dist/auth/GeminiCodeAssistProjectResolver.js +6 -5
- package/dist/{chunk-2DCNB7DF.cjs → chunk-3Q6Z6JTO.cjs} +154 -26
- package/dist/chunk-3QFXFCHG.js +33 -0
- package/dist/chunk-3Z5BQZFM.cjs +52 -0
- package/dist/{chunk-4VAVYUZS.cjs → chunk-4XMYPW46.cjs} +9 -9
- package/dist/chunk-4YINUUKQ.cjs +33 -0
- package/dist/{chunk-S4WBV25P.js → chunk-6QZGDLL4.js} +106 -23
- package/dist/{chunk-C72S6TTV.cjs → chunk-7FEBOPJO.cjs} +5 -4
- package/dist/chunk-APYG5QD7.cjs +50 -0
- package/dist/{chunk-5HTVET6E.js → chunk-BODMAL6G.js} +143 -15
- package/dist/{chunk-CWM2ZDU5.js → chunk-BPKCU575.js} +3 -10
- package/dist/{chunk-2FMI2B6V.cjs → chunk-CGKLE6IW.cjs} +350 -461
- package/dist/{chunk-BO4RFWBR.js → chunk-D3TDKWRP.js} +84 -3
- package/dist/{chunk-RSJ3TWJQ.cjs → chunk-DDMRUL76.cjs} +5 -5
- package/dist/chunk-FCR77GYM.cjs +33 -0
- package/dist/{chunk-4DECIFU7.js → chunk-FH2P4OCD.js} +178 -289
- package/dist/{chunk-N5QFKSDO.js → chunk-HRRYG2AX.js} +2 -1
- package/dist/{chunk-KUU2RNG6.cjs → chunk-HYN75H6G.cjs} +3 -0
- package/dist/{chunk-Z7LUNECE.js → chunk-IB3FDI4O.js} +5 -4
- package/dist/chunk-IFXJ2BG7.js +109 -0
- package/dist/{chunk-JO5NLTLY.js → chunk-IK3KE3AU.js} +3 -0
- 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-K5NM7VAH.js +33 -0
- package/dist/{chunk-Y6OM7EV7.cjs → chunk-KFI44N2R.cjs} +2 -1
- package/dist/{chunk-Z7Y2NPHY.js → chunk-MFZ5437A.js} +1 -1
- package/dist/chunk-OE6TDIWW.js +22 -0
- package/dist/{chunk-MQNDWYPN.js → chunk-OQWKZCXP.js} +13 -6
- package/dist/chunk-OZFM4X3S.js +18 -0
- package/dist/chunk-PG7PS2NN.cjs +170 -0
- package/dist/{chunk-3QOSDDNI.cjs → chunk-SNYBEXLB.cjs} +6 -13
- package/dist/chunk-SYQF7OIR.js +52 -0
- package/dist/{chunk-CZHZGRU7.js → chunk-UHGVBFU3.js} +2 -0
- package/dist/chunk-UIBD2YY5.cjs +22 -0
- package/dist/chunk-UNWKG6EI.cjs +109 -0
- package/dist/{chunk-SVXC36MU.cjs → chunk-VACWOIRE.cjs} +2 -0
- package/dist/chunk-WLYIIEAF.js +50 -0
- package/dist/chunk-XSVNC2UD.cjs +18 -0
- package/dist/{chunk-FFALUUZZ.cjs → chunk-ZCIQ3L3R.cjs} +18 -11
- package/dist/completion/CompletionService.cjs +26 -19
- package/dist/completion/CompletionService.js +25 -18
- package/dist/completion.cjs +28 -21
- package/dist/completion.js +27 -20
- package/dist/index.cjs +35 -25
- package/dist/index.d.cts +7 -3
- package/dist/index.d.ts +7 -3
- package/dist/index.js +44 -34
- package/dist/keyPolicy-Cp0FntZl.d.cts +90 -0
- package/dist/keyPolicy-Cp0FntZl.d.ts +90 -0
- package/dist/outbound-api/auditCapture.cjs +9 -0
- package/dist/outbound-api/auditCapture.d.cts +54 -0
- package/dist/outbound-api/auditCapture.d.ts +54 -0
- package/dist/outbound-api/auditCapture.js +9 -0
- package/dist/outbound-api/auditRedact.cjs +8 -0
- package/dist/outbound-api/auditRedact.d.cts +30 -0
- package/dist/outbound-api/auditRedact.d.ts +30 -0
- package/dist/outbound-api/auditRedact.js +8 -0
- package/dist/outbound-api/billingCapture.cjs +8 -0
- package/dist/outbound-api/billingCapture.d.cts +61 -0
- package/dist/outbound-api/billingCapture.d.ts +61 -0
- package/dist/outbound-api/billingCapture.js +8 -0
- package/dist/outbound-api/quotaWarn.cjs +12 -0
- package/dist/outbound-api/quotaWarn.d.cts +43 -0
- package/dist/outbound-api/quotaWarn.d.ts +43 -0
- package/dist/outbound-api/quotaWarn.js +12 -0
- package/dist/outbound-api/routeResolver.cjs +2 -2
- package/dist/outbound-api/routeResolver.d.cts +3 -2
- package/dist/outbound-api/routeResolver.d.ts +3 -2
- package/dist/outbound-api/routeResolver.js +1 -1
- package/dist/outbound-api/types.d.cts +2 -1
- package/dist/outbound-api/types.d.ts +2 -1
- package/dist/outbound-api.cjs +33 -23
- package/dist/outbound-api.d.cts +9 -140
- package/dist/outbound-api.d.ts +9 -140
- package/dist/outbound-api.js +32 -22
- package/dist/pipeline/AuthSource.d.cts +6 -0
- package/dist/pipeline/AuthSource.d.ts +6 -0
- package/dist/pipeline/SubscriptionAuthSource.cjs +2 -2
- package/dist/pipeline/SubscriptionAuthSource.js +1 -1
- package/dist/pipeline/SubscriptionAuthStrategy.d.cts +6 -0
- package/dist/pipeline/SubscriptionAuthStrategy.d.ts +6 -0
- package/dist/pipeline/auditUsageStash.cjs +10 -0
- package/dist/pipeline/auditUsageStash.d.cts +37 -0
- package/dist/pipeline/auditUsageStash.d.ts +37 -0
- package/dist/pipeline/auditUsageStash.js +10 -0
- package/dist/pipeline/executeProviderCall.cjs +2 -2
- package/dist/pipeline/executeProviderCall.js +1 -1
- package/dist/pipeline/upstreamFetch.cjs +15 -0
- package/dist/pipeline/upstreamFetch.d.cts +89 -0
- package/dist/pipeline/upstreamFetch.d.ts +89 -0
- package/dist/pipeline/upstreamFetch.js +15 -0
- 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/pipeline/webhookEmit.cjs +10 -0
- package/dist/pipeline/webhookEmit.d.cts +36 -0
- package/dist/pipeline/webhookEmit.d.ts +36 -0
- package/dist/pipeline/webhookEmit.js +10 -0
- package/dist/ports.d.cts +2 -1
- package/dist/ports.d.ts +2 -1
- package/dist/provider-proxy/ProviderProxy.cjs +26 -19
- package/dist/provider-proxy/ProviderProxy.js +25 -18
- package/dist/provider-proxy/ingress/providerProxyShared.cjs +28 -19
- 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 +27 -18
- package/dist/provider-proxy/types.d.cts +7 -0
- package/dist/provider-proxy/types.d.ts +7 -0
- package/dist/provider-proxy.cjs +26 -19
- package/dist/provider-proxy.js +25 -18
- package/dist/{routeResolver-B1NglTfe.d.ts → routeResolver-C4T7yClx.d.ts} +1 -1
- package/dist/{routeResolver-CbG5uBgm.d.cts → routeResolver-CB3tvJKy.d.cts} +1 -1
- 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 +8 -8
- package/dist/transformer/transformers.js +7 -7
- package/dist/transformer.cjs +8 -8
- package/dist/transformer.js +7 -7
- package/dist/{types-aBFFXoBz.d.cts → types-B8Arpxn0.d.cts} +14 -90
- package/dist/{types-6OUY_xfA.d.ts → types-lgPYQuZS.d.ts} +14 -90
- package/dist/usage/usage-recorder.cjs +3 -2
- package/dist/usage/usage-recorder.js +2 -1
- package/dist/usage.cjs +3 -2
- package/dist/usage.js +2 -1
- package/package.json +64 -64
- package/dist/chunk-S6JGLF3G.cjs +0 -89
- package/dist/{chunk-FTQ7IQUC.js → chunk-C6OV7GCC.js} +8 -8
|
@@ -6,16 +6,13 @@ import {
|
|
|
6
6
|
} from "./chunk-G2UTNSGU.js";
|
|
7
7
|
import {
|
|
8
8
|
AnthropicTransformer
|
|
9
|
-
} from "./chunk-
|
|
9
|
+
} from "./chunk-C6OV7GCC.js";
|
|
10
10
|
import {
|
|
11
11
|
GeminiTransformer
|
|
12
|
-
} from "./chunk-
|
|
12
|
+
} from "./chunk-IWQAX3CS.js";
|
|
13
13
|
import {
|
|
14
14
|
OpenAIResponseTransformer
|
|
15
|
-
} from "./chunk-
|
|
16
|
-
import {
|
|
17
|
-
readAuditUsage
|
|
18
|
-
} from "./chunk-CWM2ZDU5.js";
|
|
15
|
+
} from "./chunk-BODMAL6G.js";
|
|
19
16
|
import {
|
|
20
17
|
injectExtendedContextBeta
|
|
21
18
|
} from "./chunk-MZNPGW5Q.js";
|
|
@@ -31,32 +28,14 @@ import {
|
|
|
31
28
|
deriveSubscriptionSessionKey
|
|
32
29
|
} from "./chunk-IAXWICZU.js";
|
|
33
30
|
import {
|
|
34
|
-
|
|
35
|
-
} from "./chunk-
|
|
36
|
-
import {
|
|
37
|
-
getSharedAccountHealth,
|
|
38
|
-
resolveResetSeconds
|
|
39
|
-
} from "./chunk-5ENKBSWO.js";
|
|
40
|
-
import {
|
|
41
|
-
SubscriptionAuthSource
|
|
42
|
-
} from "./chunk-N5QFKSDO.js";
|
|
43
|
-
import {
|
|
44
|
-
serializeError
|
|
45
|
-
} from "./chunk-AVYJ4YBN.js";
|
|
31
|
+
emitWebhookEvent
|
|
32
|
+
} from "./chunk-OE6TDIWW.js";
|
|
46
33
|
import {
|
|
47
34
|
getGeminiCodeAssistResolver
|
|
48
35
|
} from "./chunk-DRWHTIIZ.js";
|
|
49
|
-
import {
|
|
50
|
-
getAuditCaptureConfig,
|
|
51
|
-
recordAudit
|
|
52
|
-
} from "./chunk-WNY4WMRF.js";
|
|
53
|
-
import {
|
|
54
|
-
getBillingCaptureConfig,
|
|
55
|
-
publishBillingEvent
|
|
56
|
-
} from "./chunk-TKJMZBAH.js";
|
|
57
36
|
import {
|
|
58
37
|
executeProviderCall
|
|
59
|
-
} from "./chunk-
|
|
38
|
+
} from "./chunk-IK3KE3AU.js";
|
|
60
39
|
import {
|
|
61
40
|
LlmConfigProviderAuth,
|
|
62
41
|
getProviderHeaders
|
|
@@ -65,10 +44,25 @@ import {
|
|
|
65
44
|
resolveProviderChain
|
|
66
45
|
} from "./chunk-JWC6APFQ.js";
|
|
67
46
|
import {
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
47
|
+
resolveSubscriptionChain
|
|
48
|
+
} from "./chunk-5ERIZW3D.js";
|
|
49
|
+
import {
|
|
50
|
+
getSharedAccountHealth,
|
|
51
|
+
resolveResetSeconds
|
|
52
|
+
} from "./chunk-5ENKBSWO.js";
|
|
53
|
+
import {
|
|
54
|
+
SubscriptionAuthSource
|
|
55
|
+
} from "./chunk-HRRYG2AX.js";
|
|
56
|
+
import {
|
|
57
|
+
serializeError
|
|
58
|
+
} from "./chunk-AVYJ4YBN.js";
|
|
59
|
+
import {
|
|
60
|
+
beginBillingCapture
|
|
61
|
+
} from "./chunk-WLYIIEAF.js";
|
|
62
|
+
import {
|
|
63
|
+
computeQuotaWarnings,
|
|
64
|
+
markQuotaWarnedOnce
|
|
65
|
+
} from "./chunk-3QFXFCHG.js";
|
|
72
66
|
import {
|
|
73
67
|
detectRequestRole,
|
|
74
68
|
endpointToIngressFormat,
|
|
@@ -78,14 +72,22 @@ import {
|
|
|
78
72
|
parseModelRef,
|
|
79
73
|
resolveRoute,
|
|
80
74
|
validateServerModelConfig
|
|
81
|
-
} from "./chunk-
|
|
75
|
+
} from "./chunk-UHGVBFU3.js";
|
|
76
|
+
import {
|
|
77
|
+
buildProviderApiUrl,
|
|
78
|
+
resolveApiFormat,
|
|
79
|
+
resolveProviderEndpoint
|
|
80
|
+
} from "./chunk-H5JUT3KV.js";
|
|
81
|
+
import {
|
|
82
|
+
beginAuditCapture
|
|
83
|
+
} from "./chunk-IFXJ2BG7.js";
|
|
82
84
|
import {
|
|
83
85
|
convertAnthropicToOpenAI,
|
|
84
86
|
convertOpenAIToAnthropic
|
|
85
87
|
} from "./chunk-5ZQBEOMD.js";
|
|
86
88
|
import {
|
|
87
89
|
fetchUpstream
|
|
88
|
-
} from "./chunk-
|
|
90
|
+
} from "./chunk-D3TDKWRP.js";
|
|
89
91
|
import {
|
|
90
92
|
applyAugmentation
|
|
91
93
|
} from "./chunk-Y7FO65VT.js";
|
|
@@ -649,6 +651,95 @@ async function relayResponse(res, providerResponse, isStream, rewriteModel) {
|
|
|
649
651
|
res.end(clientText);
|
|
650
652
|
return bodyText;
|
|
651
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
|
+
}
|
|
652
743
|
function writeError(res, status, message) {
|
|
653
744
|
if (res.headersSent) return;
|
|
654
745
|
res.writeHead(status, { "Content-Type": "application/json" });
|
|
@@ -715,6 +806,7 @@ function buildSubscriptionIterationPlan(profile, route, deps, resolvedModel, isS
|
|
|
715
806
|
};
|
|
716
807
|
return {
|
|
717
808
|
auth,
|
|
809
|
+
preferredAccountId: route.preferredAccountId,
|
|
718
810
|
chain,
|
|
719
811
|
transformerProvider,
|
|
720
812
|
resolvedModel,
|
|
@@ -788,6 +880,7 @@ async function runPipeline(anthropicBody, plan, reportSelection) {
|
|
|
788
880
|
upstreamUrl,
|
|
789
881
|
model: resolvedModel,
|
|
790
882
|
sessionKey: plan.sessionKey,
|
|
883
|
+
preferredAccountId: plan.preferredAccountId,
|
|
791
884
|
reportSelection: (accountId, isActive) => {
|
|
792
885
|
proxyAccountId = accountId;
|
|
793
886
|
reportSelection?.(accountId, isActive);
|
|
@@ -833,6 +926,7 @@ async function runSubscriptionSameFormatFetch(rawBody, plan, reportSelection, op
|
|
|
833
926
|
upstreamUrl: plan.upstreamUrl,
|
|
834
927
|
model: plan.resolvedModel,
|
|
835
928
|
sessionKey: plan.sessionKey,
|
|
929
|
+
preferredAccountId: plan.preferredAccountId,
|
|
836
930
|
reportSelection: (accountId, isActive, remapped) => {
|
|
837
931
|
proxyAccountId = accountId;
|
|
838
932
|
remappedModel = remapped;
|
|
@@ -1021,7 +1115,21 @@ async function handleAnthropicMessagesByo(res, rawBody, route, deps, options = {
|
|
|
1021
1115
|
if (!plan) return;
|
|
1022
1116
|
anthropicBody.model = plan.resolvedModel;
|
|
1023
1117
|
const providerResponse = route.authMode === "subscription" ? await runPipelineWithSubscriptionRetry(anthropicBody, rawBody, plan, route, deps, options) : await runPipelineWithPoolReporting(anthropicBody, rawBody, plan, options);
|
|
1024
|
-
const
|
|
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
|
+
}
|
|
1025
1133
|
if (bodyText && deps.usageRecorder) {
|
|
1026
1134
|
recordAnthropicNonStreamUsage(deps.usageRecorder, bodyText, {
|
|
1027
1135
|
sessionId: route.sessionId,
|
|
@@ -1754,6 +1862,7 @@ async function buildSubscriptionPlan3(res, route, deps, resolvedModel, isStream)
|
|
|
1754
1862
|
}
|
|
1755
1863
|
return {
|
|
1756
1864
|
auth,
|
|
1865
|
+
preferredAccountId: route.preferredAccountId,
|
|
1757
1866
|
chain,
|
|
1758
1867
|
transformerProvider,
|
|
1759
1868
|
resolvedModel,
|
|
@@ -1785,6 +1894,7 @@ async function runPipeline4(responsesBody, plan) {
|
|
|
1785
1894
|
await auth.applyHeaders(authHeaders, {
|
|
1786
1895
|
upstreamUrl,
|
|
1787
1896
|
model: resolvedModel,
|
|
1897
|
+
preferredAccountId: plan.preferredAccountId,
|
|
1788
1898
|
reportSelection: (accountId) => {
|
|
1789
1899
|
proxyAccountId = accountId;
|
|
1790
1900
|
}
|
|
@@ -2044,17 +2154,6 @@ var KeyedMutex = class {
|
|
|
2044
2154
|
// src/outbound-api/outboundApiRouter.ts
|
|
2045
2155
|
import { Readable } from "stream";
|
|
2046
2156
|
|
|
2047
|
-
// src/pipeline/webhookEmit.ts
|
|
2048
|
-
var sink = null;
|
|
2049
|
-
function emitWebhookEvent(event) {
|
|
2050
|
-
const active = sink;
|
|
2051
|
-
if (!active) return;
|
|
2052
|
-
try {
|
|
2053
|
-
active(event);
|
|
2054
|
-
} catch {
|
|
2055
|
-
}
|
|
2056
|
-
}
|
|
2057
|
-
|
|
2058
2157
|
// src/outbound-api/apiServerConfig.ts
|
|
2059
2158
|
import { DEFAULT_AUDIT_CONFIG } from "@omnicross/contracts/audit-types";
|
|
2060
2159
|
import { DEFAULT_BILLING_CONFIG } from "@omnicross/contracts/billing-types";
|
|
@@ -2291,6 +2390,9 @@ function normalizePrefixTargets(raw) {
|
|
|
2291
2390
|
function normalizeEndpointConfig(e) {
|
|
2292
2391
|
const endpoint = e.endpoint;
|
|
2293
2392
|
const useSubscription = e.useSubscription === true;
|
|
2393
|
+
const boundAccountId = typeof e.boundAccountId === "string" && e.boundAccountId.trim() !== "" ? e.boundAccountId : void 0;
|
|
2394
|
+
const boundKeyId = typeof e.boundKeyId === "string" && e.boundKeyId.trim() !== "" ? e.boundKeyId : void 0;
|
|
2395
|
+
let config;
|
|
2294
2396
|
if (isKindMappedEndpoint(endpoint)) {
|
|
2295
2397
|
const rawMap = e.modelMap && typeof e.modelMap === "object" ? e.modelMap : {};
|
|
2296
2398
|
const modelMap = {};
|
|
@@ -2298,27 +2400,28 @@ function normalizeEndpointConfig(e) {
|
|
|
2298
2400
|
const v = rawMap[kind];
|
|
2299
2401
|
modelMap[kind] = typeof v === "string" ? v : "";
|
|
2300
2402
|
}
|
|
2301
|
-
|
|
2302
|
-
}
|
|
2303
|
-
if (endpoint === "chat") {
|
|
2403
|
+
config = { endpoint, modelMap, useSubscription };
|
|
2404
|
+
} else if (endpoint === "chat") {
|
|
2304
2405
|
const models = Array.isArray(e.models) ? e.models.filter((m) => typeof m === "string" && m.trim() !== "") : [];
|
|
2305
|
-
|
|
2406
|
+
config = { endpoint, models, useSubscription };
|
|
2306
2407
|
if (e.dispatchMode === "prefix") {
|
|
2307
|
-
|
|
2408
|
+
config.dispatchMode = "prefix";
|
|
2308
2409
|
const targets = normalizePrefixTargets(e.prefixTargets);
|
|
2309
|
-
if (targets)
|
|
2410
|
+
if (targets) config.prefixTargets = targets;
|
|
2411
|
+
}
|
|
2412
|
+
} else {
|
|
2413
|
+
config = {
|
|
2414
|
+
endpoint,
|
|
2415
|
+
defaultModel: typeof e.defaultModel === "string" ? e.defaultModel : "",
|
|
2416
|
+
backgroundModel: typeof e.backgroundModel === "string" ? e.backgroundModel : "",
|
|
2417
|
+
useSubscription
|
|
2418
|
+
};
|
|
2419
|
+
if (Array.isArray(e.backgroundModelIds)) {
|
|
2420
|
+
config.backgroundModelIds = e.backgroundModelIds;
|
|
2310
2421
|
}
|
|
2311
|
-
return config2;
|
|
2312
|
-
}
|
|
2313
|
-
const config = {
|
|
2314
|
-
endpoint,
|
|
2315
|
-
defaultModel: typeof e.defaultModel === "string" ? e.defaultModel : "",
|
|
2316
|
-
backgroundModel: typeof e.backgroundModel === "string" ? e.backgroundModel : "",
|
|
2317
|
-
useSubscription
|
|
2318
|
-
};
|
|
2319
|
-
if (Array.isArray(e.backgroundModelIds)) {
|
|
2320
|
-
config.backgroundModelIds = e.backgroundModelIds;
|
|
2321
2422
|
}
|
|
2423
|
+
if (boundAccountId) config.boundAccountId = boundAccountId;
|
|
2424
|
+
if (boundKeyId) config.boundKeyId = boundKeyId;
|
|
2322
2425
|
return config;
|
|
2323
2426
|
}
|
|
2324
2427
|
function defaultServerConfig() {
|
|
@@ -2406,204 +2509,6 @@ function mergeServerConfig(current, patch) {
|
|
|
2406
2509
|
});
|
|
2407
2510
|
}
|
|
2408
2511
|
|
|
2409
|
-
// src/outbound-api/auditCapture.ts
|
|
2410
|
-
import { randomUUID } from "crypto";
|
|
2411
|
-
|
|
2412
|
-
// src/outbound-api/auditRedact.ts
|
|
2413
|
-
var AUDIT_REDACTED = "***REDACTED***";
|
|
2414
|
-
var RULES = [
|
|
2415
|
-
// `sk-…` family (Anthropic sk-ant-, omnicross sk-omnicross-, OpenAI sk-proj-/sk-).
|
|
2416
|
-
{ re: /\bsk-[A-Za-z0-9_-]{6,}/g, replace: AUDIT_REDACTED },
|
|
2417
|
-
// Google API keys.
|
|
2418
|
-
{ re: /\bAIza[A-Za-z0-9_-]{10,}/g, replace: AUDIT_REDACTED },
|
|
2419
|
-
// `Bearer <token>` (auth headers echoed into a body / SSE error).
|
|
2420
|
-
{ re: /\bBearer\s+[A-Za-z0-9._~+/=-]{6,}/gi, replace: `Bearer ${AUDIT_REDACTED}` },
|
|
2421
|
-
// Inline `x-api-key` / `api-key` / `authorization` label followed by a value.
|
|
2422
|
-
{
|
|
2423
|
-
re: /\b(x-api-key|api[_-]?key|authorization)(["']?\s*[:=]\s*["']?)[A-Za-z0-9._~+/=-]{6,}/gi,
|
|
2424
|
-
replace: `$1$2${AUDIT_REDACTED}`
|
|
2425
|
-
},
|
|
2426
|
-
// `x-goog-api-key` header echoed inline.
|
|
2427
|
-
{
|
|
2428
|
-
re: /\b(x-goog-api-key)(["']?\s*[:=]\s*["']?)[A-Za-z0-9._~+/=-]{6,}/gi,
|
|
2429
|
-
replace: `$1$2${AUDIT_REDACTED}`
|
|
2430
|
-
}
|
|
2431
|
-
];
|
|
2432
|
-
function redactAuditText(text) {
|
|
2433
|
-
if (typeof text !== "string" || text.length === 0) return text ?? "";
|
|
2434
|
-
let out = text;
|
|
2435
|
-
for (const { re, replace } of RULES) {
|
|
2436
|
-
out = out.replace(re, replace);
|
|
2437
|
-
}
|
|
2438
|
-
return out;
|
|
2439
|
-
}
|
|
2440
|
-
|
|
2441
|
-
// src/outbound-api/auditCapture.ts
|
|
2442
|
-
function isStreamingContentType(res) {
|
|
2443
|
-
const ct = res.getHeader("content-type");
|
|
2444
|
-
const value = Array.isArray(ct) ? ct.join(";") : String(ct ?? "");
|
|
2445
|
-
return value.toLowerCase().includes("text/event-stream");
|
|
2446
|
-
}
|
|
2447
|
-
function resolveClientIp(req, trustForwardedFor) {
|
|
2448
|
-
if (trustForwardedFor) {
|
|
2449
|
-
const xff = req.headers["x-forwarded-for"];
|
|
2450
|
-
const raw = Array.isArray(xff) ? xff[0] : xff;
|
|
2451
|
-
if (typeof raw === "string" && raw.trim()) {
|
|
2452
|
-
const first = raw.split(",")[0]?.trim();
|
|
2453
|
-
if (first) return first;
|
|
2454
|
-
}
|
|
2455
|
-
}
|
|
2456
|
-
return req.socket?.remoteAddress ?? void 0;
|
|
2457
|
-
}
|
|
2458
|
-
function truncateToBytes(text, maxBytes) {
|
|
2459
|
-
const buf = Buffer.from(text, "utf8");
|
|
2460
|
-
if (buf.length <= maxBytes) return text;
|
|
2461
|
-
return buf.subarray(0, maxBytes).toString("utf8");
|
|
2462
|
-
}
|
|
2463
|
-
function beginAuditCapture(req, res, now) {
|
|
2464
|
-
const config = getAuditCaptureConfig();
|
|
2465
|
-
if (!config) return null;
|
|
2466
|
-
let rawRequestBody;
|
|
2467
|
-
const responseChunks = [];
|
|
2468
|
-
let responseBytes = 0;
|
|
2469
|
-
let streamDetected = false;
|
|
2470
|
-
let finished = false;
|
|
2471
|
-
const ctx = {
|
|
2472
|
-
setRequestBody(raw) {
|
|
2473
|
-
if (config.captureBodies) rawRequestBody = raw;
|
|
2474
|
-
}
|
|
2475
|
-
};
|
|
2476
|
-
if (config.captureBodies) {
|
|
2477
|
-
installResponseCapture(res, config.maxBodyBytes, {
|
|
2478
|
-
push(chunk) {
|
|
2479
|
-
responseBytes += chunk.length;
|
|
2480
|
-
responseChunks.push(chunk);
|
|
2481
|
-
},
|
|
2482
|
-
get bytes() {
|
|
2483
|
-
return responseBytes;
|
|
2484
|
-
},
|
|
2485
|
-
markStream() {
|
|
2486
|
-
streamDetected = true;
|
|
2487
|
-
},
|
|
2488
|
-
get isStream() {
|
|
2489
|
-
return streamDetected;
|
|
2490
|
-
}
|
|
2491
|
-
});
|
|
2492
|
-
}
|
|
2493
|
-
const finalize = () => {
|
|
2494
|
-
if (finished) return;
|
|
2495
|
-
finished = true;
|
|
2496
|
-
try {
|
|
2497
|
-
const record = {
|
|
2498
|
-
id: randomUUID(),
|
|
2499
|
-
ts: now,
|
|
2500
|
-
method: req.method ?? "",
|
|
2501
|
-
path: (req.url ?? "").split("?")[0] ?? "",
|
|
2502
|
-
status: res.statusCode,
|
|
2503
|
-
latencyMs: Math.max(0, Date.now() - now)
|
|
2504
|
-
};
|
|
2505
|
-
if (ctx.keyId != null) record.keyId = ctx.keyId;
|
|
2506
|
-
const ip = resolveClientIp(req, config.trustForwardedFor);
|
|
2507
|
-
if (ip) record.ip = ip;
|
|
2508
|
-
const ua = req.headers["user-agent"];
|
|
2509
|
-
if (typeof ua === "string" && ua) record.ua = ua;
|
|
2510
|
-
if (ctx.model) record.model = ctx.model;
|
|
2511
|
-
if (ctx.provider) record.provider = ctx.provider;
|
|
2512
|
-
const usage = readAuditUsage(res);
|
|
2513
|
-
if (usage) {
|
|
2514
|
-
if (typeof usage.inputTokens === "number") record.inputTokens = usage.inputTokens;
|
|
2515
|
-
if (typeof usage.outputTokens === "number") record.outputTokens = usage.outputTokens;
|
|
2516
|
-
if (typeof usage.costUsd === "number") record.costUsd = usage.costUsd;
|
|
2517
|
-
if (!record.model && usage.model) record.model = usage.model;
|
|
2518
|
-
if (!record.provider && usage.provider) record.provider = usage.provider;
|
|
2519
|
-
}
|
|
2520
|
-
if (ctx.error) record.error = redactAuditText(ctx.error);
|
|
2521
|
-
if (config.captureBodies) {
|
|
2522
|
-
if (rawRequestBody != null && rawRequestBody.length > 0) {
|
|
2523
|
-
record.requestBody = redactAuditText(truncateToBytes(rawRequestBody, config.maxBodyBytes));
|
|
2524
|
-
}
|
|
2525
|
-
if (!streamDetected && responseChunks.length > 0) {
|
|
2526
|
-
const body = Buffer.concat(responseChunks).toString("utf8");
|
|
2527
|
-
record.responseBody = redactAuditText(body);
|
|
2528
|
-
}
|
|
2529
|
-
}
|
|
2530
|
-
recordAudit(record);
|
|
2531
|
-
} catch {
|
|
2532
|
-
}
|
|
2533
|
-
};
|
|
2534
|
-
res.once("close", finalize);
|
|
2535
|
-
return ctx;
|
|
2536
|
-
}
|
|
2537
|
-
function installResponseCapture(res, maxBodyBytes, sink2) {
|
|
2538
|
-
let contentTypeChecked = false;
|
|
2539
|
-
const capture = (chunk) => {
|
|
2540
|
-
if (sink2.isStream) return;
|
|
2541
|
-
if (!contentTypeChecked) {
|
|
2542
|
-
contentTypeChecked = true;
|
|
2543
|
-
if (isStreamingContentType(res)) {
|
|
2544
|
-
sink2.markStream();
|
|
2545
|
-
return;
|
|
2546
|
-
}
|
|
2547
|
-
}
|
|
2548
|
-
if (sink2.bytes >= maxBodyBytes) return;
|
|
2549
|
-
let buf = null;
|
|
2550
|
-
if (Buffer.isBuffer(chunk)) buf = chunk;
|
|
2551
|
-
else if (typeof chunk === "string") buf = Buffer.from(chunk, "utf8");
|
|
2552
|
-
if (!buf || buf.length === 0) return;
|
|
2553
|
-
const remaining = maxBodyBytes - sink2.bytes;
|
|
2554
|
-
sink2.push(buf.length > remaining ? buf.subarray(0, remaining) : buf);
|
|
2555
|
-
};
|
|
2556
|
-
const originalWrite = res.write.bind(res);
|
|
2557
|
-
const originalEnd = res.end.bind(res);
|
|
2558
|
-
res.write = ((chunk, ...args) => {
|
|
2559
|
-
if (chunk != null) capture(chunk);
|
|
2560
|
-
return originalWrite(chunk, ...args);
|
|
2561
|
-
});
|
|
2562
|
-
res.end = ((chunk, ...args) => {
|
|
2563
|
-
if (chunk != null && typeof chunk !== "function") capture(chunk);
|
|
2564
|
-
return originalEnd(chunk, ...args);
|
|
2565
|
-
});
|
|
2566
|
-
}
|
|
2567
|
-
|
|
2568
|
-
// src/outbound-api/billingCapture.ts
|
|
2569
|
-
import { randomUUID as randomUUID2 } from "crypto";
|
|
2570
|
-
var defaultDefer = (fn) => {
|
|
2571
|
-
setTimeout(fn, 0);
|
|
2572
|
-
};
|
|
2573
|
-
function beginBillingCapture(_req, res, now, defer = defaultDefer) {
|
|
2574
|
-
if (!getBillingCaptureConfig()) return null;
|
|
2575
|
-
const ctx = {};
|
|
2576
|
-
let finished = false;
|
|
2577
|
-
const finalize = () => {
|
|
2578
|
-
if (finished) return;
|
|
2579
|
-
finished = true;
|
|
2580
|
-
const status = res.statusCode;
|
|
2581
|
-
defer(() => {
|
|
2582
|
-
try {
|
|
2583
|
-
const usage = readAuditUsage(res);
|
|
2584
|
-
if (!usage) return;
|
|
2585
|
-
const event = {
|
|
2586
|
-
id: randomUUID2(),
|
|
2587
|
-
ts: now,
|
|
2588
|
-
model: ctx.model ?? usage.model ?? "",
|
|
2589
|
-
authMode: ctx.authMode ?? "byo",
|
|
2590
|
-
inputTokens: usage.inputTokens ?? 0,
|
|
2591
|
-
outputTokens: usage.outputTokens ?? 0,
|
|
2592
|
-
costUsd: usage.costUsd ?? 0,
|
|
2593
|
-
status
|
|
2594
|
-
};
|
|
2595
|
-
if (ctx.keyId != null) event.keyId = ctx.keyId;
|
|
2596
|
-
const provider = ctx.provider ?? usage.provider;
|
|
2597
|
-
if (provider) event.provider = provider;
|
|
2598
|
-
publishBillingEvent(event);
|
|
2599
|
-
} catch {
|
|
2600
|
-
}
|
|
2601
|
-
});
|
|
2602
|
-
};
|
|
2603
|
-
res.once("close", finalize);
|
|
2604
|
-
return ctx;
|
|
2605
|
-
}
|
|
2606
|
-
|
|
2607
2512
|
// src/outbound-api/outboundApiKeyAuth.ts
|
|
2608
2513
|
import { createHash, randomBytes as randomBytes2 } from "crypto";
|
|
2609
2514
|
|
|
@@ -2752,30 +2657,6 @@ async function verifyPresentedKey(db, presentedKey) {
|
|
|
2752
2657
|
return result.status === "ok" ? result.key : null;
|
|
2753
2658
|
}
|
|
2754
2659
|
|
|
2755
|
-
// src/outbound-api/quotaWarn.ts
|
|
2756
|
-
var WEBHOOK_QUOTA_WARN_RATIO = 0.8;
|
|
2757
|
-
function computeQuotaWarnings(limits, spend, ratio = WEBHOOK_QUOTA_WARN_RATIO) {
|
|
2758
|
-
const out = [];
|
|
2759
|
-
const consider = (scope, limit, spent, windowStart) => {
|
|
2760
|
-
if (limit == null || limit <= 0) return;
|
|
2761
|
-
if (spent >= limit) return;
|
|
2762
|
-
if (spent >= ratio * limit) out.push({ scope, limitUsd: limit, spentUsd: spent, windowStart });
|
|
2763
|
-
};
|
|
2764
|
-
consider("daily", limits.dailyUsd, spend.dailyUsd, spend.dailyWindowStart);
|
|
2765
|
-
consider("weekly", limits.weeklyUsd, spend.weeklyUsd, spend.weeklyWindowStart);
|
|
2766
|
-
consider("total", limits.totalUsd, spend.totalUsd, 0);
|
|
2767
|
-
return out;
|
|
2768
|
-
}
|
|
2769
|
-
var WARN_GUARD_MAX = 1e4;
|
|
2770
|
-
var warned = /* @__PURE__ */ new Set();
|
|
2771
|
-
function markQuotaWarnedOnce(keyId, scope, windowStart) {
|
|
2772
|
-
const key = `${keyId}\0${scope}\0${windowStart}`;
|
|
2773
|
-
if (warned.has(key)) return false;
|
|
2774
|
-
if (warned.size >= WARN_GUARD_MAX) warned.clear();
|
|
2775
|
-
warned.add(key);
|
|
2776
|
-
return true;
|
|
2777
|
-
}
|
|
2778
|
-
|
|
2779
2660
|
// src/outbound-api/outboundConcurrencyGate.ts
|
|
2780
2661
|
var ConcurrencyQueueFullError = class extends Error {
|
|
2781
2662
|
constructor(apiKeyId, maxQueueSize) {
|
|
@@ -3817,6 +3698,7 @@ var OutboundApiServer = class {
|
|
|
3817
3698
|
}
|
|
3818
3699
|
/** Per-request handler. Auth is enforced on EVERY request (incl. loopback). */
|
|
3819
3700
|
onRequest(req, res) {
|
|
3701
|
+
if (req.url) req.url = normalizeDoubledEndpointPath(req.url);
|
|
3820
3702
|
if (this.deps.healthReportProvider && this.tryServeHealth(req, res)) return;
|
|
3821
3703
|
handleOutboundRequest(
|
|
3822
3704
|
req,
|
|
@@ -3939,6 +3821,16 @@ function firstLanIPv4() {
|
|
|
3939
3821
|
}
|
|
3940
3822
|
return null;
|
|
3941
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
|
+
}
|
|
3942
3834
|
|
|
3943
3835
|
// src/outbound-api/keySpendTracker.ts
|
|
3944
3836
|
function startOfLocalDay(ts) {
|
|
@@ -5646,8 +5538,8 @@ var CompletionService = class {
|
|
|
5646
5538
|
* emission is unconditional in production. Optional — when unset (unit-test
|
|
5647
5539
|
* constructors), the emit calls no-op, identical to `usageRecorder`.
|
|
5648
5540
|
*/
|
|
5649
|
-
setUsageEventSink(
|
|
5650
|
-
this.usageEventSink =
|
|
5541
|
+
setUsageEventSink(sink) {
|
|
5542
|
+
this.usageEventSink = sink;
|
|
5651
5543
|
}
|
|
5652
5544
|
/**
|
|
5653
5545
|
* Set the vision-fallback provider used by `applyVisionFallback` to describe
|
|
@@ -6126,6 +6018,7 @@ export {
|
|
|
6126
6018
|
getGeminiEndpointTransformer,
|
|
6127
6019
|
readBody,
|
|
6128
6020
|
relayResponse,
|
|
6021
|
+
aggregateAnthropicSseToJsonBody,
|
|
6129
6022
|
writeError,
|
|
6130
6023
|
resolvePoolBoundKey,
|
|
6131
6024
|
extractRouteToken,
|
|
@@ -6155,10 +6048,6 @@ export {
|
|
|
6155
6048
|
loadServerConfig,
|
|
6156
6049
|
saveServerConfig,
|
|
6157
6050
|
mergeServerConfig,
|
|
6158
|
-
AUDIT_REDACTED,
|
|
6159
|
-
redactAuditText,
|
|
6160
|
-
beginAuditCapture,
|
|
6161
|
-
beginBillingCapture,
|
|
6162
6051
|
computeKeyExpiry,
|
|
6163
6052
|
checkKeyQuota,
|
|
6164
6053
|
randomBase62,
|
|
@@ -33,7 +33,8 @@ var SubscriptionAuthSource = class {
|
|
|
33
33
|
upstreamUrl: hints.upstreamUrl,
|
|
34
34
|
resolvedModel: hints.model,
|
|
35
35
|
sessionKey: hints.sessionKey,
|
|
36
|
-
reportSelection: hints.reportSelection
|
|
36
|
+
reportSelection: hints.reportSelection,
|
|
37
|
+
preferredAccountId: hints.preferredAccountId
|
|
37
38
|
});
|
|
38
39
|
} catch (err) {
|
|
39
40
|
console.warn("[SubscriptionAuthSource] authStrategy.applyHeaders threw:", serializeError(err));
|
|
@@ -23,6 +23,9 @@ async function executeProviderCall(ctx) {
|
|
|
23
23
|
const finalBody = prepareBody ? await prepareBody(requestBody, config) : requestBody;
|
|
24
24
|
const url = resolveUrl(config);
|
|
25
25
|
const headers = buildHeaders(config);
|
|
26
|
+
if (!headers["content-type"] && !headers["Content-Type"]) {
|
|
27
|
+
headers["content-type"] = "application/json";
|
|
28
|
+
}
|
|
26
29
|
const fetched = await fetchFn(url, headers, finalBody);
|
|
27
30
|
let response = fetched;
|
|
28
31
|
if (runResponseChain) {
|
|
@@ -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
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
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,
|