@omnicross/core 0.1.9 → 0.2.0
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 +22 -15
- package/dist/{CompletionService-kNA17cfI.d.cts → CompletionService-BiJqftc-.d.cts} +1 -1
- package/dist/{CompletionService-C3BX0Ovy.d.ts → CompletionService-NXN_Av5W.d.ts} +1 -1
- package/dist/{ProviderProxy-QdwNV6l1.d.cts → ProviderProxy-CgIcCVwk.d.cts} +1 -1
- package/dist/{ProviderProxy--ROec6VI.d.ts → ProviderProxy-DYoY5XoT.d.ts} +1 -1
- package/dist/auth/GeminiCodeAssistProjectResolver.cjs +6 -6
- package/dist/auth/GeminiCodeAssistProjectResolver.js +4 -4
- package/dist/chunk-32SRZFFP.cjs +153 -0
- package/dist/chunk-4JOU54M5.js +200 -0
- package/dist/{chunk-2UTGX6FM.js → chunk-4VVCXVB7.js} +1 -1
- package/dist/{chunk-EPN67EGP.cjs → chunk-5UK3KLE2.cjs} +9 -1
- package/dist/chunk-6DDYNS2B.cjs +384 -0
- package/dist/{chunk-HKB656B4.js → chunk-6OC3ORW6.js} +55 -287
- package/dist/chunk-6OKXH2TW.js +320 -0
- package/dist/{chunk-XELFM7KL.cjs → chunk-7B56AJBB.cjs} +6275 -2421
- package/dist/{chunk-YWL7YZWS.cjs → chunk-7LRTPNFL.cjs} +5 -0
- package/dist/{chunk-CCVRRJOX.js → chunk-7PIUVCKK.js} +9 -2
- package/dist/{chunk-IIRPUVPH.cjs → chunk-7ZHBN75N.cjs} +3 -1
- package/dist/{chunk-UAPBLNN2.js → chunk-AQDON6MB.js} +8 -0
- package/dist/{chunk-RJ5ZGNI3.js → chunk-CFSGYFOZ.js} +1 -1
- package/dist/chunk-CTKM773J.cjs +3919 -0
- package/dist/chunk-DEIUR2TH.js +3919 -0
- package/dist/{chunk-WNKWAEUR.js → chunk-EYGBM2VC.js} +3 -1
- package/dist/{chunk-NGYOO5TO.js → chunk-FJNKXOWE.js} +9 -9
- package/dist/chunk-FX325I5Q.cjs +320 -0
- package/dist/chunk-G4CZIUIB.cjs +200 -0
- package/dist/chunk-HCOQQAZE.cjs +123 -0
- package/dist/{chunk-55FMGZ3L.js → chunk-HN74IGEO.js} +1 -1
- package/dist/{chunk-ZY6KU6P3.js → chunk-HOMUGKHR.js} +8 -5
- package/dist/{chunk-AOFWNWLT.cjs → chunk-IUL4VWNU.cjs} +22 -1
- package/dist/{chunk-5LNYGCIW.cjs → chunk-KIQ2HA2A.cjs} +5 -5
- package/dist/{chunk-MUHWHQVM.cjs → chunk-KQBLZMP6.cjs} +4 -3
- package/dist/chunk-LFEH7CEO.js +384 -0
- package/dist/chunk-N76KU6F5.js +123 -0
- package/dist/{chunk-CMVXX7ON.cjs → chunk-NOITAVHA.cjs} +114 -58
- package/dist/{chunk-Q27JY5RG.cjs → chunk-OIKREZVQ.cjs} +7 -4
- package/dist/{chunk-RJUONLUQ.cjs → chunk-OST5RJOJ.cjs} +1 -1
- package/dist/chunk-QIIAMBTM.js +153 -0
- package/dist/{chunk-56QD3YW6.cjs → chunk-QWNUOR7F.cjs} +11 -4
- package/dist/{chunk-S3DYFEBE.js → chunk-R4VCO2CB.js} +10 -1
- package/dist/{chunk-ZQQUD66M.cjs → chunk-SQMAEDNE.cjs} +63 -295
- package/dist/{chunk-4VZX5F4T.cjs → chunk-T6NWPIYZ.cjs} +5 -2
- package/dist/{chunk-P7EM6BND.cjs → chunk-TVYA5JSQ.cjs} +10 -10
- package/dist/{chunk-EBLFCNPY.js → chunk-U47LQXPB.js} +5 -2
- package/dist/{chunk-N7OOJI5V.js → chunk-V2UKUTJ3.js} +5 -0
- package/dist/{chunk-45FHEOKW.js → chunk-V53ZEFXC.js} +92 -36
- package/dist/{chunk-OC6DOOFX.cjs → chunk-VXRTQZF2.cjs} +5 -5
- package/dist/{chunk-CQIJCPMF.js → chunk-WSJE42SG.js} +5149 -1295
- package/dist/{chunk-RICPANBY.cjs → chunk-WX2E2G7H.cjs} +13 -4
- package/dist/{chunk-DE2SRBFZ.js → chunk-X335TJNS.js} +4 -3
- package/dist/{chunk-N2EIM2XJ.js → chunk-ZLNHPUFA.js} +22 -1
- package/dist/completion/CompletionService.cjs +30 -27
- package/dist/completion/CompletionService.d.cts +3 -2
- package/dist/completion/CompletionService.d.ts +3 -2
- package/dist/completion/CompletionService.js +29 -26
- package/dist/completion.cjs +38 -35
- package/dist/completion.d.cts +3 -2
- package/dist/completion.d.ts +3 -2
- package/dist/completion.js +37 -34
- package/dist/image-generation.cjs +52 -0
- package/dist/image-generation.d.cts +93 -0
- package/dist/image-generation.d.ts +93 -0
- package/dist/image-generation.js +52 -0
- package/dist/index.cjs +126 -31
- package/dist/index.d.cts +11 -7
- package/dist/index.d.ts +11 -7
- package/dist/index.js +143 -48
- package/dist/openai-operation.cjs +18 -0
- package/dist/openai-operation.d.cts +19 -0
- package/dist/openai-operation.d.ts +19 -0
- package/dist/openai-operation.js +18 -0
- package/dist/outbound-api/auditCapture.cjs +3 -3
- package/dist/outbound-api/auditCapture.d.cts +19 -2
- package/dist/outbound-api/auditCapture.d.ts +19 -2
- package/dist/outbound-api/auditCapture.js +2 -2
- package/dist/outbound-api/auditRedact.cjs +2 -2
- package/dist/outbound-api/auditRedact.js +1 -1
- package/dist/outbound-api/routeResolver.cjs +2 -2
- package/dist/outbound-api/routeResolver.d.cts +7 -4
- package/dist/outbound-api/routeResolver.d.ts +7 -4
- package/dist/outbound-api/routeResolver.js +1 -1
- package/dist/outbound-api/subscriptionRegistryPort.d.cts +2 -1
- package/dist/outbound-api/subscriptionRegistryPort.d.ts +2 -1
- package/dist/outbound-api/types.d.cts +6 -3
- package/dist/outbound-api/types.d.ts +6 -3
- package/dist/outbound-api.cjs +49 -32
- package/dist/outbound-api.d.cts +97 -10
- package/dist/outbound-api.d.ts +97 -10
- package/dist/outbound-api.js +48 -31
- package/dist/pipeline/AccountAllowanceScheduling.d.cts +18 -15
- package/dist/pipeline/AccountAllowanceScheduling.d.ts +18 -15
- package/dist/pipeline/LlmConfigProviderAuth.cjs +3 -3
- package/dist/pipeline/LlmConfigProviderAuth.js +2 -2
- package/dist/pipeline/SubscriptionAccountHealth.cjs +2 -2
- package/dist/pipeline/SubscriptionAccountHealth.d.cts +7 -0
- package/dist/pipeline/SubscriptionAccountHealth.d.ts +7 -0
- package/dist/pipeline/SubscriptionAccountHealth.js +1 -1
- package/dist/pipeline/executeProviderCall.cjs +2 -2
- package/dist/pipeline/executeProviderCall.d.cts +11 -6
- package/dist/pipeline/executeProviderCall.d.ts +11 -6
- package/dist/pipeline/executeProviderCall.js +1 -1
- package/dist/pipeline/upstreamFetch.cjs +2 -2
- package/dist/pipeline/upstreamFetch.d.cts +5 -0
- package/dist/pipeline/upstreamFetch.d.ts +5 -0
- package/dist/pipeline/upstreamFetch.js +1 -1
- package/dist/ports.d.cts +6 -3
- package/dist/ports.d.ts +6 -3
- package/dist/provider-proxy/ProviderProxy.cjs +30 -27
- package/dist/provider-proxy/ProviderProxy.d.cts +3 -2
- package/dist/provider-proxy/ProviderProxy.d.ts +3 -2
- package/dist/provider-proxy/ProviderProxy.js +29 -26
- package/dist/provider-proxy/identity/codexCliHeaders.cjs +4 -2
- package/dist/provider-proxy/identity/codexCliHeaders.d.cts +26 -6
- package/dist/provider-proxy/identity/codexCliHeaders.d.ts +26 -6
- package/dist/provider-proxy/identity/codexCliHeaders.js +5 -3
- package/dist/provider-proxy/ingress/providerProxyShared.cjs +32 -27
- package/dist/provider-proxy/ingress/providerProxyShared.d.cts +21 -8
- package/dist/provider-proxy/ingress/providerProxyShared.d.ts +21 -8
- package/dist/provider-proxy/ingress/providerProxyShared.js +31 -26
- package/dist/provider-proxy/types.d.cts +14 -483
- package/dist/provider-proxy/types.d.ts +14 -483
- package/dist/provider-proxy.cjs +44 -27
- package/dist/provider-proxy.d.cts +30 -8
- package/dist/provider-proxy.d.ts +30 -8
- package/dist/provider-proxy.js +43 -26
- package/dist/{routeResolver-C0mkkZaM.d.ts → routeResolver-CTCcSHWu.d.ts} +4 -2
- package/dist/{routeResolver-CVFE8KKe.d.cts → routeResolver-rpKQLyDO.d.cts} +4 -2
- package/dist/transformer/TransformerChainExecutor.cjs +2 -2
- package/dist/transformer/TransformerChainExecutor.d.cts +2 -2
- package/dist/transformer/TransformerChainExecutor.d.ts +2 -2
- package/dist/transformer/TransformerChainExecutor.js +1 -1
- package/dist/transformer/transformers/AnthropicOpenAIToAnthropicStream.cjs +16 -0
- package/dist/transformer/transformers/AnthropicOpenAIToAnthropicStream.d.cts +53 -0
- package/dist/transformer/transformers/AnthropicOpenAIToAnthropicStream.d.ts +53 -0
- package/dist/transformer/transformers/AnthropicOpenAIToAnthropicStream.js +16 -0
- package/dist/transformer/transformers/AnthropicTransformer.cjs +4 -3
- package/dist/transformer/transformers/AnthropicTransformer.js +3 -2
- package/dist/transformer/transformers/GeminiCodeAssistTransformer.cjs +4 -4
- package/dist/transformer/transformers/GeminiCodeAssistTransformer.js +3 -3
- package/dist/transformer/transformers/GeminiTransformer.cjs +4 -4
- package/dist/transformer/transformers/GeminiTransformer.js +3 -3
- package/dist/transformer/transformers/OpenAIResponseTransformer.cjs +3 -3
- package/dist/transformer/transformers/OpenAIResponseTransformer.js +2 -2
- package/dist/transformer/transformers/OpenAITransformer.cjs +3 -3
- package/dist/transformer/transformers/OpenAITransformer.js +2 -2
- package/dist/transformer/transformers.cjs +10 -9
- package/dist/transformer/transformers.js +13 -12
- package/dist/transformer/types.d.cts +39 -4
- package/dist/transformer/types.d.ts +39 -4
- package/dist/transformer.cjs +14 -13
- package/dist/transformer.js +14 -13
- package/dist/{types-BB8pxk_3.d.ts → types-5T223WYQ.d.ts} +183 -23
- package/dist/types-Bd72H4SB.d.ts +196 -0
- package/dist/types-CVRge76p.d.ts +1115 -0
- package/dist/types-CbglB73l.d.cts +196 -0
- package/dist/types-DsHBBk3h.d.cts +1115 -0
- package/dist/{types-C2MwkLah.d.cts → types-jjU24eYG.d.cts} +183 -23
- package/dist/usage/usage-recorder.cjs +2 -2
- package/dist/usage/usage-recorder.d.cts +12 -2
- package/dist/usage/usage-recorder.d.ts +12 -2
- package/dist/usage/usage-recorder.js +1 -1
- package/dist/usage.cjs +20 -3
- package/dist/usage.d.cts +154 -0
- package/dist/usage.d.ts +154 -0
- package/dist/usage.js +20 -3
- package/package.json +69 -64
- package/dist/chunk-7C7DET6S.js +0 -154
- package/dist/chunk-7VU7V2E4.js +0 -0
- package/dist/chunk-EYZYXJTJ.cjs +0 -1
- package/dist/chunk-FCR77GYM.cjs +0 -33
- package/dist/chunk-K5NM7VAH.js +0 -33
- package/dist/chunk-XPIOJQS2.cjs +0 -154
- /package/dist/{chunk-XXFYLL7R.js → chunk-ECZ3ZE2C.js} +0 -0
- /package/dist/{chunk-3SCOLIPT.cjs → chunk-MXI2PWIC.cjs} +0 -0
|
@@ -1,10 +1,10 @@
|
|
|
1
|
-
import {
|
|
2
|
-
resolveApiFormat
|
|
3
|
-
} from "./chunk-H5JUT3KV.js";
|
|
4
1
|
import {
|
|
5
2
|
OPENROUTER_APP_HEADERS,
|
|
6
3
|
isOpenRouterProvider
|
|
7
4
|
} from "./chunk-HUZZZ3JL.js";
|
|
5
|
+
import {
|
|
6
|
+
resolveApiFormat
|
|
7
|
+
} from "./chunk-H5JUT3KV.js";
|
|
8
8
|
|
|
9
9
|
// src/completion/header-builder.ts
|
|
10
10
|
function getProviderHeaders(provider, apiKey) {
|
|
@@ -17,8 +17,11 @@ function getProviderHeaders(provider, apiKey) {
|
|
|
17
17
|
// Third-party Anthropic-Messages relays often gate on a Bearer token
|
|
18
18
|
// rather than x-api-key; `provider.useBearer` opts into that.
|
|
19
19
|
...provider.useBearer ? { Authorization: `Bearer ${apiKey}` } : { "x-api-key": apiKey },
|
|
20
|
-
|
|
21
|
-
//
|
|
20
|
+
// Official documented version date (claude-api-protocol-fidelity, R5);
|
|
21
|
+
// the former non-official future-dated value was removed. The BYO
|
|
22
|
+
// same-format path additionally forwards the caller's own
|
|
23
|
+
// `anthropic-version` verbatim when present (see `runSameFormatFetch`).
|
|
24
|
+
"anthropic-version": "2023-06-01"
|
|
22
25
|
};
|
|
23
26
|
break;
|
|
24
27
|
case "google":
|
|
@@ -191,6 +191,27 @@ function resolveRequestReasoning(request, provider, options = {}) {
|
|
|
191
191
|
return { ...intent, effort: plan.effort, enabled: plan.enabled };
|
|
192
192
|
}
|
|
193
193
|
|
|
194
|
+
// src/transformer/transformWarnings.ts
|
|
195
|
+
var droppedFieldCounts = {};
|
|
196
|
+
var warnedOnce = /* @__PURE__ */ new Set();
|
|
197
|
+
function recordDroppedField(request, field, target) {
|
|
198
|
+
attachTransformWarnings(request).push({ field, target });
|
|
199
|
+
const key = `${field}\0${target}`;
|
|
200
|
+
droppedFieldCounts[key] = (_nullishCoalesce(droppedFieldCounts[key], () => ( 0))) + 1;
|
|
201
|
+
if (!warnedOnce.has(key)) {
|
|
202
|
+
warnedOnce.add(key);
|
|
203
|
+
console.warn(
|
|
204
|
+
`[transform] dropped_field: '${field}' has no representation on the '${target}' wire (counting; values never logged)`
|
|
205
|
+
);
|
|
206
|
+
}
|
|
207
|
+
}
|
|
208
|
+
function attachTransformWarnings(request) {
|
|
209
|
+
const holder = request;
|
|
210
|
+
holder._transformWarnings ??= [];
|
|
211
|
+
return holder._transformWarnings;
|
|
212
|
+
}
|
|
213
|
+
|
|
214
|
+
|
|
194
215
|
|
|
195
216
|
|
|
196
217
|
|
|
@@ -200,4 +221,4 @@ function resolveRequestReasoning(request, provider, options = {}) {
|
|
|
200
221
|
|
|
201
222
|
|
|
202
223
|
|
|
203
|
-
exports.THINK_LEVELS = THINK_LEVELS; exports.normalizeThinkLevel = normalizeThinkLevel; exports.extractReasoningIntent = extractReasoningIntent; exports.resolveTargetModelCapabilities = resolveTargetModelCapabilities; exports.resolveReasoningEffort = resolveReasoningEffort; exports.resolveReasoningTokenLimit = resolveReasoningTokenLimit; exports.resolveReasoningPlan = resolveReasoningPlan; exports.resolveRequestReasoning = resolveRequestReasoning;
|
|
224
|
+
exports.THINK_LEVELS = THINK_LEVELS; exports.normalizeThinkLevel = normalizeThinkLevel; exports.extractReasoningIntent = extractReasoningIntent; exports.resolveTargetModelCapabilities = resolveTargetModelCapabilities; exports.resolveReasoningEffort = resolveReasoningEffort; exports.resolveReasoningTokenLimit = resolveReasoningTokenLimit; exports.resolveReasoningPlan = resolveReasoningPlan; exports.resolveRequestReasoning = resolveRequestReasoning; exports.recordDroppedField = recordDroppedField;
|
|
@@ -3,7 +3,7 @@
|
|
|
3
3
|
|
|
4
4
|
|
|
5
5
|
|
|
6
|
-
var
|
|
6
|
+
var _chunkWX2E2G7Hcjs = require('./chunk-WX2E2G7H.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 =
|
|
47
|
+
const body = _chunkWX2E2G7Hcjs.buildRequestBody.call(void 0,
|
|
48
48
|
request,
|
|
49
49
|
provider,
|
|
50
50
|
context.reasoningSourceFormat === this.name
|
|
@@ -69,7 +69,7 @@ var GeminiTransformer = (_class = class {
|
|
|
69
69
|
* (For requests coming into the Gemini endpoint)
|
|
70
70
|
*/
|
|
71
71
|
async transformRequestOut(request, context) {
|
|
72
|
-
const unifiedRequest =
|
|
72
|
+
const unifiedRequest = _chunkWX2E2G7Hcjs.transformRequestOut.call(void 0, request);
|
|
73
73
|
if (_optionalChain([unifiedRequest, 'access', _2 => _2.reasoning, 'optionalAccess', _3 => _3.effort])) {
|
|
74
74
|
context.reasoningSourceFormat = this.name;
|
|
75
75
|
}
|
|
@@ -79,14 +79,14 @@ var GeminiTransformer = (_class = class {
|
|
|
79
79
|
* Transform Gemini response to OpenAI-compatible format
|
|
80
80
|
*/
|
|
81
81
|
async transformResponseOut(response, _context) {
|
|
82
|
-
return
|
|
82
|
+
return _chunkWX2E2G7Hcjs.transformResponseOut.call(void 0, response, this.name, this.logger);
|
|
83
83
|
}
|
|
84
84
|
/**
|
|
85
85
|
* Transform OpenAI-compatible response back to Gemini format
|
|
86
86
|
* (For endpoint mode — returning Gemini-format responses to the client)
|
|
87
87
|
*/
|
|
88
88
|
async transformResponseIn(response, _context) {
|
|
89
|
-
return
|
|
89
|
+
return _chunkWX2E2G7Hcjs.transformResponseIn.call(void 0, response, this.logger);
|
|
90
90
|
}
|
|
91
91
|
}, _class.__initStatic(), _class);
|
|
92
92
|
|
|
@@ -12,9 +12,10 @@ async function executeProviderCall(ctx) {
|
|
|
12
12
|
prepareBody,
|
|
13
13
|
fetchFn,
|
|
14
14
|
runResponseChain = false,
|
|
15
|
-
responseChainRequest
|
|
15
|
+
responseChainRequest,
|
|
16
|
+
preserveEndpointRequestForResponseChain = false
|
|
16
17
|
} = ctx;
|
|
17
|
-
const { requestBody, config } = await executor.executeRequestChain(
|
|
18
|
+
const { requestBody, endpointRequest, config } = await executor.executeRequestChain(
|
|
18
19
|
request,
|
|
19
20
|
provider,
|
|
20
21
|
chain,
|
|
@@ -34,7 +35,7 @@ async function executeProviderCall(ctx) {
|
|
|
34
35
|
// unified ingresses → their pre-transform request. The caller supplies
|
|
35
36
|
// it via `responseChainRequest`; fall back to `requestBody` (the proxy
|
|
36
37
|
// shape) so the contract is never silently `undefined`.
|
|
37
|
-
_nullishCoalesce(responseChainRequest, () => ( requestBody)),
|
|
38
|
+
_nullishCoalesce(_nullishCoalesce(responseChainRequest, () => ( (preserveEndpointRequestForResponseChain ? endpointRequest : void 0))), () => ( requestBody)),
|
|
38
39
|
fetched,
|
|
39
40
|
provider,
|
|
40
41
|
chain,
|
|
@@ -0,0 +1,384 @@
|
|
|
1
|
+
// src/transformer/transformers/AnthropicOpenAIToAnthropicStream.ts
|
|
2
|
+
var DEFAULT_ANTHROPIC_PING_HEARTBEAT_MS = 2e4;
|
|
3
|
+
var anthropicPingHeartbeatMs = DEFAULT_ANTHROPIC_PING_HEARTBEAT_MS;
|
|
4
|
+
function setAnthropicPingHeartbeatMs(ms) {
|
|
5
|
+
anthropicPingHeartbeatMs = typeof ms === "number" && Number.isFinite(ms) ? ms : DEFAULT_ANTHROPIC_PING_HEARTBEAT_MS;
|
|
6
|
+
}
|
|
7
|
+
function getAnthropicPingHeartbeatMs() {
|
|
8
|
+
return anthropicPingHeartbeatMs;
|
|
9
|
+
}
|
|
10
|
+
var stopReasonContentFilterCount = 0;
|
|
11
|
+
function __resetStopReasonContentFilterCountForTests() {
|
|
12
|
+
stopReasonContentFilterCount = 0;
|
|
13
|
+
}
|
|
14
|
+
function noteContentFilterRemap(logger) {
|
|
15
|
+
stopReasonContentFilterCount += 1;
|
|
16
|
+
console.warn(
|
|
17
|
+
`[AnthropicStream] upstream finish_reason=content_filter remapped to stop_reason=refusal (count ${stopReasonContentFilterCount})`
|
|
18
|
+
);
|
|
19
|
+
logger?.warn?.("upstream finish_reason=content_filter remapped to stop_reason=refusal");
|
|
20
|
+
}
|
|
21
|
+
function sniffErrorType(error) {
|
|
22
|
+
let text;
|
|
23
|
+
try {
|
|
24
|
+
text = JSON.stringify(error) ?? "";
|
|
25
|
+
} catch {
|
|
26
|
+
text = String(error);
|
|
27
|
+
}
|
|
28
|
+
const lower = text.toLowerCase();
|
|
29
|
+
if (lower.includes("overload") || lower.includes("capacity") || lower.includes("server_error")) {
|
|
30
|
+
return "overloaded_error";
|
|
31
|
+
}
|
|
32
|
+
const e = error;
|
|
33
|
+
for (const raw of [e?.status, e?.code]) {
|
|
34
|
+
const n = typeof raw === "string" ? Number.parseInt(raw, 10) : raw;
|
|
35
|
+
if (typeof n === "number" && Number.isFinite(n) && n >= 500) return "overloaded_error";
|
|
36
|
+
}
|
|
37
|
+
return "api_error";
|
|
38
|
+
}
|
|
39
|
+
function convertOpenAIStreamToAnthropic(openaiStream, _context, logger) {
|
|
40
|
+
const decoder = new TextDecoder();
|
|
41
|
+
const encoder = new TextEncoder();
|
|
42
|
+
let hasStarted = false;
|
|
43
|
+
let hasTextContentStarted = false;
|
|
44
|
+
let isThinkingStarted = false;
|
|
45
|
+
let contentIndex = 0;
|
|
46
|
+
let currentContentBlockIndex = -1;
|
|
47
|
+
const toolCallIndexToContentBlockIndex = /* @__PURE__ */ new Map();
|
|
48
|
+
let reader = null;
|
|
49
|
+
return new ReadableStream({
|
|
50
|
+
start: async (controller) => {
|
|
51
|
+
reader = openaiStream.getReader();
|
|
52
|
+
let buffer = "";
|
|
53
|
+
const messageId = `msg_${Date.now()}`;
|
|
54
|
+
let model = "unknown";
|
|
55
|
+
let isClosed = false;
|
|
56
|
+
let stopReasonDelta = null;
|
|
57
|
+
const safeEnqueue = (data) => {
|
|
58
|
+
if (!isClosed) {
|
|
59
|
+
try {
|
|
60
|
+
controller.enqueue(encoder.encode(data));
|
|
61
|
+
} catch (_e) {
|
|
62
|
+
isClosed = true;
|
|
63
|
+
}
|
|
64
|
+
}
|
|
65
|
+
};
|
|
66
|
+
let pingTimer = null;
|
|
67
|
+
const clearPing = () => {
|
|
68
|
+
if (pingTimer !== null) {
|
|
69
|
+
clearTimeout(pingTimer);
|
|
70
|
+
pingTimer = null;
|
|
71
|
+
}
|
|
72
|
+
};
|
|
73
|
+
const armPing = () => {
|
|
74
|
+
clearPing();
|
|
75
|
+
const interval = getAnthropicPingHeartbeatMs();
|
|
76
|
+
if (!(interval > 0)) return;
|
|
77
|
+
pingTimer = setTimeout(() => {
|
|
78
|
+
pingTimer = null;
|
|
79
|
+
safeEnqueue(`event: ping
|
|
80
|
+
data: ${JSON.stringify({ type: "ping" })}
|
|
81
|
+
|
|
82
|
+
`);
|
|
83
|
+
armPing();
|
|
84
|
+
}, interval);
|
|
85
|
+
pingTimer.unref?.();
|
|
86
|
+
};
|
|
87
|
+
const assignContentBlockIndex = () => {
|
|
88
|
+
return contentIndex++;
|
|
89
|
+
};
|
|
90
|
+
const safeClose = () => {
|
|
91
|
+
if (isClosed) return;
|
|
92
|
+
if (currentContentBlockIndex >= 0) {
|
|
93
|
+
safeEnqueue(`event: content_block_stop
|
|
94
|
+
data: ${JSON.stringify({
|
|
95
|
+
type: "content_block_stop",
|
|
96
|
+
index: currentContentBlockIndex
|
|
97
|
+
})}
|
|
98
|
+
|
|
99
|
+
`);
|
|
100
|
+
}
|
|
101
|
+
if (stopReasonDelta) {
|
|
102
|
+
safeEnqueue(`event: message_delta
|
|
103
|
+
data: ${JSON.stringify(stopReasonDelta)}
|
|
104
|
+
|
|
105
|
+
`);
|
|
106
|
+
} else {
|
|
107
|
+
safeEnqueue(`event: message_delta
|
|
108
|
+
data: ${JSON.stringify({
|
|
109
|
+
type: "message_delta",
|
|
110
|
+
delta: { stop_reason: "end_turn", stop_sequence: null },
|
|
111
|
+
usage: { input_tokens: 0, output_tokens: 0 }
|
|
112
|
+
})}
|
|
113
|
+
|
|
114
|
+
`);
|
|
115
|
+
}
|
|
116
|
+
safeEnqueue(`event: message_stop
|
|
117
|
+
data: ${JSON.stringify({ type: "message_stop" })}
|
|
118
|
+
|
|
119
|
+
`);
|
|
120
|
+
try {
|
|
121
|
+
controller.close();
|
|
122
|
+
} catch (_e) {
|
|
123
|
+
}
|
|
124
|
+
isClosed = true;
|
|
125
|
+
};
|
|
126
|
+
try {
|
|
127
|
+
armPing();
|
|
128
|
+
while (true) {
|
|
129
|
+
const { done, value } = await reader.read();
|
|
130
|
+
if (done) break;
|
|
131
|
+
buffer += decoder.decode(value, { stream: true });
|
|
132
|
+
const lines = buffer.split("\n");
|
|
133
|
+
buffer = lines.pop() || "";
|
|
134
|
+
for (const line of lines) {
|
|
135
|
+
if (isClosed) break;
|
|
136
|
+
if (!line.startsWith("data:")) continue;
|
|
137
|
+
const data = line.slice(5).trim();
|
|
138
|
+
if (data === "[DONE]") continue;
|
|
139
|
+
try {
|
|
140
|
+
const chunk = JSON.parse(data);
|
|
141
|
+
if (chunk.error) {
|
|
142
|
+
safeEnqueue(`event: error
|
|
143
|
+
data: ${JSON.stringify({
|
|
144
|
+
type: "error",
|
|
145
|
+
error: {
|
|
146
|
+
type: sniffErrorType(chunk.error),
|
|
147
|
+
message: JSON.stringify(chunk.error)
|
|
148
|
+
}
|
|
149
|
+
})}
|
|
150
|
+
|
|
151
|
+
`);
|
|
152
|
+
continue;
|
|
153
|
+
}
|
|
154
|
+
if (chunk.type === "response.failed" && chunk.response?.error) {
|
|
155
|
+
safeEnqueue(`event: error
|
|
156
|
+
data: ${JSON.stringify({
|
|
157
|
+
type: "error",
|
|
158
|
+
error: {
|
|
159
|
+
type: sniffErrorType(chunk.response.error),
|
|
160
|
+
message: JSON.stringify(chunk.response.error)
|
|
161
|
+
}
|
|
162
|
+
})}
|
|
163
|
+
|
|
164
|
+
`);
|
|
165
|
+
continue;
|
|
166
|
+
}
|
|
167
|
+
model = chunk.model || model;
|
|
168
|
+
if (!hasStarted) {
|
|
169
|
+
hasStarted = true;
|
|
170
|
+
const startUsage = chunk.usage ? {
|
|
171
|
+
input_tokens: (chunk.usage.prompt_tokens || 0) - (chunk.usage.prompt_tokens_details?.cached_tokens || 0),
|
|
172
|
+
output_tokens: chunk.usage.completion_tokens || 0
|
|
173
|
+
} : { input_tokens: 0, output_tokens: 0 };
|
|
174
|
+
safeEnqueue(`event: message_start
|
|
175
|
+
data: ${JSON.stringify({
|
|
176
|
+
type: "message_start",
|
|
177
|
+
message: {
|
|
178
|
+
id: messageId,
|
|
179
|
+
type: "message",
|
|
180
|
+
role: "assistant",
|
|
181
|
+
content: [],
|
|
182
|
+
model,
|
|
183
|
+
stop_reason: null,
|
|
184
|
+
stop_sequence: null,
|
|
185
|
+
usage: startUsage
|
|
186
|
+
}
|
|
187
|
+
})}
|
|
188
|
+
|
|
189
|
+
`);
|
|
190
|
+
}
|
|
191
|
+
const choice = chunk.choices?.[0];
|
|
192
|
+
if (!choice) continue;
|
|
193
|
+
if (chunk.usage) {
|
|
194
|
+
stopReasonDelta = {
|
|
195
|
+
type: "message_delta",
|
|
196
|
+
delta: { stop_reason: "end_turn", stop_sequence: null },
|
|
197
|
+
usage: {
|
|
198
|
+
input_tokens: (chunk.usage.prompt_tokens || 0) - (chunk.usage.prompt_tokens_details?.cached_tokens || 0),
|
|
199
|
+
output_tokens: chunk.usage.completion_tokens || 0,
|
|
200
|
+
cache_read_input_tokens: chunk.usage.prompt_tokens_details?.cached_tokens || 0
|
|
201
|
+
}
|
|
202
|
+
};
|
|
203
|
+
}
|
|
204
|
+
if (choice.delta?.thinking) {
|
|
205
|
+
if (!isThinkingStarted) {
|
|
206
|
+
const thinkingBlockIndex = assignContentBlockIndex();
|
|
207
|
+
safeEnqueue(`event: content_block_start
|
|
208
|
+
data: ${JSON.stringify({
|
|
209
|
+
type: "content_block_start",
|
|
210
|
+
index: thinkingBlockIndex,
|
|
211
|
+
content_block: { type: "thinking", thinking: "" }
|
|
212
|
+
})}
|
|
213
|
+
|
|
214
|
+
`);
|
|
215
|
+
currentContentBlockIndex = thinkingBlockIndex;
|
|
216
|
+
isThinkingStarted = true;
|
|
217
|
+
}
|
|
218
|
+
if (choice.delta.thinking.signature) {
|
|
219
|
+
safeEnqueue(`event: content_block_delta
|
|
220
|
+
data: ${JSON.stringify({
|
|
221
|
+
type: "content_block_delta",
|
|
222
|
+
index: currentContentBlockIndex,
|
|
223
|
+
delta: { type: "signature_delta", signature: choice.delta.thinking.signature }
|
|
224
|
+
})}
|
|
225
|
+
|
|
226
|
+
`);
|
|
227
|
+
safeEnqueue(`event: content_block_stop
|
|
228
|
+
data: ${JSON.stringify({
|
|
229
|
+
type: "content_block_stop",
|
|
230
|
+
index: currentContentBlockIndex
|
|
231
|
+
})}
|
|
232
|
+
|
|
233
|
+
`);
|
|
234
|
+
currentContentBlockIndex = -1;
|
|
235
|
+
} else if (choice.delta.thinking.content) {
|
|
236
|
+
safeEnqueue(`event: content_block_delta
|
|
237
|
+
data: ${JSON.stringify({
|
|
238
|
+
type: "content_block_delta",
|
|
239
|
+
index: currentContentBlockIndex,
|
|
240
|
+
delta: { type: "thinking_delta", thinking: choice.delta.thinking.content }
|
|
241
|
+
})}
|
|
242
|
+
|
|
243
|
+
`);
|
|
244
|
+
}
|
|
245
|
+
}
|
|
246
|
+
if (choice.delta?.content) {
|
|
247
|
+
if (!hasTextContentStarted) {
|
|
248
|
+
if (currentContentBlockIndex >= 0 && isThinkingStarted) {
|
|
249
|
+
safeEnqueue(`event: content_block_stop
|
|
250
|
+
data: ${JSON.stringify({
|
|
251
|
+
type: "content_block_stop",
|
|
252
|
+
index: currentContentBlockIndex
|
|
253
|
+
})}
|
|
254
|
+
|
|
255
|
+
`);
|
|
256
|
+
}
|
|
257
|
+
hasTextContentStarted = true;
|
|
258
|
+
const textBlockIndex = assignContentBlockIndex();
|
|
259
|
+
safeEnqueue(`event: content_block_start
|
|
260
|
+
data: ${JSON.stringify({
|
|
261
|
+
type: "content_block_start",
|
|
262
|
+
index: textBlockIndex,
|
|
263
|
+
content_block: { type: "text", text: "" }
|
|
264
|
+
})}
|
|
265
|
+
|
|
266
|
+
`);
|
|
267
|
+
currentContentBlockIndex = textBlockIndex;
|
|
268
|
+
}
|
|
269
|
+
safeEnqueue(`event: content_block_delta
|
|
270
|
+
data: ${JSON.stringify({
|
|
271
|
+
type: "content_block_delta",
|
|
272
|
+
index: currentContentBlockIndex,
|
|
273
|
+
delta: { type: "text_delta", text: choice.delta.content }
|
|
274
|
+
})}
|
|
275
|
+
|
|
276
|
+
`);
|
|
277
|
+
}
|
|
278
|
+
if (choice.delta?.tool_calls) {
|
|
279
|
+
for (const toolCall of choice.delta.tool_calls) {
|
|
280
|
+
const toolCallIndex = toolCall.index ?? 0;
|
|
281
|
+
if (!toolCallIndexToContentBlockIndex.has(toolCallIndex)) {
|
|
282
|
+
if (currentContentBlockIndex >= 0) {
|
|
283
|
+
safeEnqueue(`event: content_block_stop
|
|
284
|
+
data: ${JSON.stringify({
|
|
285
|
+
type: "content_block_stop",
|
|
286
|
+
index: currentContentBlockIndex
|
|
287
|
+
})}
|
|
288
|
+
|
|
289
|
+
`);
|
|
290
|
+
hasTextContentStarted = false;
|
|
291
|
+
}
|
|
292
|
+
const newBlockIndex = assignContentBlockIndex();
|
|
293
|
+
toolCallIndexToContentBlockIndex.set(toolCallIndex, newBlockIndex);
|
|
294
|
+
safeEnqueue(`event: content_block_start
|
|
295
|
+
data: ${JSON.stringify({
|
|
296
|
+
type: "content_block_start",
|
|
297
|
+
index: newBlockIndex,
|
|
298
|
+
content_block: {
|
|
299
|
+
type: "tool_use",
|
|
300
|
+
id: toolCall.id || `call_${Date.now()}_${toolCallIndex}`,
|
|
301
|
+
name: toolCall.function?.name || `tool_${toolCallIndex}`,
|
|
302
|
+
input: {}
|
|
303
|
+
}
|
|
304
|
+
})}
|
|
305
|
+
|
|
306
|
+
`);
|
|
307
|
+
currentContentBlockIndex = newBlockIndex;
|
|
308
|
+
}
|
|
309
|
+
if (toolCall.function?.arguments) {
|
|
310
|
+
const blockIndex = toolCallIndexToContentBlockIndex.get(toolCallIndex);
|
|
311
|
+
if (blockIndex !== void 0) {
|
|
312
|
+
safeEnqueue(`event: content_block_delta
|
|
313
|
+
data: ${JSON.stringify({
|
|
314
|
+
type: "content_block_delta",
|
|
315
|
+
index: blockIndex,
|
|
316
|
+
delta: { type: "input_json_delta", partial_json: toolCall.function.arguments }
|
|
317
|
+
})}
|
|
318
|
+
|
|
319
|
+
`);
|
|
320
|
+
}
|
|
321
|
+
}
|
|
322
|
+
}
|
|
323
|
+
}
|
|
324
|
+
if (choice.finish_reason) {
|
|
325
|
+
if (choice.finish_reason === "content_filter") {
|
|
326
|
+
noteContentFilterRemap(logger);
|
|
327
|
+
}
|
|
328
|
+
const stopReasonMapping = {
|
|
329
|
+
stop: "end_turn",
|
|
330
|
+
length: "max_tokens",
|
|
331
|
+
tool_calls: "tool_use",
|
|
332
|
+
content_filter: "refusal",
|
|
333
|
+
refusal: "refusal",
|
|
334
|
+
pause_turn: "pause_turn"
|
|
335
|
+
};
|
|
336
|
+
stopReasonDelta = {
|
|
337
|
+
type: "message_delta",
|
|
338
|
+
delta: {
|
|
339
|
+
stop_reason: stopReasonMapping[choice.finish_reason] || "end_turn",
|
|
340
|
+
stop_sequence: null
|
|
341
|
+
},
|
|
342
|
+
usage: {
|
|
343
|
+
input_tokens: (chunk.usage?.prompt_tokens || 0) - (chunk.usage?.prompt_tokens_details?.cached_tokens || 0),
|
|
344
|
+
output_tokens: chunk.usage?.completion_tokens || 0,
|
|
345
|
+
cache_read_input_tokens: chunk.usage?.prompt_tokens_details?.cached_tokens || 0
|
|
346
|
+
}
|
|
347
|
+
};
|
|
348
|
+
}
|
|
349
|
+
} catch (e) {
|
|
350
|
+
logger?.error("Error parsing stream chunk:", e);
|
|
351
|
+
}
|
|
352
|
+
}
|
|
353
|
+
armPing();
|
|
354
|
+
}
|
|
355
|
+
} catch (e) {
|
|
356
|
+
if (!isClosed) {
|
|
357
|
+
controller.error(e);
|
|
358
|
+
}
|
|
359
|
+
} finally {
|
|
360
|
+
clearPing();
|
|
361
|
+
safeClose();
|
|
362
|
+
reader.releaseLock();
|
|
363
|
+
}
|
|
364
|
+
},
|
|
365
|
+
// R6: client disconnect. Cancelling the upstream reader settles the pending
|
|
366
|
+
// read(), which unblocks the loop's `finally` → `clearPing` — the timer is
|
|
367
|
+
// cleared INDIRECTLY (pinned by the cancel-leak fake-timer test).
|
|
368
|
+
cancel: async () => {
|
|
369
|
+
try {
|
|
370
|
+
await reader?.cancel();
|
|
371
|
+
} catch (_e) {
|
|
372
|
+
}
|
|
373
|
+
}
|
|
374
|
+
});
|
|
375
|
+
}
|
|
376
|
+
|
|
377
|
+
export {
|
|
378
|
+
DEFAULT_ANTHROPIC_PING_HEARTBEAT_MS,
|
|
379
|
+
setAnthropicPingHeartbeatMs,
|
|
380
|
+
getAnthropicPingHeartbeatMs,
|
|
381
|
+
stopReasonContentFilterCount,
|
|
382
|
+
__resetStopReasonContentFilterCountForTests,
|
|
383
|
+
convertOpenAIStreamToAnthropic
|
|
384
|
+
};
|
|
@@ -0,0 +1,123 @@
|
|
|
1
|
+
// src/outbound-api/auditRedact.ts
|
|
2
|
+
var AUDIT_REDACTED = "***REDACTED***";
|
|
3
|
+
var RULES = [
|
|
4
|
+
// `sk-…` family (Anthropic sk-ant-, omnicross sk-omnicross-, OpenAI sk-proj-/sk-).
|
|
5
|
+
{ re: /\bsk-[A-Za-z0-9_-]{6,}/g, replace: AUDIT_REDACTED },
|
|
6
|
+
// Google API keys.
|
|
7
|
+
{ re: /\bAIza[A-Za-z0-9_-]{10,}/g, replace: AUDIT_REDACTED },
|
|
8
|
+
// `Bearer <token>` (auth headers echoed into a body / SSE error).
|
|
9
|
+
{ re: /\bBearer\s+[A-Za-z0-9._~+/=-]{6,}/gi, replace: `Bearer ${AUDIT_REDACTED}` },
|
|
10
|
+
// Inline `x-api-key` / `api-key` / `authorization` label followed by a value.
|
|
11
|
+
{
|
|
12
|
+
re: /\b(x-api-key|api[_-]?key|authorization)(["']?\s*[:=]\s*["']?)[A-Za-z0-9._~+/=-]{6,}/gi,
|
|
13
|
+
replace: `$1$2${AUDIT_REDACTED}`
|
|
14
|
+
},
|
|
15
|
+
// `x-goog-api-key` header echoed inline.
|
|
16
|
+
{
|
|
17
|
+
re: /\b(x-goog-api-key)(["']?\s*[:=]\s*["']?)[A-Za-z0-9._~+/=-]{6,}/gi,
|
|
18
|
+
replace: `$1$2${AUDIT_REDACTED}`
|
|
19
|
+
}
|
|
20
|
+
];
|
|
21
|
+
function redactEncryptedContentValue(value) {
|
|
22
|
+
if (!value || typeof value !== "object") return false;
|
|
23
|
+
if (Array.isArray(value)) {
|
|
24
|
+
let changed2 = false;
|
|
25
|
+
for (const item of value) changed2 = redactEncryptedContentValue(item) || changed2;
|
|
26
|
+
return changed2;
|
|
27
|
+
}
|
|
28
|
+
let changed = false;
|
|
29
|
+
const record = value;
|
|
30
|
+
for (const [key, nested] of Object.entries(record)) {
|
|
31
|
+
if (key === "encrypted_content") {
|
|
32
|
+
record[key] = AUDIT_REDACTED;
|
|
33
|
+
changed = true;
|
|
34
|
+
} else {
|
|
35
|
+
changed = redactEncryptedContentValue(nested) || changed;
|
|
36
|
+
}
|
|
37
|
+
}
|
|
38
|
+
return changed;
|
|
39
|
+
}
|
|
40
|
+
function redactJsonValue(text) {
|
|
41
|
+
try {
|
|
42
|
+
const parsed = JSON.parse(text);
|
|
43
|
+
return redactEncryptedContentValue(parsed) ? JSON.stringify(parsed) : null;
|
|
44
|
+
} catch {
|
|
45
|
+
return null;
|
|
46
|
+
}
|
|
47
|
+
}
|
|
48
|
+
function redactEncryptedContentSse(text) {
|
|
49
|
+
return text.replace(/^(\s*data:\s*)([^\r\n]*)(\r?)$/gm, (line, prefix, payload, cr) => {
|
|
50
|
+
if (!payload || payload.trim() === "[DONE]") return line;
|
|
51
|
+
const redacted = redactJsonValue(payload.trim());
|
|
52
|
+
return redacted === null ? line : `${prefix}${redacted}${cr}`;
|
|
53
|
+
});
|
|
54
|
+
}
|
|
55
|
+
function findJsonLikeValueEnd(text, start) {
|
|
56
|
+
const first = text[start];
|
|
57
|
+
if (first === '"' || first === "'") {
|
|
58
|
+
let escaped = false;
|
|
59
|
+
for (let index = start + 1; index < text.length; index += 1) {
|
|
60
|
+
const char = text[index];
|
|
61
|
+
if (escaped) escaped = false;
|
|
62
|
+
else if (char === "\\") escaped = true;
|
|
63
|
+
else if (char === first) return index + 1;
|
|
64
|
+
}
|
|
65
|
+
return text.length;
|
|
66
|
+
}
|
|
67
|
+
if (first === "{" || first === "[") {
|
|
68
|
+
const opening = first;
|
|
69
|
+
const closing = first === "{" ? "}" : "]";
|
|
70
|
+
let depth = 0;
|
|
71
|
+
let quote = "";
|
|
72
|
+
let escaped = false;
|
|
73
|
+
for (let index = start; index < text.length; index += 1) {
|
|
74
|
+
const char = text[index];
|
|
75
|
+
if (quote) {
|
|
76
|
+
if (escaped) escaped = false;
|
|
77
|
+
else if (char === "\\") escaped = true;
|
|
78
|
+
else if (char === quote) quote = "";
|
|
79
|
+
continue;
|
|
80
|
+
}
|
|
81
|
+
if (char === '"' || char === "'") quote = char;
|
|
82
|
+
else if (char === opening) depth += 1;
|
|
83
|
+
else if (char === closing && --depth === 0) return index + 1;
|
|
84
|
+
}
|
|
85
|
+
return text.length;
|
|
86
|
+
}
|
|
87
|
+
let end = start;
|
|
88
|
+
while (end < text.length && !/[\r\n,}\]]/.test(text[end])) end += 1;
|
|
89
|
+
return end;
|
|
90
|
+
}
|
|
91
|
+
function redactEncryptedContentText(text) {
|
|
92
|
+
const key = /["']encrypted_content["']\s*:\s*/g;
|
|
93
|
+
let output = "";
|
|
94
|
+
let cursor = 0;
|
|
95
|
+
for (; ; ) {
|
|
96
|
+
const match = key.exec(text);
|
|
97
|
+
if (!match) break;
|
|
98
|
+
const valueStart = match.index + match[0].length;
|
|
99
|
+
const valueEnd = findJsonLikeValueEnd(text, valueStart);
|
|
100
|
+
output += text.slice(cursor, valueStart) + JSON.stringify(AUDIT_REDACTED);
|
|
101
|
+
cursor = valueEnd;
|
|
102
|
+
key.lastIndex = valueEnd;
|
|
103
|
+
}
|
|
104
|
+
return cursor === 0 ? text : output + text.slice(cursor);
|
|
105
|
+
}
|
|
106
|
+
function redactEncryptedContent(text) {
|
|
107
|
+
const completeJson = redactJsonValue(text);
|
|
108
|
+
if (completeJson !== null) return completeJson;
|
|
109
|
+
return redactEncryptedContentText(redactEncryptedContentSse(text));
|
|
110
|
+
}
|
|
111
|
+
function redactAuditText(text) {
|
|
112
|
+
if (typeof text !== "string" || text.length === 0) return text ?? "";
|
|
113
|
+
let out = redactEncryptedContent(text);
|
|
114
|
+
for (const { re, replace } of RULES) {
|
|
115
|
+
out = out.replace(re, replace);
|
|
116
|
+
}
|
|
117
|
+
return out;
|
|
118
|
+
}
|
|
119
|
+
|
|
120
|
+
export {
|
|
121
|
+
AUDIT_REDACTED,
|
|
122
|
+
redactAuditText
|
|
123
|
+
};
|