@bman654/clodex 2.2.2 → 2.3.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/README.md +9 -0
- package/dist/cli.js +177 -17
- package/dist/cli.js.map +1 -1
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -275,6 +275,15 @@ clodex --version # version
|
|
|
275
275
|
- Proxied routes forward configured provider headers for API-key and OAuth authentication. Anonymous routes preserve non-credential headers while removing authorization, API-key, cookie, token, secret, and credential-bearing header names before dispatch.
|
|
276
276
|
- `CLODEX_CLAUDE_PATH` overrides Claude Code binary discovery.
|
|
277
277
|
- **Outbound proxy:** when `HTTP_PROXY`/`HTTPS_PROXY` (and optionally `NO_PROXY`) are set in clodex's environment, all clodex-originated network calls honor them — OAuth sign-in and token refresh, model-list and models.dev refreshes, upstream OpenAI API calls, and the ChatGPT/Codex OAuth WebSocket transport (tunneled via HTTP CONNECT).
|
|
278
|
+
- **Upstream retries:** set `CLODEX_UPSTREAM_MAX_RETRIES` to an integer from
|
|
279
|
+
`0` through `5` to override the SDK's default of two retries for retryable
|
|
280
|
+
provider failures. `0` disables retries. The SDK honors valid
|
|
281
|
+
`retry-after`/`retry-after-ms` headers and otherwise uses exponential
|
|
282
|
+
backoff. Larger integers clamp to `5` with a one-time warning because a sixth
|
|
283
|
+
retry cannot complete before the translated streaming paths' 120-second
|
|
284
|
+
no-data timeout. Unset, empty, or malformed values preserve the default. A
|
|
285
|
+
stream that fails after output begins cannot be replayed safely and still
|
|
286
|
+
terminates the request.
|
|
278
287
|
|
|
279
288
|
## Known limitations
|
|
280
289
|
|
package/dist/cli.js
CHANGED
|
@@ -218,7 +218,7 @@ import { join } from "path";
|
|
|
218
218
|
// package.json
|
|
219
219
|
var package_default = {
|
|
220
220
|
name: "@bman654/clodex",
|
|
221
|
-
version: "2.
|
|
221
|
+
version: "2.3.0",
|
|
222
222
|
publishConfig: {
|
|
223
223
|
access: "public"
|
|
224
224
|
},
|
|
@@ -4496,6 +4496,61 @@ function warnReasoningNormalizationGap(fields, log12) {
|
|
|
4496
4496
|
} catch {
|
|
4497
4497
|
}
|
|
4498
4498
|
}
|
|
4499
|
+
function toolArgumentNormalizationGap(expected, actual, requiredProps) {
|
|
4500
|
+
if (conversationItemKind(expected) !== "function_call") return void 0;
|
|
4501
|
+
if (conversationItemKind(actual) !== "function_call") return void 0;
|
|
4502
|
+
const left = expected;
|
|
4503
|
+
const right = actual;
|
|
4504
|
+
const callId = left.call_id;
|
|
4505
|
+
if (typeof callId !== "string" || !callId || callId !== right.call_id) return void 0;
|
|
4506
|
+
if (typeof left.name !== "string" || left.name !== right.name) return void 0;
|
|
4507
|
+
if (canonicalJson(normalizeToolCallJson(left)) === canonicalJson(normalizeToolCallJson(right))) {
|
|
4508
|
+
return void 0;
|
|
4509
|
+
}
|
|
4510
|
+
const required = requiredProps().get(left.name);
|
|
4511
|
+
const stripped = (item) => {
|
|
4512
|
+
if (typeof item.arguments !== "string") return void 0;
|
|
4513
|
+
const raw = item.arguments.trim();
|
|
4514
|
+
try {
|
|
4515
|
+
const parsed = raw === "" ? {} : JSON.parse(raw);
|
|
4516
|
+
if (!parsed || typeof parsed !== "object" || Array.isArray(parsed)) return void 0;
|
|
4517
|
+
return canonicalJson({
|
|
4518
|
+
...normalizeToolCallJson(item),
|
|
4519
|
+
arguments: canonicalJson(sanitizeToolInput(parsed, required))
|
|
4520
|
+
});
|
|
4521
|
+
} catch {
|
|
4522
|
+
return void 0;
|
|
4523
|
+
}
|
|
4524
|
+
};
|
|
4525
|
+
const leftStripped = stripped(left);
|
|
4526
|
+
const rightStripped = stripped(right);
|
|
4527
|
+
return {
|
|
4528
|
+
tool: left.name,
|
|
4529
|
+
equalAfterStrip: leftStripped !== void 0 && leftStripped === rightStripped
|
|
4530
|
+
};
|
|
4531
|
+
}
|
|
4532
|
+
var warnedToolArgumentGaps = /* @__PURE__ */ new Set();
|
|
4533
|
+
var MAX_TOOL_ARGUMENT_GAP_WARNINGS = 3;
|
|
4534
|
+
function warnToolArgumentNormalizationGap(gap, log12) {
|
|
4535
|
+
const tool3 = typeof gap.tool === "string" ? gap.tool : "unknown";
|
|
4536
|
+
const signature = `${tool3}:filler`;
|
|
4537
|
+
const message = `clodex: warning: tool call "${tool3}" failed the continuation match, but both sides are identical once clodex's filler-strip rule is applied, so the head should have matched. Prompt caching is degraded for this turn \u2014 please report it, with the adapter debug log from --trace if you can, at https://github.com/bman654/clodex/issues`;
|
|
4538
|
+
try {
|
|
4539
|
+
log12?.(`tool argument normalization gap: ${signature}`);
|
|
4540
|
+
} catch {
|
|
4541
|
+
}
|
|
4542
|
+
if (warnedToolArgumentGaps.has(signature)) return;
|
|
4543
|
+
if (warnedToolArgumentGaps.size >= MAX_TOOL_ARGUMENT_GAP_WARNINGS) return;
|
|
4544
|
+
warnedToolArgumentGaps.add(signature);
|
|
4545
|
+
try {
|
|
4546
|
+
process.stderr.write(`${message}
|
|
4547
|
+
`);
|
|
4548
|
+
if (warnedToolArgumentGaps.size === MAX_TOOL_ARGUMENT_GAP_WARNINGS) {
|
|
4549
|
+
process.stderr.write("clodex: warning: further tool-argument normalization warnings suppressed.\n");
|
|
4550
|
+
}
|
|
4551
|
+
} catch {
|
|
4552
|
+
}
|
|
4553
|
+
}
|
|
4499
4554
|
function continuationMismatchDetails(entry, payload, log12, warnOnGap = false) {
|
|
4500
4555
|
const full = inputArray(payload);
|
|
4501
4556
|
const prefix = [...entry.requestInput ?? [], ...entry.expectedAssistant ?? []];
|
|
@@ -4511,6 +4566,34 @@ function continuationMismatchDetails(entry, payload, log12, warnOnGap = false) {
|
|
|
4511
4566
|
const actual = mismatch < full.length ? full[mismatch] : void 0;
|
|
4512
4567
|
const reasoningGap = reasoningNormalizationGap(expected, actual);
|
|
4513
4568
|
if (reasoningGap && warnOnGap) warnReasoningNormalizationGap(reasoningGap, log12);
|
|
4569
|
+
let gapExpected = expected;
|
|
4570
|
+
if (conversationItemKind(expected) === "reasoning" && conversationItemKind(actual) === "function_call") {
|
|
4571
|
+
for (let index = mismatch; index < prefix.length; index += 1) {
|
|
4572
|
+
if (conversationItemKind(prefix[index]) !== "reasoning") {
|
|
4573
|
+
gapExpected = prefix[index];
|
|
4574
|
+
break;
|
|
4575
|
+
}
|
|
4576
|
+
}
|
|
4577
|
+
}
|
|
4578
|
+
let toolArgumentGap;
|
|
4579
|
+
try {
|
|
4580
|
+
toolArgumentGap = toolArgumentNormalizationGap(
|
|
4581
|
+
gapExpected,
|
|
4582
|
+
actual,
|
|
4583
|
+
// The head's own schema when it has one; the current turn's tools are only a
|
|
4584
|
+
// fallback for a head that predates the snapshot (see headRequiredToolProps).
|
|
4585
|
+
() => entry.headRequiredToolProps ?? requiredToolProps(payload)
|
|
4586
|
+
);
|
|
4587
|
+
} catch {
|
|
4588
|
+
}
|
|
4589
|
+
if (toolArgumentGap?.equalAfterStrip === true) {
|
|
4590
|
+
if (warnOnGap) warnToolArgumentNormalizationGap(toolArgumentGap, log12);
|
|
4591
|
+
} else if (toolArgumentGap && warnOnGap) {
|
|
4592
|
+
try {
|
|
4593
|
+
log12?.(`tool argument mismatch beyond the strip rule: ${String(toolArgumentGap.tool)}`);
|
|
4594
|
+
} catch {
|
|
4595
|
+
}
|
|
4596
|
+
}
|
|
4514
4597
|
return {
|
|
4515
4598
|
fullItems: full.length,
|
|
4516
4599
|
expectedPrefixItems: prefix.length,
|
|
@@ -4528,11 +4611,12 @@ function continuationMismatchDetails(entry, payload, log12, warnOnGap = false) {
|
|
|
4528
4611
|
entry.expectedAssistant ?? [],
|
|
4529
4612
|
mismatch
|
|
4530
4613
|
)
|
|
4531
|
-
} : {}
|
|
4614
|
+
} : {},
|
|
4615
|
+
...toolArgumentGap ? { toolArgumentNormalizationGap: toolArgumentGap } : {}
|
|
4532
4616
|
};
|
|
4533
4617
|
}
|
|
4534
|
-
function continuationMismatchSummary(entry, payload, log12, mismatchDump = false) {
|
|
4535
|
-
const details = continuationMismatchDetails(entry, payload, log12, true);
|
|
4618
|
+
function continuationMismatchSummary(entry, payload, log12, mismatchDump = false, precomputedDetails) {
|
|
4619
|
+
const details = precomputedDetails ?? continuationMismatchDetails(entry, payload, log12, true);
|
|
4536
4620
|
let summary = `full_items=${details.fullItems} expected_prefix_items=${details.expectedPrefixItems} first_mismatch=${details.firstMismatch} expected=${details.expectedKind} actual=${details.actualKind}`;
|
|
4537
4621
|
if (details.expectedHash || details.actualHash) {
|
|
4538
4622
|
summary += ` expected_hash=${details.expectedHash ?? "none"} actual_hash=${details.actualHash ?? "none"}`;
|
|
@@ -4668,6 +4752,7 @@ function emitContextDiagnostic(entry, ctx, details) {
|
|
|
4668
4752
|
retried: ctx.retried,
|
|
4669
4753
|
frameCount: ctx.frameCount,
|
|
4670
4754
|
emittedModelData: ctx.emittedModelData,
|
|
4755
|
+
emittedDownstreamData: ctx.emittedDownstreamData,
|
|
4671
4756
|
responseIdReceived: Boolean(ctx.responseId),
|
|
4672
4757
|
inFlightMs: entry.inFlightStartedAt === void 0 ? void 0 : Math.max(0, entry.options.now() - entry.inFlightStartedAt),
|
|
4673
4758
|
...details
|
|
@@ -4922,6 +5007,7 @@ function expectedAssistantItems(ctx) {
|
|
|
4922
5007
|
}
|
|
4923
5008
|
function encodeSse(ctx, event) {
|
|
4924
5009
|
if (ctx.closed) return;
|
|
5010
|
+
ctx.emittedDownstreamData = true;
|
|
4925
5011
|
ctx.controller.enqueue(ctx.encoder.encode(`data: ${JSON.stringify(event)}
|
|
4926
5012
|
|
|
4927
5013
|
`));
|
|
@@ -4973,12 +5059,12 @@ function failContext(entry, ctx, message, diagnosticDetails, statusCode, retryAf
|
|
|
4973
5059
|
closeContext(ctx);
|
|
4974
5060
|
}
|
|
4975
5061
|
function retryTransportFailure(entry, ctx, diagnosticDetails) {
|
|
4976
|
-
if (ctx.closed || entry.current !== ctx || ctx.retried || ctx
|
|
5062
|
+
if (ctx.closed || entry.current !== ctx || ctx.retried || !transportReplaySafe(ctx)) {
|
|
4977
5063
|
return false;
|
|
4978
5064
|
}
|
|
4979
5065
|
ctx.retried = true;
|
|
4980
5066
|
ctx.transportRetryPending = true;
|
|
4981
|
-
entry.debug("transport failed before
|
|
5067
|
+
entry.debug("transport failed before downstream output; retrying once with full context");
|
|
4982
5068
|
emitContextDiagnostic(entry, ctx, {
|
|
4983
5069
|
event: "ws_transport_retry",
|
|
4984
5070
|
outcome: "started",
|
|
@@ -5012,9 +5098,9 @@ function retryTransportFailure(entry, ctx, diagnosticDetails) {
|
|
|
5012
5098
|
function handleTransportFailure(entry, ctx, message, diagnosticDetails) {
|
|
5013
5099
|
if (retryTransportFailure(entry, ctx, diagnosticDetails)) return;
|
|
5014
5100
|
if (ctx.closed || entry.current !== ctx) return;
|
|
5015
|
-
if (ctx.retried && ctx.
|
|
5101
|
+
if (ctx.retried && ctx.transportRetryPending && transportReplaySafe(ctx)) {
|
|
5016
5102
|
ctx.transportRetryPending = false;
|
|
5017
|
-
entry.debug("transport retry exhausted before
|
|
5103
|
+
entry.debug("transport retry exhausted before downstream output");
|
|
5018
5104
|
emitContextDiagnostic(entry, ctx, {
|
|
5019
5105
|
event: "ws_transport_retry",
|
|
5020
5106
|
outcome: "exhausted",
|
|
@@ -5118,6 +5204,9 @@ function resetContextForRetry(ctx) {
|
|
|
5118
5204
|
ctx.recentUpstreamEventTypes = [];
|
|
5119
5205
|
ctx.emittedProtocolAnomalies.clear();
|
|
5120
5206
|
}
|
|
5207
|
+
function transportReplaySafe(ctx) {
|
|
5208
|
+
return !ctx.emittedDownstreamData && !ctx.emittedModelData && ctx.outputByIndex.size === 0;
|
|
5209
|
+
}
|
|
5121
5210
|
function handleSocketMessage(entry, data) {
|
|
5122
5211
|
const ctx = entry.current;
|
|
5123
5212
|
if (!ctx || ctx.closed) return;
|
|
@@ -5232,6 +5321,7 @@ function handleSocketMessage(entry, data) {
|
|
|
5232
5321
|
entry.responseId = ctx.responseId;
|
|
5233
5322
|
entry.requestInput = inputArray(ctx.originalPayload);
|
|
5234
5323
|
entry.expectedAssistant = expectedAssistantItems(ctx);
|
|
5324
|
+
entry.headRequiredToolProps = requiredToolProps(ctx.originalPayload);
|
|
5235
5325
|
entry.canonicalPrefix = void 0;
|
|
5236
5326
|
entry.canonicalEchoablePrefix = void 0;
|
|
5237
5327
|
entry.promptFieldHashes = ctx.promptFieldHashes;
|
|
@@ -5417,6 +5507,7 @@ function createResponsesWebSocketFetch(wsUrl, log12, options = {}) {
|
|
|
5417
5507
|
let persistent = Boolean(partitionKey);
|
|
5418
5508
|
let promotedConnectionId;
|
|
5419
5509
|
let decision;
|
|
5510
|
+
let candidateMismatchDetails;
|
|
5420
5511
|
if (selected && selectedDelta) {
|
|
5421
5512
|
sendPayload = { ...payload, input: selectedDelta, previous_response_id: selected.responseId };
|
|
5422
5513
|
continued = true;
|
|
@@ -5439,8 +5530,23 @@ function createResponsesWebSocketFetch(wsUrl, log12, options = {}) {
|
|
|
5439
5530
|
decision = "parallel_isolated";
|
|
5440
5531
|
debug("parallel request using an isolated socket");
|
|
5441
5532
|
} else if (diagnosticEntry) {
|
|
5533
|
+
const diagnosticMismatch = continuationMismatchDetails(diagnosticEntry, payload, debug, true);
|
|
5534
|
+
candidateMismatchDetails = /* @__PURE__ */ new Map([[diagnosticEntry, diagnosticMismatch]]);
|
|
5535
|
+
for (const candidate of candidates) {
|
|
5536
|
+
if (candidate === diagnosticEntry) continue;
|
|
5537
|
+
candidateMismatchDetails.set(
|
|
5538
|
+
candidate,
|
|
5539
|
+
continuationMismatchDetails(candidate, payload, debug, true)
|
|
5540
|
+
);
|
|
5541
|
+
}
|
|
5442
5542
|
debug(
|
|
5443
|
-
`history mismatch starting an additional chain; retained ${candidates.length} existing head(s) (${continuationMismatchSummary(
|
|
5543
|
+
`history mismatch starting an additional chain; retained ${candidates.length} existing head(s) (${continuationMismatchSummary(
|
|
5544
|
+
diagnosticEntry,
|
|
5545
|
+
payload,
|
|
5546
|
+
debug,
|
|
5547
|
+
mismatchDump,
|
|
5548
|
+
diagnosticMismatch
|
|
5549
|
+
)})`
|
|
5444
5550
|
);
|
|
5445
5551
|
decision = "history_mismatch_new_head";
|
|
5446
5552
|
} else if (partitionKey) {
|
|
@@ -5500,7 +5606,7 @@ function createResponsesWebSocketFetch(wsUrl, log12, options = {}) {
|
|
|
5500
5606
|
ttlPausedMs: entry.ttlPausedMs,
|
|
5501
5607
|
idleMs: Math.max(0, now - entry.lastUsedAt),
|
|
5502
5608
|
promptChanges: changedPromptFields(entry.promptFieldHashes, promptFieldHashes),
|
|
5503
|
-
mismatch: continuationMismatchDetails(entry, payload, debug)
|
|
5609
|
+
mismatch: candidateMismatchDetails?.get(entry) ?? continuationMismatchDetails(entry, payload, debug)
|
|
5504
5610
|
})),
|
|
5505
5611
|
evictions
|
|
5506
5612
|
}, diagnosticCorrelation);
|
|
@@ -5520,6 +5626,7 @@ function createResponsesWebSocketFetch(wsUrl, log12, options = {}) {
|
|
|
5520
5626
|
frameCount: 0,
|
|
5521
5627
|
pendingEvents: [],
|
|
5522
5628
|
emittedModelData: false,
|
|
5629
|
+
emittedDownstreamData: false,
|
|
5523
5630
|
transportRetryPending: false,
|
|
5524
5631
|
outputByIndex: /* @__PURE__ */ new Map(),
|
|
5525
5632
|
outputIndexByItemId: /* @__PURE__ */ new Map(),
|
|
@@ -9882,6 +9989,41 @@ function resolveUpstreamTools(tools, messages) {
|
|
|
9882
9989
|
return upstream;
|
|
9883
9990
|
}
|
|
9884
9991
|
|
|
9992
|
+
// src/upstream-retry.ts
|
|
9993
|
+
var UPSTREAM_MAX_RETRIES_ENV = "CLODEX_UPSTREAM_MAX_RETRIES";
|
|
9994
|
+
var MAX_UPSTREAM_MAX_RETRIES = 5;
|
|
9995
|
+
var reportedValues = /* @__PURE__ */ new Set();
|
|
9996
|
+
function reportOnce(raw, message, warn) {
|
|
9997
|
+
if (reportedValues.has(raw)) return;
|
|
9998
|
+
reportedValues.add(raw);
|
|
9999
|
+
try {
|
|
10000
|
+
warn(message);
|
|
10001
|
+
} catch {
|
|
10002
|
+
}
|
|
10003
|
+
}
|
|
10004
|
+
function upstreamMaxRetries(env = process.env, warn = (message) => console.error(`clodex: ${message}`)) {
|
|
10005
|
+
const raw = env[UPSTREAM_MAX_RETRIES_ENV]?.trim();
|
|
10006
|
+
if (raw === void 0 || raw === "") return void 0;
|
|
10007
|
+
const value = Number(raw);
|
|
10008
|
+
if (!Number.isInteger(value) || value < 0) {
|
|
10009
|
+
reportOnce(
|
|
10010
|
+
raw,
|
|
10011
|
+
`ignoring ${UPSTREAM_MAX_RETRIES_ENV}=${raw} (expected a non-negative integer)`,
|
|
10012
|
+
warn
|
|
10013
|
+
);
|
|
10014
|
+
return void 0;
|
|
10015
|
+
}
|
|
10016
|
+
if (value > MAX_UPSTREAM_MAX_RETRIES) {
|
|
10017
|
+
reportOnce(
|
|
10018
|
+
raw,
|
|
10019
|
+
`clamping ${UPSTREAM_MAX_RETRIES_ENV}=${raw} to ${MAX_UPSTREAM_MAX_RETRIES} (higher values exceed the 120s streaming idle budget)`,
|
|
10020
|
+
warn
|
|
10021
|
+
);
|
|
10022
|
+
return MAX_UPSTREAM_MAX_RETRIES;
|
|
10023
|
+
}
|
|
10024
|
+
return value;
|
|
10025
|
+
}
|
|
10026
|
+
|
|
9885
10027
|
// src/sdk-adapter.ts
|
|
9886
10028
|
function sdkTranslationErrorSignature(error) {
|
|
9887
10029
|
const message = error instanceof Error ? error.message : typeof error === "string" ? error : void 0;
|
|
@@ -9952,10 +10094,12 @@ function openAiCacheBreakpoint(block, enabled) {
|
|
|
9952
10094
|
function translateTopLevelSystemForOpenAi(system) {
|
|
9953
10095
|
if (!system) return [];
|
|
9954
10096
|
if (typeof system === "string") {
|
|
9955
|
-
|
|
10097
|
+
const stripped = stripClaudeCodeBillingHeader(system);
|
|
10098
|
+
return stripped?.trim() ? [{ role: "system", content: stripped }] : [];
|
|
9956
10099
|
}
|
|
9957
10100
|
return system.flatMap((block) => {
|
|
9958
|
-
const
|
|
10101
|
+
const raw = typeof block === "string" ? block : block.text ?? "";
|
|
10102
|
+
const text4 = stripClaudeCodeBillingHeader(raw) ?? "";
|
|
9959
10103
|
if (!text4.trim()) return [];
|
|
9960
10104
|
const cacheControl = typeof block === "string" ? void 0 : block.cache_control;
|
|
9961
10105
|
return [{
|
|
@@ -10141,7 +10285,7 @@ function isClaudeCodeStructuredOutputCompactRequest(body) {
|
|
|
10141
10285
|
function translateRequest(body, npm, options) {
|
|
10142
10286
|
const messages = body.messages ?? [];
|
|
10143
10287
|
annotateToolNames(messages);
|
|
10144
|
-
const baseSystem = systemToString(body.system,
|
|
10288
|
+
const baseSystem = systemToString(body.system, true);
|
|
10145
10289
|
const systemText = baseSystem?.trim() || (options?.openAiOAuth ? "You are a coding assistant." : void 0);
|
|
10146
10290
|
const compactRequest = isClaudeCodeStructuredOutputCompactRequest(body);
|
|
10147
10291
|
let upstreamTools = resolveUpstreamTools(
|
|
@@ -10432,6 +10576,7 @@ async function streamAnthropicResponse(model, params, modelId, write, log12, obs
|
|
|
10432
10576
|
const result = streamText({
|
|
10433
10577
|
model,
|
|
10434
10578
|
...params,
|
|
10579
|
+
maxRetries: upstreamMaxRetries(),
|
|
10435
10580
|
abortSignal,
|
|
10436
10581
|
onError: () => {
|
|
10437
10582
|
}
|
|
@@ -10480,6 +10625,7 @@ async function generateAnthropicResponse(model, params, modelId, options) {
|
|
|
10480
10625
|
const r = streamText({
|
|
10481
10626
|
model,
|
|
10482
10627
|
...params,
|
|
10628
|
+
maxRetries: upstreamMaxRetries(),
|
|
10483
10629
|
abortSignal,
|
|
10484
10630
|
onError: () => {
|
|
10485
10631
|
}
|
|
@@ -10536,6 +10682,7 @@ async function generateAnthropicResponse(model, params, modelId, options) {
|
|
|
10536
10682
|
const r = await generateText({
|
|
10537
10683
|
model,
|
|
10538
10684
|
...params,
|
|
10685
|
+
maxRetries: upstreamMaxRetries(),
|
|
10539
10686
|
abortSignal: generateAbort.signal
|
|
10540
10687
|
});
|
|
10541
10688
|
({ text: text4, toolCalls, finishReason, usage } = r);
|
|
@@ -11490,11 +11637,20 @@ async function collectOpenAiStream(stream) {
|
|
|
11490
11637
|
async function generateOpenAiResponse(model, params, responseModelId, options) {
|
|
11491
11638
|
let result;
|
|
11492
11639
|
if (options?.forceStream) {
|
|
11493
|
-
const { stream } = streamText2({
|
|
11494
|
-
|
|
11640
|
+
const { stream } = streamText2({
|
|
11641
|
+
model,
|
|
11642
|
+
...params,
|
|
11643
|
+
maxRetries: upstreamMaxRetries(),
|
|
11644
|
+
onError: () => {
|
|
11645
|
+
}
|
|
11646
|
+
});
|
|
11495
11647
|
result = await collectOpenAiStream(stream);
|
|
11496
11648
|
} else {
|
|
11497
|
-
result = await generateText2({
|
|
11649
|
+
result = await generateText2({
|
|
11650
|
+
model,
|
|
11651
|
+
...params,
|
|
11652
|
+
maxRetries: upstreamMaxRetries()
|
|
11653
|
+
});
|
|
11498
11654
|
}
|
|
11499
11655
|
const message = { role: "assistant", content: result.text || null };
|
|
11500
11656
|
if (result.toolCalls?.length) {
|
|
@@ -11518,7 +11674,11 @@ async function generateOpenAiResponse(model, params, responseModelId, options) {
|
|
|
11518
11674
|
};
|
|
11519
11675
|
}
|
|
11520
11676
|
async function streamOpenAiResponse(model, params, responseModelId, onChunk) {
|
|
11521
|
-
const { stream } = streamText2({
|
|
11677
|
+
const { stream } = streamText2({
|
|
11678
|
+
model,
|
|
11679
|
+
...params,
|
|
11680
|
+
maxRetries: upstreamMaxRetries()
|
|
11681
|
+
});
|
|
11522
11682
|
const baseData = {
|
|
11523
11683
|
id: `chatcmpl-${Date.now()}`,
|
|
11524
11684
|
object: "chat.completion.chunk",
|